Adding vlans field to Device tagging metadata

Handle the network interface new vlans field and expose it in the devices
metadata
The vlan tag will be exposed to the instance through the metadata API and
on the config drive.

Implements: blueprint sriov-pf-passthrough-neutron-port-vlan
Change-Id: Id7b9f3f1c2107ec604e7f0ef4fbfd31a9e05d0b0
This commit is contained in:
Vladik Romanovsky 2016-12-01 10:41:21 -05:00 committed by Matt Riedemann
parent 18a23b747b
commit 1a0778d280
3 changed files with 57 additions and 11 deletions

View File

@ -73,6 +73,7 @@ HAVANA = '2013-10-17'
LIBERTY = '2015-10-15'
NEWTON_ONE = '2016-06-30'
NEWTON_TWO = '2016-10-06'
OCATA = '2017-02-22'
OPENSTACK_VERSIONS = [
FOLSOM,
@ -81,6 +82,7 @@ OPENSTACK_VERSIONS = [
LIBERTY,
NEWTON_ONE,
NEWTON_TWO,
OCATA,
]
VERSION = "version"
@ -372,19 +374,19 @@ class InstanceMetadata(object):
metadata['project_id'] = self.instance.project_id
if self._check_os_version(NEWTON_ONE, version):
metadata['devices'] = self._get_device_metadata()
metadata['devices'] = self._get_device_metadata(version)
self.set_mimetype(MIME_TYPE_APPLICATION_JSON)
return jsonutils.dump_as_bytes(metadata)
def _get_device_metadata(self):
def _get_device_metadata(self, version):
"""Build a device metadata dict based on the metadata objects. This is
done here in the metadata API as opposed to in the objects themselves
because the metadata dict is part of the guest API and thus must be
controlled.
"""
device_metadata_list = []
vif_vlans_supported = self._check_os_version(OCATA, version)
if self.instance.device_metadata is not None:
for device in self.instance.device_metadata.devices:
device_metadata = {}
@ -413,8 +415,19 @@ 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
device_metadata['type'] = 'nic'
device_metadata['mac'] = device.mac
if vlan:
device_metadata['vlan'] = vlan
elif isinstance(device, metadata_obj.DiskMetadata):
device_metadata['type'] = 'disk'
# serial and path are optional parameters
@ -430,10 +443,10 @@ class InstanceMetadata(object):
device_metadata['bus'] = bus
device_metadata['address'] = address
if 'tags' in device:
device_metadata['tags'] = device.tags
device_metadata_list.append(device_metadata)
return device_metadata_list
def _handle_content(self, path_tokens):

View File

@ -176,6 +176,11 @@ def fake_metadata_objects():
mac='00:00:00:00:00:00',
tags=['foo']
)
nic_vlans_obj = metadata_obj.NetworkInterfaceMetadata(
bus=metadata_obj.PCIDeviceBus(address='0000:80:01.0'),
mac='e3:a0:d0:12:c5:10',
vlan=1000,
)
ide_disk_obj = metadata_obj.DiskMetadata(
bus=metadata_obj.IDEDeviceBus(address='0:0'),
serial='disk-vol-2352423',
@ -203,11 +208,11 @@ 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])
fake_device_obj, device_with_fake_bus_obj, nic_vlans_obj])
return mdlist
def fake_metadata_dicts():
def fake_metadata_dicts(include_vlan=False):
nic_meta = {
'type': 'nic',
'bus': 'pci',
@ -215,6 +220,13 @@ def fake_metadata_dicts():
'mac': '00:00:00:00:00:00',
'tags': ['foo'],
}
vlan_nic_meta = {
'type': 'nic',
'bus': 'pci',
'address': '0000:80:01.0',
'mac': 'e3:a0:d0:12:c5:10',
'vlan': 1000,
}
ide_disk_meta = {
'type': 'disk',
'bus': 'ide',
@ -232,7 +244,10 @@ def fake_metadata_dicts():
usb_disk_meta['bus'] = 'usb'
usb_disk_meta['address'] = '05c8:021e'
return [nic_meta, ide_disk_meta, scsi_disk_meta, usb_disk_meta]
dicts = [nic_meta, ide_disk_meta, scsi_disk_meta, usb_disk_meta]
if include_vlan:
dicts += [vlan_nic_meta]
return dicts
class MetadataTestCase(test.TestCase):
@ -437,6 +452,11 @@ class MetadataTestCase(test.TestCase):
'openstack/2016-10-06/vendor_data.json',
'openstack/2016-10-06/network_data.json',
'openstack/2016-10-06/vendor_data2.json',
'openstack/2017-02-22/meta_data.json',
'openstack/2017-02-22/user_data',
'openstack/2017-02-22/vendor_data.json',
'openstack/2017-02-22/network_data.json',
'openstack/2017-02-22/vendor_data2.json',
'openstack/latest/meta_data.json',
'openstack/latest/user_data',
'openstack/latest/vendor_data.json',
@ -524,8 +544,8 @@ class MetadataTestCase(test.TestCase):
if md._check_os_version(base.LIBERTY, os_version):
expected_metadata['project_id'] = instance.project_id
if md._check_os_version(base.NEWTON_ONE, os_version):
expected_metadata['devices'] = fake_metadata_dicts()
expose_vlan = md._check_os_version(base.OCATA, os_version)
expected_metadata['devices'] = fake_metadata_dicts(expose_vlan)
mock_cells_keypair.return_value = keypair
md._metadata_as_json(os_version, 'non useless path parameter')
if instance.key_name:
@ -589,7 +609,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(), mddict['devices'])
self.assertEqual(fake_metadata_dicts(True), mddict['devices'])
def test_top_level_listing(self):
# request for /openstack/<version>/ should show metadata.json

View File

@ -0,0 +1,13 @@
---
features:
- |
VLAN tags associated with instance network interfaces are now exposed via
the metadata API and instance config drives and can be consumed by the
instance. This is an extension of the device tagging mechanism added in
past releases. This is useful for instances utilizing SR-IOV physical
functions (PFs). The VLAN configuration for the guest's virtual interfaces
associated with these devices cannot be configured inside the guest OS from
the host, but nonetheless must be configured with the VLAN tags of the
device to ensure packet delivery. This feature makes this possible.
.. note:: VLAN tags are currently only supported via the Libvirt driver.