diff options
Diffstat (limited to 'snaps/openstack/utils')
-rw-r--r-- | snaps/openstack/utils/heat_utils.py | 26 | ||||
-rw-r--r-- | snaps/openstack/utils/nova_utils.py | 12 | ||||
-rw-r--r-- | snaps/openstack/utils/settings_utils.py | 26 | ||||
-rw-r--r-- | snaps/openstack/utils/tests/heat_utils_tests.py | 173 |
4 files changed, 155 insertions, 82 deletions
diff --git a/snaps/openstack/utils/heat_utils.py b/snaps/openstack/utils/heat_utils.py index f2d4efd..f09857a 100644 --- a/snaps/openstack/utils/heat_utils.py +++ b/snaps/openstack/utils/heat_utils.py @@ -227,9 +227,31 @@ def get_stack_servers(heat_cli, nova, stack): return out +def get_stack_keypairs(heat_cli, nova, stack): + """ + Returns a list of Keypair domain objects associated with a Stack + :param heat_cli: the OpenStack heat client object + :param nova: the OpenStack nova client object + :param stack: the SNAPS-OO Stack domain object + :return: a list of VMInst domain objects + """ + + out = list() + resources = get_resources(heat_cli, stack, 'OS::Nova::KeyPair') + for resource in resources: + try: + keypair = nova_utils.get_keypair_by_id(nova, resource.id) + if keypair: + out.append(keypair) + except NotFound: + logger.warn('Keypair cannot be located with ID %s', resource.id) + + return out + + def get_stack_volumes(heat_cli, cinder, stack): """ - Returns an instance of NetworkSettings for each network owned by this stack + Returns an instance of Volume domain objects created by this stack :param heat_cli: the OpenStack heat client object :param cinder: the OpenStack cinder client object :param stack: the SNAPS-OO Stack domain object @@ -251,7 +273,7 @@ def get_stack_volumes(heat_cli, cinder, stack): def get_stack_volume_types(heat_cli, cinder, stack): """ - Returns an instance of NetworkSettings for each network owned by this stack + Returns an instance of VolumeType domain objects created by this stack :param heat_cli: the OpenStack heat client object :param cinder: the OpenStack cinder client object :param stack: the SNAPS-OO Stack domain object diff --git a/snaps/openstack/utils/nova_utils.py b/snaps/openstack/utils/nova_utils.py index 42b7356..0820289 100644 --- a/snaps/openstack/utils/nova_utils.py +++ b/snaps/openstack/utils/nova_utils.py @@ -419,6 +419,18 @@ def get_keypair_by_name(nova, name): return None +def get_keypair_by_id(nova, kp_id): + """ + Returns a list of all available keypairs + :param nova: the Nova client + :param kp_id: the ID of the keypair to return + :return: the keypair object + """ + keypair = nova.keypairs.get(kp_id) + return Keypair(name=keypair.name, kp_id=keypair.id, + public_key=keypair.public_key) + + def delete_keypair(nova, key): """ Deletes a keypair object from OpenStack diff --git a/snaps/openstack/utils/settings_utils.py b/snaps/openstack/utils/settings_utils.py index 7169319..68dbf71 100644 --- a/snaps/openstack/utils/settings_utils.py +++ b/snaps/openstack/utils/settings_utils.py @@ -109,6 +109,32 @@ def create_volume_type_settings(volume_type): qos_spec_name=qos_spec_name, public=volume_type.public) +def create_keypair_settings(heat_cli, stack, keypair, pk_output_key): + """ + Instantiates a KeypairSettings object from a Keypair domain objects + :param heat_cli: the heat client + :param stack: the Stack domain object + :param keypair: the Keypair SNAPS domain object + :param pk_output_key: the key to the heat template's outputs for retrieval + of the private key file + :return: a KeypairSettings object + """ + if pk_output_key: + outputs = heat_utils.get_outputs(heat_cli, stack) + for output in outputs: + if output.key == pk_output_key: + # Save to file + guid = uuid.uuid4() + key_file = file_utils.save_string_to_file( + output.value, str(guid), 0o400) + + # Use outputs, file and resources for the KeypairSettings + return KeypairSettings( + name=keypair.name, private_filepath=key_file.name) + + return KeypairSettings(name=keypair.name) + + def create_vm_inst_settings(nova, neutron, server): """ Returns a NetworkSettings object diff --git a/snaps/openstack/utils/tests/heat_utils_tests.py b/snaps/openstack/utils/tests/heat_utils_tests.py index 4f58613..b021701 100644 --- a/snaps/openstack/utils/tests/heat_utils_tests.py +++ b/snaps/openstack/utils/tests/heat_utils_tests.py @@ -169,22 +169,7 @@ class HeatUtilsCreateSimpleStackTests(OSComponentTestCase): self.assertIsNotNone(outputs) self.assertEqual(0, len(outputs)) - # Wait until stack deployment has completed - end_time = time.time() + create_stack.STACK_COMPLETE_TIMEOUT - is_active = False - while time.time() < end_time: - status = heat_utils.get_stack_status(self.heat_client, - self.stack1.id) - if status == create_stack.STATUS_CREATE_COMPLETE: - is_active = True - break - elif status == create_stack.STATUS_CREATE_FAILED: - is_active = False - break - - time.sleep(3) - - self.assertTrue(is_active) + self.assertTrue(stack_active(self.heat_client, self.stack1)) neutron = neutron_utils.neutron_client(self.os_creds) networks = heat_utils.get_stack_networks( @@ -223,21 +208,7 @@ class HeatUtilsCreateSimpleStackTests(OSComponentTestCase): self.stack1.id) self.assertEqual(self.stack1, stack1_query_3) - end_time = time.time() + create_stack.STACK_COMPLETE_TIMEOUT - is_active = False - while time.time() < end_time: - status = heat_utils.get_stack_status(self.heat_client, - self.stack1.id) - if status == create_stack.STATUS_CREATE_COMPLETE: - is_active = True - break - elif status == create_stack.STATUS_CREATE_FAILED: - is_active = False - break - - time.sleep(3) - - self.assertTrue(is_active) + self.assertTrue(stack_active(self.heat_client, self.stack1)) self.stack2 = heat_utils.create_stack(self.heat_client, self.stack_settings2) @@ -319,21 +290,7 @@ class HeatUtilsCreateComplexStackTests(OSComponentTestCase): self.heat_client = heat_utils.heat_client(self.os_creds) self.stack = heat_utils.create_stack(self.heat_client, stack_settings) - # Wait until stack deployment has completed - end_time = time.time() + create_stack.STACK_COMPLETE_TIMEOUT - is_active = False - while time.time() < end_time: - status = heat_utils.get_stack_status(self.heat_client, - self.stack.id) - if status == create_stack.STATUS_CREATE_COMPLETE: - is_active = True - break - elif status == create_stack.STATUS_CREATE_FAILED: - is_active = False - break - - time.sleep(3) - self.assertTrue(is_active) + self.assertTrue(stack_active(self.heat_client, self.stack)) def tearDown(self): """ @@ -506,23 +463,7 @@ class HeatUtilsVolumeTests(OSComponentTestCase): """ self.stack = heat_utils.create_stack( self.heat_client, self.stack_settings) - - # Wait until stack deployment has completed - end_time = time.time() + create_stack.STACK_COMPLETE_TIMEOUT - is_active = False - while time.time() < end_time: - status = heat_utils.get_stack_status(self.heat_client, - self.stack.id) - if status == create_stack.STATUS_CREATE_COMPLETE: - is_active = True - break - elif status == create_stack.STATUS_CREATE_FAILED: - is_active = False - break - - time.sleep(3) - - self.assertTrue(is_active) + self.assertTrue(stack_active(self.heat_client, self.stack)) volumes = heat_utils.get_stack_volumes( self.heat_client, self.cinder, self.stack) @@ -541,23 +482,7 @@ class HeatUtilsVolumeTests(OSComponentTestCase): """ self.stack = heat_utils.create_stack( self.heat_client, self.stack_settings) - - # Wait until stack deployment has completed - end_time = time.time() + create_stack.STACK_COMPLETE_TIMEOUT - is_active = False - while time.time() < end_time: - status = heat_utils.get_stack_status(self.heat_client, - self.stack.id) - if status == create_stack.STATUS_CREATE_COMPLETE: - is_active = True - break - elif status == create_stack.STATUS_CREATE_FAILED: - is_active = False - break - - time.sleep(3) - - self.assertTrue(is_active) + self.assertTrue(stack_active(self.heat_client, self.stack)) volume_types = heat_utils.get_stack_volume_types( self.heat_client, self.cinder, self.stack) @@ -578,3 +503,91 @@ class HeatUtilsVolumeTests(OSComponentTestCase): self.assertEqual(u'nova.volume.encryptors.luks.LuksEncryptor', encryption.provider) self.assertEqual(volume_type.id, encryption.volume_type_id) + + +class HeatUtilsKeypairTests(OSComponentTestCase): + """ + Test Heat volume functionality + """ + + def setUp(self): + """ + Instantiates OpenStack instances that cannot be spawned by Heat + """ + guid = self.__class__.__name__ + '-' + str(uuid.uuid4()) + stack_name = guid + '-stack' + self.keypair_name = guid + '-kp' + + env_values = { + 'keypair_name': self.keypair_name} + + heat_tmplt_path = pkg_resources.resource_filename( + 'snaps.openstack.tests.heat', 'keypair_heat_template.yaml') + self.stack_settings = StackSettings( + 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) + + def tearDown(self): + """ + Cleans the image and downloaded image file + """ + if self.stack: + try: + heat_utils.delete_stack(self.heat_client, self.stack) + except: + pass + + def test_create_keypair_with_stack(self): + """ + Tests the creation of an OpenStack keypair with Heat. + """ + self.stack = heat_utils.create_stack( + self.heat_client, self.stack_settings) + self.assertTrue(stack_active(self.heat_client, self.stack)) + + keypairs = heat_utils.get_stack_keypairs( + self.heat_client, self.nova, self.stack) + + self.assertEqual(1, len(keypairs)) + keypair = keypairs[0] + + self.assertEqual(self.keypair_name, keypair.name) + + outputs = heat_utils.get_outputs(self.heat_client, self.stack) + + for output in outputs: + if output.key == 'private_key': + self.assertTrue(output.value.startswith( + '-----BEGIN RSA PRIVATE KEY-----')) + + keypair = nova_utils.get_keypair_by_id(self.nova, keypair.id) + self.assertIsNotNone(keypair) + + self.assertEqual(self.keypair_name, keypair.name) + + +def stack_active(heat_cli, stack): + """ + Blocks until stack application has successfully completed or failed + :param heat_cli: the Heat client + :param stack: the Stack domain object + :return: T/F + """ + # Wait until stack deployment has completed + end_time = time.time() + create_stack.STACK_COMPLETE_TIMEOUT + is_active = False + while time.time() < end_time: + status = heat_utils.get_stack_status(heat_cli, stack.id) + if status == create_stack.STATUS_CREATE_COMPLETE: + is_active = True + break + elif status == create_stack.STATUS_CREATE_FAILED: + is_active = False + break + + time.sleep(3) + + return is_active |