diff options
69 files changed, 4085 insertions, 1861 deletions
diff --git a/docs/how-to-use/APITests.rst b/docs/how-to-use/APITests.rst index f71426c..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 | +---------------------------------------+---------------+-----------------------------------------------------------+ @@ -566,6 +566,6 @@ settings_utils_tests.py - SettingsUtilsVmInstTests | test_derive_vm_inst_settings | Neutron 2 | Tests to ensure that derived VmInstanceSettings from an | | | | OpenStack VM instance is correct | +---------------------------------------+---------------+-----------------------------------------------------------+ -| test_derive_image_settings | Neutron 2 | Tests to ensure that derived ImageSettings from an | +| test_derive_image_settings | Neutron 2 | Tests to ensure that derived ImageConfig from an | | | | OpenStack VM instance is correct | +---------------------------------------+---------------+-----------------------------------------------------------+ diff --git a/docs/how-to-use/IntegrationTests.rst b/docs/how-to-use/IntegrationTests.rst index 1368eaf..f3d17f7 100644 --- a/docs/how-to-use/IntegrationTests.rst +++ b/docs/how-to-use/IntegrationTests.rst @@ -80,7 +80,7 @@ create_image_tests.py - CreateImageNegativeTests | Test Name | Glance API | Description | +=======================================+===============+===========================================================+ | test_bad_image_name | 1 & 2 | Ensures OpenStackImage.create() results in an Exception | -| | | being raised when the ImageSettings.name attribute has | +| | | being raised when the ImageConfig.name attribute has | | | | not been set | +---------------------------------------+---------------+-----------------------------------------------------------+ | test_bad_image_url | 1 & 2 | Ensures OpenStackImage.create() results in an Exception | diff --git a/docs/how-to-use/LibraryUsage.rst b/docs/how-to-use/LibraryUsage.rst index 9518c2b..aa7bf91 100644 --- a/docs/how-to-use/LibraryUsage.rst +++ b/docs/how-to-use/LibraryUsage.rst @@ -79,7 +79,7 @@ Create User ----------- - User - snaps.openstack.create\_user.OpenStackUser - - snaps.openstack.create\_user.UserSettings + - snaps.openstack.user.UserConfig - name - the username (required) - password - the user's password (required) @@ -94,8 +94,9 @@ Create User .. code:: python - from snaps.openstack.create_user import UserSettings, OpenStackUser - user_settings = UserSettings(name='username', password='password') + from snaps.config.user import UserConfig + from snaps.openstack.create_user import OpenStackUser + user_settings = UserConfig(name='username', password='password') user_creator = OpenStackUser(os_creds, user_settings) user_creator.create() @@ -112,7 +113,7 @@ Create Project -------------- - Project - snaps.openstack.create\_project.OpenStackProject - - snaps.openstack.create\_project.ProjectSettings + - snaps.openstack.project.ProjectConfig - name - the project name (required) - domain - the project's domain (default='default') @@ -123,8 +124,9 @@ Create Project .. code:: python - from snaps.openstack.create_project import ProjectSettings, OpenStackProject - project_settings = ProjectSettings(name='username', password='password') + from snaps.openstack.project import ProjectConfig + from snaps.openstack.create_project import OpenStackProject + project_settings = ProjectConfig(name='username', password='password') project_creator = OpenStackProject(os_creds, project_settings) project_creator.create() @@ -138,7 +140,7 @@ Create Flavor ------------- - Flavor - snaps.openstack.create\_flavor.OpenStackFlavor - - snaps.openstack.create\_flavor.FlavorSettings + - snaps.config.flavor.FlavorConfig - name - the flavor name (required) - flavor\_id - the flavor's string ID (default='auto') @@ -155,8 +157,9 @@ Create Flavor .. code:: python - from snaps.openstack.create_flavor import FlavorSettings, OpenStackFlavor - flavor_settings = FlavorSettings(name='flavor-name', ram=4, disk=10, vcpus=2) + from snaps.config.flavor import FlavorConfig + from snaps.openstack.create_flavor import OpenStackFlavor + flavor_settings = FlavorConfig(name='flavor-name', ram=4, disk=10, vcpus=2) flavor_creator = OpenStackFlavor(os_creds, flavor_settings) flavor_creator.create() @@ -170,7 +173,7 @@ Create Image ------------ - Image - snaps.openstack.create\_image.OpenStackImage - - snaps.openstack.create\_image.ImageSettings + - snaps.config.image.ImageConfig - name - the image name (required) - image\_user - the default image user generally used by @@ -193,9 +196,10 @@ Create Image .. code:: python - from snaps.openstack.create_image import ImageSettings, OpenStackImage - image_settings = ImageSettings(name='image-name', image_user='ubuntu', img_format='qcow2', - url='http://uec-images.ubuntu.com/releases/trusty/14.04/ubuntu-14.04-server-cloudimg-amd64-disk1.img') + from snaps.openstack.create_image import OpenStackImage + from snaps.config.image import ImageConfig + image_settings = ImageConfig(name='image-name', image_user='ubuntu', img_format='qcow2', + url='http://uec-images.ubuntu.com/releases/trusty/14.04/ubuntu-14.04-server-cloudimg-amd64-disk1.img') image_creator = OpenStackImage(os_creds, image_settings) image_creator.create() @@ -209,7 +213,7 @@ Create Keypair -------------- - Keypair - snaps.openstack.create\_keypair.OpenStackKeypair - - snaps.openstack.create\_keypair.KeypairSettings + - snaps.openstack.keypair.KeypairConfig - name - the keypair name (required) - public\_filepath - the file location to where the public key is @@ -225,8 +229,9 @@ Create Keypair .. code:: python - from snaps.openstack.create_keypairs import KeypairSettings, OpenStackKeypair - keypair_settings = KeypairSettings(name='kepair-name', private_filepath='/tmp/priv-kp') + from snaps.openstack.keypair.KeypairConfig + from snaps.openstack.create_keypairs import OpenStackKeypair + keypair_settings = KeypairConfig(name='kepair-name', private_filepath='/tmp/priv-kp') keypair_creator = OpenStackKeypair(os_creds, keypair_settings) keypair_creator.create() @@ -241,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 @@ -258,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) @@ -282,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() @@ -335,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) @@ -358,7 +366,7 @@ Create Router - Router - snaps.openstack.create\_router.OpenStackRouter - - snaps.openstack.create\_router.RouterSettings + - snaps.openstack.router.RouterConfig - name - the router name (required) - project\_name - the name of the project (optional - can only be @@ -371,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) @@ -402,9 +410,10 @@ Create Router .. code:: python - from snaps.openstack.create_router import RouterSettings, OpenStackRouter + from snaps.config.router import RouterConfig + from snaps.openstack.create_router import OpenStackRouter - router_settings = RouterSettings(name='router-name', external_gateway='external') + router_settings = RouterConfig(name='router-name', external_gateway='external') router_creator = OpenStackRouter(os_creds, router_settings) router_creator.create() @@ -419,7 +428,7 @@ Create QoS Spec - Volume Type - snaps.openstack.create\_qos.OpenStackQoS - - snaps.openstack.create\_qos.QoSSettings + - snaps.openstack.qos.QoSConfig - name - the volume type's name (required) - consumer - the qos's consumer type of the enum type Consumer (required) @@ -427,9 +436,10 @@ Create QoS Spec .. code:: python - from snaps.openstack.create_qos import QoSSettings, OpenStackQoS + from snaps.openstack.qos import QoSConfig + from snaps.openstack.create_qos import OpenStackQoS - qos_settings = QoSSettings(name='stack-name', consumer=Consumer.front-end) + qos_settings = QoSConfig(name='stack-name', consumer=Consumer.front-end) qos_creator = OpenStackQoS(os_creds, vol_type_settings) qos_creator.create() @@ -444,19 +454,20 @@ Create Volume Type - Volume Type - snaps.openstack.create\_volume\_type.OpenStackVolumeType - - snaps.openstack.create\_volume\_type.VolumeTypeSettings + - snaps.config.volume\_type.VolumeTypeConfig - name - the volume type's name (required) - description - the volume type's description (optional) - - encryption - instance or config for VolumeTypeEncryptionSettings (optional) + - encryption - instance or config for VolumeTypeEncryptionConfig (optional) - qos\_spec\_name - name of the QoS Spec to associate (optional) - - public - instance or config for VolumeTypeEncryptionSettings (optional) + - public - instance or config for VolumeTypeEncryptionConfig (optional) .. code:: python - from snaps.openstack.create_volume_type import VolumeTypeSettings, OpenStackVolumeType + from snaps.config.volume_type import VolumeTypeConfig + from snaps.openstack.create_volume_type import OpenStackVolumeType - vol_type_settings = VolumeTypeSettings(name='stack-name') + vol_type_settings = VolumeTypeConfig(name='stack-name') vol_type_creator = OpenStackHeatStack(os_creds, vol_type_settings) vol_type_creator.create() @@ -471,7 +482,7 @@ Create Volume - Volume - snaps.openstack.create\_volume.OpenStackVolume - - snaps.openstack.create\_volume.VolumeSettings + - snaps.config.volume.VolumeConfig - name - the volume type's name (required) - description - the volume type's description (optional) @@ -485,9 +496,10 @@ Create Volume .. code:: python - from snaps.openstack.create\_volume import VolumeSettings, OpenStackVolume + from snaps.config.volume import VolumeConfig + from snaps.openstack.create\_volume import OpenStackVolume - vol_settings = VolumeSettings(name='stack-name') + vol_settings = VolumeConfig(name='stack-name') vol_creator = OpenStackVolume(os_creds, vol_settings) vol_creator.create() @@ -502,7 +514,7 @@ Create Heat Stack - Heat Stack - snaps.openstack.create\_stack.OpenStackHeatStack - - snaps.openstack.create\_stack.StackSettings + - snaps.config.stack.StackConfig - name - the stack's name (required) - template - the heat template in dict() format (required when @@ -514,9 +526,10 @@ Create Heat Stack .. code:: python - from snaps.openstack.create_stack import StackSettings, OpenStackHeatStack + from snaps.config.stack import StackConfig + from snaps.openstack.create_stack import OpenStackHeatStack - stack_settings = StackSettings(name='stack-name', template_path='/tmp/template.yaml') + stack_settings = StackConfig(name='stack-name', template_path='/tmp/template.yaml') stack_creator = OpenStackHeatStack(os_creds, stack_settings) stack_creator.create() @@ -536,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 @@ -571,17 +584,17 @@ Create VM Instance - userdata - the cloud-init script to execute after VM has been started - - image\_settings - see snaps.openstack.create\_image.ImageSettings + - image\_settings - see snaps.config.image.ImageConfig above (required) - keypair\_settings - see - snaps.openstack.create\_keypairs.KeypairSettings above (optional) + snaps.openstack.keypair.KeypairConfig above (optional) .. 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 4a360d4..c053372 100644 --- a/docs/how-to-use/UnitTests.rst +++ b/docs/how-to-use/UnitTests.rst @@ -60,11 +60,17 @@ SecurityGroupDomainObjectTests Ensures that all required members are included when constructing a SecurityGroup domain object +ImageConfigUnitTests +-------------------- + +Ensures that all required members are included when constructing a +ImageConfig object + ImageSettingsUnitTests ---------------------- Ensures that all required members are included when constructing a -ImageSettings object +ImageSettings object (deprecated see ImageConfigUnitTests) ImageDomainObjectTests ---------------------- @@ -72,11 +78,17 @@ ImageDomainObjectTests Ensures that all required members are included when constructing a Image domain object +FlavorConfigUnitTests +--------------------- + +Ensures that all required members are included when constructing a +FlavorConfig object + FlavorSettingsUnitTests ----------------------- Ensures that all required members are included when constructing a -FlavorSettings object +deprecated FlavorSettings object FlavorDomainObjectTests ----------------------- @@ -84,11 +96,17 @@ FlavorDomainObjectTests Ensures that all required members are included when constructing a Flavor domain object +KeypairConfigUnitTests +---------------------- + +Ensures that all required members are included when constructing a +KeypairConfig object + KeypairSettingsUnitTests ------------------------ Ensures that all required members are included when constructing a -KeypairSettings object +deprecated KeypairSettings object KeypairDomainObjectTests ------------------------ @@ -96,11 +114,17 @@ KeypairDomainObjectTests Ensures that all required members are included when constructing a Keypair domain object +UserConfigUnitTests +------------------- + +Ensures that all required members are included when constructing a +UserConfig object + UserSettingsUnitTests --------------------- Ensures that all required members are included when constructing a -UserSettings object +deprecated UserSettings object UserDomainObjectTests --------------------- @@ -108,11 +132,17 @@ UserDomainObjectTests Ensures that all required members are included when constructing a User domain object +ProjectConfigUnitTests +---------------------- + +Ensures that all required members are included when constructing a +ProjectConfig object + ProjectSettingsUnitTests ------------------------ Ensures that all required members are included when constructing a -ProjectSettings object +deprecated ProjectSettings object ProjectDomainObjectTests ------------------------ @@ -144,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 ------------------ @@ -156,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 ----------------- @@ -168,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 --------------------- @@ -180,11 +228,17 @@ PortDomainObjectTests Ensures that all required members are included when constructing a Port domain object +RouterConfigUnitTests +--------------------- + +Ensures that all required members are included when constructing a +RouterConfig object + RouterSettingsUnitTests ----------------------- Ensures that all required members are included when constructing a -RouterSettings object +deprecated RouterSettings object RouterDomainObjectTests ----------------------- @@ -198,11 +252,17 @@ InterfaceRouterDomainObjectTests Ensures that all required members are included when constructing a InterfaceRouter domain object +StackConfigUnitTests +-------------------- + +Ensures that all required members are included when constructing a +StackConfig object + StackSettingsUnitTests ---------------------- Ensures that all required members are included when constructing a -StackSettings object +deprecated StackSettings object StackDomainObjectTests ---------------------- @@ -222,11 +282,17 @@ OutputDomainObjectTests Ensures that all required members are included when constructing a Output domain object (for Heat) +VolumeConfigUnitTests +--------------------- + +Ensures that all required members are included when constructing a +VolumeConfig object + VolumeSettingsUnitTests ----------------------- Ensures that all required members are included when constructing a -VolumeSettings object +deprecated VolumeSettings object VolumeDomainObjectTests ----------------------- @@ -234,11 +300,17 @@ VolumeDomainObjectTests Ensures that all required members are included when constructing a Volume domain object (for Cinder) +VolumeTypeConfigUnitTests +------------------------- + +Ensures that all required members are included when constructing a +VolumeTypeConfig object + VolumeTypeSettingsUnitTests --------------------------- Ensures that all required members are included when constructing a -VolumeTypeSettings object +deprecated VolumeTypeSettings object VolumeTypeDomainObjectTests --------------------------- @@ -252,11 +324,17 @@ VolumeTypeEncryptionObjectTests Ensures that all required members are included when constructing a VolumeTypeEncryption domain object (for Cinder) +QoSConfigUnitTests +------------------ + +Ensures that all required members are included when constructing a +QoSConfig object + QoSSettingsUnitTests -------------------- Ensures that all required members are included when constructing a -QoSSettings object +deprecated QoSSettings object QoSSpecDomainObjectTests ------------------------ @@ -297,13 +375,13 @@ VmInst domain object SettingsUtilsUnitTests ---------------------- -Ensures that the settings_utils.py#create_volume_settings() function properly +Ensures that the settings_utils.py#create_volume_config() function properly maps a snaps.domain.Volume object correctly to a -snaps.openstack.create_volume.VolumeSettings object as well as a +snaps.config.volume.VolumeConfig object as well as a snaps.domain.VolumeType object to a -snaps.openstack.create_volume.VolumeSettings object +snaps.config.volume.VolumeConfig object -Ensures that the settings_utils.py#create_flavor_settings() function properly +Ensures that the settings_utils.py#create_flavor_config() function properly maps a snaps.domain.Flavor object correctly to a -snaps.openstack.create_flavor.FlavorSettings object
\ No newline at end of file +snaps.config.flavor.FlavorConfig object
\ No newline at end of file diff --git a/examples/demo.py b/examples/demo.py index 108bdc0..c888d7b 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -5,18 +5,22 @@ 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 -from snaps.openstack.create_image import ImageSettings, OpenStackImage +from snaps.openstack.create_image import OpenStackImage +from snaps.config.image import ImageConfig -image_settings = ImageSettings(name='cirros-test', image_user='cirros', img_format='qcow2', - url='http://download.cirros-cloud.net/0.3.4/cirros-0.3.4-x86_64-disk.img') +image_settings = ImageConfig(name='cirros-test', image_user='cirros', img_format='qcow2', + url='http://download.cirros-cloud.net/0.3.4/cirros-0.3.4-x86_64-disk.img') image = OpenStackImage(os_creds, image_settings) image.create() @@ -24,27 +28,34 @@ 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() # Flavors -from snaps.openstack.create_flavor import FlavorSettings, OpenStackFlavor +from snaps.config.flavor import FlavorConfig +from snaps.openstack.create_flavor import OpenStackFlavor -flavor_settings = FlavorSettings(name='test-flavor', ram=256, disk=10, vcpus=2) +flavor_settings = FlavorConfig(name='test-flavor', ram=256, disk=10, vcpus=2) 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 88ff420..9320512 100644 --- a/examples/launch.py +++ b/examples/launch.py @@ -26,21 +26,29 @@ import os import yaml from snaps import file_utils -from snaps.openstack.create_flavor import FlavorSettings, OpenStackFlavor -from snaps.openstack.create_image import ImageSettings, OpenStackImage +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 +from snaps.config.user import UserConfig +from snaps.config.volume import VolumeConfig +from snaps.config.volume_type import VolumeTypeConfig +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 KeypairSettings, OpenStackKeypair -from snaps.openstack.create_network import ( - PortSettings, NetworkSettings, OpenStackNetwork) -from snaps.openstack.create_project import OpenStackProject, ProjectSettings -from snaps.openstack.create_qos import QoSSettings, OpenStackQoS -from snaps.openstack.create_router import RouterSettings, OpenStackRouter +from snaps.openstack.create_keypairs import OpenStackKeypair +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 from snaps.openstack.create_security_group import ( OpenStackSecurityGroup, SecurityGroupSettings) -from snaps.openstack.create_user import OpenStackUser, UserSettings -from snaps.openstack.create_volume import OpenStackVolume, VolumeSettings -from snaps.openstack.create_volume_type import ( - OpenStackVolumeType, VolumeTypeSettings) +from snaps.openstack.create_user import OpenStackUser +from snaps.openstack.create_volume import OpenStackVolume +from snaps.openstack.create_volume_type import OpenStackVolumeType from snaps.openstack.os_credentials import OSCreds, ProxySettings from snaps.openstack.utils import deploy_utils from snaps.provisioning import ansible_utils @@ -144,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 @@ -612,13 +620,13 @@ def main(arguments): try: # Create projects projects_dict = __create_instances( - os_creds_dict, OpenStackProject, ProjectSettings, + os_creds_dict, OpenStackProject, ProjectConfig, os_config.get('projects'), 'project', clean) creators.append(projects_dict) # Create users users_dict = __create_instances( - os_creds_dict, OpenStackUser, UserSettings, + os_creds_dict, OpenStackUser, UserConfig, os_config.get('users'), 'user', clean) creators.append(users_dict) @@ -634,48 +642,48 @@ def main(arguments): # Create flavors flavors_dict = __create_instances( - os_creds_dict, OpenStackFlavor, FlavorSettings, + os_creds_dict, OpenStackFlavor, FlavorConfig, os_config.get('flavors'), 'flavor', clean, users_dict) creators.append(flavors_dict) # Create QoS specs qos_dict = __create_instances( - os_creds_dict, OpenStackQoS, QoSSettings, + os_creds_dict, OpenStackQoS, QoSConfig, os_config.get('qos_specs'), 'qos_spec', clean, users_dict) creators.append(qos_dict) # Create volume types vol_type_dict = __create_instances( - os_creds_dict, OpenStackVolumeType, VolumeTypeSettings, + os_creds_dict, OpenStackVolumeType, VolumeTypeConfig, os_config.get('volume_types'), 'volume_type', clean, users_dict) creators.append(vol_type_dict) # Create volume types vol_dict = __create_instances( - os_creds_dict, OpenStackVolume, VolumeSettings, + os_creds_dict, OpenStackVolume, VolumeConfig, os_config.get('volumes'), 'volume', clean, users_dict) creators.append(vol_dict) # Create images images_dict = __create_instances( - os_creds_dict, OpenStackImage, ImageSettings, + os_creds_dict, OpenStackImage, ImageConfig, os_config.get('images'), 'image', clean, users_dict) creators.append(images_dict) # 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 creators.append(__create_instances( - os_creds_dict, OpenStackRouter, RouterSettings, + os_creds_dict, OpenStackRouter, RouterConfig, os_config.get('routers'), 'router', clean, users_dict)) # Create keypairs keypairs_dict = __create_instances( - os_creds_dict, OpenStackKeypair, KeypairSettings, + os_creds_dict, OpenStackKeypair, KeypairConfig, os_config.get('keypairs'), 'keypair', clean, users_dict) creators.append(keypairs_dict) diff --git a/snaps/config/__init__.py b/snaps/config/__init__.py new file mode 100644 index 0000000..271c742 --- /dev/null +++ b/snaps/config/__init__.py @@ -0,0 +1,15 @@ +# 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. +__author__ = 'spisarski' diff --git a/snaps/config/flavor.py b/snaps/config/flavor.py new file mode 100644 index 0000000..b29fb7c --- /dev/null +++ b/snaps/config/flavor.py @@ -0,0 +1,107 @@ +# Copyright (c) 2016 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. + + +class FlavorConfig(object): + """ + Configuration settings for OpenStack flavor creation + """ + + def __init__(self, **kwargs): + """ + Constructor + :param name: the flavor's name (required) + :param flavor_id: the string ID (default 'auto') + :param ram: the required RAM in MB (required) + :param disk: the size of the root disk in GB (required) + :param vcpus: the number of virtual CPUs (required) + :param ephemeral: the size of the ephemeral disk in GB (default 0) + :param swap: the size of the dedicated swap disk in GB (default 0) + :param rxtx_factor: the receive/transmit factor to be set on ports if + backend supports QoS extension (default 1.0) + :param is_public: denotes whether or not the flavor is public + (default True) + :param metadata: freeform dict() for special metadata + """ + self.name = kwargs.get('name') + + if kwargs.get('flavor_id'): + self.flavor_id = kwargs['flavor_id'] + else: + self.flavor_id = 'auto' + + self.ram = kwargs.get('ram') + self.disk = kwargs.get('disk') + self.vcpus = kwargs.get('vcpus') + + if kwargs.get('ephemeral'): + self.ephemeral = kwargs['ephemeral'] + else: + self.ephemeral = 0 + + if kwargs.get('swap'): + self.swap = kwargs['swap'] + else: + self.swap = 0 + + if kwargs.get('rxtx_factor'): + self.rxtx_factor = kwargs['rxtx_factor'] + else: + self.rxtx_factor = 1.0 + + if kwargs.get('is_public') is not None: + self.is_public = kwargs['is_public'] + else: + self.is_public = True + + if kwargs.get('metadata'): + self.metadata = kwargs['metadata'] + else: + self.metadata = None + + if not self.name or not self.ram or not self.disk or not self.vcpus: + raise FlavorConfigError( + 'The attributes name, ram, disk, and vcpus are required for' + 'FlavorConfig') + + if not isinstance(self.ram, int): + raise FlavorConfigError('The ram attribute must be a integer') + + if not isinstance(self.disk, int): + raise FlavorConfigError('The ram attribute must be a integer') + + if not isinstance(self.vcpus, int): + raise FlavorConfigError('The vcpus attribute must be a integer') + + if self.ephemeral and not isinstance(self.ephemeral, int): + raise FlavorConfigError( + 'The ephemeral attribute must be an integer') + + if self.swap and not isinstance(self.swap, int): + raise FlavorConfigError('The swap attribute must be an integer') + + if self.rxtx_factor and not isinstance(self.rxtx_factor, (int, float)): + raise FlavorConfigError( + 'The is_public attribute must be an integer or float') + + if self.is_public and not isinstance(self.is_public, bool): + raise FlavorConfigError( + 'The is_public attribute must be a boolean') + + +class FlavorConfigError(Exception): + """ + Exception to be thrown when a flavor configuration is incorrect + """ diff --git a/snaps/config/image.py b/snaps/config/image.py new file mode 100644 index 0000000..fe1c913 --- /dev/null +++ b/snaps/config/image.py @@ -0,0 +1,110 @@ +# 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. + + +class ImageConfig(object): + def __init__(self, **kwargs): + """ + Constructor + :param name: the image's name (required) + :param image_user: the image's default sudo user (required) + :param format or img_format: the image format type (required) + :param url or download_url: the image download location (requires url + or img_file) + :param image_file: the image file location (requires url or img_file) + :param extra_properties: dict() object containing extra parameters to + pass when loading the image; + can be ids of kernel and initramfs images for + a 3-part image + :param nic_config_pb_loc: the file location to the Ansible Playbook + that can configure multiple NICs + :param kernel_image_settings: the settings for a kernel image + :param ramdisk_image_settings: the settings for a ramdisk image + :param exists: When True, an image with the given name must exist + :param public: When True, an image will be created with public + visibility + """ + + self.name = kwargs.get('name') + self.image_user = kwargs.get('image_user') + self.format = kwargs.get('format') + if not self.format: + self.format = kwargs.get('img_format') + + self.url = kwargs.get('url') + if not self.url: + self.url = kwargs.get('download_url') + if self.url == 'None': + self.url = None + + self.image_file = kwargs.get('image_file') + if self.image_file == 'None': + self.image_file = None + + self.extra_properties = kwargs.get('extra_properties') + self.nic_config_pb_loc = kwargs.get('nic_config_pb_loc') + + kernel_image_settings = kwargs.get('kernel_image_settings') + if kernel_image_settings: + if isinstance(kernel_image_settings, dict): + self.kernel_image_settings = ImageConfig( + **kernel_image_settings) + else: + self.kernel_image_settings = kernel_image_settings + else: + self.kernel_image_settings = None + + ramdisk_image_settings = kwargs.get('ramdisk_image_settings') + if ramdisk_image_settings: + if isinstance(ramdisk_image_settings, dict): + self.ramdisk_image_settings = ImageConfig( + **ramdisk_image_settings) + else: + self.ramdisk_image_settings = ramdisk_image_settings + else: + self.ramdisk_image_settings = None + + if 'exists' in kwargs and kwargs['exists'] is True: + self.exists = True + else: + self.exists = False + + if 'public' in kwargs and kwargs['public'] is True: + self.public = True + else: + self.public = False + + if not self.name: + raise ImageConfigError("The attribute name is required") + + if not (self.url or self.image_file) and not self.exists: + raise ImageConfigError( + 'URL or image file must be set or image must already exist') + + if not self.image_user: + raise ImageConfigError('Image user is required') + + if not self.format and not self.exists: + raise ImageConfigError( + 'Format is required when the image should not already exist') + + +class ImageConfigError(Exception): + """ + Exception to be thrown when an image settings are incorrect + """ + + def __init__(self, message): + Exception.__init__(self, message) diff --git a/snaps/config/keypair.py b/snaps/config/keypair.py new file mode 100644 index 0000000..2304c6e --- /dev/null +++ b/snaps/config/keypair.py @@ -0,0 +1,61 @@ +# 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. +from neutronclient.common.utils import str2bool + + +class KeypairConfig(object): + """ + Class representing a keypair configuration + """ + + def __init__(self, **kwargs): + """ + Constructor - all parameters are optional + :param name: The keypair name. + :param public_filepath: The path to/from the filesystem where the + public key file is or will be stored + :param private_filepath: The path where the generated private key file + will be stored + :param key_size: The number of bytes for the key size when it needs to + be generated (Must be >=512 default 1024) + :param delete_on_clean: when True, the key files will be deleted when + OpenStackKeypair#clean() is called + :return: + """ + + self.name = kwargs.get('name') + self.public_filepath = kwargs.get('public_filepath') + self.private_filepath = kwargs.get('private_filepath') + self.key_size = int(kwargs.get('key_size', 1024)) + + if kwargs.get('delete_on_clean') is not None: + if isinstance(kwargs.get('delete_on_clean'), bool): + self.delete_on_clean = kwargs.get('delete_on_clean') + else: + self.delete_on_clean = str2bool(kwargs.get('delete_on_clean')) + else: + self.delete_on_clean = None + + if not self.name: + raise KeypairConfigError('Name is a required attribute') + + if self.key_size < 512: + raise KeypairConfigError('key_size must be >=512') + + +class KeypairConfigError(Exception): + """ + Exception to be thrown when keypair settings are incorrect + """ 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/project.py b/snaps/config/project.py new file mode 100644 index 0000000..6790609 --- /dev/null +++ b/snaps/config/project.py @@ -0,0 +1,57 @@ +# 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. + + +class ProjectConfig(object): + """ + Class to hold the configuration settings required for creating OpenStack + project objects + """ + + def __init__(self, **kwargs): + + """ + Constructor + :param name: the project's name (required) + :param domain or domain_name: the project's domain name + (default = 'Default'). + Field is used for v3 clients + :param description: the description (optional) + :param users: list of users to associate project to (optional) + :param enabled: denotes whether or not the project is enabled + (default True) + """ + + self.name = kwargs.get('name') + self.domain_name = kwargs.get( + 'domain', kwargs.get('domain', 'Default')) + + self.description = kwargs.get('description') + if kwargs.get('enabled') is not None: + self.enabled = kwargs['enabled'] + else: + self.enabled = True + + self.users = kwargs.get('users', list()) + + if not self.name: + raise ProjectConfigError( + "The attribute name is required for ProjectConfig") + + +class ProjectConfigError(Exception): + """ + Exception to be thrown when project settings attributes are incorrect + """ diff --git a/snaps/config/qos.py b/snaps/config/qos.py new file mode 100644 index 0000000..e507d2d --- /dev/null +++ b/snaps/config/qos.py @@ -0,0 +1,92 @@ +# 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 + + +class Consumer(enum.Enum): + """ + QoS Specification consumer types + """ + front_end = 'front-end' + back_end = 'back-end' + both = 'both' + + +class QoSConfig(object): + def __init__(self, **kwargs): + """ + Constructor + :param name: the qos's name (required) + :param consumer: the qos's consumer type of the enum type Consumer + (required) + :param specs: dict of key/values + """ + + self.name = kwargs.get('name') + + if kwargs.get('consumer'): + self.consumer = map_consumer(kwargs['consumer']) + else: + self.consumer = None + + self.specs = kwargs.get('specs') + if not self.specs: + self.specs = dict() + + if not self.name or not self.consumer: + raise QoSConfigError( + "The attributes name and consumer are required") + + +def map_consumer(consumer): + """ + Takes a the protocol value maps it to the Consumer enum. When None return + None + :param consumer: the value to map to the Enum + :return: the Protocol enum object + :raise: Exception if value is invalid + """ + if not consumer: + return None + elif isinstance(consumer, Consumer): + return consumer + elif isinstance(consumer, str): + proto_str = str(consumer) + if proto_str == 'front-end': + return Consumer.front_end + elif proto_str == 'back-end': + return Consumer.back_end + elif proto_str == 'both': + return Consumer.both + else: + raise QoSConfigError('Invalid Consumer - ' + proto_str) + else: + if consumer.value == 'front-end': + return Consumer.front_end + elif consumer.value == 'back-end': + return Consumer.back_end + elif consumer.value == 'both': + return Consumer.both + else: + raise QoSConfigError('Invalid Consumer - ' + consumer.value) + + +class QoSConfigError(Exception): + """ + Exception to be thrown when an qos settings are incorrect + """ + + def __init__(self, message): + Exception.__init__(self, message) diff --git a/snaps/config/router.py b/snaps/config/router.py new file mode 100644 index 0000000..72164f2 --- /dev/null +++ b/snaps/config/router.py @@ -0,0 +1,113 @@ +# 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. +from snaps.config.network import PortConfig +from snaps.openstack.utils import neutron_utils, keystone_utils + + +class RouterConfig(object): + """ + Class representing a router configuration + """ + + def __init__(self, **kwargs): + """ + Constructor - all parameters are optional + :param name: The router name. + :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. + :param external_gateway: Name of the external network to which to route + :param admin_state_up: The administrative status of the router. + 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 PortConfig objects + :return: + """ + self.name = kwargs.get('name') + self.project_name = kwargs.get('project_name') + self.external_gateway = kwargs.get('external_gateway') + + self.admin_state_up = kwargs.get('admin_state_up', True) + self.enable_snat = kwargs.get('enable_snat') + if kwargs.get('internal_subnets'): + self.internal_subnets = kwargs['internal_subnets'] + else: + self.internal_subnets = list() + + self.port_settings = list() + if kwargs.get('interfaces', kwargs.get('port_settings')): + interfaces = kwargs.get('interfaces', kwargs.get('port_settings')) + for interface in interfaces: + if isinstance(interface, PortConfig): + self.port_settings.append(interface) + else: + self.port_settings.append( + PortConfig(**interface['port'])) + + if not self.name: + raise RouterConfigError('Name is required') + + 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 to retrieve external network + information if necessary + :param os_creds: The OpenStack credentials + :return: the dictionary object + """ + out = dict() + ext_gw = dict() + + 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 RouterConfigError( + 'Could not find project ID for project named - ' + + self.project_name) + if self.admin_state_up is not None: + out['admin_state_up'] = self.admin_state_up + if self.external_gateway: + ext_net = neutron_utils.get_network( + neutron, network_name=self.external_gateway) + if ext_net: + ext_gw['network_id'] = ext_net.id + out['external_gateway_info'] = ext_gw + else: + raise RouterConfigError( + 'Could not find the external network named - ' + + self.external_gateway) + + return {'router': out} + + +class RouterConfigError(Exception): + """ + Exception to be thrown when router settings attributes are incorrect + """ diff --git a/snaps/config/stack.py b/snaps/config/stack.py new file mode 100644 index 0000000..0655961 --- /dev/null +++ b/snaps/config/stack.py @@ -0,0 +1,68 @@ +# 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. + +STACK_DELETE_TIMEOUT = 1200 +STACK_COMPLETE_TIMEOUT = 1200 +POLL_INTERVAL = 3 +STATUS_CREATE_FAILED = 'CREATE_FAILED' +STATUS_CREATE_COMPLETE = 'CREATE_COMPLETE' +STATUS_DELETE_COMPLETE = 'DELETE_COMPLETE' +STATUS_DELETE_FAILED = 'DELETE_FAILED' + + +class StackConfig(object): + """ + Configuration for Heat stack + """ + + def __init__(self, **kwargs): + """ + Constructor + :param name: the stack's name (required) + :param template: the heat template in dict() format (required if + template_path attribute is None) + :param template_path: the location of the heat template file (required + if template attribute is None) + :param env_values: dict() of strings for substitution of template + default values (optional) + """ + + self.name = kwargs.get('name') + self.template = kwargs.get('template') + self.template_path = kwargs.get('template_path') + self.env_values = kwargs.get('env_values') + if 'stack_create_timeout' in kwargs: + self.stack_create_timeout = kwargs['stack_create_timeout'] + else: + self.stack_create_timeout = STACK_COMPLETE_TIMEOUT + + if not self.name: + raise StackConfigError('name is required') + + if not self.template and not self.template_path: + raise StackConfigError('A Heat template is required') + + def __eq__(self, other): + return (self.name == other.name and + self.template == other.template and + self.template_path == other.template_path and + self.env_values == other.env_values and + self.stack_create_timeout == other.stack_create_timeout) + + +class StackConfigError(Exception): + """ + Exception to be thrown when an stack configuration are incorrect + """ diff --git a/snaps/config/tests/__init__.py b/snaps/config/tests/__init__.py new file mode 100644 index 0000000..271c742 --- /dev/null +++ b/snaps/config/tests/__init__.py @@ -0,0 +1,15 @@ +# 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. +__author__ = 'spisarski' diff --git a/snaps/config/tests/flavor_tests.py b/snaps/config/tests/flavor_tests.py new file mode 100644 index 0000000..15cd99a --- /dev/null +++ b/snaps/config/tests/flavor_tests.py @@ -0,0 +1,254 @@ +# 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.flavor import FlavorConfig, FlavorConfigError + + +class FlavorConfigUnitTests(unittest.TestCase): + """ + Tests the construction of the FlavorConfig class + """ + + def test_no_params(self): + with self.assertRaises(FlavorConfigError): + FlavorConfig() + + def test_empty_config(self): + with self.assertRaises(FlavorConfigError): + FlavorConfig(config=dict()) + + def test_name_only(self): + with self.assertRaises(FlavorConfigError): + FlavorConfig(name='foo') + + def test_config_with_name_only(self): + with self.assertRaises(FlavorConfigError): + FlavorConfig(config={'name': 'foo'}) + + def test_name_ram_only(self): + with self.assertRaises(FlavorConfigError): + FlavorConfig(name='foo', ram=1) + + def test_config_with_name_ram_only(self): + with self.assertRaises(FlavorConfigError): + FlavorConfig(config={'name': 'foo', 'ram': 1}) + + def test_name_ram_disk_only(self): + with self.assertRaises(FlavorConfigError): + FlavorConfig(name='foo', ram=1, disk=1) + + def test_config_with_name_ram_disk_only(self): + with self.assertRaises(FlavorConfigError): + FlavorConfig(config={'name': 'foo', 'ram': 1, 'disk': 1}) + + def test_ram_string(self): + with self.assertRaises(FlavorConfigError): + FlavorConfig(name='foo', ram='bar', disk=2, vcpus=3, ephemeral=4, + swap=5, rxtx_factor=6.0, + is_public=False) + + def test_config_ram_string(self): + with self.assertRaises(FlavorConfigError): + FlavorConfig( + config={'name': 'foo', 'ram': 'bar', 'disk': 2, 'vcpus': 3, + 'ephemeral': 4, 'swap': 5, + 'rxtx_factor': 6.0, 'is_public': False}) + + def test_ram_float(self): + with self.assertRaises(FlavorConfigError): + FlavorConfig(name='foo', ram=1.5, disk=2, vcpus=3, ephemeral=4, + swap=5, rxtx_factor=6.0, is_public=False) + + def test_config_ram_float(self): + with self.assertRaises(FlavorConfigError): + FlavorConfig( + config={'name': 'foo', 'ram': 1.5, 'disk': 2, 'vcpus': 3, + 'ephemeral': 4, 'swap': 5, + 'rxtx_factor': 6.0, 'is_public': False}) + + def test_disk_string(self): + with self.assertRaises(FlavorConfigError): + FlavorConfig(name='foo', ram=1, disk='bar', vcpus=3, ephemeral=4, + swap=5, rxtx_factor=6.0, + is_public=False) + + def test_config_disk_string(self): + with self.assertRaises(FlavorConfigError): + FlavorConfig( + config={'name': 'foo', 'ram': 1, 'disk': 'bar', 'vcpus': 3, + 'ephemeral': 4, 'swap': 5, + 'rxtx_factor': 6.0, 'is_public': False}) + + def test_disk_float(self): + with self.assertRaises(FlavorConfigError): + FlavorConfig(name='foo', ram=1, disk=2.5, vcpus=3, ephemeral=4, + swap=5, rxtx_factor=6.0, is_public=False) + + def test_config_disk_float(self): + with self.assertRaises(FlavorConfigError): + FlavorConfig( + config={'name': 'foo', 'ram': 1, 'disk': 2.5, 'vcpus': 3, + 'ephemeral': 4, 'swap': 5, + 'rxtx_factor': 6.0, 'is_public': False}) + + def test_vcpus_string(self): + with self.assertRaises(FlavorConfigError): + FlavorConfig(name='foo', ram=1, disk=2, vcpus='bar', ephemeral=4, + swap=5, rxtx_factor=6.0, + is_public=False) + + def test_config_vcpus_string(self): + with self.assertRaises(FlavorConfigError): + FlavorConfig( + config={'name': 'foo', 'ram': 1, 'disk': 2, 'vcpus': 'bar', + 'ephemeral': 4, 'swap': 5, + 'rxtx_factor': 6.0, 'is_public': False}) + + def test_ephemeral_string(self): + with self.assertRaises(FlavorConfigError): + FlavorConfig(name='foo', ram=1, disk=2, vcpus=3, ephemeral='bar', + swap=5, rxtx_factor=6.0, + is_public=False) + + def test_config_ephemeral_string(self): + with self.assertRaises(FlavorConfigError): + FlavorConfig( + config={'name': 'foo', 'ram': 1, 'disk': 2, 'vcpus': 3, + 'ephemeral': 'bar', 'swap': 5, + 'rxtx_factor': 6.0, 'is_public': False}) + + def test_ephemeral_float(self): + with self.assertRaises(FlavorConfigError): + FlavorConfig(name='foo', ram=1, disk=2, vcpus=3, ephemeral=4.5, + swap=5, rxtx_factor=6.0, is_public=False) + + def test_config_ephemeral_float(self): + with self.assertRaises(FlavorConfigError): + FlavorConfig( + config={'name': 'foo', 'ram': 1, 'disk': 2, 'vcpus': 3, + 'ephemeral': 4.5, 'swap': 5, + 'rxtx_factor': 6.0, 'is_public': False}) + + def test_swap_string(self): + with self.assertRaises(FlavorConfigError): + FlavorConfig(name='foo', ram=1, disk=2, vcpus=3, ephemeral=4, + swap='bar', rxtx_factor=6.0, + is_public=False) + + def test_config_swap_string(self): + with self.assertRaises(FlavorConfigError): + FlavorConfig( + config={'name': 'foo', 'ram': 1, 'disk': 2, 'vcpus': 3, + 'ephemeral': 4, 'swap': 'bar', + 'rxtx_factor': 6.0, 'is_public': False}) + + def test_swap_float(self): + with self.assertRaises(FlavorConfigError): + FlavorConfig(name='foo', ram=1, disk=2, vcpus=3, ephemeral=4, + swap=5.5, rxtx_factor=6.0, is_public=False) + + def test_config_swap_float(self): + with self.assertRaises(FlavorConfigError): + FlavorConfig( + config={'name': 'foo', 'ram': 1, 'disk': 2, 'vcpus': 3, + 'ephemeral': 4, 'swap': 5.5, + 'rxtx_factor': 6.0, 'is_public': False}) + + def test_rxtx_string(self): + with self.assertRaises(FlavorConfigError): + FlavorConfig(name='foo', ram=1, disk=2, vcpus=3, ephemeral=4, + swap=5, rxtx_factor='bar', is_public=False) + + def test_config_rxtx_string(self): + with self.assertRaises(FlavorConfigError): + FlavorConfig( + config={'name': 'foo', 'ram': 1, 'disk': 2, 'vcpus': 3, + 'ephemeral': 4, 'swap': 5, + 'rxtx_factor': 'bar', 'is_public': False}) + + def test_is_pub_string(self): + with self.assertRaises(FlavorConfigError): + FlavorConfig(name='foo', ram=1, disk=2, vcpus=3, ephemeral=4, + swap=5, rxtx_factor=6.0, is_public='bar') + + def test_config_is_pub_string(self): + with self.assertRaises(FlavorConfigError): + FlavorConfig( + config={'name': 'foo', 'ram': 1, 'disk': 2, 'vcpus': 3, + 'ephemeral': 4, 'swap': 5, + 'rxtx_factor': 6.0, 'is_public': 'bar'}) + + def test_name_ram_disk_vcpus_only(self): + settings = FlavorConfig(name='foo', ram=1, disk=2, vcpus=3) + self.assertEqual('foo', settings.name) + self.assertEqual('auto', settings.flavor_id) + self.assertEqual(1, settings.ram) + self.assertEqual(2, settings.disk) + self.assertEqual(3, settings.vcpus) + self.assertEqual(0, settings.ephemeral) + self.assertEqual(0, settings.swap) + self.assertEqual(1.0, settings.rxtx_factor) + self.assertEqual(True, settings.is_public) + self.assertEqual(None, settings.metadata) + + def test_config_with_name_ram_disk_vcpus_only(self): + settings = FlavorConfig( + **{'name': 'foo', 'ram': 1, 'disk': 2, 'vcpus': 3}) + self.assertEqual('foo', settings.name) + self.assertEqual('auto', settings.flavor_id) + self.assertEqual(1, settings.ram) + self.assertEqual(2, settings.disk) + self.assertEqual(3, settings.vcpus) + self.assertEqual(0, settings.ephemeral) + self.assertEqual(0, settings.swap) + self.assertEqual(1.0, settings.rxtx_factor) + self.assertEqual(True, settings.is_public) + self.assertEqual(None, settings.metadata) + + def test_all(self): + metadata = {'foo': 'bar'} + settings = FlavorConfig( + name='foo', flavor_id='bar', ram=1, disk=2, vcpus=3, ephemeral=4, + swap=5, rxtx_factor=6.0, is_public=False, metadata=metadata) + self.assertEqual('foo', settings.name) + self.assertEqual('bar', settings.flavor_id) + self.assertEqual(1, settings.ram) + self.assertEqual(2, settings.disk) + self.assertEqual(3, settings.vcpus) + self.assertEqual(4, settings.ephemeral) + self.assertEqual(5, settings.swap) + self.assertEqual(6.0, settings.rxtx_factor) + self.assertEqual(False, settings.is_public) + self.assertEqual(metadata, settings.metadata) + + def test_config_all(self): + metadata = {'foo': 'bar'} + settings = FlavorConfig( + **{'name': 'foo', 'flavor_id': 'bar', 'ram': 1, 'disk': 2, + 'vcpus': 3, + 'ephemeral': 4, 'swap': 5, 'rxtx_factor': 6.0, + 'is_public': False, + 'metadata': metadata}) + self.assertEqual('foo', settings.name) + self.assertEqual('bar', settings.flavor_id) + self.assertEqual(1, settings.ram) + self.assertEqual(2, settings.disk) + self.assertEqual(3, settings.vcpus) + self.assertEqual(4, settings.ephemeral) + self.assertEqual(5, settings.swap) + self.assertEqual(6.0, settings.rxtx_factor) + self.assertEqual(False, settings.is_public) + self.assertEqual(metadata, settings.metadata) diff --git a/snaps/config/tests/image_tests.py b/snaps/config/tests/image_tests.py new file mode 100644 index 0000000..8dcd2b4 --- /dev/null +++ b/snaps/config/tests/image_tests.py @@ -0,0 +1,226 @@ +# 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.image import ImageConfigError, ImageConfig + + +class ImageConfigUnitTests(unittest.TestCase): + """ + Tests the construction of the ImageConfig class + """ + + def test_no_params(self): + with self.assertRaises(ImageConfigError): + ImageConfig() + + def test_empty_config(self): + with self.assertRaises(ImageConfigError): + ImageConfig(**dict()) + + def test_name_only(self): + with self.assertRaises(ImageConfigError): + ImageConfig(name='foo') + + def test_config_with_name_only(self): + with self.assertRaises(ImageConfigError): + ImageConfig(**{'name': 'foo'}) + + def test_name_user_only(self): + with self.assertRaises(ImageConfigError): + ImageConfig(name='foo', image_user='bar') + + def test_config_with_name_user_only(self): + with self.assertRaises(ImageConfigError): + ImageConfig(**{'name': 'foo', 'image_user': 'bar'}) + + def test_name_user_format_only(self): + with self.assertRaises(ImageConfigError): + ImageConfig(name='foo', image_user='bar', img_format='qcow2') + + def test_config_with_name_user_format_only(self): + with self.assertRaises(ImageConfigError): + ImageConfig( + **{'name': 'foo', 'image_user': 'bar', 'format': 'qcow2'}) + + def test_name_user_format_url_only(self): + settings = ImageConfig(name='foo', image_user='bar', + img_format='qcow2', url='http://foo.com') + self.assertEqual('foo', settings.name) + self.assertEqual('bar', settings.image_user) + self.assertEqual('qcow2', settings.format) + self.assertEqual('http://foo.com', settings.url) + self.assertIsNone(settings.image_file) + self.assertFalse(settings.exists) + self.assertFalse(settings.public) + self.assertIsNone(settings.nic_config_pb_loc) + + def test_name_user_format_url_only_properties(self): + properties = {'hw_video_model': 'vga'} + settings = ImageConfig(name='foo', image_user='bar', + img_format='qcow2', url='http://foo.com', + extra_properties=properties) + self.assertEqual('foo', settings.name) + self.assertEqual('bar', settings.image_user) + self.assertEqual('qcow2', settings.format) + self.assertEqual('http://foo.com', settings.url) + self.assertEqual(properties, settings.extra_properties) + self.assertIsNone(settings.image_file) + self.assertFalse(settings.exists) + self.assertFalse(settings.public) + self.assertIsNone(settings.nic_config_pb_loc) + + def test_config_with_name_user_format_url_only(self): + settings = ImageConfig( + **{'name': 'foo', 'image_user': 'bar', 'format': 'qcow2', + 'download_url': 'http://foo.com'}) + self.assertEqual('foo', settings.name) + self.assertEqual('bar', settings.image_user) + self.assertEqual('qcow2', settings.format) + self.assertEqual('http://foo.com', settings.url) + self.assertIsNone(settings.image_file) + self.assertFalse(settings.exists) + self.assertFalse(settings.public) + self.assertIsNone(settings.nic_config_pb_loc) + + def test_name_user_format_file_only(self): + settings = ImageConfig(name='foo', image_user='bar', + img_format='qcow2', + image_file='/foo/bar.qcow') + self.assertEqual('foo', settings.name) + self.assertEqual('bar', settings.image_user) + self.assertEqual('qcow2', settings.format) + self.assertIsNone(settings.url) + self.assertEqual('/foo/bar.qcow', settings.image_file) + self.assertFalse(settings.exists) + self.assertFalse(settings.public) + self.assertIsNone(settings.nic_config_pb_loc) + + def test_config_with_name_user_format_file_only(self): + settings = ImageConfig( + **{'name': 'foo', 'image_user': 'bar', 'format': 'qcow2', + 'image_file': '/foo/bar.qcow'}) + self.assertEqual('foo', settings.name) + self.assertEqual('bar', settings.image_user) + self.assertEqual('qcow2', settings.format) + self.assertIsNone(settings.url) + self.assertEqual('/foo/bar.qcow', settings.image_file) + self.assertFalse(settings.exists) + self.assertFalse(settings.public) + self.assertIsNone(settings.nic_config_pb_loc) + + def test_all_url(self): + properties = {'hw_video_model': 'vga'} + kernel_settings = ImageConfig(name='kernel', url='http://kernel.com', + image_user='bar', img_format='qcow2') + ramdisk_settings = ImageConfig(name='ramdisk', + url='http://ramdisk.com', + image_user='bar', img_format='qcow2') + settings = ImageConfig(name='foo', image_user='bar', + img_format='qcow2', url='http://foo.com', + extra_properties=properties, + nic_config_pb_loc='/foo/bar', + kernel_image_settings=kernel_settings, + ramdisk_image_settings=ramdisk_settings, + exists=True, public=True) + self.assertEqual('foo', settings.name) + self.assertEqual('bar', settings.image_user) + self.assertEqual('qcow2', settings.format) + self.assertEqual('http://foo.com', settings.url) + self.assertEqual(properties, settings.extra_properties) + self.assertIsNone(settings.image_file) + self.assertEqual('/foo/bar', settings.nic_config_pb_loc) + self.assertEqual('kernel', settings.kernel_image_settings.name) + self.assertEqual('http://kernel.com', + settings.kernel_image_settings.url) + self.assertEqual('bar', settings.kernel_image_settings.image_user) + self.assertEqual('qcow2', settings.kernel_image_settings.format) + self.assertEqual('ramdisk', settings.ramdisk_image_settings.name) + self.assertEqual('http://ramdisk.com', + settings.ramdisk_image_settings.url) + self.assertEqual('bar', settings.ramdisk_image_settings.image_user) + self.assertEqual('qcow2', settings.ramdisk_image_settings.format) + self.assertTrue(settings.exists) + self.assertTrue(settings.public) + + def test_config_all_url(self): + settings = ImageConfig( + **{'name': 'foo', 'image_user': 'bar', 'format': 'qcow2', + 'download_url': 'http://foo.com', + 'extra_properties': '{\'hw_video_model\': \'vga\'}', + 'nic_config_pb_loc': '/foo/bar', + 'kernel_image_settings': { + 'name': 'kernel', + 'download_url': 'http://kernel.com', + 'image_user': 'bar', + 'format': 'qcow2'}, + 'ramdisk_image_settings': { + 'name': 'ramdisk', + 'download_url': 'http://ramdisk.com', + 'image_user': 'bar', + 'format': 'qcow2'}, + 'exists': True, 'public': True}) + self.assertEqual('foo', settings.name) + self.assertEqual('bar', settings.image_user) + self.assertEqual('qcow2', settings.format) + self.assertEqual('http://foo.com', settings.url) + self.assertEqual('{\'hw_video_model\': \'vga\'}', + settings.extra_properties) + self.assertIsNone(settings.image_file) + self.assertEqual('/foo/bar', settings.nic_config_pb_loc) + self.assertEqual('kernel', settings.kernel_image_settings.name) + self.assertEqual('http://kernel.com', + settings.kernel_image_settings.url) + self.assertEqual('ramdisk', settings.ramdisk_image_settings.name) + self.assertEqual('http://ramdisk.com', + settings.ramdisk_image_settings.url) + self.assertTrue(settings.exists) + self.assertTrue(settings.public) + + def test_all_file(self): + properties = {'hw_video_model': 'vga'} + settings = ImageConfig(name='foo', image_user='bar', + img_format='qcow2', + image_file='/foo/bar.qcow', + extra_properties=properties, + nic_config_pb_loc='/foo/bar', exists=True, + public=True) + self.assertEqual('foo', settings.name) + self.assertEqual('bar', settings.image_user) + self.assertEqual('qcow2', settings.format) + self.assertIsNone(settings.url) + self.assertEqual('/foo/bar.qcow', settings.image_file) + self.assertEqual(properties, settings.extra_properties) + self.assertEqual('/foo/bar', settings.nic_config_pb_loc) + self.assertTrue(settings.exists) + self.assertTrue(settings.public) + + def test_config_all_file(self): + settings = ImageConfig( + **{'name': 'foo', 'image_user': 'bar', 'format': 'qcow2', + 'image_file': '/foo/bar.qcow', + 'extra_properties': '{\'hw_video_model\' : \'vga\'}', + 'nic_config_pb_loc': '/foo/bar', 'exists': True, + 'public': True}) + self.assertEqual('foo', settings.name) + self.assertEqual('bar', settings.image_user) + self.assertEqual('qcow2', settings.format) + self.assertIsNone(settings.url) + self.assertEqual('/foo/bar.qcow', settings.image_file) + self.assertEqual('{\'hw_video_model\' : \'vga\'}', + settings.extra_properties) + self.assertEqual('/foo/bar', settings.nic_config_pb_loc) + self.assertTrue(settings.exists) + self.assertTrue(settings.public) diff --git a/snaps/config/tests/keypair_tests.py b/snaps/config/tests/keypair_tests.py new file mode 100644 index 0000000..6d0fec4 --- /dev/null +++ b/snaps/config/tests/keypair_tests.py @@ -0,0 +1,179 @@ +# 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.keypair import KeypairConfigError, KeypairConfig + + +class KeypairConfigUnitTests(unittest.TestCase): + """ + Tests the construction of the KeypairConfig class + """ + + def test_no_params(self): + with self.assertRaises(KeypairConfigError): + KeypairConfig() + + def test_empty_config(self): + with self.assertRaises(KeypairConfigError): + KeypairConfig(**dict()) + + def test_small_key_size(self): + with self.assertRaises(KeypairConfigError): + KeypairConfig(name='foo', key_size=511) + + def test_name_only(self): + settings = KeypairConfig(name='foo') + self.assertEqual('foo', settings.name) + self.assertEqual(1024, settings.key_size) + self.assertIsNone(settings.public_filepath) + self.assertIsNone(settings.private_filepath) + self.assertIsNone(settings.delete_on_clean) + + def test_config_with_name_only(self): + settings = KeypairConfig(**{'name': 'foo'}) + self.assertEqual('foo', settings.name) + self.assertEqual(1024, settings.key_size) + self.assertIsNone(settings.public_filepath) + self.assertIsNone(settings.private_filepath) + self.assertIsNone(settings.delete_on_clean) + + def test_name_pub_only(self): + settings = KeypairConfig(name='foo', public_filepath='/foo/bar.pub') + self.assertEqual('foo', settings.name) + self.assertEqual(1024, settings.key_size) + self.assertEqual('/foo/bar.pub', settings.public_filepath) + self.assertIsNone(settings.private_filepath) + self.assertIsNone(settings.delete_on_clean) + + def test_config_with_name_pub_only(self): + settings = KeypairConfig( + **{'name': 'foo', 'public_filepath': '/foo/bar.pub'}) + self.assertEqual('foo', settings.name) + self.assertEqual(1024, settings.key_size) + self.assertEqual('/foo/bar.pub', settings.public_filepath) + self.assertIsNone(settings.private_filepath) + self.assertIsNone(settings.delete_on_clean) + + def test_name_priv_only(self): + settings = KeypairConfig(name='foo', private_filepath='/foo/bar') + self.assertEqual('foo', settings.name) + self.assertEqual(1024, settings.key_size) + self.assertIsNone(settings.public_filepath) + self.assertEqual('/foo/bar', settings.private_filepath) + self.assertIsNone(settings.delete_on_clean) + + def test_config_with_name_priv_only(self): + settings = KeypairConfig( + **{'name': 'foo', 'private_filepath': '/foo/bar'}) + self.assertEqual('foo', settings.name) + self.assertEqual(1024, settings.key_size) + self.assertIsNone(settings.public_filepath) + self.assertEqual('/foo/bar', settings.private_filepath) + self.assertIsNone(settings.delete_on_clean) + + def test_all_delete_bool(self): + settings = KeypairConfig( + name='foo', public_filepath='/foo/bar.pub', + private_filepath='/foo/bar', delete_on_clean=True, + key_size=999) + self.assertEqual('foo', settings.name) + self.assertEqual(999, settings.key_size) + self.assertEqual('/foo/bar.pub', settings.public_filepath) + self.assertEqual('/foo/bar', settings.private_filepath) + self.assertTrue(settings.delete_on_clean) + + def test_all_delete_str_true_cap(self): + settings = KeypairConfig( + name='foo', public_filepath='/foo/bar.pub', + private_filepath='/foo/bar', delete_on_clean='True') + self.assertEqual('foo', settings.name) + self.assertEqual(1024, settings.key_size) + self.assertEqual('/foo/bar.pub', settings.public_filepath) + self.assertEqual('/foo/bar', settings.private_filepath) + self.assertTrue(settings.delete_on_clean) + + def test_all_delete_str_true_lc(self): + settings = KeypairConfig( + name='foo', public_filepath='/foo/bar.pub', + private_filepath='/foo/bar', delete_on_clean='true') + self.assertEqual('foo', settings.name) + self.assertEqual(1024, settings.key_size) + self.assertEqual('/foo/bar.pub', settings.public_filepath) + self.assertEqual('/foo/bar', settings.private_filepath) + self.assertTrue(settings.delete_on_clean) + + def test_all_delete_str_false_cap(self): + settings = KeypairConfig( + name='foo', public_filepath='/foo/bar.pub', + private_filepath='/foo/bar', delete_on_clean='False') + self.assertEqual('foo', settings.name) + self.assertEqual(1024, settings.key_size) + self.assertEqual('/foo/bar.pub', settings.public_filepath) + self.assertEqual('/foo/bar', settings.private_filepath) + self.assertFalse(settings.delete_on_clean) + + def test_all_delete_str_false_lc(self): + settings = KeypairConfig( + name='foo', public_filepath='/foo/bar.pub', + private_filepath='/foo/bar', delete_on_clean='false', + key_size='999') + self.assertEqual('foo', settings.name) + self.assertEqual(999, settings.key_size) + self.assertEqual('/foo/bar.pub', settings.public_filepath) + self.assertEqual('/foo/bar', settings.private_filepath) + self.assertFalse(settings.delete_on_clean) + + def test_config_all_delete_false_bool(self): + settings = KeypairConfig( + **{'name': 'foo', 'public_filepath': '/foo/bar.pub', + 'private_filepath': '/foo/bar', 'delete_on_clean': False, + 'key_size': 999}) + self.assertEqual('foo', settings.name) + self.assertEqual(999, settings.key_size) + self.assertEqual('/foo/bar.pub', settings.public_filepath) + self.assertEqual('/foo/bar', settings.private_filepath) + self.assertFalse(settings.delete_on_clean) + + def test_config_all_delete_false_str_cap(self): + settings = KeypairConfig( + **{'name': 'foo', 'public_filepath': '/foo/bar.pub', + 'private_filepath': '/foo/bar', 'delete_on_clean': 'False'}) + self.assertEqual('foo', settings.name) + self.assertEqual(1024, settings.key_size) + self.assertEqual('/foo/bar.pub', settings.public_filepath) + self.assertEqual('/foo/bar', settings.private_filepath) + self.assertFalse(settings.delete_on_clean) + + def test_config_all_delete_false_str_lc(self): + settings = KeypairConfig( + **{'name': 'foo', 'public_filepath': '/foo/bar.pub', + 'private_filepath': '/foo/bar', 'delete_on_clean': 'false'}) + self.assertEqual('foo', settings.name) + self.assertEqual(1024, settings.key_size) + self.assertEqual('/foo/bar.pub', settings.public_filepath) + self.assertEqual('/foo/bar', settings.private_filepath) + self.assertFalse(settings.delete_on_clean) + + def test_config_all_delete_false_str_foo(self): + settings = KeypairConfig( + **{'name': 'foo', 'public_filepath': '/foo/bar.pub', + 'private_filepath': '/foo/bar', 'delete_on_clean': 'foo', + 'key_size': '999'}) + self.assertEqual('foo', settings.name) + self.assertEqual(999, settings.key_size) + self.assertEqual('/foo/bar.pub', settings.public_filepath) + self.assertEqual('/foo/bar', settings.private_filepath) + self.assertFalse(settings.delete_on_clean) 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/project_tests.py b/snaps/config/tests/project_tests.py new file mode 100644 index 0000000..0470d83 --- /dev/null +++ b/snaps/config/tests/project_tests.py @@ -0,0 +1,69 @@ +# 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.project import ProjectConfig, ProjectConfigError + + +class ProjectConfigUnitTests(unittest.TestCase): + """ + Tests the construction of the ProjectConfig class + """ + + def test_no_params(self): + with self.assertRaises(ProjectConfigError): + ProjectConfig() + + def test_empty_config(self): + with self.assertRaises(ProjectConfigError): + ProjectConfig(**dict()) + + def test_name_only(self): + settings = ProjectConfig(name='foo') + self.assertEqual('foo', settings.name) + self.assertEqual('Default', settings.domain_name) + self.assertIsNone(settings.description) + self.assertTrue(settings.enabled) + self.assertEqual(list(), settings.users) + + def test_config_with_name_only(self): + settings = ProjectConfig(**{'name': 'foo'}) + self.assertEqual('foo', settings.name) + self.assertEqual('Default', settings.domain_name) + self.assertIsNone(settings.description) + self.assertTrue(settings.enabled) + self.assertEqual(list(), settings.users) + + def test_all(self): + users = ['test1', 'test2'] + settings = ProjectConfig( + name='foo', domain='bar', description='foobar', enabled=False, + users=users) + self.assertEqual('foo', settings.name) + self.assertEqual('bar', settings.domain_name) + self.assertEqual('foobar', settings.description) + self.assertFalse(settings.enabled) + self.assertEqual(users, settings.users) + + def test_config_all(self): + users = ['test1', 'test2'] + settings = ProjectConfig( + **{'name': 'foo', 'domain': 'bar', 'description': 'foobar', + 'enabled': False, 'users': users}) + self.assertEqual('foo', settings.name) + self.assertEqual('bar', settings.domain_name) + self.assertEqual('foobar', settings.description) + self.assertFalse(settings.enabled) + self.assertEqual(users, settings.users) diff --git a/snaps/config/tests/qos_tests.py b/snaps/config/tests/qos_tests.py new file mode 100644 index 0000000..7314c5b --- /dev/null +++ b/snaps/config/tests/qos_tests.py @@ -0,0 +1,91 @@ +# 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.qos import QoSConfig, QoSConfigError, Consumer + + +class QoSConfigUnitTests(unittest.TestCase): + """ + Tests the construction of the QoSConfig class + """ + + def test_no_params(self): + with self.assertRaises(QoSConfigError): + QoSConfig() + + def test_empty_config(self): + with self.assertRaises(QoSConfigError): + QoSConfig(**dict()) + + def test_name_only(self): + with self.assertRaises(QoSConfigError): + QoSConfig(name='foo') + + def test_config_with_name_only(self): + with self.assertRaises(QoSConfigError): + QoSConfig(**{'name': 'foo'}) + + def test_invalid_consumer(self): + with self.assertRaises(QoSConfigError): + QoSConfig(name='foo', consumer='bar') + + def test_config_with_invalid_consumer(self): + with self.assertRaises(QoSConfigError): + QoSConfig(**{'name': 'foo', 'consumer': 'bar'}) + + def test_name_consumer(self): + settings = QoSConfig(name='foo', consumer=Consumer.front_end) + + self.assertEqual('foo', settings.name) + self.assertEqual(Consumer.front_end, settings.consumer) + self.assertEqual(dict(), settings.specs) + + def test_name_consumer_front_end_strings(self): + settings = QoSConfig(name='foo', consumer='front-end') + + self.assertEqual('foo', settings.name) + self.assertEqual(Consumer.front_end, settings.consumer) + self.assertEqual(dict(), settings.specs) + + def test_name_consumer_back_end_strings(self): + settings = QoSConfig(name='foo', consumer='back-end') + + self.assertEqual('foo', settings.name) + self.assertEqual(Consumer.back_end, settings.consumer) + self.assertEqual(dict(), settings.specs) + + def test_name_consumer_both_strings(self): + settings = QoSConfig(name='foo', consumer='both') + + self.assertEqual('foo', settings.name) + self.assertEqual(Consumer.both, settings.consumer) + self.assertEqual(dict(), settings.specs) + + def test_all(self): + specs = {'spec1': 'val1', 'spec2': 'val2'} + settings = QoSConfig(name='foo', consumer=Consumer.both, specs=specs) + + self.assertEqual('foo', settings.name) + self.assertEqual(Consumer.both, settings.consumer) + self.assertEqual(specs, settings.specs) + + def test_config_all(self): + settings = QoSConfig( + **{'name': 'foo', 'consumer': 'both', 'specs': {'spec1': 'val1'}}) + + self.assertEqual('foo', settings.name) + self.assertEqual(Consumer.both, settings.consumer) + self.assertEqual({'spec1': 'val1'}, settings.specs) diff --git a/snaps/config/tests/router_tests.py b/snaps/config/tests/router_tests.py new file mode 100644 index 0000000..2c8f91f --- /dev/null +++ b/snaps/config/tests/router_tests.py @@ -0,0 +1,98 @@ +# 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 PortConfig +from snaps.config.router import RouterConfig, RouterConfigError + + +class RouterConfigUnitTests(unittest.TestCase): + """ + Class for testing the RouterConfig class + """ + + def test_no_params(self): + with self.assertRaises(RouterConfigError): + RouterConfig() + + def test_empty_config(self): + with self.assertRaises(RouterConfigError): + RouterConfig(**dict()) + + def test_name_only(self): + settings = RouterConfig(name='foo') + self.assertEqual('foo', settings.name) + self.assertIsNone(settings.project_name) + self.assertIsNone(settings.external_gateway) + self.assertTrue(settings.admin_state_up) + self.assertIsNone(settings.enable_snat) + self.assertIsNotNone(settings.internal_subnets) + self.assertTrue(isinstance(settings.internal_subnets, list)) + self.assertEqual(0, len(settings.internal_subnets)) + self.assertIsNotNone(settings.port_settings) + self.assertTrue(isinstance(settings.port_settings, list)) + self.assertEqual(0, len(settings.port_settings)) + + def test_config_with_name_only(self): + settings = RouterConfig(**{'name': 'foo'}) + self.assertEqual('foo', settings.name) + self.assertIsNone(settings.project_name) + self.assertIsNone(settings.external_gateway) + self.assertTrue(settings.admin_state_up) + self.assertIsNone(settings.enable_snat) + self.assertIsNotNone(settings.internal_subnets) + self.assertTrue(isinstance(settings.internal_subnets, list)) + self.assertEqual(0, len(settings.internal_subnets)) + self.assertIsNotNone(settings.port_settings) + self.assertTrue(isinstance(settings.port_settings, list)) + self.assertEqual(0, len(settings.port_settings)) + + def test_all(self): + port_settings = PortConfig(name='foo', network_name='bar') + settings = RouterConfig( + name='foo', project_name='bar', external_gateway='foo_gateway', + admin_state_up=True, enable_snat=False, + internal_subnets=['10.0.0.1/24'], interfaces=[port_settings]) + self.assertEqual('foo', settings.name) + self.assertEqual('bar', settings.project_name) + self.assertEqual('foo_gateway', settings.external_gateway) + self.assertTrue(settings.admin_state_up) + self.assertFalse(settings.enable_snat) + self.assertIsNotNone(settings.internal_subnets) + self.assertTrue(isinstance(settings.internal_subnets, list)) + self.assertEqual(1, len(settings.internal_subnets)) + self.assertEqual(['10.0.0.1/24'], settings.internal_subnets) + self.assertEqual([port_settings], settings.port_settings) + + def test_config_all(self): + settings = RouterConfig( + **{'name': 'foo', 'project_name': 'bar', + 'external_gateway': 'foo_gateway', 'admin_state_up': True, + 'enable_snat': False, 'internal_subnets': ['10.0.0.1/24'], + 'interfaces': + [{'port': {'name': 'foo-port', + 'network_name': 'bar-net'}}]}) + self.assertEqual('foo', settings.name) + self.assertEqual('bar', settings.project_name) + self.assertEqual('foo_gateway', settings.external_gateway) + self.assertTrue(settings.admin_state_up) + self.assertFalse(settings.enable_snat) + self.assertIsNotNone(settings.internal_subnets) + self.assertTrue(isinstance(settings.internal_subnets, list)) + self.assertEqual(1, len(settings.internal_subnets)) + self.assertEqual(['10.0.0.1/24'], settings.internal_subnets) + self.assertEqual([PortConfig(**{'name': 'foo-port', + 'network_name': 'bar-net'})], + settings.port_settings) diff --git a/snaps/config/tests/stack_tests.py b/snaps/config/tests/stack_tests.py new file mode 100644 index 0000000..cf6e7d8 --- /dev/null +++ b/snaps/config/tests/stack_tests.py @@ -0,0 +1,98 @@ +# 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 + +import snaps +from snaps.config.stack import StackConfigError, StackConfig + + +class StackConfigUnitTests(unittest.TestCase): + """ + Tests the construction of the StackConfig class + """ + + def test_no_params(self): + with self.assertRaises(StackConfigError): + StackConfig() + + def test_empty_config(self): + with self.assertRaises(StackConfigError): + StackConfig(**dict()) + + def test_name_only(self): + with self.assertRaises(StackConfigError): + StackConfig(name='foo') + + def test_config_with_name_only(self): + with self.assertRaises(StackConfigError): + StackConfig(**{'name': 'foo'}) + + def test_config_minimum_template(self): + settings = StackConfig(**{'name': 'stack', 'template': 'foo'}) + self.assertEqual('stack', settings.name) + self.assertEqual('foo', settings.template) + self.assertIsNone(settings.template_path) + self.assertIsNone(settings.env_values) + self.assertEqual(snaps.config.stack.STACK_COMPLETE_TIMEOUT, + settings.stack_create_timeout) + + def test_config_minimum_template_path(self): + settings = StackConfig(**{'name': 'stack', 'template_path': 'foo'}) + self.assertEqual('stack', settings.name) + self.assertIsNone(settings.template) + self.assertEqual('foo', settings.template_path) + self.assertIsNone(settings.env_values) + self.assertEqual(snaps.config.stack.STACK_COMPLETE_TIMEOUT, + settings.stack_create_timeout) + + def test_minimum_template(self): + settings = StackConfig(name='stack', template='foo') + self.assertEqual('stack', settings.name) + self.assertEqual('foo', settings.template) + self.assertIsNone(settings.template_path) + self.assertIsNone(settings.env_values) + self.assertEqual(snaps.config.stack.STACK_COMPLETE_TIMEOUT, + settings.stack_create_timeout) + + def test_minimum_template_path(self): + settings = StackConfig(name='stack', template_path='foo') + self.assertEqual('stack', settings.name) + self.assertEqual('foo', settings.template_path) + self.assertIsNone(settings.template) + self.assertIsNone(settings.env_values) + self.assertEqual(snaps.config.stack.STACK_COMPLETE_TIMEOUT, + settings.stack_create_timeout) + + def test_all(self): + env_values = {'foo': 'bar'} + settings = StackConfig( + name='stack', template='bar', template_path='foo', + env_values=env_values, stack_create_timeout=999) + self.assertEqual('stack', settings.name) + self.assertEqual('bar', settings.template) + self.assertEqual('foo', settings.template_path) + self.assertEqual(env_values, settings.env_values) + self.assertEqual(999, settings.stack_create_timeout) + + def test_config_all(self): + env_values = {'foo': 'bar'} + settings = StackConfig( + **{'name': 'stack', 'template': 'bar', 'template_path': 'foo', + 'env_values': env_values, 'stack_create_timeout': 999}) + self.assertEqual('stack', settings.name) + self.assertEqual('bar', settings.template) + self.assertEqual('foo', settings.template_path) + self.assertEqual(env_values, settings.env_values) + self.assertEqual(999, settings.stack_create_timeout) diff --git a/snaps/config/tests/user_tests.py b/snaps/config/tests/user_tests.py new file mode 100644 index 0000000..d3d8feb --- /dev/null +++ b/snaps/config/tests/user_tests.py @@ -0,0 +1,84 @@ +# 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.user import UserConfig + + +class UserConfigUnitTests(unittest.TestCase): + """ + Tests the construction of the UserConfig class + """ + + def test_no_params(self): + with self.assertRaises(Exception): + UserConfig() + + def test_empty_config(self): + with self.assertRaises(Exception): + UserConfig(**dict()) + + def test_name_only(self): + with self.assertRaises(Exception): + UserConfig(name='foo') + + def test_config_with_name_only(self): + with self.assertRaises(Exception): + UserConfig(**{'name': 'foo'}) + + def test_name_pass_enabled_str(self): + with self.assertRaises(Exception): + UserConfig(name='foo', password='bar', enabled='true') + + def test_config_with_name_pass_enabled_str(self): + with self.assertRaises(Exception): + UserConfig( + **{'name': 'foo', 'password': 'bar', 'enabled': 'true'}) + + def test_name_pass_only(self): + settings = UserConfig(name='foo', password='bar') + self.assertEqual('foo', settings.name) + self.assertEqual('bar', settings.password) + self.assertIsNone(settings.project_name) + self.assertIsNone(settings.email) + self.assertTrue(settings.enabled) + + def test_config_with_name_pass_only(self): + settings = UserConfig(**{'name': 'foo', 'password': 'bar'}) + self.assertEqual('foo', settings.name) + self.assertEqual('bar', settings.password) + self.assertIsNone(settings.project_name) + self.assertIsNone(settings.email) + self.assertTrue(settings.enabled) + + def test_all(self): + settings = UserConfig( + name='foo', password='bar', project_name='proj-foo', + email='foo@bar.com', enabled=False) + self.assertEqual('foo', settings.name) + self.assertEqual('bar', settings.password) + self.assertEqual('proj-foo', settings.project_name) + self.assertEqual('foo@bar.com', settings.email) + self.assertFalse(settings.enabled) + + def test_config_all(self): + settings = UserConfig( + **{'name': 'foo', 'password': 'bar', 'project_name': 'proj-foo', + 'email': 'foo@bar.com', 'enabled': False}) + self.assertEqual('foo', settings.name) + self.assertEqual('bar', settings.password) + self.assertEqual('proj-foo', settings.project_name) + self.assertEqual('foo@bar.com', settings.email) + self.assertFalse(settings.enabled) diff --git a/snaps/config/tests/volume_tests.py b/snaps/config/tests/volume_tests.py new file mode 100644 index 0000000..b4b54bd --- /dev/null +++ b/snaps/config/tests/volume_tests.py @@ -0,0 +1,91 @@ +# 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.volume import VolumeConfigError, VolumeConfig + + +class VolumeConfigUnitTests(unittest.TestCase): + """ + Tests the construction of the VolumeConfig class + """ + + def test_no_params(self): + with self.assertRaises(VolumeConfigError): + VolumeConfig() + + def test_empty_config(self): + with self.assertRaises(VolumeConfigError): + VolumeConfig(**dict()) + + def test_name_only(self): + settings = VolumeConfig(name='foo') + self.assertEqual('foo', settings.name) + self.assertIsNone(settings.description) + self.assertEquals(1, settings.size) + self.assertIsNone(settings.image_name) + self.assertIsNone(settings.type_name) + self.assertIsNone(settings.availability_zone) + self.assertFalse(settings.multi_attach) + + def test_config_with_name_only(self): + settings = VolumeConfig(**{'name': 'foo'}) + self.assertEqual('foo', settings.name) + self.assertIsNone(settings.description) + self.assertEquals(1, settings.size) + self.assertIsNone(settings.image_name) + self.assertIsNone(settings.type_name) + self.assertIsNone(settings.availability_zone) + self.assertFalse(settings.multi_attach) + + def test_all_strings(self): + settings = VolumeConfig( + name='foo', description='desc', size='2', image_name='image', + type_name='type', availability_zone='zone1', multi_attach='true') + + self.assertEqual('foo', settings.name) + self.assertEqual('desc', settings.description) + self.assertEqual(2, settings.size) + self.assertEqual('image', settings.image_name) + self.assertEqual('type', settings.type_name) + self.assertEqual('zone1', settings.availability_zone) + self.assertTrue(settings.multi_attach) + + def test_all_correct_type(self): + settings = VolumeConfig( + name='foo', description='desc', size=2, image_name='image', + type_name='bar', availability_zone='zone1', multi_attach=True) + + self.assertEqual('foo', settings.name) + self.assertEqual('desc', settings.description) + self.assertEqual(2, settings.size) + self.assertEqual('image', settings.image_name) + self.assertEqual('bar', settings.type_name) + self.assertEqual('zone1', settings.availability_zone) + self.assertTrue(settings.multi_attach) + + def test_config_all(self): + settings = VolumeConfig( + **{'name': 'foo', 'description': 'desc', 'size': '2', + 'image_name': 'foo', 'type_name': 'bar', + 'availability_zone': 'zone1', 'multi_attach': 'true'}) + + self.assertEqual('foo', settings.name) + self.assertEqual('desc', settings.description) + self.assertEqual(2, settings.size) + self.assertEqual('foo', settings.image_name) + self.assertEqual('bar', settings.type_name) + self.assertEqual('zone1', settings.availability_zone) + self.assertTrue(settings.multi_attach) diff --git a/snaps/config/tests/volume_type_tests.py b/snaps/config/tests/volume_type_tests.py new file mode 100644 index 0000000..7b4fb1b --- /dev/null +++ b/snaps/config/tests/volume_type_tests.py @@ -0,0 +1,91 @@ +# 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.volume_type import ( + VolumeTypeConfig, VolumeTypeEncryptionConfig, ControlLocation, + VolumeTypeConfigError) + + +class VolumeTypeConfigUnitTests(unittest.TestCase): + """ + Tests the construction of the VolumeTypeConfig class + """ + + def test_no_params(self): + with self.assertRaises(VolumeTypeConfigError): + VolumeTypeConfig() + + def test_empty_config(self): + with self.assertRaises(VolumeTypeConfigError): + VolumeTypeConfig(**dict()) + + def test_name_only(self): + settings = VolumeTypeConfig(name='foo') + self.assertEqual('foo', settings.name) + self.assertIsNone(settings.description) + self.assertIsNone(settings.qos_spec_name) + self.assertIsNone(settings.encryption) + self.assertFalse(settings.public) + + def test_config_with_name_only(self): + settings = VolumeTypeConfig(**{'name': 'foo'}) + self.assertEqual('foo', settings.name) + self.assertIsNone(settings.description) + self.assertIsNone(settings.qos_spec_name) + self.assertIsNone(settings.encryption) + self.assertFalse(settings.public) + + def test_all(self): + encryption_settings = VolumeTypeEncryptionConfig( + name='foo', provider_class='bar', + control_location=ControlLocation.back_end) + settings = VolumeTypeConfig( + name='foo', description='desc', encryption=encryption_settings, + qos_spec_name='spec_name', public=True) + self.assertEqual('foo', settings.name) + self.assertEqual('desc', settings.description) + self.assertEqual('spec_name', settings.qos_spec_name) + self.assertEqual(encryption_settings, settings.encryption) + self.assertTrue(True, settings.public) + + def test_all_string(self): + encryption_settings = { + 'name': 'foo', 'provider_class': 'bar', + 'control_location': 'back-end'} + settings = VolumeTypeConfig( + name='foo', description='desc', encryption=encryption_settings, + qos_spec_name='spec_name', public='true') + self.assertEqual('foo', settings.name) + self.assertEqual('desc', settings.description) + self.assertEqual('spec_name', settings.qos_spec_name) + self.assertEqual(VolumeTypeEncryptionConfig(**encryption_settings), + settings.encryption) + self.assertTrue(settings.public) + + def test_config_all(self): + encryption_settings = { + 'name': 'foo', 'provider_class': 'bar', + 'control_location': 'back-end'} + settings = VolumeTypeConfig( + **{'name': 'foo', 'description': 'desc', + 'encryption': encryption_settings, + 'qos_spec_name': 'spec_name', 'public': 'false'}) + self.assertEqual('foo', settings.name) + self.assertEqual('desc', settings.description) + self.assertEqual('spec_name', settings.qos_spec_name) + self.assertEqual(VolumeTypeEncryptionConfig(**encryption_settings), + settings.encryption) + self.assertFalse(settings.public) diff --git a/snaps/config/user.py b/snaps/config/user.py new file mode 100644 index 0000000..fcc8fac --- /dev/null +++ b/snaps/config/user.py @@ -0,0 +1,59 @@ +# 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. + + +class UserConfig(object): + """ + Class for holding user configurations + """ + def __init__(self, **kwargs): + + """ + Constructor + :param name: the user's name (required) + :param password: the user's password (required) + :param project_name: the user's primary project name (optional) + :param domain_name: the user's domain name (default='Default'). For v3 + APIs + :param email: the user's email address (optional) + :param enabled: denotes whether or not the user is enabled + (default True) + :param roles: dict where key is the role's name and value is the name + of the project to associate with the role (optional) + """ + + self.name = kwargs.get('name') + self.password = kwargs.get('password') + self.project_name = kwargs.get('project_name') + self.email = kwargs.get('email') + self.domain_name = kwargs.get('domain_name', 'Default') + self.enabled = kwargs.get('enabled', True) + self.roles = kwargs.get('roles', dict()) + + if not self.name or not self.password: + raise UserConfigException( + 'The attributes name and password are required for ' + 'UserConfig') + + if not isinstance(self.enabled, bool): + raise UserConfigException( + 'The attribute enabled must be of type boolean') + + +class UserConfigException(Exception): + """ + Raised when there is a problem with the values set in the UserConfig + class + """ diff --git a/snaps/config/volume.py b/snaps/config/volume.py new file mode 100644 index 0000000..20ca985 --- /dev/null +++ b/snaps/config/volume.py @@ -0,0 +1,55 @@ +# 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. + + +class VolumeConfig(object): + def __init__(self, **kwargs): + """ + Constructor + :param name: the volume's name (required) + :param description: the volume's name (optional) + :param size: the volume's size in GB (default 1) + :param image_name: when a glance image is used for the image source + (optional) + :param type_name: the associated volume's type name (optional) + :param availability_zone: the name of the compute server on which to + deploy the volume (optional) + :param multi_attach: when true, volume can be attached to more than one + server (default False) + """ + + self.name = kwargs.get('name') + self.description = kwargs.get('description') + self.size = int(kwargs.get('size', 1)) + self.image_name = kwargs.get('image_name') + self.type_name = kwargs.get('type_name') + self.availability_zone = kwargs.get('availability_zone') + + if kwargs.get('availability_zone'): + self.multi_attach = bool(kwargs.get('availability_zone')) + else: + self.multi_attach = False + + if not self.name: + raise VolumeConfigError("The attribute name is required") + + +class VolumeConfigError(Exception): + """ + Exception to be thrown when an volume settings are incorrect + """ + + def __init__(self, message): + Exception.__init__(self, message) diff --git a/snaps/config/volume_type.py b/snaps/config/volume_type.py new file mode 100644 index 0000000..35ca1d4 --- /dev/null +++ b/snaps/config/volume_type.py @@ -0,0 +1,146 @@ +# 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 neutronclient.common.utils import str2bool + + +class VolumeTypeConfig(object): + def __init__(self, **kwargs): + """ + Constructor + :param name: the volume's name (required) + :param description: the volume's name (optional) + :param encryption: VolumeTypeEncryptionConfig (optional) + :param qos_spec_name: name of the QoS Spec to associate (optional) + :param public: volume visibility where True denotes global + (default - False) + + TODO - Implement project_access parameter that will associate this + VolumeType to a list of project names + """ + + self.name = kwargs.get('name') + self.description = kwargs.get('description') + self.qos_spec_name = kwargs.get('qos_spec_name') + + if 'encryption' in kwargs: + if isinstance(kwargs['encryption'], dict): + self.encryption = VolumeTypeEncryptionConfig( + **kwargs['encryption']) + elif isinstance(kwargs['encryption'], + VolumeTypeEncryptionConfig): + self.encryption = kwargs['encryption'] + else: + self.encryption = None + + if 'public' in kwargs: + if isinstance(kwargs['public'], str): + self.public = str2bool(kwargs['public']) + else: + self.public = kwargs['public'] + else: + self.public = False + + if not self.name: + raise VolumeTypeConfigError("The attribute name is required") + + def __eq__(self, other): + return (self.name == other.name + and self.description == other.description + and self.qos_spec_name == other.qos_spec_name + and self.encryption == other.encryption + and self.public == other.public) + + +class ControlLocation(enum.Enum): + """ + QoS Specification consumer types + """ + front_end = 'front-end' + back_end = 'back-end' + + +class VolumeTypeEncryptionConfig(object): + def __init__(self, **kwargs): + """ + Constructor + :param name: the volume's name (required) + :param provider_class: the volume's provider class (e.g. LuksEncryptor) + :param control_location: the notional service where encryption is + performed (e.g., front-end=Nova). The default + value is 'front-end.' + :param cipher: the encryption algorithm/mode to use + (e.g., aes-xts-plain64). If the field is left empty, + the provider default will be used + :param key_size: the size of the encryption key, in bits + (e.g., 128, 256). If the field is left empty, the + provider default will be used + """ + + self.name = kwargs.get('name') + self.provider_class = kwargs.get('provider_class') + self.control_location = kwargs.get('control_location') + if kwargs.get('control_location'): + self.control_location = map_control_location( + kwargs['control_location']) + else: + self.control_location = None + + self.cipher = kwargs.get('cipher') + self.key_size = kwargs.get('key_size') + + if (not self.name or not self.provider_class + or not self.control_location): + raise VolumeTypeConfigError( + 'The attributes name, provider_class, and control_location ' + 'are required') + + def __eq__(self, other): + return (self.name == other.name + and self.provider_class == other.provider_class + and self.control_location == other.control_location + and self.cipher == other.cipher + and self.key_size == other.key_size) + + +def map_control_location(control_location): + """ + Takes a the protocol value maps it to the Consumer enum. When None return + None + :param control_location: the value to map to the Enum + :return: a ControlLocation enum object + :raise: Exception if control_location parameter is invalid + """ + if not control_location: + return None + elif isinstance(control_location, ControlLocation): + return control_location + else: + proto_str = str(control_location) + if proto_str == 'front-end': + return ControlLocation.front_end + elif proto_str == 'back-end': + return ControlLocation.back_end + else: + raise VolumeTypeConfigError('Invalid Consumer - ' + proto_str) + + +class VolumeTypeConfigError(Exception): + """ + Exception to be thrown when an volume settings are incorrect + """ + + def __init__(self, message): + Exception.__init__(self, message) diff --git a/snaps/openstack/create_flavor.py b/snaps/openstack/create_flavor.py index b428621..b866d43 100644 --- a/snaps/openstack/create_flavor.py +++ b/snaps/openstack/create_flavor.py @@ -16,6 +16,7 @@ import logging from novaclient.exceptions import NotFound +from snaps.config.flavor import FlavorConfig from snaps.openstack.openstack_creator import OpenStackComputeObject from snaps.openstack.utils import nova_utils @@ -36,7 +37,7 @@ class OpenStackFlavor(OpenStackComputeObject): """ Constructor :param os_creds: The OpenStack connection credentials - :param flavor_settings: The flavor settings + :param flavor_settings: a FlavorConfig instance :return: """ super(self.__class__, self).__init__(os_creds) @@ -96,94 +97,13 @@ class OpenStackFlavor(OpenStackComputeObject): return self.__flavor -class FlavorSettings: +class FlavorSettings(FlavorConfig): """ Configuration settings for OpenStack flavor creation """ def __init__(self, **kwargs): - """ - Constructor - :param name: the flavor's name (required) - :param flavor_id: the string ID (default 'auto') - :param ram: the required RAM in MB (required) - :param disk: the size of the root disk in GB (required) - :param vcpus: the number of virtual CPUs (required) - :param ephemeral: the size of the ephemeral disk in GB (default 0) - :param swap: the size of the dedicated swap disk in GB (default 0) - :param rxtx_factor: the receive/transmit factor to be set on ports if - backend supports QoS extension (default 1.0) - :param is_public: denotes whether or not the flavor is public - (default True) - :param metadata: freeform dict() for special metadata - """ - self.name = kwargs.get('name') - - if kwargs.get('flavor_id'): - self.flavor_id = kwargs['flavor_id'] - else: - self.flavor_id = 'auto' - - self.ram = kwargs.get('ram') - self.disk = kwargs.get('disk') - self.vcpus = kwargs.get('vcpus') - - if kwargs.get('ephemeral'): - self.ephemeral = kwargs['ephemeral'] - else: - self.ephemeral = 0 - - if kwargs.get('swap'): - self.swap = kwargs['swap'] - else: - self.swap = 0 - - if kwargs.get('rxtx_factor'): - self.rxtx_factor = kwargs['rxtx_factor'] - else: - self.rxtx_factor = 1.0 - - if kwargs.get('is_public') is not None: - self.is_public = kwargs['is_public'] - else: - self.is_public = True - - if kwargs.get('metadata'): - self.metadata = kwargs['metadata'] - else: - self.metadata = None - - if not self.name or not self.ram or not self.disk or not self.vcpus: - raise FlavorSettingsError( - 'The attributes name, ram, disk, and vcpus are required for' - 'FlavorSettings') - - if not isinstance(self.ram, int): - raise FlavorSettingsError('The ram attribute must be a integer') - - if not isinstance(self.disk, int): - raise FlavorSettingsError('The ram attribute must be a integer') - - if not isinstance(self.vcpus, int): - raise FlavorSettingsError('The vcpus attribute must be a integer') - - if self.ephemeral and not isinstance(self.ephemeral, int): - raise FlavorSettingsError( - 'The ephemeral attribute must be an integer') - - if self.swap and not isinstance(self.swap, int): - raise FlavorSettingsError('The swap attribute must be an integer') - - if self.rxtx_factor and not isinstance(self.rxtx_factor, (int, float)): - raise FlavorSettingsError( - 'The is_public attribute must be an integer or float') - - if self.is_public and not isinstance(self.is_public, bool): - raise FlavorSettingsError( - 'The is_public attribute must be a boolean') - - -class FlavorSettingsError(Exception): - """ - Exception to be thrown when an flavor settings are incorrect - """ + from warnings import warn + warn('Use snaps.config.flavor.FlavorConfig instead', + DeprecationWarning) + super(self.__class__, self).__init__(**kwargs) diff --git a/snaps/openstack/create_image.py b/snaps/openstack/create_image.py index c8782bf..2e7aa39 100644 --- a/snaps/openstack/create_image.py +++ b/snaps/openstack/create_image.py @@ -19,6 +19,7 @@ import time from snaps.openstack.openstack_creator import OpenStackCloudObject from snaps.openstack.utils import glance_utils +from snaps.config import image __author__ = 'spisarski' @@ -38,8 +39,7 @@ class OpenStackImage(OpenStackCloudObject): """ Constructor :param os_creds: The OpenStack connection credentials - :param image_settings: The image settings - :return: + :param image_settings: An snaps.config.image.ImageConfig object """ super(self.__class__, self).__init__(os_creds) @@ -132,10 +132,10 @@ class OpenStackImage(OpenStackCloudObject): Cleanse environment of all artifacts :return: void """ - for image in [self.__image, self.__kernel_image, self.__ramdisk_image]: - if image: + for img in [self.__image, self.__kernel_image, self.__ramdisk_image]: + if img: try: - glance_utils.delete_image(self.__glance, image) + glance_utils.delete_image(self.__glance, img) except HTTPNotFound: pass @@ -236,100 +236,14 @@ class OpenStackImage(OpenStackCloudObject): return status == expected_status_code -class ImageSettings: - def __init__(self, **kwargs): - """ - Constructor - :param name: the image's name (required) - :param image_user: the image's default sudo user (required) - :param format or img_format: the image format type (required) - :param url or download_url: the image download location (requires url - or img_file) - :param image_file: the image file location (requires url or img_file) - :param extra_properties: dict() object containing extra parameters to - pass when loading the image; - can be ids of kernel and initramfs images for - a 3-part image - :param nic_config_pb_loc: the file location to the Ansible Playbook - that can configure multiple NICs - :param kernel_image_settings: the settings for a kernel image - :param ramdisk_image_settings: the settings for a ramdisk image - :param exists: When True, an image with the given name must exist - :param public: When True, an image will be created with public - visibility - """ - - self.name = kwargs.get('name') - self.image_user = kwargs.get('image_user') - self.format = kwargs.get('format') - if not self.format: - self.format = kwargs.get('img_format') - - self.url = kwargs.get('url') - if not self.url: - self.url = kwargs.get('download_url') - if self.url == 'None': - self.url = None - - self.image_file = kwargs.get('image_file') - if self.image_file == 'None': - self.image_file = None - - self.extra_properties = kwargs.get('extra_properties') - self.nic_config_pb_loc = kwargs.get('nic_config_pb_loc') - - kernel_image_settings = kwargs.get('kernel_image_settings') - if kernel_image_settings: - if isinstance(kernel_image_settings, dict): - self.kernel_image_settings = ImageSettings( - **kernel_image_settings) - else: - self.kernel_image_settings = kernel_image_settings - else: - self.kernel_image_settings = None - - ramdisk_image_settings = kwargs.get('ramdisk_image_settings') - if ramdisk_image_settings: - if isinstance(ramdisk_image_settings, dict): - self.ramdisk_image_settings = ImageSettings( - **ramdisk_image_settings) - else: - self.ramdisk_image_settings = ramdisk_image_settings - else: - self.ramdisk_image_settings = None - - if 'exists' in kwargs and kwargs['exists'] is True: - self.exists = True - else: - self.exists = False - - if 'public' in kwargs and kwargs['public'] is True: - self.public = True - else: - self.public = False - - if not self.name: - raise ImageSettingsError("The attribute name is required") - - if not (self.url or self.image_file) and not self.exists: - raise ImageSettingsError( - 'URL or image file must be set or image must already exist') - - if not self.image_user: - raise ImageSettingsError('Image user is required') - - if not self.format and not self.exists: - raise ImageSettingsError( - 'Format is required when the image should not already exist') - - -class ImageSettingsError(Exception): +class ImageSettings(image.ImageConfig): """ - Exception to be thrown when an image settings are incorrect + Deprecated, use snaps.config.image.ImageSettings instead """ - - def __init__(self, message): - Exception.__init__(self, message) + def __init__(self, **kwargs): + from warnings import warn + warn('Use snaps.config.image.ImageConfig instead', DeprecationWarning) + super(ImageSettings, self).__init__(**kwargs) class ImageCreationError(Exception): 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_keypairs.py b/snaps/openstack/create_keypairs.py index 6c66134..a181a7b 100644 --- a/snaps/openstack/create_keypairs.py +++ b/snaps/openstack/create_keypairs.py @@ -15,10 +15,10 @@ import logging import os -from neutronclient.common.utils import str2bool from novaclient.exceptions import NotFound from snaps import file_utils +from snaps.config.keypair import KeypairConfig from snaps.openstack.openstack_creator import OpenStackComputeObject from snaps.openstack.utils import nova_utils @@ -36,7 +36,7 @@ class OpenStackKeypair(OpenStackComputeObject): """ Constructor - all parameters are required :param os_creds: The credentials to connect with OpenStack - :param keypair_settings: The settings used to create a keypair + :param keypair_settings: a KeypairConfig object """ super(self.__class__, self).__init__(os_creds) @@ -141,47 +141,13 @@ class OpenStackKeypair(OpenStackComputeObject): return self.__keypair -class KeypairSettings: +class KeypairSettings(KeypairConfig): """ Class representing a keypair configuration """ def __init__(self, **kwargs): - """ - Constructor - all parameters are optional - :param name: The keypair name. - :param public_filepath: The path to/from the filesystem where the - public key file is or will be stored - :param private_filepath: The path where the generated private key file - will be stored - :param key_size: The number of bytes for the key size when it needs to - be generated (Must be >=512 default 1024) - :param delete_on_clean: when True, the key files will be deleted when - OpenStackKeypair#clean() is called - :return: - """ - - self.name = kwargs.get('name') - self.public_filepath = kwargs.get('public_filepath') - self.private_filepath = kwargs.get('private_filepath') - self.key_size = int(kwargs.get('key_size', 1024)) - - if kwargs.get('delete_on_clean') is not None: - if isinstance(kwargs.get('delete_on_clean'), bool): - self.delete_on_clean = kwargs.get('delete_on_clean') - else: - self.delete_on_clean = str2bool(kwargs.get('delete_on_clean')) - else: - self.delete_on_clean = None - - if not self.name: - raise KeypairSettingsError('Name is a required attribute') - - if self.key_size < 512: - raise KeypairSettingsError('key_size must be >=512') - - -class KeypairSettingsError(Exception): - """ - Exception to be thrown when keypair settings are incorrect - """ + from warnings import warn + warn('Use snaps.config.keypair.KeypairConfig instead', + DeprecationWarning) + super(self.__class__, self).__init__(**kwargs) 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_project.py b/snaps/openstack/create_project.py index 7d405a8..0349890 100644 --- a/snaps/openstack/create_project.py +++ b/snaps/openstack/create_project.py @@ -16,6 +16,7 @@ import logging from keystoneclient.exceptions import NotFound, Conflict +from snaps.config.project import ProjectConfig from snaps.openstack.openstack_creator import OpenStackIdentityObject from snaps.openstack.utils import keystone_utils, neutron_utils, nova_utils @@ -169,44 +170,15 @@ class OpenStackProject(OpenStackIdentityObject): neutron_utils.update_quotas(neutron, self.__project.id, network_quotas) -class ProjectSettings: +class ProjectSettings(ProjectConfig): """ Class to hold the configuration settings required for creating OpenStack project objects + deprecated """ def __init__(self, **kwargs): - - """ - Constructor - :param name: the project's name (required) - :param domain or domain_name: the project's domain name - (default = 'Default'). - Field is used for v3 clients - :param description: the description (optional) - :param users: list of users to associate project to (optional) - :param enabled: denotes whether or not the project is enabled - (default True) - """ - - self.name = kwargs.get('name') - self.domain_name = kwargs.get( - 'domain', kwargs.get('domain', 'Default')) - - self.description = kwargs.get('description') - if kwargs.get('enabled') is not None: - self.enabled = kwargs['enabled'] - else: - self.enabled = True - - self.users = kwargs.get('users', list()) - - if not self.name: - raise ProjectSettingsError( - "The attribute name is required for ProjectSettings") - - -class ProjectSettingsError(Exception): - """ - Exception to be thrown when project settings attributes are incorrect - """ + from warnings import warn + warn('Use snaps.config.project.ProjectConfig instead', + DeprecationWarning) + super(self.__class__, self).__init__(**kwargs)
\ No newline at end of file diff --git a/snaps/openstack/create_qos.py b/snaps/openstack/create_qos.py index 96f8c9b..44e35a3 100644 --- a/snaps/openstack/create_qos.py +++ b/snaps/openstack/create_qos.py @@ -18,6 +18,7 @@ import logging import enum from cinderclient.exceptions import NotFound +from snaps.config.qos import QoSConfig from snaps.openstack.openstack_creator import OpenStackVolumeObject from snaps.openstack.utils import cinder_utils @@ -101,69 +102,25 @@ class OpenStackQoS(OpenStackVolumeObject): class Consumer(enum.Enum): """ QoS Specification consumer types + deprecated - use snaps.config.qos.Consumer """ front_end = 'front-end' back_end = 'back-end' both = 'both' -class QoSSettings: - def __init__(self, **kwargs): - """ - Constructor - :param name: the qos's name (required) - :param consumer: the qos's consumer type of the enum type Consumer - (required) - :param specs: dict of key/values - """ - - self.name = kwargs.get('name') - - if kwargs.get('consumer'): - self.consumer = map_consumer(kwargs['consumer']) - else: - self.consumer = None - - self.specs = kwargs.get('specs') - if not self.specs: - self.specs = dict() - - if not self.name or not self.consumer: - raise QoSSettingsError( - "The attributes name and consumer are required") - - -def map_consumer(consumer): - """ - Takes a the protocol value maps it to the Consumer enum. When None return - None - :param consumer: the value to map to the Enum - :return: the Protocol enum object - :raise: Exception if value is invalid - """ - if not consumer: - return None - elif isinstance(consumer, Consumer): - return consumer - else: - proto_str = str(consumer) - if proto_str == 'front-end': - return Consumer.front_end - elif proto_str == 'back-end': - return Consumer.back_end - elif proto_str == 'both': - return Consumer.both - else: - raise QoSSettingsError('Invalid Consumer - ' + proto_str) - - -class QoSSettingsError(Exception): +class QoSSettings(QoSConfig): """ - Exception to be thrown when an qos settings are incorrect + Class to hold the configuration settings required for creating OpenStack + QoS objects + deprecated """ - def __init__(self, message): - Exception.__init__(self, message) + def __init__(self, **kwargs): + from warnings import warn + warn('Use snaps.config.qos.QoSConfig instead', + DeprecationWarning) + super(self.__class__, self).__init__(**kwargs) class QoSCreationError(Exception): diff --git a/snaps/openstack/create_router.py b/snaps/openstack/create_router.py index 6da5f8e..bf68347 100644 --- a/snaps/openstack/create_router.py +++ b/snaps/openstack/create_router.py @@ -15,9 +15,10 @@ import logging from neutronclient.common.exceptions import NotFound -from snaps.openstack.create_network import PortSettings + +from snaps.config.router import RouterConfig from snaps.openstack.openstack_creator import OpenStackNetworkObject -from snaps.openstack.utils import neutron_utils, keystone_utils +from snaps.openstack.utils import neutron_utils __author__ = 'spisarski' @@ -34,7 +35,7 @@ class OpenStackRouter(OpenStackNetworkObject): Constructor - all parameters are required :param os_creds: The credentials to connect with OpenStack :param router_settings: The settings used to create a router object - (must be an instance of the RouterSettings + (must be an instance of the RouterConfig class) """ super(self.__class__, self).__init__(os_creds) @@ -192,98 +193,15 @@ class RouterCreationError(Exception): """ -class RouterSettings: +class RouterSettings(RouterConfig): """ - Class representing a router configuration + Class to hold the configuration settings required for creating OpenStack + router objects + deprecated """ def __init__(self, **kwargs): - """ - Constructor - all parameters are optional - :param name: The router name. - :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. - :param external_gateway: Name of the external network to which to route - :param admin_state_up: The administrative status of the router. - 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 - :return: - """ - self.name = kwargs.get('name') - self.project_name = kwargs.get('project_name') - self.external_gateway = kwargs.get('external_gateway') - - self.admin_state_up = kwargs.get('admin_state_up', True) - self.enable_snat = kwargs.get('enable_snat') - if kwargs.get('internal_subnets'): - self.internal_subnets = kwargs['internal_subnets'] - else: - self.internal_subnets = list() - - self.port_settings = list() - if kwargs.get('interfaces', kwargs.get('port_settings')): - interfaces = kwargs.get('interfaces', kwargs.get('port_settings')) - for interface in interfaces: - if isinstance(interface, PortSettings): - self.port_settings.append(interface) - else: - self.port_settings.append( - PortSettings(**interface['port'])) - - if not self.name: - raise RouterSettingsError('Name is required') - - 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 to retrieve external network - information if necessary - :param os_creds: The OpenStack credentials - :return: the dictionary object - """ - out = dict() - ext_gw = dict() - - 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 RouterSettingsError( - 'Could not find project ID for project named - ' + - self.project_name) - if self.admin_state_up is not None: - out['admin_state_up'] = self.admin_state_up - if self.external_gateway: - ext_net = neutron_utils.get_network( - neutron, network_name=self.external_gateway) - if ext_net: - ext_gw['network_id'] = ext_net.id - out['external_gateway_info'] = ext_gw - else: - raise RouterSettingsError( - 'Could not find the external network named - ' + - self.external_gateway) - - return {'router': out} - - -class RouterSettingsError(Exception): - """ - Exception to be thrown when router settings attributes are incorrect - """ + from warnings import warn + warn('Use snaps.config.router.RouterConfig instead', + DeprecationWarning) + super(self.__class__, self).__init__(**kwargs) diff --git a/snaps/openstack/create_stack.py b/snaps/openstack/create_stack.py index 6075e7f..1fcc5b4 100644 --- a/snaps/openstack/create_stack.py +++ b/snaps/openstack/create_stack.py @@ -18,6 +18,8 @@ import time from heatclient.exc import HTTPNotFound +import snaps +from snaps.config.stack import StackConfig from snaps.openstack.create_flavor import OpenStackFlavor from snaps.openstack.create_instance import OpenStackVmInstance from snaps.openstack.create_keypairs import OpenStackKeypair @@ -36,14 +38,6 @@ __author__ = 'spisarski' logger = logging.getLogger('create_stack') -STACK_DELETE_TIMEOUT = 1200 -STACK_COMPLETE_TIMEOUT = 1200 -POLL_INTERVAL = 3 -STATUS_CREATE_FAILED = 'CREATE_FAILED' -STATUS_CREATE_COMPLETE = 'CREATE_COMPLETE' -STATUS_DELETE_COMPLETE = 'DELETE_COMPLETE' -STATUS_DELETE_FAILED = 'DELETE_FAILED' - class OpenStackHeatStack(OpenStackCloudObject, object): """ @@ -56,11 +50,9 @@ class OpenStackHeatStack(OpenStackCloudObject, object): Constructor :param os_creds: The OpenStack connection credentials :param stack_settings: The stack settings - :param image_settings: A list of ImageSettings objects that were used - for spawning this stack - :param image_settings: A list of ImageSettings objects that were used + :param image_settings: A list of ImageConfig objects that were used for spawning this stack - :param keypair_settings: A list of KeypairSettings objects that were + :param keypair_settings: A list of KeypairConfig objects that were used for spawning this stack :return: """ @@ -185,7 +177,7 @@ class OpenStackHeatStack(OpenStackCloudObject, object): return heat_utils.get_stack_status(self.__heat_cli, self.__stack.id) def stack_complete(self, block=False, timeout=None, - poll_interval=POLL_INTERVAL): + poll_interval=snaps.config.stack.POLL_INTERVAL): """ Returns true when the stack status returns the value of expected_status_code @@ -197,11 +189,13 @@ class OpenStackHeatStack(OpenStackCloudObject, object): """ if not timeout: timeout = self.stack_settings.stack_create_timeout - return self._stack_status_check(STATUS_CREATE_COMPLETE, block, timeout, - poll_interval, STATUS_CREATE_FAILED) + return self._stack_status_check( + snaps.config.stack.STATUS_CREATE_COMPLETE, block, timeout, + poll_interval, snaps.config.stack.STATUS_CREATE_FAILED) - def stack_deleted(self, block=False, timeout=STACK_DELETE_TIMEOUT, - poll_interval=POLL_INTERVAL): + def stack_deleted(self, block=False, + timeout=snaps.config.stack.STACK_DELETE_TIMEOUT, + poll_interval=snaps.config.stack.POLL_INTERVAL): """ Returns true when the stack status returns the value of expected_status_code @@ -211,8 +205,9 @@ class OpenStackHeatStack(OpenStackCloudObject, object): :param poll_interval: The polling interval in seconds :return: T/F """ - return self._stack_status_check(STATUS_DELETE_COMPLETE, block, timeout, - poll_interval, STATUS_DELETE_FAILED) + return self._stack_status_check( + snaps.config.stack.STATUS_DELETE_COMPLETE, block, timeout, + poll_interval, snaps.config.stack.STATUS_DELETE_FAILED) def get_network_creators(self): """ @@ -228,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) @@ -299,9 +294,9 @@ class OpenStackHeatStack(OpenStackCloudObject, object): for stack_server in stack_servers: vm_inst_settings = settings_utils.create_vm_inst_settings( nova, neutron, stack_server) - image_settings = settings_utils.determine_image_settings( + image_settings = settings_utils.determine_image_config( glance, stack_server, self.image_settings) - keypair_settings = settings_utils.determine_keypair_settings( + keypair_settings = settings_utils.determine_keypair_config( self.__heat_cli, self.__stack, stack_server, keypair_settings=self.keypair_settings, priv_key_key=heat_keypair_option) @@ -327,7 +322,7 @@ class OpenStackHeatStack(OpenStackCloudObject, object): self.__heat_cli, cinder, self.__stack) for volume in volumes: - settings = settings_utils.create_volume_settings(volume) + settings = settings_utils.create_volume_config(volume) creator = OpenStackVolume(self._os_creds, settings) out.append(creator) @@ -353,7 +348,7 @@ class OpenStackHeatStack(OpenStackCloudObject, object): self.__heat_cli, cinder, self.__stack) for volume in vol_types: - settings = settings_utils.create_volume_type_settings(volume) + settings = settings_utils.create_volume_type_config(volume) creator = OpenStackVolumeType(self._os_creds, settings) out.append(creator) @@ -408,7 +403,7 @@ class OpenStackHeatStack(OpenStackCloudObject, object): self.__heat_cli, nova, self.__stack) for flavor in flavors: - settings = settings_utils.create_flavor_settings(flavor) + settings = settings_utils.create_flavor_config(flavor) creator = OpenStackFlavor(self._os_creds, settings) out.append(creator) @@ -457,7 +452,8 @@ class OpenStackHeatStack(OpenStackCloudObject, object): 'Timeout checking for stack status for ' + expected_status_code) return False - def _status(self, expected_status_code, fail_status=STATUS_CREATE_FAILED): + def _status(self, expected_status_code, + fail_status=snaps.config.stack.STATUS_CREATE_FAILED): """ Returns True when active else False :param expected_status_code: stack status evaluated with this string @@ -474,7 +470,8 @@ class OpenStackHeatStack(OpenStackCloudObject, object): resources = heat_utils.get_resources(self.__heat_cli, self.__stack) logger.error('Stack %s failed', self.__stack.name) for resource in resources: - if resource.status != STATUS_CREATE_COMPLETE: + if (resource.status != + snaps.config.stack.STATUS_CREATE_COMPLETE): logger.error( 'Resource: [%s] status: [%s] reason: [%s]', resource.name, resource.status, resource.status_reason) @@ -488,47 +485,19 @@ class OpenStackHeatStack(OpenStackCloudObject, object): return status == expected_status_code -class StackSettings: - def __init__(self, **kwargs): - """ - Constructor - :param name: the stack's name (required) - :param template: the heat template in dict() format (required if - template_path attribute is None) - :param template_path: the location of the heat template file (required - if template attribute is None) - :param env_values: dict() of strings for substitution of template - default values (optional) - """ - - self.name = kwargs.get('name') - self.template = kwargs.get('template') - self.template_path = kwargs.get('template_path') - self.env_values = kwargs.get('env_values') - if 'stack_create_timeout' in kwargs: - self.stack_create_timeout = kwargs['stack_create_timeout'] - else: - self.stack_create_timeout = STACK_COMPLETE_TIMEOUT - - if not self.name: - raise StackSettingsError('name is required') - - if not self.template and not self.template_path: - raise StackSettingsError('A Heat template is required') - - def __eq__(self, other): - return (self.name == other.name and - self.template == other.template and - self.template_path == other.template_path and - self.env_values == other.env_values and - self.stack_create_timeout == other.stack_create_timeout) - - -class StackSettingsError(Exception): +class StackSettings(StackConfig): """ - Exception to be thrown when an stack settings are incorrect + Class to hold the configuration settings required for creating OpenStack + stack objects + deprecated """ + def __init__(self, **kwargs): + from warnings import warn + warn('Use snaps.config.stack.StackConfig instead', + DeprecationWarning) + super(self.__class__, self).__init__(**kwargs) + class StackCreationError(Exception): """ diff --git a/snaps/openstack/create_user.py b/snaps/openstack/create_user.py index bbed133..5da3a5e 100644 --- a/snaps/openstack/create_user.py +++ b/snaps/openstack/create_user.py @@ -16,6 +16,7 @@ import logging from keystoneclient.exceptions import NotFound +from snaps.config.user import UserConfig from snaps.openstack.openstack_creator import OpenStackIdentityObject from snaps.openstack.os_credentials import OSCreds from snaps.openstack.utils import keystone_utils @@ -110,43 +111,15 @@ class OpenStackUser(OpenStackIdentityObject): cacert=self._os_creds.cacert) -class UserSettings: - def __init__(self, **kwargs): - - """ - Constructor - :param name: the user's name (required) - :param password: the user's password (required) - :param project_name: the user's primary project name (optional) - :param domain_name: the user's domain name (default='Default'). For v3 - APIs - :param email: the user's email address (optional) - :param enabled: denotes whether or not the user is enabled - (default True) - :param roles: dict where key is the role's name and value is the name - of the project to associate with the role (optional) - """ - - self.name = kwargs.get('name') - self.password = kwargs.get('password') - self.project_name = kwargs.get('project_name') - self.email = kwargs.get('email') - self.domain_name = kwargs.get('domain_name', 'Default') - self.enabled = kwargs.get('enabled', True) - self.roles = kwargs.get('roles', dict()) - - if not self.name or not self.password: - raise UserSettingsException( - 'The attributes name and password are required for ' - 'UserSettings') - - if not isinstance(self.enabled, bool): - raise UserSettingsException('The attribute enabled must be of type' - ' boolean') - - -class UserSettingsException(Exception): +class UserSettings(UserConfig): """ - Raised when there is a problem with the values set in the UserSettings - class + Class to hold the configuration settings required for creating OpenStack + user objects + deprecated """ + + def __init__(self, **kwargs): + from warnings import warn + warn('Use snaps.config.user.UserConfig instead', + DeprecationWarning) + super(self.__class__, self).__init__(**kwargs) diff --git a/snaps/openstack/create_volume.py b/snaps/openstack/create_volume.py index 65acee8..c134ca1 100644 --- a/snaps/openstack/create_volume.py +++ b/snaps/openstack/create_volume.py @@ -18,6 +18,7 @@ import time from cinderclient.exceptions import NotFound +from snaps.config.volume import VolumeConfig from snaps.openstack.openstack_creator import OpenStackVolumeObject from snaps.openstack.utils import cinder_utils @@ -228,45 +229,18 @@ class OpenStackVolume(OpenStackVolumeObject): return status == expected_status_code -class VolumeSettings: - def __init__(self, **kwargs): - """ - Constructor - :param name: the volume's name (required) - :param description: the volume's name (optional) - :param size: the volume's size in GB (default 1) - :param image_name: when a glance image is used for the image source - (optional) - :param type_name: the associated volume's type name (optional) - :param availability_zone: the name of the compute server on which to - deploy the volume (optional) - :param multi_attach: when true, volume can be attached to more than one - server (default False) - """ - - self.name = kwargs.get('name') - self.description = kwargs.get('description') - self.size = int(kwargs.get('size', 1)) - self.image_name = kwargs.get('image_name') - self.type_name = kwargs.get('type_name') - self.availability_zone = kwargs.get('availability_zone') - - if kwargs.get('availability_zone'): - self.multi_attach = bool(kwargs.get('availability_zone')) - else: - self.multi_attach = False - - if not self.name: - raise VolumeSettingsError("The attribute name is required") - - -class VolumeSettingsError(Exception): +class VolumeSettings(VolumeConfig): """ - Exception to be thrown when an volume settings are incorrect + Class to hold the configuration settings required for creating OpenStack + Volume Type Encryption objects + deprecated """ - def __init__(self, message): - Exception.__init__(self, message) + def __init__(self, **kwargs): + from warnings import warn + warn('Use snaps.config.volume.VolumeConfig instead', + DeprecationWarning) + super(self.__class__, self).__init__(**kwargs) class VolumeCreationError(Exception): diff --git a/snaps/openstack/create_volume_type.py b/snaps/openstack/create_volume_type.py index fe20c40..a7198d8 100644 --- a/snaps/openstack/create_volume_type.py +++ b/snaps/openstack/create_volume_type.py @@ -15,10 +15,10 @@ import logging -import enum from cinderclient.exceptions import NotFound -from neutronclient.common.utils import str2bool +from snaps.config.volume_type import ( + VolumeTypeConfig, VolumeTypeEncryptionConfig) from snaps.openstack.openstack_creator import OpenStackVolumeObject from snaps.openstack.utils import cinder_utils @@ -96,134 +96,32 @@ class OpenStackVolumeType(OpenStackVolumeObject): return self.__volume_type -class VolumeTypeSettings: - def __init__(self, **kwargs): - """ - Constructor - :param name: the volume's name (required) - :param description: the volume's name (optional) - :param encryption: VolumeTypeEncryptionSettings (optional) - :param qos_spec_name: name of the QoS Spec to associate (optional) - :param public: volume visibility where True denotes global - (default - False) - - TODO - Implement project_access parameter that will associate this - VolumeType to a list of project names - """ - - self.name = kwargs.get('name') - self.description = kwargs.get('description') - self.qos_spec_name = kwargs.get('qos_spec_name') - - if 'encryption' in kwargs: - if isinstance(kwargs['encryption'], dict): - self.encryption = VolumeTypeEncryptionSettings( - **kwargs['encryption']) - elif isinstance(kwargs['encryption'], - VolumeTypeEncryptionSettings): - self.encryption = kwargs['encryption'] - else: - self.encryption = None - - if 'public' in kwargs: - if isinstance(kwargs['public'], str): - self.public = str2bool(kwargs['public']) - else: - self.public = kwargs['public'] - else: - self.public = False - - if not self.name: - raise VolumeTypeSettingsError("The attribute name is required") - - def __eq__(self, other): - return (self.name == other.name - and self.description == other.description - and self.qos_spec_name == other.qos_spec_name - and self.encryption == other.encryption - and self.public == other.public) - - -class ControlLocation(enum.Enum): +class VolumeTypeSettings(VolumeTypeConfig): """ - QoS Specification consumer types + Class to hold the configuration settings required for creating OpenStack + Volume Type objects + deprecated """ - front_end = 'front-end' - back_end = 'back-end' - -class VolumeTypeEncryptionSettings: def __init__(self, **kwargs): - """ - Constructor - :param name: the volume's name (required) - :param provider_class: the volume's provider class (e.g. LuksEncryptor) - :param control_location: the notional service where encryption is - performed (e.g., front-end=Nova). The default - value is 'front-end.' - :param cipher: the encryption algorithm/mode to use - (e.g., aes-xts-plain64). If the field is left empty, - the provider default will be used - :param key_size: the size of the encryption key, in bits - (e.g., 128, 256). If the field is left empty, the - provider default will be used - """ + from warnings import warn + warn('Use snaps.config.volume_type.VolumeTypeConfig instead', + DeprecationWarning) + super(self.__class__, self).__init__(**kwargs) - self.name = kwargs.get('name') - self.provider_class = kwargs.get('provider_class') - self.control_location = kwargs.get('control_location') - if kwargs.get('control_location'): - self.control_location = map_control_location( - kwargs['control_location']) - else: - self.control_location = None - - self.cipher = kwargs.get('cipher') - self.key_size = kwargs.get('key_size') - - if (not self.name or not self.provider_class - or not self.control_location): - raise VolumeTypeSettingsError( - 'The attributes name, provider_class, and control_location ' - 'are required') - - def __eq__(self, other): - return (self.name == other.name - and self.provider_class == other.provider_class - and self.control_location == other.control_location - and self.cipher == other.cipher - and self.key_size == other.key_size) - - -def map_control_location(control_location): - """ - Takes a the protocol value maps it to the Consumer enum. When None return - None - :param control_location: the value to map to the Enum - :return: a ControlLocation enum object - :raise: Exception if control_location parameter is invalid - """ - if not control_location: - return None - elif isinstance(control_location, ControlLocation): - return control_location - else: - proto_str = str(control_location) - if proto_str == 'front-end': - return ControlLocation.front_end - elif proto_str == 'back-end': - return ControlLocation.back_end - else: - raise VolumeTypeSettingsError('Invalid Consumer - ' + proto_str) - - -class VolumeTypeSettingsError(Exception): + +class VolumeTypeEncryptionSettings(VolumeTypeEncryptionConfig): """ - Exception to be thrown when an volume settings are incorrect + Class to hold the configuration settings required for creating OpenStack + Volume Type Encryption objects + deprecated """ - def __init__(self, message): - Exception.__init__(self, message) + def __init__(self, **kwargs): + from warnings import warn + warn('Use snaps.config.volume_type.VolumeTypeEncryptionConfig instead', + DeprecationWarning) + super(self.__class__, self).__init__(**kwargs) class VolumeTypeCreationError(Exception): diff --git a/snaps/openstack/tests/create_flavor_tests.py b/snaps/openstack/tests/create_flavor_tests.py index 3eb07bd..f84355d 100644 --- a/snaps/openstack/tests/create_flavor_tests.py +++ b/snaps/openstack/tests/create_flavor_tests.py @@ -15,9 +15,9 @@ import unittest import uuid +from snaps.config.flavor import FlavorConfig, FlavorConfigError from snaps.openstack import create_flavor -from snaps.openstack.create_flavor import FlavorSettings, OpenStackFlavor, \ - FlavorSettingsError +from snaps.openstack.create_flavor import OpenStackFlavor, FlavorSettings from snaps.openstack.tests.os_source_file_test import OSComponentTestCase from snaps.openstack.utils import nova_utils @@ -30,169 +30,169 @@ class FlavorSettingsUnitTests(unittest.TestCase): """ def test_no_params(self): - with self.assertRaises(FlavorSettingsError): + with self.assertRaises(FlavorConfigError): FlavorSettings() def test_empty_config(self): - with self.assertRaises(FlavorSettingsError): + with self.assertRaises(FlavorConfigError): FlavorSettings(config=dict()) def test_name_only(self): - with self.assertRaises(FlavorSettingsError): + with self.assertRaises(FlavorConfigError): FlavorSettings(name='foo') def test_config_with_name_only(self): - with self.assertRaises(FlavorSettingsError): + with self.assertRaises(FlavorConfigError): FlavorSettings(config={'name': 'foo'}) def test_name_ram_only(self): - with self.assertRaises(FlavorSettingsError): + with self.assertRaises(FlavorConfigError): FlavorSettings(name='foo', ram=1) def test_config_with_name_ram_only(self): - with self.assertRaises(FlavorSettingsError): + with self.assertRaises(FlavorConfigError): FlavorSettings(config={'name': 'foo', 'ram': 1}) def test_name_ram_disk_only(self): - with self.assertRaises(FlavorSettingsError): + with self.assertRaises(FlavorConfigError): FlavorSettings(name='foo', ram=1, disk=1) def test_config_with_name_ram_disk_only(self): - with self.assertRaises(FlavorSettingsError): + with self.assertRaises(FlavorConfigError): FlavorSettings(config={'name': 'foo', 'ram': 1, 'disk': 1}) def test_ram_string(self): - with self.assertRaises(FlavorSettingsError): + with self.assertRaises(FlavorConfigError): FlavorSettings(name='foo', ram='bar', disk=2, vcpus=3, ephemeral=4, swap=5, rxtx_factor=6.0, is_public=False) def test_config_ram_string(self): - with self.assertRaises(FlavorSettingsError): + with self.assertRaises(FlavorConfigError): FlavorSettings( config={'name': 'foo', 'ram': 'bar', 'disk': 2, 'vcpus': 3, 'ephemeral': 4, 'swap': 5, 'rxtx_factor': 6.0, 'is_public': False}) def test_ram_float(self): - with self.assertRaises(FlavorSettingsError): + with self.assertRaises(FlavorConfigError): FlavorSettings(name='foo', ram=1.5, disk=2, vcpus=3, ephemeral=4, swap=5, rxtx_factor=6.0, is_public=False) def test_config_ram_float(self): - with self.assertRaises(FlavorSettingsError): + with self.assertRaises(FlavorConfigError): FlavorSettings( config={'name': 'foo', 'ram': 1.5, 'disk': 2, 'vcpus': 3, 'ephemeral': 4, 'swap': 5, 'rxtx_factor': 6.0, 'is_public': False}) def test_disk_string(self): - with self.assertRaises(FlavorSettingsError): + with self.assertRaises(FlavorConfigError): FlavorSettings(name='foo', ram=1, disk='bar', vcpus=3, ephemeral=4, swap=5, rxtx_factor=6.0, is_public=False) def test_config_disk_string(self): - with self.assertRaises(FlavorSettingsError): + with self.assertRaises(FlavorConfigError): FlavorSettings( config={'name': 'foo', 'ram': 1, 'disk': 'bar', 'vcpus': 3, 'ephemeral': 4, 'swap': 5, 'rxtx_factor': 6.0, 'is_public': False}) def test_disk_float(self): - with self.assertRaises(FlavorSettingsError): + with self.assertRaises(FlavorConfigError): FlavorSettings(name='foo', ram=1, disk=2.5, vcpus=3, ephemeral=4, swap=5, rxtx_factor=6.0, is_public=False) def test_config_disk_float(self): - with self.assertRaises(FlavorSettingsError): + with self.assertRaises(FlavorConfigError): FlavorSettings( config={'name': 'foo', 'ram': 1, 'disk': 2.5, 'vcpus': 3, 'ephemeral': 4, 'swap': 5, 'rxtx_factor': 6.0, 'is_public': False}) def test_vcpus_string(self): - with self.assertRaises(FlavorSettingsError): + with self.assertRaises(FlavorConfigError): FlavorSettings(name='foo', ram=1, disk=2, vcpus='bar', ephemeral=4, swap=5, rxtx_factor=6.0, is_public=False) def test_config_vcpus_string(self): - with self.assertRaises(FlavorSettingsError): + with self.assertRaises(FlavorConfigError): FlavorSettings( config={'name': 'foo', 'ram': 1, 'disk': 2, 'vcpus': 'bar', 'ephemeral': 4, 'swap': 5, 'rxtx_factor': 6.0, 'is_public': False}) def test_ephemeral_string(self): - with self.assertRaises(FlavorSettingsError): + with self.assertRaises(FlavorConfigError): FlavorSettings(name='foo', ram=1, disk=2, vcpus=3, ephemeral='bar', swap=5, rxtx_factor=6.0, is_public=False) def test_config_ephemeral_string(self): - with self.assertRaises(FlavorSettingsError): + with self.assertRaises(FlavorConfigError): FlavorSettings( config={'name': 'foo', 'ram': 1, 'disk': 2, 'vcpus': 3, 'ephemeral': 'bar', 'swap': 5, 'rxtx_factor': 6.0, 'is_public': False}) def test_ephemeral_float(self): - with self.assertRaises(FlavorSettingsError): + with self.assertRaises(FlavorConfigError): FlavorSettings(name='foo', ram=1, disk=2, vcpus=3, ephemeral=4.5, swap=5, rxtx_factor=6.0, is_public=False) def test_config_ephemeral_float(self): - with self.assertRaises(FlavorSettingsError): + with self.assertRaises(FlavorConfigError): FlavorSettings( config={'name': 'foo', 'ram': 1, 'disk': 2, 'vcpus': 3, 'ephemeral': 4.5, 'swap': 5, 'rxtx_factor': 6.0, 'is_public': False}) def test_swap_string(self): - with self.assertRaises(FlavorSettingsError): + with self.assertRaises(FlavorConfigError): FlavorSettings(name='foo', ram=1, disk=2, vcpus=3, ephemeral=4, swap='bar', rxtx_factor=6.0, is_public=False) def test_config_swap_string(self): - with self.assertRaises(FlavorSettingsError): + with self.assertRaises(FlavorConfigError): FlavorSettings( config={'name': 'foo', 'ram': 1, 'disk': 2, 'vcpus': 3, 'ephemeral': 4, 'swap': 'bar', 'rxtx_factor': 6.0, 'is_public': False}) def test_swap_float(self): - with self.assertRaises(FlavorSettingsError): + with self.assertRaises(FlavorConfigError): FlavorSettings(name='foo', ram=1, disk=2, vcpus=3, ephemeral=4, swap=5.5, rxtx_factor=6.0, is_public=False) def test_config_swap_float(self): - with self.assertRaises(FlavorSettingsError): + with self.assertRaises(FlavorConfigError): FlavorSettings( config={'name': 'foo', 'ram': 1, 'disk': 2, 'vcpus': 3, 'ephemeral': 4, 'swap': 5.5, 'rxtx_factor': 6.0, 'is_public': False}) def test_rxtx_string(self): - with self.assertRaises(FlavorSettingsError): + with self.assertRaises(FlavorConfigError): FlavorSettings(name='foo', ram=1, disk=2, vcpus=3, ephemeral=4, swap=5, rxtx_factor='bar', is_public=False) def test_config_rxtx_string(self): - with self.assertRaises(FlavorSettingsError): + with self.assertRaises(FlavorConfigError): FlavorSettings( config={'name': 'foo', 'ram': 1, 'disk': 2, 'vcpus': 3, 'ephemeral': 4, 'swap': 5, 'rxtx_factor': 'bar', 'is_public': False}) def test_is_pub_string(self): - with self.assertRaises(FlavorSettingsError): + with self.assertRaises(FlavorConfigError): FlavorSettings(name='foo', ram=1, disk=2, vcpus=3, ephemeral=4, swap=5, rxtx_factor=6.0, is_public='bar') def test_config_is_pub_string(self): - with self.assertRaises(FlavorSettingsError): + with self.assertRaises(FlavorConfigError): FlavorSettings( config={'name': 'foo', 'ram': 1, 'disk': 2, 'vcpus': 3, 'ephemeral': 4, 'swap': 5, @@ -291,8 +291,8 @@ class CreateFlavorTests(OSComponentTestCase): Tests the creation of an OpenStack flavor. """ # Create Flavor - flavor_settings = FlavorSettings(name=self.flavor_name, ram=1, disk=1, - vcpus=1) + flavor_settings = FlavorConfig( + name=self.flavor_name, ram=1, disk=1, vcpus=1) self.flavor_creator = OpenStackFlavor(self.os_creds, flavor_settings) flavor = self.flavor_creator.create() self.assertTrue(validate_flavor(self.nova, flavor_settings, flavor)) @@ -303,8 +303,8 @@ class CreateFlavorTests(OSComponentTestCase): to ensure it has not been done twice. """ # Create Flavor - flavor_settings = FlavorSettings(name=self.flavor_name, ram=1, disk=1, - vcpus=1) + flavor_settings = FlavorConfig( + name=self.flavor_name, ram=1, disk=1, vcpus=1) self.flavor_creator = OpenStackFlavor(self.os_creds, flavor_settings) flavor = self.flavor_creator.create() self.assertTrue(validate_flavor(self.nova, flavor_settings, flavor)) @@ -319,8 +319,8 @@ class CreateFlavorTests(OSComponentTestCase): Tests the creation and cleanup of an OpenStack flavor. """ # Create Flavor - flavor_settings = FlavorSettings(name=self.flavor_name, ram=1, disk=1, - vcpus=1) + flavor_settings = FlavorConfig( + name=self.flavor_name, ram=1, disk=1, vcpus=1) self.flavor_creator = OpenStackFlavor(self.os_creds, flavor_settings) flavor = self.flavor_creator.create() self.assertTrue(validate_flavor(self.nova, flavor_settings, flavor)) @@ -339,8 +339,8 @@ class CreateFlavorTests(OSComponentTestCase): raise any exceptions. """ # Create Flavor - flavor_settings = FlavorSettings(name=self.flavor_name, ram=1, disk=1, - vcpus=1) + flavor_settings = FlavorConfig( + name=self.flavor_name, ram=1, disk=1, vcpus=1) self.flavor_creator = OpenStackFlavor(self.os_creds, flavor_settings) flavor = self.flavor_creator.create() self.assertTrue(validate_flavor(self.nova, flavor_settings, flavor)) @@ -362,7 +362,7 @@ class CreateFlavorTests(OSComponentTestCase): raise any exceptions. """ # Create Flavor - flavor_settings = FlavorSettings( + flavor_settings = FlavorConfig( name=self.flavor_name, ram=1, disk=1, vcpus=1, ephemeral=2, swap=3, rxtx_factor=2.2, is_public=False, metadata=create_flavor.MEM_PAGE_SIZE_ANY) diff --git a/snaps/openstack/tests/create_image_tests.py b/snaps/openstack/tests/create_image_tests.py index f70a71c..9965f87 100644 --- a/snaps/openstack/tests/create_image_tests.py +++ b/snaps/openstack/tests/create_image_tests.py @@ -27,9 +27,10 @@ import uuid import os from snaps import file_utils +from snaps.config.image import ImageConfigError from snaps.openstack import create_image -from snaps.openstack.create_image import (ImageSettings, ImageCreationError, - ImageSettingsError) +from snaps.openstack.create_image import ImageSettings, ImageCreationError +from snaps.config.image import ImageConfig from snaps.openstack.tests import openstack_tests from snaps.openstack.tests.os_source_file_test import OSIntegrationTestCase from snaps.openstack.utils import glance_utils @@ -42,38 +43,40 @@ logger = logging.getLogger('create_image_tests') class ImageSettingsUnitTests(unittest.TestCase): """ Tests the construction of the ImageSettings class + To be removed once the deprecated class ImageSettings is finally removed + from the source tree """ def test_no_params(self): - with self.assertRaises(ImageSettingsError): + with self.assertRaises(ImageConfigError): ImageSettings() def test_empty_config(self): - with self.assertRaises(ImageSettingsError): + with self.assertRaises(ImageConfigError): ImageSettings(**dict()) def test_name_only(self): - with self.assertRaises(ImageSettingsError): + with self.assertRaises(ImageConfigError): ImageSettings(name='foo') def test_config_with_name_only(self): - with self.assertRaises(ImageSettingsError): + with self.assertRaises(ImageConfigError): ImageSettings(**{'name': 'foo'}) def test_name_user_only(self): - with self.assertRaises(ImageSettingsError): + with self.assertRaises(ImageConfigError): ImageSettings(name='foo', image_user='bar') def test_config_with_name_user_only(self): - with self.assertRaises(ImageSettingsError): + with self.assertRaises(ImageConfigError): ImageSettings(**{'name': 'foo', 'image_user': 'bar'}) def test_name_user_format_only(self): - with self.assertRaises(ImageSettingsError): + with self.assertRaises(ImageConfigError): ImageSettings(name='foo', image_user='bar', img_format='qcow2') def test_config_with_name_user_format_only(self): - with self.assertRaises(ImageSettingsError): + with self.assertRaises(ImageConfigError): ImageSettings( **{'name': 'foo', 'image_user': 'bar', 'format': 'qcow2'}) @@ -448,8 +451,8 @@ class CreateImageSuccessTests(OSIntegrationTestCase): self.assertEqual(image1.properties, retrieved_image.properties) # Should be retrieving the instance data - image_2_settings = ImageSettings(name=self.image_settings.name, - image_user='foo', exists=True) + image_2_settings = ImageConfig(name=self.image_settings.name, + image_user='foo', exists=True) os_image_2 = create_image.OpenStackImage(self.os_creds, image_2_settings) image2 = os_image_2.create() @@ -478,8 +481,8 @@ class CreateImageNegativeTests(OSIntegrationTestCase): Expect an ImageCreationError when the image name does not exist when a file or URL has not been configured """ - os_image_settings = ImageSettings(name='foo', image_user='bar', - exists=True) + os_image_settings = ImageConfig(name='foo', image_user='bar', + exists=True) self.image_creator = create_image.OpenStackImage(self.os_creds, os_image_settings) @@ -497,10 +500,11 @@ class CreateImageNegativeTests(OSIntegrationTestCase): name=self.image_name) self.image_creator = create_image.OpenStackImage( self.os_creds, - create_image.ImageSettings(name=os_image_settings.name, - image_user=os_image_settings.image_user, - img_format=os_image_settings.format, - url="http://foo.bar")) + ImageConfig( + name=os_image_settings.name, + image_user=os_image_settings.image_user, + img_format=os_image_settings.format, + url="http://foo.bar")) try: self.image_creator.create() @@ -519,10 +523,10 @@ class CreateImageNegativeTests(OSIntegrationTestCase): name=self.image_name) self.image_creator = create_image.OpenStackImage( self.os_creds, - create_image.ImageSettings(name=os_image_settings.name, - image_user=os_image_settings.image_user, - img_format='foo', - url=os_image_settings.url)) + ImageConfig( + name=os_image_settings.name, + image_user=os_image_settings.image_user, + img_format='foo', url=os_image_settings.url)) with self.assertRaises(Exception): self.image_creator.create() @@ -535,10 +539,10 @@ class CreateImageNegativeTests(OSIntegrationTestCase): name=self.image_name) self.image_creator = create_image.OpenStackImage( self.os_creds, - create_image.ImageSettings(name=os_image_settings.name, - image_user=os_image_settings.image_user, - img_format=os_image_settings.format, - image_file="/foo/bar.qcow")) + ImageConfig( + name=os_image_settings.name, + image_user=os_image_settings.image_user, + img_format=os_image_settings.format, image_file="/foo/bar.qcow")) with self.assertRaises(IOError): self.image_creator.create() diff --git a/snaps/openstack/tests/create_instance_tests.py b/snaps/openstack/tests/create_instance_tests.py index cd4e4da..f806100 100644 --- a/snaps/openstack/tests/create_instance_tests.py +++ b/snaps/openstack/tests/create_instance_tests.py @@ -24,20 +24,25 @@ from neutronclient.common.exceptions import InvalidIpForSubnetClient from novaclient.exceptions import BadRequest 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, SubnetConfig +from snaps.config.router import RouterConfig +from snaps.config.volume import VolumeConfig from snaps.openstack import create_network, create_router -from snaps.openstack.create_flavor import OpenStackFlavor, FlavorSettings -from snaps.openstack.create_image import OpenStackImage, ImageSettings +from snaps.openstack.create_flavor import OpenStackFlavor +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, KeypairSettings -from snaps.openstack.create_network import ( - OpenStackNetwork, PortSettings, NetworkSettings, SubnetSettings) -from snaps.openstack.create_router import OpenStackRouter, RouterSettings +from snaps.openstack.create_keypairs import OpenStackKeypair +from snaps.openstack.create_network import OpenStackNetwork +from snaps.openstack.create_router import OpenStackRouter from snaps.openstack.create_security_group import ( SecurityGroupSettings, OpenStackSecurityGroup, SecurityGroupRuleSettings, Direction, Protocol) -from snaps.openstack.create_volume import OpenStackVolume, VolumeSettings +from snaps.openstack.create_volume import OpenStackVolume from snaps.openstack.tests import openstack_tests, validation_utils from snaps.openstack.tests.os_source_file_test import ( OSIntegrationTestCase, OSComponentTestCase) @@ -80,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) @@ -98,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) @@ -116,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') @@ -148,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') @@ -298,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) @@ -321,8 +326,8 @@ class SimpleHealthCheck(OSIntegrationTestCase): # Create Flavor self.flavor_creator = OpenStackFlavor( self.admin_os_creds, - FlavorSettings(name=guid + '-flavor-name', ram=256, disk=10, - vcpus=1, metadata=self.flavor_metadata)) + FlavorConfig(name=guid + '-flavor-name', ram=256, disk=10, + vcpus=1, metadata=self.flavor_metadata)) self.flavor_creator.create() except Exception as e: self.tearDown() @@ -428,8 +433,8 @@ class CreateInstanceSimpleTests(OSIntegrationTestCase): # Create Flavor self.flavor_creator = OpenStackFlavor( self.admin_os_creds, - FlavorSettings(name=guid + '-flavor-name', ram=256, disk=10, - vcpus=2, metadata=self.flavor_metadata)) + FlavorConfig(name=guid + '-flavor-name', ram=256, disk=10, + vcpus=2, metadata=self.flavor_metadata)) self.flavor_creator.create() # Create Network @@ -437,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) @@ -566,12 +571,12 @@ class CreateInstanceSingleNetworkTests(OSIntegrationTestCase): # Create Flavor self.flavor_creator = OpenStackFlavor( self.admin_os_creds, - FlavorSettings(name=guid + '-flavor-name', ram=256, disk=10, - vcpus=2, metadata=self.flavor_metadata)) + FlavorConfig(name=guid + '-flavor-name', ram=256, disk=10, + vcpus=2, metadata=self.flavor_metadata)) self.flavor_creator.create() self.keypair_creator = OpenStackKeypair( - self.os_creds, KeypairSettings( + self.os_creds, KeypairConfig( name=self.keypair_name, public_filepath=self.keypair_pub_filepath, private_filepath=self.keypair_priv_filepath)) @@ -663,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=[ @@ -693,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) @@ -728,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) @@ -765,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) @@ -844,13 +849,13 @@ class CreateInstanceIPv6NetworkTests(OSIntegrationTestCase): self.flavor_creator = OpenStackFlavor( self.admin_os_creds, - FlavorSettings( + FlavorConfig( name=self.guid + '-flavor-name', ram=256, disk=10, vcpus=2, metadata=self.flavor_metadata)) self.flavor_creator.create() self.keypair_creator = OpenStackKeypair( - self.os_creds, KeypairSettings( + self.os_creds, KeypairConfig( name=self.keypair_name, public_filepath=self.keypair_pub_filepath, private_filepath=self.keypair_priv_filepath)) @@ -940,12 +945,12 @@ 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 = RouterSettings( + router_settings = RouterConfig( name=self.guid + '-router', external_gateway=self.ext_net_name, internal_subnets=[subnet_settings.name]) @@ -959,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( @@ -984,16 +989,16 @@ 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 = RouterSettings( + router_settings = RouterConfig( name=self.guid + '-router', external_gateway=self.ext_net_name, internal_subnets=[subnet4_settings.name]) @@ -1007,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( @@ -1074,8 +1079,8 @@ class CreateInstancePortManipulationTests(OSIntegrationTestCase): # Create Flavor self.flavor_creator = OpenStackFlavor( self.admin_os_creds, - FlavorSettings(name=guid + '-flavor-name', ram=256, disk=10, - vcpus=2, metadata=self.flavor_metadata)) + FlavorConfig(name=guid + '-flavor-name', ram=256, disk=10, + vcpus=2, metadata=self.flavor_metadata)) self.flavor_creator.create() except Exception as e: self.tearDown() @@ -1125,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}]) @@ -1152,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}]) @@ -1175,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) @@ -1199,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') @@ -1224,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, @@ -1255,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]) @@ -1287,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]) @@ -1313,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]) @@ -1367,8 +1372,8 @@ class CreateInstanceOnComputeHost(OSIntegrationTestCase): # Create Flavor self.flavor_creator = OpenStackFlavor( self.admin_os_creds, - FlavorSettings(name=guid + '-flavor-name', ram=512, disk=1, - vcpus=1, metadata=self.flavor_metadata)) + FlavorConfig(name=guid + '-flavor-name', ram=512, disk=1, + vcpus=1, metadata=self.flavor_metadata)) self.flavor_creator.create() # Create Image @@ -1430,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) @@ -1533,14 +1538,14 @@ class CreateInstancePubPrivNetTests(OSIntegrationTestCase): # Create Flavor self.flavor_creator = OpenStackFlavor( self.admin_os_creds, - FlavorSettings(name=self.guid + '-flavor-name', ram=512, - disk=10, vcpus=2, - metadata=self.flavor_metadata)) + FlavorConfig(name=self.guid + '-flavor-name', ram=512, + disk=10, vcpus=2, + metadata=self.flavor_metadata)) self.flavor_creator.create() # Create Keypair self.keypair_creator = OpenStackKeypair( - self.os_creds, KeypairSettings( + self.os_creds, KeypairConfig( name=self.keypair_name, public_filepath=self.keypair_pub_filepath, private_filepath=self.keypair_priv_filepath)) @@ -1642,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 @@ -1729,12 +1734,12 @@ class InstanceSecurityGroupTests(OSIntegrationTestCase): # Create Flavor self.flavor_creator = OpenStackFlavor( self.admin_os_creds, - FlavorSettings(name=self.guid + '-flavor-name', ram=256, - disk=10, vcpus=2, - metadata=self.flavor_metadata)) + FlavorConfig(name=self.guid + '-flavor-name', ram=256, + disk=10, vcpus=2, + 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: @@ -2063,8 +2068,8 @@ class CreateInstanceFromThreePartImage(OSIntegrationTestCase): # Create Flavor self.flavor_creator = OpenStackFlavor( self.admin_os_creds, - FlavorSettings(name=guid + '-flavor-name', ram=256, disk=10, - vcpus=2, metadata=self.flavor_metadata)) + FlavorConfig(name=guid + '-flavor-name', ram=256, disk=10, + vcpus=2, metadata=self.flavor_metadata)) self.flavor_creator.create() # Create Network @@ -2072,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: @@ -2167,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) @@ -2184,7 +2189,7 @@ class CreateInstanceMockOfflineTests(OSComponentTestCase): # Create Flavor self.flavor_creator = OpenStackFlavor( self.os_creds, - FlavorSettings( + FlavorConfig( name=self.guid + '-flavor-name', ram=256, disk=10, vcpus=1)) self.flavor_creator.create() @@ -2316,9 +2321,9 @@ class CreateInstanceMockOfflineTests(OSComponentTestCase): image_settings = self.image_creator.image_settings test_image_creator = OpenStackImage( self.os_creds, - ImageSettings(name=image_settings.name, - image_user=image_settings.image_user, - exists=True)) + ImageConfig( + name=image_settings.name, image_user=image_settings.image_user, + exists=True)) test_image_creator.create() self.assertEqual(self.image_creator.get_image().id, test_image_creator.get_image().id) @@ -2611,9 +2616,9 @@ class CreateInstanceMockOfflineTests(OSComponentTestCase): image_settings = self.image_creator.image_settings test_image_creator = OpenStackImage( self.os_creds, - ImageSettings(name=image_settings.name, - image_user=image_settings.image_user, - exists=True)) + ImageConfig( + name=image_settings.name, image_user=image_settings.image_user, + exists=True)) test_image_creator.create() self.assertEqual(self.image_creator.get_image().id, test_image_creator.get_image().id) @@ -2665,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)]) @@ -2698,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': @@ -2707,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': @@ -2717,8 +2722,8 @@ class CreateInstanceTwoNetTests(OSIntegrationTestCase): network_name=self.net_config_2.name, project_name=self.os_creds.project_name)] - router_settings = RouterSettings(name=self.guid + '-pub-router', - port_settings=port_settings) + router_settings = RouterConfig( + name=self.guid + '-pub-router', port_settings=port_settings) self.router_creator = create_router.OpenStackRouter( self.os_creds, router_settings) self.router_creator.create() @@ -2726,9 +2731,9 @@ class CreateInstanceTwoNetTests(OSIntegrationTestCase): # Create Flavor self.flavor_creator = OpenStackFlavor( self.admin_os_creds, - FlavorSettings(name=self.guid + '-flavor-name', ram=512, - disk=10, vcpus=2, - metadata=self.flavor_metadata)) + FlavorConfig(name=self.guid + '-flavor-name', ram=512, + disk=10, vcpus=2, + metadata=self.flavor_metadata)) self.flavor_creator.create() sec_grp_name = self.guid + '-sec-grp' @@ -2808,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 @@ -2818,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': @@ -2830,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': @@ -2882,9 +2887,9 @@ class CreateInstanceVolumeTests(OSIntegrationTestCase): net_name=guid + '-pub-net', subnet_name=guid + '-pub-subnet', router_name=guid + '-pub-router', external_net=self.ext_net_name) - self.volume_settings1 = VolumeSettings( + self.volume_settings1 = VolumeConfig( name=self.__class__.__name__ + '-' + str(guid) + '-1') - self.volume_settings2 = VolumeSettings( + self.volume_settings2 = VolumeConfig( name=self.__class__.__name__ + '-' + str(guid) + '-2') # Initialize for tearDown() @@ -2905,8 +2910,8 @@ class CreateInstanceVolumeTests(OSIntegrationTestCase): # Create Flavor self.flavor_creator = OpenStackFlavor( self.admin_os_creds, - FlavorSettings(name=guid + '-flavor-name', ram=256, disk=1, - vcpus=2, metadata=self.flavor_metadata)) + FlavorConfig(name=guid + '-flavor-name', ram=256, disk=1, + vcpus=2, metadata=self.flavor_metadata)) self.flavor_creator.create() # Create Network @@ -2914,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_keypairs_tests.py b/snaps/openstack/tests/create_keypairs_tests.py index d2de6fe..63e0bcc 100644 --- a/snaps/openstack/tests/create_keypairs_tests.py +++ b/snaps/openstack/tests/create_keypairs_tests.py @@ -18,8 +18,9 @@ import uuid import os from snaps import file_utils +from snaps.config.keypair import KeypairConfig, KeypairConfigError from snaps.openstack.create_keypairs import ( - KeypairSettings, OpenStackKeypair, KeypairSettingsError) + KeypairSettings, OpenStackKeypair) from snaps.openstack.tests.os_source_file_test import OSIntegrationTestCase from snaps.openstack.utils import nova_utils @@ -32,15 +33,15 @@ class KeypairSettingsUnitTests(unittest.TestCase): """ def test_no_params(self): - with self.assertRaises(KeypairSettingsError): + with self.assertRaises(KeypairConfigError): KeypairSettings() def test_empty_config(self): - with self.assertRaises(KeypairSettingsError): + with self.assertRaises(KeypairConfigError): KeypairSettings(**dict()) def test_small_key_size(self): - with self.assertRaises(KeypairSettingsError): + with self.assertRaises(KeypairConfigError): KeypairSettings(name='foo', key_size=511) def test_name_only(self): @@ -228,7 +229,7 @@ class CreateKeypairsTests(OSIntegrationTestCase): Tests the creation of a generated keypair without saving to file :return: """ - self.keypair_creator = OpenStackKeypair(self.os_creds, KeypairSettings( + self.keypair_creator = OpenStackKeypair(self.os_creds, KeypairConfig( name=self.keypair_name)) self.keypair_creator.create() @@ -241,7 +242,7 @@ class CreateKeypairsTests(OSIntegrationTestCase): Tests the creation of a generated keypair without saving to file :return: """ - self.keypair_creator = OpenStackKeypair(self.os_creds, KeypairSettings( + self.keypair_creator = OpenStackKeypair(self.os_creds, KeypairConfig( name=self.keypair_name, key_size=10000)) self.keypair_creator.create() @@ -255,7 +256,7 @@ class CreateKeypairsTests(OSIntegrationTestCase): clean() does not raise an Exception. """ # Create Image - self.keypair_creator = OpenStackKeypair(self.os_creds, KeypairSettings( + self.keypair_creator = OpenStackKeypair(self.os_creds, KeypairConfig( name=self.keypair_name)) created_keypair = self.keypair_creator.create() self.assertIsNotNone(created_keypair) @@ -277,8 +278,8 @@ class CreateKeypairsTests(OSIntegrationTestCase): :return: """ self.keypair_creator = OpenStackKeypair( - self.os_creds, KeypairSettings(name=self.keypair_name, - public_filepath=self.pub_file_path)) + self.os_creds, KeypairConfig( + name=self.keypair_name, public_filepath=self.pub_file_path)) self.keypair_creator.create() keypair = nova_utils.keypair_exists(self.nova, @@ -302,7 +303,7 @@ class CreateKeypairsTests(OSIntegrationTestCase): :return: """ self.keypair_creator = OpenStackKeypair( - self.os_creds, KeypairSettings( + self.os_creds, KeypairConfig( name=self.keypair_name, public_filepath=self.pub_file_path, private_filepath=self.priv_file_path)) self.keypair_creator.create() @@ -335,8 +336,8 @@ class CreateKeypairsTests(OSIntegrationTestCase): file_utils.save_keys_to_files(keys=keys, pub_file_path=self.pub_file_path) self.keypair_creator = OpenStackKeypair( - self.os_creds, KeypairSettings(name=self.keypair_name, - public_filepath=self.pub_file_path)) + self.os_creds, KeypairConfig( + name=self.keypair_name, public_filepath=self.pub_file_path)) self.keypair_creator.create() keypair = nova_utils.keypair_exists(self.nova, @@ -400,7 +401,7 @@ class CreateKeypairsCleanupTests(OSIntegrationTestCase): :return: """ self.keypair_creator = OpenStackKeypair( - self.os_creds, KeypairSettings( + self.os_creds, KeypairConfig( name=self.keypair_name, public_filepath=self.pub_file_path, private_filepath=self.priv_file_path)) self.keypair_creator.create() @@ -416,7 +417,7 @@ class CreateKeypairsCleanupTests(OSIntegrationTestCase): :return: """ self.keypair_creator = OpenStackKeypair( - self.os_creds, KeypairSettings( + self.os_creds, KeypairConfig( name=self.keypair_name, public_filepath=self.pub_file_path, private_filepath=self.priv_file_path, delete_on_clean=True)) self.keypair_creator.create() @@ -432,7 +433,7 @@ class CreateKeypairsCleanupTests(OSIntegrationTestCase): :return: """ self.keypair_creator = OpenStackKeypair( - self.os_creds, KeypairSettings( + self.os_creds, KeypairConfig( name=self.keypair_name, public_filepath=self.pub_file_path, private_filepath=self.priv_file_path, delete_on_clean=False)) self.keypair_creator.create() @@ -452,7 +453,7 @@ class CreateKeypairsCleanupTests(OSIntegrationTestCase): keys=keys, pub_file_path=self.pub_file_path, priv_file_path=self.priv_file_path) self.keypair_creator = OpenStackKeypair( - self.os_creds, KeypairSettings( + self.os_creds, KeypairConfig( name=self.keypair_name, public_filepath=self.pub_file_path, private_filepath=self.priv_file_path, delete_on_clean=False)) self.keypair_creator.create() @@ -472,7 +473,7 @@ class CreateKeypairsCleanupTests(OSIntegrationTestCase): keys=keys, pub_file_path=self.pub_file_path, priv_file_path=self.priv_file_path) self.keypair_creator = OpenStackKeypair( - self.os_creds, KeypairSettings( + self.os_creds, KeypairConfig( name=self.keypair_name, public_filepath=self.pub_file_path, private_filepath=self.priv_file_path, delete_on_clean=True)) self.keypair_creator.create() 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_project_tests.py b/snaps/openstack/tests/create_project_tests.py index aa9dcfb..d7d4dcf 100644 --- a/snaps/openstack/tests/create_project_tests.py +++ b/snaps/openstack/tests/create_project_tests.py @@ -17,13 +17,14 @@ import uuid from keystoneclient.exceptions import BadRequest +from snaps.config.user import UserConfig +from snaps.config.project import ProjectConfigError, ProjectConfig from snaps.domain.project import ComputeQuotas, NetworkQuotas from snaps.openstack.create_project import ( - OpenStackProject, ProjectSettings, ProjectSettingsError) + OpenStackProject, ProjectSettings) from snaps.openstack.create_security_group import OpenStackSecurityGroup from snaps.openstack.create_security_group import SecurityGroupSettings from snaps.openstack.create_user import OpenStackUser -from snaps.openstack.create_user import UserSettings from snaps.openstack.tests.os_source_file_test import OSComponentTestCase from snaps.openstack.utils import keystone_utils, nova_utils, neutron_utils @@ -36,11 +37,11 @@ class ProjectSettingsUnitTests(unittest.TestCase): """ def test_no_params(self): - with self.assertRaises(ProjectSettingsError): + with self.assertRaises(ProjectConfigError): ProjectSettings() def test_empty_config(self): - with self.assertRaises(ProjectSettingsError): + with self.assertRaises(ProjectConfigError): ProjectSettings(**dict()) def test_name_only(self): @@ -94,7 +95,7 @@ class CreateProjectSuccessTests(OSComponentTestCase): """ guid = str(uuid.uuid4())[:-19] guid = self.__class__.__name__ + '-' + guid - self.project_settings = ProjectSettings( + self.project_settings = ProjectConfig( name=guid + '-name', domain=self.os_creds.project_domain_name) @@ -236,7 +237,7 @@ class CreateProjectUserTests(OSComponentTestCase): """ guid = str(uuid.uuid4())[:-19] self.guid = self.__class__.__name__ + '-' + guid - self.project_settings = ProjectSettings( + self.project_settings = ProjectConfig( name=self.guid + '-name', domain=self.os_creds.project_domain_name) @@ -272,9 +273,10 @@ class CreateProjectUserTests(OSComponentTestCase): self.assertIsNotNone(created_project) user_creator = OpenStackUser( - self.os_creds, UserSettings( + self.os_creds, UserConfig( name=self.guid + '-user', - password=self.guid, roles={'admin': self.project_settings.name}, + password=self.guid, + roles={'admin': self.project_settings.name}, domain_name=self.os_creds.user_domain_name)) self.project_creator.assoc_user(user_creator.create()) self.user_creators.append(user_creator) @@ -282,8 +284,8 @@ class CreateProjectUserTests(OSComponentTestCase): sec_grp_os_creds = user_creator.get_os_creds( self.project_creator.get_project().name) sec_grp_creator = OpenStackSecurityGroup( - sec_grp_os_creds, SecurityGroupSettings(name=self.guid + '-name', - description='hello group')) + sec_grp_os_creds, SecurityGroupSettings( + name=self.guid + '-name', description='hello group')) sec_grp = sec_grp_creator.create() self.assertIsNotNone(sec_grp) self.sec_grp_creators.append(sec_grp_creator) @@ -302,7 +304,7 @@ class CreateProjectUserTests(OSComponentTestCase): self.assertIsNotNone(created_project) user_creator_1 = OpenStackUser( - self.os_creds, UserSettings( + self.os_creds, UserConfig( name=self.guid + '-user1', password=self.guid, roles={'admin': self.project_settings.name}, domain_name=self.os_creds.user_domain_name)) @@ -310,7 +312,7 @@ class CreateProjectUserTests(OSComponentTestCase): self.user_creators.append(user_creator_1) user_creator_2 = OpenStackUser( - self.os_creds, UserSettings( + self.os_creds, UserConfig( name=self.guid + '-user2', password=self.guid, roles={'admin': self.project_settings.name}, domain_name=self.os_creds.user_domain_name)) diff --git a/snaps/openstack/tests/create_qos_tests.py b/snaps/openstack/tests/create_qos_tests.py index 6c0a056..68737f8 100644 --- a/snaps/openstack/tests/create_qos_tests.py +++ b/snaps/openstack/tests/create_qos_tests.py @@ -12,6 +12,8 @@ # 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.config.qos import Consumer, QoSConfigError, QoSConfig +from snaps.openstack.create_qos import Consumer as Consumer_old try: from urllib.request import URLError @@ -23,8 +25,7 @@ import unittest import uuid from snaps.openstack import create_qos -from snaps.openstack.create_qos import (QoSSettings, QoSSettingsError, - Consumer) +from snaps.openstack.create_qos import QoSSettings from snaps.openstack.tests.os_source_file_test import OSIntegrationTestCase from snaps.openstack.utils import cinder_utils @@ -39,64 +40,64 @@ class QoSSettingsUnitTests(unittest.TestCase): """ def test_no_params(self): - with self.assertRaises(QoSSettingsError): + with self.assertRaises(QoSConfigError): QoSSettings() def test_empty_config(self): - with self.assertRaises(QoSSettingsError): + with self.assertRaises(QoSConfigError): QoSSettings(**dict()) def test_name_only(self): - with self.assertRaises(QoSSettingsError): + with self.assertRaises(QoSConfigError): QoSSettings(name='foo') def test_config_with_name_only(self): - with self.assertRaises(QoSSettingsError): + with self.assertRaises(QoSConfigError): QoSSettings(**{'name': 'foo'}) def test_invalid_consumer(self): - with self.assertRaises(QoSSettingsError): + with self.assertRaises(QoSConfigError): QoSSettings(name='foo', consumer='bar') def test_config_with_invalid_consumer(self): - with self.assertRaises(QoSSettingsError): + with self.assertRaises(QoSConfigError): QoSSettings(**{'name': 'foo', 'consumer': 'bar'}) def test_name_consumer(self): - settings = QoSSettings(name='foo', consumer=Consumer.front_end) + settings = QoSSettings(name='foo', consumer=Consumer_old.front_end) self.assertEqual('foo', settings.name) - self.assertEqual(Consumer.front_end, settings.consumer) + self.assertEqual(Consumer_old.front_end.value, settings.consumer.value) self.assertEqual(dict(), settings.specs) def test_name_consumer_front_end_strings(self): settings = QoSSettings(name='foo', consumer='front-end') self.assertEqual('foo', settings.name) - self.assertEqual(Consumer.front_end, settings.consumer) + self.assertEqual(Consumer_old.front_end.value, settings.consumer.value) self.assertEqual(dict(), settings.specs) def test_name_consumer_back_end_strings(self): settings = QoSSettings(name='foo', consumer='back-end') self.assertEqual('foo', settings.name) - self.assertEqual(Consumer.back_end, settings.consumer) + self.assertEqual(Consumer_old.back_end.value, settings.consumer.value) self.assertEqual(dict(), settings.specs) def test_name_consumer_both_strings(self): settings = QoSSettings(name='foo', consumer='both') self.assertEqual('foo', settings.name) - self.assertEqual(Consumer.both, settings.consumer) + self.assertEqual(Consumer_old.both.value, settings.consumer.value) self.assertEqual(dict(), settings.specs) def test_all(self): specs = {'spec1': 'val1', 'spec2': 'val2'} - settings = QoSSettings(name='foo', consumer=Consumer.both, + settings = QoSSettings(name='foo', consumer=Consumer_old.both, specs=specs) self.assertEqual('foo', settings.name) - self.assertEqual(Consumer.both, settings.consumer) + self.assertEqual(Consumer_old.both.value, settings.consumer.value) self.assertEqual(specs, settings.specs) def test_config_all(self): @@ -121,7 +122,7 @@ class CreateQoSTests(OSIntegrationTestCase): super(self.__class__, self).__start__() guid = uuid.uuid4() - self.qos_settings = QoSSettings( + self.qos_settings = QoSConfig( name=self.__class__.__name__ + '-' + str(guid), consumer=Consumer.both) diff --git a/snaps/openstack/tests/create_router_tests.py b/snaps/openstack/tests/create_router_tests.py index d0f0a9f..5c34037 100644 --- a/snaps/openstack/tests/create_router_tests.py +++ b/snaps/openstack/tests/create_router_tests.py @@ -15,13 +15,12 @@ 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, RouterSettingsError) +from snaps.openstack.create_router import RouterSettings from snaps.openstack.tests.os_source_file_test import OSIntegrationTestCase from snaps.openstack.utils import neutron_utils, settings_utils @@ -39,11 +38,11 @@ class RouterSettingsUnitTests(unittest.TestCase): """ def test_no_params(self): - with self.assertRaises(RouterSettingsError): + with self.assertRaises(RouterConfigError): RouterSettings() def test_empty_config(self): - with self.assertRaises(RouterSettingsError): + with self.assertRaises(RouterConfigError): RouterSettings(**dict()) def test_name_only(self): @@ -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): @@ -150,8 +149,8 @@ class CreateRouterSuccessTests(OSIntegrationTestCase): """ Test creation of a most basic router with minimal options. """ - router_settings = RouterSettings(name=self.guid + '-pub-router', - external_gateway=self.ext_net_name) + router_settings = RouterConfig( + name=self.guid + '-pub-router', external_gateway=self.ext_net_name) self.router_creator = create_router.OpenStackRouter(self.os_creds, router_settings) @@ -170,7 +169,7 @@ class CreateRouterSuccessTests(OSIntegrationTestCase): Test creation of a most basic router with the admin user pointing to the new project. """ - router_settings = RouterSettings( + router_settings = RouterConfig( name=self.guid + '-pub-router', external_gateway=self.ext_net_name, project_name=self.os_creds.project_name) @@ -191,7 +190,7 @@ class CreateRouterSuccessTests(OSIntegrationTestCase): Test creation of a most basic router with the new user pointing to the admin project. """ - router_settings = RouterSettings( + router_settings = RouterConfig( name=self.guid + '-pub-router', external_gateway=self.ext_net_name, project_name=self.admin_os_creds.project_name) @@ -212,7 +211,7 @@ class CreateRouterSuccessTests(OSIntegrationTestCase): Test that clean() will not raise an exception if the router is deleted by another process. """ - self.router_settings = RouterSettings( + self.router_settings = RouterConfig( name=self.guid + '-pub-router', external_gateway=self.ext_net_name) self.router_creator = create_router.OpenStackRouter( @@ -236,8 +235,8 @@ class CreateRouterSuccessTests(OSIntegrationTestCase): """ Test creation of a basic router with admin state down. """ - router_settings = RouterSettings(name=self.guid + '-pub-router', - admin_state_up=False) + router_settings = RouterConfig( + name=self.guid + '-pub-router', admin_state_up=False) self.router_creator = create_router.OpenStackRouter(self.os_creds, router_settings) @@ -255,7 +254,7 @@ class CreateRouterSuccessTests(OSIntegrationTestCase): """ Test creation of a basic router with admin state Up. """ - router_settings = RouterSettings( + router_settings = RouterConfig( name=self.guid + '-pub-router', admin_state_up=True) self.router_creator = create_router.OpenStackRouter( @@ -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, @@ -315,8 +314,8 @@ class CreateRouterSuccessTests(OSIntegrationTestCase): network_name=network_settings2.name, project_name=self.os_creds.project_name)] - router_settings = RouterSettings(name=self.guid + '-pub-router', - port_settings=port_settings) + router_settings = RouterConfig( + name=self.guid + '-pub-router', port_settings=port_settings) self.router_creator = create_router.OpenStackRouter(self.os_creds, router_settings) self.router_creator.create() @@ -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, @@ -359,7 +358,7 @@ class CreateRouterSuccessTests(OSIntegrationTestCase): network_name=network_settings.name, project_name=self.os_creds.project_name)] - router_settings = RouterSettings( + router_settings = RouterConfig( name=self.guid + '-pub-router', external_gateway=self.ext_net_name, port_settings=port_settings) self.router_creator = create_router.OpenStackRouter( @@ -375,11 +374,11 @@ class CreateRouterSuccessTests(OSIntegrationTestCase): def check_router_recreation(self, router, orig_settings): """ - Validates the derived RouterSettings with the original + Validates the derived RouterConfig with the original :param router: the Router domain object to test - :param orig_settings: the original RouterSettings object that was + :param orig_settings: the original RouterConfig object that was responsible for creating the router - :return: the derived RouterSettings object + :return: the derived RouterConfig object """ derived_settings = settings_utils.create_router_settings( self.neutron, router) @@ -437,8 +436,8 @@ class CreateRouterNegativeTests(OSIntegrationTestCase): """ Test creating a router without a name. """ - with self.assertRaises(RouterSettingsError): - router_settings = RouterSettings( + with self.assertRaises(RouterConfigError): + router_settings = RouterConfig( name=None, external_gateway=self.ext_net_name) self.router_creator = create_router.OpenStackRouter( self.os_creds, router_settings) @@ -448,9 +447,10 @@ class CreateRouterNegativeTests(OSIntegrationTestCase): """ Test creating a router without a valid network gateway name. """ - with self.assertRaises(RouterSettingsError): - router_settings = RouterSettings(name=self.guid + '-pub-router', - external_gateway="Invalid_name") + with self.assertRaises(RouterConfigError): + router_settings = RouterConfig( + name=self.guid + '-pub-router', + external_gateway="Invalid_name") self.router_creator = create_router.OpenStackRouter( self.os_creds, router_settings) self.router_creator.create() diff --git a/snaps/openstack/tests/create_stack_tests.py b/snaps/openstack/tests/create_stack_tests.py index 9a26918..1df22fa 100644 --- a/snaps/openstack/tests/create_stack_tests.py +++ b/snaps/openstack/tests/create_stack_tests.py @@ -17,9 +17,14 @@ import time import pkg_resources from heatclient.exc import HTTPBadRequest + +import snaps from snaps import file_utils -from snaps.openstack.create_flavor import OpenStackFlavor, FlavorSettings -from snaps.openstack.create_image import OpenStackImage, ImageSettings +from snaps.config.flavor import FlavorConfig +from snaps.config.image import ImageConfig +from snaps.config.stack import StackConfigError, StackConfig +from snaps.openstack.create_flavor import OpenStackFlavor +from snaps.openstack.create_image import OpenStackImage try: from urllib.request import URLError @@ -30,9 +35,8 @@ import logging import unittest import uuid -from snaps.openstack import create_stack from snaps.openstack.create_stack import ( - StackSettings, StackSettingsError, StackCreationError, StackError) + StackSettings, StackCreationError, StackError, OpenStackHeatStack) from snaps.openstack.tests import openstack_tests, create_instance_tests from snaps.openstack.tests.os_source_file_test import OSIntegrationTestCase from snaps.openstack.utils import heat_utils, neutron_utils, nova_utils @@ -48,19 +52,19 @@ class StackSettingsUnitTests(unittest.TestCase): """ def test_no_params(self): - with self.assertRaises(StackSettingsError): + with self.assertRaises(StackConfigError): StackSettings() def test_empty_config(self): - with self.assertRaises(StackSettingsError): + with self.assertRaises(StackConfigError): StackSettings(**dict()) def test_name_only(self): - with self.assertRaises(StackSettingsError): + with self.assertRaises(StackConfigError): StackSettings(name='foo') def test_config_with_name_only(self): - with self.assertRaises(StackSettingsError): + with self.assertRaises(StackConfigError): StackSettings(**{'name': 'foo'}) def test_config_minimum_template(self): @@ -69,7 +73,7 @@ class StackSettingsUnitTests(unittest.TestCase): self.assertEqual('foo', settings.template) self.assertIsNone(settings.template_path) self.assertIsNone(settings.env_values) - self.assertEqual(create_stack.STACK_COMPLETE_TIMEOUT, + self.assertEqual(snaps.config.stack.STACK_COMPLETE_TIMEOUT, settings.stack_create_timeout) def test_config_minimum_template_path(self): @@ -78,7 +82,7 @@ class StackSettingsUnitTests(unittest.TestCase): self.assertIsNone(settings.template) self.assertEqual('foo', settings.template_path) self.assertIsNone(settings.env_values) - self.assertEqual(create_stack.STACK_COMPLETE_TIMEOUT, + self.assertEqual(snaps.config.stack.STACK_COMPLETE_TIMEOUT, settings.stack_create_timeout) def test_minimum_template(self): @@ -87,7 +91,7 @@ class StackSettingsUnitTests(unittest.TestCase): self.assertEqual('foo', settings.template) self.assertIsNone(settings.template_path) self.assertIsNone(settings.env_values) - self.assertEqual(create_stack.STACK_COMPLETE_TIMEOUT, + self.assertEqual(snaps.config.stack.STACK_COMPLETE_TIMEOUT, settings.stack_create_timeout) def test_minimum_template_path(self): @@ -96,7 +100,7 @@ class StackSettingsUnitTests(unittest.TestCase): self.assertEqual('foo', settings.template_path) self.assertIsNone(settings.template) self.assertIsNone(settings.env_values) - self.assertEqual(create_stack.STACK_COMPLETE_TIMEOUT, + self.assertEqual(snaps.config.stack.STACK_COMPLETE_TIMEOUT, settings.stack_create_timeout) def test_all(self): @@ -148,8 +152,8 @@ class CreateStackSuccessTests(OSIntegrationTestCase): # Create Flavor self.flavor_creator = OpenStackFlavor( self.admin_os_creds, - FlavorSettings(name=self.guid + '-flavor-name', ram=256, disk=10, - vcpus=1)) + FlavorConfig( + name=self.guid + '-flavor-name', ram=256, disk=10, vcpus=1)) self.flavor_creator.create() self.network_name = self.guid + '-net' @@ -197,12 +201,12 @@ class CreateStackSuccessTests(OSIntegrationTestCase): # Create Stack # Set the default stack settings, then set any custom parameters sent # from the app - stack_settings = StackSettings( + stack_settings = StackConfig( name=self.__class__.__name__ + '-' + str(self.guid) + '-stack', template_path=self.heat_tmplt_path, env_values=self.env_values) - self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds, - stack_settings) + self.stack_creator = OpenStackHeatStack( + self.heat_creds, stack_settings) created_stack = self.stack_creator.create() self.assertIsNotNone(created_stack) @@ -220,13 +224,13 @@ class CreateStackSuccessTests(OSIntegrationTestCase): # Create Stack # Set the default stack settings, then set any custom parameters sent # from the app - stack_settings = StackSettings( + stack_settings = StackConfig( name=self.__class__.__name__ + '-' + str(self.guid) + '-stack', template_path=self.heat_tmplt_path, env_values=self.env_values, stack_create_timeout=0) - self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds, - stack_settings) + self.stack_creator = OpenStackHeatStack( + self.heat_creds, stack_settings) with self.assertRaises(StackCreationError): self.stack_creator.create() @@ -239,12 +243,12 @@ class CreateStackSuccessTests(OSIntegrationTestCase): # from the app template_dict = heat_utils.parse_heat_template_str( file_utils.read_file(self.heat_tmplt_path)) - stack_settings = StackSettings( + stack_settings = StackConfig( name=self.__class__.__name__ + '-' + str(self.guid) + '-stack', template=template_dict, env_values=self.env_values) - self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds, - stack_settings) + self.stack_creator = OpenStackHeatStack( + self.heat_creds, stack_settings) created_stack = self.stack_creator.create() self.assertIsNotNone(created_stack) @@ -263,12 +267,12 @@ class CreateStackSuccessTests(OSIntegrationTestCase): # Create Stack template_dict = heat_utils.parse_heat_template_str( file_utils.read_file(self.heat_tmplt_path)) - stack_settings = StackSettings( + stack_settings = StackConfig( name=self.__class__.__name__ + '-' + str(self.guid) + '-stack', template=template_dict, env_values=self.env_values) - self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds, - stack_settings) + self.stack_creator = OpenStackHeatStack( + self.heat_creds, stack_settings) created_stack = self.stack_creator.create() self.assertIsNotNone(created_stack) @@ -278,7 +282,7 @@ class CreateStackSuccessTests(OSIntegrationTestCase): self.assertEqual(created_stack.name, retrieved_stack.name) self.assertEqual(created_stack.id, retrieved_stack.id) self.assertEqual(0, len(self.stack_creator.get_outputs())) - self.assertEqual(create_stack.STATUS_CREATE_COMPLETE, + self.assertEqual(snaps.config.stack.STATUS_CREATE_COMPLETE, self.stack_creator.get_status()) # Delete Stack manually @@ -289,7 +293,7 @@ class CreateStackSuccessTests(OSIntegrationTestCase): while time.time() < end_time: status = heat_utils.get_stack_status(self.heat_cli, retrieved_stack.id) - if status == create_stack.STATUS_DELETE_COMPLETE: + if status == snaps.config.stack.STATUS_DELETE_COMPLETE: deleted = True break @@ -307,12 +311,12 @@ class CreateStackSuccessTests(OSIntegrationTestCase): # Create Stack template_dict = heat_utils.parse_heat_template_str( file_utils.read_file(self.heat_tmplt_path)) - stack_settings = StackSettings( + stack_settings = StackConfig( name=self.__class__.__name__ + '-' + str(self.guid) + '-stack', template=template_dict, env_values=self.env_values) - self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds, - stack_settings) + self.stack_creator = OpenStackHeatStack( + self.heat_creds, stack_settings) created_stack1 = self.stack_creator.create() retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli, @@ -323,8 +327,7 @@ class CreateStackSuccessTests(OSIntegrationTestCase): self.assertEqual(0, len(self.stack_creator.get_outputs())) # Should be retrieving the instance data - stack_creator2 = create_stack.OpenStackHeatStack(self.heat_creds, - stack_settings) + stack_creator2 = OpenStackHeatStack(self.heat_creds, stack_settings) stack2 = stack_creator2.create() self.assertEqual(created_stack1.id, stack2.id) @@ -333,12 +336,12 @@ class CreateStackSuccessTests(OSIntegrationTestCase): Tests the creation of an OpenStack stack from Heat template file and the retrieval of the network creator. """ - stack_settings = StackSettings( + stack_settings = StackConfig( name=self.__class__.__name__ + '-' + str(self.guid) + '-stack', template_path=self.heat_tmplt_path, env_values=self.env_values) - self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds, - stack_settings) + self.stack_creator = OpenStackHeatStack( + self.heat_creds, stack_settings) created_stack = self.stack_creator.create() self.assertIsNotNone(created_stack) @@ -369,12 +372,12 @@ class CreateStackSuccessTests(OSIntegrationTestCase): Tests the creation of an OpenStack stack from Heat template file and the retrieval of the network creator. """ - stack_settings = StackSettings( + stack_settings = StackConfig( name=self.__class__.__name__ + '-' + str(self.guid) + '-stack', template_path=self.heat_tmplt_path, env_values=self.env_values) - self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds, - stack_settings) + self.stack_creator = OpenStackHeatStack( + self.heat_creds, stack_settings) created_stack = self.stack_creator.create() self.assertIsNotNone(created_stack) @@ -478,11 +481,11 @@ class CreateStackFloatingIpTests(OSIntegrationTestCase): the retrieval of two VM instance creators and attempt to connect via SSH to the first one with a floating IP. """ - stack_settings = StackSettings( + stack_settings = StackConfig( name=self.__class__.__name__ + '-' + str(self.guid) + '-stack', template_path=self.heat_tmplt_path, env_values=self.env_values) - self.stack_creator = create_stack.OpenStackHeatStack( + self.stack_creator = OpenStackHeatStack( self.heat_creds, stack_settings, [self.image_creator.image_settings]) created_stack = self.stack_creator.create() @@ -537,11 +540,11 @@ class CreateStackRouterTests(OSIntegrationTestCase): self.heat_tmplt_path = pkg_resources.resource_filename( 'snaps.openstack.tests.heat', 'router_heat_template.yaml') - stack_settings = StackSettings( + stack_settings = StackConfig( name=self.__class__.__name__ + '-' + str(self.guid) + '-stack', template_path=self.heat_tmplt_path, env_values=self.env_values) - self.stack_creator = create_stack.OpenStackHeatStack( + self.stack_creator = OpenStackHeatStack( self.heat_creds, stack_settings) self.created_stack = self.stack_creator.create() self.assertIsNotNone(self.created_stack) @@ -604,11 +607,11 @@ class CreateStackVolumeTests(OSIntegrationTestCase): self.heat_tmplt_path = pkg_resources.resource_filename( 'snaps.openstack.tests.heat', 'volume_heat_template.yaml') - stack_settings = StackSettings( + stack_settings = StackConfig( name=self.__class__.__name__ + '-' + str(self.guid) + '-stack', template_path=self.heat_tmplt_path, env_values=self.env_values) - self.stack_creator = create_stack.OpenStackHeatStack( + self.stack_creator = OpenStackHeatStack( self.heat_creds, stack_settings) self.created_stack = self.stack_creator.create() self.assertIsNotNone(self.created_stack) @@ -691,10 +694,10 @@ class CreateStackFlavorTests(OSIntegrationTestCase): self.heat_tmplt_path = pkg_resources.resource_filename( 'snaps.openstack.tests.heat', 'flavor_heat_template.yaml') - stack_settings = StackSettings( + stack_settings = StackConfig( name=self.guid + '-stack', template_path=self.heat_tmplt_path) - self.stack_creator = create_stack.OpenStackHeatStack( + self.stack_creator = OpenStackHeatStack( self.heat_creds, stack_settings) self.created_stack = self.stack_creator.create() self.assertIsNotNone(self.created_stack) @@ -757,11 +760,11 @@ class CreateStackKeypairTests(OSIntegrationTestCase): self.heat_tmplt_path = pkg_resources.resource_filename( 'snaps.openstack.tests.heat', 'keypair_heat_template.yaml') - stack_settings = StackSettings( + stack_settings = StackConfig( name=self.__class__.__name__ + '-' + str(self.guid) + '-stack', template_path=self.heat_tmplt_path, env_values=self.env_values) - self.stack_creator = create_stack.OpenStackHeatStack( + self.stack_creator = OpenStackHeatStack( self.heat_creds, stack_settings) self.created_stack = self.stack_creator.create() self.assertIsNotNone(self.created_stack) @@ -842,11 +845,11 @@ class CreateStackSecurityGroupTests(OSIntegrationTestCase): self.heat_tmplt_path = pkg_resources.resource_filename( 'snaps.openstack.tests.heat', 'security_group_heat_template.yaml') - stack_settings = StackSettings( + stack_settings = StackConfig( name=self.__class__.__name__ + '-' + str(self.guid) + '-stack', template_path=self.heat_tmplt_path, env_values=self.env_values) - self.stack_creator = create_stack.OpenStackHeatStack( + self.stack_creator = OpenStackHeatStack( self.heat_creds, stack_settings) self.created_stack = self.stack_creator.create() self.assertIsNotNone(self.created_stack) @@ -933,10 +936,10 @@ class CreateStackNegativeTests(OSIntegrationTestCase): """ Expect an StackCreationError when the stack file does not exist """ - stack_settings = StackSettings(name=self.stack_name, - template_path=self.heat_tmplt_path) - self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds, - stack_settings) + stack_settings = StackConfig(name=self.stack_name, + template_path=self.heat_tmplt_path) + self.stack_creator = OpenStackHeatStack( + self.heat_creds, stack_settings) with self.assertRaises(HTTPBadRequest): self.stack_creator.create() @@ -944,10 +947,10 @@ class CreateStackNegativeTests(OSIntegrationTestCase): """ Expect an StackCreationError when the stack file does not exist """ - stack_settings = StackSettings(name=self.stack_name, - template_path='foo') - self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds, - stack_settings) + stack_settings = StackConfig( + name=self.stack_name, template_path='foo') + self.stack_creator = OpenStackHeatStack( + self.heat_creds, stack_settings) with self.assertRaises(IOError): self.stack_creator.create() @@ -974,7 +977,7 @@ class CreateStackFailureTests(OSIntegrationTestCase): self.tmp_file = file_utils.save_string_to_file( ' ', str(uuid.uuid4()) + '-bad-image') self.image_creator = OpenStackImage( - self.heat_creds, ImageSettings( + self.heat_creds, ImageConfig( name=self.guid + 'image', image_file=self.tmp_file.name, image_user='foo', img_format='qcow2')) self.image_creator.create() @@ -982,8 +985,9 @@ class CreateStackFailureTests(OSIntegrationTestCase): # Create Flavor self.flavor_creator = OpenStackFlavor( self.admin_os_creds, - FlavorSettings(name=self.guid + '-flavor-name', ram=256, disk=10, - vcpus=1000000)) + FlavorConfig( + name=self.guid + '-flavor-name', ram=256, disk=10, + vcpus=1000000)) self.flavor_creator.create() self.network_name = self.guid + '-net' @@ -1038,12 +1042,12 @@ class CreateStackFailureTests(OSIntegrationTestCase): # Create Stack # Set the default stack settings, then set any custom parameters sent # from the app - stack_settings = StackSettings( + stack_settings = StackConfig( name=self.__class__.__name__ + '-' + str(self.guid) + '-stack', template_path=self.heat_tmplt_path, env_values=self.env_values) - self.stack_creator = create_stack.OpenStackHeatStack(self.heat_creds, - stack_settings) + self.stack_creator = OpenStackHeatStack( + self.heat_creds, stack_settings) with self.assertRaises(StackError): try: @@ -1054,7 +1058,8 @@ class CreateStackFailureTests(OSIntegrationTestCase): found = False for resource in resources: - if resource.status == create_stack.STATUS_CREATE_COMPLETE: + if (resource.status == + snaps.config.stack.STATUS_CREATE_COMPLETE): found = True self.assertTrue(found) raise diff --git a/snaps/openstack/tests/create_user_tests.py b/snaps/openstack/tests/create_user_tests.py index ffae596..d3eb4a6 100644 --- a/snaps/openstack/tests/create_user_tests.py +++ b/snaps/openstack/tests/create_user_tests.py @@ -15,6 +15,7 @@ import unittest import uuid +from snaps.config.user import UserConfig from snaps.openstack.create_user import OpenStackUser, UserSettings from snaps.openstack.tests.os_source_file_test import OSComponentTestCase from snaps.openstack.utils import keystone_utils @@ -102,7 +103,7 @@ class CreateUserSuccessTests(OSComponentTestCase): """ guid = str(uuid.uuid4())[:-19] guid = self.__class__.__name__ + '-' + guid - self.user_settings = UserSettings( + self.user_settings = UserConfig( name=guid + '-name', password=guid + '-password', roles={'admin': self.os_creds.project_name}, diff --git a/snaps/openstack/tests/create_volume_tests.py b/snaps/openstack/tests/create_volume_tests.py index 9c3f90f..ca13860 100644 --- a/snaps/openstack/tests/create_volume_tests.py +++ b/snaps/openstack/tests/create_volume_tests.py @@ -14,9 +14,10 @@ # limitations under the License. from cinderclient.exceptions import NotFound, BadRequest +from snaps.config.volume import VolumeConfig, VolumeConfigError +from snaps.config.volume_type import VolumeTypeConfig from snaps.openstack.create_image import OpenStackImage -from snaps.openstack.create_volume_type import ( - VolumeTypeSettings, OpenStackVolumeType) +from snaps.openstack.create_volume_type import OpenStackVolumeType from snaps.openstack.tests import openstack_tests try: @@ -29,7 +30,7 @@ import unittest import uuid from snaps.openstack.create_volume import ( - VolumeSettings, VolumeSettingsError, OpenStackVolume) + VolumeSettings, OpenStackVolume) from snaps.openstack.tests.os_source_file_test import OSIntegrationTestCase from snaps.openstack.utils import cinder_utils @@ -44,11 +45,11 @@ class VolumeSettingsUnitTests(unittest.TestCase): """ def test_no_params(self): - with self.assertRaises(VolumeSettingsError): + with self.assertRaises(VolumeConfigError): VolumeSettings() def test_empty_config(self): - with self.assertRaises(VolumeSettingsError): + with self.assertRaises(VolumeConfigError): VolumeSettings(**dict()) def test_name_only(self): @@ -125,7 +126,7 @@ class CreateSimpleVolumeSuccessTests(OSIntegrationTestCase): super(self.__class__, self).__start__() guid = uuid.uuid4() - self.volume_settings = VolumeSettings( + self.volume_settings = VolumeConfig( name=self.__class__.__name__ + '-' + str(guid)) self.cinder = cinder_utils.cinder_client(self.os_creds) @@ -234,7 +235,7 @@ class CreateSimpleVolumeFailureTests(OSIntegrationTestCase): Tests the creation of an OpenStack volume with a negative size to ensure it raises a BadRequest exception. """ - volume_settings = VolumeSettings( + volume_settings = VolumeConfig( name=self.__class__.__name__ + '-' + str(self.guid), size=-1) # Create Volume @@ -248,7 +249,7 @@ class CreateSimpleVolumeFailureTests(OSIntegrationTestCase): Tests the creation of an OpenStack volume with a type that does not exist to ensure it raises a NotFound exception. """ - volume_settings = VolumeSettings( + volume_settings = VolumeConfig( name=self.__class__.__name__ + '-' + str(self.guid), type_name='foo') @@ -263,7 +264,7 @@ class CreateSimpleVolumeFailureTests(OSIntegrationTestCase): Tests the creation of an OpenStack volume with an image that does not exist to ensure it raises a BadRequest exception. """ - volume_settings = VolumeSettings( + volume_settings = VolumeConfig( name=self.__class__.__name__ + '-' + str(self.guid), image_name='foo') @@ -278,7 +279,7 @@ class CreateSimpleVolumeFailureTests(OSIntegrationTestCase): Tests the creation of an OpenStack volume with an availability zone that does not exist to ensure it raises a BadRequest exception. """ - volume_settings = VolumeSettings( + volume_settings = VolumeConfig( name=self.__class__.__name__ + '-' + str(self.guid), availability_zone='foo') @@ -303,7 +304,7 @@ class CreateVolumeWithTypeTests(OSIntegrationTestCase): self.volume_type_name = guid + '-vol-type' self.volume_type_creator = OpenStackVolumeType( - self.os_creds, VolumeTypeSettings(name=self.volume_type_name)) + self.os_creds, VolumeTypeConfig(name=self.volume_type_name)) self.volume_type_creator.create() self.volume_creator = None @@ -321,7 +322,7 @@ class CreateVolumeWithTypeTests(OSIntegrationTestCase): """ self.volume_creator = OpenStackVolume( self.os_creds, - VolumeSettings(name=self.volume_name, type_name='foo')) + VolumeConfig(name=self.volume_name, type_name='foo')) with self.assertRaises(NotFound): self.volume_creator.create() @@ -332,8 +333,8 @@ class CreateVolumeWithTypeTests(OSIntegrationTestCase): """ self.volume_creator = OpenStackVolume( self.os_creds, - VolumeSettings(name=self.volume_name, - type_name=self.volume_type_name)) + VolumeConfig( + name=self.volume_name, type_name=self.volume_type_name)) created_volume = self.volume_creator.create(block=True) self.assertIsNotNone(created_volume) @@ -383,7 +384,7 @@ class CreateVolumeWithImageTests(OSIntegrationTestCase): """ self.volume_creator = OpenStackVolume( self.os_creds, - VolumeSettings(name=self.volume_name, image_name='foo')) + VolumeConfig(name=self.volume_name, image_name='foo')) with self.assertRaises(BadRequest): self.volume_creator.create(block=True) @@ -395,7 +396,7 @@ class CreateVolumeWithImageTests(OSIntegrationTestCase): """ self.volume_creator = OpenStackVolume( self.os_creds, - VolumeSettings(name=self.volume_name, image_name=self.image_name)) + VolumeConfig(name=self.volume_name, image_name=self.image_name)) created_volume = self.volume_creator.create(block=True) self.assertIsNotNone(created_volume) diff --git a/snaps/openstack/tests/create_volume_type_tests.py b/snaps/openstack/tests/create_volume_type_tests.py index 93e9351..70c40cc 100644 --- a/snaps/openstack/tests/create_volume_type_tests.py +++ b/snaps/openstack/tests/create_volume_type_tests.py @@ -12,7 +12,11 @@ # 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_qos import QoSSettings, Consumer, OpenStackQoS +from snaps.config.volume_type import ( + VolumeTypeConfig, VolumeTypeEncryptionConfig, VolumeTypeConfigError, + ControlLocation) +from snaps.config.qos import QoSConfig, Consumer +from snaps.openstack.create_qos import OpenStackQoS try: from urllib.request import URLError @@ -25,8 +29,7 @@ import uuid from snaps.openstack import create_volume_type from snaps.openstack.create_volume_type import ( - VolumeTypeSettings, VolumeTypeSettingsError, VolumeTypeEncryptionSettings, - ControlLocation) + VolumeTypeSettings, VolumeTypeEncryptionSettings) from snaps.openstack.tests.os_source_file_test import OSIntegrationTestCase from snaps.openstack.utils import cinder_utils @@ -41,11 +44,11 @@ class VolumeTypeSettingsUnitTests(unittest.TestCase): """ def test_no_params(self): - with self.assertRaises(VolumeTypeSettingsError): + with self.assertRaises(VolumeTypeConfigError): VolumeTypeSettings() def test_empty_config(self): - with self.assertRaises(VolumeTypeSettingsError): + with self.assertRaises(VolumeTypeConfigError): VolumeTypeSettings(**dict()) def test_name_only(self): @@ -109,7 +112,7 @@ class VolumeTypeSettingsUnitTests(unittest.TestCase): class CreateSimpleVolumeTypeSuccessTests(OSIntegrationTestCase): """ - Test for the OpenStackVolumeType class defined in create_volume_type.py + Test for the OpenStackVolumeType class defined in py without any QoS Specs or Encryption """ @@ -121,7 +124,7 @@ class CreateSimpleVolumeTypeSuccessTests(OSIntegrationTestCase): super(self.__class__, self).__start__() guid = uuid.uuid4() - self.volume_type_settings = VolumeTypeSettings( + self.volume_type_settings = VolumeTypeConfig( name=self.__class__.__name__ + '-' + str(guid)) self.cinder = cinder_utils.cinder_client(self.os_creds) @@ -220,7 +223,7 @@ class CreateVolumeTypeComplexTests(OSIntegrationTestCase): self.volume_type_name = guid + '-vol_type' self.volume_type_creator = None - qos_settings = QoSSettings( + qos_settings = QoSConfig( name=guid + '-qos-spec', consumer=Consumer.both) self.qos_creator = OpenStackQoS(self.os_creds, qos_settings) self.qos_creator.create() @@ -240,7 +243,7 @@ class CreateVolumeTypeComplexTests(OSIntegrationTestCase): """ self.volume_type_creator = create_volume_type.OpenStackVolumeType( self.os_creds, - VolumeTypeSettings( + VolumeTypeConfig( name=self.volume_type_name, qos_spec_name=self.qos_creator.qos_settings.name)) @@ -264,12 +267,12 @@ class CreateVolumeTypeComplexTests(OSIntegrationTestCase): """ Creates a Volume Type object with encryption """ - encryption_settings = VolumeTypeEncryptionSettings( + encryption_settings = VolumeTypeEncryptionConfig( name='foo', provider_class='bar', control_location=ControlLocation.back_end) self.volume_type_creator = create_volume_type.OpenStackVolumeType( self.os_creds, - VolumeTypeSettings( + VolumeTypeConfig( name=self.volume_type_name, encryption=encryption_settings)) @@ -293,12 +296,12 @@ class CreateVolumeTypeComplexTests(OSIntegrationTestCase): """ Creates a Volume Type object with encryption and an associated QoS Spec """ - encryption_settings = VolumeTypeEncryptionSettings( + encryption_settings = VolumeTypeEncryptionConfig( name='foo', provider_class='bar', control_location=ControlLocation.back_end) self.volume_type_creator = create_volume_type.OpenStackVolumeType( self.os_creds, - VolumeTypeSettings( + VolumeTypeConfig( name=self.volume_type_name, encryption=encryption_settings, qos_spec_name=self.qos_creator.qos_settings.name)) diff --git a/snaps/openstack/tests/openstack_tests.py b/snaps/openstack/tests/openstack_tests.py index 16fb0b5..78e8601 100644 --- a/snaps/openstack/tests/openstack_tests.py +++ b/snaps/openstack/tests/openstack_tests.py @@ -17,9 +17,9 @@ import re import pkg_resources from snaps import file_utils -from snaps.openstack.create_image import ImageSettings -from snaps.openstack.create_network import NetworkSettings, SubnetSettings -from snaps.openstack.create_router import RouterSettings +from snaps.config.image import ImageConfig +from snaps.config.network import NetworkConfig, SubnetConfig +from snaps.config.router import RouterConfig from snaps.openstack.os_credentials import OSCreds, ProxySettings __author__ = 'spisarski' @@ -81,7 +81,7 @@ def get_credentials(os_env_file=None, proxy_settings_str=None, elif config.get('OS_INSECURE'): https_cacert = False - interface = 'admin' + interface = 'public' if config.get('OS_INTERFACE'): interface = config.get('OS_INTERFACE') @@ -171,7 +171,7 @@ def create_image_settings(image_name, image_user, image_format, metadata, logger.debug('Image metadata - ' + str(metadata)) if metadata and 'config' in metadata: - return ImageSettings(**metadata['config']) + return ImageConfig(**metadata['config']) disk_file = None if metadata: @@ -185,10 +185,9 @@ def create_image_settings(image_name, image_user, image_format, metadata, if metadata and \ ('kernel_file' in metadata or 'kernel_url' in metadata) and \ kernel_settings is None: - kernel_image_settings = ImageSettings( + kernel_image_settings = ImageConfig( name=image_name + '-kernel', image_user=image_user, - img_format=image_format, - image_file=metadata.get('kernel_file'), + img_format=image_format, image_file=metadata.get('kernel_file'), url=metadata.get('kernel_url'), public=public) else: kernel_image_settings = kernel_settings @@ -196,7 +195,7 @@ def create_image_settings(image_name, image_user, image_format, metadata, if metadata and \ ('ramdisk_file' in metadata or 'ramdisk_url' in metadata) and \ ramdisk_settings is None: - ramdisk_image_settings = ImageSettings( + ramdisk_image_settings = ImageConfig( name=image_name + '-ramdisk', image_user=image_user, img_format=image_format, image_file=metadata.get('ramdisk_file'), @@ -208,13 +207,13 @@ def create_image_settings(image_name, image_user, image_format, metadata, if metadata and 'extra_properties' in metadata: extra_properties = metadata['extra_properties'] - return ImageSettings(name=image_name, image_user=image_user, - img_format=image_format, image_file=disk_file, - url=disk_url, extra_properties=extra_properties, - kernel_image_settings=kernel_image_settings, - ramdisk_image_settings=ramdisk_image_settings, - public=public, - nic_config_pb_loc=nic_config_pb_loc) + return ImageConfig(name=image_name, image_user=image_user, + img_format=image_format, image_file=disk_file, + url=disk_url, extra_properties=extra_properties, + kernel_image_settings=kernel_image_settings, + ramdisk_image_settings=ramdisk_image_settings, + public=public, + nic_config_pb_loc=nic_config_pb_loc) def cirros_image_settings(name=None, url=None, image_metadata=None, @@ -248,8 +247,8 @@ def cirros_image_settings(name=None, url=None, image_metadata=None, def file_image_test_settings(name, file_path, image_user=CIRROS_USER): - return ImageSettings(name=name, image_user=image_user, - img_format=DEFAULT_IMAGE_FORMAT, image_file=file_path) + return ImageConfig(name=name, image_user=image_user, + img_format=DEFAULT_IMAGE_FORMAT, image_file=file_path) def centos_image_settings(name, url=None, image_metadata=None, @@ -339,17 +338,17 @@ 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: - self.router_settings = RouterSettings( + self.router_settings = RouterConfig( name=router_name, external_gateway=external_gateway, internal_subnets=[subnet_name]) else: - self.router_settings = RouterSettings( + self.router_settings = RouterConfig( name=router_name, external_gateway=external_gateway) diff --git a/snaps/openstack/tests/os_source_file_test.py b/snaps/openstack/tests/os_source_file_test.py index 1617f91..ef4fcfa 100644 --- a/snaps/openstack/tests/os_source_file_test.py +++ b/snaps/openstack/tests/os_source_file_test.py @@ -14,14 +14,12 @@ # limitations under the License. import logging import pkg_resources -import requests -from requests.packages.urllib3.exceptions import InsecureRequestWarning import uuid import unittest from snaps import file_utils -from snaps.openstack.create_project import ProjectSettings -from snaps.openstack.create_user import UserSettings +from snaps.config.project import ProjectConfig +from snaps.config.user import UserConfig from snaps.openstack.tests import openstack_tests from snaps.openstack.utils import deploy_utils, keystone_utils @@ -29,8 +27,6 @@ from snaps.openstack.utils import deploy_utils, keystone_utils dev_os_env_file = pkg_resources.resource_filename( 'snaps.openstack.tests.conf', 'os_env.yaml') -requests.packages.urllib3.disable_warnings(InsecureRequestWarning) - class OSComponentTestCase(unittest.TestCase): @@ -149,12 +145,12 @@ class OSIntegrationTestCase(OSComponentTestCase): guid = self.__class__.__name__ + '-' + str(uuid.uuid4())[:-19] project_name = guid + '-proj' self.project_creator = deploy_utils.create_project( - self.admin_os_creds, ProjectSettings( + self.admin_os_creds, ProjectConfig( name=project_name, domain=self.admin_os_creds.project_domain_name)) self.user_creator = deploy_utils.create_user( - self.admin_os_creds, UserSettings( + self.admin_os_creds, UserConfig( name=guid + '-user', password=guid, project_name=project_name, roles={ 'admin': self.project_creator.project_settings.name}, diff --git a/snaps/openstack/utils/deploy_utils.py b/snaps/openstack/utils/deploy_utils.py index c936c1f..8c8431d 100644 --- a/snaps/openstack/utils/deploy_utils.py +++ b/snaps/openstack/utils/deploy_utils.py @@ -78,7 +78,7 @@ def create_router(os_creds, router_settings, cleanup=False): """ Creates a network on which the CMTSs can attach :param os_creds: The OpenStack credentials object - :param router_settings: The RouterSettings instance + :param router_settings: The RouterConfig instance :param cleanup: Denotes whether or not this is being called for cleanup :return: A reference to the network creator objects for each network from which network elements such as the subnet, router, interface @@ -103,7 +103,7 @@ def create_keypair(os_creds, keypair_settings, cleanup=False): """ Creates a keypair that can be applied to an instance :param os_creds: The OpenStack credentials object - :param keypair_settings: The KeypairSettings object + :param keypair_settings: The KeypairConfig object :param cleanup: Denotes whether or not this is being called for cleanup :return: A reference to the keypair creator object """ diff --git a/snaps/openstack/utils/keystone_utils.py b/snaps/openstack/utils/keystone_utils.py index 387f6c7..b8769c0 100644 --- a/snaps/openstack/utils/keystone_utils.py +++ b/snaps/openstack/utils/keystone_utils.py @@ -114,7 +114,7 @@ def get_project(keystone=None, os_creds=None, project_settings=None, :param keystone: the Keystone client :param os_creds: the OpenStack credentials used to obtain the Keystone client if the keystone parameter is None - :param project_settings: a ProjectSettings object + :param project_settings: a ProjectConfig object :param project_name: the name to query :return: the SNAPS-OO Project domain object or None """ diff --git a/snaps/openstack/utils/neutron_utils.py b/snaps/openstack/utils/neutron_utils.py index 9ca9aba..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 @@ -327,7 +327,7 @@ def get_router(neutron, router_settings=None, router_name=None): values if not None, else finds the first with the value of the router_name parameter, else None :param neutron: the client - :param router_settings: the RouterSettings object + :param router_settings: the RouterConfig object :param router_name: the name of the network to retrieve :return: a SNAPS-OO Router 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/nova_utils.py b/snaps/openstack/utils/nova_utils.py index 0820289..b974f2e 100644 --- a/snaps/openstack/utils/nova_utils.py +++ b/snaps/openstack/utils/nova_utils.py @@ -52,22 +52,22 @@ def nova_client(os_creds): region_name=os_creds.region_name) -def create_server(nova, neutron, glance, instance_settings, image_settings, - keypair_settings=None): +def create_server(nova, neutron, glance, instance_config, image_config, + keypair_config=None): """ Creates a VM instance :param nova: the nova client (required) :param neutron: the neutron client for retrieving ports (required) :param glance: the glance client (required) - :param instance_settings: the VM instance settings object (required) - :param image_settings: the VM's image settings object (required) - :param keypair_settings: the VM's keypair settings object (optional) + :param instance_config: the VMInstConfig object (required) + :param image_config: the VM's ImageConfig object (required) + :param keypair_config: the VM's KeypairConfig object (optional) :return: a snaps.domain.VmInst object """ ports = list() - for port_setting in instance_settings.port_settings: + for port_setting in instance_config.port_settings: ports.append(neutron_utils.get_port( neutron, port_settings=port_setting)) nics = [] @@ -76,41 +76,41 @@ def create_server(nova, neutron, glance, instance_settings, image_settings, kv['port-id'] = port.id nics.append(kv) - logger.info('Creating VM with name - ' + instance_settings.name) + logger.info('Creating VM with name - ' + instance_config.name) keypair_name = None - if keypair_settings: - keypair_name = keypair_settings.name + if keypair_config: + keypair_name = keypair_config.name - flavor = get_flavor_by_name(nova, instance_settings.flavor) + flavor = get_flavor_by_name(nova, instance_config.flavor) if not flavor: raise NovaException( - 'Flavor not found with name - %s', instance_settings.flavor) + 'Flavor not found with name - %s', instance_config.flavor) - image = glance_utils.get_image(glance, image_settings=image_settings) + image = glance_utils.get_image(glance, image_settings=image_config) if image: userdata = None - if instance_settings.userdata: - if isinstance(instance_settings.userdata, str): - userdata = instance_settings.userdata + '\n' - elif (isinstance(instance_settings.userdata, dict) and - 'script_file' in instance_settings.userdata): + if instance_config.userdata: + if isinstance(instance_config.userdata, str): + userdata = instance_config.userdata + '\n' + elif (isinstance(instance_config.userdata, dict) and + 'script_file' in instance_config.userdata): try: userdata = file_utils.read_file( - instance_settings.userdata['script_file']) + instance_config.userdata['script_file']) except Exception as e: logger.warn('error reading userdata file %s - %s', - instance_settings.userdata, e) - args = {'name': instance_settings.name, + instance_config.userdata, e) + args = {'name': instance_config.name, 'flavor': flavor, 'image': image, 'nics': nics, 'key_name': keypair_name, 'security_groups': - instance_settings.security_group_names, + instance_config.security_group_names, 'userdata': userdata} - if instance_settings.availability_zone: - args['availability_zone'] = instance_settings.availability_zone + if instance_config.availability_zone: + args['availability_zone'] = instance_config.availability_zone server = nova.servers.create(**args) @@ -118,7 +118,7 @@ def create_server(nova, neutron, glance, instance_settings, image_settings, else: raise NovaException( 'Cannot create instance, image cannot be located with name %s', - image_settings.name) + image_config.name) def get_server(nova, vm_inst_settings=None, server_name=None): diff --git a/snaps/openstack/utils/settings_utils.py b/snaps/openstack/utils/settings_utils.py index ea1d018..ab26d3d 100644 --- a/snaps/openstack/utils/settings_utils.py +++ b/snaps/openstack/utils/settings_utils.py @@ -15,37 +15,36 @@ import uuid from snaps import file_utils -from snaps.openstack.create_flavor import FlavorSettings +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_keypairs import KeypairSettings -from snaps.openstack.create_network import ( - PortSettings, SubnetSettings, NetworkSettings) from snaps.openstack.create_security_group import ( SecurityGroupSettings, SecurityGroupRuleSettings) -from snaps.openstack.create_router import RouterSettings -from snaps.openstack.create_volume import VolumeSettings -from snaps.openstack.create_volume_type import ( - VolumeTypeSettings, VolumeTypeEncryptionSettings, ControlLocation) 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,13 +89,13 @@ 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 def create_router_settings(neutron, router): """ - Returns a RouterSettings object + Returns a RouterConfig object :param neutron: the neutron client :param router: a SNAPS-OO Router domain object :return: @@ -135,33 +134,33 @@ 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: if port_setting.network_name != ext_net_name: filtered_settings.append(port_setting) - return RouterSettings( + return RouterConfig( name=router.name, external_gateway=ext_net_name, admin_state_up=router.admin_state_up, port_settings=filtered_settings) -def create_volume_settings(volume): +def create_volume_config(volume): """ Returns a VolumeSettings object :param volume: a SNAPS-OO Volume object """ - return VolumeSettings( + return VolumeConfig( name=volume.name, description=volume.description, size=volume.size, type_name=volume.type, availability_zone=volume.availability_zone, multi_attach=volume.multi_attach) -def create_volume_type_settings(volume_type): +def create_volume_type_config(volume_type): """ Returns a VolumeTypeSettings object :param volume_type: a SNAPS-OO VolumeType object @@ -175,7 +174,7 @@ def create_volume_type_settings(volume_type): else: control = ControlLocation.back_end - encrypt_settings = VolumeTypeEncryptionSettings( + encrypt_settings = VolumeTypeEncryptionConfig( name=volume_type.encryption.__class__, provider_class=volume_type.encryption.provider, control_location=control, @@ -186,17 +185,17 @@ def create_volume_type_settings(volume_type): if volume_type.qos_spec: qos_spec_name = volume_type.qos_spec.name - return VolumeTypeSettings( + return VolumeTypeConfig( name=volume_type.name, encryption=encrypt_settings, qos_spec_name=qos_spec_name, public=volume_type.public) -def create_flavor_settings(flavor): +def create_flavor_config(flavor): """ Returns a VolumeSettings object :param flavor: a SNAPS-OO Volume object """ - return FlavorSettings( + return FlavorConfig( name=flavor.name, flavor_id=flavor.id, ram=flavor.ram, disk=flavor.disk, vcpus=flavor.vcpus, ephemeral=flavor.ephemeral, swap=flavor.swap, rxtx_factor=flavor.rxtx_factor, @@ -205,13 +204,13 @@ def create_flavor_settings(flavor): def create_keypair_settings(heat_cli, stack, keypair, pk_output_key): """ - Instantiates a KeypairSettings object from a Keypair domain objects + Instantiates a KeypairConfig object from a Keypair domain objects :param heat_cli: the heat client :param stack: the Stack domain object :param keypair: the Keypair SNAPS domain object :param pk_output_key: the key to the heat template's outputs for retrieval of the private key file - :return: a KeypairSettings object + :return: a KeypairConfig object """ if pk_output_key: outputs = heat_utils.get_outputs(heat_cli, stack) @@ -222,16 +221,16 @@ def create_keypair_settings(heat_cli, stack, keypair, pk_output_key): key_file = file_utils.save_string_to_file( output.value, str(guid), 0o400) - # Use outputs, file and resources for the KeypairSettings - return KeypairSettings( + # Use outputs, file and resources for the KeypairConfig + return KeypairConfig( name=keypair.name, private_filepath=key_file.name) - return KeypairSettings(name=keypair.name) + return KeypairConfig(name=keypair.name) 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 """ @@ -348,14 +347,14 @@ def __create_floatingip_settings(neutron, port_settings): return out -def determine_image_settings(glance, server, image_settings): +def determine_image_config(glance, server, image_settings): """ - Returns a ImageSettings object from the list that matches the name in one + Returns a ImageConfig object from the list that matches the name in one of the image_settings parameter :param glance: the glance client :param server: a SNAPS-OO VmInst domain object - :param image_settings: list of ImageSettings objects - :return: ImageSettings or None + :param image_settings: list of ImageConfig objects + :return: ImageConfig or None """ if image_settings: for image_setting in image_settings: @@ -364,20 +363,20 @@ def determine_image_settings(glance, server, image_settings): return image_setting -def determine_keypair_settings(heat_cli, stack, server, keypair_settings=None, - priv_key_key=None): +def determine_keypair_config(heat_cli, stack, server, keypair_settings=None, + priv_key_key=None): """ - Returns a KeypairSettings object from the list that matches the + Returns a KeypairConfig object from the list that matches the server.keypair_name value in the keypair_settings parameter if not None, else if the output_key is not None, the output's value when contains the string 'BEGIN RSA PRIVATE KEY', this value will be stored into a file and - encoded into the KeypairSettings object returned + encoded into the KeypairConfig object returned :param heat_cli: the OpenStack heat client :param stack: a SNAPS-OO Stack domain object :param server: a SNAPS-OO VmInst domain object - :param keypair_settings: list of KeypairSettings objects + :param keypair_settings: list of KeypairConfig objects :param priv_key_key: the stack options that holds the private key value - :return: KeypairSettings or None + :return: KeypairConfig or None """ # Existing keypair being used by Heat Template if keypair_settings: @@ -395,6 +394,6 @@ def determine_keypair_settings(heat_cli, stack, server, keypair_settings=None, key_file = file_utils.save_string_to_file( output.value, str(guid), 0o400) - # Use outputs, file and resources for the KeypairSettings - return KeypairSettings( + # Use outputs, file and resources for the KeypairConfig + return KeypairConfig( name=server.keypair_name, private_filepath=key_file.name) diff --git a/snaps/openstack/utils/tests/cinder_utils_tests.py b/snaps/openstack/utils/tests/cinder_utils_tests.py index 6fd92e3..b624b09 100644 --- a/snaps/openstack/utils/tests/cinder_utils_tests.py +++ b/snaps/openstack/utils/tests/cinder_utils_tests.py @@ -18,11 +18,12 @@ import uuid import time from cinderclient.exceptions import NotFound, BadRequest +from snaps.config.volume import VolumeConfig +from snaps.config.volume_type import ( + VolumeTypeConfig, ControlLocation, VolumeTypeEncryptionConfig) +from snaps.config.qos import Consumer, QoSConfig from snaps.openstack import create_volume -from snaps.openstack.create_qos import QoSSettings, Consumer -from snaps.openstack.create_volume import VolumeSettings -from snaps.openstack.create_volume_type import ( - VolumeTypeSettings, VolumeTypeEncryptionSettings, ControlLocation) +from snaps.openstack.create_qos import Consumer from snaps.openstack.tests import validation_utils from snaps.openstack.tests.os_source_file_test import OSComponentTestCase from snaps.openstack.utils import cinder_utils @@ -91,7 +92,7 @@ class CinderUtilsVolumeTests(OSComponentTestCase): """ Tests the cinder_utils.create_volume() """ - volume_settings = VolumeSettings(name=self.volume_name) + volume_settings = VolumeConfig(name=self.volume_name) self.volume = cinder_utils.create_volume( self.cinder, volume_settings) self.assertIsNotNone(self.volume) @@ -108,7 +109,7 @@ class CinderUtilsVolumeTests(OSComponentTestCase): """ Tests the cinder_utils.create_volume() """ - volume_settings = VolumeSettings(name=self.volume_name) + volume_settings = VolumeConfig(name=self.volume_name) self.volume = cinder_utils.create_volume( self.cinder, volume_settings) self.assertIsNotNone(self.volume) @@ -196,8 +197,8 @@ class CinderUtilsQoSTests(OSComponentTestCase): """ Tests the cinder_utils.create_qos() """ - qos_settings = QoSSettings(name=self.qos_name, specs=self.specs, - consumer=Consumer.both) + qos_settings = QoSConfig( + name=self.qos_name, specs=self.specs, consumer=Consumer.both) self.qos = cinder_utils.create_qos(self.cinder, qos_settings) self.assertIsNotNone(self.qos) @@ -213,8 +214,8 @@ class CinderUtilsQoSTests(OSComponentTestCase): """ Tests the cinder_utils.create_qos() """ - qos_settings = QoSSettings(name=self.qos_name, specs=self.specs, - consumer=Consumer.front_end) + qos_settings = QoSConfig( + name=self.qos_name, specs=self.specs, consumer=Consumer.front_end) self.qos = cinder_utils.create_qos(self.cinder, qos_settings) self.assertIsNotNone(self.qos) @@ -230,8 +231,8 @@ class CinderUtilsQoSTests(OSComponentTestCase): """ Tests the cinder_utils.create_qos() """ - qos_settings = QoSSettings(name=self.qos_name, specs=self.specs, - consumer=Consumer.back_end) + qos_settings = QoSConfig( + name=self.qos_name, specs=self.specs, consumer=Consumer.back_end) self.qos = cinder_utils.create_qos(self.cinder, qos_settings) self.assertIsNotNone(self.qos) @@ -247,7 +248,7 @@ class CinderUtilsQoSTests(OSComponentTestCase): """ Tests the cinder_utils.create_qos() """ - qos_settings = QoSSettings(name=self.qos_name, consumer=Consumer.both) + qos_settings = QoSConfig(name=self.qos_name, consumer=Consumer.both) self.qos = cinder_utils.create_qos(self.cinder, qos_settings) self.assertIsNotNone(self.qos) self.assertEqual(self.qos_name, self.qos.name) @@ -275,7 +276,7 @@ class CinderUtilsSimpleVolumeTypeTests(OSComponentTestCase): """ guid = uuid.uuid4() volume_type_name = self.__class__.__name__ + '-' + str(guid) - self.volume_type_settings = VolumeTypeSettings(name=volume_type_name) + self.volume_type_settings = VolumeTypeConfig(name=volume_type_name) self.volume_type = None self.cinder = cinder_utils.cinder_client(self.os_creds) @@ -349,7 +350,7 @@ class CinderUtilsAddEncryptionTests(OSComponentTestCase): volume_type_name = self.__class__.__name__ + '-' + str(guid) + '-type' self.volume_type = cinder_utils.create_volume_type( - self.cinder, VolumeTypeSettings(name=volume_type_name)) + self.cinder, VolumeTypeConfig(name=volume_type_name)) def tearDown(self): """ @@ -373,7 +374,7 @@ class CinderUtilsAddEncryptionTests(OSComponentTestCase): Tests the cinder_utils.create_volume_encryption(), get_volume_encryption(), and get_volume_encryption_by_id() """ - encryption_settings = VolumeTypeEncryptionSettings( + encryption_settings = VolumeTypeEncryptionConfig( name=self.encryption_name, provider_class='foo', control_location=ControlLocation.front_end) self.encryption = cinder_utils.create_volume_encryption( @@ -391,7 +392,7 @@ class CinderUtilsAddEncryptionTests(OSComponentTestCase): """ Primarily tests the cinder_utils.delete_volume_type_encryption() """ - encryption_settings = VolumeTypeEncryptionSettings( + encryption_settings = VolumeTypeEncryptionConfig( name=self.encryption_name, provider_class='LuksEncryptor', control_location=ControlLocation.back_end) self.encryption = cinder_utils.create_volume_encryption( @@ -417,7 +418,7 @@ class CinderUtilsAddEncryptionTests(OSComponentTestCase): Tests the cinder_utils.create_volume_encryption() with all valid settings """ - encryption_settings = VolumeTypeEncryptionSettings( + encryption_settings = VolumeTypeEncryptionConfig( name=self.encryption_name, provider_class='foo', cipher='bar', control_location=ControlLocation.back_end, key_size=1) @@ -439,7 +440,7 @@ class CinderUtilsAddEncryptionTests(OSComponentTestCase): Tests the cinder_utils.create_volume_encryption() raises an exception when the provider class does not exist """ - encryption_settings = VolumeTypeEncryptionSettings( + encryption_settings = VolumeTypeEncryptionConfig( name=self.encryption_name, provider_class='foo', cipher='bar', control_location=ControlLocation.back_end, key_size=-1) @@ -463,8 +464,8 @@ class CinderUtilsVolumeTypeCompleteTests(OSComponentTestCase): self.vol_type_name = self.__class__.__name__ + '-' + str(guid) self.specs = {'foo': 'bar'} self.cinder = cinder_utils.cinder_client(self.os_creds) - qos_settings = QoSSettings(name=self.qos_name, specs=self.specs, - consumer=Consumer.both) + qos_settings = QoSConfig( + name=self.qos_name, specs=self.specs, consumer=Consumer.both) self.qos = cinder_utils.create_qos(self.cinder, qos_settings) self.volume_type = None @@ -495,10 +496,10 @@ class CinderUtilsVolumeTypeCompleteTests(OSComponentTestCase): Tests the cinder_utils.create_volume_type() where encryption has been configured """ - encryption_settings = VolumeTypeEncryptionSettings( + encryption_settings = VolumeTypeEncryptionConfig( name='foo', provider_class='bar', control_location=ControlLocation.back_end) - volume_type_settings = VolumeTypeSettings( + volume_type_settings = VolumeTypeConfig( name=self.vol_type_name, encryption=encryption_settings) self.volume_type = cinder_utils.create_volume_type( self.cinder, volume_type_settings) @@ -514,7 +515,7 @@ class CinderUtilsVolumeTypeCompleteTests(OSComponentTestCase): """ Tests the cinder_utils.create_volume_type() with an associated QoS Spec """ - volume_type_settings = VolumeTypeSettings( + volume_type_settings = VolumeTypeConfig( name=self.vol_type_name, qos_spec_name=self.qos_name) self.volume_type = cinder_utils.create_volume_type( self.cinder, volume_type_settings) @@ -529,7 +530,7 @@ class CinderUtilsVolumeTypeCompleteTests(OSComponentTestCase): Tests the cinder_utils.create_volume_type() when the QoS Spec name does not exist """ - volume_type_settings = VolumeTypeSettings( + volume_type_settings = VolumeTypeConfig( name=self.vol_type_name, qos_spec_name='foo') self.volume_type = cinder_utils.create_volume_type( @@ -542,10 +543,10 @@ class CinderUtilsVolumeTypeCompleteTests(OSComponentTestCase): Tests the cinder_utils.create_volume_type() with encryption and an associated QoS Spec """ - encryption_settings = VolumeTypeEncryptionSettings( + encryption_settings = VolumeTypeEncryptionConfig( name='foo', provider_class='bar', control_location=ControlLocation.back_end) - volume_type_settings = VolumeTypeSettings( + volume_type_settings = VolumeTypeConfig( name=self.vol_type_name, qos_spec_name=self.qos_name, encryption=encryption_settings) self.volume_type = cinder_utils.create_volume_type( diff --git a/snaps/openstack/utils/tests/heat_utils_tests.py b/snaps/openstack/utils/tests/heat_utils_tests.py index 1068903..2f1e7cc 100644 --- a/snaps/openstack/utils/tests/heat_utils_tests.py +++ b/snaps/openstack/utils/tests/heat_utils_tests.py @@ -20,12 +20,13 @@ import uuid import time -from snaps.openstack import create_stack -from snaps.openstack.create_flavor import OpenStackFlavor, FlavorSettings +import snaps.config.stack as stack_config +from snaps.config.flavor import FlavorConfig +from snaps.openstack.create_flavor import OpenStackFlavor from snaps.openstack.create_image import OpenStackImage from snaps.openstack.create_instance import OpenStackVmInstance -from snaps.openstack.create_stack import StackSettings +from snaps.openstack.create_stack import StackConfig from snaps.openstack.tests import openstack_tests from snaps.openstack.tests.os_source_file_test import OSComponentTestCase from snaps.openstack.utils import ( @@ -96,7 +97,7 @@ class HeatUtilsCreateSimpleStackTests(OSComponentTestCase): # Create Flavor self.flavor_creator = OpenStackFlavor( self.os_creds, - FlavorSettings(name=guid + '-flavor', ram=256, disk=10, vcpus=1)) + FlavorConfig(name=guid + '-flavor', ram=256, disk=10, vcpus=1)) self.flavor_creator.create() env_values = {'image_name': self.image_creator.image_settings.name, @@ -106,10 +107,10 @@ class HeatUtilsCreateSimpleStackTests(OSComponentTestCase): 'inst_name': self.vm_inst_name} heat_tmplt_path = pkg_resources.resource_filename( 'snaps.openstack.tests.heat', 'test_heat_template.yaml') - self.stack_settings1 = StackSettings( + self.stack_settings1 = StackConfig( name=stack_name1, template_path=heat_tmplt_path, env_values=env_values) - self.stack_settings2 = StackSettings( + self.stack_settings2 = StackConfig( name=stack_name2, template_path=heat_tmplt_path, env_values=env_values) self.stack1 = None @@ -271,7 +272,7 @@ class HeatUtilsCreateComplexStackTests(OSComponentTestCase): 'external_net_name': self.ext_net_name} heat_tmplt_path = pkg_resources.resource_filename( 'snaps.openstack.tests.heat', 'floating_ip_heat_template.yaml') - stack_settings = StackSettings( + stack_settings = StackConfig( name=stack_name, template_path=heat_tmplt_path, env_values=env_values) self.heat_client = heat_utils.heat_client(self.os_creds) @@ -290,15 +291,16 @@ class HeatUtilsCreateComplexStackTests(OSComponentTestCase): try: heat_utils.delete_stack(self.heat_client, self.stack) # Wait until stack deployment has completed - end_time = time.time() + create_stack.STACK_COMPLETE_TIMEOUT + end_time = (time.time() + + stack_config.STACK_COMPLETE_TIMEOUT) is_deleted = False while time.time() < end_time: status = heat_utils.get_stack_status(self.heat_client, self.stack.id) - if status == create_stack.STATUS_DELETE_COMPLETE: + if status == stack_config.STATUS_DELETE_COMPLETE: is_deleted = True break - elif status == create_stack.STATUS_DELETE_FAILED: + elif status == stack_config.STATUS_DELETE_FAILED: is_deleted = False break @@ -313,7 +315,7 @@ class HeatUtilsCreateComplexStackTests(OSComponentTestCase): for server in servers: vm_settings = settings_utils.create_vm_inst_settings( nova, neutron, server) - img_settings = settings_utils.determine_image_settings( + img_settings = settings_utils.determine_image_config( glance, server, [self.image_creator1.image_settings, self.image_creator2.image_settings]) @@ -372,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) @@ -385,7 +387,7 @@ class HeatUtilsCreateComplexStackTests(OSComponentTestCase): self.assertIsNotNone(servers) self.assertEqual(2, len(servers)) - image_settings = settings_utils.determine_image_settings( + image_settings = settings_utils.determine_image_config( glance, servers[0], [self.image_creator1.image_settings, self.image_creator2.image_settings]) @@ -398,7 +400,7 @@ class HeatUtilsCreateComplexStackTests(OSComponentTestCase): self.assertEqual( self.image_creator2.image_settings.name, image_settings.name) - image_settings = settings_utils.determine_image_settings( + image_settings = settings_utils.determine_image_config( glance, servers[1], [self.image_creator1.image_settings, self.image_creator2.image_settings]) @@ -409,13 +411,13 @@ class HeatUtilsCreateComplexStackTests(OSComponentTestCase): self.assertEqual( self.image_creator2.image_settings.name, image_settings.name) - self.keypair1_settings = settings_utils.determine_keypair_settings( + self.keypair1_settings = settings_utils.determine_keypair_config( self.heat_client, self.stack, servers[0], priv_key_key='private_key') self.assertIsNotNone(self.keypair1_settings) self.assertEqual(self.keypair_name, self.keypair1_settings.name) - self.keypair2_settings = settings_utils.determine_keypair_settings( + self.keypair2_settings = settings_utils.determine_keypair_config( self.heat_client, self.stack, servers[1], priv_key_key='private_key') self.assertIsNotNone(self.keypair2_settings) @@ -446,7 +448,7 @@ class HeatUtilsRouterTests(OSComponentTestCase): heat_tmplt_path = pkg_resources.resource_filename( 'snaps.openstack.tests.heat', 'router_heat_template.yaml') - self.stack_settings = StackSettings( + self.stack_settings = StackConfig( name=stack_name, template_path=heat_tmplt_path, env_values=env_values) self.stack = None @@ -472,15 +474,15 @@ class HeatUtilsRouterTests(OSComponentTestCase): self.heat_client, self.stack_settings) # Wait until stack deployment has completed - end_time = time.time() + create_stack.STACK_COMPLETE_TIMEOUT + end_time = time.time() + stack_config.STACK_COMPLETE_TIMEOUT is_active = False while time.time() < end_time: status = heat_utils.get_stack_status(self.heat_client, self.stack.id) - if status == create_stack.STATUS_CREATE_COMPLETE: + if status == stack_config.STATUS_CREATE_COMPLETE: is_active = True break - elif status == create_stack.STATUS_CREATE_FAILED: + elif status == stack_config.STATUS_CREATE_FAILED: is_active = False break @@ -521,7 +523,7 @@ class HeatUtilsVolumeTests(OSComponentTestCase): heat_tmplt_path = pkg_resources.resource_filename( 'snaps.openstack.tests.heat', 'volume_heat_template.yaml') - self.stack_settings = StackSettings( + self.stack_settings = StackConfig( name=stack_name, template_path=heat_tmplt_path, env_values=env_values) self.stack = None @@ -601,7 +603,7 @@ class HeatUtilsFlavorTests(OSComponentTestCase): heat_tmplt_path = pkg_resources.resource_filename( 'snaps.openstack.tests.heat', 'flavor_heat_template.yaml') - self.stack_settings = StackSettings( + self.stack_settings = StackConfig( name=stack_name, template_path=heat_tmplt_path) self.stack = None self.heat_client = heat_utils.heat_client(self.os_creds) @@ -659,7 +661,7 @@ class HeatUtilsKeypairTests(OSComponentTestCase): heat_tmplt_path = pkg_resources.resource_filename( 'snaps.openstack.tests.heat', 'keypair_heat_template.yaml') - self.stack_settings = StackSettings( + self.stack_settings = StackConfig( name=stack_name, template_path=heat_tmplt_path, env_values=env_values) self.stack = None @@ -722,7 +724,7 @@ class HeatUtilsSecurityGroupTests(OSComponentTestCase): heat_tmplt_path = pkg_resources.resource_filename( 'snaps.openstack.tests.heat', 'security_group_heat_template.yaml') - self.stack_settings = StackSettings( + self.stack_settings = StackConfig( name=stack_name, template_path=heat_tmplt_path, env_values=env_values) self.stack = None @@ -789,14 +791,14 @@ def stack_active(heat_cli, stack): :return: T/F """ # Wait until stack deployment has completed - end_time = time.time() + create_stack.STACK_COMPLETE_TIMEOUT + end_time = time.time() + stack_config.STACK_COMPLETE_TIMEOUT is_active = False while time.time() < end_time: status = heat_utils.get_stack_status(heat_cli, stack.id) - if status == create_stack.STATUS_CREATE_COMPLETE: + if status == stack_config.STATUS_CREATE_COMPLETE: is_active = True break - elif status == create_stack.STATUS_CREATE_FAILED: + elif status == stack_config.STATUS_CREATE_FAILED: is_active = False break diff --git a/snaps/openstack/utils/tests/keystone_utils_tests.py b/snaps/openstack/utils/tests/keystone_utils_tests.py index bd0086b..b7f024d 100644 --- a/snaps/openstack/utils/tests/keystone_utils_tests.py +++ b/snaps/openstack/utils/tests/keystone_utils_tests.py @@ -14,8 +14,8 @@ # limitations under the License. import uuid -from snaps.openstack.create_project import ProjectSettings -from snaps.openstack.create_user import UserSettings +from snaps.config.project import ProjectConfig +from snaps.config.user import UserConfig from snaps.openstack.tests.os_source_file_test import OSComponentTestCase from snaps.openstack.utils import keystone_utils, neutron_utils @@ -96,7 +96,7 @@ class KeystoneUtilsTests(OSComponentTestCase): """ Tests the keystone_utils.create_user() function """ - user_settings = UserSettings( + user_settings = UserConfig( name=self.username, password=str(uuid.uuid4()), domain_name=self.os_creds.user_domain_name) @@ -111,7 +111,7 @@ class KeystoneUtilsTests(OSComponentTestCase): """ Tests the keyston_utils.create_project() funtion """ - project_settings = ProjectSettings( + project_settings = ProjectConfig( name=self.project_name, domain=self.os_creds.project_domain_name) self.project = keystone_utils.create_project(self.keystone, project_settings) @@ -180,13 +180,13 @@ class KeystoneUtilsTests(OSComponentTestCase): Tests the keystone_utils function grant_user_role_to_project() :return: """ - user_settings = UserSettings( + user_settings = UserConfig( name=self.username, password=str(uuid.uuid4()), domain_name=self.os_creds.user_domain_name) self.user = keystone_utils.create_user(self.keystone, user_settings) self.assertEqual(self.username, self.user.name) - project_settings = ProjectSettings( + project_settings = ProjectConfig( name=self.project_name, domain=self.os_creds.project_domain_name) self.project = keystone_utils.create_project(self.keystone, project_settings) 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 e290c6e..6d4bc3c 100644 --- a/snaps/openstack/utils/tests/nova_utils_tests.py +++ b/snaps/openstack/utils/tests/nova_utils_tests.py @@ -13,19 +13,22 @@ # See the License for the specific language governing permissions and # limitations under the License. import logging +import time import uuid import os -import time from snaps import file_utils +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 FlavorSettings, OpenStackFlavor +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_volume import OpenStackVolume, VolumeSettings +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 from snaps.openstack.utils import ( @@ -159,11 +162,9 @@ class NovaUtilsFlavorTests(OSComponentTestCase): and creating an OS image file within OpenStack """ guid = self.__class__.__name__ + '-' + str(uuid.uuid4()) - self.flavor_settings = FlavorSettings(name=guid + '-name', - flavor_id=guid + '-id', ram=1, - disk=1, vcpus=1, - ephemeral=1, swap=2, - rxtx_factor=3.0, is_public=False) + self.flavor_settings = FlavorConfig( + name=guid + '-name', flavor_id=guid + '-id', ram=1, disk=1, + vcpus=1, ephemeral=1, swap=2, rxtx_factor=3.0, is_public=False) self.nova = nova_utils.nova_client(self.os_creds) self.flavor = None @@ -255,12 +256,12 @@ class NovaUtilsInstanceTests(OSComponentTestCase): self.flavor_creator = OpenStackFlavor( self.os_creds, - FlavorSettings( + FlavorConfig( 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) @@ -371,18 +372,18 @@ class NovaUtilsInstanceVolumeTests(OSComponentTestCase): self.flavor_creator = OpenStackFlavor( self.os_creds, - FlavorSettings( + FlavorConfig( name=guid + '-flavor-name', ram=256, disk=10, vcpus=1)) self.flavor_creator.create() # Create Volume - volume_settings = VolumeSettings( + volume_settings = VolumeConfig( name=self.__class__.__name__ + '-' + str(guid)) self.volume_creator = OpenStackVolume( 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 3073d53..b34e68b 100644 --- a/snaps/openstack/utils/tests/settings_utils_tests.py +++ b/snaps/openstack/utils/tests/settings_utils_tests.py @@ -18,15 +18,18 @@ 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 from snaps.domain.flavor import Flavor from snaps.domain.volume import ( Volume, VolumeType, VolumeTypeEncryption, QoSSpec) 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) @@ -42,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 """ @@ -68,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) @@ -95,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) @@ -200,13 +203,13 @@ class SettingsUtilsVmInstTests(OSComponentTestCase): # Create Flavor self.flavor_creator = create_flavor.OpenStackFlavor( self.os_creds, - create_flavor.FlavorSettings(name=guid + '-flavor-name', - ram=256, disk=1, vcpus=1)) + FlavorConfig( + name=guid + '-flavor-name', ram=256, disk=1, vcpus=1)) self.flavor_creator.create() # Create Key/Pair self.keypair_creator = create_keypairs.OpenStackKeypair( - self.os_creds, create_keypairs.KeypairSettings( + self.os_creds, KeypairConfig( name=self.keypair_name, public_filepath=self.keypair_pub_filepath, private_filepath=self.keypair_priv_filepath)) @@ -231,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)) @@ -332,13 +335,13 @@ class SettingsUtilsVmInstTests(OSComponentTestCase): def test_derive_image_settings(self): """ Validates the utility function settings_utils#create_image_settings - returns an acceptable ImageSettings object + returns an acceptable ImageConfig object """ self.inst_creator.create(block=True) server = nova_utils.get_server( self.nova, vm_inst_settings=self.inst_creator.instance_settings) - derived_image_settings = settings_utils.determine_image_settings( + derived_image_settings = settings_utils.determine_image_config( self.glance, server, [self.image_creator.image_settings]) self.assertIsNotNone(derived_image_settings) self.assertEqual(self.image_creator.image_settings.name, @@ -354,7 +357,7 @@ class SettingsUtilsUnitTests(unittest.TestCase): volume = Volume( name='vol-name', volume_id='vol-id', description='desc', size=99, vol_type='vol-type', availability_zone='zone1', multi_attach=True) - settings = settings_utils.create_volume_settings(volume) + settings = settings_utils.create_volume_config(volume) self.assertEqual(volume.name, settings.name) self.assertEqual(volume.description, settings.description) self.assertEqual(volume.size, settings.size) @@ -373,7 +376,7 @@ class SettingsUtilsUnitTests(unittest.TestCase): name='vol-type-name', volume_type_id='vol-type-id', public=True, encryption=encryption, qos_spec=qos_spec) - settings = settings_utils.create_volume_type_settings(volume_type) + settings = settings_utils.create_volume_type_config(volume_type) self.assertEqual(volume_type.name, settings.name) self.assertEqual(volume_type.public, settings.public) @@ -390,7 +393,7 @@ class SettingsUtilsUnitTests(unittest.TestCase): flavor = Flavor( name='flavor-name', flavor_id='flavor-id', ram=99, disk=101, vcpus=9, ephemeral=3, swap=5, rxtx_factor=7, is_public=False) - settings = settings_utils.create_flavor_settings(flavor) + settings = settings_utils.create_flavor_config(flavor) self.assertEqual(flavor.name, settings.name) self.assertEqual(flavor.id, settings.flavor_id) self.assertEqual(flavor.ram, settings.ram) diff --git a/snaps/provisioning/tests/ansible_utils_tests.py b/snaps/provisioning/tests/ansible_utils_tests.py index da056b2..b78249e 100644 --- a/snaps/provisioning/tests/ansible_utils_tests.py +++ b/snaps/provisioning/tests/ansible_utils_tests.py @@ -18,6 +18,11 @@ import uuid 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.openstack import create_flavor from snaps.openstack import create_image from snaps.openstack import create_instance @@ -100,14 +105,14 @@ class AnsibleProvisioningTests(OSIntegrationTestCase): # Create Flavor self.flavor_creator = create_flavor.OpenStackFlavor( self.admin_os_creds, - create_flavor.FlavorSettings(name=guid + '-flavor-name', - ram=2048, disk=10, vcpus=2, - metadata=self.flavor_metadata)) + FlavorConfig( + name=guid + '-flavor-name', ram=2048, disk=10, vcpus=2, + metadata=self.flavor_metadata)) self.flavor_creator.create() # Create Key/Pair self.keypair_creator = create_keypairs.OpenStackKeypair( - self.os_creds, create_keypairs.KeypairSettings( + self.os_creds, KeypairConfig( name=self.keypair_name, public_filepath=self.keypair_pub_filepath, private_filepath=self.keypair_priv_filepath)) @@ -132,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)) @@ -262,12 +267,13 @@ class AnsibleProvisioningTests(OSIntegrationTestCase): ssh = ansible_utils.ssh_client(ip, user, priv_key, self.os_creds.proxy_settings) self.assertIsNotNone(ssh) - + scp = None try: scp = SCPClient(ssh.get_transport()) scp.get('~/hello.txt', self.test_file_local_path) finally: - scp.close() + if scp: + scp.close() ssh.close() self.assertTrue(os.path.isfile(self.test_file_local_path)) @@ -326,12 +332,14 @@ class AnsibleProvisioningTests(OSIntegrationTestCase): ssh = ansible_utils.ssh_client(ip, user, priv_key, self.os_creds.proxy_settings) self.assertIsNotNone(ssh) + scp = None try: scp = SCPClient(ssh.get_transport()) scp.get('/tmp/hello.txt', self.test_file_local_path) finally: - scp.close() + if scp: + scp.close() ssh.close() self.assertTrue(os.path.isfile(self.test_file_local_path)) diff --git a/snaps/test_suite_builder.py b/snaps/test_suite_builder.py index 6ee9099..2d2427f 100644 --- a/snaps/test_suite_builder.py +++ b/snaps/test_suite_builder.py @@ -16,6 +16,19 @@ 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 +from snaps.config.tests.stack_tests import StackConfigUnitTests +from snaps.config.tests.router_tests import RouterConfigUnitTests +from snaps.config.tests.user_tests import UserConfigUnitTests +from snaps.config.tests.project_tests import ProjectConfigUnitTests +from snaps.config.tests.keypair_tests import KeypairConfigUnitTests +from snaps.config.tests.flavor_tests import FlavorConfigUnitTests +import snaps.config.tests.image_tests as image_tests +import snaps.openstack.tests.create_image_tests as creator_tests from snaps.domain.test.flavor_tests import FlavorDomainObjectTests from snaps.domain.test.image_tests import ImageDomainObjectTests from snaps.domain.test.keypair_tests import KeypairDomainObjectTests @@ -40,7 +53,7 @@ from snaps.openstack.tests.conf.os_credentials_tests import ( from snaps.openstack.tests.create_flavor_tests import ( CreateFlavorTests, FlavorSettingsUnitTests) from snaps.openstack.tests.create_image_tests import ( - CreateImageSuccessTests, CreateImageNegativeTests, ImageSettingsUnitTests, + CreateImageSuccessTests, CreateImageNegativeTests, CreateMultiPartImageTests) from snaps.openstack.tests.create_instance_tests import ( CreateInstanceSingleNetworkTests, CreateInstancePubPrivNetTests, @@ -132,22 +145,32 @@ def add_unit_tests(suite): suite.addTest(unittest.TestLoader().loadTestsFromTestCase( SecurityGroupRuleDomainObjectTests)) suite.addTest(unittest.TestLoader().loadTestsFromTestCase( - ImageSettingsUnitTests)) + image_tests.ImageConfigUnitTests)) + suite.addTest(unittest.TestLoader().loadTestsFromTestCase( + creator_tests.ImageSettingsUnitTests)) suite.addTest(unittest.TestLoader().loadTestsFromTestCase( ImageDomainObjectTests)) suite.addTest(unittest.TestLoader().loadTestsFromTestCase( + FlavorConfigUnitTests)) + suite.addTest(unittest.TestLoader().loadTestsFromTestCase( FlavorSettingsUnitTests)) suite.addTest(unittest.TestLoader().loadTestsFromTestCase( FlavorDomainObjectTests)) suite.addTest(unittest.TestLoader().loadTestsFromTestCase( + KeypairConfigUnitTests)) + suite.addTest(unittest.TestLoader().loadTestsFromTestCase( KeypairSettingsUnitTests)) suite.addTest(unittest.TestLoader().loadTestsFromTestCase( KeypairDomainObjectTests)) suite.addTest(unittest.TestLoader().loadTestsFromTestCase( + UserConfigUnitTests)) + suite.addTest(unittest.TestLoader().loadTestsFromTestCase( UserSettingsUnitTests)) suite.addTest(unittest.TestLoader().loadTestsFromTestCase( UserDomainObjectTests)) suite.addTest(unittest.TestLoader().loadTestsFromTestCase( + ProjectConfigUnitTests)) + suite.addTest(unittest.TestLoader().loadTestsFromTestCase( ProjectSettingsUnitTests)) suite.addTest(unittest.TestLoader().loadTestsFromTestCase( ProjectDomainObjectTests)) @@ -160,18 +183,26 @@ def add_unit_tests(suite): 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( PortDomainObjectTests)) suite.addTest(unittest.TestLoader().loadTestsFromTestCase( + RouterConfigUnitTests)) + suite.addTest(unittest.TestLoader().loadTestsFromTestCase( RouterSettingsUnitTests)) suite.addTest(unittest.TestLoader().loadTestsFromTestCase( RouterDomainObjectTests)) @@ -186,6 +217,8 @@ def add_unit_tests(suite): suite.addTest(unittest.TestLoader().loadTestsFromTestCase( ResourceDomainObjectTests)) suite.addTest(unittest.TestLoader().loadTestsFromTestCase( + StackConfigUnitTests)) + suite.addTest(unittest.TestLoader().loadTestsFromTestCase( StackSettingsUnitTests)) suite.addTest(unittest.TestLoader().loadTestsFromTestCase( VolumeTypeDomainObjectTests)) @@ -200,10 +233,16 @@ def add_unit_tests(suite): suite.addTest(unittest.TestLoader().loadTestsFromTestCase( FloatingIpDomainObjectTests)) suite.addTest(unittest.TestLoader().loadTestsFromTestCase( + QoSConfigUnitTests)) + suite.addTest(unittest.TestLoader().loadTestsFromTestCase( QoSSettingsUnitTests)) suite.addTest(unittest.TestLoader().loadTestsFromTestCase( + VolumeTypeConfigUnitTests)) + suite.addTest(unittest.TestLoader().loadTestsFromTestCase( VolumeTypeSettingsUnitTests)) suite.addTest(unittest.TestLoader().loadTestsFromTestCase( + VolumeConfigUnitTests)) + suite.addTest(unittest.TestLoader().loadTestsFromTestCase( VolumeSettingsUnitTests)) suite.addTest(unittest.TestLoader().loadTestsFromTestCase( SettingsUtilsUnitTests)) |