[OVN] Check new added segments in OVN mech driver

Check new segments added to OVN mechanism driver. This mechanism
driver does not inherit from ``SimpleAgentMechanismDriverBase``
because OVN has no agents (NOTE 1). However OVN mechanism driver
requires an OVN controller service in each deployed chassis. This
is how OVN driver knows the hosts using this backend.

The segments, attached to an external network (connected to a
physical network), can be mapped to a host if ther is a chassis (OVN
controller agent) in this host.

NOTE 1: OVN provides agent API compatibility, presenting the
controller and the metadata services as agents. But OVN mechanism
driver has no control or provides any information (via RPC) to
those services.

NOTE 2: stable/train does not have OVN ML2 driver in-tree. This driver
can be used by installing networking-ovn. This patch in Neutron is
needed to provide support for the referred feature. The corresponding
code will land in the plugin repository too.

Conflicts:
      neutron/common/ovn/constants.py
      neutron/plugins/ml2/drivers/ovn/mech_driver/mech_driver.py
      neutron/tests/unit/plugins/ml2/drivers/openvswitch/mech_driver/test_mech_openvswitch.py
      neutron/tests/unit/plugins/ml2/drivers/ovn/mech_driver/test_mech_driver.py

Closes-Bug: #1949967
Change-Id: I570b2251da8a4a25d155ba838346b24afafd727f
(cherry picked from commit c8427c82da)
(cherry picked from commit d53733c33a)
(cherry picked from commit b0080c4719)
This commit is contained in:
Rodolfo Alonso Hernandez 2021-11-05 14:56:15 +00:00
parent 0124181916
commit e12580f602
8 changed files with 93 additions and 31 deletions

View File

@ -334,6 +334,8 @@ class SimpleAgentMechanismDriverBase(AgentMechanismDriverBase):
determine whether or not the specified network segment can be
bound for the agent.
"""
if agent['agent_type'] != self.agent_type:
return False
mappings = self.get_mappings(agent)
allowed_network_types = self.get_allowed_network_types(agent)

View File

@ -178,6 +178,9 @@ class SriovNicSwitchMechanismDriver(mech_agent.SimpleAgentMechanismDriverBase):
:param agent: agents_db entry describing agent to bind or None
:returns: True if segment can be bound for agent
"""
if agent and agent['agent_type'] != self.agent_type:
return False
network_type = segment[api.NETWORK_TYPE]
if network_type in self.get_allowed_network_types(agent):
if agent:

View File

@ -2321,8 +2321,9 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
def check_segment_for_agent(self, segment, agent):
for mech_driver in self.mechanism_manager.ordered_mech_drivers:
driver_agent_type = getattr(mech_driver.obj, 'agent_type', None)
if driver_agent_type and driver_agent_type == agent['agent_type']:
# TODO(ralonsoh): add "check_segment_for_agent" method to ABC
# "MechanismDriver", returning False by default.
if hasattr(mech_driver.obj, 'check_segment_for_agent'):
if mech_driver.obj.check_segment_for_agent(segment, agent):
return True
return False

View File

@ -246,17 +246,19 @@ class AgentMechanismGenericTestCase(AgentMechanismBaseTestCase):
api.NETWORK_ID: 'fake_network_id'}]
def test_unknown_type(self):
context = FakePortContext(self.AGENT_TYPE,
self.AGENTS,
self.UNKNOWN_TYPE_SEGMENTS,
vnic_type=self.VNIC_TYPE)
self.context = FakePortContext(self.AGENT_TYPE, self.AGENTS,
self.UNKNOWN_TYPE_SEGMENTS,
vnic_type=self.VNIC_TYPE)
context = self.context
self.driver.bind_port(context)
self._check_unbound(context)
def test_driver_not_responsible_for_ports_allocation(self):
agents = [
{'configurations': {'rp_bandwidths': {'eth0': {}}},
'host': 'host'},
'host': 'host',
'agent_type': self.AGENT_TYPE,
},
]
profile = {}
segments = []

View File

@ -38,16 +38,24 @@ class LinuxbridgeMechanismBaseTestCase(base.AgentMechanismBaseTestCase):
AGENTS = [{'alive': True,
'configurations': GOOD_CONFIGS,
'host': 'host'}]
'host': 'host',
'agent_type': AGENT_TYPE,
}]
AGENTS_DEAD = [{'alive': False,
'configurations': GOOD_CONFIGS,
'host': 'dead_host'}]
'host': 'dead_host',
'agent_type': AGENT_TYPE,
}]
AGENTS_BAD = [{'alive': False,
'configurations': GOOD_CONFIGS,
'host': 'bad_host_1'},
'host': 'bad_host_1',
'agent_type': AGENT_TYPE,
},
{'alive': True,
'configurations': BAD_CONFIGS,
'host': 'bad_host_2'}]
'host': 'bad_host_2',
'agent_type': AGENT_TYPE,
}]
def setUp(self):
super(LinuxbridgeMechanismBaseTestCase, self).setUp()

View File

@ -34,18 +34,26 @@ class MacvtapMechanismBaseTestCase(base.AgentMechanismBaseTestCase):
AGENT = {'alive': True,
'configurations': GOOD_CONFIGS,
'host': 'host'}
'host': 'host',
'agent_type': AGENT_TYPE,
}
AGENTS = [AGENT]
AGENTS_DEAD = [{'alive': False,
'configurations': GOOD_CONFIGS,
'host': 'dead_host'}]
'host': 'dead_host',
'agent_type': AGENT_TYPE,
}]
AGENTS_BAD = [{'alive': False,
'configurations': GOOD_CONFIGS,
'host': 'bad_host_1'},
'host': 'bad_host_1',
'agent_type': AGENT_TYPE,
},
{'alive': True,
'configurations': BAD_CONFIGS,
'host': 'bad_host_2'}]
'host': 'bad_host_2',
'agent_type': AGENT_TYPE,
}]
def setUp(self):
super(MacvtapMechanismBaseTestCase, self).setUp()

View File

@ -57,13 +57,21 @@ class SriovNicSwitchMechanismBaseTestCase(base.AgentMechanismBaseTestCase):
BAD_CONFIGS = {'device_mappings': BAD_MAPPINGS}
AGENTS = [{'alive': True,
'configurations': GOOD_CONFIGS}]
'configurations': GOOD_CONFIGS,
'agent_type': AGENT_TYPE,
}]
AGENTS_DEAD = [{'alive': False,
'configurations': GOOD_CONFIGS}]
'configurations': GOOD_CONFIGS,
'agent_type': AGENT_TYPE,
}]
AGENTS_BAD = [{'alive': False,
'configurations': GOOD_CONFIGS},
'configurations': GOOD_CONFIGS,
'agent_type': AGENT_TYPE,
},
{'alive': True,
'configurations': BAD_CONFIGS}]
'configurations': BAD_CONFIGS,
'agent_type': AGENT_TYPE,
}]
def setUp(self):
super(SriovNicSwitchMechanismBaseTestCase, self).setUp()
@ -75,17 +83,23 @@ class SriovSwitchMechGenericTestCase(SriovNicSwitchMechanismBaseTestCase,
base.AgentMechanismGenericTestCase):
def test_check_segment(self):
"""Validate the check_segment call."""
segment = {'api.NETWORK_TYPE': ""}
segment[api.NETWORK_TYPE] = constants.TYPE_VLAN
self.assertTrue(self.driver.check_segment_for_agent(segment))
agent = {'agent_type': self.AGENT_TYPE,
'configurations': {'device_mappings': ['physnet1']}}
segment = {api.NETWORK_TYPE: constants.TYPE_VLAN,
api.PHYSICAL_NETWORK: 'physnet1'}
self.assertTrue(self.driver.check_segment_for_agent(segment, agent))
# Validate a network type not currently supported
segment[api.NETWORK_TYPE] = constants.TYPE_GRE
self.assertFalse(self.driver.check_segment_for_agent(segment))
self.assertFalse(self.driver.check_segment_for_agent(segment, agent))
def test_check_segment_allows_supported_network_types(self):
for network_type in self.driver.get_allowed_network_types(agent=None):
segment = {api.NETWORK_TYPE: network_type}
self.assertTrue(self.driver.check_segment_for_agent(segment))
agent = {'agent_type': self.AGENT_TYPE,
'configurations': {'device_mappings': ['physnet1']}}
segment = {api.NETWORK_TYPE: network_type,
api.PHYSICAL_NETWORK: 'physnet1'}
self.assertTrue(self.driver.check_segment_for_agent(segment,
agent))
def test_driver_responsible_for_ports_allocation(self):
agents = [

View File

@ -53,16 +53,24 @@ class OpenvswitchMechanismBaseTestCase(base.AgentMechanismBaseTestCase):
AGENTS = [{'alive': True,
'configurations': GOOD_CONFIGS,
'host': 'host'}]
'host': 'host',
'agent_type': AGENT_TYPE,
}]
AGENTS_DEAD = [{'alive': False,
'configurations': GOOD_CONFIGS,
'host': 'dead_host'}]
'host': 'dead_host',
'agent_type': AGENT_TYPE,
}]
AGENTS_BAD = [{'alive': False,
'configurations': GOOD_CONFIGS,
'host': 'bad_host_1'},
'host': 'bad_host_1',
'agent_type': AGENT_TYPE,
},
{'alive': True,
'configurations': BAD_CONFIGS,
'host': 'bad_host_2'}]
'host': 'bad_host_2',
'agent_type': AGENT_TYPE,
}]
def setUp(self):
super(OpenvswitchMechanismBaseTestCase, self).setUp()
@ -118,6 +126,18 @@ class OpenvswitchMechanismSGDisabledBaseTestCase(
portbindings.VIF_DETAILS_CONNECTIVITY:
portbindings.CONNECTIVITY_L2}
GOOD_MAPPINGS = {'fake_physical_network': 'fake_bridge'}
GOOD_TUNNEL_TYPES = ['gre', 'vxlan']
GOOD_CONFIGS = {'bridge_mappings': GOOD_MAPPINGS,
'integration_bridge': 'br-int',
portbindings.OVS_HYBRID_PLUG: False,
'tunnel_types': GOOD_TUNNEL_TYPES}
AGENTS = [{'alive': True,
'configurations': GOOD_CONFIGS,
'host': 'host',
'agent_type': constants.AGENT_TYPE_OVS,
}]
def setUp(self):
cfg.CONF.set_override('enable_security_group',
False,
@ -150,7 +170,9 @@ class OpenvswitchMechanismHybridPlugTestCase(OpenvswitchMechanismBaseTestCase):
self.driver.vif_details[hybrid] = False
agents = [{'alive': True,
'configurations': {hybrid: True},
'host': 'host'}]
'host': 'host',
'agent_type': self.AGENT_TYPE,
}]
context = self._make_port_ctx(agents)
self.driver.bind_port(context)
self.assertTrue(context._bound_vif_details[hybrid])
@ -162,7 +184,9 @@ class OpenvswitchMechanismHybridPlugTestCase(OpenvswitchMechanismBaseTestCase):
self.driver.vif_details[hybrid] = True
agents = [{'alive': True,
'configurations': {hybrid: False},
'host': 'host'}]
'host': 'host',
'agent_type': self.AGENT_TYPE,
}]
context = self._make_port_ctx(agents)
self.driver.bind_port(context)
self.assertFalse(context._bound_vif_details[hybrid])