Check in "_update_segmentation_id" that the mech_driver has an agent
In [1] it is assumed that all mechanism drivers have an agent, but the mech driver API [2] doesn't enforce it. VIF types will be retrieved only from those mechanism drivers with an associated agent. [1]https://review.openstack.org/#/c/633165/20/neutron/plugins/ml2/plugin.py@814 [2]https://github.com/openstack/neutron-lib/blob/stable/stein/neutron_lib/plugins/ml2/api.py#L37 Change-Id: I5c334f31259871ed5251d5d4a2ba8cae36bd2355 Closes-Bug: #1824346
This commit is contained in:
parent
5d607a13ba
commit
749b33e41b
@ -115,6 +115,7 @@ from neutron.objects import ports as ports_obj
|
|||||||
from neutron.plugins.ml2.common import exceptions as ml2_exc
|
from neutron.plugins.ml2.common import exceptions as ml2_exc
|
||||||
from neutron.plugins.ml2 import db
|
from neutron.plugins.ml2 import db
|
||||||
from neutron.plugins.ml2 import driver_context
|
from neutron.plugins.ml2 import driver_context
|
||||||
|
from neutron.plugins.ml2.drivers import mech_agent
|
||||||
from neutron.plugins.ml2.extensions import qos as qos_ext
|
from neutron.plugins.ml2.extensions import qos as qos_ext
|
||||||
from neutron.plugins.ml2 import managers
|
from neutron.plugins.ml2 import managers
|
||||||
from neutron.plugins.ml2 import models
|
from neutron.plugins.ml2 import models
|
||||||
@ -809,11 +810,13 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
|||||||
vif_types = [portbindings.VIF_TYPE_UNBOUND,
|
vif_types = [portbindings.VIF_TYPE_UNBOUND,
|
||||||
portbindings.VIF_TYPE_BINDING_FAILED]
|
portbindings.VIF_TYPE_BINDING_FAILED]
|
||||||
for mech_driver in self.mechanism_manager.ordered_mech_drivers:
|
for mech_driver in self.mechanism_manager.ordered_mech_drivers:
|
||||||
if (provider_net.SEGMENTATION_ID in mech_driver.obj.
|
if (isinstance(mech_driver.obj,
|
||||||
|
mech_agent.AgentMechanismDriverBase) and
|
||||||
|
provider_net.SEGMENTATION_ID in mech_driver.obj.
|
||||||
provider_network_attribute_updates_supported()):
|
provider_network_attribute_updates_supported()):
|
||||||
agent_type = mech_driver.obj.agent_type
|
agent_type = mech_driver.obj.agent_type
|
||||||
agents = self.get_agents(context,
|
agents = self.get_agents(
|
||||||
filters={'agent_type': [agent_type]})
|
context, filters={'agent_type': [agent_type]})
|
||||||
for agent in agents:
|
for agent in agents:
|
||||||
vif_types.append(mech_driver.obj.get_vif_type(
|
vif_types.append(mech_driver.obj.get_vif_type(
|
||||||
context, agent, segments[0]))
|
context, agent, segments[0]))
|
||||||
|
@ -16,9 +16,12 @@
|
|||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from neutron_lib.api.definitions import portbindings
|
from neutron_lib.api.definitions import portbindings
|
||||||
|
from neutron_lib.api.definitions import provider_net as pnet
|
||||||
from neutron_lib import constants as const
|
from neutron_lib import constants as const
|
||||||
from neutron_lib.plugins.ml2 import api
|
from neutron_lib.plugins.ml2 import api
|
||||||
|
|
||||||
|
from neutron.plugins.ml2.drivers import mech_agent
|
||||||
|
|
||||||
|
|
||||||
VIF_TYPE_TEST = 'vif_type_test'
|
VIF_TYPE_TEST = 'vif_type_test'
|
||||||
|
|
||||||
@ -26,6 +29,10 @@ VIF_TYPE_TEST = 'vif_type_test'
|
|||||||
class TestMechanismDriver(api.MechanismDriver):
|
class TestMechanismDriver(api.MechanismDriver):
|
||||||
"""Test mechanism driver for testing mechanism driver api."""
|
"""Test mechanism driver for testing mechanism driver api."""
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(TestMechanismDriver, self).__init__(*args, **kwargs)
|
||||||
|
self._supported_vnic_types = ('test_mechanism_driver_vnic_type', )
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
self.bound_ports = set()
|
self.bound_ports = set()
|
||||||
|
|
||||||
@ -249,24 +256,50 @@ class TestMechanismDriver(api.MechanismDriver):
|
|||||||
self, context, segments, candidate_hosts, agent_getter):
|
self, context, segments, candidate_hosts, agent_getter):
|
||||||
return set()
|
return set()
|
||||||
|
|
||||||
def get_vif_type(self, context, agent, segment):
|
|
||||||
return VIF_TYPE_TEST
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def resource_provider_uuid5_namespace(self):
|
def resource_provider_uuid5_namespace(self):
|
||||||
return uuid.UUID('7f0ce65c-1f13-11e9-8921-3c6aa7b21d17')
|
return uuid.UUID('7f0ce65c-1f13-11e9-8921-3c6aa7b21d17')
|
||||||
|
|
||||||
@property
|
|
||||||
def agent_type(self):
|
|
||||||
return 'test_mechanism_driver_agent'
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def supported_vnic_types(self):
|
def supported_vnic_types(self):
|
||||||
return ('test_mechanism_driver_vnic_type',)
|
return self._supported_vnic_types
|
||||||
|
|
||||||
def get_standard_device_mappings(self, agent):
|
def get_standard_device_mappings(self, agent):
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
# NOTE(ralonsoh): to be removed with neutron-lib >= 1.26.0
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def provider_network_attribute_updates_supported():
|
def provider_network_attribute_updates_supported():
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
class TestMechanismDriverWithAgent(mech_agent.AgentMechanismDriverBase,
|
||||||
|
TestMechanismDriver):
|
||||||
|
"""Test mechanism driver with agent for testing mechanism driver api."""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super(TestMechanismDriverWithAgent, self).__init__('test_agent_type')
|
||||||
|
self.bound_ports = set()
|
||||||
|
self._agent_type = 'test_mechanism_driver_agent'
|
||||||
|
|
||||||
|
def get_vif_type(self, context, agent, segment):
|
||||||
|
return VIF_TYPE_TEST
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def provider_network_attribute_updates_supported():
|
||||||
|
return [pnet.SEGMENTATION_ID]
|
||||||
|
|
||||||
|
def try_to_bind_segment_for_agent(self, context, segment, agent):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@property
|
||||||
|
def agent_type(self):
|
||||||
|
return self._agent_type
|
||||||
|
|
||||||
|
@agent_type.setter
|
||||||
|
def agent_type(self, agent_type):
|
||||||
|
self._agent_type = agent_type
|
||||||
|
|
||||||
|
@TestMechanismDriver.supported_vnic_types.setter
|
||||||
|
def supported_vnic_types(self, vnic_types):
|
||||||
|
self._supported_vnic_types = vnic_types
|
||||||
|
@ -473,6 +473,44 @@ class TestMl2NetworksV2(test_plugin.TestNetworksV2,
|
|||||||
exc.InvalidInput, plugin._update_segmentation_id,
|
exc.InvalidInput, plugin._update_segmentation_id,
|
||||||
self.context, net['network'], {})
|
self.context, net['network'], {})
|
||||||
|
|
||||||
|
def test__update_segmentation_id_agentless_mech_drivers(self):
|
||||||
|
plugin = directory.get_plugin()
|
||||||
|
segments = [{pnet.NETWORK_TYPE: 'vlan',
|
||||||
|
pnet.PHYSICAL_NETWORK: 'physnet1',
|
||||||
|
pnet.SEGMENTATION_ID: 1}]
|
||||||
|
mech_drivers = plugin.mechanism_manager.ordered_mech_drivers
|
||||||
|
for mech_driver in (md.obj for md in mech_drivers if
|
||||||
|
hasattr(md.obj, 'agent_type')):
|
||||||
|
mock.patch.object(type(mech_driver), 'agent_type',
|
||||||
|
new_callable=mock.PropertyMock(return_value=None)).start()
|
||||||
|
|
||||||
|
with self.network(**{'arg_list': (mpnet_apidef.SEGMENTS, ),
|
||||||
|
mpnet_apidef.SEGMENTS: segments}) as net, \
|
||||||
|
mock.patch.object(db_base_plugin_v2.NeutronDbPluginV2,
|
||||||
|
'get_ports_count') as mock_get_ports_count, \
|
||||||
|
mock.patch.object(plugin.type_manager,
|
||||||
|
'update_network_segment'), \
|
||||||
|
mock.patch.object(plugin, 'get_agents') as mock_get_agents, \
|
||||||
|
mock.patch.object(obj_utils, 'NotIn') as mock_not_in:
|
||||||
|
mock_get_ports_count.return_value = 0
|
||||||
|
net_data = {pnet.SEGMENTATION_ID: 1000}
|
||||||
|
plugin._update_segmentation_id(self.context, net['network'],
|
||||||
|
net_data)
|
||||||
|
|
||||||
|
mock_get_agents.assert_not_called()
|
||||||
|
mock_not_in.assert_called_once_with([
|
||||||
|
portbindings.VIF_TYPE_UNBOUND,
|
||||||
|
portbindings.VIF_TYPE_BINDING_FAILED])
|
||||||
|
filters = {portbindings.VIF_TYPE: mock.ANY,
|
||||||
|
'network_id': [net['network']['id']]}
|
||||||
|
mock_get_ports_count.assert_called_once_with(
|
||||||
|
self.context, filters=filters)
|
||||||
|
|
||||||
|
|
||||||
|
class TestMl2NetworksV2AgentMechDrivers(Ml2PluginV2TestCase):
|
||||||
|
|
||||||
|
_mechanism_drivers = ['logger', 'test', 'test_with_agent']
|
||||||
|
|
||||||
def test__update_segmentation_id_ports(self):
|
def test__update_segmentation_id_ports(self):
|
||||||
plugin = directory.get_plugin()
|
plugin = directory.get_plugin()
|
||||||
segments = [{pnet.NETWORK_TYPE: 'vlan',
|
segments = [{pnet.NETWORK_TYPE: 'vlan',
|
||||||
@ -484,10 +522,6 @@ class TestMl2NetworksV2(test_plugin.TestNetworksV2,
|
|||||||
'get_ports_count') as mock_get_ports_count, \
|
'get_ports_count') as mock_get_ports_count, \
|
||||||
mock.patch.object(plugin.type_manager,
|
mock.patch.object(plugin.type_manager,
|
||||||
'update_network_segment'), \
|
'update_network_segment'), \
|
||||||
mock.patch.object(
|
|
||||||
mech_test.TestMechanismDriver,
|
|
||||||
'provider_network_attribute_updates_supported',
|
|
||||||
return_value=[pnet.SEGMENTATION_ID]), \
|
|
||||||
mock.patch.object(plugin, 'get_agents',
|
mock.patch.object(plugin, 'get_agents',
|
||||||
return_value=[mock.ANY]), \
|
return_value=[mock.ANY]), \
|
||||||
mock.patch.object(obj_utils, 'NotIn') as mock_not_in:
|
mock.patch.object(obj_utils, 'NotIn') as mock_not_in:
|
||||||
|
@ -27,6 +27,8 @@ LOG = logging.getLogger(__name__)
|
|||||||
|
|
||||||
class PlacementReportPluginTestCases(test_plugin.Ml2PluginV2TestCase):
|
class PlacementReportPluginTestCases(test_plugin.Ml2PluginV2TestCase):
|
||||||
|
|
||||||
|
_mechanism_drivers = ['logger', 'test_with_agent']
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(PlacementReportPluginTestCases, self).setUp()
|
super(PlacementReportPluginTestCases, self).setUp()
|
||||||
self.service_plugin = plugin.PlacementReportPlugin()
|
self.service_plugin = plugin.PlacementReportPlugin()
|
||||||
@ -223,6 +225,8 @@ class PlacementReportPluginTestCases(test_plugin.Ml2PluginV2TestCase):
|
|||||||
|
|
||||||
class PlacementReporterAgentsTestCases(test_plugin.Ml2PluginV2TestCase):
|
class PlacementReporterAgentsTestCases(test_plugin.Ml2PluginV2TestCase):
|
||||||
|
|
||||||
|
_mechanism_drivers = ['logger', 'test_with_agent']
|
||||||
|
|
||||||
def test_supported_agent_types(self):
|
def test_supported_agent_types(self):
|
||||||
self.agents = plugin.PlacementReporterAgents(ml2_plugin=self.plugin)
|
self.agents = plugin.PlacementReporterAgents(ml2_plugin=self.plugin)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
|
@ -86,6 +86,7 @@ neutron.ml2.type_drivers =
|
|||||||
neutron.ml2.mechanism_drivers =
|
neutron.ml2.mechanism_drivers =
|
||||||
logger = neutron.tests.unit.plugins.ml2.drivers.mechanism_logger:LoggerMechanismDriver
|
logger = neutron.tests.unit.plugins.ml2.drivers.mechanism_logger:LoggerMechanismDriver
|
||||||
test = neutron.tests.unit.plugins.ml2.drivers.mechanism_test:TestMechanismDriver
|
test = neutron.tests.unit.plugins.ml2.drivers.mechanism_test:TestMechanismDriver
|
||||||
|
test_with_agent = neutron.tests.unit.plugins.ml2.drivers.mechanism_test:TestMechanismDriverWithAgent
|
||||||
linuxbridge = neutron.plugins.ml2.drivers.linuxbridge.mech_driver.mech_linuxbridge:LinuxbridgeMechanismDriver
|
linuxbridge = neutron.plugins.ml2.drivers.linuxbridge.mech_driver.mech_linuxbridge:LinuxbridgeMechanismDriver
|
||||||
macvtap = neutron.plugins.ml2.drivers.macvtap.mech_driver.mech_macvtap:MacvtapMechanismDriver
|
macvtap = neutron.plugins.ml2.drivers.macvtap.mech_driver.mech_macvtap:MacvtapMechanismDriver
|
||||||
openvswitch = neutron.plugins.ml2.drivers.openvswitch.mech_driver.mech_openvswitch:OpenvswitchMechanismDriver
|
openvswitch = neutron.plugins.ml2.drivers.openvswitch.mech_driver.mech_openvswitch:OpenvswitchMechanismDriver
|
||||||
|
Loading…
x
Reference in New Issue
Block a user