From a82209830309354c5bdc7e8b885c51df42c731d1 Mon Sep 17 00:00:00 2001 From: spisarski Date: Fri, 17 Nov 2017 16:07:40 -0700 Subject: Refactoring of NetworkSettings to extend NetworkConfig This also includes SubnetSettings extending to SubnetConfig and PortSettings extenting to Portconfig and neutron_utils have a runtime cyclical dependency. This patch reduces this dependency and deprecates the NetworkSettings, SubnetSettings, and PortSettings classes. JIRA: SNAPS-220 Change-Id: I996d73d9b910c075a6511a423f01d966f5b6fb74 Signed-off-by: spisarski --- docs/how-to-use/APITests.rst | 4 +- docs/how-to-use/LibraryUsage.rst | 25 +- docs/how-to-use/UnitTests.rst | 24 +- examples/demo.py | 33 +- examples/launch.py | 8 +- snaps/config/network.py | 495 +++++++++++++++++++++ snaps/config/router.py | 8 +- snaps/config/tests/network_tests.py | 331 ++++++++++++++ snaps/config/tests/router_tests.py | 8 +- snaps/openstack/create_instance.py | 6 +- snaps/openstack/create_network.py | 477 ++------------------ snaps/openstack/create_stack.py | 2 +- snaps/openstack/tests/create_instance_tests.py | 92 ++-- snaps/openstack/tests/create_network_tests.py | 98 ++-- snaps/openstack/tests/create_router_tests.py | 29 +- snaps/openstack/tests/openstack_tests.py | 8 +- snaps/openstack/utils/neutron_utils.py | 4 +- snaps/openstack/utils/settings_utils.py | 31 +- snaps/openstack/utils/tests/heat_utils_tests.py | 2 +- snaps/openstack/utils/tests/neutron_utils_tests.py | 64 ++- snaps/openstack/utils/tests/nova_utils_tests.py | 11 +- .../openstack/utils/tests/settings_utils_tests.py | 31 +- snaps/provisioning/tests/ansible_utils_tests.py | 5 +- snaps/test_suite_builder.py | 8 + 24 files changed, 1123 insertions(+), 681 deletions(-) create mode 100644 snaps/config/network.py create mode 100644 snaps/config/tests/network_tests.py diff --git a/docs/how-to-use/APITests.rst b/docs/how-to-use/APITests.rst index fe8e51d..83edd66 100644 --- a/docs/how-to-use/APITests.rst +++ b/docs/how-to-use/APITests.rst @@ -550,10 +550,10 @@ settings_utils_tests.py - SettingsUtilsNetworkingTests +---------------------------------------+---------------+-----------------------------------------------------------+ | Test Name | API | Description | +=======================================+===============+===========================================================+ -| test_derive_net_settings_no_subnet | Neutron 2 | Tests to ensure that derived NetworkSettings from an | +| test_derive_net_settings_no_subnet | Neutron 2 | Tests to ensure that derived NetworkConfig from an | | | | OpenStack network are correct without a subnet | +---------------------------------------+---------------+-----------------------------------------------------------+ -| test_derive_net_settings_two_subnets | Neutron 2 | Tests to ensure that derived NetworkSettings from an | +| test_derive_net_settings_two_subnets | Neutron 2 | Tests to ensure that derived NetworkConfig from an | | | | OpenStack network are correct with two subnets | +---------------------------------------+---------------+-----------------------------------------------------------+ diff --git a/docs/how-to-use/LibraryUsage.rst b/docs/how-to-use/LibraryUsage.rst index fc22a3d..aa7bf91 100644 --- a/docs/how-to-use/LibraryUsage.rst +++ b/docs/how-to-use/LibraryUsage.rst @@ -246,7 +246,7 @@ Create Network - Network - snaps.openstack.create\_network.OpenStackNetwork - - snaps.openstack.create\_network.NetworkSettings + - snaps.config_network.NetworkConfig - name - the name of the network (required) - admin\_state\_up - flag denoting the administrative status of @@ -263,7 +263,7 @@ Create Network - segmentation\_id - the id of the segmentation (required when network\_type is 'vlan') - subnet\_settings (list of optional - snaps.openstack.create\_network.SubnetSettings objects) + snaps.config.network.SubnetConfig objects) - cidr - the subnet's CIDR (required) - ip\_version - 4 or 6 (default=4) @@ -287,10 +287,11 @@ Create Network .. code:: python - from snaps.openstack.create_network import NetworkSettings, SubnetSettings, OpenStackNetwork + from snaps.config.network import NetworkConfig, SubnetConfig + from snaps.openstack.create_network import OpenStackNetwork - subnet_settings = SubnetSettings(name='subnet-name', cidr='10.0.0.0/24') - network_settings = NetworkSettings(name='network-name', subnet_settings=[subnet_settings]) + subnet_settings = SubnetConfig(name='subnet-name', cidr='10.0.0.0/24') + network_settings = NetworkConfig(name='network-name', subnet_settings=[subnet_settings]) network_creator = OpenStackNetwork(os_creds, network_settings) network_creator.create() @@ -340,10 +341,12 @@ Create Security Group .. code:: python + from snaps.config.network import SubnetConfig + from snaps.config.rule import RuleConfig from snaps.openstack.create_security_group import SecurityGroupSettings, SecurityGroupRuleSettings, Direction, OpenStackSecurityGroup - rule_settings = SubnetSettings(name='subnet-name', cidr='10.0.0.0/24') - network_settings = NetworkSettings(name='network-name', subnet_settings=[subnet_settings]) + rule_settings = RuleConfig(name='subnet-name', cidr='10.0.0.0/24') + network_settings = SubnetConfig(name='network-name', subnet_settings=[subnet_settings]) sec_grp_name = 'sec-grp-name' rule_settings = SecurityGroupRuleSettings(name=sec_grp_name, direction=Direction.ingress) @@ -376,7 +379,7 @@ Create Router - internal\_subnets - list of subnet names to which this router will connect (optional) - port\_settings (list of optional - snaps.openstack.create\_router.PortSettings objects) - creates + snaps.config.network.PortConfig objects) - creates custom ports to internal subnets (similar to internal\_subnets with more control) @@ -546,7 +549,7 @@ Create VM Instance - name - the name of the VM (required) - flavor - the name of the flavor (required) - port\_settings - list of - snaps.openstack.create\_network.PortSettings objects where each + snaps.config.network.PortConfig objects where each denote a NIC (see above in create router section for details) API does not require, but newer NFVIs now require VMs have at least one network @@ -589,9 +592,9 @@ Create VM Instance .. code:: python from snaps.openstack.create_instance import VmInstanceSettings, FloatingIpSettings, OpenStackVmInstance - from snaps.openstack.create_network import PortSettings + from snaps.config.network import PortConfig - port_settings = PortSettings(name='port-name', network_name=network_settings.name) + port_settings = PortConfig(name='port-name', network_name=network_settings.name) floating_ip_settings = FloatingIpSettings(name='fip1', port_name=port_settings.name, router_name=router_settings.name) instance_settings = VmInstanceSettings(name='vm-name', flavor='flavor_settings.name', port_settings=[port_settings], floating_ip_settings=[floating_ip_settings]) diff --git a/docs/how-to-use/UnitTests.rst b/docs/how-to-use/UnitTests.rst index 044503e..c053372 100644 --- a/docs/how-to-use/UnitTests.rst +++ b/docs/how-to-use/UnitTests.rst @@ -174,11 +174,17 @@ RoleDomainObjectTests Ensures that all required members are included when constructing a Role domain object +NetworkConfigUnitTests +---------------------- + +Ensures that all required members are included when constructing a +NetworkConfig object + NetworkSettingsUnitTests ------------------------ Ensures that all required members are included when constructing a -NetworkSettings object +deprecated NetworkSettings object NetworkObjectTests ------------------ @@ -186,11 +192,17 @@ NetworkObjectTests Ensures that all required members are included when constructing a Network domain object +SubnetConfigUnitTests +--------------------- + +Ensures that all required members are included when constructing a +SubnetConfig object + SubnetSettingsUnitTests ----------------------- Ensures that all required members are included when constructing a -SubnetSettings object +deprecated SubnetSettings object SubnetObjectTests ----------------- @@ -198,11 +210,17 @@ SubnetObjectTests Ensures that all required members are included when constructing a Subnet domain object +PortConfigUnitTests +------------------- + +Ensures that all required members are included when constructing a +PortConfig object + PortSettingsUnitTests --------------------- Ensures that all required members are included when constructing a -PortSettings object +deprecated PortSettings object PortDomainObjectTests --------------------- diff --git a/examples/demo.py b/examples/demo.py index 8837bd2..c888d7b 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -5,11 +5,14 @@ logging.basicConfig(level=logging.INFO) from snaps.openstack.os_credentials import OSCreds, ProxySettings -proxy_settings = ProxySettings(host='10.197.123.27', port='3128', - ssh_proxy_cmd='/usr/local/bin/corkscrew 10.197.123.27 3128 %h %p') +proxy_settings = ProxySettings( + host='10.197.123.27', port='3128', + ssh_proxy_cmd='/usr/local/bin/corkscrew 10.197.123.27 3128 %h %p') -os_creds = OSCreds(username='admin', password='cable123', auth_url='http://192.168.67.10:5000/v2.0/', - project_name='admin', proxy_settings=proxy_settings) +os_creds = OSCreds( + username='admin', password='cable123', + auth_url='http://192.168.67.10:5000/v2.0/', project_name='admin', + proxy_settings=proxy_settings) # Images @@ -25,10 +28,12 @@ image.create() # Network -from snaps.openstack.create_network import NetworkSettings, SubnetSettings, OpenStackNetwork +from snaps.config.network import NetworkConfig, SubnetConfig +from snaps.openstack.create_network import OpenStackNetwork -subnet_settings = SubnetSettings(name='test-subnet', cidr='10.0.0.1/24') -network_settings = NetworkSettings(name='test-net', subnet_settings=[subnet_settings]) +subnet_settings = SubnetConfig(name='test-subnet', cidr='10.0.0.1/24') +network_settings = NetworkConfig( + name='test-net', subnet_settings=[subnet_settings]) network = OpenStackNetwork(os_creds, network_settings) network.create() @@ -42,11 +47,15 @@ flavor = OpenStackFlavor(os_creds, flavor_settings) flavor.create() # Instances -from snaps.openstack.create_network import PortSettings -from snaps.openstack.create_instance import VmInstanceSettings, OpenStackVmInstance - -port_settings = PortSettings(name='test-port', network_name=network_settings.name) -instance_settings = VmInstanceSettings(name='test-inst', flavor=flavor_settings.name, port_settings=[port_settings]) +from snaps.config.network import PortConfig +from snaps.openstack.create_instance import ( + VmInstanceSettings, OpenStackVmInstance) + +port_settings = PortConfig( + name='test-port', network_name=network_settings.name) +instance_settings = VmInstanceSettings( + name='test-inst', flavor=flavor_settings.name, + port_settings=[port_settings]) vm_inst = OpenStackVmInstance(os_creds, instance_settings, image_settings) vm_inst.create(block=True) diff --git a/examples/launch.py b/examples/launch.py index b0311e6..9320512 100644 --- a/examples/launch.py +++ b/examples/launch.py @@ -29,6 +29,7 @@ from snaps import file_utils from snaps.config.flavor import FlavorConfig from snaps.config.image import ImageConfig from snaps.config.keypair import KeypairConfig +from snaps.config.network import PortConfig, NetworkConfig from snaps.config.project import ProjectConfig from snaps.config.qos import QoSConfig from snaps.config.router import RouterConfig @@ -39,8 +40,7 @@ from snaps.openstack.create_flavor import OpenStackFlavor from snaps.openstack.create_image import OpenStackImage from snaps.openstack.create_instance import VmInstanceSettings from snaps.openstack.create_keypairs import OpenStackKeypair -from snaps.openstack.create_network import ( - PortSettings, NetworkSettings, OpenStackNetwork) +from snaps.openstack.create_network import OpenStackNetwork from snaps.openstack.create_project import OpenStackProject from snaps.openstack.create_qos import OpenStackQoS from snaps.openstack.create_router import OpenStackRouter @@ -152,7 +152,7 @@ def __parse_ports_config(config): """ out = list() for port_config in config: - out.append(PortSettings(**port_config.get('port'))) + out.append(PortConfig(**port_config.get('port'))) return out @@ -673,7 +673,7 @@ def main(arguments): # Create networks creators.append(__create_instances( - os_creds_dict, OpenStackNetwork, NetworkSettings, + os_creds_dict, OpenStackNetwork, NetworkConfig, os_config.get('networks'), 'network', clean, users_dict)) # Create routers diff --git a/snaps/config/network.py b/snaps/config/network.py new file mode 100644 index 0000000..bc6ae1b --- /dev/null +++ b/snaps/config/network.py @@ -0,0 +1,495 @@ +# Copyright (c) 2017 Cable Television Laboratories, Inc. ("CableLabs") +# and others. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import enum + +from snaps.openstack.utils import keystone_utils, neutron_utils + + +class NetworkConfig(object): + """ + Class representing a network configuration + """ + + def __init__(self, **kwargs): + """ + Constructor - all parameters are optional + :param name: The network name. + :param admin_state_up: The administrative status of the network. + True = up / False = down (default True) + :param shared: Boolean value indicating whether this network is shared + across all projects/tenants. By default, only + administrative users can change this value. + :param project_name: Admin-only. The name of the project that will own + the network. This project can be different from + the project that makes the create network request. + However, only administrative users can specify a + project ID other than their own. You cannot change + this value through authorization policies. + :param external: when true, will setup an external network + (default False). + :param network_type: the type of network (i.e. vlan|flat). + :param physical_network: the name of the physical network + (required when network_type is 'flat') + :param segmentation_id: the id of the segmentation + (this is required when network_type is 'vlan') + :param subnets or subnet_settings: List of SubnetConfig objects. + :return: + """ + + self.project_id = None + + self.name = kwargs.get('name') + if kwargs.get('admin_state_up') is not None: + self.admin_state_up = bool(kwargs['admin_state_up']) + else: + self.admin_state_up = True + + if kwargs.get('shared') is not None: + self.shared = bool(kwargs['shared']) + else: + self.shared = None + + self.project_name = kwargs.get('project_name') + + if kwargs.get('external') is not None: + self.external = bool(kwargs.get('external')) + else: + self.external = False + + self.network_type = kwargs.get('network_type') + self.physical_network = kwargs.get('physical_network') + self.segmentation_id = kwargs.get('segmentation_id') + + self.subnet_settings = list() + subnet_settings = kwargs.get('subnets') + if not subnet_settings: + subnet_settings = kwargs.get('subnet_settings', list()) + if subnet_settings: + for subnet_config in subnet_settings: + if isinstance(subnet_config, SubnetConfig): + self.subnet_settings.append(subnet_config) + else: + self.subnet_settings.append( + SubnetConfig(**subnet_config['subnet'])) + + if not self.name or len(self.name) < 1: + raise NetworkConfigError('Name required for networks') + + def get_project_id(self, os_creds): + """ + Returns the project ID for a given project_name or None + :param os_creds: the credentials required for keystone client retrieval + :return: the ID or None + """ + if self.project_id: + return self.project_id + else: + if self.project_name: + keystone = keystone_utils.keystone_client(os_creds) + project = keystone_utils.get_project( + keystone=keystone, project_name=self.project_name) + if project: + return project.id + + return None + + def dict_for_neutron(self, os_creds): + """ + Returns a dictionary object representing this object. + This is meant to be converted into JSON designed for use by the Neutron + API + TODO - expand automated testing to exercise all parameters + + :param os_creds: the OpenStack credentials + :return: the dictionary object + """ + out = dict() + + if self.name: + out['name'] = self.name + if self.admin_state_up is not None: + out['admin_state_up'] = self.admin_state_up + if self.shared: + out['shared'] = self.shared + if self.project_name: + project_id = self.get_project_id(os_creds) + if project_id: + out['tenant_id'] = project_id + else: + raise NetworkConfigError( + 'Could not find project ID for project named - ' + + self.project_name) + if self.network_type: + out['provider:network_type'] = self.network_type + if self.physical_network: + out['provider:physical_network'] = self.physical_network + if self.segmentation_id: + out['provider:segmentation_id'] = self.segmentation_id + if self.external: + out['router:external'] = self.external + return {'network': out} + + +class NetworkConfigError(Exception): + """ + Exception to be thrown when networks settings attributes are incorrect + """ + + +class IPv6Mode(enum.Enum): + """ + A rule's direction + """ + slaac = 'slaac' + stateful = 'dhcpv6-stateful' + stateless = 'dhcpv6-stateless' + + +class SubnetConfig(object): + """ + Class representing a subnet configuration + """ + + def __init__(self, **kwargs): + """ + Constructor - all parameters are optional except cidr (subnet mask) + :param name: The subnet name (required) + :param cidr: The CIDR (required) + :param ip_version: The IP version, which is 4 or 6 (required) + :param project_name: The name of the project who owns the network. + Only administrative users can specify a project ID + other than their own. You cannot change this value + through authorization policies (optional) + :param start: The start address for the allocation pools (optional) + :param end: The end address for the allocation pools (optional) + :param gateway_ip: The gateway IP address (optional) + :param enable_dhcp: Set to true if DHCP is enabled and false if DHCP is + disabled (optional) + :param dns_nameservers: A list of DNS name servers for the subnet. + Specify each name server as an IP address + and separate multiple entries with a space. + For example [8.8.8.7 8.8.8.8] + (default '8.8.8.8') + :param host_routes: A list of host route dictionaries for the subnet. + For example: + "host_routes":[ + { + "destination":"0.0.0.0/0", + "nexthop":"123.456.78.9" + }, + { + "destination":"192.168.0.0/24", + "nexthop":"192.168.0.1" + } + ] + :param destination: The destination for static route (optional) + :param nexthop: The next hop for the destination (optional) + :param ipv6_ra_mode: an instance of the IPv6Mode enum + (optional when enable_dhcp is True) + :param ipv6_address_mode: an instance of the IPv6Mode enum + (optional when enable_dhcp is True) + :raise: SubnetConfigError when config does not have or cidr values + are None + """ + self.cidr = kwargs.get('cidr') + if kwargs.get('ip_version'): + self.ip_version = kwargs['ip_version'] + else: + self.ip_version = 4 + + # Optional attributes that can be set after instantiation + self.name = kwargs.get('name') + self.project_name = kwargs.get('project_name') + self.start = kwargs.get('start') + self.end = kwargs.get('end') + self.gateway_ip = kwargs.get('gateway_ip') + self.enable_dhcp = kwargs.get('enable_dhcp') + + if 'dns_nameservers' in kwargs: + self.dns_nameservers = kwargs.get('dns_nameservers') + else: + if self.ip_version == 4: + self.dns_nameservers = ['8.8.8.8'] + else: + self.dns_nameservers = list() + + self.host_routes = kwargs.get('host_routes') + self.destination = kwargs.get('destination') + self.nexthop = kwargs.get('nexthop') + self.ipv6_ra_mode = map_mode(kwargs.get('ipv6_ra_mode')) + self.ipv6_address_mode = map_mode(kwargs.get('ipv6_address_mode')) + + if not self.name or not self.cidr: + raise SubnetConfigError('Name and cidr required for subnets') + + def dict_for_neutron(self, os_creds, network=None): + """ + Returns a dictionary object representing this object. + This is meant to be converted into JSON designed for use by the Neutron + API + :param os_creds: the OpenStack credentials + :param network: The network object on which the subnet will be created + (optional) + :return: the dictionary object + """ + out = { + 'cidr': self.cidr, + 'ip_version': self.ip_version, + } + + if network: + out['network_id'] = network.id + if self.name: + out['name'] = self.name + if self.project_name: + keystone = keystone_utils.keystone_client(os_creds) + project = keystone_utils.get_project( + keystone=keystone, project_name=self.project_name) + project_id = None + if project: + project_id = project.id + if project_id: + out['tenant_id'] = project_id + else: + raise SubnetConfigError( + 'Could not find project ID for project named - ' + + self.project_name) + if self.start and self.end: + out['allocation_pools'] = [{'start': self.start, 'end': self.end}] + if self.gateway_ip: + out['gateway_ip'] = self.gateway_ip + if self.enable_dhcp is not None: + out['enable_dhcp'] = self.enable_dhcp + if self.dns_nameservers and len(self.dns_nameservers) > 0: + out['dns_nameservers'] = self.dns_nameservers + if self.host_routes and len(self.host_routes) > 0: + out['host_routes'] = self.host_routes + if self.destination: + out['destination'] = self.destination + if self.nexthop: + out['nexthop'] = self.nexthop + if self.ipv6_ra_mode: + out['ipv6_ra_mode'] = self.ipv6_ra_mode.value + if self.ipv6_address_mode: + out['ipv6_address_mode'] = self.ipv6_address_mode.value + return out + + +def map_mode(mode): + """ + Takes a the direction value maps it to the Direction enum. When None return + None + :param mode: the mode value + :return: the IPv6Mode enum object + :raise: SubnetConfigError if value is invalid + """ + if not mode: + return None + if isinstance(mode, IPv6Mode): + return mode + elif isinstance(mode, str): + mode_str = str(mode) + if mode_str == 'slaac': + return IPv6Mode.slaac + elif mode_str == 'dhcpv6-stateful': + return IPv6Mode.stateful + elif mode_str == 'stateful': + return IPv6Mode.stateful + elif mode_str == 'dhcpv6-stateless': + return IPv6Mode.stateless + elif mode_str == 'stateless': + return IPv6Mode.stateless + else: + raise SubnetConfigError('Invalid mode - ' + mode_str) + else: + return map_mode(mode.value) + + +class SubnetConfigError(Exception): + """ + Exception to be thrown when subnet settings attributes are incorrect + """ + + +class PortConfig(object): + """ + Class representing a port configuration + """ + + def __init__(self, **kwargs): + """ + Constructor + :param name: A symbolic name for the port (optional). + :param network_name: The name of the network on which to create the + port (required). + :param admin_state_up: A boolean value denoting the administrative + status of the port (default = True) + :param project_name: The name of the project who owns the network. + Only administrative users can specify a project ID + other than their own. You cannot change this value + through authorization policies (optional) + :param mac_address: The MAC address. If you specify an address that is + not valid, a Bad Request (400) status code is + returned. If you do not specify a MAC address, + OpenStack Networking tries to allocate one. If a + failure occurs, a Service Unavailable (503) status + code is returned (optional) + :param ip_addrs: A list of dict objects where each contains two keys + 'subnet_name' and 'ip' values which will get mapped to + self.fixed_ips. These values will be directly + translated into the fixed_ips dict (optional) + :param security_groups: One or more security group IDs. + :param allowed_address_pairs: A dictionary containing a set of zero or + more allowed address pairs. An address + pair contains an IP address and MAC + address (optional) + :param opt_value: The extra DHCP option value (optional) + :param opt_name: The extra DHCP option name (optional) + :param device_owner: The ID of the entity that uses this port. + For example, a DHCP agent (optional) + :param device_id: The ID of the device that uses this port. + For example, a virtual server (optional) + :return: + """ + if 'port' in kwargs: + kwargs = kwargs['port'] + + self.name = kwargs.get('name') + self.network_name = kwargs.get('network_name') + + if kwargs.get('admin_state_up') is not None: + self.admin_state_up = bool(kwargs['admin_state_up']) + else: + self.admin_state_up = True + + self.project_name = kwargs.get('project_name') + self.mac_address = kwargs.get('mac_address') + self.ip_addrs = kwargs.get('ip_addrs') + self.security_groups = kwargs.get('security_groups') + self.allowed_address_pairs = kwargs.get('allowed_address_pairs') + self.opt_value = kwargs.get('opt_value') + self.opt_name = kwargs.get('opt_name') + self.device_owner = kwargs.get('device_owner') + self.device_id = kwargs.get('device_id') + + if not self.network_name: + raise PortConfigError( + 'The attribute network_name is required') + + def __get_fixed_ips(self, neutron): + """ + Sets the self.fixed_ips value + :param neutron: the Neutron client + :return: None + """ + + fixed_ips = list() + if self.ip_addrs: + + for ip_addr_dict in self.ip_addrs: + subnet = neutron_utils.get_subnet( + neutron, subnet_name=ip_addr_dict['subnet_name']) + if subnet and 'ip' in ip_addr_dict: + fixed_ips.append({'ip_address': ip_addr_dict['ip'], + 'subnet_id': subnet.id}) + else: + raise PortConfigError( + 'Invalid port configuration, subnet does not exist ' + 'with name - ' + ip_addr_dict['subnet_name']) + + return fixed_ips + + def dict_for_neutron(self, neutron, os_creds): + """ + Returns a dictionary object representing this object. + This is meant to be converted into JSON designed for use by the Neutron + API + + TODO - expand automated testing to exercise all parameters + :param neutron: the Neutron client + :param os_creds: the OpenStack credentials + :return: the dictionary object + """ + + out = dict() + + project_id = None + if self.project_name: + keystone = keystone_utils.keystone_client(os_creds) + project = keystone_utils.get_project( + keystone=keystone, project_name=self.project_name) + if project: + project_id = project.id + + network = neutron_utils.get_network( + neutron, network_name=self.network_name, project_id=project_id) + if not network: + raise PortConfigError( + 'Cannot locate network with name - ' + self.network_name) + + out['network_id'] = network.id + + if self.admin_state_up is not None: + out['admin_state_up'] = self.admin_state_up + if self.name: + out['name'] = self.name + if self.project_name: + if project_id: + out['tenant_id'] = project_id + else: + raise PortConfigError( + 'Could not find project ID for project named - ' + + self.project_name) + if self.mac_address: + out['mac_address'] = self.mac_address + + fixed_ips = self.__get_fixed_ips(neutron) + if fixed_ips and len(fixed_ips) > 0: + out['fixed_ips'] = fixed_ips + + if self.security_groups: + out['security_groups'] = self.security_groups + if self.allowed_address_pairs and len(self.allowed_address_pairs) > 0: + out['allowed_address_pairs'] = self.allowed_address_pairs + if self.opt_value: + out['opt_value'] = self.opt_value + if self.opt_name: + out['opt_name'] = self.opt_name + if self.device_owner: + out['device_owner'] = self.device_owner + 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) + + +class PortConfigError(Exception): + """ + Exception to be thrown when port settings attributes are incorrect + """ diff --git a/snaps/config/router.py b/snaps/config/router.py index db26870..72164f2 100644 --- a/snaps/config/router.py +++ b/snaps/config/router.py @@ -12,7 +12,7 @@ # 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 snaps.openstack.create_network import PortSettings +from snaps.config.network import PortConfig from snaps.openstack.utils import neutron_utils, keystone_utils @@ -34,7 +34,7 @@ class RouterConfig(object): True = up / False = down (default True) :param internal_subnets: List of subnet names to which to connect this router for Floating IP purposes - :param port_settings: List of PortSettings objects + :param port_settings: List of PortConfig objects :return: """ self.name = kwargs.get('name') @@ -52,11 +52,11 @@ class RouterConfig(object): if kwargs.get('interfaces', kwargs.get('port_settings')): interfaces = kwargs.get('interfaces', kwargs.get('port_settings')) for interface in interfaces: - if isinstance(interface, PortSettings): + if isinstance(interface, PortConfig): self.port_settings.append(interface) else: self.port_settings.append( - PortSettings(**interface['port'])) + PortConfig(**interface['port'])) if not self.name: raise RouterConfigError('Name is required') diff --git a/snaps/config/tests/network_tests.py b/snaps/config/tests/network_tests.py new file mode 100644 index 0000000..1fe1bb0 --- /dev/null +++ b/snaps/config/tests/network_tests.py @@ -0,0 +1,331 @@ +# Copyright (c) 2017 Cable Television Laboratories, Inc. ("CableLabs") +# and others. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import unittest + +from snaps.config.network import ( + NetworkConfigError, NetworkConfig, SubnetConfig, SubnetConfigError, + IPv6Mode, PortConfig, PortConfigError) + + +class NetworkConfigUnitTests(unittest.TestCase): + """ + Tests the construction of the NetworkConfig class + """ + + def test_no_params(self): + with self.assertRaises(NetworkConfigError): + NetworkConfig() + + def test_empty_config(self): + with self.assertRaises(NetworkConfigError): + NetworkConfig(**dict()) + + def test_name_only(self): + settings = NetworkConfig(name='foo') + self.assertEqual('foo', settings.name) + self.assertTrue(settings.admin_state_up) + self.assertIsNone(settings.shared) + self.assertIsNone(settings.project_name) + self.assertFalse(settings.external) + self.assertIsNone(settings.network_type) + self.assertIsNone(settings.segmentation_id) + self.assertEqual(0, len(settings.subnet_settings)) + + def test_config_with_name_only(self): + settings = NetworkConfig(**{'name': 'foo'}) + self.assertEqual('foo', settings.name) + self.assertTrue(settings.admin_state_up) + self.assertIsNone(settings.shared) + self.assertIsNone(settings.project_name) + self.assertFalse(settings.external) + self.assertIsNone(settings.network_type) + self.assertIsNone(settings.segmentation_id) + self.assertEqual(0, len(settings.subnet_settings)) + + def test_all(self): + sub_settings = SubnetConfig(name='foo-subnet', cidr='10.0.0.0/24') + settings = NetworkConfig( + name='foo', admin_state_up=False, shared=True, project_name='bar', + external=True, network_type='vlan', physical_network='phy', + segmentation_id=2366, subnet_settings=[sub_settings]) + self.assertEqual('foo', settings.name) + self.assertFalse(settings.admin_state_up) + self.assertTrue(settings.shared) + self.assertEqual('bar', settings.project_name) + self.assertTrue(settings.external) + self.assertEqual('vlan', settings.network_type) + self.assertEqual('phy', settings.physical_network) + self.assertEqual(2366, settings.segmentation_id) + self.assertEqual(1, len(settings.subnet_settings)) + self.assertEqual('foo-subnet', settings.subnet_settings[0].name) + + def test_config_all(self): + settings = NetworkConfig( + **{'name': 'foo', 'admin_state_up': False, 'shared': True, + 'project_name': 'bar', 'external': True, 'network_type': 'vlan', + 'physical_network': 'phy', + 'segmentation_id': 2366, + 'subnets': + [{'subnet': {'name': 'foo-subnet', + 'cidr': '10.0.0.0/24'}}]}) + self.assertEqual('foo', settings.name) + self.assertFalse(settings.admin_state_up) + self.assertTrue(settings.shared) + self.assertEqual('bar', settings.project_name) + self.assertTrue(settings.external) + self.assertEqual('vlan', settings.network_type) + self.assertEqual('phy', settings.physical_network) + self.assertEqual(2366, settings.segmentation_id) + self.assertEqual(1, len(settings.subnet_settings)) + self.assertEqual('foo-subnet', settings.subnet_settings[0].name) + + +class SubnetConfigUnitTests(unittest.TestCase): + """ + Tests the construction of the SubnetConfig class + """ + + def test_no_params(self): + with self.assertRaises(SubnetConfigError): + SubnetConfig() + + def test_empty_config(self): + with self.assertRaises(SubnetConfigError): + SubnetConfig(**dict()) + + def test_name_only(self): + with self.assertRaises(SubnetConfigError): + SubnetConfig(name='foo') + + def test_config_with_name_only(self): + with self.assertRaises(SubnetConfigError): + SubnetConfig(**{'name': 'foo'}) + + def test_name_cidr_only(self): + settings = SubnetConfig(name='foo', cidr='10.0.0.0/24') + self.assertEqual('foo', settings.name) + self.assertEqual('10.0.0.0/24', settings.cidr) + self.assertEqual(4, settings.ip_version) + self.assertIsNone(settings.project_name) + self.assertIsNone(settings.start) + self.assertIsNone(settings.end) + self.assertIsNone(settings.enable_dhcp) + self.assertEqual(1, len(settings.dns_nameservers)) + self.assertEqual('8.8.8.8', settings.dns_nameservers[0]) + self.assertIsNone(settings.host_routes) + self.assertIsNone(settings.destination) + self.assertIsNone(settings.nexthop) + self.assertIsNone(settings.ipv6_ra_mode) + self.assertIsNone(settings.ipv6_address_mode) + + def test_config_with_name_cidr_only(self): + settings = SubnetConfig(**{'name': 'foo', 'cidr': '10.0.0.0/24'}) + self.assertEqual('foo', settings.name) + self.assertEqual('10.0.0.0/24', settings.cidr) + self.assertEqual(4, settings.ip_version) + self.assertIsNone(settings.project_name) + self.assertIsNone(settings.start) + self.assertIsNone(settings.end) + self.assertIsNone(settings.gateway_ip) + self.assertIsNone(settings.enable_dhcp) + self.assertEqual(1, len(settings.dns_nameservers)) + self.assertEqual('8.8.8.8', settings.dns_nameservers[0]) + self.assertIsNone(settings.host_routes) + self.assertIsNone(settings.destination) + self.assertIsNone(settings.nexthop) + self.assertIsNone(settings.ipv6_ra_mode) + self.assertIsNone(settings.ipv6_address_mode) + + def test_all_string_enums(self): + host_routes = {'destination': '0.0.0.0/0', 'nexthop': '123.456.78.9'} + settings = SubnetConfig( + name='foo', cidr='10.0.0.0/24', ip_version=6, + project_name='bar-project', start='10.0.0.2', end='10.0.0.101', + gateway_ip='10.0.0.1', enable_dhcp=False, + dns_nameservers=['8.8.8.8'], host_routes=[host_routes], + destination='dest', nexthop='hop', ipv6_ra_mode='dhcpv6-stateful', + ipv6_address_mode='slaac') + self.assertEqual('foo', settings.name) + self.assertEqual('10.0.0.0/24', settings.cidr) + self.assertEqual(6, settings.ip_version) + self.assertEqual('bar-project', settings.project_name) + self.assertEqual('10.0.0.2', settings.start) + self.assertEqual('10.0.0.101', settings.end) + self.assertEqual('10.0.0.1', settings.gateway_ip) + self.assertEqual(False, settings.enable_dhcp) + self.assertEqual(1, len(settings.dns_nameservers)) + self.assertEqual('8.8.8.8', settings.dns_nameservers[0]) + self.assertEqual(1, len(settings.host_routes)) + self.assertEqual(host_routes, settings.host_routes[0]) + self.assertEqual('dest', settings.destination) + self.assertEqual('hop', settings.nexthop) + self.assertEqual(IPv6Mode.stateful, settings.ipv6_ra_mode) + self.assertEqual(IPv6Mode.slaac, settings.ipv6_address_mode) + + def test_all_type_enums(self): + host_routes = {'destination': '0.0.0.0/0', 'nexthop': '123.456.78.9'} + settings = SubnetConfig( + name='foo', cidr='10.0.0.0/24', ip_version=6, + project_name='bar-project', start='10.0.0.2', end='10.0.0.101', + gateway_ip='10.0.0.1', enable_dhcp=False, + dns_nameservers=['8.8.8.8'], host_routes=[host_routes], + destination='dest', nexthop='hop', ipv6_ra_mode=IPv6Mode.stateful, + ipv6_address_mode=IPv6Mode.slaac) + self.assertEqual('foo', settings.name) + self.assertEqual('10.0.0.0/24', settings.cidr) + self.assertEqual(6, settings.ip_version) + self.assertEqual('bar-project', settings.project_name) + self.assertEqual('10.0.0.2', settings.start) + self.assertEqual('10.0.0.101', settings.end) + self.assertEqual('10.0.0.1', settings.gateway_ip) + self.assertEqual(False, settings.enable_dhcp) + self.assertEqual(1, len(settings.dns_nameservers)) + self.assertEqual('8.8.8.8', settings.dns_nameservers[0]) + self.assertEqual(1, len(settings.host_routes)) + self.assertEqual(host_routes, settings.host_routes[0]) + self.assertEqual('dest', settings.destination) + self.assertEqual('hop', settings.nexthop) + self.assertEqual(IPv6Mode.stateful, settings.ipv6_ra_mode) + self.assertEqual(IPv6Mode.slaac, settings.ipv6_address_mode) + + def test_config_all(self): + host_routes = {'destination': '0.0.0.0/0', 'nexthop': '123.456.78.9'} + settings = SubnetConfig( + **{'name': 'foo', 'cidr': '10.0.0.0/24', 'ip_version': 6, + 'project_name': 'bar-project', 'start': '10.0.0.2', + 'end': '10.0.0.101', + 'gateway_ip': '10.0.0.1', 'enable_dhcp': False, + 'dns_nameservers': ['8.8.8.8'], 'host_routes': [host_routes], + 'destination': 'dest', 'nexthop': 'hop', + 'ipv6_ra_mode': 'dhcpv6-stateless', + 'ipv6_address_mode': 'slaac'}) + self.assertEqual('foo', settings.name) + self.assertEqual('10.0.0.0/24', settings.cidr) + self.assertEqual(6, settings.ip_version) + self.assertEqual('bar-project', settings.project_name) + self.assertEqual('10.0.0.2', settings.start) + self.assertEqual('10.0.0.101', settings.end) + self.assertEqual('10.0.0.1', settings.gateway_ip) + self.assertEqual(False, settings.enable_dhcp) + self.assertEqual(1, len(settings.dns_nameservers)) + self.assertEqual('8.8.8.8', settings.dns_nameservers[0]) + self.assertEqual(1, len(settings.host_routes)) + self.assertEqual(host_routes, settings.host_routes[0]) + self.assertEqual('dest', settings.destination) + self.assertEqual('hop', settings.nexthop) + self.assertEqual(IPv6Mode.stateless, settings.ipv6_ra_mode) + self.assertEqual(IPv6Mode.slaac, settings.ipv6_address_mode) + + +class PortConfigUnitTests(unittest.TestCase): + """ + Tests the construction of the PortConfig class + """ + + def test_no_params(self): + with self.assertRaises(PortConfigError): + PortConfig() + + def test_empty_config(self): + with self.assertRaises(PortConfigError): + PortConfig(**dict()) + + def test_name_only(self): + with self.assertRaises(PortConfigError): + PortConfig(name='foo') + + def test_config_name_only(self): + with self.assertRaises(PortConfigError): + PortConfig(**{'name': 'foo'}) + + def test_name_netname_only(self): + settings = PortConfig(name='foo', network_name='bar') + self.assertEqual('foo', settings.name) + self.assertEqual('bar', settings.network_name) + self.assertTrue(settings.admin_state_up) + self.assertIsNone(settings.project_name) + self.assertIsNone(settings.mac_address) + self.assertIsNone(settings.ip_addrs) + self.assertIsNone(settings.security_groups) + self.assertIsNone(settings.allowed_address_pairs) + self.assertIsNone(settings.opt_value) + self.assertIsNone(settings.opt_name) + self.assertIsNone(settings.device_owner) + self.assertIsNone(settings.device_id) + + def test_config_with_name_netname_only(self): + settings = PortConfig(**{'name': 'foo', 'network_name': 'bar'}) + self.assertEqual('foo', settings.name) + self.assertEqual('bar', settings.network_name) + self.assertTrue(settings.admin_state_up) + self.assertIsNone(settings.project_name) + self.assertIsNone(settings.mac_address) + self.assertIsNone(settings.ip_addrs) + self.assertIsNone(settings.security_groups) + self.assertIsNone(settings.allowed_address_pairs) + self.assertIsNone(settings.opt_value) + self.assertIsNone(settings.opt_name) + self.assertIsNone(settings.device_owner) + self.assertIsNone(settings.device_id) + + def test_all(self): + ip_addrs = [{'subnet_name', 'foo-sub', 'ip', '10.0.0.10'}] + allowed_address_pairs = {'10.0.0.101', '1234.5678'} + + settings = PortConfig( + name='foo', network_name='bar', admin_state_up=False, + project_name='foo-project', mac_address='1234', ip_addrs=ip_addrs, + security_groups=['foo_grp_id'], + allowed_address_pairs=allowed_address_pairs, opt_value='opt value', + opt_name='opt name', device_owner='owner', + device_id='device number') + self.assertEqual('foo', settings.name) + self.assertEqual('bar', settings.network_name) + self.assertFalse(settings.admin_state_up) + self.assertEqual('foo-project', settings.project_name) + self.assertEqual('1234', settings.mac_address) + self.assertEqual(ip_addrs, settings.ip_addrs) + self.assertEqual(1, len(settings.security_groups)) + self.assertEqual('foo_grp_id', settings.security_groups[0]) + self.assertEqual(allowed_address_pairs, settings.allowed_address_pairs) + self.assertEqual('opt value', settings.opt_value) + self.assertEqual('opt name', settings.opt_name) + self.assertEqual('owner', settings.device_owner) + self.assertEqual('device number', settings.device_id) + + def test_config_all(self): + ip_addrs = [{'subnet_name', 'foo-sub', 'ip', '10.0.0.10'}] + allowed_address_pairs = {'10.0.0.101', '1234.5678'} + + settings = PortConfig( + **{'name': 'foo', 'network_name': 'bar', 'admin_state_up': False, + 'project_name': 'foo-project', 'mac_address': '1234', + 'ip_addrs': ip_addrs, 'security_groups': ['foo_grp_id'], + 'allowed_address_pairs': allowed_address_pairs, + 'opt_value': 'opt value', 'opt_name': 'opt name', + 'device_owner': 'owner', 'device_id': 'device number'}) + self.assertEqual('foo', settings.name) + self.assertEqual('bar', settings.network_name) + self.assertFalse(settings.admin_state_up) + self.assertEqual('foo-project', settings.project_name) + self.assertEqual('1234', settings.mac_address) + self.assertEqual(ip_addrs, settings.ip_addrs) + self.assertEqual(1, len(settings.security_groups)) + self.assertEqual('foo_grp_id', settings.security_groups[0]) + self.assertEqual(allowed_address_pairs, settings.allowed_address_pairs) + self.assertEqual('opt value', settings.opt_value) + self.assertEqual('opt name', settings.opt_name) + self.assertEqual('owner', settings.device_owner) + self.assertEqual('device number', settings.device_id) diff --git a/snaps/config/tests/router_tests.py b/snaps/config/tests/router_tests.py index ffa227a..2c8f91f 100644 --- a/snaps/config/tests/router_tests.py +++ b/snaps/config/tests/router_tests.py @@ -14,8 +14,8 @@ # limitations under the License. import unittest +from snaps.config.network import PortConfig from snaps.config.router import RouterConfig, RouterConfigError -from snaps.openstack.create_network import PortSettings class RouterConfigUnitTests(unittest.TestCase): @@ -60,7 +60,7 @@ class RouterConfigUnitTests(unittest.TestCase): self.assertEqual(0, len(settings.port_settings)) def test_all(self): - port_settings = PortSettings(name='foo', network_name='bar') + port_settings = PortConfig(name='foo', network_name='bar') settings = RouterConfig( name='foo', project_name='bar', external_gateway='foo_gateway', admin_state_up=True, enable_snat=False, @@ -93,6 +93,6 @@ class RouterConfigUnitTests(unittest.TestCase): 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'})], + self.assertEqual([PortConfig(**{'name': 'foo-port', + 'network_name': 'bar-net'})], settings.port_settings) diff --git a/snaps/openstack/create_instance.py b/snaps/openstack/create_instance.py index 706e6a6..58d6105 100644 --- a/snaps/openstack/create_instance.py +++ b/snaps/openstack/create_instance.py @@ -18,7 +18,7 @@ import time from neutronclient.common.exceptions import PortNotFoundClient from novaclient.exceptions import NotFound, BadRequest -from snaps.openstack.create_network import PortSettings +from snaps.config.network import PortConfig from snaps.openstack.openstack_creator import OpenStackComputeObject from snaps.openstack.utils import glance_utils, cinder_utils from snaps.openstack.utils import neutron_utils @@ -814,8 +814,8 @@ class VmInstanceSettings: if port_settings: for port_setting in port_settings: if isinstance(port_setting, dict): - self.port_settings.append(PortSettings(**port_setting)) - elif isinstance(port_setting, PortSettings): + self.port_settings.append(PortConfig(**port_setting)) + elif isinstance(port_setting, PortConfig): self.port_settings.append(port_setting) if kwargs.get('security_group_names'): diff --git a/snaps/openstack/create_network.py b/snaps/openstack/create_network.py index d639c2b..c9c58e8 100644 --- a/snaps/openstack/create_network.py +++ b/snaps/openstack/create_network.py @@ -17,8 +17,9 @@ import logging import enum from neutronclient.common.exceptions import NetworkNotFoundClient +from snaps.config.network import NetworkConfig, SubnetConfig, PortConfig from snaps.openstack.openstack_creator import OpenStackNetworkObject -from snaps.openstack.utils import keystone_utils, neutron_utils +from snaps.openstack.utils import neutron_utils __author__ = 'spisarski' @@ -91,477 +92,53 @@ class OpenStackNetwork(OpenStackNetworkObject): return self.__network -class NetworkSettings: +class NetworkSettings(NetworkConfig): """ - Class representing a network configuration + Class to hold the configuration settings required for creating OpenStack + Network objects + deprecated """ def __init__(self, **kwargs): - """ - Constructor - all parameters are optional - :param name: The network name. - :param admin_state_up: The administrative status of the network. - True = up / False = down (default True) - :param shared: Boolean value indicating whether this network is shared - across all projects/tenants. By default, only - administrative users can change this value. - :param project_name: Admin-only. The name of the project that will own - the network. This project can be different from - the project that makes the create network request. - However, only administrative users can specify a - project ID other than their own. You cannot change - this value through authorization policies. - :param external: when true, will setup an external network - (default False). - :param network_type: the type of network (i.e. vlan|flat). - :param physical_network: the name of the physical network - (required when network_type is 'flat') - :param segmentation_id: the id of the segmentation - (this is required when network_type is 'vlan') - :param subnets or subnet_settings: List of SubnetSettings objects. - :return: - """ - - self.project_id = None - - self.name = kwargs.get('name') - if kwargs.get('admin_state_up') is not None: - self.admin_state_up = bool(kwargs['admin_state_up']) - else: - self.admin_state_up = True - - if kwargs.get('shared') is not None: - self.shared = bool(kwargs['shared']) - else: - self.shared = None - - self.project_name = kwargs.get('project_name') - - if kwargs.get('external') is not None: - self.external = bool(kwargs.get('external')) - else: - self.external = False - - self.network_type = kwargs.get('network_type') - self.physical_network = kwargs.get('physical_network') - self.segmentation_id = kwargs.get('segmentation_id') - - self.subnet_settings = list() - subnet_settings = kwargs.get('subnets') - if not subnet_settings: - subnet_settings = kwargs.get('subnet_settings', list()) - if subnet_settings: - for subnet_config in subnet_settings: - if isinstance(subnet_config, SubnetSettings): - self.subnet_settings.append(subnet_config) - else: - self.subnet_settings.append( - SubnetSettings(**subnet_config['subnet'])) - - if not self.name or len(self.name) < 1: - raise NetworkSettingsError('Name required for networks') - - def get_project_id(self, os_creds): - """ - Returns the project ID for a given project_name or None - :param os_creds: the credentials required for keystone client retrieval - :return: the ID or None - """ - if self.project_id: - return self.project_id - else: - if self.project_name: - keystone = keystone_utils.keystone_client(os_creds) - project = keystone_utils.get_project( - keystone=keystone, project_name=self.project_name) - if project: - return project.id - - return None - - def dict_for_neutron(self, os_creds): - """ - Returns a dictionary object representing this object. - This is meant to be converted into JSON designed for use by the Neutron - API - TODO - expand automated testing to exercise all parameters - - :param os_creds: the OpenStack credentials - :return: the dictionary object - """ - out = dict() - - if self.name: - out['name'] = self.name - if self.admin_state_up is not None: - out['admin_state_up'] = self.admin_state_up - if self.shared: - out['shared'] = self.shared - if self.project_name: - project_id = self.get_project_id(os_creds) - if project_id: - out['tenant_id'] = project_id - else: - raise NetworkSettingsError( - 'Could not find project ID for project named - ' + - self.project_name) - if self.network_type: - out['provider:network_type'] = self.network_type - if self.physical_network: - out['provider:physical_network'] = self.physical_network - if self.segmentation_id: - out['provider:segmentation_id'] = self.segmentation_id - if self.external: - out['router:external'] = self.external - return {'network': out} - - -class NetworkSettingsError(Exception): - """ - Exception to be thrown when networks settings attributes are incorrect - """ + from warnings import warn + warn('Use snaps.config.network.NetworkConfig instead', + DeprecationWarning) + super(self.__class__, self).__init__(**kwargs) class IPv6Mode(enum.Enum): """ A rule's direction + deprecated - use snaps.config.network.IPv6Mode """ slaac = 'slaac' stateful = 'dhcpv6-stateful' stateless = 'dhcpv6-stateless' -class SubnetSettings: +class SubnetSettings(SubnetConfig): """ - Class representing a subnet configuration + Class to hold the configuration settings required for creating OpenStack + Subnet objects + deprecated """ def __init__(self, **kwargs): - """ - Constructor - all parameters are optional except cidr (subnet mask) - :param name: The subnet name (required) - :param cidr: The CIDR (required) - :param ip_version: The IP version, which is 4 or 6 (required) - :param project_name: The name of the project who owns the network. - Only administrative users can specify a project ID - other than their own. You cannot change this value - through authorization policies (optional) - :param start: The start address for the allocation pools (optional) - :param end: The end address for the allocation pools (optional) - :param gateway_ip: The gateway IP address (optional) - :param enable_dhcp: Set to true if DHCP is enabled and false if DHCP is - disabled (optional) - :param dns_nameservers: A list of DNS name servers for the subnet. - Specify each name server as an IP address - and separate multiple entries with a space. - For example [8.8.8.7 8.8.8.8] - (default '8.8.8.8') - :param host_routes: A list of host route dictionaries for the subnet. - For example: - "host_routes":[ - { - "destination":"0.0.0.0/0", - "nexthop":"123.456.78.9" - }, - { - "destination":"192.168.0.0/24", - "nexthop":"192.168.0.1" - } - ] - :param destination: The destination for static route (optional) - :param nexthop: The next hop for the destination (optional) - :param ipv6_ra_mode: an instance of the IPv6Mode enum - (optional when enable_dhcp is True) - :param ipv6_address_mode: an instance of the IPv6Mode enum - (optional when enable_dhcp is True) - :raise: SubnetSettingsError when config does not have or cidr values - are None - """ - self.cidr = kwargs.get('cidr') - if kwargs.get('ip_version'): - self.ip_version = kwargs['ip_version'] - else: - self.ip_version = 4 - - # Optional attributes that can be set after instantiation - self.name = kwargs.get('name') - self.project_name = kwargs.get('project_name') - self.start = kwargs.get('start') - self.end = kwargs.get('end') - self.gateway_ip = kwargs.get('gateway_ip') - self.enable_dhcp = kwargs.get('enable_dhcp') - - if 'dns_nameservers' in kwargs: - self.dns_nameservers = kwargs.get('dns_nameservers') - else: - if self.ip_version == 4: - self.dns_nameservers = ['8.8.8.8'] - else: - self.dns_nameservers = list() + from warnings import warn + warn('Use snaps.config.network.SubnetConfig instead', + DeprecationWarning) + super(self.__class__, self).__init__(**kwargs) - self.host_routes = kwargs.get('host_routes') - self.destination = kwargs.get('destination') - self.nexthop = kwargs.get('nexthop') - self.ipv6_ra_mode = map_mode(kwargs.get('ipv6_ra_mode')) - self.ipv6_address_mode = map_mode(kwargs.get('ipv6_address_mode')) - if not self.name or not self.cidr: - raise SubnetSettingsError('Name and cidr required for subnets') - - def dict_for_neutron(self, os_creds, network=None): - """ - Returns a dictionary object representing this object. - This is meant to be converted into JSON designed for use by the Neutron - API - :param os_creds: the OpenStack credentials - :param network: The network object on which the subnet will be created - (optional) - :return: the dictionary object - """ - out = { - 'cidr': self.cidr, - 'ip_version': self.ip_version, - } - - if network: - out['network_id'] = network.id - if self.name: - out['name'] = self.name - if self.project_name: - keystone = keystone_utils.keystone_client(os_creds) - project = keystone_utils.get_project( - keystone=keystone, project_name=self.project_name) - project_id = None - if project: - project_id = project.id - if project_id: - out['tenant_id'] = project_id - else: - raise SubnetSettingsError( - 'Could not find project ID for project named - ' + - self.project_name) - if self.start and self.end: - out['allocation_pools'] = [{'start': self.start, 'end': self.end}] - if self.gateway_ip: - out['gateway_ip'] = self.gateway_ip - if self.enable_dhcp is not None: - out['enable_dhcp'] = self.enable_dhcp - if self.dns_nameservers and len(self.dns_nameservers) > 0: - out['dns_nameservers'] = self.dns_nameservers - if self.host_routes and len(self.host_routes) > 0: - out['host_routes'] = self.host_routes - if self.destination: - out['destination'] = self.destination - if self.nexthop: - out['nexthop'] = self.nexthop - if self.ipv6_ra_mode: - out['ipv6_ra_mode'] = self.ipv6_ra_mode.value - if self.ipv6_address_mode: - out['ipv6_address_mode'] = self.ipv6_address_mode.value - return out - - -def map_mode(mode): +class PortSettings(PortConfig): """ - Takes a the direction value maps it to the Direction enum. When None return - None - :param mode: the mode value - :return: the IPv6Mode enum object - :raise: SubnetSettingsError if value is invalid - """ - if not mode: - return None - if isinstance(mode, IPv6Mode): - return mode - else: - mode_str = str(mode) - if mode_str == 'slaac': - return IPv6Mode.slaac - elif mode_str == 'dhcpv6-stateful': - return IPv6Mode.stateful - elif mode_str == 'stateful': - return IPv6Mode.stateful - elif mode_str == 'dhcpv6-stateless': - return IPv6Mode.stateless - elif mode_str == 'stateless': - return IPv6Mode.stateless - else: - raise SubnetSettingsError('Invalid mode - ' + mode_str) - - -class SubnetSettingsError(Exception): - """ - Exception to be thrown when subnet settings attributes are incorrect - """ - - -class PortSettings: - """ - Class representing a port configuration + Class to hold the configuration settings required for creating OpenStack + Subnet objects + deprecated """ def __init__(self, **kwargs): - """ - Constructor - :param name: A symbolic name for the port (optional). - :param network_name: The name of the network on which to create the - port (required). - :param admin_state_up: A boolean value denoting the administrative - status of the port (default = True) - :param project_name: The name of the project who owns the network. - Only administrative users can specify a project ID - other than their own. You cannot change this value - through authorization policies (optional) - :param mac_address: The MAC address. If you specify an address that is - not valid, a Bad Request (400) status code is - returned. If you do not specify a MAC address, - OpenStack Networking tries to allocate one. If a - failure occurs, a Service Unavailable (503) status - code is returned (optional) - :param ip_addrs: A list of dict objects where each contains two keys - 'subnet_name' and 'ip' values which will get mapped to - self.fixed_ips. These values will be directly - translated into the fixed_ips dict (optional) - :param security_groups: One or more security group IDs. - :param allowed_address_pairs: A dictionary containing a set of zero or - more allowed address pairs. An address - pair contains an IP address and MAC - address (optional) - :param opt_value: The extra DHCP option value (optional) - :param opt_name: The extra DHCP option name (optional) - :param device_owner: The ID of the entity that uses this port. - For example, a DHCP agent (optional) - :param device_id: The ID of the device that uses this port. - For example, a virtual server (optional) - :return: - """ - if 'port' in kwargs: - kwargs = kwargs['port'] - - self.name = kwargs.get('name') - self.network_name = kwargs.get('network_name') - - if kwargs.get('admin_state_up') is not None: - self.admin_state_up = bool(kwargs['admin_state_up']) - else: - self.admin_state_up = True - - self.project_name = kwargs.get('project_name') - self.mac_address = kwargs.get('mac_address') - self.ip_addrs = kwargs.get('ip_addrs') - self.security_groups = kwargs.get('security_groups') - self.allowed_address_pairs = kwargs.get('allowed_address_pairs') - self.opt_value = kwargs.get('opt_value') - self.opt_name = kwargs.get('opt_name') - self.device_owner = kwargs.get('device_owner') - self.device_id = kwargs.get('device_id') - - if not self.network_name: - raise PortSettingsError( - 'The attribute network_name is required') - - def __get_fixed_ips(self, neutron): - """ - Sets the self.fixed_ips value - :param neutron: the Neutron client - :return: None - """ - - fixed_ips = list() - if self.ip_addrs: - - for ip_addr_dict in self.ip_addrs: - subnet = neutron_utils.get_subnet( - neutron, subnet_name=ip_addr_dict['subnet_name']) - if subnet and 'ip' in ip_addr_dict: - fixed_ips.append({'ip_address': ip_addr_dict['ip'], - 'subnet_id': subnet.id}) - else: - raise PortSettingsError( - 'Invalid port configuration, subnet does not exist ' - 'with name - ' + ip_addr_dict['subnet_name']) - - return fixed_ips - - def dict_for_neutron(self, neutron, os_creds): - """ - Returns a dictionary object representing this object. - This is meant to be converted into JSON designed for use by the Neutron - API - - TODO - expand automated testing to exercise all parameters - :param neutron: the Neutron client - :param os_creds: the OpenStack credentials - :return: the dictionary object - """ - - out = dict() - - project_id = None - if self.project_name: - keystone = keystone_utils.keystone_client(os_creds) - project = keystone_utils.get_project( - keystone=keystone, project_name=self.project_name) - if project: - project_id = project.id - - network = neutron_utils.get_network( - neutron, network_name=self.network_name, project_id=project_id) - if not network: - raise PortSettingsError( - 'Cannot locate network with name - ' + self.network_name) - - out['network_id'] = network.id - - if self.admin_state_up is not None: - out['admin_state_up'] = self.admin_state_up - if self.name: - out['name'] = self.name - if self.project_name: - if project_id: - out['tenant_id'] = project_id - else: - raise PortSettingsError( - 'Could not find project ID for project named - ' + - self.project_name) - if self.mac_address: - out['mac_address'] = self.mac_address - - fixed_ips = self.__get_fixed_ips(neutron) - if fixed_ips and len(fixed_ips) > 0: - out['fixed_ips'] = fixed_ips - - if self.security_groups: - out['security_groups'] = self.security_groups - if self.allowed_address_pairs and len(self.allowed_address_pairs) > 0: - out['allowed_address_pairs'] = self.allowed_address_pairs - if self.opt_value: - out['opt_value'] = self.opt_value - if self.opt_name: - out['opt_name'] = self.opt_name - if self.device_owner: - out['device_owner'] = self.device_owner - 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) - - -class PortSettingsError(Exception): - """ - Exception to be thrown when port settings attributes are incorrect - """ + from warnings import warn + warn('Use snaps.config.network.PortConfig instead', + DeprecationWarning) + super(self.__class__, self).__init__(**kwargs) diff --git a/snaps/openstack/create_stack.py b/snaps/openstack/create_stack.py index cd65a27..1fcc5b4 100644 --- a/snaps/openstack/create_stack.py +++ b/snaps/openstack/create_stack.py @@ -223,7 +223,7 @@ class OpenStackHeatStack(OpenStackCloudObject, object): self.__heat_cli, neutron, self.__stack) for stack_network in stack_networks: - net_settings = settings_utils.create_network_settings( + net_settings = settings_utils.create_network_config( neutron, stack_network) net_creator = OpenStackNetwork(self._os_creds, net_settings) out.append(net_creator) diff --git a/snaps/openstack/tests/create_instance_tests.py b/snaps/openstack/tests/create_instance_tests.py index c7a6c83..f806100 100644 --- a/snaps/openstack/tests/create_instance_tests.py +++ b/snaps/openstack/tests/create_instance_tests.py @@ -24,20 +24,20 @@ from neutronclient.common.exceptions import InvalidIpForSubnetClient from novaclient.exceptions import BadRequest from snaps import file_utils -from snaps.config.volume import VolumeConfig -from snaps.config.router import RouterConfig +from snaps.config.flavor import FlavorConfig +from snaps.config.image import ImageConfig from snaps.config.keypair import KeypairConfig +from snaps.config.network import PortConfig, NetworkConfig, SubnetConfig +from snaps.config.router import RouterConfig +from snaps.config.volume import VolumeConfig from snaps.openstack import create_network, create_router -from snaps.config.flavor import FlavorConfig from snaps.openstack.create_flavor import OpenStackFlavor -from snaps.config.image import ImageConfig from snaps.openstack.create_image import OpenStackImage from snaps.openstack.create_instance import ( VmInstanceSettings, OpenStackVmInstance, FloatingIpSettings, VmInstanceSettingsError, FloatingIpSettingsError) from snaps.openstack.create_keypairs import OpenStackKeypair -from snaps.openstack.create_network import ( - OpenStackNetwork, PortSettings, NetworkSettings, SubnetSettings) +from snaps.openstack.create_network import OpenStackNetwork from snaps.openstack.create_router import OpenStackRouter from snaps.openstack.create_security_group import ( SecurityGroupSettings, OpenStackSecurityGroup, SecurityGroupRuleSettings, @@ -85,7 +85,7 @@ class VmInstanceSettingsUnitTests(unittest.TestCase): VmInstanceSettings(config={'name': 'foo', 'flavor': 'bar'}) def test_name_flavor_port_only(self): - port_settings = PortSettings(name='foo-port', network_name='bar-net') + port_settings = PortConfig(name='foo-port', network_name='bar-net') settings = VmInstanceSettings(name='foo', flavor='bar', port_settings=[port_settings]) self.assertEqual('foo', settings.name) @@ -103,7 +103,7 @@ class VmInstanceSettingsUnitTests(unittest.TestCase): self.assertIsNone(settings.volume_names) def test_config_with_name_flavor_port_only(self): - port_settings = PortSettings(name='foo-port', network_name='bar-net') + port_settings = PortConfig(name='foo-port', network_name='bar-net') settings = VmInstanceSettings( **{'name': 'foo', 'flavor': 'bar', 'ports': [port_settings]}) self.assertEqual('foo', settings.name) @@ -121,7 +121,7 @@ class VmInstanceSettingsUnitTests(unittest.TestCase): self.assertIsNone(settings.volume_names) def test_all(self): - port_settings = PortSettings(name='foo-port', network_name='bar-net') + port_settings = PortConfig(name='foo-port', network_name='bar-net') fip_settings = FloatingIpSettings(name='foo-fip', port_name='bar-port', router_name='foo-bar-router') @@ -153,7 +153,7 @@ class VmInstanceSettingsUnitTests(unittest.TestCase): self.assertEqual('vol1', settings.volume_names[0]) def test_config_all(self): - port_settings = PortSettings(name='foo-port', network_name='bar-net') + port_settings = PortConfig(name='foo-port', network_name='bar-net') fip_settings = FloatingIpSettings(name='foo-fip', port_name='bar-port', router_name='foo-bar-router') @@ -303,7 +303,7 @@ class SimpleHealthCheck(OSIntegrationTestCase): self.priv_net_config = openstack_tests.get_priv_net_config( net_name=guid + '-priv-net', subnet_name=guid + '-priv-subnet') - self.port_settings = PortSettings( + self.port_settings = PortConfig( name=self.port_1_name, network_name=self.priv_net_config.network_settings.name) @@ -442,7 +442,7 @@ class CreateInstanceSimpleTests(OSIntegrationTestCase): self.os_creds, net_config.network_settings) self.network_creator.create() - self.port_settings = PortSettings( + self.port_settings = PortConfig( name=guid + '-port', network_name=net_config.network_settings.name) @@ -668,7 +668,7 @@ class CreateInstanceSingleNetworkTests(OSIntegrationTestCase): """ ip_1 = '10.55.1.100' sub_settings = self.pub_net_config.network_settings.subnet_settings - port_settings = PortSettings( + port_settings = PortConfig( name=self.port_1_name, network_name=self.pub_net_config.network_settings.name, ip_addrs=[ @@ -698,7 +698,7 @@ class CreateInstanceSingleNetworkTests(OSIntegrationTestCase): Tests the ability to access a VM via SSH and a floating IP when it has been assigned prior to being active. """ - port_settings = PortSettings( + port_settings = PortConfig( name=self.port_1_name, network_name=self.pub_net_config.network_settings.name) @@ -733,7 +733,7 @@ class CreateInstanceSingleNetworkTests(OSIntegrationTestCase): Tests the ability to access a VM via SSH and a floating IP when it has been assigned prior to being active. """ - port_settings = PortSettings( + port_settings = PortConfig( name=self.port_1_name, network_name=self.pub_net_config.network_settings.name) @@ -770,7 +770,7 @@ class CreateInstanceSingleNetworkTests(OSIntegrationTestCase): Tests the ability to access a VM via SSH and a floating IP via a creator that is identical to the original creator. """ - port_settings = PortSettings( + port_settings = PortConfig( name=self.port_1_name, network_name=self.pub_net_config.network_settings.name) @@ -945,10 +945,10 @@ class CreateInstanceIPv6NetworkTests(OSIntegrationTestCase): Tests the ability to assign an IPv4 floating IP to an IPv6 overlay network when the external network does not have an IPv6 subnet. """ - subnet_settings = SubnetSettings( + subnet_settings = SubnetConfig( name=self.guid + '-subnet', cidr='1:1:0:0:0:0:0:0/64', ip_version=6) - network_settings = NetworkSettings( + network_settings = NetworkConfig( name=self.guid + '-net', subnet_settings=[subnet_settings]) router_settings = RouterConfig( name=self.guid + '-router', external_gateway=self.ext_net_name, @@ -964,7 +964,7 @@ class CreateInstanceIPv6NetworkTests(OSIntegrationTestCase): self.os_creds, router_settings) self.router_creator.create() - port_settings = PortSettings( + port_settings = PortConfig( name=self.port1_name, network_name=network_settings.name) instance_settings = VmInstanceSettings( @@ -989,13 +989,13 @@ class CreateInstanceIPv6NetworkTests(OSIntegrationTestCase): Tests the ability to assign an IPv4 floating IP to an IPv6 overlay network when the external network does not have an IPv6 subnet. """ - subnet4_settings = SubnetSettings( + subnet4_settings = SubnetConfig( name=self.guid + '-subnet4', cidr='10.0.1.0/24', ip_version=4) - subnet6_settings = SubnetSettings( + subnet6_settings = SubnetConfig( name=self.guid + '-subnet6', cidr='1:1:0:0:0:0:0:0/64', ip_version=6) - network_settings = NetworkSettings( + network_settings = NetworkConfig( name=self.guid + '-net', subnet_settings=[subnet4_settings, subnet6_settings]) router_settings = RouterConfig( @@ -1012,7 +1012,7 @@ class CreateInstanceIPv6NetworkTests(OSIntegrationTestCase): self.os_creds, router_settings) self.router_creator.create() - port_settings = PortSettings( + port_settings = PortConfig( name=self.port1_name, network_name=network_settings.name) instance_settings = VmInstanceSettings( @@ -1130,7 +1130,7 @@ class CreateInstancePortManipulationTests(OSIntegrationTestCase): """ ip = '10.55.0.101' sub_settings = self.net_config.network_settings.subnet_settings - port_settings = PortSettings( + port_settings = PortConfig( name=self.port_1_name, network_name=self.net_config.network_settings.name, ip_addrs=[{'subnet_name': sub_settings[0].name, 'ip': ip}]) @@ -1157,7 +1157,7 @@ class CreateInstancePortManipulationTests(OSIntegrationTestCase): """ ip = '10.66.0.101' sub_settings = self.net_config.network_settings.subnet_settings - port_settings = PortSettings( + port_settings = PortConfig( name=self.port_1_name, network_name=self.net_config.network_settings.name, ip_addrs=[{'subnet_name': sub_settings[0].name, 'ip': ip}]) @@ -1180,7 +1180,7 @@ class CreateInstancePortManipulationTests(OSIntegrationTestCase): the MAC address is assigned. """ mac_addr = '0a:1b:2c:3d:4e:5f' - port_settings = PortSettings( + port_settings = PortConfig( name=self.port_1_name, network_name=self.net_config.network_settings.name, mac_address=mac_addr) @@ -1204,7 +1204,7 @@ class CreateInstancePortManipulationTests(OSIntegrationTestCase): invalid MAC address value is being assigned. This should raise an Exception """ - port_settings = PortSettings( + port_settings = PortConfig( name=self.port_1_name, network_name=self.net_config.network_settings.name, mac_address='foo') @@ -1229,7 +1229,7 @@ class CreateInstancePortManipulationTests(OSIntegrationTestCase): ip = '10.55.0.101' mac_addr = '0a:1b:2c:3d:4e:5f' sub_settings = self.net_config.network_settings.subnet_settings - port_settings = PortSettings( + port_settings = PortConfig( name=self.port_1_name, network_name=self.net_config.network_settings.name, mac_address=mac_addr, @@ -1260,7 +1260,7 @@ class CreateInstancePortManipulationTests(OSIntegrationTestCase): ip = '10.55.0.101' mac_addr = '0a:1b:2c:3d:4e:5f' pair = {'ip_address': ip, 'mac_address': mac_addr} - port_settings = PortSettings( + port_settings = PortConfig( name=self.port_1_name, network_name=self.net_config.network_settings.name, allowed_address_pairs=[pair]) @@ -1292,7 +1292,7 @@ class CreateInstancePortManipulationTests(OSIntegrationTestCase): pair = {'ip_address': ip, 'mac_address': mac_addr} pairs = set() pairs.add((ip, mac_addr)) - port_settings = PortSettings( + port_settings = PortConfig( name=self.port_1_name, network_name=self.net_config.network_settings.name, allowed_address_pairs=[pair]) @@ -1318,7 +1318,7 @@ class CreateInstancePortManipulationTests(OSIntegrationTestCase): pair = {'ip_address': ip, 'mac_address': mac_addr} pairs = set() pairs.add((ip, mac_addr)) - port_settings = PortSettings( + port_settings = PortConfig( name=self.port_1_name, network_name=self.net_config.network_settings.name, allowed_address_pairs=[pair]) @@ -1435,7 +1435,7 @@ class CreateInstanceOnComputeHost(OSIntegrationTestCase): for zone in zone_hosts: inst_name = self.vm_inst_name + '-' + zone ctr += 1 - port_settings = PortSettings( + port_settings = PortConfig( name=self.port_base_name + '-' + str(ctr), network_name=self.priv_net_config.network_settings.name) @@ -1647,7 +1647,7 @@ class CreateInstancePubPrivNetTests(OSIntegrationTestCase): ports_settings = [] ctr = 1 for network_creator in self.network_creators: - ports_settings.append(PortSettings( + ports_settings.append(PortConfig( name=self.guid + '-port-' + str(ctr), network_name=network_creator.network_settings.name)) ctr += 1 @@ -1739,7 +1739,7 @@ class InstanceSecurityGroupTests(OSIntegrationTestCase): metadata=self.flavor_metadata)) self.flavor_creator.create() - self.port_settings = PortSettings( + self.port_settings = PortConfig( name=self.guid + '-port', network_name=net_config.network_settings.name) except Exception as e: @@ -2077,7 +2077,7 @@ class CreateInstanceFromThreePartImage(OSIntegrationTestCase): self.os_creds, net_config.network_settings) self.network_creator.create() - self.port_settings = PortSettings( + self.port_settings = PortConfig( name=guid + '-port', network_name=net_config.network_settings.name) except Exception as e: @@ -2172,7 +2172,7 @@ class CreateInstanceMockOfflineTests(OSComponentTestCase): self.priv_net_config = openstack_tests.get_priv_net_config( net_name=self.guid + '-priv-net', subnet_name=self.guid + '-priv-subnet') - self.port_settings = PortSettings( + self.port_settings = PortConfig( name=self.port_1_name, network_name=self.priv_net_config.network_settings.name) @@ -2670,16 +2670,16 @@ class CreateInstanceTwoNetTests(OSIntegrationTestCase): self.vm_inst2_name = self.guid + '-inst2' self.port_1_name = self.guid + '-vm1-port' self.port_2_name = self.guid + '-vm2-port' - self.net_config_1 = NetworkSettings( + self.net_config_1 = NetworkConfig( name=self.guid + '-net1', subnet_settings=[ - create_network.SubnetSettings( + create_network.SubnetConfig( cidr=cidr1, name=self.guid + '-subnet1', gateway_ip=static_gateway_ip1)]) - self.net_config_2 = NetworkSettings( + self.net_config_2 = NetworkConfig( name=self.guid + '-net2', subnet_settings=[ - create_network.SubnetSettings( + create_network.SubnetConfig( cidr=cidr2, name=self.guid + '-subnet2', gateway_ip=static_gateway_ip2)]) @@ -2703,7 +2703,7 @@ class CreateInstanceTwoNetTests(OSIntegrationTestCase): network_creator.create() port_settings = [ - create_network.PortSettings( + create_network.PortConfig( name=self.guid + '-router-port1', ip_addrs=[{ 'subnet_name': @@ -2712,7 +2712,7 @@ class CreateInstanceTwoNetTests(OSIntegrationTestCase): }], network_name=self.net_config_1.name, project_name=self.os_creds.project_name), - create_network.PortSettings( + create_network.PortConfig( name=self.guid + '-router-port2', ip_addrs=[{ 'subnet_name': @@ -2813,7 +2813,7 @@ class CreateInstanceTwoNetTests(OSIntegrationTestCase): ports_settings = [] ctr = 1 for network_creator in self.network_creators: - ports_settings.append(PortSettings( + ports_settings.append(PortConfig( name=self.guid + '-port-' + str(ctr), network_name=network_creator.network_settings.name)) ctr += 1 @@ -2823,7 +2823,7 @@ class CreateInstanceTwoNetTests(OSIntegrationTestCase): name=self.vm_inst1_name, flavor=self.flavor_creator.flavor_settings.name, userdata=_get_ping_userdata(self.ip2), - port_settings=[PortSettings( + port_settings=[PortConfig( name=self.port_1_name, ip_addrs=[{ 'subnet_name': @@ -2835,7 +2835,7 @@ class CreateInstanceTwoNetTests(OSIntegrationTestCase): name=self.vm_inst2_name, flavor=self.flavor_creator.flavor_settings.name, userdata=_get_ping_userdata(self.ip1), - port_settings=[PortSettings( + port_settings=[PortConfig( name=self.port_2_name, ip_addrs=[{ 'subnet_name': @@ -2919,7 +2919,7 @@ class CreateInstanceVolumeTests(OSIntegrationTestCase): self.os_creds, net_config.network_settings) self.network_creator.create() - self.port_settings = PortSettings( + self.port_settings = PortConfig( name=guid + '-port', network_name=net_config.network_settings.name) diff --git a/snaps/openstack/tests/create_network_tests.py b/snaps/openstack/tests/create_network_tests.py index 3d0a102..ac0aad1 100644 --- a/snaps/openstack/tests/create_network_tests.py +++ b/snaps/openstack/tests/create_network_tests.py @@ -15,15 +15,18 @@ import unittest import uuid +from snaps.config.network import ( + NetworkConfig, SubnetConfig, SubnetConfigError, NetworkConfigError, + PortConfigError, IPv6Mode) from snaps.openstack import create_router from snaps.openstack.create_network import ( - OpenStackNetwork, NetworkSettings, SubnetSettings, PortSettings, - NetworkSettingsError, SubnetSettingsError, PortSettingsError, IPv6Mode) + OpenStackNetwork, NetworkSettings, SubnetSettings, PortSettings) from snaps.openstack.tests import openstack_tests from snaps.openstack.tests.os_source_file_test import ( OSIntegrationTestCase, OSComponentTestCase) from snaps.openstack.utils import neutron_utils from snaps.openstack.utils.tests import neutron_utils_tests +from snaps.openstack.create_network import IPv6Mode as IPv6Mode_old __author__ = 'spisarski' @@ -34,11 +37,11 @@ class NetworkSettingsUnitTests(unittest.TestCase): """ def test_no_params(self): - with self.assertRaises(NetworkSettingsError): + with self.assertRaises(NetworkConfigError): NetworkSettings() def test_empty_config(self): - with self.assertRaises(NetworkSettingsError): + with self.assertRaises(NetworkConfigError): NetworkSettings(**dict()) def test_name_only(self): @@ -109,19 +112,19 @@ class SubnetSettingsUnitTests(unittest.TestCase): """ def test_no_params(self): - with self.assertRaises(SubnetSettingsError): + with self.assertRaises(SubnetConfigError): SubnetSettings() def test_empty_config(self): - with self.assertRaises(SubnetSettingsError): + with self.assertRaises(SubnetConfigError): SubnetSettings(**dict()) def test_name_only(self): - with self.assertRaises(SubnetSettingsError): + with self.assertRaises(SubnetConfigError): SubnetSettings(name='foo') def test_config_with_name_only(self): - with self.assertRaises(SubnetSettingsError): + with self.assertRaises(SubnetConfigError): SubnetSettings(**{'name': 'foo'}) def test_name_cidr_only(self): @@ -161,16 +164,13 @@ class SubnetSettingsUnitTests(unittest.TestCase): def test_all_string_enums(self): host_routes = {'destination': '0.0.0.0/0', 'nexthop': '123.456.78.9'} - settings = SubnetSettings(name='foo', cidr='10.0.0.0/24', ip_version=6, - project_name='bar-project', - start='10.0.0.2', end='10.0.0.101', - gateway_ip='10.0.0.1', enable_dhcp=False, - dns_nameservers=['8.8.8.8'], - host_routes=[host_routes], - destination='dest', - nexthop='hop', - ipv6_ra_mode='dhcpv6-stateful', - ipv6_address_mode='slaac') + settings = SubnetSettings( + name='foo', cidr='10.0.0.0/24', ip_version=6, + project_name='bar-project', start='10.0.0.2', end='10.0.0.101', + gateway_ip='10.0.0.1', enable_dhcp=False, + dns_nameservers=['8.8.8.8'], host_routes=[host_routes], + destination='dest', nexthop='hop', ipv6_ra_mode='dhcpv6-stateful', + ipv6_address_mode='slaac') self.assertEqual('foo', settings.name) self.assertEqual('10.0.0.0/24', settings.cidr) self.assertEqual(6, settings.ip_version) @@ -185,21 +185,21 @@ class SubnetSettingsUnitTests(unittest.TestCase): self.assertEqual(host_routes, settings.host_routes[0]) self.assertEqual('dest', settings.destination) self.assertEqual('hop', settings.nexthop) - self.assertEqual(IPv6Mode.stateful, settings.ipv6_ra_mode) - self.assertEqual(IPv6Mode.slaac, settings.ipv6_address_mode) + self.assertEqual(IPv6Mode_old.stateful.value, + settings.ipv6_ra_mode.value) + self.assertEqual(IPv6Mode_old.slaac.value, + settings.ipv6_address_mode.value) def test_all_type_enums(self): host_routes = {'destination': '0.0.0.0/0', 'nexthop': '123.456.78.9'} - settings = SubnetSettings(name='foo', cidr='10.0.0.0/24', ip_version=6, - project_name='bar-project', - start='10.0.0.2', end='10.0.0.101', - gateway_ip='10.0.0.1', enable_dhcp=False, - dns_nameservers=['8.8.8.8'], - host_routes=[host_routes], - destination='dest', - nexthop='hop', - ipv6_ra_mode=IPv6Mode.stateful, - ipv6_address_mode=IPv6Mode.slaac) + settings = SubnetSettings( + name='foo', cidr='10.0.0.0/24', ip_version=6, + project_name='bar-project', start='10.0.0.2', end='10.0.0.101', + gateway_ip='10.0.0.1', enable_dhcp=False, + dns_nameservers=['8.8.8.8'], host_routes=[host_routes], + destination='dest', nexthop='hop', + ipv6_ra_mode=IPv6Mode_old.stateful, + ipv6_address_mode=IPv6Mode.slaac) self.assertEqual('foo', settings.name) self.assertEqual('10.0.0.0/24', settings.cidr) self.assertEqual(6, settings.ip_version) @@ -214,8 +214,9 @@ class SubnetSettingsUnitTests(unittest.TestCase): self.assertEqual(host_routes, settings.host_routes[0]) self.assertEqual('dest', settings.destination) self.assertEqual('hop', settings.nexthop) - self.assertEqual(IPv6Mode.stateful, settings.ipv6_ra_mode) - self.assertEqual(IPv6Mode.slaac, settings.ipv6_address_mode) + self.assertEqual(IPv6Mode.stateful.value, settings.ipv6_ra_mode.value) + self.assertEqual(IPv6Mode.slaac.value, + settings.ipv6_address_mode.value) def test_config_all(self): host_routes = {'destination': '0.0.0.0/0', 'nexthop': '123.456.78.9'} @@ -242,8 +243,9 @@ class SubnetSettingsUnitTests(unittest.TestCase): self.assertEqual(host_routes, settings.host_routes[0]) self.assertEqual('dest', settings.destination) self.assertEqual('hop', settings.nexthop) - self.assertEqual(IPv6Mode.stateless, settings.ipv6_ra_mode) - self.assertEqual(IPv6Mode.slaac, settings.ipv6_address_mode) + self.assertEqual(IPv6Mode.stateless.value, settings.ipv6_ra_mode.value) + self.assertEqual(IPv6Mode.slaac.value, + settings.ipv6_address_mode.value) class PortSettingsUnitTests(unittest.TestCase): @@ -252,19 +254,19 @@ class PortSettingsUnitTests(unittest.TestCase): """ def test_no_params(self): - with self.assertRaises(PortSettingsError): + with self.assertRaises(PortConfigError): PortSettings() def test_empty_config(self): - with self.assertRaises(PortSettingsError): + with self.assertRaises(PortConfigError): PortSettings(**dict()) def test_name_only(self): - with self.assertRaises(PortSettingsError): + with self.assertRaises(PortConfigError): PortSettings(name='foo') def test_config_name_only(self): - with self.assertRaises(PortSettingsError): + with self.assertRaises(PortConfigError): PortSettings(**{'name': 'foo'}) def test_name_netname_only(self): @@ -566,10 +568,10 @@ class CreateNetworkIPv6Tests(OSIntegrationTestCase): Tests the creation of an OpenStack network without a router. """ # Create Network - subnet_settings = SubnetSettings( + subnet_settings = SubnetConfig( name=self.guid + '-subnet', cidr='1:1:0:0:0:0:0:0/64', ip_version=6) - network_settings = NetworkSettings( + network_settings = NetworkConfig( name=self.guid + '-net', subnet_settings=[subnet_settings]) self.net_creator = OpenStackNetwork(self.os_creds, network_settings) @@ -594,13 +596,13 @@ class CreateNetworkIPv6Tests(OSIntegrationTestCase): Tests the creation of an OpenStack network without a router. """ # Create Network - subnet4_settings = SubnetSettings( + subnet4_settings = SubnetConfig( name=self.guid + '-subnet4', cidr='10.0.1.0/24', ip_version=4) - subnet6_settings = SubnetSettings( + subnet6_settings = SubnetConfig( name=self.guid + '-subnet6', cidr='1:1:0:0:0:0:0:0/64', ip_version=6) - network_settings = NetworkSettings( + network_settings = NetworkConfig( name=self.guid + '-net', subnet_settings=[subnet4_settings, subnet6_settings]) @@ -666,7 +668,7 @@ class CreateNetworkTypeTests(OSComponentTestCase): """ # Create Network network_type = 'vlan' - net_settings = NetworkSettings( + net_settings = NetworkConfig( name=self.net_config.network_settings.name, subnet_settings=self.net_config.network_settings.subnet_settings, network_type=network_type) @@ -693,7 +695,7 @@ class CreateNetworkTypeTests(OSComponentTestCase): physical_network = 'datacentre' segmentation_id = 2366 - net_settings = NetworkSettings( + net_settings = NetworkConfig( name=self.net_config.network_settings.name, subnet_settings=self.net_config.network_settings.subnet_settings, network_type=network_type, @@ -716,7 +718,7 @@ class CreateNetworkTypeTests(OSComponentTestCase): """ # Create Network network_type = 'vxlan' - net_settings = NetworkSettings( + net_settings = NetworkConfig( name=self.net_config.network_settings.name, subnet_settings=self.net_config.network_settings.subnet_settings, network_type=network_type) @@ -741,7 +743,7 @@ class CreateNetworkTypeTests(OSComponentTestCase): # This value must be variable to work on all OpenStack pods physical_network = 'datacentre' - net_settings = NetworkSettings( + net_settings = NetworkConfig( name=self.net_config.network_settings.name, subnet_settings=self.net_config.network_settings.subnet_settings, network_type=network_type, physical_network=physical_network) @@ -761,7 +763,7 @@ class CreateNetworkTypeTests(OSComponentTestCase): """ # Create Network network_type = 'foo' - net_settings = NetworkSettings( + net_settings = NetworkConfig( name=self.net_config.network_settings.name, subnet_settings=self.net_config.network_settings.subnet_settings, network_type=network_type) diff --git a/snaps/openstack/tests/create_router_tests.py b/snaps/openstack/tests/create_router_tests.py index 70dbd6d..5c34037 100644 --- a/snaps/openstack/tests/create_router_tests.py +++ b/snaps/openstack/tests/create_router_tests.py @@ -15,11 +15,10 @@ import unittest import uuid +from snaps.config.network import PortConfig, NetworkConfig from snaps.config.router import RouterConfigError, RouterConfig from snaps.openstack import create_network from snaps.openstack import create_router -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 @@ -75,7 +74,7 @@ class RouterSettingsUnitTests(unittest.TestCase): self.assertEqual(0, len(settings.port_settings)) def test_all(self): - port_settings = PortSettings(name='foo', network_name='bar') + port_settings = PortConfig(name='foo', network_name='bar') settings = RouterSettings( name='foo', project_name='bar', external_gateway='foo_gateway', admin_state_up=True, enable_snat=False, @@ -108,9 +107,9 @@ class RouterSettingsUnitTests(unittest.TestCase): 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) + self.assertEqual( + [PortConfig(**{'name': 'foo-port', 'network_name': 'bar-net'})], + settings.port_settings) class CreateRouterSuccessTests(OSIntegrationTestCase): @@ -275,16 +274,16 @@ class CreateRouterSuccessTests(OSIntegrationTestCase): Test creation of a router connected with two private networks and no external gateway """ - network_settings1 = NetworkSettings( + network_settings1 = NetworkConfig( name=self.guid + '-pub-net1', subnet_settings=[ - create_network.SubnetSettings( + create_network.SubnetConfig( cidr=cidr1, name=self.guid + '-pub-subnet1', gateway_ip=static_gateway_ip1)]) - network_settings2 = NetworkSettings( + network_settings2 = NetworkConfig( name=self.guid + '-pub-net2', subnet_settings=[ - create_network.SubnetSettings( + create_network.SubnetConfig( cidr=cidr2, name=self.guid + '-pub-subnet2', gateway_ip=static_gateway_ip2)]) @@ -297,7 +296,7 @@ class CreateRouterSuccessTests(OSIntegrationTestCase): self.network_creator2.create() port_settings = [ - create_network.PortSettings( + create_network.PortConfig( name=self.guid + '-port1', ip_addrs=[{ 'subnet_name': @@ -306,7 +305,7 @@ class CreateRouterSuccessTests(OSIntegrationTestCase): }], network_name=network_settings1.name, project_name=self.os_creds.project_name), - create_network.PortSettings( + create_network.PortConfig( name=self.guid + '-port2', ip_addrs=[{ 'subnet_name': network_settings2.subnet_settings[0].name, @@ -340,10 +339,10 @@ class CreateRouterSuccessTests(OSIntegrationTestCase): Test creation of a router connected to an external network and a private network. """ - network_settings = NetworkSettings( + network_settings = NetworkConfig( name=self.guid + '-pub-net1', subnet_settings=[ - create_network.SubnetSettings( + create_network.SubnetConfig( cidr=cidr1, name=self.guid + '-pub-subnet1', gateway_ip=static_gateway_ip1)]) self.network_creator1 = OpenStackNetwork(self.os_creds, @@ -351,7 +350,7 @@ class CreateRouterSuccessTests(OSIntegrationTestCase): self.network_creator1.create() port_settings = [ - create_network.PortSettings( + create_network.PortConfig( name=self.guid + '-port1', ip_addrs=[{ 'subnet_name': network_settings.subnet_settings[0].name, diff --git a/snaps/openstack/tests/openstack_tests.py b/snaps/openstack/tests/openstack_tests.py index ff64af5..78e8601 100644 --- a/snaps/openstack/tests/openstack_tests.py +++ b/snaps/openstack/tests/openstack_tests.py @@ -18,8 +18,8 @@ import re import pkg_resources from snaps import file_utils from snaps.config.image import ImageConfig +from snaps.config.network import NetworkConfig, SubnetConfig from snaps.config.router import RouterConfig -from snaps.openstack.create_network import NetworkSettings, SubnetSettings from snaps.openstack.os_credentials import OSCreds, ProxySettings __author__ = 'spisarski' @@ -338,11 +338,11 @@ class OSNetworkConfig: router_name=None, external_gateway=None): if subnet_name and subnet_cidr: - self.network_settings = NetworkSettings( + self.network_settings = NetworkConfig( name=net_name, subnet_settings=[ - SubnetSettings(cidr=subnet_cidr, name=subnet_name)]) + SubnetConfig(cidr=subnet_cidr, name=subnet_name)]) else: - self.network_settings = NetworkSettings(name=net_name) + self.network_settings = NetworkConfig(name=net_name) if router_name: if subnet_name: diff --git a/snaps/openstack/utils/neutron_utils.py b/snaps/openstack/utils/neutron_utils.py index ec8daff..b59f811 100644 --- a/snaps/openstack/utils/neutron_utils.py +++ b/snaps/openstack/utils/neutron_utils.py @@ -109,7 +109,7 @@ def get_network(neutron, network_settings=None, network_name=None, else the query will use just the name from the network_name parameter. When the project_id is included, that will be added to the query filter. :param neutron: the client - :param network_settings: the NetworkSettings object used to create filter + :param network_settings: the NetworkConfig object used to create filter :param network_name: the name of the network to retrieve :param project_id: the id of the network's project :return: a SNAPS-OO Network domain object @@ -480,7 +480,7 @@ def get_port(neutron, port_settings=None, port_name=None): """ Returns the first port object (dictionary) found for the given query :param neutron: the client - :param port_settings: the PortSettings object used for generating the query + :param port_settings: the PortConfig object used for generating the query :param port_name: if port_settings is None, this name is the value to place into the query :return: a SNAPS-OO Port domain object diff --git a/snaps/openstack/utils/settings_utils.py b/snaps/openstack/utils/settings_utils.py index 80dfc84..ab26d3d 100644 --- a/snaps/openstack/utils/settings_utils.py +++ b/snaps/openstack/utils/settings_utils.py @@ -17,35 +17,34 @@ import uuid from snaps import file_utils from snaps.config.flavor import FlavorConfig from snaps.config.keypair import KeypairConfig +from snaps.config.network import SubnetConfig, PortConfig, NetworkConfig from snaps.config.router import RouterConfig from snaps.config.volume import VolumeConfig from snaps.config.volume_type import ( ControlLocation, VolumeTypeEncryptionConfig, VolumeTypeConfig) from snaps.openstack.create_instance import ( VmInstanceSettings, FloatingIpSettings) -from snaps.openstack.create_network import ( - PortSettings, SubnetSettings, NetworkSettings) from snaps.openstack.create_security_group import ( SecurityGroupSettings, SecurityGroupRuleSettings) from snaps.openstack.utils import ( neutron_utils, nova_utils, heat_utils, glance_utils) -def create_network_settings(neutron, network): +def create_network_config(neutron, network): """ - Returns a NetworkSettings object + Returns a NetworkConfig object :param neutron: the neutron client :param network: a SNAPS-OO Network domain object :return: """ - return NetworkSettings( + return NetworkConfig( name=network.name, network_type=network.type, - subnet_settings=create_subnet_settings(neutron, network)) + subnet_settings=create_subnet_config(neutron, network)) def create_security_group_settings(neutron, security_group): """ - Returns a NetworkSettings object + Returns a NetworkConfig object :param neutron: the neutron client :param security_group: a SNAPS-OO SecurityGroup domain object :return: @@ -67,9 +66,9 @@ def create_security_group_settings(neutron, security_group): rule_settings=rule_settings) -def create_subnet_settings(neutron, network): +def create_subnet_config(neutron, network): """ - Returns a list of SubnetSettings objects for a given network + Returns a list of SubnetConfig objects for a given network :param neutron: the OpenStack neutron client :param network: the SNAPS-OO Network domain object :return: a list @@ -90,7 +89,7 @@ def create_subnet_settings(neutron, network): kwargs['host_routes'] = subnet.host_routes kwargs['ipv6_ra_mode'] = subnet.ipv6_ra_mode kwargs['ipv6_address_mode'] = subnet.ipv6_address_mode - out.append(SubnetSettings(**kwargs)) + out.append(SubnetConfig(**kwargs)) return out @@ -135,7 +134,7 @@ def create_router_settings(neutron, router): ports_tuple_list.append((network, ip_list)) - port_settings = __create_port_settings(neutron, ports_tuple_list) + port_settings = __create_port_config(neutron, ports_tuple_list) filtered_settings = list() for port_setting in port_settings: @@ -231,7 +230,7 @@ def create_keypair_settings(heat_cli, stack, keypair, pk_output_key): def create_vm_inst_settings(nova, neutron, server): """ - Returns a NetworkSettings object + Returns a NetworkConfig object :param nova: the nova client :param neutron: the neutron client :param server: a SNAPS-OO VmInst domain object @@ -250,7 +249,7 @@ def create_vm_inst_settings(nova, neutron, server): if network: net_tuples.append((network, ips)) - kwargs['port_settings'] = __create_port_settings( + kwargs['port_settings'] = __create_port_config( neutron, net_tuples) kwargs['security_group_names'] = server.sec_grp_names kwargs['floating_ip_settings'] = __create_floatingip_settings( @@ -259,7 +258,7 @@ def create_vm_inst_settings(nova, neutron, server): return VmInstanceSettings(**kwargs) -def __create_port_settings(neutron, networks): +def __create_port_config(neutron, networks): """ Returns a list of port settings based on the networks parameter :param neutron: the neutron client @@ -288,7 +287,7 @@ def __create_port_settings(neutron, networks): kwargs['allowed_address_pairs'] = port.allowed_address_pairs kwargs['admin_state_up'] = port.admin_state_up kwargs['ip_addrs'] = ip_addrs - out.append(PortSettings(**kwargs)) + out.append(PortConfig(**kwargs)) return out @@ -298,7 +297,7 @@ def __create_floatingip_settings(neutron, port_settings): Returns a list of FloatingIPSettings objects as they pertain to an existing deployed server instance :param neutron: the neutron client - :param port_settings: list of SNAPS-OO PortSettings objects + :param port_settings: list of SNAPS-OO PortConfig objects :return: a list of FloatingIPSettings objects or an empty list if no floating IPs have been created """ diff --git a/snaps/openstack/utils/tests/heat_utils_tests.py b/snaps/openstack/utils/tests/heat_utils_tests.py index d90fed4..2f1e7cc 100644 --- a/snaps/openstack/utils/tests/heat_utils_tests.py +++ b/snaps/openstack/utils/tests/heat_utils_tests.py @@ -374,7 +374,7 @@ class HeatUtilsCreateComplexStackTests(OSComponentTestCase): self.assertEqual(1, len(networks)) self.assertEqual(self.network_name, networks[0].name) - network_settings = settings_utils.create_network_settings( + network_settings = settings_utils.create_network_config( neutron, networks[0]) self.assertIsNotNone(network_settings) self.assertEqual(self.network_name, network_settings.name) diff --git a/snaps/openstack/utils/tests/neutron_utils_tests.py b/snaps/openstack/utils/tests/neutron_utils_tests.py index 9022578..44bc59f 100644 --- a/snaps/openstack/utils/tests/neutron_utils_tests.py +++ b/snaps/openstack/utils/tests/neutron_utils_tests.py @@ -16,11 +16,9 @@ import uuid from neutronclient.common.exceptions import NotFound, BadRequest -from snaps.openstack import create_router -from snaps.openstack.create_network import NetworkSettings, SubnetSettings, \ - PortSettings -from snaps.openstack.create_security_group import SecurityGroupSettings, \ - SecurityGroupRuleSettings, Direction +from snaps.config.network import NetworkConfig, SubnetConfig, PortConfig +from snaps.openstack.create_security_group import ( + SecurityGroupSettings, SecurityGroupRuleSettings, Direction) from snaps.openstack.tests import openstack_tests from snaps.openstack.tests import validation_utils from snaps.openstack.tests.os_source_file_test import OSComponentTestCase @@ -123,7 +121,7 @@ class NeutronUtilsNetworkTests(OSComponentTestCase): with self.assertRaises(Exception): self.network = neutron_utils.create_network( self.neutron, self.os_creds, - network_settings=NetworkSettings(name='')) + network_settings=NetworkConfig(name='')) def test_create_network_null_name(self): """ @@ -133,7 +131,7 @@ class NeutronUtilsNetworkTests(OSComponentTestCase): with self.assertRaises(Exception): self.network = neutron_utils.create_network( self.neutron, self.os_creds, - network_settings=NetworkSettings()) + network_settings=NetworkConfig()) class NeutronUtilsSubnetTests(OSComponentTestCase): @@ -198,7 +196,7 @@ class NeutronUtilsSubnetTests(OSComponentTestCase): self.neutron, self.net_config.network_settings.name, True)) with self.assertRaises(Exception): - SubnetSettings(cidr=self.net_config.subnet_cidr) + SubnetConfig(cidr=self.net_config.subnet_cidr) def test_create_subnet_empty_name(self): """ @@ -274,12 +272,12 @@ class NeutronUtilsIPv6Tests(OSComponentTestCase): Tests the neutron_utils.create_network() with an IPv6 subnet where DHCP is True and IPv6 modes are slaac """ - sub_setting = SubnetSettings( + sub_setting = SubnetConfig( name=self.guid + '-subnet', cidr='1:1:0:0:0:0:0:0/64', ip_version=6, dns_nameservers=['2620:0:ccc:0:0:0:0:2'], gateway_ip='1:1:0:0:0:0:0:1', start='1:1::ff', end='1:1::ffff', enable_dhcp=True, ipv6_ra_mode='slaac', ipv6_address_mode='slaac') - self.network_settings = NetworkSettings( + self.network_settings = NetworkConfig( name=self.guid + '-net', subnet_settings=[sub_setting]) self.network = neutron_utils.create_network( @@ -310,13 +308,13 @@ class NeutronUtilsIPv6Tests(OSComponentTestCase): Tests the neutron_utils.create_network() with an IPv6 subnet where DHCP is True and IPv6 modes are stateful """ - sub_setting = SubnetSettings( + sub_setting = SubnetConfig( name=self.guid + '-subnet', cidr='1:1:0:0:0:0:0:0/64', ip_version=6, dns_nameservers=['2620:0:ccc:0:0:0:0:2'], gateway_ip='1:1:0:0:0:0:0:1', start='1:1::ff', end='1:1::ffff', enable_dhcp=True, ipv6_ra_mode='dhcpv6-stateful', ipv6_address_mode='dhcpv6-stateful') - self.network_settings = NetworkSettings( + self.network_settings = NetworkConfig( name=self.guid + '-net', subnet_settings=[sub_setting]) self.network = neutron_utils.create_network( @@ -348,13 +346,13 @@ class NeutronUtilsIPv6Tests(OSComponentTestCase): Tests the neutron_utils.create_network() when DHCP is enabled and the RA and address modes are both 'slaac' """ - sub_setting = SubnetSettings( + sub_setting = SubnetConfig( name=self.guid + '-subnet', cidr='1:1:0:0:0:0:0:0/64', ip_version=6, dns_nameservers=['2620:0:ccc:0:0:0:0:2'], gateway_ip='1:1:0:0:0:0:0:1', start='1:1::ff', end='1:1::ffff', enable_dhcp=True, ipv6_ra_mode='dhcpv6-stateless', ipv6_address_mode='dhcpv6-stateless') - self.network_settings = NetworkSettings( + self.network_settings = NetworkConfig( name=self.guid + '-net', subnet_settings=[sub_setting]) self.network = neutron_utils.create_network( @@ -386,12 +384,12 @@ class NeutronUtilsIPv6Tests(OSComponentTestCase): Tests the neutron_utils.create_network() for a BadRequest when DHCP is not enabled and the RA and address modes are both 'slaac' """ - sub_setting = SubnetSettings( + sub_setting = SubnetConfig( name=self.guid + '-subnet', cidr='1:1:0:0:0:0:0:0/64', ip_version=6, dns_nameservers=['2620:0:ccc:0:0:0:0:2'], gateway_ip='1:1:0:0:0:0:0:1', start='1:1::ff', end='1:1::ffff', enable_dhcp=False, ipv6_ra_mode='slaac', ipv6_address_mode='slaac') - self.network_settings = NetworkSettings( + self.network_settings = NetworkConfig( name=self.guid + '-net', subnet_settings=[sub_setting]) with self.assertRaises(BadRequest): @@ -404,10 +402,10 @@ class NeutronUtilsIPv6Tests(OSComponentTestCase): with an invalid start IP to ensure Neutron assigns it the smallest IP possible """ - sub_setting = SubnetSettings( + sub_setting = SubnetConfig( name=self.guid + '-subnet', cidr='1:1::/48', ip_version=6, start='foo') - self.network_settings = NetworkSettings( + self.network_settings = NetworkConfig( name=self.guid + '-net', subnet_settings=[sub_setting]) self.network = neutron_utils.create_network( @@ -423,10 +421,10 @@ class NeutronUtilsIPv6Tests(OSComponentTestCase): with an invalid end IP to ensure Neutron assigns it the largest IP possible """ - sub_setting = SubnetSettings( + sub_setting = SubnetConfig( name=self.guid + '-subnet', cidr='1:1::/48', ip_version=6, end='bar') - self.network_settings = NetworkSettings( + self.network_settings = NetworkConfig( name=self.guid + '-net', subnet_settings=[sub_setting]) self.network = neutron_utils.create_network( @@ -441,9 +439,9 @@ class NeutronUtilsIPv6Tests(OSComponentTestCase): Tests the neutron_utils.create_network() for a BadRequest when the subnet CIDR is invalid """ - sub_setting = SubnetSettings( + sub_setting = SubnetConfig( name=self.guid + '-subnet', cidr='1:1:1:/48', ip_version=6) - self.network_settings = NetworkSettings( + self.network_settings = NetworkConfig( name=self.guid + '-net', subnet_settings=[sub_setting]) with self.assertRaises(BadRequest): @@ -455,10 +453,10 @@ class NeutronUtilsIPv6Tests(OSComponentTestCase): Tests the neutron_utils.create_network() for a BadRequest when the subnet gateway IP is invalid """ - sub_setting = SubnetSettings( + sub_setting = SubnetConfig( name=self.guid + '-subnet', cidr='1:1::/48', ip_version=6, gateway_ip='1:2::1') - self.network_settings = NetworkSettings( + self.network_settings = NetworkConfig( name=self.guid + '-net', subnet_settings=[sub_setting]) with self.assertRaises(BadRequest): @@ -470,10 +468,10 @@ class NeutronUtilsIPv6Tests(OSComponentTestCase): Tests the neutron_utils.create_network() for a BadRequest when the DNS IP is invalid """ - sub_setting = SubnetSettings( + sub_setting = SubnetConfig( name=self.guid + '-subnet', cidr='1:1::/48', ip_version=6, dns_nameservers=['foo']) - self.network_settings = NetworkSettings( + self.network_settings = NetworkConfig( name=self.guid + '-net', subnet_settings=[sub_setting]) with self.assertRaises(BadRequest): @@ -657,7 +655,7 @@ class NeutronUtilsRouterTests(OSComponentTestCase): self.neutron, subnet_setting.name, subnet_setting.cidr, True)) self.port = neutron_utils.create_port( - self.neutron, self.os_creds, PortSettings( + self.neutron, self.os_creds, PortConfig( name=self.port_name, ip_addrs=[{ 'subnet_name': subnet_setting.name, @@ -681,7 +679,7 @@ class NeutronUtilsRouterTests(OSComponentTestCase): subnet_setting.cidr, True)) self.port = neutron_utils.create_port( - self.neutron, self.os_creds, PortSettings( + self.neutron, self.os_creds, PortConfig( name=self.port_name, network_name=self.net_config.network_settings.name, ip_addrs=[{ @@ -706,7 +704,7 @@ class NeutronUtilsRouterTests(OSComponentTestCase): self.port = neutron_utils.create_port( self.neutron, self.os_creds, - PortSettings( + PortConfig( network_name=self.net_config.network_settings.name, ip_addrs=[{ 'subnet_name': subnet_setting.name, @@ -723,7 +721,7 @@ class NeutronUtilsRouterTests(OSComponentTestCase): with self.assertRaises(Exception): self.port = neutron_utils.create_port( self.neutron, self.os_creds, - PortSettings( + PortConfig( name=self.port_name, network_name=self.net_config.network_settings.name, ip_addrs=[{ @@ -751,7 +749,7 @@ class NeutronUtilsRouterTests(OSComponentTestCase): with self.assertRaises(Exception): self.port = neutron_utils.create_port( self.neutron, self.os_creds, - PortSettings( + PortConfig( name=self.port_name, network_name=self.net_config.network_settings.name, ip_addrs=[{ @@ -777,7 +775,7 @@ class NeutronUtilsRouterTests(OSComponentTestCase): with self.assertRaises(Exception): self.port = neutron_utils.create_port( self.neutron, self.os_creds, - PortSettings( + PortConfig( name=self.port_name, network_name=self.net_config.network_settings.name, ip_addrs=[{ @@ -803,7 +801,7 @@ class NeutronUtilsRouterTests(OSComponentTestCase): with self.assertRaises(Exception): self.port = neutron_utils.create_port( self.neutron, self.os_creds, - PortSettings( + PortConfig( name=self.port_name, network_name=self.net_config.network_settings.name, ip_addrs=[{ diff --git a/snaps/openstack/utils/tests/nova_utils_tests.py b/snaps/openstack/utils/tests/nova_utils_tests.py index 6335ed9..6d4bc3c 100644 --- a/snaps/openstack/utils/tests/nova_utils_tests.py +++ b/snaps/openstack/utils/tests/nova_utils_tests.py @@ -19,14 +19,15 @@ import uuid import os from snaps import file_utils -from snaps.config.volume import VolumeConfig from snaps.config.flavor import FlavorConfig +from snaps.config.network import PortConfig +from snaps.config.volume import VolumeConfig from snaps.openstack import create_instance from snaps.openstack.create_flavor import OpenStackFlavor from snaps.openstack.create_image import OpenStackImage from snaps.openstack.create_instance import ( VmInstanceSettings, OpenStackVmInstance) -from snaps.openstack.create_network import OpenStackNetwork, PortSettings +from snaps.openstack.create_network import OpenStackNetwork from snaps.openstack.create_volume import OpenStackVolume from snaps.openstack.tests import openstack_tests from snaps.openstack.tests.os_source_file_test import OSComponentTestCase @@ -259,8 +260,8 @@ class NovaUtilsInstanceTests(OSComponentTestCase): name=guid + '-flavor-name', ram=256, disk=10, vcpus=1)) self.flavor_creator.create() - port_settings = PortSettings(name=guid + '-port', - network_name=network_settings.name) + port_settings = PortConfig( + name=guid + '-port', network_name=network_settings.name) self.port = neutron_utils.create_port( self.neutron, self.os_creds, port_settings) @@ -382,7 +383,7 @@ class NovaUtilsInstanceVolumeTests(OSComponentTestCase): self.os_creds, volume_settings) self.volume_creator.create(block=True) - port_settings = PortSettings( + port_settings = PortConfig( name=guid + '-port', network_name=network_settings.name) instance_settings = VmInstanceSettings( name=guid + '-vm_inst', diff --git a/snaps/openstack/utils/tests/settings_utils_tests.py b/snaps/openstack/utils/tests/settings_utils_tests.py index 1157f2c..b34e68b 100644 --- a/snaps/openstack/utils/tests/settings_utils_tests.py +++ b/snaps/openstack/utils/tests/settings_utils_tests.py @@ -18,6 +18,7 @@ import unittest import os import uuid +from snaps.config.network import SubnetConfig, NetworkConfig, PortConfig from snaps.config.flavor import FlavorConfig from snaps.config.keypair import KeypairConfig from snaps.config.qos import Consumer @@ -27,8 +28,8 @@ from snaps.domain.volume import ( from snaps.openstack import ( create_image, create_network, create_router, create_flavor, create_keypairs, create_instance) -from snaps.openstack.create_network import ( - NetworkSettings, OpenStackNetwork, SubnetSettings) +from snaps.openstack.create_qos import Consumer +from snaps.openstack.create_network import OpenStackNetwork from snaps.openstack.create_security_group import ( SecurityGroupRuleSettings, Direction, Protocol, OpenStackSecurityGroup, SecurityGroupSettings) @@ -44,7 +45,7 @@ logger = logging.getLogger('nova_utils_tests') class SettingsUtilsNetworkingTests(OSComponentTestCase): """ - Tests the ability to reverse engineer NetworkSettings objects from existing + Tests the ability to reverse engineer NetworkConfig objects from existing networks deployed to OpenStack """ @@ -70,16 +71,16 @@ class SettingsUtilsNetworkingTests(OSComponentTestCase): def test_derive_net_settings_no_subnet(self): """ - Validates the utility function settings_utils#create_network_settings - returns an acceptable NetworkSettings object and ensures that the + Validates the utility function settings_utils#create_network_config + returns an acceptable NetworkConfig object and ensures that the new settings object will not cause the new OpenStackNetwork instance to create another network """ - net_settings = NetworkSettings(name=self.network_name) + net_settings = NetworkConfig(name=self.network_name) self.net_creator = OpenStackNetwork(self.os_creds, net_settings) network = self.net_creator.create() - derived_settings = settings_utils.create_network_settings( + derived_settings = settings_utils.create_network_config( self.neutron, network) self.assertIsNotNone(derived_settings) @@ -97,18 +98,18 @@ class SettingsUtilsNetworkingTests(OSComponentTestCase): def test_derive_net_settings_two_subnets(self): """ - Validates the utility function settings_utils#create_network_settings - returns an acceptable NetworkSettings object + Validates the utility function settings_utils#create_network_config + returns an acceptable NetworkConfig object """ subnet_settings = list() - subnet_settings.append(SubnetSettings(name='sub1', cidr='10.0.0.0/24')) - subnet_settings.append(SubnetSettings(name='sub2', cidr='10.0.1.0/24')) - net_settings = NetworkSettings(name=self.network_name, - subnet_settings=subnet_settings) + subnet_settings.append(SubnetConfig(name='sub1', cidr='10.0.0.0/24')) + subnet_settings.append(SubnetConfig(name='sub2', cidr='10.0.1.0/24')) + net_settings = NetworkConfig( + name=self.network_name, subnet_settings=subnet_settings) self.net_creator = OpenStackNetwork(self.os_creds, net_settings) network = self.net_creator.create() - derived_settings = settings_utils.create_network_settings( + derived_settings = settings_utils.create_network_config( self.neutron, network) self.assertIsNotNone(derived_settings) @@ -233,7 +234,7 @@ class SettingsUtilsVmInstTests(OSComponentTestCase): # Create instance ports_settings = list() ports_settings.append( - create_network.PortSettings( + PortConfig( name=self.port_1_name, network_name=self.pub_net_config.network_settings.name)) diff --git a/snaps/provisioning/tests/ansible_utils_tests.py b/snaps/provisioning/tests/ansible_utils_tests.py index f50b7de..b78249e 100644 --- a/snaps/provisioning/tests/ansible_utils_tests.py +++ b/snaps/provisioning/tests/ansible_utils_tests.py @@ -19,9 +19,10 @@ import os import pkg_resources from scp import SCPClient +from snaps.config.flavor import FlavorConfig from snaps.config.keypair import KeypairConfig +from snaps.config.network import PortConfig -from snaps.config.flavor import FlavorConfig from snaps.openstack import create_flavor from snaps.openstack import create_image from snaps.openstack import create_instance @@ -136,7 +137,7 @@ class AnsibleProvisioningTests(OSIntegrationTestCase): # Create instance ports_settings = list() ports_settings.append( - create_network.PortSettings( + PortConfig( name=self.port_1_name, network_name=self.pub_net_config.network_settings.name)) diff --git a/snaps/test_suite_builder.py b/snaps/test_suite_builder.py index 264651a..2d2427f 100644 --- a/snaps/test_suite_builder.py +++ b/snaps/test_suite_builder.py @@ -16,6 +16,8 @@ import logging import unittest +from snaps.config.tests.network_tests import ( + NetworkConfigUnitTests, SubnetConfigUnitTests, PortConfigUnitTests) from snaps.config.tests.volume_tests import VolumeConfigUnitTests from snaps.config.tests.volume_type_tests import VolumeTypeConfigUnitTests from snaps.config.tests.qos_tests import QoSConfigUnitTests @@ -180,14 +182,20 @@ def add_unit_tests(suite): NetworkQuotasDomainObjectTests)) suite.addTest(unittest.TestLoader().loadTestsFromTestCase( RoleDomainObjectTests)) + suite.addTest(unittest.TestLoader().loadTestsFromTestCase( + NetworkConfigUnitTests)) suite.addTest(unittest.TestLoader().loadTestsFromTestCase( NetworkSettingsUnitTests)) suite.addTest(unittest.TestLoader().loadTestsFromTestCase( NetworkObjectTests)) + suite.addTest(unittest.TestLoader().loadTestsFromTestCase( + SubnetConfigUnitTests)) suite.addTest(unittest.TestLoader().loadTestsFromTestCase( SubnetSettingsUnitTests)) suite.addTest(unittest.TestLoader().loadTestsFromTestCase( SubnetObjectTests)) + suite.addTest(unittest.TestLoader().loadTestsFromTestCase( + PortConfigUnitTests)) suite.addTest(unittest.TestLoader().loadTestsFromTestCase( PortSettingsUnitTests)) suite.addTest(unittest.TestLoader().loadTestsFromTestCase( -- cgit 1.2.3-korg