def execute(self): # unpack args skybase_id = self.args.get('skybase_id') planet_name = self.args.get('planet_name') service_name = self.args.get('service_name') continent_tag = self.args.get('tag') stack_name = self.args.get('stack_name') verbose = self.args.get('verbose') # test if any query filtering args are provided to drive type of query no_query_args = skybase_id == planet_name == service_name == continent_tag == stack_name == None # initialize service status query if no_query_args: # no query filter args provided; limit output to planet list query = PlanetStateDbQuery( planet=planet_name, service=service_name, tag=continent_tag, stack=stack_name, query_type=PlanetStateQueryTypes.DRILLDOWN, ) elif skybase_id: # query by unique skybase id query = PlanetStateDbQuery.init_from_id(skybase_id,) else: # query by provided arguments query = PlanetStateDbQuery( planet=planet_name, service=service_name, tag=continent_tag, stack=stack_name, query_type=PlanetStateQueryTypes.WILDCARD, ) # execute query and return standard result query_result = query.format_result_set(query.execute()) # extend query results if working with skybase ID or filter args that return stacks if not no_query_args: for result in query_result: # unpack query result recid, info = result.items()[0] stackname = info['cloud']['stack_name'] # TODO: performance / DRY enhancement: register planet and only init when not present planet_name = recid.split('/')[1] planet = Planet(planet_name) # get stack status try: stack_status = call_cloud_api( planet=planet, stack_name=stackname, action='get_stack_status', ) except Exception as e: stack_status = e.message # add skybase ID info['skybase_id'] = recid # add status to results info['cloud'].update({'stack_status': stack_status}) # query cloud provider for current state information if verbose and stack_status == 'CREATE_COMPLETE': instance_info = call_cloud_api( planet=planet, stack_name=stackname, action='get_instance_info', ) # insert roles info into query result object info['roles'] = instance_info # execute query self.result.output = query_result self.result.format = skytask.output_format_json return self.result
def preflight_check(self): # container for preflight check issues preflight_result = [] # instantiate planet try: self.planet = Planet(self.args.get('planet_name')) except Exception as e: self.preflight_check_result.status = 'FAIL' preflight_result.append(skybase.exceptions.SkyBaseValidationError('planet init: {0}'.format(simple_error_format(e)))) # validate required options to delete one or all stacks if not (self.args.get('stack_name') or self.args.get('delete_all_stacks'))\ or (self.args.get('stack_name') and self.args.get('delete_all_stacks')): self.preflight_check_result.status = 'FAIL' preflight_result.append(('specify one stack or option to delete all stacks for {0}'.format(self.args.get('service_name')))) # validate existence of requested service/stack in state registry query = PlanetStateDbQuery( planet=self.args.get('planet_name'), service=self.args.get('service_name'), tag=self.runtime.tag, stack=self.args.get('stack_name'), query_type='exact', ) # verify unique pointer to service or service/stack if not query.can_find_exact(): self.preflight_check_result.status = 'FAIL' preflight_result.append((skybase.exceptions.SkyBaseDeployError( 'options do not identify a unique service or stack: {0}'.format(query.show_query_path()) ))) # TODO: push stack path into task result # save validated query path for postprocessing self.stack_path = query.query # reconfigure query to read resources for one or many service stacks query.query_type = query.WILDCARD query.query = query.make_query() # collect all stacks for deletion result_set = query.execute() # collect status of launched stacks for record in result_set: # accumulate list of provider stack ids for deletion self.stack_deletion_list.append(record.cloud.stack_id) try: # verify cloud provider DELETE* status for stack id stack_status = skybase.actions.skycloud.call_cloud_api( planet=self.planet, stack_name=record.cloud.stack_id, action='get_stack_status') except Exception as e: raise skybase.exceptions.SkyBaseDeployError(skybase.utils.simple_error_format(e)) if stack_status.startswith('DELETE'): self.preflight_check_result.status = 'FAIL' preflight_result.append(skybase.exceptions.SkyBaseDeployError( 'cannot delete stack {0} with status {1}'.format(record.cloud.stack_id, stack_status))) # accumulate stack information for deleting state db records and logging result self.stack_deletion_info[record.cloud.id] = { 'stack_id': record.cloud.stack_id, 'stack_name': record.cloud.stack_name, } # determine if deployed service used chef server. if so, then prepare to delete chef nodes # TODO: find authoritative location/source for skybase id definition # skybase state DB id skybase_id = '/{0}/{1}/{2}'.format( self.args.get('planet_name'), self.args.get('service_name'), self.runtime.tag, ) # init service registry record and examine blueprint chef type service_record = ServiceRegistryRecord.init_from_id(skybase_id) self.chef_type = service_record.blueprint.definition.get('chef_type') self.is_chef_type_server = (self.chef_type and self.chef_type == 'server') # prepopulate list of host/instance names for use in chef node delete when chef_type server # NOTE: self.stack_chef_nodes = dict() if self.is_chef_type_server: for skybase_stack_id, stack_info in self.stack_deletion_info.items(): self.stack_chef_nodes[stack_info['stack_name']] = skybase.actions.skychef.get_stack_chef_nodes( skybase_stack_id=skybase_stack_id, runner_cfg=self.runner_cfg, ) self.preflight_check_result.set_output(preflight_result) return self.preflight_check_result
def preflight_check(self): # container for preflight check issues preflight_result = [] # instantiate planet try: self.planet = Planet(self.args.get('planet_name')) except Exception as e: self.preflight_check_result.status = 'FAIL' preflight_result.append( skybase.exceptions.SkyBaseValidationError( 'planet init: {0}'.format(simple_error_format(e)))) # validate required options to delete one or all stacks if not (self.args.get('stack_name') or self.args.get('delete_all_stacks'))\ or (self.args.get('stack_name') and self.args.get('delete_all_stacks')): self.preflight_check_result.status = 'FAIL' preflight_result.append( ('specify one stack or option to delete all stacks for {0}'. format(self.args.get('service_name')))) # validate existence of requested service/stack in state registry query = PlanetStateDbQuery( planet=self.args.get('planet_name'), service=self.args.get('service_name'), tag=self.runtime.tag, stack=self.args.get('stack_name'), query_type='exact', ) # verify unique pointer to service or service/stack if not query.can_find_exact(): self.preflight_check_result.status = 'FAIL' preflight_result.append((skybase.exceptions.SkyBaseDeployError( 'options do not identify a unique service or stack: {0}'. format(query.show_query_path())))) # TODO: push stack path into task result # save validated query path for postprocessing self.stack_path = query.query # reconfigure query to read resources for one or many service stacks query.query_type = query.WILDCARD query.query = query.make_query() # collect all stacks for deletion result_set = query.execute() # collect status of launched stacks for record in result_set: # accumulate list of provider stack ids for deletion self.stack_deletion_list.append(record.cloud.stack_id) try: # verify cloud provider DELETE* status for stack id stack_status = skybase.actions.skycloud.call_cloud_api( planet=self.planet, stack_name=record.cloud.stack_id, action='get_stack_status') except Exception as e: raise skybase.exceptions.SkyBaseDeployError( skybase.utils.simple_error_format(e)) if stack_status.startswith('DELETE'): self.preflight_check_result.status = 'FAIL' preflight_result.append( skybase.exceptions.SkyBaseDeployError( 'cannot delete stack {0} with status {1}'.format( record.cloud.stack_id, stack_status))) # accumulate stack information for deleting state db records and logging result self.stack_deletion_info[record.cloud.id] = { 'stack_id': record.cloud.stack_id, 'stack_name': record.cloud.stack_name, } # determine if deployed service used chef server. if so, then prepare to delete chef nodes # TODO: find authoritative location/source for skybase id definition # skybase state DB id skybase_id = '/{0}/{1}/{2}'.format( self.args.get('planet_name'), self.args.get('service_name'), self.runtime.tag, ) # init service registry record and examine blueprint chef type service_record = ServiceRegistryRecord.init_from_id(skybase_id) self.chef_type = service_record.blueprint.definition.get('chef_type') self.is_chef_type_server = (self.chef_type and self.chef_type == 'server') # prepopulate list of host/instance names for use in chef node delete when chef_type server # NOTE: self.stack_chef_nodes = dict() if self.is_chef_type_server: for skybase_stack_id, stack_info in self.stack_deletion_info.items( ): self.stack_chef_nodes[stack_info[ 'stack_name']] = skybase.actions.skychef.get_stack_chef_nodes( skybase_stack_id=skybase_stack_id, runner_cfg=self.runner_cfg, ) self.preflight_check_result.set_output(preflight_result) return self.preflight_check_result