Merge "[OVN] Check new added segments in OVN mech driver"

This commit is contained in:
Zuul 2022-01-24 11:46:52 +00:00 committed by Gerrit Code Review
commit 2999b8e579
11 changed files with 121 additions and 32 deletions

View File

@ -69,6 +69,9 @@ OVN_AGENT_METADATA_ID_KEY = 'neutron:ovn-metadata-id'
OVN_CONTROLLER_AGENT = 'OVN Controller agent'
OVN_CONTROLLER_GW_AGENT = 'OVN Controller Gateway agent'
OVN_METADATA_AGENT = 'OVN Metadata agent'
OVN_CONTROLLER_TYPES = (OVN_CONTROLLER_AGENT,
OVN_CONTROLLER_GW_AGENT,
)
# OVN ACLs have priorities. The highest priority ACL that matches is the one
# that takes effect. Our choice of priority numbers is arbitrary, but it

View File

@ -364,6 +364,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

@ -177,6 +177,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

@ -33,6 +33,7 @@ from neutron_lib import exceptions as n_exc
from neutron_lib.exceptions import availability_zone as az_exc
from neutron_lib.plugins import directory
from neutron_lib.plugins.ml2 import api
from neutron_lib.utils import helpers
from oslo_concurrency import processutils
from oslo_config import cfg
from oslo_db import exception as os_db_exc
@ -1152,6 +1153,20 @@ class OVNMechanismDriver(api.MechanismDriver):
if phynet in phynets}
segment_service_db.map_segment_to_hosts(context, segment.id, hosts)
def check_segment_for_agent(self, segment, agent):
"""Check if the OVN controller agent br mappings has segment physnet
Only segments on physical networks (flat or vlan) can be associated
to a host.
"""
if agent['agent_type'] not in ovn_const.OVN_CONTROLLER_TYPES:
return False
br_map = agent.get('configurations', {}).get('bridge-mappings', '')
mapping_dict = helpers.parse_mappings(br_map.split(','),
unique_values=False)
return segment['physical_network'] in mapping_dict
def patch_plugin_merge(self, method_name, new_fn, op=operator.add):
old_method = getattr(self._plugin, method_name)

View File

@ -2379,8 +2379,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

@ -58,13 +58,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()
@ -76,17 +84,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

@ -55,16 +55,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()
@ -128,7 +136,9 @@ class OpenvswitchMechanismSGDisabledBaseTestCase(
'tunnel_types': GOOD_TUNNEL_TYPES}
AGENTS = [{'alive': True,
'configurations': GOOD_CONFIGS,
'host': 'host'}]
'host': 'host',
'agent_type': constants.AGENT_TYPE_OVS,
}]
def setUp(self):
cfg.CONF.set_override('enable_security_group',
@ -151,7 +161,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])
@ -163,7 +175,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])

View File

@ -2626,6 +2626,25 @@ class TestOVNMechanismDriverSegment(MechDriverSetupBase,
3,
ovn_nb_api.delete_lswitch_port.call_count)
def test_check_segment_for_agent(self):
segment = {'physical_network': 'physnet1'}
agent = {'agent_type': ovn_const.OVN_METADATA_AGENT}
self.assertFalse(
self.mech_driver.check_segment_for_agent(segment, agent))
agent = {'agent_type': ovn_const.OVN_CONTROLLER_AGENT,
'configurations': {}}
self.assertFalse(
self.mech_driver.check_segment_for_agent(segment, agent))
agent['configurations'] = {'bridge-mappings': 'physnet2:br-ex2'}
self.assertFalse(
self.mech_driver.check_segment_for_agent(segment, agent))
agent['configurations'] = {'bridge-mappings': 'physnet1:br-ex1'}
self.assertTrue(
self.mech_driver.check_segment_for_agent(segment, agent))
@mock.patch.object(n_net, 'get_random_mac', lambda *_: '01:02:03:04:05:06')
class TestOVNMechanismDriverDHCPOptions(OVNMechanismDriverTestCase):