mirror of
https://github.com/OpenNebula/one.git
synced 2024-12-22 13:33:52 +03:00
F #1684: Support for LXD/LXC Containers. The LXD/LXC drivers are heavily
inspired by the LXD addon https://github.com/OpenNebula/addon-lxdone. Co-authored-by: Daniel Clavijo Coca <dclavijo@opennebula.systems> Co-authored-by: Sergio Vega Gutiérrez <svega@opennebula.systems> Co-authored-by: José Manuel de la Fé Herrero <jmdelafe92@gmail.com>
This commit is contained in:
parent
175e9456ce
commit
07399094b3
4
.gitignore
vendored
4
.gitignore
vendored
@ -21,6 +21,8 @@ src/oca/java/jar
|
||||
src/oca/java/share/doc
|
||||
src/oca/java/java-oca*.tar.gz
|
||||
|
||||
src/vmm_mad/remotes/lxd/tests/
|
||||
|
||||
src/docker_machine/pkg
|
||||
src/docker_machine/src/docker_machine/bin/docker-machine-driver-opennebula
|
||||
src/docker_machine/src/docker_machine/vendor/
|
||||
@ -36,3 +38,5 @@ src/sunstone/public/locale/languages/*.js
|
||||
|
||||
share/esx-fw-vnc/*.rpm
|
||||
share/esx-fw-vnc/.vagrant*
|
||||
|
||||
*.vscode
|
||||
|
62
SConstruct
Normal file → Executable file
62
SConstruct
Normal file → Executable file
@ -21,11 +21,11 @@ sys.path.append("./share/scons")
|
||||
from lex_bison import *
|
||||
|
||||
# This is the absolute path where the project is located
|
||||
cwd=os.getcwd()
|
||||
cwd = os.getcwd()
|
||||
|
||||
# Environment that will be applied to each scons child
|
||||
main_env=Environment()
|
||||
main_env['ENV']['PATH']=os.environ['PATH']
|
||||
main_env = Environment()
|
||||
main_env['ENV']['PATH'] = os.environ['PATH']
|
||||
|
||||
# snippet borrowed from http://dev.gentoo.org/~vapier/scons-blows.txt
|
||||
# makes scons aware of build related environment variables
|
||||
@ -40,7 +40,7 @@ if os.environ.has_key('CXXFLAGS'):
|
||||
if os.environ.has_key('LDFLAGS'):
|
||||
main_env['LINKFLAGS'] += SCons.Util.CLVar(os.environ['LDFLAGS'])
|
||||
else:
|
||||
os.environ['LDFLAGS']=""
|
||||
os.environ['LDFLAGS'] = ""
|
||||
|
||||
# Add builders for flex and bison
|
||||
add_lex(main_env)
|
||||
@ -110,13 +110,13 @@ main_env.Append(LIBS=['z'])
|
||||
#######################
|
||||
|
||||
# SQLITE
|
||||
sqlite_dir=ARGUMENTS.get('sqlite_dir', 'none')
|
||||
if sqlite_dir!='none':
|
||||
sqlite_dir = ARGUMENTS.get('sqlite_dir', 'none')
|
||||
if sqlite_dir != 'none':
|
||||
main_env.Append(LIBPATH=[sqlite_dir+"/lib", sqlite_dir+"/lib64"])
|
||||
main_env.Append(CPPPATH=[sqlite_dir+"/include"])
|
||||
|
||||
sqlite=ARGUMENTS.get('sqlite', 'yes')
|
||||
if sqlite=='yes':
|
||||
sqlite = ARGUMENTS.get('sqlite', 'yes')
|
||||
if sqlite == 'yes':
|
||||
main_env.Append(sqlite='yes')
|
||||
main_env.Append(CPPFLAGS=["-DSQLITE_DB"])
|
||||
main_env.Append(LIBS=['sqlite3'])
|
||||
@ -124,8 +124,8 @@ else:
|
||||
main_env.Append(sqlite='no')
|
||||
|
||||
# MySQL
|
||||
mysql=ARGUMENTS.get('mysql', 'no')
|
||||
if mysql=='yes':
|
||||
mysql = ARGUMENTS.get('mysql', 'no')
|
||||
if mysql == 'yes':
|
||||
main_env.Append(mysql='yes')
|
||||
main_env.Append(CPPFLAGS=["-DMYSQL_DB"])
|
||||
main_env.Append(LIBS=['mysqlclient'])
|
||||
@ -133,22 +133,22 @@ else:
|
||||
main_env.Append(mysql='no')
|
||||
|
||||
# Flag to compile with xmlrpc-c versions prior to 1.31 (September 2012)
|
||||
new_xmlrpc=ARGUMENTS.get('new_xmlrpc', 'no')
|
||||
if new_xmlrpc=='yes':
|
||||
new_xmlrpc = ARGUMENTS.get('new_xmlrpc', 'no')
|
||||
if new_xmlrpc == 'yes':
|
||||
main_env.Append(new_xmlrpc='yes')
|
||||
else:
|
||||
main_env.Append(new_xmlrpc='no')
|
||||
main_env.Append(CPPFLAGS=["-DOLD_XMLRPC"])
|
||||
|
||||
# xmlrpc
|
||||
xmlrpc_dir=ARGUMENTS.get('xmlrpc', 'none')
|
||||
if xmlrpc_dir!='none':
|
||||
xmlrpc_dir = ARGUMENTS.get('xmlrpc', 'none')
|
||||
if xmlrpc_dir != 'none':
|
||||
main_env.Append(LIBPATH=[xmlrpc_dir+"/lib", xmlrpc_dir+"/lib64"])
|
||||
main_env.Append(CPPPATH=[xmlrpc_dir+"/include"])
|
||||
|
||||
# systemd
|
||||
systemd=ARGUMENTS.get('systemd', 'no')
|
||||
if systemd=='yes':
|
||||
systemd = ARGUMENTS.get('systemd', 'no')
|
||||
if systemd == 'yes':
|
||||
main_env.Append(systemd='yes')
|
||||
main_env.Append(CPPFLAGS=["-DSYSTEMD"])
|
||||
main_env.Append(LIBS=['systemd'])
|
||||
@ -156,8 +156,8 @@ else:
|
||||
main_env.Append(systemd='no')
|
||||
|
||||
# build lex/bison
|
||||
build_parsers=ARGUMENTS.get('parsers', 'no')
|
||||
if build_parsers=='yes':
|
||||
build_parsers = ARGUMENTS.get('parsers', 'no')
|
||||
if build_parsers == 'yes':
|
||||
main_env.Append(parsers='yes')
|
||||
else:
|
||||
main_env.Append(parsers='no')
|
||||
@ -173,7 +173,7 @@ main_env.Append(docker_machine=ARGUMENTS.get('docker_machine', 'no'))
|
||||
|
||||
if not main_env.GetOption('clean'):
|
||||
try:
|
||||
if mysql=='yes':
|
||||
if mysql == 'yes':
|
||||
main_env.ParseConfig('mysql_config --cflags --libs')
|
||||
except Exception, e:
|
||||
print ""
|
||||
@ -186,28 +186,27 @@ if not main_env.GetOption('clean'):
|
||||
print ""
|
||||
exit(-1)
|
||||
|
||||
|
||||
try:
|
||||
main_env.ParseConfig(("LDFLAGS='%s' share/scons/get_xmlrpc_config"+
|
||||
" server") % (os.environ['LDFLAGS'],))
|
||||
main_env.ParseConfig(("LDFLAGS='%s' share/scons/get_xmlrpc_config"+
|
||||
" client") % (os.environ['LDFLAGS'],))
|
||||
main_env.ParseConfig(("LDFLAGS='%s' share/scons/get_xmlrpc_config" +
|
||||
" server") % (os.environ['LDFLAGS'],))
|
||||
main_env.ParseConfig(("LDFLAGS='%s' share/scons/get_xmlrpc_config" +
|
||||
" client") % (os.environ['LDFLAGS'],))
|
||||
|
||||
except Exception, e:
|
||||
print ""
|
||||
print "Error searching for xmlrpc-c libraries. Please check this"+\
|
||||
print "Error searching for xmlrpc-c libraries. Please check this" +\
|
||||
" things:"
|
||||
print ""
|
||||
print " * You have installed development libraries for xmlrpc-c. One"+\
|
||||
print " * You have installed development libraries for xmlrpc-c. One" +\
|
||||
" way to check"
|
||||
print " this is calling xmlrpc-c-config that is provided with the"+\
|
||||
print " this is calling xmlrpc-c-config that is provided with the" +\
|
||||
" development"
|
||||
print " package."
|
||||
print " * Check that the version of xmlrpc-c is at least 1.06. You"+\
|
||||
print " * Check that the version of xmlrpc-c is at least 1.06. You" +\
|
||||
" can do this also"
|
||||
print " calling:"
|
||||
print " $ xmlrpc-c-config --version"
|
||||
print " * If all this requirements are already met please send log"+\
|
||||
print " * If all this requirements are already met please send log" +\
|
||||
" files located in"
|
||||
print " .xmlrpc_test to the mailing list."
|
||||
print ""
|
||||
@ -269,9 +268,10 @@ build_scripts=[
|
||||
'share/rubygems/SConstruct',
|
||||
'src/im_mad/collectd/SConstruct',
|
||||
'src/client/SConstruct',
|
||||
'src/docker_machine/SConstruct'
|
||||
'src/docker_machine/SConstruct',
|
||||
'src/vmm_mad/remotes/lib/lxd/svncterm_server/SConstruct'
|
||||
]
|
||||
|
||||
for script in build_scripts:
|
||||
env=main_env.Clone()
|
||||
env = main_env.Clone()
|
||||
SConscript(script, exports='env')
|
||||
|
65
install.sh
65
install.sh
@ -253,12 +253,16 @@ VAR_DIRS="$VAR_LOCATION/remotes \
|
||||
$VAR_LOCATION/remotes/etc \
|
||||
$VAR_LOCATION/remotes/etc/datastore/ceph \
|
||||
$VAR_LOCATION/remotes/etc/im/kvm-probes.d \
|
||||
$VAR_LOCATION/remotes/etc/im/lxd-probes.d \
|
||||
$VAR_LOCATION/remotes/etc/vmm/kvm \
|
||||
$VAR_LOCATION/remotes/etc/vmm/lxd \
|
||||
$VAR_LOCATION/remotes/etc/vmm/vcenter \
|
||||
$VAR_LOCATION/remotes/etc/vnm \
|
||||
$VAR_LOCATION/remotes/im \
|
||||
$VAR_LOCATION/remotes/im/kvm.d \
|
||||
$VAR_LOCATION/remotes/im/kvm-probes.d \
|
||||
$VAR_LOCATION/remotes/im/lxd.d \
|
||||
$VAR_LOCATION/remotes/im/lxd-probes.d \
|
||||
$VAR_LOCATION/remotes/im/vcenter.d \
|
||||
$VAR_LOCATION/remotes/im/ec2.d \
|
||||
$VAR_LOCATION/remotes/im/az.d \
|
||||
@ -270,6 +274,7 @@ VAR_DIRS="$VAR_LOCATION/remotes \
|
||||
$VAR_LOCATION/remotes/vmm/ec2 \
|
||||
$VAR_LOCATION/remotes/vmm/az \
|
||||
$VAR_LOCATION/remotes/vmm/one \
|
||||
$VAR_LOCATION/remotes/vmm/lxd \
|
||||
$VAR_LOCATION/remotes/vnm \
|
||||
$VAR_LOCATION/remotes/vnm/802.1Q \
|
||||
$VAR_LOCATION/remotes/vnm/vxlan \
|
||||
@ -396,6 +401,9 @@ INSTALL_FILES=(
|
||||
IM_PROBES_KVM_FILES:$VAR_LOCATION/remotes/im/kvm.d
|
||||
IM_PROBES_KVM_PROBES_FILES:$VAR_LOCATION/remotes/im/kvm-probes.d
|
||||
IM_PROBES_ETC_KVM_PROBES_FILES:$VAR_LOCATION/remotes/etc/im/kvm-probes.d
|
||||
IM_PROBES_LXD_FILES:$VAR_LOCATION/remotes/im/lxd.d
|
||||
IM_PROBES_LXD_PROBES_FILES:$VAR_LOCATION/remotes/im/lxd-probes.d
|
||||
IM_PROBES_ETC_LXD_PROBES_FILES:$VAR_LOCATION/remotes/etc/im/lxd-probes.d
|
||||
IM_PROBES_VCENTER_FILES:$VAR_LOCATION/remotes/im/vcenter.d
|
||||
IM_PROBES_EC2_FILES:$VAR_LOCATION/remotes/im/ec2.d
|
||||
IM_PROBES_AZ_FILES:$VAR_LOCATION/remotes/im/az.d
|
||||
@ -411,7 +419,10 @@ INSTALL_FILES=(
|
||||
VMM_EXEC_LIB_FILES:$VAR_LOCATION/remotes/vmm/lib
|
||||
VMM_EXEC_LIB_VCENTER_FILES:$LIB_LOCATION/ruby/vcenter_driver
|
||||
VMM_EXEC_KVM_SCRIPTS:$VAR_LOCATION/remotes/vmm/kvm
|
||||
VMM_EXEC_LXD_SCRIPTS:$VAR_LOCATION/remotes/vmm/lxd
|
||||
VMM_EXEC_LXD_LIB:$VAR_LOCATION/remotes/vmm/lxd
|
||||
VMM_EXEC_ETC_KVM_SCRIPTS:$VAR_LOCATION/remotes/etc/vmm/kvm
|
||||
VMM_EXEC_ETC_LXD_SCRIPTS:$VAR_LOCATION/remotes/etc/vmm/lxd
|
||||
VMM_EXEC_VCENTER_SCRIPTS:$VAR_LOCATION/remotes/vmm/vcenter
|
||||
VMM_EXEC_ETC_VCENTER_SCRIPTS:$VAR_LOCATION/remotes/etc/vmm/vcenter
|
||||
VMM_EXEC_EC2_SCRIPTS:$VAR_LOCATION/remotes/vmm/ec2
|
||||
@ -712,6 +723,45 @@ VMM_EXEC_LIB_VCENTER_FILES="src/vmm_mad/remotes/lib/vcenter_driver/datastore.rb
|
||||
src/vmm_mad/remotes/lib/vcenter_driver/vm_template.rb \
|
||||
src/vmm_mad/remotes/lib/vcenter_driver/network.rb"
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# VMM SH Driver LXD scripts, to be installed under $REMOTES_LOCATION/vmm/lxd
|
||||
#-------------------------------------------------------------------------------
|
||||
VMM_EXEC_LXD_SCRIPTS="src/vmm_mad/remotes/lxd/cancel \
|
||||
src/vmm_mad/remotes/lxd/deploy \
|
||||
src/vmm_mad/remotes/lxd/migrate \
|
||||
src/vmm_mad/remotes/lxd/migrate_local \
|
||||
src/vmm_mad/remotes/lxd/restore \
|
||||
src/vmm_mad/remotes/lxd/reboot \
|
||||
src/vmm_mad/remotes/lxd/reset \
|
||||
src/vmm_mad/remotes/lxd/save \
|
||||
src/vmm_mad/remotes/lxd/poll \
|
||||
src/vmm_mad/remotes/lxd/attach_disk \
|
||||
src/vmm_mad/remotes/lxd/detach_disk \
|
||||
src/vmm_mad/remotes/lxd/attach_nic \
|
||||
src/vmm_mad/remotes/lxd/detach_nic \
|
||||
src/vmm_mad/remotes/lxd/snapshot_create \
|
||||
src/vmm_mad/remotes/lxd/snapshot_revert \
|
||||
src/vmm_mad/remotes/lxd/snapshot_delete \
|
||||
src/vmm_mad/remotes/lxd/shutdown \
|
||||
src/vmm_mad/remotes/lxd/reconfigure \
|
||||
src/vmm_mad/remotes/lxd/prereconfigure \
|
||||
src/vmm_mad/remotes/lxd/resize_disk"
|
||||
|
||||
VMM_EXEC_LXD_LIB="src/vmm_mad/remotes/lib/lxd/opennebula_vm.rb \
|
||||
src/vmm_mad/remotes/lib/lxd/mapper/mapper.rb \
|
||||
src/vmm_mad/remotes/lib/lxd/mapper/qcow2.rb \
|
||||
src/vmm_mad/remotes/lib/lxd/mapper/raw.rb \
|
||||
src/vmm_mad/remotes/lib/lxd/mapper/rbd.rb \
|
||||
src/vmm_mad/remotes/lib/lxd/client.rb \
|
||||
src/vmm_mad/remotes/lib/lxd/command.rb \
|
||||
src/vmm_mad/remotes/lib/lxd/container.rb"
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# VMM configuration LXD scripts, to be installed under $REMOTES_LOCATION/etc/vmm/lxd
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
VMM_EXEC_ETC_LXD_SCRIPTS="src/vmm_mad/remotes/lxd/lxdrc"
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# VMM SH Driver KVM scripts, to be installed under $REMOTES_LOCATION/vmm/kvm
|
||||
#-------------------------------------------------------------------------------
|
||||
@ -870,6 +920,21 @@ IM_PROBES_KVM_PROBES_FILES="src/im_mad/remotes/kvm-probes.d/kvm.rb \
|
||||
|
||||
IM_PROBES_ETC_KVM_PROBES_FILES="src/im_mad/remotes/kvm-probes.d/pci.conf"
|
||||
|
||||
IM_PROBES_LXD_PROBES_FILES="src/im_mad/remotes/lxd-probes.d/lxd.rb \
|
||||
src/im_mad/remotes/lxd-probes.d/architecture.sh \
|
||||
src/im_mad/remotes/lxd-probes.d/cpu.sh \
|
||||
src/im_mad/remotes/lxd-probes.d/poll.sh \
|
||||
src/im_mad/remotes/lxd-probes.d/name.sh \
|
||||
src/im_mad/remotes/lxd-probes.d/pci.rb \
|
||||
src/im_mad/remotes/lxd-probes.d/monitor_ds.sh \
|
||||
src/im_mad/remotes/lxd-probes.d/version.sh \
|
||||
src/im_mad/remotes/lxd-probes.d/collectd-client-shepherd.sh"
|
||||
|
||||
IM_PROBES_LXD_FILES="src/im_mad/remotes/lxd.d/collectd-client_control.sh \
|
||||
src/im_mad/remotes/lxd.d/collectd-client.rb"
|
||||
|
||||
IM_PROBES_ETC_LXD_PROBES_FILES="src/im_mad/remotes/lxd-probes.d/pci.conf"
|
||||
|
||||
IM_PROBES_VCENTER_FILES="src/im_mad/remotes/vcenter.d/poll"
|
||||
|
||||
IM_PROBES_EC2_FILES="src/im_mad/remotes/ec2.d/poll"
|
||||
|
@ -409,6 +409,32 @@ IM_MAD = [
|
||||
# ARGUMENTS = "-r 3 -t 15 -w 90 kvm-probes" ]
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# LXD UDP-push Information Driver Manager Configuration
|
||||
# -r number of retries when monitoring a host
|
||||
# -t number of threads, i.e. number of hosts monitored at the same time
|
||||
# -w Timeout in seconds to execute external commands (default unlimited)
|
||||
#-------------------------------------------------------------------------------
|
||||
IM_MAD = [
|
||||
NAME = "lxd",
|
||||
SUNSTONE_NAME = "LXD",
|
||||
EXECUTABLE = "one_im_ssh",
|
||||
ARGUMENTS = "-r 3 -t 15 -w 90 lxd" ]
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# LXD SSH-pull Information Driver Manager Configuration
|
||||
# -r number of retries when monitoring a host
|
||||
# -t number of threads, i.e. number of hosts monitored at the same time
|
||||
# -w Timeout in seconds to execute external commands (default unlimited)
|
||||
#-------------------------------------------------------------------------------
|
||||
# IM_MAD = [
|
||||
# NAME = "lxd",
|
||||
# SUNSTONE_NAME = "lxd-ssh",
|
||||
# EXECUTABLE = "one_im_ssh",
|
||||
# ARGUMENTS = "-r 3 -t 15 -w 90 lxd-probes" ]
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# vCenter Information Driver Manager Configuration
|
||||
# -r number of retries when monitoring a host
|
||||
@ -548,6 +574,32 @@ VM_MAD = [
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# LXD Virtualization Driver Manager Configuration
|
||||
# -r number of retries when monitoring a host
|
||||
# -t number of threads, i.e. number of hosts monitored at the same time
|
||||
# -l <actions[=command_name]> actions executed locally, command can be
|
||||
# overridden for each action.
|
||||
# Valid actions: deploy, shutdown, cancel, save, restore, migrate, poll
|
||||
# An example: "-l migrate=migrate_local,save"
|
||||
# -p more than one action per host in parallel, needs support from hypervisor
|
||||
# -s <shell> to execute remote commands, bash by default
|
||||
# -w Timeout in seconds to execute external commands (default unlimited)
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
VM_MAD = [
|
||||
NAME = "lxd",
|
||||
SUNSTONE_NAME = "LXD",
|
||||
EXECUTABLE = "one_vmm_exec",
|
||||
ARGUMENTS = "-t 15 -r 0 lxd",
|
||||
# DEFAULT = "vmm_exec/vmm_exec_lxd.conf",
|
||||
TYPE = "xml",
|
||||
KEEP_SNAPSHOTS = "no",
|
||||
IMPORTED_VMS_ACTIONS = "terminate, terminate-hard, reboot, reboot-hard, poweroff, poweroff-hard, suspend, resume, stop, delete, nic-attach, nic-detach"
|
||||
]
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# vCenter Virtualization Driver Manager Configuration
|
||||
# -r number of retries when monitoring a host
|
||||
|
@ -1,19 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2018, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
echo ARCH=`uname -m`
|
1
src/im_mad/remotes/kvm-probes.d/architecture.sh
Symbolic link
1
src/im_mad/remotes/kvm-probes.d/architecture.sh
Symbolic link
@ -0,0 +1 @@
|
||||
../node-probes.d/architecture.sh
|
1
src/im_mad/remotes/kvm-probes.d/collectd-client-shepherd.sh
Symbolic link
1
src/im_mad/remotes/kvm-probes.d/collectd-client-shepherd.sh
Symbolic link
@ -0,0 +1 @@
|
||||
../common.d/collectd-client-shepherd.sh
|
@ -1,35 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2018, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
MODEL=''
|
||||
|
||||
if [ -f /proc/cpuinfo ]; then
|
||||
for NAME in 'model name' 'cpu'; do
|
||||
MODEL=$(grep -m1 "^${NAME}[[:space:]]*:" /proc/cpuinfo | \
|
||||
cut -d: -f2 | \
|
||||
sed -e 's/^ *//')
|
||||
|
||||
if [ -n "${MODEL}" ]; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [ -n "${MODEL}" ]; then
|
||||
echo "MODELNAME=\"${MODEL}\""
|
||||
fi
|
1
src/im_mad/remotes/kvm-probes.d/cpu.sh
Symbolic link
1
src/im_mad/remotes/kvm-probes.d/cpu.sh
Symbolic link
@ -0,0 +1 @@
|
||||
../node-probes.d/cpu.sh
|
1
src/im_mad/remotes/kvm-probes.d/monitor_ds.sh
Symbolic link
1
src/im_mad/remotes/kvm-probes.d/monitor_ds.sh
Symbolic link
@ -0,0 +1 @@
|
||||
../common.d/monitor_ds.sh
|
@ -1,21 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2018, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
echo HOSTNAME=`uname -n`
|
||||
|
||||
|
1
src/im_mad/remotes/kvm-probes.d/name.sh
Symbolic link
1
src/im_mad/remotes/kvm-probes.d/name.sh
Symbolic link
@ -0,0 +1 @@
|
||||
../node-probes.d/name.sh
|
@ -1,66 +0,0 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2018, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
# This option specifies the main filters for PCI card monitoring. The format
|
||||
# is the same as used by lspci to filter on PCI card by vendor:device(:class)
|
||||
# identification. Several filters can be added as a list, or separated
|
||||
# by commas. The NULL filter will retrieve all PCI cards.
|
||||
#
|
||||
# From lspci help:
|
||||
# -d [<vendor>]:[<device>][:<class>]
|
||||
# Show only devices with specified vendor, device and class ID.
|
||||
# The ID's are given in hexadecimal and may be omitted or given
|
||||
# as "*", both meaning "any value"#
|
||||
#
|
||||
# For example:
|
||||
# :filter:
|
||||
# - '10de:*' # all NVIDIA VGA cards
|
||||
# - '10de:11bf' # only GK104GL [GRID K2]
|
||||
# - '*:10d3' # only 82574L Gigabit Network cards
|
||||
# - '8086::0c03' # only Intel USB controllers
|
||||
#
|
||||
# or
|
||||
#
|
||||
# :filter: '*:*' # all devices
|
||||
#
|
||||
# or
|
||||
#
|
||||
# :filter: '0:0' # no devices
|
||||
#
|
||||
:filter: '0:0'
|
||||
|
||||
# The PCI cards list restricted by the :filter option above can be even more
|
||||
# filtered by the list of exact PCI addresses (bus:device.func).
|
||||
#
|
||||
# For example:
|
||||
# :short_address:
|
||||
# - '07:00.0'
|
||||
# - '06:00.0'
|
||||
#
|
||||
:short_address: []
|
||||
|
||||
# The PCI cards list restricted by the :filter option above can be even more
|
||||
# filtered by matching the device name against the list of regular expression
|
||||
# case-insensitive patterns.
|
||||
#
|
||||
# For example:
|
||||
# :device_name:
|
||||
# - 'Virtual Function'
|
||||
# - 'Gigabit Network'
|
||||
# - 'USB.*Host Controller'
|
||||
# - '^MegaRAID'
|
||||
#
|
||||
:device_name: []
|
1
src/im_mad/remotes/kvm-probes.d/pci.conf
Symbolic link
1
src/im_mad/remotes/kvm-probes.d/pci.conf
Symbolic link
@ -0,0 +1 @@
|
||||
../node-probes.d/pci.conf
|
@ -1,118 +0,0 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2018, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
require 'shellwords'
|
||||
require 'yaml'
|
||||
|
||||
begin
|
||||
NAME = File.join(File.dirname(__FILE__), '../../etc/im/kvm-probes.d/pci.conf')
|
||||
CONF = {
|
||||
:filter => '0:0',
|
||||
:short_address => [],
|
||||
:device_name => [],
|
||||
}.merge(YAML.load_file(NAME))
|
||||
rescue
|
||||
STDERR.puts "Invalid configuration #{NAME}"
|
||||
exit(-1)
|
||||
end
|
||||
|
||||
def get_pci(filter=nil)
|
||||
command = "lspci -mmnn"
|
||||
command << " -d #{filter}" if filter
|
||||
|
||||
text = %x(#{command})
|
||||
|
||||
text.split("\n").map {|l| Shellwords.split(l) }
|
||||
end
|
||||
|
||||
def get_name_and_id(text)
|
||||
m = text.match(/^(.*) \[(....)\]$/)
|
||||
return m[1], m[2]
|
||||
end
|
||||
|
||||
def parse_pci(pci)
|
||||
card = {}
|
||||
|
||||
card[:short_address] = pci[0]
|
||||
card[:libvirt_address] =
|
||||
"pci_0000_#{card[:short_address].gsub(/[:.]/, '_')}"
|
||||
card[:address] = "0000:#{card[:short_address].gsub(/[:.]/, ':')}"
|
||||
|
||||
card[:class_name], card[:class] = get_name_and_id(pci[1])
|
||||
card[:vendor_name], card[:vendor] = get_name_and_id(pci[2])
|
||||
card[:device_name], card[:device] = get_name_and_id(pci[3])
|
||||
|
||||
card[:bus], card[:slot], card[:function] = pci[0].split(/[:.]/)
|
||||
|
||||
card[:type] = [card[:vendor], card[:device], card[:class]].join(':')
|
||||
|
||||
card
|
||||
end
|
||||
|
||||
def get_devices(filter=nil)
|
||||
if filter
|
||||
filter = [filter].flatten.map { |f| f.split(',') }.flatten
|
||||
else
|
||||
filter = [nil]
|
||||
end
|
||||
|
||||
filter.map do |f|
|
||||
get_pci(f).map {|pci| parse_pci(pci) }
|
||||
end.flatten
|
||||
end
|
||||
|
||||
filter = CONF[:filter]
|
||||
|
||||
devices = get_devices(filter)
|
||||
|
||||
def pval(name, value)
|
||||
%Q( #{name} = "#{value}")
|
||||
end
|
||||
|
||||
devices.each do |dev|
|
||||
next if !CONF[:short_address].empty? && !CONF[:short_address].include?(dev[:short_address])
|
||||
|
||||
if !CONF[:device_name].empty?
|
||||
matched = CONF[:device_name].each { |pattern|
|
||||
break true if !(dev[:device_name] =~ /#{pattern}/i).nil?
|
||||
}
|
||||
|
||||
next if matched != true
|
||||
end
|
||||
|
||||
puts "PCI = ["
|
||||
values = [
|
||||
pval('TYPE', dev[:type]),
|
||||
pval('VENDOR', dev[:vendor]),
|
||||
pval('VENDOR_NAME', dev[:vendor_name]),
|
||||
pval('DEVICE', dev[:device]),
|
||||
pval('DEVICE_NAME', dev[:device_name]),
|
||||
pval('CLASS', dev[:class]),
|
||||
pval('CLASS_NAME', dev[:class_name]),
|
||||
pval('ADDRESS', dev[:address]),
|
||||
pval('SHORT_ADDRESS', dev[:short_address]),
|
||||
pval('DOMAIN', '0000'),
|
||||
pval('BUS', dev[:bus]),
|
||||
pval('SLOT', dev[:slot]),
|
||||
pval('FUNCTION', dev[:function])
|
||||
]
|
||||
|
||||
puts values.join(",\n")
|
||||
puts "]"
|
||||
end
|
||||
|
1
src/im_mad/remotes/kvm-probes.d/pci.rb
Symbolic link
1
src/im_mad/remotes/kvm-probes.d/pci.rb
Symbolic link
@ -0,0 +1 @@
|
||||
../node-probes.d/pci.rb
|
1
src/im_mad/remotes/kvm-probes.d/version.sh
Symbolic link
1
src/im_mad/remotes/kvm-probes.d/version.sh
Symbolic link
@ -0,0 +1 @@
|
||||
../common.d/version.sh
|
1
src/im_mad/remotes/lxd-probes.d/architecture.sh
Symbolic link
1
src/im_mad/remotes/lxd-probes.d/architecture.sh
Symbolic link
@ -0,0 +1 @@
|
||||
../node-probes.d/architecture.sh
|
1
src/im_mad/remotes/lxd-probes.d/collectd-client-shepherd.sh
Symbolic link
1
src/im_mad/remotes/lxd-probes.d/collectd-client-shepherd.sh
Symbolic link
@ -0,0 +1 @@
|
||||
../common.d/collectd-client-shepherd.sh
|
1
src/im_mad/remotes/lxd-probes.d/cpu.sh
Symbolic link
1
src/im_mad/remotes/lxd-probes.d/cpu.sh
Symbolic link
@ -0,0 +1 @@
|
||||
../node-probes.d/cpu.sh
|
99
src/im_mad/remotes/lxd-probes.d/lxd.rb
Executable file
99
src/im_mad/remotes/lxd-probes.d/lxd.rb
Executable file
@ -0,0 +1,99 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2018, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
def print_info(name, value)
|
||||
value = "0" if value.nil? or value.to_s.strip.empty?
|
||||
puts "#{name}=#{value}"
|
||||
end
|
||||
|
||||
######
|
||||
# First, get all the posible info out of virsh
|
||||
# TODO : use virsh freecell when available
|
||||
######
|
||||
|
||||
ENV['LANG'] = 'C'
|
||||
ENV['LC_ALL'] = 'C'
|
||||
|
||||
nodeinfo_text = `virsh -c qemu:///system nodeinfo`
|
||||
exit(-1) if $?.exitstatus != 0
|
||||
|
||||
nodeinfo_text.split(/\n/).each{|line|
|
||||
if line =~ /^CPU\(s\)/
|
||||
$total_cpu = line.split(':')[1].strip.to_i * 100
|
||||
elsif line =~ /^CPU frequency/
|
||||
$cpu_speed = line.split(':')[1].strip.split(' ')[0]
|
||||
elsif line =~ /^Memory size/
|
||||
$total_memory = line.split(':')[1].strip.split(' ')[0]
|
||||
end
|
||||
}
|
||||
|
||||
######
|
||||
# CPU
|
||||
######
|
||||
vmstat = `vmstat 1 2`
|
||||
$free_cpu = $total_cpu * ((vmstat.split("\n").to_a.last.split)[14].to_i)/100
|
||||
$used_cpu = $total_cpu - $free_cpu
|
||||
|
||||
######
|
||||
# MEMORY
|
||||
######
|
||||
memory = `cat /proc/meminfo`
|
||||
meminfo = Hash.new()
|
||||
memory.each_line do |line|
|
||||
key, value = line.split(':')
|
||||
meminfo[key] = /\d+/.match(value)[0].to_i
|
||||
end
|
||||
|
||||
$total_memory = meminfo['MemTotal']
|
||||
|
||||
$used_memory = meminfo['MemTotal'] - meminfo['MemFree'] - meminfo['Buffers'] - meminfo['Cached']
|
||||
$free_memory = $total_memory - $used_memory
|
||||
|
||||
######
|
||||
# INTERFACE
|
||||
######
|
||||
NETINTERFACE = 'eth|bond|em|enp|p[0-9]+p[0-9]+'
|
||||
|
||||
net_text=`cat /proc/net/dev`
|
||||
exit(-1) if $?.exitstatus != 0
|
||||
|
||||
$netrx = 0
|
||||
$nettx = 0
|
||||
|
||||
net_text.split(/\n/).each do |line|
|
||||
next unless line =~ /^ *#{NETINTERFACE}/
|
||||
|
||||
arr = line.split(':')[1].split(' ')
|
||||
$netrx += arr[0].to_i
|
||||
$nettx += arr[8].to_i
|
||||
end
|
||||
|
||||
print_info("HYPERVISOR","lxd")
|
||||
|
||||
print_info("TOTALCPU",$total_cpu)
|
||||
print_info("CPUSPEED",$cpu_speed)
|
||||
|
||||
print_info("TOTALMEMORY",$total_memory)
|
||||
print_info("USEDMEMORY",$used_memory)
|
||||
print_info("FREEMEMORY",$free_memory)
|
||||
|
||||
print_info("FREECPU",$free_cpu)
|
||||
print_info("USEDCPU",$used_cpu)
|
||||
|
||||
print_info("NETRX",$netrx)
|
||||
print_info("NETTX",$nettx)
|
1
src/im_mad/remotes/lxd-probes.d/monitor_ds.sh
Symbolic link
1
src/im_mad/remotes/lxd-probes.d/monitor_ds.sh
Symbolic link
@ -0,0 +1 @@
|
||||
../common.d/monitor_ds.sh
|
1
src/im_mad/remotes/lxd-probes.d/name.sh
Symbolic link
1
src/im_mad/remotes/lxd-probes.d/name.sh
Symbolic link
@ -0,0 +1 @@
|
||||
../node-probes.d/name.sh
|
1
src/im_mad/remotes/lxd-probes.d/pci.conf
Symbolic link
1
src/im_mad/remotes/lxd-probes.d/pci.conf
Symbolic link
@ -0,0 +1 @@
|
||||
../node-probes.d/pci.conf
|
1
src/im_mad/remotes/lxd-probes.d/pci.rb
Symbolic link
1
src/im_mad/remotes/lxd-probes.d/pci.rb
Symbolic link
@ -0,0 +1 @@
|
||||
../node-probes.d/pci.rb
|
19
src/im_mad/remotes/lxd-probes.d/poll.sh
Executable file
19
src/im_mad/remotes/lxd-probes.d/poll.sh
Executable file
@ -0,0 +1,19 @@
|
||||
#!/bin/sh
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2018, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
../../vmm/lxd/poll -t
|
1
src/im_mad/remotes/lxd-probes.d/version.sh
Symbolic link
1
src/im_mad/remotes/lxd-probes.d/version.sh
Symbolic link
@ -0,0 +1 @@
|
||||
../common.d/version.sh
|
1
src/im_mad/remotes/lxd.d/collectd-client.rb
Symbolic link
1
src/im_mad/remotes/lxd.d/collectd-client.rb
Symbolic link
@ -0,0 +1 @@
|
||||
../common.d/collectd-client.rb
|
1
src/im_mad/remotes/lxd.d/collectd-client_control.sh
Symbolic link
1
src/im_mad/remotes/lxd.d/collectd-client_control.sh
Symbolic link
@ -0,0 +1 @@
|
||||
../common.d/collectd-client_control.sh
|
19
src/im_mad/remotes/node-probes.d/architecture.sh
Executable file
19
src/im_mad/remotes/node-probes.d/architecture.sh
Executable file
@ -0,0 +1,19 @@
|
||||
#!/bin/sh
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2018, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
echo ARCH=`uname -m`
|
35
src/im_mad/remotes/node-probes.d/cpu.sh
Executable file
35
src/im_mad/remotes/node-probes.d/cpu.sh
Executable file
@ -0,0 +1,35 @@
|
||||
#!/bin/sh
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2018, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
MODEL=''
|
||||
|
||||
if [ -f /proc/cpuinfo ]; then
|
||||
for NAME in 'model name' 'cpu'; do
|
||||
MODEL=$(grep -m1 "^${NAME}[[:space:]]*:" /proc/cpuinfo | \
|
||||
cut -d: -f2 | \
|
||||
sed -e 's/^ *//')
|
||||
|
||||
if [ -n "${MODEL}" ]; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [ -n "${MODEL}" ]; then
|
||||
echo "MODELNAME=\"${MODEL}\""
|
||||
fi
|
21
src/im_mad/remotes/node-probes.d/name.sh
Executable file
21
src/im_mad/remotes/node-probes.d/name.sh
Executable file
@ -0,0 +1,21 @@
|
||||
#!/bin/sh
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2018, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
echo HOSTNAME=`uname -n`
|
||||
|
||||
|
66
src/im_mad/remotes/node-probes.d/pci.conf
Normal file
66
src/im_mad/remotes/node-probes.d/pci.conf
Normal file
@ -0,0 +1,66 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2018, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
# This option specifies the main filters for PCI card monitoring. The format
|
||||
# is the same as used by lspci to filter on PCI card by vendor:device(:class)
|
||||
# identification. Several filters can be added as a list, or separated
|
||||
# by commas. The NULL filter will retrieve all PCI cards.
|
||||
#
|
||||
# From lspci help:
|
||||
# -d [<vendor>]:[<device>][:<class>]
|
||||
# Show only devices with specified vendor, device and class ID.
|
||||
# The ID's are given in hexadecimal and may be omitted or given
|
||||
# as "*", both meaning "any value"#
|
||||
#
|
||||
# For example:
|
||||
# :filter:
|
||||
# - '10de:*' # all NVIDIA VGA cards
|
||||
# - '10de:11bf' # only GK104GL [GRID K2]
|
||||
# - '*:10d3' # only 82574L Gigabit Network cards
|
||||
# - '8086::0c03' # only Intel USB controllers
|
||||
#
|
||||
# or
|
||||
#
|
||||
# :filter: '*:*' # all devices
|
||||
#
|
||||
# or
|
||||
#
|
||||
# :filter: '0:0' # no devices
|
||||
#
|
||||
:filter: '0:0'
|
||||
|
||||
# The PCI cards list restricted by the :filter option above can be even more
|
||||
# filtered by the list of exact PCI addresses (bus:device.func).
|
||||
#
|
||||
# For example:
|
||||
# :short_address:
|
||||
# - '07:00.0'
|
||||
# - '06:00.0'
|
||||
#
|
||||
:short_address: []
|
||||
|
||||
# The PCI cards list restricted by the :filter option above can be even more
|
||||
# filtered by matching the device name against the list of regular expression
|
||||
# case-insensitive patterns.
|
||||
#
|
||||
# For example:
|
||||
# :device_name:
|
||||
# - 'Virtual Function'
|
||||
# - 'Gigabit Network'
|
||||
# - 'USB.*Host Controller'
|
||||
# - '^MegaRAID'
|
||||
#
|
||||
:device_name: []
|
121
src/im_mad/remotes/node-probes.d/pci.rb
Executable file
121
src/im_mad/remotes/node-probes.d/pci.rb
Executable file
@ -0,0 +1,121 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2018, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
require 'shellwords'
|
||||
require 'yaml'
|
||||
|
||||
begin
|
||||
probes_path = File.dirname(File.realdirpath(__FILE__))
|
||||
ETC_NAME = probes_path.split(File::SEPARATOR)[-1]
|
||||
|
||||
NAME = File.join(File.dirname(__FILE__),"../../etc/im/#{ETC_NAME}/pci.conf")
|
||||
CONF = {
|
||||
:filter => '0:0',
|
||||
:short_address => [],
|
||||
:device_name => [],
|
||||
}.merge(YAML.load_file(NAME))
|
||||
rescue
|
||||
STDERR.puts "Invalid configuration #{NAME}"
|
||||
exit(-1)
|
||||
end
|
||||
|
||||
def get_pci(filter=nil)
|
||||
command = "lspci -mmnn"
|
||||
command << " -d #{filter}" if filter
|
||||
|
||||
text = %x(#{command})
|
||||
|
||||
text.split("\n").map {|l| Shellwords.split(l) }
|
||||
end
|
||||
|
||||
def get_name_and_id(text)
|
||||
m = text.match(/^(.*) \[(....)\]$/)
|
||||
return m[1], m[2]
|
||||
end
|
||||
|
||||
def parse_pci(pci)
|
||||
card = {}
|
||||
|
||||
card[:short_address] = pci[0]
|
||||
card[:libvirt_address] =
|
||||
"pci_0000_#{card[:short_address].gsub(/[:.]/, '_')}"
|
||||
card[:address] = "0000:#{card[:short_address].gsub(/[:.]/, ':')}"
|
||||
|
||||
card[:class_name], card[:class] = get_name_and_id(pci[1])
|
||||
card[:vendor_name], card[:vendor] = get_name_and_id(pci[2])
|
||||
card[:device_name], card[:device] = get_name_and_id(pci[3])
|
||||
|
||||
card[:bus], card[:slot], card[:function] = pci[0].split(/[:.]/)
|
||||
|
||||
card[:type] = [card[:vendor], card[:device], card[:class]].join(':')
|
||||
|
||||
card
|
||||
end
|
||||
|
||||
def get_devices(filter=nil)
|
||||
if filter
|
||||
filter = [filter].flatten.map { |f| f.split(',') }.flatten
|
||||
else
|
||||
filter = [nil]
|
||||
end
|
||||
|
||||
filter.map do |f|
|
||||
get_pci(f).map {|pci| parse_pci(pci) }
|
||||
end.flatten
|
||||
end
|
||||
|
||||
filter = CONF[:filter]
|
||||
|
||||
devices = get_devices(filter)
|
||||
|
||||
def pval(name, value)
|
||||
%Q( #{name} = "#{value}")
|
||||
end
|
||||
|
||||
devices.each do |dev|
|
||||
next if !CONF[:short_address].empty? && !CONF[:short_address].include?(dev[:short_address])
|
||||
|
||||
if !CONF[:device_name].empty?
|
||||
matched = CONF[:device_name].each { |pattern|
|
||||
break true if !(dev[:device_name] =~ /#{pattern}/i).nil?
|
||||
}
|
||||
|
||||
next if matched != true
|
||||
end
|
||||
|
||||
puts "PCI = ["
|
||||
values = [
|
||||
pval('TYPE', dev[:type]),
|
||||
pval('VENDOR', dev[:vendor]),
|
||||
pval('VENDOR_NAME', dev[:vendor_name]),
|
||||
pval('DEVICE', dev[:device]),
|
||||
pval('DEVICE_NAME', dev[:device_name]),
|
||||
pval('CLASS', dev[:class]),
|
||||
pval('CLASS_NAME', dev[:class_name]),
|
||||
pval('ADDRESS', dev[:address]),
|
||||
pval('SHORT_ADDRESS', dev[:short_address]),
|
||||
pval('DOMAIN', '0000'),
|
||||
pval('BUS', dev[:bus]),
|
||||
pval('SLOT', dev[:slot]),
|
||||
pval('FUNCTION', dev[:function])
|
||||
]
|
||||
|
||||
puts values.join(",\n")
|
||||
puts "]"
|
||||
end
|
||||
|
128
src/vmm_mad/remotes/lib/lxd/client.rb
Normal file
128
src/vmm_mad/remotes/lib/lxd/client.rb
Normal file
@ -0,0 +1,128 @@
|
||||
#!/usr/bin/ruby
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2018, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
require 'net/http'
|
||||
require 'socket'
|
||||
require 'json'
|
||||
|
||||
#
|
||||
# LXD API Client. This class is used to interact with LXD. Wraps API calls
|
||||
# through the REST API
|
||||
#
|
||||
class LXDClient
|
||||
|
||||
# API Configuration Attributes
|
||||
|
||||
API = '/1.0'.freeze
|
||||
HEADER = { 'Host' => 'localhost' }.freeze
|
||||
|
||||
SOCK_PATH = '/var/lib/lxd/unix.socket'
|
||||
|
||||
# Enable communication with LXD via unix socket
|
||||
begin
|
||||
SOCK = Net::BufferedIO.new(UNIXSocket.new(SOCK_PATH))
|
||||
rescue StandardError
|
||||
STDERR.puts('Could not open LXD socket')
|
||||
Process.exit(1)
|
||||
end
|
||||
|
||||
# Performs HTTP::Get
|
||||
# Params:
|
||||
# +uri+:: +string+ API path
|
||||
def get(uri)
|
||||
get_response(Net::HTTP::Get.new("#{API}/#{uri}", HEADER), data = nil)
|
||||
end
|
||||
|
||||
# Performs HTTP::Delete
|
||||
# Params:
|
||||
# +uri+:: +string+ API path
|
||||
def delete(uri)
|
||||
get_response(Net::HTTP::Delete.new("#{API}/#{uri}", HEADER), data = nil)
|
||||
end
|
||||
|
||||
# Performs HTTP::Put
|
||||
# Params:
|
||||
# +uri+:: +string+ API path
|
||||
def put(uri, data)
|
||||
get_response(Net::HTTP::Put.new("#{API}/#{uri}", HEADER), data)
|
||||
end
|
||||
|
||||
# Performs HTTP::Post
|
||||
# Params:
|
||||
# +uri+:: +string+ API path
|
||||
def post(uri, data)
|
||||
get_response(Net::HTTP::Post.new("#{API}/#{uri}", HEADER), data)
|
||||
end
|
||||
|
||||
# Performs HTTP::Patch
|
||||
# Params:
|
||||
# +uri+:: +string+ API path
|
||||
def patch(uri, data)
|
||||
get_response(Net::HTTP::Patch.new("#{API}/#{uri}", HEADER), data)
|
||||
end
|
||||
|
||||
# Waits for an operation returned in response to be completed
|
||||
def wait(response, timeout)
|
||||
operation_id = response['operation'].split('/').last
|
||||
|
||||
timeout = "?timeout=#{timeout}" if timeout
|
||||
|
||||
response = get("operations/#{operation_id}/wait#{timeout}")
|
||||
|
||||
raise LXDError, response if response['metadata']['status'] == 'Failure'
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Returns the HTTPResponse body as a hash
|
||||
# Params:
|
||||
# +request+:: +Net::HTTP::Request+ made to the http server
|
||||
# +data+:: +string+ for post/put/patch requests that send data to the server
|
||||
# (may be nil)
|
||||
|
||||
def get_response(request, data)
|
||||
request.body = JSON.dump(data) unless data.nil?
|
||||
|
||||
request.exec(SOCK, '1.1', request.path)
|
||||
|
||||
response = nil
|
||||
|
||||
loop do
|
||||
response = Net::HTTPResponse.read_new(SOCK)
|
||||
break unless response.is_a?(Net::HTTPContinue)
|
||||
end
|
||||
|
||||
response.reading_body(SOCK, request.response_body_permitted?) {}
|
||||
|
||||
response = JSON.parse(response.body)
|
||||
|
||||
raise LXDError, response if response['type'] == 'error'
|
||||
|
||||
response
|
||||
end
|
||||
end
|
||||
|
||||
# Error used for raising LXDClient exception when response is error return value
|
||||
class LXDError < StandardError
|
||||
attr_reader :body
|
||||
|
||||
def initialize(msg = 'LXD API error')
|
||||
@body = msg
|
||||
super
|
||||
end
|
||||
end
|
77
src/vmm_mad/remotes/lib/lxd/command.rb
Normal file
77
src/vmm_mad/remotes/lib/lxd/command.rb
Normal file
@ -0,0 +1,77 @@
|
||||
#!/usr/bin/ruby
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2018, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
require 'open3'
|
||||
|
||||
# This module can be used to execute commands. It wraps popen3 and provides
|
||||
# locking capabilites using flock
|
||||
module Command
|
||||
LOCK_FILE = '/tmp/onelxd-lock'
|
||||
|
||||
def self.execute(cmd, block)
|
||||
rc = -1
|
||||
stdout = ''
|
||||
stderr = ''
|
||||
|
||||
begin
|
||||
fd = lock if block
|
||||
|
||||
Open3.popen3(cmd) { |i, o, e, t|
|
||||
rc = t.value.exitstatus
|
||||
|
||||
stdout = o.read
|
||||
stderr = e.read
|
||||
|
||||
o.close
|
||||
e.close
|
||||
}
|
||||
rescue
|
||||
|
||||
ensure
|
||||
unlock(fd) if block
|
||||
end
|
||||
|
||||
[rc, stdout, stderr]
|
||||
end
|
||||
|
||||
def self.execute_once(cmd, lock)
|
||||
execute(cmd, lock) unless running?(cmd.split[0])
|
||||
end
|
||||
|
||||
def self.lxc_execute(lxd_id, cmd)
|
||||
cmd = "lxc exec #{lxd_id} -- #{cmd}"
|
||||
execute(cmd, true)
|
||||
end
|
||||
|
||||
# Return true if command is running
|
||||
def self.running?(command)
|
||||
!`ps --noheaders -C #{command}`.empty?
|
||||
end
|
||||
|
||||
def self.lock
|
||||
lfd = File.open(LOCK_FILE,"w")
|
||||
lfd.flock(File::LOCK_EX)
|
||||
|
||||
return lfd
|
||||
end
|
||||
|
||||
def self.unlock(lfd)
|
||||
lfd.close
|
||||
end
|
||||
end
|
||||
|
418
src/vmm_mad/remotes/lib/lxd/container.rb
Normal file
418
src/vmm_mad/remotes/lib/lxd/container.rb
Normal file
@ -0,0 +1,418 @@
|
||||
#!/usr/bin/ruby
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2018, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
$LOAD_PATH.unshift File.dirname(__FILE__)
|
||||
|
||||
require 'client'
|
||||
|
||||
require 'opennebula_vm'
|
||||
require 'command'
|
||||
|
||||
require 'mapper'
|
||||
require 'raw'
|
||||
require 'qcow2'
|
||||
require 'rbd'
|
||||
|
||||
# This class interacts with the LXD container on REST level
|
||||
class Container
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Class Constants API and Containers Paths
|
||||
#---------------------------------------------------------------------------
|
||||
CONTAINERS = 'containers'.freeze
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Methods to access container attributes
|
||||
#---------------------------------------------------------------------------
|
||||
CONTAINER_ATTRIBUTES = %w[name status status_code devices config profile
|
||||
expanded_config expanded_devices architecture].freeze
|
||||
|
||||
CONTAINER_ATTRIBUTES.each do |attr|
|
||||
define_method(attr.to_sym) do
|
||||
@lxc[attr]
|
||||
end
|
||||
|
||||
define_method("#{attr}=".to_sym) do |value|
|
||||
@lxc[attr] = value
|
||||
end
|
||||
end
|
||||
|
||||
# Return if this is a wild container. Needs the associated OpenNebulaVM
|
||||
# description
|
||||
def wild?
|
||||
@one.wild? if @one
|
||||
end
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Class constructors & static methods
|
||||
#---------------------------------------------------------------------------
|
||||
# Creates the container object in memory.
|
||||
# Can be later created in LXD using create method
|
||||
def initialize(lxc, one, client)
|
||||
@client = client
|
||||
|
||||
@lxc = lxc
|
||||
@one = one
|
||||
end
|
||||
|
||||
class << self
|
||||
|
||||
# Returns specific container, by its name
|
||||
# Params:
|
||||
# +name+:: container name
|
||||
def get(name, one_xml, client)
|
||||
info = client.get("#{CONTAINERS}/#{name}")['metadata']
|
||||
|
||||
one = nil
|
||||
one = OpenNebulaVM.new(one_xml) if one_xml
|
||||
|
||||
Container.new(info, one, client)
|
||||
rescue LXDError => exception
|
||||
raise exception
|
||||
end
|
||||
|
||||
# Creates container from a OpenNebula VM xml description
|
||||
def new_from_xml(one_xml, client)
|
||||
one = OpenNebulaVM.new(one_xml)
|
||||
|
||||
Container.new(one.to_lxc, one, client)
|
||||
end
|
||||
|
||||
# Returns an array of container objects
|
||||
def get_all(client)
|
||||
containers = []
|
||||
|
||||
container_names = client.get(CONTAINERS)['metadata']
|
||||
container_names.each do |name|
|
||||
name = name.split('/').last
|
||||
containers.push(get(name, nil, client))
|
||||
end
|
||||
|
||||
containers
|
||||
end
|
||||
|
||||
# Returns boolean indicating if the container exists(true) or not (false)
|
||||
def exist?(name, client)
|
||||
client.get("#{CONTAINERS}/#{name}")
|
||||
true
|
||||
rescue LXDError => exception
|
||||
raise exception if exception.body['error_code'] != 404
|
||||
|
||||
false
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Container Management & Monitor
|
||||
#---------------------------------------------------------------------------
|
||||
# Create a container without a base image
|
||||
def create(wait: true, timeout: '')
|
||||
@lxc['source'] = { 'type' => 'none' }
|
||||
wait?(@client.post(CONTAINERS, @lxc), wait, timeout)
|
||||
|
||||
@lxc = @client.get("#{CONTAINERS}/#{name}")['metadata']
|
||||
end
|
||||
|
||||
# Delete container
|
||||
def delete(wait: true, timeout: '')
|
||||
wait?(@client.delete("#{CONTAINERS}/#{name}"), wait, timeout)
|
||||
end
|
||||
|
||||
# Updates the container in LXD server with the new configuration
|
||||
def update(wait: true, timeout: '')
|
||||
wait?(@client.put("#{CONTAINERS}/#{name}", @lxc), wait, timeout)
|
||||
end
|
||||
|
||||
# Returns the container current state
|
||||
def monitor
|
||||
@client.get("#{CONTAINERS}/#{name}/state")
|
||||
end
|
||||
|
||||
# Retreive metadata for the container
|
||||
def get_metadata
|
||||
@lxc = @client.get("#{CONTAINERS}/#{name}")['metadata']
|
||||
end
|
||||
|
||||
# Runs command inside container
|
||||
# @param command [String] to execute through lxc exec
|
||||
def exec(command)
|
||||
Command.lxd_execute(name, command)
|
||||
end
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Contianer Status Control
|
||||
#---------------------------------------------------------------------------
|
||||
def start(options = {})
|
||||
change_state(__method__, options)
|
||||
end
|
||||
|
||||
def stop(options = {})
|
||||
change_state(__method__, options)
|
||||
end
|
||||
|
||||
def restart(options = {})
|
||||
change_state(__method__, options)
|
||||
end
|
||||
|
||||
def freeze(options = {})
|
||||
change_state(__method__, options)
|
||||
end
|
||||
|
||||
def unfreeze(options = {})
|
||||
change_state(__method__, options)
|
||||
end
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Container Networking
|
||||
#---------------------------------------------------------------------------
|
||||
def attach_nic(mac)
|
||||
return unless @one
|
||||
|
||||
nic_xml = @one.get_nic_by_mac(mac)
|
||||
|
||||
return unless nic_xml
|
||||
|
||||
nic_config = @one.nic(nic_xml)
|
||||
|
||||
@lxc['devices'].update(nic_config)
|
||||
|
||||
update
|
||||
end
|
||||
|
||||
def detach_nic(mac)
|
||||
@lxc['devices'].delete_if do |device, config|
|
||||
device.include?('eth') && config['hwaddr'] == mac
|
||||
end
|
||||
|
||||
update
|
||||
end
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Container Storage
|
||||
#---------------------------------------------------------------------------
|
||||
# Sets up the container mounts for type: disk devices.
|
||||
def setup_storage(operation)
|
||||
return unless @one
|
||||
|
||||
@one.get_disks.each do |disk|
|
||||
setup_disk(disk, operation)
|
||||
end
|
||||
|
||||
return unless @one.has_context?
|
||||
|
||||
csrc = @lxc['devices']['context']['source'].clone
|
||||
|
||||
context = @one.get_context_disk
|
||||
mapper = FSRawMapper.new
|
||||
|
||||
context_path = "#{@one.lxdrc[:containers]}/#{name}/rootfs/context"
|
||||
create_context_dir = "#{Mapper::COMMANDS[:su_mkdir]} #{context_path}"
|
||||
|
||||
Command.execute(create_context_dir, false)
|
||||
|
||||
mapper.public_send(operation, @one, context, csrc)
|
||||
end
|
||||
|
||||
# Generate the context devices and maps the context the device
|
||||
def attach_context
|
||||
@one.context(@lxc['devices'])
|
||||
|
||||
csrc = @lxc['devices']['context']['source'].clone
|
||||
|
||||
context = @one.get_context_disk
|
||||
mapper = FSRawMapper.new
|
||||
|
||||
mapper.map(@one, context, csrc)
|
||||
|
||||
update
|
||||
end
|
||||
|
||||
# Removes the context section from the LXD configuration and unmap the
|
||||
# context device
|
||||
def detach_context
|
||||
return unless @one.has_context?
|
||||
|
||||
csrc = @lxc['devices']['context']['source'].clone
|
||||
|
||||
@lxc['devices'].delete('context')['source']
|
||||
|
||||
update
|
||||
|
||||
context = @one.get_context_disk
|
||||
mapper = FSRawMapper.new
|
||||
|
||||
mapper.unmap(@one, context, csrc)
|
||||
end
|
||||
|
||||
# Attach disk to container (ATTACH = YES) in VM description
|
||||
def attach_disk(source)
|
||||
disk_element = hotplug_disk
|
||||
return unless disk_element
|
||||
|
||||
setup_disk(disk_element, 'map')
|
||||
|
||||
source2 = source.dup
|
||||
if source
|
||||
mapper_location = source2.index('/disk.')
|
||||
source2.insert(mapper_location, '/mapper')
|
||||
end
|
||||
|
||||
disk_hash = @one.disk(disk_element, source2, nil)
|
||||
|
||||
@lxc['devices'].update(disk_hash)
|
||||
|
||||
update
|
||||
end
|
||||
|
||||
# Detects disk being hotplugged
|
||||
def hotplug_disk
|
||||
return unless @one
|
||||
|
||||
disk_a = @one.get_disks.select do |disk|
|
||||
disk['ATTACH'].casecmp('YES').zero?
|
||||
end
|
||||
|
||||
disk_a.first
|
||||
end
|
||||
|
||||
# Detach disk to container (ATTACH = YES) in VM description
|
||||
def detach_disk
|
||||
disk_element = hotplug_disk
|
||||
return unless disk_element
|
||||
|
||||
disk_name = "disk#{disk_element['DISK_ID']}"
|
||||
|
||||
csrc = @lxc['devices'][disk_name]['source'].clone
|
||||
|
||||
|
||||
@lxc['devices'].delete(disk_name)['source']
|
||||
|
||||
update
|
||||
|
||||
mapper = new_disk_mapper(@one, disk_element)
|
||||
mapper.unmap(@one, disk_element, csrc)
|
||||
end
|
||||
|
||||
# Setup the disk by mapping/unmapping the disk device
|
||||
def setup_disk(disk, operation)
|
||||
return unless @one
|
||||
|
||||
ds_path = @one.ds_path
|
||||
ds_id = @one.sysds_id
|
||||
|
||||
vm_id = @one.vm_id
|
||||
disk_id = disk['DISK_ID']
|
||||
|
||||
if disk_id == @one.rootfs_id
|
||||
target = "#{@one.lxdrc[:containers]}/#{name}/rootfs"
|
||||
else
|
||||
target = @one.disk_mountpoint(disk_id)
|
||||
end
|
||||
|
||||
mapper = new_disk_mapper(disk)
|
||||
mapper.public_send(operation, @one, disk, target)
|
||||
end
|
||||
|
||||
# Start the svncterm server if it is down.
|
||||
def vnc(signal)
|
||||
command = @one.vnc_command(signal)
|
||||
return if command.nil?
|
||||
|
||||
w = @one.lxdrc[:vnc][:width]
|
||||
h = @one.lxdrc[:vnc][:height]
|
||||
t = @one.lxdrc[:vnc][:timeout]
|
||||
|
||||
vnc_args = "-w #{w} -h #{h} -t #{t}"
|
||||
|
||||
pipe = '/tmp/svncterm_server_pipe'
|
||||
bin = 'svncterm_server'
|
||||
server = "#{bin} #{vnc_args}"
|
||||
|
||||
Command.execute_once(server, true)
|
||||
|
||||
lfd = Command.lock
|
||||
|
||||
File.open(pipe, 'a') do |f|
|
||||
f.write command
|
||||
end
|
||||
|
||||
ensure
|
||||
Command.unlock(lfd) if lfd
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Waits or no for response depending on wait value
|
||||
def wait?(response, wait, timeout)
|
||||
@client.wait(response, timeout) unless wait == false
|
||||
end
|
||||
|
||||
# Performs an action on the container that changes the execution status.
|
||||
# Accepts optional args
|
||||
def change_state(action, options)
|
||||
options.update(:action => action)
|
||||
|
||||
response = @client.put("#{CONTAINERS}/#{name}/state", options)
|
||||
wait?(response, options[:wait], options[:timeout])
|
||||
|
||||
@lxc = @client.get("#{CONTAINERS}/#{name}")['metadata']
|
||||
|
||||
status
|
||||
end
|
||||
|
||||
# Returns a mapper for the disk
|
||||
# @param disk [XMLElement] with the disk data
|
||||
#
|
||||
# TODO This maps should be built dynamically or based on a DISK attribute
|
||||
# so new mappers does not need to modified source code
|
||||
def new_disk_mapper(disk)
|
||||
case disk['TYPE']
|
||||
when 'FILE'
|
||||
ds_path = @one.ds_path
|
||||
ds_id = @one.sysds_id
|
||||
|
||||
vm_id = @one.vm_id
|
||||
disk_id = disk['DISK_ID']
|
||||
|
||||
ds = "#{ds_path}/#{ds_id}/#{vm_id}/disk.#{disk_id}"
|
||||
|
||||
Command.execute("#{Mapper::COMMANDS[:chmod_nfs]} #{ds}", false)
|
||||
|
||||
_rc, out, _err = Command.execute("#{Mapper::COMMANDS[:file]} #{ds}", false)
|
||||
|
||||
case out
|
||||
when /.*QEMU QCOW.*/
|
||||
OpenNebula.log "Using qcow2 mapper for #{ds}"
|
||||
return Qcow2Mapper.new
|
||||
when /.*filesystem.*/
|
||||
OpenNebula.log "Using raw filesystem mapper for #{ds}"
|
||||
return FSRawMapper.new
|
||||
when /.*boot sector.*/
|
||||
OpenNebula.log "Using raw disk mapper for #{ds}"
|
||||
return DiskRawMapper.new
|
||||
else
|
||||
OpenNebula.log('Unknown image format, trying raw filesystem mapper')
|
||||
return FSRawMapper.new
|
||||
end
|
||||
when 'RBD'
|
||||
RBDMapper.new
|
||||
end
|
||||
end
|
||||
|
||||
end
|
413
src/vmm_mad/remotes/lib/lxd/mapper/mapper.rb
Normal file
413
src/vmm_mad/remotes/lib/lxd/mapper/mapper.rb
Normal file
@ -0,0 +1,413 @@
|
||||
#!/usr/bin/ruby
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2018, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
$LOAD_PATH.unshift File.dirname(__FILE__)
|
||||
|
||||
require 'fileutils'
|
||||
require 'json'
|
||||
|
||||
require 'opennebula_vm'
|
||||
require 'command'
|
||||
|
||||
# Mappers class provides an interface to map devices into the host filesystem
|
||||
# This class uses an array of partitions as output by lsblk in JSON:
|
||||
# [
|
||||
# {
|
||||
# "name" : "loop1p3",
|
||||
# "path" : "/dev/mapper/loop1p3",
|
||||
# "type" : "part",
|
||||
# "fstype" : "..",
|
||||
# "label" : null,
|
||||
# "uuid" : null,
|
||||
# "fsavail": "...M",
|
||||
# "fsuse%" : "..%",
|
||||
# "mountpoint":"/boot"
|
||||
# },
|
||||
# {
|
||||
# ....
|
||||
# children : [
|
||||
# ]
|
||||
# }
|
||||
# ]
|
||||
class Mapper
|
||||
#---------------------------------------------------------------------------
|
||||
# Class constants
|
||||
# - COMMANDS list of commands executed by the driver. This list can
|
||||
# be tunned to specific paths. It contians the list of commands executed
|
||||
# as root
|
||||
#---------------------------------------------------------------------------
|
||||
COMMANDS = {
|
||||
:lsblk => 'sudo lsblk',
|
||||
:losetup => 'sudo losetup',
|
||||
:mount => 'sudo mount',
|
||||
:umount => 'sudo umount',
|
||||
:kpartx => 'sudo kpartx',
|
||||
:nbd => 'sudo qemu-nbd',
|
||||
:su_mkdir => 'sudo mkdir -p',
|
||||
:mkdir => 'mkdir -p',
|
||||
:cat => 'sudo cat',
|
||||
:file => 'file -L',
|
||||
:blkid => 'sudo blkid',
|
||||
:e2fsck => 'sudo e2fsck',
|
||||
:resize2fs => 'sudo resize2fs',
|
||||
:xfs_growfs => 'sudo xfs_growfs',
|
||||
:chmod_nfs => 'chmod o+w'
|
||||
}
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Interface to be implemented by specific mapper modules
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# Maps the disk to host devices
|
||||
# @param onevm [OpenNebulaVM] with the VM description
|
||||
# @param disk [XMLElement] with the disk data
|
||||
# @param directory [String] where the disk has to be mounted
|
||||
# @return [String] Name of the mapped device, empty in case of error.
|
||||
#
|
||||
# Errors should be log using OpenNebula driver functions
|
||||
def do_map(one_vm, disk, directory)
|
||||
OpenNebula.log_error("map function not implemented for #{self.class}")
|
||||
return nil
|
||||
end
|
||||
|
||||
# Unmaps a previously mapped partition
|
||||
# @param device [String] where the disk is mapped
|
||||
# @param disk [XMLElement] with the disk data
|
||||
# @param directory [String] where the disk has to be mounted
|
||||
#
|
||||
# @return nil
|
||||
def do_unmap(device, one_vm, disk, directory)
|
||||
OpenNebula.log_error("unmap function not implemented for #{self.class}")
|
||||
return nil
|
||||
end
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Mapper Interface 'map' & 'unmap' methods
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# Maps a disk to a given directory
|
||||
# @param onevm [OpenNebulaVM] with the VM description
|
||||
# @param disk [XMLElement] with the disk data
|
||||
# @param directory [String] Path to the directory where the disk has to be
|
||||
# mounted. Example: /var/lib/one/datastores/100/3/mapper/disk.2
|
||||
#
|
||||
# @return true on success
|
||||
def map(one_vm, disk, directory)
|
||||
device = do_map(one_vm, disk, directory)
|
||||
|
||||
OpenNebula.log_info "Mapping disk at #{directory} using device #{device}"
|
||||
|
||||
return false if !device
|
||||
|
||||
partitions = lsblk(device)
|
||||
|
||||
return false if !partitions
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Mount disk images with partitions
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
return mount(partitions, directory) if partitions[0]['type'] == 'part'
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Resize partitions if needed and mount single filesystem disk images
|
||||
#-----------------------------------------------------------------------
|
||||
type = partitions[0]['type']
|
||||
|
||||
return mount_dev(device, directory) unless %w[loop disk].include?(type)
|
||||
|
||||
size = disk['SIZE'].to_i if disk['SIZE']
|
||||
osize = disk['ORIGINAL_SIZE'].to_i if disk['ORIGINAL_SIZE']
|
||||
|
||||
# TODO: Osize is always < size after 1st resize during deployment
|
||||
return mount_dev(device, directory) unless size > osize
|
||||
|
||||
# Resize filesystem
|
||||
cmd = "#{COMMANDS[:blkid]} -o export #{device}"
|
||||
_rc, o, _e = Command.execute(cmd, false)
|
||||
|
||||
fs_type = ''
|
||||
|
||||
o.each_line {|l|
|
||||
next unless (m = l.match(/TYPE=(.*)/))
|
||||
|
||||
fs_type = m[1]
|
||||
break
|
||||
}
|
||||
|
||||
rc = true
|
||||
|
||||
OpenNebula.log_info "Resizing filesystem #{fs_type} on #{device}"
|
||||
|
||||
case fs_type
|
||||
when /xfs/
|
||||
rc = mount_dev(device, directory)
|
||||
return false unless rc
|
||||
|
||||
Command.execute("#{COMMANDS[:xfs_growfs]} -d #{directory}", false)
|
||||
when /ext/
|
||||
Command.execute("#{COMMANDS[:e2fsck]} -f -y #{device}", false)
|
||||
Command.execute("#{COMMANDS[:resize2fs]} #{device}", false)
|
||||
rc = mount_dev(device, directory)
|
||||
else
|
||||
OpenNebula.log_info "Skipped filesystem #{fs_type} resize"
|
||||
rc = mount_dev(device, directory)
|
||||
end
|
||||
|
||||
rc
|
||||
end
|
||||
|
||||
# Unmaps a disk from a given directory
|
||||
# @param disk [XMLElement] with the disk data
|
||||
# @param directory [String] Path to the directory where the disk has to be
|
||||
# mounted. Example: /var/lib/one/datastores/100/3/mapper/disk.2
|
||||
#
|
||||
# @return true on success
|
||||
def unmap(one_vm, disk, directory)
|
||||
OpenNebula.log_info "Unmapping disk at #{directory}"
|
||||
|
||||
sys_parts = lsblk('')
|
||||
partitions = []
|
||||
device = ''
|
||||
|
||||
return false if !sys_parts
|
||||
|
||||
sys_parts.each { |d|
|
||||
if d['mountpoint'] == directory
|
||||
partitions = [d]
|
||||
device = d['path']
|
||||
break
|
||||
end
|
||||
|
||||
d['children'].each { |c|
|
||||
if c['mountpoint'] == directory
|
||||
partitions = d['children']
|
||||
device = d['path']
|
||||
break
|
||||
end
|
||||
} if d['children']
|
||||
|
||||
break if !partitions.empty?
|
||||
}
|
||||
|
||||
partitions.delete_if { |p| !p['mountpoint'] }
|
||||
|
||||
partitions.sort! { |a,b|
|
||||
b['mountpoint'].length <=> a['mountpoint'].length
|
||||
}
|
||||
|
||||
umount(partitions)
|
||||
|
||||
do_unmap(device, one_vm, disk, directory)
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
private
|
||||
#---------------------------------------------------------------------------
|
||||
# Methods to mount/umount partitions
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# Umounts partitions
|
||||
# @param partitions [Array] with partition device names
|
||||
def umount(partitions)
|
||||
partitions.each { |p|
|
||||
next if !p['mountpoint']
|
||||
|
||||
umount_dev(p['path'])
|
||||
}
|
||||
end
|
||||
|
||||
# Mounts partitions
|
||||
# @param partitions [Array] with partition device names
|
||||
# @param path [String] to directory to mount the disk partitions
|
||||
def mount(partitions, path)
|
||||
# Single partition
|
||||
# ----------------
|
||||
return mount_dev(partitions[0]['path'], path) if partitions.size == 1
|
||||
|
||||
# Multiple partitions
|
||||
# -------------------
|
||||
rc = true
|
||||
fstab = ''
|
||||
|
||||
# Look for fstab and mount rootfs in path. First partition with
|
||||
# a /etc/fstab file is used as rootfs and it is kept mounted
|
||||
partitions.each do |p|
|
||||
rc = mount_dev(p['path'], path)
|
||||
|
||||
return false if !rc
|
||||
|
||||
cmd = "#{COMMANDS[:cat]} #{path}/etc/fstab"
|
||||
|
||||
rc, fstab, e = Command.execute(cmd, false)
|
||||
|
||||
if fstab.empty?
|
||||
umount_dev(p['path'])
|
||||
next
|
||||
end
|
||||
|
||||
break
|
||||
end
|
||||
|
||||
if fstab.empty?
|
||||
OpenNebula.log_error("mount: No fstab file found in disk partitions")
|
||||
return false
|
||||
end
|
||||
|
||||
# Parse fstab contents & mount partitions
|
||||
fstab.each_line do |l|
|
||||
next if l.strip.chomp.empty?
|
||||
next if l =~ /\s*#/
|
||||
|
||||
fs, mount_point, type, opts, dump, pass = l.split
|
||||
|
||||
if l =~ /^\s*LABEL=/ # disk by LABEL
|
||||
value = fs.split("=").last.strip.chomp
|
||||
key = 'label'
|
||||
elsif l =~ /^\s*UUID=/ #disk by UUID
|
||||
value = fs.split("=").last.strip.chomp
|
||||
key = 'uuid'
|
||||
else #disk by device - NOT SUPPORTED or other FS
|
||||
next
|
||||
end
|
||||
|
||||
next if mount_point == '/' || mount_point == 'swap'
|
||||
|
||||
partitions.each { |p|
|
||||
next if p[key] != value
|
||||
|
||||
rc = mount_dev(p['path'], path + mount_point)
|
||||
return false if !rc
|
||||
break
|
||||
}
|
||||
end
|
||||
|
||||
return rc
|
||||
end
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# Functions to mount/umount devices
|
||||
# --------------------------------------------------------------------------
|
||||
|
||||
# Mount the given device. It creates the directory if need. NOTE: The rootfs
|
||||
# dir is created as root as it is typically under lxd/storage-pools and it
|
||||
# is managed by LXD
|
||||
# @param dev [String] device name
|
||||
# @param path [String] to mount the device
|
||||
#
|
||||
# @return true on success
|
||||
def mount_dev(dev, path)
|
||||
OpenNebula.log_info "Mounting #{dev} at #{path}"
|
||||
|
||||
if path =~ /.*\/rootfs/
|
||||
cmd = COMMANDS[:su_mkdir]
|
||||
else
|
||||
cmd = COMMANDS[:mkdir]
|
||||
end
|
||||
|
||||
Command.execute("#{cmd} #{path}", false)
|
||||
|
||||
rc, out, err = Command.execute("#{COMMANDS[:mount]} #{dev} #{path}",true)
|
||||
|
||||
if rc != 0
|
||||
OpenNebula.log_error("mount_dev: #{err}")
|
||||
return false
|
||||
end
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
def umount_dev(dev)
|
||||
OpenNebula.log_info "Umounting disk mapped at #{dev}"
|
||||
|
||||
Command.execute("#{COMMANDS[:umount]} #{dev}", true)
|
||||
end
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Mapper helper functions
|
||||
#---------------------------------------------------------------------------
|
||||
# Get the partitions on the system or device
|
||||
# @param device [String] to get the partitions from. Use and empty string
|
||||
# for host partitions
|
||||
# @return [Hash] with partitions
|
||||
def lsblk(device)
|
||||
rc, o, e = Command.execute("#{COMMANDS[:lsblk]} -OJ #{device}", false)
|
||||
|
||||
if rc != 0 || o.empty?
|
||||
OpenNebula.log_error("lsblk: #{e}")
|
||||
return nil
|
||||
end
|
||||
|
||||
partitions = nil
|
||||
|
||||
begin
|
||||
partitions = JSON.parse(o)['blockdevices']
|
||||
|
||||
if !device.empty?
|
||||
partitions = partitions[0]
|
||||
|
||||
if partitions['children']
|
||||
partitions = partitions['children']
|
||||
else
|
||||
partitions = [partitions]
|
||||
end
|
||||
|
||||
partitions.delete_if { |p|
|
||||
p['fstype'].casecmp?('swap') if p['fstype']
|
||||
}
|
||||
end
|
||||
rescue
|
||||
OpenNebula.log_error("lsblk: error parsing lsblk -OJ #{device}")
|
||||
return nil
|
||||
end
|
||||
|
||||
# Fix for lsblk paths for version < 2.33
|
||||
partitions.each { |p|
|
||||
lsblk_path(p)
|
||||
|
||||
p['children'].each { |q| lsblk_path(q) } if p['children']
|
||||
}
|
||||
|
||||
partitions
|
||||
end
|
||||
|
||||
# @return [String] the canonical disk path for the given disk
|
||||
def disk_source(one_vm, disk)
|
||||
ds_path = one_vm.ds_path
|
||||
ds_id = one_vm.sysds_id
|
||||
|
||||
vm_id = one_vm.vm_id
|
||||
disk_id = disk['DISK_ID']
|
||||
|
||||
"#{ds_path}/#{ds_id}/#{vm_id}/disk.#{disk_id}"
|
||||
end
|
||||
|
||||
# Adds path to the partition Hash. This is needed for lsblk version < 2.33
|
||||
def lsblk_path(p)
|
||||
return unless !p['path'] && p['name']
|
||||
|
||||
if File.exists?("/dev/#{p['name']}")
|
||||
p['path'] = "/dev/#{p['name']}"
|
||||
elsif File.exists?("/dev/mapper/#{p['name']}")
|
||||
p['path'] = "/dev/mapper/#{p['name']}"
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
86
src/vmm_mad/remotes/lib/lxd/mapper/qcow2.rb
Normal file
86
src/vmm_mad/remotes/lib/lxd/mapper/qcow2.rb
Normal file
@ -0,0 +1,86 @@
|
||||
#!/usr/bin/ruby
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2018, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
$LOAD_PATH.unshift File.dirname(__FILE__)
|
||||
|
||||
require 'mapper'
|
||||
|
||||
class Qcow2Mapper < Mapper
|
||||
# Max number of block devices. This should be set to the parameter used
|
||||
# to load the nbd kernel module (default in kernel is 16)
|
||||
NBDS_MAX = 256
|
||||
|
||||
def do_map(one_vm, disk, directory)
|
||||
device = nbd_device
|
||||
|
||||
return nil if device.empty?
|
||||
|
||||
dsrc = disk_source(one_vm, disk)
|
||||
cmd = "#{COMMANDS[:nbd]} -c #{device} #{dsrc}"
|
||||
|
||||
rc, out, err = Command.execute(cmd, true)
|
||||
|
||||
loop do
|
||||
sleep 0.5
|
||||
|
||||
nbd_parts = lsblk(device)
|
||||
|
||||
break if nbd_parts && nbd_parts[0] && nbd_parts[0]['fstype']
|
||||
end
|
||||
|
||||
if rc != 0
|
||||
OpenNebula.log_error("do_map: #{err}")
|
||||
return nil
|
||||
end
|
||||
|
||||
device
|
||||
end
|
||||
|
||||
def do_unmap(device, one_vm, disk, directory)
|
||||
cmd = "#{COMMANDS[:nbd]} -d #{device}"
|
||||
|
||||
rc, out, err = Command.execute(cmd, true)
|
||||
|
||||
if rc != 0
|
||||
OpenNebula.log_error("do_unmap: #{err}")
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def nbd_device()
|
||||
sys_parts = lsblk('')
|
||||
device_id = -1
|
||||
nbds = []
|
||||
|
||||
sys_parts.each { |p|
|
||||
m = p['name'].match(/nbd(\d+)/)
|
||||
next if !m
|
||||
|
||||
nbds << m[1].to_i
|
||||
}
|
||||
|
||||
NBDS_MAX.times { |i|
|
||||
return "/dev/nbd#{i}" unless nbds.include?(i)
|
||||
}
|
||||
|
||||
OpenNebula.log_error("nbd_device: Cannot find free nbd device")
|
||||
|
||||
''
|
||||
end
|
||||
end
|
87
src/vmm_mad/remotes/lib/lxd/mapper/raw.rb
Normal file
87
src/vmm_mad/remotes/lib/lxd/mapper/raw.rb
Normal file
@ -0,0 +1,87 @@
|
||||
#!/usr/bin/ruby
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2018, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
$LOAD_PATH.unshift File.dirname(__FILE__)
|
||||
|
||||
require 'mapper'
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# These classes implements the mapping of raw filesystems & raw disk images
|
||||
#-------------------------------------------------------------------------------
|
||||
class FSRawMapper < Mapper
|
||||
|
||||
def do_map(one_vm, disk, directory)
|
||||
dsrc = disk_source(one_vm, disk)
|
||||
cmd = "#{COMMANDS[:losetup]} -f --show #{dsrc}"
|
||||
|
||||
rc, out, err = Command.execute(cmd, true)
|
||||
|
||||
if rc != 0 || out.empty?
|
||||
OpenNebula.log_error("do_map: #{err}")
|
||||
return
|
||||
end
|
||||
|
||||
out.chomp
|
||||
end
|
||||
|
||||
def do_unmap(device, one_vm, disk, directory)
|
||||
cmd = "#{COMMANDS[:losetup]} -d #{device}"
|
||||
|
||||
rc, _out, err = Command.execute(cmd, true)
|
||||
|
||||
OpenNebula.log_error("do_unmap: #{err}") if rc != 0
|
||||
end
|
||||
end
|
||||
|
||||
class DiskRawMapper < Mapper
|
||||
# Maps the whole file using kpartx. The output should be something like:
|
||||
# $ sudo kpartx -av /var/lib/one/datastores/100/0/disk.0
|
||||
# add map loop3p1 (253:0): 0 204800 linear 7:3 2048
|
||||
# add map loop3p2 (253:1): 0 524288 linear 7:3 206848
|
||||
# add map loop3p3 (253:2): 0 1366016 linear 7:3 731136
|
||||
# Fisrt line is matched to look for loop device 3, and return "/dev/loop3"
|
||||
def do_map(one_vm, disk, directory)
|
||||
dsrc = disk_source(one_vm, disk)
|
||||
cmd = "#{COMMANDS[:kpartx]} -av #{dsrc}"
|
||||
|
||||
rc, out, err = Command.execute(cmd, true)
|
||||
|
||||
if rc != 0 || out.empty?
|
||||
OpenNebula.log_error("do_map: #{err}")
|
||||
return nil
|
||||
end
|
||||
|
||||
loopdev = out.lines[0].match(/.*add map loop(\d+)p\d+.*/)
|
||||
|
||||
return nil if !loopdev
|
||||
|
||||
"/dev/loop#{loopdev[1]}"
|
||||
end
|
||||
|
||||
# Unmaps all devices and loops with kpartx using the source file
|
||||
def do_unmap(device, one_vm, disk, directory)
|
||||
dsrc = disk_source(one_vm, disk)
|
||||
cmd = "#{COMMANDS[:kpartx]} -d #{dsrc}"
|
||||
|
||||
rc, out, err = Command.execute(cmd, true)
|
||||
|
||||
if rc != 0
|
||||
OpenNebula.log_error("do_unmap: #{err}")
|
||||
end
|
||||
end
|
||||
end
|
60
src/vmm_mad/remotes/lib/lxd/mapper/rbd.rb
Normal file
60
src/vmm_mad/remotes/lib/lxd/mapper/rbd.rb
Normal file
@ -0,0 +1,60 @@
|
||||
#!/usr/bin/ruby
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2018, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
$LOAD_PATH.unshift File.dirname(__FILE__)
|
||||
|
||||
require 'mapper'
|
||||
|
||||
# Ceph RBD mapper
|
||||
class RBD < Mapper
|
||||
|
||||
def initialize(ceph_user)
|
||||
@ceph_user = ceph_user
|
||||
end
|
||||
|
||||
def map(image)
|
||||
`sudo rbd --id #{@ceph_user} map #{image}`.chomp
|
||||
end
|
||||
|
||||
def unmap(block)
|
||||
shell("sudo rbd --id #{@ceph_user} unmap #{block}")
|
||||
end
|
||||
|
||||
# Returns an array of mountable block's partitions
|
||||
def detect_parts(block)
|
||||
parts = `blkid | grep #{block} | grep -w UUID | awk {'print $1'}`.split(":\n")
|
||||
uuids = []
|
||||
parts.each {|part| uuids.append `blkid #{part} -o export | grep -w UUID`.chomp("\n")[5..-1] }
|
||||
|
||||
formatted = []
|
||||
0.upto parts.length - 1 do |i|
|
||||
formatted[i] = { 'name' => parts[i], 'uuid' => uuids[i] }
|
||||
end
|
||||
|
||||
formatted
|
||||
end
|
||||
|
||||
def get_parts(block)
|
||||
parts = detect_parts(block)
|
||||
parts.each do |part|
|
||||
part['name'].slice!('//dev')
|
||||
end
|
||||
parts
|
||||
end
|
||||
|
||||
end
|
425
src/vmm_mad/remotes/lib/lxd/opennebula_vm.rb
Normal file
425
src/vmm_mad/remotes/lib/lxd/opennebula_vm.rb
Normal file
@ -0,0 +1,425 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2018, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
require 'rexml/document'
|
||||
require 'yaml'
|
||||
|
||||
# This class reads and holds configuration attributes for the LXD driver
|
||||
class LXDConfiguration < Hash
|
||||
|
||||
DEFAULT_CONFIGURATION = {
|
||||
:vnc => {
|
||||
:command => '/bin/bash',
|
||||
:width => '800',
|
||||
:height => '600',
|
||||
:timeout => '300'
|
||||
},
|
||||
:datastore_location => '/var/lib/one/datastores',
|
||||
:containers => '/var/lib/lxd/storage-pools/default/containers'
|
||||
}
|
||||
|
||||
def initialize
|
||||
replace(DEFAULT_CONFIGURATION)
|
||||
|
||||
begin
|
||||
merge!(YAML.load_file("#{__dir__}/../../etc/vmm/lxd/lxdrc"))
|
||||
rescue
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# This class parses and wraps the information in the Driver action data
|
||||
class OpenNebulaVM
|
||||
|
||||
attr_reader :xml, :vm_id, :vm_name, :sysds_id, :ds_path, :rootfs_id, :lxdrc
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Class Constructor
|
||||
#---------------------------------------------------------------------------
|
||||
def initialize(xml)
|
||||
@xml = XMLElement.new_s(xml)
|
||||
@xml = @xml.element('//VM')
|
||||
|
||||
@vm_id = @xml['//TEMPLATE/VMID']
|
||||
@sysds_id = @xml['//HISTORY_RECORDS/HISTORY/DS_ID']
|
||||
|
||||
@vm_name = @xml['//DEPLOY_ID']
|
||||
@vm_name = "one-#{@vm_id}" if @vm_name.empty?
|
||||
|
||||
return if wild?
|
||||
|
||||
# Load Driver configuration
|
||||
@lxdrc = LXDConfiguration.new
|
||||
|
||||
@ds_path = @lxdrc[:datastore_location]
|
||||
|
||||
# Sets the DISK ID of the root filesystem
|
||||
disk = @xml.element('//TEMPLATE/DISK')
|
||||
|
||||
return unless disk
|
||||
|
||||
@rootfs_id = disk['DISK_ID']
|
||||
boot_order = @xml['//TEMPLATE/OS/BOOT']
|
||||
@rootfs_id = boot_order.split(',')[0][-1] unless boot_order.empty?
|
||||
end
|
||||
|
||||
def has_context?
|
||||
!@xml['//TEMPLATE/CONTEXT/DISK_ID'].empty?
|
||||
end
|
||||
|
||||
def wild?
|
||||
@vm_name && !@vm_name.include?('one-')
|
||||
end
|
||||
|
||||
# Returns a Hash representing the LXC configuration for this OpenNebulaVM
|
||||
def to_lxc
|
||||
lxc = {}
|
||||
|
||||
lxc['name'] = @vm_name
|
||||
|
||||
lxc['config'] = {}
|
||||
lxc['devices'] = {}
|
||||
|
||||
profile(lxc)
|
||||
memory(lxc['config'])
|
||||
cpu(lxc['config'])
|
||||
extra_config(lxc['config'])
|
||||
network(lxc['devices'])
|
||||
storage(lxc['devices']) unless wild?
|
||||
|
||||
lxc
|
||||
end
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Container Attribute Mapping
|
||||
#---------------------------------------------------------------------------
|
||||
# Creates a dictionary for LXD containing $MEMORY RAM allocated
|
||||
def memory(hash)
|
||||
hash['limits.memory'] = "#{@xml['//TEMPLATE/MEMORY']}MB"
|
||||
end
|
||||
|
||||
# Creates a dictionary for LXD $CPU percentage and cores
|
||||
def cpu(hash)
|
||||
cpu = @xml['//TEMPLATE/CPU']
|
||||
hash['limits.cpu.allowance'] = "#{(cpu.to_f * 100).to_i}%"
|
||||
|
||||
vcpu = @xml['//TEMPLATE/VCPU']
|
||||
hash['limits.cpu'] = vcpu unless vcpu.empty?
|
||||
end
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Container Device Mapping: Networking
|
||||
#---------------------------------------------------------------------------
|
||||
# Get nic by mac
|
||||
def get_nic_by_mac(mac)
|
||||
get_nics.each do |n|
|
||||
return n if n['MAC'] == mac
|
||||
end
|
||||
end
|
||||
|
||||
def get_nics
|
||||
@xml.elements('//TEMPLATE/NIC')
|
||||
end
|
||||
|
||||
# Sets up the network interfaces configuration in devices
|
||||
def network(hash)
|
||||
get_nics.each do |n|
|
||||
hash.update(nic(n))
|
||||
end
|
||||
end
|
||||
|
||||
# Creates a nic hash from NIC xml root
|
||||
def nic(info)
|
||||
eth = {
|
||||
'name' => "eth#{info['NIC_ID']}",
|
||||
'host_name' => info['TARGET'],
|
||||
'parent' => info['BRIDGE'],
|
||||
'hwaddr' => info['MAC'],
|
||||
'nictype' => 'bridged',
|
||||
'type' => 'nic'
|
||||
}
|
||||
|
||||
nic_map = {
|
||||
'limits.ingress' => 'INBOUND_AVG_BW',
|
||||
'limits.egress' => 'OUTBOUND_AVG_BW'
|
||||
}
|
||||
|
||||
io_map(nic_map, eth, info) {|v| "#{v.to_i * 8}kbit" }
|
||||
|
||||
{ "eth#{info['NIC_ID']}" => eth }
|
||||
end
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Container Device Mapping: Storage
|
||||
#---------------------------------------------------------------------------
|
||||
# Get disk by target
|
||||
def get_disk_by_target(value)
|
||||
get_disk_by('TARGET', value)
|
||||
end
|
||||
|
||||
# Get disk by id
|
||||
def get_disk_by_id(value)
|
||||
get_disk_by('DISK_ID', value)
|
||||
end
|
||||
|
||||
# Get a disk depending on the filter xml key and the matching value
|
||||
def get_disks_by(filter, value)
|
||||
get_disks.each do |n|
|
||||
return n if n[filter] == value
|
||||
end
|
||||
end
|
||||
|
||||
def get_context_disk()
|
||||
@xml.element('//TEMPLATE/CONTEXT')
|
||||
end
|
||||
|
||||
def get_disks
|
||||
@xml.elements('//TEMPLATE/DISK')
|
||||
end
|
||||
|
||||
# Sets up the storage devices configuration in devices
|
||||
def storage(hash)
|
||||
disks = @xml.elements('//TEMPLATE/DISK')
|
||||
|
||||
disks.each do |n|
|
||||
hash.update(disk(n, nil, nil))
|
||||
end
|
||||
|
||||
context(hash)
|
||||
end
|
||||
|
||||
# Generate Context information
|
||||
def context(hash)
|
||||
cid = @xml['//TEMPLATE/CONTEXT/DISK_ID']
|
||||
|
||||
return if cid.empty?
|
||||
|
||||
source = "#{@ds_path}/#{@sysds_id}/#{@vm_id}/mapper/disk.#{cid}"
|
||||
|
||||
hash['context'] = {
|
||||
'type' => 'disk',
|
||||
'source' => source,
|
||||
'path' => '/context'
|
||||
}
|
||||
end
|
||||
|
||||
def disk_mountpoint(disk_id)
|
||||
"#{@ds_path}/#{@sysds_id}/#{@vm_id}/mapper/disk.#{disk_id}"
|
||||
end
|
||||
|
||||
# Creates a disk hash from DISK xml element
|
||||
def disk(info, source, path)
|
||||
disk_id = info['DISK_ID']
|
||||
disk = {}
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Source & Path attributes
|
||||
#-----------------------------------------------------------------------
|
||||
if disk_id == @rootfs_id
|
||||
disk_name = 'root'
|
||||
disk = { 'type' => 'disk', 'path' => '/', 'pool' => 'default' }
|
||||
else
|
||||
source ||= disk_mountpoint(disk_id)
|
||||
|
||||
unless path
|
||||
path = info['TARGET']
|
||||
path = "/media/#{disk_id}" unless path[0] == '/'
|
||||
end
|
||||
|
||||
disk_name = "disk#{disk_id}"
|
||||
disk = { 'type' => 'disk', 'source' => source, 'path' => path }
|
||||
end
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Readonly attributes
|
||||
#-----------------------------------------------------------------------
|
||||
if info['READONLY'].casecmp('yes').zero?
|
||||
disk['readonly'] = 'true'
|
||||
else
|
||||
disk['readonly'] = 'false'
|
||||
end
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# IO limits
|
||||
#-----------------------------------------------------------------------
|
||||
tbytes = info['TOTAL_BYTES_SEC']
|
||||
tiops = info['TOTAL_IOPS_SEC']
|
||||
|
||||
if tbytes && !tbytes.empty?
|
||||
disk['limits.max'] = tbytes
|
||||
elsif tiops && !tiops.empty?
|
||||
disk['limits.max'] = "#{tiops}iops"
|
||||
end
|
||||
|
||||
if tbytes.empty? && tiops.empty?
|
||||
disk_map = {
|
||||
'limits.read' => 'READ_BYTES_SEC',
|
||||
'limits.write' => 'WRITE_BYTES_SEC'
|
||||
}
|
||||
|
||||
mapped = io_map(disk_map, disk, info) {|v| v }
|
||||
|
||||
if !mapped
|
||||
disk_map = {
|
||||
'limits.read' => 'READ_IOPS_SEC',
|
||||
'limits.write' => 'WRITE_IOPS_SEC'
|
||||
}
|
||||
|
||||
io_map(disk_map, disk, info) {|v| "#{v}iops" }
|
||||
end
|
||||
end
|
||||
|
||||
{ disk_name => disk }
|
||||
end
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Container Mapping: Extra Configuration & Profiles
|
||||
#---------------------------------------------------------------------------
|
||||
def extra_config(hash)
|
||||
security = {
|
||||
'security.privileged' => 'false',
|
||||
'security.nesting' => 'false'
|
||||
}
|
||||
|
||||
security.each_key do |key|
|
||||
item = "LXD_SECURITY_#{key.split('.').last.swapcase}"
|
||||
|
||||
value = @xml["//USER_TEMPLATE/#{item}"]
|
||||
security[key] = value unless value.empty?
|
||||
end
|
||||
|
||||
hash.merge!(security)
|
||||
|
||||
raw_data = {}
|
||||
|
||||
data = @xml['//TEMPLATE/RAW/DATA']
|
||||
type = @xml['//TEMPLATE/RAW/TYPE']
|
||||
|
||||
if !data.empty? && type.casecmp('lxd').zero?
|
||||
begin
|
||||
raw_data = JSON.parse("{#{data}}")
|
||||
rescue StandardError
|
||||
end
|
||||
end
|
||||
|
||||
hash.merge!(raw_data) unless raw_data.empty?
|
||||
end
|
||||
|
||||
def profile(hash)
|
||||
profile = @xml['//USER_TEMPLATE/LXD_PROFILE']
|
||||
profile = 'default' if profile.empty?
|
||||
|
||||
hash['profiles'] = [profile]
|
||||
end
|
||||
|
||||
def device_info(devices, key, filter)
|
||||
devices.each do |device|
|
||||
return device[key] if device[key].value?(filter)
|
||||
end
|
||||
end
|
||||
|
||||
# Creates container vnc connection
|
||||
# Creates or closes a connection to a container rfb port depending on signal
|
||||
def vnc_command(signal)
|
||||
data = @xml.element('//TEMPLATE/GRAPHICS')
|
||||
return unless data && data['PORT'] && data['TYPE'] == 'VNC'
|
||||
|
||||
pass = data['PASSWD']
|
||||
pass = '-' unless pass && !pass.empty?
|
||||
|
||||
case signal
|
||||
when 'start'
|
||||
command = @lxdrc[:vnc][:command]
|
||||
"#{data['PORT']} #{pass} lxc exec #{@vm_name} #{command}\n"
|
||||
when 'stop'
|
||||
"-#{data['PORT']}\n"
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Maps IO limits from an OpenNebula VM configuration to a LXD configuration
|
||||
# map: Hash that defines LXD name to OpenNebula name mapping
|
||||
# lxd_conf: Hash with LXD configuration
|
||||
# one_conf: XML Element with OpenNebula Configuration
|
||||
#
|
||||
# Block: To transform OpenNebula value
|
||||
def io_map(map, lxd_conf, one_conf)
|
||||
mapped = false
|
||||
|
||||
map.each do |key, value|
|
||||
one_value = one_conf[value]
|
||||
|
||||
next if one_value.empty?
|
||||
|
||||
lxd_conf[key] = yield(one_value)
|
||||
|
||||
mapped = true
|
||||
end
|
||||
|
||||
mapped
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# This class abstracts the access to XML elements. It provides basic methods
|
||||
# to get elements by their xpath
|
||||
class XMLElement
|
||||
|
||||
def initialize(xml)
|
||||
@xml = xml
|
||||
end
|
||||
|
||||
# Create a new XMLElement using a xml document in a string
|
||||
def self.new_s(xml_s)
|
||||
xml = nil
|
||||
xml = REXML::Document.new(xml_s).root unless xml_s.empty?
|
||||
|
||||
new(xml)
|
||||
end
|
||||
|
||||
# Gets the text associated to a th element. The element is select by
|
||||
# its xpath. If not found an empty string is returned
|
||||
def [](key)
|
||||
element = @xml.elements[key.to_s]
|
||||
|
||||
return '' if (element && !element.has_text?) || !element
|
||||
|
||||
element.text
|
||||
end
|
||||
|
||||
# Return an XMLElement for the given xpath
|
||||
def element(key)
|
||||
e = @xml.elements[key.to_s]
|
||||
|
||||
element = nil
|
||||
element = XMLElement.new(e) if e
|
||||
|
||||
element
|
||||
end
|
||||
|
||||
# Get elements by xpath. This function returns an Array of XMLElements
|
||||
def elements(key)
|
||||
collection = []
|
||||
|
||||
@xml.elements.each(key) do |pelem|
|
||||
collection << XMLElement.new(pelem)
|
||||
end
|
||||
|
||||
collection
|
||||
end
|
||||
|
||||
end
|
31
src/vmm_mad/remotes/lib/lxd/svncterm_server/SConstruct
Normal file
31
src/vmm_mad/remotes/lib/lxd/svncterm_server/SConstruct
Normal file
@ -0,0 +1,31 @@
|
||||
# ---------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2018, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
# ---------------------------------------------------------------------------- #
|
||||
|
||||
import os
|
||||
|
||||
env = Environment()
|
||||
|
||||
env['LIBS'] = ['-lz']
|
||||
|
||||
env.Program('genfont.c')
|
||||
|
||||
env = Environment()
|
||||
env['LIBS'] = ['-lvncserver', '-lnsl', '-lpthread', '-lz', '-ljpeg',
|
||||
'-lutil', '-lgnutls']
|
||||
|
||||
env['CFLAGS'] = ['-D_GNU_SOURCE']
|
||||
|
||||
env.Program('svncterm_server.c')
|
35
src/vmm_mad/remotes/lib/lxd/svncterm_server/copyright
Normal file
35
src/vmm_mad/remotes/lib/lxd/svncterm_server/copyright
Normal file
@ -0,0 +1,35 @@
|
||||
Copyright 2002-2018, OpenNebula Project, OpenNebula Systems
|
||||
|
||||
-Changes to genfont utility
|
||||
* Update psf loader to PSFv2
|
||||
* Added command line options & usage
|
||||
* Other minor code changes
|
||||
|
||||
-Changes to svncterm
|
||||
* Added command line options
|
||||
* inetd like behavior, start vncserver when a conneciton is accepted
|
||||
|
||||
|
||||
Copyright (C) 2016 Universitat Politecnica de Valencia
|
||||
* Removing the usage of TLS and the need of patched versions of libraries
|
||||
|
||||
Copyright (C) 2007 Proxmox Server Solutions GmbH
|
||||
|
||||
Copyright: svncterm is under GNU GPL, the GNU General Public License.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
The complete text of the GNU General
|
||||
Public License can be found in `/usr/share/common-licenses/GPL'.
|
371
src/vmm_mad/remotes/lib/lxd/svncterm_server/genfont.c
Normal file
371
src/vmm_mad/remotes/lib/lxd/svncterm_server/genfont.c
Normal file
@ -0,0 +1,371 @@
|
||||
/*
|
||||
|
||||
Copyright (C) 2007 Proxmox Server Solutions GmbH
|
||||
|
||||
Copyright: vzdump is under GNU GPL, the GNU General Public License.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 dated June, 1991.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
|
||||
Author: Dietmar Maurer <dietmar@proxmox.com>
|
||||
|
||||
Copyright 2002-2018, OpenNebula Project, OpenNebula Systems
|
||||
|
||||
- Update psf loader to PSFv2
|
||||
- Added command line options & usage
|
||||
- Other minor code changes
|
||||
|
||||
contact@opennebula.systems
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <zlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Font glyph storage array and map pointer */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* map unicode to font */
|
||||
static unsigned short vt_fontmap[65536];
|
||||
|
||||
/* font glyph storage */
|
||||
static unsigned char * vt_font_data = NULL;
|
||||
|
||||
static int vt_font_size = 0; //Index to current glyph
|
||||
static int vt_font_maxsize = 0; //Max size of fontmap
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* PC Screen Font v2 data (PSFv2) Header & Constants */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
#define PSF2_MAGIC0 0x72
|
||||
#define PSF2_MAGIC1 0xb5
|
||||
#define PSF2_MAGIC2 0x4a
|
||||
#define PSF2_MAGIC3 0x86
|
||||
|
||||
/* bits used in flags */
|
||||
#define PSF2_HAS_UNICODE_TABLE 0x01
|
||||
|
||||
/* max version recognized so far */
|
||||
#define PSF2_MAXVERSION 0
|
||||
|
||||
/* UTF8 separators */
|
||||
#define PSF2_SEPARATOR 0xFF
|
||||
#define PSF2_STARTSEQ 0xFE
|
||||
|
||||
struct psf2_header
|
||||
{
|
||||
unsigned char magic[4];
|
||||
unsigned int version;
|
||||
unsigned int headersize; /* offset of bitmaps in file */
|
||||
unsigned int flags;
|
||||
unsigned int length; /* number of glyphs */
|
||||
unsigned int charsize; /* number of bytes for each character */
|
||||
unsigned int height, width; /* max dimensions of glyphs */
|
||||
/* charsize = height * ((width + 7) / 8) */
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Font map management */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Copy the glyph to the font map array
|
||||
* @param data, the glyph bitmap
|
||||
* @param gzise, size of glyph
|
||||
*/
|
||||
static int font_add_glyph (const char *data, unsigned int gsize)
|
||||
{
|
||||
if (vt_font_size >= vt_font_maxsize)
|
||||
{
|
||||
vt_font_maxsize += 256;
|
||||
vt_font_data = realloc (vt_font_data, vt_font_maxsize * gsize);
|
||||
}
|
||||
|
||||
memcpy(vt_font_data + vt_font_size * gsize, data, gsize);
|
||||
|
||||
return vt_font_size++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert UTF8 to (1, 2 & 3 bytes) Unicode char
|
||||
* Return 0 success, -1 not ucode, -2 EOU (end of unicode)
|
||||
*/
|
||||
static int utf8_2_unicode(gzFile stream, char s, u_int16_t * ucode)
|
||||
{
|
||||
char s1, s2;
|
||||
|
||||
*ucode = (u_int16_t) s;
|
||||
|
||||
if (*ucode == 0xFFFF)
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (*ucode == 0xFFFE)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(*ucode & 0x80))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
*ucode = 0;
|
||||
|
||||
if ((s & 0xE0) == 0xC0)
|
||||
{
|
||||
gzread(stream, &s1, 1);
|
||||
|
||||
*ucode = (s & 0x1F) << 6;
|
||||
*ucode |= (s1 & 0x3F);
|
||||
}
|
||||
else if ((s & 0xF0) == 0xE0)
|
||||
{
|
||||
gzread(stream, &s1, 1);
|
||||
gzread(stream, &s2, 1);
|
||||
|
||||
*ucode = (s & 0x0F) << 12;
|
||||
*ucode |= (s1 & 0x3F) << 6;
|
||||
*ucode |= (s2 & 0x3F);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the PSF font file
|
||||
*/
|
||||
static int load_psf_font (const char *filename, int is_default)
|
||||
{
|
||||
struct psf2_header psf2hdr;
|
||||
|
||||
size_t psf2hdr_len = sizeof(struct psf2_header);
|
||||
|
||||
gzFile f = gzopen(filename, "rb");
|
||||
|
||||
if (f == NULL)
|
||||
{
|
||||
fprintf (stderr, "unable to read file %s\n", filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Load PSF2 header and check consistency */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
if (gzread(f, &psf2hdr, psf2hdr_len) != psf2hdr_len)
|
||||
{
|
||||
fprintf(stderr, "Wrong header in psf2 font file (%s)\n", filename);
|
||||
gzclose(f);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (psf2hdr.magic[0] != PSF2_MAGIC0 || psf2hdr.magic[1] != PSF2_MAGIC1 ||
|
||||
psf2hdr.magic[2] != PSF2_MAGIC2 || psf2hdr.magic[3] != PSF2_MAGIC3 )
|
||||
{
|
||||
fprintf(stderr, "File %s not in PSFv2 format\n", filename);
|
||||
gzclose(f);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(psf2hdr.flags & PSF2_HAS_UNICODE_TABLE))
|
||||
{
|
||||
fprintf(stderr, "File %s does not include Unicode glyphs\n", filename);
|
||||
gzclose(f);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( psf2hdr.height != 16 && psf2hdr.width != 8 )
|
||||
{
|
||||
fprintf(stderr, "File %s does not include 8x16 font\n", filename);
|
||||
gzclose(f);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Read the bitmaps */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
int gsize = psf2hdr.charsize;
|
||||
int font_size = gsize * psf2hdr.length;
|
||||
|
||||
char *chardata = (char *) malloc (font_size);
|
||||
|
||||
if (gzread(f, chardata, font_size)!= font_size)
|
||||
{
|
||||
fprintf (stderr, "Cannot read font character data from %s\n", filename);
|
||||
gzclose (f);
|
||||
|
||||
free(chardata);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Read the Unicode description of the glyphs */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
for (int glyph = 0 ;glyph < psf2hdr.length ;glyph++)
|
||||
{
|
||||
int fi = 0;
|
||||
char s;
|
||||
|
||||
while (gzread(f, &s, 1) == 1)
|
||||
{
|
||||
u_int16_t uchar;
|
||||
|
||||
int rc = utf8_2_unicode(f, s, &uchar);
|
||||
|
||||
if ( rc == -1 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if ( rc == -2 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (!vt_fontmap[uchar] && uchar != 0)
|
||||
{
|
||||
if (!fi)
|
||||
{
|
||||
fi = font_add_glyph(chardata + glyph * gsize, gsize);
|
||||
}
|
||||
|
||||
vt_fontmap[uchar] = fi;
|
||||
}
|
||||
|
||||
if (is_default && fi && glyph < 256)
|
||||
{
|
||||
vt_fontmap[0xf000 + glyph] = fi;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(chardata);
|
||||
gzclose(f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Print the include file */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void print_glyphs ()
|
||||
{
|
||||
printf ("static int vt_font_size = %d;\n\n", vt_font_size);
|
||||
|
||||
printf ("static unsigned char vt_font_data[] = {\n");
|
||||
|
||||
for (int i = 0; i < vt_font_size; i++)
|
||||
{
|
||||
printf("\t/* %d 0x%02x */\n", i, i);
|
||||
|
||||
for (int j = 0; j < 16; j++) //glyph size == 16
|
||||
{
|
||||
unsigned char d = vt_font_data[i*16+j];
|
||||
|
||||
printf ("\t0x%02X, /* ", d);
|
||||
|
||||
for (int k = 128; k > 0; k = k>>1)
|
||||
{
|
||||
printf ("%c", (d & k) ? '1': '0');
|
||||
}
|
||||
|
||||
printf (" */\n");
|
||||
}
|
||||
|
||||
printf ("\n");
|
||||
}
|
||||
|
||||
printf ("};\n\n");
|
||||
|
||||
printf ("static unsigned short vt_fontmap[65536] = {\n");
|
||||
|
||||
for (int i = 0; i < 0x0ffff; i++)
|
||||
{
|
||||
printf ("\t/* 0x%04X => */ %d,\n", i, vt_fontmap[i]);
|
||||
}
|
||||
|
||||
printf ("};\n\n");
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
static void print_usage()
|
||||
{
|
||||
fprintf(stderr, "Usage: genfont [-d font_path] [font1 font2...]\n");
|
||||
fprintf(stderr, "Generate Glyph Bitmaps and associated Unicode mapping\n\n");
|
||||
fprintf(stderr, "\tfont1... List of fonts, the first one is the default\n\n");
|
||||
fprintf(stderr, "\t-d path: Font path defaults to /usr/share/consolefonts\n\n");
|
||||
fprintf(stderr, "Example: genfont default8x16.psf.gz lat1u-16.psf.gz"
|
||||
" lat2u-16.psf.gz\n");
|
||||
}
|
||||
|
||||
int main (int argc, char** argv)
|
||||
{
|
||||
char empty[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
char font_dir[PATH_MAX - 256] = "/usr/share/consolefonts";
|
||||
|
||||
int opt;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Arguments parsing */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
while ((opt = getopt(argc, argv, "hd:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'h':
|
||||
print_usage();
|
||||
exit(0);
|
||||
case 'd':
|
||||
strncpy(font_dir, optarg, PATH_MAX - 257);
|
||||
break;
|
||||
default: /* '?' */
|
||||
print_usage();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Load PSF fonts & print glyphs */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
font_add_glyph(empty, sizeof(empty));
|
||||
|
||||
if ( optind >= argc )
|
||||
{
|
||||
print_usage();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
for (int i=optind ; i < argc; ++i)
|
||||
{
|
||||
char font_path[PATH_MAX];
|
||||
|
||||
snprintf(font_path, PATH_MAX, "%s/%s", font_dir, argv[i]);
|
||||
|
||||
/* font load order is only important if glyphs are redefined */
|
||||
load_psf_font(font_path, i == optind);
|
||||
}
|
||||
|
||||
print_glyphs ();
|
||||
|
||||
exit (0);
|
||||
}
|
||||
|
72293
src/vmm_mad/remotes/lib/lxd/svncterm_server/glyphs.h
Normal file
72293
src/vmm_mad/remotes/lib/lxd/svncterm_server/glyphs.h
Normal file
File diff suppressed because it is too large
Load Diff
235
src/vmm_mad/remotes/lib/lxd/svncterm_server/svncterm.h
Normal file
235
src/vmm_mad/remotes/lib/lxd/svncterm_server/svncterm.h
Normal file
@ -0,0 +1,235 @@
|
||||
#include <rfb/rfb.h>
|
||||
|
||||
#define IBUFSIZE 1024
|
||||
#define MAX_ESC_PARAMS 16
|
||||
|
||||
typedef unsigned short unicode;
|
||||
|
||||
typedef struct TextAttributes {
|
||||
unsigned int fgcol:4;
|
||||
unsigned int bgcol:4;
|
||||
unsigned int bold:1;
|
||||
unsigned int uline:1;
|
||||
unsigned int blink:1;
|
||||
unsigned int invers:1;
|
||||
unsigned int unvisible:1;
|
||||
} TextAttributes;
|
||||
|
||||
typedef struct TextCell {
|
||||
unicode ch;
|
||||
TextAttributes attrib;
|
||||
} TextCell;
|
||||
|
||||
typedef struct vncTerm {
|
||||
int maxx;
|
||||
int maxy;
|
||||
|
||||
int width;
|
||||
int height;
|
||||
|
||||
int total_height;
|
||||
int scroll_height;
|
||||
int y_base;
|
||||
int y_displ;
|
||||
int altbuf:1;
|
||||
|
||||
unsigned int utf8:1; // utf8 mode
|
||||
long utf_char; // used by utf8 parser
|
||||
int utf_count; // used by utf8 parser
|
||||
|
||||
|
||||
TextAttributes default_attrib;
|
||||
|
||||
TextCell *cells;
|
||||
TextCell *altcells;
|
||||
|
||||
rfbScreenInfoPtr screen;
|
||||
|
||||
// cursor
|
||||
TextAttributes cur_attrib;
|
||||
TextAttributes cur_attrib_saved;
|
||||
int tty_state; // 0 - normal, 1 - ESC, 2 - CSI
|
||||
int cx; // cursor x position
|
||||
int cy; // cursor y position
|
||||
int cx_saved; // saved cursor x position
|
||||
int cy_saved; // saved cursor y position
|
||||
int esc_buf[MAX_ESC_PARAMS];
|
||||
int esc_count;
|
||||
int esc_ques;
|
||||
int esc_has_par;
|
||||
char osc_textbuf[4096];
|
||||
char osc_cmd;
|
||||
int region_top;
|
||||
int region_bottom;
|
||||
|
||||
unsigned int charset:1; // G0 or G1
|
||||
unsigned int charset_saved:1; // G0 or G1
|
||||
unsigned int g0enc:2;
|
||||
unsigned int g0enc_saved:2;
|
||||
unsigned int g1enc:2;
|
||||
unsigned int g1enc_saved:2;
|
||||
unsigned int cur_enc:2;
|
||||
unsigned int cur_enc_saved:2;
|
||||
|
||||
// input buffer
|
||||
char ibuf[IBUFSIZE];
|
||||
int ibuf_count;
|
||||
|
||||
unicode *selection;
|
||||
int selection_len;
|
||||
|
||||
unsigned int mark_active:1;
|
||||
|
||||
unsigned int report_mouse:1;
|
||||
|
||||
} vncTerm;
|
||||
|
||||
/* Unicode translations copied from kernel source consolemap.c */
|
||||
|
||||
#define LAT1_MAP 0
|
||||
#define GRAF_MAP 1
|
||||
#define IBMPC_MAP 2
|
||||
#define USER_MAP 3
|
||||
|
||||
static unsigned short translations[][256] = {
|
||||
/* 8-bit Latin-1 mapped to Unicode -- trivial mapping */
|
||||
{
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
|
||||
0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
|
||||
0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
|
||||
0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
|
||||
0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
|
||||
0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
|
||||
0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
|
||||
0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
|
||||
0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
|
||||
0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
|
||||
0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
|
||||
0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
|
||||
0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
|
||||
0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
|
||||
0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
|
||||
0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
|
||||
0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
|
||||
0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
|
||||
0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
|
||||
0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
|
||||
0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
|
||||
0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
|
||||
0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
|
||||
0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
|
||||
0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
|
||||
},
|
||||
/* VT100 graphics mapped to Unicode */
|
||||
{
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
|
||||
0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
|
||||
0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
|
||||
0x0028, 0x0029, 0x002a, 0x2192, 0x2190, 0x2191, 0x2193, 0x002f,
|
||||
0x2588, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
|
||||
0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
|
||||
0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
|
||||
0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x00a0,
|
||||
0x25c6, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0, 0x00b1,
|
||||
0x2591, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c, 0x23ba,
|
||||
0x23bb, 0x2500, 0x23bc, 0x23bd, 0x251c, 0x2524, 0x2534, 0x252c,
|
||||
0x2502, 0x2264, 0x2265, 0x03c0, 0x2260, 0x00a3, 0x00b7, 0x007f,
|
||||
0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
|
||||
0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
|
||||
0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
|
||||
0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
|
||||
0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
|
||||
0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
|
||||
0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
|
||||
0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
|
||||
0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
|
||||
0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
|
||||
0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
|
||||
0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
|
||||
0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
|
||||
0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
|
||||
0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
|
||||
0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
|
||||
},
|
||||
/* IBM Codepage 437 mapped to Unicode */
|
||||
{
|
||||
0x0000, 0x263a, 0x263b, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022,
|
||||
0x25d8, 0x25cb, 0x25d9, 0x2642, 0x2640, 0x266a, 0x266b, 0x263c,
|
||||
0x25b6, 0x25c0, 0x2195, 0x203c, 0x00b6, 0x00a7, 0x25ac, 0x21a8,
|
||||
0x2191, 0x2193, 0x2192, 0x2190, 0x221f, 0x2194, 0x25b2, 0x25bc,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
|
||||
0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
|
||||
0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
|
||||
0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
|
||||
0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
|
||||
0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
|
||||
0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x2302,
|
||||
0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7,
|
||||
0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
|
||||
0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
|
||||
0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
|
||||
0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba,
|
||||
0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
|
||||
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
|
||||
0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
|
||||
0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
|
||||
0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
|
||||
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b,
|
||||
0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
|
||||
0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4,
|
||||
0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229,
|
||||
0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248,
|
||||
0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0
|
||||
},
|
||||
/* User mapping -- default to codes for direct font mapping */
|
||||
{
|
||||
0xf000, 0xf001, 0xf002, 0xf003, 0xf004, 0xf005, 0xf006, 0xf007,
|
||||
0xf008, 0xf009, 0xf00a, 0xf00b, 0xf00c, 0xf00d, 0xf00e, 0xf00f,
|
||||
0xf010, 0xf011, 0xf012, 0xf013, 0xf014, 0xf015, 0xf016, 0xf017,
|
||||
0xf018, 0xf019, 0xf01a, 0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f,
|
||||
0xf020, 0xf021, 0xf022, 0xf023, 0xf024, 0xf025, 0xf026, 0xf027,
|
||||
0xf028, 0xf029, 0xf02a, 0xf02b, 0xf02c, 0xf02d, 0xf02e, 0xf02f,
|
||||
0xf030, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037,
|
||||
0xf038, 0xf039, 0xf03a, 0xf03b, 0xf03c, 0xf03d, 0xf03e, 0xf03f,
|
||||
0xf040, 0xf041, 0xf042, 0xf043, 0xf044, 0xf045, 0xf046, 0xf047,
|
||||
0xf048, 0xf049, 0xf04a, 0xf04b, 0xf04c, 0xf04d, 0xf04e, 0xf04f,
|
||||
0xf050, 0xf051, 0xf052, 0xf053, 0xf054, 0xf055, 0xf056, 0xf057,
|
||||
0xf058, 0xf059, 0xf05a, 0xf05b, 0xf05c, 0xf05d, 0xf05e, 0xf05f,
|
||||
0xf060, 0xf061, 0xf062, 0xf063, 0xf064, 0xf065, 0xf066, 0xf067,
|
||||
0xf068, 0xf069, 0xf06a, 0xf06b, 0xf06c, 0xf06d, 0xf06e, 0xf06f,
|
||||
0xf070, 0xf071, 0xf072, 0xf073, 0xf074, 0xf075, 0xf076, 0xf077,
|
||||
0xf078, 0xf079, 0xf07a, 0xf07b, 0xf07c, 0xf07d, 0xf07e, 0xf07f,
|
||||
0xf080, 0xf081, 0xf082, 0xf083, 0xf084, 0xf085, 0xf086, 0xf087,
|
||||
0xf088, 0xf089, 0xf08a, 0xf08b, 0xf08c, 0xf08d, 0xf08e, 0xf08f,
|
||||
0xf090, 0xf091, 0xf092, 0xf093, 0xf094, 0xf095, 0xf096, 0xf097,
|
||||
0xf098, 0xf099, 0xf09a, 0xf09b, 0xf09c, 0xf09d, 0xf09e, 0xf09f,
|
||||
0xf0a0, 0xf0a1, 0xf0a2, 0xf0a3, 0xf0a4, 0xf0a5, 0xf0a6, 0xf0a7,
|
||||
0xf0a8, 0xf0a9, 0xf0aa, 0xf0ab, 0xf0ac, 0xf0ad, 0xf0ae, 0xf0af,
|
||||
0xf0b0, 0xf0b1, 0xf0b2, 0xf0b3, 0xf0b4, 0xf0b5, 0xf0b6, 0xf0b7,
|
||||
0xf0b8, 0xf0b9, 0xf0ba, 0xf0bb, 0xf0bc, 0xf0bd, 0xf0be, 0xf0bf,
|
||||
0xf0c0, 0xf0c1, 0xf0c2, 0xf0c3, 0xf0c4, 0xf0c5, 0xf0c6, 0xf0c7,
|
||||
0xf0c8, 0xf0c9, 0xf0ca, 0xf0cb, 0xf0cc, 0xf0cd, 0xf0ce, 0xf0cf,
|
||||
0xf0d0, 0xf0d1, 0xf0d2, 0xf0d3, 0xf0d4, 0xf0d5, 0xf0d6, 0xf0d7,
|
||||
0xf0d8, 0xf0d9, 0xf0da, 0xf0db, 0xf0dc, 0xf0dd, 0xf0de, 0xf0df,
|
||||
0xf0e0, 0xf0e1, 0xf0e2, 0xf0e3, 0xf0e4, 0xf0e5, 0xf0e6, 0xf0e7,
|
||||
0xf0e8, 0xf0e9, 0xf0ea, 0xf0eb, 0xf0ec, 0xf0ed, 0xf0ee, 0xf0ef,
|
||||
0xf0f0, 0xf0f1, 0xf0f2, 0xf0f3, 0xf0f4, 0xf0f5, 0xf0f6, 0xf0f7,
|
||||
0xf0f8, 0xf0f9, 0xf0fa, 0xf0fb, 0xf0fc, 0xf0fd, 0xf0fe, 0xf0ff
|
||||
}
|
||||
};
|
2426
src/vmm_mad/remotes/lib/lxd/svncterm_server/svncterm_server.c
Normal file
2426
src/vmm_mad/remotes/lib/lxd/svncterm_server/svncterm_server.c
Normal file
File diff suppressed because it is too large
Load Diff
40
src/vmm_mad/remotes/lxd/attach_disk
Executable file
40
src/vmm_mad/remotes/lxd/attach_disk
Executable file
@ -0,0 +1,40 @@
|
||||
#!/usr/bin/ruby
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2018, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
$LOAD_PATH.unshift File.dirname(__FILE__)
|
||||
|
||||
require 'container'
|
||||
|
||||
require_relative '../../scripts_common'
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Action Arguments, STDIN includes XML description of the OpenNebula VM
|
||||
# ------------------------------------------------------------------------------
|
||||
vm_name = ARGV[0]
|
||||
image_path = ARGV[1]
|
||||
target = ARGV[2]
|
||||
disk_index = ARGV[3]
|
||||
xml64 = ARGV[4]
|
||||
vm_id = ARGV[5]
|
||||
|
||||
xml = STDIN.read
|
||||
|
||||
client = LXDClient.new
|
||||
container = Container.get(vm_name, xml, client)
|
||||
|
||||
container.attach_disk(image_path)
|
43
src/vmm_mad/remotes/lxd/attach_nic
Executable file
43
src/vmm_mad/remotes/lxd/attach_nic
Executable file
@ -0,0 +1,43 @@
|
||||
#!/usr/bin/ruby
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2018, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
$LOAD_PATH.unshift File.dirname(__FILE__)
|
||||
|
||||
require 'container'
|
||||
|
||||
require_relative '../../scripts_common'
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Action Arguments, STDIN includes XML description of the OpenNebula VM
|
||||
# ------------------------------------------------------------------------------
|
||||
vm_name = ARGV[0]
|
||||
mac = ARGV[1]
|
||||
bridge = ARGV[2]
|
||||
model = ARGV[3]
|
||||
net_drv = ARGV[4]
|
||||
host_nic= ARGV[5]
|
||||
|
||||
vm_id = ARGV[6]
|
||||
host = ARGV[7]
|
||||
|
||||
xml = STDIN.read
|
||||
|
||||
client = LXDClient.new
|
||||
container = Container.get(vm_name, xml, client)
|
||||
|
||||
container.attach_nic(mac)
|
19
src/vmm_mad/remotes/lxd/cancel
Executable file
19
src/vmm_mad/remotes/lxd/cancel
Executable file
@ -0,0 +1,19 @@
|
||||
#!/bin/bash
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2018, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
$(dirname $0)/shutdown $@ '-f'
|
91
src/vmm_mad/remotes/lxd/deploy
Executable file
91
src/vmm_mad/remotes/lxd/deploy
Executable file
@ -0,0 +1,91 @@
|
||||
#!/usr/bin/ruby
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2018, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
$LOAD_PATH.unshift File.dirname(__FILE__)
|
||||
|
||||
require 'container'
|
||||
|
||||
require_relative '../../scripts_common'
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Action Arguments, STDIN includes XML description of the OpenNebula VM
|
||||
# ------------------------------------------------------------------------------
|
||||
xml_path = ARGV[0]
|
||||
vm_id = ARGV[2]
|
||||
|
||||
xml = STDIN.read
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Action Arguments, STDIN includes XML description of the OpenNebula VM
|
||||
# ------------------------------------------------------------------------------
|
||||
client = LXDClient.new
|
||||
container = Container.new_from_xml(xml, client)
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Create Container in LXD
|
||||
# - Already exists: gets container metadata from LXD and set OpenNebula
|
||||
# configurations to update existing container.
|
||||
# - Not exists. Creates new container in LXD.
|
||||
# ------------------------------------------------------------------------------
|
||||
if Container.exist?(container.name, client)
|
||||
OpenNebula.log_info('Overriding container')
|
||||
|
||||
config = container.config
|
||||
devices = container.devices
|
||||
|
||||
container.get_metadata
|
||||
|
||||
err_msg = 'A container with the same ID is already running'
|
||||
raise LXDError, err_msg if container.status == 'Running'
|
||||
|
||||
container.config = config
|
||||
|
||||
container.devices = devices
|
||||
|
||||
container.update
|
||||
else
|
||||
container.create
|
||||
end
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Start the container, if not wild, maps storage to host directories
|
||||
# ------------------------------------------------------------------------------
|
||||
if container.wild?
|
||||
container.start
|
||||
else
|
||||
container.setup_storage('map')
|
||||
|
||||
if container.start != 'Running'
|
||||
OpenNebula.log_error('Container failed to start')
|
||||
|
||||
container.setup_storage('unmap')
|
||||
container.delete
|
||||
|
||||
raise LXDError, container.status
|
||||
end
|
||||
end
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Updates container configuration with the OpenNebulaVM description
|
||||
# ------------------------------------------------------------------------------
|
||||
container.config.update('user.xml' => xml)
|
||||
container.update
|
||||
|
||||
container.vnc('start')
|
||||
|
||||
puts container.name
|
38
src/vmm_mad/remotes/lxd/detach_disk
Executable file
38
src/vmm_mad/remotes/lxd/detach_disk
Executable file
@ -0,0 +1,38 @@
|
||||
#!/usr/bin/ruby
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2018, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
$LOAD_PATH.unshift File.dirname(__FILE__)
|
||||
|
||||
require 'container'
|
||||
|
||||
require_relative '../../scripts_common'
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Action Arguments, STDIN includes XML description of the OpenNebula VM
|
||||
# ------------------------------------------------------------------------------
|
||||
vm_name = ARGV[0]
|
||||
tgt_path = ARGV[1]
|
||||
tgt = ARGV[2]
|
||||
tgt_index = ARGV[3]
|
||||
|
||||
xml = STDIN.read
|
||||
|
||||
client = LXDClient.new
|
||||
container = Container.get(vm_name, xml, client)
|
||||
|
||||
container.detach_disk
|
39
src/vmm_mad/remotes/lxd/detach_nic
Executable file
39
src/vmm_mad/remotes/lxd/detach_nic
Executable file
@ -0,0 +1,39 @@
|
||||
#!/usr/bin/ruby
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2018, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
$LOAD_PATH.unshift File.dirname(__FILE__)
|
||||
|
||||
require 'container'
|
||||
|
||||
require_relative '../../scripts_common'
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Action Arguments, STDIN includes XML description of the OpenNebula VM
|
||||
# ------------------------------------------------------------------------------
|
||||
vm_name = ARGV[0]
|
||||
mac = ARGV[1]
|
||||
vm_id = ARGV[2]
|
||||
host = ARGV[3]
|
||||
|
||||
xml = STDIN.read
|
||||
|
||||
client = LXDClient.new
|
||||
container = Container.get(vm_name, xml, client)
|
||||
|
||||
container.detach_nic(mac)
|
||||
|
46
src/vmm_mad/remotes/lxd/lxdrc
Normal file
46
src/vmm_mad/remotes/lxd/lxdrc
Normal file
@ -0,0 +1,46 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2018, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
################################################################################
|
||||
# VNC Options
|
||||
################################################################################
|
||||
#
|
||||
# Options to customize the VNC access to the container:
|
||||
# - :command: to be executed in the VNC terminal.
|
||||
# - :width: of the terminal
|
||||
# - :height: of the terminal
|
||||
# - :timeout: seconds to close the terminal if no input has been received
|
||||
:vnc:
|
||||
:command: /bin/bash
|
||||
:width: 800
|
||||
:height: 600
|
||||
:timeout: 300
|
||||
|
||||
################################################################################
|
||||
# OpenNebula Configuration Options
|
||||
################################################################################
|
||||
#
|
||||
# Default path for the datastores. This only need to be change if the
|
||||
# corresponding value in oned.conf has been modified.
|
||||
:datastore_location: /var/lib/one/datastores
|
||||
|
||||
|
||||
################################################################################
|
||||
# LXD Options
|
||||
################################################################################
|
||||
#
|
||||
# Path to containers location to mount the root file systems
|
||||
:containers: /var/lib/lxd/storage-pools/default/containers
|
1
src/vmm_mad/remotes/lxd/migrate
Symbolic link
1
src/vmm_mad/remotes/lxd/migrate
Symbolic link
@ -0,0 +1 @@
|
||||
../common/not_supported.sh
|
1
src/vmm_mad/remotes/lxd/migrate_local
Symbolic link
1
src/vmm_mad/remotes/lxd/migrate_local
Symbolic link
@ -0,0 +1 @@
|
||||
../common/not_supported.sh
|
275
src/vmm_mad/remotes/lxd/poll
Executable file
275
src/vmm_mad/remotes/lxd/poll
Executable file
@ -0,0 +1,275 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2018, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
$LOAD_PATH.unshift File.dirname(__FILE__)
|
||||
|
||||
require 'container'
|
||||
require 'client'
|
||||
require_relative '../lib/poll_common'
|
||||
|
||||
require 'base64'
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# LXD Monitor Module
|
||||
#
|
||||
################################################################################
|
||||
module LXD
|
||||
|
||||
CLIENT = LXDClient.new
|
||||
|
||||
class << self
|
||||
|
||||
# Get the information of a single VM. In case of error the VM is reported
|
||||
# as not found.
|
||||
# @param one_vm [String] with the VM name
|
||||
def get_vm_info(one_vm)
|
||||
vm = Container.get(one_vm, nil, CLIENT)
|
||||
|
||||
return { :state => '-' } unless vm
|
||||
|
||||
vm_info = get_values([vm]).first.last
|
||||
|
||||
vm_info
|
||||
end
|
||||
|
||||
# Gets the information of all VMs
|
||||
#
|
||||
# @return [Hash, nil] Hash with the VM information or nil in case of error
|
||||
def get_all_vm_info
|
||||
vms = Container.get_all(CLIENT)
|
||||
|
||||
return unless vms
|
||||
|
||||
vms_info = get_values(vms)
|
||||
vms_info
|
||||
end
|
||||
|
||||
def get_values(vms)
|
||||
vms_info = {}
|
||||
|
||||
running_containers = []
|
||||
|
||||
vms.each do |container|
|
||||
values = {}
|
||||
name = container.name
|
||||
values[:state] = get_state(container)
|
||||
|
||||
unless name =~ /^one-\d+/ # Wild VMs
|
||||
template = to_one(container)
|
||||
values[:template] = Base64.encode64(template).delete("\n")
|
||||
values[:vm_name] = name
|
||||
end
|
||||
|
||||
vms_info[name] = values
|
||||
next unless values[:state] == 'a'
|
||||
|
||||
vmd = container.monitor['metadata']
|
||||
|
||||
values[:memory] = get_memory(name)
|
||||
values[:netrx], values[:nettx] = get_net_statistics(vmd['network'])
|
||||
|
||||
running_containers.append(name)
|
||||
vms_info[name][:memory] = values[:memory]
|
||||
end
|
||||
|
||||
unless running_containers.empty?
|
||||
cpu = get_cpu(running_containers)
|
||||
vms.each do |container|
|
||||
vms_info[container.name][:cpu] = cpu[container.name] if cpu[container.name]
|
||||
end
|
||||
end
|
||||
|
||||
vms_info
|
||||
end
|
||||
|
||||
# Get and translate LXD state to Opennebula monitor state
|
||||
# @param state [String] libvirt state
|
||||
# @return [String] OpenNebula state
|
||||
#
|
||||
# LXD states for the guest are
|
||||
# * 'running' state refers to containers which are currently active.
|
||||
# * 'frozen' after lxc freeze (suspended).
|
||||
# * 'stopped' container not running or in the process of shutting down.
|
||||
# * 'failure' container have failed.
|
||||
def get_state(container)
|
||||
begin
|
||||
status = container.status.downcase
|
||||
rescue StandardError
|
||||
status = 'unknown'
|
||||
end
|
||||
|
||||
case status
|
||||
when 'running'
|
||||
state = 'a'
|
||||
when 'frozen'
|
||||
state = 'p'
|
||||
when 'stopped'
|
||||
state = 'd'
|
||||
when 'failure'
|
||||
state = 'e'
|
||||
else
|
||||
state = '-'
|
||||
end
|
||||
|
||||
state
|
||||
end
|
||||
|
||||
def get_memory(vm_name)
|
||||
stat = File.read('/sys/fs/cgroup/memory/lxc/' + vm_name + '/memory.usage_in_bytes').to_i
|
||||
stat / 1024
|
||||
end
|
||||
|
||||
def get_net_statistics(vmd)
|
||||
netrx = 0
|
||||
nettx = 0
|
||||
|
||||
vmd.each do |interface, values|
|
||||
next if interface == 'lo'
|
||||
|
||||
netrx += values['counters']['bytes_received']
|
||||
nettx += values['counters']['bytes_sent']
|
||||
end
|
||||
|
||||
[netrx, nettx]
|
||||
end
|
||||
|
||||
# Gathers process information from a set of VMs.
|
||||
# @param vm_names [Array] of vms indexed by name. Value is a hash with :pid
|
||||
# @return [Hash] with ps information
|
||||
def get_cpu(vm_names)
|
||||
multiplier = `nproc`.to_i * 100
|
||||
|
||||
start_cpu_jiffies = get_cpu_jiffies
|
||||
|
||||
cpu_used = {}
|
||||
vm_names.each do |vm_name|
|
||||
cpu_used[vm_name] = get_process_jiffies(vm_name).to_f
|
||||
end
|
||||
|
||||
sleep 1
|
||||
|
||||
cpu_jiffies = get_cpu_jiffies - start_cpu_jiffies
|
||||
|
||||
vm_names.each do |vm_name|
|
||||
cpu_used[vm_name] = (get_process_jiffies(vm_name).to_f -
|
||||
cpu_used[vm_name]) / cpu_jiffies
|
||||
|
||||
cpu_used[vm_name] = (cpu_used[vm_name] * multiplier).round(2)
|
||||
end
|
||||
|
||||
cpu_used
|
||||
end
|
||||
|
||||
def get_cpu_jiffies
|
||||
begin
|
||||
stat = File.read('/proc/stat')
|
||||
rescue StandardError
|
||||
return 0
|
||||
end
|
||||
|
||||
jiffies = 0
|
||||
|
||||
# skip cpu string and guest jiffies
|
||||
stat.lines.first.split(' ')[1..-3].each do |num|
|
||||
jiffies += num.to_i
|
||||
end
|
||||
|
||||
jiffies
|
||||
end
|
||||
|
||||
def get_process_jiffies(vm_name)
|
||||
begin
|
||||
jiffies = 0
|
||||
stat = File.read('/sys/fs/cgroup/cpu,cpuacct/lxc/' + vm_name + '/cpuacct.stat')
|
||||
stat.lines.each {|line| jiffies += line.split(' ')[1] }
|
||||
rescue StandardError
|
||||
return 0
|
||||
end
|
||||
|
||||
jiffies
|
||||
end
|
||||
|
||||
def parse_memory(memory)
|
||||
mem_suffix = memory[-2..-1]
|
||||
memory = memory[0..-3].to_i # remove sufix
|
||||
case mem_suffix[-2..-1]
|
||||
when 'GB'
|
||||
memory *= 1024
|
||||
when 'TB'
|
||||
memory *= 1024**2
|
||||
end
|
||||
memory
|
||||
end
|
||||
|
||||
def to_one(container)
|
||||
name = container.name
|
||||
arch = container.architecture
|
||||
capacity = container.expanded_config
|
||||
|
||||
cpu = ""
|
||||
vcpu= ""
|
||||
mem = ""
|
||||
|
||||
if capacity
|
||||
cpu = capacity['limits.cpu.allowance']
|
||||
vcpu = capacity['limits.cpu']
|
||||
mem = capacity['limits.memory']
|
||||
end
|
||||
|
||||
cpu = "50%" if !cpu || cpu.empty?
|
||||
vcpu = "1" if !vcpu || vcpu.empty?
|
||||
mem = "512M" if !mem || mem.empty?
|
||||
|
||||
cpu = cpu.chomp('%').to_f / 100
|
||||
mem = parse_memory(mem)
|
||||
|
||||
template = <<EOT
|
||||
NAME="#{name}"
|
||||
CPU=#{cpu}
|
||||
VCPU=#{vcpu}
|
||||
MEMORY=#{mem}
|
||||
HYPERVISOR="lxd"
|
||||
IMPORT_VM_ID="#{name}"
|
||||
OS=[ARCH="#{arch}"]
|
||||
EOT
|
||||
template
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
################################################################################
|
||||
# MAIN PROGRAM
|
||||
################################################################################
|
||||
|
||||
hypervisor = LXD
|
||||
# file = '../../etc/vmm/kvm/kvmrc'
|
||||
|
||||
# load_vars(hypervisor)
|
||||
|
||||
vm_id = ARGV[0]
|
||||
|
||||
if vm_id == '-t'
|
||||
print_all_vm_template(hypervisor)
|
||||
elsif vm_id
|
||||
print_one_vm_info(hypervisor, vm_id)
|
||||
else
|
||||
print_all_vm_info(hypervisor)
|
||||
end
|
39
src/vmm_mad/remotes/lxd/prereconfigure
Executable file
39
src/vmm_mad/remotes/lxd/prereconfigure
Executable file
@ -0,0 +1,39 @@
|
||||
#!/usr/bin/ruby
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2018, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
$LOAD_PATH.unshift File.dirname(__FILE__)
|
||||
|
||||
require 'container'
|
||||
|
||||
require_relative '../../scripts_common'
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Action Arguments, STDIN includes XML description of the OpenNebula VM
|
||||
# ------------------------------------------------------------------------------
|
||||
vm_name = ARGV[0]
|
||||
vm_id = ARGV[2]
|
||||
|
||||
xml = STDIN.read
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Setup Context for the container
|
||||
# ------------------------------------------------------------------------------
|
||||
client = LXDClient.new
|
||||
container = Container.get(vm_name, xml, client)
|
||||
|
||||
container.detach_context
|
42
src/vmm_mad/remotes/lxd/reboot
Executable file
42
src/vmm_mad/remotes/lxd/reboot
Executable file
@ -0,0 +1,42 @@
|
||||
#!/usr/bin/ruby
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2018, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
$LOAD_PATH.unshift File.dirname(__FILE__)
|
||||
|
||||
require 'container'
|
||||
|
||||
require_relative '../../scripts_common'
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Action Arguments, STDIN includes XML description of the OpenNebula VM
|
||||
# ------------------------------------------------------------------------------
|
||||
vm_name = ARGV[0]
|
||||
|
||||
client = LXDClient.new
|
||||
container = Container.get(vm_name, nil, client)
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Stop the container, start it and reset VNC server
|
||||
# ------------------------------------------------------------------------------
|
||||
if ARGV[-1] == '-f'
|
||||
container.stop(:force => true)
|
||||
else
|
||||
container.stop
|
||||
end
|
||||
|
||||
container.start
|
43
src/vmm_mad/remotes/lxd/reconfigure
Executable file
43
src/vmm_mad/remotes/lxd/reconfigure
Executable file
@ -0,0 +1,43 @@
|
||||
#!/usr/bin/ruby
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2018, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
$LOAD_PATH.unshift File.dirname(__FILE__)
|
||||
|
||||
require 'container'
|
||||
|
||||
require_relative '../../scripts_common'
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Action Arguments, STDIN includes XML description of the OpenNebula VM
|
||||
# ------------------------------------------------------------------------------
|
||||
vm_name = ARGV[0]
|
||||
iso_path = ARGV[2]
|
||||
vm_id = ARGV[3]
|
||||
|
||||
xml = STDIN.read
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Setup Context for the container
|
||||
# ------------------------------------------------------------------------------
|
||||
if iso_path != ''
|
||||
client = LXDClient.new
|
||||
container = Container.get(vm_name, xml, client)
|
||||
|
||||
container.attach_context
|
||||
container.exec('one-contextd local 2>/dev/null')
|
||||
end
|
19
src/vmm_mad/remotes/lxd/reset
Executable file
19
src/vmm_mad/remotes/lxd/reset
Executable file
@ -0,0 +1,19 @@
|
||||
#!/bin/bash
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2018, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
$(dirname $0)/reboot $1 '-f'
|
1
src/vmm_mad/remotes/lxd/resize_disk
Symbolic link
1
src/vmm_mad/remotes/lxd/resize_disk
Symbolic link
@ -0,0 +1 @@
|
||||
../common/not_supported.sh
|
1
src/vmm_mad/remotes/lxd/restore
Symbolic link
1
src/vmm_mad/remotes/lxd/restore
Symbolic link
@ -0,0 +1 @@
|
||||
../common/not_supported.sh
|
1
src/vmm_mad/remotes/lxd/save
Symbolic link
1
src/vmm_mad/remotes/lxd/save
Symbolic link
@ -0,0 +1 @@
|
||||
../common/not_supported.sh
|
57
src/vmm_mad/remotes/lxd/shutdown
Executable file
57
src/vmm_mad/remotes/lxd/shutdown
Executable file
@ -0,0 +1,57 @@
|
||||
#!/usr/bin/ruby
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2018, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
$LOAD_PATH.unshift File.dirname(__FILE__)
|
||||
|
||||
require 'container'
|
||||
|
||||
require_relative '../../scripts_common'
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Action Arguments, STDIN includes XML description of the OpenNebula VM
|
||||
# ------------------------------------------------------------------------------
|
||||
vm_name = ARGV[0]
|
||||
vm_id = ARGV[2]
|
||||
|
||||
xml = STDIN.read
|
||||
|
||||
client = LXDClient.new
|
||||
container = Container.get(vm_name, xml, client)
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Stop the container & unmap devices if not a wild container
|
||||
# ------------------------------------------------------------------------------
|
||||
if ARGV[-1] == '-f'
|
||||
container.stop(:force => true)
|
||||
else
|
||||
container.stop
|
||||
end
|
||||
|
||||
if !container.wild?
|
||||
begin
|
||||
container.setup_storage('unmap')
|
||||
rescue StandardError => e
|
||||
container.start
|
||||
raise e
|
||||
end
|
||||
|
||||
container.delete
|
||||
|
||||
end
|
||||
|
||||
container.vnc('stop')
|
1
src/vmm_mad/remotes/lxd/snapshot_create
Symbolic link
1
src/vmm_mad/remotes/lxd/snapshot_create
Symbolic link
@ -0,0 +1 @@
|
||||
../common/not_supported.sh
|
1
src/vmm_mad/remotes/lxd/snapshot_delete
Symbolic link
1
src/vmm_mad/remotes/lxd/snapshot_delete
Symbolic link
@ -0,0 +1 @@
|
||||
../common/not_supported.sh
|
1
src/vmm_mad/remotes/lxd/snapshot_revert
Symbolic link
1
src/vmm_mad/remotes/lxd/snapshot_revert
Symbolic link
@ -0,0 +1 @@
|
||||
../common/not_supported.sh
|
@ -16,76 +16,142 @@
|
||||
|
||||
module VNMMAD
|
||||
|
||||
module VNMNetwork
|
||||
module VNMNetwork
|
||||
|
||||
# This Hash will be pppulated by the NicKVM and other hypervisor-nic
|
||||
# specific classes.
|
||||
HYPERVISORS = {}
|
||||
# This Hash will be pppulated by the NicKVM and other hypervisor-nic
|
||||
# specific classes.
|
||||
HYPERVISORS = {}
|
||||
|
||||
# This class represents the NICS of a VM, it provides a factory method
|
||||
# to create VMs of the given hyprtvisor
|
||||
class Nics < Array
|
||||
def initialize(hypervisor)
|
||||
@nicClass = HYPERVISORS[hypervisor] || NicKVM
|
||||
end
|
||||
# This class represents the NICS of a VM, it provides a factory method
|
||||
# to create VMs of the given hyprtvisor
|
||||
class Nics < Array
|
||||
|
||||
def new_nic
|
||||
@nicClass.new
|
||||
end
|
||||
end
|
||||
|
||||
############################################################################
|
||||
# Hypervisor specific implementation of network interfaces. Each class
|
||||
# implements the following interface:
|
||||
# - get_info to populste the VM.vm_info Hash
|
||||
# - get_tap to set the [:tap] attribute with the associated NIC
|
||||
############################################################################
|
||||
|
||||
# A NIC using KVM. This class implements functions to get the physical
|
||||
# interface that the NIC is using, based on the MAC address
|
||||
class NicKVM < Hash
|
||||
VNMNetwork::HYPERVISORS["kvm"] = self
|
||||
|
||||
def initialize
|
||||
super(nil)
|
||||
end
|
||||
|
||||
# Get the VM information with virsh dumpxml
|
||||
def get_info(vm)
|
||||
if vm.deploy_id
|
||||
deploy_id = vm.deploy_id
|
||||
else
|
||||
deploy_id = vm['DEPLOY_ID']
|
||||
def initialize(hypervisor)
|
||||
@nicClass = HYPERVISORS[hypervisor] || NicKVM
|
||||
end
|
||||
|
||||
if deploy_id and vm.vm_info[:dumpxml].nil?
|
||||
vm.vm_info[:dumpxml] = `#{VNMNetwork::COMMANDS[:virsh]} dumpxml #{deploy_id} 2>/dev/null`
|
||||
def new_nic
|
||||
@nicClass.new
|
||||
end
|
||||
|
||||
vm.vm_info.each_key do |k|
|
||||
vm.vm_info[k] = nil if vm.vm_info[k].to_s.strip.empty?
|
||||
end
|
||||
|
||||
############################################################################
|
||||
# Hypervisor specific implementation of network interfaces. Each class
|
||||
# implements the following interface:
|
||||
# - get_info to populste the VM.vm_info Hash
|
||||
# - get_tap to set the [:tap] attribute with the associated NIC
|
||||
############################################################################
|
||||
|
||||
# A NIC using KVM. This class implements functions to get the physical
|
||||
# interface that the NIC is using, based on the MAC address
|
||||
class NicKVM < Hash
|
||||
|
||||
VNMNetwork::HYPERVISORS['kvm'] = self
|
||||
|
||||
def initialize
|
||||
super(nil)
|
||||
end
|
||||
|
||||
# Get the VM information with virsh dumpxml
|
||||
def get_info(vm)
|
||||
if vm.deploy_id
|
||||
deploy_id = vm.deploy_id
|
||||
else
|
||||
deploy_id = vm['DEPLOY_ID']
|
||||
end
|
||||
|
||||
if deploy_id && vm.vm_info[:dumpxml].nil?
|
||||
vm.vm_info[:dumpxml] = `#{VNMNetwork::COMMANDS[:virsh]} dumpxml #{deploy_id} 2>/dev/null`
|
||||
|
||||
vm.vm_info.each_key do |k|
|
||||
vm.vm_info[k] = nil if vm.vm_info[k].to_s.strip.empty?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Look for the tap in
|
||||
# devices/interface[@type='bridge']/mac[@address='<mac>']/../target"
|
||||
def get_tap(vm)
|
||||
dumpxml = vm.vm_info[:dumpxml]
|
||||
# Look for the tap in
|
||||
# devices/interface[@type='bridge']/mac[@address='<mac>']/../target"
|
||||
def get_tap(vm)
|
||||
dumpxml = vm.vm_info[:dumpxml]
|
||||
|
||||
if dumpxml
|
||||
dumpxml_root = REXML::Document.new(dumpxml).root
|
||||
if dumpxml
|
||||
dumpxml_root = REXML::Document.new(dumpxml).root
|
||||
|
||||
xpath = "devices/interface[@type='bridge']/" \
|
||||
"mac[@address='#{self[:mac]}']/../target"
|
||||
xpath = "devices/interface[@type='bridge']/" \
|
||||
"mac[@address='#{self[:mac]}']/../target"
|
||||
|
||||
tap = dumpxml_root.elements[xpath]
|
||||
tap = dumpxml_root.elements[xpath]
|
||||
|
||||
self[:tap] = tap.attributes['dev'] if tap
|
||||
self[:tap] = tap.attributes['dev'] if tap
|
||||
end
|
||||
|
||||
self
|
||||
end
|
||||
|
||||
self
|
||||
end
|
||||
|
||||
# A NIC using LXD. This class implements functions to get the physical
|
||||
# interface that the NIC is using, based on the MAC address
|
||||
class NicLXD < Hash
|
||||
|
||||
VNMNetwork::HYPERVISORS['lxd'] = self
|
||||
|
||||
def initialize
|
||||
super(nil)
|
||||
end
|
||||
|
||||
# Get the VM information with lxc config show
|
||||
def get_info(vm)
|
||||
if vm.deploy_id
|
||||
deploy_id = vm.deploy_id
|
||||
else
|
||||
deploy_id = vm['DEPLOY_ID']
|
||||
end
|
||||
|
||||
if deploy_id && vm.vm_info[:dumpxml].nil?
|
||||
vm.vm_info[:dumpxml] = YAML.safe_load(`lxc config show #{deploy_id} 2>/dev/null`)
|
||||
|
||||
vm.vm_info.each_key do |k|
|
||||
vm.vm_info[k] = nil if vm.vm_info[k].to_s.strip.empty?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Look for the tap in config
|
||||
def get_tap(vm)
|
||||
dumpxml = vm.vm_info[:dumpxml]
|
||||
|
||||
if dumpxml
|
||||
devices = dumpxml['devices']
|
||||
xpath = find_path(devices, self[:mac])
|
||||
end
|
||||
|
||||
if xpath
|
||||
self[:tap] = devices[xpath]['host_name'] if devices[xpath]['host_name']
|
||||
end
|
||||
|
||||
self
|
||||
end
|
||||
|
||||
def find_path(hash, text)
|
||||
path = '' unless path.is_a?(String)
|
||||
hash.each do |k, v|
|
||||
if v == text
|
||||
return k
|
||||
end
|
||||
|
||||
if v.is_a?(Hash)
|
||||
path = k
|
||||
tmp = find_path(v, text)
|
||||
end
|
||||
return path unless tmp.nil?
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user