From e912f5e54785d77b4fabd1113c16b19d0981f003 Mon Sep 17 00:00:00 2001 From: Russell Bryant Date: Tue, 22 Dec 2015 14:15:07 -0500 Subject: [PATCH] neutronv2: Allow Neutron to specify OVS/LB bridge. Previously, the OVS bridge name only came from nova.conf. It will be helpful to allow Neutron to specify the name. In particular, this has come up as a requirement for implementing Neutron's "vlan-aware-vms" spec, which will require a separate bridge per port, at least for the existing default ML2+OVS backend. This patch will allow Neutron to customize the bridge name on a per-port basis. The implementation is quite simple, as the use of the config value was already localized to a small area of code. That code just has to prefer a name in vif_details, but fall back to the config value, otherwise. While not immediately needed, it seems convenient to go ahead and apply the same change for VIF_TYPE_BRIDGE (linux bridge) and VIF_TYPE_VHOSTUSER, since it's a trivial addition to the patch. The test cases just follow the same pattern as several other test cases for this code, but makes sure that a custom bridge name in vif_details is honored. Implements blueprint neutron-ovs-bridge-name. Change-Id: I66c25e0c9d971163d0ddad186a0c49f20a77aaa9 Signed-off-by: Russell Bryant --- nova/network/model.py | 1 + nova/network/neutronv2/api.py | 18 +++++------ nova/tests/unit/network/test_neutronv2.py | 32 +++++++++++++++++++ ...tron-ovs-bridge-name-7b3477103622f4cc.yaml | 4 +++ 4 files changed, 46 insertions(+), 9 deletions(-) create mode 100644 releasenotes/notes/neutron-ovs-bridge-name-7b3477103622f4cc.yaml diff --git a/nova/network/model.py b/nova/network/model.py index d81611bccc..81a655f339 100644 --- a/nova/network/model.py +++ b/nova/network/model.py @@ -51,6 +51,7 @@ VIF_TYPE_BINDING_FAILED = 'binding_failed' VIF_DETAILS_PORT_FILTER = 'port_filter' VIF_DETAILS_OVS_HYBRID_PLUG = 'ovs_hybrid_plug' VIF_DETAILS_PHYSICAL_NETWORK = 'physical_network' +VIF_DETAILS_BRIDGE_NAME = 'bridge_name' # The following constant defines an SR-IOV related parameter in the # 'vif_details'. 'profileid' should be used for VIF_TYPE_802_QBH diff --git a/nova/network/neutronv2/api.py b/nova/network/neutronv2/api.py index 1f8c9b2978..66d77218a2 100644 --- a/nova/network/neutronv2/api.py +++ b/nova/network/neutronv2/api.py @@ -49,11 +49,10 @@ neutron_opts = [ help='URL for connecting to neutron'), cfg.StrOpt('region_name', help='Region name for connecting to neutron in admin context'), - # TODO(berrange) temporary hack until Neutron can pass over the - # name of the OVS bridge it is configured with cfg.StrOpt('ovs_bridge', default='br-int', - help='Name of Integration Bridge used by Open vSwitch'), + help='Default OVS bridge name to use if not specified ' + 'by Neutron'), cfg.IntOpt('extension_sync_interval', default=600, help='Number of seconds before querying neutron for' @@ -1518,14 +1517,14 @@ class API(base_api.NetworkAPI): # Network model metadata should_create_bridge = None vif_type = port.get('binding:vif_type') - port_details = port.get('binding:vif_details') - # TODO(berrange) Neutron should pass the bridge name - # in another binding metadata field + port_details = port.get('binding:vif_details', {}) if vif_type == network_model.VIF_TYPE_OVS: - bridge = CONF.neutron.ovs_bridge + bridge = port_details.get(network_model.VIF_DETAILS_BRIDGE_NAME, + CONF.neutron.ovs_bridge) ovs_interfaceid = port['id'] elif vif_type == network_model.VIF_TYPE_BRIDGE: - bridge = "brq" + port['network_id'] + bridge = port_details.get(network_model.VIF_DETAILS_BRIDGE_NAME, + "brq" + port['network_id']) should_create_bridge = True elif vif_type == network_model.VIF_TYPE_DVS: # The name of the DVS port group will contain the neutron @@ -1534,7 +1533,8 @@ class API(base_api.NetworkAPI): elif (vif_type == network_model.VIF_TYPE_VHOSTUSER and port_details.get(network_model.VIF_DETAILS_VHOSTUSER_OVS_PLUG, False)): - bridge = CONF.neutron.ovs_bridge + bridge = port_details.get(network_model.VIF_DETAILS_BRIDGE_NAME, + CONF.neutron.ovs_bridge) ovs_interfaceid = port['id'] # Prune the bridge name if necessary. For the DVS this is not done diff --git a/nova/tests/unit/network/test_neutronv2.py b/nova/tests/unit/network/test_neutronv2.py index d0307fe45c..2e586971f0 100644 --- a/nova/tests/unit/network/test_neutronv2.py +++ b/nova/tests/unit/network/test_neutronv2.py @@ -2482,6 +2482,38 @@ class TestNeutronv2(TestNeutronv2Base): self.assertNotIn('should_create_bridge', net) self.assertEqual('port-id', iid) + def _test_nw_info_build_custom_bridge(self, vif_type, extra_details=None): + fake_port = { + 'fixed_ips': [{'ip_address': '1.1.1.1'}], + 'id': 'port-id', + 'network_id': 'net-id', + 'binding:vif_type': vif_type, + 'binding:vif_details': { + model.VIF_DETAILS_BRIDGE_NAME: 'custom-bridge', + } + } + if extra_details: + fake_port['binding:vif_details'].update(extra_details) + fake_subnets = [model.Subnet(cidr='1.0.0.0/8')] + fake_nets = [{'id': 'net-id', 'name': 'foo', 'tenant_id': 'tenant'}] + api = neutronapi.API() + self.mox.ReplayAll() + neutronapi.get_client('fake') + net, iid = api._nw_info_build_network(fake_port, fake_nets, + fake_subnets) + self.assertNotEqual(CONF.neutron.ovs_bridge, net['bridge']) + self.assertEqual('custom-bridge', net['bridge']) + + def test_nw_info_build_custom_ovs_bridge(self): + self._test_nw_info_build_custom_bridge(model.VIF_TYPE_OVS) + + def test_nw_info_build_custom_ovs_bridge_vhostuser(self): + self._test_nw_info_build_custom_bridge(model.VIF_TYPE_VHOSTUSER, + {model.VIF_DETAILS_VHOSTUSER_OVS_PLUG: True}) + + def test_nw_info_build_custom_lb_bridge(self): + self._test_nw_info_build_custom_bridge(model.VIF_TYPE_BRIDGE) + def test_build_network_info_model(self): api = neutronapi.API() diff --git a/releasenotes/notes/neutron-ovs-bridge-name-7b3477103622f4cc.yaml b/releasenotes/notes/neutron-ovs-bridge-name-7b3477103622f4cc.yaml new file mode 100644 index 0000000000..8d4b877aa8 --- /dev/null +++ b/releasenotes/notes/neutron-ovs-bridge-name-7b3477103622f4cc.yaml @@ -0,0 +1,4 @@ +--- +features: + - Add support for allowing Neutron to specify the + bridge name for the OVS, Linux Bridge, and vhost-user VIF types.