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 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 info(gxml): listen = vmxml.find_first(gxml, 'listen') display_ip = listen.attrib.get('address', '0') return { 'type': vmxml.attr(gxml, 'type'), 'port': vmxml.attr(gxml, 'port'), 'tlsPort': vmxml.attr(gxml, 'tlsPort'), 'ipAddress': display_ip, }
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': 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 _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 _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_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 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 update_device_info(cls, vm, device_conf): for device_xml in vm.domain.get_device_elements('hostdev'): device_type = vmxml.attr(device_xml, 'type') try: cls._DEVICE_MAPPING[device_type].update_from_xml( vm, device_conf, device_xml) except KeyError: # Unknown device, be careful. continue
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 update_device_info(cls, vm, device_conf): for device_xml in vm.domain.get_device_elements('hostdev'): device_type = vmxml.attr(device_xml, 'type') try: cls._DEVICE_MAPPING[device_type].update_from_xml( vm, device_conf, device_xml) except KeyError: # Unknown device, be careful. continue
def update_device_info(cls, vm, device_conf): for x in vm.domain.get_device_elements('controller'): # Ignore controller devices without address address = find_device_guest_address(x) alias = find_device_alias(x) if address is None: continue device = vmxml.attr(x, 'type') # Get model and index. Relevant for USB controllers. model = vmxml.attr(x, 'model') index = vmxml.attr(x, 'index') # In case the controller has index and/or model, they # are compared. Currently relevant for USB controllers. for ctrl in device_conf: if ((ctrl.device == device) and (not hasattr(ctrl, 'index') or ctrl.index == index) and (not hasattr(ctrl, 'model') or ctrl.model == model)): ctrl.alias = alias ctrl.address = address # Update vm's conf with address for known controller devices # In case the controller has index and/or model, they # are compared. Currently relevant for USB controllers. knownDev = False for dev in vm.conf['devices']: if ((dev['type'] == hwclass.CONTROLLER) and (dev['device'] == device) and ('index' not in dev or dev['index'] == index) and ('model' not in dev or dev['model'] == model)): dev['address'] = address dev['alias'] = alias knownDev = True # Add unknown controller device to vm's conf if not knownDev: vm.conf['devices'].append({ 'type': hwclass.CONTROLLER, 'device': device, 'address': address, 'alias': alias })
def get_number_of_cpus(self): """ Return the number of VM's CPUs as int. """ vcpu = self._dom.find('./vcpu') if vcpu is None: raise LookupError('Element vcpu not found in domain XML') cpus = vmxml.attr(vcpu, 'current') if cpus == '': # If attribute current is not present fall-back to element text cpus = vcpu.text return int(cpus)
def is_vnc_secure(vmParams, log): """ This function checks if VNC is not mis-configured to offer insecure, free-for-all access. The engine can send the XML with empty password, but it's acceptable IFF qemu uses SASL as the authentication mechanism. is_vnc_secure returns False in such case (i.e. no password and no SASL), otherwise VNC connection is considered secure. """ parsed = xmlutils.fromstring(vmParams['xml']) graphics = vmxml.find_all(parsed, 'graphics') for g in graphics: if vmxml.attr(g, 'type') == 'vnc': # When the XML does not contain 'passwordValidTo' attribute # this is a way to say 'don't use password auth'. no_password_auth = vmxml.attr(g, 'passwdValidTo') == '' if no_password_auth and not utils.sasl_enabled(): log.warning("VNC not secure: passwdValidTo empty or missing" " and SASL not configured") return False return True
def is_vnc_secure(vmParams, log): """ This function checks if VNC is not mis-configured to offer insecure, free-for-all access. The engine can send the XML with empty password, but it's acceptable IFF qemu uses SASL as the authentication mechanism. is_vnc_secure returns False in such case (i.e. no password and no SASL), otherwise VNC connection is considered secure. """ parsed = xmlutils.fromstring(vmParams['xml']) graphics = vmxml.find_all(parsed, 'graphics') for g in graphics: if vmxml.attr(g, 'type') == 'vnc': # When the XML does not contain 'passwordValidTo' attribute # this is a way to say 'don't use password auth'. no_password_auth = vmxml.attr(g, 'passwdValidTo') == '' if no_password_auth and not utils.sasl_enabled(): log.warning("VNC not secure: passwdValidTo empty or missing" " and SASL not configured") return False return True
def parse_volume_chain(self, disk_xml): """ Parses libvirt xml and extracts volume chain from it. Arguments: disk_xml (ElementTree): libvirt xml to parse Returns: list: VolumeChainEntry[] - List of chain entries where each entry contains volume UUID, volume path and volume index. For the 'top' volume index is None, as 'top' volume have no indices at all. VolumeChainEntry is reversed in relation to libvirt xml: xml is ordered from top to base volume, while volume chain is ordered from base to the top. Raises: InvalidBackingStoreIndex exception when index value is not int. """ volChain = [] index = None source_attr = SOURCE_ATTR[self.diskType] while True: path = vmxml.find_attr(disk_xml, 'source', source_attr) if not path: break if index is not None: try: index = int(index) except ValueError: raise InvalidBackingStoreIndex(path, index) # TODO: Allocation information is not available in the XML. Switch # to the new interface once it becomes available in libvirt. alloc = None backingstore = next(vmxml.children(disk_xml, 'backingStore'), None) if backingstore is None: self.log.warning( "<backingStore/> missing from backing " "chain for drive %s", self.name) break entry = VolumeChainEntry(self.volume_id(path), path, alloc, index) volChain.insert(0, entry) disk_xml = backingstore index = vmxml.attr(backingstore, 'index') return volChain or None
def update_device_info(cls, vm, device_conf): for x in vm.domain.get_device_elements('controller'): # Ignore controller devices without address address = find_device_guest_address(x) alias = find_device_alias(x) if address is None: continue device = vmxml.attr(x, 'type') # Get model and index. Relevant for USB controllers. model = vmxml.attr(x, 'model') index = vmxml.attr(x, 'index') # In case the controller has index and/or model, they # are compared. Currently relevant for USB controllers. for ctrl in device_conf: if ((ctrl.device == device) and (not hasattr(ctrl, 'index') or ctrl.index == index) and (not hasattr(ctrl, 'model') or ctrl.model == model)): ctrl.alias = alias ctrl.address = address # Update vm's conf with address for known controller devices # In case the controller has index and/or model, they # are compared. Currently relevant for USB controllers. knownDev = False for dev in vm.conf['devices']: if ((dev['type'] == hwclass.CONTROLLER) and (dev['device'] == device) and ('index' not in dev or dev['index'] == index) and ('model' not in dev or dev['model'] == model)): dev['address'] = address dev['alias'] = alias knownDev = True # Add unknown controller device to vm's conf if not knownDev: vm.conf['devices'].append( {'type': hwclass.CONTROLLER, 'device': device, 'address': address, 'alias': alias})
def update_device_info(cls, vm, device_conf): for gxml in vm.domain.get_device_elements('graphics'): port = vmxml.attr(gxml, 'port') tlsPort = vmxml.attr(gxml, 'tlsPort') graphicsType = vmxml.attr(gxml, 'type') for d in device_conf: if d.device == graphicsType: if port: d.port = port if tlsPort: d.tlsPort = tlsPort break for dev in vm.conf['devices']: if (dev.get('type') == hwclass.GRAPHICS and dev.get('device') == graphicsType): if port: dev['port'] = port if tlsPort: dev['tlsPort'] = tlsPort break
def from_xml_tree(cls, log, dev, meta): params = { 'device': dev.tag, 'type': find_device_type(dev), } update_device_params(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 update_device_params_from_meta(params, meta) return cls(log, **params)
def update_device_info(cls, vm, device_conf): for gxml in vm.domain.get_device_elements('graphics'): port = vmxml.attr(gxml, 'port') tlsPort = vmxml.attr(gxml, 'tlsPort') graphicsType = vmxml.attr(gxml, 'type') for d in device_conf: if d.device == graphicsType: if port: d.port = port if tlsPort: d.tlsPort = tlsPort break for dev in vm.conf['devices']: if (dev.get('type') == hwclass.GRAPHICS and dev.get('device') == graphicsType): if port: dev['port'] = port if tlsPort: dev['tlsPort'] = tlsPort break
def parse_volume_chain(self, disk_xml): """ Parses libvirt xml and extracts volume chain from it. Arguments: disk_xml (ElementTree): libvirt xml to parse Returns: list: VolumeChainEntry[] - List of chain entries where each entry contains volume UUID, volume path and volume index. For the 'top' volume index is None, as 'top' volume have no indices at all. VolumeChainEntry is reversed in relation to libvirt xml: xml is ordered from top to base volume, while volume chain is ordered from base to the top. Raises: InvalidBackingStoreIndex exception when index value is not int. """ volChain = [] index = None source_attr = SOURCE_ATTR[self.diskType] while True: path = vmxml.find_attr(disk_xml, 'source', source_attr) if not path: break if index is not None: try: index = int(index) except ValueError: raise InvalidBackingStoreIndex(path, index) # TODO: Allocation information is not available in the XML. Switch # to the new interface once it becomes available in libvirt. alloc = None backingstore = next(vmxml.children(disk_xml, 'backingStore'), None) if backingstore is None: self.log.warning("<backingStore/> missing from backing " "chain for drive %s", self.name) break entry = VolumeChainEntry(self.volume_id(path), path, alloc, index) volChain.insert(0, entry) disk_xml = backingstore index = vmxml.attr(backingstore, 'index') return volChain or None
def from_xml_tree(cls, log, dev, meta): params = { 'device': dev.tag, 'type': find_device_type(dev), } update_device_params(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 update_device_params_from_meta(params, meta) return cls(log, **params)
def change_disk(disk_element, disk_devices, log): # TODO: Code below is broken and will not work as expected. # Drives of different types require different data to be provided # by the engine. For example file based drives need just # a path to file, while network based drives require host information. # Therefore, replacing disk type on the fly is not safe and # will lead to incorrect drive configuration. # Even more - we do not support snapshots on different types of drives # and have a special check for that in the snapshotting code, # so it should never happen. diskType = vmxml.attr(disk_element, 'type') if diskType not in storage.SOURCE_ATTR: return try: vm_drive = lookup.drive_from_element(disk_devices, disk_element) except LookupError as exc: log.warning('%s', str(exc)) else: update_disk_element_from_object(disk_element, vm_drive, log)
def change_disk(disk_element, disk_devices, log): # TODO: Code below is broken and will not work as expected. # Drives of different types require different data to be provided # by the engine. For example file based drives need just # a path to file, while network based drives require host information. # Therefore, replacing disk type on the fly is not safe and # will lead to incorrect drive configuration. # Even more - we do not support snapshots on different types of drives # and have a special check for that in the snapshotting code, # so it should never happen. diskType = vmxml.attr(disk_element, 'type') if diskType not in storage.SOURCE_ATTR: return try: vm_drive = lookup.drive_from_element(disk_devices, disk_element) except LookupError as exc: log.warning('%s', str(exc)) else: update_disk_element_from_object(disk_element, vm_drive, log)
def from_xml_tree(cls, log, dev, meta): params = { 'custom': {}, 'vm_custom': {}, 'specParams': {}, } params.update(core.parse_device_params(dev)) params['device'] = params['type'] params.update(_get_xml_elem(dev, 'macAddr', 'mac', 'address')) params.update(_get_xml_elem(dev, 'nicModel', 'model', 'type')) params.update(_get_xml_elem(dev, 'bootOrder', 'boot', 'order')) filterref = vmxml.find_first(dev, 'filterref', None) if filterref is not None: params['filter'] = vmxml.attr(filterref, 'filter') params['filterParameters'] = { param.attrib['name']: 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 RuntimeError('could not detect the network to join') params['network'] = net return cls(log, **params)
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) if xdrivers is not None: driver = core.parse_device_attrs( xdrivers, ('name', 'queues',) ) else: driver = {} 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.update(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_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') 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')) # Get nic address address = {} # TODO: fix vmxml.device_address and its users to have this code. for child in vmxml.children(x, 'address'): address = dict((k.strip(), v.strip()) for k, v in vmxml.attributes(child).items()) break 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_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.iterkeys()) 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.warn('Found unknown drive: %s', diskDev) vm.conf['devices'].append(diskDev)
def get_device_elements_with_attrs(self, tag_name, **kwargs): for element in vmxml.find_all(self.devices, tag_name): if all( vmxml.attr(element, key) == value for key, value in kwargs.items()): yield element
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.iterkeys()) 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.warn('Found unknown drive: %s', diskDev) vm.conf['devices'].append(diskDev)
def find_first_domain_device_by_type(domain, device_class, device_type): for dev in domain.get_device_elements(device_class): if vmxml.attr(dev, 'type') == device_type: return dev return None