diff options
author | Wojciech Dec <wdec@cisco.com> | 2016-08-17 13:14:23 +0200 |
---|---|---|
committer | Wojciech Dec <wdec@cisco.com> | 2016-08-17 13:14:23 +0200 |
commit | 4979a23b8b2c0094ced98cf05eebb692d6609937 (patch) | |
tree | c49ceeb5b127fdb0e10c0f5ac0516be96cbd31a9 /networking-odl/networking_odl/tests | |
parent | c3b2c2a9a22bac5cf17813c589444d3abebaa23b (diff) |
Correcting networking-odl to mitaka/stable + app topology patch
Change-Id: Iddcd8dda2d49fcdd8e0f37a1d052a6fa8a24b035
Signed-off-by: Wojciech Dec <wdec@cisco.com>
Diffstat (limited to 'networking-odl/networking_odl/tests')
18 files changed, 196 insertions, 1018 deletions
diff --git a/networking-odl/networking_odl/tests/unit/common/test_callback.py b/networking-odl/networking_odl/tests/unit/common/test_callback.py index f5e2ee6..b7720b3 100644 --- a/networking-odl/networking_odl/tests/unit/common/test_callback.py +++ b/networking-odl/networking_odl/tests/unit/common/test_callback.py @@ -18,6 +18,7 @@ from networking_odl.common import constants as odl_const from networking_odl.ml2.mech_driver import OpenDaylightDriver import mock +import testscenarios import testtools from neutron.callbacks import events @@ -27,57 +28,110 @@ from neutron.callbacks import resources FAKE_ID = 'fakeid' -class ODLCallbackTestCase(testtools.TestCase): - odl_driver = OpenDaylightDriver() - sgh = callback.OdlSecurityGroupsHandler(odl_driver) +class ODLCallbackTestCase(testscenarios.WithScenarios, testtools.TestCase): + odl_client = OpenDaylightDriver() + scenarios = [ + ('after', { + 'sgh': callback.OdlSecurityGroupsHandler(odl_client, + "AFTER")}), + ('precommit', { + 'sgh': callback.OdlSecurityGroupsHandler(odl_client, + "PRECOMMIT")}), + ] def setUp(self): super(ODLCallbackTestCase, self).setUp() @mock.patch.object(OpenDaylightDriver, 'sync_from_callback') - def _test_callback_for_sg(self, event, op, sg, sg_id, sfc): + def test_callback_sg_create(self, sfc): + context = mock.Mock() + sg = mock.Mock() + default_sg = mock.Mock() + kwargs = { + 'context': context, + 'security_group': sg, + 'security_groups': odl_const.ODL_SGS, + 'is_default': default_sg, + } self.sgh.sg_callback(resources.SECURITY_GROUP, - event, - None, - security_group=sg, - security_group_id=sg_id) + events.AFTER_CREATE, + "trigger", + **kwargs) - expected_dict = ({resources.SECURITY_GROUP: sg} - if sg is not None else None) - sfc.assert_called_with( - op, callback._RESOURCE_MAPPING[resources.SECURITY_GROUP], sg_id, - expected_dict) + sfc.assert_called_with(odl_const.ODL_CREATE, + 'security-groups', + None, {'security_group': sg}) - def test_callback_sg_create(self): - self._test_callback_for_sg(events.AFTER_CREATE, odl_const.ODL_CREATE, - mock.Mock(), None) + @mock.patch.object(OpenDaylightDriver, 'sync_from_callback') + def test_callback_sg_update(self, sfc): + context = mock.Mock() + sg = mock.Mock() + kwargs = { + 'context': context, + 'security_group_id': FAKE_ID, + 'security_group': sg, + 'security_groups': odl_const.ODL_SGS, + } + self.sgh.sg_callback(resources.SECURITY_GROUP, + events.AFTER_UPDATE, + "trigger", + **kwargs) + + sfc.assert_called_with(odl_const.ODL_UPDATE, + 'security-groups', + FAKE_ID, {'security_group': sg}) + + @mock.patch.object(OpenDaylightDriver, 'sync_from_callback') + def test_callback_sg_delete(self, sfc): + context = mock.Mock() + sg = mock.Mock() + kwargs = { + 'context': context, + 'security_group_id': FAKE_ID, + 'security_group': sg, + 'security_groups': odl_const.ODL_SGS, + } + self.sgh.sg_callback(resources.SECURITY_GROUP, + events.AFTER_DELETE, + "trigger", + **kwargs) - def test_callback_sg_update(self): - self._test_callback_for_sg(events.AFTER_UPDATE, odl_const.ODL_UPDATE, - mock.Mock(), FAKE_ID) + sfc.assert_called_with(odl_const.ODL_DELETE, + 'security-groups', + FAKE_ID, {'security_group': sg}) - def test_callback_sg_delete(self): - self._test_callback_for_sg(events.AFTER_DELETE, odl_const.ODL_DELETE, - None, FAKE_ID) + @mock.patch.object(OpenDaylightDriver, 'sync_from_callback') + def test_callback_sg_rules_create(self, sfc): + context = mock.Mock() + security_group_rule = mock.Mock() + kwargs = { + 'context': context, + 'security_group_rule': security_group_rule, + 'security_group_rules': odl_const.ODL_SG_RULES, + } + self.sgh.sg_callback(resources.SECURITY_GROUP_RULE, + events.AFTER_CREATE, + "trigger", + **kwargs) + + sfc.assert_called_with(odl_const.ODL_CREATE, + 'security-group-rules', + None, + {'security_group_rule': security_group_rule}) @mock.patch.object(OpenDaylightDriver, 'sync_from_callback') - def _test_callback_for_sg_rules(self, event, op, sg_rule, sg_rule_id, sfc): + def test_callback_sg_rules_delete(self, sfc): + context = mock.Mock() + kwargs = { + 'context': context, + 'security_group_rule_id': FAKE_ID, + 'security_group_rules': odl_const.ODL_SG_RULES, + } self.sgh.sg_callback(resources.SECURITY_GROUP_RULE, - event, - None, - security_group_rule=sg_rule, - security_group_rule_id=sg_rule_id) - - expected_dict = ({resources.SECURITY_GROUP_RULE: sg_rule} - if sg_rule is not None else None) - sfc.assert_called_with( - op, callback._RESOURCE_MAPPING[resources.SECURITY_GROUP_RULE], - sg_rule_id, expected_dict) - - def test_callback_sg_rules_create(self): - self._test_callback_for_sg_rules( - events.AFTER_CREATE, odl_const.ODL_CREATE, mock.Mock(), None) - - def test_callback_sg_rules_delete(self): - self._test_callback_for_sg_rules( - events.AFTER_DELETE, odl_const.ODL_DELETE, None, FAKE_ID) + events.AFTER_DELETE, + "trigger", + **kwargs) + + sfc.assert_called_with(odl_const.ODL_DELETE, + 'security-group-rules', + FAKE_ID, None) diff --git a/networking-odl/networking_odl/tests/unit/common/test_lightweight_testing.py b/networking-odl/networking_odl/tests/unit/common/test_lightweight_testing.py index ea3b5a8..3fa63fa 100644 --- a/networking-odl/networking_odl/tests/unit/common/test_lightweight_testing.py +++ b/networking-odl/networking_odl/tests/unit/common/test_lightweight_testing.py @@ -152,7 +152,7 @@ class LightweightTestingTestCase(base.DietTestCase): self.assertEqual(lwt.NO_CONTENT, response.status_code) lwt_dict = lwt.OpenDaylightLwtClient.lwt_dict network = lwt_dict['networks'].get('fakeid1') - self.assertIsNone(network) + self.assertEqual(None, network) @mock.patch.dict(lwt.OpenDaylightLwtClient.lwt_dict, {'networks': {'fakeid1': {'id': 'fakeid1', @@ -169,6 +169,6 @@ class LightweightTestingTestCase(base.DietTestCase): self.assertEqual(lwt.NO_CONTENT, response.status_code) lwt_dict = lwt.OpenDaylightLwtClient.lwt_dict network = lwt_dict['networks'].get('fakeid1') - self.assertIsNone(network) + self.assertEqual(None, network) network = lwt_dict['networks'].get('fakeid2') - self.assertIsNone(network) + self.assertEqual(None, network) diff --git a/networking-odl/networking_odl/tests/unit/db/test_db.py b/networking-odl/networking_odl/tests/unit/db/test_db.py index 72749ad..9c03490 100644 --- a/networking-odl/networking_odl/tests/unit/db/test_db.py +++ b/networking-odl/networking_odl/tests/unit/db/test_db.py @@ -41,7 +41,6 @@ class DbTestCase(SqlTestCaseLight, TestCase): def _db_cleanup(self): self.db_session.query(models.OpendaylightJournal).delete() - self.db_session.query(models.OpendaylightMaintenance).delete() def _update_row(self, row): self.db_session.merge(row) @@ -162,33 +161,6 @@ class DbTestCase(SqlTestCaseLight, TestCase): self.assertEqual(2, update_mock.call_count) - def _test_delete_rows_by_state_and_time(self, last_retried, row_retention, - state, expected_rows): - db.create_pending_row(self.db_session, *self.UPDATE_ROW) - - # update state and last retried - row = db.get_all_db_rows(self.db_session)[0] - row.state = state - row.last_retried = row.last_retried - timedelta(seconds=last_retried) - self._update_row(row) - - db.delete_rows_by_state_and_time(self.db_session, - odl_const.COMPLETED, - timedelta(seconds=row_retention)) - - # validate the number of rows in the journal - rows = db.get_all_db_rows(self.db_session) - self.assertEqual(expected_rows, len(rows)) - - def test_delete_completed_rows_no_new_rows(self): - self._test_delete_rows_by_state_and_time(0, 10, odl_const.COMPLETED, 1) - - def test_delete_completed_rows_one_new_row(self): - self._test_delete_rows_by_state_and_time(6, 5, odl_const.COMPLETED, 0) - - def test_delete_completed_rows_wrong_state(self): - self._test_delete_rows_by_state_and_time(10, 8, odl_const.PENDING, 1) - def test_valid_retry_count(self): self._test_retry_count(1, 1, 1, odl_const.PENDING) @@ -206,38 +178,3 @@ class DbTestCase(SqlTestCaseLight, TestCase): def test_update_row_state_to_completed(self): self._test_update_row_state(odl_const.PROCESSING, odl_const.COMPLETED) - - def _test_maintenance_lock_unlock(self, db_func, existing_state, - expected_state, expected_result): - row = models.OpendaylightMaintenance(id='test', - state=existing_state) - self.db_session.add(row) - self.db_session.flush() - - self.assertEqual(expected_result, db_func(self.db_session)) - row = self.db_session.query(models.OpendaylightMaintenance).one() - self.assertEqual(expected_state, row['state']) - - def test_lock_maintenance(self): - self._test_maintenance_lock_unlock(db.lock_maintenance, - odl_const.PENDING, - odl_const.PROCESSING, - True) - - def test_lock_maintenance_fails_when_processing(self): - self._test_maintenance_lock_unlock(db.lock_maintenance, - odl_const.PROCESSING, - odl_const.PROCESSING, - False) - - def test_unlock_maintenance(self): - self._test_maintenance_lock_unlock(db.unlock_maintenance, - odl_const.PROCESSING, - odl_const.PENDING, - True) - - def test_unlock_maintenance_fails_when_pending(self): - self._test_maintenance_lock_unlock(db.unlock_maintenance, - odl_const.PENDING, - odl_const.PENDING, - False) diff --git a/networking-odl/networking_odl/tests/unit/journal/__init__.py b/networking-odl/networking_odl/tests/unit/journal/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/networking-odl/networking_odl/tests/unit/journal/__init__.py +++ /dev/null diff --git a/networking-odl/networking_odl/tests/unit/journal/test_dependency_validations.py b/networking-odl/networking_odl/tests/unit/journal/test_dependency_validations.py deleted file mode 100644 index 39a4b98..0000000 --- a/networking-odl/networking_odl/tests/unit/journal/test_dependency_validations.py +++ /dev/null @@ -1,44 +0,0 @@ -# -# Copyright (C) 2016 Intel Corp. Isaku Yamahata <isaku.yamahata@gmail com> -# 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 neutron.tests import base - -from networking_odl.journal import dependency_validations - - -class DependencyValidationsTestCase(base.DietTestCase): - _RESOURCE_DUMMY = 'test_type' - - def setUp(self): - super(DependencyValidationsTestCase, self).setUp() - mock_validation_map = mock.patch.dict( - dependency_validations._VALIDATION_MAP) - mock_validation_map.start() - self.addCleanup(mock_validation_map.stop) - - def test_register_validator(self): - mock_session = mock.Mock() - mock_validator = mock.Mock(return_value=False) - mock_row = mock.Mock() - mock_row.object_type = self._RESOURCE_DUMMY - dependency_validations.register_validator(self._RESOURCE_DUMMY, - mock_validator) - valid = dependency_validations.validate(mock_session, mock_row) - mock_validator.assert_called_once_with(mock_session, mock_row) - self.assertFalse(valid) diff --git a/networking-odl/networking_odl/tests/unit/journal/test_full_sync.py b/networking-odl/networking_odl/tests/unit/journal/test_full_sync.py deleted file mode 100644 index cedccbd..0000000 --- a/networking-odl/networking_odl/tests/unit/journal/test_full_sync.py +++ /dev/null @@ -1,152 +0,0 @@ -# -# Copyright (C) 2016 Red Hat, Inc. -# -# 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 -import requests - -from neutron.db import api as neutron_db_api -from neutron import manager -from neutron.tests.unit.testlib_api import SqlTestCaseLight - -from networking_odl.common import constants as odl_const -from networking_odl.db import db -from networking_odl.db import models -from networking_odl.journal import full_sync - - -class FullSyncTestCase(SqlTestCaseLight): - def setUp(self): - super(FullSyncTestCase, self).setUp() - self.db_session = neutron_db_api.get_session() - - full_sync._CLIENT = mock.MagicMock() - self.plugin_mock = mock.patch.object(manager.NeutronManager, - 'get_plugin').start() - self.l3_plugin_mock = mock.patch.object(manager.NeutronManager, - 'get_service_plugins').start() - - self.addCleanup(self._db_cleanup) - - def _db_cleanup(self): - self.db_session.query(models.OpendaylightJournal).delete() - - def test_no_full_sync_when_canary_exists(self): - full_sync.full_sync(self.db_session) - self.assertEqual([], db.get_all_db_rows(self.db_session)) - - def _mock_l2_resources(self): - expected_journal = {odl_const.ODL_NETWORK: '1', - odl_const.ODL_SUBNET: '2', - odl_const.ODL_PORT: '3'} - plugin_instance = self.plugin_mock.return_value - plugin_instance.get_networks.return_value = [ - {'id': expected_journal[odl_const.ODL_NETWORK]}] - plugin_instance.get_subnets.return_value = [ - {'id': expected_journal[odl_const.ODL_SUBNET]}] - plugin_instance.get_ports.side_effect = ([ - {'id': expected_journal[odl_const.ODL_PORT]}], []) - return expected_journal - - def _filter_out_canary(self, rows): - return [row for row in rows if row['object_uuid'] != - full_sync._CANARY_NETWORK_ID] - - def _test_no_full_sync_when_canary_in_journal(self, state): - self._mock_canary_missing() - self._mock_l2_resources() - db.create_pending_row(self.db_session, odl_const.ODL_NETWORK, - full_sync._CANARY_NETWORK_ID, - odl_const.ODL_CREATE, {}) - row = db.get_all_db_rows(self.db_session)[0] - db.update_db_row_state(self.db_session, row, state) - - full_sync.full_sync(self.db_session) - - rows = db.get_all_db_rows(self.db_session) - self.assertEqual([], self._filter_out_canary(rows)) - - def test_no_full_sync_when_canary_pending_creation(self): - self._test_no_full_sync_when_canary_in_journal(odl_const.PENDING) - - def test_no_full_sync_when_canary_is_processing(self): - self._test_no_full_sync_when_canary_in_journal(odl_const.PROCESSING) - - def test_client_error_propagates(self): - class TestException(Exception): - def __init__(self): - pass - - full_sync._CLIENT.get.side_effect = TestException() - self.assertRaises(TestException, full_sync.full_sync, self.db_session) - - def _mock_canary_missing(self): - get_return = mock.MagicMock() - get_return.status_code = requests.codes.not_found - full_sync._CLIENT.get.return_value = get_return - - def _assert_canary_created(self): - rows = db.get_all_db_rows(self.db_session) - self.assertTrue(any(r['object_uuid'] == full_sync._CANARY_NETWORK_ID - for r in rows)) - return rows - - def _test_full_sync_resources(self, expected_journal): - self._mock_canary_missing() - - full_sync.full_sync(self.db_session) - - rows = self._assert_canary_created() - rows = self._filter_out_canary(rows) - self.assertItemsEqual(expected_journal.keys(), - [row['object_type'] for row in rows]) - for row in rows: - self.assertEqual(expected_journal[row['object_type']], - row['object_uuid']) - - def test_full_sync_removes_pending_rows(self): - db.create_pending_row(self.db_session, odl_const.ODL_NETWORK, "uuid", - odl_const.ODL_CREATE, {'foo': 'bar'}) - self._test_full_sync_resources({}) - - def test_full_sync_no_resources(self): - self._test_full_sync_resources({}) - - def test_full_sync_l2_resources(self): - self._test_full_sync_resources(self._mock_l2_resources()) - - def _mock_router_port(self, port_id): - router_port = {'id': port_id, - 'device_id': '1', - 'tenant_id': '1', - 'fixed_ips': [{'subnet_id': '1'}]} - plugin_instance = self.plugin_mock.return_value - plugin_instance.get_ports.side_effect = ([], [router_port]) - - def _mock_l3_resources(self): - expected_journal = {odl_const.ODL_ROUTER: '1', - odl_const.ODL_FLOATINGIP: '2', - odl_const.ODL_ROUTER_INTF: '3'} - plugin_instance = self.l3_plugin_mock.return_value.get.return_value - plugin_instance.get_routers.return_value = [ - {'id': expected_journal[odl_const.ODL_ROUTER]}] - plugin_instance.get_floatingips.return_value = [ - {'id': expected_journal[odl_const.ODL_FLOATINGIP]}] - self._mock_router_port(expected_journal[odl_const.ODL_ROUTER_INTF]) - - return expected_journal - - def test_full_sync_l3_resources(self): - self._test_full_sync_resources(self._mock_l3_resources()) diff --git a/networking-odl/networking_odl/tests/unit/journal/test_maintenance.py b/networking-odl/networking_odl/tests/unit/journal/test_maintenance.py deleted file mode 100644 index eb823cd..0000000 --- a/networking-odl/networking_odl/tests/unit/journal/test_maintenance.py +++ /dev/null @@ -1,93 +0,0 @@ -# -# Copyright (C) 2016 Red Hat, Inc. -# -# 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 -import threading -from unittest2.case import TestCase - -from neutron.db import api as neutron_db_api -from neutron.tests.unit.testlib_api import SqlTestCaseLight - -from networking_odl.common import constants as odl_const -from networking_odl.db import models -from networking_odl.journal import maintenance - - -class MaintenanceThreadTestCase(SqlTestCaseLight, TestCase): - def setUp(self): - super(MaintenanceThreadTestCase, self).setUp() - self.db_session = neutron_db_api.get_session() - - row = models.OpendaylightMaintenance(state=odl_const.PENDING) - self.db_session.add(row) - self.db_session.flush() - - self.thread = maintenance.MaintenanceThread() - self.thread.maintenance_interval = 0.01 - - def test__execute_op_no_exception(self): - with mock.patch.object(maintenance, 'LOG') as mock_log: - operation = mock.MagicMock() - operation.__name__ = "test" - self.thread._execute_op(operation, self.db_session) - self.assertTrue(operation.called) - self.assertTrue(mock_log.info.called) - self.assertFalse(mock_log.exception.called) - - def test__execute_op_with_exception(self): - with mock.patch.object(maintenance, 'LOG') as mock_log: - operation = mock.MagicMock(side_effect=Exception()) - operation.__name__ = "test" - self.thread._execute_op(operation, self.db_session) - self.assertTrue(mock_log.exception.called) - - def test_thread_works(self): - callback_event = threading.Event() - count = [0] - - def callback_op(**kwargs): - count[0] += 1 - - # The following should be true on the second call, so we're making - # sure that the thread runs more than once. - if count[0] > 1: - callback_event.set() - - self.thread.register_operation(callback_op) - self.thread.start() - - # Make sure the callback event was called and not timed out - self.assertTrue(callback_event.wait(timeout=5)) - - def test_thread_continues_after_exception(self): - exception_event = threading.Event() - callback_event = threading.Event() - - def exception_op(**kwargs): - if not exception_event.is_set(): - exception_event.set() - raise Exception() - - def callback_op(**kwargs): - callback_event.set() - - for op in [exception_op, callback_op]: - self.thread.register_operation(op) - - self.thread.start() - - # Make sure the callback event was called and not timed out - self.assertTrue(callback_event.wait(timeout=5)) diff --git a/networking-odl/networking_odl/tests/unit/l3/test_l3_odl.py b/networking-odl/networking_odl/tests/unit/l3/test_l3_odl.py index 232864d..77a874f 100644 --- a/networking-odl/networking_odl/tests/unit/l3/test_l3_odl.py +++ b/networking-odl/networking_odl/tests/unit/l3/test_l3_odl.py @@ -22,7 +22,6 @@ import copy import mock from neutron.extensions import l3 -from neutron.extensions import l3_ext_gw_mode from neutron.tests.unit.api.v2 import test_base from neutron.tests.unit.extensions import base as test_extensions_base from webob import exc @@ -36,15 +35,11 @@ class Testodll3(test_extensions_base.ExtensionTestCase): def setUp(self): super(Testodll3, self).setUp() - # support ext-gw-mode - for key in l3.RESOURCE_ATTRIBUTE_MAP.keys(): - l3.RESOURCE_ATTRIBUTE_MAP[key].update( - l3_ext_gw_mode.EXTENDED_ATTRIBUTES_2_0.get(key, {})) self._setUpExtension( 'neutron.extensions.l3.RouterPluginBase', None, l3.RESOURCE_ATTRIBUTE_MAP, l3.L3, '', allow_pagination=True, allow_sorting=True, - supported_extension_aliases=['router', 'ext-gw-mode'], + supported_extension_aliases=['router'], use_quota=True) @staticmethod @@ -116,13 +111,13 @@ class Testodll3(test_extensions_base.ExtensionTestCase): content_type='application/%s' % self.fmt) instance.create_router.assert_called_once_with(mock.ANY, router=router) - self.assertEqual(exc.HTTPCreated.code, res.status_int) + self.assertEqual(res.status_int, exc.HTTPCreated.code) res = self.deserialize(res) self.assertIn('router', res) router = res['router'] - self.assertEqual(router_id, router['id']) - self.assertEqual("ACTIVE", router['status']) - self.assertEqual(True, router['admin_state_up']) + self.assertEqual(router['id'], router_id) + self.assertEqual(router['status'], "ACTIVE") + self.assertEqual(router['admin_state_up'], True) def test_update_router(self): router_id, router = self._get_router_test() @@ -144,14 +139,14 @@ class Testodll3(test_extensions_base.ExtensionTestCase): instance.update_router.assert_called_once_with(mock.ANY, router_id, router=router_request) - self.assertEqual(exc.HTTPOk.code, res.status_int) + self.assertEqual(res.status_int, exc.HTTPOk.code) res = self.deserialize(res) self.assertIn('router', res) router = res['router'] - self.assertEqual(router_id, router['id']) - self.assertEqual("3c5bcddd-6af9-4e6b-9c3e-c153e521cab8", - router["external_gateway_info"]['network_id']) - self.assertEqual(True, router["external_gateway_info"]['enable_snat']) + self.assertEqual(router['id'], router_id) + self.assertEqual(router["external_gateway_info"]['network_id'], + "3c5bcddd-6af9-4e6b-9c3e-c153e521cab8") + self.assertEqual(router["external_gateway_info"]['enable_snat'], True) def test_delete_router(self): router_id, router = self._get_router_test() @@ -161,7 +156,7 @@ class Testodll3(test_extensions_base.ExtensionTestCase): res = self.api.delete(_get_path('routers', id=router_id, fmt=self.fmt)) instance.delete_router.assert_called_once_with(mock.ANY, router_id) - self.assertEqual(exc.HTTPNoContent.code, res.status_int) + self.assertEqual(res.status_int, exc.HTTPNoContent.code) def test_create_floating_ip(self): floating_ip_id, floating_ip = self._get_floating_ip_test() @@ -194,12 +189,12 @@ class Testodll3(test_extensions_base.ExtensionTestCase): assert_called_once_with(mock.ANY, floatingip=floating_ip_request) - self.assertEqual(exc.HTTPCreated.code, res.status_int) + self.assertEqual(res.status_int, exc.HTTPCreated.code) res = self.deserialize(res) self.assertIn('floatingip', res) floatingip = res['floatingip'] - self.assertEqual(floating_ip_id, floatingip['id']) - self.assertEqual("ACTIVE", floatingip['status']) + self.assertEqual(floatingip['id'], floating_ip_id) + self.assertEqual(floatingip['status'], "ACTIVE") def test_update_floating_ip(self): floating_ip_id, floating_ip = self._get_floating_ip_test() @@ -232,13 +227,13 @@ class Testodll3(test_extensions_base.ExtensionTestCase): floating_ip_id, floatingip=floating_ip_request) - self.assertEqual(exc.HTTPOk.code, res.status_int) + self.assertEqual(res.status_int, exc.HTTPOk.code) res = self.deserialize(res) self.assertIn('floatingip', res) floatingip = res['floatingip'] - self.assertEqual(floating_ip_id, floatingip['id']) - self.assertIsNone(floatingip['port_id']) - self.assertIsNone(floatingip['fixed_ip_address']) + self.assertEqual(floatingip['id'], floating_ip_id) + self.assertEqual(floatingip['port_id'], None) + self.assertEqual(floatingip['fixed_ip_address'], None) def test_delete_floating_ip(self): floating_ip_id, floating_ip = self._get_floating_ip_test() @@ -250,7 +245,7 @@ class Testodll3(test_extensions_base.ExtensionTestCase): instance.delete_floatingip.assert_called_once_with(mock.ANY, floating_ip_id) - self.assertEqual(exc.HTTPNoContent.code, res.status_int) + self.assertEqual(res.status_int, exc.HTTPNoContent.code) def test_add_router_interface(self): router_id, router = self._get_router_test() @@ -274,11 +269,11 @@ class Testodll3(test_extensions_base.ExtensionTestCase): router_id, interface_info) - self.assertEqual(exc.HTTPOk.code, res.status_int) + self.assertEqual(res.status_int, exc.HTTPOk.code) res = self.deserialize(res) - self.assertEqual(router_id, res['id']) - self.assertEqual("a2f1f29d-571b-4533-907f-5803ab96ead1", - res['subnet_id']) + self.assertEqual(res['id'], router_id) + self.assertEqual(res['subnet_id'], + "a2f1f29d-571b-4533-907f-5803ab96ead1") def test_remove_router_interface(self): router_id, router = self._get_router_test() @@ -303,8 +298,8 @@ class Testodll3(test_extensions_base.ExtensionTestCase): router_id, interface_info) - self.assertEqual(exc.HTTPOk.code, res.status_int) + self.assertEqual(res.status_int, exc.HTTPOk.code) res = self.deserialize(res) - self.assertEqual(router_id, res['id']) - self.assertEqual("a2f1f29d-571b-4533-907f-5803ab96ead1", - res['subnet_id']) + self.assertEqual(res['id'], router_id) + self.assertEqual(res['subnet_id'], + "a2f1f29d-571b-4533-907f-5803ab96ead1") diff --git a/networking-odl/networking_odl/tests/unit/l3/test_l3_odl_v2.py b/networking-odl/networking_odl/tests/unit/l3/test_l3_odl_v2.py index da3f644..4f9061a 100644..100755 --- a/networking-odl/networking_odl/tests/unit/l3/test_l3_odl_v2.py +++ b/networking-odl/networking_odl/tests/unit/l3/test_l3_odl_v2.py @@ -78,7 +78,10 @@ class DataMatcher(object): def __init__(self, operation, object_type, object_dict): self._data = object_dict.copy() self._object_type = object_type - filters.filter_for_odl(object_type, operation, self._data) + filter_cls = filters.FILTER_MAP[object_type] + attr_filter = getattr(filter_cls, + 'filter_' + operation + '_attributes') + attr_filter(self._data) def __eq__(self, s): data = jsonutils.loads(s) @@ -87,9 +90,6 @@ class DataMatcher(object): else: return self._data == data[self._object_type] - def __ne__(self, s): - return not self.__eq__(s) - class OpenDaylightL3TestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase, base.BaseTestCase): diff --git a/networking-odl/networking_odl/tests/unit/ml2/config-ovs-external_ids.sh b/networking-odl/networking_odl/tests/unit/ml2/config-ovs-external_ids.sh deleted file mode 100755 index 15f9b93..0000000 --- a/networking-odl/networking_odl/tests/unit/ml2/config-ovs-external_ids.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/sh -# 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. - -uuid=$(sudo ovs-vsctl get Open_vSwitch . _uuid) - -# Test data -sudo ovs-vsctl set Open_vSwitch $uuid \ - external_ids:odl_os_hostconfig_hostid="devstack" - -# sudo ovs-vsctl set Open_vSwitch $uuid \ -# external_ids:odl_os_hostconfig_hosttype="ODL L2" - -config=$(cat <<____CONFIG -{"supported_vnic_types":[ - {"vnic_type":"normal","vif_type":"ovs","vif_details":{}}], - "allowed_network_types":["local","vlan","vxlan","gre"], - "bridge_mappings":{"physnet1":"br-ex"}} -____CONFIG -) - -echo config: $config - -sudo ovs-vsctl set Open_vSwitch $uuid \ - external_ids:odl_os_hostconfig_config_odl_l2="$config" diff --git a/networking-odl/networking_odl/tests/unit/ml2/odl_teststub.js b/networking-odl/networking_odl/tests/unit/ml2/odl_teststub.js deleted file mode 100644 index 1ee02d5..0000000 --- a/networking-odl/networking_odl/tests/unit/ml2/odl_teststub.js +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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. - * - * $nodejs odl_teststub.js - * - * local.conf or ml2_conf.ini should be set to the following: - * - * [ml2_odl] - * port_binding_controller = pseudo-agentdb-binding - * password = admin - * username = admin - * url = http://localhost:8080/controller/nb/v2/neutron - * restconf_uri = http://localhost:8125/ # for this stub - * - * To test with ODL *end to end* use below URL for restconf_uri and configure - * ovsdb external_ids using the test script: config-ovs-external_ids.sh - * - * http://localhost:8181/restconf/operational/neutron:neutron/hostconfigs - */ - -var http = require('http'); - -const PORT=8125; - -__test_odl_hconfig = {"hostconfigs": {"hostconfig": [ - {"host-id": "devstack", - "host-type": "ODL L2", - "config": { - "supported_vnic_types": [ - {"vnic_type": "normal", - "vif_type": "ovs", - "vif_details": {}}], - "allowed_network_types": ["local", "vlan", "vxlan", "gre"], - "bridge_mappings": {"physnet1":"br-ex"} - } - }] - }} - - -function handleRequest(req, res){ - res.setHeader('Content-Type', 'application/json'); - res.end(JSON.stringify(__test_odl_hconfig)); -} - -var server = http.createServer(handleRequest); - -server.listen(PORT, function(){ - console.log("Server listening on: http://localhost:%s", PORT); - }); diff --git a/networking-odl/networking_odl/tests/unit/ml2/test_driver.py b/networking-odl/networking_odl/tests/unit/ml2/test_driver.py index 661eb55..e2ceda5 100644 --- a/networking-odl/networking_odl/tests/unit/ml2/test_driver.py +++ b/networking-odl/networking_odl/tests/unit/ml2/test_driver.py @@ -32,55 +32,55 @@ class TestODLShim(test_plugin.Ml2PluginV2TestCase): def test_create_network_postcommit(self): self.driver.create_network_postcommit(self.context) - self.driver.odl_drv.synchronize.assert_called_with(const.ODL_CREATE, + self.driver.odl_drv.synchronize.assert_called_with('create', const.ODL_NETWORKS, self.context) def test_update_network_postcommit(self): self.driver.update_network_postcommit(self.context) - self.driver.odl_drv.synchronize.assert_called_with(const.ODL_UPDATE, + self.driver.odl_drv.synchronize.assert_called_with('update', const.ODL_NETWORKS, self.context) def test_delete_network_postcommit(self): self.driver.delete_network_postcommit(self.context) - self.driver.odl_drv.synchronize.assert_called_with(const.ODL_DELETE, + self.driver.odl_drv.synchronize.assert_called_with('delete', const.ODL_NETWORKS, self.context) def test_create_subnet_postcommit(self): self.driver.create_subnet_postcommit(self.context) - self.driver.odl_drv.synchronize.assert_called_with(const.ODL_CREATE, + self.driver.odl_drv.synchronize.assert_called_with('create', const.ODL_SUBNETS, self.context) def test_update_subnet_postcommit(self): self.driver.update_subnet_postcommit(self.context) - self.driver.odl_drv.synchronize.assert_called_with(const.ODL_UPDATE, + self.driver.odl_drv.synchronize.assert_called_with('update', const.ODL_SUBNETS, self.context) def test_delete_subnet_postcommit(self): self.driver.delete_subnet_postcommit(self.context) - self.driver.odl_drv.synchronize.assert_called_with(const.ODL_DELETE, + self.driver.odl_drv.synchronize.assert_called_with('delete', const.ODL_SUBNETS, self.context) def test_create_port_postcommit(self): self.driver.create_port_postcommit(self.context) - self.driver.odl_drv.synchronize.assert_called_with(const.ODL_CREATE, + self.driver.odl_drv.synchronize.assert_called_with('create', const.ODL_PORTS, self.context) def test_update_port_postcommit(self): self.driver.update_port_postcommit(self.context) - self.driver.odl_drv.synchronize.assert_called_with(const.ODL_UPDATE, + self.driver.odl_drv.synchronize.assert_called_with('update', const.ODL_PORTS, self.context) def test_delete_port_postcommit(self): self.driver.delete_port_postcommit(self.context) - self.driver.odl_drv.synchronize.assert_called_with(const.ODL_DELETE, + self.driver.odl_drv.synchronize.assert_called_with('delete', const.ODL_PORTS, self.context) diff --git a/networking-odl/networking_odl/tests/unit/ml2/test_legacy_port_binding.py b/networking-odl/networking_odl/tests/unit/ml2/test_legacy_port_binding.py index 932c961..8ebda22 100644 --- a/networking-odl/networking_odl/tests/unit/ml2/test_legacy_port_binding.py +++ b/networking-odl/networking_odl/tests/unit/ml2/test_legacy_port_binding.py @@ -15,11 +15,10 @@ import mock -from neutron.extensions import portbindings +from neutron.common import constants as n_constants from neutron.plugins.common import constants from neutron.plugins.ml2 import driver_api as api from neutron.plugins.ml2 import driver_context as ctx -from neutron_lib import constants as n_constants from networking_odl.ml2 import legacy_port_binding from networking_odl.tests import base @@ -74,16 +73,3 @@ class TestLegacyPortBindingManager(base.DietTestCase): port_context.set_binding.assert_called_once_with( self.valid_segment[api.ID], vif_type, mgr.vif_details, status=n_constants.PORT_STATUS_ACTIVE) - - def test_bind_port_unsupported_vnic_type(self): - network = mock.MagicMock(spec=api.NetworkContext) - port_context = mock.MagicMock( - spec=ctx.PortContext, - current={'id': 'CURRENT_CONTEXT_ID', - portbindings.VNIC_TYPE: portbindings.VNIC_DIRECT}, - segments_to_bind=[self.valid_segment, self.invalid_segment], - network=network) - - mgr = legacy_port_binding.LegacyPortBindingManager() - mgr.bind_port(port_context) - port_context.set_binding.assert_not_called() diff --git a/networking-odl/networking_odl/tests/unit/ml2/test_mechanism_odl.py b/networking-odl/networking_odl/tests/unit/ml2/test_mechanism_odl.py index 95de10c..a012085 100644 --- a/networking-odl/networking_odl/tests/unit/ml2/test_mechanism_odl.py +++ b/networking-odl/networking_odl/tests/unit/ml2/test_mechanism_odl.py @@ -23,7 +23,7 @@ from oslo_serialization import jsonutils import requests import webob.exc -from neutron.db import segments_db +from neutron.common import constants as n_constants from neutron.extensions import portbindings from neutron.plugins.common import constants from neutron.plugins.ml2 import config as config @@ -33,7 +33,6 @@ from neutron.plugins.ml2 import plugin from neutron.tests import base from neutron.tests.unit.plugins.ml2 import test_plugin from neutron.tests.unit import testlib_api -from neutron_lib import constants as n_constants from networking_odl.common import client from networking_odl.common import constants as odl_const @@ -208,6 +207,12 @@ class OpenDaylightMechanismTestPortsV2(test_plugin.TestMl2PortsV2, expected_status=webob.exc.HTTPConflict.code, expected_error='PortBound') + def test_create_router_port_and_fail_create_postcommit(self): + # Skip this test case for now as a workaround. + # TODO(rzang): remove this once [1] gets in. + # [1]https://review.openstack.org/#/c/310682/ + self.skipTest("skip as a workaround") + class DataMatcher(object): @@ -223,9 +228,6 @@ class DataMatcher(object): data = jsonutils.loads(s) return self._data == data[self._object_type] - def __ne__(self, s): - return not self.__eq__(s) - class OpenDaylightSyncTestCase(OpenDaylightTestCase): @@ -376,8 +378,7 @@ class OpenDaylightMechanismDriverTestCase(base.BaseTestCase): context = self._get_mock_operation_context(object_type) url = '%s/%ss' % (config.cfg.CONF.ml2_odl.url, object_type) kwargs = {'url': url, - 'data': DataMatcher(odl_const.ODL_CREATE, object_type, - context)} + 'data': DataMatcher('create', object_type, context)} self._test_single_operation(method, context, status_code, exc_class, 'post', **kwargs) @@ -388,8 +389,7 @@ class OpenDaylightMechanismDriverTestCase(base.BaseTestCase): url = '%s/%ss/%s' % (config.cfg.CONF.ml2_odl.url, object_type, context.current['id']) kwargs = {'url': url, - 'data': DataMatcher(odl_const.ODL_UPDATE, object_type, - context)} + 'data': DataMatcher('update', object_type, context)} self._test_single_operation(method, context, status_code, exc_class, 'put', **kwargs) @@ -401,20 +401,18 @@ class OpenDaylightMechanismDriverTestCase(base.BaseTestCase): context.current['id']) kwargs = {'url': url, 'data': None} self._test_single_operation(method, context, status_code, exc_class, - odl_const.ODL_DELETE, **kwargs) + 'delete', **kwargs) def test_create_network_postcommit(self): - self._test_create_resource_postcommit(odl_const.ODL_NETWORK, + self._test_create_resource_postcommit('network', requests.codes.created) for status_code in (requests.codes.bad_request, requests.codes.unauthorized): self._test_create_resource_postcommit( - odl_const.ODL_NETWORK, status_code, - requests.exceptions.HTTPError) + 'network', status_code, requests.exceptions.HTTPError) def test_create_subnet_postcommit(self): - self._test_create_resource_postcommit(odl_const.ODL_SUBNET, - requests.codes.created) + self._test_create_resource_postcommit('subnet', requests.codes.created) for status_code in (requests.codes.bad_request, requests.codes.unauthorized, requests.codes.forbidden, @@ -422,12 +420,10 @@ class OpenDaylightMechanismDriverTestCase(base.BaseTestCase): requests.codes.conflict, requests.codes.not_implemented): self._test_create_resource_postcommit( - odl_const.ODL_SUBNET, status_code, - requests.exceptions.HTTPError) + 'subnet', status_code, requests.exceptions.HTTPError) def test_create_port_postcommit(self): - self._test_create_resource_postcommit(odl_const.ODL_PORT, - requests.codes.created) + self._test_create_resource_postcommit('port', requests.codes.created) for status_code in (requests.codes.bad_request, requests.codes.unauthorized, requests.codes.forbidden, @@ -436,34 +432,28 @@ class OpenDaylightMechanismDriverTestCase(base.BaseTestCase): requests.codes.not_implemented, requests.codes.service_unavailable): self._test_create_resource_postcommit( - odl_const.ODL_PORT, status_code, - requests.exceptions.HTTPError) + 'port', status_code, requests.exceptions.HTTPError) def test_update_network_postcommit(self): - self._test_update_resource_postcommit(odl_const.ODL_NETWORK, - requests.codes.ok) + self._test_update_resource_postcommit('network', requests.codes.ok) for status_code in (requests.codes.bad_request, requests.codes.forbidden, requests.codes.not_found): self._test_update_resource_postcommit( - odl_const.ODL_NETWORK, status_code, - requests.exceptions.HTTPError) + 'network', status_code, requests.exceptions.HTTPError) def test_update_subnet_postcommit(self): - self._test_update_resource_postcommit(odl_const.ODL_SUBNET, - requests.codes.ok) + self._test_update_resource_postcommit('subnet', requests.codes.ok) for status_code in (requests.codes.bad_request, requests.codes.unauthorized, requests.codes.forbidden, requests.codes.not_found, requests.codes.not_implemented): self._test_update_resource_postcommit( - odl_const.ODL_SUBNET, status_code, - requests.exceptions.HTTPError) + 'subnet', status_code, requests.exceptions.HTTPError) def test_update_port_postcommit(self): - self._test_update_resource_postcommit(odl_const.ODL_PORT, - requests.codes.ok) + self._test_update_resource_postcommit('port', requests.codes.ok) for status_code in (requests.codes.bad_request, requests.codes.unauthorized, requests.codes.forbidden, @@ -471,55 +461,50 @@ class OpenDaylightMechanismDriverTestCase(base.BaseTestCase): requests.codes.conflict, requests.codes.not_implemented): self._test_update_resource_postcommit( - odl_const.ODL_PORT, status_code, - requests.exceptions.HTTPError) + 'port', status_code, requests.exceptions.HTTPError) def test_delete_network_postcommit(self): - self._test_delete_resource_postcommit(odl_const.ODL_NETWORK, + self._test_delete_resource_postcommit('network', requests.codes.no_content) - self._test_delete_resource_postcommit(odl_const.ODL_NETWORK, + self._test_delete_resource_postcommit('network', requests.codes.not_found) for status_code in (requests.codes.unauthorized, requests.codes.conflict): self._test_delete_resource_postcommit( - odl_const.ODL_NETWORK, status_code, - requests.exceptions.HTTPError) + 'network', status_code, requests.exceptions.HTTPError) def test_delete_subnet_postcommit(self): - self._test_delete_resource_postcommit(odl_const.ODL_SUBNET, + self._test_delete_resource_postcommit('subnet', requests.codes.no_content) - self._test_delete_resource_postcommit(odl_const.ODL_SUBNET, + self._test_delete_resource_postcommit('subnet', requests.codes.not_found) for status_code in (requests.codes.unauthorized, requests.codes.conflict, requests.codes.not_implemented): self._test_delete_resource_postcommit( - odl_const.ODL_SUBNET, status_code, - requests.exceptions.HTTPError) + 'subnet', status_code, requests.exceptions.HTTPError) def test_delete_port_postcommit(self): - self._test_delete_resource_postcommit(odl_const.ODL_PORT, + self._test_delete_resource_postcommit('port', requests.codes.no_content) - self._test_delete_resource_postcommit(odl_const.ODL_PORT, + self._test_delete_resource_postcommit('port', requests.codes.not_found) for status_code in (requests.codes.unauthorized, requests.codes.forbidden, requests.codes.not_implemented): self._test_delete_resource_postcommit( - odl_const.ODL_PORT, status_code, - requests.exceptions.HTTPError) + 'port', status_code, requests.exceptions.HTTPError) def test_port_emtpy_tenant_id_work_around(self): """Validate the work around code of port creation""" plugin = mock.Mock() plugin_context = mock.Mock() - network = self._get_mock_operation_context( - odl_const.ODL_NETWORK).current - port = self._get_mock_operation_context(odl_const.ODL_PORT).current + network = self._get_mock_operation_context('network').current + port = self._get_mock_operation_context('port').current tenant_id = network['tenant_id'] port['tenant_id'] = '' - with mock.patch.object(segments_db, 'get_network_segments'): + with mock.patch.object(driver_context.db, 'get_network_segments'): context = driver_context.PortContext( plugin, plugin_context, port, network, {}, 0, None) self.mech.odl_drv.FILTER_MAP[ @@ -530,16 +515,15 @@ class OpenDaylightMechanismDriverTestCase(base.BaseTestCase): """Validate the filter code on update port operation""" items_to_filter = ['network_id', 'id', 'status', 'tenant_id'] plugin_context = mock.Mock() - network = self._get_mock_operation_context( - odl_const.ODL_NETWORK).current - subnet = self._get_mock_operation_context(odl_const.ODL_SUBNET).current - port = self._get_mock_operation_context(odl_const.ODL_PORT).current + network = self._get_mock_operation_context('network').current + subnet = self._get_mock_operation_context('subnet').current + port = self._get_mock_operation_context('port').current port['fixed_ips'] = [{'subnet_id': subnet['id'], 'ip_address': '10.0.0.10'}] port['mac_address'] = port['mac_address'].upper() orig_port = copy.deepcopy(port) - with mock.patch.object(segments_db, 'get_network_segments'): + with mock.patch.object(driver_context.db, 'get_network_segments'): context = driver_context.PortContext( plugin, plugin_context, port, network, {}, 0, None) self.mech.odl_drv.FILTER_MAP[ diff --git a/networking-odl/networking_odl/tests/unit/ml2/test_mechanism_odl_v2.py b/networking-odl/networking_odl/tests/unit/ml2/test_mechanism_odl_v2.py index 7e8c7fc..08cf653 100644 --- a/networking-odl/networking_odl/tests/unit/ml2/test_mechanism_odl_v2.py +++ b/networking-odl/networking_odl/tests/unit/ml2/test_mechanism_odl_v2.py @@ -12,14 +12,12 @@ # 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 datetime +from datetime import timedelta -from networking_odl.common import callback from networking_odl.common import client from networking_odl.common import constants as odl_const from networking_odl.common import filters from networking_odl.db import db -from networking_odl.journal import cleanup from networking_odl.journal import journal from networking_odl.ml2 import mech_driver_v2 @@ -29,7 +27,6 @@ from oslo_serialization import jsonutils import requests from neutron.db import api as neutron_db_api -from neutron import manager from neutron.plugins.ml2 import config as config from neutron.plugins.ml2 import plugin from neutron.tests.unit.plugins.ml2 import test_plugin @@ -37,6 +34,8 @@ from neutron.tests.unit import testlib_api cfg.CONF.import_group('ml2_odl', 'networking_odl.common.config') +HOST = 'fake-host' +PLUGIN_NAME = 'neutron.plugins.ml2.plugin.Ml2Plugin' SECURITY_GROUP = '2f9244b4-9bee-4e81-bc4a-3f3c2045b3d7' SG_FAKE_ID = 'sg_fake_uuid' SG_RULE_FAKE_ID = 'sg_rule_fake_uuid' @@ -124,21 +123,14 @@ class DataMatcher(object): else: self._data = context.current.copy() self._object_type = object_type - filters.filter_for_odl(object_type, operation, self._data) + filter_cls = filters.FILTER_MAP[object_type] + attr_filter = getattr(filter_cls, 'filter_%s_attributes' % operation) + attr_filter(self._data) def __eq__(self, s): data = jsonutils.loads(s) return self._data == data[self._object_type] - def __ne__(self, s): - return not self.__eq__(s) - - -class AttributeDict(dict): - def __init__(self, *args, **kwargs): - super(AttributeDict, self).__init__(*args, **kwargs) - self.__dict__ = self - class OpenDaylightMechanismDriverTestCase(OpenDaylightConfigBase): def setUp(self): @@ -209,19 +201,15 @@ class OpenDaylightMechanismDriverTestCase(OpenDaylightConfigBase): 'binding:vnic_type': 'normal', 'binding:vif_type': 'unbound', 'mac_address': '12:34:56:78:21:b6'} - _network = OpenDaylightMechanismDriverTestCase.\ - _get_mock_network_operation_context().current - _plugin = manager.NeutronManager.get_plugin() - _plugin.get_security_group = mock.Mock(return_value=SECURITY_GROUP) - _plugin.get_port = mock.Mock(return_value=current) - _plugin.get_network = mock.Mock(return_value=_network) - _plugin_context_mock = {'session': neutron_db_api.get_session()} - _network_context_mock = {'_network': _network} - context = {'current': AttributeDict(current), - '_plugin': _plugin, - '_plugin_context': AttributeDict(_plugin_context_mock), - '_network_context': AttributeDict(_network_context_mock)} - return AttributeDict(context) + context = mock.Mock(current=current) + context._plugin.get_security_group = mock.Mock( + return_value=SECURITY_GROUP) + context._plugin.get_port = mock.Mock(return_value=current) + context._plugin_context.session = neutron_db_api.get_session() + context._network_context = mock.Mock( + _network=OpenDaylightMechanismDriverTestCase. + _get_mock_network_operation_context().current) + return context @staticmethod def _get_mock_security_group_operation_context(): @@ -285,9 +273,7 @@ class OpenDaylightMechanismDriverTestCase(OpenDaylightConfigBase): context = self._get_mock_operation_context(object_type) if object_type in [odl_const.ODL_SG, odl_const.ODL_SG_RULE]: - res_type = [rt for rt in callback._RESOURCE_MAPPING.values() - if rt.singular == object_type][0] - self.mech.sync_from_callback(operation, res_type, + self.mech.sync_from_callback(operation, object_type + 's', context[object_type]['id'], context) else: method = getattr(self.mech, '%s_%s_precommit' % (operation, @@ -413,26 +399,6 @@ class OpenDaylightMechanismDriverTestCase(OpenDaylightConfigBase): self._test_object_operation_pending_another_object_operation( parent, odl_const.ODL_DELETE, child, odl_const.ODL_DELETE) - def _test_cleanup_processing_rows(self, last_retried, expected_state): - # Create a dummy network (creates db row in pending state). - self._call_operation_object(odl_const.ODL_CREATE, - odl_const.ODL_NETWORK) - - # Get pending row and mark as processing and update - # the last_retried time - row = db.get_all_db_rows_by_state(self.db_session, - odl_const.PENDING)[0] - row.last_retried = last_retried - db.update_db_row_state(self.db_session, row, odl_const.PROCESSING) - - # Test if the cleanup marks this in the desired state - # based on the last_retried timestamp - cleanup.JournalCleanup().cleanup_processing_rows(self.db_session) - - # Verify that the Db row is in the desired state - rows = db.get_all_db_rows_by_state(self.db_session, expected_state) - self.assertEqual(1, len(rows)) - def test_driver(self): for operation in [odl_const.ODL_CREATE, odl_const.ODL_UPDATE, odl_const.ODL_DELETE]: @@ -440,20 +406,6 @@ class OpenDaylightMechanismDriverTestCase(OpenDaylightConfigBase): odl_const.ODL_PORT]: self._test_operation_object(operation, object_type) - def test_port_precommit_no_tenant(self): - context = self._get_mock_operation_context(odl_const.ODL_PORT) - context.current['tenant_id'] = '' - - method = getattr(self.mech, 'create_port_precommit') - method(context) - - # Verify that the Db row has a tenant - rows = db.get_all_db_rows_by_state(self.db_session, odl_const.PENDING) - self.assertEqual(1, len(rows)) - _network = OpenDaylightMechanismDriverTestCase.\ - _get_mock_network_operation_context().current - self.assertEqual(_network['tenant_id'], rows[0]['data']['tenant_id']) - def test_network(self): self._test_object_type(odl_const.ODL_NETWORK) @@ -523,14 +475,6 @@ class OpenDaylightMechanismDriverTestCase(OpenDaylightConfigBase): def test_port_processing_network(self): self._test_object_type_processing_network(odl_const.ODL_PORT) - def test_cleanup_processing_rows_time_not_expired(self): - self._test_cleanup_processing_rows(datetime.datetime.utcnow(), - odl_const.PROCESSING) - - def test_cleanup_processing_rows_time_expired(self): - old_time = datetime.datetime.utcnow() - datetime.timedelta(hours=24) - self._test_cleanup_processing_rows(old_time, odl_const.PENDING) - def test_thread_call(self): """Verify that the sync thread method is called.""" @@ -549,7 +493,7 @@ class OpenDaylightMechanismDriverTestCase(OpenDaylightConfigBase): self._test_object_type(odl_const.ODL_SG_RULE) def _decrease_row_created_time(self, row): - row.created_at -= datetime.timedelta(hours=1) + row.created_at -= timedelta(hours=1) self.db_session.merge(row) self.db_session.flush() diff --git a/networking-odl/networking_odl/tests/unit/ml2/test_networking_topology.py b/networking-odl/networking_odl/tests/unit/ml2/test_networking_topology.py index fb83a7b..d342dde 100644 --- a/networking-odl/networking_odl/tests/unit/ml2/test_networking_topology.py +++ b/networking-odl/networking_odl/tests/unit/ml2/test_networking_topology.py @@ -21,11 +21,11 @@ from oslo_log import log from oslo_serialization import jsonutils import requests +from neutron.common import constants as n_constants from neutron.extensions import portbindings from neutron.plugins.common import constants from neutron.plugins.ml2 import driver_api from neutron.plugins.ml2 import driver_context -from neutron_lib import constants as n_constants from networking_odl.common import cache from networking_odl.ml2 import mech_driver diff --git a/networking-odl/networking_odl/tests/unit/ml2/test_ovsdb_topology.py b/networking-odl/networking_odl/tests/unit/ml2/test_ovsdb_topology.py index 228154d..5502e5a 100644 --- a/networking-odl/networking_odl/tests/unit/ml2/test_ovsdb_topology.py +++ b/networking-odl/networking_odl/tests/unit/ml2/test_ovsdb_topology.py @@ -19,11 +19,11 @@ import mock from oslo_log import log from oslo_serialization import jsonutils +from neutron.common import constants as n_constants from neutron.extensions import portbindings from neutron.plugins.common import constants from neutron.plugins.ml2 import driver_api from neutron.plugins.ml2 import driver_context -from neutron_lib import constants as n_constants from networking_odl.ml2 import ovsdb_topology from networking_odl.tests import base diff --git a/networking-odl/networking_odl/tests/unit/ml2/test_pseudo_agentdb_binding.py b/networking-odl/networking_odl/tests/unit/ml2/test_pseudo_agentdb_binding.py deleted file mode 100644 index d69150c..0000000 --- a/networking-odl/networking_odl/tests/unit/ml2/test_pseudo_agentdb_binding.py +++ /dev/null @@ -1,334 +0,0 @@ -# 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. - -from copy import deepcopy -import mock -from os import path as os_path -from string import Template - -from neutron.extensions import portbindings -from neutron.plugins.common import constants -from neutron.plugins.ml2 import config -from neutron.plugins.ml2 import driver_api as api -from neutron.plugins.ml2 import driver_context as ctx -from neutron_lib import constants as n_const - -from networking_odl.ml2 import pseudo_agentdb_binding -from networking_odl.tests import base - -AGENTDB_BINARY = 'neutron-odlagent-portbinding' -L2_TYPE = "ODL L2" - - -class TestPseudoAgentDBBindingController(base.DietTestCase): - """Test class for AgentDBPortBinding.""" - - # test data hostconfig and hostconfig-dbget - sample_odl_hconfigs = {"hostconfigs": {"hostconfig": [ - {"host-id": "devstack", - "host-type": "ODL L2", - "config": """{"supported_vnic_types": [ - {"vnic_type": "normal", "vif_type": "ovs", - "vif_details": {}}], - "allowed_network_types": [ - "local", "vlan", "vxlan", "gre"], - "bridge_mappings": {"physnet1": "br-ex"}}"""} - ]}} - - # Test data for string interpolation of substitutable identifers - # e.g. $PORT_ID identifier in the configurations JSON string below shall - # be substituted with portcontext.current['id'] eliminating the check - # for specific vif_type making port-binding truly switch agnostic. - # Refer: Python string templates and interpolation (string.Template) - sample_hconf_str_tmpl_subs_vpp = { - "host": "devstack", # host-id in ODL JSON - "agent_type": "ODL L2", # host-type in ODL JSON - # config in ODL JSON - "configurations": """{"supported_vnic_types": [ - {"vnic_type": "normal", "vif_type": "vhostuser", - "vif_details": { - "uuid": "TEST_UUID", - "has_datapath_type_netdev": true, - "support_vhost_user": true, - "port_prefix": "socket_", - "vhostuser_socket_dir": "/tmp", - "vhostuser_ovs_plug": true, - "vhostuser_mode": "server", - "vhostuser_socket": - "/tmp/socket_$PORT_ID" - }}], - "allowed_network_types": [ - "local", "vlan", "vxlan", "gre"], - "bridge_mappings": {"physnet1": "br-ex"}}""" - } - - sample_hconf_str_tmpl_subs_ovs = { - "host": "devstack", # host-id in ODL JSON - "agent_type": "ODL L2", # host-type in ODL JSON - # config in ODL JSON - "configurations": """{"supported_vnic_types": [ - {"vnic_type": "normal", "vif_type": "vhostuser", - "vif_details": { - "uuid": "TEST_UUID", - "has_datapath_type_netdev": true, - "support_vhost_user": true, - "port_prefix": "vhu_", - "vhostuser_socket_dir": "/var/run/openvswitch", - "vhostuser_ovs_plug": true, - "vhostuser_mode": "client", - "vhostuser_socket": - "/var/run/openvswitch/vhu_$PORT_ID" - }}], - "allowed_network_types": [ - "local", "vlan", "vxlan", "gre"], - "bridge_mappings": {"physnet1": "br-ex"}}""" - } - - sample_hconf_str_tmpl_nosubs = { - "host": "devstack", # host-id in ODL JSON - "agent_type": "ODL L2", # host-type in ODL JSON - # config in ODL JSON - "configurations": """{"supported_vnic_types": [ - {"vnic_type": "normal", "vif_type": "ovs", - "vif_details": { - "uuid": "TEST_UUID", - "has_datapath_type_netdev": true, - "support_vhost_user": true, - "port_prefix": "socket_", - "vhostuser_socket_dir": "/tmp", - "vhostuser_ovs_plug": true, - "vhostuser_mode": "server", - "vhostuser_socket": - "/var/run/openvswitch/PORT_NOSUBS" - }}], - "allowed_network_types": [ - "local", "vlan", "vxlan", "gre"], - "bridge_mappings": {"physnet1": "br-ex"}}""" - } - - # Test data for vanilla OVS - sample_hconfig_dbget_ovs = {"configurations": {"supported_vnic_types": [ - {"vnic_type": "normal", "vif_type": portbindings.VIF_TYPE_OVS, - "vif_details": { - "some_test_details": None - }}], - "allowed_network_types": ["local", "vlan", "vxlan", "gre"], - "bridge_mappings": {"physnet1": "br-ex"}}} - - # Test data for OVS-DPDK - sample_hconfig_dbget_ovs_dpdk = {"configurations": { - "supported_vnic_types": [{ - "vnic_type": "normal", - "vif_type": portbindings.VIF_TYPE_VHOST_USER, - "vif_details": { - "uuid": "TEST_UUID", - "has_datapath_type_netdev": True, - "support_vhost_user": True, - "port_prefix": "vhu_", - # Assumption: /var/run mounted as tmpfs - "vhostuser_socket_dir": "/var/run/openvswitch", - "vhostuser_ovs_plug": True, - "vhostuser_mode": "client", - "vhostuser_socket": "/var/run/openvswitch/vhu_$PORT_ID"}}], - "allowed_network_types": ["local", "vlan", "vxlan", "gre"], - "bridge_mappings": {"physnet1": "br-ex"}}} - - # Test data for VPP - sample_hconfig_dbget_vpp = {"configurations": {"supported_vnic_types": [ - {"vnic_type": "normal", "vif_type": portbindings.VIF_TYPE_VHOST_USER, - "vif_details": { - "uuid": "TEST_UUID", - "has_datapath_type_netdev": True, - "support_vhost_user": True, - "port_prefix": "socket_", - "vhostuser_socket_dir": "/tmp", - "vhostuser_ovs_plug": True, - "vhostuser_mode": "server", - "vhostuser_socket": "/tmp/socket_$PORT_ID" - }}], - "allowed_network_types": ["local", "vlan", "vxlan", "gre"], - "bridge_mappings": {"physnet1": "br-ex"}}} - - # test data valid and invalid segments - test_valid_segment = { - api.ID: 'API_ID', - api.NETWORK_TYPE: constants.TYPE_LOCAL, - api.SEGMENTATION_ID: 'API_SEGMENTATION_ID', - api.PHYSICAL_NETWORK: 'API_PHYSICAL_NETWORK'} - - test_invalid_segment = { - api.ID: 'API_ID', - api.NETWORK_TYPE: constants.TYPE_NONE, - api.SEGMENTATION_ID: 'API_SEGMENTATION_ID', - api.PHYSICAL_NETWORK: 'API_PHYSICAL_NETWORK'} - - def setUp(self): - """Setup test.""" - super(TestPseudoAgentDBBindingController, self).setUp() - - config.cfg.CONF.set_override('url', - 'http://localhost:8080' - '/controller/nb/v2/neutron', 'ml2_odl') - - fake_agents_db = mock.MagicMock() - fake_agents_db.create_or_update_agent = mock.MagicMock() - - self.mgr = pseudo_agentdb_binding.PseudoAgentDBBindingController( - db_plugin=fake_agents_db) - - def test_make_hostconf_uri(self): - """test make uri.""" - test_path = '/restconf/neutron:neutron/hostconfigs' - expected = "http://localhost:8080/restconf/neutron:neutron/hostconfigs" - test_uri = self.mgr._make_hostconf_uri(path=test_path) - - self.assertEqual(expected, test_uri) - - def test_update_agents_db(self): - """test agent update.""" - self.mgr._update_agents_db( - hostconfigs=self.sample_odl_hconfigs['hostconfigs']['hostconfig']) - self.mgr.agents_db.create_or_update_agent.assert_called_once() - - def test_is_valid_segment(self): - """Validate the _check_segment method.""" - all_network_types = [constants.TYPE_FLAT, constants.TYPE_GRE, - constants.TYPE_LOCAL, constants.TYPE_VXLAN, - constants.TYPE_VLAN, constants.TYPE_NONE] - - valid_types = { - network_type - for network_type in all_network_types - if self.mgr._is_valid_segment({api.NETWORK_TYPE: network_type}, { - 'allowed_network_types': [ - constants.TYPE_LOCAL, constants.TYPE_GRE, - constants.TYPE_VXLAN, constants.TYPE_VLAN]})} - - self.assertEqual({ - constants.TYPE_LOCAL, constants.TYPE_GRE, constants.TYPE_VXLAN, - constants.TYPE_VLAN}, valid_types) - - def test_bind_port_with_vif_type_ovs(self): - """test bind_port with vanilla ovs.""" - port_context = self._fake_port_context( - fake_segments=[self.test_invalid_segment, self.test_valid_segment]) - - vif_type = portbindings.VIF_TYPE_OVS - vif_details = {'some_test_details': None} - - self.mgr._hconfig_bind_port( - port_context, self.sample_hconfig_dbget_ovs) - - port_context.set_binding.assert_called_once_with( - self.test_valid_segment[api.ID], vif_type, - vif_details, status=n_const.PORT_STATUS_ACTIVE) - - def _set_pass_vif_details(self, port_context, vif_details): - """extract vif_details and update vif_details if needed.""" - vhostuser_socket_dir = vif_details.get( - 'vhostuser_socket_dir', '/var/run/openvswitch') - port_spec = vif_details.get( - 'port_prefix', 'vhu_') + port_context.current['id'] - socket_path = os_path.join(vhostuser_socket_dir, port_spec) - vif_details.update({portbindings.VHOST_USER_SOCKET: socket_path}) - - return vif_details - - def test_bind_port_with_vif_type_vhost_user(self): - """test bind_port with ovs-dpdk.""" - port_context = self._fake_port_context( - fake_segments=[self.test_invalid_segment, self.test_valid_segment], - host_agents=[deepcopy(self.sample_hconf_str_tmpl_subs_ovs)]) - - self.mgr.bind_port(port_context) - - pass_vif_type = portbindings.VIF_TYPE_VHOST_USER - pass_vif_details = self.sample_hconfig_dbget_ovs_dpdk[ - 'configurations']['supported_vnic_types'][0]['vif_details'] - self._set_pass_vif_details(port_context, pass_vif_details) - - port_context.set_binding.assert_called_once_with( - self.test_valid_segment[api.ID], pass_vif_type, - pass_vif_details, status=n_const.PORT_STATUS_ACTIVE) - - def test_bind_port_with_vif_type_vhost_user_vpp(self): - """test bind_port with vpp.""" - port_context = self._fake_port_context( - fake_segments=[self.test_invalid_segment, self.test_valid_segment], - host_agents=[deepcopy(self.sample_hconf_str_tmpl_subs_vpp)]) - - self.mgr.bind_port(port_context) - - pass_vif_type = portbindings.VIF_TYPE_VHOST_USER - pass_vif_details = self.sample_hconfig_dbget_vpp['configurations'][ - 'supported_vnic_types'][0]['vif_details'] - self._set_pass_vif_details(port_context, pass_vif_details) - - port_context.set_binding.assert_called_once_with( - self.test_valid_segment[api.ID], pass_vif_type, - pass_vif_details, status=n_const.PORT_STATUS_ACTIVE) - - def test_bind_port_without_valid_segment(self): - """test bind_port without a valid segment.""" - port_context = self._fake_port_context( - fake_segments=[self.test_invalid_segment]) - - self.mgr._hconfig_bind_port( - port_context, self.sample_hconfig_dbget_ovs) - - port_context.set_binding.assert_not_called() - - def test_no_str_template_substitution_in_configuration_string(self): - """Test for no identifier substituion in config JSON string.""" - port_context = self._fake_port_context( - fake_segments=[self.test_invalid_segment, self.test_valid_segment]) - - hconf_dict = self.mgr._substitute_hconfig_tmpl( - port_context, self.sample_hconf_str_tmpl_nosubs) - - test_string = hconf_dict['configurations'][ - 'supported_vnic_types'][0][ - 'vif_details'][portbindings.VHOST_USER_SOCKET] - - expected_str = '/var/run/openvswitch/PORT_NOSUBS' - - self.assertEqual(expected_str, test_string) - - def test_str_template_substitution_in_configuration_string(self): - """Test for identifier substitution in config JSON string.""" - port_context = self._fake_port_context( - fake_segments=[self.test_invalid_segment, self.test_valid_segment]) - - hconf_dict = self.mgr._substitute_hconfig_tmpl( - port_context, self.sample_hconf_str_tmpl_subs_vpp) - - test_string = hconf_dict['configurations'][ - 'supported_vnic_types'][0][ - 'vif_details'][portbindings.VHOST_USER_SOCKET] - - expected_str = Template('/tmp/socket_$PORT_ID') - expected_str = expected_str.safe_substitute({ - 'PORT_ID': port_context.current['id']}) - - self.assertEqual(expected_str, test_string) - - def _fake_port_context(self, fake_segments, host_agents=None): - network = mock.MagicMock(spec=api.NetworkContext) - return mock.MagicMock( - spec=ctx.PortContext, - current={'id': 'CONTEXT_ID', - portbindings.VNIC_TYPE: portbindings.VNIC_NORMAL}, - segments_to_bind=fake_segments, network=network, - host_agents=lambda agent_type: host_agents) |