@@ -8019,15 +8019,52 @@ def _get_mdev_capable_devices(self, types=None):
8019
8019
8020
8020
def _get_mediated_device_information(self, devname):
8021
8021
"""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])
8023
8053
xmlstr = virtdev.XMLDesc(0)
8024
8054
cfgdev = vconfig.LibvirtConfigNodeDevice()
8025
8055
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)
8026
8064
8027
8065
device = {
8028
8066
"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,
8031
8068
# the physical GPU PCI device
8032
8069
"parent": cfgdev.parent,
8033
8070
"type": cfgdev.mdev_information.type,
0 commit comments