############################################################################### # Copyright (c) 2015 Ericsson AB and others. # szilard.cserey@ericsson.com # All rights reserved. This program and the accompanying materials # are made available under the terms of the Apache License, Version 2.0 # which accompanies this distribution, and is available at # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################### from lxml import etree from hardware_adapter import HardwareAdapter import tempfile import os from common import ( log, exec_cmd, err, delete, ) DEV = {'pxe': 'network', 'disk': 'hd', 'iso': 'cdrom'} VOL_XML_TEMPLATE = ''' {name} {size!s} ''' DEFAULT_POOL = 'jenkins' class LibvirtAdapter(HardwareAdapter): def __init__(self, yaml_path): super(LibvirtAdapter, self).__init__(yaml_path) self.parser = etree.XMLParser(remove_blank_text=True) def node_power_off(self, node_id): vm_name = self.get_node_property(node_id, 'libvirtName') log('Power OFF Node %s' % vm_name) state = exec_cmd('virsh domstate %s' % vm_name) if state == 'running': exec_cmd('virsh destroy %s' % vm_name, False) def node_power_on(self, node_id): vm_name = self.get_node_property(node_id, 'libvirtName') log('Power ON Node %s' % vm_name) state = exec_cmd('virsh domstate %s' % vm_name) if state == 'shut off': exec_cmd('virsh start %s' % vm_name) def node_reset(self, node_id): vm_name = self.get_node_property(node_id, 'libvirtName') log('Reset Node %s' % vm_name) exec_cmd('virsh reset %s' % vm_name) def translate(self, boot_order_list): translated = [] for boot_dev in boot_order_list: if boot_dev in DEV: translated.append(DEV[boot_dev]) else: err('Boot device %s not recognized' % boot_dev) return translated def node_set_boot_order(self, node_id, boot_order_list): boot_order_list = self.translate(boot_order_list) vm_name = self.get_node_property(node_id, 'libvirtName') temp_dir = tempfile.mkdtemp() log('Set boot order %s on Node %s' % (boot_order_list, vm_name)) resp = exec_cmd('virsh dumpxml %s' % vm_name) xml_dump = etree.fromstring(resp, self.parser) os = xml_dump.xpath('/domain/os') for o in os: for bootelem in ['boot', 'bootmenu']: boot = o.xpath(bootelem) for b in boot: o.remove(b) for dev in boot_order_list: b = etree.Element('boot') b.set('dev', dev) o.append(b) bmenu = etree.Element('bootmenu') bmenu.set('enable', 'no') o.append(bmenu) tree = etree.ElementTree(xml_dump) xml_file = temp_dir + '/%s.xml' % vm_name with open(xml_file, 'w') as f: tree.write(f, pretty_print=True, xml_declaration=True) exec_cmd('virsh define %s' % xml_file) delete(temp_dir) def node_zero_mbr(self, node_id): vm_name = self.get_node_property(node_id, 'libvirtName') resp = exec_cmd('virsh dumpxml %s' % vm_name) xml_dump = etree.fromstring(resp) disks = xml_dump.xpath('/domain/devices/disk') for disk in disks: if disk.get('device') == 'disk': sources = disk.xpath('source') for source in sources: disk_file = source.get('file') disk_size = exec_cmd('qemu-img info ' '%s |grep \"virtual size:\"' % disk_file).split()[2] delete(disk_file) exec_cmd('qemu-img create -f qcow2 %s %s' % (disk_file, disk_size)) def node_eject_iso(self, node_id): vm_name = self.get_node_property(node_id, 'libvirtName') device = self.get_name_of_device(vm_name, 'cdrom') exec_cmd('virsh change-media %s --eject %s --config --live' % (vm_name, device), False) def node_insert_iso(self, node_id, iso_file): vm_name = self.get_node_property(node_id, 'libvirtName') device = self.get_name_of_device(vm_name, 'cdrom') exec_cmd('virsh change-media %s --insert %s %s' % (vm_name, device, iso_file)) def get_node_pxe_mac(self, node_id): mac_list = [] vm_name = self.get_node_property(node_id, 'libvirtName') resp = exec_cmd('virsh dumpxml %s' % vm_name) xml_dump = etree.fromstring(resp) interfaces = xml_dump.xpath('/domain/devices/interface') for interface in interfaces: macs = interface.xpath('mac') for mac in macs: mac_list.append(mac.get('address').lower()) return mac_list def get_name_of_device(self, vm_name, device_type): resp = exec_cmd('virsh dumpxml %s' % vm_name) xml_dump = etree.fromstring(resp) disks = xml_dump.xpath('/domain/devices/disk') for disk in disks: if disk.get('device') == device_type: targets = disk.xpath('target') for target in targets: device = target.get('dev') if device: return device 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.format(name=vol_name, unit='bytes', size=size, format_type='raw') fd, fname = tempfile.mkstemp(text=True, suffix='deploy') os.write(fd, vol_xml) os.close(fd) log(vol_xml) pool = DEFAULT_POOL # 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