Always set ovs bridge name in vif:binding-details

- This change updates _set_bridge_name to set
  the bridge name field in the vif binding details.
- This change adds the integration_bridge name
  to the agent configuration report.

Closes-Bug: #1788009
Closes-Bug: #1856152

(cherry picked from commit 995744c576)
Change-Id: I454efcb226745c585935d5bd1b3d378f69a55ca2
This commit is contained in:
zhangyuhe 2018-08-28 01:30:53 +08:00
parent ca63f48054
commit d286f9ea1e
5 changed files with 66 additions and 10 deletions

View File

@ -273,6 +273,8 @@ class OVSNeutronAgent(l2population_rpc.L2populationRpcCallBackTunnelMixin,
'host': host, 'host': host,
'topic': n_const.L2_AGENT_TOPIC, 'topic': n_const.L2_AGENT_TOPIC,
'configurations': {'bridge_mappings': self.bridge_mappings, 'configurations': {'bridge_mappings': self.bridge_mappings,
'integration_bridge':
ovs_conf.integration_bridge,
'tunnel_types': self.tunnel_types, 'tunnel_types': self.tunnel_types,
'tunneling_ip': self.local_ip, 'tunneling_ip': self.local_ip,
'l2_population': self.l2_pop, 'l2_population': self.l2_pop,

View File

@ -111,11 +111,11 @@ class OpenvswitchMechanismDriver(mech_agent.SimpleAgentMechanismDriverBase):
def get_vif_details(self, context, agent, segment): def get_vif_details(self, context, agent, segment):
vif_details = self._pre_get_vif_details(agent, context) vif_details = self._pre_get_vif_details(agent, context)
self._set_bridge_name(context.current, vif_details) self._set_bridge_name(context.current, vif_details, agent)
return vif_details return vif_details
@staticmethod @staticmethod
def _set_bridge_name(port, vif_details): def _set_bridge_name(port, vif_details, agent):
# REVISIT(rawlin): add BridgeName as a nullable column to the Port # REVISIT(rawlin): add BridgeName as a nullable column to the Port
# model and simply check here if it's set and insert it into the # model and simply check here if it's set and insert it into the
# vif_details. # vif_details.
@ -123,6 +123,10 @@ class OpenvswitchMechanismDriver(mech_agent.SimpleAgentMechanismDriverBase):
def set_bridge_name_inner(bridge_name): def set_bridge_name_inner(bridge_name):
vif_details[portbindings.VIF_DETAILS_BRIDGE_NAME] = bridge_name vif_details[portbindings.VIF_DETAILS_BRIDGE_NAME] = bridge_name
bridge_name = agent['configurations'].get('integration_bridge')
if bridge_name:
vif_details[portbindings.VIF_DETAILS_BRIDGE_NAME] = bridge_name
registry.publish(a_const.OVS_BRIDGE_NAME, events.BEFORE_READ, registry.publish(a_const.OVS_BRIDGE_NAME, events.BEFORE_READ,
set_bridge_name_inner, payload=events.EventPayload( set_bridge_name_inner, payload=events.EventPayload(
None, metadata={'port': port})) None, metadata={'port': port}))

View File

@ -142,7 +142,8 @@ def set_agent_admin_state(agent_id, admin_state_up=False):
def _get_l2_agent_dict(host, agent_type, binary, tunnel_types=None, def _get_l2_agent_dict(host, agent_type, binary, tunnel_types=None,
tunneling_ip='20.0.0.1', interface_mappings=None, tunneling_ip='20.0.0.1', interface_mappings=None,
bridge_mappings=None, l2pop_network_types=None, bridge_mappings=None, l2pop_network_types=None,
device_mappings=None, start_flag=True): device_mappings=None, start_flag=True,
integration_bridge=None):
agent = { agent = {
'binary': binary, 'binary': binary,
'host': host, 'host': host,
@ -163,6 +164,8 @@ def _get_l2_agent_dict(host, agent_type, binary, tunnel_types=None,
agent['configurations']['l2pop_network_types'] = l2pop_network_types agent['configurations']['l2pop_network_types'] = l2pop_network_types
if device_mappings is not None: if device_mappings is not None:
agent['configurations']['device_mappings'] = device_mappings agent['configurations']['device_mappings'] = device_mappings
if integration_bridge is not None:
agent['configurations']['integration_bridge'] = integration_bridge
return agent return agent
@ -170,11 +173,13 @@ def register_ovs_agent(host=HOST, agent_type=constants.AGENT_TYPE_OVS,
binary='neutron-openvswitch-agent', binary='neutron-openvswitch-agent',
tunnel_types=['vxlan'], tunneling_ip='20.0.0.1', tunnel_types=['vxlan'], tunneling_ip='20.0.0.1',
interface_mappings=None, bridge_mappings=None, interface_mappings=None, bridge_mappings=None,
l2pop_network_types=None, plugin=None, start_flag=True): l2pop_network_types=None, plugin=None, start_flag=True,
integration_bridge=None):
agent = _get_l2_agent_dict(host, agent_type, binary, tunnel_types, agent = _get_l2_agent_dict(host, agent_type, binary, tunnel_types,
tunneling_ip, interface_mappings, tunneling_ip, interface_mappings,
bridge_mappings, l2pop_network_types, bridge_mappings, l2pop_network_types,
start_flag=start_flag) start_flag=start_flag,
integration_bridge=integration_bridge)
return _register_agent(agent, plugin) return _register_agent(agent, plugin)

View File

@ -42,7 +42,20 @@ class TestTrunkServicePlugin(ml2_test_base.ML2TestFramework):
utils.gen_trunk_br_name(trunk_res['id']), utils.gen_trunk_br_name(trunk_res['id']),
bound_port[pb.VIF_DETAILS][pb.VIF_DETAILS_BRIDGE_NAME]) bound_port[pb.VIF_DETAILS][pb.VIF_DETAILS_BRIDGE_NAME])
def test_ovs_bridge_name_not_set_when_not_trunk(self): def test_ovs_bridge_name_set_to_integration_bridge_when_not_trunk(self):
helpers.register_ovs_agent(host=helpers.HOST,
integration_bridge='br-fake')
with self.port() as port:
port['port'][pb.HOST_ID] = helpers.HOST
bound_port = self.core_plugin.update_port(self.context,
port['port']['id'], port)
self.assertEqual('br-fake',
bound_port[pb.VIF_DETAILS].get(pb.VIF_DETAILS_BRIDGE_NAME))
def test_ovs_bridge_name_not_set_if_integration_bridge_not_set(self):
"""This will only happen if a stein or later ml2 driver is
binding an interface for a pre stein ml2 agent.
"""
helpers.register_ovs_agent(host=helpers.HOST) helpers.register_ovs_agent(host=helpers.HOST)
with self.port() as port: with self.port() as port:
port['port'][pb.HOST_ID] = helpers.HOST port['port'][pb.HOST_ID] = helpers.HOST

View File

@ -30,7 +30,8 @@ from neutron.tests.unit.plugins.ml2 import _test_mech_agent as base
class OpenvswitchMechanismBaseTestCase(base.AgentMechanismBaseTestCase): class OpenvswitchMechanismBaseTestCase(base.AgentMechanismBaseTestCase):
VIF_TYPE = portbindings.VIF_TYPE_OVS VIF_TYPE = portbindings.VIF_TYPE_OVS
VIF_DETAILS = {portbindings.OVS_DATAPATH_TYPE: 'system', VIF_DETAILS = {'bridge_name': 'br-int',
portbindings.OVS_DATAPATH_TYPE: 'system',
portbindings.CAP_PORT_FILTER: True, portbindings.CAP_PORT_FILTER: True,
portbindings.OVS_HYBRID_PLUG: True} portbindings.OVS_HYBRID_PLUG: True}
AGENT_TYPE = constants.AGENT_TYPE_OVS AGENT_TYPE = constants.AGENT_TYPE_OVS
@ -38,11 +39,13 @@ class OpenvswitchMechanismBaseTestCase(base.AgentMechanismBaseTestCase):
GOOD_MAPPINGS = {'fake_physical_network': 'fake_bridge'} GOOD_MAPPINGS = {'fake_physical_network': 'fake_bridge'}
GOOD_TUNNEL_TYPES = ['gre', 'vxlan'] GOOD_TUNNEL_TYPES = ['gre', 'vxlan']
GOOD_CONFIGS = {'bridge_mappings': GOOD_MAPPINGS, GOOD_CONFIGS = {'bridge_mappings': GOOD_MAPPINGS,
'integration_bridge': 'br-int',
'tunnel_types': GOOD_TUNNEL_TYPES} 'tunnel_types': GOOD_TUNNEL_TYPES}
BAD_MAPPINGS = {'wrong_physical_network': 'wrong_bridge'} BAD_MAPPINGS = {'wrong_physical_network': 'wrong_bridge'}
BAD_TUNNEL_TYPES = ['bad_tunnel_type'] BAD_TUNNEL_TYPES = ['bad_tunnel_type']
BAD_CONFIGS = {'bridge_mappings': BAD_MAPPINGS, BAD_CONFIGS = {'bridge_mappings': BAD_MAPPINGS,
'integration_bridge': 'br-int',
'tunnel_types': BAD_TUNNEL_TYPES} 'tunnel_types': BAD_TUNNEL_TYPES}
AGENTS = [{'alive': True, AGENTS = [{'alive': True,
@ -70,18 +73,43 @@ class OpenvswitchMechanismBaseTestCase(base.AgentMechanismBaseTestCase):
def fake_callback(resource, event, trigger, payload=None): def fake_callback(resource, event, trigger, payload=None):
trigger('fake-br-name') trigger('fake-br-name')
def noop_callback(resource, event, trigger, payload=None):
pass
# hardcode callback to override bridge name
registry.subscribe(fake_callback, a_const.OVS_BRIDGE_NAME, registry.subscribe(fake_callback, a_const.OVS_BRIDGE_NAME,
events.BEFORE_READ) events.BEFORE_READ)
fake_vif_details = {} fake_vif_details = {}
self.driver._set_bridge_name('foo', fake_vif_details) fake_agent = {'configurations': {'integration_bridge': 'fake-br'}}
old_fake_agent = {'configurations': {}}
self.driver._set_bridge_name('foo', fake_vif_details, fake_agent)
# assert that callback value is used
self.assertEqual( self.assertEqual(
'fake-br-name', 'fake-br-name',
fake_vif_details.get(portbindings.VIF_DETAILS_BRIDGE_NAME, '')) fake_vif_details.get(portbindings.VIF_DETAILS_BRIDGE_NAME, ''))
# replace callback with noop
registry.unsubscribe(fake_callback, a_const.OVS_BRIDGE_NAME,
events.BEFORE_READ)
registry.subscribe(noop_callback, a_const.OVS_BRIDGE_NAME,
events.BEFORE_READ)
fake_vif_details = {}
self.driver._set_bridge_name('foo', fake_vif_details, fake_agent)
# assert that agent config value is used
self.assertEqual(
'fake-br',
fake_vif_details.get(portbindings.VIF_DETAILS_BRIDGE_NAME, ''))
fake_vif_details = {}
self.driver._set_bridge_name('foo', fake_vif_details, old_fake_agent)
# assert that if agent does not supply integration_bridge bridge_name
# is not set in vif:binding-details
self.assertIsNone(
fake_vif_details.get(portbindings.VIF_DETAILS_BRIDGE_NAME))
class OpenvswitchMechanismSGDisabledBaseTestCase( class OpenvswitchMechanismSGDisabledBaseTestCase(
OpenvswitchMechanismBaseTestCase): OpenvswitchMechanismBaseTestCase):
VIF_DETAILS = {portbindings.OVS_DATAPATH_TYPE: 'system', VIF_DETAILS = {'bridge_name': 'br-int',
portbindings.OVS_DATAPATH_TYPE: 'system',
portbindings.CAP_PORT_FILTER: False, portbindings.CAP_PORT_FILTER: False,
portbindings.OVS_HYBRID_PLUG: False} portbindings.OVS_HYBRID_PLUG: False}
@ -169,7 +197,8 @@ class OpenvswitchMechanismSGDisabledLocalTestCase(
class OpenvswitchMechanismFirewallUndefinedTestCase( class OpenvswitchMechanismFirewallUndefinedTestCase(
OpenvswitchMechanismBaseTestCase, base.AgentMechanismLocalTestCase): OpenvswitchMechanismBaseTestCase, base.AgentMechanismLocalTestCase):
VIF_DETAILS = {portbindings.OVS_DATAPATH_TYPE: 'system', VIF_DETAILS = {'bridge_name': 'br-int',
portbindings.OVS_DATAPATH_TYPE: 'system',
portbindings.CAP_PORT_FILTER: True, portbindings.CAP_PORT_FILTER: True,
portbindings.OVS_HYBRID_PLUG: True} portbindings.OVS_HYBRID_PLUG: True}
@ -190,18 +219,21 @@ class OpenvswitchMechanismDPDKTestCase(OpenvswitchMechanismBaseTestCase):
GOOD_TUNNEL_TYPES = ['gre', 'vxlan'] GOOD_TUNNEL_TYPES = ['gre', 'vxlan']
VHOST_CONFIGS = {'bridge_mappings': GOOD_MAPPINGS, VHOST_CONFIGS = {'bridge_mappings': GOOD_MAPPINGS,
'integration_bridge': 'br-int',
'tunnel_types': GOOD_TUNNEL_TYPES, 'tunnel_types': GOOD_TUNNEL_TYPES,
'datapath_type': a_const.OVS_DATAPATH_NETDEV, 'datapath_type': a_const.OVS_DATAPATH_NETDEV,
'ovs_capabilities': { 'ovs_capabilities': {
'iface_types': [a_const.OVS_DPDK_VHOST_USER]}} 'iface_types': [a_const.OVS_DPDK_VHOST_USER]}}
VHOST_SERVER_CONFIGS = {'bridge_mappings': GOOD_MAPPINGS, VHOST_SERVER_CONFIGS = {'bridge_mappings': GOOD_MAPPINGS,
'integration_bridge': 'br-int',
'tunnel_types': GOOD_TUNNEL_TYPES, 'tunnel_types': GOOD_TUNNEL_TYPES,
'datapath_type': a_const.OVS_DATAPATH_NETDEV, 'datapath_type': a_const.OVS_DATAPATH_NETDEV,
'ovs_capabilities': { 'ovs_capabilities': {
'iface_types': [a_const.OVS_DPDK_VHOST_USER_CLIENT]}} 'iface_types': [a_const.OVS_DPDK_VHOST_USER_CLIENT]}}
SYSTEM_CONFIGS = {'bridge_mappings': GOOD_MAPPINGS, SYSTEM_CONFIGS = {'bridge_mappings': GOOD_MAPPINGS,
'integration_bridge': 'br-int',
'tunnel_types': GOOD_TUNNEL_TYPES, 'tunnel_types': GOOD_TUNNEL_TYPES,
'datapath_type': a_const.OVS_DATAPATH_SYSTEM, 'datapath_type': a_const.OVS_DATAPATH_SYSTEM,
'ovs_capabilities': {'iface_types': []}} 'ovs_capabilities': {'iface_types': []}}