def _update_interface_params(params, dev): iface = vmxml.find_attr(dev, 'target', 'bus') if iface is not None: params['iface'] = iface dev_name = vmxml.find_attr(dev, 'target', 'dev') if dev_name is not None: params['name'] = dev_name
def _update_hostdev_params(params, dev): boot_order = vmxml.find_attr(dev, 'boot', 'order') if boot_order: params['bootOrder'] = boot_order driver = vmxml.find_attr(dev, 'driver', 'name') if driver: params['driver'] = driver
def all_channels(self): if self.devices: for channel in vmxml.find_all(self.devices, 'channel'): name = vmxml.find_attr(channel, 'target', 'name') path = vmxml.find_attr(channel, 'source', 'path') if name and path: yield name, path
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 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 from_xml_tree(cls, log, 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) 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 all_channels(self): """ Returns a tuple (name, path, state) for each channel device in domain XML. Name and path are always non-empty strings, state is non-empty string (connected/disconnected) or None if the channel state is unknown. """ if self.devices is not None: for channel in vmxml.find_all(self.devices, 'channel'): name = vmxml.find_attr(channel, 'target', 'name') path = vmxml.find_attr(channel, 'source', 'path') state = vmxml.find_attr(channel, 'target', 'state') if name and path: yield name, path, (None if not state else state)
def from_xml_tree(cls, log, dev, meta): params = parse_device_params(dev, attrs=('index', 'model', 'ports')) params['device'] = params['type'] iothread = vmxml.find_attr(dev, 'driver', 'iothread') if iothread: params['specParams'] = {'ioThreadId': iothread} 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'] 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 get_identifying_attrs(cls, dev_elem): attrs = {'mac_address': vmxml.find_attr(dev_elem, 'mac', 'address')} teaming = vmxml.find_first(dev_elem, 'teaming', None) if teaming is not None: attrs['alias'] = core.find_device_alias(dev_elem) return attrs
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 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 from_xml_tree(cls, log, dev, meta): has_sock = dev.attrib.get('type', 'pty') == 'unix' params = parse_device_params(dev) params['specParams'] = { 'consoleType': vmxml.find_attr(dev, 'target', 'type'), 'enableSocket': has_sock, } params['vmid'] = meta['vmid'] 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 _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 from_xml_tree(cls, log, dev, meta): params = { 'device': find_device_type(dev), 'type': dev.tag, } update_device_params_from_meta(params, meta) update_device_params(params, dev, attrs=('index', 'model', 'ports')) iothread = vmxml.find_attr(dev, 'driver', 'iothread') if iothread: params['specParams'] = {'ioThreadId': iothread} return cls(log, **params)
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 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 from_xml_tree(cls, log, dev, meta): params = { 'device': find_device_type(dev), 'type': dev.tag, } update_device_params_from_meta(params, meta) update_device_params( params, dev, attrs=('index', 'model', 'ports') ) iothread = vmxml.find_attr(dev, 'driver', 'iothread') if iothread: params['specParams'] = {'ioThreadId': iothread} return cls(log, **params)
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 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 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 get_xml_elem(dev, key, elem, attr): value = vmxml.find_attr(dev, elem, attr) return {key: value} if value else {}
def find_device_alias(dev): return vmxml.find_attr(dev, 'alias', 'name')
def _is_feature_flag_enabled(dev, node, attr): value = vmxml.find_attr(dev, node, attr) if value is not None and value.lower() == 'no': return False else: return True
def _update_boot_params(params, dev): boot_order = vmxml.find_attr(dev, 'boot', 'order') if boot_order: params['bootOrder'] = boot_order
def test_find_attr(self, tag, attribute, result): value = vmxml.find_attr(self._dom, tag, attribute) self.assertEqual(value, result)
def test_find_attr(self, tag, attribute, result): value = vmxml.find_attr(self._dom, tag, attribute) assert value == result
def _normalize_scsi_address(dev, addr): adapter = vmxml.find_attr(dev, 'adapter', 'name') addr['host'] = adapter.replace('scsi_host', '') addr['lun'] = addr.pop('unit') return addr
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): 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): # 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)