@@ -8019,15 +8019,52 @@ def _get_mdev_capable_devices(self, types=None):
80198019
80208020 def _get_mediated_device_information(self, devname):
80218021 """Returns a dict of a mediated device."""
8022- virtdev = self._host.device_lookup_by_name(devname)
8022+ # LP #1951656 - In Libvirt 7.7, the mdev name now includes the PCI
8023+ # address of the parent device (e.g. mdev_<uuid>_<pci_address>) due to
8024+ # the mdevctl allowing for multiple mediated devs having the same UUID
8025+ # defined (only one can be active at a time). Since the guest
8026+ # information doesn't have the parent ID, try to lookup which
8027+ # mediated device is available that matches the UUID. If multiple
8028+ # devices are found that match the UUID, then this is an error
8029+ # condition.
8030+ try:
8031+ virtdev = self._host.device_lookup_by_name(devname)
8032+ except libvirt.libvirtError as ex:
8033+ if ex.get_error_code() != libvirt.VIR_ERR_NO_NODE_DEVICE:
8034+ raise
8035+ mdevs = [dev for dev in self._host.list_mediated_devices()
8036+ if dev.startswith(devname)]
8037+ # If no matching devices are found, simply raise the original
8038+ # exception indicating that no devices are found.
8039+ if not mdevs:
8040+ raise
8041+ elif len(mdevs) > 1:
8042+ msg = ("The mediated device name %(devname)s refers to a UUID "
8043+ "that is present in multiple libvirt mediated devices. "
8044+ "Matching libvirt mediated devices are %(devices)s. "
8045+ "Mediated device UUIDs must be unique for Nova." %
8046+ {'devname': devname,
8047+ 'devices': ', '.join(mdevs)})
8048+ raise exception.InvalidLibvirtMdevConfig(reason=msg)
8049+
8050+ LOG.debug('Found requested device %s as %s. Using that.',
8051+ devname, mdevs[0])
8052+ virtdev = self._host.device_lookup_by_name(mdevs[0])
80238053 xmlstr = virtdev.XMLDesc(0)
80248054 cfgdev = vconfig.LibvirtConfigNodeDevice()
80258055 cfgdev.parse_str(xmlstr)
8056+ # Starting with Libvirt 7.3, the uuid information is available in the
8057+ # node device information. If its there, use that. Otherwise,
8058+ # fall back to the previous behavior of parsing the uuid from the
8059+ # devname.
8060+ if cfgdev.mdev_information.uuid:
8061+ mdev_uuid = cfgdev.mdev_information.uuid
8062+ else:
8063+ mdev_uuid = libvirt_utils.mdev_name2uuid(cfgdev.name)
80268064
80278065 device = {
80288066 "dev_id": cfgdev.name,
8029- # name is like mdev_00ead764_fdc0_46b6_8db9_2963f5c815b4
8030- "uuid": libvirt_utils.mdev_name2uuid(cfgdev.name),
8067+ "uuid": mdev_uuid,
80318068 # the physical GPU PCI device
80328069 "parent": cfgdev.parent,
80338070 "type": cfgdev.mdev_information.type,
0 commit comments