vmware-nsx/neutron/tests/unit/ml2/_test_mech_agent.py
Bob Kukura 0f0499b89e Implement ML2 port binding
The ml2 plugin uses mechanism drivers to determine which network
segment and what VIF driver to use for a port. Mechanism drivers
supporting the openvswitch, linuxbridge, and hyperv agents are
added. The binding:host attribute is set on ports belonging to the
dhcp and l3 agents so that they can be bound.

To use with devstack until it is updated, set
"Q_ML2_PLUGIN_MECHANISM_DRIVERS=openvswitch,linuxbridge" in localrc.

The hyperv L2 agent does not currently implement the agents_db RPC,
and will therefore not work with its ml2 mechanism driver. This issue
will be tracked as a bug to be fixed in a separate merge.

implements blueprint: ml2-portbinding

Change-Id: Icb9c70d8b0d7fcb34b57adc760bb713b740e5dad
2013-09-03 18:05:20 -04:00

208 lines
7.2 KiB
Python

# Copyright (c) 2013 OpenStack Foundation
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from neutron.plugins.ml2 import driver_api as api
from neutron.tests import base
NETWORK_ID = "fake_network"
PORT_ID = "fake_port"
class FakeNetworkContext(api.NetworkContext):
def __init__(self, segments):
self._network_segments = segments
@property
def current(self):
return {'id': NETWORK_ID}
@property
def original(self):
return None
@property
def network_segments(self):
return self._network_segments
class FakePortContext(api.PortContext):
def __init__(self, agent_type, agents, segments):
self._agent_type = agent_type
self._agents = agents
self._network_context = FakeNetworkContext(segments)
self._bound_segment_id = None
self._bound_vif_type = None
self._bound_cap_port_filter = None
@property
def current(self):
return {'id': PORT_ID}
@property
def original(self):
return None
@property
def network(self):
return self._network_context
@property
def bound_segment(self):
if self._bound_segment_id:
for segment in self._network_context.network_segments:
if segment[api.ID] == self._bound_segment_id:
return segment
def host_agents(self, agent_type):
if agent_type == self._agent_type:
return self._agents
else:
return []
def set_binding(self, segment_id, vif_type, cap_port_filter):
self._bound_segment_id = segment_id
self._bound_vif_type = vif_type
self._bound_cap_port_filter = cap_port_filter
class AgentMechanismBaseTestCase(base.BaseTestCase):
# These following must be overriden for the specific mechanism
# driver being tested:
VIF_TYPE = None
CAP_PORT_FILTER = None
AGENT_TYPE = None
AGENTS = None
AGENTS_DEAD = None
AGENTS_BAD = None
def _check_unbound(self, context):
self.assertIsNone(context._bound_segment_id)
self.assertIsNone(context._bound_vif_type)
self.assertIsNone(context._bound_cap_port_filter)
def _check_bound(self, context, segment):
self.assertEqual(context._bound_segment_id, segment[api.ID])
self.assertEqual(context._bound_vif_type, self.VIF_TYPE)
self.assertEqual(context._bound_cap_port_filter, self.CAP_PORT_FILTER)
class AgentMechanismGenericTestCase(AgentMechanismBaseTestCase):
UNKNOWN_TYPE_SEGMENTS = [{api.ID: 'unknown_segment_id',
api.NETWORK_TYPE: 'no_such_type'}]
def test_unknown_type(self):
context = FakePortContext(self.AGENT_TYPE,
self.AGENTS,
self.UNKNOWN_TYPE_SEGMENTS)
self.driver.bind_port(context)
self._check_unbound(context)
class AgentMechanismLocalTestCase(AgentMechanismBaseTestCase):
LOCAL_SEGMENTS = [{api.ID: 'unknown_segment_id',
api.NETWORK_TYPE: 'no_such_type'},
{api.ID: 'local_segment_id',
api.NETWORK_TYPE: 'local'}]
def test_type_local(self):
context = FakePortContext(self.AGENT_TYPE,
self.AGENTS,
self.LOCAL_SEGMENTS)
self.driver.bind_port(context)
self._check_bound(context, self.LOCAL_SEGMENTS[1])
self.assertTrue(self.driver.validate_port_binding(context))
self.driver.unbind_port(context)
def test_type_local_dead(self):
context = FakePortContext(self.AGENT_TYPE,
self.AGENTS_DEAD,
self.LOCAL_SEGMENTS)
self.driver.bind_port(context)
self._check_unbound(context)
class AgentMechanismFlatTestCase(AgentMechanismBaseTestCase):
FLAT_SEGMENTS = [{api.ID: 'unknown_segment_id',
api.NETWORK_TYPE: 'no_such_type'},
{api.ID: 'flat_segment_id',
api.NETWORK_TYPE: 'flat',
api.PHYSICAL_NETWORK: 'fake_physical_network'}]
def test_type_flat(self):
context = FakePortContext(self.AGENT_TYPE,
self.AGENTS,
self.FLAT_SEGMENTS)
self.driver.bind_port(context)
self._check_bound(context, self.FLAT_SEGMENTS[1])
self.assertTrue(self.driver.validate_port_binding(context))
self.driver.unbind_port(context)
def test_type_flat_bad(self):
context = FakePortContext(self.AGENT_TYPE,
self.AGENTS_BAD,
self.FLAT_SEGMENTS)
self.driver.bind_port(context)
self._check_unbound(context)
class AgentMechanismVlanTestCase(AgentMechanismBaseTestCase):
VLAN_SEGMENTS = [{api.ID: 'unknown_segment_id',
api.NETWORK_TYPE: 'no_such_type'},
{api.ID: 'vlan_segment_id',
api.NETWORK_TYPE: 'vlan',
api.PHYSICAL_NETWORK: 'fake_physical_network',
api.SEGMENTATION_ID: 1234}]
def test_type_vlan(self):
context = FakePortContext(self.AGENT_TYPE,
self.AGENTS,
self.VLAN_SEGMENTS)
self.driver.bind_port(context)
self._check_bound(context, self.VLAN_SEGMENTS[1])
self.assertTrue(self.driver.validate_port_binding(context))
self.driver.unbind_port(context)
def test_type_vlan_bad(self):
context = FakePortContext(self.AGENT_TYPE,
self.AGENTS_BAD,
self.VLAN_SEGMENTS)
self.driver.bind_port(context)
self._check_unbound(context)
class AgentMechanismGreTestCase(AgentMechanismBaseTestCase):
GRE_SEGMENTS = [{api.ID: 'unknown_segment_id',
api.NETWORK_TYPE: 'no_such_type'},
{api.ID: 'gre_segment_id',
api.NETWORK_TYPE: 'gre',
api.SEGMENTATION_ID: 1234}]
def test_type_gre(self):
context = FakePortContext(self.AGENT_TYPE,
self.AGENTS,
self.GRE_SEGMENTS)
self.driver.bind_port(context)
self._check_bound(context, self.GRE_SEGMENTS[1])
self.assertTrue(self.driver.validate_port_binding(context))
self.driver.unbind_port(context)
def test_type_gre_bad(self):
context = FakePortContext(self.AGENT_TYPE,
self.AGENTS_BAD,
self.GRE_SEGMENTS)
self.driver.bind_port(context)
self._check_unbound(context)