From cec7ecdc93c3b9ba401edf3cf84088b580247cb8 Mon Sep 17 00:00:00 2001 From: Scott Moser Date: Fri, 31 Mar 2017 17:01:33 -0400 Subject: [PATCH] Limit exposure of network device types to the guest. Previously, the 'type' of the hypervisor network device, was exposed to the guest directly. That does not make sense, as a.) this leaks needless information into the guest b.) the guest cannot be reasonably expected to make decisions based on a type of link that is present underneath the virtual device that is presented to the guest. c.) guests then are forced to either continuously track these types or to assume that unknown type is "phy". This limits the exposure of types to a specific list. Any other type will be shown to the guest as 'phy'. Change-Id: Iea458fba29596cd2773d8d3565451af60b02bcca Closes-Bug: #1642679 (cherry picked from commit f559be35a03f5801f527355895a97c89cdc3c336) --- nova/network/model.py | 13 ++++++ nova/tests/unit/network/test_network_info.py | 43 +++++++++++++++++--- nova/virt/netutils.py | 6 +-- 3 files changed, 54 insertions(+), 8 deletions(-) diff --git a/nova/network/model.py b/nova/network/model.py index 11fd371253d5..e591502ebc98 100644 --- a/nova/network/model.py +++ b/nova/network/model.py @@ -47,6 +47,7 @@ VIF_TYPE_OTHER = 'other' VIF_TYPE_TAP = 'tap' VIF_TYPE_MACVTAP = 'macvtap' VIF_TYPE_BINDING_FAILED = 'binding_failed' +VIF_TYPE_VIF = 'vif' # Constants for dictionary keys in the 'vif_details' field in the VIF # class @@ -136,6 +137,18 @@ VIF_MODEL_ALL = ( VIF_MODEL_VMXNET3, ) +# these types have been leaked to guests in network_data.json +LEGACY_EXPOSED_VIF_TYPES = ( + VIF_TYPE_BRIDGE, + VIF_TYPE_DVS, + VIF_TYPE_HW_VEB, + VIF_TYPE_HYPERV, + VIF_TYPE_OVS, + VIF_TYPE_TAP, + VIF_TYPE_VHOSTUSER, + VIF_TYPE_VIF, +) + # Constant for max length of network interface names # eg 'bridge' in the Network class or 'devname' in # the VIF class diff --git a/nova/tests/unit/network/test_network_info.py b/nova/tests/unit/network/test_network_info.py index ce7d37da7462..100edbd4c851 100644 --- a/nova/tests/unit/network/test_network_info.py +++ b/nova/tests/unit/network/test_network_info.py @@ -856,16 +856,20 @@ iface eth1 inet static class TestNetworkMetadata(test.NoDBTestCase): def setUp(self): super(TestNetworkMetadata, self).setUp() - self.netinfo = model.NetworkInfo([fake_network_cache_model.new_vif( - {'type': 'ethernet'})]) + self.netinfo = self._new_netinfo() + + def _new_netinfo(self, vif_type='ethernet'): + netinfo = model.NetworkInfo([fake_network_cache_model.new_vif( + {'type': vif_type})]) # Give this vif ipv4 and ipv6 dhcp subnets ipv4_subnet = fake_network_cache_model.new_subnet(version=4) ipv6_subnet = fake_network_cache_model.new_subnet(version=6) - self.netinfo[0]['network']['subnets'][0] = ipv4_subnet - self.netinfo[0]['network']['subnets'][1] = ipv6_subnet - self.netinfo[0]['network']['meta']['mtu'] = 1500 + netinfo[0]['network']['subnets'][0] = ipv4_subnet + netinfo[0]['network']['subnets'][1] = ipv6_subnet + netinfo[0]['network']['meta']['mtu'] = 1500 + return netinfo def test_get_network_metadata_json(self): @@ -1195,3 +1199,32 @@ class TestNetworkMetadata(test.NoDBTestCase): self.netinfo[0]['network']['subnets'].pop(0) network_json = netutils.get_network_metadata(self.netinfo) self.assertEqual(expected_json, network_json) + + def test_legacy_vif_types_type_passed_through(self): + legacy_types = [ + model.VIF_TYPE_BRIDGE, + model.VIF_TYPE_DVS, + model.VIF_TYPE_HW_VEB, + model.VIF_TYPE_HYPERV, + model.VIF_TYPE_OVS, + model.VIF_TYPE_TAP, + model.VIF_TYPE_VHOSTUSER, + model.VIF_TYPE_VIF, + ] + link_types = [] + for vif_type in legacy_types: + network_json = netutils.get_network_metadata( + self._new_netinfo(vif_type=vif_type)) + link_types.append(network_json["links"][0]["type"]) + + self.assertEqual(legacy_types, link_types) + + def test_new_vif_types_get_type_phy(self): + new_types = ["whizbang_nvf", "vswitch9"] + link_types = [] + for vif_type in new_types: + network_json = netutils.get_network_metadata( + self._new_netinfo(vif_type=vif_type)) + link_types.append(network_json["links"][0]["type"]) + + self.assertEqual(["phy"] * len(new_types), link_types) diff --git a/nova/virt/netutils.py b/nova/virt/netutils.py index 89f2db6c564f..57afbbbd2e02 100644 --- a/nova/virt/netutils.py +++ b/nova/virt/netutils.py @@ -248,10 +248,10 @@ def _get_eth_link(vif, ifc_num): link_id = 'interface%d' % ifc_num # Use 'phy' for physical links. Ethernet can be confusing - if vif.get('type') == 'ethernet': - nic_type = 'phy' - else: + if vif.get('type') in model.LEGACY_EXPOSED_VIF_TYPES: nic_type = vif.get('type') + else: + nic_type = 'phy' link = { 'id': link_id,