neutron/neutron/tests/functional/agent/test_l2_lb_agent.py

145 lines
6.4 KiB
Python

# 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 mock
from oslo_config import cfg
from oslo_utils import uuidutils
import testtools
from neutron.agent.linux import ip_lib
from neutron.objects import trunk
from neutron.plugins.ml2.drivers.linuxbridge.agent import \
linuxbridge_neutron_agent
from neutron.services.trunk.drivers.linuxbridge.agent import trunk_plumber
from neutron.tests.functional.agent.linux import test_ip_lib
lba = linuxbridge_neutron_agent
class LinuxBridgeAgentTests(test_ip_lib.IpLibTestFramework):
def setUp(self):
super(LinuxBridgeAgentTests, self).setUp()
agent_rpc = ('neutron.agent.rpc.PluginApi')
mock.patch(agent_rpc).start()
mock.patch('neutron.agent.rpc.PluginReportStateAPI').start()
cfg.CONF.set_override('enable_vxlan', False, 'VXLAN')
def test_validate_interface_mappings(self):
mappings = {'physnet1': 'int1', 'physnet2': 'int2'}
with testtools.ExpectedException(SystemExit):
lba.LinuxBridgeManager({}, mappings)
self.manage_device(
self.generate_device_details()._replace(namespace=None,
name='int1'))
with testtools.ExpectedException(SystemExit):
lba.LinuxBridgeManager({}, mappings)
self.manage_device(
self.generate_device_details()._replace(namespace=None,
name='int2'))
lba.LinuxBridgeManager({}, mappings)
def test_validate_bridge_mappings(self):
mappings = {'physnet1': 'br-eth1'}
with testtools.ExpectedException(SystemExit):
lba.LinuxBridgeManager(mappings, {})
self.manage_device(
self.generate_device_details()._replace(namespace=None,
name='br-eth1'))
lba.LinuxBridgeManager(mappings, {})
def test_vlan_subinterfaces(self):
attr = self.generate_device_details()
device = self.manage_device(attr)
devname = device.name
plumber = trunk_plumber.Plumber(namespace=attr.namespace)
for i in range(20):
subname = 'vtest-%s' % i
plumber._create_vlan_subint(devname, subname, i)
# ensure no addresses were assigned (e.g. ipv6)
vlan_int = ip_lib.IPDevice(subname, namespace=attr.namespace)
self.assertFalse(vlan_int.addr.list())
children = plumber._get_vlan_children(devname)
expected = {('vtest-%s' % i, i) for i in range(20)}
self.assertEqual(expected, children)
# delete one
plumber._safe_delete_device('vtest-19')
children = plumber._get_vlan_children(devname)
expected = {('vtest-%s' % i, i) for i in range(19)}
self.assertEqual(expected, children)
# ensure they are removed by parent removal
self._safe_delete_device(device)
self.assertFalse(plumber._get_vlan_children(devname))
def test_vlan_QinQ_subinterfaces(self):
# the trunk model does not support this right now, but this is to
# ensure the plumber on the agent side doesn't explode in their
# presence in case an operator does something fancy or we have a
# race where a trunk's parent port is converted to a subport while
# the agent is offline.
attr = self.generate_device_details()
device = self.manage_device(attr)
devname = device.name
plumber = trunk_plumber.Plumber(namespace=attr.namespace)
for i in range(20):
plumber._create_vlan_subint(devname, 'vtest-%s' % i, i)
plumber._create_vlan_subint('vtest-%s' % i, 'qinq-%s' % i, 2)
top_level = {('vtest-%s' % i, i) for i in range(20)}
for i in range(20):
# as we iterate, we delete a vlan from each dev and ensure it
# didn't break the top-level vlans
self.assertEqual({('qinq-%s' % i, 2)},
plumber._get_vlan_children('vtest-%s' % i))
plumber._safe_delete_device('qinq-%s' % i)
self.assertEqual(set(), plumber._get_vlan_children('vtest-%i' % i))
self.assertEqual(top_level, plumber._get_vlan_children(devname))
def test_ensure_trunk_subports(self):
attr = self.generate_device_details()
device = self.manage_device(attr)
devname = device.name
plumber = trunk_plumber.Plumber(namespace=attr.namespace)
plumber._trunk_device_name = lambda x: devname
trunk_obj = self._gen_trunk()
plumber.ensure_trunk_subports(trunk_obj)
# ensure no mutation the second time
with mock.patch.object(plumber, '_safe_delete_device',
side_effect=RuntimeError()):
plumber.ensure_trunk_subports(trunk_obj)
while trunk_obj.sub_ports:
# drain down the sub-ports and make sure it keeps
# them equal
trunk_obj.sub_ports.pop()
plumber.ensure_trunk_subports(trunk_obj)
expected = {(plumber._get_tap_device_name(sp.port_id),
sp.segmentation_id)
for sp in trunk_obj.sub_ports}
wired = plumber._get_vlan_children(devname)
self.assertEqual(expected, wired)
def _gen_trunk(self):
trunk_obj = trunk.Trunk(id=uuidutils.generate_uuid(),
port_id=uuidutils.generate_uuid(),
project_id=uuidutils.generate_uuid())
subports = [trunk.SubPort(id=uuidutils.generate_uuid(),
port_id=uuidutils.generate_uuid(),
segmentation_type='vlan',
trunk_id=trunk_obj.id,
segmentation_id=i)
for i in range(20, 40)]
trunk_obj.sub_ports = subports
return trunk_obj