diff --git a/gbpservice/neutron/tests/unit/nfp/orchestrator/test_openstack_driver.py b/gbpservice/neutron/tests/unit/nfp/orchestrator/test_openstack_driver.py new file mode 100644 index 000000000..de1fdc921 --- /dev/null +++ b/gbpservice/neutron/tests/unit/nfp/orchestrator/test_openstack_driver.py @@ -0,0 +1,672 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import mock +from oslo_config import cfg +import unittest + +from gbpclient.v2_0 import client as gbp_client +from gbpservice.nfp.orchestrator.openstack import openstack_driver +from keystoneclient.v2_0 import client as identity_client +from neutronclient.v2_0 import client as neutron_client +from novaclient import client as nova_client + +cfg.CONF.import_group('keystone_authtoken', 'keystonemiddleware.auth_token') + + +class SampleData(unittest.TestCase): + + def __init__(self, *args, **kwargs): + super(SampleData, self).__init__(*args, **kwargs) + self.AUTH_TOKEN = '6db9dfa4d29d442eb2b23811ad4b3a6d' + self.AUTH_URL = 'https://127.0.0.1:35357/None/' + self.ENDPOINT_URL = 'https://127.0.0.1:9696/' + self.FLAVOR_NAME = 'm1.tiny' + self.IMAGE_NAME = 'cirros-0.3.4-x86_64-uec' + self.IMAGE_ID = '7022c5a4-ef0c-4f7e-a2c8-b7f5b36c9086' + self.INSTANCE_ID = '60c7ebc4-aa70-4ee6-aad6-41e99d27ceec' + self.PASSWORD = 'admin_pass' + self.PORT_ID = '16fa0e95-3c7a-4dd6-87bd-c76b14f9eac2' + self.TENANT_ID = '384757095ca4495683c7f34ae077f8c0' + self.TENANT_NAME = 'admin' + self.USERNAME = 'admin' + + +@mock.patch.object(identity_client, "Client") +class TestKeystoneClient(SampleData): + + def __init__(self, *args, **kwargs): + super(TestKeystoneClient, self).__init__(*args, **kwargs) + self.keystone_obj = openstack_driver.KeystoneClient(cfg.CONF) + + def setUp(self): + cfg.CONF.set_override('admin_user', + 'neutron', + group='keystone_authtoken') + cfg.CONF.set_override('admin_password', + 'neutron_pass', + group='keystone_authtoken') + cfg.CONF.set_override('admin_tenant_name', + 'service', + group='keystone_authtoken') + cfg.CONF.set_override('auth_version', + 'None', + group='keystone_authtoken') + + def test_get_admin_token(self, mock_obj): + instance = mock_obj.return_value + instance.auth_token = True + retval = self.keystone_obj.get_admin_token() + self.assertTrue(retval) + mock_obj.assert_called_once_with(auth_url=self.AUTH_URL, + password='neutron_pass', + tenant_id=None, + tenant_name='service', + username='neutron') + + def test_get_scoped_keystone_token(self, mock_obj): + instance = mock_obj.return_value + instance.auth_token = True + retval = self.keystone_obj.get_scoped_keystone_token(self.USERNAME, + self.PASSWORD, + self.TENANT_NAME, + self.TENANT_ID) + self.assertTrue(retval) + mock_obj.assert_called_once_with(auth_url=self.AUTH_URL, + password=self.PASSWORD, + tenant_id=self.TENANT_ID, + tenant_name=self.TENANT_NAME, + username=self.USERNAME) + + def test_get_tenant_id(self, mock_obj): + instance = mock_obj.return_value + instance.tenants.find().id = True + retval = self.keystone_obj.get_tenant_id(self.AUTH_TOKEN, + "service") + self.assertTrue(retval) + mock_obj.assert_called_once_with(auth_url=self.AUTH_URL, + token=self.AUTH_TOKEN) + + +@mock.patch.object(nova_client, "Client") +class TestNovaClient(SampleData): + + def __init__(self, *args, **kwargs): + super(TestNovaClient, self).__init__(*args, **kwargs) + self.nova_obj = openstack_driver.NovaClient(cfg.CONF) + + @mock.patch.object(identity_client, "Client") + def test_get_image_id(self, key_obj, mock_obj): + instance = mock_obj.return_value + key_obj.return_value = True + instance.images.find().id = True + retval = self.nova_obj.get_image_id(self.AUTH_TOKEN, + self.TENANT_ID, + self.IMAGE_NAME) + self.assertTrue(retval) + mock_obj.assert_called_once_with('2', auth_token=self.AUTH_TOKEN, + tenant_id=self.TENANT_ID, + auth_url=self.AUTH_URL) + + def test_get_flavor_id(self, mock_obj): + instance = mock_obj.return_value + instance.flavors.find().id = True + retval = self.nova_obj.get_flavor_id(self.AUTH_TOKEN, + self.TENANT_ID, + self.FLAVOR_NAME) + self.assertTrue(retval) + + @mock.patch.object(identity_client, "Client") + def test_get_instance(self, key_obj, mock_obj): + instance = mock_obj.return_value + obj = instance.servers.get(self.INSTANCE_ID).to_dict() + key_obj.return_value = self.AUTH_TOKEN + retval = self.nova_obj.get_instance(self.AUTH_TOKEN, + self.TENANT_ID, + self.INSTANCE_ID) + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with('2', auth_token=self.AUTH_TOKEN, + tenant_id=self.TENANT_ID, + auth_url=self.AUTH_URL) + + def test_get_keypair(self, mock_obj): + instance = mock_obj.return_value + obj = instance.keypairs.find(name="keypair_name").to_dict() + retval = self.nova_obj.get_keypair(self.AUTH_TOKEN, + self.TENANT_ID, + "keypair_name") + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with('2', auth_token=self.AUTH_TOKEN, + tenant_id=self.TENANT_ID, + auth_url=self.AUTH_URL) + + def test_attach_interface(self, mock_obj): + instance = mock_obj.return_value + with mock.patch.object(instance.servers, + "interface_attach") as mock_obj1: + mock_obj1.return_value = True + retval = self.nova_obj.attach_interface(self.AUTH_TOKEN, + self.TENANT_ID, + self.INSTANCE_ID, + "port_id") + self.assertTrue(retval) + mock_obj.assert_called_once_with('2', auth_token=self.AUTH_TOKEN, + tenant_id=self.TENANT_ID, + auth_url=self.AUTH_URL) + + def test_detach_interface(self, mock_obj): + instance = mock_obj.return_value + with mock.patch.object(instance.servers, + "interface_detach") as mock_obj1: + mock_obj1.return_value = True + retval = self.nova_obj.detach_interface(self.AUTH_TOKEN, + self.TENANT_ID, + self.INSTANCE_ID, + "port_id") + + self.assertTrue(retval) + mock_obj.assert_called_once_with('2', auth_token=self.AUTH_TOKEN, + tenant_id=self.TENANT_ID, + auth_url=self.AUTH_URL) + + def test_delete_instance(self, mock_obj): + instance = mock_obj.return_value + with mock.patch.object(instance.servers, "delete") as mock_obj1: + mock_obj1.return_value = True + retval = self.nova_obj.delete_instance(self.AUTH_TOKEN, + self.TENANT_ID, + self.INSTANCE_ID) + + self.assertIsNone(retval) + mock_obj.assert_called_once_with('2', auth_token=self.AUTH_TOKEN, + tenant_id=self.TENANT_ID, + auth_url=self.AUTH_URL) + + def test_get_instances(self, mock_obj): + instance = mock_obj.return_value + instance.servers.list("instance_test").to_dict() + retval = self.nova_obj.get_instances(self.AUTH_TOKEN, + {'tenant_id': self.TENANT_ID}) + self.assertIsNotNone(retval) + mock_obj.assert_called_once_with('2', auth_token=self.AUTH_TOKEN, + tenant_id=self.TENANT_ID, + auth_url=self.AUTH_URL) + + def test_create_instance(self, mock_obj): + instance = mock_obj.return_value + instance.flavors.find(self.FLAVOR_NAME) + with mock.patch.object(instance.servers, "create") as mock_obj1: + instance = mock_obj1.return_value + obj1 = instance.to_dict()['id'] + retval = self.nova_obj.create_instance(self.AUTH_TOKEN, + self.TENANT_ID, + self.IMAGE_ID, + self.FLAVOR_NAME, + None, + "name", + "secgroup_name", + "metadata={}", + "files=[]", + "config_drive=False", + "userdata=None", + "key_name=''", + "different_hosts=None", + "volume_support=False", + "volume_size='2'") + + self.assertEqual(retval, obj1) + mock_obj.assert_called_once_with('2', auth_token=self.AUTH_TOKEN, + tenant_id=self.TENANT_ID, + auth_url=self.AUTH_URL) + + +@mock.patch.object(neutron_client, "Client") +class TestNeutronClient(SampleData): + + def __init__(self, *args, **kwargs): + super(TestNeutronClient, self).__init__(*args, **kwargs) + self.neutron_obj = openstack_driver.NeutronClient(cfg.CONF) + + def test_get_floating_ip(self, mock_obj): + instance = mock_obj.return_value + obj = instance.show_floatingip('floatingip_id')['floatingip'] + retval = self.neutron_obj.get_floating_ip( + self.AUTH_TOKEN, 'floatingip_id') + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + def test_get_floating_ips(self, mock_obj): + instance = mock_obj.return_value + obj = instance.list_floatingips()['floatingips'] + retval = self.neutron_obj.get_floating_ips(self.AUTH_TOKEN, + self.TENANT_ID, + self.PORT_ID) + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + def test_get_port(self, mock_obj): + instance = mock_obj.return_value + obj = instance.show_port(self.PORT_ID) + retval = self.neutron_obj.get_port(self.AUTH_TOKEN, + self.PORT_ID) + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + def test_get_ports(self, mock_obj): + instance = mock_obj.return_value + obj = instance.list_ports().get('ports', []) + retval = self.neutron_obj.get_ports(self.AUTH_TOKEN, + {}) + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + def test_get_subnets(self, mock_obj): + instance = mock_obj.return_value + obj = instance.list_subnets().get('subnets', []) + retval = self.neutron_obj.get_subnets(self.AUTH_TOKEN, {}) + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + def test_get_pools(self, mock_obj): + instance = mock_obj.return_value + obj = instance.list_pools().get('pools', []) + retval = self.neutron_obj.get_pools(self.AUTH_TOKEN, + {}) + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + def test_get_vip(self, mock_obj): + instance = mock_obj.return_value + obj = instance.show_vip('vip_id') + retval = self.neutron_obj.get_vip(self.AUTH_TOKEN, + 'vip_id') + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + def test_get_subnet(self, mock_obj): + instance = mock_obj.return_value + obj = instance.show_subnet('subnet_id') + retval = self.neutron_obj.get_subnet(self.AUTH_TOKEN, + 'subnet_id') + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + def test_delete_floatingip(self, mock_obj): + instance = mock_obj.return_value + obj = instance.delete_floatingip('floatingip_id') + retval = self.neutron_obj.delete_floatingip(self.AUTH_TOKEN, + 'floatingip_id') + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + def test_update_port(self, mock_obj): + instance = mock_obj.return_value + obj = instance.update_port('port_id', body='port_info') + retval = self.neutron_obj.update_port(self.AUTH_TOKEN, + 'port_id') + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + def test_get_floating_ips_for_ports(self, mock_obj): + instance = mock_obj.return_value + obj = instance.list_floatingips('port_id') + retval = self.neutron_obj.get_floating_ips_for_ports( + self.AUTH_TOKEN) + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + def test_disassociate_floating_ip(self, mock_obj): + instance = mock_obj.return_value + instance.update_floatingip('floatingip_id', body='data') + retval = self.neutron_obj.disassociate_floating_ip(self.AUTH_TOKEN, + 'floatingip_id') + self.assertIsNone(retval) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + def test_associate_floating_ip(self, mock_obj): + instance = mock_obj.return_value + instance.update_floatingip('floatingip_id', body='data') + retval = self.neutron_obj.associate_floating_ip(self.AUTH_TOKEN, + 'floatingip_id', + 'port_id') + self.assertIsNone(retval) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + def test_list_ports(self, mock_obj): + instance = mock_obj.return_value + obj = instance.list_ports(id='port_ids').get('ports', []) + retval = self.neutron_obj.list_ports(self.AUTH_TOKEN, + 'port_ids=[]') + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + def test_list_subnets(self, mock_obj): + instance = mock_obj.return_value + obj = instance.list_subnets(id='subnet_ids').get('subnets', []) + retval = self.neutron_obj.list_subnets(self.AUTH_TOKEN, + 'subnet_ids=[]') + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + def test_create_port(self, mock_obj): + instance = mock_obj.return_value + obj = instance.create_port(body='attr')['port'] + retval = self.neutron_obj.create_port(self.AUTH_TOKEN, + self.TENANT_ID, + 'net_id') + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + def test_delete_port(self, mock_obj): + instance = mock_obj.return_value + obj = instance.delete_port('port_id') + retval = self.neutron_obj.delete_port(self.AUTH_TOKEN, + 'port_id') + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + +@mock.patch.object(gbp_client, "Client") +class TestGBPClient(SampleData): + + def __init__(self, *args, **kwargs): + super(TestGBPClient, self).__init__(*args, **kwargs) + self.gbp_obj = openstack_driver.GBPClient(cfg.CONF) + + def test_get_policy_target_groups(self, mock_obj): + instance = mock_obj.return_value + obj = instance.list_policy_target_groups()['policy_target_groups'] + retval = self.gbp_obj.get_policy_target_groups(self.AUTH_TOKEN, {}) + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + def test_get_policy_target_group(self, mock_obj): + instance = mock_obj.return_value + obj = instance.show_policy_target_group( + 'ptg_id', {})['policy_target_group'] + retval = self.gbp_obj.get_policy_target_group(self.AUTH_TOKEN, + 'ptg_id', {}) + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + def test_update_policy_target_group(self, mock_obj): + instance = mock_obj.return_value + obj = instance.update_policy_target_group( + body='policy_target_group_info')['policy_target_group'] + retval = self.gbp_obj.update_policy_target_group( + self.AUTH_TOKEN, + 'ptg_id', + 'policy_target_group_info') + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + def test_update_policy_target(self, mock_obj): + instance = mock_obj.return_value + obj = instance.update_policy_target('policy_target_id', + body='policy_target_info')[ + 'policy_target'] + retval = self.gbp_obj.update_policy_target(self.AUTH_TOKEN, + 'policy_target_id', + 'updated_pt') + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + def test_create_policy_target(self, mock_obj): + instance = mock_obj.return_value + obj = instance.create_policy_target( + body='policy_target_info')['policy_target'] + retval = self.gbp_obj.create_policy_target(self.AUTH_TOKEN, + self.TENANT_ID, + 'policy_target_group_id', + 'name', port_id=None) + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + def test_create_policy_target_group(self, mock_obj): + instance = mock_obj.return_value + obj = instance.create_policy_target_group( + body='policy_target_group_info')['policy_target_group'] + retval = self.gbp_obj.create_policy_target_group( + self.AUTH_TOKEN, + self.TENANT_ID, + 'name', + l2_policy_id=None) + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + def test_delete_policy_target(self, mock_obj): + instance = mock_obj.return_value + obj = instance.delete_policy_target('policy_target_id') + retval = self.gbp_obj.delete_policy_target(self.AUTH_TOKEN, + 'policy_target_id') + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + def test_delete_policy_target_group(self, mock_obj): + instance = mock_obj.return_value + obj = instance.delete_policy_target_group('policy_target_id') + retval = self.gbp_obj.delete_policy_target_group( + self.AUTH_TOKEN, + 'policy_target_group_id') + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + def test_create_l2_policy(self, mock_obj): + instance = mock_obj.return_value + obj = instance.create_l2_policy(body='l2_policy_info')['l2_policy'] + retval = self.gbp_obj.create_l2_policy(self.AUTH_TOKEN, + self.TENANT_ID, + 'name', + l3_policy_id=None) + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + def test_delete_l2_policy(self, mock_obj): + instance = mock_obj.return_value + obj = instance.delete_l2_policy('l2_policy_id') + retval = self.gbp_obj.delete_l2_policy(self.AUTH_TOKEN, + 'l2_policy_id') + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + def test_get_l2_policys(self, mock_obj): + instance = mock_obj.return_value + obj = instance.list_l2_policies({})['l2_policies'] + retval = self.gbp_obj.get_l2_policys(self.AUTH_TOKEN, + filters={}) + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + def test_get_l2_policy(self, mock_obj): + instance = mock_obj.return_value + obj = instance.show_l2_policy( + 'policy_id', {})['l2_policy'] + retval = self.gbp_obj.get_l2_policy(self.AUTH_TOKEN, + 'policy_id', + filters={}) + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + def test_create_network_service_policy(self, mock_obj): + instance = mock_obj.return_value + obj = instance.create_network_service_policy( + body='network_service_policy_info')['network_service_policy'] + retval = self.gbp_obj.create_network_service_policy( + self.AUTH_TOKEN, + 'network_service_policy_info') + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + def test_get_network_service_policies(self, mock_obj): + instance = mock_obj.return_value + obj = instance.list_network_service_policies({})[ + 'network_service_policies'] + retval = self.gbp_obj.get_network_service_policies(self.AUTH_TOKEN, + filters={}) + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + def test_get_external_policies(self, mock_obj): + instance = mock_obj.return_value + obj = instance.list_external_policies({})['external_policies'] + retval = self.gbp_obj.get_external_policies(self.AUTH_TOKEN, + filters={}) + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + def test_get_policy_rule_sets(self, mock_obj): + instance = mock_obj.return_value + obj = instance.list_policy_rule_sets({})['policy_rule_sets'] + retval = self.gbp_obj.get_policy_rule_sets(self.AUTH_TOKEN, + filters={}) + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + def test_get_policy_actions(self, mock_obj): + instance = mock_obj.return_value + obj = instance.list_policy_actions({})['policy_actions'] + retval = self.gbp_obj.get_policy_actions(self.AUTH_TOKEN, + filters={}) + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + def test_get_policy_rules(self, mock_obj): + instance = mock_obj.return_value + obj = instance.list_policy_rules({})['policy_rules'] + retval = self.gbp_obj.get_policy_rules(self.AUTH_TOKEN, + filters={}) + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + def test_create_l3_policy(self, mock_obj): + instance = mock_obj.return_value + obj = instance.create_l3_policy( + body='l3_policy_info')['l3_policy'] + retval = self.gbp_obj.create_l3_policy(self.AUTH_TOKEN, + 'l3_policy_info') + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + def test_get_l3_policy(self, mock_obj): + instance = mock_obj.return_value + obj = instance.show_l3_policy('policy_id', + {})['l3_policy'] + retval = self.gbp_obj.get_l3_policy(self.AUTH_TOKEN, + 'policy_id', + filters={}) + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + def test_get_l3_policies(self, mock_obj): + instance = mock_obj.return_value + obj = instance.list_l3_policies({})['l3_policy'] + retval = self.gbp_obj.get_l3_policies(self.AUTH_TOKEN, + filters={}) + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + def test_get_policy_targets(self, mock_obj): + instance = mock_obj.return_value + obj = instance.list_policy_targets({})['policy_targets'] + retval = self.gbp_obj.get_policy_targets(self.AUTH_TOKEN, + filters={}) + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + def test_list_pt(self, mock_obj): + instance = mock_obj.return_value + obj = instance.list_policy_targets({})['policy_targets'] + retval = self.gbp_obj.list_pt(self.AUTH_TOKEN, + filters={}) + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + def test_get_policy_target(self, mock_obj): + instance = mock_obj.return_value + obj = instance.show_policy_target('pt_id', + {})['policy_target'] + retval = self.gbp_obj.get_policy_target(self.AUTH_TOKEN, + 'pt_id', + filters={}) + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + def test_get_service_profile(self, mock_obj): + instance = mock_obj.return_value + obj = instance.show_service_profile( + 'service_profile_id')['service_profile'] + retval = self.gbp_obj.get_service_profile(self.AUTH_TOKEN, + 'service_profile_id') + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + def test_get_servicechain_node(self, mock_obj): + instance = mock_obj.return_value + obj = instance.show_servicechain_node( + 'node_id')['servicechain_node'] + retval = self.gbp_obj.get_servicechain_node(self.AUTH_TOKEN, + 'node_id') + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) + + def test_get_servicechain_instance(self, mock_obj): + instance = mock_obj.return_value + obj = instance.show_servicechain_instance( + 'instance_id')['servicechain_instance'] + retval = self.gbp_obj.get_servicechain_instance(self.AUTH_TOKEN, + 'instance_id') + self.assertEqual(retval, obj) + mock_obj.assert_called_once_with(token=self.AUTH_TOKEN, + endpoint_url=self.ENDPOINT_URL) diff --git a/gbpservice/nfp/orchestrator/coal/__init__.py b/gbpservice/nfp/orchestrator/coal/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/gbpservice/nfp/orchestrator/coal/networking/__init__.py b/gbpservice/nfp/orchestrator/coal/networking/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/gbpservice/nfp/orchestrator/coal/networking/nfp_gbp_network_driver.py b/gbpservice/nfp/orchestrator/coal/networking/nfp_gbp_network_driver.py new file mode 100644 index 000000000..55e454ecd --- /dev/null +++ b/gbpservice/nfp/orchestrator/coal/networking/nfp_gbp_network_driver.py @@ -0,0 +1,78 @@ +# 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 gbpservice.nfp.orchestrator.openstack import openstack_driver +from gbpservice.nfp.orchestrator.coal.networking import( + nfp_neutron_network_driver as neutron_nd +) + + +class NFPGBPNetworkDriver(neutron_nd.NFPNeutronNetworkDriver): + def __init__(self, config): + self.config = config + super(NFPGBPNetworkDriver, self).__init__(config) + self.network_handler = openstack_driver.GBPClient(config) + + def setup_traffic_steering(self): + pass + + def create_port(self, token, tenant_id, net_id, name=None): + port = self.network_handler.create_policy_target(token, tenant_id, + net_id, name) + return port + + def delete_port(self, token, port_id): + self.network_handler.delete_policy_target(token, port_id) + + def get_port_id(self, token, port_id): + pt = self.network_handler.get_policy_target(token, port_id) + return pt['port_id'] + + def update_port(self, token, port_id, port): + pt = self.network_handler.update_policy_target(token, port_id, + port) + return pt['port_id'] + + def get_neutron_port_details(self, token, port_id): + #self.network_handler = openstack_driver.NeutronClient(self.config) + port_details = ( + super(NFPGBPNetworkDriver, self).get_port_and_subnet_details( + token, port_id)) + #self.network_handler = openstack_driver.GBPClient(self.config) + return port_details + + def get_port_details(self, token, port_id): + _port_id = self.get_port_id(token, port_id) + #self.network_handler = openstack_driver.NeutronClient(self.config) + port_details = super(NFPGBPNetworkDriver, self).get_port_details( + token, _port_id) + #self.network_handler = openstack_driver.GBPClient(self.config) + return port_details + + def get_networks(self, token, filters): + return self.network_handler.get_policy_target_groups(token, + filters=filters) + + def set_promiscuos_mode(self, token, port_id): + port_id = self.get_port_id(token, port_id) + #self.network_handler = openstack_driver.NeutronClient(self.config) + super(NFPGBPNetworkDriver, self).set_promiscuos_mode(token, port_id) + #self.network_handler = openstack_driver.GBPClient(self.config) + + def set_promiscuos_mode_fast(self, token, port_id): + #self.network_handler = openstack_driver.NeutronClient(self.config) + super(NFPGBPNetworkDriver, self).set_promiscuos_mode(token, port_id) + #self.network_handler = openstack_driver.GBPClient(self.config) + + def get_service_profile(self, token, service_profile_id): + return self.network_handler.get_service_profile(token, + service_profile_id) diff --git a/gbpservice/nfp/orchestrator/coal/networking/nfp_network_driver_base.py b/gbpservice/nfp/orchestrator/coal/networking/nfp_network_driver_base.py new file mode 100644 index 000000000..a9150d075 --- /dev/null +++ b/gbpservice/nfp/orchestrator/coal/networking/nfp_network_driver_base.py @@ -0,0 +1,38 @@ +# 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. + + +class NFPNetworkDriverBase(object): + """ NFP Network Driver Base class + + Handles ports, operations on them + """ + def __init__(self): + pass + + def setup_traffic_steering(self): + pass + + def create_port(self, token, admin_id, net_id, name=None): + pass + + def delete_port(self, token, port_id): + pass + + def get_port_id(self, token, port_id): + pass + + def get_port_details(self, token, port_id): + pass + + def set_promiscuos_mode(self, token, port_id): + pass diff --git a/gbpservice/nfp/orchestrator/coal/networking/nfp_neutron_network_driver.py b/gbpservice/nfp/orchestrator/coal/networking/nfp_neutron_network_driver.py new file mode 100644 index 000000000..79c12c869 --- /dev/null +++ b/gbpservice/nfp/orchestrator/coal/networking/nfp_neutron_network_driver.py @@ -0,0 +1,83 @@ +# 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 gbpservice.nfp.orchestrator.openstack import openstack_driver +from gbpservice.nfp.orchestrator.coal.networking import( + nfp_network_driver_base as ndb +) + + +class NFPNeutronNetworkDriver(ndb.NFPNetworkDriverBase): + + def __init__(self, config): + # self.network_handler = openstack_driver.NeutronClient(config) + self.neutron_client = openstack_driver.NeutronClient(config) + + def setup_traffic_steering(self): + pass + + def create_port(self, token, tenant_id, net_id, name=None): + port = self.neutron_client.create_port(token, tenant_id, net_id, + attrs={'name': name}) + return port + + def delete_port(self, token, port_id): + self.neutron_client.delete_port(token, port_id) + + def get_port_id(self, token, port_id): + return port_id + + def update_port(self, token, port_id, port): + port = self.neutron_client.update_port(token, port_id, port) + return port['port'] + + def get_port_and_subnet_details(self, token, port_id): + port = self.neutron_client.get_port(token, port_id) + + # ip + ip = port['port']['fixed_ips'][0]['ip_address'] + + # mac + mac = port['port']['mac_address'] + + # gateway ip + subnet_id = port['port']['fixed_ips'][0]['subnet_id'] + subnet = self.neutron_client.get_subnet(token, subnet_id) + cidr = subnet['subnet']['cidr'] + gateway_ip = subnet['subnet']['gateway_ip'] + + return (ip, mac, cidr, gateway_ip, port, subnet) + + def get_port_details(self, token, port_id): + port = self.neutron_client.get_port(token, port_id) + + # ip + ip = port['port']['fixed_ips'][0]['ip_address'] + + # mac + mac = port['port']['mac_address'] + + # gateway ip + subnet_id = port['port']['fixed_ips'][0]['subnet_id'] + subnet = self.neutron_client.get_subnet(token, subnet_id) + cidr = subnet['subnet']['cidr'] + gateway_ip = subnet['subnet']['gateway_ip'] + + return (ip, mac, cidr, gateway_ip) + + def set_promiscuos_mode(self, token, port_id): + self.neutron_client.update_port(token, port_id, + security_groups=[], + port_security_enabled=False) + + def get_service_profile(self, token, service_profile_id): + return {} diff --git a/gbpservice/nfp/orchestrator/openstack/__init__.py b/gbpservice/nfp/orchestrator/openstack/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/gbpservice/nfp/orchestrator/openstack/openstack_driver.py b/gbpservice/nfp/orchestrator/openstack/openstack_driver.py new file mode 100644 index 000000000..5baf63fb8 --- /dev/null +++ b/gbpservice/nfp/orchestrator/openstack/openstack_driver.py @@ -0,0 +1,1277 @@ +# 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 gbpclient.v2_0 import client as gbp_client +from keystoneclient.v2_0 import client as identity_client +from keystoneclient.v3 import client as keyclientv3 +from neutronclient.v2_0 import client as neutron_client +from novaclient import client as nova_client + +from gbpservice.nfp.core import log as nfp_logging +LOG = nfp_logging.getLogger(__name__) + + +class OpenstackApi(object): + """Initializes common attributes for openstack client drivers.""" + + def __init__(self, config, username=None, + password=None, tenant_name=None): + self.nova_version = '2' + self.config = config + self.identity_service = ("%s://%s:%d/%s/" % + (config.keystone_authtoken.auth_protocol, + config.keystone_authtoken.auth_host, + config.keystone_authtoken.auth_port, + config.keystone_authtoken.auth_version)) + self.network_service = ("%s://%s:%d/" % + (config.keystone_authtoken.auth_protocol, + config.keystone_authtoken.auth_host, + config.bind_port)) + self.username = username or config.keystone_authtoken.admin_user + self.password = password or config.keystone_authtoken.admin_password + self.tenant_name = (tenant_name or + config.keystone_authtoken.admin_tenant_name) + self.token = None + self.admin_tenant_id = None + + +class KeystoneClient(OpenstackApi): + """ Keystone Client Apis for orchestrator. """ + + def get_admin_token(self): + try: + admin_token = self.get_scoped_keystone_token( + self.config.keystone_authtoken.admin_user, + self.config.keystone_authtoken.admin_password, + self.config.keystone_authtoken.admin_tenant_name) + except Exception as ex: + err = ("Failed to obtain user token. Error: %s" % ex) + LOG.error(err) + raise Exception(err) + + return admin_token + + def get_scoped_keystone_token(self, user, password, tenant_name, + tenant_id=None): + """ Get a scoped token from Openstack Keystone service. + + A scoped token is bound to the specific tenant. + + :param user: User name + :param password: Password + :param tenantName: Tenant name + + :return: A scoped token or None if unable to get + """ + if not (tenant_name or tenant_id): + err = "Tenant Not specified for getting a scoped token" + LOG.error(err) + raise Exception(err) + + keystone = identity_client.Client( + username=user, + password=password, + tenant_name=tenant_name, + tenant_id=tenant_id, + auth_url=self.identity_service) + try: + scoped_token = keystone.auth_token + except Exception as err: + err = ("Failed to get scoped token from" + " Openstack Keystone service" + " KeyError :: %s" % (err)) + self.config.keystone_authtoken.auth_port, + LOG.error(err) + raise Exception(err) + else: + return scoped_token + + def get_admin_tenant_id(self, token): + if not self.admin_tenant_id: + self.admin_tenant_id = self.get_tenant_id( + token, + self.config.keystone_authtoken.admin_tenant_name) + + return self.admin_tenant_id + + def get_tenant_id(self, token, tenant_name): + """ Get the tenant UUID associated to tenant name + + :param token: A scoped token + :param tenant: Tenant name + + :return: Tenant UUID + """ + try: + keystone = identity_client.Client(token=token, + auth_url=self.identity_service) + tenant = keystone.tenants.find(name=tenant_name) + return tenant.id + except Exception as ex: + err = ("Failed to read tenant UUID from" + " tenant_name %s." + " Error :: %s" % (tenant_name, ex)) + LOG.error(err) + raise Exception(err) + err = 'No tenant with name "%s" found in keystone db' % tenant_name + LOG.error(err) + raise Exception(err) + + def _get_v2_keystone_admin_client(self): + """ Returns keystone v2 client with admin credentials + Using this client one can perform CRUD operations over + keystone resources. + """ + keystone_conf = self.config.keystone_authtoken + + v2client = identity_client.Client( + username=keystone_conf.admin_user, + password=keystone_conf.admin_password, + tenant_name=keystone_conf.admin_tenant_name, + tenant_id=None, + auth_url=self.identity_service) + + return v2client + + def _get_v3_keystone_admin_client(self): + """ Returns keystone v3 client with admin credentials + Using this client one can perform CRUD operations over + keystone resources. + """ + keystone_conf = self.config.keystone_authtoken + v3_auth_url = ('%s://%s:%s/%s/' % ( + keystone_conf.auth_protocol, keystone_conf.auth_host, + keystone_conf.auth_port, self.config.heat_driver.keystone_version)) + v3client = keyclientv3.Client( + username=keystone_conf.admin_user, + password=keystone_conf.admin_password, + domain_name="default", + auth_url=v3_auth_url) + return v3client + + +class NovaClient(OpenstackApi): + """ Nova Client Api driver. """ + + def get_image_id(self, token, tenant_id, image_name): + """ Get the image UUID associated to image name + + :param token: A scoped token + :param tenant_id: Tenant UUID + :param image_name: Image name + + :return: Image UUID + """ + try: + nova = nova_client.Client(self.nova_version, auth_token=token, + tenant_id=tenant_id, + auth_url=self.identity_service) + image = nova.images.find(name=image_name) + return image.id + except Exception as ex: + err = ("Failed to get image id from image name %s: %s" % ( + image_name, ex)) + LOG.error(err) + raise Exception(err) + + def get_image_metadata(self, token, tenant_id, image_name): + """ Get the image UUID associated to image name + + :param token: A scoped token + :param tenant_id: Tenant UUID + :param image_name: Image name + + :return: Image UUID + """ + try: + nova = nova_client.Client(self.nova_version, auth_token=token, + tenant_id=tenant_id, + auth_url=self.identity_service) + image = nova.images.find(name=image_name) + return image.metadata + except Exception as ex: + err = ("Failed to get image metadata from image name %s: %s" % ( + image_name, ex)) + LOG.error(err) + raise Exception(err) + + def get_flavor_id(self, token, tenant_id, flavor_name): + """ Get the flavor UUID associated to flavor name + + :param token: A scoped token + :param tenant_id: Tenant UUID + :param flavor_name: Flavor name + + :return: Flavor UUID or None if not found + """ + try: + nova = nova_client.Client(self.nova_version, auth_token=token, + tenant_id=tenant_id, + auth_url=self.identity_service) + flavor = nova.flavors.find(name=flavor_name) + return flavor.id + except Exception as ex: + err = ("Failed to get flavor id from flavor name %s: %s" % ( + flavor_name, ex)) + LOG.error(err) + raise Exception(err) + + def get_instance(self, token, tenant_id, instance_id): + """ Get instance details + + :param token: A scoped_token + :param tenant_id: Tenant UUID + :param instance_id: Instance UUID + + :return: Instance details + + """ + try: + nova = nova_client.Client(self.nova_version, auth_token=token, + tenant_id=tenant_id, + auth_url=self.identity_service) + instance = nova.servers.get(instance_id) + if instance: + return instance.to_dict() + raise Exception("No instance with id %s found in db for tenant %s" + % (instance_id, tenant_id)) + except Exception as ex: + err = ("Failed to read instance information from" + " Openstack Nova service's response" + " KeyError :: %s" % (ex)) + LOG.error(err) + raise Exception(err) + + def get_keypair(self, token, tenant_id, keypair_name): + """ Get Nova keypair details + + :param token: A scoped_token + :param tenant_id: Tenant UUID + :param keypair_name: Nova keypair name + + :return: Nova keypair details + + """ + tenant_id = str(tenant_id) + try: + nova = nova_client.Client(self.nova_version, auth_token=token, + tenant_id=tenant_id, + auth_url=self.identity_service) + keypair = nova.keypairs.find(name=keypair_name) + return keypair.to_dict() + except Exception as ex: + err = ("Failed to read keypair information from" + " Openstack Nova service's response." + " %s" % ex) + LOG.error(err) + raise Exception(err) + + def attach_interface(self, token, tenant_id, instance_id, port_id): + """ Attaches a port to already created instance + :param token: A scoped token + :param tenant_id: Tenant UUID + :param instance_id: UUID of the instance + :param port_id: Port UUID + """ + try: + nova = nova_client.Client(self.nova_version, auth_token=token, + tenant_id=tenant_id, + auth_url=self.identity_service) + instance = nova.servers.interface_attach(instance_id, port_id, + None, None) + return instance + except Exception as ex: + err = ("Failed to attach interface %s to instance" + " %s %s" % (port_id, instance_id, ex)) + LOG.error(err) + raise Exception(err) + + def detach_interface(self, token, tenant_id, instance_id, port_id): + """ Detaches a port to already created instance + :param token: A scoped token + :param tenant_id: Tenant UUID + :param instance_id: UUID of the instance + :param port_id: Port UUID + """ + try: + nova = nova_client.Client(self.nova_version, auth_token=token, + tenant_id=tenant_id, + auth_url=self.identity_service) + instance = nova.servers.interface_detach(instance_id, port_id) + return instance + except Exception as ex: + err = ("Failed to detach interface %s from instance" + " %s %s" % (port_id, instance_id, ex)) + LOG.error(err) + raise Exception(err) + + def delete_instance(self, token, tenant_id, instance_id): + """ Delete the instance + + :param token: A scoped token + :param tenant_id: Tenant UUID + :param instance_id: Instance UUID + + """ + try: + nova = nova_client.Client(self.nova_version, auth_token=token, + tenant_id=tenant_id, + auth_url=self.identity_service) + nova.servers.delete(instance_id) + except Exception as ex: + err = ("Failed to delete instance" + " %s %s" % (instance_id, ex)) + LOG.error(err) + raise Exception(err) + + def get_instances(self, token, filters=None): + """ List instances + + :param token: A scoped_token + :param filters: Parameters for list filter + example for filter: {}, tenant_id is mandatory + + :return: instance List + + """ + if ( + not filters or + type(filters) != dict or + 'tenant_id' not in filters + ): + err = ("Failed to process get_instances," + " filters(type: dict) with tenant_id is mandatory") + LOG.error(err) + raise Exception(err) + + tenant_id = filters.get('tenant_id') + try: + nova = nova_client.Client(self.nova_version, auth_token=token, + tenant_id=tenant_id, + auth_url=self.identity_service) + instances = nova.servers.list(search_opts=filters) + data = [instance.to_dict() for instance in instances] + return data + except Exception as ex: + err = ("Failed to list instances under tenant" + " %s %s" % (tenant_id, ex)) + LOG.error(err) + raise Exception(err) + + def create_instance(self, token, tenant_id, image_id, flavor, + nw_port_id_list, name, secgroup_name=None, + metadata=None, files=None, config_drive=False, + userdata=None, key_name='', different_hosts=None, + volume_support=False, volume_size="2"): + """ Launch a VM with given details + + :param token: A scoped token + :param tenant_id: Tenant UUID + :param image_id: Image UUID + :param flavor: Flavor name + :param nw_port_id_list: Network UUID and port UUID list + :param name: Service istance name + :param secgroup_name: Nova security group name + :param metadata: metadata key-value pairs + :param files: List of files to be copied. + :example files: [{"dst": , + "src": }] + :param userdata: user data file name + :param key_name: Nova keypair name + :param different_hosts: Different host filter (List) + :param volume_support: volume support to launch instance + :param volume_size: cinder volume size in GB + :return: VM instance UUID + + """ + kwargs = dict() + if volume_support: + block_device_mapping_v2 = [ + { + "boot_index": "1", + "uuid": image_id, + "source_type": "image", + "volume_size": volume_size, + "destination_type": "volume", + "delete_on_termination": True + } + ] + kwargs.update(block_device_mapping_v2=block_device_mapping_v2) + + if different_hosts: + kwargs.update(scheduler_hints={"different_host": different_hosts}) + if key_name != '': + kwargs.update(key_name=key_name) + if config_drive is True: + kwargs.update(config_drive=True) + if userdata is not None and type(userdata) is str: + kwargs.update(userdata=userdata) + if metadata is not None and type(metadata) is dict and metadata != {}: + kwargs.update(meta=metadata) + if files is not None and type(files) is list and files != []: + kwargs.update(files=files) + if nw_port_id_list: + nics = [{"port-id": entry.get("port"), "net-id": entry.get("uuid"), + "v4-fixed-ip": entry.get("fixed_ip")} + for entry in nw_port_id_list] + kwargs.update(nics=nics) + if secgroup_name: + kwargs.update(security_groups=[secgroup_name]) + + try: + nova = nova_client.Client(self.nova_version, auth_token=token, + tenant_id=tenant_id, + auth_url=self.identity_service) + flavor = nova.flavors.find(name=flavor) + instance = nova.servers.create(name, nova.images.get(image_id), + flavor, **kwargs) + data = instance.to_dict() + return data['id'] + except Exception as ex: + err = ("Failed to create instance under tenant" + " %s %s" % (tenant_id, ex)) + LOG.error(err) + raise Exception(err) + + +class NeutronClient(OpenstackApi): + """ Neutron Client Api Driver. """ + + def get_floating_ip(self, token, floatingip_id): + """ Get floatingip details + + :param token: A scoped_token + :param floatingip_id: Port UUID + + :return: floatingip details + + """ + try: + neutron = neutron_client.Client(token=token, + endpoint_url=self.network_service) + return neutron.show_floatingip(floatingip_id)['floatingip'] + except Exception as ex: + err = ("Failed to read floatingip from" + " Openstack Neutron service's response" + " KeyError :: %s" % (ex)) + LOG.error(err) + raise Exception(err) + + def get_floating_ips(self, token, tenant_id=None, port_id=None): + """ Get list of floatingips, associated with port if passed""" + try: + neutron = neutron_client.Client(token=token, + endpoint_url=self.network_service) + if port_id: + return neutron.list_floatingips(port_id=port_id)['floatingips'] + else: + return neutron.list_floatingips()['floatingips'] + except Exception as ex: + err = ("Failed to read floatingips from" + " Openstack Neutron service's response" + " KeyError :: %s" % (ex)) + LOG.error(err) + raise Exception(err) + + def get_port(self, token, port_id): + """ Get port details + + :param token: A scoped_token + :param port_id: Port UUID + + :return: Port details + + """ + try: + neutron = neutron_client.Client(token=token, + endpoint_url=self.network_service) + return neutron.show_port(port_id) + except Exception as ex: + err = ("Failed to read port information" + " Exception :: %s" % (ex)) + LOG.error(err) + raise Exception(err) + + def get_ports(self, token, filters=None): + """ List Ports + + :param token: A scoped_token + :param filters: Parameters for list filter + example for filter: ?tenant_id=%s&id=%s + + :return: Port List + + """ + try: + neutron = neutron_client.Client(token=token, + endpoint_url=self.network_service) + ports = neutron.list_ports(**filters).get('ports', []) + return ports + except Exception as ex: + err = ("Failed to read port list from" + " Openstack Neutron service's response" + " KeyError :: %s" % (ex)) + LOG.error(err) + raise Exception(err) + + def get_subnets(self, token, filters=None): + """ List subnets + + :param token: A scoped_token + :param filters: Parameters for list filter + example for filter: ?tenant_id=%s&id=%s + + :return: Subnet List + + """ + try: + neutron = neutron_client.Client(token=token, + endpoint_url=self.network_service) + subnets = neutron.list_subnets(**filters).get('subnets', []) + return subnets + except Exception as ex: + err = ("Failed to read subnet list from" + " Openstack Neutron service's response" + " KeyError :: %s" % (ex)) + LOG.error(err) + raise Exception(err) + + def get_subnet(self, token, subnet_id): + """ Get subnet details + :param token: A scoped_token + :param subnet_id: Subnet UUID + :return: Subnet details + """ + try: + neutron = neutron_client.Client(token=token, + endpoint_url=self.network_service) + return neutron.show_subnet(subnet_id) + except Exception as ex: + err = ("Failed to read subnet from" + " Openstack Neutron service's response" + " KeyError :: %s" % (ex)) + LOG.error(err) + raise Exception(err) + + def delete_floatingip(self, token, floatingip_id): + """ Delete the floatingip + :param token: A scoped token + :param tenant_id: Tenant UUID + :param floatingip_id: Floatingip UUID + """ + try: + neutron = neutron_client.Client(token=token, + endpoint_url=self.network_service) + return neutron.delete_floatingip(floatingip_id) + except Exception as ex: + err = ("Failed to delete floatingip from" + " Openstack Neutron service's response" + " KeyError :: %s" % (ex)) + LOG.error(err) + raise Exception(err) + + def update_port(self, token, port_id, **kwargs): + """ + :param token: + :param port_id: + :param kwargs: name=<>, allowed_address_pairs={'ip_address': <>, + 'mac_address': <>} + :return: + """ + try: + neutron = neutron_client.Client(token=token, + endpoint_url=self.network_service) + port_info = dict(port={}) + port_info['port'].update(kwargs) + return neutron.update_port(port_id, body=port_info) + except Exception as ex: + err = ("Failed to update port info" + " Error :: %s" % (ex)) + LOG.error(err) + raise Exception(err) + + def get_floating_ips_for_ports(self, token, **kwargs): + """ + :param self: + :param token: + :param kwargs: + :return: + """ + data = {'floatingips': []} + try: + neutron = neutron_client.Client(token=token, + endpoint_url=self.network_service) + data = neutron.list_floatingips(port_id=[kwargs[key] + for key in kwargs]) + return data + except Exception as ex: + raise Exception(ex) + + def _update_floatingip(self, token, floatingip_id, data): + """ Update the floatingip + :param token: A scoped token + :param floatingip_id: Floatingip UUID + :param data: data to update + """ + try: + neutron = neutron_client.Client(token=token, + endpoint_url=self.network_service) + return neutron.update_floatingip(floatingip_id, body=data) + except Exception as ex: + err = ("Failed to update floatingip from" + " Openstack Neutron service's response" + " KeyError :: %s" % (ex)) + LOG.error(err) + raise Exception(err) + + def disassociate_floating_ip(self, token, floatingip_id): + """ + :param self: + :param token: + :param floatingip_id: + :return: + """ + info = { + "floatingip": { + "port_id": None} + } + self._update_floatingip(token, floatingip_id, info) + LOG.debug("Successfully disassociated floatingip %s" + % floatingip_id) + + def associate_floating_ip(self, token, floatingip_id, port_id): + """ + :param self: + :param token: + :param floatingip_id: + :return: + """ + + info = { + "floatingip": { + "port_id": port_id} + } + + self._update_floatingip(token, floatingip_id, info) + LOG.debug("Successfully associated floatingip %s" + % floatingip_id) + + def list_ports(self, token, port_ids=None, **kwargs): + """ + :param token: + :param port_ids: + :param kwargs: + :return: + """ + try: + neutron = neutron_client.Client(token=token, + endpoint_url=self.network_service) + port_ids = port_ids if port_ids is not None else [] + ports = neutron.list_ports(id=port_ids).get('ports', []) + return ports + except Exception as ex: + err = ("Failed to list ports %s" % ex) + LOG.error(err) + raise Exception(err) + + def list_subnets(self, token, subnet_ids=None, **kwargs): + """ + :param token: + :param subnet_ids: + :param kwargs: + :return: + """ + try: + neutron = neutron_client.Client(token=token, + endpoint_url=self.network_service) + subnet_ids = subnet_ids if subnet_ids is not None else [] + subnets = neutron.list_subnets(id=subnet_ids).get('subnets', []) + return subnets + except Exception as ex: + err = ("Failed to list subnets %s" % ex) + LOG.error(err) + raise Exception(err) + + def create_port(self, token, tenant_id, net_id, attrs=None): + + attr = { + 'port': { + # 'tenant_id': tenant_id, + 'network_id': net_id + } + } + + if attrs: + attr['port'].update(attrs) + + try: + neutron = neutron_client.Client(token=token, + endpoint_url=self.network_service) + return neutron.create_port(body=attr)['port'] + except Exception as ex: + raise Exception("Port creation failed in network: %r of tenant: %r" + " Error: %s" % (net_id, tenant_id, ex)) + + def delete_port(self, token, port_id): + """ + :param token: + :param port_id: + :return: + """ + try: + neutron = neutron_client.Client(token=token, + endpoint_url=self.network_service) + return neutron.delete_port(port_id) + except Exception as ex: + err = ("Failed to delete port %s" + " Exception :: %s" % (port_id, ex)) + LOG.error(err) + raise Exception(err) + + def get_pools(self, token, filters=None): + """ List Pools + + :param token: A scoped_token + :param filters: Parameters for list filter + example for filter: ?tenant_id=%s&id=%s + + :return: Pool List + + """ + try: + neutron = neutron_client.Client(token=token, + endpoint_url=self.network_service) + pools = neutron.list_pools(**filters).get('pools', []) + return pools + except Exception as ex: + err = ("Failed to read pool list from" + " Openstack Neutron service's response" + " KeyError :: %s" % (ex)) + LOG.error(err) + raise Exception(err) + + def get_vip(self, token, vip_id): + """ Get vip details + + :param token: A scoped_token + :param vip_id: Port UUID + + :return: VIP details + + """ + try: + neutron = neutron_client.Client(token=token, + endpoint_url=self.network_service) + return neutron.show_vip(vip_id) + except Exception as ex: + err = ("Failed to read vip information" + " Exception :: %s" % (ex)) + LOG.error(err) + raise Exception(err) + + +class GBPClient(OpenstackApi): + """ GBP Client Api Driver. """ + + def get_policy_target_groups(self, token, filters=None): + """ List Policy Target Groups + + :param token: A scoped_token + :param filters: Parameters for list filter + example for filter: ?tenant_id=%s&id=%s + + :return: PTG List + + """ + try: + gbp = gbp_client.Client(token=token, + endpoint_url=self.network_service) + return gbp.list_policy_target_groups( + **filters)['policy_target_groups'] + except Exception as ex: + err = ("Failed to read PTG list from" + " Openstack Neutron service's response." + " KeyError :: %s" % (ex)) + LOG.error(err) + raise Exception(err) + + def get_policy_target_group(self, token, ptg_id, filters=None): + """ + :param token: A scoped token + :param ptg_id: PTG + :param filters: Optional + :return: + """ + try: + gbp = gbp_client.Client(token=token, + endpoint_url=self.network_service) + filters = filters if filters is not None else {} + return gbp.show_policy_target_group( + ptg_id, **filters)['policy_target_group'] + except Exception as ex: + err = ("Failed to read PTG list from" + " Openstack Neutron service's response." + " KeyError :: %s" % (ex)) + LOG.error(err) + raise Exception(err) + + def update_policy_target_group(self, token, ptg_id, + policy_target_group_info): + """ Updates a GBP Policy Target Group + + :param token: A scoped token + :param ptg_id: PTG UUID + :param policy_target_group_info: PTG info dict + :return: PTG dict + """ + try: + gbp = gbp_client.Client(token=token, + endpoint_url=self.network_service) + return gbp.update_policy_target_group( + ptg_id, + body=policy_target_group_info)['policy_target_group'] + except Exception as ex: + err = ("Failed to update policy target group. Error :: %s" % (ex)) + LOG.error(err) + raise Exception(err) + + def create_policy_target(self, token, tenant_id, + policy_target_group_id, name, port_id=None): + """ Creates a GBP Policy Target + + :param token: A scoped token + :param tenant_id: Tenant UUID + :param policy_target_group_id: PTG UUID + :param name: PT name + :return: PT dict + """ + policy_target_info = { + "policy_target": { + "policy_target_group_id": policy_target_group_id, + "tenant_id": tenant_id, + } + } + if name: + policy_target_info['policy_target'].update({'name': name}) + if port_id: + policy_target_info["policy_target"]["port_id"] = port_id + + try: + gbp = gbp_client.Client(token=token, + endpoint_url=self.network_service) + return gbp.create_policy_target( + body=policy_target_info)['policy_target'] + + except Exception as ex: + err = ("Failed to read policy target information from" + " Openstack Neutron service's response." + " KeyError :: %s" % (ex)) + LOG.error(err) + raise Exception(err) + + def delete_policy_target(self, token, policy_target_id): + """ Delete the GBP policy_target + :param token: A scoped token + :param policy_target_id: PT UUID + """ + try: + gbp = gbp_client.Client(token=token, + endpoint_url=self.network_service) + return gbp.delete_policy_target(policy_target_id) + + except Exception as ex: + err = ("Failed to delete policy target information from" + " Openstack Neutron service's response." + " KeyError :: %s" % (ex)) + LOG.error(err) + raise Exception(err) + + def delete_policy_target_group(self, token, policy_target_group_id): + """ Delete the GBP policy_target group + :param token: A scoped token + :param policy_target_id: PTG UUID + """ + try: + gbp = gbp_client.Client(token=token, + endpoint_url=self.network_service) + return gbp.delete_policy_target_group(policy_target_group_id) + except Exception as ex: + err = ("Failed to delete policy target group from" + " Openstack." + " Error :: %s" % (ex)) + LOG.error(err) + raise Exception(err) + + def update_policy_target(self, token, policy_target_id, updated_pt): + """ Update the Policy Target + :param token: A scoped token + :param policy_target_id: PT UUID + :param updated_pt: New PT dict + {\"policy_target\": {\"description\": \"test123\"}} + """ + + policy_target_info = { + "policy_target": updated_pt + } + + try: + gbp = gbp_client.Client(token=token, + endpoint_url=self.network_service) + return gbp.update_policy_target( + policy_target_id, body=policy_target_info)['policy_target'] + except Exception as ex: + err = ("Failed to read updated PT information" + ". PT %s." + " KeyError :: %s" % (policy_target_id, ex)) + LOG.error(err) + raise Exception(err) + + def create_policy_target_group(self, token, tenant_id, name, + l2_policy_id=None): + """ Creates a GBP Policy Target Group + + :param token: A scoped token + :param tenant_id: Tenant UUID + :param name: PTG name + :return: PTG dict + """ + + policy_target_group_info = { + "policy_target_group": { + "tenant_id": tenant_id, + "name": name, + } + } + + if l2_policy_id: + policy_target_group_info["policy_target_group"].update( + {"l2_policy_id": l2_policy_id}) + + try: + gbp = gbp_client.Client(token=token, + endpoint_url=self.network_service) + return gbp.create_policy_target_group( + body=policy_target_group_info)['policy_target_group'] + except Exception as ex: + err = ("Failed to create policy target group. %s" + " Error :: %s" % (policy_target_group_info, ex)) + LOG.error(err) + raise Exception(err) + + def create_l2_policy(self, token, tenant_id, name, l3_policy_id=None): + + l2_policy_info = { + "l2_policy": { + "tenant_id": tenant_id, + "name": name + } + } + if l3_policy_id: + l2_policy_info["l2_policy"].update({'l3_policy_id': l3_policy_id}) + + try: + gbp = gbp_client.Client(token=token, + endpoint_url=self.network_service) + return gbp.create_l2_policy(body=l2_policy_info)['l2_policy'] + except Exception as ex: + err = ("Failed to create l2 policy under tenant" + " %s. Error :: %s" % (tenant_id, ex)) + LOG.error(err) + raise Exception(err) + + def delete_l2_policy(self, token, l2policy_id): + """ + :param token: + :param l2policy_id: + :return: + """ + try: + gbp = gbp_client.Client(token=token, + endpoint_url=self.network_service) + return gbp.delete_l2_policy(l2policy_id) + except Exception as ex: + err = ("Failed to delete l2 policy %s. Reason %s" % + (l2policy_id, ex)) + LOG.error(err) + raise Exception(err) + + # NOTE: The plural form in the function name is needed in that way + # to construct the function generically + def get_l2_policys(self, token, filters=None): + """ List L2 policies + + :param token: A scoped_token + :param filters: Parameters for list filter + example for filter: {} + + :return: L2 policies List + + """ + try: + gbp = gbp_client.Client(token=token, + endpoint_url=self.network_service) + filters = filters if filters is not None else {} + return gbp.list_l2_policies(**filters)['l2_policies'] + except Exception as ex: + err = ("Failed to list l2 policies. Reason %s" % ex) + LOG.error(err) + raise Exception(err) + + def get_l2_policy(self, token, policy_id, filters=None): + """ List L2 policies + + :param token: A scoped_token + :param policy_id: l2 policy id + :param filters: Parameters for list filter + example for filter: {} + + :return: L2 policies List + + """ + try: + gbp = gbp_client.Client(token=token, + endpoint_url=self.network_service) + filters = filters if filters is not None else {} + return gbp.show_l2_policy( + policy_id, **filters)['l2_policy'] + except Exception as ex: + err = ("Failed to read l2 policy list from" + " Openstack Neutron service's response." + " KeyError :: %s" % (ex)) + LOG.error(err) + raise Exception(err) + + def create_network_service_policy(self, token, + network_service_policy_info): + + try: + gbp = gbp_client.Client(token=token, + endpoint_url=self.network_service) + return gbp.create_network_service_policy( + body=network_service_policy_info)['network_service_policy'] + except Exception as ex: + err = ("Failed to create network service policy " + "Error :: %s" % (ex)) + LOG.error(err) + raise Exception(err) + + def get_network_service_policies(self, token, filters=None): + """ List network service policies + + :param token: A scoped_token + :param filters: Parameters for list filter + example for filter: {} + + :return: network service policy List + + """ + try: + gbp = gbp_client.Client(token=token, + endpoint_url=self.network_service) + filters = filters if filters is not None else {} + return gbp.list_network_service_policies(**filters)[ + 'network_service_policies'] + except Exception as ex: + err = ("Failed to list network service policies. Reason %s" % ex) + LOG.error(err) + raise Exception(err) + + def get_external_policies(self, token, filters=None): + """ List external policies + + :param token: A scoped_token + :param filters: Parameters for list filter + example for filter: {} + + :return: external policy List + + """ + try: + gbp = gbp_client.Client(token=token, + endpoint_url=self.network_service) + filters = filters if filters is not None else {} + return gbp.list_external_policies(**filters)['external_policies'] + except Exception as ex: + err = ("Failed to list external policies. Reason %s" % ex) + LOG.error(err) + raise Exception(err) + + def get_policy_rule_sets(self, token, filters=None): + """ List policy rule sets + + :param token: A scoped_token + :param filters: Parameters for list filter + example for filter: {} + + :return: policy rule set List + + """ + try: + gbp = gbp_client.Client(token=token, + endpoint_url=self.network_service) + filters = filters if filters is not None else {} + return gbp.list_policy_rule_sets(**filters)['policy_rule_sets'] + except Exception as ex: + err = ("Failed to list policy rule sets. Reason %s" % ex) + LOG.error(err) + raise Exception(err) + + def get_policy_actions(self, token, filters=None): + """ List policy actions + + :param token: A scoped_token + :param filters: Parameters for list filter + example for filter: {} + + :return: policy actions List + + """ + try: + gbp = gbp_client.Client(token=token, + endpoint_url=self.network_service) + filters = filters if filters is not None else {} + return gbp.list_policy_actions(**filters)['policy_actions'] + except Exception as ex: + err = ("Failed to list policy actions. Reason %s" % ex) + LOG.error(err) + raise Exception(err) + + def get_policy_rules(self, token, filters=None): + """ List policy rules + + :param token: A scoped_token + :param filters: Parameters for list filter + example for filter: {} + + :return: policy rules List + + """ + try: + gbp = gbp_client.Client(token=token, + endpoint_url=self.network_service) + filters = filters if filters is not None else {} + return gbp.list_policy_rules(**filters)['policy_rules'] + except Exception as ex: + err = ("Failed to list policy rules. Reason %s" % ex) + LOG.error(err) + raise Exception(err) + + def create_l3_policy(self, token, l3_policy_info): # tenant_id, name): + + try: + gbp = gbp_client.Client(token=token, + endpoint_url=self.network_service) + return gbp.create_l3_policy(body=l3_policy_info)['l3_policy'] + except Exception as ex: + err = ("Failed to create l3 policy under tenant" + " %s. Error :: %s" + % (l3_policy_info['l3_policy']['tenant_id'], ex)) + LOG.error(err) + raise Exception(err) + + def get_l3_policy(self, token, policy_id, filters=None): + """ List L3 policies + + :param token: A scoped_token + :param filters: Parameters for list filter + example for filter: {} + + :return: L3 policies List + + """ + try: + gbp = gbp_client.Client(token=token, + endpoint_url=self.network_service) + filters = filters if filters is not None else {} + return gbp.show_l3_policy( + policy_id, **filters)['l3_policy'] + except Exception as ex: + err = ("Failed to read l3 policy list from" + " Openstack Neutron service's response." + " KeyError :: %s" % (ex)) + LOG.error(err) + raise Exception(err) + + def get_l3_policies(self, token, filters=None): + """ List L3 policies + + :param token: A scoped_token + :param filters: Parameters for list filter + example for filter: {} + + :return: L2 policies List + + """ + try: + gbp = gbp_client.Client(token=token, + endpoint_url=self.network_service) + filters = filters if filters is not None else {} + return gbp.list_l3_policies(**filters)['l3_policies'] + except Exception as ex: + err = ("Failed to list l3 policies. Reason %s" % ex) + LOG.error(err) + raise Exception(err) + + def get_policy_targets(self, token, filters=None): + """ List Policy Targets + + :param token: A scoped_token + :param filters: Parameters for list filter + example for filter: {} + + :return: PT List + + """ + try: + gbp = gbp_client.Client(token=token, + endpoint_url=self.network_service) + filters = filters if filters is not None else {} + return gbp.list_policy_targets(**filters)['policy_targets'] + except Exception as ex: + err = ("Failed to read PT list." + " Error :: %s" % (ex)) + LOG.error(err) + raise Exception(err) + + def list_pt(self, token, filters=None): + filters = filters if filters is not None else {} + return self.get_policy_targets(token, filters=filters) + + def get_policy_target(self, token, pt_id, filters=None): + try: + gbp = gbp_client.Client(token=token, + endpoint_url=self.network_service) + filters = filters if filters is not None else {} + return gbp.show_policy_target(pt_id, + **filters)['policy_target'] + except Exception as ex: + err = ("Failed to read PT information" + ". PT %s." + " Error :: %s" % (pt_id, ex)) + LOG.error(err) + raise Exception(err) + + def get_service_profile(self, token, service_profile_id): + gbp = gbp_client.Client(token=token, + endpoint_url=self.network_service) + return gbp.show_service_profile(service_profile_id)['service_profile'] + + def get_servicechain_node(self, token, node_id): + gbp = gbp_client.Client(token=token, + endpoint_url=self.network_service) + return gbp.show_servicechain_node(node_id)['servicechain_node'] + + def get_servicechain_instance(self, token, instance_id): + gbp = gbp_client.Client(token=token, + endpoint_url=self.network_service) + return gbp.show_servicechain_instance(instance_id)[ + 'servicechain_instance'] diff --git a/test-requirements.txt b/test-requirements.txt index b829df66b..6ba5c7cfd 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -5,6 +5,7 @@ setuptools>=19.2 -e git+https://git.openstack.org/openstack/neutron.git@stable/mitaka#egg=neutron -e git+https://github.com/noironetworks/apic-ml2-driver.git@master#egg=apic_ml2 +-e git+https://git.openstack.org/openstack/python-group-based-policy-client@master#egg=gbpclient hacking<0.11,>=0.10.0 cliff>=1.15.0 # Apache-2.0