diff --git a/doc/source/user/metadata-service.rst b/doc/source/user/metadata-service.rst index 279b4012c776..25405cd2062a 100644 --- a/doc/source/user/metadata-service.rst +++ b/doc/source/user/metadata-service.rst @@ -25,6 +25,7 @@ GET request to ``http://169.254.169.254/openstack``: 2016-06-30 2016-10-06 2017-02-22 + 2018-08-27 latest To list supported versions for the EC2-compatible metadata API, make a GET diff --git a/nova/api/metadata/base.py b/nova/api/metadata/base.py index 2c61cdb25bc0..b4cd397c4e2e 100644 --- a/nova/api/metadata/base.py +++ b/nova/api/metadata/base.py @@ -72,6 +72,7 @@ LIBERTY = '2015-10-15' NEWTON_ONE = '2016-06-30' NEWTON_TWO = '2016-10-06' OCATA = '2017-02-22' +ROCKY = '2018-08-27' OPENSTACK_VERSIONS = [ FOLSOM, @@ -81,6 +82,7 @@ OPENSTACK_VERSIONS = [ NEWTON_ONE, NEWTON_TWO, OCATA, + ROCKY, ] VERSION = "version" @@ -391,6 +393,7 @@ class InstanceMetadata(object): """ device_metadata_list = [] vif_vlans_supported = self._check_os_version(OCATA, version) + vif_vfs_trusted_supported = self._check_os_version(ROCKY, version) if self.instance.device_metadata is not None: for device in self.instance.device_metadata.devices: device_metadata = {} @@ -421,19 +424,20 @@ class InstanceMetadata(object): address = device.bus.address if isinstance(device, metadata_obj.NetworkInterfaceMetadata): - vlan = None - if vif_vlans_supported and 'vlan' in device: - vlan = device.vlan - - # Skip devices without tags on versions that - # don't support vlans - if not (vlan or 'tags' in device): - continue - + vlan = device.vlan if 'vlan' in device else None + if vif_vlans_supported and vlan is not None: + device_metadata['vlan'] = vlan + if vif_vfs_trusted_supported: + vf_trusted = (device.vf_trusted if + 'vf_trusted' in device else False) + device_metadata['vf_trusted'] = vf_trusted device_metadata['type'] = 'nic' device_metadata['mac'] = device.mac - if vlan: - device_metadata['vlan'] = vlan + # NOTE(artom) If a device has neither tags, vlan or + # vf_trusted, don't expose it + if not ('tags' in device or 'vlan' in device_metadata + or 'vf_trusted' in device_metadata): + continue elif isinstance(device, metadata_obj.DiskMetadata): device_metadata['type'] = 'disk' # serial and path are optional parameters diff --git a/nova/tests/unit/test_metadata.py b/nova/tests/unit/test_metadata.py index b94999aff573..641c7af89b70 100644 --- a/nova/tests/unit/test_metadata.py +++ b/nova/tests/unit/test_metadata.py @@ -168,6 +168,12 @@ def fake_metadata_objects(): mac='00:00:00:00:00:00', tags=['foo'] ) + nic_vf_trusted_obj = metadata_obj.NetworkInterfaceMetadata( + bus=metadata_obj.PCIDeviceBus(address='0000:00:02.0'), + mac='00:11:22:33:44:55', + vf_trusted=True, + tags=['trusted'] + ) nic_vlans_obj = metadata_obj.NetworkInterfaceMetadata( bus=metadata_obj.PCIDeviceBus(address='0000:80:01.0'), mac='e3:a0:d0:12:c5:10', @@ -200,11 +206,12 @@ def fake_metadata_objects(): mdlist = metadata_obj.InstanceDeviceMetadata( instance_uuid='b65cee2f-8c69-4aeb-be2f-f79742548fc2', devices=[nic_obj, ide_disk_obj, scsi_disk_obj, usb_disk_obj, - fake_device_obj, device_with_fake_bus_obj, nic_vlans_obj]) + fake_device_obj, device_with_fake_bus_obj, nic_vlans_obj, + nic_vf_trusted_obj]) return mdlist -def fake_metadata_dicts(include_vlan=False): +def fake_metadata_dicts(include_vlan=False, include_vf_trusted=False): nic_meta = { 'type': 'nic', 'bus': 'pci', @@ -219,6 +226,13 @@ def fake_metadata_dicts(include_vlan=False): 'mac': 'e3:a0:d0:12:c5:10', 'vlan': 1000, } + vf_trusted_nic_meta = { + 'type': 'nic', + 'bus': 'pci', + 'address': '0000:00:02.0', + 'mac': '00:11:22:33:44:55', + 'tags': ['trusted'], + } ide_disk_meta = { 'type': 'disk', 'bus': 'ide', @@ -236,9 +250,15 @@ def fake_metadata_dicts(include_vlan=False): usb_disk_meta['bus'] = 'usb' usb_disk_meta['address'] = '05c8:021e' - dicts = [nic_meta, ide_disk_meta, scsi_disk_meta, usb_disk_meta] + dicts = [nic_meta, ide_disk_meta, scsi_disk_meta, usb_disk_meta, + vf_trusted_nic_meta] if include_vlan: - dicts += [vlan_nic_meta] + # NOTE(artom) Yeah, the order is important. + dicts.insert(len(dicts) - 1, vlan_nic_meta) + if include_vf_trusted: + nic_meta['vf_trusted'] = False + vlan_nic_meta['vf_trusted'] = False + vf_trusted_nic_meta['vf_trusted'] = True return dicts @@ -478,6 +498,11 @@ class MetadataTestCase(test.TestCase): 'openstack/2017-02-22/vendor_data.json', 'openstack/2017-02-22/network_data.json', 'openstack/2017-02-22/vendor_data2.json', + 'openstack/2018-08-27/meta_data.json', + 'openstack/2018-08-27/user_data', + 'openstack/2018-08-27/vendor_data.json', + 'openstack/2018-08-27/network_data.json', + 'openstack/2018-08-27/vendor_data2.json', 'openstack/latest/meta_data.json', 'openstack/latest/user_data', 'openstack/latest/vendor_data.json', @@ -567,6 +592,10 @@ class MetadataTestCase(test.TestCase): if md._check_os_version(base.NEWTON_ONE, os_version): expose_vlan = md._check_os_version(base.OCATA, os_version) expected_metadata['devices'] = fake_metadata_dicts(expose_vlan) + if md._check_os_version(base.OCATA, os_version): + expose_trusted = md._check_os_version(base.ROCKY, os_version) + expected_metadata['devices'] = fake_metadata_dicts( + True, expose_trusted) mock_cells_keypair.return_value = keypair md._metadata_as_json(os_version, 'non useless path parameter') if instance.key_name: @@ -648,7 +677,7 @@ class OpenStackMetadataTestCase(test.TestCase): mdinst = fake_InstanceMetadata(self, inst) mdjson = mdinst.lookup("/openstack/latest/meta_data.json") mddict = jsonutils.loads(mdjson) - self.assertEqual(fake_metadata_dicts(True), mddict['devices']) + self.assertEqual(fake_metadata_dicts(True, True), mddict['devices']) def test_top_level_listing(self): # request for /openstack// should show metadata.json diff --git a/releasenotes/notes/trusted-metatada-b999f1417f678c44.yaml b/releasenotes/notes/trusted-metatada-b999f1417f678c44.yaml new file mode 100644 index 000000000000..b6a44edd03cf --- /dev/null +++ b/releasenotes/notes/trusted-metatada-b999f1417f678c44.yaml @@ -0,0 +1,6 @@ +--- +features: + - | + As of the ``2018-08-27`` metadata API version, a boolean ``vf_trusted`` key + appears for all network interface ``devices`` in ``meta_data.json``, + indicating whether the device is a trusted virtual function or not.