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 _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 get_identifying_attrs(cls, dom): dev_type = core.find_device_type(dom) attrs = {'devtype': dom.tag} if dev_type == 'mdev': attrs['uuid'] = vmxml.device_address(dom)['uuid'] else: attrs['name'] = core.find_device_alias(dom)
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 _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) return device_name_from_address(dev_type, src_addr)
def _get_hostdev_params(dev): src_dev = vmxml.find_first(dev, 'source') src_addr = vmxml.device_address(src_dev) src_addr_type = src_addr.pop('type', None) if src_addr_type != 'pci': raise UnsupportedAddress(src_addr_type) addr = validate.normalize_pci_address(**src_addr) return {'hostdev': pci_address_to_name(**addr)}
def update_from_xml(cls, vm, device_conf, device_xml): alias = core.find_device_alias(device_xml) bus_address = vmxml.device_address(device_xml) source = vmxml.find_first(device_xml, 'source') adapter = vmxml.find_attr(source, 'adapter', 'name') # The routine is quite unusual because we cannot directly # reconstruct the unique name. Therefore, we first look up # corresponding device object address, for dev in device_conf: if (hasattr(dev, 'bus_address') and bus_address == dev.bus_address and adapter == dev.adapter): dev.alias = alias device = dev.device dev.address = vmxml.device_address(device_xml, 1) for dev in vm.conf['devices']: if dev['device'] == device: dev['alias'] = alias dev['address'] = vmxml.device_address(device_xml, 1)
def _get_device_name_type(dev): dev_type = core.find_device_type(dev) 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'], dev_type return device_name_from_address(dev_type, src_addr), dev_type
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_from_xml(cls, vm, device_conf, device_xml): alias = core.find_device_alias(device_xml) host_address = vmxml.device_address(device_xml) # The routine is quite unusual because we cannot directly # reconstruct the unique name. Therefore, we first look up # corresponding device object address, for dev in device_conf: if host_address == dev.hostAddress: dev.alias = alias device = dev.device # RHBZ#1215968 # dev.address = vmxml.device_address(device_xml, 1) for dev in vm.conf['devices']: if dev['device'] == device: dev['alias'] = alias
def get_identifying_attrs(cls, dev_elem): return { 'devtype': core.dev_class_from_dev_elem(dev_elem), 'uuid': vmxml.device_address(dev_elem)['uuid'] }
def parse_device_ident(dev): try: address = vmxml.device_address(dev) except IndexError: address = None return address, find_device_alias(dev)
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 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)