diff --git a/nova/tests/unit/virt/libvirt/test_driver.py b/nova/tests/unit/virt/libvirt/test_driver.py index 7447836dcf2c..c5af658b8e09 100644 --- a/nova/tests/unit/virt/libvirt/test_driver.py +++ b/nova/tests/unit/virt/libvirt/test_driver.py @@ -1620,6 +1620,12 @@ class LibvirtConnTestCase(test.NoDBTestCase,
+ + +
+ + """ @@ -1673,24 +1679,32 @@ class LibvirtConnTestCase(test.NoDBTestCase, vif.instance_uuid = '32dfcb37-5af1-552b-357c-be8c3aa38310' vif.uuid = '12ec4b21-ef22-6c21-534b-ba3e3ab3a311' vif.tag = 'mytag1' + vif1 = obj_vif.VirtualInterface(context=self.context) vif1.address = '51:5a:2c:a4:5e:1b' vif1.network_id = 123 vif1.instance_uuid = '32dfcb37-5af1-552b-357c-be8c3aa38310' vif1.uuid = 'abec4b21-ef22-6c21-534b-ba3e3ab3a312' + vif2 = obj_vif.VirtualInterface(context=self.context) vif2.address = 'fa:16:3e:d1:28:e4' vif2.network_id = 123 vif2.instance_uuid = '32dfcb37-5af1-552b-357c-be8c3aa38310' vif2.uuid = '645686e4-7086-4eab-8c2f-c41f017a1b16' vif2.tag = 'mytag2' + vif3 = obj_vif.VirtualInterface(context=self.context) vif3.address = '52:54:00:14:6f:50' vif3.network_id = 123 vif3.instance_uuid = '32dfcb37-5af1-552b-357c-be8c3aa38310' vif3.uuid = '99cc3604-782d-4a32-a27c-bc33ac56ce86' vif3.tag = 'mytag3' - vifs = [vif, vif1, vif2, vif3] + + vif4 = obj_vif.VirtualInterface(context=self.context) + vif4.address = 'da:d1:f2:91:95:c1' + vif4.tag = 'pf_tag' + + vifs = [vif, vif1, vif2, vif3, vif4] network_info = _fake_network_info(self, 4) network_info[0]['vnic_type'] = network_model.VNIC_TYPE_DIRECT_PHYSICAL @@ -1708,11 +1722,13 @@ class LibvirtConnTestCase(test.NoDBTestCase, mock.patch('nova.virt.libvirt.host.Host.get_guest', return_value=guest), mock.patch.object(nova.virt.libvirt.guest.Guest, 'get_xml_desc', - return_value=xml)): + return_value=xml), + mock.patch.object(pci_utils, 'get_mac_by_pci_address', + return_value='da:d1:f2:91:95:c1')): metadata_obj = drvr._build_device_metadata(self.context, instance_ref) metadata = metadata_obj.devices - self.assertEqual(10, len(metadata)) + self.assertEqual(11, len(metadata)) self.assertIsInstance(metadata[0], objects.DiskMetadata) self.assertIsInstance(metadata[0].bus, @@ -1774,6 +1790,11 @@ class LibvirtConnTestCase(test.NoDBTestCase, objects.NetworkInterfaceMetadata) self.assertEqual(['mytag3'], metadata[9].tags) self.assertFalse(metadata[9].vf_trusted) + self.assertIsInstance(metadata[10], + objects.NetworkInterfaceMetadata) + self.assertEqual(['pf_tag'], metadata[10].tags) + self.assertEqual('da:d1:f2:91:95:c1', metadata[10].mac) + self.assertEqual('0000:06:00.1', metadata[10].bus.address) @mock.patch.object(host.Host, 'get_connection') @mock.patch.object(nova.virt.libvirt.guest.Guest, 'get_xml_desc') diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index b78b5365b34a..3c5bc7dc84be 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -8609,6 +8609,42 @@ class LibvirtDriver(driver.ComputeDriver): device.bus = bus return device + def _build_hostdev_metadata(self, dev, vifs_to_expose, vlans_by_mac): + """Builds a metadata object for a hostdev. This can only be a PF, so we + don't need trusted_by_mac like in _build_interface_metadata because + only VFs can be trusted. + + :param dev: The LibvirtConfigGuestHostdevPCI to build metadata for. + :param vifs_to_expose: The list of tagged and/or vlan'ed + VirtualInterface objects. + :param vlans_by_mac: A dictionary of mac address -> vlan associations. + :return: A NetworkInterfaceMetadata object, or None. + """ + # Strip out the leading '0x' + pci_address = pci_utils.get_pci_address( + *[x[2:] for x in (dev.domain, dev.bus, dev.slot, dev.function)]) + try: + mac = pci_utils.get_mac_by_pci_address(pci_address, + pf_interface=True) + except exception.PciDeviceNotFoundById: + LOG.debug('Not exposing metadata for not found PCI device %s', + pci_address) + return None + + vif = vifs_to_expose.get(mac) + if not vif: + LOG.debug('No VIF found with MAC %s, not building metadata', mac) + return None + + device = objects.NetworkInterfaceMetadata(mac=mac) + device.bus = objects.PCIDeviceBus(address=pci_address) + if 'tag' in vif and vif.tag: + device.tags = [vif.tag] + vlan = vlans_by_mac.get(mac) + if vlan: + device.vlan = int(vlan) + return device + def _build_device_metadata(self, context, instance): """Builds a metadata object for instance devices, that maps the user provided tag to the hypervisor assigned device address. @@ -8646,6 +8682,9 @@ class LibvirtDriver(driver.ComputeDriver): trusted_by_mac) if isinstance(dev, vconfig.LibvirtConfigGuestDisk): device = self._build_disk_metadata(dev, tagged_bdms) + if isinstance(dev, vconfig.LibvirtConfigGuestHostdevPCI): + device = self._build_hostdev_metadata(dev, vifs_to_expose, + vlans_by_mac) if device: devices.append(device) if devices: