def update_device_info(cls, vm, device_conf): conf_aliases = frozenset([getattr(conf, 'alias') for conf in device_conf if hasattr(conf, 'alias')]) dev_aliases = frozenset([dev['alias'] for dev in vm.conf['devices'] if 'alias' in dev]) for element in vm.domain.get_device_elements('memory'): address, alias = parse_device_ident(element) node = int(vmxml.text(vmxml.find_first(element, 'node'))) size = int(vmxml.text(vmxml.find_first(element, 'size'))) if alias not in conf_aliases: for conf in device_conf: if not hasattr(conf, 'alias') and \ conf.node == node and \ conf.size == size: conf.address = address conf.alias = alias break if alias not in dev_aliases: for dev in vm.conf['devices']: if dev['type'] == hwclass.MEMORY and \ dev.get('alias') is None and \ dev.get('node') == node and \ dev.get('size', 0) * 1024 == size: dev['address'] = address dev['alias'] = alias break
def io_tune_dom_to_values(dom): """ This method converts the VmDiskDeviceTuneLimits structure from its XML representation to the dictionary representation. :param dom: XML DOM object to parse :return: The structure in the dictionary form """ values = {} if vmxml.attr(dom, "name"): values["name"] = vmxml.attr(dom, "name") if vmxml.attr(dom, "path"): values["path"] = vmxml.attr(dom, "path") element = vmxml.find_first(dom, "guaranteed", None) if element is not None: values["guaranteed"] = {} collect_inner_elements(element, values["guaranteed"]) element = vmxml.find_first(dom, "maximum", None) if element is not None: values["maximum"] = {} collect_inner_elements(element, values["maximum"]) return values
def from_xml_tree(cls, log, dev, meta): params = parse_device_params(dev) target = vmxml.find_first(dev, 'target') params['size'] = ( int(vmxml.text(vmxml.find_first(target, 'size'))) / 1024 ) params['node'] = vmxml.text(vmxml.find_first(target, 'node')) return cls(log, **params)
def from_xml_tree(cls, log, dev, meta): params = { 'lease_id': vmxml.text(vmxml.find_first(dev, 'key')), 'sd_id': vmxml.text(vmxml.find_first(dev, 'lockspace')), 'path': vmxml.find_attr(dev, 'target', 'path'), 'offset': vmxml.find_attr(dev, 'target', 'offset'), } return cls(log, **params)
def update_from_xml(cls, vm, device_conf, device_xml): alias = core.find_device_alias(device_xml) source = vmxml.find_first(device_xml, 'source') address = vmxml.find_first(source, 'address') uuid = address.attrib['uuid'] for dev in device_conf: if isinstance(dev, MdevDevice) and uuid == dev.mdev_uuid: dev.alias = alias return
def dev_elems_from_xml(vm, xml): """ Return device instance building elements from provided XML. The XML must contain <devices> element with a single device subelement, the one to create the instance for. Depending on the device kind <metadata> element may be required to provide device metadata; the element may and needn't contain unrelated metadata. This function is used in device hot(un)plugs. Example `xml` value (top element tag may be arbitrary): <?xml version='1.0' encoding='UTF-8'?> <hotplug> <devices> <interface type="bridge"> <mac address="66:55:44:33:22:11"/> <model type="virtio" /> <source bridge="ovirtmgmt" /> <filterref filter="vdsm-no-mac-spoofing" /> <link state="up" /> <bandwidth /> </interface> </devices> <metadata xmlns:ns0="http://ovirt.org/vm/tune/1.0" xmlns:ovirt-vm="http://ovirt.org/vm/1.0"> <ovirt-vm:vm xmlns:ovirt-vm="http://ovirt.org/vm/1.0"> <ovirt-vm:device mac_address='66:55:44:33:22:11'> <ovirt-vm:network>test</ovirt-vm:network> <ovirt-vm:portMirroring> <ovirt-vm:network>network1</ovirt-vm:network> <ovirt-vm:network>network2</ovirt-vm:network> </ovirt-vm:portMirroring> </ovirt-vm:device> </ovirt-vm:vm> </metadata> </hotplug> :param xml: XML specifying the device as described above. :type xml: basestring :returns: Triplet (device_class, device_element, device_meta) where `device_class` is the class to be used to create the device instance; `device_element` and `device_meta` are objects to be passed as arguments to device_class `from_xml_tree` method. """ dom = xmlutils.fromstring(xml) devices = vmxml.find_first(dom, 'devices') dev_elem = next(vmxml.children(devices)) _dev_type, dev_class = identify_from_xml_elem(dev_elem) meta = vmxml.find_first(dom, 'metadata', None) if meta is None: md_desc = metadata.Descriptor() else: md_desc = metadata.Descriptor.from_xml(xmlutils.tostring(meta)) dev_meta = _get_metadata_from_elem_xml(vm.id, md_desc, dev_class, dev_elem) return dev_class, dev_elem, dev_meta
def from_xml_tree(cls, log, dev, meta): params = parse_device_params(dev, attrs=('model', )) params['specParams'] = parse_device_attrs( vmxml.find_first(dev, 'rate'), ('period', 'bytes') ) params['specParams']['source'] = rngsources.get_source_name( vmxml.text(vmxml.find_first(dev, 'backend')) ) params['vmid'] = meta['vmid'] return cls(log, **params)
def parse_xml(dev, meta): params = { 'type': dev.tag, 'device': core.find_device_type(dev), 'lease_id': vmxml.text(vmxml.find_first(dev, 'key')), 'sd_id': vmxml.text(vmxml.find_first(dev, 'lockspace')), 'path': vmxml.find_attr(dev, 'target', 'path'), 'offset': vmxml.find_attr(dev, 'target', 'offset'), } core.update_device_params(params, dev) core.update_device_params_from_meta(params, meta) return params
def update_disk_element_from_object(disk_element, vm_drive, log, replace_attribs=False): # key: (old_value, new_value) changes = {} # the only change relevant for floppies is the path, # because their only usage left is sysprep - aka payload devices. device = disk_element.attrib.get('device') old_disk_type = disk_element.attrib.get('type') disk_type = vm_drive.diskType if device != 'floppy': vmxml.set_attr(disk_element, 'type', disk_type) changes['type'] = (old_disk_type, disk_type) # update the path source = vmxml.find_first(disk_element, 'source') old_disk_attr = storage.SOURCE_ATTR[old_disk_type] # on resume, empty CDroms may lack the 'file' attribute old_path = source.attrib.get(old_disk_attr, None) if old_path is not None and replace_attribs: del source.attrib[old_disk_attr] disk_attr = storage.SOURCE_ATTR[disk_type] vmxml.set_attr(source, disk_attr, vm_drive.path) changes['path'] = ( '%s=%s' % (old_disk_attr, '' if old_path is None else old_path), # We intentionally create the new value using a different format # - note leading asterisk - to force the _log_changes function to # always log this information. # We want to see how good is Engine at predicting drive paths, # and how often Vdsm needs to correct that. '*%s=%s' % (disk_attr, vm_drive.path), ) if device != 'floppy': # update the format (the disk might have been collapsed) driver = vmxml.find_first(disk_element, 'driver') drive_format = 'qcow2' if vm_drive.format == 'cow' else 'raw' # on resume, CDroms may have minimal 'driver' attribute old_drive_format = driver.attrib.get('type') vmxml.set_attr(driver, 'type', drive_format) changes['format'] = (old_drive_format, drive_format) # dynamic_ownership workaround if (disk_type == storage.DISK_TYPE.FILE or disk_type == storage.DISK_TYPE.BLOCK): try: vmxml.find_first(source, 'seclabel') except vmxml.NotFound: storage.disable_dynamic_ownership(source) _log_changes(log, 'drive', vm_drive.name, changes)
def test_find_first_nested(self): XML = u'''<?xml version="1.0" ?> <topelement> <subelement id="1"> <subelement id="2"/> </subelement> </topelement> ''' dom = vmxml.parse_xml(XML) sub1 = vmxml.find_first(dom, 'subelement') # outermost sub2 = vmxml.find_first(sub1, 'subelement') # innermost last = vmxml.find_first(sub2, 'subelement') self.assertIsNot(sub2, last)
def from_xml_tree(cls, log, dev, meta): params = { 'device': dev.tag, 'type': find_device_type(dev), } update_device_params(params, dev) target = vmxml.find_first(dev, 'target') params['size'] = ( int(vmxml.text(vmxml.find_first(target, 'size'))) // 1024 ) params['node'] = vmxml.text(vmxml.find_first(target, 'node')) update_device_params_from_meta(params, meta) return cls(log, **params)
def _make_spec_params(dev, meta): spec_params = { 'copyPasteEnable': _is_feature_flag_enabled( dev, 'clipboard', 'copypaste' ), 'fileTransferEnable': _is_feature_flag_enabled( dev, 'filetransfer', 'enable' ), } key_map = dev.attrib.get('keymap') if key_map: spec_params['keyMap'] = key_map # we need some overrides to undo legacy defaults display_network = meta.get('display_network') if display_network: spec_params['displayNetwork'] = display_network listen = vmxml.find_first(dev, 'listen') if listen.attrib.get('type') == 'network': xml_display_network = listen.attrib.get('network') if xml_display_network: spec_params['displayNetwork'] = libvirtnetwork.netname_l2o( xml_display_network ) elif listen.attrib.get('type') == 'address': spec_params['displayIp'] = listen.attrib.get('address', '0') return spec_params
def _update_unknown_device_info(vm): """ Obtain info about unknown devices from libvirt domain and update the corresponding device structures. Unknown device is a device that has an address but wasn't passed during VM creation request. :param vm: VM for which the device info should be updated :type vm: `class:Vm` instance """ def isKnownDevice(alias): for dev in vm.conf['devices']: if dev.get('alias') == alias: return True return False for x in vmxml.children(vm.domain.devices): # Ignore empty nodes and devices without address if vmxml.find_first(x, 'address', None) is None: continue alias = core.find_device_alias(x) if not isKnownDevice(alias): address = vmxml.device_address(x) # In general case we assume that device has attribute 'type', # if it hasn't dom_attribute returns ''. device = vmxml.attr(x, 'type') newDev = {'type': vmxml.tag(x), 'alias': alias, 'device': device, 'address': address} vm.conf['devices'].append(newDev)
def update_from_xml(cls, vm, device_conf, device_xml): alias = core.find_device_alias(device_xml) address = vmxml.device_address(device_xml) source = vmxml.find_first(device_xml, 'source') device = pci_address_to_name(**vmxml.device_address(source)) # We can assume the device name to be correct since we're # inspecting source element. For the address, we may look at # both addresses and determine the correct one. if pci_address_to_name(**address) == device: address = vmxml.device_address(device_xml, 1) known_device = False for dev in device_conf: if dev.device == device: dev.alias = alias dev.address = address known_device = True for dev in vm.conf['devices']: if dev['device'] == device: dev['alias'] = alias dev['address'] = address if not known_device: device = pci_address_to_name(**vmxml.device_address(source)) hostdevice = { 'type': hwclass.HOSTDEV, 'device': device, 'alias': alias, 'address': address, } vm.conf['devices'].append(hostdevice)
def test_remove_child(self): top = vmxml.find_first(self._dom, 'topelement') hello = list(vmxml.find_all(top, 'hello')) old = hello[1] vmxml.remove_child(top, old) updated_hello = list(vmxml.find_all(top, 'hello')) hello = hello[:1] + hello[2:] self.assertEqual(updated_hello, hello)
def from_xml_tree(cls, log, dev, meta): params = {'type': find_device_type(dev)} update_device_params(params, dev, attrs=('model', )) params['device'] = params['model'] rate = vmxml.find_first(dev, 'rate', None) if rate is not None: params['specParams'] = parse_device_attrs( rate, ('period', 'bytes') ) else: params['specParams'] = {} params['specParams']['source'] = rngsources.get_source_name( vmxml.text(vmxml.find_first(dev, 'backend')) ) update_device_params_from_meta(params, meta) params['vmid'] = meta['vmid'] return cls(log, **params)
def test_find_all(self, start_tag, tag, number): dom = self._dom if start_tag is not None: dom = vmxml.find_first(self._dom, 'topelement') elements = vmxml.find_all(dom, tag) matches = [vmxml.tag(e) == tag for e in elements] self.assertTrue(all(matches)) self.assertEqual(len(matches), number)
def from_xml_tree(cls, log, dev, meta): params = parse_device_params(dev) # override params['device'] = vmxml.find_attr(dev, 'model', 'type') params['specParams'] = parse_device_attrs( vmxml.find_first(dev, 'model'), ('vram', 'heads', 'vgamem', 'ram') ) return cls(log, **params)
def from_xml_tree(cls, log, dev, meta): params = parse_device_params(dev) specParams = parse_device_attrs(dev, ('model',)) backend = vmxml.find_first(dev, 'backend') specParams['mode'] = vmxml.attr(backend, 'type') specParams['path'] = vmxml.find_attr( dev, 'device', 'path') params['specParams'] = specParams return cls(log, **params)
def test_restore_paths(self): xml = self.XML second_disk_path = '/path/secondary-drive' snapshot_params = {'path': '/path/snapshot-path', 'volume_id': 'aaa', 'device': '/dev/random', 'second_disk_path': second_disk_path, } engine_params = {'path': '/path/engine-path', 'volume_id': 'bbb', 'device': '/dev/urandom', 'second_disk_path': second_disk_path, } snapshot_xml = xml.format(**snapshot_params) engine_xml = xml.format(**engine_params) params = {'_srcDomXML': snapshot_xml, 'xml': engine_xml, 'restoreState': { 'device': 'disk', 'imageID': u'111', 'poolID': u'222', 'domainID': u'333', 'volumeID': u'bbb', }, 'restoreFromSnapshot': True, } with fake.VM(params) as vm: vm._normalizeVdsmImg = lambda *args: None devices = vm._make_devices() vm_xml = vm.conf['xml'] # Check that unrelated devices are taken from the snapshot untouched, # not from the XML provided from Engine: for d in devices[hwclass.RNG]: self.assertEqual(d.specParams['source'], os.path.basename(snapshot_params['device'])) break else: raise Exception('RNG device not found') tested_drives = (('1234', engine_params['path'],), ('5678', second_disk_path,),) for serial, path in tested_drives: for d in devices[hwclass.DISK]: if d.serial == serial: self.assertEqual(d.path, path) break else: raise Exception('Tested drive not found', serial) dom = xmlutils.fromstring(vm_xml) random = vmxml.find_first(dom, 'backend') self.assertEqual(random.text, snapshot_params['device']) for serial, path in tested_drives: for d in dom.findall(".//disk[serial='{}']".format(serial)): self.assertEqual(vmxml.find_attr(d, 'source', 'file'), path) break else: raise Exception('Tested drive not found', serial) self.assertEqual(vm_xml, vm._domain.xml)
def _update_driver_params(params, dev): driver = vmxml.find_first(dev, 'driver', None) if driver is not None: driver_params, spec_params = _get_driver_params(driver) params.update(driver_params) params['specParams'].update(spec_params) else: # the initialization code always checks this parameter params['propagateErrors'] = 'off'
def _get_device_name(dev, dev_type): src_dev = vmxml.find_first(dev, 'source') src_addr = vmxml.device_address(src_dev) if dev_type == 'scsi': src_addr = _normalize_scsi_address(dev, src_addr) elif dev_type == 'pci': src_addr = _normalize_pci_address(**src_addr) elif dev_type == 'mdev': return src_addr['uuid'] return device_name_from_address(dev_type, src_addr)
def _update_iotune_params(params, dev): iotune = vmxml.find_first(dev, 'iotune', None) if iotune is None: return iotune_params = { setting.tag: int(setting.text) for setting in iotune } if iotune_params: params['iotune'] = iotune_params
def _check_leases(self, xml_str, vol_infos): xml_dom = xmlutils.fromstring(xml_str) lease_elems = xml_dom.findall('./devices/lease') self.assertEqual(len(lease_elems), len(vol_infos)) for lease_elem, vol_info in zip(lease_elems, vol_infos): target = vmxml.find_first(lease_elem, 'target') self.assertEqual( target.attrib['path'], str(vol_info['leasePath'])) self.assertEqual( target.attrib['offset'], str(vol_info['leaseOffset']))
def _get_drive_identification(dom): source = vmxml.find_first(dom, 'source', None) if source is not None: devPath = (vmxml.attr(source, 'file') or vmxml.attr(source, 'dev') or vmxml.attr(source, 'name')) else: devPath = '' name = vmxml.find_attr(dom, 'target', 'dev') alias = core.find_device_alias(dom) return alias, devPath, name
def from_xml_tree(cls, log, dev, meta): params = { 'device': vmxml.find_attr(dev, 'model', 'type'), 'type': find_device_type(dev), } update_device_params(params, dev) params['specParams'] = parse_device_attrs( vmxml.find_first(dev, 'model'), ('vram', 'heads', 'vgamem', 'ram') ) update_device_params_from_meta(params, meta) return cls(log, **params)
def _update_auth_params(params, auth): # auth may be None, and this is OK if auth is None: return secret = vmxml.find_first(auth, 'secret', None) if secret is None: return params['auth'] = { 'username': auth.attrib.get('username'), 'type': secret.attrib.get('type'), 'uuid': secret.attrib.get('uuid'), }
def test_disk_ignore_volumeinfo_from_metadata_xml(self): xml_snippet = u'''<volumeInfo> <path>/rhev/data-center/omitted/for/brevity</path> <volType>path</volType> </volumeInfo>''' root = xmlutils.fromstring(_DISK_DATA.metadata_xml) dev = vmxml.find_first(root, 'device') vmxml.append_child(dev, etree_child=xmlutils.fromstring(xml_snippet)) data = _TestData( copy.deepcopy(_DISK_DATA.conf), xmlutils.tostring(root)) self._check_drive_from_metadata_xml(data)
def drive_from_element(disk_devices, disk_element): # we try serial first for backward compatibility # REQUIRED_FOR: vdsm <= 4.2 serial_elem = vmxml.find_first(disk_element, 'serial', None) if serial_elem is not None: serial = vmxml.text(serial_elem) try: return drive_by_serial(disk_devices, serial) except LookupError: pass # try again by alias before to give up alias = core.find_device_alias(disk_element) return device_by_alias(disk_devices, alias)
def parse(dev, meta): """Parse the XML configuration of a storage device and returns the corresponding params, such as xmlutils.tostring(dev) is equivalent to params = parse(dev, meta) xmlutils.tostring(vmdevices.storage.Drive(log, **params).getXML()) Args: dev (ElementTree.Element): Root of the XML configuration snippet. meta (dict): Device-specific metadata. Returns: dict: params to be used to configure a storage.Drive. """ disk_type = core.find_device_type(dev) params = { 'device': dev.attrib.get('device', None) or dev.tag, 'type': dev.tag, 'diskType': disk_type, 'specParams': {}, } core.update_device_params(params, dev, ('sgio',)) _update_meta_params(params, meta) _update_source_params( params, disk_type, vmxml.find_first(dev, 'source', None) ) _update_payload_params(params, meta) _update_auth_params(params, vmxml.find_first(dev, 'auth', None)) _update_driver_params(params, dev) _update_interface_params(params, dev) _update_iotune_params(params, dev) _update_readonly_params(params, dev) _update_boot_params(params, dev) _update_serial_params(params, dev) add_vdsm_parameters(params) return params
def test_append_child_etree(self): empty = vmxml.find_first(self._dom, 'empty') vmxml.append_child(empty, etree_child=vmxml.parse_xml('<new/>')) self.assertIsNotNone(vmxml.find_first(self._dom, 'new', None)) empty = vmxml.find_first(self._dom, 'empty') self.assertIsNotNone(vmxml.find_first(empty, 'new', None))
def metadata(self): return vmxml.find_first(self._dom, 'metadata', None)
def update_device_info(cls, vm, device_conf): # FIXME! We need to gather as much info as possible from the libvirt. # In the future we can return this real data to management instead of # vm's conf for x in vm.domain.get_device_elements('disk'): alias, devPath, name = _get_drive_identification(x) readonly = vmxml.find_first(x, 'readonly', None) is not None bootOrder = vmxml.find_attr(x, 'boot', 'order') devType = vmxml.attr(x, 'device') if devType == 'disk': # raw/qcow2 drv = vmxml.find_attr(x, 'driver', 'type') else: drv = 'raw' # Get disk address address = vmxml.device_address(x) # Keep data as dict for easier debugging deviceDict = { 'path': devPath, 'name': name, 'readonly': readonly, 'bootOrder': bootOrder, 'address': address, 'type': devType } # display indexed pairs of ordered values from 2 dicts # such as {key_1: (valueA_1, valueB_1), ...} def mergeDicts(deviceDef, dev): return dict((k, (deviceDef[k], getattr(dev, k, None))) for k in deviceDef) vm.log.debug('Looking for drive with attributes %s', deviceDict) for d in device_conf: # When we analyze a disk device that was already discovered in # the past (generally as soon as the VM is created) we should # verify that the cached path is the one used in libvirt. # We already hit few times the problem that after a live # migration the paths were not in sync anymore (BZ#1059482). if (hasattr(d, 'alias') and d.alias == alias and d.path != devPath): vm.log.warning('updating drive %s path from %s to %s', d.alias, d.path, devPath) d.path = devPath if d.path == devPath: d.name = name d.type = devType d.drv = drv d.alias = alias d.address = address d.readonly = readonly if bootOrder: d.bootOrder = bootOrder vm.log.debug('Matched %s', mergeDicts(deviceDict, d)) # Update vm's conf with address for known disk devices knownDev = False for dev in vm.conf['devices']: # See comment in previous loop. This part is used to update # the vm configuration as well. if ('alias' in dev and dev['alias'] == alias and dev['path'] != devPath): vm.log.warning( 'updating drive %s config path from %s ' 'to %s', dev['alias'], dev['path'], devPath) dev['path'] = devPath if (dev['type'] == hwclass.DISK and dev['path'] == devPath): dev['name'] = name dev['address'] = address dev['alias'] = alias dev['readonly'] = str(readonly) if bootOrder: dev['bootOrder'] = bootOrder vm.log.debug('Matched %s', mergeDicts(deviceDict, dev)) knownDev = True # Add unknown disk device to vm's conf if not knownDev: archIface = DEFAULT_INTERFACE_FOR_ARCH[vm.arch] iface = archIface if address['type'] == 'drive' else 'pci' diskDev = { 'type': hwclass.DISK, 'device': devType, 'iface': iface, 'path': devPath, 'name': name, 'address': address, 'alias': alias, 'readonly': str(readonly) } if bootOrder: diskDev['bootOrder'] = bootOrder vm.log.warning('Found unknown drive: %s', diskDev) vm.conf['devices'].append(diskDev)
def get_identifying_attrs(cls, dev_elem): return { 'devtype': core.dev_class_from_dev_elem(dev_elem), 'name': vmxml.text(vmxml.find_first(dev_elem, 'key')), }
def test_text(self, tag, result): element = vmxml.find_first(self._dom, tag) text = vmxml.text(element) self.assertEqual(text, result)
def test_children(self, start_tag, tag, number): element = vmxml.find_first(self._dom, start_tag) self.assertEqual(len(list(vmxml.children(element, tag))), number)
def update_device_info(cls, vm, device_conf): for x in vm.domain.get_device_elements('interface'): devType = vmxml.attr(x, 'type') mac = vmxml.find_attr(x, 'mac', 'address') alias = core.find_device_alias(x) xdrivers = vmxml.find_first(x, 'driver', None) driver = ({ 'name': vmxml.attr(xdrivers, 'name'), 'queues': vmxml.attr(xdrivers, 'queues') } if xdrivers is not None else {}) if devType == 'hostdev': name = alias model = 'passthrough' else: name = vmxml.find_attr(x, 'target', 'dev') model = vmxml.find_attr(x, 'model', 'type') if model == 'virtio': # Reverse action of the conversion in __init__. model = 'pv' network = None try: if vmxml.find_attr(x, 'link', 'state') == 'down': linkActive = False else: linkActive = True except IndexError: linkActive = True source = vmxml.find_first(x, 'source', None) if source is not None: network = vmxml.attr(source, 'bridge') if not network: network = libvirtnetwork.netname_l2o( vmxml.attr(source, 'network')) address = core.find_device_guest_address(x) for nic in device_conf: if nic.macAddr.lower() == mac.lower(): nic.name = name nic.alias = alias nic.address = address nic.linkActive = linkActive if driver: # If a driver was reported, pass it back to libvirt. # Engine (vm's conf) is not interested in this value. nic.driver = driver # Update vm's conf with address for known nic devices knownDev = False for dev in vm.conf['devices']: if (dev['type'] == hwclass.NIC and dev['macAddr'].lower() == mac.lower()): dev['address'] = address dev['alias'] = alias dev['name'] = name dev['linkActive'] = linkActive knownDev = True # Add unknown nic device to vm's conf if not knownDev: nicDev = { 'type': hwclass.NIC, 'device': devType, 'macAddr': mac, 'nicModel': model, 'address': address, 'alias': alias, 'name': name, 'linkActive': linkActive } if network: nicDev['network'] = network vm.conf['devices'].append(nicDev)
def _update_driver_params(params, dev): driver = vmxml.find_first(dev, 'driver', None) if driver is not None: driver_params, spec_params = _get_driver_params(driver) params.update(driver_params) params['specParams'].update(spec_params)
def test_restore_paths(self): xml = self.XML second_disk_path = '/path/secondary-drive' snapshot_params = { 'path': '/path/snapshot-path', 'volume_id': 'aaa', 'device': '/dev/random', 'second_disk_path': second_disk_path, } engine_params = { 'path': '/path/engine-path', 'volume_id': 'bbb', 'device': '/dev/urandom', 'second_disk_path': second_disk_path, } snapshot_xml = xml.format(**snapshot_params) engine_xml = xml.format(**engine_params) params = { '_srcDomXML': snapshot_xml, 'xml': engine_xml, 'restoreState': { 'device': 'disk', 'imageID': u'111', 'poolID': u'222', 'domainID': u'333', 'volumeID': u'bbb', }, 'restoreFromSnapshot': True, } with fake.VM(params) as vm: vm._normalizeVdsmImg = lambda *args: None devices = vm._make_devices() vm_xml = vm.conf['xml'] # Check that unrelated devices are taken from the snapshot untouched, # not from the XML provided from Engine: for d in devices[hwclass.RNG]: self.assertEqual(d.specParams['source'], os.path.basename(snapshot_params['device'])) break else: raise Exception('RNG device not found') tested_drives = ( ( '1234', engine_params['path'], ), ( '5678', second_disk_path, ), ) for serial, path in tested_drives: for d in devices[hwclass.DISK]: if d.serial == serial: self.assertEqual(d.path, path) break else: raise Exception('Tested drive not found', serial) dom = xmlutils.fromstring(vm_xml) random = vmxml.find_first(dom, 'backend') self.assertEqual(random.text, snapshot_params['device']) for serial, path in tested_drives: for d in dom.findall(".//disk[serial='{}']".format(serial)): self.assertEqual(vmxml.find_attr(d, 'source', 'file'), path) break else: raise Exception('Tested drive not found', serial) self.assertEqual(vm_xml, vm._domain.xml)
def _update_readonly_params(params, dev): if vmxml.find_first(dev, 'readonly', None) is not None: params['readonly'] = True
def nvram(self): """ :return: NVRAM element defining NVRAM store (used to store UEFI or SecureBoot variables) or None if the VM has no NVRAM store. """ return vmxml.find_first(self._dom, 'os/nvram', None)
def from_xml_tree(cls, log, dev, meta): params = { 'device': core.find_device_type(dev), 'type': dev.tag, 'custom': meta.get('custom', {}), 'vmid': meta['vmid'], 'vm_custom': {}, 'specParams': {}, } core.update_device_params(params, dev) params.update(core.get_xml_elem(dev, 'macAddr', 'mac', 'address')) params.update(core.get_xml_elem(dev, 'nicModel', 'model', 'type')) params.update(core.get_xml_elem(dev, 'bootOrder', 'boot', 'order')) if params['device'] == 'hostdev': params.update(_get_hostdev_params(dev)) link = vmxml.find_first(dev, 'link', None) if link is not None: if link.attrib.get('state', 'down') == 'down': params['linkActive'] = False else: params['linkActive'] = True vlan = vmxml.find_first(dev, 'vlan', None) if vlan is not None: params['specParams']['vlanid'] = vmxml.find_attr( vlan, 'tag', 'id' ) mtu = vmxml.find_first(dev, "mtu", None) if mtu is not None: params['mtu'] = int(vmxml.attr(mtu, 'size')) filterref = vmxml.find_first(dev, 'filterref', None) if filterref is not None: params['filter'] = vmxml.attr(filterref, 'filter') params['filterParameters'] = [ { 'name': param.attrib['name'], 'value': param.attrib['value'], } for param in vmxml.find_all(filterref, 'parameter') ] driver = vmxml.find_first(dev, 'driver', None) if driver is not None: params['custom'].update( core.parse_device_attrs(driver, ('queues',)) ) sndbuf = dev.find('./tune/sndbuf') if sndbuf is not None: params['vm_custom']['sndbuf'] = vmxml.text(sndbuf) bandwidth = vmxml.find_first(dev, 'bandwidth', None) if bandwidth is not None: for mode in ('inbound', 'outbound'): elem = vmxml.find_first(bandwidth, mode, None) if elem is not None: params['specParams'][mode] = elem.attrib.copy() net = ( meta.get('network', None) or vmxml.find_attr(dev, 'source', 'bridge') ) if net is None: raise MissingNetwork("no network to join") params['network'] = net _update_port_mirroring(params, meta) core.update_device_params_from_meta(params, meta) return cls(log, **params)
def test_append_child_noargs(self): empty = vmxml.find_first(self._dom, 'empty') self.assertRaises(RuntimeError, vmxml.append_child, empty)
def add_mediated_device(dom, mdev_uuid): devs = vmxml.find_first(dom, 'devices') hostdev = libvirtxml.make_mdev_element(mdev_uuid) devs.append(hostdev)
def test_append_child_too_many_args(self): empty = vmxml.find_first(self._dom, 'empty') self.assertRaises(RuntimeError, vmxml.append_child, empty, vmxml.Element('new'), xmlutils.fromstring('<new/>'))
def test_append_child(self): empty = vmxml.find_first(self._dom, 'empty') vmxml.append_child(empty, vmxml.Element('new')) self.assertIsNotNone(vmxml.find_first(self._dom, 'new', None)) empty = vmxml.find_first(self._dom, 'empty') self.assertIsNotNone(vmxml.find_first(empty, 'new', None))
def devices(self): return vmxml.find_first(self._dom, 'devices', None)
def _update_serial_params(params, dev): serial = vmxml.find_first(dev, 'serial', None) if serial is not None: params['serial'] = vmxml.text(serial)
def test_append_child_etree(self): empty = vmxml.find_first(self._dom, 'empty') vmxml.append_child(empty, etree_child=xmlutils.fromstring('<new/>')) self.assertIsNotNone(vmxml.find_first(self._dom, 'new', None)) empty = vmxml.find_first(self._dom, 'empty') self.assertIsNotNone(vmxml.find_first(empty, 'new', None))