Merge "Check mech driver connectivity during port binding"
This commit is contained in:
commit
84317b8820
@ -826,10 +826,19 @@ class MechanismManager(stevedore.named.NamedExtensionManager):
|
|||||||
'host': context.host})
|
'host': context.host})
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
drivers = self._check_drivers_connectivity(drivers, context)
|
||||||
|
if not drivers:
|
||||||
|
LOG.error("Port %(port)s does not have an IP address assigned and "
|
||||||
|
"there are no driver with 'connectivity' = 'l2'. The "
|
||||||
|
"port cannot be bound.",
|
||||||
|
{'port': context.current['id']})
|
||||||
|
return False
|
||||||
|
|
||||||
for driver in drivers:
|
for driver in drivers:
|
||||||
if not self._check_driver_to_bind(driver, segments_to_bind,
|
if not self._check_driver_to_bind(driver, segments_to_bind,
|
||||||
context._binding_levels):
|
context._binding_levels):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
try:
|
try:
|
||||||
context._prepare_to_bind(segments_to_bind)
|
context._prepare_to_bind(segments_to_bind)
|
||||||
driver.obj.bind_port(context)
|
driver.obj.bind_port(context)
|
||||||
@ -1028,6 +1037,21 @@ class MechanismManager(stevedore.named.NamedExtensionManager):
|
|||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def _check_drivers_connectivity(self, drivers, port_context):
|
||||||
|
"""If port does not have an IP address, driver connectivity must be l2
|
||||||
|
|
||||||
|
A port without an IP address can be bound only to a mech driver with
|
||||||
|
"connectivity" = "l2". "legacy" or "l3" (e.g.: Calico) drivers cannot
|
||||||
|
have a port bound without an IP allocated.
|
||||||
|
"""
|
||||||
|
if port_context.current.get('fixed_ips'):
|
||||||
|
return drivers
|
||||||
|
|
||||||
|
return [d for d in drivers if
|
||||||
|
getattr(d.obj, 'vif_details', {}).get(
|
||||||
|
portbindings.VIF_DETAILS_CONNECTIVITY) ==
|
||||||
|
portbindings.CONNECTIVITY_L2]
|
||||||
|
|
||||||
def get_workers(self):
|
def get_workers(self):
|
||||||
workers = []
|
workers = []
|
||||||
for driver in self.ordered_mech_drivers:
|
for driver in self.ordered_mech_drivers:
|
||||||
|
@ -13,6 +13,8 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
import copy
|
||||||
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_config import fixture as config_fixture
|
from oslo_config import fixture as config_fixture
|
||||||
|
|
||||||
@ -59,9 +61,14 @@ class FakePortContext(api.PortContext):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def current(self):
|
def current(self):
|
||||||
return {'id': PORT_ID,
|
current_data = {'id': PORT_ID,
|
||||||
portbindings.VNIC_TYPE: self._bound_vnic_type,
|
portbindings.VNIC_TYPE: self._bound_vnic_type,
|
||||||
portbindings.PROFILE: self._bound_profile}
|
portbindings.PROFILE: self._bound_profile}
|
||||||
|
ret_value = current_data
|
||||||
|
if self._original:
|
||||||
|
ret_value = copy.deepcopy(self.original)
|
||||||
|
ret_value.update(current_data)
|
||||||
|
return ret_value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def original(self):
|
def original(self):
|
||||||
|
@ -45,7 +45,10 @@ class FakeAgentMechanismDriver(mech_agent.SimpleAgentMechanismDriverBase):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
sg_enabled = securitygroups_rpc.is_firewall_enabled()
|
sg_enabled = securitygroups_rpc.is_firewall_enabled()
|
||||||
vif_details = {portbindings.CAP_PORT_FILTER: sg_enabled,
|
vif_details = {portbindings.CAP_PORT_FILTER: sg_enabled,
|
||||||
portbindings.OVS_HYBRID_PLUG: sg_enabled}
|
portbindings.OVS_HYBRID_PLUG: sg_enabled,
|
||||||
|
portbindings.VIF_DETAILS_CONNECTIVITY:
|
||||||
|
portbindings.CONNECTIVITY_L2,
|
||||||
|
}
|
||||||
super(FakeAgentMechanismDriver, self).__init__(
|
super(FakeAgentMechanismDriver, self).__init__(
|
||||||
# NOTE(yamamoto): l2pop driver has a hardcoded list of
|
# NOTE(yamamoto): l2pop driver has a hardcoded list of
|
||||||
# supported agent types.
|
# supported agent types.
|
||||||
@ -64,3 +67,12 @@ class FakeAgentMechanismDriver(mech_agent.SimpleAgentMechanismDriverBase):
|
|||||||
|
|
||||||
class AnotherFakeAgentMechanismDriver(FakeAgentMechanismDriver):
|
class AnotherFakeAgentMechanismDriver(FakeAgentMechanismDriver):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class FakeAgentMechanismDriverL3(FakeAgentMechanismDriver):
|
||||||
|
"""ML2 mechanism driver for testing, with L3 connectivity only"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super(FakeAgentMechanismDriverL3, self).__init__()
|
||||||
|
self.vif_details[portbindings.VIF_DETAILS_CONNECTIVITY] = (
|
||||||
|
portbindings.CONNECTIVITY_L3)
|
||||||
|
@ -41,9 +41,10 @@ class TestManagers(base.BaseTestCase):
|
|||||||
'network_type': 'vlan',
|
'network_type': 'vlan',
|
||||||
'physical_network': 'public',
|
'physical_network': 'public',
|
||||||
api.SEGMENTATION_ID: 49}]
|
api.SEGMENTATION_ID: 49}]
|
||||||
self.context = FakePortContext(None,
|
original_port = {'fixed_ips': [{'subnet_id': mock.ANY,
|
||||||
None,
|
'ip_address': mock.ANY}]}
|
||||||
self.segments_to_bind)
|
self.context = FakePortContext(None, None, self.segments_to_bind,
|
||||||
|
original=original_port)
|
||||||
self.context._binding = mock.Mock()
|
self.context._binding = mock.Mock()
|
||||||
self.context._binding_levels = []
|
self.context._binding_levels = []
|
||||||
self.context._new_bound_segment = self.segment_id
|
self.context._new_bound_segment = self.segment_id
|
||||||
@ -73,6 +74,26 @@ class TestManagers(base.BaseTestCase):
|
|||||||
manager._bind_port_level(self.context, 0, self.segments_to_bind)
|
manager._bind_port_level(self.context, 0, self.segments_to_bind)
|
||||||
self.assertEqual(0, bind_port.call_count)
|
self.assertEqual(0, bind_port.call_count)
|
||||||
|
|
||||||
|
def _check_drivers_connectivity(self, agents):
|
||||||
|
cfg.CONF.set_override('mechanism_drivers', agents, group='ml2')
|
||||||
|
manager = managers.MechanismManager()
|
||||||
|
return (manager.ordered_mech_drivers,
|
||||||
|
manager._check_drivers_connectivity(
|
||||||
|
manager.ordered_mech_drivers, self.context))
|
||||||
|
|
||||||
|
def test__check_drivers_connectivity(self):
|
||||||
|
self.assertEqual(*self._check_drivers_connectivity(['fake_agent']))
|
||||||
|
|
||||||
|
def test__check_drivers_connectivity_ip_less_port(self):
|
||||||
|
self.context._original['fixed_ips'] = []
|
||||||
|
self.assertEqual(*self._check_drivers_connectivity(['fake_agent']))
|
||||||
|
|
||||||
|
def test__check_drivers_connectivity_ip_less_port_l3_only_driver(self):
|
||||||
|
self.context._original['fixed_ips'] = []
|
||||||
|
self.assertEqual(
|
||||||
|
[],
|
||||||
|
self._check_drivers_connectivity(['fake_agent_l3'])[1])
|
||||||
|
|
||||||
def test__infer_driver_from_allocation_positive(self):
|
def test__infer_driver_from_allocation_positive(self):
|
||||||
cfg.CONF.set_override(
|
cfg.CONF.set_override(
|
||||||
'mechanism_drivers', ['fake_agent'], group='ml2')
|
'mechanism_drivers', ['fake_agent'], group='ml2')
|
||||||
|
@ -95,6 +95,7 @@ neutron.ml2.mechanism_drivers =
|
|||||||
l2population = neutron.plugins.ml2.drivers.l2pop.mech_driver:L2populationMechanismDriver
|
l2population = neutron.plugins.ml2.drivers.l2pop.mech_driver:L2populationMechanismDriver
|
||||||
sriovnicswitch = neutron.plugins.ml2.drivers.mech_sriov.mech_driver.mech_driver:SriovNicSwitchMechanismDriver
|
sriovnicswitch = neutron.plugins.ml2.drivers.mech_sriov.mech_driver.mech_driver:SriovNicSwitchMechanismDriver
|
||||||
fake_agent = neutron.tests.unit.plugins.ml2.drivers.mech_fake_agent:FakeAgentMechanismDriver
|
fake_agent = neutron.tests.unit.plugins.ml2.drivers.mech_fake_agent:FakeAgentMechanismDriver
|
||||||
|
fake_agent_l3 = neutron.tests.unit.plugins.ml2.drivers.mech_fake_agent:FakeAgentMechanismDriverL3
|
||||||
another_fake_agent = neutron.tests.unit.plugins.ml2.drivers.mech_fake_agent:AnotherFakeAgentMechanismDriver
|
another_fake_agent = neutron.tests.unit.plugins.ml2.drivers.mech_fake_agent:AnotherFakeAgentMechanismDriver
|
||||||
faulty_agent = neutron.tests.unit.plugins.ml2.drivers.mech_faulty_agent:FaultyAgentMechanismDriver
|
faulty_agent = neutron.tests.unit.plugins.ml2.drivers.mech_faulty_agent:FaultyAgentMechanismDriver
|
||||||
neutron.ml2.extension_drivers =
|
neutron.ml2.extension_drivers =
|
||||||
|
Loading…
Reference in New Issue
Block a user