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:
parent
18a23b747b
commit
1a0778d280
@ -73,6 +73,7 @@ HAVANA = '2013-10-17'
|
|||||||
LIBERTY = '2015-10-15'
|
LIBERTY = '2015-10-15'
|
||||||
NEWTON_ONE = '2016-06-30'
|
NEWTON_ONE = '2016-06-30'
|
||||||
NEWTON_TWO = '2016-10-06'
|
NEWTON_TWO = '2016-10-06'
|
||||||
|
OCATA = '2017-02-22'
|
||||||
|
|
||||||
OPENSTACK_VERSIONS = [
|
OPENSTACK_VERSIONS = [
|
||||||
FOLSOM,
|
FOLSOM,
|
||||||
@ -81,6 +82,7 @@ OPENSTACK_VERSIONS = [
|
|||||||
LIBERTY,
|
LIBERTY,
|
||||||
NEWTON_ONE,
|
NEWTON_ONE,
|
||||||
NEWTON_TWO,
|
NEWTON_TWO,
|
||||||
|
OCATA,
|
||||||
]
|
]
|
||||||
|
|
||||||
VERSION = "version"
|
VERSION = "version"
|
||||||
@ -372,19 +374,19 @@ class InstanceMetadata(object):
|
|||||||
metadata['project_id'] = self.instance.project_id
|
metadata['project_id'] = self.instance.project_id
|
||||||
|
|
||||||
if self._check_os_version(NEWTON_ONE, version):
|
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)
|
self.set_mimetype(MIME_TYPE_APPLICATION_JSON)
|
||||||
return jsonutils.dump_as_bytes(metadata)
|
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
|
"""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
|
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
|
because the metadata dict is part of the guest API and thus must be
|
||||||
controlled.
|
controlled.
|
||||||
"""
|
"""
|
||||||
device_metadata_list = []
|
device_metadata_list = []
|
||||||
|
vif_vlans_supported = self._check_os_version(OCATA, version)
|
||||||
if self.instance.device_metadata is not None:
|
if self.instance.device_metadata is not None:
|
||||||
for device in self.instance.device_metadata.devices:
|
for device in self.instance.device_metadata.devices:
|
||||||
device_metadata = {}
|
device_metadata = {}
|
||||||
@ -413,8 +415,19 @@ class InstanceMetadata(object):
|
|||||||
address = device.bus.address
|
address = device.bus.address
|
||||||
|
|
||||||
if isinstance(device, metadata_obj.NetworkInterfaceMetadata):
|
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['type'] = 'nic'
|
||||||
device_metadata['mac'] = device.mac
|
device_metadata['mac'] = device.mac
|
||||||
|
if vlan:
|
||||||
|
device_metadata['vlan'] = vlan
|
||||||
elif isinstance(device, metadata_obj.DiskMetadata):
|
elif isinstance(device, metadata_obj.DiskMetadata):
|
||||||
device_metadata['type'] = 'disk'
|
device_metadata['type'] = 'disk'
|
||||||
# serial and path are optional parameters
|
# serial and path are optional parameters
|
||||||
@ -430,10 +443,10 @@ class InstanceMetadata(object):
|
|||||||
|
|
||||||
device_metadata['bus'] = bus
|
device_metadata['bus'] = bus
|
||||||
device_metadata['address'] = address
|
device_metadata['address'] = address
|
||||||
|
if 'tags' in device:
|
||||||
device_metadata['tags'] = device.tags
|
device_metadata['tags'] = device.tags
|
||||||
|
|
||||||
device_metadata_list.append(device_metadata)
|
device_metadata_list.append(device_metadata)
|
||||||
|
|
||||||
return device_metadata_list
|
return device_metadata_list
|
||||||
|
|
||||||
def _handle_content(self, path_tokens):
|
def _handle_content(self, path_tokens):
|
||||||
|
@ -176,6 +176,11 @@ def fake_metadata_objects():
|
|||||||
mac='00:00:00:00:00:00',
|
mac='00:00:00:00:00:00',
|
||||||
tags=['foo']
|
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(
|
ide_disk_obj = metadata_obj.DiskMetadata(
|
||||||
bus=metadata_obj.IDEDeviceBus(address='0:0'),
|
bus=metadata_obj.IDEDeviceBus(address='0:0'),
|
||||||
serial='disk-vol-2352423',
|
serial='disk-vol-2352423',
|
||||||
@ -203,11 +208,11 @@ def fake_metadata_objects():
|
|||||||
mdlist = metadata_obj.InstanceDeviceMetadata(
|
mdlist = metadata_obj.InstanceDeviceMetadata(
|
||||||
instance_uuid='b65cee2f-8c69-4aeb-be2f-f79742548fc2',
|
instance_uuid='b65cee2f-8c69-4aeb-be2f-f79742548fc2',
|
||||||
devices=[nic_obj, ide_disk_obj, scsi_disk_obj, usb_disk_obj,
|
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
|
return mdlist
|
||||||
|
|
||||||
|
|
||||||
def fake_metadata_dicts():
|
def fake_metadata_dicts(include_vlan=False):
|
||||||
nic_meta = {
|
nic_meta = {
|
||||||
'type': 'nic',
|
'type': 'nic',
|
||||||
'bus': 'pci',
|
'bus': 'pci',
|
||||||
@ -215,6 +220,13 @@ def fake_metadata_dicts():
|
|||||||
'mac': '00:00:00:00:00:00',
|
'mac': '00:00:00:00:00:00',
|
||||||
'tags': ['foo'],
|
'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 = {
|
ide_disk_meta = {
|
||||||
'type': 'disk',
|
'type': 'disk',
|
||||||
'bus': 'ide',
|
'bus': 'ide',
|
||||||
@ -232,7 +244,10 @@ def fake_metadata_dicts():
|
|||||||
usb_disk_meta['bus'] = 'usb'
|
usb_disk_meta['bus'] = 'usb'
|
||||||
usb_disk_meta['address'] = '05c8:021e'
|
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):
|
class MetadataTestCase(test.TestCase):
|
||||||
@ -437,6 +452,11 @@ class MetadataTestCase(test.TestCase):
|
|||||||
'openstack/2016-10-06/vendor_data.json',
|
'openstack/2016-10-06/vendor_data.json',
|
||||||
'openstack/2016-10-06/network_data.json',
|
'openstack/2016-10-06/network_data.json',
|
||||||
'openstack/2016-10-06/vendor_data2.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/meta_data.json',
|
||||||
'openstack/latest/user_data',
|
'openstack/latest/user_data',
|
||||||
'openstack/latest/vendor_data.json',
|
'openstack/latest/vendor_data.json',
|
||||||
@ -524,8 +544,8 @@ class MetadataTestCase(test.TestCase):
|
|||||||
if md._check_os_version(base.LIBERTY, os_version):
|
if md._check_os_version(base.LIBERTY, os_version):
|
||||||
expected_metadata['project_id'] = instance.project_id
|
expected_metadata['project_id'] = instance.project_id
|
||||||
if md._check_os_version(base.NEWTON_ONE, os_version):
|
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
|
mock_cells_keypair.return_value = keypair
|
||||||
md._metadata_as_json(os_version, 'non useless path parameter')
|
md._metadata_as_json(os_version, 'non useless path parameter')
|
||||||
if instance.key_name:
|
if instance.key_name:
|
||||||
@ -589,7 +609,7 @@ class OpenStackMetadataTestCase(test.TestCase):
|
|||||||
mdinst = fake_InstanceMetadata(self, inst)
|
mdinst = fake_InstanceMetadata(self, inst)
|
||||||
mdjson = mdinst.lookup("/openstack/latest/meta_data.json")
|
mdjson = mdinst.lookup("/openstack/latest/meta_data.json")
|
||||||
mddict = jsonutils.loads(mdjson)
|
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):
|
def test_top_level_listing(self):
|
||||||
# request for /openstack/<version>/ should show metadata.json
|
# request for /openstack/<version>/ should show metadata.json
|
||||||
|
@ -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.
|
Loading…
Reference in New Issue
Block a user