diff options
Diffstat (limited to 'snaps/openstack/create_stack.py')
-rw-r--r-- | snaps/openstack/create_stack.py | 180 |
1 files changed, 132 insertions, 48 deletions
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): """ |