dragonflow/dragonflow/tests/unit/test_l3_router_plugin.py

283 lines
12 KiB
Python

# Copyright (c) 2016 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 itertools
import mock
from neutron.db.models import l3
from neutron.tests.unit.api import test_extensions
from neutron.tests.unit.extensions import test_l3
from neutron_lib import constants
from neutron_lib import context as nctx
from neutron_lib.plugins import directory
import testtools
from dragonflow.db.models import l3 as df_l3
from dragonflow.neutron.db.models import l3 as neutron_l3
from dragonflow.tests.unit import test_mech_driver
def nb_api_get_funcs(*instances):
"""
Create an method that can be used to override the mock's nb_api's get
to return objects that should exist, e.g. instances that were created
with create (and verified with the relevant assert)
:param instances: An iterable of instances that should exist in nb_api
:type instances: iterable of instances
"""
ids = {instance.id: instance for instance in instances}
def nb_api_get(inst):
try:
return ids[inst.id]
except KeyError:
return mock.MagicMock(name='NbApi.get_instance().get()')
def nb_api_create(inst):
inst.on_create_pre()
ids[inst.id] = inst
def nb_api_update(inst):
ids[inst.id].update(inst)
return nb_api_get, nb_api_create, nb_api_update
class TestDFL3RouterPlugin(test_mech_driver.DFMechanismDriverTestCase,
test_l3.L3NatTestCaseMixin):
l3_plugin = ('dragonflow.neutron.services.l3_router_plugin.'
'DFL3RouterPlugin')
def setUp(self):
super(TestDFL3RouterPlugin, self).setUp()
self.l3p = directory.get_plugin('L3_ROUTER_NAT')
self.nb_api = self.l3p.nb_api
self.nb_api.get().unique_key = 5
self.nb_api.get().topic = 'topic'
self.ext_api = test_extensions.setup_extensions_middleware(
test_l3.L3TestExtensionManager()
)
def _test_create_router_revision(self):
r = {'router': {'name': 'router', 'tenant_id': 'tenant',
'admin_state_up': True}}
router = self.l3p.create_router(self.context, r)
self.assertEqual(router['revision_number'], 0)
lrouter = neutron_l3.logical_router_from_neutron_router(router)
self.nb_api.create.assert_called_once_with(lrouter)
return router, lrouter
def test_create_update_router_revision(self):
router, _ = self._test_create_router_revision()
old_version = router['revision_number']
router['name'] = 'another_router'
new_router = self.l3p.update_router(
self.context, router['id'], {'router': router})
self.assertGreater(new_router['revision_number'], old_version)
def test_add_delete_router_interface_revision(self):
router, lrouter = self._test_create_router_revision()
old_version = router['revision_number']
nb_api_get, nb_api_create, nb_api_update = nb_api_get_funcs(lrouter)
self.nb_api.get.side_effect = nb_api_get
self.nb_api.update.side_effect = nb_api_update
self.nb_api.create.side_effect = nb_api_create
self.nb_api.driver.allocate_unique_key.side_effect = itertools.count()
with self.subnet() as s:
data = {'subnet_id': s['subnet']['id']}
self.l3p.add_router_interface(self.context, router['id'], data)
# NOTE(oanson) The calls to expire_all may need to be removed once
# Neutron complete the move to EngineFacade. Currently they exist
# to make sure we don't get stale Router objects with the old
# version
self.context.session.expire_all()
router_with_int = self.l3p.get_router(self.context, router['id'])
self.assertGreater(router_with_int['revision_number'],
old_version)
lrouter.version = router_with_int['revision_number']
self.nb_api.update.assert_has_calls([mock.call(lrouter)])
# Second call is with the router lport
self.nb_api.update.reset_mock()
self.l3p.remove_router_interface(self.context, router['id'], data)
self.context.session.expire_all()
router_without_int = self.l3p.get_router(self.context,
router['id'])
self.assertGreater(router_without_int['revision_number'],
router_with_int['revision_number'])
lrouter.version = router_without_int['revision_number']
self.nb_api.update.assert_called_once_with(lrouter)
def _test_create_floatingip_revision(self):
kwargs = {'arg_list': ('router:external',),
'router:external': True}
with self.network(**kwargs) as n:
with self.subnet(network=n):
floatingip = self.l3p.create_floatingip(
self.context,
{'floatingip': {'floating_network_id': n['network']['id'],
'subnet_id': None,
'floating_ip_address': None,
'tenant_id': n['network']['tenant_id']}})
self.assertEqual(floatingip['revision_number'], 0)
nb_fip = self.nb_api.create.call_args_list[-1][0][0]
self.assertIsInstance(nb_fip, df_l3.FloatingIp)
self.assertEqual(floatingip['id'], nb_fip.id)
self.assertEqual(floatingip['tenant_id'], nb_fip.topic)
self.assertEqual(floatingip['revision_number'],
nb_fip.version)
return floatingip
def test_create_update_floatingip_revision(self):
floatingip = self._test_create_floatingip_revision()
old_version = floatingip['revision_number']
floatingip['tenant_id'] = 'another_tenant'
new_fip = self.l3p.update_floatingip(
self.context, floatingip['id'], {'floatingip': floatingip})
self.assertGreater(new_fip['revision_number'], old_version)
nb_fip = self.nb_api.update.call_args_list[-1][0][0]
self.assertIsInstance(nb_fip, df_l3.FloatingIp)
self.assertEqual(new_fip['id'], nb_fip.id)
self.assertEqual(new_fip['tenant_id'], nb_fip.topic)
self.assertEqual(new_fip['revision_number'], nb_fip.version)
@testtools.skip("bug/1736952")
def test_create_floatingip_with_normal_user(self):
normal_context = nctx.Context(is_admin=False, overwrite=False)
kwargs = {'arg_list': ('router:external',),
'router:external': True}
with self.network(**kwargs) as n:
with self.subnet(network=n):
floatingip = self.l3p.create_floatingip(
normal_context,
{'floatingip': {'floating_network_id': n['network']['id'],
'tenant_id': n['network']['tenant_id']}})
self.assertTrue(floatingip)
def test_create_router_have_extra_attrs(self):
r = {'router': {'name': 'router', 'tenant_id': 'tenant',
'admin_state_up': True}}
router = self.l3p.create_router(self.context, r)
record = (self.context.session.query(l3.Router).
filter_by(id=router['id']).
one())
self.assertIsNotNone(record['extra_attributes'])
def test_floatingip_create_not_assoc(self):
with self.subnet() as subnet:
with self.floatingip_no_assoc(subnet) as fip:
self.assertEqual(
constants.FLOATINGIP_STATUS_DOWN,
fip['floatingip']['status'],
)
def test_floatingip_create_port_status_down(self):
with self.port() as port:
self.l3p.core_plugin.update_port_status(
self.context, port['port']['id'], constants.PORT_STATUS_DOWN)
with self.floatingip_with_assoc(port_id=port['port']['id']) as fip:
self.assertEqual(
constants.FLOATINGIP_STATUS_DOWN,
fip['floatingip']['status'],
)
def test_floatingip_create_port_status_active(self):
with self.port() as port:
self.l3p.core_plugin.update_port_status(
self.context, port['port']['id'], constants.PORT_STATUS_ACTIVE)
with self.floatingip_with_assoc(port_id=port['port']['id']) as fip:
self.assertEqual(
constants.FLOATINGIP_STATUS_ACTIVE,
fip['floatingip']['status'],
)
def test_floatingip_port_updated_to_active(self):
with self.port() as port:
self.l3p.core_plugin.update_port_status(
self.context, port['port']['id'], constants.PORT_STATUS_DOWN)
with self.floatingip_with_assoc(port_id=port['port']['id']) as fip:
self.l3p.core_plugin.update_port_status(
self.context, port['port']['id'],
constants.PORT_STATUS_ACTIVE)
self.assertEqual(
constants.FLOATINGIP_STATUS_ACTIVE,
self.l3p.get_floatingip(
self.context,
fip['floatingip']['id'],
)['status'],
)
def test_floatingip_port_updated_to_down(self):
with self.port() as port:
self.l3p.core_plugin.update_port_status(
self.context, port['port']['id'], constants.PORT_STATUS_ACTIVE)
with self.floatingip_with_assoc(port_id=port['port']['id']) as fip:
self.l3p.core_plugin.update_port_status(
self.context, port['port']['id'],
constants.PORT_STATUS_DOWN)
self.assertEqual(
constants.FLOATINGIP_STATUS_DOWN,
self.l3p.get_floatingip(
self.context,
fip['floatingip']['id'],
)['status'],
)
def test_floatingip_update_disassoc(self):
with self.port() as port:
self.l3p.core_plugin.update_port_status(
self.context, port['port']['id'], constants.PORT_STATUS_ACTIVE)
with self.floatingip_with_assoc(port_id=port['port']['id']) as fip:
floatingip_id = fip['floatingip']['id']
self.l3p.update_floatingip(
self.context,
floatingip_id,
{'floatingip': {'port_id': None}},
)
self.assertEqual(
constants.FLOATINGIP_STATUS_DOWN,
self.l3p.get_floatingip(
self.context,
floatingip_id,
)['status'],
)
def test_floatingip_update_assoc(self):
with self.port() as port:
self.l3p.core_plugin.update_port_status(
self.context, port['port']['id'], constants.PORT_STATUS_ACTIVE)
with self.floatingip_with_assoc(port_id=port['port']['id']) as fip:
floatingip_id = fip['floatingip']['id']
self.l3p.update_floatingip(
self.context,
floatingip_id,
{'floatingip': {'port_id': None}},
)
self.l3p.update_floatingip(
self.context,
floatingip_id,
{'floatingip': {'port_id': port['port']['id']}},
)
self.assertEqual(
constants.FLOATINGIP_STATUS_ACTIVE,
self.l3p.get_floatingip(
self.context,
floatingip_id,
)['status'],
)