Esempio n. 1
0
    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
Esempio n. 2
0
    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