neutron/neutron/tests/unit/plugins/ml2/_test_mech_agent.py
Brian Haley 055036ba2b Improve terminology in the Neutron tree
There is no real reason we should be using some of the
terms we do, they're outdated, and we're behind other
open-source projects in this respect. Let's switch to
using more inclusive terms in all possible places.

Change-Id: I99913107e803384b34cbd5ca588451b1cf64d594
2020-08-19 16:47:53 -04:00

373 lines
12 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.
import copy
from oslo_config import cfg
from oslo_config import fixture as config_fixture
from neutron_lib.api.definitions import portbindings
from neutron_lib.plugins.ml2 import 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,
vnic_type=portbindings.VNIC_NORMAL,
original=None, profile=None):
self._agent_type = agent_type
self._agents = agents
self._network_context = FakeNetworkContext(segments)
self._bound_vnic_type = vnic_type
self._bound_profile = profile
self._bound_segment_id = None
self._bound_vif_type = None
self._bound_vif_details = None
self._original = original
self._binding_levels = []
@property
def current(self):
current_data = {'id': PORT_ID,
portbindings.VNIC_TYPE: self._bound_vnic_type,
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
def original(self):
return self._original
@property
def status(self):
return 'DOWN'
@property
def original_status(self):
return None
@property
def network(self):
return self._network_context
def _prepare_to_bind(self, segments_to_bind):
self._segments_to_bind = segments_to_bind
self._new_bound_segment = None
self._next_segments_to_bind = None
def _push_binding_level(self, binding_level):
self._binding_levels.append(binding_level)
def _pop_binding_level(self):
return self._binding_levels.pop()
@property
def binding_levels(self):
if self._binding_levels:
return [{
api.BOUND_DRIVER: level.driver,
api.BOUND_SEGMENT: self._expand_segment(level.segment_id)
} for level in self._binding_levels]
@property
def original_binding_levels(self):
return None
@property
def top_bound_segment(self):
if self._binding_levels:
return self._expand_segment(self._binding_levels[0].segment_id)
@property
def original_top_bound_segment(self):
return None
@property
def bottom_bound_segment(self):
if self._binding_levels:
return self._expand_segment(self._binding_levels[-1].segment_id)
@property
def original_bottom_bound_segment(self):
return None
def _expand_segment(self, segment_id):
for segment in self._network_context.network_segments:
if segment[api.ID] == self._bound_segment_id:
return segment
@property
def host(self):
return ''
@property
def original_host(self):
return None
@property
def vif_type(self):
return portbindings.UNBOUND
@property
def original_vif_type(self):
return portbindings.UNBOUND
@property
def vif_details(self):
return None
@property
def original_vif_details(self):
return None
@property
def segments_to_bind(self):
return self._network_context.network_segments
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, vif_details):
self._bound_segment_id = segment_id
self._bound_vif_type = vif_type
self._bound_vif_details = vif_details
def continue_binding(self, segment_id, next_segments_to_bind):
pass
def allocate_dynamic_segment(self, segment):
pass
def release_dynamic_segment(self, segment_id):
pass
class MechDriverConfFixture(config_fixture.Config):
def __init__(self, conf=cfg.CONF, prohibit_list_cfg=None,
registration_func=None):
"""ConfigFixture for vnic_type_prohibit_list
:param conf: The driver configuration object
:param prohibit_list_cfg: A dictionary in the form
{'group': {'opt': 'value'}}, i.e.:
{'OVS_DRIVER': {'vnic_type_prohibit_list':
['foo']}}
:param registration_func: The method which do the config group's
registration.
"""
super(MechDriverConfFixture, self).__init__(conf)
self.prohibit_list_cfg = prohibit_list_cfg
self.registration_func = registration_func
def setUp(self):
super(MechDriverConfFixture, self).setUp()
self.registration_func(self.conf)
for group, option in self.prohibit_list_cfg.items():
self.config(group=group, **option)
class AgentMechanismBaseTestCase(base.BaseTestCase):
# The following must be overridden for the specific mechanism
# driver being tested:
VIF_TYPE = None
VIF_DETAILS = None
AGENT_TYPE = None
AGENTS = None
AGENTS_DEAD = None
AGENTS_BAD = None
VNIC_TYPE = portbindings.VNIC_NORMAL
def _check_unbound(self, context):
self.assertIsNone(context._bound_segment_id)
self.assertIsNone(context._bound_vif_type)
self.assertIsNone(context._bound_vif_details)
def _check_bound(self, context, segment):
self.assertEqual(context._bound_segment_id, segment[api.ID])
self.assertEqual(context._bound_vif_type, self.VIF_TYPE)
vif_details = context._bound_vif_details
self.assertIsNotNone(vif_details)
# NOTE(r-mibu): The following five lines are just for backward
# compatibility. In this class, HAS_PORT_FILTER has been replaced
# by VIF_DETAILS which can be set expected vif_details to check,
# but all replacement of HAS_PORT_FILTER in successor has not been
# completed.
if self.VIF_DETAILS is None:
expected = getattr(self, 'CAP_PORT_FILTER', None)
port_filter = vif_details[portbindings.CAP_PORT_FILTER]
self.assertEqual(expected, port_filter)
return
self.assertEqual(self.VIF_DETAILS, vif_details)
class AgentMechanismGenericTestCase(AgentMechanismBaseTestCase):
UNKNOWN_TYPE_SEGMENTS = [{api.ID: 'unknown_segment_id',
api.NETWORK_TYPE: 'no_such_type',
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.driver.bind_port(context)
self._check_unbound(context)
def test_driver_not_responsible_for_ports_allocation(self):
agents = [
{'configurations': {'rp_bandwidths': {'eth0': {}}},
'host': 'host'},
]
profile = {}
segments = []
port_ctx = FakePortContext(
self.AGENT_TYPE,
agents,
segments,
vnic_type=portbindings.VNIC_DIRECT,
profile=profile)
self.assertFalse(
self.driver.responsible_for_ports_allocation(port_ctx))
class AgentMechanismLocalTestCase(AgentMechanismBaseTestCase):
LOCAL_SEGMENTS = [{api.ID: 'unknown_segment_id',
api.NETWORK_TYPE: 'no_such_type',
api.NETWORK_ID: 'fake_network_id'},
{api.ID: 'local_segment_id',
api.NETWORK_TYPE: 'local',
api.NETWORK_ID: 'fake_network_id'}]
def test_type_local(self):
context = FakePortContext(self.AGENT_TYPE,
self.AGENTS,
self.LOCAL_SEGMENTS,
vnic_type=self.VNIC_TYPE)
self.driver.bind_port(context)
self._check_bound(context, self.LOCAL_SEGMENTS[1])
def test_type_local_dead(self):
context = FakePortContext(self.AGENT_TYPE,
self.AGENTS_DEAD,
self.LOCAL_SEGMENTS,
vnic_type=self.VNIC_TYPE)
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.NETWORK_ID: 'fake_network_id'},
{api.ID: 'flat_segment_id',
api.NETWORK_TYPE: 'flat',
api.PHYSICAL_NETWORK: 'fake_physical_network',
api.NETWORK_ID: 'fake_network_id'}]
def test_type_flat(self):
context = FakePortContext(self.AGENT_TYPE,
self.AGENTS,
self.FLAT_SEGMENTS,
vnic_type=self.VNIC_TYPE)
self.driver.bind_port(context)
self._check_bound(context, self.FLAT_SEGMENTS[1])
def test_type_flat_bad(self):
context = FakePortContext(self.AGENT_TYPE,
self.AGENTS_BAD,
self.FLAT_SEGMENTS,
vnic_type=self.VNIC_TYPE)
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.NETWORK_ID: 'fake_network_id'},
{api.ID: 'vlan_segment_id',
api.NETWORK_TYPE: 'vlan',
api.PHYSICAL_NETWORK: 'fake_physical_network',
api.SEGMENTATION_ID: 1234,
api.NETWORK_ID: 'fake_network_id'}]
def test_type_vlan(self):
context = FakePortContext(self.AGENT_TYPE,
self.AGENTS,
self.VLAN_SEGMENTS,
vnic_type=self.VNIC_TYPE)
self.driver.bind_port(context)
self._check_bound(context, self.VLAN_SEGMENTS[1])
def test_type_vlan_bad(self):
context = FakePortContext(self.AGENT_TYPE,
self.AGENTS_BAD,
self.VLAN_SEGMENTS,
vnic_type=self.VNIC_TYPE)
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.NETWORK_ID: 'fake_network_id'},
{api.ID: 'gre_segment_id',
api.NETWORK_TYPE: 'gre',
api.SEGMENTATION_ID: 1234,
api.NETWORK_ID: 'fake_network_id'}]
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])
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)