metadata: add vf_trusted field to device metadata

The trusted vf attribute will be exposed to the instance through the
metadata API and on the config drive.

Note the logic when dealing with NetworkInterfaceMetadata devices was
refactored slightly in order to handle the existing cases where these
types of devices are skipped.

Implements blueprint sriov-trusted-vfs
Change-Id: Icbac4f11b2383b3d8295ec3362db0fc60b9c35a9
Signed-off-by: Sahid Orentino Ferdjaoui <sahid.ferdjaoui@redhat.com>
This commit is contained in:
Sahid Orentino Ferdjaoui 2018-05-04 17:23:01 +02:00 committed by Matt Riedemann
parent 397e883d67
commit f9ddddc358
4 changed files with 56 additions and 16 deletions

View File

@ -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

View File

@ -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

View File

@ -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/<version>/ should show metadata.json

View File

@ -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.