@@ -8227,15 +8227,52 @@ def _get_mdev_capable_devices(self, types=None):
8227
8227
8228
8228
def _get_mediated_device_information(self, devname):
8229
8229
"""Returns a dict of a mediated device."""
8230
- virtdev = self._host.device_lookup_by_name(devname)
8230
+ # LP #1951656 - In Libvirt 7.7, the mdev name now includes the PCI
8231
+ # address of the parent device (e.g. mdev_<uuid>_<pci_address>) due to
8232
+ # the mdevctl allowing for multiple mediated devs having the same UUID
8233
+ # defined (only one can be active at a time). Since the guest
8234
+ # information doesn't have the parent ID, try to lookup which
8235
+ # mediated device is available that matches the UUID. If multiple
8236
+ # devices are found that match the UUID, then this is an error
8237
+ # condition.
8238
+ try:
8239
+ virtdev = self._host.device_lookup_by_name(devname)
8240
+ except libvirt.libvirtError as ex:
8241
+ if ex.get_error_code() != libvirt.VIR_ERR_NO_NODE_DEVICE:
8242
+ raise
8243
+ mdevs = [dev for dev in self._host.list_mediated_devices()
8244
+ if dev.startswith(devname)]
8245
+ # If no matching devices are found, simply raise the original
8246
+ # exception indicating that no devices are found.
8247
+ if not mdevs:
8248
+ raise
8249
+ elif len(mdevs) > 1:
8250
+ msg = ("The mediated device name %(devname)s refers to a UUID "
8251
+ "that is present in multiple libvirt mediated devices. "
8252
+ "Matching libvirt mediated devices are %(devices)s. "
8253
+ "Mediated device UUIDs must be unique for Nova." %
8254
+ {'devname': devname,
8255
+ 'devices': ', '.join(mdevs)})
8256
+ raise exception.InvalidLibvirtMdevConfig(reason=msg)
8257
+
8258
+ LOG.debug('Found requested device %s as %s. Using that.',
8259
+ devname, mdevs[0])
8260
+ virtdev = self._host.device_lookup_by_name(mdevs[0])
8231
8261
xmlstr = virtdev.XMLDesc(0)
8232
8262
cfgdev = vconfig.LibvirtConfigNodeDevice()
8233
8263
cfgdev.parse_str(xmlstr)
8264
+ # Starting with Libvirt 7.3, the uuid information is available in the
8265
+ # node device information. If its there, use that. Otherwise,
8266
+ # fall back to the previous behavior of parsing the uuid from the
8267
+ # devname.
8268
+ if cfgdev.mdev_information.uuid:
8269
+ mdev_uuid = cfgdev.mdev_information.uuid
8270
+ else:
8271
+ mdev_uuid = libvirt_utils.mdev_name2uuid(cfgdev.name)
8234
8272
8235
8273
device = {
8236
8274
"dev_id": cfgdev.name,
8237
- # name is like mdev_00ead764_fdc0_46b6_8db9_2963f5c815b4
8238
- "uuid": libvirt_utils.mdev_name2uuid(cfgdev.name),
8275
+ "uuid": mdev_uuid,
8239
8276
# the physical GPU PCI device
8240
8277
"parent": cfgdev.parent,
8241
8278
"type": cfgdev.mdev_information.type,
0 commit comments