diff options
Diffstat (limited to 'patches/opnfv-fuel/0015-virtual_fuel-initial-support-for-libvirt-volumes.patch')
-rw-r--r-- | patches/opnfv-fuel/0015-virtual_fuel-initial-support-for-libvirt-volumes.patch | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/patches/opnfv-fuel/0015-virtual_fuel-initial-support-for-libvirt-volumes.patch b/patches/opnfv-fuel/0015-virtual_fuel-initial-support-for-libvirt-volumes.patch new file mode 100644 index 00000000..87266ef8 --- /dev/null +++ b/patches/opnfv-fuel/0015-virtual_fuel-initial-support-for-libvirt-volumes.patch @@ -0,0 +1,209 @@ +From: Josep Puigdemont <josep.puigdemont@enea.com> +Date: Wed, 4 May 2016 14:27:23 +0200 +Subject: [PATCH] virtual_fuel: initial support for libvirt volumes + +This patch introduces the ability to create volumes on the libvirt host +where the Fuel VM is being deployed. For now a default pool is used, +but the idea is to allow this to be configured. + +Since all virsh commands honor LIBVIRT_DEFAULT_URI, we use this +environment variable to detect wheter we should create a volume or not. +The rationale being that this environment variable will only be set if +the user wants to do the VM deployment on a remote libvirt host. + +All this could also be done using scp and a user directory on the host +machine, but using pools allows us to take advantage of libvirt's +policies and file permissions. + +CHANGE: before this patch, the file system image was named like the VM: +vm_name.raw. This patch introduces a change and adds a timestamp suffix +to the image: vm_name-timestamp.raw. This is so to avoid collisions with +an image with the same name on the remote pool. It may also be useful to +keep around old images for later testing, while the VM definition can +likely be the same. + +FIXME: This patch will use a pool called "jenkins" in the libvirt +server, and it will fail if it is not present. This is a requirement +that should be amended in the future, and properly documented. + +Signed-off-by: Josep Puigdemont <josep.puigdemont@enea.com> +--- + deploy/deploy.py | 5 +++ + deploy/dha_adapters/libvirt_adapter.py | 28 +++++++++++++++++ + deploy/environments/virtual_fuel.py | 57 +++++++++++++++++++++++++++++----- + deploy/install_fuel_master.py | 8 +++-- + 4 files changed, 88 insertions(+), 10 deletions(-) + +diff --git a/deploy/deploy.py b/deploy/deploy.py +index f86f2be..265e888 100755 +--- a/deploy/deploy.py ++++ b/deploy/deploy.py +@@ -243,6 +243,11 @@ class AutoDeploy(object): + + + def check_bridge(pxe_bridge, dha_path): ++ # Assume that bridges on remote nodes exists, we could ssh but ++ # the remote user might not have a login shell. ++ if os.environ.get('LIBVIRT_DEFAULT_URI'): ++ return ++ + with io.open(dha_path) as yaml_file: + dha_struct = yaml.load(yaml_file) + if dha_struct['adapter'] != 'libvirt': +diff --git a/deploy/dha_adapters/libvirt_adapter.py b/deploy/dha_adapters/libvirt_adapter.py +index 85913ac..8f3042c 100644 +--- a/deploy/dha_adapters/libvirt_adapter.py ++++ b/deploy/dha_adapters/libvirt_adapter.py +@@ -11,6 +11,7 @@ + from lxml import etree + from hardware_adapter import HardwareAdapter + import tempfile ++import os + + from common import ( + log, +@@ -23,6 +24,13 @@ DEV = {'pxe': 'network', + 'disk': 'hd', + 'iso': 'cdrom'} + ++vol_xml_template = '''<volume type='file'> ++ <name>%s</name> ++ <capacity unit='%s'>%s</capacity> ++ <target> ++ <format type='%s'/> ++ </target> ++</volume>''' + + class LibvirtAdapter(HardwareAdapter): + +@@ -140,3 +148,23 @@ class LibvirtAdapter(HardwareAdapter): + + def get_virt_net_conf_dir(self): + return self.dha_struct['virtNetConfDir'] ++ ++ def upload_iso(self, iso_file): ++ size = os.path.getsize(iso_file) ++ vol_name = os.path.basename(iso_file) ++ vol_xml = vol_xml_template % (vol_name, 'bytes', str(size), 'raw') ++ fd, fname = tempfile.mkstemp(text=True, suffix='deploy') ++ os.write(fd, vol_xml) ++ os.close(fd) ++ ++ log(vol_xml) ++ pool = 'jenkins' # FIXME ++ exec_cmd('virsh vol-create --pool %s %s' % (pool, fname)) ++ vol_path = exec_cmd('virsh vol-path --pool %s %s' % (pool, vol_name)) ++ ++ exec_cmd('virsh vol-upload %s %s' % (vol_path, iso_file), ++ attempts=5, delay=10, verbose=True) ++ ++ delete(fname) ++ ++ return vol_path +diff --git a/deploy/environments/virtual_fuel.py b/deploy/environments/virtual_fuel.py +index 82c4e47..56d6f98 100644 +--- a/deploy/environments/virtual_fuel.py ++++ b/deploy/environments/virtual_fuel.py +@@ -11,14 +11,33 @@ + from lxml import etree + from execution_environment import ExecutionEnvironment + import tempfile ++import os ++import re + + from common import ( + exec_cmd, + check_file_exists, + check_if_root, + delete, ++ log, + ) + ++vol_xml_template = '''<volume type='file'> ++ <name>%s</name> ++ <capacity unit='%s'>%s</capacity> ++ <target> ++ <format type='%s'/> ++ </target> ++</volume>''' ++ ++def get_size_and_unit(s): ++ p = re.compile('^(\d+)\s*(\D+)') ++ m = p.match(s) ++ if m == None: ++ return None, None ++ size = m.groups()[0] ++ unit = m.groups()[1] ++ return size, unit + + class VirtualFuel(ExecutionEnvironment): + +@@ -51,19 +70,41 @@ class VirtualFuel(ExecutionEnvironment): + with open(temp_vm_file, 'w') as f: + vm_xml.write(f, pretty_print=True, xml_declaration=True) + ++ def create_volume(self, pool, name, su, img_type='qcow2'): ++ log('Creating image using Libvirt volumes in pool %s, name: %s' % ++ (pool, name)) ++ size, unit = get_size_and_unit(su) ++ if size == None: ++ err('Could not determine size and unit of %s' % s) ++ ++ vol_xml = vol_xml_template % (name, unit, str(size), img_type) ++ fname = os.path.join(self.temp_dir, '%s_vol.xml' % name) ++ with file(fname, 'w') as f: ++ f.write(vol_xml) ++ ++ exec_cmd('virsh vol-create --pool %s %s' % (pool, fname)) ++ vol_path = exec_cmd('virsh vol-path --pool %s %s' % (pool, name)) ++ ++ delete(fname) ++ ++ return vol_path ++ + def create_image(self, disk_path, disk_size): +- exec_cmd('qemu-img create -f qcow2 %s %s' % (disk_path, disk_size)) ++ if os.environ.get('LIBVIRT_DEFAULT_URI') == None: ++ exec_cmd('qemu-img create -f qcow2 %s %s' % (disk_path, disk_size)) ++ else: ++ pool = 'jenkins' # FIXME ++ name = os.path.basename(disk_path) ++ disk_path = self.create_volume(pool, name, disk_size) + +- def create_vm(self): +- vm_template = '%s/%s' % (self.root_dir, +- self.dha.get_node_property( +- self.fuel_node_id, 'libvirtTemplate')) +- check_file_exists(vm_template) ++ return disk_path + +- disk_path = '%s/%s.raw' % (self.storage_dir, self.vm_name) ++ def create_vm(self): ++ stamp = time.strftime("%Y%m%d%H%M%S") ++ disk_path = '%s/%s-%s.raw' % (self.storage_dir, self.vm_name, stamp) + disk_sizes = self.dha.get_disks() + disk_size = disk_sizes['fuel'] +- self.create_image(disk_path, disk_size) ++ disk_path = self.create_image(disk_path, disk_size) + + temp_vm_file = '%s/%s' % (self.temp_dir, self.vm_name) + exec_cmd('cp %s %s' % (vm_template, temp_vm_file)) +diff --git a/deploy/install_fuel_master.py b/deploy/install_fuel_master.py +index 4f6a052..1c1bf05 100644 +--- a/deploy/install_fuel_master.py ++++ b/deploy/install_fuel_master.py +@@ -54,8 +54,12 @@ class InstallFuelMaster(object): + + self.dha.node_power_off(self.fuel_node_id) + +- log('Zero the MBR') +- self.dha.node_zero_mbr(self.fuel_node_id) ++ if os.environ.get('LIBVIRT_DEFAULT_URI'): ++ log('Upload ISO to pool') ++ self.iso_file = self.dha.upload_iso(self.iso_file) ++ else: ++ log('Zero the MBR') ++ self.dha.node_zero_mbr(self.fuel_node_id) + + self.dha.node_set_boot_order(self.fuel_node_id, ['disk', 'iso']) + |