diff options
author | 2017-07-13 19:55:08 +0000 | |
---|---|---|
committer | 2017-07-13 19:55:08 +0000 | |
commit | b490e8dc9fb01c6f9c44dd9a585ca1a1ae00bf19 (patch) | |
tree | a7545c34d10803375b606f0abcf88d2b2f955268 | |
parent | 317a6f8c44efbefaeb800edafcc6fb4cb88bedea (diff) | |
parent | 7f989290a14c836b4982e1548d24c9c09f9a0068 (diff) |
Merge "Created domain class for routers."
-rw-r--r-- | snaps/domain/network.py | 44 | ||||
-rw-r--r-- | snaps/domain/test/network_tests.py | 55 | ||||
-rw-r--r-- | snaps/openstack/create_instance.py | 4 | ||||
-rw-r--r-- | snaps/openstack/create_network.py | 15 | ||||
-rw-r--r-- | snaps/openstack/create_router.py | 10 | ||||
-rw-r--r-- | snaps/openstack/tests/create_network_tests.py | 26 | ||||
-rw-r--r-- | snaps/openstack/tests/create_router_tests.py | 107 | ||||
-rw-r--r-- | snaps/openstack/utils/neutron_utils.py | 36 | ||||
-rw-r--r-- | snaps/openstack/utils/tests/neutron_utils_tests.py | 8 | ||||
-rw-r--r-- | snaps/test_suite_builder.py | 12 |
10 files changed, 263 insertions, 54 deletions
diff --git a/snaps/domain/network.py b/snaps/domain/network.py index 8ac5300..0ba9e99 100644 --- a/snaps/domain/network.py +++ b/snaps/domain/network.py @@ -37,6 +37,50 @@ class Port: self.ips == other.ips, self.mac_address == other.mac_address) +class Router: + """ + SNAPS domain object for routers. Should contain attributes that are shared + amongst cloud providers + """ + def __init__(self, **kwargs): + """ + Constructor + :param name: the router's name + :param id: the router's id + """ + self.name = kwargs.get('name') + self.id = kwargs.get('id') + self.status = kwargs.get('status') + self.tenant_id = kwargs.get('tenant_id') + self.admin_state_up = kwargs.get('admin_state_up') + self.external_gateway_info = kwargs.get('external_gateway_info') + + def __eq__(self, other): + return (self.name == other.name and self.id == other.id and + self.status == other.status and + self.tenant_id == other.tenant_id and + self.admin_state_up == other.admin_state_up and + self.external_gateway_info == other.external_gateway_info) + + +class InterfaceRouter: + """ + SNAPS domain object for interface routers. Should contain attributes that + are shared amongst cloud providers + """ + def __init__(self, **kwargs): + """ + Constructor + """ + self.id = kwargs.get('id') + self.subnet_id = kwargs.get('subnet_id') + self.port_id = kwargs.get('port_id') + + def __eq__(self, other): + return (self.id == other.id and self.subnet_id == other.subnet_id and + self.port_id == other.port_id) + + class SecurityGroup: """ SNAPS domain object for SecurityGroups. Should contain attributes that diff --git a/snaps/domain/test/network_tests.py b/snaps/domain/test/network_tests.py index 13015b2..c394b4a 100644 --- a/snaps/domain/test/network_tests.py +++ b/snaps/domain/test/network_tests.py @@ -14,7 +14,8 @@ # limitations under the License. import unittest -from snaps.domain.network import Port, SecurityGroup, SecurityGroupRule +from snaps.domain.network import ( + Port, SecurityGroup, SecurityGroupRule, Router, InterfaceRouter) class PortDomainObjectTests(unittest.TestCase): @@ -38,9 +39,57 @@ class PortDomainObjectTests(unittest.TestCase): self.assertEqual(ips, port.ips) +class RouterDomainObjectTests(unittest.TestCase): + """ + Tests the construction of the snaps.domain.network.Router class + """ + + def test_construction_kwargs(self): + sec_grp = Router( + **{'name': 'name', 'id': 'id', 'status': 'hello', + 'tenant_id': '1234', 'admin_state_up': 'yes', + 'external_gateway_info': 'no'}) + self.assertEqual('name', sec_grp.name) + self.assertEqual('id', sec_grp.id) + self.assertEqual('hello', sec_grp.status) + self.assertEqual('1234', sec_grp.tenant_id) + self.assertEqual('yes', sec_grp.admin_state_up) + self.assertEqual('no', sec_grp.external_gateway_info) + + def test_construction_named(self): + sec_grp = Router( + external_gateway_info='no', admin_state_up='yes', tenant_id='1234', + status='hello', id='id', name='name') + self.assertEqual('name', sec_grp.name) + self.assertEqual('id', sec_grp.id) + self.assertEqual('hello', sec_grp.status) + self.assertEqual('1234', sec_grp.tenant_id) + self.assertEqual('yes', sec_grp.admin_state_up) + self.assertEqual('no', sec_grp.external_gateway_info) + + +class InterfaceRouterDomainObjectTests(unittest.TestCase): + """ + Tests the construction of the snaps.domain.network.InterfaceRouter class + """ + + def test_construction_kwargs(self): + sec_grp = InterfaceRouter( + **{'id': 'id', 'subnet_id': 'foo', 'port_id': 'bar'}) + self.assertEqual('id', sec_grp.id) + self.assertEqual('foo', sec_grp.subnet_id) + self.assertEqual('bar', sec_grp.port_id) + + def test_construction_named(self): + sec_grp = InterfaceRouter(port_id='bar', subnet_id='foo', id='id') + self.assertEqual('id', sec_grp.id) + self.assertEqual('foo', sec_grp.subnet_id) + self.assertEqual('bar', sec_grp.port_id) + + class SecurityGroupDomainObjectTests(unittest.TestCase): """ - Tests the construction of the snaps.domain.test.SecurityGroup class + Tests the construction of the snaps.domain.network.SecurityGroup class """ def test_construction_proj_id_kwargs(self): @@ -68,7 +117,7 @@ class SecurityGroupDomainObjectTests(unittest.TestCase): class SecurityGroupRuleDomainObjectTests(unittest.TestCase): """ - Tests the construction of the snaps.domain.test.SecurityGroupRule class + Tests the construction of the snaps.domain.network.SecurityGroupRule class """ def test_construction_kwargs(self): diff --git a/snaps/openstack/create_instance.py b/snaps/openstack/create_instance.py index c970a31..08e90c1 100644 --- a/snaps/openstack/create_instance.py +++ b/snaps/openstack/create_instance.py @@ -190,10 +190,10 @@ class OpenStackVmInstance: :return: the external network name or None """ router = neutron_utils.get_router_by_name(self.__neutron, router_name) - if router and router['router'].get('external_gateway_info'): + if router and router.external_gateway_info: network = neutron_utils.get_network_by_id( self.__neutron, - router['router']['external_gateway_info']['network_id']) + router.external_gateway_info['network_id']) if network: return network['network']['name'] return None diff --git a/snaps/openstack/create_network.py b/snaps/openstack/create_network.py index 3aa379b..96fca77 100644 --- a/snaps/openstack/create_network.py +++ b/snaps/openstack/create_network.py @@ -524,3 +524,18 @@ class PortSettings: if self.device_id: out['device_id'] = self.device_id return {'port': out} + + def __eq__(self, other): + return (self.name == other.name and + self.network_name == other.network_name and + self.admin_state_up == other.admin_state_up and + self.project_name == other.project_name and + self.mac_address == other.mac_address and + self.ip_addrs == other.ip_addrs and + self.fixed_ips == other.fixed_ips and + self.security_groups == other.security_groups and + self.allowed_address_pairs == other.allowed_address_pairs and + self.opt_value == other.opt_value and + self.opt_name == other.opt_name and + self.device_owner == other.device_owner and + self.device_id == other.device_id) diff --git a/snaps/openstack/create_router.py b/snaps/openstack/create_router.py index ffdf2e6..89c3431 100644 --- a/snaps/openstack/create_router.py +++ b/snaps/openstack/create_router.py @@ -120,7 +120,7 @@ class OpenStackRouter: for port in self.__ports: logger.info( 'Removing router interface from router %s and port %s', - self.router_settings.name, port['port']['name']) + self.router_settings.name, port.name) try: neutron_utils.remove_interface_router(self.__neutron, self.__router, port=port) @@ -199,10 +199,12 @@ class RouterSettings: self.internal_subnets = list() self.port_settings = list() - if kwargs.get('interfaces'): - interfaces = kwargs['interfaces'] + if kwargs.get('interfaces', kwargs.get('port_settings')): + interfaces = kwargs.get('interfaces', kwargs.get('port_settings')) for interface in interfaces: - if interface.get('port'): + if isinstance(interface, PortSettings): + self.port_settings.append(interface) + else: self.port_settings.append( PortSettings(**interface['port'])) diff --git a/snaps/openstack/tests/create_network_tests.py b/snaps/openstack/tests/create_network_tests.py index c66cd48..1bb1369 100644 --- a/snaps/openstack/tests/create_network_tests.py +++ b/snaps/openstack/tests/create_network_tests.py @@ -508,18 +508,21 @@ class CreateNetworkTypeTests(OSComponentTestCase): """ # Create Network network_type = 'vlan' - net_settings = NetworkSettings(name=self.net_config.network_settings.name, - subnet_settings=self.net_config.network_settings.subnet_settings, - network_type=network_type) + net_settings = NetworkSettings( + name=self.net_config.network_settings.name, + subnet_settings=self.net_config.network_settings.subnet_settings, + network_type=network_type) # When setting the network_type, creds must be admin self.net_creator = OpenStackNetwork(self.os_creds, net_settings) network = self.net_creator.create() # Validate network was created - neutron_utils_tests.validate_network(self.neutron, net_settings.name, True) + neutron_utils_tests.validate_network( + self.neutron, net_settings.name, True) - self.assertEquals(network_type, network['network']['provider:network_type']) + self.assertEquals( + network_type, network['network']['provider:network_type']) def test_create_network_type_vxlan(self): """ @@ -552,16 +555,19 @@ class CreateNetworkTypeTests(OSComponentTestCase): # TODO - this value must be variable to work on all OpenStack pods physical_network = 'datacentre' - net_settings = NetworkSettings(name=self.net_config.network_settings.name, - subnet_settings=self.net_config.network_settings.subnet_settings, - network_type=network_type, physical_network=physical_network) + net_settings = NetworkSettings( + name=self.net_config.network_settings.name, + subnet_settings=self.net_config.network_settings.subnet_settings, + network_type=network_type, physical_network=physical_network) self.net_creator = OpenStackNetwork(self.os_creds, net_settings) network = self.net_creator.create() # Validate network was created - neutron_utils_tests.validate_network(self.neutron, net_settings.name, True) + neutron_utils_tests.validate_network( + self.neutron, net_settings.name, True) - self.assertEquals(network_type, network['network']['provider:network_type']) + self.assertEquals(network_type, + network['network']['provider:network_type']) def test_create_network_type_foo(self): """ diff --git a/snaps/openstack/tests/create_router_tests.py b/snaps/openstack/tests/create_router_tests.py index bd2588a..5f2534d 100644 --- a/snaps/openstack/tests/create_router_tests.py +++ b/snaps/openstack/tests/create_router_tests.py @@ -12,12 +12,13 @@ # 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 unittest import uuid from snaps.openstack import create_network from snaps.openstack import create_router -from snaps.openstack.create_network import NetworkSettings +from snaps.openstack.create_network import ( + NetworkSettings, PortSettings) from snaps.openstack.create_network import OpenStackNetwork from snaps.openstack.create_router import RouterSettings from snaps.openstack.tests.os_source_file_test import OSIntegrationTestCase @@ -31,6 +32,91 @@ static_gateway_ip1 = '10.200.201.1' static_gateway_ip2 = '10.200.202.1' +class RouterSettingsUnitTests(unittest.TestCase): + """ + Class for testing the RouterSettings class + """ + + def test_no_params(self): + with self.assertRaises(Exception): + RouterSettings() + + def test_empty_config(self): + with self.assertRaises(Exception): + RouterSettings(**dict()) + + def test_name_only(self): + settings = RouterSettings(name='foo') + self.assertEqual('foo', settings.name) + self.assertIsNone(settings.project_name) + self.assertIsNone(settings.external_gateway) + self.assertIsNone(settings.admin_state_up) + self.assertIsNone(settings.enable_snat) + self.assertIsNone(settings.external_fixed_ips) + self.assertIsNotNone(settings.internal_subnets) + self.assertTrue(isinstance(settings.internal_subnets, list)) + self.assertEqual(0, len(settings.internal_subnets)) + self.assertIsNotNone(settings.port_settings) + self.assertTrue(isinstance(settings.port_settings, list)) + self.assertEqual(0, len(settings.port_settings)) + + def test_config_with_name_only(self): + settings = RouterSettings(**{'name': 'foo'}) + self.assertEqual('foo', settings.name) + self.assertIsNone(settings.project_name) + self.assertIsNone(settings.external_gateway) + self.assertIsNone(settings.admin_state_up) + self.assertIsNone(settings.enable_snat) + self.assertIsNone(settings.external_fixed_ips) + self.assertIsNotNone(settings.internal_subnets) + self.assertTrue(isinstance(settings.internal_subnets, list)) + self.assertEqual(0, len(settings.internal_subnets)) + self.assertIsNotNone(settings.port_settings) + self.assertTrue(isinstance(settings.port_settings, list)) + self.assertEqual(0, len(settings.port_settings)) + + def test_all(self): + port_settings = PortSettings(name='foo', network_name='bar') + settings = RouterSettings( + name='foo', project_name='bar', external_gateway='foo_gateway', + admin_state_up=True, enable_snat=False, external_fixed_ips=['ip1'], + internal_subnets=['10.0.0.1/24'], interfaces=[port_settings]) + self.assertEqual('foo', settings.name) + self.assertEqual('bar', settings.project_name) + self.assertEqual('foo_gateway', settings.external_gateway) + self.assertTrue(settings.admin_state_up) + self.assertFalse(settings.enable_snat) + self.assertEqual(['ip1'], settings.external_fixed_ips) + self.assertIsNotNone(settings.internal_subnets) + self.assertTrue(isinstance(settings.internal_subnets, list)) + self.assertEqual(1, len(settings.internal_subnets)) + self.assertEqual(['10.0.0.1/24'], settings.internal_subnets) + self.assertEqual([port_settings], settings.port_settings) + + def test_config_all(self): + settings = RouterSettings( + **{'name': 'foo', 'project_name': 'bar', + 'external_gateway': 'foo_gateway', 'admin_state_up': True, + 'enable_snat': False, 'external_fixed_ips': ['ip1'], + 'internal_subnets': ['10.0.0.1/24'], + 'interfaces': + [{'port': {'name': 'foo-port', + 'network_name': 'bar-net'}}]}) + self.assertEqual('foo', settings.name) + self.assertEqual('bar', settings.project_name) + self.assertEqual('foo_gateway', settings.external_gateway) + self.assertTrue(settings.admin_state_up) + self.assertFalse(settings.enable_snat) + self.assertEqual(['ip1'], settings.external_fixed_ips) + self.assertIsNotNone(settings.internal_subnets) + self.assertTrue(isinstance(settings.internal_subnets, list)) + self.assertEqual(1, len(settings.internal_subnets)) + self.assertEqual(['10.0.0.1/24'], settings.internal_subnets) + self.assertEqual([PortSettings(**{'name': 'foo-port', + 'network_name': 'bar-net'})], + settings.port_settings) + + class CreateRouterSuccessTests(OSIntegrationTestCase): """ Class for testing routers with various positive scenarios expected to @@ -277,7 +363,7 @@ def verify_router_attributes(router_operational, router_creator, Helper function to validate the attributes of router created with the one operational :param router_operational: Operational Router object returned from neutron - utils + utils of type snaps.domain.Router :param router_creator: router_creator object returned from creating a router in the router test functions :param admin_state: True if router is expected to be Up, else False @@ -291,21 +377,20 @@ def verify_router_attributes(router_operational, router_creator, return False elif not router_creator: return False - elif not (router_operational['router'][ - 'name'] == router_creator.router_settings.name): + elif not (router_operational.name == router_creator.router_settings.name): return False - elif not (router_operational['router']['id'] == router['router']['id']): + elif not (router_operational.id == router.id): return False - elif not (router_operational['router']['status'] == router['router']['status']): + elif not (router_operational.status == router.status): return False - elif not (router_operational['router']['tenant_id'] == router['router']['tenant_id']): + elif not (router_operational.tenant_id == router.tenant_id): return False - elif not (admin_state == router_operational['router']['admin_state_up']): + elif not (admin_state == router_operational.admin_state_up): return False elif (ext_gateway is None) and \ - (router_operational['router']['external_gateway_info'] is not None): + (router_operational.external_gateway_info is not None): return False elif ext_gateway is not None: - if router_operational['router']['external_gateway_info'] is None: + if router_operational.external_gateway_info is None: return False return True diff --git a/snaps/openstack/utils/neutron_utils.py b/snaps/openstack/utils/neutron_utils.py index e1bed66..aaa0903 100644 --- a/snaps/openstack/utils/neutron_utils.py +++ b/snaps/openstack/utils/neutron_utils.py @@ -17,7 +17,8 @@ import logging from neutronclient.common.exceptions import NotFound from neutronclient.neutron.client import Client -from snaps.domain.network import Port, SecurityGroup, SecurityGroupRule +from snaps.domain.network import ( + Port, SecurityGroup, SecurityGroupRule, Router, InterfaceRouter) from snaps.domain.vm_inst import FloatingIp from snaps.openstack.utils import keystone_utils @@ -168,12 +169,13 @@ def create_router(neutron, os_creds, router_settings): :param router_settings: A dictionary containing the router configuration and is responsible for creating the subnet request JSON body - :return: the router object + :return: a SNAPS-OO Router domain object """ if neutron: json_body = router_settings.dict_for_neutron(neutron, os_creds) logger.info('Creating router with name - ' + router_settings.name) - return neutron.create_router(json_body) + os_router = neutron.create_router(json_body) + return Router(**os_router['router']) else: logger.error("Failed to create router.") raise Exception @@ -183,12 +185,11 @@ def delete_router(neutron, router): """ Deletes a router for OpenStack :param neutron: the client - :param router: the router object + :param router: a SNAPS-OO Router domain object """ if neutron and router: - logger.info('Deleting router with name - ' + router['router']['name']) - neutron.delete_router(router=router['router']['id']) - return True + logger.info('Deleting router with name - ' + router.name) + neutron.delete_router(router=router.id) def get_router_by_name(neutron, router_name): @@ -196,13 +197,13 @@ def get_router_by_name(neutron, router_name): Returns the first router object (dictionary) found with a given name :param neutron: the client :param router_name: the name of the network to retrieve - :return: + :return: a SNAPS-OO Router domain object """ routers = neutron.list_routers(**{'name': router_name}) for router, routerInst in routers.items(): for inst in routerInst: if inst.get('name') == router_name: - return {'router': inst} + return Router(**inst) return None @@ -221,11 +222,10 @@ def add_interface_router(neutron, router, subnet=None, port=None): 'port were sent in. Either or please.') if neutron and router and (router or subnet): - logger.info('Adding interface to router with name ' + - router['router']['name']) - return neutron.add_interface_router( - router=router['router']['id'], - body=__create_port_json_body(subnet, port)) + logger.info('Adding interface to router with name ' + router.name) + os_intf_router = neutron.add_interface_router( + router=router.id, body=__create_port_json_body(subnet, port)) + return InterfaceRouter(**os_intf_router) else: raise Exception('Unable to create interface router as neutron client,' ' router or subnet were not created') @@ -235,16 +235,16 @@ def remove_interface_router(neutron, router, subnet=None, port=None): """ Removes an interface router for OpenStack :param neutron: the client - :param router: the router object + :param router: the SNAPS-OO Router domain object :param subnet: the subnet object (either subnet or port, not both) :param port: the port object """ if router: try: logger.info('Removing router interface from router named ' + - router['router']['name']) + router.name) neutron.remove_interface_router( - router=router['router']['id'], + router=router.id, body=__create_port_json_body(subnet, port)) except NotFound as e: logger.warning('Could not remove router interface. NotFound - %s', @@ -271,7 +271,7 @@ def __create_port_json_body(subnet=None, port=None): if subnet: return {"subnet_id": subnet['subnet']['id']} else: - return {"port_id": port['port']['id']} + return {"port_id": port.id} def create_port(neutron, os_creds, port_settings): diff --git a/snaps/openstack/utils/tests/neutron_utils_tests.py b/snaps/openstack/utils/tests/neutron_utils_tests.py index 0080b57..f3cacd5 100644 --- a/snaps/openstack/utils/tests/neutron_utils_tests.py +++ b/snaps/openstack/utils/tests/neutron_utils_tests.py @@ -288,7 +288,7 @@ class NeutronUtilsRouterTests(OSComponentTestCase): if self.router: neutron_utils.delete_router(self.neutron, self.router) - validate_router(self.neutron, self.router.get('name'), False) + validate_router(self.neutron, self.router.name, False) if self.port: neutron_utils.delete_port(self.neutron, self.port) @@ -877,13 +877,13 @@ def validate_interface_router(interface_router, router, subnet): """ Returns true if the router ID & subnet ID have been properly included into the interface router object - :param interface_router: the object to validate + :param interface_router: the SNAPS-OO InterfaceRouter domain object :param router: to validate against the interface_router :param subnet: to validate against the interface_router :return: True if both IDs match else False """ - subnet_id = interface_router.get('subnet_id') - router_id = interface_router.get('port_id') + subnet_id = interface_router.subnet_id + router_id = interface_router.port_id return subnet.get('id') == subnet_id and router.get('id') == router_id diff --git a/snaps/test_suite_builder.py b/snaps/test_suite_builder.py index 59acc2b..ec9d17b 100644 --- a/snaps/test_suite_builder.py +++ b/snaps/test_suite_builder.py @@ -21,7 +21,8 @@ from snaps.domain.test.image_tests import ImageDomainObjectTests from snaps.domain.test.keypair_tests import KeypairDomainObjectTests from snaps.domain.test.network_tests import ( SecurityGroupDomainObjectTests, SecurityGroupRuleDomainObjectTests, - PortDomainObjectTests) + PortDomainObjectTests, RouterDomainObjectTests, + InterfaceRouterDomainObjectTests) from snaps.domain.test.project_tests import ProjectDomainObjectTests from snaps.domain.test.role_tests import RoleDomainObjectTests from snaps.domain.test.stack_tests import StackDomainObjectTests @@ -51,7 +52,8 @@ from snaps.openstack.tests.create_project_tests import ( CreateProjectSuccessTests, ProjectSettingsUnitTests, CreateProjectUserTests) from snaps.openstack.tests.create_router_tests import ( - CreateRouterSuccessTests, CreateRouterNegativeTests) + CreateRouterSuccessTests, CreateRouterNegativeTests, + RouterSettingsUnitTests) from snaps.openstack.tests.create_security_group_tests import ( CreateSecurityGroupTests, SecurityGroupRuleSettingsUnitTests, SecurityGroupSettingsUnitTests) @@ -131,6 +133,12 @@ def add_unit_tests(suite): suite.addTest(unittest.TestLoader().loadTestsFromTestCase( PortDomainObjectTests)) suite.addTest(unittest.TestLoader().loadTestsFromTestCase( + RouterSettingsUnitTests)) + suite.addTest(unittest.TestLoader().loadTestsFromTestCase( + RouterDomainObjectTests)) + suite.addTest(unittest.TestLoader().loadTestsFromTestCase( + InterfaceRouterDomainObjectTests)) + suite.addTest(unittest.TestLoader().loadTestsFromTestCase( FloatingIpSettingsUnitTests)) suite.addTest(unittest.TestLoader().loadTestsFromTestCase( VmInstanceSettingsUnitTests)) |