diff --git a/congress/datasources/neutron_driver.py b/congress/datasources/neutron_driver.py deleted file mode 100644 index 38e5813b2..000000000 --- a/congress/datasources/neutron_driver.py +++ /dev/null @@ -1,338 +0,0 @@ -# Copyright (c) 2014 VMware, Inc. 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 __future__ import print_function -from __future__ import division -from __future__ import absolute_import - -import neutronclient.v2_0.client -from oslo_log import log as logging - -from congress.datasources import constants -from congress.datasources import datasource_driver -from congress.datasources import datasource_utils - -LOG = logging.getLogger(__name__) - - -class NeutronDriver(datasource_driver.PollingDataSourceDriver, - datasource_driver.ExecutionDriver): - - NETWORKS = "networks" - NETWORKS_SUBNETS = "networks.subnets" - PORTS = "ports" - PORTS_ADDR_PAIRS = "ports.address_pairs" - PORTS_SECURITY_GROUPS = "ports.security_groups" - PORTS_BINDING_CAPABILITIES = "ports.binding_capabilities" - PORTS_FIXED_IPS = "ports.fixed_ips" - PORTS_FIXED_IPS_GROUPS = "ports.fixed_ips_groups" - PORTS_EXTRA_DHCP_OPTS = "ports.extra_dhcp_opts" - ROUTERS = "routers" - ROUTERS_EXTERNAL_GATEWAYS = "routers.external_gateways" - SECURITY_GROUPS = "security_groups" - - # This is the most common per-value translator, so define it once here. - value_trans = {'translation-type': 'VALUE'} - - networks_translator = { - 'translation-type': 'HDICT', - 'table-name': NETWORKS, - 'selector-type': 'DICT_SELECTOR', - 'field-translators': - ({'fieldname': 'status', 'translator': value_trans}, - {'fieldname': 'name', 'translator': value_trans}, - {'fieldname': 'subnets', 'col': 'subnet_group_id', - 'translator': {'translation-type': 'LIST', - 'table-name': 'networks.subnets', - 'id-col': 'subnet_group_id', - 'val-col': 'subnet', - 'translator': value_trans}}, - {'fieldname': 'provider:physical_network', - 'translator': value_trans}, - {'fieldname': 'admin_state_up', 'translator': value_trans}, - {'fieldname': 'tenant_id', 'translator': value_trans}, - {'fieldname': 'provider:network_type', 'translator': value_trans}, - {'fieldname': 'router:external', 'translator': value_trans}, - {'fieldname': 'shared', 'translator': value_trans}, - {'fieldname': 'id', 'translator': value_trans}, - {'fieldname': 'provider:segmentation_id', - 'translator': value_trans})} - - ports_translator = { - 'translation-type': 'HDICT', - 'table-name': PORTS, - 'selector-type': 'DICT_SELECTOR', - 'field-translators': - ({'fieldname': 'allowed_address_pairs', - 'col': 'allowed_address_pairs_id', - 'translator': {'translation-type': 'LIST', - 'table-name': PORTS_ADDR_PAIRS, - 'id-col': 'allowed_address_pairs_id', - 'val-col': 'address', - 'translator': value_trans}}, - {'fieldname': 'security_groups', - 'col': 'security_groups_id', - 'translator': {'translation-type': 'LIST', - 'table-name': PORTS_SECURITY_GROUPS, - 'id-col': 'security_groups_id', - 'val-col': 'security_group_id', - 'translator': value_trans}}, - {'fieldname': 'extra_dhcp_opts', - 'col': 'extra_dhcp_opt_group_id', - 'translator': {'translation-type': 'LIST', - 'table-name': PORTS_EXTRA_DHCP_OPTS, - 'id-col': 'extra_dhcp_opt_group_id', - 'val-col': 'dhcp_opt', - 'translator': value_trans}}, - {'fieldname': 'binding:capabilities', - 'col': 'binding:capabilities_id', - 'translator': {'translation-type': 'VDICT', - 'table-name': PORTS_BINDING_CAPABILITIES, - 'id-col': 'binding:capabilities_id', - 'key-col': 'key', 'val-col': 'value', - 'translator': value_trans}}, - {'fieldname': 'status', 'translator': value_trans}, - {'fieldname': 'name', 'translator': value_trans}, - {'fieldname': 'admin_state_up', 'translator': value_trans}, - {'fieldname': 'network_id', 'translator': value_trans}, - {'fieldname': 'tenant_id', 'translator': value_trans}, - {'fieldname': 'binding:vif_type', 'translator': value_trans}, - {'fieldname': 'device_owner', 'translator': value_trans}, - {'fieldname': 'mac_address', 'translator': value_trans}, - - {'fieldname': 'fixed_ips', - 'col': 'fixed_ips', - 'translator': {'translation-type': 'LIST', - 'table-name': PORTS_FIXED_IPS_GROUPS, - 'id-col': 'fixed_ips_group_id', - 'val-col': 'fixed_ip_id', - 'translator': {'translation-type': 'VDICT', - 'table-name': PORTS_FIXED_IPS, - 'id-col': 'fixed_ip_id', - 'key-col': 'key', - 'val-col': 'value', - 'translator': value_trans}}}, - {'fieldname': 'id', 'translator': value_trans}, - {'fieldname': 'device_id', 'translator': value_trans}, - {'fieldname': 'binding:host_id', 'translator': value_trans})} - - routers_translator = { - 'translation-type': 'HDICT', - 'table-name': ROUTERS, - 'selector-type': 'DICT_SELECTOR', - 'field-translators': - ({'fieldname': 'status', 'translator': value_trans}, - {'fieldname': 'external_gateway_info', - 'translator': {'translation-type': 'VDICT', - 'table-name': ROUTERS_EXTERNAL_GATEWAYS, - 'id-col': 'external_gateway_info', - 'key-col': 'key', 'val-col': 'value', - 'translator': value_trans}}, - {'fieldname': 'networks', 'translator': value_trans}, - {'fieldname': 'name', 'translator': value_trans}, - {'fieldname': 'admin_state_up', 'translator': value_trans}, - {'fieldname': 'tenant_id', 'translator': value_trans}, - {'fieldname': 'id', 'translator': value_trans})} - - security_groups_translator = { - 'translation-type': 'HDICT', - 'table-name': SECURITY_GROUPS, - 'selector-type': 'DICT_SELECTOR', - 'field-translators': - ({'fieldname': 'tenant_id', 'translator': value_trans}, - {'fieldname': 'name', 'translator': value_trans}, - {'fieldname': 'description', 'translator': value_trans}, - {'fieldname': 'id', 'translator': value_trans})} - - TRANSLATORS = [networks_translator, ports_translator, routers_translator, - security_groups_translator] - - def __init__(self, name='', args=None): - super(NeutronDriver, self).__init__(name, args=args) - datasource_driver.ExecutionDriver.__init__(self) - self.creds = self.get_neutron_credentials(args) - self.neutron = neutronclient.v2_0.client.Client(**self.creds) - self.initialize_update_methods() - self._init_end_start_poll() - - @staticmethod - def get_datasource_info(): - result = {} - result['id'] = 'neutron' - result['description'] = ('Do not use this driver is deprecated') - result['config'] = datasource_utils.get_openstack_required_config() - result['config']['lazy_tables'] = constants.OPTIONAL - result['secret'] = ['password'] - return result - - def get_neutron_credentials(self, creds): - d = {} - d['username'] = creds['username'] - d['tenant_name'] = creds['tenant_name'] - d['password'] = creds['password'] - d['auth_url'] = creds['auth_url'] - return d - - def initialize_update_methods(self): - networks_method = lambda: self._translate_networks( - self.neutron.list_networks()) - self.add_update_method(networks_method, self.networks_translator) - - ports_method = lambda: self._translate_ports(self.neutron.list_ports()) - self.add_update_method(ports_method, self.ports_translator) - - routers_method = lambda: self._translate_routers( - self.neutron.list_routers()) - self.add_update_method(routers_method, self.routers_translator) - - security_method = lambda: self._translate_security_group( - self.neutron.list_security_groups()) - self.add_update_method(security_method, - self.security_groups_translator) - - @datasource_utils.update_state_on_changed(NETWORKS) - def _translate_networks(self, obj): - """Translate the networks represented by OBJ into tables. - - Assigns self.state[tablename] for all those TABLENAMEs - generated from OBJ: NETWORKS, NETWORKS_SUBNETS - """ - LOG.debug("NETWORKS: %s", dict(obj)) - - row_data = NeutronDriver.convert_objs(obj['networks'], - self.networks_translator) - return row_data - - @datasource_utils.update_state_on_changed(PORTS) - def _translate_ports(self, obj): - """Translate the ports represented by OBJ into tables. - - Assigns self.state[tablename] for all those TABLENAMEs - generated from OBJ: PORTS, PORTS_ADDR_PAIRS, - PORTS_SECURITY_GROUPS, PORTS_BINDING_CAPABILITIES, - PORTS_FIXED_IPS, PORTS_FIXED_IPS_GROUPS, - PORTS_EXTRA_DHCP_OPTS. - """ - LOG.debug("PORTS: %s", obj) - - row_data = NeutronDriver.convert_objs(obj['ports'], - self.ports_translator) - return row_data - - @datasource_utils.update_state_on_changed(ROUTERS) - def _translate_routers(self, obj): - """Translates the routers represented by OBJ into a single table. - - Assigns self.state[SECURITY_GROUPS] to that table. - """ - LOG.debug("ROUTERS: %s", dict(obj)) - - row_data = NeutronDriver.convert_objs(obj['routers'], - self.routers_translator) - return row_data - - @datasource_utils.update_state_on_changed(SECURITY_GROUPS) - def _translate_security_groups(self, obj): - LOG.debug("SECURITY_GROUPS: %s", dict(obj)) - - row_data = NeutronDriver.convert_objs(obj['security_groups'], - self.security_groups_translator) - return row_data - - def execute(self, action, action_args): - """Overwrite ExecutionDriver.execute().""" - # action can be written as a method or an API call. - func = getattr(self, action, None) - if func and self.is_executable(func): - func(action_args) - else: - self._execute_api(self.neutron, action, action_args) - -# Sample Mapping -# Network : -# ======== -# -# json -# ------ -# {u'status': u'ACTIVE', u'subnets': -# [u'4cef03d0-1d02-40bb-8c99-2f442aac6ab0'], -# u'name':u'test-network', u'provider:physical_network': None, -# u'admin_state_up': True, -# u'tenant_id': u'570fe78a1dc54cffa053bd802984ede2', -# u'provider:network_type': u'gre', -# u'router:external': False, u'shared': False, u'id': -# u'240ff9df-df35-43ae-9df5-27fae87f2492', -# u'provider:segmentation_id': 4} -# -# tuple -# ----- -# -# Networks : (u'ACTIVE', 'cdca5538-ae2d-11e3-92c1-bcee7bdf8d69', -# u'vova_network', None, -# True, u'570fe78a1dc54cffa053bd802984ede2', u'gre', 'False', 'False', -# u'1e3bc4fe-85c2-4b04-9b7f-ee40239787ef', 7) -# -# Networks and subnets -# ('cdcaa1a0-ae2d-11e3-92c1-bcee7bdf8d69', -# u'4cef03d0-1d02-40bb-8c99-2f442aac6ab0') -# -# -# Ports -# ====== -# json -# ---- -# {u'status': u'ACTIVE', -# u'binding:host_id': u'havana', u'name': u'', -# u'allowed_address_pairs': [], -# u'admin_state_up': True, u'network_id': -# u'240ff9df-df35-43ae-9df5-27fae87f2492', -# u'tenant_id': u'570fe78a1dc54cffa053bd802984ede2', -# u'extra_dhcp_opts': [], -# u'binding:vif_type': u'ovs', u'device_owner': -# u'network:router_interface', -# u'binding:capabilities': {u'port_filter': True}, -# u'mac_address': u'fa:16:3e:ab:90:df', -# u'fixed_ips': [{u'subnet_id': -# u'4cef03d0-1d02-40bb-8c99-2f442aac6ab0', -# u'ip_address': u'90.0.0.1'}], u'id': -# u'0a2ce569-85a8-45ec-abb3-0d4b34ff69ba',u'security_groups': [], -# u'device_id': u'864e4acf-bf8e-4664-8cf7-ad5daa95681e'}, -# tuples -# ------- -# Ports [(u'ACTIVE', u'havana', u'', -# '6425751e-ae2c-11e3-bba1-bcee7bdf8d69', 'True', -# u'240ff9df-df35-43ae-9df5-27fae87f2492', -# u'570fe78a1dc54cffa053bd802984ede2', -# '642579e2-ae2c-11e3-bba1-bcee7bdf8d69', u'ovs', -# u'network:router_interface', '64257dac-ae2c-11e3-bba1-bcee7bdf8d69', -# u'fa:16:3e:ab:90:df', -# '64258126-ae2c-11e3-bba1-bcee7bdf8d69', -# u'0a2ce569-85a8-45ec-abb3-0d4b34ff69ba', -# '64258496-ae2c-11e3-bba1-bcee7bdf8d69', -# u'864e4acf-bf8e-4664-8cf7-ad5daa95681e') -# -# Ports and Address Pairs -# [('6425751e-ae2c-11e3-bba1-bcee7bdf8d69', '') -# Ports and Security Groups -# [('64258496-ae2c-11e3-bba1-bcee7bdf8d69', '') -# Ports and Binding Capabilities [ -# ('64257dac-ae2c-11e3-bba1-bcee7bdf8d69',u'port_filter','True') -# Ports and Fixed IPs [('64258126-ae2c-11e3-bba1-bcee7bdf8d69', -# u'subnet_id',u'4cef03d0-1d02-40bb-8c99-2f442aac6ab0'), -# ('64258126-ae2c-11e3-bba1-bcee7bdf8d69', u'ip_address', -# u'90.0.0.1') -# -# Ports and Extra dhcp opts [ -# ('642579e2-ae2c-11e3-bba1-bcee7bdf8d69', '') diff --git a/congress/tests/datasources/fakes.py b/congress/tests/datasources/fakes.py index 51a145f2b..c75768dd3 100644 --- a/congress/tests/datasources/fakes.py +++ b/congress/tests/datasources/fakes.py @@ -19,6 +19,76 @@ from __future__ import absolute_import import mock +# Sample responses from neutron-client, after parsing +network_response = { + 'networks': + [{'status': 'ACTIVE', + 'subnets': ['4cef03d0-1d02-40bb-8c99-2f442aac6ab0'], + 'name': 'test-network', + 'provider:physical_network': None, + 'admin_state_up': True, + 'tenant_id': '570fe78a1dc54cffa053bd802984ede2', + 'provider:network_type': 'gre', + 'router:external': False, + 'shared': False, + 'id': '240ff9df-df35-43ae-9df5-27fae87f2492', + 'provider:segmentation_id': 4}]} + +port_response = { + "ports": + [{"status": "ACTIVE", + "binding:host_id": "havana", + "name": "", + "allowed_address_pairs": [], + "admin_state_up": True, + "network_id": "240ff9df-df35-43ae-9df5-27fae87f2492", + "tenant_id": "570fe78a1dc54cffa053bd802984ede2", + "extra_dhcp_opts": [], + "binding:vif_type": "ovs", + "device_owner": "network:router_interface", + "binding:capabilities": {"port_filter": True}, + "mac_address": "fa:16:3e:ab:90:df", + "fixed_ips": [ + {"subnet_id": "4cef03d0-1d02-40bb-8c99-2f442aac6ab0", + "ip_address": "90.0.0.1"}, + {"subnet_id": "5cef03d0-1d02-40bb-8c99-2f442aac6ab0", + "ip_address": "100.0.0.1"}], + "id": "0a2ce569-85a8-45ec-abb3-0d4b34ff69ba", + "security_groups": ['15ea0516-11ec-46e9-9e8e-7d1b6e3d7523', + '25ea0516-11ec-46e9-9e8e-7d1b6e3d7523'], + "device_id": "864e4acf-bf8e-4664-8cf7-ad5daa95681e"}]} + + +router_response = { + 'routers': + [{u'status': u'ACTIVE', + u'external_gateway_info': + {u'network_id': u'a821b8d3-af1f-4d79-9b8e-3da9674338ae', + u'enable_snat': True}, + u'name': u'router1', + u'admin_state_up': True, + u'tenant_id': u'abb53cc6636848218f46d01f22bf1060', + u'routes': [], + u'id': u'4598c424-d608-4366-9beb-139adbd7cff5'}]} + +security_group_response = { + 'security_groups': + [{u'tenant_id': u'abb53cc6636848218f46d01f22bf1060', + u'name': u'default', + u'description': u'default', + u'security_group_rules': [ + {u'remote_group_id': u'9f3860a5-87b1-499c-bf93-5ca3ef247517', + u'direction': u'ingress', + u'remote_ip_prefix': None, + u'protocol': None, + u'tenant_id': u'abb53cc6636848218f46d01f22bf1060', + u'port_range_max': None, + u'security_group_id': u'9f3860a5-87b1-499c-bf93-5ca3ef247517', + u'port_range_min': None, + u'ethertype': u'IPv6', + u'id': u'15ea0516-11ec-46e9-9e8e-7d1b6e3d7523'}], + u'id': u'9f3860a5-87b1-499c-bf93-5ca3ef247517'}]} + class NovaFakeClient(mock.MagicMock): # TODO(rajdeepd): Replace Fake with mocks directly in test_neutron_driver diff --git a/congress/tests/datasources/test_neutron_driver.py b/congress/tests/datasources/test_neutron_driver.py deleted file mode 100644 index 49c5dd4ec..000000000 --- a/congress/tests/datasources/test_neutron_driver.py +++ /dev/null @@ -1,699 +0,0 @@ -# Copyright (c) 2013 VMware, Inc. 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 __future__ import print_function -from __future__ import division -from __future__ import absolute_import - -import datetime - -import mock -from mox3 import mox -import neutronclient.v2_0.client -from oslo_config import cfg -from six.moves import range - -from congress.datalog import compile -from congress.datasources import neutron_driver -from congress import harness -from congress.tests import base -from congress.tests import helper - - -class TestNeutronDriver(base.TestCase): - - def setUp(self): - super(TestNeutronDriver, self).setUp() - self.neutron_client = mock.MagicMock() - self.neutron_client.list_networks.return_value = network_response - self.neutron_client.list_ports.return_value = port_response - self.neutron_client.list_routers.return_value = router_response - self.neutron_client.list_security_groups.return_value = ( - security_group_response) - args = helper.datasource_openstack_args() - self.driver = neutron_driver.NeutronDriver(args=args) - self.driver.neutron = self.neutron_client - - def test_list_networks(self): - """Test conversion of complex network objects to tables.""" - network_list = self.neutron_client.list_networks() - self.driver._translate_networks(network_list) - network_tuples = self.driver.state[self.driver.NETWORKS] - network_subnet_tuples = self.driver.state[ - self.driver.NETWORKS_SUBNETS] - - # size of networks/subnets - self.assertIsNotNone(network_tuples) - self.assertEqual(1, len(network_tuples)) - self.assertEqual(1, len(network_subnet_tuples)) - - # properties of first network - key_to_index = self.driver.get_column_map( - self.driver.NETWORKS) - network_tuple = network_tuples.pop() - subnet_tuple_guid = network_tuple[key_to_index['subnet_group_id']] - name = network_tuple[key_to_index['name']] - status = network_tuple[key_to_index['status']] - provider_physical_network = ( - network_tuple[key_to_index['provider:physical_network']]) - admin_state_up = network_tuple[key_to_index['admin_state_up']] - tenant_id = network_tuple[key_to_index['tenant_id']] - provider_network_type = ( - network_tuple[key_to_index['provider:network_type']]) - router_external = network_tuple[key_to_index['router:external']] - shared = network_tuple[key_to_index['shared']] - id = network_tuple[key_to_index['id']] - provider_segmentation_id = ( - network_tuple[key_to_index['provider:segmentation_id']]) - - # properties of first subnet - network_subnet_tuple = network_subnet_tuples.pop() - guid_key = network_subnet_tuple[0] - guid_value = network_subnet_tuple[1] - - # tests for network/subnet - self.assertEqual('ACTIVE', status) - self.assertIsNotNone(subnet_tuple_guid) - self.assertEqual(guid_key, subnet_tuple_guid) - self.assertEqual('4cef03d0-1d02-40bb-8c99-2f442aac6ab0', - guid_value) - self.assertEqual('test-network', - name) - self.assertEqual('None', provider_physical_network) - self.assertEqual('True', admin_state_up) - self.assertEqual('570fe78a1dc54cffa053bd802984ede2', - tenant_id) - self.assertEqual('gre', provider_network_type) - self.assertEqual('False', router_external) - self.assertEqual('False', shared) - self.assertEqual('240ff9df-df35-43ae-9df5-27fae87f2492', - id) - self.assertEqual(4, provider_segmentation_id) - - def test_list_ports(self): - """Test conversion of complex port objects to tuples.""" - # setup - self.driver._translate_ports(self.neutron_client.list_ports()) - d = self.driver.get_column_map(self.driver.PORTS) - - # number of ports - ports = self.driver.state[self.driver.PORTS] - self.assertIsNotNone(ports) - self.assertEqual(1, len(ports)) - - # simple properties of a port - port = ports.pop() - self.assertEqual('ACTIVE', port[d['status']]) - self.assertEqual('havana', port[d['binding:host_id']]) - self.assertEqual('', port[d['name']]) - self.assertEqual('True', port[d['admin_state_up']]) - self.assertEqual('240ff9df-df35-43ae-9df5-27fae87f2492', - port[d['network_id']]) - self.assertEqual('570fe78a1dc54cffa053bd802984ede2', - port[d['tenant_id']]) - self.assertEqual('ovs', port[d['binding:vif_type']]) - self.assertEqual('network:router_interface', port[d['device_owner']]) - self.assertEqual('fa:16:3e:ab:90:df', port[d['mac_address']]) - self.assertEqual('0a2ce569-85a8-45ec-abb3-0d4b34ff69ba', - port[d['id']]) - self.assertEqual('864e4acf-bf8e-4664-8cf7-ad5daa95681e', - port[d['device_id']]) - - # complex property: allowed_address_pairs - # TODO(thinrichs): add representative allowed_address_pairs - address_pairs = self.driver.state[ - self.driver.PORTS_ADDR_PAIRS] - self.assertEqual(0, len(address_pairs)) - - # complex property: extra_dhcp_opts - # TODO(thinrichs): add representative port_extra_dhcp_opts - dhcp_opts = self.driver.state[ - self.driver.PORTS_EXTRA_DHCP_OPTS] - self.assertEqual(0, len(dhcp_opts)) - - # complex property: binding:capabilities - binding_caps = self.driver.state[ - self.driver.PORTS_BINDING_CAPABILITIES] - cap_id = port[d['binding:capabilities_id']] - self.assertEqual(1, len(binding_caps)) - self.assertEqual((cap_id, 'port_filter', 'True'), binding_caps.pop()) - - # complex property: security_groups - sec_grps = self.driver.state[self.driver.PORTS_SECURITY_GROUPS] - self.assertEqual(2, len(sec_grps)) - security_grp_grp = port[d['security_groups_id']] - security_grp1 = '15ea0516-11ec-46e9-9e8e-7d1b6e3d7523' - security_grp2 = '25ea0516-11ec-46e9-9e8e-7d1b6e3d7523' - security_data = set([(security_grp_grp, security_grp1), - (security_grp_grp, security_grp2)]) - self.assertEqual(security_data, set(sec_grps)) - - # complex property: fixed_ips - # Need to show we have the following - # port(..., , ...) - # fixed_ips_groups(, ) - # fixed_ips_groups(, ) - # fixedips(, "subnet_id", "4cef03d0-1d02-40bb-8c99-2f442aac6ab0") - # fixedips(, "ip_address", "90.0.0.1") - # fixedips(, "subnet_id", "5cef03d0-1d02-40bb-8c99-2f442aac6ab0") - # fixedips(, "ip_address", "100.0.0.1") - # TODO(thinrichs): use functionality of policy-engine - # to make this test simpler to understand/write - fixed_ip_groups = self.driver.state[ - self.driver.PORTS_FIXED_IPS_GROUPS] - fixed_ips = self.driver.state[self.driver.PORTS_FIXED_IPS] - fixed_ip_grp = port[d['fixed_ips']] - # ensure groups of IPs are correct - self.assertEqual(2, len(fixed_ip_groups)) - groups = set([x[0] for x in fixed_ip_groups]) - self.assertEqual(set([fixed_ip_grp]), groups) - # ensure the IDs for fixed_ips are the right ones - fixed_ips_from_grp = [x[1] for x in fixed_ip_groups] - fixed_ips_from_ips = [x[0] for x in fixed_ips] - self.assertEqual(set(fixed_ips_from_grp), set(fixed_ips_from_ips)) - # ensure actual fixed_ips are right - self.assertEqual(4, len(fixed_ips)) - ips = [x for x in fixed_ips if x[1] == 'ip_address'] - subnets = [x for x in fixed_ips if x[1] == 'subnet_id'] - if ips[0][0] == subnets[0][0]: - ip0 = ips[0][2] - subnet0 = subnets[0][2] - ip1 = ips[1][2] - subnet1 = subnets[1][2] - else: - ip0 = ips[0][2] - subnet0 = subnets[1][2] - ip1 = ips[1][2] - subnet1 = subnets[0][2] - if ip0 == "90.0.0.1": - self.assertEqual("4cef03d0-1d02-40bb-8c99-2f442aac6ab0", subnet0) - self.assertEqual("90.0.0.1", ip0) - self.assertEqual("5cef03d0-1d02-40bb-8c99-2f442aac6ab0", subnet1) - self.assertEqual("100.0.0.1", ip1) - else: - self.assertEqual("4cef03d0-1d02-40bb-8c99-2f442aac6ab0", subnet1) - self.assertEqual("90.0.0.1", ip1) - self.assertEqual("5cef03d0-1d02-40bb-8c99-2f442aac6ab0", subnet0) - self.assertEqual("100.0.0.1", ip0) - - def test_list_routers(self): - self.driver._translate_routers(self.neutron_client.list_routers()) - d = self.driver.get_column_map(self.driver.ROUTERS) - - # number of routers - routers = self.driver.state[self.driver.ROUTERS] - self.assertIsNotNone(routers) - self.assertEqual(1, len(routers)) - - # simple properties of a router - router = routers.pop() - self.assertEqual('ACTIVE', router[d['status']]) - self.assertEqual('router1', router[d['name']]) - self.assertEqual('True', router[d['admin_state_up']]) - self.assertEqual('abb53cc6636848218f46d01f22bf1060', - router[d['tenant_id']]) - self.assertEqual('4598c424-d608-4366-9beb-139adbd7cff5', - router[d['id']]) - - # external gateway info - gateway_info = self.driver.state[ - self.driver.ROUTERS_EXTERNAL_GATEWAYS] - gateway_id = router[d['external_gateway_info']] - self.assertEqual(2, len(gateway_info)) - row1 = (gateway_id, 'network_id', - 'a821b8d3-af1f-4d79-9b8e-3da9674338ae') - row2 = (gateway_id, 'enable_snat', 'True') - self.assertEqual(set([row1, row2]), gateway_info) - - def test_list_security_groups(self): - self.driver._translate_security_groups( - self.neutron_client.list_security_groups()) - d = self.driver.get_column_map(self.driver.SECURITY_GROUPS) - - # number of security groups - sec_grps = self.driver.state[self.driver.SECURITY_GROUPS] - self.assertIsNotNone(sec_grps) - self.assertEqual(1, len(sec_grps)) - - # simple properties - sec_grp = sec_grps.pop() - self.assertEqual('abb53cc6636848218f46d01f22bf1060', - sec_grp[d['tenant_id']]) - self.assertEqual('default', sec_grp[d['name']]) - self.assertEqual('default', sec_grp[d['description']]) - self.assertEqual('9f3860a5-87b1-499c-bf93-5ca3ef247517', - sec_grp[d['id']]) - - def test_execute(self): - class NeutronClient(object): - def __init__(self): - self.testkey = None - - def connectNetwork(self, arg1): - self.testkey = 'arg1=%s' % arg1 - - neutron_client = NeutronClient() - self.driver.neutron = neutron_client - api_args = { - 'positional': ['1'] - } - expected_ans = 'arg1=1' - - self.driver.execute('connectNetwork', api_args) - - self.assertEqual(expected_ans, neutron_client.testkey) - - -class TestDataSourceDriver(base.TestCase): - - def setUp(self): - """Setup polling tests.""" - super(TestDataSourceDriver, self).setUp() - cfg.CONF.set_override( - 'drivers', - ['congress.datasources.neutron_driver.NeutronDriver']) - - # Create mock of Neutron client so we can control data - mock_factory = mox.Mox() - neutron_client = mock_factory.CreateMock( - neutronclient.v2_0.client.Client) - neutron_client.list_networks().InAnyOrder(1).AndReturn(network1) - neutron_client.list_ports().InAnyOrder(1).AndReturn(port_response) - neutron_client.list_routers().InAnyOrder(1).AndReturn(router_response) - neutron_client.list_security_groups().InAnyOrder(1).AndReturn( - security_group_response) - neutron_client.list_networks().InAnyOrder(2).AndReturn(network2) - neutron_client.list_ports().InAnyOrder(2).AndReturn(port_response) - neutron_client.list_routers().InAnyOrder(2).AndReturn(router_response) - neutron_client.list_security_groups().InAnyOrder(2).AndReturn( - security_group_response) - mock_factory.ReplayAll() - - node = helper.make_dsenode_new_partition('neutron_ds_node') - - engine = harness.create_policy_engine() - node.register_service(engine) - - neutron_args = { - 'name': 'neutron', - 'driver': 'neutron', - 'description': None, - 'type': None, - 'enabled': '1' - } - neutron_args['config'] = helper.datasource_openstack_args() - neutron_args['config']['poll_time'] = 0 - neutron_args['config']['client'] = neutron_client - neutron_ds = node.create_datasource_service(neutron_args) - node.register_service(neutron_ds) - - engine.create_policy('neutron') - engine.set_schema('neutron', neutron_ds.get_schema()) - neutron_ds.neutron = neutron_client - engine.debug_mode() - - # insert rule into policy to make testing easier. - # (Some of the IDs are auto-generated each time we convert) - engine.insert(create_network_group('p')) - - # create some garbage data - args = helper.datasource_openstack_args() - driver = neutron_driver.NeutronDriver(args=args) - network_key_to_index = driver.get_column_map( - neutron_driver.NeutronDriver.NETWORKS) - network_max_index = max(network_key_to_index.values()) - args1 = ['1'] * (network_max_index + 1) - args2 = ['2'] * (network_max_index + 1) - args1 = ",".join(args1) - args2 = ",".join(args2) - fake_networks = [ - 'neutron:networks({})'.format(args1), - 'neutron:networks({})'.format(args2)] - - # answer to query above for network1 - datalog1 = ( - 'p("240ff9df-df35-43ae-9df5-27fae87f2492") ' - 'p("340ff9df-df35-43ae-9df5-27fae87f2492") ' - 'p("440ff9df-df35-43ae-9df5-27fae87f2492")') - - # answer to query above for network2 - datalog2 = ( - 'p("240ff9df-df35-43ae-9df5-27fae87f2492") ' - 'p("640ff9df-df35-43ae-9df5-27fae87f2492") ' - 'p("540ff9df-df35-43ae-9df5-27fae87f2492")') - - # return value - self.info = {} - self.info['node'] = node - self.info['datalog1'] = datalog1 - self.info['datalog2'] = datalog2 - self.info['fake_networks'] = fake_networks - - def test_last_updated(self): - """Test the last_updated timestamping.""" - node = self.info['node'] - neutron = node.service_object('neutron') - - # initial value - last_updated = neutron.get_last_updated_time() - self.assertIsNone(last_updated) - - # first time updated - before_time = datetime.datetime.now() - neutron.poll() - last_updated = neutron.get_last_updated_time() - self.assertLess(before_time, last_updated) - self.assertLess(last_updated, datetime.datetime.now()) - - # second time updated - before_time = datetime.datetime.now() - neutron.poll() - last_updated = neutron.get_last_updated_time() - self.assertLess(before_time, last_updated) - self.assertLess(last_updated, datetime.datetime.now()) - - # TODO(dse2): port using generic test driver instead of Neutron - # def test_subscribe_poll(self): - # """Test subscribing before polling. The common case.""" - # cage = self.info['cage'] - # policy = cage.service_object('policy') - # neutron = cage.service_object('neutron') - # datalog1 = self.info['datalog1'] - # datalog2 = self.info['datalog2'] - - # # subscribe - # policy.subscribe('neutron', 'networks', callback=policy.receive_data) - # helper.retry_check_subscribers(neutron, [(policy.name, 'networks')]) - - # # poll 1 - # neutron.poll() - # helper.retry_check_db_equal(policy, 'p(x)', datalog1) - - # # poll 2 - # neutron.poll() - # helper.retry_check_db_equal(policy, 'p(x)', datalog2) - - # TODO(dse2): port using generic test driver instead of Neutron - # def test_policy_initialization(self): - # """Test subscribing before polling. The common case.""" - # cage = self.info['cage'] - # policy = cage.service_object('policy') - # neutron = cage.service_object('neutron') - # datalog1 = self.info['datalog1'] - # fake_networks = self.info['fake_networks'] - - # # add garbage to policy - # for formula in fake_networks: - # policy.insert(formula) - - # # subscribe - # policy.subscribe('neutron', 'networks', callback=policy.receive_data) - # helper.retry_check_subscribers(neutron, [(policy.name, 'networks')]) - - # # poll 1 - # neutron.poll() - # helper.retry_check_db_equal(policy, 'p(x)', datalog1) - - # TODO(dse2): port using generic test driver instead of Neutron - # def test_poll_subscribe(self): - # """Test polling before subscribing.""" - # cage = self.info['cage'] - # policy = cage.service_object('policy') - # neutron = cage.service_object('neutron') - # datalog1 = self.info['datalog1'] - # datalog2 = self.info['datalog2'] - # fake_networks = self.info['fake_networks'] - - # # add garbage to policy - # for formula in fake_networks: - # policy.insert(formula) - - # # poll 1 and then subscribe; should still see first result - # neutron.poll() - # helper.retry_check_number_of_updates(neutron, 1) - # policy.subscribe('neutron', 'networks', callback=policy.receive_data) - # helper.retry_check_db_equal(policy, 'p(x)', datalog1) - - # # poll 2 - # neutron.poll() - # helper.retry_check_db_equal(policy, 'p(x)', datalog2) - - # TODO(dse2): port using generic test driver instead of Neutron - # def test_double_poll_subscribe(self): - # """Test double polling before subscribing.""" - # cage = self.info['cage'] - # policy = cage.service_object('policy') - # neutron = cage.service_object('neutron') - # datalog2 = self.info['datalog2'] - - # # poll twice and then subscribe: should see 2nd result - # neutron.poll() - # helper.retry_check_number_of_updates(neutron, 1) - # neutron.poll() - # helper.retry_check_number_of_updates(neutron, 2) - # policy.subscribe('neutron', 'networks', callback=policy.receive_data) - # helper.retry_check_db_equal(policy, 'p(x)', datalog2) - - # TODO(dse2): port using generic test driver instead of Neutron - # def test_policy_recovery(self): - # """Test policy crashing and recovering (sort of).""" - # cage = self.info['cage'] - # policy = cage.service_object('policy') - # neutron = cage.service_object('neutron') - # datalog1 = self.info['datalog1'] - - # # get initial data - # policy.subscribe('neutron', 'networks', callback=policy.receive_data) - # helper.retry_check_subscribers(neutron, [(policy.name, 'networks')]) - # neutron.poll() - # helper.retry_check_db_equal(policy, 'p(x)', datalog1) - - # # clear out policy's neutron:networks data (to simulate crashing) - # policy.initialize_tables(['neutron:networks'], []) - # # subscribe again (without unsubscribing) - # policy.subscribe('neutron', 'networks', callback=policy.receive_data) - # helper.retry_check_db_equal(policy, 'p(x)', datalog1) - - -def create_network_group(tablename, full_neutron_tablename=None): - driver = neutron_driver.NeutronDriver( - args=helper.datasource_openstack_args()) - if full_neutron_tablename is None: - full_neutron_tablename = 'neutron:networks' - network_key_to_index = driver.get_column_map( - neutron_driver.NeutronDriver.NETWORKS) - network_id_index = network_key_to_index['id'] - network_max_index = max(network_key_to_index.values()) - network_args = ['x' + str(i) for i in range(0, network_max_index + 1)] - formula = compile.parse1( - '{}({}) :- {}({})'.format( - tablename, - 'x' + str(network_id_index), - full_neutron_tablename, - ",".join(network_args))) - return formula - - -def create_networkXnetwork_group(tablename): - """Return rule of the form: - - TABLENAME(x,y) :- neutron:network(...,x,...),neutron:network(...,y,...) - """ - driver = neutron_driver.NeutronDriver( - args=helper.datasource_openstack_args()) - network_key_to_index = driver.get_column_map( - neutron_driver.NeutronDriver.NETWORKS) - network_id_index = network_key_to_index['id'] - network_max_index = max(network_key_to_index.values()) - net1_args = ['x' + str(i) for i in range(0, network_max_index + 1)] - net2_args = ['y' + str(i) for i in range(0, network_max_index + 1)] - formula = compile.parse1( - '{}({},{}) :- neutron:networks({}), neutron2:networks({})'.format( - tablename, - 'x' + str(network_id_index), - 'y' + str(network_id_index), - ",".join(net1_args), - ",".join(net2_args))) - return formula - -# Only diffs between network1 and network2 are the IDs -network1 = {'networks': [ - {'status': 'ACTIVE', - 'subnets': ['4cef03d0-1d02-40bb-8c99-2f442aac6ab0'], - 'name': 'test-network', - 'provider:physical_network': None, - 'admin_state_up': True, - 'tenant_id': '570fe78a1dc54cffa053bd802984ede2', - 'provider:network_type': 'gre', - 'router:external': False, - 'shared': False, - 'id': '240ff9df-df35-43ae-9df5-27fae87f2492', - 'provider:segmentation_id': 4}, - {'status': 'ACTIVE', - 'subnets': ['4cef03d0-1d02-40bb-8c99-2f442aac6ab0'], - 'name': 'test-network', - 'provider:physical_network': None, - 'admin_state_up': True, - 'tenant_id': '570fe78a1dc54cffa053bd802984ede2', - 'provider:network_type': 'gre', - 'router:external': False, - 'shared': False, - 'id': '340ff9df-df35-43ae-9df5-27fae87f2492', - 'provider:segmentation_id': 4}, - {'status': 'ACTIVE', - 'subnets': ['4cef03d0-1d02-40bb-8c99-2f442aac6ab0'], - 'name': 'test-network', - 'provider:physical_network': None, - 'admin_state_up': True, - 'tenant_id': '570fe78a1dc54cffa053bd802984ede2', - 'provider:network_type': 'gre', - 'router:external': False, - 'shared': False, - 'id': '440ff9df-df35-43ae-9df5-27fae87f2492', - 'provider:segmentation_id': 4}]} - -network2 = {'networks': [ - {'status': 'ACTIVE', - 'subnets': ['4cef03d0-1d02-40bb-8c99-2f442aac6ab0'], - 'name': 'test-network', - 'provider:physical_network': None, - 'admin_state_up': True, - 'tenant_id': '570fe78a1dc54cffa053bd802984ede2', - 'provider:network_type': 'gre', - 'router:external': False, - 'shared': False, - 'id': '240ff9df-df35-43ae-9df5-27fae87f2492', - 'provider:segmentation_id': 4}, - {'status': 'ACTIVE', - 'subnets': ['4cef03d0-1d02-40bb-8c99-2f442aac6ab0'], - 'name': 'test-network', - 'provider:physical_network': None, - 'admin_state_up': True, - 'tenant_id': '570fe78a1dc54cffa053bd802984ede2', - 'provider:network_type': 'gre', - 'router:external': False, - 'shared': False, - 'id': '540ff9df-df35-43ae-9df5-27fae87f2492', - 'provider:segmentation_id': 4}, - {'status': 'ACTIVE', - 'subnets': ['4cef03d0-1d02-40bb-8c99-2f442aac6ab0'], - 'name': 'test-network', - 'provider:physical_network': None, - 'admin_state_up': True, - 'tenant_id': '570fe78a1dc54cffa053bd802984ede2', - 'provider:network_type': 'gre', - 'router:external': False, - 'shared': False, - 'id': '640ff9df-df35-43ae-9df5-27fae87f2492', - 'provider:segmentation_id': 4}]} - - -# Sample responses from neutron-client, after parsing -network_response = { - 'networks': - [{'status': 'ACTIVE', - 'subnets': ['4cef03d0-1d02-40bb-8c99-2f442aac6ab0'], - 'name': 'test-network', - 'provider:physical_network': None, - 'admin_state_up': True, - 'tenant_id': '570fe78a1dc54cffa053bd802984ede2', - 'provider:network_type': 'gre', - 'router:external': False, - 'shared': False, - 'id': '240ff9df-df35-43ae-9df5-27fae87f2492', - 'provider:segmentation_id': 4}]} - -port_response = { - "ports": - [{"status": "ACTIVE", - "binding:host_id": "havana", - "name": "", - "allowed_address_pairs": [], - "admin_state_up": True, - "network_id": "240ff9df-df35-43ae-9df5-27fae87f2492", - "tenant_id": "570fe78a1dc54cffa053bd802984ede2", - "extra_dhcp_opts": [], - "binding:vif_type": "ovs", - "device_owner": "network:router_interface", - "binding:capabilities": {"port_filter": True}, - "mac_address": "fa:16:3e:ab:90:df", - "fixed_ips": [ - {"subnet_id": "4cef03d0-1d02-40bb-8c99-2f442aac6ab0", - "ip_address": "90.0.0.1"}, - {"subnet_id": "5cef03d0-1d02-40bb-8c99-2f442aac6ab0", - "ip_address": "100.0.0.1"}], - "id": "0a2ce569-85a8-45ec-abb3-0d4b34ff69ba", - "security_groups": ['15ea0516-11ec-46e9-9e8e-7d1b6e3d7523', - '25ea0516-11ec-46e9-9e8e-7d1b6e3d7523'], - "device_id": "864e4acf-bf8e-4664-8cf7-ad5daa95681e"}]} - -router_response = { - 'routers': - [{u'status': u'ACTIVE', - u'external_gateway_info': - {u'network_id': u'a821b8d3-af1f-4d79-9b8e-3da9674338ae', - u'enable_snat': True}, - u'name': u'router1', - u'admin_state_up': True, - u'tenant_id': u'abb53cc6636848218f46d01f22bf1060', - u'routes': [], - u'id': u'4598c424-d608-4366-9beb-139adbd7cff5'}]} - -security_group_response = { - 'security_groups': - [{u'tenant_id': u'abb53cc6636848218f46d01f22bf1060', - u'name': u'default', - u'description': u'default', - u'security_group_rules': [ - {u'remote_group_id': u'9f3860a5-87b1-499c-bf93-5ca3ef247517', - u'direction': u'ingress', - u'remote_ip_prefix': None, - u'protocol': None, - u'tenant_id': u'abb53cc6636848218f46d01f22bf1060', - u'port_range_max': None, - u'security_group_id': u'9f3860a5-87b1-499c-bf93-5ca3ef247517', - u'port_range_min': None, - u'ethertype': u'IPv6', - u'id': u'15ea0516-11ec-46e9-9e8e-7d1b6e3d7523'}, - {u'remote_group_id': None, u'direction': u'egress', - u'remote_ip_prefix': None, - u'protocol': None, - u'tenant_id': u'abb53cc6636848218f46d01f22bf1060', - u'port_range_max': None, - u'security_group_id': u'9f3860a5-87b1-499c-bf93-5ca3ef247517', - u'port_range_min': None, - u'ethertype': u'IPv6', - u'id': u'5a2a86c5-c63c-4f17-b625-f9cd809c8331'}, - {u'remote_group_id': u'9f3860a5-87b1-499c-bf93-5ca3ef247517', - u'direction': u'ingress', - u'remote_ip_prefix': None, - u'protocol': None, - u'tenant_id': u'abb53cc6636848218f46d01f22bf1060', - u'port_range_max': None, - u'security_group_id': u'9f3860a5-87b1-499c-bf93-5ca3ef247517', - u'port_range_min': None, - u'ethertype': u'IPv4', - u'id': u'6499e807-af24-4486-9fa4-4897da2eb1dd'}, - {u'remote_group_id': None, - u'direction': u'egress', - u'remote_ip_prefix': None, - u'protocol': None, - u'tenant_id': u'abb53cc6636848218f46d01f22bf1060', - u'port_range_max': None, - u'security_group_id': u'9f3860a5-87b1-499c-bf93-5ca3ef247517', - u'port_range_min': None, - u'ethertype': u'IPv4', - u'id': u'bb03ea93-b984-48de-8752-d816f1c4fbfa'}], - u'id': u'9f3860a5-87b1-499c-bf93-5ca3ef247517'}]} diff --git a/congress/tests/test_congress.py b/congress/tests/test_congress.py index 9f8d2f7c9..7b04c5db3 100644 --- a/congress/tests/test_congress.py +++ b/congress/tests/test_congress.py @@ -35,7 +35,7 @@ from congress.datasources import nova_driver from congress.db import db_library_policies from congress.tests.api import base as tests_api_base from congress.tests import base -from congress.tests.datasources import test_neutron_driver as test_neutron +from congress.tests.datasources import fakes from congress.tests import helper @@ -69,10 +69,10 @@ class BaseTestPolicyCongress(base.SqlTestCase): neutronv2.neutron = neutron_mock # initialize neutron_mocks - network1 = test_neutron.network_response - port_response = test_neutron.port_response - router_response = test_neutron.router_response - sg_group_response = test_neutron.security_group_response + network1 = fakes.network_response + port_response = fakes.port_response + router_response = fakes.router_response + sg_group_response = fakes.security_group_response neutron_mock.list_networks.return_value = network1 neutron_mock.list_ports.return_value = port_response neutron_mock.list_routers.return_value = router_response diff --git a/releasenotes/notes/remove-deprecated-neutron-driver-f6dec90e66bd4855.yaml b/releasenotes/notes/remove-deprecated-neutron-driver-f6dec90e66bd4855.yaml new file mode 100644 index 000000000..6d7931625 --- /dev/null +++ b/releasenotes/notes/remove-deprecated-neutron-driver-f6dec90e66bd4855.yaml @@ -0,0 +1,6 @@ +--- +deprecations: + - | + neutron datasource driver is deprecated and no longer to be used. The same + has been removed in Rocky release. NeutronV2 datasource driver needs to be + used instead.