summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--INFO.yaml44
-rw-r--r--docs/conf.py1
-rw-r--r--docs/conf.yaml3
-rw-r--r--docs/how-to-use/APITests.rst14
-rw-r--r--docs/how-to-use/IntegrationTests.rst162
-rw-r--r--docs/how-to-use/LibraryUsage.rst4
-rw-r--r--docs/how-to-use/Testing.rst4
-rw-r--r--docs/how-to-use/VirtEnvDeploy.rst6
-rw-r--r--docs/index.rst16
-rw-r--r--docs/release/release-notes.rst25
-rw-r--r--docs/requirements.txt2
-rw-r--r--examples/complex-network/deploy-complex-network.yaml20
-rw-r--r--examples/external-network/deploy-ext-net.yaml5
-rw-r--r--examples/inst-w-volume/deploy-vm-with-volume.yaml5
-rw-r--r--examples/launch.py4
-rw-r--r--examples/simple/deploy-simple.yaml5
-rw-r--r--examples/two-network/deploy-two-net-centos.yaml5
-rw-r--r--examples/two-network/deploy-two-net-ubuntu.yaml5
-rw-r--r--requirements.txt17
-rw-r--r--setup.cfg4
-rw-r--r--snaps/config/network.py95
-rw-r--r--snaps/config/project.py5
-rw-r--r--snaps/config/router.py78
-rw-r--r--snaps/config/security_group.py55
-rw-r--r--snaps/config/stack.py3
-rw-r--r--snaps/config/tests/network_tests.py17
-rw-r--r--snaps/config/tests/project_tests.py32
-rw-r--r--snaps/config/tests/router_tests.py54
-rw-r--r--snaps/config/tests/volume_tests.py18
-rw-r--r--snaps/config/volume.py4
-rw-r--r--snaps/domain/network.py14
-rw-r--r--snaps/domain/stack.py10
-rw-r--r--snaps/domain/test/network_tests.py40
-rw-r--r--snaps/domain/test/stack_tests.py13
-rw-r--r--snaps/domain/test/vm_inst_tests.py7
-rw-r--r--snaps/domain/test/volume_tests.py9
-rw-r--r--snaps/domain/vm_inst.py11
-rw-r--r--snaps/domain/volume.py11
-rw-r--r--snaps/file_utils.py21
-rw-r--r--snaps/openstack/cluster_template.py2
-rw-r--r--snaps/openstack/create_flavor.py2
-rw-r--r--snaps/openstack/create_image.py10
-rw-r--r--snaps/openstack/create_instance.py212
-rw-r--r--snaps/openstack/create_keypairs.py2
-rw-r--r--snaps/openstack/create_network.py26
-rw-r--r--snaps/openstack/create_project.py83
-rw-r--r--snaps/openstack/create_qos.py2
-rw-r--r--snaps/openstack/create_router.py61
-rw-r--r--snaps/openstack/create_security_group.py23
-rw-r--r--snaps/openstack/create_stack.py180
-rw-r--r--snaps/openstack/create_user.py6
-rw-r--r--snaps/openstack/create_volume.py8
-rw-r--r--snaps/openstack/create_volume_type.py2
-rw-r--r--snaps/openstack/openstack_creator.py46
-rw-r--r--snaps/openstack/os_credentials.py46
-rw-r--r--snaps/openstack/tests/cluster_template_tests.py10
-rw-r--r--snaps/openstack/tests/conf/os_credentials_tests.py29
-rw-r--r--snaps/openstack/tests/conf/os_env.yaml.template5
-rw-r--r--snaps/openstack/tests/create_flavor_tests.py11
-rw-r--r--snaps/openstack/tests/create_image_tests.py10
-rw-r--r--snaps/openstack/tests/create_instance_tests.py520
-rw-r--r--snaps/openstack/tests/create_keypairs_tests.py4
-rw-r--r--snaps/openstack/tests/create_network_tests.py374
-rw-r--r--snaps/openstack/tests/create_project_tests.py46
-rw-r--r--snaps/openstack/tests/create_qos_tests.py24
-rw-r--r--snaps/openstack/tests/create_router_tests.py481
-rw-r--r--snaps/openstack/tests/create_security_group_tests.py168
-rw-r--r--snaps/openstack/tests/create_stack_tests.py364
-rw-r--r--snaps/openstack/tests/create_user_tests.py9
-rw-r--r--snaps/openstack/tests/create_volume_tests.py129
-rw-r--r--snaps/openstack/tests/create_volume_type_tests.py33
-rw-r--r--snaps/openstack/tests/heat/agent-group.yaml8
-rw-r--r--snaps/openstack/tests/heat/agent.yaml1
-rw-r--r--snaps/openstack/tests/heat/floating_ip_heat_template.yaml27
-rw-r--r--snaps/openstack/tests/openstack_tests.py105
-rw-r--r--snaps/openstack/tests/os_source_file_test.py86
-rw-r--r--snaps/openstack/utils/__init__.py3
-rw-r--r--snaps/openstack/utils/cinder_utils.py104
-rw-r--r--snaps/openstack/utils/glance_utils.py9
-rw-r--r--snaps/openstack/utils/heat_utils.py142
-rw-r--r--snaps/openstack/utils/keystone_utils.py66
-rw-r--r--snaps/openstack/utils/launch_utils.py160
-rw-r--r--snaps/openstack/utils/magnum_utils.py9
-rw-r--r--snaps/openstack/utils/neutron_utils.py219
-rw-r--r--snaps/openstack/utils/nova_utils.py167
-rw-r--r--snaps/openstack/utils/settings_utils.py16
-rw-r--r--snaps/openstack/utils/tests/cinder_utils_tests.py43
-rw-r--r--snaps/openstack/utils/tests/glance_utils_tests.py7
-rw-r--r--snaps/openstack/utils/tests/heat_utils_tests.py103
-rw-r--r--snaps/openstack/utils/tests/keystone_utils_tests.py22
-rw-r--r--snaps/openstack/utils/tests/magnum_utils_tests.py8
-rw-r--r--snaps/openstack/utils/tests/neutron_utils_tests.py286
-rw-r--r--snaps/openstack/utils/tests/nova_utils_tests.py220
-rw-r--r--snaps/openstack/utils/tests/settings_utils_tests.py33
-rw-r--r--snaps/playbook_runner.py48
-rw-r--r--snaps/provisioning/ansible_utils.py108
-rw-r--r--snaps/provisioning/tests/ansible_utils_tests.py39
-rw-r--r--snaps/test_runner.py177
-rw-r--r--snaps/test_suite_builder.py98
-rw-r--r--snaps/tests/file_utils_tests.py4
-rw-r--r--snaps/thread_utils.py27
-rw-r--r--tox.ini17
103 files changed, 4700 insertions, 1440 deletions
diff --git a/.gitignore b/.gitignore
index b3c2444..9292c06 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,5 @@
*.*project
build
dist
+.tox
+docs/_build/*
diff --git a/INFO.yaml b/INFO.yaml
new file mode 100644
index 0000000..b29addf
--- /dev/null
+++ b/INFO.yaml
@@ -0,0 +1,44 @@
+---
+project: 'SNAPS-OO'
+project_creation_date: '07.02.2017'
+project_category: ''
+lifecycle_state: 'Incubation'
+project_lead: &opnfv_snaps_ptl
+ name: 'Steven Pisarski'
+ email: 's.pisarski@cablelabs.com'
+ id: 'spisarski'
+ company: 'cablelabs.com'
+ timezone: 'Unknown'
+primary_contact: *opnfv_snaps_ptl
+issue_tracking:
+ type: 'jira'
+ url: 'https://jira.opnfv.org/projects/SNAPS'
+ key: 'SNAPS'
+mailing_list:
+ type: 'mailman2'
+ url: 'opnfv-tech-discuss@lists.opnfv.org'
+ tag: '[snaps]'
+realtime_discussion:
+ type: irc
+ server: 'freenode.net'
+ channel: '#opnfv-snaps'
+meetings:
+ - type: 'gotomeeting+irc'
+ agenda: # eg: 'https://wiki.opnfv.org/display/'
+ url: # eg: 'https://global.gotomeeting.com/join/819733085'
+ server: 'freenode.net'
+ channel: '#opnfv-meeting'
+ repeats: 'weekly'
+ time: # eg: '16:00 UTC'
+repositories:
+ - 'snaps'
+committers:
+ - <<: *opnfv_snaps_ptl
+ - name: 'Randy Levensalor'
+ email: 'r.levensalor@cablelabs.com'
+ company: 'cablelabs.com'
+ id: 'RandyL'
+tsc:
+ # yamllint disable rule:line-length
+ approval: 'http//meetbot.opnfv.org/meetings/opnfv-meeting/2017/opnfv-meeting.2017-02-07-15.00.html'
+ # yamllint enable rule:line-length
diff --git a/docs/conf.py b/docs/conf.py
new file mode 100644
index 0000000..3c4453e
--- /dev/null
+++ b/docs/conf.py
@@ -0,0 +1 @@
+from docs_conf.conf import *
diff --git a/docs/conf.yaml b/docs/conf.yaml
new file mode 100644
index 0000000..0bb596d
--- /dev/null
+++ b/docs/conf.yaml
@@ -0,0 +1,3 @@
+---
+project_cfg: opnfv
+project: SNAPS
diff --git a/docs/how-to-use/APITests.rst b/docs/how-to-use/APITests.rst
index 50cd437..9f46839 100644
--- a/docs/how-to-use/APITests.rst
+++ b/docs/how-to-use/APITests.rst
@@ -104,6 +104,9 @@ create_project_tests.py - CreateProjectSuccessTests
| test_create_project | 2 & 3 | Tests the creation of a project via the OpenStackProject |
| | | class |
+----------------------------------+---------------+-----------------------------------------------------------+
+| test_create_project_quota | 2 & 3 | Tests the creation of a project via the OpenStackProject |
+| _override | | class with overriding the default quota values |
++----------------------------------+---------------+-----------------------------------------------------------+
| test_create_project_2x | 2 & 3 | Tests the creation of a project a second time via the |
| | | OpenStackProject class to ensure it is only created once |
+----------------------------------+---------------+-----------------------------------------------------------+
@@ -435,7 +438,16 @@ nova_utils_tests.py - NovaUtilsInstanceVolumeTests
| Test Name | Nova API | Description |
+=======================================+===============+===========================================================+
| test_add_remove_volume | 2 | Ensures that a VM instance can properly attach and detach |
-| | | a volume using the nova interface |
+| | | a volume using the nova interface while waiting for |
+| | | the update to fully occur |
++---------------------------------------+---------------+-----------------------------------------------------------+
+| test_attach_volume_nowait | 2 | Ensures that the call to nova_utils.attach_volume raises |
+| | | an exception when the timeout is too short to return an |
+| | | properly updated VmInst object |
++---------------------------------------+---------------+-----------------------------------------------------------+
+| test_detach_volume_nowait | 2 | Ensures that the call to nova_utils.detach_volume raises |
+| | | an exception when the timeout is too short to return an |
+| | | properly updated VmInst object |
+---------------------------------------+---------------+-----------------------------------------------------------+
create_flavor_tests.py - CreateFlavorTests
diff --git a/docs/how-to-use/IntegrationTests.rst b/docs/how-to-use/IntegrationTests.rst
index eb627ad..79ef8ef 100644
--- a/docs/how-to-use/IntegrationTests.rst
+++ b/docs/how-to-use/IntegrationTests.rst
@@ -46,6 +46,17 @@ create_security_group_tests.py - CreateSecurityGroupTests
| | | setting object |
+---------------------------------------+---------------+-----------------------------------------------------------+
+create_security_group_tests.py - CreateMultipleSecurityGroupTests
+-----------------------------------------------------------------
+
++---------------------------------------+---------------+-----------------------------------------------------------+
+| Test Name | API Versions | Description |
++=======================================+===============+===========================================================+
+| test_sec_grp_same_name_diff_proj | Keysone 2 & 3 | Ensures the OpenStackSecurityGroup class does not |
+| | Neutron 2 | initialize security groups with the same name from other |
+| | | project/tenants |
++---------------------------------------+---------------+-----------------------------------------------------------+
+
create_image_tests.py - CreateImageSuccessTests
-----------------------------------------------
@@ -144,7 +155,7 @@ create_keypairs_tests.py - CreateKeypairsCleanupTests
| test_create_keypair_gen_files_delete_1| 2 | Ensures that new keypair files are deleted by default |
| | | by OpenStackKeypair#clean() |
+---------------------------------------+---------------+-----------------------------------------------------------+
-| test_create_keypair_gen_files_delete_2| 2 | Ensures that new keypair files are deleted by |
+| test_create_keypair_gen_files_delete_2| 2 | Ensures that new keypair files are deleted by |
| | | OpenStackKeypair#clean() when the settings delete_on_clean|
| | | attribute is set to True |
+---------------------------------------+---------------+-----------------------------------------------------------+
@@ -185,6 +196,25 @@ create_network_tests.py - CreateNetworkSuccessTests
| | | 'admin' project ID |
+---------------------------------------+---------------+-----------------------------------------------------------+
+create_network_tests.py - CreateNetworkGatewayTests
+---------------------------------------------------
+
++---------------------------------------+---------------+-----------------------------------------------------------+
+| Test Name | Neutron API | Description |
++=======================================+===============+===========================================================+
+| test_create_subnet_default_gateway_ip | 2 | Ensures that a network can be created with a Subnet that |
+| | | has the gateway_ip automatically assigned |
++---------------------------------------+---------------+-----------------------------------------------------------+
+| test_create_subnet_valid_gateway_ip | 2 | Ensures that a network can be created with a Subnet that |
+| | | has the gateway_ip statically assigned with a valid IP |
++---------------------------------------+---------------+-----------------------------------------------------------+
+| test_create_subnet_no_gateway | 2 | Ensures that a network can be created where no gateway_ip |
+| | | is assigned |
++---------------------------------------+---------------+-----------------------------------------------------------+
+| test_create_subnet_invalid_gateway_ip | 2 | Ensures that a network cannot be created with a Subnet |
+| | | has an invalid gateway_ip value such as 'foo' |
++---------------------------------------+---------------+-----------------------------------------------------------+
+
create_network_tests.py - CreateNetworkIPv6Tests
------------------------------------------------
@@ -197,6 +227,21 @@ create_network_tests.py - CreateNetworkIPv6Tests
| | | IPv6 subnet |
+---------------------------------------+---------------+-----------------------------------------------------------+
+create_network_tests.py - CreateMultipleNetworkTests
+----------------------------------------------------
+
++---------------------------------------+---------------+-----------------------------------------------------------+
+| Test Name | Neutron API | Description |
++=======================================+===============+===========================================================+
+| test_network_same_name_diff_proj | 2 | Ensures that a network with the same name can be created |
+| | | against different projects |
++---------------------------------------+---------------+-----------------------------------------------------------+
+| test_network_create_by_admin_to | 2 | Ensures that a network can be created by the admin user |
+| _different_project | | to another project and that a creator with the credentials|
+| | | to the other project will not create a new network with |
+| | | the same name |
++---------------------------------------+---------------+-----------------------------------------------------------+
+
create_router_tests.py - CreateRouterSuccessTests
-------------------------------------------------
@@ -215,6 +260,12 @@ create_router_tests.py - CreateRouterSuccessTests
| test_create_delete_router | 2 | Ensures that a router can be deleted via the |
| | | OpenStackRouter.clean() method |
+---------------------------------------+---------------+-----------------------------------------------------------+
+| test_create_with_internal_sub | 2 | Ensures that a router can be joined to a subnet created by|
+| | | the same user who created the subnet |
++---------------------------------------+---------------+-----------------------------------------------------------+
+| test_create_with_invalid_internal_sub | 2 | Ensures that a router cannot be created when attempting to|
+| | | join a subnet created by the admin user |
++---------------------------------------+---------------+-----------------------------------------------------------+
| test_create_router_admin_state_false | 2 | Ensures that a router can created with |
| | | admin_state_up = False |
+---------------------------------------+---------------+-----------------------------------------------------------+
@@ -227,6 +278,9 @@ create_router_tests.py - CreateRouterSuccessTests
| test_create_router_external_network | 2 | Ensures that a router can be created that is connected to |
| | | both external and private internal networks |
+---------------------------------------+---------------+-----------------------------------------------------------+
+| test_create_router_with_ext_port | 2 | Ensures that a router can be created by an 'admin' user |
+| | | with a port to an external network |
++---------------------------------------+---------------+-----------------------------------------------------------+
create_router_tests.py - CreateRouterNegativeTests
--------------------------------------------------
@@ -240,6 +294,51 @@ create_router_tests.py - CreateRouterNegativeTests
| test_create_router_invalid_gateway_name| 2 | Ensures that an exception is raised when attempting to |
| | | create a router to an external network that does not exist|
+----------------------------------------+---------------+-----------------------------------------------------------+
+| test_create_router_admin_ports | 2 | Ensures that an exception is raised when attempting to |
+| | | create a router with ports to networks owned by another |
+| | | project |
++----------------------------------------+---------------+-----------------------------------------------------------+
+
+create_router_tests.py - CreateMultipleRouterTests
+--------------------------------------------------
+
++---------------------------------------+---------------+-----------------------------------------------------------+
+| Test Name | Neutron API | Description |
++=======================================+===============+===========================================================+
+| test_router_same_name_diff_proj | 2 | Ensures that a router with the same name can be created |
+| | | against different projects |
++---------------------------------------+---------------+-----------------------------------------------------------+
+| test_router_create_by_admin_to | 2 | Ensures that a router can be created by the admin user |
+| _different_project | | to another project and that a creator with the credentials|
+| | | to the other project will not create a new router with |
+| | | the same name |
++---------------------------------------+---------------+-----------------------------------------------------------+
+
+create_router_tests.py - CreateRouterSecurityGroupTests
+-------------------------------------------------------
+
++---------------------------------------+---------------+-----------------------------------------------------------+
+| Test Name | Neutron API | Description |
++=======================================+===============+===========================================================+
+| test_create_router_secure_port | 2 | Ensures that a router's port can have a security group |
+| | | applied to it |
++---------------------------------------+---------------+-----------------------------------------------------------+
+
+create_router_tests.py - CreateRouterSharedNetworksTests
+--------------------------------------------------------
+
++---------------------------------------+---------------+-----------------------------------------------------------+
+| Test Name | Neutron API | Description |
++=======================================+===============+===========================================================+
+| test_create_router_external | 2 | Ensures that a router can be joined to an external network|
+| | | that was created by an admin user |
++---------------------------------------+---------------+-----------------------------------------------------------+
+| test_create_router_port_external | 2 | Ensures that a router can have a port created to an |
+| | | external network that was created by an admin user |
++---------------------------------------+---------------+-----------------------------------------------------------+
+| test_create_router_port_shared | 2 | Ensures that a router can have a port created to an |
+| | | shared network that was created by an admin user |
++---------------------------------------+---------------+-----------------------------------------------------------+
create_qos_tests.py - CreateQoSTests
------------------------------------
@@ -332,9 +431,6 @@ create_volume_tests.py - CreateSimpleVolumeFailureTests
| test_create_volume_bad_image | 2 & 3 | Tests to ensure that attempting to create a volume with an|
| | | image that does not exist raises a BadRequest exception |
+----------------------------------------+---------------+-----------------------------------------------------------+
-| test_create_volume_bad_zone | 2 & 3 | Tests to ensure that attempting to create a volume with an|
-| | | invalid availability zone raises a BadRequest exception |
-+----------------------------------------+---------------+-----------------------------------------------------------+
create_volume_tests.py - CreateVolumeWithTypeTests
--------------------------------------------------
@@ -368,6 +464,25 @@ create_volume_tests.py - CreateVolumeWithImageTests
| | | volume when associating with a valid image |
+----------------------------------------+---------------+-----------------------------------------------------------+
+create_volume_tests.py - CreateVolMultipleCredsTests
+----------------------------------------------------
+
++----------------------------------------+---------------+-----------------------------------------------------------+
+| Test Name | Cinder API | Description |
++========================================+===============+===========================================================+
+| test_create_by_admin_to_other_proj | 2 & 3 | Tests to ensure the creation of a Volume as a user with |
+| | | an 'admin' role can create a volume to another project |
+| | | and a creator with the credentails to that project will |
+| | | not create another with the same name |
+| | | Currently inactive due to |
+| | | https://bugs.launchpad.net/cinder/+bug/1641982 |
++----------------------------------------+---------------+-----------------------------------------------------------+
+| test_create_two_vol_same_name_diff_proj| 2 & 3 | Tests to ensure the creation of a Volume with the same |
+| | | name by two different creators with different credentials |
+| | | will create two different volumes with the same name |
+| | | that are applied to each project in question |
++----------------------------------------+---------------+-----------------------------------------------------------+
+
create_stack_tests.py - CreateStackSuccessTests
-----------------------------------------------
@@ -418,6 +533,12 @@ create_stack_tests.py - CreateStackFloatingIpTests
| | | VM with a floating IP that can be accessed via |
| | | OpenStackVmInstance |
+---------------------------------------+---------------+-----------------------------------------------------------+
+| test_connect_via_ssh_heat_vm_derived | 1 | Ensures that an OpenStackHeatStack instance can create a |
+| | | VM with a floating IP where a generated initialized |
+| | | OpenStackHeatStack can return an initialized |
+| | | OpenStackVmInstance object that will be used to access the|
+| | | VM via SSH |
++---------------------------------------+---------------+-----------------------------------------------------------+
create_stack_tests.py - CreateStackNestedResourceTests
------------------------------------------------------
@@ -431,6 +552,17 @@ create_stack_tests.py - CreateStackNestedResourceTests
| | | initialized OpenStackVmInstance objects |
+---------------------------------------+---------------+-----------------------------------------------------------+
+create_stack_tests.py - CreateStackUpdateTests
+----------------------------------------------
+
++---------------------------------------+---------------+-----------------------------------------------------------+
+| Test Name | Heat API | Description |
++=======================================+===============+===========================================================+
+| test_update | 1 | Ensures that an OpenStackHeatStack can have the number of |
+| | | VMs updated and they are spawned and access can be |
+| | | obtained with SSH over floating IPs |
++---------------------------------------+---------------+-----------------------------------------------------------+
+
create_stack_tests.py - CreateStackRouterTests
----------------------------------------------
@@ -516,7 +648,21 @@ create_instance_tests.py - CreateInstanceSimpleTests
| Test Name | API Versions | Description |
+=======================================+===============+===========================================================+
| test_create_delete_instance | Nova 2 | Ensures that the OpenStackVmInstance.clean() method |
-| | Neutron 2 | deletes the instance |
+| | Neutron 2 | deletes the instance as well as ensuring the VmInst |
+| | | availability_zone is populated and compute_host is None |
++---------------------------------------+---------------+-----------------------------------------------------------+
+| test_create_admin_instance | Nova 2 | Ensures that the VmInst object members availability_zone |
+| | Neutron 2 | and compute_host return a value |
++---------------------------------------+---------------+-----------------------------------------------------------+
+
+create_instance_tests.py - CreateInstanceExternalNetTests
+---------------------------------------------------------
+
++---------------------------------------+---------------+-----------------------------------------------------------+
+| Test Name | API Versions | Description |
++=======================================+===============+===========================================================+
+| test_create_instance_public_net | Nova 2 | Ensures that an OpenStackVmInstance initialized as a user |
+| | Neutron 2 | of type 'admin' can create a VM against an external net |
+---------------------------------------+---------------+-----------------------------------------------------------+
create_instance_tests.py - SimpleHealthCheck
@@ -576,6 +722,12 @@ create_instance_tests.py - CreateInstancePortManipulationTests
| test_set_custom_valid_ip_one_subnet | Nova 2 | Ensures that an instance's can have a valid static IP is |
| | Neutron 2 | properly assigned |
+---------------------------------------+---------------+-----------------------------------------------------------+
+| test_set_one_port_two_ip_one_subnet | Nova 2 | Ensures that an instance can have two static IPs on a |
+| | Neutron 2 | single port from a single subnet |
++---------------------------------------+---------------+-----------------------------------------------------------+
+| test_set_one_port_two_ip_two_subnets | Nova 2 | Ensures that an instance can have two static IPs on a |
+| | Neutron 2 | single port from different subnets on a network |
++---------------------------------------+---------------+-----------------------------------------------------------+
| test_set_custom_invalid_ip_one_subnet | Nova 2 | Ensures that an instance's port with an invalid static IP |
| | Neutron 2 | raises an exception |
+---------------------------------------+---------------+-----------------------------------------------------------+
diff --git a/docs/how-to-use/LibraryUsage.rst b/docs/how-to-use/LibraryUsage.rst
index aa7bf91..3183305 100644
--- a/docs/how-to-use/LibraryUsage.rst
+++ b/docs/how-to-use/LibraryUsage.rst
@@ -154,6 +154,10 @@ Create Flavor
- is\_public - flag that denotes whether or not other projects
can access image (default=True)
- metadata - freeform dict() for special metadata (optional)
+ - freeform dict() for values of basic elements
+ (e.g. ram, vcpu, disk, etc) could be added.
+ As result the hard coded values of those elements will be
+ overwritten by the new ones (optional)
.. code:: python
diff --git a/docs/how-to-use/Testing.rst b/docs/how-to-use/Testing.rst
index 92340ab..8e08abb 100644
--- a/docs/how-to-use/Testing.rst
+++ b/docs/how-to-use/Testing.rst
@@ -26,6 +26,8 @@ Execute the tests
| \* -f [optional - When set, will execute tests requiring Floating
IPS]
| \* -im [optional - File containing image endpoints to override
-| \* -fm [optional - JSON string containing a dict() for flavor metadata default='{\"hw:mem_page_size\": \"any\"}']
+| \* -fm [optional - JSON string containing a dict(): - for flavor metadata default='{\"hw:mem_page_size\": \"any\"}'
+ - for values of basic elements (e.g. ram, vcpu, disk, etc) could be added.
+ As result the hard coded values of those elements will be overwritten by the new ones]
| \* -ci [optional - runs the tests required by SNAPS-OO CI]
| \* -r [optional with default value of '1' - The number of test iterations to execute]
diff --git a/docs/how-to-use/VirtEnvDeploy.rst b/docs/how-to-use/VirtEnvDeploy.rst
index 6c99992..0345f34 100644
--- a/docs/how-to-use/VirtEnvDeploy.rst
+++ b/docs/how-to-use/VirtEnvDeploy.rst
@@ -121,7 +121,11 @@ Use launcher.py to deploy and clean up example environments. These examples are
- rxtx\_factor: the receive/transmit factor to be set on ports if
backend supports QoS extension (default 1.0)
- is\_public: denotes whether or not the flavor is public (default = True)
- - metadata: freeform dict() for special metadata (optional)
+ - metadata: - freeform dict() for special metadata (optional)
+ - freeform dict() for values of basic elements
+ (e.g. ram, vcpu, disk, etc) could be added.
+ As result the hard coded values of those elements will be
+ overwritten by the new ones (optional)
- qos_specs: the QoS Specs to create
diff --git a/docs/index.rst b/docs/index.rst
new file mode 100644
index 0000000..aceb2fc
--- /dev/null
+++ b/docs/index.rst
@@ -0,0 +1,16 @@
+.. _snaps:
+
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
+.. http://creativecommons.org/licenses/by/4.0
+.. SPDX-License-Identifier CC-BY-4.0
+.. (c) Open Platform for NFV Project, Inc. and its contributors
+
+*********************************
+OPNFV Snaps
+*********************************
+
+.. toctree::
+ :numbered:
+ :maxdepth: 3
+
+ /how-to-use/index
diff --git a/docs/release/release-notes.rst b/docs/release/release-notes.rst
new file mode 100644
index 0000000..d682dd9
--- /dev/null
+++ b/docs/release/release-notes.rst
@@ -0,0 +1,25 @@
+=================
+SNAPS-OO in OPNFV
+=================
+
+Introduction
+============
+
+SNAPS-OO is a object-oriented library designed for managing objects deployed
+on OpenStack. In addition to its ability to deploy and manage objects, this
+project also contains many API and integration tests that can be used to
+validate your OpenStack cloud. Also included is a lightweight orchestrator that
+can be used for rapid prototyping virtual environments.
+
+Installation
+============
+
+To use SNAPS-OO, it must first be installed into your Python 2.7-3.5 runtime.
+To install:
+
+pip install -e <SNAPS-OO directory>
+
+Using SNAPS-OO
+==============
+
+Please refer to the RST documents in ../how-to-use \ No newline at end of file
diff --git a/docs/requirements.txt b/docs/requirements.txt
new file mode 100644
index 0000000..9fde2df
--- /dev/null
+++ b/docs/requirements.txt
@@ -0,0 +1,2 @@
+lfdocs-conf
+sphinx_opnfv_theme
diff --git a/examples/complex-network/deploy-complex-network.yaml b/examples/complex-network/deploy-complex-network.yaml
index 7915c38..be38794 100644
--- a/examples/complex-network/deploy-complex-network.yaml
+++ b/examples/complex-network/deploy-complex-network.yaml
@@ -70,8 +70,14 @@ openstack:
name: mgr-router
external_gateway: external
internal_subnets:
- - mgr-subnet
- - mgr-subnet-2
+ - subnet:
+ project_name: admin
+ network_name: mgr-net
+ subnet_name: mgr-subnet
+ - subnet:
+ project_name: admin
+ network_name: mgr-net
+ subnet_name: mgr-subnet-2
interfaces:
- port:
name: mgr-router-to-site1
@@ -83,12 +89,18 @@ openstack:
name: site1-router
external_gateway: external
internal_subnets:
- - site1-subnet
+ - subnet:
+ project_name: admin
+ network_name: site1-net
+ subnet_name: site1-subnet
- router:
name: site2-router
external_gateway: external
internal_subnets:
- - site2-subnet
+ - subnet:
+ project_name: admin
+ network_name: site2-net
+ subnet_name: site2-subnet
- router:
name: site-to-site-router
interfaces:
diff --git a/examples/external-network/deploy-ext-net.yaml b/examples/external-network/deploy-ext-net.yaml
index ac5e214..b5f00b1 100644
--- a/examples/external-network/deploy-ext-net.yaml
+++ b/examples/external-network/deploy-ext-net.yaml
@@ -52,7 +52,10 @@ openstack:
name: ext-net-router
external_gateway: ext-net
internal_subnets:
- - internal-subnet
+ - subnet:
+ project_name: admin
+ network_name: internal-net
+ subnet_name: internal-subnet
keypairs:
- keypair:
name: ext-net-kp
diff --git a/examples/inst-w-volume/deploy-vm-with-volume.yaml b/examples/inst-w-volume/deploy-vm-with-volume.yaml
index 30dbcc0..b15f655 100644
--- a/examples/inst-w-volume/deploy-vm-with-volume.yaml
+++ b/examples/inst-w-volume/deploy-vm-with-volume.yaml
@@ -95,7 +95,10 @@ openstack:
name: {{ router_name }}
external_gateway: {{ ext_net }}
internal_subnets:
- - {{ subnet_name }}
+ - subnet:
+ project_name: {{ admin_proj }}
+ network_name: {{ net_name }}
+ subnet_name: {{ subnet_name }}
keypairs:
- keypair:
os_user:
diff --git a/examples/launch.py b/examples/launch.py
index 04bc5d6..cfd7f65 100644
--- a/examples/launch.py
+++ b/examples/launch.py
@@ -32,6 +32,10 @@ logger = logging.getLogger('snaps_launcher')
ARG_NOT_SET = "argument not set"
+from warnings import warn
+warn('This script will be removed in a subsequent release',
+ DeprecationWarning)
+
def main(arguments):
"""
diff --git a/examples/simple/deploy-simple.yaml b/examples/simple/deploy-simple.yaml
index 3124210..fa4c8b2 100644
--- a/examples/simple/deploy-simple.yaml
+++ b/examples/simple/deploy-simple.yaml
@@ -41,7 +41,10 @@ openstack:
name: simple-router
external_gateway: external
internal_subnets:
- - simple-subnet
+ - subnet:
+ project_name: admin
+ network_name: simple-net
+ subnet_name: simple-subnet
keypairs:
- keypair:
name: simple-kp
diff --git a/examples/two-network/deploy-two-net-centos.yaml b/examples/two-network/deploy-two-net-centos.yaml
index 4b5ba89..d23fff9 100644
--- a/examples/two-network/deploy-two-net-centos.yaml
+++ b/examples/two-network/deploy-two-net-centos.yaml
@@ -48,7 +48,10 @@ openstack:
name: router-1
external_gateway: external
internal_subnets:
- - subnet-1
+ - subnet:
+ project_name: admin
+ network_name: net-1
+ subnet_name: subnet-1
keypairs:
- keypair:
name: two-net
diff --git a/examples/two-network/deploy-two-net-ubuntu.yaml b/examples/two-network/deploy-two-net-ubuntu.yaml
index 0ad471c..0381bff 100644
--- a/examples/two-network/deploy-two-net-ubuntu.yaml
+++ b/examples/two-network/deploy-two-net-ubuntu.yaml
@@ -48,7 +48,10 @@ openstack:
name: router-1
external_gateway: external
internal_subnets:
- - subnet-1
+ - subnet:
+ project_name: admin
+ network_name: net-1
+ subnet_name: subnet-1
keypairs:
- keypair:
name: simple
diff --git a/requirements.txt b/requirements.txt
index 137159f..6721540 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,14 +1,17 @@
# The order of packages is significant, because pip processes them in the order
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
-python-novaclient>=9.0.0 # Apache-2.0
-python-neutronclient>=6.3.0 # Apache-2.0
+python-novaclient>=9.1.0 # Apache-2.0
+python-neutronclient>=6.7.0 # Apache-2.0
python-keystoneclient>=3.8.0 # Apache-2.0
python-glanceclient>=2.8.0 # Apache-2.0
-python-heatclient>=1.6.1 # Apache-2.0
-python-cinderclient>=3.1.0 # Apache-2.0
-python-magnumclient>=2.0.0 # Apache-2.0
-ansible<2.4,>=2.1.0
+python-heatclient>=1.10.0 # Apache-2.0
+python-cinderclient>=3.3.0 # Apache-2.0
+python-magnumclient>=2.1.0,<2.3 # Apache-2.0
+ansible>=2.4
wrapt>=1.7.0 # BSD License
scp
-cryptography!=2.0,>=1.6 # BSD/Apache-2.0
+cryptography>=2.1 # BSD/Apache-2.0
+concurrencytest
+Jinja2 # BSD License (3 clause)
+keystoneauth1 # Apache-2.0
diff --git a/setup.cfg b/setup.cfg
index c999c81..3d42cd7 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,6 +1,6 @@
[metadata]
-name = snaps
-version = 1.0
+name = snaps-oo
+version = 7.0.0
home-page = https://gerrit.opnfv.org/gerrit/gitweb?p=snaps.git;a=summary
author = Steve Pisarski
author-email = s.pisarski@cablelabs.com
diff --git a/snaps/config/network.py b/snaps/config/network.py
index 39a4254..b142480 100644
--- a/snaps/config/network.py
+++ b/snaps/config/network.py
@@ -46,6 +46,7 @@ class NetworkConfig(object):
: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.
+ :param mtu: MTU setting (optional)
:return:
"""
@@ -88,6 +89,8 @@ class NetworkConfig(object):
if not self.name or len(self.name) < 1:
raise NetworkConfigError('Name required for networks')
+ self.mtu = kwargs.get('mtu')
+
def get_project_id(self, os_creds):
"""
Returns the project ID for a given project_name or None
@@ -98,11 +101,15 @@ class NetworkConfig(object):
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
+ session = keystone_utils.keystone_session(os_creds)
+ keystone = keystone_utils.keystone_client(os_creds, session)
+ try:
+ project = keystone_utils.get_project(
+ keystone=keystone, project_name=self.project_name)
+ if project:
+ return project.id
+ finally:
+ keystone_utils.close_session(session)
return None
@@ -140,6 +147,8 @@ class NetworkConfig(object):
out['provider:segmentation_id'] = self.segmentation_id
if self.external:
out['router:external'] = self.external
+ if self.mtu:
+ out['mtu'] = self.mtu
return {'network': out}
@@ -175,14 +184,17 @@ class SubnetConfig(object):
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 gateway_ip: The gateway IP address (optional). When not
+ configured, the IP address will be automatically
+ assigned; when 'none', no gateway address will be
+ assigned, else the value must be valid
: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')
+ (default [])
:param host_routes: A list of host route dictionaries for the subnet.
For example:
"host_routes":[
@@ -221,10 +233,7 @@ class SubnetConfig(object):
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.dns_nameservers = list()
self.host_routes = kwargs.get('host_routes')
self.destination = kwargs.get('destination')
@@ -255,9 +264,13 @@ class SubnetConfig(object):
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)
+ session = keystone_utils.keystone_session(os_creds)
+ keystone = keystone_utils.keystone_client(os_creds, session)
+ try:
+ project = keystone_utils.get_project(
+ keystone=keystone, project_name=self.project_name)
+ finally:
+ keystone_utils.close_session(session)
project_id = None
if project:
project_id = project.id
@@ -270,7 +283,10 @@ class SubnetConfig(object):
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.gateway_ip == 'none':
+ out['gateway_ip'] = None
+ else:
+ 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:
@@ -401,22 +417,23 @@ class PortConfig(object):
raise PortConfigError(
'The attribute network_name is required')
- def __get_fixed_ips(self, neutron):
+ def __get_fixed_ips(self, neutron, network):
"""
Sets the self.fixed_ips value
:param neutron: the Neutron client
+ :param network: the SNAPS-OO network domain object
: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})
+ neutron, network, subnet_name=ip_addr_dict['subnet_name'])
+ if subnet:
+ if '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 '
@@ -435,22 +452,28 @@ class PortConfig(object):
:param os_creds: the OpenStack credentials
:return: the dictionary object
"""
-
out = dict()
+ session = keystone_utils.keystone_session(os_creds)
+ keystone = keystone_utils.keystone_client(os_creds, session)
- project_id = None
+ project_name = os_creds.project_name
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
+ project_name = project_name
+ try:
+ network = neutron_utils.get_network(
+ neutron, keystone, network_name=self.network_name)
+ if network and not (network.shared or network.external):
+ network = neutron_utils.get_network(
+ neutron, keystone, network_name=self.network_name,
+ project_name=project_name)
+ finally:
+ if session:
+ keystone_utils.close_session(session)
- 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)
+ 'Cannot locate network with name - ' + self.network_name
+ + ' in project - ' + str(project_name))
out['network_id'] = network.id
@@ -459,6 +482,11 @@ class PortConfig(object):
if self.name:
out['name'] = self.name
if self.project_name:
+ 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:
@@ -468,7 +496,7 @@ class PortConfig(object):
if self.mac_address:
out['mac_address'] = self.mac_address
- fixed_ips = self.__get_fixed_ips(neutron)
+ fixed_ips = self.__get_fixed_ips(neutron, network)
if fixed_ips and len(fixed_ips) > 0:
out['fixed_ips'] = fixed_ips
@@ -476,7 +504,8 @@ class PortConfig(object):
sec_grp_ids = list()
for sec_grp_name in self.security_groups:
sec_grp = neutron_utils.get_security_group(
- neutron, sec_grp_name=sec_grp_name)
+ neutron, keystone, sec_grp_name=sec_grp_name,
+ project_name=self.project_name)
if sec_grp:
sec_grp_ids.append(sec_grp.id)
out['security_groups'] = sec_grp_ids
diff --git a/snaps/config/project.py b/snaps/config/project.py
index 6790609..d6d175f 100644
--- a/snaps/config/project.py
+++ b/snaps/config/project.py
@@ -32,11 +32,12 @@ class ProjectConfig(object):
:param users: list of users to associate project to (optional)
:param enabled: denotes whether or not the project is enabled
(default True)
+ :param quotas: quota values to override (optional)
"""
self.name = kwargs.get('name')
self.domain_name = kwargs.get(
- 'domain', kwargs.get('domain', 'Default'))
+ 'domain_name', kwargs.get('domain', 'Default'))
self.description = kwargs.get('description')
if kwargs.get('enabled') is not None:
@@ -46,6 +47,8 @@ class ProjectConfig(object):
self.users = kwargs.get('users', list())
+ self.quotas = kwargs.get('quotas')
+
if not self.name:
raise ProjectConfigError(
"The attribute name is required for ProjectConfig")
diff --git a/snaps/config/router.py b/snaps/config/router.py
index 72164f2..2a0b6a4 100644
--- a/snaps/config/router.py
+++ b/snaps/config/router.py
@@ -33,7 +33,11 @@ class RouterConfig(object):
: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
+ router (this way is deprecated).
+ *** NEW WAY ***
+ List of dict where the key is 'subnet' that
+ contains members with the following keys:
+ project_name, network_name, and subnet_name
:param port_settings: List of PortConfig objects
:return:
"""
@@ -45,6 +49,19 @@ class RouterConfig(object):
self.enable_snat = kwargs.get('enable_snat')
if kwargs.get('internal_subnets'):
self.internal_subnets = kwargs['internal_subnets']
+ if isinstance(self.internal_subnets, dict):
+ if 'subnet' not in self.internal_subnets:
+ raise RouterConfigError(
+ 'subnet is a required key to internal_subnets')
+ if 'project_name' not in self.internal_subnets['subnet']:
+ raise RouterConfigError(
+ 'subnet.project is a required key to subnet')
+ if 'network_name' not in self.internal_subnets['subnet']:
+ raise RouterConfigError(
+ 'network_name is a required key to subnet')
+ if 'subnet_name' not in self.internal_subnets['subnet']:
+ raise RouterConfigError(
+ 'subnet_name is a required key to subnet')
else:
self.internal_subnets = list()
@@ -70,39 +87,42 @@ class RouterConfig(object):
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
+ :param os_creds: The OpenStack credentials for retrieving the keystone
+ client for looking up the project ID when the
+ self.project_name is not None
: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)
+ session = keystone_utils.keystone_session(os_creds)
+ keystone = keystone_utils.keystone_client(os_creds, session)
+ try:
+ if self.name:
+ out['name'] = self.name
+ if self.project_name:
+ project = keystone_utils.get_project(
+ keystone=keystone, project_name=self.project_name)
+ if project:
+ 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, keystone, 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)
+ finally:
+ keystone_utils.close_session(session)
return {'router': out}
diff --git a/snaps/config/security_group.py b/snaps/config/security_group.py
index 32a1e95..9e485c3 100644
--- a/snaps/config/security_group.py
+++ b/snaps/config/security_group.py
@@ -54,7 +54,7 @@ class SecurityGroupConfig(object):
raise SecurityGroupConfigError('The attribute name is required')
for rule_setting in self.rule_settings:
- if rule_setting.sec_grp_name is not self.name:
+ if rule_setting.sec_grp_name != self.name:
raise SecurityGroupConfigError(
'Rule settings must correspond with the name of this '
'security group')
@@ -204,13 +204,14 @@ class SecurityGroupRuleConfig(object):
raise SecurityGroupRuleConfigError(
'direction and sec_grp_name are required')
- def dict_for_neutron(self, neutron):
+ def dict_for_neutron(self, neutron, keystone, project_name):
"""
Returns a dictionary object representing this object.
This is meant to be converted into JSON designed for use by the Neutron
API
-
:param neutron: the neutron client for performing lookups
+ :param keystone: the keystone client for performing lookups
+ :param project_name: the name of the project associated with the group
:return: the dictionary object
"""
out = dict()
@@ -229,7 +230,8 @@ class SecurityGroupRuleConfig(object):
out['protocol'] = self.protocol.value
if self.sec_grp_name:
sec_grp = neutron_utils.get_security_group(
- neutron, sec_grp_name=self.sec_grp_name)
+ neutron, keystone, sec_grp_name=self.sec_grp_name,
+ project_name=project_name)
if sec_grp:
out['security_group_id'] = sec_grp.id
else:
@@ -312,12 +314,15 @@ def map_direction(direction):
:return: the Direction enum object
:raise: Exception if value is invalid
"""
- if not direction:
+ if not direction or 'None' == str(direction):
return None
- if isinstance(direction, Direction):
- return direction
- elif (isinstance(direction, str) or isinstance(direction, unicode)
- or isinstance(direction, unicode)):
+ if isinstance(direction, enum.Enum):
+ if direction.__class__.__name__ == 'Direction':
+ return direction
+ else:
+ raise SecurityGroupRuleConfigError(
+ 'Invalid class - ' + direction.__class__.__name__)
+ elif isinstance(direction, str):
dir_str = str(direction)
if dir_str == 'egress':
return Direction.egress
@@ -327,7 +332,7 @@ def map_direction(direction):
raise SecurityGroupRuleConfigError(
'Invalid Direction - ' + dir_str)
else:
- return map_direction(direction.value)
+ return map_direction(str(direction))
def map_protocol(protocol):
@@ -340,19 +345,22 @@ def map_protocol(protocol):
"""
if not protocol:
return None
- elif isinstance(protocol, Protocol):
- return protocol
- elif (isinstance(protocol, str) or isinstance(protocol, unicode)
- or isinstance(protocol, int)):
+ elif isinstance(protocol, enum.Enum):
+ if protocol.__class__.__name__ == 'Protocol':
+ return protocol
+ else:
+ raise SecurityGroupRuleConfigError(
+ 'Invalid class - ' + protocol.__class__.__name__)
+ elif isinstance(protocol, str) or isinstance(protocol, int):
for proto_enum in Protocol:
if proto_enum.name == protocol or proto_enum.value == protocol:
if proto_enum == Protocol.any:
return Protocol.null
return proto_enum
raise SecurityGroupRuleConfigError(
- 'Invalid Protocol - ' + protocol)
+ 'Invalid Protocol - ' + str(protocol))
else:
- return map_protocol(protocol.value)
+ return map_protocol(str(protocol))
def map_ethertype(ethertype):
@@ -363,12 +371,15 @@ def map_ethertype(ethertype):
:return: the Ethertype enum object
:raise: Exception if value is invalid
"""
- if not ethertype:
+ if not ethertype or 'None' == str(ethertype):
return None
- elif isinstance(ethertype, Ethertype):
- return ethertype
- elif (isinstance(ethertype, str) or isinstance(ethertype, unicode)
- or isinstance(ethertype, int)):
+ elif isinstance(ethertype, enum.Enum):
+ if ethertype.__class__.__name__ == 'Ethertype':
+ return ethertype
+ else:
+ raise SecurityGroupRuleConfigError(
+ 'Invalid class - ' + ethertype.__class__.__name__)
+ elif isinstance(ethertype, str) or isinstance(ethertype, int):
eth_str = str(ethertype)
if eth_str == 'IPv6' or eth_str == '6':
return Ethertype.IPv6
@@ -378,7 +389,7 @@ def map_ethertype(ethertype):
raise SecurityGroupRuleConfigError(
'Invalid Ethertype - ' + eth_str)
else:
- return map_ethertype(ethertype.value)
+ return map_ethertype(str(ethertype))
class SecurityGroupRuleConfigError(Exception):
diff --git a/snaps/config/stack.py b/snaps/config/stack.py
index 4d5db29..3fc820e 100644
--- a/snaps/config/stack.py
+++ b/snaps/config/stack.py
@@ -15,9 +15,12 @@
STACK_DELETE_TIMEOUT = 1200
STACK_COMPLETE_TIMEOUT = 1200
+STACK_UPDATE_TIMEOUT = 1200
POLL_INTERVAL = 3
STATUS_CREATE_FAILED = 'CREATE_FAILED'
STATUS_CREATE_COMPLETE = 'CREATE_COMPLETE'
+STATUS_UPDATE_FAILED = 'UPDATE_FAILED'
+STATUS_UPDATE_COMPLETE = 'UPDATE_COMPLETE'
STATUS_DELETE_COMPLETE = 'DELETE_COMPLETE'
STATUS_DELETE_FAILED = 'DELETE_FAILED'
diff --git a/snaps/config/tests/network_tests.py b/snaps/config/tests/network_tests.py
index 43b69c7..cbc71af 100644
--- a/snaps/config/tests/network_tests.py
+++ b/snaps/config/tests/network_tests.py
@@ -15,7 +15,7 @@
import unittest
from snaps.config.network import (
- NetworkConfigError, NetworkConfig, SubnetConfig, SubnetConfigError,
+ NetworkConfigError, NetworkConfig, SubnetConfig, SubnetConfigError,
IPv6Mode, PortConfig, PortConfigError)
@@ -42,6 +42,7 @@ class NetworkConfigUnitTests(unittest.TestCase):
self.assertIsNone(settings.network_type)
self.assertIsNone(settings.segmentation_id)
self.assertEqual(0, len(settings.subnet_settings))
+ self.assertIsNone(settings.mtu)
def test_config_with_name_only(self):
settings = NetworkConfig(**{'name': 'foo'})
@@ -53,13 +54,14 @@ class NetworkConfigUnitTests(unittest.TestCase):
self.assertIsNone(settings.network_type)
self.assertIsNone(settings.segmentation_id)
self.assertEqual(0, len(settings.subnet_settings))
+ self.assertIsNone(settings.mtu)
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])
+ segmentation_id=2366, subnet_settings=[sub_settings], mtu=999)
self.assertEqual('foo', settings.name)
self.assertFalse(settings.admin_state_up)
self.assertTrue(settings.shared)
@@ -70,6 +72,7 @@ class NetworkConfigUnitTests(unittest.TestCase):
self.assertEqual(2366, settings.segmentation_id)
self.assertEqual(1, len(settings.subnet_settings))
self.assertEqual('foo-subnet', settings.subnet_settings[0].name)
+ self.assertEqual(999, settings.mtu)
def test_config_all(self):
settings = NetworkConfig(
@@ -79,7 +82,8 @@ class NetworkConfigUnitTests(unittest.TestCase):
'segmentation_id': 2366,
'subnets':
[{'subnet': {'name': 'foo-subnet',
- 'cidr': '10.0.0.0/24'}}]})
+ 'cidr': '10.0.0.0/24'}}],
+ 'mtu': 999})
self.assertEqual('foo', settings.name)
self.assertFalse(settings.admin_state_up)
self.assertTrue(settings.shared)
@@ -90,6 +94,7 @@ class NetworkConfigUnitTests(unittest.TestCase):
self.assertEqual(2366, settings.segmentation_id)
self.assertEqual(1, len(settings.subnet_settings))
self.assertEqual('foo-subnet', settings.subnet_settings[0].name)
+ self.assertEqual(999, settings.mtu)
class SubnetConfigUnitTests(unittest.TestCase):
@@ -122,8 +127,7 @@ class SubnetConfigUnitTests(unittest.TestCase):
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.assertEqual(0, len(settings.dns_nameservers))
self.assertIsNone(settings.host_routes)
self.assertIsNone(settings.destination)
self.assertIsNone(settings.nexthop)
@@ -140,8 +144,7 @@ class SubnetConfigUnitTests(unittest.TestCase):
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.assertEqual(0, len(settings.dns_nameservers))
self.assertIsNone(settings.host_routes)
self.assertIsNone(settings.destination)
self.assertIsNone(settings.nexthop)
diff --git a/snaps/config/tests/project_tests.py b/snaps/config/tests/project_tests.py
index 0470d83..99de4a9 100644
--- a/snaps/config/tests/project_tests.py
+++ b/snaps/config/tests/project_tests.py
@@ -37,6 +37,7 @@ class ProjectConfigUnitTests(unittest.TestCase):
self.assertIsNone(settings.description)
self.assertTrue(settings.enabled)
self.assertEqual(list(), settings.users)
+ self.assertIsNone(settings.quotas)
def test_config_with_name_only(self):
settings = ProjectConfig(**{'name': 'foo'})
@@ -45,25 +46,52 @@ class ProjectConfigUnitTests(unittest.TestCase):
self.assertIsNone(settings.description)
self.assertTrue(settings.enabled)
self.assertEqual(list(), settings.users)
+ self.assertIsNone(settings.quotas)
def test_all(self):
users = ['test1', 'test2']
+ quotas = {
+ 'cores': 4, 'instances': 5, 'injected_files': 6,
+ 'injected_file_content_bytes': 60000, 'ram': 70000, 'fixed_ips': 7,
+ 'key_pairs': 8}
settings = ProjectConfig(
name='foo', domain='bar', description='foobar', enabled=False,
- users=users)
+ users=users, quotas=quotas)
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)
+ self.assertIsNotNone(settings.quotas)
+ self.assertEquals(4, settings.quotas.get('cores'))
+ self.assertEquals(5, settings.quotas.get('instances'))
+ self.assertEquals(6, settings.quotas.get('injected_files'))
+ self.assertEquals(
+ 60000, settings.quotas.get('injected_file_content_bytes'))
+ self.assertEquals(70000, settings.quotas.get('ram'))
+ self.assertEquals(7, settings.quotas.get('fixed_ips'))
+ self.assertEquals(8, settings.quotas.get('key_pairs'))
def test_config_all(self):
users = ['test1', 'test2']
settings = ProjectConfig(
**{'name': 'foo', 'domain': 'bar', 'description': 'foobar',
- 'enabled': False, 'users': users})
+ 'enabled': False, 'users': users,
+ 'quotas': {
+ 'cores': 4, 'instances': 5, 'injected_files': 6,
+ 'injected_file_content_bytes': 60000, 'ram': 70000,
+ 'fixed_ips': 7, 'key_pairs': 8}})
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)
+ self.assertIsNotNone(settings.quotas)
+ self.assertEquals(4, settings.quotas.get('cores'))
+ self.assertEquals(5, settings.quotas.get('instances'))
+ self.assertEquals(6, settings.quotas.get('injected_files'))
+ self.assertEquals(
+ 60000, settings.quotas.get('injected_file_content_bytes'))
+ self.assertEquals(70000, settings.quotas.get('ram'))
+ self.assertEquals(7, settings.quotas.get('fixed_ips'))
+ self.assertEquals(8, settings.quotas.get('key_pairs'))
diff --git a/snaps/config/tests/router_tests.py b/snaps/config/tests/router_tests.py
index 2c8f91f..1397f23 100644
--- a/snaps/config/tests/router_tests.py
+++ b/snaps/config/tests/router_tests.py
@@ -31,6 +31,25 @@ class RouterConfigUnitTests(unittest.TestCase):
with self.assertRaises(RouterConfigError):
RouterConfig(**dict())
+ def test_bad_internal_subnets_bad_key(self):
+ with self.assertRaises(RouterConfigError):
+ RouterConfig(name='foo', internal_subnets={'foo': 'bar'})
+
+ def test_bad_internal_subnets_no_project(self):
+ with self.assertRaises(RouterConfigError):
+ RouterConfig(name='foo', internal_subnets={
+ 'subnet': {'subnet_name': 'bar', 'network_name': 'foo'}})
+
+ def test_bad_internal_subnets_no_network(self):
+ with self.assertRaises(RouterConfigError):
+ RouterConfig(name='foo', internal_subnets={
+ 'subnet': {'subnet_name': 'bar', 'project_name': 'foo'}})
+
+ def test_bad_internal_subnets_no_subnet(self):
+ with self.assertRaises(RouterConfigError):
+ RouterConfig(name='foo', internal_subnets={
+ 'subnet': {'project_name': 'bar', 'network_name': 'foo'}})
+
def test_name_only(self):
settings = RouterConfig(name='foo')
self.assertEqual('foo', settings.name)
@@ -59,7 +78,7 @@ class RouterConfigUnitTests(unittest.TestCase):
self.assertTrue(isinstance(settings.port_settings, list))
self.assertEqual(0, len(settings.port_settings))
- def test_all(self):
+ def test_all_internal_subnets_str(self):
port_settings = PortConfig(name='foo', network_name='bar')
settings = RouterConfig(
name='foo', project_name='bar', external_gateway='foo_gateway',
@@ -76,11 +95,36 @@ class RouterConfigUnitTests(unittest.TestCase):
self.assertEqual(['10.0.0.1/24'], settings.internal_subnets)
self.assertEqual([port_settings], settings.port_settings)
- def test_config_all(self):
+ def test_all_internal_subnets_dict(self):
+ port_settings = PortConfig(name='foo', network_name='bar')
+ int_subs = {'subnet': {
+ 'project_name': 'proj_a', 'network_name': 'net_name',
+ 'subnet_name': 'sub_name'}}
+ settings = RouterConfig(
+ name='foo', project_name='bar', external_gateway='foo_gateway',
+ admin_state_up=True, enable_snat=False,
+ internal_subnets=int_subs,
+ 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, dict))
+ self.assertEqual(1, len(settings.internal_subnets))
+ self.assertEqual(int_subs, settings.internal_subnets)
+ self.assertEqual([port_settings], settings.port_settings)
+
+ def test_config_all_internal_subnets_str(self):
+ int_subs = {'subnet': {
+ 'project_name': 'proj_a', 'network_name': 'net_name',
+ 'subnet_name': 'sub_name'}}
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'],
+ 'enable_snat': False,
+ 'internal_subnets': int_subs,
'interfaces':
[{'port': {'name': 'foo-port',
'network_name': 'bar-net'}}]})
@@ -90,9 +134,9 @@ class RouterConfigUnitTests(unittest.TestCase):
self.assertTrue(settings.admin_state_up)
self.assertFalse(settings.enable_snat)
self.assertIsNotNone(settings.internal_subnets)
- self.assertTrue(isinstance(settings.internal_subnets, list))
+ self.assertTrue(isinstance(settings.internal_subnets, dict))
self.assertEqual(1, len(settings.internal_subnets))
- self.assertEqual(['10.0.0.1/24'], settings.internal_subnets)
+ self.assertEqual(int_subs, settings.internal_subnets)
self.assertEqual([PortConfig(**{'name': 'foo-port',
'network_name': 'bar-net'})],
settings.port_settings)
diff --git a/snaps/config/tests/volume_tests.py b/snaps/config/tests/volume_tests.py
index b4b54bd..21adffa 100644
--- a/snaps/config/tests/volume_tests.py
+++ b/snaps/config/tests/volume_tests.py
@@ -33,6 +33,7 @@ class VolumeConfigUnitTests(unittest.TestCase):
def test_name_only(self):
settings = VolumeConfig(name='foo')
self.assertEqual('foo', settings.name)
+ self.assertIsNone(settings.project_name)
self.assertIsNone(settings.description)
self.assertEquals(1, settings.size)
self.assertIsNone(settings.image_name)
@@ -43,6 +44,7 @@ class VolumeConfigUnitTests(unittest.TestCase):
def test_config_with_name_only(self):
settings = VolumeConfig(**{'name': 'foo'})
self.assertEqual('foo', settings.name)
+ self.assertIsNone(settings.project_name)
self.assertIsNone(settings.description)
self.assertEquals(1, settings.size)
self.assertIsNone(settings.image_name)
@@ -52,10 +54,12 @@ class VolumeConfigUnitTests(unittest.TestCase):
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')
+ name='foo', project_name='proj-foo', description='desc', size='2',
+ image_name='image', type_name='type', availability_zone='zone1',
+ multi_attach='true')
self.assertEqual('foo', settings.name)
+ self.assertEqual('proj-foo', settings.project_name)
self.assertEqual('desc', settings.description)
self.assertEqual(2, settings.size)
self.assertEqual('image', settings.image_name)
@@ -65,10 +69,12 @@ class VolumeConfigUnitTests(unittest.TestCase):
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)
+ name='foo', project_name='proj-foo', description='desc', size=2,
+ image_name='image', type_name='bar', availability_zone='zone1',
+ multi_attach=True)
self.assertEqual('foo', settings.name)
+ self.assertEqual('proj-foo', settings.project_name)
self.assertEqual('desc', settings.description)
self.assertEqual(2, settings.size)
self.assertEqual('image', settings.image_name)
@@ -78,11 +84,13 @@ class VolumeConfigUnitTests(unittest.TestCase):
def test_config_all(self):
settings = VolumeConfig(
- **{'name': 'foo', 'description': 'desc', 'size': '2',
+ **{'name': 'foo', 'project_name': 'proj-foo',
+ 'description': 'desc', 'size': '2',
'image_name': 'foo', 'type_name': 'bar',
'availability_zone': 'zone1', 'multi_attach': 'true'})
self.assertEqual('foo', settings.name)
+ self.assertEqual('proj-foo', settings.project_name)
self.assertEqual('desc', settings.description)
self.assertEqual(2, settings.size)
self.assertEqual('foo', settings.image_name)
diff --git a/snaps/config/volume.py b/snaps/config/volume.py
index a31e8f5..0b4b73e 100644
--- a/snaps/config/volume.py
+++ b/snaps/config/volume.py
@@ -20,6 +20,9 @@ class VolumeConfig(object):
"""
Constructor
:param name: the volume's name (required)
+ :param project_name: the name of the project to associate (optional)
+ note: due to a bug in the Cinder API, this functionality will not
+ work. see https://bugs.launchpad.net/cinder/+bug/1641982
: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
@@ -32,6 +35,7 @@ class VolumeConfig(object):
"""
self.name = kwargs.get('name')
+ self.project_name = kwargs.get('project_name')
self.description = kwargs.get('description')
self.size = int(kwargs.get('size', 1))
self.image_name = kwargs.get('image_name')
diff --git a/snaps/domain/network.py b/snaps/domain/network.py
index 2d02966..3d5e4af 100644
--- a/snaps/domain/network.py
+++ b/snaps/domain/network.py
@@ -24,6 +24,7 @@ class Network:
Constructor
:param name: the network's name
:param id: the network's ID
+ :param project_id: the associated project ID
:param admin_state_up: T/F - network is up when True
:param shared: T/F - network can be shared amongst other project's
:param external: T/F - network is deemed to be external
@@ -32,19 +33,22 @@ class Network:
"""
self.name = kwargs.get('name')
self.id = kwargs.get('id')
+ self.project_id = kwargs.get('project_id')
self.admin_state_up = kwargs.get('admin_state_up')
self.shared = kwargs.get('shared')
self.external = kwargs.get('router:external', kwargs.get('external'))
self.type = kwargs.get('provider:network_type', kwargs.get('type'))
self.subnets = kwargs.get('subnets', list())
+ self.mtu = kwargs.get('mtu')
def __eq__(self, other):
return (self.name == other.name and self.id == other.id and
+ self.project_id == other.project_id and
self.admin_state_up == other.admin_state_up and
self.shared == other.shared and
self.external == other.external and
- self.type == other.type and
- self.subnets == other.subnets)
+ self.subnets == other.subnets and
+ self.mtu == other.mtu)
class Subnet:
@@ -57,6 +61,7 @@ class Subnet:
Constructor
:param name: the network's name
:param id: the subnet's ID
+ :param project_id: the associated project ID
:param network_id: the network's ID
:param cidr: the CIDR
:param ip_version: the IP version
@@ -71,6 +76,7 @@ class Subnet:
"""
self.name = kwargs.get('name')
self.id = kwargs.get('id')
+ self.project_id = kwargs.get('project_id')
self.network_id = kwargs.get('network_id')
self.cidr = kwargs.get('cidr')
self.ip_version = kwargs.get('ip_version')
@@ -95,6 +101,7 @@ class Subnet:
def __eq__(self, other):
return (self.name == other.name and
self.id == other.id and
+ self.project_id == other.project_id and
self.network_id == other.network_id and
self.cidr == other.cidr and
self.ip_version == other.ip_version and
@@ -181,8 +188,7 @@ class Router:
self.port_subnets = kwargs.get('port_subnets')
if (kwargs.get('external_gateway_info') and
- isinstance(kwargs.get('external_gateway_info'), dict) and
- kwargs.get('external_gateway_info').get('external_fixed_ips')):
+ isinstance(kwargs.get('external_gateway_info'), dict)):
gateway_info = kwargs.get('external_gateway_info')
self.external_network_id = gateway_info.get('network_id')
diff --git a/snaps/domain/stack.py b/snaps/domain/stack.py
index 080ab17..2c593d3 100644
--- a/snaps/domain/stack.py
+++ b/snaps/domain/stack.py
@@ -19,14 +19,22 @@ class Stack:
SNAPS domain object for Heat Stacks. Should contain attributes that
are shared amongst cloud providers
"""
- def __init__(self, name, stack_id):
+ def __init__(self, name, stack_id, stack_project_id,
+ status, status_reason):
"""
Constructor
:param name: the stack's name
:param stack_id: the stack's stack_id
+ :param stack_project_id: the project ID that was spawned from this
+ deployment
+ :param status: the stack's last known status code
+ :param status_reason: the stack's last known explanation of the status
"""
self.name = name
self.id = stack_id
+ self.stack_project_id = stack_project_id
+ self.status = status
+ self.status_reason = status_reason
def __eq__(self, other):
return (self.name == other.name and
diff --git a/snaps/domain/test/network_tests.py b/snaps/domain/test/network_tests.py
index 3003326..2c4c841 100644
--- a/snaps/domain/test/network_tests.py
+++ b/snaps/domain/test/network_tests.py
@@ -26,28 +26,34 @@ class NetworkObjectTests(unittest.TestCase):
def test_construction_kwargs_1(self):
subnet = Subnet(
- **{'name': 'foo', 'id': 'bar', 'network_id': 'foo-bar'})
+ **{'name': 'foo', 'id': 'bar', 'project_id': 'proj1',
+ 'network_id': 'foo-bar'})
network = Network(
- **{'name': 'foo', 'id': 'bar', 'provider:network_type': 'flat',
- 'admin_state_up': False, 'shared': True,
- 'router:external': False, 'subnets': [subnet]})
+ **{'name': 'foo', 'id': 'bar', 'project_id': 'proj1',
+ 'provider:network_type': 'flat', 'admin_state_up': False,
+ 'shared': True, 'router:external': False, 'subnets': [subnet],
+ 'mtu': 999})
self.assertEqual('foo', network.name)
self.assertEqual('bar', network.id)
+ self.assertEqual('proj1', network.project_id)
self.assertEqual('flat', network.type)
self.assertFalse(network.admin_state_up)
self.assertFalse(network.external)
self.assertTrue(network.shared)
self.assertEqual([subnet], network.subnets)
+ self.assertEqual(999, network.mtu)
def test_construction_kwargs_2(self):
subnet = Subnet(
- **{'name': 'foo', 'id': 'bar', 'network_id': 'foo-bar'})
+ **{'name': 'foo', 'id': 'bar', 'project_id': 'proj1',
+ 'network_id': 'foo-bar'})
network = Network(
- **{'name': 'foo', 'id': 'bar', 'type': 'flat',
- 'admin_state_up': False, 'shared': True, 'external': False,
- 'subnets': [subnet]})
+ **{'name': 'foo', 'id': 'bar', 'project_id': 'proj1',
+ 'type': 'flat', 'admin_state_up': False, 'shared': True,
+ 'external': False, 'subnets': [subnet]})
self.assertEqual('foo', network.name)
self.assertEqual('bar', network.id)
+ self.assertEqual('proj1', network.project_id)
self.assertEqual('flat', network.type)
self.assertFalse(network.admin_state_up)
self.assertFalse(network.external)
@@ -56,12 +62,15 @@ class NetworkObjectTests(unittest.TestCase):
def test_construction_named(self):
subnet = Subnet(
- **{'name': 'foo', 'id': 'bar', 'network_id': 'foo-bar'})
+ **{'name': 'foo', 'id': 'bar', 'project_id': 'proj1',
+ 'network_id': 'foo-bar'})
network = Network(
- name='foo', id='bar', type='flat', admin_state_up=False,
- shared=True, external=False, subnets=[subnet])
+ name='foo', id='bar', project_id='proj1', type='flat',
+ admin_state_up=False, shared=True, external=False,
+ subnets=[subnet])
self.assertEqual('foo', network.name)
self.assertEqual('bar', network.id)
+ self.assertEqual('proj1', network.project_id)
self.assertEqual('flat', network.type)
self.assertFalse(network.admin_state_up)
self.assertFalse(network.external)
@@ -76,12 +85,14 @@ class SubnetObjectTests(unittest.TestCase):
def test_construction_kwargs(self):
subnet = Subnet(
- **{'name': 'foo', 'id': 'bar', 'cidr': '10.0.0.0/24',
- 'ip_version': 4, 'gateway_ip': '10.0.0.1', 'enable_dhcp': True,
+ **{'name': 'foo', 'id': 'bar', 'project_id': 'proj1',
+ 'cidr': '10.0.0.0/24', 'ip_version': 4,
+ 'gateway_ip': '10.0.0.1', 'enable_dhcp': True,
'dns_nameservers': ['8.8.8.8'], 'host_routes': list(),
'ipv6_ra_mode': 'hello', 'ipv6_address_mode': 'world'})
self.assertEqual('foo', subnet.name)
self.assertEqual('bar', subnet.id)
+ self.assertEqual('proj1', subnet.project_id)
self.assertEqual('10.0.0.0/24', subnet.cidr)
self.assertEqual(4, subnet.ip_version)
self.assertEqual('10.0.0.1', subnet.gateway_ip)
@@ -94,12 +105,13 @@ class SubnetObjectTests(unittest.TestCase):
def test_construction_named(self):
subnet = Subnet(
- name='foo', id='bar', cidr='10.0.0.0/24',
+ name='foo', id='bar', project_id='proj1', cidr='10.0.0.0/24',
ip_version=4, gateway_ip='10.0.0.1', enable_dhcp=True,
dns_nameservers=['8.8.8.8'], host_routes=list(),
ipv6_ra_mode='hello', ipv6_address_mode='world')
self.assertEqual('foo', subnet.name)
self.assertEqual('bar', subnet.id)
+ self.assertEqual('proj1', subnet.project_id)
self.assertEqual('10.0.0.0/24', subnet.cidr)
self.assertEqual(4, subnet.ip_version)
self.assertEqual('10.0.0.1', subnet.gateway_ip)
diff --git a/snaps/domain/test/stack_tests.py b/snaps/domain/test/stack_tests.py
index 21e31d2..2ad690a 100644
--- a/snaps/domain/test/stack_tests.py
+++ b/snaps/domain/test/stack_tests.py
@@ -23,14 +23,23 @@ class StackDomainObjectTests(unittest.TestCase):
"""
def test_construction_positional(self):
- stack = Stack('name', 'id')
+ stack = Stack(
+ 'name', 'id', 'stack_proj_id', 'fine', 'good')
self.assertEqual('name', stack.name)
self.assertEqual('id', stack.id)
+ self.assertEqual('stack_proj_id', stack.stack_project_id)
+ self.assertEqual('fine', stack.status)
+ self.assertEqual('good', stack.status_reason)
def test_construction_named(self):
- stack = Stack(stack_id='id', name='name')
+ stack = Stack(
+ stack_id='id', name='name', stack_project_id='stack_proj_id',
+ status='fine', status_reason='good')
self.assertEqual('name', stack.name)
self.assertEqual('id', stack.id)
+ self.assertEqual('stack_proj_id', stack.stack_project_id)
+ self.assertEqual('fine', stack.status)
+ self.assertEqual('good', stack.status_reason)
class ResourceDomainObjectTests(unittest.TestCase):
diff --git a/snaps/domain/test/vm_inst_tests.py b/snaps/domain/test/vm_inst_tests.py
index ad7a9ce..c90837d 100644
--- a/snaps/domain/test/vm_inst_tests.py
+++ b/snaps/domain/test/vm_inst_tests.py
@@ -24,7 +24,7 @@ class VmInstDomainObjectTests(unittest.TestCase):
def test_construction_positional(self):
vm_inst = VmInst('name', 'id', '456', '123', list(), 'kp-name',
- ['foo', 'bar'], ['123', '456'])
+ ['foo', 'bar'], ['123', '456'], 'host1', 'zone1')
self.assertEqual('name', vm_inst.name)
self.assertEqual('id', vm_inst.id)
self.assertEqual('456', vm_inst.image_id)
@@ -33,9 +33,12 @@ class VmInstDomainObjectTests(unittest.TestCase):
self.assertEqual('kp-name', vm_inst.keypair_name)
self.assertEqual(['foo', 'bar'], vm_inst.sec_grp_names)
self.assertEqual(['123', '456'], vm_inst.volume_ids)
+ self.assertEqual('host1', vm_inst.compute_host)
+ self.assertEqual('zone1', vm_inst.availability_zone)
def test_construction_named(self):
vm_inst = VmInst(
+ availability_zone='zone1', compute_host='host1',
volume_ids=['123', '456'], sec_grp_names=['foo', 'bar'],
ports=list(), inst_id='id', name='name', flavor_id='123',
image_id='456', keypair_name='kp-name')
@@ -47,6 +50,8 @@ class VmInstDomainObjectTests(unittest.TestCase):
self.assertEqual('kp-name', vm_inst.keypair_name)
self.assertEqual(['foo', 'bar'], vm_inst.sec_grp_names)
self.assertEqual(['123', '456'], vm_inst.volume_ids)
+ self.assertEqual('host1', vm_inst.compute_host)
+ self.assertEqual('zone1', vm_inst.availability_zone)
class FloatingIpDomainObjectTests(unittest.TestCase):
diff --git a/snaps/domain/test/volume_tests.py b/snaps/domain/test/volume_tests.py
index 6feadc9..09401d3 100644
--- a/snaps/domain/test/volume_tests.py
+++ b/snaps/domain/test/volume_tests.py
@@ -24,10 +24,12 @@ class VolumeDomainObjectTests(unittest.TestCase):
"""
def test_construction_positional(self):
- volume = Volume('name1', 'id1', 'desc_val1', 2, 'type_val1',
- 'avail_zone1', False, [{'attached_at': 'foo'}])
+ volume = Volume('name1', 'id1', 'proj_id1', 'desc_val1', 2,
+ 'type_val1', 'avail_zone1', False,
+ [{'attached_at': 'foo'}])
self.assertEqual('name1', volume.name)
self.assertEqual('id1', volume.id)
+ self.assertEqual('proj_id1', volume.project_id)
self.assertEqual('desc_val1', volume.description)
self.assertEqual(2, volume.size)
self.assertEqual('type_val1', volume.type)
@@ -41,9 +43,10 @@ class VolumeDomainObjectTests(unittest.TestCase):
volume = Volume(attachments=[{'attached_at': 'foo'}],
multi_attach=True, availability_zone='avail_zone2',
vol_type='type_val2', size=3, description='desc_val2',
- volume_id='id2', name='name2')
+ volume_id='id2', name='name2', project_id='proj_id1')
self.assertEqual('name2', volume.name)
self.assertEqual('id2', volume.id)
+ self.assertEqual('proj_id1', volume.project_id)
self.assertEqual('desc_val2', volume.description)
self.assertEqual(3, volume.size)
self.assertEqual('type_val2', volume.type)
diff --git a/snaps/domain/vm_inst.py b/snaps/domain/vm_inst.py
index c49b03e..f3b5381 100644
--- a/snaps/domain/vm_inst.py
+++ b/snaps/domain/vm_inst.py
@@ -20,7 +20,8 @@ class VmInst:
are shared amongst cloud providers
"""
def __init__(self, name, inst_id, image_id, flavor_id, ports,
- keypair_name, sec_grp_names, volume_ids):
+ keypair_name, sec_grp_names, volume_ids, compute_host,
+ availability_zone):
"""
Constructor
:param name: the image's name
@@ -32,6 +33,11 @@ class VmInst:
:param keypair_name: the name of the associated keypair
:param sec_grp_names: list of security group names
:param volume_ids: list of attached volume IDs
+ :param compute_host: the name of the host on which this VM is running
+ When the user requesting this query is not part of
+ the 'admin' role, this value will be None
+ :param availability_zone: the name of the availability zone to which
+ this VM has been assigned
"""
self.name = name
self.id = inst_id
@@ -41,6 +47,8 @@ class VmInst:
self.keypair_name = keypair_name
self.sec_grp_names = sec_grp_names
self.volume_ids = volume_ids
+ self.compute_host = compute_host
+ self.availability_zone = availability_zone
def __eq__(self, other):
return (self.name == other.name and
@@ -49,7 +57,6 @@ class VmInst:
self.flavor_id == other.flavor_id and
self.ports == other.ports and
self.keypair_name == other.keypair_name and
- self.sec_grp_names == other.sec_grp_names and
self.volume_ids == other.volume_ids)
diff --git a/snaps/domain/volume.py b/snaps/domain/volume.py
index 0042d71..0ab2a7d 100644
--- a/snaps/domain/volume.py
+++ b/snaps/domain/volume.py
@@ -19,12 +19,14 @@ class Volume:
SNAPS domain object for Volumes. Should contain attributes that
are shared amongst cloud providers
"""
- def __init__(self, name, volume_id, description, size, vol_type,
- availability_zone, multi_attach, attachments=list()):
+ def __init__(self, name, volume_id, project_id, description, size,
+ vol_type, availability_zone, multi_attach,
+ attachments=list()):
"""
Constructor
:param name: the volume's name
:param volume_id: the volume's id
+ :param project_id: the volume's associated project id
:param description: the volume's description
:param size: the volume's size in GB
:param vol_type: the volume's type
@@ -35,6 +37,7 @@ class Volume:
"""
self.name = name
self.id = volume_id
+ self.project_id = project_id
self.description = description
self.size = size
self.type = vol_type
@@ -43,7 +46,9 @@ class Volume:
self.attachments = attachments
def __eq__(self, other):
- return (self.name == other.name and self.id == other.id
+ return (self.name == other.name
+ and self.id == other.id
+ and self.project_id == other.project_id
and self.description == other.description
and self.size == other.size
and self.type == other.type
diff --git a/snaps/file_utils.py b/snaps/file_utils.py
index a421dd3..284ae15 100644
--- a/snaps/file_utils.py
+++ b/snaps/file_utils.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.
+import ssl
+
import os
import logging
@@ -168,7 +170,8 @@ def __get_url_response(url):
proxy_handler = urllib.ProxyHandler({})
opener = urllib.build_opener(proxy_handler)
urllib.install_opener(opener)
- return urllib.urlopen(url)
+ context = ssl._create_unverified_context()
+ return urllib.urlopen(url, context=context)
def read_yaml(config_file_path):
@@ -180,7 +183,7 @@ def read_yaml(config_file_path):
logger.debug('Attempting to load configuration file - ' + config_file_path)
config_file = None
try:
- with open(config_file_path) as config_file:
+ with open(config_file_path, 'r') as config_file:
config = yaml.safe_load(config_file)
logger.info('Loaded configuration')
return config
@@ -190,6 +193,20 @@ def read_yaml(config_file_path):
config_file.close()
+def persist_dict_to_yaml(the_dict, file_name):
+ """
+ Creates a YAML file from a dict
+ :param the_dict: the dictionary to store
+ :param conf_dir: the directory used to store the config file
+ :return: the file object
+ """
+ logger.info('Persisting %s to [%s]', the_dict, file_name)
+ file_path = os.path.expanduser(file_name)
+ yaml_from_dict = yaml.dump(
+ the_dict, default_flow_style=False, default_style='')
+ return save_string_to_file(yaml_from_dict, file_path)
+
+
def read_os_env_file(os_env_filename):
"""
Reads the OS environment source file and returns a map of each key/value
diff --git a/snaps/openstack/cluster_template.py b/snaps/openstack/cluster_template.py
index c4ba76d..f6c7aa2 100644
--- a/snaps/openstack/cluster_template.py
+++ b/snaps/openstack/cluster_template.py
@@ -85,6 +85,8 @@ class OpenStackClusterTemplate(OpenStackMagnumObject):
self.__cluster_template = None
+ super(self.__class__, self).clean()
+
def get_cluster_template(self):
"""
Returns the domain Volume object as it was populated when create() was
diff --git a/snaps/openstack/create_flavor.py b/snaps/openstack/create_flavor.py
index 65b9059..48b3e7c 100644
--- a/snaps/openstack/create_flavor.py
+++ b/snaps/openstack/create_flavor.py
@@ -87,6 +87,8 @@ class OpenStackFlavor(OpenStackComputeObject):
self.__flavor = None
+ super(self.__class__, self).clean()
+
def get_flavor(self):
"""
Returns the OpenStack flavor object
diff --git a/snaps/openstack/create_image.py b/snaps/openstack/create_image.py
index a5520e3..1a8aa12 100644
--- a/snaps/openstack/create_image.py
+++ b/snaps/openstack/create_image.py
@@ -54,7 +54,10 @@ class OpenStackImage(OpenStackCloudObject):
Loads the existing Image
:return: The Image domain object or None
"""
- self.__glance = glance_utils.glance_client(self._os_creds)
+ super(self.__class__, self).initialize()
+
+ self.__glance = glance_utils.glance_client(
+ self._os_creds, self._os_session)
self.__image = glance_utils.get_image(
self.__glance, image_settings=self.image_settings)
@@ -145,6 +148,11 @@ class OpenStackImage(OpenStackCloudObject):
self.__kernel_image = None
self.__ramdisk_image = None
+ if self.__glance:
+ self.__glance.http_client.session.session.close()
+
+ super(self.__class__, self).clean()
+
def get_image(self):
"""
Returns the domain Image object as it was populated when create() was
diff --git a/snaps/openstack/create_instance.py b/snaps/openstack/create_instance.py
index d91e360..b158a25 100644
--- a/snaps/openstack/create_instance.py
+++ b/snaps/openstack/create_instance.py
@@ -15,11 +15,12 @@
import logging
import time
-from novaclient.exceptions import NotFound, BadRequest
+from novaclient.exceptions import NotFound
from snaps.config.vm_inst import VmInstanceConfig, FloatingIpConfig
from snaps.openstack.openstack_creator import OpenStackComputeObject
-from snaps.openstack.utils import glance_utils, cinder_utils, settings_utils
+from snaps.openstack.utils import (
+ glance_utils, cinder_utils, settings_utils, keystone_utils)
from snaps.openstack.utils import neutron_utils
from snaps.openstack.utils import nova_utils
from snaps.openstack.utils.nova_utils import RebootType
@@ -72,7 +73,14 @@ class OpenStackVmInstance(OpenStackComputeObject):
"""
super(self.__class__, self).initialize()
- self.__neutron = neutron_utils.neutron_client(self._os_creds)
+ self.__neutron = neutron_utils.neutron_client(
+ self._os_creds, self._os_session)
+ self.__keystone = keystone_utils.keystone_client(
+ self._os_creds, self._os_session)
+ self.__cinder = cinder_utils.cinder_client(
+ self._os_creds, self._os_session)
+ self.__glance = glance_utils.glance_client(
+ self._os_creds, self._os_session)
self.__ports = self.__query_ports(self.instance_settings.port_settings)
self.__lookup_existing_vm_by_name()
@@ -88,7 +96,7 @@ class OpenStackVmInstance(OpenStackComputeObject):
"""
self.initialize()
- if len(self.__ports) == 0:
+ if len(self.__ports) != len(self.instance_settings.port_settings):
self.__ports = self.__create_ports(
self.instance_settings.port_settings)
if not self.__vm:
@@ -103,7 +111,7 @@ class OpenStackVmInstance(OpenStackComputeObject):
within the project
"""
server = nova_utils.get_server(
- self._nova, self.__neutron,
+ self._nova, self.__neutron, self.__keystone,
vm_inst_settings=self.instance_settings)
if server:
if server.name == self.instance_settings.name:
@@ -112,8 +120,8 @@ class OpenStackVmInstance(OpenStackComputeObject):
'Found existing machine with name - %s',
self.instance_settings.name)
- fips = neutron_utils.get_floating_ips(self.__neutron,
- self.__ports)
+ fips = neutron_utils.get_port_floating_ips(
+ self.__neutron, self.__ports)
for port_id, fip in fips:
settings = self.instance_settings.floating_ip_settings
for fip_setting in settings:
@@ -132,10 +140,10 @@ class OpenStackVmInstance(OpenStackComputeObject):
active, error, or timeout waiting. Floating IPs will be
assigned after active when block=True
"""
- glance = glance_utils.glance_client(self._os_creds)
self.__vm = nova_utils.create_server(
- self._nova, self.__neutron, glance, self.instance_settings,
- self.image_settings, self.keypair_settings)
+ self._nova, self.__keystone, self.__neutron, self.__glance,
+ self.instance_settings, self.image_settings,
+ self._os_creds.project_name, self.keypair_settings)
logger.info('Created instance with name - %s',
self.instance_settings.name)
@@ -159,20 +167,20 @@ class OpenStackVmInstance(OpenStackComputeObject):
if self.instance_settings.volume_names:
for volume_name in self.instance_settings.volume_names:
- cinder = cinder_utils.cinder_client(self._os_creds)
volume = cinder_utils.get_volume(
- cinder, volume_name=volume_name)
+ self.__cinder, self.__keystone, volume_name=volume_name,
+ project_name=self._os_creds.project_name)
if volume and self.vm_active(block=True):
- timeout = 30
vm = nova_utils.attach_volume(
- self._nova, self.__neutron, self.__vm, volume, timeout)
+ self._nova, self.__neutron, self.__keystone, self.__vm,
+ volume, self._os_creds.project_name)
if vm:
self.__vm = vm
else:
- logger.warn('Volume [%s] not attached within timeout '
- 'of [%s]', volume.name, timeout)
+ logger.warn(
+ 'Volume [%s] attachment timeout ', volume.name)
else:
logger.warn('Unable to attach volume named [%s]',
volume_name)
@@ -213,18 +221,15 @@ class OpenStackVmInstance(OpenStackComputeObject):
# gateway
ext_gateway = self.__ext_gateway_by_router(
floating_ip_setting.router_name)
- if ext_gateway:
- subnet = neutron_utils.get_subnet(
- self.__neutron,
- subnet_name=floating_ip_setting.subnet_name)
+ if ext_gateway and self.vm_active(block=True):
floating_ip = neutron_utils.create_floating_ip(
- self.__neutron, ext_gateway)
+ self.__neutron, self.__keystone, ext_gateway, port.id)
self.__floating_ip_dict[floating_ip_setting.name] = floating_ip
logger.info(
'Created floating IP %s via router - %s', floating_ip.ip,
floating_ip_setting.router_name)
- self.__add_floating_ip(floating_ip, port, subnet)
+
return floating_ip
else:
raise VmInstanceCreationError(
@@ -239,7 +244,8 @@ class OpenStackVmInstance(OpenStackComputeObject):
:return: the external network name or None
"""
router = neutron_utils.get_router(
- self.__neutron, router_name=router_name)
+ self.__neutron, self.__keystone, router_name=router_name,
+ project_name=self._os_creds.project_name)
if router and router.external_network_id:
network = neutron_utils.get_network_by_id(
self.__neutron, router.external_network_id)
@@ -269,12 +275,12 @@ class OpenStackVmInstance(OpenStackComputeObject):
if self.__vm:
# Detach Volume
for volume_rec in self.__vm.volume_ids:
- cinder = cinder_utils.cinder_client(self._os_creds)
volume = cinder_utils.get_volume_by_id(
- cinder, volume_rec['id'])
+ self.__cinder, volume_rec['id'])
if volume:
vm = nova_utils.detach_volume(
- self._nova, self.__neutron, self.__vm, volume, 30)
+ self._nova, self.__neutron, self.__keystone, self.__vm,
+ volume, self._os_creds.project_name)
if vm:
self.__vm = vm
else:
@@ -307,6 +313,8 @@ class OpenStackVmInstance(OpenStackComputeObject):
'VM not deleted within the timeout period of %s '
'seconds', self.instance_settings.vm_delete_timeout)
+ super(self.__class__, self).clean()
+
def __query_ports(self, port_settings):
"""
Returns the previously configured ports or an empty list if none
@@ -319,7 +327,8 @@ class OpenStackVmInstance(OpenStackComputeObject):
for port_setting in port_settings:
port = neutron_utils.get_port(
- self.__neutron, port_settings=port_setting)
+ self.__neutron, self.__keystone, port_settings=port_setting,
+ project_name=self._os_creds.project_name)
if port:
ports.append((port_setting.name, port))
@@ -337,63 +346,16 @@ class OpenStackVmInstance(OpenStackComputeObject):
for port_setting in port_settings:
port = neutron_utils.get_port(
- self.__neutron, port_settings=port_setting)
+ self.__neutron, self.__keystone, port_settings=port_setting,
+ project_name=self._os_creds.project_name)
if not port:
port = neutron_utils.create_port(
self.__neutron, self._os_creds, port_setting)
- if port:
- ports.append((port_setting.name, port))
+ if port:
+ ports.append((port_setting.name, port))
return ports
- def __add_floating_ip(self, floating_ip, port, subnet, timeout=30,
- poll_interval=POLL_INTERVAL):
- """
- Returns True when active else False
- TODO - Make timeout and poll_interval configurable...
- """
- ip = None
-
- if subnet:
- # Take IP of subnet if there is one configured on which to place
- # the floating IP
- for fixed_ip in port.ips:
- if fixed_ip['subnet_id'] == subnet.id:
- ip = fixed_ip['ip_address']
- break
- else:
- # Simply take the first
- ip = port.ips[0]['ip_address']
-
- if ip:
- count = timeout / poll_interval
- while count > 0:
- logger.debug('Attempting to add floating IP to instance')
- try:
- nova_utils.add_floating_ip_to_server(
- self._nova, self.__vm, floating_ip, ip)
- logger.info(
- 'Added floating IP %s to port IP %s on instance %s',
- floating_ip.ip, ip, self.instance_settings.name)
- return
- except BadRequest as bre:
- logger.error('Cannot add floating IP [%s]', bre)
- raise
- except Exception as e:
- logger.debug(
- 'Retry adding floating IP to instance. Last attempt '
- 'failed with - %s', e)
- time.sleep(poll_interval)
- count -= 1
- pass
- else:
- raise VmInstanceCreationError(
- 'Unable find IP address on which to place the floating IP')
-
- logger.error('Timeout attempting to add the floating IP to instance.')
- raise VmInstanceCreationError(
- 'Timeout while attempting add floating IP to instance')
-
def get_os_creds(self):
"""
Returns the OpenStack credentials used to create these objects
@@ -407,7 +369,8 @@ class OpenStackVmInstance(OpenStackComputeObject):
:return: Server object
"""
return nova_utils.get_server_object_by_id(
- self._nova, self.__neutron, self.__vm.id)
+ self._nova, self.__neutron, self.__keystone, self.__vm.id,
+ self._os_creds.project_name)
def get_console_output(self):
"""
@@ -428,8 +391,10 @@ class OpenStackVmInstance(OpenStackComputeObject):
port = self.get_port_by_name(port_name)
if port:
if subnet_name:
+ network = neutron_utils.get_network_by_id(
+ self.__neutron, port.network_id)
subnet = neutron_utils.get_subnet(
- self.__neutron, subnet_name=subnet_name)
+ self.__neutron, network, subnet_name=subnet_name)
if not subnet:
logger.warning('Cannot retrieve port IP as subnet could '
'not be located with name - %s',
@@ -474,6 +439,10 @@ class OpenStackVmInstance(OpenStackComputeObject):
Returns a dictionary of a VMs info as returned by OpenStack
:return: a dict()
"""
+ from warnings import warn
+ warn('Do not use the returned dict() structure',
+ DeprecationWarning)
+
return nova_utils.get_server_info(self._nova, self.__vm)
def __get_first_provisioning_floating_ip(self):
@@ -505,12 +474,16 @@ class OpenStackVmInstance(OpenStackComputeObject):
playbook
:param fip_name: the name of the floating IP to use for applying the
playbook (default - will take the first)
- :return: the return value from ansible
"""
- return ansible_utils.apply_playbook(
+ from warnings import warn
+ warn('This method will be removed in a subsequent release',
+ DeprecationWarning)
+
+ ansible_utils.apply_playbook(
pb_file_loc, [self.get_floating_ip(fip_name=fip_name).ip],
- self.get_image_user(), self.keypair_settings.private_filepath,
- variables, self._os_creds.proxy_settings)
+ self.get_image_user(),
+ ssh_priv_key_file_path=self.keypair_settings.private_filepath,
+ variables=variables, proxy_setting=self._os_creds.proxy_settings)
def get_image_user(self):
"""
@@ -554,7 +527,8 @@ class OpenStackVmInstance(OpenStackComputeObject):
STATUS_ACTIVE, block, self.instance_settings.vm_boot_timeout,
poll_interval):
self.__vm = nova_utils.get_server_object_by_id(
- self._nova, self.__neutron, self.__vm.id)
+ self._nova, self.__neutron, self.__keystone, self.__vm.id,
+ self._os_creds.project_name)
return True
return False
@@ -619,18 +593,27 @@ class OpenStackVmInstance(OpenStackComputeObject):
status)
return status == expected_status_code
- def vm_ssh_active(self, block=False, poll_interval=POLL_INTERVAL):
+ def vm_ssh_active(self, user_override=None, password=None, block=False,
+ timeout=None, poll_interval=POLL_INTERVAL):
"""
Returns true when the VM can be accessed via SSH
+ :param user_override: overrides the user with which to create the
+ connection
+ :param password: overrides the use of a password instead of a private
+ key with which to create the connection
:param block: When true, thread will block until active or timeout
value in seconds has been exceeded (False)
+ :param timeout: the number of seconds to retry obtaining the connection
+ and overrides the ssh_connect_timeout member of the
+ self.instance_settings object
:param poll_interval: The polling interval
:return: T/F
"""
# sleep and wait for VM status change
logger.info('Checking if VM is active')
- timeout = self.instance_settings.ssh_connect_timeout
+ if not timeout:
+ timeout = self.instance_settings.ssh_connect_timeout
if self.vm_active(block=True):
if block:
@@ -639,7 +622,8 @@ class OpenStackVmInstance(OpenStackComputeObject):
start = time.time() - timeout
while timeout > time.time() - start:
- status = self.__ssh_active()
+ status = self.__ssh_active(
+ user_override=user_override, password=password)
if status:
logger.info('SSH is active for VM instance')
return True
@@ -653,13 +637,14 @@ class OpenStackVmInstance(OpenStackComputeObject):
logger.error('Timeout attempting to connect with VM via SSH')
return False
- def __ssh_active(self):
+ def __ssh_active(self, user_override=None, password=None):
"""
Returns True when can create a SSH session else False
:return: T/F
"""
if len(self.__floating_ip_dict) > 0:
- ssh = self.ssh_client()
+ ssh = self.ssh_client(
+ user_override=user_override, password=password)
if ssh:
ssh.close()
return True
@@ -727,19 +712,32 @@ class OpenStackVmInstance(OpenStackComputeObject):
else:
return self.__get_first_provisioning_floating_ip()
- def ssh_client(self, fip_name=None):
+ def ssh_client(self, fip_name=None, user_override=None, password=None):
"""
Returns an SSH client using the name or the first known floating IP if
exists, else None
:param fip_name: the name of the floating IP to return
+ :param user_override: the username to use instead of the default
+ :param password: the password to use instead of the private key
:return: the SSH client or None
"""
fip = self.get_floating_ip(fip_name)
+
+ ansible_user = self.get_image_user()
+ if user_override:
+ ansible_user = user_override
+
+ if password:
+ private_key = None
+ else:
+ private_key = self.keypair_settings.private_filepath
+
if fip:
return ansible_utils.ssh_client(
self.__get_first_provisioning_floating_ip().ip,
- self.get_image_user(),
- self.keypair_settings.private_filepath,
+ ansible_user,
+ private_key_filepath=private_key,
+ password=password,
proxy_settings=self._os_creds.proxy_settings)
else:
FloatingIPAllocationError(
@@ -797,24 +795,32 @@ class OpenStackVmInstance(OpenStackComputeObject):
self._nova, self.__vm, reboot_type=reboot_type)
-def generate_creator(os_creds, vm_inst, image_config, keypair_config=None):
+def generate_creator(os_creds, vm_inst, image_config, project_name,
+ keypair_config=None):
"""
Initializes an OpenStackVmInstance object
:param os_creds: the OpenStack credentials
:param vm_inst: the SNAPS-OO VmInst domain object
:param image_config: the associated ImageConfig object
+ :param project_name: the associated project ID
:param keypair_config: the associated KeypairConfig object (optional)
:return: an initialized OpenStackVmInstance object
"""
- nova = nova_utils.nova_client(os_creds)
- neutron = neutron_utils.neutron_client(os_creds)
- derived_inst_config = settings_utils.create_vm_inst_config(
- nova, neutron, vm_inst)
-
- derived_inst_creator = OpenStackVmInstance(
- os_creds, derived_inst_config, image_config, keypair_config)
- derived_inst_creator.initialize()
- return derived_inst_creator
+ session = keystone_utils.keystone_session(os_creds)
+ nova = nova_utils.nova_client(os_creds, session)
+ keystone = keystone_utils.keystone_client(os_creds, session)
+ neutron = neutron_utils.neutron_client(os_creds, session)
+
+ try:
+ derived_inst_config = settings_utils.create_vm_inst_config(
+ nova, keystone, neutron, vm_inst, project_name)
+
+ derived_inst_creator = OpenStackVmInstance(
+ os_creds, derived_inst_config, image_config, keypair_config)
+ derived_inst_creator.initialize()
+ return derived_inst_creator
+ finally:
+ keystone_utils.close_session(session)
class VmInstanceSettings(VmInstanceConfig):
diff --git a/snaps/openstack/create_keypairs.py b/snaps/openstack/create_keypairs.py
index a181a7b..b037c3f 100644
--- a/snaps/openstack/create_keypairs.py
+++ b/snaps/openstack/create_keypairs.py
@@ -133,6 +133,8 @@ class OpenStackKeypair(OpenStackComputeObject):
os.remove(expanded_path)
logger.info('Deleted private key file [%s]', expanded_path)
+ super(self.__class__, self).clean()
+
def get_keypair(self):
"""
Returns the OpenStack keypair object
diff --git a/snaps/openstack/create_network.py b/snaps/openstack/create_network.py
index c9c58e8..13c9667 100644
--- a/snaps/openstack/create_network.py
+++ b/snaps/openstack/create_network.py
@@ -15,7 +15,7 @@
import logging
import enum
-from neutronclient.common.exceptions import NetworkNotFoundClient
+from neutronclient.common.exceptions import NetworkNotFoundClient, Unauthorized
from snaps.config.network import NetworkConfig, SubnetConfig, PortConfig
from snaps.openstack.openstack_creator import OpenStackNetworkObject
@@ -51,9 +51,14 @@ class OpenStackNetwork(OpenStackNetworkObject):
"""
super(self.__class__, self).initialize()
- self.__network = neutron_utils.get_network(
- self._neutron, network_settings=self.network_settings,
- project_id=self.network_settings.get_project_id(self._os_creds))
+ try:
+ self.__network = neutron_utils.get_network(
+ self._neutron, self._keystone,
+ network_settings=self.network_settings,
+ project_name=self._os_creds.project_name)
+ except Unauthorized as e:
+ logger.warn('Unable to lookup network with name %s - %s',
+ self.network_settings.name, e)
return self.__network
@@ -77,12 +82,13 @@ class OpenStackNetwork(OpenStackNetworkObject):
"""
Removes and deletes all items created in reverse order.
"""
- if self.__network:
- try:
- neutron_utils.delete_network(self._neutron, self.__network)
- except NetworkNotFoundClient:
- pass
- self.__network = None
+ try:
+ neutron_utils.delete_network(self._neutron, self.__network)
+ except NetworkNotFoundClient:
+ pass
+ self.__network = None
+
+ super(self.__class__, self).clean()
def get_network(self):
"""
diff --git a/snaps/openstack/create_project.py b/snaps/openstack/create_project.py
index 0349890..ed7e9cd 100644
--- a/snaps/openstack/create_project.py
+++ b/snaps/openstack/create_project.py
@@ -74,6 +74,29 @@ class OpenStackProject(OpenStackIdentityObject):
logger.warn('Unable to associate user %s due to %s',
user.name, e)
+ if self.project_settings.quotas:
+ quota_dict = self.project_settings.quotas
+ nova = nova_utils.nova_client(self._os_creds, self._os_session)
+ quotas = nova_utils.get_compute_quotas(nova, self.__project.id)
+ if quotas:
+ if 'cores' in quota_dict:
+ quotas.cores = quota_dict['cores']
+ if 'instances' in quota_dict:
+ quotas.instances = quota_dict['instances']
+ if 'injected_files' in quota_dict:
+ quotas.injected_files = quota_dict['injected_files']
+ if 'injected_file_content_bytes' in quota_dict:
+ quotas.injected_file_content_bytes = \
+ quota_dict['injected_file_content_bytes']
+ if 'ram' in quota_dict:
+ quotas.ram = quota_dict['ram']
+ if 'fixed_ips' in quota_dict:
+ quotas.fixed_ips = quota_dict['fixed_ips']
+ if 'key_pairs' in quota_dict:
+ quotas.key_pairs = quota_dict['key_pairs']
+
+ nova_utils.update_quotas(nova, self.__project.id, quotas)
+
return self.__project
def clean(self):
@@ -83,16 +106,20 @@ class OpenStackProject(OpenStackIdentityObject):
"""
if self.__project:
# Delete security group 'default' if exists
- neutron = neutron_utils.neutron_client(self._os_creds)
- default_sec_grp = neutron_utils.get_security_group(
- neutron, sec_grp_name='default',
- project_id=self.__project.id)
- if default_sec_grp:
- try:
- neutron_utils.delete_security_group(
- neutron, default_sec_grp)
- except:
- pass
+ neutron = neutron_utils.neutron_client(
+ self._os_creds, self._os_session)
+ try:
+ default_sec_grp = neutron_utils.get_security_group(
+ neutron, self._keystone, sec_grp_name='default',
+ project_name=self.__project.name)
+ if default_sec_grp:
+ try:
+ neutron_utils.delete_security_group(
+ neutron, default_sec_grp)
+ except:
+ pass
+ finally:
+ neutron.httpclient.session.session.close()
# Delete Project
try:
@@ -114,6 +141,8 @@ class OpenStackProject(OpenStackIdentityObject):
if role:
keystone_utils.delete_role(self._keystone, role)
+ super(self.__class__, self).clean()
+
def get_project(self):
"""
Returns the OpenStack project object populated on create()
@@ -142,32 +171,48 @@ class OpenStackProject(OpenStackIdentityObject):
Returns the compute quotas as an instance of the ComputeQuotas class
:return:
"""
- nova = nova_utils.nova_client(self._os_creds)
- return nova_utils.get_compute_quotas(nova, self.__project.id)
+ nova = nova_utils.nova_client(self._os_creds, self._os_session)
+
+ try:
+ return nova_utils.get_compute_quotas(nova, self.__project.id)
+ finally:
+ nova.client.session.session.close()
def get_network_quotas(self):
"""
Returns the network quotas as an instance of the NetworkQuotas class
:return:
"""
- neutron = neutron_utils.neutron_client(self._os_creds)
- return neutron_utils.get_network_quotas(neutron, self.__project.id)
+ neutron = neutron_utils.neutron_client(
+ self._os_creds, self._os_session)
+ try:
+ return neutron_utils.get_network_quotas(neutron, self.__project.id)
+ finally:
+ neutron.httpclient.session.session.close()
def update_compute_quotas(self, compute_quotas):
"""
Updates the compute quotas for this project
:param compute_quotas: a ComputeQuotas object.
"""
- nova = nova_utils.nova_client(self._os_creds)
- nova_utils.update_quotas(nova, self.__project.id, compute_quotas)
+ nova = nova_utils.nova_client(self._os_creds, self._os_session)
+ try:
+ nova_utils.update_quotas(nova, self.__project.id, compute_quotas)
+ finally:
+ nova.client.session.session.close()
def update_network_quotas(self, network_quotas):
"""
Updates the network quotas for this project
:param network_quotas: a NetworkQuotas object.
"""
- neutron = neutron_utils.neutron_client(self._os_creds)
- neutron_utils.update_quotas(neutron, self.__project.id, network_quotas)
+ neutron = neutron_utils.neutron_client(
+ self._os_creds, self._os_session)
+ try:
+ neutron_utils.update_quotas(
+ neutron, self.__project.id, network_quotas)
+ finally:
+ neutron.httpclient.session.session.close()
class ProjectSettings(ProjectConfig):
@@ -181,4 +226,4 @@ class ProjectSettings(ProjectConfig):
from warnings import warn
warn('Use snaps.config.project.ProjectConfig instead',
DeprecationWarning)
- super(self.__class__, self).__init__(**kwargs) \ No newline at end of file
+ super(self.__class__, self).__init__(**kwargs)
diff --git a/snaps/openstack/create_qos.py b/snaps/openstack/create_qos.py
index 44e35a3..7764a57 100644
--- a/snaps/openstack/create_qos.py
+++ b/snaps/openstack/create_qos.py
@@ -90,6 +90,8 @@ class OpenStackQoS(OpenStackVolumeObject):
self.__qos = None
+ super(self.__class__, self).clean()
+
def get_qos(self):
"""
Returns the domain QoS object as it was populated when create() was
diff --git a/snaps/openstack/create_router.py b/snaps/openstack/create_router.py
index 4f95c3b..3269bbd 100644
--- a/snaps/openstack/create_router.py
+++ b/snaps/openstack/create_router.py
@@ -14,7 +14,7 @@
# limitations under the License.
import logging
-from neutronclient.common.exceptions import NotFound
+from neutronclient.common.exceptions import NotFound, Unauthorized
from snaps.config.router import RouterConfig
from snaps.openstack.openstack_creator import OpenStackNetworkObject
@@ -61,22 +61,28 @@ class OpenStackRouter(OpenStackNetworkObject):
"""
super(self.__class__, self).initialize()
- self.__router = neutron_utils.get_router(
- self._neutron, router_settings=self.router_settings)
+ try:
+ self.__router = neutron_utils.get_router(
+ self._neutron, self._keystone,
+ router_settings=self.router_settings,
+ project_name=self._os_creds.project_name)
+ except Unauthorized as e:
+ logger.warn('Unable to lookup router with name %s - %s',
+ self.router_settings.name, e)
if self.__router:
- for internal_subnet_name in self.router_settings.internal_subnets:
- internal_subnet = neutron_utils.get_subnet(
- self._neutron, subnet_name=internal_subnet_name)
+ for sub_config in self.router_settings.internal_subnets:
+ internal_subnet = self.__get_internal_subnet(sub_config)
if internal_subnet:
self.__internal_subnets.append(internal_subnet)
else:
raise RouterCreationError(
- 'Subnet not found with name ' + internal_subnet_name)
+ 'Subnet not found with name ' + internal_subnet.name)
for port_setting in self.router_settings.port_settings:
port = neutron_utils.get_port(
- self._neutron, port_settings=port_setting)
+ self._neutron, self._keystone, port_settings=port_setting,
+ project_name=self._os_creds.project_name)
if port:
self.__ports.append(port)
@@ -93,9 +99,8 @@ class OpenStackRouter(OpenStackNetworkObject):
self.__router = neutron_utils.create_router(
self._neutron, self._os_creds, self.router_settings)
- for internal_subnet_name in self.router_settings.internal_subnets:
- internal_subnet = neutron_utils.get_subnet(
- self._neutron, subnet_name=internal_subnet_name)
+ for sub_config in self.router_settings.internal_subnets:
+ internal_subnet = self.__get_internal_subnet(sub_config)
if internal_subnet:
self.__internal_subnets.append(internal_subnet)
if internal_subnet:
@@ -106,11 +111,12 @@ class OpenStackRouter(OpenStackNetworkObject):
self.__internal_router_interface = router_intf
else:
raise RouterCreationError(
- 'Subnet not found with name ' + internal_subnet_name)
+ 'Subnet not found with name {}'.format(sub_config))
for port_setting in self.router_settings.port_settings:
port = neutron_utils.get_port(
- self._neutron, port_settings=port_setting)
+ self._neutron, self._keystone, port_settings=port_setting,
+ project_name=self._os_creds.project_name)
logger.info(
'Retrieved port %s for router - %s', port_setting.name,
self.router_settings.name)
@@ -126,9 +132,8 @@ class OpenStackRouter(OpenStackNetworkObject):
port_setting.name,
self.router_settings.name)
self.__ports.append(port)
- neutron_utils.add_interface_router(self._neutron,
- self.__router,
- port=port)
+ neutron_utils.add_interface_router(
+ self._neutron, self.__router, port=port)
else:
raise RouterCreationError(
'Error creating port with name - '
@@ -138,6 +143,28 @@ class OpenStackRouter(OpenStackNetworkObject):
self._neutron, self.__router.id)
return self.__router
+ def __get_internal_subnet(self, sub_config):
+ """
+ returns the Subnet domain object from the subnet configurator
+ :param sub_config:
+ :return:
+ """
+ if isinstance(sub_config, dict):
+ sub_dict = sub_config['subnet']
+ network = neutron_utils.get_network(
+ self._neutron, self._keystone,
+ network_name=sub_dict['network_name'],
+ project_name=sub_dict['project_name'])
+ if network:
+ return neutron_utils.get_subnet(
+ self._neutron, network,
+ subnet_name=sub_dict['subnet_name'])
+ else:
+ return neutron_utils.get_subnet_by_name(
+ self._neutron, self._keystone,
+ subnet_name=sub_config,
+ project_name=self._os_creds.project_name)
+
def clean(self):
"""
Removes and deletes all items created in reverse order.
@@ -173,6 +200,8 @@ class OpenStackRouter(OpenStackNetworkObject):
pass
self.__router = None
+ super(self.__class__, self).clean()
+
def get_router(self):
"""
Returns the OpenStack router object
diff --git a/snaps/openstack/create_security_group.py b/snaps/openstack/create_security_group.py
index 7a20fe1..490f419 100644
--- a/snaps/openstack/create_security_group.py
+++ b/snaps/openstack/create_security_group.py
@@ -20,7 +20,6 @@ from neutronclient.common.exceptions import NotFound, Conflict
from snaps.config.security_group import (
SecurityGroupConfig, SecurityGroupRuleConfig)
from snaps.openstack.openstack_creator import OpenStackNetworkObject
-from snaps.openstack.utils import keystone_utils
from snaps.openstack.utils import neutron_utils
__author__ = 'spisarski'
@@ -57,7 +56,9 @@ class OpenStackSecurityGroup(OpenStackNetworkObject):
super(self.__class__, self).initialize()
self.__security_group = neutron_utils.get_security_group(
- self._neutron, sec_grp_settings=self.sec_grp_settings)
+ self._neutron, self._keystone,
+ sec_grp_settings=self.sec_grp_settings,
+ project_name=self._os_creds.project_name)
if self.__security_group:
# Populate rules
existing_rules = neutron_utils.get_rules_by_security_group(
@@ -84,10 +85,8 @@ class OpenStackSecurityGroup(OpenStackNetworkObject):
logger.info(
'Creating security group %s...' % self.sec_grp_settings.name)
- keystone = keystone_utils.keystone_client(self._os_creds)
self.__security_group = neutron_utils.create_security_group(
- self._neutron, keystone,
- self.sec_grp_settings)
+ self._neutron, self._keystone, self.sec_grp_settings)
# Get the rules added for free
auto_rules = neutron_utils.get_rules_by_security_group(
@@ -103,15 +102,16 @@ class OpenStackSecurityGroup(OpenStackNetworkObject):
for sec_grp_rule_setting in self.sec_grp_settings.rule_settings:
try:
custom_rule = neutron_utils.create_security_group_rule(
- self._neutron, sec_grp_rule_setting)
+ self._neutron, self._keystone, sec_grp_rule_setting,
+ self._os_creds.project_name)
self.__rules[sec_grp_rule_setting] = custom_rule
except Conflict as e:
logger.warn('Unable to create rule due to conflict - %s',
e)
# Refresh security group object to reflect the new rules added
- self.__security_group = neutron_utils.get_security_group(
- self._neutron, sec_grp_settings=self.sec_grp_settings)
+ self.__security_group = neutron_utils.get_security_group_by_id(
+ self._neutron, self.__security_group.id)
return self.__security_group
@@ -159,6 +159,8 @@ class OpenStackSecurityGroup(OpenStackNetworkObject):
self.__security_group = None
+ super(self.__class__, self).clean()
+
def get_security_group(self):
"""
Returns the OpenStack security group object
@@ -179,8 +181,9 @@ class OpenStackSecurityGroup(OpenStackNetworkObject):
:param rule_setting: the rule configuration
"""
rule_setting.sec_grp_name = self.sec_grp_settings.name
- new_rule = neutron_utils.create_security_group_rule(self._neutron,
- rule_setting)
+ new_rule = neutron_utils.create_security_group_rule(
+ self._neutron, self._keystone, rule_setting,
+ self._os_creds.project_name)
self.__rules[rule_setting] = new_rule
self.sec_grp_settings.rule_settings.append(rule_setting)
diff --git a/snaps/openstack/create_stack.py b/snaps/openstack/create_stack.py
index d4a6b10..71e5d0a 100644
--- a/snaps/openstack/create_stack.py
+++ b/snaps/openstack/create_stack.py
@@ -23,16 +23,17 @@ 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
-from snaps.openstack.create_security_group import OpenStackSecurityGroup
+from snaps.openstack.create_network import OpenStackNetwork
from snaps.openstack.create_router import OpenStackRouter
+from snaps.openstack.create_security_group import OpenStackSecurityGroup
from snaps.openstack.create_volume import OpenStackVolume
from snaps.openstack.create_volume_type import OpenStackVolumeType
from snaps.openstack.openstack_creator import OpenStackCloudObject
from snaps.openstack.utils import (
nova_utils, settings_utils, glance_utils, cinder_utils)
-
-from snaps.openstack.create_network import OpenStackNetwork
from snaps.openstack.utils import heat_utils, neutron_utils
+from snaps.thread_utils import worker_pool
+
__author__ = 'spisarski'
@@ -73,19 +74,35 @@ class OpenStackHeatStack(OpenStackCloudObject, object):
self.__stack = None
self.__heat_cli = None
+ self.__neutron = None
+ self.__nova = None
+ self.__glance = None
+ self.__cinder = None
+
def initialize(self):
"""
Loads the existing heat stack
:return: The Stack domain object or None
"""
- self.__heat_cli = heat_utils.heat_client(self._os_creds)
+ super(self.__class__, self).initialize()
+
+ self.__neutron = neutron_utils.neutron_client(
+ self._os_creds, self._os_session)
+ self.__nova = nova_utils.nova_client(self._os_creds, self._os_session)
+ self.__glance = glance_utils.glance_client(
+ self._os_creds, self._os_session)
+ self.__cinder = cinder_utils.cinder_client(
+ self._os_creds, self._os_session)
+
+ self.__heat_cli = heat_utils.heat_client(
+ self._os_creds, self._os_session)
self.__stack = heat_utils.get_stack(
self.__heat_cli, stack_settings=self.stack_settings)
if self.__stack:
logger.info('Found stack with name - ' + self.stack_settings.name)
return self.__stack
- def create(self):
+ def create(self, block=False):
"""
Creates the heat stack in OpenStack if it does not already exist and
returns the domain Stack object
@@ -101,7 +118,7 @@ class OpenStackHeatStack(OpenStackCloudObject, object):
self.stack_settings)
logger.info(
'Created stack with name - %s', self.stack_settings.name)
- if self.__stack and self.stack_complete(block=True):
+ if self.__stack and self.stack_complete(block=block):
logger.info('Stack is now active with name - %s',
self.stack_settings.name)
return self.__stack
@@ -111,6 +128,28 @@ class OpenStackHeatStack(OpenStackCloudObject, object):
logger.error('ERROR: STACK CREATION FAILED: %s', status)
raise StackCreationError('Failure while creating stack')
+ def update(self, env_vals, block=False):
+ """
+ Updates the heat stack in OpenStack
+ :param: env_vals - the values to update
+ :return: The Stack domain object or None
+ """
+ if self.__stack:
+ logger.info('Updating stack - %s', self.__stack.name)
+ heat_utils.update_stack(self.__heat_cli, self.__stack, env_vals)
+ if self.stack_updated(block=block):
+ logger.info('Stack %s is now updated with params: %s',
+ self.__stack.name, env_vals)
+ self.stack_settings.env_values = env_vals
+ self.__stack = heat_utils.get_stack_by_id(
+ self.__heat_cli, self.__stack.id)
+ return self.__stack
+ else:
+ status = heat_utils.get_stack_status_reason(self.__heat_cli,
+ self.__stack.id)
+ logger.error('ERROR: STACK UPDATE FAILED: %s', status)
+ raise StackUpdateError('Failure while updating stack')
+
def clean(self):
"""
Cleanse environment of all artifacts
@@ -152,13 +191,21 @@ class OpenStackHeatStack(OpenStackCloudObject, object):
self.__stack = None
+ self.__neutron.httpclient.session.session.close()
+ self.__nova.client.session.session.close()
+ self.__glance.http_client.session.session.close()
+ self.__cinder.client.session.session.close()
+
+ super(self.__class__, self).clean()
+
def get_stack(self):
"""
Returns the domain Stack object as it was populated when create() was
called
:return: the object
"""
- return self.__stack
+ if self.__stack:
+ return heat_utils.get_stack_by_id(self.__heat_cli, self.__stack.id)
def get_outputs(self):
"""
@@ -174,7 +221,9 @@ class OpenStackHeatStack(OpenStackCloudObject, object):
object
:return:
"""
- return heat_utils.get_stack_status(self.__heat_cli, self.__stack.id)
+ stack = self.get_stack()
+ if stack:
+ return stack.status
def stack_complete(self, block=False, timeout=None,
poll_interval=snaps.config.stack.POLL_INTERVAL):
@@ -193,6 +242,22 @@ class OpenStackHeatStack(OpenStackCloudObject, object):
snaps.config.stack.STATUS_CREATE_COMPLETE, block, timeout,
poll_interval, snaps.config.stack.STATUS_CREATE_FAILED)
+ def stack_updated(self, block=False,
+ timeout=snaps.config.stack.STACK_UPDATE_TIMEOUT,
+ poll_interval=snaps.config.stack.POLL_INTERVAL):
+ """
+ Returns true when the stack status returns the value of
+ expected_status_code
+ :param block: When true, thread will block until active or timeout
+ value in seconds has been exceeded (False)
+ :param timeout: The timeout value
+ :param poll_interval: The polling interval in seconds
+ :return: T/F
+ """
+ return self._stack_status_check(
+ snaps.config.stack.STATUS_UPDATE_COMPLETE, block, timeout,
+ poll_interval, snaps.config.stack.STATUS_UPDATE_FAILED)
+
def stack_deleted(self, block=False,
timeout=snaps.config.stack.STACK_DELETE_TIMEOUT,
poll_interval=snaps.config.stack.POLL_INTERVAL):
@@ -216,15 +281,13 @@ class OpenStackHeatStack(OpenStackCloudObject, object):
:return: list() of OpenStackNetwork objects
"""
- neutron = neutron_utils.neutron_client(self._os_creds)
-
out = list()
stack_networks = heat_utils.get_stack_networks(
- self.__heat_cli, neutron, self.__stack)
+ self.__heat_cli, self.__neutron, self.__stack)
for stack_network in stack_networks:
net_settings = settings_utils.create_network_config(
- neutron, stack_network)
+ self.__neutron, stack_network)
net_creator = OpenStackNetwork(self._os_creds, net_settings)
out.append(net_creator)
net_creator.initialize()
@@ -238,15 +301,13 @@ class OpenStackHeatStack(OpenStackCloudObject, object):
:return: list() of OpenStackNetwork objects
"""
- neutron = neutron_utils.neutron_client(self._os_creds)
-
out = list()
stack_security_groups = heat_utils.get_stack_security_groups(
- self.__heat_cli, neutron, self.__stack)
+ self.__heat_cli, self.__neutron, self.__stack)
for stack_security_group in stack_security_groups:
settings = settings_utils.create_security_group_config(
- neutron, stack_security_group)
+ self.__neutron, stack_security_group)
creator = OpenStackSecurityGroup(self._os_creds, settings)
out.append(creator)
creator.initialize()
@@ -260,21 +321,36 @@ class OpenStackHeatStack(OpenStackCloudObject, object):
:return: list() of OpenStackRouter objects
"""
- neutron = neutron_utils.neutron_client(self._os_creds)
-
out = list()
stack_routers = heat_utils.get_stack_routers(
- self.__heat_cli, neutron, self.__stack)
+ self.__heat_cli, self.__neutron, self.__stack)
for routers in stack_routers:
settings = settings_utils.create_router_config(
- neutron, routers)
+ self.__neutron, routers)
creator = OpenStackRouter(self._os_creds, settings)
out.append(creator)
creator.initialize()
return out
+ def __create_vm_inst(self, heat_keypair_option, stack_server):
+
+ vm_inst_settings = settings_utils.create_vm_inst_config(
+ self.__nova, self._keystone, self.__neutron, stack_server,
+ self._os_creds.project_name)
+ image_settings = settings_utils.determine_image_config(
+ self.__glance, stack_server, self.image_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)
+ vm_inst_creator = OpenStackVmInstance(
+ self._os_creds, vm_inst_settings, image_settings,
+ keypair_settings)
+ vm_inst_creator.initialize()
+ return vm_inst_creator
+
def get_vm_inst_creators(self, heat_keypair_option=None):
"""
Returns a list of VM Instance creator objects as configured by the heat
@@ -283,28 +359,21 @@ class OpenStackHeatStack(OpenStackCloudObject, object):
"""
out = list()
- nova = nova_utils.nova_client(self._os_creds)
- neutron = neutron_utils.neutron_client(self._os_creds)
stack_servers = heat_utils.get_stack_servers(
- self.__heat_cli, nova, neutron, self.__stack)
-
- glance = glance_utils.glance_client(self._os_creds)
+ self.__heat_cli, self.__nova, self.__neutron, self._keystone,
+ self.__stack, self._os_creds.project_name)
+ workers = []
for stack_server in stack_servers:
- vm_inst_settings = settings_utils.create_vm_inst_config(
- nova, neutron, stack_server)
- image_settings = settings_utils.determine_image_config(
- glance, stack_server, self.image_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)
- vm_inst_creator = OpenStackVmInstance(
- self._os_creds, vm_inst_settings, image_settings,
- keypair_settings)
- out.append(vm_inst_creator)
- vm_inst_creator.initialize()
+ worker = worker_pool().apply_async(
+ self.__create_vm_inst,
+ (heat_keypair_option,
+ stack_server))
+ workers.append(worker)
+
+ for worker in workers:
+ out.append(worker.get())
return out
@@ -316,10 +385,8 @@ class OpenStackHeatStack(OpenStackCloudObject, object):
"""
out = list()
- cinder = cinder_utils.cinder_client(self._os_creds)
-
volumes = heat_utils.get_stack_volumes(
- self.__heat_cli, cinder, self.__stack)
+ self.__heat_cli, self.__cinder, self.__stack)
for volume in volumes:
settings = settings_utils.create_volume_config(volume)
@@ -342,10 +409,8 @@ class OpenStackHeatStack(OpenStackCloudObject, object):
"""
out = list()
- cinder = cinder_utils.cinder_client(self._os_creds)
-
vol_types = heat_utils.get_stack_volume_types(
- self.__heat_cli, cinder, self.__stack)
+ self.__heat_cli, self.__cinder, self.__stack)
for volume in vol_types:
settings = settings_utils.create_volume_type_config(volume)
@@ -369,10 +434,9 @@ class OpenStackHeatStack(OpenStackCloudObject, object):
"""
out = list()
- nova = nova_utils.nova_client(self._os_creds)
keypairs = heat_utils.get_stack_keypairs(
- self.__heat_cli, nova, self.__stack)
+ self.__heat_cli, self.__nova, self.__stack)
for keypair in keypairs:
settings = settings_utils.create_keypair_config(
@@ -397,10 +461,9 @@ class OpenStackHeatStack(OpenStackCloudObject, object):
"""
out = list()
- nova = nova_utils.nova_client(self._os_creds)
flavors = heat_utils.get_stack_flavors(
- self.__heat_cli, nova, self.__stack)
+ self.__heat_cli, self.__nova, self.__stack)
for flavor in flavors:
settings = settings_utils.create_flavor_config(flavor)
@@ -486,6 +549,22 @@ class OpenStackHeatStack(OpenStackCloudObject, object):
return status == expected_status_code
+def generate_creator(os_creds, stack_inst, image_settings):
+ """
+ Initializes an OpenStackHeatStack object
+ :param os_creds: the OpenStack credentials
+ :param stack_inst: the SNAPS-OO VmInst domain object
+ :param image_settings: list of SNAPS-OO ImageConfig objects
+ :return: an initialized OpenStackHeatStack object
+ """
+
+ heat_config = StackConfig(
+ name=stack_inst.name, template={'place': 'holder'})
+ heat_creator = OpenStackHeatStack(os_creds, heat_config, image_settings)
+ heat_creator.initialize()
+ return heat_creator
+
+
class StackSettings(StackConfig):
"""
Class to hold the configuration settings required for creating OpenStack
@@ -505,6 +584,11 @@ class StackCreationError(Exception):
Exception to be thrown when an stack cannot be created
"""
+class StackUpdateError(Exception):
+ """
+ Exception to be thrown when an stack update failed
+ """
+
class StackError(Exception):
"""
diff --git a/snaps/openstack/create_user.py b/snaps/openstack/create_user.py
index 5da3a5e..b187f4e 100644
--- a/snaps/openstack/create_user.py
+++ b/snaps/openstack/create_user.py
@@ -77,6 +77,8 @@ class OpenStackUser(OpenStackIdentityObject):
pass
self.__user = None
+ super(self.__class__, self).clean()
+
def get_user(self):
"""
Returns the OpenStack user object populated in create()
@@ -91,6 +93,9 @@ class OpenStackUser(OpenStackIdentityObject):
credentials
:return:
"""
+ if not project_name:
+ project_name = self._os_creds.project_name
+
return OSCreds(
username=self.user_settings.name,
password=self.user_settings.password,
@@ -102,6 +107,7 @@ class OpenStackUser(OpenStackIdentityObject):
compute_api_version=self._os_creds.compute_api_version,
heat_api_version=self._os_creds.heat_api_version,
volume_api_version=self._os_creds.volume_api_version,
+ region_name=self._os_creds.region_name,
user_domain_name=self._os_creds.user_domain_name,
user_domain_id=self._os_creds.user_domain_id,
project_domain_name=self._os_creds.project_domain_name,
diff --git a/snaps/openstack/create_volume.py b/snaps/openstack/create_volume.py
index c134ca1..b35cd89 100644
--- a/snaps/openstack/create_volume.py
+++ b/snaps/openstack/create_volume.py
@@ -60,7 +60,9 @@ class OpenStackVolume(OpenStackVolumeObject):
super(self.__class__, self).initialize()
self.__volume = cinder_utils.get_volume(
- self._cinder, volume_settings=self.volume_settings)
+ self._cinder, self._keystone,
+ volume_settings=self.volume_settings,
+ project_name=self._os_creds.project_name)
return self.__volume
def create(self, block=False):
@@ -73,7 +75,7 @@ class OpenStackVolume(OpenStackVolumeObject):
if not self.__volume:
self.__volume = cinder_utils.create_volume(
- self._cinder, self.volume_settings)
+ self._cinder, self._keystone, self.volume_settings)
logger.info(
'Created volume with name - %s', self.volume_settings.name)
@@ -124,6 +126,8 @@ class OpenStackVolume(OpenStackVolumeObject):
self.__volume = None
+ super(self.__class__, self).clean()
+
def get_volume(self):
"""
Returns the domain Volume object as it was populated when create() was
diff --git a/snaps/openstack/create_volume_type.py b/snaps/openstack/create_volume_type.py
index a7198d8..9a45561 100644
--- a/snaps/openstack/create_volume_type.py
+++ b/snaps/openstack/create_volume_type.py
@@ -87,6 +87,8 @@ class OpenStackVolumeType(OpenStackVolumeObject):
self.__volume_type = None
+ super(self.__class__, self).clean()
+
def get_volume_type(self):
"""
Returns the domain Volume object as it was populated when create() was
diff --git a/snaps/openstack/openstack_creator.py b/snaps/openstack/openstack_creator.py
index 0caee9a..6eeac37 100644
--- a/snaps/openstack/openstack_creator.py
+++ b/snaps/openstack/openstack_creator.py
@@ -29,17 +29,24 @@ class OpenStackCloudObject(CloudObject):
Constructor
:param os_creds: the OpenStack credentials object
"""
- # super(self.__class__, self, os_creds)
self._os_creds = os_creds
+ self._os_session = None
+ self._keystone = None
def initialize(self):
- raise NotImplementedError('Do not override abstract method')
+ self._os_session = keystone_utils.keystone_session(self._os_creds)
+ self._keystone = keystone_utils.keystone_client(
+ self._os_creds, session=self._os_session)
+
+ def get_os_creds(self):
+ return self._os_creds
def create(self):
raise NotImplementedError('Do not override abstract method')
def clean(self):
- raise NotImplementedError('Do not override abstract method')
+ if self._os_session:
+ keystone_utils.close_session(self._os_session)
class OpenStackComputeObject(OpenStackCloudObject):
@@ -56,14 +63,12 @@ class OpenStackComputeObject(OpenStackCloudObject):
self._nova = None
def initialize(self):
- self._nova = nova_utils.nova_client(self._os_creds)
+ super(OpenStackComputeObject, self).initialize()
+ self._nova = nova_utils.nova_client(self._os_creds, self._os_session)
def create(self):
raise NotImplementedError('Do not override abstract method')
- def clean(self):
- raise NotImplementedError('Do not override abstract method')
-
class OpenStackNetworkObject(OpenStackCloudObject):
"""
@@ -79,14 +84,13 @@ class OpenStackNetworkObject(OpenStackCloudObject):
self._neutron = None
def initialize(self):
- self._neutron = neutron_utils.neutron_client(self._os_creds)
+ super(OpenStackNetworkObject, self).initialize()
+ self._neutron = neutron_utils.neutron_client(
+ self._os_creds, self._os_session)
def create(self):
raise NotImplementedError('Do not override abstract method')
- def clean(self):
- raise NotImplementedError('Do not override abstract method')
-
class OpenStackIdentityObject(OpenStackCloudObject):
"""
@@ -99,17 +103,13 @@ class OpenStackIdentityObject(OpenStackCloudObject):
:param os_creds: the OpenStack credentials object
"""
super(OpenStackIdentityObject, self).__init__(os_creds)
- self._keystone = None
def initialize(self):
- self._keystone = keystone_utils.keystone_client(self._os_creds)
+ super(OpenStackIdentityObject, self).initialize()
def create(self):
raise NotImplementedError('Do not override abstract method')
- def clean(self):
- raise NotImplementedError('Do not override abstract method')
-
class OpenStackVolumeObject(OpenStackCloudObject):
"""
@@ -125,14 +125,13 @@ class OpenStackVolumeObject(OpenStackCloudObject):
self._cinder = None
def initialize(self):
- self._cinder = cinder_utils.cinder_client(self._os_creds)
+ super(OpenStackVolumeObject, self).initialize()
+ self._cinder = cinder_utils.cinder_client(
+ self._os_creds, self._os_session)
def create(self):
raise NotImplementedError('Do not override abstract method')
- def clean(self):
- raise NotImplementedError('Do not override abstract method')
-
class OpenStackMagnumObject(OpenStackCloudObject):
"""
@@ -148,10 +147,9 @@ class OpenStackMagnumObject(OpenStackCloudObject):
self._magnum = None
def initialize(self):
- self._magnum = magnum_utils.magnum_client(self._os_creds)
+ super(OpenStackMagnumObject, self).initialize()
+ self._magnum = magnum_utils.magnum_client(
+ self._os_creds, self._os_session)
def create(self):
raise NotImplementedError('Do not override abstract method')
-
- def clean(self):
- raise NotImplementedError('Do not override abstract method')
diff --git a/snaps/openstack/os_credentials.py b/snaps/openstack/os_credentials.py
index 2553410..11ef8ff 100644
--- a/snaps/openstack/os_credentials.py
+++ b/snaps/openstack/os_credentials.py
@@ -63,7 +63,7 @@ class OSCreds:
self.project_name = kwargs.get('project_name')
if kwargs.get('identity_api_version') is None:
- self.identity_api_version = keystone_utils.V2_VERSION_NUM
+ self.identity_api_version = keystone_utils.V3_VERSION_NUM
else:
self.identity_api_version = float(kwargs['identity_api_version'])
@@ -85,7 +85,9 @@ class OSCreds:
if kwargs.get('heat_api_version') is None:
self.heat_api_version = 1
else:
- self.heat_api_version = float(kwargs['heat_api_version'])
+ val = kwargs['heat_api_version']
+ ver = float(val)
+ self.heat_api_version = int(ver)
if kwargs.get('volume_api_version') is None:
self.volume_api_version = cinder_utils.VERSION_2
@@ -169,7 +171,45 @@ class OSCreds:
return new_url
- @property
+ def to_dict(self):
+ """Converts object to a dict that can be used to construct another"""
+ return {'username': self.username,
+ 'password': self.password,
+ 'auth_url': self.auth_url,
+ 'project_name': self.project_name,
+ 'identity_api_version': self.identity_api_version,
+ 'image_api_version': self.image_api_version,
+ 'network_api_version': self.network_api_version,
+ 'compute_api_version': self.compute_api_version,
+ 'heat_api_version': self.heat_api_version,
+ 'user_domain_id': self.user_domain_id,
+ 'user_domain_name': self.user_domain_name,
+ 'project_domain_id': self.project_domain_id,
+ 'project_domain_name': self.project_domain_name,
+ 'interface': self.interface,
+ 'region_name': self.region_name,
+ 'proxy_settings': self.proxy_settings,
+ 'cacert': self.cacert}
+
+ def __eq__(self, other):
+ return (self.username == other.username and
+ self.password == other.password and
+ self.auth_url == other.auth_url and
+ self.project_name == other.project_name and
+ float(self.identity_api_version) == float(other.identity_api_version) and
+ float(self.image_api_version) == float(other.image_api_version) and
+ float(self.network_api_version) == float(other.network_api_version) and
+ float(self.compute_api_version) == float(other.compute_api_version) and
+ float(self.heat_api_version) == float(other.heat_api_version) and
+ self.user_domain_id == other.user_domain_id and
+ self.user_domain_name == other.user_domain_name and
+ self.project_domain_id == other.project_domain_id and
+ self.project_domain_name == other.project_domain_name and
+ self.interface == other.interface and
+ self.region_name == other.region_name and
+ self.proxy_settings == other.proxy_settings and
+ self.cacert == other.cacert)
+
def __str__(self):
"""Converts object to a string"""
return ('OSCreds - username=' + str(self.username) +
diff --git a/snaps/openstack/tests/cluster_template_tests.py b/snaps/openstack/tests/cluster_template_tests.py
index 355467d..eda790d 100644
--- a/snaps/openstack/tests/cluster_template_tests.py
+++ b/snaps/openstack/tests/cluster_template_tests.py
@@ -54,7 +54,8 @@ class CreateClusterTemplateTests(OSIntegrationTestCase):
self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
self.cluster_type_name = self.guid + '-cluster-type'
- self.magnum = magnum_utils.magnum_client(self.os_creds)
+ self.magnum = magnum_utils.magnum_client(
+ self.os_creds, self.os_session)
metadata = self.image_metadata
if not metadata:
@@ -68,9 +69,10 @@ class CreateClusterTemplateTests(OSIntegrationTestCase):
self.image_creator = OpenStackImage(self.os_creds, os_image_settings)
- self.flavor_creator = OpenStackFlavor(
- self.os_creds, FlavorConfig(
- name=self.guid + '-flavor', ram=512, disk=10, vcpus=1))
+ flavor_config = openstack_tests.get_flavor_config(
+ name=self.guid + '-flavor', ram=512, disk=10,
+ vcpus=1, metadata=self.flavor_metadata)
+ self.flavor_creator = OpenStackFlavor(self.os_creds, flavor_config)
keypair_priv_filepath = 'tmp/' + self.guid
keypair_pub_filepath = keypair_priv_filepath + '.pub'
diff --git a/snaps/openstack/tests/conf/os_credentials_tests.py b/snaps/openstack/tests/conf/os_credentials_tests.py
index 192be86..696ca2d 100644
--- a/snaps/openstack/tests/conf/os_credentials_tests.py
+++ b/snaps/openstack/tests/conf/os_credentials_tests.py
@@ -142,9 +142,9 @@ class OSCredsUnitTests(unittest.TestCase):
project_name='hello')
self.assertEqual('foo', os_creds.username)
self.assertEqual('bar', os_creds.password)
- self.assertEqual('http://foo.bar:5000/v2.0', os_creds.auth_url)
+ self.assertEqual('http://foo.bar:5000/v3', os_creds.auth_url)
self.assertEqual('hello', os_creds.project_name)
- self.assertEqual(2, os_creds.identity_api_version)
+ self.assertEqual(3, os_creds.identity_api_version)
self.assertEqual(2, os_creds.image_api_version)
self.assertEqual(2, os_creds.compute_api_version)
self.assertEqual(1, os_creds.heat_api_version)
@@ -165,9 +165,9 @@ class OSCredsUnitTests(unittest.TestCase):
'project_name': 'hello'})
self.assertEqual('foo', os_creds.username)
self.assertEqual('bar', os_creds.password)
- self.assertEqual('http://foo.bar:5000/v2.0', os_creds.auth_url)
+ self.assertEqual('http://foo.bar:5000/v3', os_creds.auth_url)
self.assertEqual('hello', os_creds.project_name)
- self.assertEqual(2, os_creds.identity_api_version)
+ self.assertEqual(3, os_creds.identity_api_version)
self.assertEqual(2, os_creds.image_api_version)
self.assertEqual(2, os_creds.compute_api_version)
self.assertEqual(1, os_creds.heat_api_version)
@@ -243,9 +243,9 @@ class OSCredsUnitTests(unittest.TestCase):
project_name='hello', proxy_settings=proxy_settings)
self.assertEqual('foo', os_creds.username)
self.assertEqual('bar', os_creds.password)
- self.assertEqual('http://foo.bar:5000/v2.0', os_creds.auth_url)
+ self.assertEqual('http://foo.bar:5000/v3', os_creds.auth_url)
self.assertEqual('hello', os_creds.project_name)
- self.assertEqual(2, os_creds.identity_api_version)
+ self.assertEqual(3, os_creds.identity_api_version)
self.assertEqual(2, os_creds.image_api_version)
self.assertEqual(2, os_creds.compute_api_version)
self.assertEqual(1, os_creds.heat_api_version)
@@ -262,6 +262,11 @@ class OSCredsUnitTests(unittest.TestCase):
self.assertIsNone(os_creds.proxy_settings.ssh_proxy_cmd)
self.assertIsNone(os_creds.region_name)
+ creds_dict = os_creds.to_dict()
+ creds_from_dict = OSCreds(**creds_dict)
+
+ self.assertEqual(os_creds, creds_from_dict)
+
def test_proxy_settings_obj_kwargs(self):
proxy_settings = ProxySettings(host='foo', port=1234)
os_creds = OSCreds(
@@ -273,9 +278,9 @@ class OSCredsUnitTests(unittest.TestCase):
'project_domain_name': 'domain4'})
self.assertEqual('foo', os_creds.username)
self.assertEqual('bar', os_creds.password)
- self.assertEqual('http://foo.bar:5000/v2.0', os_creds.auth_url)
+ self.assertEqual('http://foo.bar:5000/v3', os_creds.auth_url)
self.assertEqual('hello', os_creds.project_name)
- self.assertEqual(2, os_creds.identity_api_version)
+ self.assertEqual(3, os_creds.identity_api_version)
self.assertEqual(2, os_creds.image_api_version)
self.assertEqual(2, os_creds.compute_api_version)
self.assertEqual(1, os_creds.heat_api_version)
@@ -300,9 +305,9 @@ class OSCredsUnitTests(unittest.TestCase):
project_domain_id='domain3', project_domain_name='domain4')
self.assertEqual('foo', os_creds.username)
self.assertEqual('bar', os_creds.password)
- self.assertEqual('http://foo.bar:5000/v2.0', os_creds.auth_url)
+ self.assertEqual('http://foo.bar:5000/v3', os_creds.auth_url)
self.assertEqual('hello', os_creds.project_name)
- self.assertEqual(2, os_creds.identity_api_version)
+ self.assertEqual(3, os_creds.identity_api_version)
self.assertEqual(2, os_creds.image_api_version)
self.assertEqual(2, os_creds.compute_api_version)
self.assertEqual(1, os_creds.heat_api_version)
@@ -326,9 +331,9 @@ class OSCredsUnitTests(unittest.TestCase):
'region_name': 'test_region'})
self.assertEqual('foo', os_creds.username)
self.assertEqual('bar', os_creds.password)
- self.assertEqual('http://foo.bar:5000/v2.0', os_creds.auth_url)
+ self.assertEqual('http://foo.bar:5000/v3', os_creds.auth_url)
self.assertEqual('hello', os_creds.project_name)
- self.assertEqual(2, os_creds.identity_api_version)
+ self.assertEqual(3, os_creds.identity_api_version)
self.assertEqual(2, os_creds.image_api_version)
self.assertEqual(2, os_creds.compute_api_version)
self.assertEqual(1, os_creds.heat_api_version)
diff --git a/snaps/openstack/tests/conf/os_env.yaml.template b/snaps/openstack/tests/conf/os_env.yaml.template
index 36e3cfd..53d500f 100644
--- a/snaps/openstack/tests/conf/os_env.yaml.template
+++ b/snaps/openstack/tests/conf/os_env.yaml.template
@@ -14,4 +14,7 @@
#os_auth_url: http://<host>:<port>/
#project_name: admin
#identity_api_version: 3
-#ext_net: <external network name> \ No newline at end of file
+#ext_net: <external network name>
+
+flavor_metadata:
+ hw:mem_page_size: large
diff --git a/snaps/openstack/tests/create_flavor_tests.py b/snaps/openstack/tests/create_flavor_tests.py
index f84355d..a69de40 100644
--- a/snaps/openstack/tests/create_flavor_tests.py
+++ b/snaps/openstack/tests/create_flavor_tests.py
@@ -20,6 +20,7 @@ from snaps.openstack import create_flavor
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
+from snaps.openstack.tests import openstack_tests
__author__ = 'spisarski'
@@ -274,7 +275,7 @@ class CreateFlavorTests(OSComponentTestCase):
guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
self.flavor_name = guid + 'name'
- self.nova = nova_utils.nova_client(self.os_creds)
+ self.nova = nova_utils.nova_client(self.os_creds, self.os_session)
# Initialize for cleanup
self.flavor_creator = None
@@ -286,6 +287,8 @@ class CreateFlavorTests(OSComponentTestCase):
if self.flavor_creator:
self.flavor_creator.clean()
+ super(self.__class__, self).__clean__()
+
def test_create_flavor(self):
"""
Tests the creation of an OpenStack flavor.
@@ -362,10 +365,12 @@ class CreateFlavorTests(OSComponentTestCase):
raise any exceptions.
"""
# Create Flavor
- flavor_settings = FlavorConfig(
+ if self.flavor_metadata:
+ self.flavor_metadata.update(create_flavor.MEM_PAGE_SIZE_ANY)
+ flavor_settings = openstack_tests.get_flavor_config(
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)
+ metadata=self.flavor_metadata)
self.flavor_creator = OpenStackFlavor(self.os_creds, flavor_settings)
flavor = self.flavor_creator.create()
self.assertTrue(validate_flavor(self.nova, flavor_settings, flavor))
diff --git a/snaps/openstack/tests/create_image_tests.py b/snaps/openstack/tests/create_image_tests.py
index 9965f87..ae59a67 100644
--- a/snaps/openstack/tests/create_image_tests.py
+++ b/snaps/openstack/tests/create_image_tests.py
@@ -265,7 +265,8 @@ class CreateImageSuccessTests(OSIntegrationTestCase):
guid = uuid.uuid4()
self.image_name = self.__class__.__name__ + '-' + str(guid)
- self.glance = glance_utils.glance_client(self.os_creds)
+ self.glance = glance_utils.glance_client(
+ self.os_creds, self.os_session)
self.image_creator = None
if self.image_metadata and 'glance_tests' in self.image_metadata:
@@ -379,8 +380,8 @@ class CreateImageSuccessTests(OSIntegrationTestCase):
clean() does not raise an Exception.
"""
# Create Image
- self.image_creator = create_image.OpenStackImage(self.os_creds,
- self.image_settings)
+ self.image_creator = create_image.OpenStackImage(
+ self.os_creds, self.image_settings)
created_image = self.image_creator.create()
self.assertIsNotNone(created_image)
@@ -562,7 +563,8 @@ class CreateMultiPartImageTests(OSIntegrationTestCase):
guid = uuid.uuid4()
self.image_creators = list()
self.image_name = self.__class__.__name__ + '-' + str(guid)
- self.glance = glance_utils.glance_client(self.os_creds)
+ self.glance = glance_utils.glance_client(
+ self.os_creds, self.os_session)
self.tmp_dir = 'tmp/' + str(guid)
if not os.path.exists(self.tmp_dir):
diff --git a/snaps/openstack/tests/create_instance_tests.py b/snaps/openstack/tests/create_instance_tests.py
index 55da144..17831b3 100644
--- a/snaps/openstack/tests/create_instance_tests.py
+++ b/snaps/openstack/tests/create_instance_tests.py
@@ -20,11 +20,10 @@ import unittest
import uuid
import os
-from neutronclient.common.exceptions import InvalidIpForSubnetClient
-from novaclient.exceptions import BadRequest
+from neutronclient.common.exceptions import (
+ InvalidIpForSubnetClient, 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
@@ -45,10 +44,11 @@ from snaps.openstack.create_network import OpenStackNetwork
from snaps.openstack.create_router import OpenStackRouter
from snaps.openstack.create_security_group import OpenStackSecurityGroup
from snaps.openstack.create_volume import OpenStackVolume
+from snaps.openstack.os_credentials import OSCreds
from snaps.openstack.tests import openstack_tests, validation_utils
from snaps.openstack.tests.os_source_file_test import (
OSIntegrationTestCase, OSComponentTestCase)
-from snaps.openstack.utils import nova_utils
+from snaps.openstack.utils import nova_utils, keystone_utils, neutron_utils
from snaps.openstack.utils.nova_utils import RebootType
from snaps.openstack.utils import nova_utils, settings_utils, neutron_utils
@@ -294,7 +294,7 @@ class SimpleHealthCheck(OSIntegrationTestCase):
"""
super(self.__class__, self).__start__()
- self.nova = nova_utils.nova_client(self.os_creds)
+ self.nova = nova_utils.nova_client(self.os_creds, self.os_session)
guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
self.vm_inst_name = guid + '-inst'
self.port_1_name = guid + 'port-1'
@@ -306,6 +306,7 @@ class SimpleHealthCheck(OSIntegrationTestCase):
self.inst_creator = None
self.priv_net_config = openstack_tests.get_priv_net_config(
+ project_name=self.os_creds.project_name,
net_name=guid + '-priv-net',
subnet_name=guid + '-priv-subnet',
netconf_override=self.netconf_override)
@@ -334,10 +335,11 @@ class SimpleHealthCheck(OSIntegrationTestCase):
if (self.flavor_metadata and
self.flavor_metadata.get('hw:mem_page_size') == 'large'):
self.flavor_ram = 1024
+ flavor_config = openstack_tests.get_flavor_config(
+ name=guid + '-flavor-name', ram=self.flavor_ram, disk=10,
+ vcpus=1, metadata=self.flavor_metadata)
self.flavor_creator = OpenStackFlavor(
- self.admin_os_creds,
- FlavorConfig(name=guid + '-flavor-name', ram=self.flavor_ram,
- disk=10, vcpus=1, metadata=self.flavor_metadata))
+ self.admin_os_creds, flavor_config)
self.flavor_creator.create()
except Exception as e:
self.tearDown()
@@ -411,23 +413,16 @@ class CreateInstanceSimpleTests(OSIntegrationTestCase):
def setUp(self):
"""
- Instantiates the CreateImage object that is responsible for downloading
- and creating an OS image file
- within OpenStack
+ Setup the objects required for the test
"""
super(self.__class__, self).__start__()
- guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
- self.vm_inst_name = guid + '-inst'
+ self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
+ self.vm_inst_name = self.guid + '-inst'
self.nova = nova_utils.nova_client(self.os_creds)
self.neutron = neutron_utils.neutron_client(self.os_creds)
os_image_settings = openstack_tests.cirros_image_settings(
- name=guid + '-image', image_metadata=self.image_metadata)
-
- net_config = openstack_tests.get_priv_net_config(
- net_name=guid + '-pub-net', subnet_name=guid + '-pub-subnet',
- router_name=guid + '-pub-router', external_net=self.ext_net_name,
- netconf_override=self.netconf_override)
+ name=self.guid + '-image', image_metadata=self.image_metadata)
# Initialize for tearDown()
self.image_creator = None
@@ -443,21 +438,13 @@ class CreateInstanceSimpleTests(OSIntegrationTestCase):
self.image_creator.create()
# Create Flavor
+ flavor_config = openstack_tests.get_flavor_config(
+ name=self.guid + '-flavor-name', ram=256, disk=10,
+ vcpus=2, metadata=self.flavor_metadata)
self.flavor_creator = OpenStackFlavor(
- self.admin_os_creds,
- FlavorConfig(name=guid + '-flavor-name', ram=256, disk=10,
- vcpus=2, metadata=self.flavor_metadata))
+ self.admin_os_creds, flavor_config)
self.flavor_creator.create()
-
- # Create Network
- self.network_creator = OpenStackNetwork(
- self.os_creds, net_config.network_settings)
- self.network_creator.create()
-
- self.port_settings = PortConfig(
- name=guid + '-port',
- network_name=net_config.network_settings.name)
-
+ self.network_creator = None
except Exception as e:
self.tearDown()
raise e
@@ -504,6 +491,22 @@ class CreateInstanceSimpleTests(OSIntegrationTestCase):
Tests the creation of an OpenStack instance with a single port with a
static IP without a Floating IP.
"""
+ # Create Network
+ net_config = openstack_tests.get_priv_net_config(
+ project_name=self.os_creds.project_name,
+ net_name=self.guid + '-pub-net',
+ subnet_name=self.guid + '-pub-subnet',
+ router_name=self.guid + '-pub-router',
+ external_net=self.ext_net_name,
+ netconf_override=self.netconf_override)
+ self.network_creator = OpenStackNetwork(
+ self.os_creds, net_config.network_settings)
+ self.network_creator.create()
+
+ self.port_settings = PortConfig(
+ name=self.guid + '-port',
+ network_name=net_config.network_settings.name)
+
instance_settings = VmInstanceConfig(
name=self.vm_inst_name,
flavor=self.flavor_creator.flavor_settings.name,
@@ -513,20 +516,174 @@ class CreateInstanceSimpleTests(OSIntegrationTestCase):
self.os_creds, instance_settings,
self.image_creator.image_settings)
- vm_inst = self.inst_creator.create()
- self.assertIsNotNone(nova_utils.get_server(
- self.nova, self.neutron, vm_inst_settings=instance_settings))
+ vm_inst = self.inst_creator.create(block=True)
+ vm_inst_get = nova_utils.get_server(
+ self.nova, self.neutron, self.keystone,
+ vm_inst_settings=instance_settings)
+ self.assertEqual(vm_inst, vm_inst_get)
+
+ self.assertIsNotNone(self.inst_creator.get_vm_inst().availability_zone)
+ self.assertIsNone(self.inst_creator.get_vm_inst().compute_host)
# Delete instance
nova_utils.delete_vm_instance(self.nova, vm_inst)
self.assertTrue(self.inst_creator.vm_deleted(block=True))
self.assertIsNone(nova_utils.get_server(
- self.nova, self.neutron, vm_inst_settings=instance_settings))
+ self.nova, self.neutron, self.keystone,
+ vm_inst_settings=instance_settings))
# Exception should not be thrown
self.inst_creator.clean()
+ def test_create_admin_instance(self):
+ """
+ Tests the creation of an OpenStack instance with a single port with a
+ static IP without a Floating IP.
+ """
+ # Create Network
+ net_config = openstack_tests.get_priv_net_config(
+ project_name=self.os_creds.project_name,
+ net_name=self.guid + '-pub-net',
+ subnet_name=self.guid + '-pub-subnet',
+ router_name=self.guid + '-pub-router',
+ external_net=self.ext_net_name,
+ netconf_override=self.netconf_override)
+ self.network_creator = OpenStackNetwork(
+ self.admin_os_creds, net_config.network_settings)
+ self.network_creator.create()
+
+ self.port_settings = PortConfig(
+ name=self.guid + '-port',
+ network_name=net_config.network_settings.name)
+
+ instance_settings = VmInstanceConfig(
+ name=self.vm_inst_name,
+ flavor=self.flavor_creator.flavor_settings.name,
+ port_settings=[self.port_settings])
+
+ self.inst_creator = OpenStackVmInstance(
+ self.admin_os_creds, instance_settings,
+ self.image_creator.image_settings)
+
+ admin_nova = nova_utils.nova_client(self.admin_os_creds)
+ admin_neutron = neutron_utils.neutron_client(self.admin_os_creds)
+ admin_key = keystone_utils.keystone_client(self.admin_os_creds)
+ vm_inst = self.inst_creator.create(block=True)
+
+ self.assertIsNotNone(vm_inst)
+ vm_inst_get = nova_utils.get_server(
+ admin_nova, admin_neutron, admin_key,
+ vm_inst_settings=instance_settings)
+ self.assertEqual(vm_inst, vm_inst_get)
+
+ self.assertIsNone(nova_utils.get_server(
+ self.nova, self.neutron, self.keystone,
+ vm_inst_settings=instance_settings))
+
+ self.assertIsNotNone(self.inst_creator.get_vm_inst().availability_zone)
+ self.assertIsNotNone(self.inst_creator.get_vm_inst().compute_host)
+
+
+class CreateInstanceExternalNetTests(OSIntegrationTestCase):
+ """
+ Simple instance creation tests where the network is external
+ """
+
+ def setUp(self):
+ """
+ Instantiates the CreateImage object that is responsible for downloading
+ and creating an OS image file
+ within OpenStack
+ """
+ super(self.__class__, self).__start__()
+
+ guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
+ self.vm_inst_name = guid + '-inst'
+ self.nova = nova_utils.nova_client(self.admin_os_creds)
+ self.neutron = neutron_utils.neutron_client(self.admin_os_creds)
+ os_image_settings = openstack_tests.cirros_image_settings(
+ name=guid + '-image', image_metadata=self.image_metadata)
+
+ # Initialize for tearDown()
+ self.image_creator = None
+ self.flavor_creator = None
+ self.inst_creator = None
+
+ try:
+ # Create Image
+ self.image_creator = OpenStackImage(self.os_creds,
+ os_image_settings)
+ self.image_creator.create()
+
+ # Create Flavor
+ flavor_config = openstack_tests.get_flavor_config(
+ name=guid + '-flavor-name', ram=256, disk=10,
+ vcpus=2, metadata=self.flavor_metadata)
+ self.flavor_creator = OpenStackFlavor(
+ self.admin_os_creds, flavor_config)
+ self.flavor_creator.create()
+
+ self.port_settings = PortConfig(
+ name=guid + '-port',
+ network_name=self.ext_net_name)
+
+ except Exception as e:
+ self.tearDown()
+ raise e
+
+ def tearDown(self):
+ """
+ Cleans the created object
+ """
+ if self.inst_creator:
+ try:
+ self.inst_creator.clean()
+ except Exception as e:
+ logger.error(
+ 'Unexpected exception cleaning VM instance with message '
+ '- %s', e)
+
+ if self.flavor_creator:
+ try:
+ self.flavor_creator.clean()
+ except Exception as e:
+ logger.error(
+ 'Unexpected exception cleaning flavor with message - %s',
+ e)
+
+ if self.image_creator and not self.image_creator.image_settings.exists:
+ try:
+ self.image_creator.clean()
+ except Exception as e:
+ logger.error(
+ 'Unexpected exception cleaning image with message - %s', e)
+
+ super(self.__class__, self).__clean__()
+
+ def test_create_instance_public_net(self):
+ """
+ Tests the creation of an OpenStack instance with a single port to
+ the external network.
+ """
+ instance_settings = VmInstanceConfig(
+ name=self.vm_inst_name,
+ flavor=self.flavor_creator.flavor_settings.name,
+ port_settings=[self.port_settings])
+
+ self.inst_creator = OpenStackVmInstance(
+ self.admin_os_creds, instance_settings,
+ self.image_creator.image_settings)
+
+ vm_inst = self.inst_creator.create(block=True)
+ vm_inst_get = nova_utils.get_server(
+ self.nova, self.neutron, self.keystone,
+ vm_inst_settings=instance_settings)
+ self.assertEqual(vm_inst, vm_inst_get)
+ ip = self.inst_creator.get_port_ip(self.port_settings.name)
+
+ check_dhcp_lease(self.inst_creator, ip)
+
class CreateInstanceSingleNetworkTests(OSIntegrationTestCase):
"""
@@ -538,9 +695,10 @@ class CreateInstanceSingleNetworkTests(OSIntegrationTestCase):
Instantiates the CreateImage object that is responsible for downloading
and creating an OS image file within OpenStack
"""
+ self.proj_users = ['admin']
super(self.__class__, self).__start__()
- self.nova = nova_utils.nova_client(self.os_creds)
+ self.nova = nova_utils.nova_client(self.os_creds, self.os_session)
guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
self.keypair_priv_filepath = 'tmp/' + guid
self.keypair_pub_filepath = self.keypair_priv_filepath + '.pub'
@@ -560,6 +718,7 @@ class CreateInstanceSingleNetworkTests(OSIntegrationTestCase):
self.inst_creators = list()
self.pub_net_config = openstack_tests.get_pub_net_config(
+ project_name=self.os_creds.project_name,
net_name=guid + '-pub-net', subnet_name=guid + '-pub-subnet',
router_name=guid + '-pub-router', external_net=self.ext_net_name,
netconf_override=self.netconf_override)
@@ -582,10 +741,11 @@ class CreateInstanceSingleNetworkTests(OSIntegrationTestCase):
self.router_creator.create()
# Create Flavor
+ flavor_config = openstack_tests.get_flavor_config(
+ name=guid + '-flavor-name', ram=256, disk=10,
+ vcpus=2, metadata=self.flavor_metadata)
self.flavor_creator = OpenStackFlavor(
- self.admin_os_creds,
- FlavorConfig(name=guid + '-flavor-name', ram=256, disk=10,
- vcpus=2, metadata=self.flavor_metadata))
+ self.admin_os_creds, flavor_config)
self.flavor_creator.create()
self.keypair_creator = OpenStackKeypair(
@@ -816,19 +976,19 @@ class CreateInstanceSingleNetworkTests(OSIntegrationTestCase):
# Test default reboot which should be 'SOFT'
inst_creator.reboot()
# Lag time to allow for shutdown routine to take effect
- time.sleep(10)
+ time.sleep(15)
self.assertTrue(check_dhcp_lease(inst_creator, ip))
self.assertTrue(validate_ssh_client(inst_creator))
# Test 'SOFT' reboot
inst_creator.reboot(reboot_type=RebootType.soft)
- time.sleep(10)
+ time.sleep(15)
self.assertTrue(check_dhcp_lease(inst_creator, ip))
self.assertTrue(validate_ssh_client(inst_creator))
# Test 'HARD' reboot
inst_creator.reboot(reboot_type=RebootType.hard)
- time.sleep(10)
+ time.sleep(15)
self.assertTrue(check_dhcp_lease(inst_creator, ip))
self.assertTrue(validate_ssh_client(inst_creator))
@@ -897,9 +1057,35 @@ class CreateInstanceSingleNetworkTests(OSIntegrationTestCase):
self.assertTrue(inst_creator.vm_active(block=True))
+ vm_os_creds = OSCreds(
+ auth_url=self.admin_os_creds.auth_url,
+ username=self.admin_os_creds.username,
+ password=self.admin_os_creds.password,
+ project_name=self.os_creds.project_name,
+ identity_api_version=self.os_creds.identity_api_version)
derived_inst_creator = create_instance.generate_creator(
- self.os_creds, vm_inst, self.image_creator.image_settings,
- self.keypair_creator.keypair_settings)
+ vm_os_creds, vm_inst, self.image_creator.image_settings,
+ self.os_creds.project_name, self.keypair_creator.keypair_settings)
+
+ # Tests to ensure that a instance can be returned with an invalid
+ # image config object and admin credentials (when the 'admin' user has
+ # been added to the project) as this should not matter unless one
+ # needs to access the machine via ssh and its floating IP
+
+ # Invalid ImageConfig
+ derived_foo_image_creator = create_instance.generate_creator(
+ vm_os_creds, vm_inst, ImageConfig(
+ name='foo', image_user='bar', format='qcow2',
+ image_file='foo/bar'),
+ vm_os_creds.project_name)
+ self.assertIsNotNone(derived_foo_image_creator)
+ self.assertTrue(derived_foo_image_creator.vm_active())
+
+ # None ImageConfig
+ derived_none_image_creator = create_instance.generate_creator(
+ vm_os_creds, vm_inst, None, vm_os_creds.project_name)
+ self.assertIsNotNone(derived_none_image_creator)
+ self.assertTrue(derived_none_image_creator.vm_active())
derived_inst_creator.add_floating_ip(FloatingIpConfig(
name=self.floating_ip_name, port_name=self.port_1_name,
@@ -966,7 +1152,7 @@ class CreateInstanceIPv6NetworkTests(OSIntegrationTestCase):
"""
super(self.__class__, self).__start__()
- self.nova = nova_utils.nova_client(self.os_creds)
+ self.nova = nova_utils.nova_client(self.os_creds, self.os_session)
self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
self.keypair_priv_filepath = 'tmp/' + self.guid
self.keypair_pub_filepath = self.keypair_priv_filepath + '.pub'
@@ -991,11 +1177,11 @@ class CreateInstanceIPv6NetworkTests(OSIntegrationTestCase):
self.os_creds, os_image_settings)
self.image_creator.create()
+ flavor_config = openstack_tests.get_flavor_config(
+ name=self.guid + '-flavor-name', ram=256, disk=10,
+ vcpus=2, metadata=self.flavor_metadata)
self.flavor_creator = OpenStackFlavor(
- self.admin_os_creds,
- FlavorConfig(
- name=self.guid + '-flavor-name', ram=256, disk=10, vcpus=2,
- metadata=self.flavor_metadata))
+ self.admin_os_creds, flavor_config)
self.flavor_creator.create()
self.keypair_creator = OpenStackKeypair(
@@ -1094,7 +1280,10 @@ class CreateInstanceIPv6NetworkTests(OSIntegrationTestCase):
name=self.guid + '-net', subnet_settings=[subnet_settings])
router_settings = RouterConfig(
name=self.guid + '-router', external_gateway=self.ext_net_name,
- internal_subnets=[subnet_settings.name])
+ internal_subnets=[{'subnet': {
+ 'project_name': self.os_creds.project_name,
+ 'network_name': network_settings.name,
+ 'subnet_name': subnet_settings.name}}])
# Create Network
self.network_creator = OpenStackNetwork(
@@ -1142,7 +1331,10 @@ class CreateInstanceIPv6NetworkTests(OSIntegrationTestCase):
subnet_settings=[subnet4_settings, subnet6_settings])
router_settings = RouterConfig(
name=self.guid + '-router', external_gateway=self.ext_net_name,
- internal_subnets=[subnet4_settings.name])
+ internal_subnets=[{'subnet': {
+ 'project_name': self.os_creds.project_name,
+ 'network_name': network_settings.name,
+ 'subnet_name': subnet4_settings.name}}])
# Create Network
self.network_creator = OpenStackNetwork(
@@ -1172,6 +1364,7 @@ class CreateInstanceIPv6NetworkTests(OSIntegrationTestCase):
keypair_settings=self.keypair_creator.keypair_settings)
self.inst_creator.create(block=True)
+ self.inst_creator.cloud_init_complete(block=True)
ssh_client = self.inst_creator.ssh_client()
self.assertIsNotNone(ssh_client)
@@ -1189,24 +1382,28 @@ class CreateInstancePortManipulationTests(OSIntegrationTestCase):
"""
super(self.__class__, self).__start__()
- guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
- self.vm_inst_name = guid + '-inst'
- self.port_1_name = guid + 'port-1'
- self.port_2_name = guid + 'port-2'
- self.floating_ip_name = guid + 'fip1'
+ self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
+ self.vm_inst_name = self.guid + '-inst'
+ self.port_1_name = self.guid + 'port-1'
+ self.port_2_name = self.guid + 'port-2'
+ self.floating_ip_name = self.guid + 'fip1'
# Initialize for tearDown()
self.image_creator = None
self.network_creator = None
+ self.network_creator2 = None
self.flavor_creator = None
self.inst_creator = None
self.net_config = openstack_tests.get_priv_net_config(
- net_name=guid + '-pub-net', subnet_name=guid + '-pub-subnet',
- router_name=guid + '-pub-router', external_net=self.ext_net_name,
+ project_name=self.os_creds.project_name,
+ net_name=self.guid + '-pub-net',
+ subnet_name=self.guid + '-pub-subnet',
+ router_name=self.guid + '-pub-router',
+ external_net=self.ext_net_name,
netconf_override=self.netconf_override)
os_image_settings = openstack_tests.cirros_image_settings(
- name=guid + '-image', image_metadata=self.image_metadata)
+ name=self.guid + '-image', image_metadata=self.image_metadata)
try:
# Create Image
@@ -1220,10 +1417,11 @@ class CreateInstancePortManipulationTests(OSIntegrationTestCase):
self.network_creator.create()
# Create Flavor
+ flavor_config = openstack_tests.get_flavor_config(
+ name=self.guid + '-flavor-name', ram=256, disk=10,
+ vcpus=2, metadata=self.flavor_metadata)
self.flavor_creator = OpenStackFlavor(
- self.admin_os_creds,
- FlavorConfig(name=guid + '-flavor-name', ram=256, disk=10,
- vcpus=2, metadata=self.flavor_metadata))
+ self.admin_os_creds, flavor_config)
self.flavor_creator.create()
except Exception as e:
self.tearDown()
@@ -1257,6 +1455,14 @@ class CreateInstancePortManipulationTests(OSIntegrationTestCase):
'Unexpected exception cleaning network with message - %s',
e)
+ if self.network_creator2:
+ try:
+ self.network_creator2.clean()
+ except Exception as e:
+ logger.error(
+ 'Unexpected exception cleaning network with message - %s',
+ e)
+
if self.image_creator and not self.image_creator.image_settings.exists:
try:
self.image_creator.clean()
@@ -1293,6 +1499,86 @@ class CreateInstancePortManipulationTests(OSIntegrationTestCase):
subnet_name=self.net_config.network_settings.subnet_settings[
0].name))
+ def test_set_one_port_two_ip_one_subnet(self):
+ """
+ Tests the creation of an OpenStack instance with a single port with a
+ two static IPs on a network with one subnet.
+ """
+ ip1 = '10.55.0.101'
+ ip2 = '10.55.0.102'
+ sub_settings = self.net_config.network_settings.subnet_settings
+ 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': ip1},
+ {'subnet_name': sub_settings[0].name, 'ip': ip2}])
+
+ instance_settings = VmInstanceConfig(
+ name=self.vm_inst_name,
+ flavor=self.flavor_creator.flavor_settings.name,
+ port_settings=[port_settings])
+
+ self.inst_creator = OpenStackVmInstance(
+ self.os_creds, instance_settings,
+ self.image_creator.image_settings)
+ vm_inst = self.inst_creator.create(block=True)
+
+ self.assertEqual(ip1, vm_inst.ports[0].ips[0]['ip_address'])
+ self.assertEqual(self.network_creator.get_network().subnets[0].id,
+ vm_inst.ports[0].ips[0]['subnet_id'])
+ self.assertEqual(ip2, vm_inst.ports[0].ips[1]['ip_address'])
+ self.assertEqual(self.network_creator.get_network().subnets[0].id,
+ vm_inst.ports[0].ips[1]['subnet_id'])
+
+ def test_set_one_port_two_ip_two_subnets(self):
+ """
+ Tests the creation of an OpenStack instance with a single port with a
+ two static IPs on a network with one subnet.
+ """
+ net2_config = NetworkConfig(
+ name=self.guid + 'net2', subnets=[
+ SubnetConfig(name=self.guid + '-subnet1', cidr='10.55.0.0/24'),
+ SubnetConfig(name=self.guid + '-subnet2', cidr='10.65.0.0/24'),
+ ])
+
+ # Create Network
+ self.network_creator2 = OpenStackNetwork(self.os_creds, net2_config)
+ net2 = self.network_creator2.create()
+
+ ip1 = '10.55.0.101'
+ ip2 = '10.65.0.101'
+
+ port_settings = PortConfig(
+ name=self.port_1_name,
+ network_name=net2_config.name,
+ ip_addrs=[
+ {'subnet_name': net2_config.subnet_settings[0].name,
+ 'ip': ip1},
+ {'subnet_name': net2_config.subnet_settings[1].name,
+ 'ip': ip2}])
+
+ instance_settings = VmInstanceConfig(
+ name=self.vm_inst_name,
+ flavor=self.flavor_creator.flavor_settings.name,
+ port_settings=[port_settings])
+
+ self.inst_creator = OpenStackVmInstance(
+ self.os_creds, instance_settings,
+ self.image_creator.image_settings)
+ vm_inst = self.inst_creator.create(block=True)
+
+ subnet1_id = None
+ subnet2_id = None
+ for subnet in net2.subnets:
+ if subnet.name == net2_config.subnet_settings[0].name:
+ subnet1_id = subnet.id
+ if subnet.name == net2_config.subnet_settings[1].name:
+ subnet2_id = subnet.id
+ self.assertEqual(ip1, vm_inst.ports[0].ips[0]['ip_address'])
+ self.assertEqual(subnet1_id, vm_inst.ports[0].ips[0]['subnet_id'])
+ self.assertEqual(ip2, vm_inst.ports[0].ips[1]['ip_address'])
+ self.assertEqual(subnet2_id, vm_inst.ports[0].ips[1]['subnet_id'])
+
def test_set_custom_invalid_ip_one_subnet(self):
"""
Tests the creation of an OpenStack instance with a single port with a
@@ -1501,6 +1787,7 @@ class CreateInstanceOnComputeHost(OSIntegrationTestCase):
self.inst_creators = list()
self.priv_net_config = openstack_tests.get_priv_net_config(
+ project_name=self.os_creds.project_name,
net_name=guid + '-priv-net', subnet_name=guid + '-priv-subnet',
netconf_override=self.netconf_override)
@@ -1514,10 +1801,11 @@ class CreateInstanceOnComputeHost(OSIntegrationTestCase):
self.network_creator.create()
# Create Flavor
+ flavor_config = openstack_tests.get_flavor_config(
+ name=guid + '-flavor-name', ram=512, disk=1,
+ vcpus=1, metadata=self.flavor_metadata)
self.flavor_creator = OpenStackFlavor(
- self.admin_os_creds,
- FlavorConfig(name=guid + '-flavor-name', ram=512, disk=1,
- vcpus=1, metadata=self.flavor_metadata))
+ self.admin_os_creds, flavor_config)
self.flavor_creator.create()
# Create Image
@@ -1571,7 +1859,8 @@ class CreateInstanceOnComputeHost(OSIntegrationTestCase):
Tests the creation of OpenStack VM instances to each compute node.
"""
from snaps.openstack.utils import nova_utils
- nova = nova_utils.nova_client(self.admin_os_creds)
+ nova = nova_utils.nova_client(
+ self.admin_os_creds, self.admin_os_session)
zone_hosts = nova_utils.get_availability_zone_hosts(nova)
# Create Instance on each server/zone
@@ -1592,7 +1881,11 @@ class CreateInstanceOnComputeHost(OSIntegrationTestCase):
self.admin_os_creds, instance_settings,
self.image_creator.image_settings)
self.inst_creators.append(inst_creator)
- inst_creator.create()
+ inst_creator.create(block=True)
+ avail_zone = inst_creator.get_vm_inst().availability_zone
+ self.assertTrue(avail_zone in zone)
+ compute_host = inst_creator.get_vm_inst().compute_host
+ self.assertTrue(compute_host in zone)
# Validate instances to ensure they've been deployed to the correct
# server
@@ -1621,7 +1914,7 @@ class InstanceSecurityGroupTests(OSIntegrationTestCase):
self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
self.vm_inst_name = self.guid + '-inst'
- self.nova = nova_utils.nova_client(self.os_creds)
+ self.nova = nova_utils.nova_client(self.os_creds, self.os_session)
os_image_settings = openstack_tests.cirros_image_settings(
name=self.guid + '-image', image_metadata=self.image_metadata)
@@ -1631,6 +1924,7 @@ class InstanceSecurityGroupTests(OSIntegrationTestCase):
self.floating_ip_name = self.guid + 'fip1'
net_config = openstack_tests.get_priv_net_config(
+ project_name=self.os_creds.project_name,
net_name=self.guid + '-pub-net',
subnet_name=self.guid + '-pub-subnet',
router_name=self.guid + '-pub-router',
@@ -1657,11 +1951,11 @@ class InstanceSecurityGroupTests(OSIntegrationTestCase):
self.network_creator.create()
# Create Flavor
+ flavor_config = openstack_tests.get_flavor_config(
+ name=self.guid + '-flavor-name', ram=256, disk=10,
+ vcpus=2, metadata=self.flavor_metadata)
self.flavor_creator = OpenStackFlavor(
- self.admin_os_creds,
- FlavorConfig(name=self.guid + '-flavor-name', ram=256,
- disk=10, vcpus=2,
- metadata=self.flavor_metadata))
+ self.admin_os_creds, flavor_config)
self.flavor_creator.create()
self.port_settings = PortConfig(
@@ -1952,9 +2246,10 @@ class CreateInstanceFromThreePartImage(OSIntegrationTestCase):
guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
self.image_name = guid
self.vm_inst_name = guid + '-inst'
- self.nova = nova_utils.nova_client(self.os_creds)
+ self.nova = nova_utils.nova_client(self.os_creds, self.os_session)
net_config = openstack_tests.get_priv_net_config(
+ project_name=self.os_creds.project_name,
net_name=guid + '-pub-net', subnet_name=guid + '-pub-subnet',
router_name=guid + '-pub-router', external_net=self.ext_net_name,
netconf_override=self.netconf_override)
@@ -1993,10 +2288,11 @@ class CreateInstanceFromThreePartImage(OSIntegrationTestCase):
self.image_creator.create()
# Create Flavor
+ flavor_config = openstack_tests.get_flavor_config(
+ name=guid + '-flavor-name', ram=256, disk=10,
+ vcpus=2, metadata=self.flavor_metadata)
self.flavor_creator = OpenStackFlavor(
- self.admin_os_creds,
- FlavorConfig(name=guid + '-flavor-name', ram=256, disk=10,
- vcpus=2, metadata=self.flavor_metadata))
+ self.admin_os_creds, flavor_config)
self.flavor_creator.create()
# Create Network
@@ -2097,6 +2393,7 @@ class CreateInstanceMockOfflineTests(OSComponentTestCase):
self.inst_creator = None
self.priv_net_config = openstack_tests.get_priv_net_config(
+ project_name=self.os_creds.project_name,
net_name=self.guid + '-priv-net',
subnet_name=self.guid + '-priv-subnet')
self.port_settings = PortConfig(
@@ -2114,11 +2411,11 @@ class CreateInstanceMockOfflineTests(OSComponentTestCase):
self.network_creator.create()
# Create Flavor
+ flavor_config = openstack_tests.get_flavor_config(
+ name=self.guid + '-flavor-name', ram=256, disk=10,
+ vcpus=2, metadata=self.flavor_metadata)
self.flavor_creator = OpenStackFlavor(
- self.os_creds,
- FlavorConfig(
- name=self.guid + '-flavor-name', ram=256, disk=10,
- vcpus=1))
+ self.os_creds, flavor_config)
self.flavor_creator.create()
except Exception as e:
self.tearDown()
@@ -2162,6 +2459,8 @@ class CreateInstanceMockOfflineTests(OSComponentTestCase):
if os.path.exists(self.tmpDir) and os.path.isdir(self.tmpDir):
shutil.rmtree(self.tmpDir)
+ super(self.__class__, self).__clean__()
+
def test_inst_from_file_image_simple_flat(self):
"""
Creates a VM instance from a locally sourced file image using simply
@@ -2582,7 +2881,7 @@ class CreateInstanceTwoNetTests(OSIntegrationTestCase):
self.ip1 = '10.200.201.5'
self.ip2 = '10.200.202.5'
- self.nova = nova_utils.nova_client(self.os_creds)
+ self.nova = nova_utils.nova_client(self.os_creds, self.os_session)
# Initialize for tearDown()
self.image_creator = None
@@ -2616,13 +2915,14 @@ class CreateInstanceTwoNetTests(OSIntegrationTestCase):
try:
# Create Image
- self.image_creator = OpenStackImage(self.os_creds,
- os_image_settings)
+ self.image_creator = OpenStackImage(
+ self.os_creds, os_image_settings)
self.image_creator.create()
# First network is public
self.network_creators.append(OpenStackNetwork(
self.os_creds, self.net_config_1))
+
# Second network is private
self.network_creators.append(OpenStackNetwork(
self.os_creds, self.net_config_2))
@@ -2630,47 +2930,47 @@ class CreateInstanceTwoNetTests(OSIntegrationTestCase):
network_creator.create()
port_settings = [
- create_network.PortConfig(
+ PortConfig(
name=self.guid + '-router-port1',
ip_addrs=[{
'subnet_name':
self.net_config_1.subnet_settings[0].name,
'ip': static_gateway_ip1
}],
- network_name=self.net_config_1.name,
- project_name=self.os_creds.project_name),
- create_network.PortConfig(
+ network_name=self.net_config_1.name),
+ PortConfig(
name=self.guid + '-router-port2',
ip_addrs=[{
'subnet_name':
self.net_config_2.subnet_settings[0].name,
'ip': static_gateway_ip2
}],
- network_name=self.net_config_2.name,
- project_name=self.os_creds.project_name)]
+ network_name=self.net_config_2.name)]
router_settings = RouterConfig(
name=self.guid + '-pub-router', port_settings=port_settings)
- self.router_creator = create_router.OpenStackRouter(
+ self.router_creator = OpenStackRouter(
self.os_creds, router_settings)
self.router_creator.create()
- # Create Flavor
+ flavor_config = openstack_tests.get_flavor_config(
+ name=self.guid + '-flavor-name', ram=512, disk=10,
+ vcpus=2, metadata=self.flavor_metadata)
self.flavor_creator = OpenStackFlavor(
- self.admin_os_creds,
- FlavorConfig(name=self.guid + '-flavor-name', ram=512,
- disk=10, vcpus=2,
- metadata=self.flavor_metadata))
+ self.admin_os_creds, flavor_config)
self.flavor_creator.create()
- sec_grp_name = self.guid + '-sec-grp'
+ self.sec_grp_name = self.guid + '-sec-grp'
rule1 = SecurityGroupRuleConfig(
- sec_grp_name=sec_grp_name, direction=Direction.ingress,
+ sec_grp_name=self.sec_grp_name, direction=Direction.ingress,
+ protocol=Protocol.icmp)
+ rule2 = SecurityGroupRuleConfig(
+ sec_grp_name=self.sec_grp_name, direction=Direction.egress,
protocol=Protocol.icmp)
self.sec_grp_creator = OpenStackSecurityGroup(
self.os_creds,
SecurityGroupConfig(
- name=sec_grp_name, rule_settings=[rule1]))
+ name=self.sec_grp_name, rule_settings=[rule1, rule2]))
self.sec_grp_creator.create()
except:
self.tearDown()
@@ -2750,6 +3050,7 @@ class CreateInstanceTwoNetTests(OSIntegrationTestCase):
name=self.vm_inst1_name,
flavor=self.flavor_creator.flavor_settings.name,
userdata=_get_ping_userdata(self.ip2),
+ security_group_names=self.sec_grp_name,
port_settings=[PortConfig(
name=self.port_1_name,
ip_addrs=[{
@@ -2762,6 +3063,7 @@ class CreateInstanceTwoNetTests(OSIntegrationTestCase):
name=self.vm_inst2_name,
flavor=self.flavor_creator.flavor_settings.name,
userdata=_get_ping_userdata(self.ip1),
+ security_group_names=self.sec_grp_name,
port_settings=[PortConfig(
name=self.port_2_name,
ip_addrs=[{
@@ -2806,12 +3108,15 @@ class CreateInstanceVolumeTests(OSIntegrationTestCase):
guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
self.vm_inst_name = guid + '-inst'
- self.nova = nova_utils.nova_client(self.os_creds)
- self.neutron = neutron_utils.neutron_client(self.os_creds)
+ self.nova = nova_utils.nova_client(
+ self.os_creds, self.os_session)
+ self.neutron = neutron_utils.neutron_client(
+ self.os_creds, self.os_session)
os_image_settings = openstack_tests.cirros_image_settings(
name=guid + '-image', image_metadata=self.image_metadata)
net_config = openstack_tests.get_priv_net_config(
+ project_name=self.os_creds.project_name,
net_name=guid + '-pub-net', subnet_name=guid + '-pub-subnet',
router_name=guid + '-pub-router', external_net=self.ext_net_name,
netconf_override=self.netconf_override)
@@ -2837,10 +3142,11 @@ class CreateInstanceVolumeTests(OSIntegrationTestCase):
self.image_creator.create()
# Create Flavor
+ flavor_config = openstack_tests.get_flavor_config(
+ name=guid + '-flavor-name', ram=256, disk=1,
+ vcpus=2, metadata=self.flavor_metadata)
self.flavor_creator = OpenStackFlavor(
- self.admin_os_creds,
- FlavorConfig(name=guid + '-flavor-name', ram=256, disk=1,
- vcpus=2, metadata=self.flavor_metadata))
+ self.admin_os_creds, flavor_config)
self.flavor_creator.create()
# Create Network
@@ -2933,7 +3239,8 @@ class CreateInstanceVolumeTests(OSIntegrationTestCase):
vm_inst = self.inst_creator.create(block=True)
self.assertIsNotNone(nova_utils.get_server(
- self.nova, self.neutron, vm_inst_settings=instance_settings))
+ self.nova, self.neutron, self.keystone,
+ vm_inst_settings=instance_settings))
self.assertIsNotNone(vm_inst)
self.assertEqual(1, len(vm_inst.volume_ids))
@@ -2957,7 +3264,8 @@ class CreateInstanceVolumeTests(OSIntegrationTestCase):
vm_inst = self.inst_creator.create(block=True)
self.assertIsNotNone(nova_utils.get_server(
- self.nova, self.neutron, vm_inst_settings=instance_settings))
+ self.nova, self.neutron, self.keystone,
+ vm_inst_settings=instance_settings))
self.assertIsNotNone(vm_inst)
self.assertEqual(2, len(vm_inst.volume_ids))
diff --git a/snaps/openstack/tests/create_keypairs_tests.py b/snaps/openstack/tests/create_keypairs_tests.py
index 63e0bcc..44214d0 100644
--- a/snaps/openstack/tests/create_keypairs_tests.py
+++ b/snaps/openstack/tests/create_keypairs_tests.py
@@ -200,7 +200,7 @@ class CreateKeypairsTests(OSIntegrationTestCase):
guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
self.priv_file_path = 'tmp/' + guid
self.pub_file_path = self.priv_file_path + '.pub'
- self.nova = nova_utils.nova_client(self.os_creds)
+ self.nova = nova_utils.nova_client(self.os_creds, self.os_session)
self.keypair_name = guid
self.keypair_creator = None
@@ -370,7 +370,7 @@ class CreateKeypairsCleanupTests(OSIntegrationTestCase):
guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
self.priv_file_path = 'tmp/' + guid
self.pub_file_path = self.priv_file_path + '.pub'
- self.nova = nova_utils.nova_client(self.os_creds)
+ self.nova = nova_utils.nova_client(self.os_creds, self.os_session)
self.keypair_name = guid
self.keypair_creator = None
diff --git a/snaps/openstack/tests/create_network_tests.py b/snaps/openstack/tests/create_network_tests.py
index 966cbd0..26c57bd 100644
--- a/snaps/openstack/tests/create_network_tests.py
+++ b/snaps/openstack/tests/create_network_tests.py
@@ -15,6 +15,8 @@
import unittest
import uuid
+from neutronclient.common.exceptions import BadRequest
+
from snaps.config.network import (
NetworkConfig, SubnetConfig, SubnetConfigError, NetworkConfigError,
PortConfigError, IPv6Mode)
@@ -24,7 +26,7 @@ from snaps.openstack.create_network import (
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 import neutron_utils, keystone_utils
from snaps.openstack.utils.tests import neutron_utils_tests
from snaps.openstack.create_network import IPv6Mode as IPv6Mode_old
@@ -136,8 +138,7 @@ class SubnetSettingsUnitTests(unittest.TestCase):
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.assertEqual(0, len(settings.dns_nameservers))
self.assertIsNone(settings.host_routes)
self.assertIsNone(settings.destination)
self.assertIsNone(settings.nexthop)
@@ -154,8 +155,7 @@ class SubnetSettingsUnitTests(unittest.TestCase):
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.assertEqual(0, len(settings.dns_nameservers))
self.assertIsNone(settings.host_routes)
self.assertIsNone(settings.destination)
self.assertIsNone(settings.nexthop)
@@ -365,11 +365,15 @@ class CreateNetworkSuccessTests(OSIntegrationTestCase):
guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
self.net_config = openstack_tests.get_pub_net_config(
- net_name=guid + '-pub-net', subnet_name=guid + '-pub-subnet',
- router_name=guid + '-pub-router', external_net=self.ext_net_name,
+ project_name=self.os_creds.project_name,
+ net_name="{}-{}".format(guid, 'pub-net'), mtu=999,
+ subnet_name="{}-{}".format(guid, 'pub-subnet'),
+ router_name="{}-{}".format(guid, 'pub-router'),
+ external_net=self.ext_net_name,
netconf_override=self.netconf_override)
- self.neutron = neutron_utils.neutron_client(self.os_creds)
+ self.neutron = neutron_utils.neutron_client(
+ self.os_creds, self.os_session)
# Initialize for cleanup
self.net_creator = None
@@ -392,17 +396,19 @@ class CreateNetworkSuccessTests(OSIntegrationTestCase):
Tests the creation of an OpenStack network without a router.
"""
# Create Network
- self.net_creator = OpenStackNetwork(self.os_creds,
- self.net_config.network_settings)
- self.net_creator.create()
+ self.net_creator = OpenStackNetwork(
+ self.os_creds, self.net_config.network_settings)
+ network = self.net_creator.create()
# Validate network was created
self.assertTrue(neutron_utils_tests.validate_network(
- self.neutron, self.net_creator.network_settings.name, True))
+ self.neutron, self.keystone,
+ self.net_creator.network_settings.name, True,
+ self.os_creds.project_name, mtu=999))
# Validate subnets
self.assertTrue(neutron_utils_tests.validate_subnet(
- self.neutron,
+ self.neutron, network,
self.net_creator.network_settings.subnet_settings[0].name,
self.net_creator.network_settings.subnet_settings[0].cidr, True))
@@ -411,18 +417,22 @@ class CreateNetworkSuccessTests(OSIntegrationTestCase):
Tests the creation of an OpenStack network, it's deletion, then cleanup
"""
# Create Network
- self.net_creator = OpenStackNetwork(self.os_creds,
- self.net_config.network_settings)
+ self.net_creator = OpenStackNetwork(
+ self.os_creds, self.net_config.network_settings)
self.net_creator.create()
# Validate network was created
self.assertTrue(neutron_utils_tests.validate_network(
- self.neutron, self.net_creator.network_settings.name, True))
+ self.neutron, self.keystone,
+ self.net_creator.network_settings.name, True,
+ self.os_creds.project_name, mtu=999))
- neutron_utils.delete_network(self.neutron,
- self.net_creator.get_network())
+ neutron_utils.delete_network(
+ self.neutron, self.net_creator.get_network())
self.assertIsNone(neutron_utils.get_network(
- self.neutron, network_settings=self.net_creator.network_settings))
+ self.neutron, self.keystone,
+ network_settings=self.net_creator.network_settings,
+ project_name=self.os_creds.project_name))
# This shall not throw an exception here
self.net_creator.clean()
@@ -432,9 +442,9 @@ class CreateNetworkSuccessTests(OSIntegrationTestCase):
Tests the creation of an OpenStack network with a router.
"""
# Create Network
- self.net_creator = OpenStackNetwork(self.os_creds,
- self.net_config.network_settings)
- self.net_creator.create()
+ self.net_creator = OpenStackNetwork(
+ self.os_creds, self.net_config.network_settings)
+ network = self.net_creator.create()
# Create Router
self.router_creator = create_router.OpenStackRouter(
@@ -443,17 +453,21 @@ class CreateNetworkSuccessTests(OSIntegrationTestCase):
# Validate network was created
self.assertTrue(neutron_utils_tests.validate_network(
- self.neutron, self.net_creator.network_settings.name, True))
+ self.neutron, self.keystone,
+ self.net_creator.network_settings.name, True,
+ self.os_creds.project_name, mtu=999))
# Validate subnets
self.assertTrue(neutron_utils_tests.validate_subnet(
- self.neutron,
+ self.neutron, network,
self.net_creator.network_settings.subnet_settings[0].name,
self.net_creator.network_settings.subnet_settings[0].cidr, True))
# Validate routers
neutron_utils_tests.validate_router(
- self.neutron, self.router_creator.router_settings.name, True)
+ self.neutron, self.keystone,
+ self.router_creator.router_settings.name,
+ self.os_creds.project_name, True)
neutron_utils_tests.validate_interface_router(
self.router_creator.get_internal_router_interface(),
@@ -466,12 +480,12 @@ class CreateNetworkSuccessTests(OSIntegrationTestCase):
OpenStackNetwork object will not create a second.
"""
# Create Network
- self.net_creator = OpenStackNetwork(self.os_creds,
- self.net_config.network_settings)
+ self.net_creator = OpenStackNetwork(
+ self.os_creds, self.net_config.network_settings)
self.net_creator.create()
- self.net_creator2 = OpenStackNetwork(self.os_creds,
- self.net_config.network_settings)
+ self.net_creator2 = OpenStackNetwork(
+ self.os_creds, self.net_config.network_settings)
self.net_creator2.create()
self.assertEqual(self.net_creator.get_network().id,
@@ -479,31 +493,42 @@ class CreateNetworkSuccessTests(OSIntegrationTestCase):
def test_create_network_router_admin_user_to_new_project(self):
"""
- Tests the creation of an OpenStack network and router with the current
- user to the admin project.
+ Tests the creation of an OpenStack network to the the current using
+ the credentials to the admin project.
"""
# Create Network/Subnet where the project names have been changed
- admin_project_name = self.admin_os_creds.project_name
- self.net_config.network_settings.project_name = admin_project_name
- self.net_config.network_settings.subnet_settings[0].project_name = \
- admin_project_name
- self.net_creator = OpenStackNetwork(self.os_creds,
- self.net_config.network_settings)
+ project_name = self.os_creds.project_name
+ config = self.net_config.network_settings
+ config.project_name = project_name
+ config.subnet_settings[0].project_name = project_name
+
+ self.net_creator = OpenStackNetwork(self.admin_os_creds, config)
self.net_creator.create()
retrieved_net = neutron_utils.get_network(
- self.neutron, network_settings=self.net_config.network_settings)
+ self.neutron, self.keystone,
+ network_name=self.net_config.network_settings.name,
+ project_name=self.os_creds.project_name)
self.assertEqual(self.net_creator.get_network().id, retrieved_net.id)
+ # Initialize with actual credentials
+ config.project_name = None
+ config.subnet_settings[0].project_name = None
+ proj_net_creator = OpenStackNetwork(self.os_creds, config)
+ proj_net = proj_net_creator.create()
+ self.assertEqual(retrieved_net, proj_net)
+
# Create Router
- self.net_config.router_settings.project_name = admin_project_name
+ self.net_config.router_settings.project_name = project_name
self.router_creator = create_router.OpenStackRouter(
- self.os_creds, self.net_config.router_settings)
+ self.admin_os_creds, self.net_config.router_settings)
self.router_creator.create()
retrieved_router = neutron_utils.get_router(
- self.neutron, router_settings=self.router_creator.router_settings)
+ self.neutron, self.keystone,
+ router_settings=self.router_creator.router_settings,
+ project_name=self.os_creds.project_name)
self.assertEqual(
self.router_creator.get_router().id, retrieved_router.id)
@@ -517,12 +542,14 @@ class CreateNetworkSuccessTests(OSIntegrationTestCase):
self.net_config.network_settings.project_name = new_project_name
self.net_config.network_settings.subnet_settings[0].project_name = \
new_project_name
- self.net_creator = OpenStackNetwork(self.admin_os_creds,
- self.net_config.network_settings)
+ self.net_creator = OpenStackNetwork(
+ self.admin_os_creds, self.net_config.network_settings)
self.net_creator.create()
retrieved_net = neutron_utils.get_network(
- self.neutron, network_settings=self.net_config.network_settings)
+ self.neutron, self.keystone,
+ network_settings=self.net_config.network_settings,
+ project_name=self.os_creds.project_name)
self.assertEqual(self.net_creator.get_network().id, retrieved_net.id)
@@ -533,14 +560,149 @@ class CreateNetworkSuccessTests(OSIntegrationTestCase):
self.router_creator.create()
retrieved_router = neutron_utils.get_router(
- self.neutron, router_settings=self.router_creator.router_settings)
+ self.neutron, self.keystone,
+ router_settings=self.router_creator.router_settings,
+ project_name=self.os_creds.project_name)
self.assertEqual(
self.router_creator.get_router().id, retrieved_router.id)
+class CreateNetworkGatewayTests(OSIntegrationTestCase):
+ """
+ Test for the CreateNetwork class defined in create_nework.py
+ """
+
+ def setUp(self):
+ """
+ Sets up object for test
+ """
+ super(self.__class__, self).__start__()
+
+ self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
+
+ self.neutron = neutron_utils.neutron_client(
+ self.os_creds, self.os_session)
+
+ self.ip_prfx = '10.1.0.'
+
+ # Initialize for cleanup
+ self.net_creator = None
+
+ def tearDown(self):
+ """
+ Cleans the network
+ """
+ if self.net_creator:
+ self.net_creator.clean()
+
+ super(self.__class__, self).__clean__()
+
+ def test_create_subnet_default_gateway_ip(self):
+ """
+ Tests the creation of an OpenStack network with a subnet that has a
+ default value assigned to the gateway IP.
+ """
+ # Create Network
+ subnet_config = SubnetConfig(
+ name=self.guid + '-subnet', cidr=self.ip_prfx + '0/24')
+ net_config = NetworkConfig(
+ name=self.guid + '-net', subnets=[subnet_config])
+ self.net_creator = OpenStackNetwork(
+ self.os_creds, net_config)
+ out_net = self.net_creator.create()
+
+ # Validate network was created
+ self.assertTrue(neutron_utils_tests.validate_network(
+ self.neutron, self.keystone,
+ self.net_creator.network_settings.name, True,
+ self.os_creds.project_name))
+
+ # Validate subnets
+ self.assertTrue(neutron_utils_tests.validate_subnet(
+ self.neutron, out_net,
+ self.net_creator.network_settings.subnet_settings[0].name,
+ self.net_creator.network_settings.subnet_settings[0].cidr, True))
+
+ self.assertEqual(self.ip_prfx + '1', out_net.subnets[0].gateway_ip)
+
+ def test_create_subnet_valid_gateway_ip(self):
+ """
+ Tests the creation of an OpenStack network with a subnet that has a
+ valid value assigned to the gateway IP.
+ """
+ # Create Network
+ subnet_config = SubnetConfig(
+ name=self.guid + '-subnet', cidr=self.ip_prfx + '0/24',
+ gateway_ip=self.ip_prfx + '2')
+ net_config = NetworkConfig(
+ name=self.guid + '-net', subnets=[subnet_config])
+ self.net_creator = OpenStackNetwork(
+ self.os_creds, net_config)
+ out_net = self.net_creator.create()
+
+ self.assertIsNotNone(out_net)
+
+ get_net = neutron_utils.get_network_by_id(self.neutron, out_net.id)
+ self.assertIsNotNone(get_net)
+
+ # Validate subnets
+ self.assertTrue(neutron_utils_tests.validate_subnet(
+ self.neutron, out_net,
+ self.net_creator.network_settings.subnet_settings[0].name,
+ self.net_creator.network_settings.subnet_settings[0].cidr, True))
+
+ self.assertEqual(self.ip_prfx + '2', out_net.subnets[0].gateway_ip)
+
+ def test_create_subnet_no_gateway(self):
+ """
+ Tests the creation of an OpenStack network with a subnet that has a
+ valid value assigned to the gateway IP.
+ """
+ # Create Network
+ subnet_config = SubnetConfig(
+ name=self.guid + '-subnet', cidr=self.ip_prfx + '0/24',
+ gateway_ip='none')
+ net_config = NetworkConfig(
+ name=self.guid + '-net', subnets=[subnet_config])
+ self.net_creator = OpenStackNetwork(
+ self.os_creds, net_config)
+ out_net = self.net_creator.create()
+
+ # Validate network was created
+ self.assertTrue(neutron_utils_tests.validate_network(
+ self.neutron, self.keystone,
+ self.net_creator.network_settings.name, True,
+ self.os_creds.project_name))
+
+ # Validate subnets
+ self.assertTrue(neutron_utils_tests.validate_subnet(
+ self.neutron, out_net,
+ self.net_creator.network_settings.subnet_settings[0].name,
+ self.net_creator.network_settings.subnet_settings[0].cidr, True))
+
+ self.assertIsNone(out_net.subnets[0].gateway_ip)
+
+ def test_create_subnet_invalid_gateway_ip(self):
+ """
+ Tests the creation of an OpenStack network with a subnet that has an
+ invalid value assigned to the gateway IP.
+ """
+ # Create Network
+ subnet_config = SubnetConfig(
+ name=self.guid + '-subnet', cidr=self.ip_prfx + '0/24',
+ gateway_ip='foo')
+ net_config = NetworkConfig(
+ name=self.guid + '-net', subnets=[subnet_config])
+ self.net_creator = OpenStackNetwork(
+ self.os_creds, net_config)
+
+ with self.assertRaises(BadRequest):
+ self.net_creator.create()
+
+
class CreateNetworkIPv6Tests(OSIntegrationTestCase):
"""
- Test for the CreateNetwork class defined in create_nework.py when
+ Test for the CreateNetwork class defined in create_nework.py when
"""
def setUp(self):
@@ -550,7 +712,8 @@ class CreateNetworkIPv6Tests(OSIntegrationTestCase):
super(self.__class__, self).__start__()
self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
- self.neutron = neutron_utils.neutron_client(self.os_creds)
+ self.neutron = neutron_utils.neutron_client(
+ self.os_creds, self.os_session)
# Initialize for cleanup
self.net_creator = None
@@ -580,7 +743,9 @@ class CreateNetworkIPv6Tests(OSIntegrationTestCase):
# Validate network was created
self.assertTrue(neutron_utils_tests.validate_network(
- self.neutron, self.net_creator.network_settings.name, True))
+ self.neutron, self.keystone,
+ self.net_creator.network_settings.name, True,
+ self.os_creds.project_name))
network = self.net_creator.get_network()
self.assertEqual(1, len(network.subnets))
@@ -627,7 +792,7 @@ class CreateNetworkIPv6Tests(OSIntegrationTestCase):
self.assertEqual(subnet4_settings.name, subnet4.name)
self.assertEqual(subnet4_settings.cidr, subnet4.cidr)
self.assertEqual(4, subnet4.ip_version)
- self.assertEqual(1, len(subnet4.dns_nameservers))
+ self.assertEqual(0, len(subnet4.dns_nameservers))
# Validate IPv6 subnet
self.assertEqual(network.id, subnet6.network_id)
@@ -649,9 +814,13 @@ class CreateNetworkTypeTests(OSComponentTestCase):
"""
guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
self.net_config = openstack_tests.get_pub_net_config(
+ project_name=self.os_creds.project_name,
net_name=guid + '-pub-net', subnet_name=guid + '-pub-subnet')
- self.neutron = neutron_utils.neutron_client(self.os_creds)
+ self.neutron = neutron_utils.neutron_client(
+ self.os_creds, self.os_session)
+ self.keystone = keystone_utils.keystone_client(
+ self.os_creds, self.os_session)
# Initialize for cleanup
self.net_creator = None
@@ -663,6 +832,8 @@ class CreateNetworkTypeTests(OSComponentTestCase):
if self.net_creator:
self.net_creator.clean()
+ super(self.__class__, self).__clean__()
+
def test_create_network_type_vlan(self):
"""
Tests the creation of an OpenStack network of type vlan.
@@ -680,7 +851,8 @@ class CreateNetworkTypeTests(OSComponentTestCase):
# Validate network was created
self.assertTrue(neutron_utils_tests.validate_network(
- self.neutron, net_settings.name, True))
+ self.neutron, self.keystone, net_settings.name, True,
+ self.os_creds.project_name))
self.assertEquals(network_type, network.type)
@@ -709,7 +881,8 @@ class CreateNetworkTypeTests(OSComponentTestCase):
# Validate network was created
self.assertTrue(neutron_utils_tests.validate_network(
- self.neutron, net_settings.name, True))
+ self.neutron, self.keystone, net_settings.name, True,
+ self.os_creds.project_name))
self.assertEquals(network_type, network.type)
@@ -730,7 +903,8 @@ class CreateNetworkTypeTests(OSComponentTestCase):
# Validate network was created
self.assertTrue(neutron_utils_tests.validate_network(
- self.neutron, net_settings.name, True))
+ self.neutron, self.keystone, net_settings.name, True,
+ self.os_creds.project_name))
self.assertEqual(network_type, network.type)
@@ -753,7 +927,8 @@ class CreateNetworkTypeTests(OSComponentTestCase):
# Validate network was created
self.assertTrue(neutron_utils_tests.validate_network(
- self.neutron, net_settings.name, True))
+ self.neutron, self.keystone, net_settings.name, True,
+ self.os_creds.project_name))
self.assertEquals(network_type, network.type)
@@ -771,3 +946,94 @@ class CreateNetworkTypeTests(OSComponentTestCase):
self.net_creator = OpenStackNetwork(self.os_creds, net_settings)
with self.assertRaises(Exception):
self.net_creator.create()
+
+
+class CreateMultipleNetworkTests(OSIntegrationTestCase):
+ """
+ Test for the CreateNetwork class and how it interacts with networks
+ groups within other projects with the same name
+ """
+
+ def setUp(self):
+ """
+ Sets up object for test
+ """
+ super(self.__class__, self).__start__()
+
+ guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
+ self.net_config = openstack_tests.get_pub_net_config(
+ project_name=self.os_creds.project_name,
+ net_name=guid + '-pub-net', subnet_name=guid + '-pub-subnet')
+
+ self.neutron = neutron_utils.neutron_client(
+ self.os_creds, self.os_session)
+
+ # Initialize for cleanup
+ self.admin_net_creator = None
+ self.proj_net_creator = None
+
+ def tearDown(self):
+ """
+ Cleans the network
+ """
+ if self.admin_net_creator:
+ self.admin_net_creator.clean()
+ if self.proj_net_creator:
+ self.proj_net_creator.clean()
+
+ super(self.__class__, self).__clean__()
+
+ def test_network_same_name_diff_proj(self):
+ """
+ Tests the creation of an OpenStackNetwork with the same name
+ within a different project/tenant when not configured but implied by
+ the OSCreds.
+ """
+ # Create Network
+
+ self.admin_net_creator = OpenStackNetwork(
+ self.admin_os_creds, self.net_config.network_settings)
+ self.admin_net_creator.create()
+
+ self.proj_net_creator = OpenStackNetwork(
+ self.os_creds, self.net_config.network_settings)
+ self.proj_net_creator.create()
+
+ self.assertNotEqual(
+ self.admin_net_creator.get_network().id,
+ self.proj_net_creator.get_network().id)
+
+ admin_creator2 = OpenStackNetwork(
+ self.admin_os_creds, self.net_config.network_settings)
+ admin_creator2.create()
+ self.assertEqual(
+ self.admin_net_creator.get_network(), admin_creator2.get_network())
+
+ proj_creator2 = OpenStackNetwork(
+ self.os_creds, self.net_config.network_settings)
+ proj_creator2.create()
+ self.assertEqual(self.proj_net_creator.get_network(),
+ proj_creator2.get_network())
+
+ def test_network_create_by_admin_to_different_project(self):
+ """
+ Tests the creation of an OpenStackNetwork by the admin user and
+ initialize again with tenant credentials.
+ """
+ # Create Network
+
+ net_settings = self.net_config.network_settings
+
+ net_settings.project_name = self.os_creds.project_name
+
+ self.admin_net_creator = OpenStackNetwork(
+ self.admin_os_creds, net_settings)
+ self.admin_net_creator.create()
+
+ self.proj_net_creator = OpenStackNetwork(
+ self.os_creds, self.net_config.network_settings)
+ self.proj_net_creator.create()
+
+ self.assertEqual(
+ self.admin_net_creator.get_network().id,
+ self.proj_net_creator.get_network().id)
diff --git a/snaps/openstack/tests/create_project_tests.py b/snaps/openstack/tests/create_project_tests.py
index 2c10311..1e3a972 100644
--- a/snaps/openstack/tests/create_project_tests.py
+++ b/snaps/openstack/tests/create_project_tests.py
@@ -99,7 +99,8 @@ class CreateProjectSuccessTests(OSComponentTestCase):
name=guid + '-name',
domain=self.os_creds.project_domain_name)
- self.keystone = keystone_utils.keystone_client(self.os_creds)
+ self.keystone = keystone_utils.keystone_client(
+ self.os_creds, self.os_session)
# Initialize for cleanup
self.project_creator = None
@@ -111,6 +112,8 @@ class CreateProjectSuccessTests(OSComponentTestCase):
if self.project_creator:
self.project_creator.clean()
+ super(self.__class__, self).__clean__()
+
def test_create_project_bad_domain(self):
"""
Tests the creation of an OpenStack project with an invalid domain
@@ -140,6 +143,38 @@ class CreateProjectSuccessTests(OSComponentTestCase):
self.assertTrue(validate_project(self.keystone, self.project_settings,
created_project))
+ def test_create_project_quota_override(self):
+ """
+ Tests the creation of an OpenStack project with new quotas.
+ """
+ quotas = {
+ 'cores': 4, 'instances': 5, 'injected_files': 6,
+ 'injected_file_content_bytes': 60000, 'ram': 70000, 'fixed_ips': 7,
+ 'key_pairs': 8}
+ self.project_settings.quotas = quotas
+ self.project_creator = OpenStackProject(self.os_creds,
+ self.project_settings)
+ created_project = self.project_creator.create()
+ self.assertIsNotNone(created_project)
+
+ retrieved_project = keystone_utils.get_project(
+ keystone=self.keystone, project_settings=self.project_settings)
+ self.assertIsNotNone(retrieved_project)
+ self.assertEqual(created_project, retrieved_project)
+ self.assertTrue(validate_project(self.keystone, self.project_settings,
+ created_project))
+
+ nova = nova_utils.nova_client(self.os_creds, self.os_session)
+ new_quotas = nova_utils.get_compute_quotas(nova, created_project.id)
+
+ self.assertEqual(4, new_quotas.cores)
+ self.assertEqual(5, new_quotas.instances)
+ self.assertEqual(6, new_quotas.injected_files)
+ self.assertEqual(60000, new_quotas.injected_file_content_bytes)
+ self.assertEqual(70000, new_quotas.ram)
+ self.assertEqual(7, new_quotas.fixed_ips)
+ self.assertEqual(8, new_quotas.key_pairs)
+
def test_create_project_2x(self):
"""
Tests the creation of an OpenStack project twice to ensure it only
@@ -214,12 +249,12 @@ class CreateProjectSuccessTests(OSComponentTestCase):
self.assertEqual(update_network_quotas,
self.project_creator.get_network_quotas())
- nova = nova_utils.nova_client(self.os_creds)
+ nova = nova_utils.nova_client(self.os_creds, self.os_session)
new_compute_quotas = nova_utils.get_compute_quotas(
nova, self.project_creator.get_project().id)
self.assertEqual(update_compute_quotas, new_compute_quotas)
- neutron = neutron_utils.neutron_client(self.os_creds)
+ neutron = neutron_utils.neutron_client(self.os_creds, self.os_session)
new_network_quotas = neutron_utils.get_network_quotas(
neutron, self.project_creator.get_project().id)
self.assertEqual(update_network_quotas, new_network_quotas)
@@ -241,7 +276,8 @@ class CreateProjectUserTests(OSComponentTestCase):
name=self.guid + '-name',
domain=self.os_creds.project_domain_name)
- self.keystone = keystone_utils.keystone_client(self.os_creds)
+ self.keystone = keystone_utils.keystone_client(
+ self.os_creds, self.os_session)
# Initialize for cleanup
self.project_creator = None
@@ -262,6 +298,8 @@ class CreateProjectUserTests(OSComponentTestCase):
if self.project_creator:
self.project_creator.clean()
+ super(self.__class__, self).__clean__()
+
def test_create_project_sec_grp_one_user(self):
"""
Tests the creation of an OpenStack object to a project with a new users
diff --git a/snaps/openstack/tests/create_qos_tests.py b/snaps/openstack/tests/create_qos_tests.py
index 68737f8..b3d7979 100644
--- a/snaps/openstack/tests/create_qos_tests.py
+++ b/snaps/openstack/tests/create_qos_tests.py
@@ -122,12 +122,14 @@ class CreateQoSTests(OSIntegrationTestCase):
super(self.__class__, self).__start__()
guid = uuid.uuid4()
- self.qos_settings = QoSConfig(
+ qos_settings = QoSConfig(
name=self.__class__.__name__ + '-' + str(guid),
consumer=Consumer.both)
- self.cinder = cinder_utils.cinder_client(self.os_creds)
- self.qos_creator = None
+ self.cinder = cinder_utils.cinder_client(
+ self.admin_os_creds, self.admin_os_session)
+ self.qos_creator = create_qos.OpenStackQoS(
+ self.admin_os_creds, qos_settings)
def tearDown(self):
"""
@@ -143,13 +145,11 @@ class CreateQoSTests(OSIntegrationTestCase):
Tests the creation of an OpenStack qos.
"""
# Create QoS
- self.qos_creator = create_qos.OpenStackQoS(
- self.os_creds, self.qos_settings)
created_qos = self.qos_creator.create()
self.assertIsNotNone(created_qos)
retrieved_qos = cinder_utils.get_qos(
- self.cinder, qos_settings=self.qos_settings)
+ self.cinder, qos_settings=self.qos_creator.qos_settings)
self.assertIsNotNone(retrieved_qos)
self.assertEqual(created_qos, retrieved_qos)
@@ -160,13 +160,11 @@ class CreateQoSTests(OSIntegrationTestCase):
clean() does not raise an Exception.
"""
# Create QoS
- self.qos_creator = create_qos.OpenStackQoS(
- self.os_creds, self.qos_settings)
created_qos = self.qos_creator.create()
self.assertIsNotNone(created_qos)
retrieved_qos = cinder_utils.get_qos(
- self.cinder, qos_settings=self.qos_settings)
+ self.cinder, qos_settings=self.qos_creator.qos_settings)
self.assertIsNotNone(retrieved_qos)
self.assertEqual(created_qos, retrieved_qos)
@@ -174,7 +172,7 @@ class CreateQoSTests(OSIntegrationTestCase):
cinder_utils.delete_qos(self.cinder, created_qos)
self.assertIsNone(cinder_utils.get_qos(
- self.cinder, qos_settings=self.qos_settings))
+ self.cinder, qos_settings=self.qos_creator.qos_settings))
# Must not raise an exception when attempting to cleanup non-existent
# qos
@@ -186,16 +184,14 @@ class CreateQoSTests(OSIntegrationTestCase):
Tests the creation of an OpenStack qos when one already exists.
"""
# Create QoS
- self.qos_creator = create_qos.OpenStackQoS(
- self.os_creds, self.qos_settings)
qos1 = self.qos_creator.create()
retrieved_qos = cinder_utils.get_qos(
- self.cinder, qos_settings=self.qos_settings)
+ self.cinder, qos_settings=self.qos_creator.qos_settings)
self.assertEqual(qos1, retrieved_qos)
# Should be retrieving the instance data
os_qos_2 = create_qos.OpenStackQoS(
- self.os_creds, self.qos_settings)
+ self.admin_os_creds, self.qos_creator.qos_settings)
qos2 = os_qos_2.create()
self.assertEqual(qos1, qos2)
diff --git a/snaps/openstack/tests/create_router_tests.py b/snaps/openstack/tests/create_router_tests.py
index 09471a3..a305cf8 100644
--- a/snaps/openstack/tests/create_router_tests.py
+++ b/snaps/openstack/tests/create_router_tests.py
@@ -15,19 +15,23 @@
import unittest
import uuid
-from snaps.config.network import PortConfig, NetworkConfig
+from snaps.config.network import PortConfig, NetworkConfig, PortConfigError
from snaps.config.router import RouterConfigError, RouterConfig
+from snaps.config.security_group import SecurityGroupConfig
from snaps.openstack import create_network
from snaps.openstack import create_router
from snaps.openstack.create_network import OpenStackNetwork
-from snaps.openstack.create_router import RouterSettings
+from snaps.openstack.create_router import (
+ RouterSettings, OpenStackRouter, RouterCreationError)
+from snaps.openstack.create_security_group import OpenStackSecurityGroup
from snaps.openstack.tests.os_source_file_test import OSIntegrationTestCase
-from snaps.openstack.utils import neutron_utils, settings_utils
+from snaps.openstack.utils import neutron_utils, settings_utils, keystone_utils
__author__ = 'mmakati'
cidr1 = '10.200.201.0/24'
cidr2 = '10.200.202.0/24'
+cidr3 = '10.200.203.0/24'
static_gateway_ip1 = '10.200.201.1'
static_gateway_ip2 = '10.200.202.1'
@@ -128,7 +132,8 @@ class CreateRouterSuccessTests(OSIntegrationTestCase):
self.router_creator = None
self.network_creator1 = None
self.network_creator2 = None
- self.neutron = neutron_utils.neutron_client(self.os_creds)
+ self.neutron = neutron_utils.neutron_client(
+ self.os_creds, self.os_session)
def tearDown(self):
"""
@@ -152,12 +157,13 @@ class CreateRouterSuccessTests(OSIntegrationTestCase):
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)
+ self.router_creator = create_router.OpenStackRouter(
+ self.os_creds, router_settings)
self.router_creator.create()
- router = neutron_utils.get_router(self.neutron,
- router_settings=router_settings)
+ router = neutron_utils.get_router(
+ self.neutron, self.keystone, router_settings=router_settings,
+ project_name=self.os_creds.project_name)
self.assertIsNotNone(router)
self.assertEqual(self.router_creator.get_router(), router)
@@ -177,32 +183,34 @@ class CreateRouterSuccessTests(OSIntegrationTestCase):
self.admin_os_creds, router_settings)
self.router_creator.create()
- router = neutron_utils.get_router(self.neutron,
- router_settings=router_settings)
+ router = neutron_utils.get_router(
+ self.neutron, self.keystone, router_settings=router_settings,
+ project_name=self.os_creds.project_name)
self.assertIsNotNone(router)
- self.assertEqual(self.router_creator.get_router(), router)
+ self.assertEqual(self.router_creator.get_router().id, router.id)
self.check_router_recreation(router, router_settings)
- def test_create_router_new_user_to_admin_project(self):
+ def test_create_router_new_user_as_admin_project(self):
"""
Test creation of a most basic router with the new user pointing
to the admin project.
"""
router_settings = RouterConfig(
name=self.guid + '-pub-router', external_gateway=self.ext_net_name,
- project_name=self.admin_os_creds.project_name)
+ project_name=self.os_creds.project_name)
self.router_creator = create_router.OpenStackRouter(
- self.os_creds, router_settings)
+ self.admin_os_creds, router_settings)
self.router_creator.create()
- router = neutron_utils.get_router(self.neutron,
- router_settings=router_settings)
+ router = neutron_utils.get_router(
+ self.neutron, self.keystone, router_settings=router_settings,
+ project_name=self.os_creds.project_name)
self.assertIsNotNone(router)
- self.assertEqual(self.router_creator.get_router(), router)
+ self.assertEqual(self.router_creator.get_router().id, router.id)
self.check_router_recreation(router, router_settings)
@@ -219,18 +227,67 @@ class CreateRouterSuccessTests(OSIntegrationTestCase):
created_router = self.router_creator.create()
self.assertIsNotNone(created_router)
retrieved_router = neutron_utils.get_router(
- self.neutron, router_settings=self.router_settings)
+ self.neutron, self.keystone, router_settings=self.router_settings,
+ project_name=self.os_creds.project_name)
self.assertIsNotNone(retrieved_router)
neutron_utils.delete_router(self.neutron, created_router)
retrieved_router = neutron_utils.get_router(
- self.neutron, router_settings=self.router_settings)
+ self.neutron, self.keystone, router_settings=self.router_settings,
+ project_name=self.os_creds.project_name)
self.assertIsNone(retrieved_router)
# Should not raise an exception
self.router_creator.clean()
+ def test_create_with_internal_sub(self):
+ """
+ Test internal_subnets works.
+ """
+ network_settings1 = NetworkConfig(
+ name=self.guid + '-pub-net1',
+ subnet_settings=[
+ create_network.SubnetConfig(
+ cidr=cidr1, name=self.guid + '-pub-subnet1',
+ gateway_ip=static_gateway_ip1)])
+ self.network_creator1 = OpenStackNetwork(self.os_creds,
+ network_settings1)
+
+ self.network_creator1.create()
+ self.router_settings = RouterConfig(
+ name=self.guid + '-pub-router', external_gateway=self.ext_net_name,
+ internal_subnets=[network_settings1.subnet_settings[0].name])
+
+ self.router_creator = create_router.OpenStackRouter(
+ self.os_creds, self.router_settings)
+ created_router = self.router_creator.create()
+ self.assertIsNotNone(created_router)
+
+ def test_create_with_invalid_internal_sub(self):
+ """
+ Test adding an internal subnet owned by admin which should fail.
+ """
+ network_settings1 = NetworkConfig(
+ name=self.guid + '-pub-net1',
+ subnet_settings=[
+ create_network.SubnetConfig(
+ cidr=cidr1, name=self.guid + '-pub-subnet1',
+ gateway_ip=static_gateway_ip1)])
+ self.network_creator1 = OpenStackNetwork(self.admin_os_creds,
+ network_settings1)
+
+ self.network_creator1.create()
+ self.router_settings = RouterConfig(
+ name=self.guid + '-pub-router', external_gateway=self.ext_net_name,
+ internal_subnets=[network_settings1.subnet_settings[0].name])
+
+ self.router_creator = create_router.OpenStackRouter(
+ self.os_creds, self.router_settings)
+
+ with self.assertRaises(RouterCreationError):
+ self.router_creator.create()
+
def test_create_router_admin_state_false(self):
"""
Test creation of a basic router with admin state down.
@@ -242,8 +299,9 @@ class CreateRouterSuccessTests(OSIntegrationTestCase):
router_settings)
self.router_creator.create()
- router = neutron_utils.get_router(self.neutron,
- router_settings=router_settings)
+ router = neutron_utils.get_router(
+ self.neutron, self.keystone, router_settings=router_settings,
+ project_name=self.os_creds.project_name)
self.assertIsNotNone(router)
self.assertEqual(self.router_creator.get_router(), router)
@@ -262,7 +320,8 @@ class CreateRouterSuccessTests(OSIntegrationTestCase):
self.router_creator.create()
router = neutron_utils.get_router(
- self.neutron, router_settings=router_settings)
+ self.neutron, self.keystone, router_settings=router_settings,
+ project_name=self.os_creds.project_name)
self.assertIsNotNone(router)
self.assertEqual(self.router_creator.get_router(), router)
@@ -303,25 +362,24 @@ class CreateRouterSuccessTests(OSIntegrationTestCase):
network_settings1.subnet_settings[0].name,
'ip': static_gateway_ip1
}],
- network_name=network_settings1.name,
- project_name=self.os_creds.project_name),
+ network_name=network_settings1.name),
create_network.PortConfig(
name=self.guid + '-port2',
ip_addrs=[{
'subnet_name': network_settings2.subnet_settings[0].name,
'ip': static_gateway_ip2
}],
- network_name=network_settings2.name,
- project_name=self.os_creds.project_name)]
+ network_name=network_settings2.name)]
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_router.OpenStackRouter(
+ self.os_creds, router_settings)
self.router_creator.create()
router = neutron_utils.get_router(
- self.neutron, router_settings=router_settings)
+ self.neutron, self.keystone, router_settings=router_settings,
+ project_name=self.os_creds.project_name)
self.assertEqual(router, self.router_creator.get_router())
@@ -355,8 +413,7 @@ class CreateRouterSuccessTests(OSIntegrationTestCase):
ip_addrs=[{
'subnet_name': network_settings.subnet_settings[0].name,
'ip': static_gateway_ip1}],
- network_name=network_settings.name,
- project_name=self.os_creds.project_name)]
+ network_name=network_settings.name)]
router_settings = RouterConfig(
name=self.guid + '-pub-router', external_gateway=self.ext_net_name,
@@ -366,12 +423,58 @@ class CreateRouterSuccessTests(OSIntegrationTestCase):
self.router_creator.create()
router = neutron_utils.get_router(
- self.neutron, router_settings=router_settings)
+ self.neutron, self.keystone, router_settings=router_settings,
+ project_name=self.os_creds.project_name)
self.assertEquals(router, self.router_creator.get_router())
self.check_router_recreation(router, router_settings)
+ def test_create_router_with_ext_port(self):
+ """
+ Test creation of a router with a port to an external network as an
+ 'admin' user.
+ """
+ port_settings = [
+ create_network.PortConfig(
+ name=self.guid + '-port1',
+ network_name=self.ext_net_name)]
+
+ router_settings = RouterConfig(
+ name=self.guid + '-pub-router', port_settings=port_settings)
+ self.router_creator = create_router.OpenStackRouter(
+ self.admin_os_creds, router_settings)
+ self.router_creator.create()
+
+ admin_neutron = neutron_utils.neutron_client(
+ self.admin_os_creds, self.admin_os_session)
+ admin_keystone = keystone_utils.keystone_client(
+ self.admin_os_creds, self.admin_os_session)
+ router = neutron_utils.get_router(
+ admin_neutron, admin_keystone, router_settings=router_settings,
+ project_name=self.admin_os_creds.project_name)
+
+ self.assertIsNotNone(router)
+ self.assertEquals(router, self.router_creator.get_router())
+
+ ext_net = neutron_utils.get_network(
+ admin_neutron, admin_keystone, network_name=self.ext_net_name)
+
+ self.assertIsNotNone(ext_net)
+ self.assertIsNotNone(router.port_subnets)
+
+ id_found = False
+ for port, subnets in router.port_subnets:
+ self.assertIsNotNone(subnets)
+ self.assertIsNotNone(port)
+
+ if ext_net.id == port.network_id:
+ id_found = True
+ for subnet in subnets:
+ self.assertIsNotNone(subnet)
+ self.assertEqual(ext_net.id, subnet.network_id)
+ self.assertTrue(id_found)
+
def check_router_recreation(self, router, orig_settings):
"""
Validates the derived RouterConfig with the original
@@ -421,6 +524,7 @@ class CreateRouterNegativeTests(OSIntegrationTestCase):
super(self.__class__, self).__start__()
self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
+ self.network_creator = None
self.router_creator = None
def tearDown(self):
@@ -430,6 +534,9 @@ class CreateRouterNegativeTests(OSIntegrationTestCase):
if self.router_creator:
self.router_creator.clean()
+ if self.network_creator:
+ self.network_creator.clean()
+
super(self.__class__, self).__clean__()
def test_create_router_noname(self):
@@ -454,3 +561,313 @@ class CreateRouterNegativeTests(OSIntegrationTestCase):
self.router_creator = create_router.OpenStackRouter(
self.os_creds, router_settings)
self.router_creator.create()
+
+ def test_create_router_admin_ports(self):
+ """
+ Test creation of a router with ports to subnets owned by the admin
+ project
+ """
+ network_settings = NetworkConfig(
+ name=self.guid + '-pub-net1',
+ subnet_settings=[
+ create_network.SubnetConfig(
+ cidr=cidr1, name=self.guid + '-pub-subnet1',
+ gateway_ip=static_gateway_ip1)])
+ self.network_creator = OpenStackNetwork(
+ self.admin_os_creds, network_settings)
+ self.network_creator.create()
+
+ port_settings = [
+ create_network.PortConfig(
+ name=self.guid + '-port1',
+ ip_addrs=[{
+ 'subnet_name': network_settings.subnet_settings[0].name,
+ 'ip': static_gateway_ip1}],
+ network_name=network_settings.name)]
+
+ router_settings = RouterConfig(
+ name=self.guid + '-pub-router', external_gateway=self.ext_net_name,
+ port_settings=port_settings)
+ self.router_creator = create_router.OpenStackRouter(
+ self.os_creds, router_settings)
+
+ with self.assertRaises(PortConfigError):
+ self.router_creator.create()
+
+
+class CreateMultipleRouterTests(OSIntegrationTestCase):
+ """
+ Test for the OpenStackRouter class and how it interacts with routers
+ groups within other projects with the same name
+ """
+
+ def setUp(self):
+ """
+ Initializes objects used for router testing
+ """
+ super(self.__class__, self).__start__()
+
+ self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
+ self.admin_router_creator = None
+ self.proj_router_creator = None
+ self.neutron = neutron_utils.neutron_client(
+ self.os_creds, self.os_session)
+
+ network_settings = NetworkConfig(
+ name=self.guid + '-pub-net', shared=True,
+ subnet_settings=[
+ create_network.SubnetConfig(
+ cidr=cidr1, name=self.guid + '-pub-subnet',
+ gateway_ip=static_gateway_ip1)])
+
+ self.network_creator = OpenStackNetwork(
+ self.admin_os_creds, network_settings)
+ self.network_creator.create()
+
+ def tearDown(self):
+ """
+ Cleans the remote OpenStack objects used for router testing
+ """
+ if self.admin_router_creator:
+ self.admin_router_creator.clean()
+
+ if self.proj_router_creator:
+ self.proj_router_creator.clean()
+
+ if self.network_creator:
+ self.network_creator.clean()
+
+ super(self.__class__, self).__clean__()
+
+ def test_router_same_name_diff_proj(self):
+ """
+ Tests the creation of an OpenStackNetwork with the same name
+ within a different project/tenant when not configured but implied by
+ the OSCreds.
+ """
+ # Create Router
+
+ router_config = RouterConfig(name=self.guid + '-router')
+ self.admin_router_creator = OpenStackRouter(
+ self.admin_os_creds, router_config)
+ self.admin_router_creator.create()
+
+ self.proj_router_creator = OpenStackRouter(
+ self.os_creds, router_config)
+ self.proj_router_creator.create()
+
+ self.assertNotEqual(
+ self.admin_router_creator.get_router().id,
+ self.proj_router_creator.get_router().id)
+
+ admin_creator2 = OpenStackRouter(
+ self.admin_os_creds, router_config)
+ admin_creator2.create()
+ self.assertEqual(
+ self.admin_router_creator.get_router(),
+ admin_creator2.get_router())
+
+ proj_creator2 = OpenStackRouter(self.os_creds, router_config)
+ proj_creator2.create()
+ self.assertEqual(self.proj_router_creator.get_router(),
+ proj_creator2.get_router())
+
+ def test_router_create_by_admin_to_different_project(self):
+ """
+ Tests the creation of an OpenStackRouter by the admin user and
+ initialize again with tenant credentials.
+ """
+ # Create Network
+
+ admin_router_config = RouterConfig(
+ name=self.guid + '-router',
+ project_name=self.os_creds.project_name)
+
+ self.admin_router_creator = OpenStackRouter(
+ self.admin_os_creds, admin_router_config)
+ self.admin_router_creator.create()
+
+ proj_router_config = RouterConfig(
+ name=self.guid + '-router',
+ project_name=self.os_creds.project_name)
+
+ self.proj_router_creator = OpenStackRouter(
+ self.os_creds, proj_router_config)
+ self.proj_router_creator.create()
+
+ self.assertEqual(
+ self.admin_router_creator.get_router().id,
+ self.proj_router_creator.get_router().id)
+
+
+class CreateRouterSecurityGroupTests(OSIntegrationTestCase):
+ """
+ Class for testing routers with ports containing security groups
+ """
+
+ def setUp(self):
+ """
+ Initializes objects used for router testing
+ """
+ super(self.__class__, self).__start__()
+
+ self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
+ self.router_creator = None
+ self.network_creator = None
+
+ self.sec_grp_creator = OpenStackSecurityGroup(
+ self.os_creds, SecurityGroupConfig(name=self.guid + '-sec_grp'))
+ self.sec_grp_creator.create()
+
+ self.neutron = neutron_utils.neutron_client(
+ self.os_creds, self.os_session)
+
+ def tearDown(self):
+ """
+ Cleans the remote OpenStack objects used for router testing
+ """
+ if self.router_creator:
+ self.router_creator.clean()
+
+ if self.network_creator:
+ self.network_creator.clean()
+
+ if self.sec_grp_creator:
+ self.sec_grp_creator.clean()
+
+ super(self.__class__, self).__clean__()
+
+ def test_create_router_secure_port(self):
+ """
+ Test creation of a router with a port that has a security group.
+ """
+ network_settings = NetworkConfig(
+ name=self.guid + '-pub-net1',
+ subnet_settings=[
+ create_network.SubnetConfig(
+ cidr=cidr1, name=self.guid + '-pub-subnet1')])
+ self.network_creator = OpenStackNetwork(
+ self.os_creds, network_settings)
+ self.network_creator.create()
+
+ port_settings = [
+ create_network.PortConfig(
+ name=self.guid + '-port1',
+ ip_addrs=[{
+ 'subnet_name': network_settings.subnet_settings[0].name,
+ 'ip': static_gateway_ip1}],
+ network_name=network_settings.name,
+ security_groups=[self.sec_grp_creator.sec_grp_settings.name])]
+
+ router_settings = RouterConfig(
+ name=self.guid + '-pub-router', external_gateway=self.ext_net_name,
+ port_settings=port_settings)
+ self.router_creator = create_router.OpenStackRouter(
+ self.os_creds, router_settings)
+ self.router_creator.create()
+
+
+class CreateRouterSharedNetworksTests(OSIntegrationTestCase):
+ """
+ Class for testing routers external and/or shared networks
+ """
+
+ def setUp(self):
+ """
+ Initializes objects used for router testing
+ """
+ super(self.__class__, self).__start__()
+
+ self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
+ self.router_creator = None
+
+ ext_network_settings = NetworkConfig(
+ name=self.guid + '-ext-net',
+ external=True,
+ subnet_settings=[
+ create_network.SubnetConfig(
+ cidr=cidr1, name=self.guid + '-ext-subnet1')])
+ self.ext_network_creator = OpenStackNetwork(
+ self.admin_os_creds, ext_network_settings)
+ self.ext_network_creator.create()
+
+ shared_network_settings = NetworkConfig(
+ name=self.guid + '-shared-net',
+ shared=True,
+ subnet_settings=[
+ create_network.SubnetConfig(
+ cidr=cidr2, name=self.guid + '-shared-subnet1')])
+ self.shared_network_creator = OpenStackNetwork(
+ self.admin_os_creds, shared_network_settings)
+ self.shared_network_creator.create()
+
+ overlay_network_settings = NetworkConfig(
+ name=self.guid + '-overlay-net',
+ subnet_settings=[
+ create_network.SubnetConfig(
+ cidr=cidr3, name=self.guid + '-overlay-subnet1')])
+ self.overlay_network_creator = OpenStackNetwork(
+ self.os_creds, overlay_network_settings)
+ self.overlay_network_creator.create()
+
+ self.neutron = neutron_utils.neutron_client(
+ self.os_creds, self.os_session)
+
+ def tearDown(self):
+ """
+ Cleans the remote OpenStack objects used for router testing
+ """
+ if self.router_creator:
+ self.router_creator.clean()
+
+ if self.overlay_network_creator:
+ self.overlay_network_creator.clean()
+
+ if self.shared_network_creator:
+ self.shared_network_creator.clean()
+
+ if self.ext_network_creator:
+ self.ext_network_creator.clean()
+
+ super(self.__class__, self).__clean__()
+
+ def test_create_router_external(self):
+ """
+ Test creation of a router with a custom external network created by
+ admin.
+ """
+ router_settings = RouterConfig(
+ name=self.guid + '-pub-router',
+ external_gateway=self.ext_network_creator.get_network().name)
+ self.router_creator = create_router.OpenStackRouter(
+ self.os_creds, router_settings)
+ self.router_creator.create()
+
+ def test_create_router_port_external(self):
+ """
+ Test creation of a router with a port to an custom external network
+ created by admin.
+ """
+ router_settings = RouterConfig(
+ name=self.guid + '-pub-router',
+ network_name=self.ext_network_creator.get_network().name)
+ self.router_creator = create_router.OpenStackRouter(
+ self.os_creds, router_settings)
+ self.router_creator.create()
+
+ def test_create_router_port_shared(self):
+ """
+ Test creation of a router with a port to an custom shared network
+ created by admin.
+ """
+ port_settings = [
+ create_network.PortConfig(
+ name=self.guid + '-port1',
+ network_name=self.shared_network_creator.get_network().name)]
+
+ 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()
diff --git a/snaps/openstack/tests/create_security_group_tests.py b/snaps/openstack/tests/create_security_group_tests.py
index 090d736..dc632b7 100644
--- a/snaps/openstack/tests/create_security_group_tests.py
+++ b/snaps/openstack/tests/create_security_group_tests.py
@@ -21,7 +21,7 @@ from snaps.config.security_group import (
from snaps.openstack import create_security_group
from snaps.openstack.create_security_group import (
SecurityGroupSettings, SecurityGroupRuleSettings, Direction, Ethertype,
- Protocol)
+ Protocol, OpenStackSecurityGroup)
from snaps.openstack.tests import validation_utils
from snaps.openstack.tests.os_source_file_test import OSIntegrationTestCase
from snaps.openstack.utils import neutron_utils
@@ -210,7 +210,8 @@ class CreateSecurityGroupTests(OSIntegrationTestCase):
guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
self.sec_grp_name = guid + 'name'
- self.neutron = neutron_utils.neutron_client(self.os_creds)
+ self.neutron = neutron_utils.neutron_client(
+ self.os_creds, self.os_session)
# Initialize for cleanup
self.sec_grp_creator = None
@@ -228,7 +229,7 @@ class CreateSecurityGroupTests(OSIntegrationTestCase):
"""
Tests the creation of an OpenStack Security Group without custom rules.
"""
- # Create Image
+ # Create Security Group
sec_grp_settings = SecurityGroupConfig(name=self.sec_grp_name,
description='hello group')
self.sec_grp_creator = create_security_group.OpenStackSecurityGroup(
@@ -236,7 +237,7 @@ class CreateSecurityGroupTests(OSIntegrationTestCase):
self.sec_grp_creator.create()
sec_grp = neutron_utils.get_security_group(
- self.neutron, sec_grp_settings=sec_grp_settings)
+ self.neutron, self.keystone, sec_grp_settings=sec_grp_settings)
self.assertIsNotNone(sec_grp)
validation_utils.objects_equivalent(
@@ -249,23 +250,24 @@ class CreateSecurityGroupTests(OSIntegrationTestCase):
self.assertTrue(
validate_sec_grp(
- self.neutron, self.sec_grp_creator.sec_grp_settings,
+ self.neutron, self.keystone,
+ self.sec_grp_creator.sec_grp_settings,
self.sec_grp_creator.get_security_group()))
def test_create_group_admin_user_to_new_project(self):
"""
Tests the creation of an OpenStack Security Group without custom rules.
"""
- # Create Image
+ # Create Security Group
sec_grp_settings = SecurityGroupConfig(
name=self.sec_grp_name, description='hello group',
- project_name=self.admin_os_creds.project_name)
- self.sec_grp_creator = create_security_group.OpenStackSecurityGroup(
- self.os_creds, sec_grp_settings)
+ project_name=self.os_creds.project_name)
+ self.sec_grp_creator = OpenStackSecurityGroup(
+ self.admin_os_creds, sec_grp_settings)
self.sec_grp_creator.create()
sec_grp = neutron_utils.get_security_group(
- self.neutron, sec_grp_settings=sec_grp_settings)
+ self.neutron, self.keystone, sec_grp_settings=sec_grp_settings)
self.assertIsNotNone(sec_grp)
validation_utils.objects_equivalent(
@@ -278,14 +280,25 @@ class CreateSecurityGroupTests(OSIntegrationTestCase):
self.assertTrue(
validate_sec_grp(
- self.neutron, self.sec_grp_creator.sec_grp_settings,
+ self.neutron, self.keystone,
+ self.sec_grp_creator.sec_grp_settings,
self.sec_grp_creator.get_security_group(), rules))
+ self.assertEqual(self.sec_grp_creator.get_security_group().id,
+ sec_grp.id)
+
+ proj_creator = OpenStackSecurityGroup(
+ self.os_creds, SecurityGroupConfig(name=self.sec_grp_name))
+ proj_creator.create()
+
+ self.assertEqual(self.sec_grp_creator.get_security_group().id,
+ proj_creator.get_security_group().id)
+
def test_create_group_new_user_to_admin_project(self):
"""
Tests the creation of an OpenStack Security Group without custom rules.
"""
- # Create Image
+ # Create Security Group
sec_grp_settings = SecurityGroupConfig(
name=self.sec_grp_name, description='hello group',
project_name=self.os_creds.project_name)
@@ -294,7 +307,7 @@ class CreateSecurityGroupTests(OSIntegrationTestCase):
self.sec_grp_creator.create()
sec_grp = neutron_utils.get_security_group(
- self.neutron, sec_grp_settings=sec_grp_settings)
+ self.neutron, self.keystone, sec_grp_settings=sec_grp_settings)
self.assertIsNotNone(sec_grp)
validation_utils.objects_equivalent(
@@ -307,14 +320,15 @@ class CreateSecurityGroupTests(OSIntegrationTestCase):
self.assertTrue(
validate_sec_grp(
- self.neutron, self.sec_grp_creator.sec_grp_settings,
+ self.neutron, self.keystone,
+ self.sec_grp_creator.sec_grp_settings,
self.sec_grp_creator.get_security_group(), rules))
def test_create_delete_group(self):
"""
Tests the creation of an OpenStack Security Group without custom rules.
"""
- # Create Image
+ # Create Security Group
sec_grp_settings = SecurityGroupConfig(name=self.sec_grp_name,
description='hello group')
self.sec_grp_creator = create_security_group.OpenStackSecurityGroup(
@@ -324,12 +338,13 @@ class CreateSecurityGroupTests(OSIntegrationTestCase):
self.assertTrue(
validate_sec_grp(
- self.neutron, self.sec_grp_creator.sec_grp_settings,
+ self.neutron, self.keystone,
+ self.sec_grp_creator.sec_grp_settings,
self.sec_grp_creator.get_security_group()))
neutron_utils.delete_security_group(self.neutron, created_sec_grp)
self.assertIsNone(neutron_utils.get_security_group(
- self.neutron,
+ self.neutron, self.keystone,
sec_grp_settings=self.sec_grp_creator.sec_grp_settings))
self.sec_grp_creator.clean()
@@ -339,7 +354,7 @@ class CreateSecurityGroupTests(OSIntegrationTestCase):
Tests the creation of an OpenStack Security Group with one simple
custom rule.
"""
- # Create Image
+ # Create Security Group
sec_grp_rule_settings = list()
sec_grp_rule_settings.append(
SecurityGroupRuleConfig(
@@ -353,7 +368,7 @@ class CreateSecurityGroupTests(OSIntegrationTestCase):
self.sec_grp_creator.create()
sec_grp = neutron_utils.get_security_group(
- self.neutron, sec_grp_settings=sec_grp_settings)
+ self.neutron, self.keystone, sec_grp_settings=sec_grp_settings)
validation_utils.objects_equivalent(
self.sec_grp_creator.get_security_group(), sec_grp)
rules = neutron_utils.get_rules_by_security_group(
@@ -364,7 +379,8 @@ class CreateSecurityGroupTests(OSIntegrationTestCase):
self.assertTrue(
validate_sec_grp(
- self.neutron, self.sec_grp_creator.sec_grp_settings,
+ self.neutron, self.keystone,
+ self.sec_grp_creator.sec_grp_settings,
self.sec_grp_creator.get_security_group(), rules))
def test_create_group_with_one_complex_rule(self):
@@ -372,7 +388,7 @@ class CreateSecurityGroupTests(OSIntegrationTestCase):
Tests the creation of an OpenStack Security Group with one simple
custom rule.
"""
- # Create Image
+ # Create Security Group
sec_grp_rule_settings = list()
sec_grp_rule_settings.append(
SecurityGroupRuleConfig(
@@ -388,7 +404,7 @@ class CreateSecurityGroupTests(OSIntegrationTestCase):
self.sec_grp_creator.create()
sec_grp = neutron_utils.get_security_group(
- self.neutron, sec_grp_settings=sec_grp_settings)
+ self.neutron, self.keystone, sec_grp_settings=sec_grp_settings)
validation_utils.objects_equivalent(
self.sec_grp_creator.get_security_group(), sec_grp)
rules = neutron_utils.get_rules_by_security_group(
@@ -399,7 +415,8 @@ class CreateSecurityGroupTests(OSIntegrationTestCase):
self.assertTrue(
validate_sec_grp(
- self.neutron, self.sec_grp_creator.sec_grp_settings,
+ self.neutron, self.keystone,
+ self.sec_grp_creator.sec_grp_settings,
self.sec_grp_creator.get_security_group(), rules))
def test_create_group_with_several_rules(self):
@@ -407,7 +424,7 @@ class CreateSecurityGroupTests(OSIntegrationTestCase):
Tests the creation of an OpenStack Security Group with one simple
custom rule.
"""
- # Create Image
+ # Create Security Group
sec_grp_rule_settings = list()
sec_grp_rule_settings.append(
SecurityGroupRuleConfig(
@@ -432,7 +449,7 @@ class CreateSecurityGroupTests(OSIntegrationTestCase):
self.sec_grp_creator.create()
sec_grp = neutron_utils.get_security_group(
- self.neutron, sec_grp_settings=sec_grp_settings)
+ self.neutron, self.keystone, sec_grp_settings=sec_grp_settings)
validation_utils.objects_equivalent(
self.sec_grp_creator.get_security_group(), sec_grp)
rules = neutron_utils.get_rules_by_security_group(
@@ -443,7 +460,8 @@ class CreateSecurityGroupTests(OSIntegrationTestCase):
self.assertTrue(
validate_sec_grp(
- self.neutron, self.sec_grp_creator.sec_grp_settings,
+ self.neutron, self.keystone,
+ self.sec_grp_creator.sec_grp_settings,
self.sec_grp_creator.get_security_group(), rules))
def test_add_rule(self):
@@ -451,7 +469,7 @@ class CreateSecurityGroupTests(OSIntegrationTestCase):
Tests the creation of an OpenStack Security Group with one simple
custom rule then adds one after creation.
"""
- # Create Image
+ # Create Security Group
sec_grp_rule_settings = list()
sec_grp_rule_settings.append(
SecurityGroupRuleConfig(
@@ -465,7 +483,7 @@ class CreateSecurityGroupTests(OSIntegrationTestCase):
self.sec_grp_creator.create()
sec_grp = neutron_utils.get_security_group(
- self.neutron, sec_grp_settings=sec_grp_settings)
+ self.neutron, self.keystone, sec_grp_settings=sec_grp_settings)
validation_utils.objects_equivalent(
self.sec_grp_creator.get_security_group(), sec_grp)
@@ -474,7 +492,8 @@ class CreateSecurityGroupTests(OSIntegrationTestCase):
self.assertTrue(
validate_sec_grp(
- self.neutron, self.sec_grp_creator.sec_grp_settings,
+ self.neutron, self.keystone,
+ self.sec_grp_creator.sec_grp_settings,
self.sec_grp_creator.get_security_group(), rules))
rules = neutron_utils.get_rules_by_security_group(
@@ -496,7 +515,7 @@ class CreateSecurityGroupTests(OSIntegrationTestCase):
Tests the creation of an OpenStack Security Group with two simple
custom rules then removes one by the rule ID.
"""
- # Create Image
+ # Create Security Group
sec_grp_rule_settings = list()
sec_grp_rule_settings.append(
SecurityGroupRuleConfig(
@@ -521,7 +540,7 @@ class CreateSecurityGroupTests(OSIntegrationTestCase):
self.sec_grp_creator.create()
sec_grp = neutron_utils.get_security_group(
- self.neutron, sec_grp_settings=sec_grp_settings)
+ self.neutron, self.keystone, sec_grp_settings=sec_grp_settings)
validation_utils.objects_equivalent(
self.sec_grp_creator.get_security_group(), sec_grp)
rules = neutron_utils.get_rules_by_security_group(
@@ -532,7 +551,8 @@ class CreateSecurityGroupTests(OSIntegrationTestCase):
self.assertTrue(
validate_sec_grp(
- self.neutron, self.sec_grp_creator.sec_grp_settings,
+ self.neutron, self.keystone,
+ self.sec_grp_creator.sec_grp_settings,
self.sec_grp_creator.get_security_group(), rules))
self.sec_grp_creator.remove_rule(
@@ -547,7 +567,7 @@ class CreateSecurityGroupTests(OSIntegrationTestCase):
Tests the creation of an OpenStack Security Group with two simple
custom rules then removes one by the rule setting object
"""
- # Create Image
+ # Create Security Group
sec_grp_rule_settings = list()
sec_grp_rule_settings.append(
SecurityGroupRuleConfig(
@@ -572,7 +592,7 @@ class CreateSecurityGroupTests(OSIntegrationTestCase):
self.sec_grp_creator.create()
sec_grp = neutron_utils.get_security_group(
- self.neutron, sec_grp_settings=sec_grp_settings)
+ self.neutron, self.keystone, sec_grp_settings=sec_grp_settings)
validation_utils.objects_equivalent(
self.sec_grp_creator.get_security_group(), sec_grp)
@@ -584,7 +604,8 @@ class CreateSecurityGroupTests(OSIntegrationTestCase):
self.assertTrue(
validate_sec_grp(
- self.neutron, self.sec_grp_creator.sec_grp_settings,
+ self.neutron, self.keystone,
+ self.sec_grp_creator.sec_grp_settings,
self.sec_grp_creator.get_security_group(), rules))
self.sec_grp_creator.remove_rule(rule_setting=sec_grp_rule_settings[0])
@@ -594,11 +615,13 @@ class CreateSecurityGroupTests(OSIntegrationTestCase):
self.assertEqual(len(rules) - 1, len(rules_after_del))
-def validate_sec_grp(neutron, sec_grp_settings, sec_grp, rules=list()):
+def validate_sec_grp(neutron, keystone, sec_grp_settings, sec_grp,
+ rules=list()):
"""
Returns True is the settings on a security group are properly contained
on the SNAPS SecurityGroup domain object
:param neutron: the neutron client
+ :param keystone: the keystone client
:param sec_grp_settings: the security group configuration
:param sec_grp: the SNAPS-OO security group object
:param rules: collection of SNAPS-OO security group rule objects
@@ -607,10 +630,10 @@ def validate_sec_grp(neutron, sec_grp_settings, sec_grp, rules=list()):
return (sec_grp.description == sec_grp_settings.description and
sec_grp.name == sec_grp_settings.name and
validate_sec_grp_rules(
- neutron, sec_grp_settings.rule_settings, rules))
+ neutron, keystone, sec_grp_settings.rule_settings, rules))
-def validate_sec_grp_rules(neutron, rule_settings, rules):
+def validate_sec_grp_rules(neutron, keystone, rule_settings, rules):
"""
Returns True is the settings on a security group rule are properly
contained on the SNAPS SecurityGroupRule domain object.
@@ -618,6 +641,7 @@ def validate_sec_grp_rules(neutron, rule_settings, rules):
this is the only means to tell if the rule is custom or defaulted by
OpenStack
:param neutron: the neutron client
+ :param keystone: the keystone client
:param rule_settings: collection of SecurityGroupRuleConfig objects
:param rules: a collection of SecurityGroupRule domain objects
:return: T/F
@@ -628,7 +652,7 @@ def validate_sec_grp_rules(neutron, rule_settings, rules):
match = False
for rule in rules:
sec_grp = neutron_utils.get_security_group(
- neutron, sec_grp_name=rule_setting.sec_grp_name)
+ neutron, keystone, sec_grp_name=rule_setting.sec_grp_name)
setting_eth_type = create_security_group.Ethertype.IPv4
if rule_setting.ethertype:
@@ -657,3 +681,69 @@ def validate_sec_grp_rules(neutron, rule_settings, rules):
return False
return True
+
+
+class CreateMultipleSecurityGroupTests(OSIntegrationTestCase):
+ """
+ Test for the CreateSecurityGroup class and how it interacts with security
+ groups within other projects with the same name
+ """
+
+ def setUp(self):
+ """
+ Instantiates the CreateSecurityGroup object that is responsible for
+ downloading and creating an OS image file within OpenStack
+ """
+ super(self.__class__, self).__start__()
+
+ guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
+ self.sec_grp_name = guid + 'name'
+ self.neutron = neutron_utils.neutron_client(
+ self.os_creds, self.os_session)
+
+ # Initialize for cleanup
+ self.admin_sec_grp_config = SecurityGroupConfig(
+ name=self.sec_grp_name, description='hello group')
+ self.sec_grp_creator_admin = OpenStackSecurityGroup(
+ self.admin_os_creds, self.admin_sec_grp_config)
+ self.sec_grp_creator_admin.create()
+ self.sec_grp_creator_proj = None
+
+ def tearDown(self):
+ """
+ Cleans the image and downloaded image file
+ """
+ if self.sec_grp_creator_admin:
+ self.sec_grp_creator_admin.clean()
+ if self.sec_grp_creator_proj:
+ self.sec_grp_creator_proj.clean()
+
+ super(self.__class__, self).__clean__()
+
+ def test_sec_grp_same_name_diff_proj(self):
+ """
+ Tests the creation of an OpenStack Security Group with the same name
+ within a different project/tenant.
+ """
+ # Create Security Group
+ sec_grp_config = SecurityGroupConfig(
+ name=self.sec_grp_name, description='hello group')
+ self.sec_grp_creator_proj = OpenStackSecurityGroup(
+ self.os_creds, sec_grp_config)
+ self.sec_grp_creator_proj.create()
+
+ self.assertNotEqual(
+ self.sec_grp_creator_admin.get_security_group().id,
+ self.sec_grp_creator_proj.get_security_group().id)
+
+ admin_sec_grp_creator = OpenStackSecurityGroup(
+ self.admin_os_creds, self.admin_sec_grp_config)
+ admin_sec_grp_creator.create()
+ self.assertEqual(self.sec_grp_creator_admin.get_security_group().id,
+ admin_sec_grp_creator.get_security_group().id)
+
+ proj_sec_grp_creator = OpenStackSecurityGroup(
+ self.os_creds, sec_grp_config)
+ proj_sec_grp_creator.create()
+ self.assertEqual(self.sec_grp_creator_proj.get_security_group().id,
+ proj_sec_grp_creator.get_security_group().id)
diff --git a/snaps/openstack/tests/create_stack_tests.py b/snaps/openstack/tests/create_stack_tests.py
index 6041735..7da5bc7 100644
--- a/snaps/openstack/tests/create_stack_tests.py
+++ b/snaps/openstack/tests/create_stack_tests.py
@@ -22,7 +22,8 @@ import snaps
from snaps import file_utils
from snaps.config.flavor import FlavorConfig
from snaps.config.image import ImageConfig
-from snaps.config.stack import StackConfigError, StackConfig
+from snaps.config.stack import (StackConfigError, StackConfig,
+ STATUS_UPDATE_COMPLETE)
from snaps.openstack.create_flavor import OpenStackFlavor
from snaps.openstack.create_image import OpenStackImage
@@ -35,11 +36,13 @@ import logging
import unittest
import uuid
+from snaps.openstack import create_stack
from snaps.openstack.create_stack import (
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
+from snaps.openstack.utils import (
+ heat_utils, neutron_utils, nova_utils, keystone_utils)
__author__ = 'spisarski'
@@ -132,28 +135,27 @@ class CreateStackSuccessTests(OSIntegrationTestCase):
"""
def setUp(self):
+ self.user_roles = ['heat_stack_owner']
super(self.__class__, self).__start__()
self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
- self.heat_creds = self.admin_os_creds
- self.heat_creds.project_name = self.admin_os_creds.project_name
-
- self.heat_cli = heat_utils.heat_client(self.heat_creds)
+ self.heat_cli = heat_utils.heat_client(self.os_creds, self.os_session)
self.stack_creator = None
self.image_creator = OpenStackImage(
- self.heat_creds, openstack_tests.cirros_image_settings(
+ self.os_creds, openstack_tests.cirros_image_settings(
name=self.guid + '-image',
image_metadata=self.image_metadata))
self.image_creator.create()
# Create Flavor
+ flavor_config = openstack_tests.get_flavor_config(
+ name=self.guid + '-flavor-name', ram=256, disk=10,
+ vcpus=1, metadata=self.flavor_metadata)
self.flavor_creator = OpenStackFlavor(
- self.admin_os_creds,
- FlavorConfig(
- name=self.guid + '-flavor-name', ram=256, disk=10, vcpus=1))
+ self.admin_os_creds, flavor_config)
self.flavor_creator.create()
self.network_name = self.guid + '-net'
@@ -206,8 +208,8 @@ class CreateStackSuccessTests(OSIntegrationTestCase):
template_path=self.heat_tmplt_path,
env_values=self.env_values)
self.stack_creator = OpenStackHeatStack(
- self.heat_creds, stack_settings)
- created_stack = self.stack_creator.create()
+ self.os_creds, stack_settings)
+ created_stack = self.stack_creator.create(block=True)
self.assertIsNotNone(created_stack)
retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
@@ -217,6 +219,12 @@ class CreateStackSuccessTests(OSIntegrationTestCase):
self.assertEqual(created_stack.id, retrieved_stack.id)
self.assertEqual(0, len(self.stack_creator.get_outputs()))
+ derived_creator = create_stack.generate_creator(
+ self.os_creds, retrieved_stack,
+ [self.image_creator.image_settings])
+ derived_stack = derived_creator.get_stack()
+ self.assertEqual(retrieved_stack, derived_stack)
+
def test_create_stack_short_timeout(self):
"""
Tests the creation of an OpenStack stack from Heat template file.
@@ -230,9 +238,9 @@ class CreateStackSuccessTests(OSIntegrationTestCase):
env_values=self.env_values, stack_create_timeout=0)
self.stack_creator = OpenStackHeatStack(
- self.heat_creds, stack_settings)
+ self.os_creds, stack_settings)
with self.assertRaises(StackCreationError):
- self.stack_creator.create()
+ self.stack_creator.create(block=True)
def test_create_stack_template_dict(self):
"""
@@ -248,8 +256,8 @@ class CreateStackSuccessTests(OSIntegrationTestCase):
template=template_dict,
env_values=self.env_values)
self.stack_creator = OpenStackHeatStack(
- self.heat_creds, stack_settings)
- created_stack = self.stack_creator.create()
+ self.os_creds, stack_settings)
+ created_stack = self.stack_creator.create(block=True)
self.assertIsNotNone(created_stack)
retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
@@ -272,8 +280,8 @@ class CreateStackSuccessTests(OSIntegrationTestCase):
template=template_dict,
env_values=self.env_values)
self.stack_creator = OpenStackHeatStack(
- self.heat_creds, stack_settings)
- created_stack = self.stack_creator.create()
+ self.os_creds, stack_settings)
+ created_stack = self.stack_creator.create(block=True)
self.assertIsNotNone(created_stack)
retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
@@ -316,8 +324,8 @@ class CreateStackSuccessTests(OSIntegrationTestCase):
template=template_dict,
env_values=self.env_values)
self.stack_creator = OpenStackHeatStack(
- self.heat_creds, stack_settings)
- created_stack1 = self.stack_creator.create()
+ self.os_creds, stack_settings)
+ created_stack1 = self.stack_creator.create(block=True)
retrieved_stack = heat_utils.get_stack_by_id(self.heat_cli,
created_stack1.id)
@@ -327,8 +335,8 @@ class CreateStackSuccessTests(OSIntegrationTestCase):
self.assertEqual(0, len(self.stack_creator.get_outputs()))
# Should be retrieving the instance data
- stack_creator2 = OpenStackHeatStack(self.heat_creds, stack_settings)
- stack2 = stack_creator2.create()
+ stack_creator2 = OpenStackHeatStack(self.os_creds, stack_settings)
+ stack2 = stack_creator2.create(block=True)
self.assertEqual(created_stack1.id, stack2.id)
def test_retrieve_network_creators(self):
@@ -341,8 +349,8 @@ class CreateStackSuccessTests(OSIntegrationTestCase):
template_path=self.heat_tmplt_path,
env_values=self.env_values)
self.stack_creator = OpenStackHeatStack(
- self.heat_creds, stack_settings)
- created_stack = self.stack_creator.create()
+ self.os_creds, stack_settings)
+ created_stack = self.stack_creator.create(block=True)
self.assertIsNotNone(created_stack)
net_creators = self.stack_creator.get_network_creators()
@@ -350,9 +358,14 @@ class CreateStackSuccessTests(OSIntegrationTestCase):
self.assertEqual(1, len(net_creators))
self.assertEqual(self.network_name, net_creators[0].get_network().name)
- neutron = neutron_utils.neutron_client(self.os_creds)
+ # Need to use 'admin' creds as heat creates objects under it's own
+ # project/tenant
+ neutron = neutron_utils.neutron_client(
+ self.os_creds, self.os_session)
+ keystone = keystone_utils.keystone_client(
+ self.os_creds, self.os_session)
net_by_name = neutron_utils.get_network(
- neutron, network_name=net_creators[0].get_network().name)
+ neutron, keystone, network_name=net_creators[0].get_network().name)
self.assertEqual(net_creators[0].get_network(), net_by_name)
self.assertIsNotNone(neutron_utils.get_network_by_id(
neutron, net_creators[0].get_network().id))
@@ -360,7 +373,7 @@ class CreateStackSuccessTests(OSIntegrationTestCase):
self.assertEqual(1, len(net_creators[0].get_network().subnets))
subnet = net_creators[0].get_network().subnets[0]
subnet_by_name = neutron_utils.get_subnet(
- neutron, subnet_name=subnet.name)
+ neutron, net_creators[0].get_network(), subnet_name=subnet.name)
self.assertEqual(subnet, subnet_by_name)
subnet_by_id = neutron_utils.get_subnet_by_id(neutron, subnet.id)
@@ -377,8 +390,8 @@ class CreateStackSuccessTests(OSIntegrationTestCase):
template_path=self.heat_tmplt_path,
env_values=self.env_values)
self.stack_creator = OpenStackHeatStack(
- self.heat_creds, stack_settings)
- created_stack = self.stack_creator.create()
+ self.os_creds, stack_settings)
+ created_stack = self.stack_creator.create(block=True)
self.assertIsNotNone(created_stack)
vm_inst_creators = self.stack_creator.get_vm_inst_creators()
@@ -387,13 +400,16 @@ class CreateStackSuccessTests(OSIntegrationTestCase):
self.assertEqual(self.vm_inst_name,
vm_inst_creators[0].get_vm_inst().name)
- nova = nova_utils.nova_client(self.admin_os_creds)
- neutron = neutron_utils.neutron_client(self.admin_os_creds)
+ nova = nova_utils.nova_client(self.os_creds, self.os_session)
+ neutron = neutron_utils.neutron_client(self.os_creds, self.os_session)
+ keystone = keystone_utils.keystone_client(self.os_creds, self.os_session)
vm_inst_by_name = nova_utils.get_server(
- nova, neutron, server_name=vm_inst_creators[0].get_vm_inst().name)
+ nova, neutron, keystone,
+ server_name=vm_inst_creators[0].get_vm_inst().name)
+
self.assertEqual(vm_inst_creators[0].get_vm_inst(), vm_inst_by_name)
self.assertIsNotNone(nova_utils.get_server_object_by_id(
- nova, neutron, vm_inst_creators[0].get_vm_inst().id))
+ nova, neutron, keystone, vm_inst_creators[0].get_vm_inst().id))
class CreateStackFloatingIpTests(OSIntegrationTestCase):
@@ -403,19 +419,17 @@ class CreateStackFloatingIpTests(OSIntegrationTestCase):
"""
def setUp(self):
+ self.user_roles = ['heat_stack_owner', 'admin']
super(self.__class__, self).__start__()
self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
- self.heat_creds = self.admin_os_creds
- self.heat_creds.project_name = self.admin_os_creds.project_name
-
- self.heat_cli = heat_utils.heat_client(self.heat_creds)
+ self.heat_cli = heat_utils.heat_client(self.os_creds, self.os_session)
self.stack_creator = None
self.image_creator = OpenStackImage(
- self.heat_creds, openstack_tests.cirros_image_settings(
+ self.os_creds, openstack_tests.cirros_image_settings(
name=self.guid + '-image',
image_metadata=self.image_metadata))
self.image_creator.create()
@@ -434,6 +448,7 @@ class CreateStackFloatingIpTests(OSIntegrationTestCase):
'image2_name': self.image_creator.image_settings.name,
'flavor1_name': self.flavor1_name,
'flavor2_name': self.flavor2_name,
+ 'flavor_extra_specs': self.flavor_metadata,
'net_name': self.network_name,
'subnet_name': self.subnet_name,
'inst1_name': self.vm_inst1_name,
@@ -487,9 +502,9 @@ class CreateStackFloatingIpTests(OSIntegrationTestCase):
template_path=self.heat_tmplt_path,
env_values=self.env_values)
self.stack_creator = OpenStackHeatStack(
- self.heat_creds, stack_settings,
+ self.os_creds, stack_settings,
[self.image_creator.image_settings])
- created_stack = self.stack_creator.create()
+ created_stack = self.stack_creator.create(block=True)
self.assertIsNotNone(created_stack)
self.vm_inst_creators = self.stack_creator.get_vm_inst_creators(
@@ -505,6 +520,39 @@ class CreateStackFloatingIpTests(OSIntegrationTestCase):
vm_settings = vm_inst_creator.instance_settings
self.assertEqual(0, len(vm_settings.floating_ip_settings))
+ def test_connect_via_ssh_heat_vm_derived(self):
+ """
+ Tests the the retrieval of two VM instance creators from a derived
+ OpenStackHeatStack object and attempt to connect via
+ SSH to the first one with a floating IP.
+ """
+ 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 = OpenStackHeatStack(
+ self.os_creds, stack_settings,
+ [self.image_creator.image_settings])
+ created_stack = self.stack_creator.create(block=True)
+ self.assertIsNotNone(created_stack)
+
+ derived_stack = create_stack.generate_creator(
+ self.os_creds, created_stack,
+ [self.image_creator.image_settings])
+
+ self.vm_inst_creators = derived_stack.get_vm_inst_creators(
+ heat_keypair_option='private_key')
+ self.assertIsNotNone(self.vm_inst_creators)
+ self.assertEqual(2, len(self.vm_inst_creators))
+
+ for vm_inst_creator in self.vm_inst_creators:
+ if vm_inst_creator.get_vm_inst().name == self.vm_inst1_name:
+ self.assertTrue(
+ create_instance_tests.validate_ssh_client(vm_inst_creator))
+ else:
+ vm_settings = vm_inst_creator.instance_settings
+ self.assertEqual(0, len(vm_settings.floating_ip_settings))
+
class CreateStackNestedResourceTests(OSIntegrationTestCase):
"""
@@ -512,19 +560,125 @@ class CreateStackNestedResourceTests(OSIntegrationTestCase):
"""
def setUp(self):
+ self.user_roles = ['heat_stack_owner']
super(self.__class__, self).__start__()
self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
- self.heat_creds = self.admin_os_creds
- self.heat_creds.project_name = self.admin_os_creds.project_name
+ self.heat_cli = heat_utils.heat_client(self.os_creds, self.os_session)
+ self.stack_creator = None
+
+ self.image_creator = OpenStackImage(
+ self.os_creds, openstack_tests.cirros_image_settings(
+ name="{}-{}".format(self.guid, 'image'),
+ image_metadata=self.image_metadata))
+ self.image_creator.create()
+
+ flavor_config = openstack_tests.get_flavor_config(
+ name="{}-{}".format(self.guid, 'flavor-name'), ram=256, disk=10,
+ vcpus=1, metadata=self.flavor_metadata)
+ self.flavor_creator = OpenStackFlavor(
+ self.admin_os_creds, flavor_config)
+ self.flavor_creator.create()
+
+ env_values = {
+ 'network_name': self.guid + '-network',
+ 'public_network': self.ext_net_name,
+ 'agent_image': self.image_creator.image_settings.name,
+ 'agent_flavor': self.flavor_creator.flavor_settings.name,
+ 'key_name': self.guid + '-key',
+ }
+
+ heat_tmplt_path = pkg_resources.resource_filename(
+ 'snaps.openstack.tests.heat', 'agent-group.yaml')
+ heat_resource_path = pkg_resources.resource_filename(
+ 'snaps.openstack.tests.heat', 'agent.yaml')
+
+ stack_settings = StackConfig(
+ name="{}-{}".format(
+ self.__class__.__name__, str(self.guid) + '-stack'),
+ template_path=heat_tmplt_path,
+ resource_files=[heat_resource_path],
+ env_values=env_values)
+
+ self.stack_creator = OpenStackHeatStack(
+ self.os_creds, stack_settings,
+ [self.image_creator.image_settings])
+
+ self.vm_inst_creators = list()
+
+ def tearDown(self):
+ """
+ Cleans the stack and downloaded stack file
+ """
+ if self.stack_creator:
+ try:
+ self.stack_creator.clean()
+ except:
+ pass
+
+ if self.image_creator:
+ try:
+ self.image_creator.clean()
+ except:
+ pass
- self.heat_cli = heat_utils.heat_client(self.heat_creds)
+ if self.flavor_creator:
+ try:
+ self.flavor_creator.clean()
+ except:
+ pass
+
+ for vm_inst_creator in self.vm_inst_creators:
+ try:
+ keypair_settings = vm_inst_creator.keypair_settings
+ if keypair_settings and keypair_settings.private_filepath:
+ expanded_path = os.path.expanduser(
+ keypair_settings.private_filepath)
+ os.chmod(expanded_path, 0o755)
+ os.remove(expanded_path)
+ except:
+ pass
+
+ super(self.__class__, self).__clean__()
+
+ def test_nested(self):
+ """
+ Tests the creation of an OpenStack stack from Heat template file and
+ the retrieval of two VM instance creators and attempt to connect via
+ SSH to the first one with a floating IP.
+ """
+ created_stack = self.stack_creator.create(block=True)
+ self.assertIsNotNone(created_stack)
+
+ self.vm_inst_creators = self.stack_creator.get_vm_inst_creators(
+ heat_keypair_option='private_key')
+ self.assertIsNotNone(self.vm_inst_creators)
+ self.assertEqual(1, len(self.vm_inst_creators))
+
+ for vm_inst_creator in self.vm_inst_creators:
+ self.assertTrue(
+ create_instance_tests.validate_ssh_client(vm_inst_creator))
+
+
+class CreateStackUpdateTests(OSIntegrationTestCase):
+ """
+ Tests to ensure that stack update commands work
+ """
+
+ def setUp(self):
+ self.user_roles = ['heat_stack_owner']
+
+ super(self.__class__, self).__start__()
+
+ self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
+
+ self.heat_cli = heat_utils.heat_client(self.os_creds, self.os_session)
self.stack_creator = None
self.image_creator = OpenStackImage(
- self.heat_creds, openstack_tests.cirros_image_settings(
+ self.os_creds, openstack_tests.cirros_image_settings(
name=self.guid + '-image',
image_metadata=self.image_metadata))
self.image_creator.create()
@@ -536,9 +690,11 @@ class CreateStackNestedResourceTests(OSIntegrationTestCase):
self.flavor_creator.create()
env_values = {
+ 'network_name': self.guid + '-network',
'public_network': self.ext_net_name,
'agent_image': self.image_creator.image_settings.name,
'agent_flavor': self.flavor_creator.flavor_settings.name,
+ 'key_name': self.guid + '-key',
}
heat_tmplt_path = pkg_resources.resource_filename(
@@ -553,7 +709,7 @@ class CreateStackNestedResourceTests(OSIntegrationTestCase):
env_values=env_values)
self.stack_creator = OpenStackHeatStack(
- self.heat_creds, stack_settings,
+ self.os_creds, stack_settings,
[self.image_creator.image_settings])
self.vm_inst_creators = list()
@@ -593,13 +749,14 @@ class CreateStackNestedResourceTests(OSIntegrationTestCase):
super(self.__class__, self).__clean__()
- def test_nested(self):
+ def test_update(self):
"""
- Tests the creation of an OpenStack stack from Heat template file and
+ Tests the update of an OpenStack stack from Heat template file
+ by changing the number of VM instances from 1 to 2, and
the retrieval of two VM instance creators and attempt to connect via
SSH to the first one with a floating IP.
"""
- created_stack = self.stack_creator.create()
+ created_stack = self.stack_creator.create(block=True)
self.assertIsNotNone(created_stack)
self.vm_inst_creators = self.stack_creator.get_vm_inst_creators(
@@ -611,6 +768,28 @@ class CreateStackNestedResourceTests(OSIntegrationTestCase):
self.assertTrue(
create_instance_tests.validate_ssh_client(vm_inst_creator))
+ env_values = {
+ 'network_name': self.guid + '-network',
+ 'public_network': self.ext_net_name,
+ 'agent_count': 2,
+ 'agent_image': self.image_creator.image_settings.name,
+ 'agent_flavor': self.flavor_creator.flavor_settings.name,
+ 'key_name': self.guid + '-key',
+ }
+
+ updated_stack = self.stack_creator.update(env_values, block=True)
+ self.assertIsNotNone(updated_stack)
+ self.assertEqual(STATUS_UPDATE_COMPLETE, updated_stack.status)
+
+ self.vm_inst_creators = self.stack_creator.get_vm_inst_creators(
+ heat_keypair_option='private_key')
+ self.assertIsNotNone(self.vm_inst_creators)
+ self.assertEqual(2, len(self.vm_inst_creators))
+
+ for vm_inst_creator in self.vm_inst_creators:
+ self.assertTrue(
+ create_instance_tests.validate_ssh_client(vm_inst_creator))
+
class CreateStackRouterTests(OSIntegrationTestCase):
"""
@@ -623,15 +802,15 @@ class CreateStackRouterTests(OSIntegrationTestCase):
Instantiates the CreateStack object that is responsible for downloading
and creating an OS stack file within OpenStack
"""
+ self.user_roles = ['heat_stack_owner']
+
super(self.__class__, self).__start__()
self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
- self.heat_creds = self.admin_os_creds
- self.heat_creds.project_name = self.admin_os_creds.project_name
-
- self.heat_cli = heat_utils.heat_client(self.heat_creds)
- self.neutron = neutron_utils.neutron_client(self.os_creds)
+ self.heat_cli = heat_utils.heat_client(self.os_creds, self.os_session)
+ self.neutron = neutron_utils.neutron_client(
+ self.os_creds, self.os_session)
self.stack_creator = None
self.net_name = self.guid + '-net'
@@ -652,8 +831,8 @@ class CreateStackRouterTests(OSIntegrationTestCase):
template_path=self.heat_tmplt_path,
env_values=self.env_values)
self.stack_creator = OpenStackHeatStack(
- self.heat_creds, stack_settings)
- self.created_stack = self.stack_creator.create()
+ self.os_creds, stack_settings)
+ self.created_stack = self.stack_creator.create(block=True)
self.assertIsNotNone(self.created_stack)
def tearDown(self):
@@ -682,7 +861,7 @@ class CreateStackRouterTests(OSIntegrationTestCase):
router = creator.get_router()
ext_net = neutron_utils.get_network(
- self.neutron, network_name=self.ext_net_name)
+ self.neutron, self.keystone, network_name=self.ext_net_name)
self.assertEqual(ext_net.id, router.external_network_id)
@@ -694,14 +873,13 @@ class CreateStackVolumeTests(OSIntegrationTestCase):
def setUp(self):
+ self.user_roles = ['heat_stack_owner', 'admin']
+
super(self.__class__, self).__start__()
self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
- self.heat_creds = self.admin_os_creds
- self.heat_creds.project_name = self.admin_os_creds.project_name
-
- self.heat_cli = heat_utils.heat_client(self.heat_creds)
+ self.heat_cli = heat_utils.heat_client(self.os_creds, self.os_session)
self.stack_creator = None
self.volume_name = self.guid + '-volume'
@@ -719,8 +897,8 @@ class CreateStackVolumeTests(OSIntegrationTestCase):
template_path=self.heat_tmplt_path,
env_values=self.env_values)
self.stack_creator = OpenStackHeatStack(
- self.heat_creds, stack_settings)
- self.created_stack = self.stack_creator.create()
+ self.os_creds, stack_settings)
+ self.created_stack = self.stack_creator.create(block=True)
self.assertIsNotNone(self.created_stack)
def tearDown(self):
@@ -789,14 +967,13 @@ class CreateStackFlavorTests(OSIntegrationTestCase):
def setUp(self):
+ self.user_roles = ['heat_stack_owner', 'admin']
+
super(self.__class__, self).__start__()
self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
- self.heat_creds = self.admin_os_creds
- self.heat_creds.project_name = self.admin_os_creds.project_name
-
- self.heat_cli = heat_utils.heat_client(self.heat_creds)
+ self.heat_cli = heat_utils.heat_client(self.os_creds, self.os_session)
self.stack_creator = None
self.heat_tmplt_path = pkg_resources.resource_filename(
@@ -806,8 +983,8 @@ class CreateStackFlavorTests(OSIntegrationTestCase):
name=self.guid + '-stack',
template_path=self.heat_tmplt_path)
self.stack_creator = OpenStackHeatStack(
- self.heat_creds, stack_settings)
- self.created_stack = self.stack_creator.create()
+ self.os_creds, stack_settings)
+ self.created_stack = self.stack_creator.create(block=True)
self.assertIsNotNone(self.created_stack)
def tearDown(self):
@@ -849,15 +1026,14 @@ class CreateStackKeypairTests(OSIntegrationTestCase):
def setUp(self):
+ self.user_roles = ['heat_stack_owner']
+
super(self.__class__, self).__start__()
self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
- self.heat_creds = self.admin_os_creds
- self.heat_creds.project_name = self.admin_os_creds.project_name
-
- self.heat_cli = heat_utils.heat_client(self.heat_creds)
- self.nova = nova_utils.nova_client(self.heat_creds)
+ self.heat_cli = heat_utils.heat_client(self.os_creds, self.os_session)
+ self.nova = nova_utils.nova_client(self.os_creds, self.os_session)
self.stack_creator = None
self.keypair_name = self.guid + '-kp'
@@ -873,8 +1049,8 @@ class CreateStackKeypairTests(OSIntegrationTestCase):
template_path=self.heat_tmplt_path,
env_values=self.env_values)
self.stack_creator = OpenStackHeatStack(
- self.heat_creds, stack_settings)
- self.created_stack = self.stack_creator.create()
+ self.os_creds, stack_settings)
+ self.created_stack = self.stack_creator.create(block=True)
self.assertIsNotNone(self.created_stack)
self.keypair_creators = list()
@@ -934,15 +1110,14 @@ class CreateStackSecurityGroupTests(OSIntegrationTestCase):
Instantiates the CreateStack object that is responsible for downloading
and creating an OS stack file within OpenStack
"""
+ self.user_roles = ['heat_stack_owner']
+
super(self.__class__, self).__start__()
self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
- self.heat_creds = self.admin_os_creds
- self.heat_creds.project_name = self.admin_os_creds.project_name
-
- self.heat_cli = heat_utils.heat_client(self.heat_creds)
- self.nova = nova_utils.nova_client(self.heat_creds)
+ self.heat_cli = heat_utils.heat_client(self.os_creds, self.os_session)
+ self.nova = nova_utils.nova_client(self.os_creds, self.os_session)
self.stack_creator = None
self.security_group_name = self.guid + '-sec-grp'
@@ -958,8 +1133,8 @@ class CreateStackSecurityGroupTests(OSIntegrationTestCase):
template_path=self.heat_tmplt_path,
env_values=self.env_values)
self.stack_creator = OpenStackHeatStack(
- self.heat_creds, stack_settings)
- self.created_stack = self.stack_creator.create()
+ self.os_creds, stack_settings)
+ self.created_stack = self.stack_creator.create(block=True)
self.assertIsNotNone(self.created_stack)
def tearDown(self):
@@ -1024,12 +1199,10 @@ class CreateStackNegativeTests(OSIntegrationTestCase):
"""
def setUp(self):
+ self.user_roles = ['heat_stack_owner']
super(self.__class__, self).__start__()
- self.heat_creds = self.admin_os_creds
- self.heat_creds.project_name = self.admin_os_creds.project_name
-
self.stack_name = self.__class__.__name__ + '-' + str(uuid.uuid4())
self.stack_creator = None
self.heat_tmplt_path = pkg_resources.resource_filename(
@@ -1038,6 +1211,7 @@ class CreateStackNegativeTests(OSIntegrationTestCase):
def tearDown(self):
if self.stack_creator:
self.stack_creator.clean()
+
super(self.__class__, self).__clean__()
def test_missing_dependencies(self):
@@ -1047,9 +1221,9 @@ class CreateStackNegativeTests(OSIntegrationTestCase):
stack_settings = StackConfig(name=self.stack_name,
template_path=self.heat_tmplt_path)
self.stack_creator = OpenStackHeatStack(
- self.heat_creds, stack_settings)
+ self.os_creds, stack_settings)
with self.assertRaises(HTTPBadRequest):
- self.stack_creator.create()
+ self.stack_creator.create(block=True)
def test_bad_stack_file(self):
"""
@@ -1058,9 +1232,9 @@ class CreateStackNegativeTests(OSIntegrationTestCase):
stack_settings = StackConfig(
name=self.stack_name, template_path='foo')
self.stack_creator = OpenStackHeatStack(
- self.heat_creds, stack_settings)
+ self.os_creds, stack_settings)
with self.assertRaises(IOError):
- self.stack_creator.create()
+ self.stack_creator.create(block=True)
class CreateStackFailureTests(OSIntegrationTestCase):
@@ -1071,21 +1245,19 @@ class CreateStackFailureTests(OSIntegrationTestCase):
"""
def setUp(self):
+ self.user_roles = ['heat_stack_owner']
super(self.__class__, self).__start__()
self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
- self.heat_creds = self.admin_os_creds
- self.heat_creds.project_name = self.admin_os_creds.project_name
-
- self.heat_cli = heat_utils.heat_client(self.heat_creds)
+ self.heat_cli = heat_utils.heat_client(self.os_creds, self.os_session)
self.stack_creator = None
self.tmp_file = file_utils.save_string_to_file(
' ', str(uuid.uuid4()) + '-bad-image')
self.image_creator = OpenStackImage(
- self.heat_creds, ImageConfig(
+ self.os_creds, ImageConfig(
name=self.guid + 'image', image_file=self.tmp_file.name,
image_user='foo', img_format='qcow2'))
self.image_creator.create()
@@ -1155,11 +1327,11 @@ class CreateStackFailureTests(OSIntegrationTestCase):
template_path=self.heat_tmplt_path,
env_values=self.env_values)
self.stack_creator = OpenStackHeatStack(
- self.heat_creds, stack_settings)
+ self.os_creds, stack_settings)
with self.assertRaises(StackError):
try:
- self.stack_creator.create()
+ self.stack_creator.create(block=True)
except StackError:
resources = heat_utils.get_resources(
self.heat_cli, self.stack_creator.get_stack().id)
diff --git a/snaps/openstack/tests/create_user_tests.py b/snaps/openstack/tests/create_user_tests.py
index d3eb4a6..c15a71f 100644
--- a/snaps/openstack/tests/create_user_tests.py
+++ b/snaps/openstack/tests/create_user_tests.py
@@ -106,10 +106,11 @@ class CreateUserSuccessTests(OSComponentTestCase):
self.user_settings = UserConfig(
name=guid + '-name',
password=guid + '-password',
- roles={'admin': self.os_creds.project_name},
+ roles={'admin': self.os_creds.project_name,
+ 'Admin': self.os_creds.project_name},
domain_name=self.os_creds.user_domain_name)
- self.keystone = keystone_utils.keystone_client(self.os_creds)
+ self.keystone = keystone_utils.keystone_client(self.os_creds, self.os_session)
# Initialize for cleanup
self.user_creator = None
@@ -121,6 +122,8 @@ class CreateUserSuccessTests(OSComponentTestCase):
if self.user_creator:
self.user_creator.clean()
+ super(self.__class__, self).__clean__()
+
def test_create_user(self):
"""
Tests the creation of an OpenStack user.
@@ -181,6 +184,8 @@ class CreateUserSuccessTests(OSComponentTestCase):
self.assertEqual(created_user, retrieved_user)
role = keystone_utils.get_role_by_name(self.keystone, 'admin')
+ if not role:
+ role = keystone_utils.get_role_by_name(self.keystone, 'Admin')
self.assertIsNotNone(role)
os_proj = keystone_utils.get_project(
diff --git a/snaps/openstack/tests/create_volume_tests.py b/snaps/openstack/tests/create_volume_tests.py
index ca13860..3c9a346 100644
--- a/snaps/openstack/tests/create_volume_tests.py
+++ b/snaps/openstack/tests/create_volume_tests.py
@@ -32,7 +32,7 @@ import uuid
from snaps.openstack.create_volume import (
VolumeSettings, OpenStackVolume)
from snaps.openstack.tests.os_source_file_test import OSIntegrationTestCase
-from snaps.openstack.utils import cinder_utils
+from snaps.openstack.utils import cinder_utils, keystone_utils
__author__ = 'spisarski'
@@ -129,7 +129,10 @@ class CreateSimpleVolumeSuccessTests(OSIntegrationTestCase):
self.volume_settings = VolumeConfig(
name=self.__class__.__name__ + '-' + str(guid))
- self.cinder = cinder_utils.cinder_client(self.os_creds)
+ self.cinder = cinder_utils.cinder_client(
+ self.os_creds, self.os_session)
+ self.keystone = keystone_utils.keystone_client(
+ self.os_creds, self.os_session)
self.volume_creator = None
def tearDown(self):
@@ -152,7 +155,8 @@ class CreateSimpleVolumeSuccessTests(OSIntegrationTestCase):
self.assertIsNotNone(created_volume)
retrieved_volume = cinder_utils.get_volume(
- self.cinder, volume_settings=self.volume_settings)
+ self.cinder, self.keystone, volume_settings=self.volume_settings,
+ project_name=self.os_creds.project_name)
self.assertIsNotNone(retrieved_volume)
self.assertEqual(created_volume.id, retrieved_volume.id)
@@ -170,7 +174,8 @@ class CreateSimpleVolumeSuccessTests(OSIntegrationTestCase):
self.assertIsNotNone(created_volume)
retrieved_volume = cinder_utils.get_volume(
- self.cinder, volume_settings=self.volume_settings)
+ self.cinder, self.keystone, volume_settings=self.volume_settings,
+ project_name=self.os_creds.project_name)
self.assertIsNotNone(retrieved_volume)
self.assertEqual(created_volume, retrieved_volume)
@@ -178,7 +183,8 @@ class CreateSimpleVolumeSuccessTests(OSIntegrationTestCase):
self.volume_creator.clean()
self.assertIsNone(cinder_utils.get_volume(
- self.cinder, volume_settings=self.volume_settings))
+ self.cinder, self.keystone, volume_settings=self.volume_settings,
+ project_name=self.os_creds.project_name))
# Must not throw an exception when attempting to cleanup non-existent
# volume
@@ -195,7 +201,8 @@ class CreateSimpleVolumeSuccessTests(OSIntegrationTestCase):
volume1 = self.volume_creator.create(block=True)
retrieved_volume = cinder_utils.get_volume(
- self.cinder, volume_settings=self.volume_settings)
+ self.cinder, self.keystone, volume_settings=self.volume_settings,
+ project_name=self.os_creds.project_name)
self.assertEqual(volume1, retrieved_volume)
# Should be retrieving the instance data
@@ -218,7 +225,8 @@ class CreateSimpleVolumeFailureTests(OSIntegrationTestCase):
super(self.__class__, self).__start__()
self.guid = uuid.uuid4()
- self.cinder = cinder_utils.cinder_client(self.os_creds)
+ self.cinder = cinder_utils.cinder_client(
+ self.os_creds, self.os_session)
self.volume_creator = None
def tearDown(self):
@@ -274,21 +282,6 @@ class CreateSimpleVolumeFailureTests(OSIntegrationTestCase):
with self.assertRaises(BadRequest):
self.volume_creator.create(block=True)
- def test_create_volume_bad_zone(self):
- """
- Tests the creation of an OpenStack volume with an availability zone
- that does not exist to ensure it raises a BadRequest exception.
- """
- volume_settings = VolumeConfig(
- name=self.__class__.__name__ + '-' + str(self.guid),
- availability_zone='foo')
-
- # Create Volume
- self.volume_creator = OpenStackVolume(self.os_creds, volume_settings)
-
- with self.assertRaises(BadRequest):
- self.volume_creator.create(block=True)
-
class CreateVolumeWithTypeTests(OSIntegrationTestCase):
"""
@@ -304,7 +297,7 @@ class CreateVolumeWithTypeTests(OSIntegrationTestCase):
self.volume_type_name = guid + '-vol-type'
self.volume_type_creator = OpenStackVolumeType(
- self.os_creds, VolumeTypeConfig(name=self.volume_type_name))
+ self.admin_os_creds, VolumeTypeConfig(name=self.volume_type_name))
self.volume_type_creator.create()
self.volume_creator = None
@@ -332,8 +325,7 @@ class CreateVolumeWithTypeTests(OSIntegrationTestCase):
Expect a NotFound to be raised when the volume type does not exist
"""
self.volume_creator = OpenStackVolume(
- self.os_creds,
- VolumeConfig(
+ self.admin_os_creds, VolumeConfig(
name=self.volume_name, type_name=self.volume_type_name))
created_volume = self.volume_creator.create(block=True)
@@ -349,7 +341,8 @@ class CreateVolumeWithImageTests(OSIntegrationTestCase):
def setUp(self):
super(self.__class__, self).__start__()
- self.cinder = cinder_utils.cinder_client(self.os_creds)
+ self.cinder = cinder_utils.cinder_client(
+ self.os_creds, self.os_session)
guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
self.volume_name = guid + '-vol'
@@ -408,3 +401,87 @@ class CreateVolumeWithImageTests(OSIntegrationTestCase):
self.cinder, created_volume.id)
self.assertEqual(created_volume, retrieved_volume)
+
+
+class CreateVolMultipleCredsTests(OSIntegrationTestCase):
+ """
+ Test for the OpenStackVolume class and how it interacts with volumes
+ created with differenct credentials and to other projects with the same
+ name
+ """
+ def setUp(self):
+ super(self.__class__, self).__start__()
+
+ self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
+ self.volume_creators = list()
+
+ def tearDown(self):
+ for volume_creator in self.volume_creators:
+ volume_creator.clean()
+
+ super(self.__class__, self).__clean__()
+
+ # TODO - activate after cinder API bug has been fixed
+ # see https://bugs.launchpad.net/cinder/+bug/1641982 as to why this test
+ # is not activated
+ # def test_create_by_admin_to_other_proj(self):
+ # """
+ # Creates a volume as admin to the project of os_creds then instantiates
+ # a creator object with the os_creds project to ensure it initializes
+ # without creation
+ # """
+ # self.volume_creators.append(OpenStackVolume(
+ # self.admin_os_creds, VolumeConfig(
+ # name=self.guid + '-vol',
+ # project_name=self.os_creds.project_name)))
+ # admin_vol = self.volume_creators[0].create(block=True)
+ #
+ # self.volume_creators.append(OpenStackVolume(
+ # self.os_creds, VolumeConfig(name=self.guid + '-vol')))
+ # proj_vol = self.volume_creators[1].create(block=True)
+ #
+ # self.assertEqual(admin_vol, proj_vol)
+
+ def test_create_two_vol_same_name_diff_proj(self):
+ """
+ Creates a volume as admin to the project of os_creds then instantiates
+ a creator object with the os_creds project to ensure it initializes
+ without creation
+ """
+ vol_name = self.guid + '-vol'
+ self.volume_creators.append(OpenStackVolume(
+ self.admin_os_creds, VolumeConfig(name=vol_name)))
+ admin_vol = self.volume_creators[0].create(block=True)
+ self.assertIsNotNone(admin_vol)
+
+ admin_key = keystone_utils.keystone_client(
+ self.admin_os_creds, self.admin_os_session)
+ admin_proj = keystone_utils.get_project(
+ admin_key, project_name=self.admin_os_creds.project_name)
+ self.assertEqual(admin_vol.project_id, admin_proj.id)
+
+ admin_cinder = cinder_utils.cinder_client(
+ self.admin_os_creds, self.admin_os_session)
+ admin_vol_get = cinder_utils.get_volume(
+ admin_cinder, admin_key, volume_name=vol_name,
+ project_name=self.admin_os_creds.project_name)
+ self.assertIsNotNone(admin_vol_get)
+ self.assertEqual(admin_vol, admin_vol_get)
+
+ self.volume_creators.append(OpenStackVolume(
+ self.os_creds, VolumeConfig(name=vol_name)))
+ proj_vol = self.volume_creators[1].create(block=True)
+ self.assertIsNotNone(proj_vol)
+
+ self.assertNotEqual(admin_vol, proj_vol)
+
+ proj_key = keystone_utils.keystone_client(
+ self.os_creds, self.os_session)
+ proj_cinder = cinder_utils.cinder_client(
+ self.os_creds, self.os_session)
+ proj_vol_get = cinder_utils.get_volume(
+ proj_cinder, proj_key, volume_name=vol_name,
+ project_name=self.os_creds.project_name)
+
+ self.assertIsNotNone(proj_vol_get)
+ self.assertEqual(proj_vol, proj_vol_get)
diff --git a/snaps/openstack/tests/create_volume_type_tests.py b/snaps/openstack/tests/create_volume_type_tests.py
index 70c40cc..b797274 100644
--- a/snaps/openstack/tests/create_volume_type_tests.py
+++ b/snaps/openstack/tests/create_volume_type_tests.py
@@ -29,7 +29,7 @@ import uuid
from snaps.openstack import create_volume_type
from snaps.openstack.create_volume_type import (
- VolumeTypeSettings, VolumeTypeEncryptionSettings)
+ VolumeTypeSettings, VolumeTypeEncryptionSettings, OpenStackVolumeType)
from snaps.openstack.tests.os_source_file_test import OSIntegrationTestCase
from snaps.openstack.utils import cinder_utils
@@ -127,8 +127,10 @@ class CreateSimpleVolumeTypeSuccessTests(OSIntegrationTestCase):
self.volume_type_settings = VolumeTypeConfig(
name=self.__class__.__name__ + '-' + str(guid))
- self.cinder = cinder_utils.cinder_client(self.os_creds)
- self.volume_type_creator = None
+ self.cinder = cinder_utils.cinder_client(
+ self.admin_os_creds, self.admin_os_session)
+ self.volume_type_creator = OpenStackVolumeType(
+ self.admin_os_creds, self.volume_type_settings)
def tearDown(self):
"""
@@ -144,8 +146,6 @@ class CreateSimpleVolumeTypeSuccessTests(OSIntegrationTestCase):
Tests the creation of an OpenStack volume.
"""
# Create VolumeType
- self.volume_type_creator = create_volume_type.OpenStackVolumeType(
- self.os_creds, self.volume_type_settings)
created_volume_type = self.volume_type_creator.create()
self.assertIsNotNone(created_volume_type)
self.assertEqual(self.volume_type_settings.name,
@@ -166,8 +166,6 @@ class CreateSimpleVolumeTypeSuccessTests(OSIntegrationTestCase):
clean() does not raise an Exception.
"""
# Create VolumeType
- self.volume_type_creator = create_volume_type.OpenStackVolumeType(
- self.os_creds, self.volume_type_settings)
created_volume_type = self.volume_type_creator.create()
self.assertIsNotNone(created_volume_type)
@@ -192,8 +190,6 @@ class CreateSimpleVolumeTypeSuccessTests(OSIntegrationTestCase):
Tests the creation of an OpenStack volume_type when one already exists.
"""
# Create VolumeType
- self.volume_type_creator = create_volume_type.OpenStackVolumeType(
- self.os_creds, self.volume_type_settings)
volume_type1 = self.volume_type_creator.create()
retrieved_volume_type = cinder_utils.get_volume_type(
@@ -202,7 +198,7 @@ class CreateSimpleVolumeTypeSuccessTests(OSIntegrationTestCase):
# Should be retrieving the instance data
os_volume_type_2 = create_volume_type.OpenStackVolumeType(
- self.os_creds, self.volume_type_settings)
+ self.admin_os_creds, self.volume_type_settings)
volume_type2 = os_volume_type_2.create()
self.assertEqual(volume_type2, volume_type2)
@@ -216,7 +212,8 @@ class CreateVolumeTypeComplexTests(OSIntegrationTestCase):
def setUp(self):
super(self.__class__, self).__start__()
- self.cinder = cinder_utils.cinder_client(self.os_creds)
+ self.cinder = cinder_utils.cinder_client(
+ self.admin_os_creds, self.admin_os_session)
guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
@@ -225,7 +222,7 @@ class CreateVolumeTypeComplexTests(OSIntegrationTestCase):
qos_settings = QoSConfig(
name=guid + '-qos-spec', consumer=Consumer.both)
- self.qos_creator = OpenStackQoS(self.os_creds, qos_settings)
+ self.qos_creator = OpenStackQoS(self.admin_os_creds, qos_settings)
self.qos_creator.create()
def tearDown(self):
@@ -241,8 +238,8 @@ class CreateVolumeTypeComplexTests(OSIntegrationTestCase):
"""
Creates a Volume Type object with an associated QoS Spec
"""
- self.volume_type_creator = create_volume_type.OpenStackVolumeType(
- self.os_creds,
+ self.volume_type_creator = OpenStackVolumeType(
+ self.admin_os_creds,
VolumeTypeConfig(
name=self.volume_type_name,
qos_spec_name=self.qos_creator.qos_settings.name))
@@ -270,8 +267,8 @@ class CreateVolumeTypeComplexTests(OSIntegrationTestCase):
encryption_settings = VolumeTypeEncryptionConfig(
name='foo', provider_class='bar',
control_location=ControlLocation.back_end)
- self.volume_type_creator = create_volume_type.OpenStackVolumeType(
- self.os_creds,
+ self.volume_type_creator = OpenStackVolumeType(
+ self.admin_os_creds,
VolumeTypeConfig(
name=self.volume_type_name,
encryption=encryption_settings))
@@ -299,8 +296,8 @@ class CreateVolumeTypeComplexTests(OSIntegrationTestCase):
encryption_settings = VolumeTypeEncryptionConfig(
name='foo', provider_class='bar',
control_location=ControlLocation.back_end)
- self.volume_type_creator = create_volume_type.OpenStackVolumeType(
- self.os_creds,
+ self.volume_type_creator = OpenStackVolumeType(
+ self.admin_os_creds,
VolumeTypeConfig(
name=self.volume_type_name,
encryption=encryption_settings,
diff --git a/snaps/openstack/tests/heat/agent-group.yaml b/snaps/openstack/tests/heat/agent-group.yaml
index 540ea93..494da0a 100644
--- a/snaps/openstack/tests/heat/agent-group.yaml
+++ b/snaps/openstack/tests/heat/agent-group.yaml
@@ -41,6 +41,10 @@ parameters:
availability_zone:
type: string
default: nova
+ network_name:
+ type: string
+ key_name:
+ type: string
resources:
slaves:
@@ -66,7 +70,7 @@ resources:
network:
type: OS::Neutron::Net
properties:
- name: network
+ name: { get_param: network_name }
subnet:
type: OS::Neutron::Subnet
@@ -91,7 +95,7 @@ resources:
type: OS::Nova::KeyPair
properties:
save_private_key: true
- name: agent_keypair
+ name: { get_param: key_name }
open_security_group:
type: OS::Neutron::SecurityGroup
diff --git a/snaps/openstack/tests/heat/agent.yaml b/snaps/openstack/tests/heat/agent.yaml
index 014b14f..8ac0660 100644
--- a/snaps/openstack/tests/heat/agent.yaml
+++ b/snaps/openstack/tests/heat/agent.yaml
@@ -25,7 +25,6 @@ parameters:
default: 'Ubuntu 16.04'
key_name:
type: string
- default: test_key
username:
type: string
default: test_user
diff --git a/snaps/openstack/tests/heat/floating_ip_heat_template.yaml b/snaps/openstack/tests/heat/floating_ip_heat_template.yaml
index a191acc..e64c7fc 100644
--- a/snaps/openstack/tests/heat/floating_ip_heat_template.yaml
+++ b/snaps/openstack/tests/heat/floating_ip_heat_template.yaml
@@ -41,6 +41,10 @@ parameters:
label: Instance Flavor for second VM
description: Flavor name for the second instance
default: m1.med
+ flavor_extra_specs:
+ type: json
+ description: Instance Flavor extra specs
+ default: {}
net_name:
type: string
label: Test network name
@@ -88,12 +92,14 @@ resources:
ram: 1024
vcpus: 2
disk: 2
+ extra_specs: { get_param: flavor_extra_specs }
flavor2:
type: OS::Nova::Flavor
properties:
ram: 1024
vcpus: 2
disk: 2
+ extra_specs: { get_param: flavor_extra_specs }
network:
type: OS::Neutron::Net
@@ -140,10 +146,10 @@ resources:
floating_network: { get_param: external_net_name }
floating_ip_association:
- type: OS::Nova::FloatingIPAssociation
+ type: OS::Neutron::FloatingIPAssociation
properties:
- floating_ip: { get_resource: floating_ip }
- server_id: {get_resource: vm1}
+ floatingip_id: { get_resource: floating_ip }
+ port_id: {get_resource: port1}
keypair:
type: OS::Nova::KeyPair
@@ -151,21 +157,28 @@ resources:
name: { get_param: keypair_name }
save_private_key: True
+ port1:
+ type: OS::Neutron::Port
+ properties:
+ network: { get_resource: network }
+ security_groups: [{ get_resource: server_security_group }]
+ fixed_ips:
+ - subnet_id: { get_resource: subnet }
+
vm1:
type: OS::Nova::Server
- depends_on: [subnet, keypair, flavor1]
+ depends_on: [subnet, keypair, flavor1, port1]
properties:
name: { get_param: inst1_name }
image: { get_param: image1_name }
flavor: { get_resource: flavor1 }
key_name: {get_resource: keypair}
- security_groups: [{ get_resource: server_security_group }]
networks:
- - network: { get_resource: network }
+ - port: { get_resource: port1 }
vm2:
type: OS::Nova::Server
- depends_on: [subnet, flavor2]
+ depends_on: [subnet, keypair, flavor2]
properties:
name: { get_param: inst2_name }
image: { get_param: image2_name }
diff --git a/snaps/openstack/tests/openstack_tests.py b/snaps/openstack/tests/openstack_tests.py
index a3dec11..f3a1df7 100644
--- a/snaps/openstack/tests/openstack_tests.py
+++ b/snaps/openstack/tests/openstack_tests.py
@@ -15,8 +15,8 @@
import logging
import re
-import pkg_resources
from snaps import file_utils
+from snaps.config.flavor import FlavorConfig
from snaps.config.image import ImageConfig
from snaps.config.network import NetworkConfig, SubnetConfig
from snaps.config.router import RouterConfig
@@ -139,6 +139,10 @@ def get_credentials(os_env_file=None, proxy_settings_str=None,
if overrides and isinstance(overrides, dict):
creds_dict.update(overrides)
+ for key, value in creds_dict.items():
+ if value is not None and isinstance(value, str):
+ creds_dict[key] = value.replace('"', '').replace('\'', '')
+
os_creds = OSCreds(**creds_dict)
logger.info('OS Credentials = %s', os_creds.__str__)
return os_creds
@@ -309,22 +313,81 @@ def ubuntu_image_settings(name, url=None, image_metadata=None,
public=public)
-def get_priv_net_config(net_name, subnet_name, router_name=None,
- cidr='10.55.0.0/24', external_net=None,
- netconf_override=None):
- return OSNetworkConfig(net_name, subnet_name, cidr, router_name,
- external_gateway=external_net,
- netconf_override=netconf_override)
+def get_priv_net_config(project_name, net_name, mtu=None, subnet_name=None,
+ router_name=None, cidr='10.55.0.0/24',
+ external_net=None, netconf_override=None):
+ return OSNetworkConfig(
+ project_name, net_name, mtu, subnet_name, cidr, router_name,
+ external_gateway=external_net, netconf_override=netconf_override)
-def get_pub_net_config(net_name, subnet_name=None, router_name=None,
- cidr='10.55.1.0/24', external_net=None,
- netconf_override=None):
- return OSNetworkConfig(net_name, subnet_name, cidr, router_name,
- external_gateway=external_net,
+def get_pub_net_config(
+ project_name, net_name, mtu=None, subnet_name=None, router_name=None,
+ cidr='10.55.1.0/24', external_net=None, netconf_override=None):
+ return OSNetworkConfig(project_name, net_name, mtu, subnet_name, cidr,
+ router_name, external_gateway=external_net,
netconf_override=netconf_override)
+def get_flavor_config(name, ram, disk, vcpus, ephemeral=None, swap=None,
+ rxtx_factor=None, is_public=None, metadata=None):
+ """This method replaces the hard coded basic element (e.g. ram, vcpu, disk
+ etc) with those are included in the new freeform dict() of metadata
+ parameter.
+
+ :param name: the flavor name (required)
+ :param ram: memory in MB to allocate to VM (required)
+ :param disk: disk storage in GB (required)
+ :param vcpus: the number of CPUs to allocate to VM (required)
+ :param ephemeral: the size of the ephemeral disk in GB (default=0)
+ :param swap: the size of the 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: flag that denotes whether or not other projects
+ can access image (default=True)
+ :param metadata: - freeform dict() for special metadata (optional)
+ - freeform dict() for values of basic elements
+ (e.g. ram, vcpu, disk, etc) could be added.
+ As result the hard coded values of those elements will be
+ overwritten by the new ones (optional)
+ :return: The FlavorConfig replacing the hard coded basic element values
+ (e.g. ram, vcpu, disk etc) with those are included in the metadata
+ dict [optional]. The metadata parameter in the FlavorConfig
+ consist of the metadata data only.
+ """
+
+ metadata_excl = metadata
+ if metadata:
+ if 'ram' in metadata:
+ ram = metadata['ram']
+ del metadata_excl['ram']
+ if 'disk' in metadata:
+ disk = metadata['disk']
+ del metadata_excl['disk']
+ if 'vcpus' in metadata:
+ vcpus = metadata['vcpus']
+ del metadata_excl['vcpus']
+ if 'ephemeral' in metadata:
+ ephemeral = metadata['ephemeral']
+ del metadata_excl['ephemeral']
+ if 'swap' in metadata:
+ swap = metadata['swap']
+ del metadata_excl['swap']
+ if 'rxtx_factor' in metadata:
+ rxtx_factor = metadata['rxtx_factor']
+ del metadata_excl['rxtx_factor']
+ if 'is_public' in metadata:
+ is_public = metadata['is_public']
+ del metadata_excl['is_public']
+ if 'metadata' in metadata:
+ metadata_excl = metadata['metadata']
+
+ return FlavorConfig(
+ name=name, ram=ram, disk=disk, vcpus=vcpus, ephemeral=ephemeral,
+ swap=swap, rxtx_factor=rxtx_factor, is_public=is_public,
+ metadata=metadata_excl)
+
+
class OSNetworkConfig:
"""
Represents the settings required for the creation of a network in OpenStack
@@ -332,18 +395,17 @@ class OSNetworkConfig:
physical_network and segmentation_id
"""
- def __init__(self, net_name, subnet_name=None, subnet_cidr=None,
- router_name=None, external_gateway=None,
+ def __init__(self, project_name, net_name, mtu=None, subnet_name=None,
+ subnet_cidr=None, router_name=None, external_gateway=None,
netconf_override=None):
"""
- :param netconf_override: dict() containing the reconfigured network_type,
- physical_network and segmentation_id
+ :param netconf_override: dict() containing the reconfigured
+ network_type, physical_network and
+ segmentation_id
"""
-
- network_conf = None
if subnet_name and subnet_cidr:
network_conf = NetworkConfig(
- name=net_name, subnet_settings=[
+ name=net_name, mtu=mtu, subnet_settings=[
SubnetConfig(cidr=subnet_cidr, name=subnet_name)])
else:
network_conf = NetworkConfig(name=net_name)
@@ -359,7 +421,10 @@ class OSNetworkConfig:
if subnet_name:
self.router_settings = RouterConfig(
name=router_name, external_gateway=external_gateway,
- internal_subnets=[subnet_name])
+ internal_subnets=[{'subnet': {
+ 'project_name': project_name,
+ 'network_name': net_name,
+ 'subnet_name': subnet_name}}])
else:
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 7e910a4..8b0a7b4 100644
--- a/snaps/openstack/tests/os_source_file_test.py
+++ b/snaps/openstack/tests/os_source_file_test.py
@@ -31,7 +31,8 @@ dev_os_env_file = pkg_resources.resource_filename(
class OSComponentTestCase(unittest.TestCase):
def __init__(self, method_name='runTest', os_creds=None, ext_net_name=None,
- image_metadata=None, log_level=logging.DEBUG):
+ flavor_metadata=None, image_metadata=None,
+ log_level=logging.DEBUG):
"""
Super for test classes requiring a connection to OpenStack
:param method_name: default 'runTest'
@@ -39,6 +40,8 @@ class OSComponentTestCase(unittest.TestCase):
in the package snaps.openstack.tests.conf.os_env.yaml
:param ext_net_name: the name of the external network that is used for
creating routers for floating IPs
+ :param flavor_metadata: dict() to be sent directly into the Nova client
+ generally used for page sizes
:param image_metadata: ability to override images being used in the
tests (see examples/image-metadata)
:param log_level: the logging level of your test run (default DEBUG)
@@ -47,23 +50,36 @@ class OSComponentTestCase(unittest.TestCase):
logging.basicConfig(level=log_level)
+ self.ext_net_name = None
+ self.flavor_metadata = None
+
if os_creds:
self.os_creds = os_creds
else:
- self.os_creds = openstack_tests.get_credentials(
- dev_os_env_file=dev_os_env_file)
-
- self.ext_net_name = ext_net_name
-
- if not self.ext_net_name and file_utils.file_exists(dev_os_env_file):
- test_conf = file_utils.read_yaml(dev_os_env_file)
- self.ext_net_name = test_conf.get('ext_net')
+ if file_utils.file_exists(dev_os_env_file):
+ self.os_creds = openstack_tests.get_credentials(
+ dev_os_env_file=dev_os_env_file)
+ test_conf = file_utils.read_yaml(dev_os_env_file)
+ self.ext_net_name = test_conf.get('ext_net')
+ os_env_dict = file_utils.read_yaml(dev_os_env_file)
+ flavor_metadata = os_env_dict.get('flavor_metadata')
+ if flavor_metadata:
+ self.flavor_metadata = {'metadata': flavor_metadata}
+ else:
+ raise Exception('Unable to obtain OSCreds')
+
+ self.os_session = keystone_utils.keystone_session(self.os_creds)
self.image_metadata = image_metadata
+ if not self.ext_net_name:
+ self.ext_net_name = ext_net_name
+ if not self.flavor_metadata:
+ self.flavor_metadata = flavor_metadata
@staticmethod
def parameterize(testcase_klass, os_creds, ext_net_name,
- image_metadata=None, log_level=logging.DEBUG):
+ flavor_metadata=None, image_metadata=None,
+ log_level=logging.DEBUG):
""" Create a suite containing all tests taken from the given
subclass, passing them the parameter 'param'.
"""
@@ -71,10 +87,18 @@ class OSComponentTestCase(unittest.TestCase):
test_names = test_loader.getTestCaseNames(testcase_klass)
suite = unittest.TestSuite()
for name in test_names:
- suite.addTest(testcase_klass(name, os_creds, ext_net_name,
- image_metadata, log_level))
+ suite.addTest(testcase_klass(
+ name, os_creds, ext_net_name, flavor_metadata, image_metadata,
+ log_level))
return suite
+ def __clean__(self):
+ """
+ Cleans up keystone session.
+ """
+ if self.os_session:
+ keystone_utils.close_session(self.os_session)
+
class OSIntegrationTestCase(OSComponentTestCase):
@@ -104,16 +128,17 @@ class OSIntegrationTestCase(OSComponentTestCase):
"""
super(OSIntegrationTestCase, self).__init__(
method_name=method_name, os_creds=os_creds,
- ext_net_name=ext_net_name, image_metadata=image_metadata,
- log_level=log_level)
+ ext_net_name=ext_net_name, flavor_metadata=flavor_metadata,
+ image_metadata=image_metadata, log_level=log_level)
self.netconf_override = netconf_override
self.use_keystone = use_keystone
self.keystone = None
- self.flavor_metadata = flavor_metadata
+ self.user_roles = None
+ self.proj_users = None
@staticmethod
def parameterize(testcase_klass, os_creds, ext_net_name,
- use_keystone=False, flavor_metadata=None,
+ use_keystone=True, flavor_metadata=None,
image_metadata=None, netconf_override=None,
log_level=logging.DEBUG):
"""
@@ -143,10 +168,11 @@ class OSIntegrationTestCase(OSComponentTestCase):
self.project_creator = None
self.user_creator = None
self.admin_os_creds = self.os_creds
- self.role = None
+ self.admin_os_session = self.os_session
+ self.keystone = keystone_utils.keystone_client(
+ self.admin_os_creds, self.admin_os_session)
if self.use_keystone:
- self.keystone = keystone_utils.keystone_client(self.admin_os_creds)
guid = self.__class__.__name__ + '-' + str(uuid.uuid4())[:-19]
project_name = guid + '-proj'
self.project_creator = deploy_utils.create_project(
@@ -154,19 +180,31 @@ class OSIntegrationTestCase(OSComponentTestCase):
name=project_name,
domain=self.admin_os_creds.project_domain_name))
+ # Set by implementing class for setting the user's roles
+ roles = dict()
+ if self.user_roles and isinstance(self.user_roles, list):
+ for user_role in self.user_roles:
+ roles[user_role] = project_name
+
self.user_creator = deploy_utils.create_user(
self.admin_os_creds, UserConfig(
name=guid + '-user', password=guid,
- project_name=project_name, roles={
- 'admin': self.project_creator.project_settings.name},
+ project_name=project_name, roles=roles,
domain_name=self.admin_os_creds.user_domain_name))
self.os_creds = self.user_creator.get_os_creds(
self.project_creator.project_settings.name)
+ self.os_session = keystone_utils.keystone_session(self.os_creds)
# add user to project
self.project_creator.assoc_user(self.user_creator.get_user())
+ if self.proj_users and isinstance(self.proj_users, list):
+ for user_name in self.proj_users:
+ user = keystone_utils.get_user(self.keystone, user_name)
+ if user:
+ self.project_creator.assoc_user(user)
+
def __clean__(self):
"""
Cleans up test user and project.
@@ -174,11 +212,13 @@ class OSIntegrationTestCase(OSComponentTestCase):
called during setUp() else these objects will persist after the test is
run
"""
- if self.role:
- keystone_utils.delete_role(self.keystone, self.role)
-
if self.project_creator:
self.project_creator.clean()
if self.user_creator:
self.user_creator.clean()
+
+ if self.admin_os_session:
+ keystone_utils.close_session(self.admin_os_session)
+
+ super(OSIntegrationTestCase, self).__clean__()
diff --git a/snaps/openstack/utils/__init__.py b/snaps/openstack/utils/__init__.py
index 7f92908..5435f8f 100644
--- a/snaps/openstack/utils/__init__.py
+++ b/snaps/openstack/utils/__init__.py
@@ -12,4 +12,5 @@
# 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' \ No newline at end of file
+
+__author__ = 'spisarski'
diff --git a/snaps/openstack/utils/cinder_utils.py b/snaps/openstack/utils/cinder_utils.py
index c50a166..61abe22 100644
--- a/snaps/openstack/utils/cinder_utils.py
+++ b/snaps/openstack/utils/cinder_utils.py
@@ -33,37 +33,55 @@ Utilities for basic neutron API calls
"""
-def cinder_client(os_creds):
+def cinder_client(os_creds, session=None):
"""
Creates and returns a cinder client object
+ :param os_creds: the credentials for connecting to the OpenStack remote API
+ :param session: the keystone session object (optional)
:return: the cinder client
"""
+ if not session:
+ session = keystone_utils.keystone_session(os_creds)
+
return Client(version=os_creds.volume_api_version,
- session=keystone_utils.keystone_session(os_creds),
+ session=session,
region_name=os_creds.region_name)
-def get_volume(cinder, volume_name=None, volume_settings=None):
+def get_volume(cinder, keystone=None, volume_name=None, volume_settings=None,
+ project_name=None):
"""
Returns an OpenStack volume object for a given name
:param cinder: the Cinder client
+ :param keystone: the Keystone client (required if project_name or
+ volume_settings.project_name is not None
:param volume_name: the volume name to lookup
:param volume_settings: the volume settings used for lookups
+ :param project_name: the name of the project associated with the volume
:return: the volume object or None
"""
if volume_settings:
volume_name = volume_settings.name
volumes = cinder.volumes.list()
- for volume in volumes:
- if volume.name == volume_name:
- return Volume(
- name=volume.name, volume_id=volume.id,
- description=volume.description, size=volume.size,
- vol_type=volume.volume_type,
- availability_zone=volume.availability_zone,
- multi_attach=volume.multiattach,
- attachments=volume.attachments)
+ for os_volume in volumes:
+ if os_volume.name == volume_name:
+ project_id = None
+ if hasattr(os_volume, 'os-vol-tenant-attr:tenant_id'):
+ project_id = getattr(
+ os_volume, 'os-vol-tenant-attr:tenant_id')
+
+ if volume_settings and volume_settings.project_name:
+ project_name = volume_settings.project_name
+
+ if project_name:
+ project = keystone_utils.get_project_by_id(
+ keystone, project_id)
+
+ if project and project.name == project_name:
+ return __map_os_volume_to_domain(os_volume)
+ else:
+ return __map_os_volume_to_domain(os_volume)
def __get_os_volume_by_id(cinder, volume_id):
@@ -83,12 +101,29 @@ def get_volume_by_id(cinder, volume_id):
:param volume_id: the volume ID to lookup
:return: the SNAPS-OO Domain Volume object or None
"""
- volume = __get_os_volume_by_id(cinder, volume_id)
+ os_volume = __get_os_volume_by_id(cinder, volume_id)
+ return __map_os_volume_to_domain(os_volume)
+
+
+def __map_os_volume_to_domain(os_volume):
+ """
+ Returns a SNAPS-OO domain Volume object that is created by an OpenStack
+ Volume object
+ :param os_volume: the OpenStack volume object
+ :return: Volume domain object
+ """
+ project_id = None
+ if hasattr(os_volume, 'os-vol-tenant-attr:tenant_id'):
+ project_id = getattr(
+ os_volume, 'os-vol-tenant-attr:tenant_id')
+
return Volume(
- name=volume.name, volume_id=volume.id, description=volume.description,
- size=volume.size, vol_type=volume.volume_type,
- availability_zone=volume.availability_zone,
- multi_attach=volume.multiattach, attachments=volume.attachments)
+ name=os_volume.name, volume_id=os_volume.id,
+ project_id=project_id, description=os_volume.description,
+ size=os_volume.size, vol_type=os_volume.volume_type,
+ availability_zone=os_volume.availability_zone,
+ multi_attach=os_volume.multiattach,
+ attachments=os_volume.attachments)
def get_volume_status(cinder, volume):
@@ -102,27 +137,36 @@ def get_volume_status(cinder, volume):
return os_volume.status
-def create_volume(cinder, volume_settings):
+def create_volume(cinder, keystone, volume_settings):
"""
Creates and returns OpenStack volume object with an external URL
:param cinder: the cinder client
+ :param keystone: the keystone client
:param volume_settings: the volume settings object
:return: the OpenStack volume object
:raise Exception if using a file and it cannot be found
"""
- volume = cinder.volumes.create(
- name=volume_settings.name, description=volume_settings.description,
- size=volume_settings.size, imageRef=volume_settings.image_name,
+ project_id = None
+ if volume_settings.project_name:
+ project = keystone_utils.get_project(
+ keystone, project_name=volume_settings.project_name)
+ if project:
+ project_id = project.id
+ else:
+ raise KeystoneUtilsException(
+ 'Project cannot be found with name - '
+ + volume_settings.project_name)
+ os_volume = cinder.volumes.create(
+ name=volume_settings.name,
+ project_id=project_id,
+ description=volume_settings.description,
+ size=volume_settings.size,
+ imageRef=volume_settings.image_name,
volume_type=volume_settings.type_name,
availability_zone=volume_settings.availability_zone,
multiattach=volume_settings.multi_attach)
- return Volume(
- name=volume.name, volume_id=volume.id,
- description=volume.description,
- size=volume.size, vol_type=volume.volume_type,
- availability_zone=volume.availability_zone,
- multi_attach=volume.multiattach, attachments=volume.attachments)
+ return __map_os_volume_to_domain(os_volume)
def delete_volume(cinder, volume):
@@ -367,3 +411,9 @@ def delete_qos(cinder, qos):
"""
logger.info('Deleting QoS named - %s', qos.name)
cinder.qos_specs.delete(qos.id)
+
+
+class KeystoneUtilsException(Exception):
+ """
+ Exception when calls to the Keystone client cannot be served properly
+ """
diff --git a/snaps/openstack/utils/glance_utils.py b/snaps/openstack/utils/glance_utils.py
index a127ad3..db20f2f 100644
--- a/snaps/openstack/utils/glance_utils.py
+++ b/snaps/openstack/utils/glance_utils.py
@@ -34,13 +34,18 @@ Utilities for basic neutron API calls
"""
-def glance_client(os_creds):
+def glance_client(os_creds, session=None):
"""
Creates and returns a glance client object
+ :param os_creds: the credentials for connecting to the OpenStack remote API
+ :param session: the keystone session object (optional)
:return: the glance client
"""
+ if not session:
+ session = keystone_utils.keystone_session(os_creds)
+
return Client(version=os_creds.image_api_version,
- session=keystone_utils.keystone_session(os_creds),
+ session=session,
region_name=os_creds.region_name)
diff --git a/snaps/openstack/utils/heat_utils.py b/snaps/openstack/utils/heat_utils.py
index e440717..17de020 100644
--- a/snaps/openstack/utils/heat_utils.py
+++ b/snaps/openstack/utils/heat_utils.py
@@ -15,32 +15,35 @@
import logging
import os
-import yaml
from heatclient.client import Client
from heatclient.common.template_format import yaml_loader
from novaclient.exceptions import NotFound
from oslo_serialization import jsonutils
+import yaml
from snaps import file_utils
from snaps.domain.stack import Stack, Resource, Output
-
from snaps.openstack.utils import (
keystone_utils, neutron_utils, nova_utils, cinder_utils)
+from snaps.thread_utils import worker_pool
+
__author__ = 'spisarski'
logger = logging.getLogger('heat_utils')
-def heat_client(os_creds):
+def heat_client(os_creds, session=None):
"""
Retrieves the Heat client
:param os_creds: the OpenStack credentials
:return: the client
"""
logger.debug('Retrieving Heat Client')
+ if not session:
+ session = keystone_utils.keystone_session(os_creds)
return Client(os_creds.heat_api_version,
- session=keystone_utils.keystone_session(os_creds),
+ session=session,
region_name=os_creds.region_name)
@@ -65,7 +68,11 @@ def get_stack(heat_cli, stack_settings=None, stack_name=None):
stacks = heat_cli.stacks.list(**stack_filter)
for stack in stacks:
- return Stack(name=stack.identifier, stack_id=stack.id)
+ return Stack(
+ name=stack.stack_name, stack_id=stack.id,
+ stack_project_id=stack.stack_user_project_id,
+ status=stack.stack_status,
+ status_reason=stack.stack_status_reason)
def get_stack_by_id(heat_cli, stack_id):
@@ -76,7 +83,11 @@ def get_stack_by_id(heat_cli, stack_id):
:return: the Stack domain object else None
"""
stack = heat_cli.stacks.get(stack_id)
- return Stack(name=stack.identifier, stack_id=stack.id)
+ return Stack(
+ name=stack.stack_name, stack_id=stack.id,
+ stack_project_id=stack.stack_user_project_id,
+ status=stack.stack_status,
+ status_reason=stack.stack_status_reason)
def get_stack_status(heat_cli, stack_id):
@@ -133,6 +144,24 @@ def create_stack(heat_cli, stack_settings):
return get_stack_by_id(heat_cli, stack_id=stack['stack']['id'])
+def update_stack(heat_cli, stack, env_vals):
+ """
+ Updates the specified parameters in the stack
+ :param heat_cli: the OpenStack heat client object
+ :param stack_settings: the stack configuration
+ """
+ args = dict()
+
+ args['stack_name'] = stack.name
+ args['existing'] = True
+
+ if env_vals:
+ args['parameters'] = env_vals
+ heat_cli.stacks.update(stack.id, **args)
+ else:
+ logger.warn('Stack not updated, env_vals are None')
+
+
def delete_stack(heat_cli, stack):
"""
Deletes the Heat stack
@@ -210,8 +239,14 @@ def get_stack_networks(heat_cli, neutron, stack):
out = list()
resources = get_resources(heat_cli, stack.id, 'OS::Neutron::Net')
+ workers = []
for resource in resources:
- network = neutron_utils.get_network_by_id(neutron, resource.id)
+ worker = worker_pool().apply_async(neutron_utils.get_network_by_id,
+ (neutron, resource.id))
+ workers.append(worker)
+
+ for worker in workers:
+ network = worker.get()
if network:
out.append(network)
@@ -229,8 +264,14 @@ def get_stack_routers(heat_cli, neutron, stack):
out = list()
resources = get_resources(heat_cli, stack.id, 'OS::Neutron::Router')
+ workers = []
for resource in resources:
- router = neutron_utils.get_router_by_id(neutron, resource.id)
+ worker = worker_pool().apply_async(neutron_utils.get_router_by_id,
+ (neutron, resource.id))
+ workers.append(worker)
+
+ for worker in workers:
+ router = worker.get()
if router:
out.append(router)
@@ -248,47 +289,68 @@ def get_stack_security_groups(heat_cli, neutron, stack):
out = list()
resources = get_resources(heat_cli, stack.id, 'OS::Neutron::SecurityGroup')
+ workers = []
for resource in resources:
- security_group = neutron_utils.get_security_group_by_id(
- neutron, resource.id)
+ worker = worker_pool().apply_async(
+ neutron_utils.get_security_group_by_id,
+ (neutron, resource.id))
+ workers.append(worker)
+
+ for worker in workers:
+ security_group = worker.get()
if security_group:
out.append(security_group)
return out
-def get_stack_servers(heat_cli, nova, neutron, stack):
+def get_stack_servers(heat_cli, nova, neutron, keystone, stack, project_name):
"""
Returns a list of VMInst domain objects associated with a Stack
:param heat_cli: the OpenStack heat client object
:param nova: the OpenStack nova client object
:param neutron: the OpenStack neutron client object
+ :param keystone: the OpenStack keystone client object
:param stack: the SNAPS-OO Stack domain object
+ :param project_name: the associated project ID
:return: a list of VMInst domain objects
"""
out = list()
srvr_res = get_resources(heat_cli, stack.id, 'OS::Nova::Server')
+ workers = []
for resource in srvr_res:
+ worker = worker_pool().apply_async(
+ nova_utils.get_server_object_by_id,
+ (nova, neutron, keystone, resource.id, project_name))
+ workers.append((resource.id, worker))
+
+ for worker in workers:
+ resource_id = worker[0]
try:
- server = nova_utils.get_server_object_by_id(
- nova, neutron, resource.id)
+ server = worker[1].get()
if server:
out.append(server)
except NotFound:
- logger.warn('VmInst cannot be located with ID %s', resource.id)
+ logger.warn('VmInst cannot be located with ID %s', resource_id)
res_grps = get_resources(heat_cli, stack.id, 'OS::Heat::ResourceGroup')
for res_grp in res_grps:
res_ress = get_resources(heat_cli, res_grp.id)
+ workers = []
for res_res in res_ress:
res_res_srvrs = get_resources(
heat_cli, res_res.id, 'OS::Nova::Server')
for res_srvr in res_res_srvrs:
- server = nova_utils.get_server_object_by_id(
- nova, neutron, res_srvr.id)
- if server:
- out.append(server)
+ worker = worker_pool().apply_async(
+ nova_utils.get_server_object_by_id,
+ (nova, neutron, keystone, res_srvr.id, project_name))
+ workers.append(worker)
+
+ for worker in workers:
+ server = worker.get()
+ if server:
+ out.append(server)
return out
@@ -304,13 +366,20 @@ def get_stack_keypairs(heat_cli, nova, stack):
out = list()
resources = get_resources(heat_cli, stack.id, 'OS::Nova::KeyPair')
+ workers = []
for resource in resources:
+ worker = worker_pool().apply_async(
+ nova_utils.get_keypair_by_id, (nova, resource.id))
+ workers.append((resource.id, worker))
+
+ for worker in workers:
+ resource_id = worker[0]
try:
- keypair = nova_utils.get_keypair_by_id(nova, resource.id)
+ keypair = worker[1].get()
if keypair:
out.append(keypair)
except NotFound:
- logger.warn('Keypair cannot be located with ID %s', resource.id)
+ logger.warn('Keypair cannot be located with ID %s', resource_id)
return out
@@ -326,13 +395,20 @@ def get_stack_volumes(heat_cli, cinder, stack):
out = list()
resources = get_resources(heat_cli, stack.id, 'OS::Cinder::Volume')
+ workers = []
for resource in resources:
+ worker = worker_pool().apply_async(
+ cinder_utils.get_volume_by_id, (cinder, resource.id))
+ workers.append((resource.id, worker))
+
+ for worker in workers:
+ resource_id = worker[0]
try:
- server = cinder_utils.get_volume_by_id(cinder, resource.id)
+ server = worker[1].get()
if server:
out.append(server)
except NotFound:
- logger.warn('Volume cannot be located with ID %s', resource.id)
+ logger.warn('Volume cannot be located with ID %s', resource_id)
return out
@@ -348,13 +424,20 @@ def get_stack_volume_types(heat_cli, cinder, stack):
out = list()
resources = get_resources(heat_cli, stack.id, 'OS::Cinder::VolumeType')
+ workers = []
for resource in resources:
+ worker = worker_pool().apply_async(
+ cinder_utils.get_volume_type_by_id, (cinder, resource.id))
+ workers.append((resource.id, worker))
+
+ for worker in workers:
+ resource_id = worker[0]
try:
- vol_type = cinder_utils.get_volume_type_by_id(cinder, resource.id)
+ vol_type = worker[1].get()
if vol_type:
out.append(vol_type)
except NotFound:
- logger.warn('VolumeType cannot be located with ID %s', resource.id)
+ logger.warn('VolumeType cannot be located with ID %s', resource_id)
return out
@@ -371,13 +454,20 @@ def get_stack_flavors(heat_cli, nova, stack):
out = list()
resources = get_resources(heat_cli, stack.id, 'OS::Nova::Flavor')
+ workers = []
for resource in resources:
+ worker = worker_pool().apply_async(
+ nova_utils.get_flavor_by_id, (nova, resource.id))
+ workers.append((resource.id, worker))
+
+ for worker in workers:
+ resource_id = worker[0]
try:
- flavor = nova_utils.get_flavor_by_id(nova, resource.id)
+ flavor = worker[1].get()
if flavor:
out.append(flavor)
except NotFound:
- logger.warn('Flavor cannot be located with ID %s', resource.id)
+ logger.warn('Flavor cannot be located with ID %s', resource_id)
return out
diff --git a/snaps/openstack/utils/keystone_utils.py b/snaps/openstack/utils/keystone_utils.py
index b8769c0..4d3c0d3 100644
--- a/snaps/openstack/utils/keystone_utils.py
+++ b/snaps/openstack/utils/keystone_utils.py
@@ -14,10 +14,12 @@
# limitations under the License.
import logging
+import keystoneauth1
from keystoneclient.client import Client
from keystoneauth1.identity import v3, v2
from keystoneauth1 import session
import requests
+from keystoneclient.exceptions import NotFound
from snaps.domain.project import Project, Domain
from snaps.domain.role import Role
@@ -26,6 +28,7 @@ from snaps.domain.user import User
logger = logging.getLogger('keystone_utils')
V2_VERSION_NUM = 2.0
+V3_VERSION_NUM = 3
V2_VERSION_STR = 'v' + str(V2_VERSION_NUM)
@@ -77,15 +80,29 @@ def keystone_session(os_creds):
verify=os_creds.cacert)
-def keystone_client(os_creds):
+def close_session(session):
+ """
+ Closes a keystone session
+ :param session: a session.Session object
+ """
+ if isinstance(session, keystoneauth1.session.Session):
+ session.session.close()
+
+
+def keystone_client(os_creds, session=None):
"""
Returns the keystone client
:param os_creds: the OpenStack credentials (OSCreds) object
+ :param session: the keystone session object (optional)
:return: the client
"""
+
+ if not session:
+ session = keystone_session(os_creds)
+
return Client(
version=os_creds.identity_api_version,
- session=keystone_session(os_creds),
+ session=session,
interface=os_creds.interface,
region_name=os_creds.region_name)
@@ -105,26 +122,16 @@ def get_endpoint(os_creds, service_type, interface='public'):
interface=interface)
-def get_project(keystone=None, os_creds=None, project_settings=None,
- project_name=None):
+def get_project(keystone=None, project_settings=None, project_name=None):
"""
Returns the first project where the project_settings is used for the query
if not None, else the project_name parameter is used for the query. If both
parameters are None, None is returned
: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 ProjectConfig object
:param project_name: the name to query
:return: the SNAPS-OO Project domain object or None
"""
- if not keystone:
- if os_creds:
- keystone = keystone_client(os_creds)
- else:
- raise KeystoneException(
- 'Cannot lookup project without the proper credentials')
-
proj_filter = dict()
if project_name:
@@ -152,6 +159,26 @@ def get_project(keystone=None, os_creds=None, project_settings=None,
domain_id=domain_id)
+def get_project_by_id(keystone, proj_id):
+ """
+ Returns the first project where the project_settings is used for the query
+ if not None, else the project_name parameter is used for the query. If both
+ parameters are None, None is returned
+ :param keystone: the Keystone client
+ :param proj_id: the project ID
+ """
+ if proj_id and len(proj_id) > 0:
+ try:
+ os_proj = keystone.projects.get(proj_id)
+ if os_proj:
+ return Project(name=os_proj.name, project_id=os_proj.id,
+ domain_id=os_proj)
+ except NotFound:
+ pass
+ except KeyError:
+ pass
+
+
def create_project(keystone, project_settings):
"""
Creates a project
@@ -184,7 +211,7 @@ def create_project(keystone, project_settings):
def delete_project(keystone, project):
"""
Deletes a project
- :param keystone: the Keystone clien
+ :param keystone: the Keystone client
:param project: the SNAPS-OO Project domain object
"""
logger.info('Deleting project with name - %s', project.name)
@@ -237,8 +264,8 @@ def create_user(keystone, user_settings):
"""
project = None
if user_settings.project_name:
- project = get_project(keystone=keystone,
- project_name=user_settings.project_name)
+ project = get_project(
+ keystone=keystone, project_name=user_settings.project_name)
if keystone.version == V2_VERSION_STR:
project_id = None
@@ -381,9 +408,10 @@ def get_domain_by_id(keystone, domain_id):
:param domain_id: the domain ID to retrieve
:return: the SNAPS-OO Domain domain object
"""
- domain = keystone.domains.get(domain_id)
- if domain:
- return Domain(name=domain.name, domain_id=domain.id)
+ if keystone.version != V2_VERSION_STR:
+ domain = keystone.domains.get(domain_id)
+ if domain:
+ return Domain(name=domain.name, domain_id=domain.id)
def __get_os_domain_by_name(keystone, domain_name):
diff --git a/snaps/openstack/utils/launch_utils.py b/snaps/openstack/utils/launch_utils.py
index e10cf48..ddaad12 100644
--- a/snaps/openstack/utils/launch_utils.py
+++ b/snaps/openstack/utils/launch_utils.py
@@ -24,6 +24,7 @@ import os
import time
from keystoneauth1.exceptions import Unauthorized
+from snaps import file_utils
from snaps.config.flavor import FlavorConfig
from snaps.config.image import ImageConfig
from snaps.config.keypair import KeypairConfig
@@ -48,9 +49,14 @@ 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, neutron_utils
+from snaps.openstack.utils import deploy_utils, neutron_utils, keystone_utils
+from snaps.openstack.utils.nova_utils import RebootType
from snaps.provisioning import ansible_utils
+from warnings import warn
+warn('This utility will be removed in a subsequent release',
+ DeprecationWarning)
+
logger = logging.getLogger('lanuch_utils')
DEFAULT_CREDS_KEY = 'admin'
@@ -118,7 +124,7 @@ def launch_config(config, tmplt_file, deploy, clean, clean_image):
users_dict)
creators.append(vol_type_dict)
- # Create volume types
+ # Create volumes
vol_dict = __create_instances(
os_creds_dict, OpenStackVolume, VolumeConfig,
os_config.get('volumes'), 'volume', clean, users_dict)
@@ -307,6 +313,8 @@ def __create_instances(os_creds_dict, creator_class, config_class, config,
creator.create()
out[inst_config['name']] = creator
+ else:
+ raise Exception('Unable to instantiate creator')
logger.info('Initialized configured %ss', config_key)
@@ -415,10 +423,9 @@ def __apply_ansible_playbooks(ansible_configs, os_creds_dict, vm_dict,
'SSH requests')
return False
- os_creds = os_creds_dict.get('admin-creds')
__apply_ansible_playbook(
- ansible_config, os_creds, vm_dict, image_dict, flavor_dict,
- networks_dict, routers_dict)
+ ansible_config, os_creds_dict, vm_dict, image_dict,
+ flavor_dict, networks_dict, routers_dict)
# Return to original directory
os.chdir(orig_cwd)
@@ -426,12 +433,13 @@ def __apply_ansible_playbooks(ansible_configs, os_creds_dict, vm_dict,
return True
-def __apply_ansible_playbook(ansible_config, os_creds, vm_dict, image_dict,
- flavor_dict, networks_dict, routers_dict):
+def __apply_ansible_playbook(ansible_config, os_creds_dict, vm_dict,
+ image_dict, flavor_dict, networks_dict,
+ routers_dict):
"""
Applies an Ansible configuration setting
:param ansible_config: the configuration settings
- :param os_creds: the OpenStack admin credentials object
+ :param os_creds_dict: dict where the key is the name and value is OSCreds
:param vm_dict: the dictionary of newly instantiated VMs where the name is
the key
:param image_dict: the dictionary of newly instantiated images where the
@@ -457,20 +465,16 @@ def __apply_ansible_playbook(ansible_config, os_creds, vm_dict, image_dict,
'completed')
variables = __get_variables(
- ansible_config.get('variables'), os_creds, vm_dict, image_dict,
- flavor_dict, networks_dict, routers_dict)
+ ansible_config.get('variables'), os_creds_dict, vm_dict,
+ image_dict, flavor_dict, networks_dict, routers_dict)
- retval = ansible_utils.apply_playbook(
+ ansible_utils.apply_playbook(
ansible_config['playbook_location'], floating_ips, remote_user,
- private_key_filepath,
+ ssh_priv_key_file_path=private_key_filepath,
variables=variables,
proxy_setting=proxy_settings)
- if retval != 0:
- # Not a fatal type of event
- raise Exception(
- 'Error applying playbook found at location - %s',
- ansible_config.get('playbook_location'))
- elif ansible_config.get('post_processing'):
+
+ if 'post_processing' in ansible_config:
post_proc_config = ansible_config['post_processing']
if 'sleep' in post_proc_config:
time.sleep(post_proc_config['sleep'])
@@ -478,9 +482,7 @@ def __apply_ansible_playbook(ansible_config, os_creds, vm_dict, image_dict,
for vm_name in post_proc_config['reboot']:
if vm_name in vm_dict:
logger.info('Rebooting VM - %s', vm_name)
- vm_dict[vm_name].reboot()
-
- return retval
+ vm_dict[vm_name].reboot(RebootType.hard)
def __get_connection_info(ansible_config, vm_dict):
@@ -526,13 +528,13 @@ def __get_connection_info(ansible_config, vm_dict):
return None
-def __get_variables(var_config, os_creds, vm_dict, image_dict, flavor_dict,
- networks_dict, routers_dict):
+def __get_variables(var_config, os_creds_dict, vm_dict, image_dict,
+ flavor_dict, networks_dict, routers_dict):
"""
Returns a dictionary of substitution variables to be used for Ansible
templates
:param var_config: the variable configuration settings
- :param os_creds: the OpenStack admin credentials object
+ :param os_creds_dict: dict where the key is the name and value is OSCreds
:param vm_dict: the dictionary of newly instantiated VMs where the name is
the key
:param image_dict: the dictionary of newly instantiated images where the
@@ -549,7 +551,7 @@ def __get_variables(var_config, os_creds, vm_dict, image_dict, flavor_dict,
variables = dict()
for key, value in var_config.items():
value = __get_variable_value(
- value, os_creds, vm_dict, image_dict, flavor_dict,
+ value, os_creds_dict, vm_dict, image_dict, flavor_dict,
networks_dict, routers_dict)
if key and value:
variables[key] = value
@@ -564,13 +566,13 @@ def __get_variables(var_config, os_creds, vm_dict, image_dict, flavor_dict,
return None
-def __get_variable_value(var_config_values, os_creds, vm_dict, image_dict,
+def __get_variable_value(var_config_values, os_creds_dict, vm_dict, image_dict,
flavor_dict, networks_dict, routers_dict):
"""
Returns the associated variable value for use by Ansible for substitution
purposes
:param var_config_values: the configuration dictionary
- :param os_creds: the OpenStack admin credentials object
+ :param os_creds_dict: dict where the key is the name and value is OSCreds
:param vm_dict: the dictionary of newly instantiated VMs where the name is
the key
:param image_dict: the dictionary of newly instantiated images where the
@@ -588,12 +590,14 @@ def __get_variable_value(var_config_values, os_creds, vm_dict, image_dict,
if var_config_values['type'] == 'vm-attr':
return __get_vm_attr_variable_value(var_config_values, vm_dict)
if var_config_values['type'] == 'os_creds':
- return __get_os_creds_variable_value(var_config_values, os_creds)
+ return __get_os_creds_variable_value(var_config_values, os_creds_dict)
+ if var_config_values['type'] == 'os_creds_dict':
+ return str(__get_os_creds_dict(var_config_values, os_creds_dict))
if var_config_values['type'] == 'network':
return __get_network_variable_value(var_config_values, networks_dict)
if var_config_values['type'] == 'router':
return __get_router_variable_value(var_config_values, routers_dict,
- os_creds)
+ os_creds_dict)
if var_config_values['type'] == 'port':
return __get_vm_port_variable_value(var_config_values, vm_dict)
if var_config_values['type'] == 'floating_ip':
@@ -602,6 +606,8 @@ def __get_variable_value(var_config_values, os_creds, vm_dict, image_dict,
return __get_image_variable_value(var_config_values, image_dict)
if var_config_values['type'] == 'flavor':
return __get_flavor_variable_value(var_config_values, flavor_dict)
+ if var_config_values['type'] == 'vm-yaml':
+ return __create_yaml(var_config_values, vm_dict)
return None
@@ -630,13 +636,19 @@ def __get_vm_attr_variable_value(var_config_values, vm_dict):
return vm.get_image_user()
-def __get_os_creds_variable_value(var_config_values, os_creds):
+def __get_os_creds_variable_value(var_config_values, os_creds_dict):
"""
Returns the associated OS credentials value
:param var_config_values: the configuration dictionary
- :param os_creds: the admin OpenStack OSCreds object
+ :param os_creds_dict: dict of OpenStack credentials where the key is the
+ name
:return: the value
"""
+ if 'creds_name' in var_config_values:
+ os_creds = os_creds_dict.get[var_config_values['creds_name']]
+ else:
+ os_creds = os_creds_dict.get('admin-creds')
+
if os_creds:
if var_config_values['value'] == 'username':
logger.info("Returning OS username")
@@ -652,6 +664,21 @@ def __get_os_creds_variable_value(var_config_values, os_creds):
return os_creds.project_name
+def __get_os_creds_dict(var_config_values, os_creds_dict):
+ """
+ Returns the associated OS credentials as a dict
+ :param var_config_values: the configuration dictionary
+ :param os_creds_dict: dict of creds where the key is the username
+ :return: the value dict
+ """
+ if 'creds_name' in var_config_values:
+ os_creds = os_creds_dict.get[var_config_values['creds_name']]
+ else:
+ os_creds = os_creds_dict.get('admin-creds')
+ if os_creds:
+ return os_creds.to_dict()
+
+
def __get_network_variable_value(var_config_values, networks_dict):
"""
Returns the associated network value
@@ -675,6 +702,12 @@ def __get_network_variable_value(var_config_values, networks_dict):
return subnet.gateway_ip
if 'ip_range' == var_config_values['value']:
return subnet.start + ' ' + subnet.end
+ if 'ip_range_start' == var_config_values['value']:
+ return subnet.start
+ if 'ip_range_end' == var_config_values['value']:
+ return subnet.end
+ if 'cidr' == var_config_values['value']:
+ return subnet.cidr
if 'cidr_ip' == var_config_values['value']:
cidr_split = subnet.cidr.split('/')
return cidr_split[0]
@@ -693,32 +726,43 @@ def __get_network_variable_value(var_config_values, networks_dict):
return broadcast_ip
-def __get_router_variable_value(var_config_values, routers_dict, os_creds):
+def __get_router_variable_value(var_config_values, routers_dict,
+ os_creds_dict):
"""
Returns the associated network value
:param var_config_values: the configuration dictionary
:param routers_dict: the dictionary containing all networks where the key
is the network name
- :param os_creds: the admin OpenStack credentials
+ :param os_creds_dict: dict of OpenStack credentials where the key is the
+ name
:return: the value
"""
+ if 'creds_name' in var_config_values:
+ os_creds = os_creds_dict.get[var_config_values['creds_name']]
+ else:
+ os_creds = os_creds_dict.get('admin-creds')
+
router_name = var_config_values.get('router_name')
router_creator = routers_dict[router_name]
if router_creator:
if 'external_fixed_ip' == var_config_values.get('attr'):
- neutron = neutron_utils.neutron_client(os_creds)
- ext_nets = neutron_utils.get_external_networks(neutron)
+ session = keystone_utils.keystone_session(os_creds)
+ neutron = neutron_utils.neutron_client(os_creds, session)
+ try:
+ ext_nets = neutron_utils.get_external_networks(neutron)
- subnet_name = var_config_values.get('subnet_name')
+ subnet_name = var_config_values.get('subnet_name')
- for ext_net in ext_nets:
- for subnet in ext_net.subnets:
- if subnet_name == subnet.name:
- router = router_creator.get_router()
- for fixed_ips in router.external_fixed_ips:
- if subnet.id == fixed_ips['subnet_id']:
- return fixed_ips['ip_address']
+ for ext_net in ext_nets:
+ for subnet in ext_net.subnets:
+ if subnet_name == subnet.name:
+ router = router_creator.get_router()
+ for fixed_ips in router.external_fixed_ips:
+ if subnet.id == fixed_ips['subnet_id']:
+ return fixed_ips['ip_address']
+ finally:
+ keystone_utils.close_session(session)
def __get_vm_port_variable_value(var_config_values, vm_dict):
@@ -801,6 +845,36 @@ def __get_flavor_variable_value(var_config_values, flavor_dict):
return flavor_creator.get_flavor().id
+def __create_yaml(var_config_values, vm_dict):
+ """
+ Creates a yaml file containing an OpenStack pod's credentials with a list
+ of server IDs that can be used for obtaining SNAPS-OO instances for
+ manipulation such as rebooting
+ :param var_config_values: the configuration dictionary
+ :param vm_dict: the dictionary containing all vm creators where the
+ key is the name
+ :return: the name of the generated file
+ """
+ out_dict = dict()
+ out_dict['vms'] = list()
+ req_vm_names = var_config_values.get('vms')
+
+ for name, vm_creator in vm_dict.items():
+ vm_inst = vm_creator.get_vm_inst()
+ if vm_inst and vm_inst.name in req_vm_names:
+ out_dict['vms'].append({
+ 'name': str(vm_inst.name),
+ 'id': str(vm_inst.id),
+ 'os_creds': vm_creator.get_os_creds().to_dict()
+ })
+
+ out_file = file_utils.persist_dict_to_yaml(
+ out_dict, var_config_values.get('file_name'))
+
+ if out_file:
+ return out_file.name
+
+
def __cleanup(creators, clean_image=False):
"""
Cleans up environment
diff --git a/snaps/openstack/utils/magnum_utils.py b/snaps/openstack/utils/magnum_utils.py
index 96ba6d1..1f39cfe 100644
--- a/snaps/openstack/utils/magnum_utils.py
+++ b/snaps/openstack/utils/magnum_utils.py
@@ -24,15 +24,18 @@ __author__ = 'spisarski'
logger = logging.getLogger('magnum_utils')
-def magnum_client(os_creds):
+def magnum_client(os_creds, session=None):
"""
Retrieves the Magnum client
:param os_creds: the OpenStack credentialsf
+ :param session: the keystone session object (optional)
:return: the client
"""
logger.debug('Retrieving Magnum Client')
- return Client(str(os_creds.magnum_api_version),
- session=keystone_utils.keystone_session(os_creds))
+ if not session:
+ session = keystone_utils.keystone_session(os_creds)
+
+ return Client(str(os_creds.magnum_api_version), session=session)
def get_cluster_template(magnum, template_config=None, template_name=None):
diff --git a/snaps/openstack/utils/neutron_utils.py b/snaps/openstack/utils/neutron_utils.py
index e94a40e..f1a5ac2 100644
--- a/snaps/openstack/utils/neutron_utils.py
+++ b/snaps/openstack/utils/neutron_utils.py
@@ -33,15 +33,18 @@ Utilities for basic neutron API calls
"""
-def neutron_client(os_creds):
+def neutron_client(os_creds, session=None):
"""
Instantiates and returns a client for communications with OpenStack's
Neutron server
:param os_creds: the credentials for connecting to the OpenStack remote API
+ :param session: the keystone session object (optional)
:return: the client object
"""
+ if not session:
+ session = keystone_utils.keystone_session(os_creds)
return Client(api_version=os_creds.network_api_version,
- session=keystone_utils.keystone_session(os_creds),
+ session=session,
region_name=os_creds.region_name)
@@ -101,17 +104,18 @@ def delete_network(neutron, network):
neutron.delete_network(network.id)
-def get_network(neutron, network_settings=None, network_name=None,
- project_id=None):
+def get_network(neutron, keystone, network_settings=None, network_name=None,
+ project_name=None):
"""
Returns Network SNAPS-OO domain object the first network found with
either the given attributes from the network_settings object if not 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
+ When the project_name is included, that will be added to the query filter.
+ :param neutron: the Neutron client
+ :param keystone: the Keystone client
: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
+ :param project_name: the name of the network's project
:return: a SNAPS-OO Network domain object
"""
net_filter = dict()
@@ -120,13 +124,20 @@ def get_network(neutron, network_settings=None, network_name=None,
elif network_name:
net_filter['name'] = network_name
- if project_id:
- net_filter['project_id'] = project_id
-
networks = neutron.list_networks(**net_filter)
for network, netInsts in networks.items():
for inst in netInsts:
- return __map_network(neutron, inst)
+ if project_name:
+ if 'project_id' in inst.keys():
+ project = keystone_utils.get_project_by_id(
+ keystone, inst['project_id'])
+ else:
+ project = keystone_utils.get_project_by_id(
+ keystone, inst['tenant_id'])
+ if project and project.name == project_name:
+ return __map_network(neutron, inst)
+ else:
+ return __map_network(neutron, inst)
def __get_os_network_by_id(neutron, network_id):
@@ -199,16 +210,17 @@ def delete_subnet(neutron, subnet):
neutron.delete_subnet(subnet.id)
-def get_subnet(neutron, subnet_settings=None, subnet_name=None):
+def get_subnet(neutron, network, subnet_settings=None, subnet_name=None):
"""
Returns the first subnet object that fits the query else None including
if subnet_settings or subnet_name parameters are None.
:param neutron: the client
+ :param network: the associated SNAPS-OO Network domain object
:param subnet_settings: the subnet settings of the object to retrieve
:param subnet_name: the name of the subnet to retrieve
:return: a SNAPS-OO Subnet domain object or None
"""
- sub_filter = dict()
+ sub_filter = {'network_id': network.id}
if subnet_settings:
sub_filter['name'] = subnet_settings.name
sub_filter['cidr'] = subnet_settings.cidr
@@ -239,6 +251,30 @@ def get_subnet(neutron, subnet_settings=None, subnet_name=None):
return Subnet(**subnet)
+def get_subnet_by_name(neutron, keystone, subnet_name, project_name=None):
+ """
+ Returns the first subnet object that fits the query else None including
+ if subnet_settings or subnet_name parameters are None.
+ :param neutron: the Neutron client
+ :param keystone: the Keystone client
+ :param subnet_name: the name of the subnet to retrieve
+ :param project_name: the name of the associated project to the subnet to
+ retrieve
+ :return: a SNAPS-OO Subnet domain object or None
+ """
+ sub_filter = {'name': subnet_name}
+ subnets = neutron.list_subnets(**sub_filter)
+ for subnet in subnets['subnets']:
+ subnet = Subnet(**subnet)
+ if project_name:
+ project = keystone_utils.get_project_by_id(
+ keystone, subnet.project_id)
+ if project and project.name == project_name:
+ return subnet
+ else:
+ return subnet
+
+
def get_subnet_by_id(neutron, subnet_id):
"""
Returns a SNAPS-OO Subnet domain object for a given ID
@@ -321,14 +357,17 @@ def get_router_by_id(neutron, router_id):
return __map_router(neutron, router['router'])
-def get_router(neutron, router_settings=None, router_name=None):
+def get_router(neutron, keystone, router_settings=None, router_name=None,
+ project_name=None):
"""
Returns the first router object (dictionary) found the given the settings
values if not None, else finds the first with the value of the router_name
parameter, else None
- :param neutron: the client
+ :param neutron: the Neutron client
+ :param keystone: the Keystone client
:param router_settings: the RouterConfig object
:param router_name: the name of the network to retrieve
+ :param project_name: the name of the router's project
:return: a SNAPS-OO Router domain object
"""
router_filter = dict()
@@ -341,12 +380,17 @@ def get_router(neutron, router_settings=None, router_name=None):
else:
return None
- routers = neutron.list_routers(**router_filter)
-
- for routerInst in routers['routers']:
- return __map_router(neutron, routerInst)
-
- return None
+ os_routers = neutron.list_routers(**router_filter)
+ for os_router in os_routers['routers']:
+ if project_name:
+ if 'project_id' in os_router.keys():
+ project = keystone_utils.get_project_by_id(
+ keystone, os_router['project_id'])
+ else:
+ project = keystone_utils.get_project_by_id(
+ keystone, os_router['tenant_id'])
+ if project and project.name == project_name:
+ return __map_router(neutron, os_router)
def __map_router(neutron, os_router):
@@ -460,10 +504,7 @@ def create_port(neutron, os_creds, port_settings):
logger.info('Creating port for network with name - %s',
port_settings.network_name)
os_port = neutron.create_port(body=json_body)['port']
- return Port(name=os_port['name'], id=os_port['id'],
- ips=os_port['fixed_ips'],
- mac_address=os_port['mac_address'],
- allowed_address_pairs=os_port['allowed_address_pairs'])
+ return Port(**os_port)
def delete_port(neutron, port):
@@ -476,13 +517,16 @@ def delete_port(neutron, port):
neutron.delete_port(port.id)
-def get_port(neutron, port_settings=None, port_name=None):
+def get_port(neutron, keystone, port_settings=None, port_name=None,
+ project_name=None):
"""
Returns the first port object (dictionary) found for the given query
- :param neutron: the client
+ :param neutron: the Neutron client
+ :param keystone: the Keystone client
: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
+ :param project_name: the associated project name
:return: a SNAPS-OO Port domain object
"""
port_filter = dict()
@@ -496,9 +540,15 @@ def get_port(neutron, port_settings=None, port_name=None):
port_filter['device_id'] = port_settings.device_id
if port_settings.mac_address:
port_filter['mac_address'] = port_settings.mac_address
+ if port_settings.project_name:
+ project_name = port_settings.project_name
if port_settings.network_name:
- network = get_network(neutron,
- network_name=port_settings.network_name)
+ network = get_network(
+ neutron, keystone, network_name=port_settings.network_name)
+ if network and not (network.shared or network.external):
+ network = get_network(
+ neutron, keystone, network_name=port_settings.network_name,
+ project_name=project_name)
if network:
port_filter['network_id'] = network.id
elif port_name:
@@ -506,7 +556,17 @@ def get_port(neutron, port_settings=None, port_name=None):
ports = neutron.list_ports(**port_filter)
for port in ports['ports']:
- return Port(**port)
+ if project_name:
+ if 'project_id' in port.keys():
+ project = keystone_utils.get_project_by_id(
+ keystone, port['project_id'])
+ else:
+ project = keystone_utils.get_project_by_id(
+ keystone, port['tenant_id'])
+ if project and project.name == project_name:
+ return Port(**port)
+ else:
+ return Port(**port)
return None
@@ -572,30 +632,31 @@ def delete_security_group(neutron, sec_grp):
neutron.delete_security_group(sec_grp.id)
-def get_security_group(neutron, sec_grp_settings=None, sec_grp_name=None,
- project_id=None):
+def get_security_group(neutron, keystone, sec_grp_settings=None,
+ sec_grp_name=None, project_name=None):
"""
Returns the first security group for a given query. The query gets built
from the sec_grp_settings parameter if not None, else only the name of
the security group will be used, else if the query parameters are None then
None will be returned
- :param neutron: the client
+ :param neutron: the neutron client
+ :param keystone: the keystone client
:param sec_grp_settings: an instance of SecurityGroupConfig object
:param sec_grp_name: the name of security group object to retrieve
- :param project_id: the ID of the project/tentant object that owns the
+ :param project_name: the name of the project/tentant object that owns the
secuity group to retrieve
:return: a SNAPS-OO SecurityGroup domain object or None if not found
"""
sec_grp_filter = dict()
- if project_id:
- sec_grp_filter['tenant_id'] = project_id
if sec_grp_settings:
sec_grp_filter['name'] = sec_grp_settings.name
if sec_grp_settings.description:
sec_grp_filter['description'] = sec_grp_settings.description
+ if sec_grp_settings.project_name:
+ project_name = sec_grp_settings.project_name
elif sec_grp_name:
sec_grp_filter['name'] = sec_grp_name
else:
@@ -603,7 +664,17 @@ def get_security_group(neutron, sec_grp_settings=None, sec_grp_name=None,
groups = neutron.list_security_groups(**sec_grp_filter)
for group in groups['security_groups']:
- return __map_os_security_group(neutron, group)
+ if project_name:
+ if 'project_id' in group.keys():
+ project = keystone_utils.get_project_by_id(
+ keystone, group['project_id'])
+ else:
+ project = keystone_utils.get_project_by_id(
+ keystone, group['tenant_id'])
+ if project and project_name == project.name:
+ return __map_os_security_group(neutron, group)
+ else:
+ return __map_os_security_group(neutron, group)
def __map_os_security_group(neutron, os_sec_grp):
@@ -635,17 +706,35 @@ def get_security_group_by_id(neutron, sec_grp_id):
return None
-def create_security_group_rule(neutron, sec_grp_rule_settings):
+def list_security_groups(neutron):
+
+ """
+ Lists the available security groups
+ :param neutron: the neutron client
+ """
+ logger.info('Listing the available security groups')
+ sec_groups = []
+ response = neutron.list_security_groups()
+ for sg in response['security_groups']:
+ sec_groups.append(__map_os_security_group(neutron, sg))
+
+ return sec_groups
+
+
+def create_security_group_rule(neutron, keystone, sec_grp_rule_settings,
+ proj_name):
"""
Creates a security group rule in OpenStack
- :param neutron: the client
+ :param neutron: the neutron client
+ :param keystone: the keystone client
:param sec_grp_rule_settings: the security group rule settings
+ :param proj_name: the default project name
:return: a SNAPS-OO SecurityGroupRule domain object
"""
logger.info('Creating security group to security group - %s',
sec_grp_rule_settings.sec_grp_name)
os_rule = neutron.create_security_group_rule(
- sec_grp_rule_settings.dict_for_neutron(neutron))
+ sec_grp_rule_settings.dict_for_neutron(neutron, keystone, proj_name))
return SecurityGroupRule(**os_rule['security_group_rule'])
@@ -716,14 +805,11 @@ def get_external_networks(neutron):
return out
-def get_floating_ips(neutron, ports=None):
+def get_port_floating_ips(neutron, ports):
"""
- Returns all of the floating IPs
- When ports is not None, FIPs returned must be associated with one of the
- ports in the list and a tuple 2 where the first element being the port's
- ID and the second being the FloatingIp SNAPS-OO domain object.
- When ports is None, all known FloatingIp SNAPS-OO domain objects will be
- returned in a list
+ Returns all of the floating IPs associated with the ports returned in a
+ list of tuples where the port object is in the first position and the
+ floating IP object is in the second
:param neutron: the Neutron client
:param ports: a list of tuple 2 where index 0 is the port name and index 1
is the SNAPS-OO Port object
@@ -733,31 +819,44 @@ def get_floating_ips(neutron, ports=None):
out = list()
fips = neutron.list_floatingips()
for fip in fips['floatingips']:
- if ports:
- for port_name, port in ports:
- if port and port.id == fip['port_id']:
- out.append((port.id, FloatingIp(**fip)))
- break
- else:
- out.append(FloatingIp(**fip))
+ for port_name, port in ports:
+ if port and port.id == fip['port_id']:
+ out.append((port.id, FloatingIp(**fip)))
+ break
+ return out
+
+def get_floating_ips(neutron):
+ """
+ Returns a list of all of the floating IPs
+ :param neutron: the Neutron client
+ """
+ out = list()
+ fips = neutron.list_floatingips()
+ for fip in fips['floatingips']:
+ out.append(FloatingIp(**fip))
return out
-def create_floating_ip(neutron, ext_net_name):
+def create_floating_ip(neutron, keystone, ext_net_name, port_id=None):
"""
Returns the floating IP object that was created with this call
:param neutron: the Neutron client
+ :param keystone: the Keystone client
:param ext_net_name: the name of the external network on which to apply the
floating IP address
+ :param port_id: the ID of the port to which the floating IP will be
+ associated
:return: the SNAPS FloatingIp object
"""
logger.info('Creating floating ip to external network - ' + ext_net_name)
- ext_net = get_network(neutron, network_name=ext_net_name)
+ ext_net = get_network(neutron, keystone, network_name=ext_net_name)
if ext_net:
- fip = neutron.create_floatingip(
- body={'floatingip':
- {'floating_network_id': ext_net.id}})
+ body = {'floatingip': {'floating_network_id': ext_net.id}}
+ if port_id:
+ body['floatingip']['port_id'] = port_id
+
+ fip = neutron.create_floatingip(body=body)
return FloatingIp(id=fip['floatingip']['id'],
ip=fip['floatingip']['floating_ip_address'])
@@ -791,7 +890,7 @@ def __get_os_floating_ip(neutron, floating_ip):
"""
logger.debug('Attempting to retrieve existing floating ip with IP - %s',
floating_ip.ip)
- fips = neutron.list_floatingips(ip=floating_ip.id)
+ fips = neutron.list_floatingips(floating_ip_address=floating_ip.ip)
for fip in fips['floatingips']:
if fip['id'] == floating_ip.id:
diff --git a/snaps/openstack/utils/nova_utils.py b/snaps/openstack/utils/nova_utils.py
index e15484c..005b56f 100644
--- a/snaps/openstack/utils/nova_utils.py
+++ b/snaps/openstack/utils/nova_utils.py
@@ -35,33 +35,41 @@ __author__ = 'spisarski'
logger = logging.getLogger('nova_utils')
+POLL_INTERVAL = 3
+
"""
Utilities for basic OpenStack Nova API calls
"""
-def nova_client(os_creds):
+def nova_client(os_creds, session=None):
"""
Instantiates and returns a client for communications with OpenStack's Nova
server
:param os_creds: The connection credentials to the OpenStack API
+ :param session: the keystone session object (optional)
:return: the client object
"""
logger.debug('Retrieving Nova Client')
+ if not session:
+ session = keystone_utils.keystone_session(os_creds)
+
return Client(os_creds.compute_api_version,
- session=keystone_utils.keystone_session(os_creds),
+ session=session,
region_name=os_creds.region_name)
-def create_server(nova, neutron, glance, instance_config, image_config,
- keypair_config=None):
+def create_server(nova, keystone, neutron, glance, instance_config,
+ image_config, project_name, keypair_config=None):
"""
Creates a VM instance
:param nova: the nova client (required)
+ :param keystone: the keystone client for retrieving projects (required)
:param neutron: the neutron client for retrieving ports (required)
:param glance: the glance client (required)
:param instance_config: the VMInstConfig object (required)
:param image_config: the VM's ImageConfig object (required)
+ :param project_name: the associated project name (required)
:param keypair_config: the VM's KeypairConfig object (optional)
:return: a snaps.domain.VmInst object
"""
@@ -69,8 +77,13 @@ def create_server(nova, neutron, glance, instance_config, image_config,
ports = list()
for port_setting in instance_config.port_settings:
- ports.append(neutron_utils.get_port(
- neutron, port_settings=port_setting))
+ port = neutron_utils.get_port(
+ neutron, keystone, port_settings=port_setting,
+ project_name=project_name)
+ if port:
+ ports.append(port)
+ else:
+ raise Exception('Cannot find port named - ' + port_setting.name)
nics = []
for port in ports:
kv = dict()
@@ -115,22 +128,26 @@ def create_server(nova, neutron, glance, instance_config, image_config,
server = nova.servers.create(**args)
- return __map_os_server_obj_to_vm_inst(neutron, server)
+ return __map_os_server_obj_to_vm_inst(
+ neutron, keystone, server, project_name)
else:
raise NovaException(
'Cannot create instance, image cannot be located with name %s',
image_config.name)
-def get_server(nova, neutron, vm_inst_settings=None, server_name=None):
+def get_server(nova, neutron, keystone, vm_inst_settings=None,
+ server_name=None, project_id=None):
"""
Returns a VmInst object for the first server instance found.
:param nova: the Nova client
:param neutron: the Neutron client
+ :param keystone: the Keystone client
:param vm_inst_settings: the VmInstanceConfig object from which to build
the query if not None
:param server_name: the server with this name to return if vm_inst_settings
is not None
+ :param project_id: the assocaited project ID
:return: a snaps.domain.VmInst object or None if not found
"""
search_opts = dict()
@@ -141,7 +158,8 @@ def get_server(nova, neutron, vm_inst_settings=None, server_name=None):
servers = nova.servers.list(search_opts=search_opts)
for server in servers:
- return __map_os_server_obj_to_vm_inst(neutron, server)
+ return __map_os_server_obj_to_vm_inst(
+ neutron, keystone, server, project_id)
def get_server_connection(nova, vm_inst_settings=None, server_name=None):
@@ -165,11 +183,14 @@ def get_server_connection(nova, vm_inst_settings=None, server_name=None):
return server.links[0]
-def __map_os_server_obj_to_vm_inst(neutron, os_server):
+def __map_os_server_obj_to_vm_inst(neutron, keystone, os_server,
+ project_name=None):
"""
Returns a VmInst object for an OpenStack Server object
- :param neutron: the Neutron client (when None, ports will be empty)
+ :param neutron: the Neutron client
+ :param keystone: the Keystone client
:param os_server: the OpenStack server object
+ :param project_name: the associated project name
:return: an equivalent SNAPS-OO VmInst domain object
"""
sec_grp_names = list()
@@ -182,10 +203,17 @@ def __map_os_server_obj_to_vm_inst(neutron, os_server):
out_ports = list()
if len(os_server.networks) > 0:
for net_name, ips in os_server.networks.items():
- network = neutron_utils.get_network(neutron, network_name=net_name)
- ports = neutron_utils.get_ports(neutron, network, ips)
- for port in ports:
- out_ports.append(port)
+ network = neutron_utils.get_network(
+ neutron, keystone, network_name=net_name,
+ project_name=project_name)
+ if network:
+ ports = neutron_utils.get_ports(neutron, network, ips)
+ for port in ports:
+ out_ports.append(port)
+ else:
+ raise NovaException(
+ 'Unable to locate network in project {} with '
+ 'name {}'.format(project_name, net_name))
volumes = None
if hasattr(os_server, 'os-extended-volumes:volumes_attached'):
@@ -195,7 +223,9 @@ def __map_os_server_obj_to_vm_inst(neutron, os_server):
name=os_server.name, inst_id=os_server.id,
image_id=os_server.image['id'], flavor_id=os_server.flavor['id'],
ports=out_ports, keypair_name=os_server.key_name,
- sec_grp_names=sec_grp_names, volume_ids=volumes)
+ sec_grp_names=sec_grp_names, volume_ids=volumes,
+ compute_host=os_server._info.get('OS-EXT-SRV-ATTR:host'),
+ availability_zone=os_server._info.get('OS-EXT-AZ:availability_zone'))
def __get_latest_server_os_object(nova, server):
@@ -244,28 +274,35 @@ def get_server_console_output(nova, server):
return None
-def get_latest_server_object(nova, neutron, server):
+def get_latest_server_object(nova, neutron, keystone, server, project_name):
"""
Returns a server with a given id
:param nova: the Nova client
:param neutron: the Neutron client
+ :param keystone: the Keystone client
:param server: the old server object
+ :param project_name: the associated project name
:return: the list of servers or None if not found
"""
server = __get_latest_server_os_object(nova, server)
- return __map_os_server_obj_to_vm_inst(neutron, server)
+ return __map_os_server_obj_to_vm_inst(
+ neutron, keystone, server, project_name)
-def get_server_object_by_id(nova, neutron, server_id):
+def get_server_object_by_id(nova, neutron, keystone, server_id,
+ project_name=None):
"""
Returns a server with a given id
:param nova: the Nova client
:param neutron: the Neutron client
+ :param keystone: the Keystone client
:param server_id: the server's id
+ :param project_name: the associated project name
:return: an SNAPS-OO VmInst object or None if not found
"""
server = __get_latest_server_os_object_by_id(nova, server_id)
- return __map_os_server_obj_to_vm_inst(neutron, server)
+ return __map_os_server_obj_to_vm_inst(
+ neutron, keystone, server, project_name)
def get_server_security_group_names(nova, server):
@@ -277,8 +314,9 @@ def get_server_security_group_names(nova, server):
"""
out = list()
os_vm_inst = __get_latest_server_os_object(nova, server)
- for sec_grp_dict in os_vm_inst.security_groups:
- out.append(sec_grp_dict['name'])
+ if hasattr(os_vm_inst, 'security_groups'):
+ for sec_grp_dict in os_vm_inst.security_groups:
+ out.append(sec_grp_dict['name'])
return out
@@ -673,18 +711,6 @@ def remove_security_group(nova, vm, security_group):
nova.servers.remove_security_group(str(vm.id), security_group.name)
-def add_floating_ip_to_server(nova, vm, floating_ip, ip_addr):
- """
- Adds a floating IP to a server instance
- :param nova: the nova client
- :param vm: VmInst domain object
- :param floating_ip: FloatingIp domain object
- :param ip_addr: the IP to which to bind the floating IP to
- """
- vm = __get_latest_server_os_object(nova, vm)
- vm.add_floating_ip(floating_ip.ip, ip_addr)
-
-
def get_compute_quotas(nova, project_id):
"""
Returns a list of all available keypairs
@@ -720,60 +746,73 @@ def update_quotas(nova, project_id, compute_quotas):
return nova.quotas.update(project_id, **update_values)
-def attach_volume(nova, neutron, server, volume, timeout=None):
+def attach_volume(nova, neutron, keystone, server, volume, project_name,
+ timeout=120):
"""
- Attaches a volume to a server
+ Attaches a volume to a server. When the timeout parameter is used, a VmInst
+ object with the proper volume updates is returned unless it has not been
+ updated in the allotted amount of time then an Exception will be raised.
:param nova: the nova client
:param neutron: the neutron client
+ :param keystone: the neutron client
:param server: the VMInst domain object
:param volume: the Volume domain object
+ :param project_name: the associated project name
:param timeout: denotes the amount of time to block to determine if the
- has been properly attached. When None, do not wait.
- :return: the value from the nova call
+ has been properly attached.
+ :return: updated VmInst object
"""
nova.volumes.create_server_volume(server.id, volume.id)
- if timeout:
- start_time = time.time()
- while time.time() < start_time + timeout:
- vm = get_server_object_by_id(nova, neutron, server.id)
- for vol_dict in vm.volume_ids:
- if volume.id == vol_dict['id']:
- return vm
+ start_time = time.time()
+ while time.time() < start_time + timeout:
+ vm = get_server_object_by_id(
+ nova, neutron, keystone, server.id, project_name)
+ for vol_dict in vm.volume_ids:
+ if volume.id == vol_dict['id']:
+ return vm
+ time.sleep(POLL_INTERVAL)
- return None
- else:
- return get_server_object_by_id(nova, neutron, server.id)
+ raise NovaException(
+ 'Attach failed on volume - {} and server - {}'.format(
+ volume.id, server.id))
-def detach_volume(nova, neutron, server, volume, timeout=None):
+def detach_volume(nova, neutron, keystone, server, volume, project_name,
+ timeout=120):
"""
- Attaches a volume to a server
+ Detaches a volume to a server. When the timeout parameter is used, a VmInst
+ object with the proper volume updates is returned unless it has not been
+ updated in the allotted amount of time then an Exception will be raised.
:param nova: the nova client
:param neutron: the neutron client
+ :param keystone: the keystone client
:param server: the VMInst domain object
:param volume: the Volume domain object
+ :param project_name: the associated project name
:param timeout: denotes the amount of time to block to determine if the
- has been properly detached. When None, do not wait.
- :return: the value from the nova call
+ has been properly detached.
+ :return: updated VmInst object
"""
nova.volumes.delete_server_volume(server.id, volume.id)
- if timeout:
- start_time = time.time()
- while time.time() < start_time + timeout:
- vm = get_server_object_by_id(nova, neutron, server.id)
- found = False
+ start_time = time.time()
+ while time.time() < start_time + timeout:
+ vm = get_server_object_by_id(
+ nova, neutron, keystone, server.id, project_name)
+ if len(vm.volume_ids) == 0:
+ return vm
+ else:
+ ids = list()
for vol_dict in vm.volume_ids:
- if volume.id == vol_dict['id']:
- found = True
-
- if not found:
+ ids.append(vol_dict['id'])
+ if volume.id not in ids:
return vm
+ time.sleep(POLL_INTERVAL)
- return None
- else:
- return get_server_object_by_id(nova, neutron, server.id)
+ raise NovaException(
+ 'Detach failed on volume - {} server - {}'.format(
+ volume.id, server.id))
class RebootType(enum.Enum):
diff --git a/snaps/openstack/utils/settings_utils.py b/snaps/openstack/utils/settings_utils.py
index 2cf6047..e43f8f5 100644
--- a/snaps/openstack/utils/settings_utils.py
+++ b/snaps/openstack/utils/settings_utils.py
@@ -224,14 +224,16 @@ def create_keypair_config(heat_cli, stack, keypair, pk_output_key):
return KeypairConfig(name=keypair.name)
-def create_vm_inst_config(nova, neutron, server):
+def create_vm_inst_config(nova, keystone, neutron, server, project_name):
"""
Returns a VmInstanceConfig object
note: if the server instance is not active, the PortSettings objects will
not be generated resulting in an invalid configuration
:param nova: the nova client
+ :param keystone: the keystone client
:param neutron: the neutron client
:param server: a SNAPS-OO VmInst domain object
+ :param project_name: the associated project name
:return:
"""
@@ -244,7 +246,7 @@ def create_vm_inst_config(nova, neutron, server):
kwargs['port_settings'] = __create_port_configs(neutron, server.ports)
kwargs['security_group_names'] = server.sec_grp_names
kwargs['floating_ip_settings'] = __create_floatingip_config(
- neutron, kwargs['port_settings'])
+ neutron, keystone, kwargs['port_settings'], project_name)
return VmInstanceConfig(**kwargs)
@@ -281,11 +283,12 @@ def __create_port_configs(neutron, ports):
return out
-def __create_floatingip_config(neutron, port_settings):
+def __create_floatingip_config(neutron, keystone, port_settings, project_name):
"""
Returns a list of FloatingIpConfig objects as they pertain to an
existing deployed server instance
:param neutron: the neutron client
+ :param keystone: the keystone client
:param port_settings: list of SNAPS-OO PortConfig objects
:return: a list of FloatingIpConfig objects or an empty list if no
floating IPs have been created
@@ -296,10 +299,11 @@ def __create_floatingip_config(neutron, port_settings):
fip_ports = list()
for port_setting in port_settings:
- setting_port = neutron_utils.get_port(neutron, port_setting)
+ setting_port = neutron_utils.get_port(
+ neutron, keystone, port_setting, project_name=project_name)
if setting_port:
network = neutron_utils.get_network(
- neutron, network_name=port_setting.network_name)
+ neutron, keystone, network_name=port_setting.network_name)
network_ports = neutron_utils.get_ports(neutron, network)
if network_ports:
for setting_port in network_ports:
@@ -307,7 +311,7 @@ def __create_floatingip_config(neutron, port_settings):
fip_ports.append((port_setting.name, setting_port))
break
- floating_ips = neutron_utils.get_floating_ips(neutron, fip_ports)
+ floating_ips = neutron_utils.get_port_floating_ips(neutron, fip_ports)
for port_id, floating_ip in floating_ips:
router = neutron_utils.get_router_by_id(neutron, floating_ip.router_id)
diff --git a/snaps/openstack/utils/tests/cinder_utils_tests.py b/snaps/openstack/utils/tests/cinder_utils_tests.py
index b624b09..073d574 100644
--- a/snaps/openstack/utils/tests/cinder_utils_tests.py
+++ b/snaps/openstack/utils/tests/cinder_utils_tests.py
@@ -26,7 +26,7 @@ from snaps.openstack import create_volume
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
+from snaps.openstack.utils import cinder_utils, keystone_utils
__author__ = 'spisarski'
@@ -43,7 +43,7 @@ class CinderSmokeTests(OSComponentTestCase):
"""
Tests to ensure that the proper credentials can connect.
"""
- cinder = cinder_utils.cinder_client(self.os_creds)
+ cinder = cinder_utils.cinder_client(self.os_creds, self.os_session)
volumes = cinder.volumes.list()
self.assertIsNotNone(volumes)
self.assertTrue(isinstance(volumes, list))
@@ -74,7 +74,10 @@ class CinderUtilsVolumeTests(OSComponentTestCase):
guid = uuid.uuid4()
self.volume_name = self.__class__.__name__ + '-' + str(guid)
self.volume = None
- self.cinder = cinder_utils.cinder_client(self.os_creds)
+ self.cinder = cinder_utils.cinder_client(
+ self.os_creds, self.os_session)
+ self.keystone = keystone_utils.keystone_client(
+ self.os_creds, self.os_session)
def tearDown(self):
"""
@@ -94,14 +97,15 @@ class CinderUtilsVolumeTests(OSComponentTestCase):
"""
volume_settings = VolumeConfig(name=self.volume_name)
self.volume = cinder_utils.create_volume(
- self.cinder, volume_settings)
+ self.cinder, self.keystone, volume_settings)
self.assertIsNotNone(self.volume)
self.assertEqual(self.volume_name, self.volume.name)
self.assertTrue(volume_active(self.cinder, self.volume))
volume = cinder_utils.get_volume(
- self.cinder, volume_settings=volume_settings)
+ self.cinder, self.keystone, volume_settings=volume_settings,
+ project_name=self.os_creds.project_name)
self.assertIsNotNone(volume)
validation_utils.objects_equivalent(self.volume, volume)
@@ -111,21 +115,24 @@ class CinderUtilsVolumeTests(OSComponentTestCase):
"""
volume_settings = VolumeConfig(name=self.volume_name)
self.volume = cinder_utils.create_volume(
- self.cinder, volume_settings)
+ self.cinder, self.keystone, volume_settings)
self.assertIsNotNone(self.volume)
self.assertEqual(self.volume_name, self.volume.name)
self.assertTrue(volume_active(self.cinder, self.volume))
volume = cinder_utils.get_volume(
- self.cinder, volume_settings=volume_settings)
+ self.cinder, self.keystone, volume_settings=volume_settings,
+ project_name=self.os_creds.project_name)
self.assertIsNotNone(volume)
validation_utils.objects_equivalent(self.volume, volume)
cinder_utils.delete_volume(self.cinder, self.volume)
self.assertTrue(volume_deleted(self.cinder, self.volume))
self.assertIsNone(
- cinder_utils.get_volume(self.cinder, volume_settings))
+ cinder_utils.get_volume(
+ self.cinder, self.keystone, volume_settings,
+ project_name=self.os_creds.project_name))
def volume_active(cinder, volume):
@@ -181,7 +188,8 @@ class CinderUtilsQoSTests(OSComponentTestCase):
self.qos_name = self.__class__.__name__ + '-' + str(guid)
self.specs = {'foo': 'bar '}
self.qos = None
- self.cinder = cinder_utils.cinder_client(self.os_creds)
+ self.cinder = cinder_utils.cinder_client(
+ self.os_creds, self.os_session)
def tearDown(self):
"""
@@ -193,6 +201,8 @@ class CinderUtilsQoSTests(OSComponentTestCase):
except NotFound:
pass
+ super(self.__class__, self).__clean__()
+
def test_create_qos_both(self):
"""
Tests the cinder_utils.create_qos()
@@ -278,7 +288,8 @@ class CinderUtilsSimpleVolumeTypeTests(OSComponentTestCase):
volume_type_name = self.__class__.__name__ + '-' + str(guid)
self.volume_type_settings = VolumeTypeConfig(name=volume_type_name)
self.volume_type = None
- self.cinder = cinder_utils.cinder_client(self.os_creds)
+ self.cinder = cinder_utils.cinder_client(
+ self.os_creds, self.os_session)
def tearDown(self):
"""
@@ -290,6 +301,8 @@ class CinderUtilsSimpleVolumeTypeTests(OSComponentTestCase):
except NotFound:
pass
+ super(self.__class__, self).__clean__()
+
def test_create_simple_volume_type(self):
"""
Tests the cinder_utils.create_volume_type(), get_volume_type(), and
@@ -346,7 +359,8 @@ class CinderUtilsAddEncryptionTests(OSComponentTestCase):
self.encryption_name = self.__class__.__name__ + '-' + str(guid)
self.encryption = None
- self.cinder = cinder_utils.cinder_client(self.os_creds)
+ self.cinder = cinder_utils.cinder_client(
+ self.os_creds, self.os_session)
volume_type_name = self.__class__.__name__ + '-' + str(guid) + '-type'
self.volume_type = cinder_utils.create_volume_type(
@@ -369,6 +383,8 @@ class CinderUtilsAddEncryptionTests(OSComponentTestCase):
except NotFound:
pass
+ super(self.__class__, self).__clean__()
+
def test_create_simple_encryption(self):
"""
Tests the cinder_utils.create_volume_encryption(),
@@ -463,7 +479,8 @@ class CinderUtilsVolumeTypeCompleteTests(OSComponentTestCase):
self.qos_name = self.__class__.__name__ + '-' + str(guid) + '-qos'
self.vol_type_name = self.__class__.__name__ + '-' + str(guid)
self.specs = {'foo': 'bar'}
- self.cinder = cinder_utils.cinder_client(self.os_creds)
+ self.cinder = cinder_utils.cinder_client(
+ self.os_creds, self.os_session)
qos_settings = QoSConfig(
name=self.qos_name, specs=self.specs, consumer=Consumer.both)
self.qos = cinder_utils.create_qos(self.cinder, qos_settings)
@@ -491,6 +508,8 @@ class CinderUtilsVolumeTypeCompleteTests(OSComponentTestCase):
except NotFound:
pass
+ super(self.__class__, self).__clean__()
+
def test_create_with_encryption(self):
"""
Tests the cinder_utils.create_volume_type() where encryption has been
diff --git a/snaps/openstack/utils/tests/glance_utils_tests.py b/snaps/openstack/utils/tests/glance_utils_tests.py
index e61b795..e761ed8 100644
--- a/snaps/openstack/utils/tests/glance_utils_tests.py
+++ b/snaps/openstack/utils/tests/glance_utils_tests.py
@@ -39,7 +39,7 @@ class GlanceSmokeTests(OSComponentTestCase):
"""
Tests to ensure that the proper credentials can connect.
"""
- glance = glance_utils.glance_client(self.os_creds)
+ glance = glance_utils.glance_client(self.os_creds, self.os_session)
image = glance_utils.get_image(glance, image_name='foo')
self.assertIsNone(image)
@@ -69,7 +69,8 @@ class GlanceUtilsTests(OSComponentTestCase):
guid = uuid.uuid4()
self.image_name = self.__class__.__name__ + '-' + str(guid)
self.image = None
- self.glance = glance_utils.glance_client(self.os_creds)
+ self.glance = glance_utils.glance_client(
+ self.os_creds, self.os_session)
if self.image_metadata:
self.glance_test_meta = self.image_metadata.get('glance_tests')
else:
@@ -89,6 +90,8 @@ class GlanceUtilsTests(OSComponentTestCase):
if os.path.exists(self.tmp_dir) and os.path.isdir(self.tmp_dir):
shutil.rmtree(self.tmp_dir)
+ super(self.__class__, self).__clean__()
+
def test_create_image_minimal_url(self):
"""
Tests the glance_utils.create_image() function with a URL unless the
diff --git a/snaps/openstack/utils/tests/heat_utils_tests.py b/snaps/openstack/utils/tests/heat_utils_tests.py
index 67fbdec..fa240bd 100644
--- a/snaps/openstack/utils/tests/heat_utils_tests.py
+++ b/snaps/openstack/utils/tests/heat_utils_tests.py
@@ -31,7 +31,7 @@ from snaps.openstack.tests import openstack_tests
from snaps.openstack.tests.os_source_file_test import OSComponentTestCase
from snaps.openstack.utils import (
heat_utils, neutron_utils, nova_utils, settings_utils, glance_utils,
- cinder_utils)
+ cinder_utils, keystone_utils)
__author__ = 'spisarski'
@@ -47,12 +47,12 @@ class HeatSmokeTests(OSComponentTestCase):
"""
Tests to ensure that the proper credentials can connect.
"""
- heat = heat_utils.heat_client(self.os_creds)
+ heat = heat_utils.heat_client(self.os_creds, self.os_session)
# This should not throw an exception
stacks = heat.stacks.list()
for stack in stacks:
- print stack
+ logger.info('Stack - %s', stack)
def test_heat_connect_fail(self):
"""
@@ -70,7 +70,7 @@ class HeatSmokeTests(OSComponentTestCase):
# This should throw an exception
with self.assertRaises(Exception):
for stack in stacks:
- print stack
+ logger.info('Stack - %s', stack)
class HeatUtilsCreateSimpleStackTests(OSComponentTestCase):
@@ -115,7 +115,8 @@ class HeatUtilsCreateSimpleStackTests(OSComponentTestCase):
env_values=env_values)
self.stack1 = None
self.stack2 = None
- self.heat_client = heat_utils.heat_client(self.os_creds)
+ self.heat_client = heat_utils.heat_client(
+ self.os_creds, self.os_session)
def tearDown(self):
"""
@@ -145,6 +146,8 @@ class HeatUtilsCreateSimpleStackTests(OSComponentTestCase):
except:
pass
+ super(self.__class__, self).__clean__()
+
def test_create_stack(self):
"""
Tests the creation of an OpenStack Heat stack1 that does not exist.
@@ -174,7 +177,7 @@ class HeatUtilsCreateSimpleStackTests(OSComponentTestCase):
self.assertTrue(stack_active(self.heat_client, self.stack1))
- neutron = neutron_utils.neutron_client(self.os_creds)
+ neutron = neutron_utils.neutron_client(self.os_creds, self.os_session)
networks = heat_utils.get_stack_networks(
self.heat_client, neutron, self.stack1)
self.assertIsNotNone(networks)
@@ -185,9 +188,12 @@ class HeatUtilsCreateSimpleStackTests(OSComponentTestCase):
self.assertEqual(1, len(subnets))
self.assertEqual(self.subnet_name, subnets[0].name)
- nova = nova_utils.nova_client(self.os_creds)
+ nova = nova_utils.nova_client(self.os_creds, self.os_session)
+ keystone = keystone_utils.keystone_client(
+ self.os_creds, self.os_session)
servers = heat_utils.get_stack_servers(
- self.heat_client, nova, neutron, self.stack1)
+ self.heat_client, nova, neutron, keystone, self.stack1,
+ self.os_creds.project_name)
self.assertIsNotNone(servers)
self.assertEqual(1, len(servers))
self.assertEqual(self.vm_inst_name, servers[0].name)
@@ -275,7 +281,8 @@ class HeatUtilsCreateComplexStackTests(OSComponentTestCase):
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)
+ self.heat_client = heat_utils.heat_client(
+ self.os_creds, self.os_session)
self.stack = heat_utils.create_stack(self.heat_client, stack_settings)
self.assertTrue(stack_active(self.heat_client, self.stack))
@@ -307,14 +314,22 @@ class HeatUtilsCreateComplexStackTests(OSComponentTestCase):
time.sleep(3)
if not is_deleted:
- nova = nova_utils.nova_client(self.os_creds)
- neutron = neutron_utils.neutron_client(self.os_creds)
- glance = glance_utils.glance_client(self.os_creds)
+ nova = nova_utils.nova_client(
+ self.os_creds, self.os_session)
+ keystone = keystone_utils.keystone_client(
+ self.os_creds, self.os_session)
+ neutron = neutron_utils.neutron_client(
+ self.os_creds, self.os_session)
+ glance = glance_utils.glance_client(
+ self.os_creds, self.os_session)
+
servers = heat_utils.get_stack_servers(
- self.heat_client, nova, neutron, self.stack)
+ self.heat_client, nova, neutron, keystone, self.stack,
+ self.os_creds.project_name)
for server in servers:
vm_settings = settings_utils.create_vm_inst_config(
- nova, neutron, server)
+ nova, keystone, neutron, server,
+ self.os_creds.project_name)
img_settings = settings_utils.determine_image_config(
glance, server,
[self.image_creator1.image_settings,
@@ -354,6 +369,8 @@ class HeatUtilsCreateComplexStackTests(OSComponentTestCase):
os.chmod(expanded_path, 0o755)
os.remove(expanded_path)
+ super(self.__class__, self).__clean__()
+
def test_get_settings_from_stack(self):
"""
Tests that a heat template with floating IPs and can have the proper
@@ -361,13 +378,13 @@ class HeatUtilsCreateComplexStackTests(OSComponentTestCase):
"""
resources = heat_utils.get_resources(self.heat_client, self.stack.id)
self.assertIsNotNone(resources)
- self.assertEqual(12, len(resources))
+ self.assertEqual(13, len(resources))
options = heat_utils.get_outputs(self.heat_client, self.stack)
self.assertIsNotNone(options)
self.assertEqual(1, len(options))
- neutron = neutron_utils.neutron_client(self.os_creds)
+ neutron = neutron_utils.neutron_client(self.os_creds, self.os_session)
networks = heat_utils.get_stack_networks(
self.heat_client, neutron, self.stack)
self.assertIsNotNone(networks)
@@ -379,11 +396,13 @@ class HeatUtilsCreateComplexStackTests(OSComponentTestCase):
self.assertIsNotNone(network_settings)
self.assertEqual(self.network_name, network_settings.name)
- nova = nova_utils.nova_client(self.os_creds)
- glance = glance_utils.glance_client(self.os_creds)
-
+ nova = nova_utils.nova_client(self.os_creds, self.os_session)
+ glance = glance_utils.glance_client(self.os_creds, self.os_session)
+ keystone = keystone_utils.keystone_client(
+ self.os_creds, self.os_session)
servers = heat_utils.get_stack_servers(
- self.heat_client, nova, neutron, self.stack)
+ self.heat_client, nova, neutron, keystone, self.stack,
+ self.os_creds.project_name)
self.assertIsNotNone(servers)
self.assertEqual(2, len(servers))
@@ -452,8 +471,10 @@ class HeatUtilsRouterTests(OSComponentTestCase):
name=stack_name, template_path=heat_tmplt_path,
env_values=env_values)
self.stack = None
- self.heat_client = heat_utils.heat_client(self.os_creds)
- self.neutron = neutron_utils.neutron_client(self.os_creds)
+ self.heat_client = heat_utils.heat_client(
+ self.os_creds, self.os_session)
+ self.neutron = neutron_utils.neutron_client(
+ self.os_creds, self.os_session)
def tearDown(self):
"""
@@ -465,6 +486,8 @@ class HeatUtilsRouterTests(OSComponentTestCase):
except:
pass
+ super(self.__class__, self).__clean__()
+
def test_create_router_with_stack(self):
"""
Tests the creation of an OpenStack router with Heat and the retrieval
@@ -498,8 +521,10 @@ class HeatUtilsRouterTests(OSComponentTestCase):
router = routers[0]
self.assertEqual(self.router_name, router.name)
+ keystone = keystone_utils.keystone_client(
+ self.os_creds, self.os_session)
ext_net = neutron_utils.get_network(
- self.neutron, network_name=self.ext_net_name)
+ self.neutron, keystone, network_name=self.ext_net_name)
self.assertEqual(ext_net.id, router.external_network_id)
@@ -527,8 +552,10 @@ class HeatUtilsVolumeTests(OSComponentTestCase):
name=stack_name, template_path=heat_tmplt_path,
env_values=env_values)
self.stack = None
- self.heat_client = heat_utils.heat_client(self.os_creds)
- self.cinder = cinder_utils.cinder_client(self.os_creds)
+ self.heat_client = heat_utils.heat_client(
+ self.os_creds, self.os_session)
+ self.cinder = cinder_utils.cinder_client(
+ self.os_creds, self.os_session)
def tearDown(self):
"""
@@ -540,6 +567,8 @@ class HeatUtilsVolumeTests(OSComponentTestCase):
except:
pass
+ super(self.__class__, self).__clean__()
+
def test_create_vol_with_stack(self):
"""
Tests the creation of an OpenStack volume with Heat.
@@ -607,8 +636,10 @@ class HeatUtilsFlavorTests(OSComponentTestCase):
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)
- self.nova = nova_utils.nova_client(self.os_creds)
+ self.heat_client = heat_utils.heat_client(
+ self.os_creds, self.os_session)
+ self.nova = nova_utils.nova_client(
+ self.os_creds, self.os_session)
def tearDown(self):
"""
@@ -620,6 +651,8 @@ class HeatUtilsFlavorTests(OSComponentTestCase):
except:
pass
+ super(self.__class__, self).__clean__()
+
def test_create_flavor_with_stack(self):
"""
Tests the creation of an OpenStack volume with Heat.
@@ -666,8 +699,10 @@ class HeatUtilsKeypairTests(OSComponentTestCase):
name=stack_name, template_path=heat_tmplt_path,
env_values=env_values)
self.stack = None
- self.heat_client = heat_utils.heat_client(self.os_creds)
- self.nova = nova_utils.nova_client(self.os_creds)
+ self.heat_client = heat_utils.heat_client(
+ self.os_creds, self.os_session)
+ self.nova = nova_utils.nova_client(
+ self.os_creds, self.os_session)
def tearDown(self):
"""
@@ -679,6 +714,8 @@ class HeatUtilsKeypairTests(OSComponentTestCase):
except:
pass
+ super(self.__class__, self).__clean__()
+
def test_create_keypair_with_stack(self):
"""
Tests the creation of an OpenStack keypair with Heat.
@@ -729,8 +766,10 @@ class HeatUtilsSecurityGroupTests(OSComponentTestCase):
name=stack_name, template_path=heat_tmplt_path,
env_values=env_values)
self.stack = None
- self.heat_client = heat_utils.heat_client(self.os_creds)
- self.neutron = neutron_utils.neutron_client(self.os_creds)
+ self.heat_client = heat_utils.heat_client(
+ self.os_creds, self.os_session)
+ self.neutron = neutron_utils.neutron_client(
+ self.os_creds, self.os_session)
def tearDown(self):
"""
@@ -742,6 +781,8 @@ class HeatUtilsSecurityGroupTests(OSComponentTestCase):
except:
pass
+ super(self.__class__, self).__clean__()
+
def test_create_security_group_with_stack(self):
"""
Tests the creation of an OpenStack SecurityGroup with Heat.
diff --git a/snaps/openstack/utils/tests/keystone_utils_tests.py b/snaps/openstack/utils/tests/keystone_utils_tests.py
index b7f024d..cc3a8ad 100644
--- a/snaps/openstack/utils/tests/keystone_utils_tests.py
+++ b/snaps/openstack/utils/tests/keystone_utils_tests.py
@@ -31,7 +31,8 @@ class KeystoneSmokeTests(OSComponentTestCase):
"""
Tests to ensure that the proper credentials can connect.
"""
- keystone = keystone_utils.keystone_client(self.os_creds)
+ keystone = keystone_utils.keystone_client(
+ self.os_creds, self.os_session)
users = keystone.users.list()
self.assertIsNotNone(users)
@@ -66,17 +67,19 @@ class KeystoneUtilsTests(OSComponentTestCase):
self.project_name = self.guid + '-projName'
self.project = None
self.role = None
- self.keystone = keystone_utils.keystone_client(self.os_creds)
+ self.keystone = keystone_utils.keystone_client(
+ self.os_creds, self.os_session)
def tearDown(self):
"""
Cleans the remote OpenStack objects
"""
if self.project:
- neutron = neutron_utils.neutron_client(self.os_creds)
+ neutron = neutron_utils.neutron_client(
+ self.os_creds, self.os_session)
default_sec_grp = neutron_utils.get_security_group(
- neutron, sec_grp_name='default',
- project_id=self.project.id)
+ neutron, self.keystone, sec_grp_name='default',
+ project_name=self.os_creds.project_name)
if default_sec_grp:
try:
neutron_utils.delete_security_group(
@@ -92,6 +95,8 @@ class KeystoneUtilsTests(OSComponentTestCase):
if self.role:
keystone_utils.delete_role(self.keystone, self.role)
+ super(self.__class__, self).__clean__()
+
def test_create_user_minimal(self):
"""
Tests the keystone_utils.create_user() function
@@ -124,8 +129,11 @@ class KeystoneUtilsTests(OSComponentTestCase):
domain = keystone_utils.get_domain_by_id(
self.keystone, project.domain_id)
- self.assertIsNotNone(domain)
- self.assertEqual(domain.id, project.domain_id)
+ if self.keystone.version == keystone_utils.V2_VERSION_STR:
+ self.assertIsNone(domain)
+ else:
+ self.assertIsNotNone(domain)
+ self.assertEqual(domain.id, project.domain_id)
def test_get_endpoint_success(self):
"""
diff --git a/snaps/openstack/utils/tests/magnum_utils_tests.py b/snaps/openstack/utils/tests/magnum_utils_tests.py
index f841c48..d87d97a 100644
--- a/snaps/openstack/utils/tests/magnum_utils_tests.py
+++ b/snaps/openstack/utils/tests/magnum_utils_tests.py
@@ -44,7 +44,8 @@ class MagnumSmokeTests(OSComponentTestCase):
"""
Tests to ensure that the proper credentials can connect.
"""
- magnum = magnum_utils.magnum_client(self.os_creds)
+ magnum = magnum_utils.magnum_client(
+ self.os_creds, self.os_session)
# This should not throw an exception
self.assertIsNotNone(magnum.clusters.list())
@@ -70,7 +71,8 @@ class MagnumUtilsClusterTypeTests(OSComponentTestCase):
def setUp(self):
self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
self.cluster_type_name = self.guid + '-cluster-type'
- self.magnum = magnum_utils.magnum_client(self.os_creds)
+ self.magnum = magnum_utils.magnum_client(
+ self.os_creds, self.os_session)
metadata = self.image_metadata
if not metadata:
@@ -130,6 +132,8 @@ class MagnumUtilsClusterTypeTests(OSComponentTestCase):
except:
pass
+ super(self.__class__, self).__clean__()
+
def test_create_cluster_template_simple(self):
config = ClusterTemplateConfig(
name=self.cluster_type_name,
diff --git a/snaps/openstack/utils/tests/neutron_utils_tests.py b/snaps/openstack/utils/tests/neutron_utils_tests.py
index 38faf71..a55f779 100644
--- a/snaps/openstack/utils/tests/neutron_utils_tests.py
+++ b/snaps/openstack/utils/tests/neutron_utils_tests.py
@@ -41,7 +41,7 @@ class NeutronSmokeTests(OSComponentTestCase):
"""
Tests to ensure that the proper credentials can connect.
"""
- neutron = neutron_utils.neutron_client(self.os_creds)
+ neutron = neutron_utils.neutron_client(self.os_creds, self.os_session)
networks = neutron.list_networks()
@@ -70,7 +70,7 @@ class NeutronSmokeTests(OSComponentTestCase):
configured self.ext_net_name is contained within the returned list
:return:
"""
- neutron = neutron_utils.neutron_client(self.os_creds)
+ neutron = neutron_utils.neutron_client(self.os_creds, self.os_session)
ext_networks = neutron_utils.get_external_networks(neutron)
found = False
for network in ext_networks:
@@ -88,9 +88,13 @@ class NeutronUtilsNetworkTests(OSComponentTestCase):
def setUp(self):
guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
self.port_name = str(guid) + '-port'
- self.neutron = neutron_utils.neutron_client(self.os_creds)
+ self.neutron = neutron_utils.neutron_client(
+ self.os_creds, self.os_session)
+ self.keystone = keystone_utils.keystone_client(
+ self.os_creds, self.os_session)
self.network = None
self.net_config = openstack_tests.get_pub_net_config(
+ project_name=self.os_creds.project_name,
net_name=guid + '-pub-net')
def tearDown(self):
@@ -100,6 +104,8 @@ class NeutronUtilsNetworkTests(OSComponentTestCase):
if self.network:
neutron_utils.delete_network(self.neutron, self.network)
+ super(self.__class__, self).__clean__()
+
def test_create_network(self):
"""
Tests the neutron_utils.create_network() function
@@ -109,7 +115,9 @@ class NeutronUtilsNetworkTests(OSComponentTestCase):
self.assertEqual(self.net_config.network_settings.name,
self.network.name)
self.assertTrue(validate_network(
- self.neutron, self.net_config.network_settings.name, True))
+ self.neutron, self.keystone,
+ self.net_config.network_settings.name, True,
+ self.os_creds.project_name))
self.assertEqual(len(self.net_config.network_settings.subnet_settings),
len(self.network.subnets))
@@ -142,9 +150,13 @@ class NeutronUtilsSubnetTests(OSComponentTestCase):
def setUp(self):
guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
self.port_name = str(guid) + '-port'
- self.neutron = neutron_utils.neutron_client(self.os_creds)
+ self.neutron = neutron_utils.neutron_client(
+ self.os_creds, self.os_session)
+ self.keystone = keystone_utils.keystone_client(
+ self.os_creds, self.os_session)
self.network = None
self.net_config = openstack_tests.get_pub_net_config(
+ project_name=self.os_creds.project_name,
net_name=guid + '-pub-net', subnet_name=guid + '-pub-subnet',
external_net=self.ext_net_name)
@@ -158,6 +170,8 @@ class NeutronUtilsSubnetTests(OSComponentTestCase):
except:
pass
+ super(self.__class__, self).__clean__()
+
def test_create_subnet(self):
"""
Tests the neutron_utils.create_network() function
@@ -167,14 +181,17 @@ class NeutronUtilsSubnetTests(OSComponentTestCase):
self.assertEqual(self.net_config.network_settings.name,
self.network.name)
self.assertTrue(validate_network(
- self.neutron, self.net_config.network_settings.name, True))
+ self.neutron, self.keystone,
+ self.net_config.network_settings.name, True,
+ self.os_creds.project_name))
subnet_setting = self.net_config.network_settings.subnet_settings[0]
self.assertTrue(validate_subnet(
- self.neutron, subnet_setting.name, subnet_setting.cidr, True))
+ self.neutron, self.network, subnet_setting.name,
+ subnet_setting.cidr, True))
subnet_query1 = neutron_utils.get_subnet(
- self.neutron, subnet_name=subnet_setting.name)
+ self.neutron, self.network, subnet_name=subnet_setting.name)
self.assertEqual(self.network.subnets[0], subnet_query1)
subnet_query2 = neutron_utils.get_subnets_by_network(self.neutron,
@@ -183,6 +200,12 @@ class NeutronUtilsSubnetTests(OSComponentTestCase):
self.assertEqual(1, len(subnet_query2))
self.assertEqual(self.network.subnets[0], subnet_query2[0])
+ subnet_query3 = neutron_utils.get_subnet_by_name(
+ self.neutron, self.keystone, subnet_setting.name,
+ self.os_creds.project_name)
+ self.assertIsNotNone(subnet_query3)
+ self.assertEqual(self.network.subnets[0], subnet_query3)
+
def test_create_subnet_null_name(self):
"""
Tests the neutron_utils.create_neutron_subnet() function for an
@@ -193,7 +216,9 @@ class NeutronUtilsSubnetTests(OSComponentTestCase):
self.assertEqual(self.net_config.network_settings.name,
self.network.name)
self.assertTrue(validate_network(
- self.neutron, self.net_config.network_settings.name, True))
+ self.neutron, self.keystone,
+ self.net_config.network_settings.name, True,
+ self.os_creds.project_name))
with self.assertRaises(Exception):
SubnetConfig(cidr=self.net_config.subnet_cidr)
@@ -208,20 +233,23 @@ class NeutronUtilsSubnetTests(OSComponentTestCase):
self.assertEqual(self.net_config.network_settings.name,
self.network.name)
self.assertTrue(validate_network(
- self.neutron, self.net_config.network_settings.name, True))
+ self.neutron, self.keystone,
+ self.net_config.network_settings.name, True,
+ self.os_creds.project_name))
subnet_setting = self.net_config.network_settings.subnet_settings[0]
self.assertTrue(validate_subnet(
- self.neutron, subnet_setting.name, subnet_setting.cidr, True))
+ self.neutron, self.network, subnet_setting.name,
+ subnet_setting.cidr, True))
self.assertFalse(validate_subnet(
- self.neutron, '', subnet_setting.cidr, True))
+ self.neutron, self.network, '', subnet_setting.cidr, True))
subnet_query1 = neutron_utils.get_subnet(
- self.neutron, subnet_name=subnet_setting.name)
+ self.neutron, self.network, subnet_name=subnet_setting.name)
self.assertEqual(self.network.subnets[0], subnet_query1)
- subnet_query2 = neutron_utils.get_subnets_by_network(self.neutron,
- self.network)
+ subnet_query2 = neutron_utils.get_subnets_by_network(
+ self.neutron, self.network)
self.assertIsNotNone(subnet_query2)
self.assertEqual(1, len(subnet_query2))
self.assertEqual(self.network.subnets[0], subnet_query2[0])
@@ -254,7 +282,8 @@ class NeutronUtilsIPv6Tests(OSComponentTestCase):
def setUp(self):
self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
- self.neutron = neutron_utils.neutron_client(self.os_creds)
+ self.neutron = neutron_utils.neutron_client(
+ self.os_creds, self.os_session)
self.network = None
def tearDown(self):
@@ -267,6 +296,8 @@ class NeutronUtilsIPv6Tests(OSComponentTestCase):
except:
pass
+ super(self.__class__, self).__clean__()
+
def test_create_network_slaac(self):
"""
Tests the neutron_utils.create_network() with an IPv6 subnet where DHCP
@@ -455,7 +486,7 @@ class NeutronUtilsIPv6Tests(OSComponentTestCase):
"""
sub_setting = SubnetConfig(
name=self.guid + '-subnet', cidr='1:1::/48', ip_version=6,
- gateway_ip='1:2::1')
+ gateway_ip='192.168.0.1')
self.network_settings = NetworkConfig(
name=self.guid + '-net', subnet_settings=[sub_setting])
@@ -487,12 +518,16 @@ class NeutronUtilsRouterTests(OSComponentTestCase):
def setUp(self):
guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
self.port_name = str(guid) + '-port'
- self.neutron = neutron_utils.neutron_client(self.os_creds)
+ self.neutron = neutron_utils.neutron_client(
+ self.os_creds, self.os_session)
+ self.keystone = keystone_utils.keystone_client(
+ self.os_creds, self.os_session)
self.network = None
self.port = None
self.router = None
self.interface_router = None
self.net_config = openstack_tests.get_pub_net_config(
+ project_name=self.os_creds.project_name,
net_name=guid + '-pub-net', subnet_name=guid + '-pub-subnet',
router_name=guid + '-pub-router', external_net=self.ext_net_name)
@@ -507,7 +542,9 @@ class NeutronUtilsRouterTests(OSComponentTestCase):
if self.router:
try:
neutron_utils.delete_router(self.neutron, self.router)
- validate_router(self.neutron, self.router.name, False)
+ validate_router(
+ self.neutron, self.keystone, self.router.name,
+ self.os_creds.project_name, False)
except:
pass
@@ -520,14 +557,17 @@ class NeutronUtilsRouterTests(OSComponentTestCase):
if self.network:
neutron_utils.delete_network(self.neutron, self.network)
+ super(self.__class__, self).__clean__()
+
def test_create_router_simple(self):
"""
Tests the neutron_utils.create_router()
"""
self.router = neutron_utils.create_router(
self.neutron, self.os_creds, self.net_config.router_settings)
- validate_router(self.neutron, self.net_config.router_settings.name,
- True)
+ validate_router(
+ self.neutron, self.keystone, self.net_config.router_settings.name,
+ self.os_creds.project_name, True)
def test_create_router_with_public_interface(self):
"""
@@ -535,18 +575,19 @@ class NeutronUtilsRouterTests(OSComponentTestCase):
"""
subnet_setting = self.net_config.network_settings.subnet_settings[0]
self.net_config = openstack_tests.OSNetworkConfig(
- self.net_config.network_settings.name,
- subnet_setting.name,
- subnet_setting.cidr,
- self.net_config.router_settings.name,
- self.ext_net_name)
+ project_name=self.os_creds.project_name,
+ net_name=self.net_config.network_settings.name,
+ subnet_name=subnet_setting.name, subnet_cidr=subnet_setting.cidr,
+ router_name=self.net_config.router_settings.name,
+ external_gateway=self.ext_net_name)
self.router = neutron_utils.create_router(
self.neutron, self.os_creds, self.net_config.router_settings)
- validate_router(self.neutron, self.net_config.router_settings.name,
- True)
+ validate_router(
+ self.neutron, self.keystone, self.net_config.router_settings.name,
+ self.os_creds.project_name, True)
ext_net = neutron_utils.get_network(
- self.neutron, network_name=self.ext_net_name)
+ self.neutron, self.keystone, network_name=self.ext_net_name)
self.assertEqual(self.router.external_network_id, ext_net.id)
def test_add_interface_router(self):
@@ -558,16 +599,20 @@ class NeutronUtilsRouterTests(OSComponentTestCase):
self.assertEqual(self.net_config.network_settings.name,
self.network.name)
self.assertTrue(validate_network(
- self.neutron, self.net_config.network_settings.name, True))
+ self.neutron, self.keystone,
+ self.net_config.network_settings.name, True,
+ self.os_creds.project_name))
subnet_setting = self.net_config.network_settings.subnet_settings[0]
self.assertTrue(validate_subnet(
- self.neutron, subnet_setting.name, subnet_setting.cidr, True))
+ self.neutron, self.network, subnet_setting.name,
+ subnet_setting.cidr, True))
self.router = neutron_utils.create_router(
self.neutron, self.os_creds, self.net_config.router_settings)
- validate_router(self.neutron, self.net_config.router_settings.name,
- True)
+ validate_router(
+ self.neutron, self.keystone, self.net_config.router_settings.name,
+ self.os_creds.project_name, True)
self.interface_router = neutron_utils.add_interface_router(
self.neutron, self.router, self.network.subnets[0])
@@ -584,11 +629,14 @@ class NeutronUtilsRouterTests(OSComponentTestCase):
self.assertEqual(self.net_config.network_settings.name,
self.network.name)
self.assertTrue(validate_network(
- self.neutron, self.net_config.network_settings.name, True))
+ self.neutron, self.keystone,
+ self.net_config.network_settings.name, True,
+ self.os_creds.project_name))
subnet_setting = self.net_config.network_settings.subnet_settings[0]
self.assertTrue(validate_subnet(
- self.neutron, subnet_setting.name, subnet_setting.cidr, True))
+ self.neutron, self.network, subnet_setting.name,
+ subnet_setting.cidr, True))
with self.assertRaises(NeutronException):
self.interface_router = neutron_utils.add_interface_router(
@@ -604,12 +652,15 @@ class NeutronUtilsRouterTests(OSComponentTestCase):
self.assertEqual(self.net_config.network_settings.name,
self.network.name)
self.assertTrue(validate_network(
- self.neutron, self.net_config.network_settings.name, True))
+ self.neutron, self.keystone,
+ self.net_config.network_settings.name, True,
+ self.os_creds.project_name))
self.router = neutron_utils.create_router(
self.neutron, self.os_creds, self.net_config.router_settings)
- validate_router(self.neutron, self.net_config.router_settings.name,
- True)
+ validate_router(
+ self.neutron, self.keystone, self.net_config.router_settings.name,
+ self.os_creds.project_name, True)
with self.assertRaises(NeutronException):
self.interface_router = neutron_utils.add_interface_router(
@@ -625,12 +676,15 @@ class NeutronUtilsRouterTests(OSComponentTestCase):
self.assertEqual(self.net_config.network_settings.name,
self.network.name)
self.assertTrue(validate_network(
- self.neutron, self.net_config.network_settings.name, True))
+ self.neutron, self.keystone,
+ self.net_config.network_settings.name, True,
+ self.os_creds.project_name))
self.router = neutron_utils.create_router(
self.neutron, self.os_creds, self.net_config.router_settings)
- validate_router(self.neutron, self.net_config.router_settings.name,
- True)
+ validate_router(
+ self.neutron, self.keystone, self.net_config.router_settings.name,
+ self.os_creds.project_name, True)
for subnet in self.network.subnets:
neutron_utils.delete_subnet(self.neutron, subnet)
@@ -648,11 +702,14 @@ class NeutronUtilsRouterTests(OSComponentTestCase):
self.assertEqual(self.net_config.network_settings.name,
self.network.name)
self.assertTrue(validate_network(
- self.neutron, self.net_config.network_settings.name, True))
+ self.neutron, self.keystone,
+ self.net_config.network_settings.name, True,
+ self.os_creds.project_name))
subnet_setting = self.net_config.network_settings.subnet_settings[0]
self.assertTrue(validate_subnet(
- self.neutron, subnet_setting.name, subnet_setting.cidr, True))
+ self.neutron, self.network, subnet_setting.name,
+ subnet_setting.cidr, True))
self.port = neutron_utils.create_port(
self.neutron, self.os_creds, PortConfig(
@@ -672,11 +729,14 @@ class NeutronUtilsRouterTests(OSComponentTestCase):
self.assertEqual(self.net_config.network_settings.name,
self.network.name)
self.assertTrue(validate_network(
- self.neutron, self.net_config.network_settings.name, True))
+ self.neutron, self.keystone,
+ self.net_config.network_settings.name, True,
+ self.os_creds.project_name))
subnet_setting = self.net_config.network_settings.subnet_settings[0]
- self.assertTrue(validate_subnet(self.neutron, subnet_setting.name,
- subnet_setting.cidr, True))
+ self.assertTrue(validate_subnet(
+ self.neutron, self.network, subnet_setting.name,
+ subnet_setting.cidr, True))
self.port = neutron_utils.create_port(
self.neutron, self.os_creds, PortConfig(
@@ -696,11 +756,14 @@ class NeutronUtilsRouterTests(OSComponentTestCase):
self.assertEqual(self.net_config.network_settings.name,
self.network.name)
self.assertTrue(validate_network(
- self.neutron, self.net_config.network_settings.name, True))
+ self.neutron, self.keystone,
+ self.net_config.network_settings.name, True,
+ self.os_creds.project_name))
subnet_setting = self.net_config.network_settings.subnet_settings[0]
self.assertTrue(validate_subnet(
- self.neutron, subnet_setting.name, subnet_setting.cidr, True))
+ self.neutron, self.network, subnet_setting.name,
+ subnet_setting.cidr, True))
self.port = neutron_utils.create_port(
self.neutron, self.os_creds,
@@ -740,11 +803,14 @@ class NeutronUtilsRouterTests(OSComponentTestCase):
self.assertEqual(self.net_config.network_settings.name,
self.network.name)
self.assertTrue(validate_network(
- self.neutron, self.net_config.network_settings.name, True))
+ self.neutron, self.keystone,
+ self.net_config.network_settings.name, True,
+ self.os_creds.project_name))
subnet_setting = self.net_config.network_settings.subnet_settings[0]
self.assertTrue(validate_subnet(
- self.neutron, subnet_setting.name, subnet_setting.cidr, True))
+ self.neutron, self.network, subnet_setting.name,
+ subnet_setting.cidr, True))
with self.assertRaises(Exception):
self.port = neutron_utils.create_port(
@@ -766,11 +832,14 @@ class NeutronUtilsRouterTests(OSComponentTestCase):
self.assertEqual(self.net_config.network_settings.name,
self.network.name)
self.assertTrue(validate_network(
- self.neutron, self.net_config.network_settings.name, True))
+ self.neutron, self.keystone,
+ self.net_config.network_settings.name, True,
+ self.os_creds.project_name))
subnet_setting = self.net_config.network_settings.subnet_settings[0]
self.assertTrue(validate_subnet(
- self.neutron, subnet_setting.name, subnet_setting.cidr, True))
+ self.neutron, self.network, subnet_setting.name,
+ subnet_setting.cidr, True))
with self.assertRaises(Exception):
self.port = neutron_utils.create_port(
@@ -792,11 +861,14 @@ class NeutronUtilsRouterTests(OSComponentTestCase):
self.assertEqual(self.net_config.network_settings.name,
self.network.name)
self.assertTrue(validate_network(
- self.neutron, self.net_config.network_settings.name, True))
+ self.neutron, self.keystone,
+ self.net_config.network_settings.name, True,
+ self.os_creds.project_name))
subnet_setting = self.net_config.network_settings.subnet_settings[0]
self.assertTrue(validate_subnet(
- self.neutron, subnet_setting.name, subnet_setting.cidr, True))
+ self.neutron, self.network, subnet_setting.name,
+ subnet_setting.cidr, True))
with self.assertRaises(Exception):
self.port = neutron_utils.create_port(
@@ -820,8 +892,10 @@ class NeutronUtilsSecurityGroupTests(OSComponentTestCase):
self.security_groups = list()
self.security_group_rules = list()
- self.neutron = neutron_utils.neutron_client(self.os_creds)
- self.keystone = keystone_utils.keystone_client(self.os_creds)
+ self.neutron = neutron_utils.neutron_client(
+ self.os_creds, self.os_session)
+ self.keystone = keystone_utils.keystone_client(
+ self.os_creds, self.os_session)
def tearDown(self):
"""
@@ -837,26 +911,27 @@ class NeutronUtilsSecurityGroupTests(OSComponentTestCase):
except:
pass
+ super(self.__class__, self).__clean__()
+
def test_create_delete_simple_sec_grp(self):
"""
Tests the neutron_utils.create_security_group() function
"""
sec_grp_settings = SecurityGroupConfig(name=self.sec_grp_name)
- security_group = neutron_utils.create_security_group(self.neutron,
- self.keystone,
- sec_grp_settings)
+ security_group = neutron_utils.create_security_group(
+ self.neutron, self.keystone, sec_grp_settings)
self.assertTrue(sec_grp_settings.name, security_group.name)
sec_grp_get = neutron_utils.get_security_group(
- self.neutron, sec_grp_settings=sec_grp_settings)
+ self.neutron, self.keystone, sec_grp_settings=sec_grp_settings)
self.assertIsNotNone(sec_grp_get)
self.assertTrue(validation_utils.objects_equivalent(
security_group, sec_grp_get))
neutron_utils.delete_security_group(self.neutron, security_group)
sec_grp_get = neutron_utils.get_security_group(
- self.neutron, sec_grp_settings=sec_grp_settings)
+ self.neutron, self.keystone, sec_grp_settings=sec_grp_settings)
self.assertIsNone(sec_grp_get)
def test_create_sec_grp_no_name(self):
@@ -869,9 +944,8 @@ class NeutronUtilsSecurityGroupTests(OSComponentTestCase):
with self.assertRaises(Exception):
sec_grp_settings = SecurityGroupConfig()
self.security_groups.append(
- neutron_utils.create_security_group(self.neutron,
- self.keystone,
- sec_grp_settings))
+ neutron_utils.create_security_group(
+ self.neutron, self.keystone, sec_grp_settings))
def test_create_sec_grp_no_rules(self):
"""
@@ -880,14 +954,14 @@ class NeutronUtilsSecurityGroupTests(OSComponentTestCase):
sec_grp_settings = SecurityGroupConfig(
name=self.sec_grp_name, description='hello group')
self.security_groups.append(
- neutron_utils.create_security_group(self.neutron, self.keystone,
- sec_grp_settings))
+ neutron_utils.create_security_group(
+ self.neutron, self.keystone, sec_grp_settings))
self.assertTrue(sec_grp_settings.name, self.security_groups[0].name)
self.assertEqual(sec_grp_settings.name, self.security_groups[0].name)
sec_grp_get = neutron_utils.get_security_group(
- self.neutron, sec_grp_settings=sec_grp_settings)
+ self.neutron, self.keystone, sec_grp_settings=sec_grp_settings)
self.assertIsNotNone(sec_grp_get)
self.assertEqual(self.security_groups[0], sec_grp_get)
@@ -903,23 +977,26 @@ class NeutronUtilsSecurityGroupTests(OSComponentTestCase):
rule_settings=[sec_grp_rule_settings])
self.security_groups.append(
- neutron_utils.create_security_group(self.neutron, self.keystone,
- sec_grp_settings))
+ neutron_utils.create_security_group(
+ self.neutron, self.keystone, sec_grp_settings))
free_rules = neutron_utils.get_rules_by_security_group(
self.neutron, self.security_groups[0])
for free_rule in free_rules:
self.security_group_rules.append(free_rule)
+ keystone = keystone_utils.keystone_client(
+ self.os_creds, self.os_session)
self.security_group_rules.append(
neutron_utils.create_security_group_rule(
- self.neutron, sec_grp_settings.rule_settings[0]))
+ self.neutron, keystone, sec_grp_settings.rule_settings[0],
+ self.os_creds.project_name))
# Refresh object so it is populated with the newly added rule
security_group = neutron_utils.get_security_group(
- self.neutron, sec_grp_settings=sec_grp_settings)
+ self.neutron, self.keystone, sec_grp_settings=sec_grp_settings)
- rules = neutron_utils.get_rules_by_security_group(self.neutron,
- security_group)
+ rules = neutron_utils.get_rules_by_security_group(
+ self.neutron, security_group)
self.assertTrue(
validation_utils.objects_equivalent(
@@ -928,7 +1005,7 @@ class NeutronUtilsSecurityGroupTests(OSComponentTestCase):
self.assertTrue(sec_grp_settings.name, security_group.name)
sec_grp_get = neutron_utils.get_security_group(
- self.neutron, sec_grp_settings=sec_grp_settings)
+ self.neutron, self.keystone, sec_grp_settings=sec_grp_settings)
self.assertIsNotNone(sec_grp_get)
self.assertEqual(security_group, sec_grp_get)
@@ -954,6 +1031,33 @@ class NeutronUtilsSecurityGroupTests(OSComponentTestCase):
self.assertEqual(self.security_groups[0].id, sec_grp_1b.id)
self.assertEqual(self.security_groups[1].id, sec_grp_2b.id)
+ def test_create_list_sec_grp_no_rules(self):
+ """
+ Tests the neutron_utils.create_security_group() and
+ list_security_groups function
+ """
+ sec_grp_settings = SecurityGroupConfig(
+ name=self.sec_grp_name + "-1", description='hello group')
+ self.security_groups.append(neutron_utils.create_security_group(
+ self.neutron, self.keystone, sec_grp_settings))
+
+ sec_grp_settings2 = SecurityGroupConfig(
+ name=self.sec_grp_name + "-2", description='hola group')
+ self.security_groups.append(neutron_utils.create_security_group(
+ self.neutron, self.keystone, sec_grp_settings2))
+
+ returned_sec_groups = neutron_utils.list_security_groups(self.neutron)
+
+ self.assertIsNotNone(returned_sec_groups)
+ worked = 0
+ for sg in returned_sec_groups:
+ if sec_grp_settings.name == sg.name:
+ worked += 1
+ elif sec_grp_settings2.name == sg.name:
+ worked += 1
+
+ self.assertEqual(worked, 2)
+
class NeutronUtilsFloatingIpTests(OSComponentTestCase):
"""
@@ -965,7 +1069,10 @@ class NeutronUtilsFloatingIpTests(OSComponentTestCase):
Instantiates the CreateImage object that is responsible for downloading
and creating an OS image file within OpenStack
"""
- self.neutron = neutron_utils.neutron_client(self.os_creds)
+ self.neutron = neutron_utils.neutron_client(
+ self.os_creds, self.os_session)
+ self.keystone = keystone_utils.keystone_client(
+ self.os_creds, self.os_session)
self.floating_ip = None
def tearDown(self):
@@ -979,6 +1086,8 @@ class NeutronUtilsFloatingIpTests(OSComponentTestCase):
except:
pass
+ super(self.__class__, self).__clean__()
+
def test_floating_ips(self):
"""
Tests the creation of a floating IP
@@ -986,8 +1095,8 @@ class NeutronUtilsFloatingIpTests(OSComponentTestCase):
"""
initial_fips = neutron_utils.get_floating_ips(self.neutron)
- self.floating_ip = neutron_utils.create_floating_ip(self.neutron,
- self.ext_net_name)
+ self.floating_ip = neutron_utils.create_floating_ip(
+ self.neutron, self.keystone, self.ext_net_name)
all_fips = neutron_utils.get_floating_ips(self.neutron)
self.assertEqual(len(initial_fips) + 1, len(all_fips))
returned = neutron_utils.get_floating_ip(self.neutron,
@@ -1001,36 +1110,43 @@ Validation routines
"""
-def validate_network(neutron, name, exists):
+def validate_network(neutron, keystone, name, exists, project_name, mtu=None):
"""
Returns true if a network for a given name DOES NOT exist if the exists
parameter is false conversely true. Returns false if a network for a given
name DOES exist if the exists parameter is true conversely false.
:param neutron: The neutron client
+ :param keystone: The keystone client
:param name: The expected network name
:param exists: Whether or not the network name should exist or not
+ :param project_name: the associated project name
:return: True/False
"""
- network = neutron_utils.get_network(neutron, network_name=name)
+ network = neutron_utils.get_network(
+ neutron, keystone, network_name=name, project_name=project_name)
if exists and network:
return True
if not exists and not network:
return True
+ if mtu:
+ return mtu == network.mtu
return False
-def validate_subnet(neutron, name, cidr, exists):
+def validate_subnet(neutron, network, name, cidr, exists):
"""
Returns true if a subnet for a given name DOES NOT exist if the exists
parameter is false conversely true. Returns false if a subnet for a given
name DOES exist if the exists parameter is true conversely false.
:param neutron: The neutron client
+ :param network: The SNAPS-OO Network domain object
:param name: The expected subnet name
:param cidr: The expected CIDR value
:param exists: Whether or not the network name should exist or not
:return: True/False
"""
- subnet = neutron_utils.get_subnet(neutron, subnet_name=name)
+ subnet = neutron_utils.get_subnet(
+ neutron, network, subnet_name=name)
if exists and subnet and subnet.name == name:
return subnet.cidr == cidr
if not exists and not subnet:
@@ -1038,17 +1154,21 @@ def validate_subnet(neutron, name, cidr, exists):
return False
-def validate_router(neutron, name, exists):
+def validate_router(neutron, keystone, name, project_name, exists):
"""
Returns true if a router for a given name DOES NOT exist if the exists
parameter is false conversely true. Returns false if a router for a given
name DOES exist if the exists parameter is true conversely false.
:param neutron: The neutron client
+ :param keystone: The keystone client
:param name: The expected router name
+ :param project_name: The name of the project in which the router should
+ exist
:param exists: Whether or not the network name should exist or not
:return: True/False
"""
- router = neutron_utils.get_router(neutron, router_name=name)
+ router = neutron_utils.get_router(
+ neutron, keystone, router_name=name, project_name=project_name)
if exists and router:
return True
return False
diff --git a/snaps/openstack/utils/tests/nova_utils_tests.py b/snaps/openstack/utils/tests/nova_utils_tests.py
index 8cb0812..7c343f8 100644
--- a/snaps/openstack/utils/tests/nova_utils_tests.py
+++ b/snaps/openstack/utils/tests/nova_utils_tests.py
@@ -32,7 +32,8 @@ 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 (
- nova_utils, neutron_utils, glance_utils, cinder_utils)
+ nova_utils, neutron_utils, glance_utils, cinder_utils, keystone_utils)
+from snaps.openstack.utils.nova_utils import NovaException
__author__ = 'spisarski'
@@ -48,7 +49,7 @@ class NovaSmokeTests(OSComponentTestCase):
"""
Tests to ensure that the proper credentials can connect.
"""
- nova = nova_utils.nova_client(self.os_creds)
+ nova = nova_utils.nova_client(self.os_creds, self.os_session)
# This should not throw an exception
nova.flavors.list()
@@ -57,7 +58,7 @@ class NovaSmokeTests(OSComponentTestCase):
"""
Tests to ensure that get_hypervisors() function works.
"""
- nova = nova_utils.nova_client(self.os_creds)
+ nova = nova_utils.nova_client(self.os_creds, self.os_session)
hosts = nova_utils.get_hypervisor_hosts(nova)
# This should not throw an exception
@@ -94,7 +95,7 @@ class NovaUtilsKeypairTests(OSComponentTestCase):
self.priv_key_file_path = 'tmp/' + guid
self.pub_key_file_path = self.priv_key_file_path + '.pub'
- self.nova = nova_utils.nova_client(self.os_creds)
+ self.nova = nova_utils.nova_client(self.os_creds, self.os_session)
self.keys = nova_utils.create_keys()
self.public_key = nova_utils.public_key_openssh(self.keys)
self.keypair_name = guid
@@ -122,6 +123,8 @@ class NovaUtilsKeypairTests(OSComponentTestCase):
except:
pass
+ super(self.__class__, self).__clean__()
+
def test_create_keypair(self):
"""
Tests the creation of an OpenStack keypair that does not exist.
@@ -175,7 +178,7 @@ class NovaUtilsFlavorTests(OSComponentTestCase):
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.nova = nova_utils.nova_client(self.os_creds, self.os_session)
self.flavor = None
def tearDown(self):
@@ -188,6 +191,8 @@ class NovaUtilsFlavorTests(OSComponentTestCase):
except:
pass
+ super(self.__class__, self).__clean__()
+
def test_create_flavor(self):
"""
Tests the creation of an OpenStack keypair that does not exist.
@@ -241,9 +246,14 @@ class NovaUtilsInstanceTests(OSComponentTestCase):
guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
- self.nova = nova_utils.nova_client(self.os_creds)
- self.neutron = neutron_utils.neutron_client(self.os_creds)
- self.glance = glance_utils.glance_client(self.os_creds)
+ self.nova = nova_utils.nova_client(
+ self.os_creds, self.os_session)
+ self.keystone = keystone_utils.keystone_client(
+ self.os_creds, self.os_session)
+ self.neutron = neutron_utils.neutron_client(
+ self.os_creds, self.os_session)
+ self.glance = glance_utils.glance_client(
+ self.os_creds, self.os_session)
self.image_creator = None
self.network_creator = None
@@ -259,15 +269,17 @@ class NovaUtilsInstanceTests(OSComponentTestCase):
self.image_creator.create()
network_settings = openstack_tests.get_priv_net_config(
- guid + '-net', guid + '-subnet').network_settings
+ project_name=self.os_creds.project_name,
+ net_name="{}-{}".format(guid, 'net'),
+ subnet_name="{}-{}".format(guid, 'subnet')).network_settings
self.network_creator = OpenStackNetwork(
self.os_creds, network_settings)
self.network_creator.create()
- self.flavor_creator = OpenStackFlavor(
- self.os_creds,
- FlavorConfig(
- name=guid + '-flavor-name', ram=256, disk=10, vcpus=1))
+ flavor_config = openstack_tests.get_flavor_config(
+ name="{}-{}".format(guid, 'flavor-name'), ram=256, disk=10,
+ vcpus=1, metadata=self.flavor_metadata)
+ self.flavor_creator = OpenStackFlavor(self.os_creds, flavor_config)
self.flavor_creator.create()
port_settings = PortConfig(
@@ -314,6 +326,8 @@ class NovaUtilsInstanceTests(OSComponentTestCase):
except:
pass
+ super(self.__class__, self).__clean__()
+
def test_create_instance(self):
"""
Tests the nova_utils.create_server() method
@@ -321,26 +335,30 @@ class NovaUtilsInstanceTests(OSComponentTestCase):
"""
self.vm_inst = nova_utils.create_server(
- self.nova, self.neutron, self.glance, self.instance_settings,
- self.image_creator.image_settings)
+ self.nova, self.keystone, self.neutron, self.glance,
+ self.instance_settings, self.image_creator.image_settings,
+ self.os_creds.project_name)
self.assertIsNotNone(self.vm_inst)
# Wait until instance is ACTIVE
iters = 0
active = False
+ status = None
while iters < 60:
- if create_instance.STATUS_ACTIVE == nova_utils.get_server_status(
- self.nova, self.vm_inst):
+ status = nova_utils.get_server_status(self.nova, self.vm_inst)
+ if create_instance.STATUS_ACTIVE == status:
active = True
break
time.sleep(3)
iters += 1
- self.assertTrue(active)
+ self.assertTrue(active, msg='VM {} status {} is not {}'.format(
+ self.vm_inst.name, status, create_instance.STATUS_ACTIVE))
vm_inst = nova_utils.get_latest_server_object(
- self.nova, self.neutron, self.vm_inst)
+ self.nova, self.neutron, self.keystone, self.vm_inst,
+ self.os_creds.project_name)
self.assertEqual(self.vm_inst.name, vm_inst.name)
self.assertEqual(self.vm_inst.id, vm_inst.id)
@@ -359,8 +377,9 @@ class NovaUtilsInstanceVolumeTests(OSComponentTestCase):
guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
- self.nova = nova_utils.nova_client(self.os_creds)
- self.cinder = cinder_utils.cinder_client(self.os_creds)
+ self.nova = nova_utils.nova_client(self.os_creds, self.os_session)
+ self.cinder = cinder_utils.cinder_client(
+ self.os_creds, self.os_session)
self.image_creator = None
self.network_creator = None
@@ -376,15 +395,19 @@ class NovaUtilsInstanceVolumeTests(OSComponentTestCase):
self.image_creator.create()
network_settings = openstack_tests.get_priv_net_config(
- guid + '-net', guid + '-subnet').network_settings
+ project_name=self.os_creds.project_name,
+ net_name="{}-{}".format(guid, 'net'),
+ subnet_name="{}-{}".format(guid, 'subnet')).network_settings
+
self.network_creator = OpenStackNetwork(
self.os_creds, network_settings)
self.network_creator.create()
+ flavor_settings = openstack_tests.get_flavor_config(
+ name=guid + '-flavor', ram=256, disk=10, vcpus=1,
+ metadata=self.flavor_metadata)
self.flavor_creator = OpenStackFlavor(
- self.os_creds,
- FlavorConfig(
- name=guid + '-flavor-name', ram=256, disk=10, vcpus=1))
+ self.os_creds, flavor_settings)
self.flavor_creator.create()
# Create Volume
@@ -438,9 +461,12 @@ class NovaUtilsInstanceVolumeTests(OSComponentTestCase):
except:
pass
+ super(self.__class__, self).__clean__()
+
def test_add_remove_volume(self):
"""
- Tests the nova_utils.create_server() method
+ Tests the nova_utils.attach_volume() and detach_volume functions with
+ a timeout value
:return:
"""
@@ -448,29 +474,36 @@ class NovaUtilsInstanceVolumeTests(OSComponentTestCase):
self.assertEqual(0, len(self.volume_creator.get_volume().attachments))
# Attach volume to VM
- neutron = neutron_utils.neutron_client(self.os_creds)
- nova_utils.attach_volume(
- self.nova, neutron, self.instance_creator.get_vm_inst(),
- self.volume_creator.get_volume())
-
- time.sleep(10)
-
- vol_attach = cinder_utils.get_volume_by_id(
- self.cinder, self.volume_creator.get_volume().id)
- vm_attach = nova_utils.get_server_object_by_id(
- self.nova, neutron, self.instance_creator.get_vm_inst().id)
+ neutron = neutron_utils.neutron_client(
+ self.os_creds, self.os_session)
+ keystone = keystone_utils.keystone_client(
+ self.os_creds, self.os_session)
+ self.assertIsNotNone(nova_utils.attach_volume(
+ self.nova, neutron, keystone, self.instance_creator.get_vm_inst(),
+ self.volume_creator.get_volume(), self.os_creds.project_name))
+
+ vol_attach = None
+ vol_detach = None
+ attached = False
+ start_time = time.time()
+ while time.time() < start_time + 120:
+ vol_attach = cinder_utils.get_volume_by_id(
+ self.cinder, self.volume_creator.get_volume().id)
+
+ if len(vol_attach.attachments) > 0:
+ attached = True
+ break
- # Detach volume to VM
- nova_utils.detach_volume(
- self.nova, neutron, self.instance_creator.get_vm_inst(),
- self.volume_creator.get_volume())
+ time.sleep(3)
- time.sleep(10)
+ self.assertTrue(attached)
+ self.assertIsNotNone(vol_attach)
- vol_detach = cinder_utils.get_volume_by_id(
- self.cinder, self.volume_creator.get_volume().id)
- vm_detach = nova_utils.get_server_object_by_id(
- self.nova, neutron, self.instance_creator.get_vm_inst().id)
+ keystone = keystone_utils.keystone_client(
+ self.os_creds, self.os_session)
+ vm_attach = nova_utils.get_server_object_by_id(
+ self.nova, neutron, keystone,
+ self.instance_creator.get_vm_inst().id, self.os_creds.project_name)
# Validate Attachment
self.assertIsNotNone(vol_attach)
@@ -479,8 +512,103 @@ class NovaUtilsInstanceVolumeTests(OSComponentTestCase):
self.assertEqual(vm_attach.volume_ids[0]['id'],
vol_attach.attachments[0]['volume_id'])
+ # Detach volume to VM
+ self.assertIsNotNone(nova_utils.detach_volume(
+ self.nova, neutron, keystone, self.instance_creator.get_vm_inst(),
+ self.volume_creator.get_volume(), self.os_creds.project_name))
+
+ start_time = time.time()
+ while time.time() < start_time + 120:
+ vol_detach = cinder_utils.get_volume_by_id(
+ self.cinder, self.volume_creator.get_volume().id)
+ if len(vol_detach.attachments) == 0:
+ attached = False
+ break
+
+ time.sleep(3)
+
+ self.assertFalse(attached)
+ self.assertIsNotNone(vol_detach)
+
+ vm_detach = nova_utils.get_server_object_by_id(
+ self.nova, neutron, keystone,
+ self.instance_creator.get_vm_inst().id, self.os_creds.project_name)
+
# Validate Detachment
self.assertIsNotNone(vol_detach)
self.assertEqual(self.volume_creator.get_volume().id, vol_detach.id)
+
self.assertEqual(0, len(vol_detach.attachments))
self.assertEqual(0, len(vm_detach.volume_ids))
+
+ def test_attach_volume_nowait(self):
+ """
+ Tests the nova_utils.attach_volume() with a timeout value that is too
+ small to have the volume attachment data to be included on the VmInst
+ object that was supposed to be returned
+ """
+
+ self.assertIsNotNone(self.volume_creator.get_volume())
+ self.assertEqual(0, len(self.volume_creator.get_volume().attachments))
+
+ # Attach volume to VM
+ neutron = neutron_utils.neutron_client(self.os_creds, self.os_session)
+ keystone = keystone_utils.keystone_client(
+ self.os_creds, self.os_session)
+ with self.assertRaises(NovaException):
+ nova_utils.attach_volume(
+ self.nova, neutron, keystone,
+ self.instance_creator.get_vm_inst(),
+ self.volume_creator.get_volume(), self.os_creds.project_name,
+ 0)
+
+ def test_detach_volume_nowait(self):
+ """
+ Tests the nova_utils.detach_volume() with a timeout value that is too
+ small to have the volume attachment data to be included on the VmInst
+ object that was supposed to be returned
+ """
+
+ self.assertIsNotNone(self.volume_creator.get_volume())
+ self.assertEqual(0, len(self.volume_creator.get_volume().attachments))
+
+ # Attach volume to VM
+ neutron = neutron_utils.neutron_client(self.os_creds, self.os_session)
+ keystone = keystone_utils.keystone_client(
+ self.os_creds, self.os_session)
+ nova_utils.attach_volume(
+ self.nova, neutron, keystone, self.instance_creator.get_vm_inst(),
+ self.volume_creator.get_volume(), self.os_creds.project_name)
+
+ # Check VmInst for attachment
+ keystone = keystone_utils.keystone_client(
+ self.os_creds, self.os_session)
+ latest_vm = nova_utils.get_server_object_by_id(
+ self.nova, neutron, keystone,
+ self.instance_creator.get_vm_inst().id, self.os_creds.project_name)
+ self.assertEqual(1, len(latest_vm.volume_ids))
+
+ # Check Volume for attachment
+ vol_attach = None
+ attached = False
+ start_time = time.time()
+ while time.time() < start_time + 120:
+ vol_attach = cinder_utils.get_volume_by_id(
+ self.cinder, self.volume_creator.get_volume().id)
+
+ if len(vol_attach.attachments) > 0:
+ attached = True
+ break
+
+ time.sleep(3)
+
+ self.assertTrue(attached)
+ self.assertIsNotNone(vol_attach)
+
+ # Detach volume
+ with self.assertRaises(NovaException):
+ nova_utils.detach_volume(
+ self.nova, neutron, keystone,
+ self.instance_creator.get_vm_inst(),
+ self.volume_creator.get_volume(), self.os_creds.project_name,
+ 0)
diff --git a/snaps/openstack/utils/tests/settings_utils_tests.py b/snaps/openstack/utils/tests/settings_utils_tests.py
index cbd78d8..3d080d4 100644
--- a/snaps/openstack/utils/tests/settings_utils_tests.py
+++ b/snaps/openstack/utils/tests/settings_utils_tests.py
@@ -37,7 +37,7 @@ from snaps.openstack.create_security_group import OpenStackSecurityGroup
from snaps.openstack.tests import openstack_tests
from snaps.openstack.tests.os_source_file_test import OSComponentTestCase
from snaps.openstack.utils import (
- neutron_utils, settings_utils, nova_utils, glance_utils)
+ neutron_utils, settings_utils, nova_utils, glance_utils, keystone_utils)
__author__ = 'spisarski'
@@ -58,7 +58,8 @@ class SettingsUtilsNetworkingTests(OSComponentTestCase):
self.network_name = guid + '-net'
self.subnet_name = guid + '-subnet'
self.net_creator = None
- self.neutron = neutron_utils.neutron_client(self.os_creds)
+ self.neutron = neutron_utils.neutron_client(
+ self.os_creds, self.os_session)
def tearDown(self):
"""
@@ -70,6 +71,8 @@ class SettingsUtilsNetworkingTests(OSComponentTestCase):
except:
pass
+ super(self.__class__, self).__clean__()
+
def test_derive_net_settings_no_subnet(self):
"""
Validates the utility function settings_utils#create_network_config
@@ -154,9 +157,14 @@ class SettingsUtilsVmInstTests(OSComponentTestCase):
Instantiates the CreateImage object that is responsible for downloading
and creating an OS image file within OpenStack
"""
- self.nova = nova_utils.nova_client(self.os_creds)
- self.glance = glance_utils.glance_client(self.os_creds)
- self.neutron = neutron_utils.neutron_client(self.os_creds)
+ self.nova = nova_utils.nova_client(
+ self.os_creds, self.os_session)
+ self.keystone = keystone_utils.keystone_client(
+ self.os_creds, self.os_session)
+ self.glance = glance_utils.glance_client(
+ self.os_creds, self.os_session)
+ self.neutron = neutron_utils.neutron_client(
+ self.os_creds, self.os_session)
guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
self.keypair_priv_filepath = 'tmp/' + guid
@@ -188,6 +196,7 @@ class SettingsUtilsVmInstTests(OSComponentTestCase):
# First network is public
self.pub_net_config = openstack_tests.get_pub_net_config(
+ project_name=self.os_creds.project_name,
net_name=guid + '-pub-net', subnet_name=guid + '-pub-subnet',
router_name=guid + '-pub-router',
external_net=self.ext_net_name)
@@ -314,7 +323,7 @@ class SettingsUtilsVmInstTests(OSComponentTestCase):
if os.path.isfile(self.test_file_local_path):
os.remove(self.test_file_local_path)
- # super(self.__class__, self).__clean__()
+ super(self.__class__, self).__clean__()
def test_derive_vm_inst_config(self):
"""
@@ -324,10 +333,11 @@ class SettingsUtilsVmInstTests(OSComponentTestCase):
self.inst_creator.create(block=True)
server = nova_utils.get_server(
- self.nova, self.neutron,
+ self.nova, self.neutron, self.keystone,
vm_inst_settings=self.inst_creator.instance_settings)
derived_vm_settings = settings_utils.create_vm_inst_config(
- self.nova, self.neutron, server)
+ self.nova, self.keystone, self.neutron, server,
+ self.os_creds.project_name)
self.assertIsNotNone(derived_vm_settings)
self.assertIsNotNone(derived_vm_settings.port_settings)
self.assertIsNotNone(derived_vm_settings.floating_ip_settings)
@@ -340,7 +350,7 @@ class SettingsUtilsVmInstTests(OSComponentTestCase):
self.inst_creator.create(block=True)
server = nova_utils.get_server(
- self.nova, self.neutron,
+ self.nova, self.neutron, self.keystone,
vm_inst_settings=self.inst_creator.instance_settings)
derived_image_settings = settings_utils.determine_image_config(
self.glance, server, [self.image_creator.image_settings])
@@ -356,8 +366,9 @@ class SettingsUtilsUnitTests(unittest.TestCase):
def test_vol_settings_from_vol(self):
volume = Volume(
- name='vol-name', volume_id='vol-id', description='desc', size=99,
- vol_type='vol-type', availability_zone='zone1', multi_attach=True)
+ name='vol-name', volume_id='vol-id', project_id='proj-id',
+ description='desc', size=99, vol_type='vol-type',
+ availability_zone='zone1', multi_attach=True)
settings = settings_utils.create_volume_config(volume)
self.assertEqual(volume.name, settings.name)
self.assertEqual(volume.description, settings.description)
diff --git a/snaps/playbook_runner.py b/snaps/playbook_runner.py
index 87321f5..7b10390 100644
--- a/snaps/playbook_runner.py
+++ b/snaps/playbook_runner.py
@@ -15,9 +15,13 @@
import argparse
import ast
import logging
+import os
import re
+import yaml
+from jinja2 import Environment, FileSystemLoader
+
from snaps.openstack.os_credentials import ProxySettings
from snaps.provisioning import ansible_utils
@@ -41,41 +45,59 @@ def main(parsed_args):
ssh_proxy_cmd=parsed_args.ssh_proxy_cmd)
# Ensure can get an SSH client
- ssh = ansible_utils.ssh_client(parsed_args.ip_addr, parsed_args.host_user,
- parsed_args.priv_key, proxy_settings)
+ ssh = ansible_utils.ssh_client(
+ parsed_args.ip_addr, parsed_args.host_user,
+ private_key_filepath=parsed_args.priv_key,
+ proxy_settings=proxy_settings)
if ssh:
ssh.close()
- vars = dict()
- if args.vars:
- vars = ast.literal_eval(args.vars)
- if not isinstance(vars, dict):
- vars = dict()
+ env = Environment(loader=FileSystemLoader(
+ searchpath=os.path.dirname(parsed_args.env_file)))
+ template = env.get_template(os.path.basename(parsed_args.env_file))
+
+ env_dict = dict()
+ if parsed_args.vars:
+ env_dict = ast.literal_eval(parsed_args.vars)
+
+ output = template.render(**env_dict)
+
+ variables = yaml.load(output)
+
+ if not variables.get('env_file'):
+ variables['env_file'] = parsed_args.env_file
- retval = ansible_utils.apply_playbook(
+ ansible_utils.apply_playbook(
parsed_args.playbook, [parsed_args.ip_addr], parsed_args.host_user,
- parsed_args.priv_key, variables=vars,
+ ssh_priv_key_file_path=parsed_args.priv_key,
+ password=parsed_args.password, variables=variables,
proxy_setting=proxy_settings)
- exit(retval)
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('-a', '--ip-addr', dest='ip_addr', required=True,
help='The Host IP Address')
- parser.add_argument('-k', '--priv-key', dest='priv_key', required=True,
- help='The location of the private key file')
parser.add_argument('-u', '--host-user', dest='host_user', required=True,
help='Host user account')
+ parser.add_argument('-k', '--priv-key', dest='priv_key', required=False,
+ help='The location of the private key file')
+ parser.add_argument('-pw', '--password', dest='password', required=False,
+ help='The host-user password')
parser.add_argument('-b', '--playbook', dest='playbook', required=True,
help='Playbook Location')
parser.add_argument('-p', '--http-proxy', dest='http_proxy',
required=False, help='<host>:<port>')
parser.add_argument('-s', '--ssh-proxy-cmd', dest='ssh_proxy_cmd',
required=False)
+ parser.add_argument('-e', '--env-file', dest='env_file',
+ help='Yaml file containing playbook substitution vals',
+ required=False)
parser.add_argument('-v', '--vars', dest='vars',
+ help='String renditon of a dict to pass into '
+ 'playbook for additional subtitution values not '
+ 'found in env_file',
required=False)
args = parser.parse_args()
main(args)
-
diff --git a/snaps/provisioning/ansible_utils.py b/snaps/provisioning/ansible_utils.py
index 63f26e1..019a8e7 100644
--- a/snaps/provisioning/ansible_utils.py
+++ b/snaps/provisioning/ansible_utils.py
@@ -21,52 +21,80 @@ import paramiko
try:
from ansible.parsing.dataloader import DataLoader
- from ansible.vars import VariableManager
- from ansible.inventory import Inventory
+ from ansible.vars.manager import VariableManager
+ from ansible.inventory.manager import InventoryManager
from ansible.executor.playbook_executor import PlaybookExecutor
except:
pass
__author__ = 'spisarski'
+from warnings import warn
+warn('This utility will be removed in a subsequent release',
+ DeprecationWarning)
+
logger = logging.getLogger('ansible_utils')
-def apply_playbook(playbook_path, hosts_inv, host_user, ssh_priv_key_file_path,
- variables=None, proxy_setting=None):
+def apply_playbook(playbook_path, hosts_inv=None, host_user=None,
+ ssh_priv_key_file_path=None, password=None, variables=None,
+ proxy_setting=None):
"""
Executes an Ansible playbook to the given host
:param playbook_path: the (relative) path to the Ansible playbook
:param hosts_inv: a list of hostnames/ip addresses to which to apply the
- Ansible playbook
+ Ansible playbook (not required when PB is configured for
+ localhost)
:param host_user: A user for the host instances (must be a password-less
- sudo user if playbook has "sudo: yes"
- :param ssh_priv_key_file_path: the file location of the ssh key
+ sudo user if playbook has "sudo: yes") (not required when
+ PB is configured for localhost)
+ :param ssh_priv_key_file_path: the file location of the ssh key. Required
+ if password is None (not required when PB is
+ configured for localhost)
+ :param password: the file location of the ssh key. Required if
+ ssh_priv_key_file_path is None (not required when PB is
+ configured for localhost)
:param variables: a dictionary containing any substitution variables needed
by the Jinga 2 templates
:param proxy_setting: instance of os_credentials.ProxySettings class
- :return: the results
+ :raises AnsibleException when the return code from the Ansible library is
+ not 0
+ :return: the return code from the Ansible library only when 0.
+ Implementation now raises an exception otherwise
"""
if not os.path.isfile(playbook_path):
- raise AnsibleException('Requested playbook not found - ' + playbook_path)
+ raise AnsibleException(
+ 'Requested playbook not found - ' + playbook_path)
+
+ pk_file_path = None
+ if ssh_priv_key_file_path:
+ pk_file_path = os.path.expanduser(ssh_priv_key_file_path)
+ if not password:
+ if not os.path.isfile(pk_file_path):
+ raise AnsibleException(
+ 'Requested private SSH key not found - ' + pk_file_path)
- pk_file_path = os.path.expanduser(ssh_priv_key_file_path)
- if not os.path.isfile(pk_file_path):
- raise AnsibleException('Requested private SSH key not found - ' +
- pk_file_path)
+ passwords = None
+ if password:
+ passwords = {'conn_pass': password, 'become_pass': password}
import ansible.constants
ansible.constants.HOST_KEY_CHECKING = False
- variable_manager = VariableManager()
+ loader = DataLoader()
+ inventory = InventoryManager(loader=loader)
+ if hosts_inv:
+ for host in hosts_inv:
+ inventory.add_host(host=host, group='ungrouped')
+ connection = 'ssh'
+ else:
+ connection = 'local'
+
+ variable_manager = VariableManager(loader=loader, inventory=inventory)
+
if variables:
variable_manager.extra_vars = variables
- loader = DataLoader()
- inventory = Inventory(loader=loader, variable_manager=variable_manager,
- host_list=hosts_inv)
- variable_manager.set_inventory(inventory)
-
ssh_extra_args = None
if proxy_setting and proxy_setting.ssh_proxy_cmd:
ssh_extra_args = '-o ProxyCommand=\'%s\'' % proxy_setting.ssh_proxy_cmd
@@ -76,14 +104,15 @@ def apply_playbook(playbook_path, hosts_inv, host_user, ssh_priv_key_file_path,
'connection', 'module_path', 'forks', 'remote_user',
'private_key_file', 'ssh_common_args', 'ssh_extra_args',
'become', 'become_method', 'become_user', 'verbosity',
- 'check', 'timeout'])
+ 'check', 'timeout', 'diff'])
ansible_opts = options(
listtags=False, listtasks=False, listhosts=False, syntax=False,
- connection='ssh', module_path=None, forks=100, remote_user=host_user,
- private_key_file=pk_file_path, ssh_common_args=None,
- ssh_extra_args=ssh_extra_args, become=None, become_method=None,
- become_user=None, verbosity=11111, check=False, timeout=30)
+ connection=connection, module_path=None, forks=100,
+ remote_user=host_user, private_key_file=pk_file_path,
+ ssh_common_args=None, ssh_extra_args=ssh_extra_args, become=None,
+ become_method=None, become_user=None, verbosity=11111, check=False,
+ timeout=30, diff=None)
logger.debug('Setting up Ansible Playbook Executor for playbook - ' +
playbook_path)
@@ -93,18 +122,28 @@ def apply_playbook(playbook_path, hosts_inv, host_user, ssh_priv_key_file_path,
variable_manager=variable_manager,
loader=loader,
options=ansible_opts,
- passwords=None)
+ passwords=passwords)
logger.debug('Executing Ansible Playbook - ' + playbook_path)
- return executor.run()
+ ret_val = executor.run()
+
+ if ret_val != 0:
+ raise AnsibleException(
+ 'Error applying playbook [{}] with value [{}] using the connection'
+ ' type of [{}]'.format(
+ playbook_path, ret_val, connection))
+ return ret_val
-def ssh_client(ip, user, private_key_filepath, proxy_settings=None):
+
+def ssh_client(ip, user, private_key_filepath=None, password=None,
+ proxy_settings=None):
"""
Retrieves and attemts an SSH connection
:param ip: the IP of the host to connect
:param user: the user with which to connect
- :param private_key_filepath: the path to the private key file
+ :param private_key_filepath: when None, password is required
+ :param password: when None, private_key_filepath is required
:param proxy_settings: instance of os_credentials.ProxySettings class
(optional)
:return: the SSH client if can connect else false
@@ -120,12 +159,17 @@ def ssh_client(ip, user, private_key_filepath, proxy_settings=None):
proxy_cmd_str = proxy_cmd_str.replace("%p", '22')
proxy_cmd = paramiko.ProxyCommand(proxy_cmd_str)
- pk_abs_path = os.path.expanduser(private_key_filepath)
- ssh.connect(ip, username=user, key_filename=pk_abs_path,
- sock=proxy_cmd)
+ pk_abs_path = None
+ if not password and private_key_filepath:
+ pk_abs_path = os.path.expanduser(private_key_filepath)
+
+ ssh.connect(
+ ip, username=user, key_filename=pk_abs_path, password=password,
+ sock=proxy_cmd)
+ logger.info('Obtained SSH connection to %s', ip)
return ssh
except Exception as e:
- logger.warning('Unable to connect via SSH with message - ' + str(e))
+ logger.debug('Unable to connect via SSH with message - ' + str(e))
class AnsibleException(Exception):
diff --git a/snaps/provisioning/tests/ansible_utils_tests.py b/snaps/provisioning/tests/ansible_utils_tests.py
index 7600002..b6ace31 100644
--- a/snaps/provisioning/tests/ansible_utils_tests.py
+++ b/snaps/provisioning/tests/ansible_utils_tests.py
@@ -19,7 +19,6 @@ import os
import pkg_resources
from scp import SCPClient
-from snaps.config.flavor import FlavorConfig
from snaps.config.keypair import KeypairConfig
from snaps.config.network import PortConfig
from snaps.config.security_group import (
@@ -58,7 +57,7 @@ class AnsibleProvisioningTests(OSIntegrationTestCase):
"""
super(self.__class__, self).__start__()
- self.nova = nova_utils.nova_client(self.os_creds)
+ self.nova = nova_utils.nova_client(self.os_creds, self.os_session)
guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
self.keypair_priv_filepath = 'tmp/' + guid
@@ -84,13 +83,15 @@ class AnsibleProvisioningTests(OSIntegrationTestCase):
os_image_settings = openstack_tests.ubuntu_image_settings(
name=guid + '-' + '-image',
image_metadata=self.image_metadata)
- self.image_creator = create_image.OpenStackImage(self.os_creds,
- os_image_settings)
+ self.image_creator = create_image.OpenStackImage(
+ self.os_creds, os_image_settings)
self.image_creator.create()
# First network is public
self.pub_net_config = openstack_tests.get_pub_net_config(
- net_name=guid + '-pub-net', subnet_name=guid + '-pub-subnet',
+ project_name=self.os_creds.project_name,
+ net_name=guid + '-pub-net',
+ mtu=1442, subnet_name=guid + '-pub-subnet',
router_name=guid + '-pub-router',
external_net=self.ext_net_name)
@@ -104,11 +105,12 @@ class AnsibleProvisioningTests(OSIntegrationTestCase):
self.router_creator.create()
# Create Flavor
+ flavor_config = openstack_tests.get_flavor_config(
+ name=guid + '-flavor-name', ram=2048, disk=10,
+ vcpus=2, metadata=self.flavor_metadata)
+
self.flavor_creator = create_flavor.OpenStackFlavor(
- self.admin_os_creds,
- FlavorConfig(
- name=guid + '-flavor-name', ram=2048, disk=10, vcpus=2,
- metadata=self.flavor_metadata))
+ self.admin_os_creds, flavor_config)
self.flavor_creator.create()
# Create Key/Pair
@@ -263,11 +265,11 @@ class AnsibleProvisioningTests(OSIntegrationTestCase):
relative_pb_path = pkg_resources.resource_filename(
'snaps.provisioning.tests.playbooks', 'simple_playbook.yml')
- retval = self.inst_creator.apply_ansible_playbook(relative_pb_path)
- self.assertEqual(0, retval)
+ self.inst_creator.apply_ansible_playbook(relative_pb_path)
- ssh = ansible_utils.ssh_client(ip, user, priv_key,
- self.os_creds.proxy_settings)
+ ssh = ansible_utils.ssh_client(
+ ip, user, private_key_filepath=priv_key,
+ proxy_settings=self.os_creds.proxy_settings)
self.assertIsNotNone(ssh)
scp = None
try:
@@ -329,13 +331,12 @@ class AnsibleProvisioningTests(OSIntegrationTestCase):
relative_pb_path = pkg_resources.resource_filename(
'snaps.provisioning.tests.playbooks',
'template_playbook.yml')
- retval = self.inst_creator.apply_ansible_playbook(relative_pb_path,
- variables={
- 'name': 'Foo'})
- self.assertEqual(0, retval)
+ self.inst_creator.apply_ansible_playbook(
+ relative_pb_path, variables={'name': 'Foo'})
- ssh = ansible_utils.ssh_client(ip, user, priv_key,
- self.os_creds.proxy_settings)
+ ssh = ansible_utils.ssh_client(
+ ip, user, private_key_filepath=priv_key,
+ proxy_settings=self.os_creds.proxy_settings)
self.assertIsNotNone(ssh)
scp = None
diff --git a/snaps/test_runner.py b/snaps/test_runner.py
index d3c1fd6..d46fe86 100644
--- a/snaps/test_runner.py
+++ b/snaps/test_runner.py
@@ -13,11 +13,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import argparse
-import json
import logging
import unittest
+from concurrencytest import ConcurrentTestSuite, fork_for_tests
-from snaps import test_suite_builder, file_utils
+from snaps import file_utils
+from snaps import test_suite_builder as tsb
from snaps.openstack.tests import openstack_tests
__author__ = 'spisarski'
@@ -30,14 +31,13 @@ LOG_LEVELS = {'FATAL': logging.FATAL, 'CRITICAL': logging.CRITICAL,
'INFO': logging.INFO, 'DEBUG': logging.DEBUG}
-def __create_test_suite(
+def __create_concurrent_test_suite(
source_filename, ext_net_name, proxy_settings, ssh_proxy_cmd,
run_unit_tests, run_connection_tests, run_api_tests,
run_integration_tests, run_staging_tests, flavor_metadata,
- image_metadata, use_keystone, use_floating_ips, continuous_integration,
- log_level):
+ image_metadata, use_floating_ips, continuous_integration, log_level):
"""
- Compiles the tests that should run
+ Compiles the tests that can be run concurrently
:param source_filename: the OpenStack credentials file (required)
:param ext_net_name: the name of the external network to use for floating
IPs (required)
@@ -56,9 +56,6 @@ def __create_test_suite(
created for test VM instance
:param image_metadata: dict() object containing the metadata for overriding
default images within the tests
- :param use_keystone: when true, tests creating users and projects will be
- exercised and must be run on a host that
- has access to the cloud's administrative network
:param use_floating_ips: when true, tests requiring floating IPs will be
executed
:param continuous_integration: when true, tests for CI will be run
@@ -73,43 +70,100 @@ def __create_test_suite(
# Tests that do not require a remote connection to an OpenStack cloud
if run_unit_tests:
- test_suite_builder.add_unit_tests(suite)
+ tsb.add_unit_tests(suite)
# Basic connection tests
if run_connection_tests:
- test_suite_builder.add_openstack_client_tests(
+ tsb.add_openstack_client_tests(
suite=suite, os_creds=os_creds, ext_net_name=ext_net_name,
- use_keystone=use_keystone, log_level=log_level)
+ use_keystone=True, log_level=log_level)
# Tests the OpenStack API calls
if run_api_tests:
- test_suite_builder.add_openstack_api_tests(
+ tsb.add_openstack_api_tests(
suite=suite, os_creds=os_creds, ext_net_name=ext_net_name,
- use_keystone=use_keystone, image_metadata=image_metadata,
- log_level=log_level)
+ use_keystone=True, flavor_metadata=flavor_metadata,
+ image_metadata=image_metadata, log_level=log_level)
# Long running integration type tests
if run_integration_tests:
- test_suite_builder.add_openstack_integration_tests(
+ tsb.add_openstack_integration_tests(
suite=suite, os_creds=os_creds, ext_net_name=ext_net_name,
- use_keystone=use_keystone, flavor_metadata=flavor_metadata,
+ use_keystone=True, flavor_metadata=flavor_metadata,
image_metadata=image_metadata, use_floating_ips=use_floating_ips,
log_level=log_level)
if run_staging_tests:
- test_suite_builder.add_openstack_staging_tests(
+ tsb.add_openstack_staging_tests(
suite=suite, os_creds=os_creds, ext_net_name=ext_net_name,
log_level=log_level)
if continuous_integration:
- test_suite_builder.add_openstack_ci_tests(
+ tsb.add_openstack_ci_tests(
suite=suite, os_creds=os_creds, ext_net_name=ext_net_name,
- use_keystone=use_keystone, flavor_metadata=flavor_metadata,
+ use_keystone=True, flavor_metadata=flavor_metadata,
image_metadata=image_metadata, use_floating_ips=use_floating_ips,
log_level=log_level)
return suite
+def __create_sequential_test_suite(
+ source_filename, ext_net_name, proxy_settings, ssh_proxy_cmd,
+ run_integration_tests, flavor_metadata, image_metadata,
+ use_floating_ips, log_level):
+ """
+ Compiles the tests that cannot be run in parallel
+ :param source_filename: the OpenStack credentials file (required)
+ :param ext_net_name: the name of the external network to use for floating
+ IPs (required)
+ :param run_integration_tests: when true, the integration tests are executed
+ :param proxy_settings: <host>:<port> of the proxy server (optional)
+ :param ssh_proxy_cmd: the command used to connect via SSH over some proxy
+ server (optional)
+ :param flavor_metadata: dict() object containing the metadata for flavors
+ created for test VM instance
+ :param image_metadata: dict() object containing the metadata for overriding
+ default images within the tests
+ :param use_floating_ips: when true, tests requiring floating IPs will be
+ executed
+ :param log_level: the logging level
+ :return:
+ """
+ if use_floating_ips and run_integration_tests:
+ suite = unittest.TestSuite()
+
+ os_creds = openstack_tests.get_credentials(
+ os_env_file=source_filename, proxy_settings_str=proxy_settings,
+ ssh_proxy_cmd=ssh_proxy_cmd)
+
+ tsb.add_ansible_integration_tests(
+ suite=suite, os_creds=os_creds, ext_net_name=ext_net_name,
+ use_keystone=True, flavor_metadata=flavor_metadata,
+ image_metadata=image_metadata, log_level=log_level)
+
+ return suite
+
+
+def __output_results(results):
+ """
+ Sends the test results to the logger
+ :param results:
+ :return:
+ """
+
+ if results.errors:
+ logger.error('Number of errors in test suite - %s',
+ len(results.errors))
+ for test, message in results.errors:
+ logger.error(str(test) + " ERROR with " + message)
+
+ if results.failures:
+ logger.error('Number of failures in test suite - %s',
+ len(results.failures))
+ for test, message in results.failures:
+ logger.error(str(test) + " FAILED with " + message)
+
+
def main(arguments):
"""
Begins running unit tests.
@@ -123,13 +177,16 @@ def main(arguments):
flavor_metadata = None
if arguments.flavor_metadata:
- flavor_metadata = json.loads(arguments.flavor_metadata)
+ flavor_metadata = {
+ 'metadata': {'hw:mem_page_size': arguments.flavor_metadata}}
image_metadata = None
if arguments.image_metadata_file:
image_metadata = file_utils.read_yaml(arguments.image_metadata_file)
- suite = None
+ concurrent_suite = None
+ sequential_suite = None
+
if arguments.env and arguments.ext_net:
unit = arguments.include_unit != ARG_NOT_SET
connection = arguments.include_connection != ARG_NOT_SET
@@ -144,40 +201,61 @@ def main(arguments):
api = True
integration = True
- suite = __create_test_suite(
+ concurrent_suite = __create_concurrent_test_suite(
arguments.env, arguments.ext_net, arguments.proxy,
arguments.ssh_proxy_cmd, unit, connection, api,
integration, staging, flavor_metadata, image_metadata,
- arguments.use_keystone != ARG_NOT_SET,
arguments.floating_ips != ARG_NOT_SET,
ci, log_level)
+
+ if (arguments.include_integration != ARG_NOT_SET
+ and arguments.floating_ips != ARG_NOT_SET):
+ sequential_suite = __create_sequential_test_suite(
+ arguments.env, arguments.ext_net, arguments.proxy,
+ arguments.ssh_proxy_cmd, integration, flavor_metadata,
+ image_metadata,
+ arguments.floating_ips != ARG_NOT_SET, log_level)
else:
logger.error('Environment file or external network not defined')
exit(1)
i = 0
while i < int(arguments.num_runs):
- result = unittest.TextTestRunner(verbosity=2).run(suite)
i += 1
- if result.errors:
- logger.error('Number of errors in test suite - %s',
- len(result.errors))
- for test, message in result.errors:
- logger.error(str(test) + " ERROR with " + message)
-
- if result.failures:
- logger.error('Number of failures in test suite - %s',
- len(result.failures))
- for test, message in result.failures:
- logger.error(str(test) + " FAILED with " + message)
-
- if ((result.errors and len(result.errors) > 0)
- or (result.failures and len(result.failures) > 0)):
- logger.error('See above for test failures')
- exit(1)
- else:
- logger.info('All tests completed successfully in run #%s', i)
+ if concurrent_suite:
+ logger.info('Running Concurrent Tests')
+ concurrent_runner = unittest.TextTestRunner(verbosity=2)
+ concurrent_suite = ConcurrentTestSuite(
+ concurrent_suite, fork_for_tests(int(arguments.threads)))
+ concurrent_results = concurrent_runner.run(concurrent_suite)
+ __output_results(concurrent_results)
+
+ if ((concurrent_results.errors
+ and len(concurrent_results.errors) > 0)
+ or (concurrent_results.failures
+ and len(concurrent_results.failures) > 0)):
+ logger.error('See above for test failures')
+ exit(1)
+ else:
+ logger.info(
+ 'Concurrent tests completed successfully in run #%s', i)
+
+ if sequential_suite:
+ logger.info('Running Sequential Tests')
+ sequential_runner = unittest.TextTestRunner(verbosity=2)
+ sequential_results = sequential_runner.run(sequential_suite)
+ __output_results(sequential_results)
+
+ if ((sequential_results.errors
+ and len(sequential_results.errors) > 0)
+ or (sequential_results.failures
+ and len(sequential_results.failures) > 0)):
+ logger.error('See above for test failures')
+ exit(1)
+ else:
+ logger.info(
+ 'Sequential tests completed successfully in run #%s', i)
logger.info('Successful completion of %s test runs', i)
exit(0)
@@ -227,15 +305,9 @@ if __name__ == '__main__':
nargs='?', help='When argument is set, all integration tests requiring'
' Floating IPs will be executed')
parser.add_argument(
- '-k', '--use-keystone', dest='use_keystone', default=ARG_NOT_SET,
- nargs='?',
- help='When argument is set, the tests will exercise the keystone APIs '
- 'and must be run on a machine that has access to the admin '
- 'network and is able to create users and groups')
- parser.add_argument(
'-fm', '--flavor-meta', dest='flavor_metadata',
- help='JSON string to be used as flavor metadata for all test instances'
- ' created')
+ help='hw:mem_page_size flavor setting value (i.e. large). '
+ 'Required for DPDK')
parser.add_argument(
'-im', '--image-meta', dest='image_metadata_file', default=None,
help='Location of YAML file containing the image metadata')
@@ -247,6 +319,9 @@ if __name__ == '__main__':
parser.add_argument(
'-r', '--num-runs', dest='num_runs', default=1,
help='Number of test runs to execute (default 1)')
+ parser.add_argument(
+ '-t', '--threads', dest='threads', default=4,
+ help='Number of threads to execute the tests (default 4)')
args = parser.parse_args()
diff --git a/snaps/test_suite_builder.py b/snaps/test_suite_builder.py
index 7b3ece7..52008a6 100644
--- a/snaps/test_suite_builder.py
+++ b/snaps/test_suite_builder.py
@@ -65,18 +65,19 @@ from snaps.openstack.tests.create_image_tests import (
CreateImageSuccessTests, CreateImageNegativeTests,
CreateMultiPartImageTests)
from snaps.openstack.tests.create_instance_tests import (
- CreateInstanceSingleNetworkTests, CreateInstanceOnComputeHost,
+ CreateInstanceSingleNetworkTests, CreateInstanceOnComputeHost,
CreateInstanceSimpleTests, FloatingIpSettingsUnitTests,
InstanceSecurityGroupTests, VmInstanceSettingsUnitTests,
CreateInstancePortManipulationTests, SimpleHealthCheck,
CreateInstanceFromThreePartImage, CreateInstanceMockOfflineTests,
CreateInstanceTwoNetTests, CreateInstanceVolumeTests,
- CreateInstanceIPv6NetworkTests)
+ CreateInstanceIPv6NetworkTests, CreateInstanceExternalNetTests)
from snaps.openstack.tests.create_keypairs_tests import (
CreateKeypairsTests, KeypairSettingsUnitTests, CreateKeypairsCleanupTests)
from snaps.openstack.tests.create_network_tests import (
CreateNetworkSuccessTests, NetworkSettingsUnitTests, PortSettingsUnitTests,
- SubnetSettingsUnitTests, CreateNetworkTypeTests, CreateNetworkIPv6Tests)
+ SubnetSettingsUnitTests, CreateNetworkTypeTests, CreateNetworkIPv6Tests,
+ CreateMultipleNetworkTests, CreateNetworkGatewayTests)
from snaps.openstack.tests.create_project_tests import (
CreateProjectSuccessTests, ProjectSettingsUnitTests,
CreateProjectUserTests)
@@ -84,21 +85,23 @@ from snaps.openstack.tests.create_qos_tests import (
QoSSettingsUnitTests, CreateQoSTests)
from snaps.openstack.tests.create_router_tests import (
CreateRouterSuccessTests, CreateRouterNegativeTests,
- RouterSettingsUnitTests)
+ RouterSettingsUnitTests, CreateMultipleRouterTests,
+ CreateRouterSecurityGroupTests, CreateRouterSharedNetworksTests)
from snaps.openstack.tests.create_security_group_tests import (
CreateSecurityGroupTests, SecurityGroupRuleSettingsUnitTests,
- SecurityGroupSettingsUnitTests)
+ SecurityGroupSettingsUnitTests, CreateMultipleSecurityGroupTests)
from snaps.openstack.tests.create_stack_tests import (
StackSettingsUnitTests, CreateStackSuccessTests, CreateStackNegativeTests,
CreateStackFlavorTests, CreateStackFloatingIpTests,
CreateStackNestedResourceTests, CreateStackKeypairTests,
- CreateStackVolumeTests, CreateStackSecurityGroupTests)
+ CreateStackVolumeTests, CreateStackSecurityGroupTests,
+ CreateStackUpdateTests)
from snaps.openstack.tests.create_user_tests import (
UserSettingsUnitTests, CreateUserSuccessTests)
from snaps.openstack.tests.create_volume_tests import (
VolumeSettingsUnitTests, CreateSimpleVolumeSuccessTests,
CreateVolumeWithTypeTests, CreateVolumeWithImageTests,
- CreateSimpleVolumeFailureTests)
+ CreateSimpleVolumeFailureTests, CreateVolMultipleCredsTests)
from snaps.openstack.tests.create_volume_type_tests import (
VolumeTypeSettingsUnitTests, CreateSimpleVolumeTypeSuccessTests,
CreateVolumeTypeComplexTests)
@@ -315,7 +318,8 @@ def add_openstack_client_tests(suite, os_creds, ext_net_name,
def add_openstack_api_tests(suite, os_creds, ext_net_name, use_keystone=True,
- image_metadata=None, log_level=logging.INFO):
+ flavor_metadata=None, image_metadata=None,
+ log_level=logging.INFO):
"""
Adds tests written to exercise all existing OpenStack APIs
:param suite: the unittest.TestSuite object to which to add the tests
@@ -326,6 +330,9 @@ def add_openstack_api_tests(suite, os_creds, ext_net_name, use_keystone=True,
:param use_keystone: when True, tests requiring direct access to Keystone
are added as these need to be running on a host that
has access to the cloud's private network
+ :param flavor_metadata: dict() object containing the metadata required by
+ your flavor based on your configuration:
+ (i.e. {'hw:mem_page_size': 'any'})
:param image_metadata: dict() object containing metadata for creating an
image with custom config
(see YAML files in examples/image-metadata)
@@ -381,7 +388,7 @@ def add_openstack_api_tests(suite, os_creds, ext_net_name, use_keystone=True,
suite.addTest(OSComponentTestCase.parameterize(
NovaUtilsInstanceVolumeTests, os_creds=os_creds,
ext_net_name=ext_net_name, log_level=log_level,
- image_metadata=image_metadata))
+ flavor_metadata=flavor_metadata, image_metadata=image_metadata))
suite.addTest(OSComponentTestCase.parameterize(
CreateFlavorTests, os_creds=os_creds, ext_net_name=ext_net_name,
log_level=log_level))
@@ -468,6 +475,11 @@ def add_openstack_integration_tests(suite, os_creds, ext_net_name,
flavor_metadata=flavor_metadata, image_metadata=image_metadata,
log_level=log_level))
suite.addTest(OSIntegrationTestCase.parameterize(
+ CreateMultipleSecurityGroupTests, os_creds=os_creds,
+ ext_net_name=ext_net_name, use_keystone=use_keystone,
+ flavor_metadata=flavor_metadata, image_metadata=image_metadata,
+ log_level=log_level))
+ suite.addTest(OSIntegrationTestCase.parameterize(
CreateImageSuccessTests, os_creds=os_creds, ext_net_name=ext_net_name,
use_keystone=use_keystone,
flavor_metadata=flavor_metadata, image_metadata=image_metadata,
@@ -499,11 +511,21 @@ def add_openstack_integration_tests(suite, os_creds, ext_net_name,
flavor_metadata=flavor_metadata, image_metadata=image_metadata,
log_level=log_level))
suite.addTest(OSIntegrationTestCase.parameterize(
+ CreateNetworkGatewayTests, os_creds=os_creds,
+ ext_net_name=ext_net_name, use_keystone=use_keystone,
+ flavor_metadata=flavor_metadata, image_metadata=image_metadata,
+ log_level=log_level))
+ suite.addTest(OSIntegrationTestCase.parameterize(
CreateNetworkIPv6Tests, os_creds=os_creds,
ext_net_name=ext_net_name, use_keystone=use_keystone,
flavor_metadata=flavor_metadata, image_metadata=image_metadata,
log_level=log_level))
suite.addTest(OSIntegrationTestCase.parameterize(
+ CreateMultipleNetworkTests, os_creds=os_creds,
+ ext_net_name=ext_net_name, use_keystone=use_keystone,
+ flavor_metadata=flavor_metadata, image_metadata=image_metadata,
+ log_level=log_level))
+ suite.addTest(OSIntegrationTestCase.parameterize(
CreateRouterSuccessTests, os_creds=os_creds, ext_net_name=ext_net_name,
use_keystone=use_keystone,
flavor_metadata=flavor_metadata, image_metadata=image_metadata,
@@ -514,6 +536,21 @@ def add_openstack_integration_tests(suite, os_creds, ext_net_name,
flavor_metadata=flavor_metadata, image_metadata=image_metadata,
log_level=log_level))
suite.addTest(OSIntegrationTestCase.parameterize(
+ CreateMultipleRouterTests, os_creds=os_creds,
+ ext_net_name=ext_net_name, use_keystone=use_keystone,
+ flavor_metadata=flavor_metadata, image_metadata=image_metadata,
+ log_level=log_level))
+ suite.addTest(OSIntegrationTestCase.parameterize(
+ CreateRouterSecurityGroupTests, os_creds=os_creds,
+ ext_net_name=ext_net_name, use_keystone=use_keystone,
+ flavor_metadata=flavor_metadata, image_metadata=image_metadata,
+ log_level=log_level))
+ suite.addTest(OSIntegrationTestCase.parameterize(
+ CreateRouterSharedNetworksTests, os_creds=os_creds,
+ ext_net_name=ext_net_name, use_keystone=use_keystone,
+ flavor_metadata=flavor_metadata, image_metadata=image_metadata,
+ log_level=log_level))
+ suite.addTest(OSIntegrationTestCase.parameterize(
CreateQoSTests, os_creds=os_creds,
ext_net_name=ext_net_name, use_keystone=use_keystone,
flavor_metadata=flavor_metadata, image_metadata=image_metadata,
@@ -548,6 +585,11 @@ def add_openstack_integration_tests(suite, os_creds, ext_net_name,
ext_net_name=ext_net_name, use_keystone=use_keystone,
flavor_metadata=flavor_metadata, image_metadata=image_metadata,
log_level=log_level))
+ suite.addTest(OSIntegrationTestCase.parameterize(
+ CreateVolMultipleCredsTests, os_creds=os_creds,
+ ext_net_name=ext_net_name, use_keystone=use_keystone,
+ flavor_metadata=flavor_metadata, image_metadata=image_metadata,
+ log_level=log_level))
# VM Instances
suite.addTest(OSIntegrationTestCase.parameterize(
@@ -566,6 +608,11 @@ def add_openstack_integration_tests(suite, os_creds, ext_net_name,
flavor_metadata=flavor_metadata, image_metadata=image_metadata,
log_level=log_level))
suite.addTest(OSIntegrationTestCase.parameterize(
+ CreateInstanceExternalNetTests, os_creds=os_creds,
+ ext_net_name=ext_net_name, use_keystone=use_keystone,
+ flavor_metadata=flavor_metadata, image_metadata=image_metadata,
+ log_level=log_level))
+ suite.addTest(OSIntegrationTestCase.parameterize(
CreateInstancePortManipulationTests, os_creds=os_creds,
ext_net_name=ext_net_name, use_keystone=use_keystone,
flavor_metadata=flavor_metadata, image_metadata=image_metadata,
@@ -643,12 +690,43 @@ def add_openstack_integration_tests(suite, os_creds, ext_net_name,
flavor_metadata=flavor_metadata, image_metadata=image_metadata,
log_level=log_level))
suite.addTest(OSIntegrationTestCase.parameterize(
- AnsibleProvisioningTests, os_creds=os_creds,
+ CreateStackUpdateTests, os_creds=os_creds,
ext_net_name=ext_net_name, use_keystone=use_keystone,
flavor_metadata=flavor_metadata, image_metadata=image_metadata,
log_level=log_level))
+def add_ansible_integration_tests(suite, os_creds, ext_net_name,
+ use_keystone=True, flavor_metadata=None,
+ image_metadata=None, log_level=logging.INFO):
+ """
+ Adds tests written to exercise all long-running OpenStack integration tests
+ meaning they will be creating VM instances and potentially performing some
+ SSH functions through floatingIPs
+ :param suite: the unittest.TestSuite object to which to add the tests
+ :param os_creds: and instance of OSCreds that holds the credentials
+ required by OpenStack
+ :param ext_net_name: the name of an external network on the cloud under
+ test
+ :param use_keystone: when True, tests requiring direct access to Keystone
+ are added as these need to be running on a host that
+ has access to the cloud's private network
+ :param image_metadata: dict() object containing metadata for creating an
+ image with custom config
+ (see YAML files in examples/image-metadata)
+ :param flavor_metadata: dict() object containing the metadata required by
+ your flavor based on your configuration:
+ (i.e. {'hw:mem_page_size': 'large'})
+ :param log_level: the logging level
+ :return: None as the tests will be adding to the 'suite' parameter object
+ """
+ suite.addTest(OSIntegrationTestCase.parameterize(
+ AnsibleProvisioningTests, os_creds=os_creds,
+ ext_net_name=ext_net_name, use_keystone=use_keystone,
+ flavor_metadata=flavor_metadata, image_metadata=image_metadata,
+ log_level=log_level))
+
+
def add_openstack_ci_tests(
suite, os_creds, ext_net_name, use_keystone=True, flavor_metadata=None,
image_metadata=None, use_floating_ips=True, log_level=logging.INFO):
diff --git a/snaps/tests/file_utils_tests.py b/snaps/tests/file_utils_tests.py
index befe37a..e09a9cc 100644
--- a/snaps/tests/file_utils_tests.py
+++ b/snaps/tests/file_utils_tests.py
@@ -31,7 +31,7 @@ class FileUtilsTests(unittest.TestCase):
def setUp(self):
guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
- self.tmp_dir = '.tmp/'
+ self.tmp_dir = 'tmp/'
self.test_dir = self.tmp_dir + str(guid)
if not os.path.exists(self.test_dir):
os.makedirs(self.test_dir)
@@ -44,7 +44,7 @@ class FileUtilsTests(unittest.TestCase):
self.tmp_file_opened.close()
if os.path.exists(self.test_dir) and os.path.isdir(self.test_dir):
- shutil.rmtree(self.tmp_dir)
+ shutil.rmtree(self.test_dir)
def testFileIsDirectory(self):
"""
diff --git a/snaps/thread_utils.py b/snaps/thread_utils.py
new file mode 100644
index 0000000..3a3eb4d
--- /dev/null
+++ b/snaps/thread_utils.py
@@ -0,0 +1,27 @@
+# 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 multiprocessing.pool import ThreadPool
+
+_pool = None
+
+
+# Define a thread pool with a limit for how many simultaneous API requests
+# can be in progress at once.
+def worker_pool(size=5):
+ global _pool
+ if _pool is None:
+ _pool = ThreadPool(processes=size)
+ return _pool
diff --git a/tox.ini b/tox.ini
new file mode 100644
index 0000000..69aa189
--- /dev/null
+++ b/tox.ini
@@ -0,0 +1,17 @@
+[tox]
+minversion = 1.6
+envlist =
+ docs,
+ docs-linkcheck
+skipsdist = true
+
+[testenv:docs]
+deps = -rdocs/requirements.txt
+commands =
+ sphinx-build -b html -n -d {envtmpdir}/doctrees ./docs/ {toxinidir}/docs/_build/html
+ echo "Generated docs available in {toxinidir}/docs/_build/html"
+whitelist_externals = echo
+
+[testenv:docs-linkcheck]
+deps = -rdocs/requirements.txt
+commands = sphinx-build -b linkcheck -d {envtmpdir}/doctrees ./docs/ {toxinidir}/docs/_build/linkcheck