Merge "Remove neutron driver"

This commit is contained in:
Zuul 2018-03-19 05:07:10 +00:00 committed by Gerrit Code Review
commit 4ea3bd02d5
5 changed files with 81 additions and 1042 deletions

View File

@ -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', '')

View File

@ -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

View File

@ -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>, ...)
# fixed_ips_groups(<fixed_ips>, <fip1>)
# fixed_ips_groups(<fixed_ips>, <fip2>)
# fixedips(<fip1>, "subnet_id", "4cef03d0-1d02-40bb-8c99-2f442aac6ab0")
# fixedips(<fip1>, "ip_address", "90.0.0.1")
# fixedips(<fip2>, "subnet_id", "5cef03d0-1d02-40bb-8c99-2f442aac6ab0")
# fixedips(<fip2>, "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'}]}

View File

@ -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

View File

@ -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.