Example #1
0
    def execute(self):

        """
        give the user name and role, create password and create a record in dbauth, return username, password, role
        """
        self.result.format = skytask.output_format_json

        if self.apply:
            try:
                # attempt to new user records from options
                create_user(self.username, self.secret, self.email, self.role)

                # attempt to read newly created record
                user_record = find_user(self.username)[0]

                # check for non-empty list of records; find_user() returns single/unique
                if user_record:
                    self.result.status = sky_cfg.API_STATUS_SUCCESS
                    self.result.output = 'user added: {0}'.format(find_user(self.username)[0])
                else:
                    self.result.status = sky_cfg.API_STATUS_FAIL
                    self.result.output = 'failure to create new user record: {0}'.format(
                        simple_error_format(SkyBaseUserIdNotFoundError(self.username))
                    )
            except (skybase.exceptions.SkyBaseError, sqlite3.Error) as e:
                self.result.output = simple_error_format(e)
                self.result.status = sky_cfg.API_STATUS_FAIL

        else:
            self.result.status = sky_cfg.API_STATUS_SUCCESS
            self.result.output = 'user record to be added: {0}; --apply required'.format(self.username)

        return self.result
Example #2
0
def delete_chef_nodes(planet, runtime, nodes):
    result = dict()

    for node in nodes:
        result[node] = dict()
        try:
            if runtime.apply:
                try:
                    result[node][
                        'delete_node'] = skybase.actions.sky_chef.delete_node(
                            planet=planet, node=node)
                except Exception as e:
                    result[node]['delete_node'] = simple_error_format(e)
                else:
                    try:
                        result[node][
                            'delete_client'] = skybase.actions.sky_chef.delete_client(
                                planet=planet, client=node)
                    except Exception as e:
                        result[node]['delete_client'] = simple_error_format(e)
            else:
                result[node]['get_node'] = skybase.actions.sky_chef.get_node(
                    planet=planet, node=node)

        except Exception as e:
            result[node] = simple_error_format(e)

    return result
Example #3
0
    def preflight_check(self):
        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 stacks for errors before writing to service state registry
        try:
            are_stacks_valid = skybase.actions.skycloud.are_stacks_valid(
                self.planet.orchestration_engine, self.stacks)

            if not are_stacks_valid:
                self.preflight_check_result.status = 'FAIL'
                preflight_result.append(
                    skybase.exceptions.SkyBaseValidationError(
                        'cannot write service state record with invalid stacks'
                    ))

        except Exception as e:
            self.preflight_check_result.status = 'FAIL'
            preflight_result.append(
                skybase.exceptions.SkyBaseValidationError(
                    'test for valid stacks: {0}'.format(
                        simple_error_format(e))))

        self.preflight_check_result.set_output(preflight_result)
        return self.preflight_check_result
Example #4
0
def execute(self, skytask_name, skytask_args, **kwargs):

    try:
        # initialize skytask from class name and submitted args
        skytask = Runner(skytask_name, skytask_args)

    except skybase.exceptions.SkyBaseError as e:
        # create a result object to handle Runner() init exceptions
        execute_result = TaskResult()
        execute_result.status = 'FAIL'
        execute_result.output = simple_error_format(e)

        logger.warning('Runner({0}) failed to instantiate: {1}'.format(
            skytask_name, simple_error_format(e)))

    else:
        # attempt to execute successfully created skytask
        execute_result = skytask.execute()

        if len(execute_result.next_task_name) > 0:
            # queue up next/postproc tasks
            # execute task in async mode, routing it to derived message queue

            # TODO: route to correct queue based on next_task_name and planet args if exist
            celery_result = execute.apply_async(
                args=[execute_result.next_task_name, execute_result.next_args],
                queue='admin',
                kwargs={},
            )

            logger.info('{0} next task_id: {1}'.format(skytask_name,
                                                       celery_result))

    return execute_result.convert_to_string()
Example #5
0
    def execute(self):
        """
        give the user name and role, create password and create a record in dbauth, return username, password, role
        """
        self.result.format = skytask.output_format_json

        if self.apply:
            try:
                # attempt to new user records from options
                create_user(self.username, self.secret, self.email, self.role)

                # attempt to read newly created record
                user_record = find_user(self.username)[0]

                # check for non-empty list of records; find_user() returns single/unique
                if user_record:
                    self.result.status = sky_cfg.API_STATUS_SUCCESS
                    self.result.output = 'user added: {0}'.format(
                        find_user(self.username)[0])
                else:
                    self.result.status = sky_cfg.API_STATUS_FAIL
                    self.result.output = 'failure to create new user record: {0}'.format(
                        simple_error_format(
                            SkyBaseUserIdNotFoundError(self.username)))
            except (skybase.exceptions.SkyBaseError, sqlite3.Error) as e:
                self.result.output = simple_error_format(e)
                self.result.status = sky_cfg.API_STATUS_FAIL

        else:
            self.result.status = sky_cfg.API_STATUS_SUCCESS
            self.result.output = 'user record to be added: {0}; --apply required'.format(
                self.username)

        return self.result
Example #6
0
    def preflight_check(self):
        # initialize results container
        preflight_result = []

        # instantiate planet
        try:
            self.planet = Planet(self.args.get('planet'))
        except Exception as e:
            self.preflight_check_result.status = 'FAIL'
            preflight_result.append(
                skybase.exceptions.SkyBaseValidationError(
                    'planet init: {0}'.format(simple_error_format(e))))

        try:
            self.node = sky_chef_actions.get_node(self.planet,
                                                  self.args.get('node'),
                                                  self.logger)
        except Exception as e:
            self.preflight_check_result.status = 'FAIL'
            preflight_result.append(
                skybase.exceptions.SkyBaseValidationError(
                    'could not find node "{0}": {1}'.format(
                        self.args.get('node'), simple_error_format(e))))

        self.preflight_check_result.set_output(preflight_result)
        return self.preflight_check_result
Example #7
0
def execute(self, skytask_name, skytask_args, **kwargs):

    try:
        # initialize skytask from class name and submitted args
        skytask = Runner(skytask_name, skytask_args)

    except skybase.exceptions.SkyBaseError as e:
        # create a result object to handle Runner() init exceptions
        execute_result = TaskResult()
        execute_result.status = 'FAIL'
        execute_result.output = simple_error_format(e)

        logger.warning('Runner({0}) failed to instantiate: {1}'.format(skytask_name, simple_error_format(e)))

    else:
        # attempt to execute successfully created skytask
        execute_result = skytask.execute()

        if len(execute_result.next_task_name) > 0:
            # queue up next/postproc tasks
            # execute task in async mode, routing it to derived message queue

            # TODO: route to correct queue based on next_task_name and planet args if exist
            celery_result = execute.apply_async(
                args=[execute_result.next_task_name, execute_result.next_args],
                queue='admin',
                kwargs={},
            )

            logger.info('{0} next task_id: {1}'.format(skytask_name, celery_result))

    return execute_result.convert_to_string()
Example #8
0
    def execute(self):

        try:
            sky_chef_actions.delete_node(self.planet, self.args.get('node'),
                                         self.logger)
        except Exception as e:
            self.result.status = sky_cfg.API_STATUS_FAIL
            raise skybase.exceptions.SkyBaseResponseError(
                'Could not delete node "{0}" from Chef: {1}'.format(
                    self.args.get('node'), simple_error_format(e)))

        try:
            sky_chef_actions.delete_client(self.planet, self.args.get('node'),
                                           self.logger)
        except Exception as e:
            self.result.status = sky_cfg.API_STATUS_FAIL
            raise skybase.exceptions.SkyBaseResponseError(
                'Could not delete node client "{0}" from Chef: {1}'.format(
                    self.args.get('node'), simple_error_format(e)))

        self.result.status = sky_cfg.API_STATUS_SUCCESS
        self.result.output = 'Node "{0}" has been deleted from Chef'.format(
            self.args.get('node'))

        return self.result
Example #9
0
    def execute(self):

        """
        update user email and/or role
        """
        self.result.format = skytask.output_format_json

        if self.apply:
            try:
                # attempt to update user information
                if self.email:
                    update_email(self.username, self.email)
                if self.role:
                    upsert_userroles(self.username, self.role)

                self.result.status = sky_cfg.API_STATUS_SUCCESS
                self.result.output = 'user updated: {0}'.format(find_user(self.username)[0])

            except (skybase.exceptions.SkyBaseError, sqlite3.Error) as e:
                self.result.output = simple_error_format(e)
                self.result.status = sky_cfg.API_STATUS_FAIL

        else:
            self.result.status = sky_cfg.API_STATUS_SUCCESS
            self.result.output = 'user not updated: {0}; --apply required'.format(find_user(self.username)[0])

        return self.result
Example #10
0
    def execute(self):
        """
        delete one user record
        """
        self.result.format = skytask.output_format_raw

        if self.apply:
            try:
                # attempt to delete record using username
                delete_user(self.username)

                if not unique_user_exists(self.username):
                    self.result.status = sky_cfg.API_STATUS_SUCCESS
                    self.result.output = 'user record deleted: {0}'.format(self.username)
                else:
                    self.result.status = sky_cfg.API_STATUS_FAIL
                    self.result.output = 'delete attempt failed user: {0}'.format(self.username)

            except (skybase.exceptions.SkyBaseError, sqlite3.Error) as e:
                self.result.output = simple_error_format(e)
                self.result.status = sky_cfg.API_STATUS_FAIL

        else:
            self.result.status = sky_cfg.API_STATUS_SUCCESS
            self.result.output = 'user record to be deleted: {0}; --apply required'.format(self.username)

        return self.result
Example #11
0
    def execute(self):
        """
        delete one user record
        """
        self.result.format = skytask.output_format_raw

        if self.apply:
            try:
                # attempt to delete record using username
                delete_user(self.username)

                if not unique_user_exists(self.username):
                    self.result.status = sky_cfg.API_STATUS_SUCCESS
                    self.result.output = 'user record deleted: {0}'.format(
                        self.username)
                else:
                    self.result.status = sky_cfg.API_STATUS_FAIL
                    self.result.output = 'delete attempt failed user: {0}'.format(
                        self.username)

            except (skybase.exceptions.SkyBaseError, sqlite3.Error) as e:
                self.result.output = simple_error_format(e)
                self.result.status = sky_cfg.API_STATUS_FAIL

        else:
            self.result.status = sky_cfg.API_STATUS_SUCCESS
            self.result.output = 'user record to be deleted: {0}; --apply required'.format(
                self.username)

        return self.result
Example #12
0
def delete_stack_chef_roles(planet, runtime, stacks):

    result = dict()

    for skybase_stack_id in stacks.keys():

        skybase_id, stack_name = os.path.split(skybase_stack_id)
        service = ServiceRegistryRecord.init_from_id(skybase_id)

        for role in service.blueprint.stacks[stack_name]['roles']:

            chef_role_name = make_chef_role_name(
                role_name=role,
                deploy_tag=service.tag,
            )

            try:
                if runtime.apply:
                    if skybase.actions.skycloud.is_stack_deleted_or_not_found(planet, stack_name):
                        result[chef_role_name] = skybase.actions.sky_chef.delete_role(planet=planet, role=chef_role_name)
                    else:
                        result[chef_role_name] = 'stack {0} exists.  cannot delete chef role {1}'.format(stack_name, chef_role_name)
                else:
                    result[chef_role_name] = skybase.actions.sky_chef.get_role(planet=planet, role=chef_role_name)
            except Exception as e:
                result[chef_role_name] = simple_error_format(e)

    return result
Example #13
0
    def execute(self):
        """
        update user email and/or role
        """
        self.result.format = skytask.output_format_json

        if self.apply:
            try:
                # attempt to update user information
                if self.email:
                    update_email(self.username, self.email)
                if self.role:
                    upsert_userroles(self.username, self.role)

                self.result.status = sky_cfg.API_STATUS_SUCCESS
                self.result.output = 'user updated: {0}'.format(
                    find_user(self.username)[0])

            except (skybase.exceptions.SkyBaseError, sqlite3.Error) as e:
                self.result.output = simple_error_format(e)
                self.result.status = sky_cfg.API_STATUS_FAIL

        else:
            self.result.status = sky_cfg.API_STATUS_SUCCESS
            self.result.output = 'user not updated: {0}; --apply required'.format(
                find_user(self.username)[0])

        return self.result
Example #14
0
def delete_stack_chef_roles(planet, runtime, stacks):

    result = dict()

    for skybase_stack_id in stacks.keys():

        skybase_id, stack_name = os.path.split(skybase_stack_id)
        service = ServiceRegistryRecord.init_from_id(skybase_id)

        for role in service.blueprint.stacks[stack_name]['roles']:

            chef_role_name = make_chef_role_name(
                role_name=role,
                deploy_tag=service.tag,
            )

            try:
                if runtime.apply:
                    if skybase.actions.skycloud.is_stack_deleted_or_not_found(
                            planet, stack_name):
                        result[
                            chef_role_name] = skybase.actions.sky_chef.delete_role(
                                planet=planet, role=chef_role_name)
                    else:
                        result[
                            chef_role_name] = 'stack {0} exists.  cannot delete chef role {1}'.format(
                                stack_name, chef_role_name)
                else:
                    result[chef_role_name] = skybase.actions.sky_chef.get_role(
                        planet=planet, role=chef_role_name)
            except Exception as e:
                result[chef_role_name] = simple_error_format(e)

    return result
Example #15
0
    def execute(self):
        self.result.output = dict()
        self.result.format = skytask.output_format_json

        self.result.output[
            'chef_update'] = skybase.actions.skychef.chef_update(
                planet=self.planet,
                service=self.source_service,
                runtime=self.runtime,
                config=self.runner_cfg,
            )

        self.result.output[
            'package_transfer'] = skybase.actions.skycloud.package_transfer(
                planet=self.planet,
                service=self.source_service,
                runtime=self.runtime,
                system=self.system,
            )

        self.result.output[
            'salt_grains_transfer'] = skybase.actions.skycloud.salt_grains_transfer(
                planet=self.planet,
                service=self.source_service,
                runtime=self.runtime,
                system=self.system,
            )

        self.result.output[
            'salt_update_service'] = skybase.actions.salt.update_service(
                service=self.target_service,
                stacks=self.source_service.deploy.stack_launch_list,
                runtime=self.runtime,
                update_plan=self.update_plan,
                authtoken=self.authtoken,
            )

        # modify service registry record on successful update
        if self.runtime.apply:
            self.target_service.metadata.version = self.source_service.manifest.get(
                'app_version')
            self.target_service.metadata.build = self.source_service.manifest.get(
                'build_id')
            self.target_service.metadata.artiball = self.source_artiball

            # attempt to update state db record
            try:
                self.result.output['update_service_registry'] = \
                    skybase.actions.state.update(
                        mode=self.mode,
                        record_id=self.id,
                        service_record=self.target_service.serialize_as_yaml(),
                        credentials=sky_cfg.SkyConfig.init_from_file('credentials').data,
                    )
            except SkyBaseError as e:
                self.result.output[
                    'update_service_registry'] = simple_error_format(e)

        self.result.format = skytask.output_format_json
        return self.result
Example #16
0
def get_chef_nodes(planet, nodes):
    result =  dict()
    for node in nodes:
        try:
            result[node] = skybase.actions.sky_chef.get_node(planet, node)
        except Exception as e:
            result[node] = simple_error_format(e)
    return result
Example #17
0
def get_chef_nodes(planet, nodes):
    result = dict()
    for node in nodes:
        try:
            result[node] = skybase.actions.sky_chef.get_node(planet, node)
        except Exception as e:
            result[node] = simple_error_format(e)
    return result
Example #18
0
 def get_restapi_execute_result(self, response):
     # extract results from backend db using execution link in response
     try:
         # result = self.pollwait(json.loads(response)['links']['result']['href'])
         result = self.pollwait(response['links']['result']['href'])
         result_data = result['data']
         return result_data
     except Exception as e:
         raise SkyBaseResponseError('{0} when accessing execution results'.format(simple_error_format(e)))
Example #19
0
 def get_restapi_execute_result(self, response):
     # extract results from backend db using execution link in response
     try:
         # result = self.pollwait(json.loads(response)['links']['result']['href'])
         result = self.pollwait(response['links']['result']['href'])
         result_data = result['data']
         return result_data
     except Exception as e:
         raise SkyBaseResponseError(
             '{0} when accessing execution results'.format(
                 simple_error_format(e)))
Example #20
0
    def preflight_check(self):
        # initialize results container
        preflight_result = []
        if not unique_user_exists(self.username):
            self.preflight_check_result.status = 'FAIL'
            preflight_result.append(simple_error_format(
                SkyBaseUserAuthorizationError(
                    'cannot find username: {0}'.format(self.username))))

        self.preflight_check_result.set_output(preflight_result)
        return self.preflight_check_result
Example #21
0
    def preflight_check(self):
        # initialize results container
        preflight_result = []
        if not unique_user_exists(self.username):
            self.preflight_check_result.status = 'FAIL'
            preflight_result.append(
                simple_error_format(
                    SkyBaseUserAuthorizationError(
                        'cannot find username: {0}'.format(self.username))))

        self.preflight_check_result.set_output(preflight_result)
        return self.preflight_check_result
Example #22
0
    def execute(self):
        """
        list all users and roles from auth db
        """
        self.result.format = skytask.output_format_json
        try:
            self.result.output = list_users(self.username)
            self.result.status = sky_cfg.API_STATUS_SUCCESS
        except (skybase.exceptions.SkyBaseError, sqlite3.Error) as e:
            self.result.output = simple_error_format(e)
            self.result.status = sky_cfg.API_STATUS_FAIL

        return self.result
Example #23
0
def update(self, record_id, record_object, **kwargs):

    try:
        logger.info('attempt to instantiate update state db record ({0}, {1})'.format(id, kwargs))

        # attempt to read state db record from local resources
        result = skybase.actions.state.local.update(record_id, record_object, **kwargs)

    except skybase.exceptions.SkyBaseError as e:
        logger.info('failed to instantiate ServiceRegistryRecord({0})'.format(id))
        result = simple_error_format(e)

    return result
Example #24
0
    def execute(self):
        """
        list all users and roles from auth db
        """
        self.result.format = skytask.output_format_json
        try:
            self.result.output = list_users(self.username)
            self.result.status = sky_cfg.API_STATUS_SUCCESS
        except (skybase.exceptions.SkyBaseError, sqlite3.Error) as e:
            self.result.output = simple_error_format(e)
            self.result.status = sky_cfg.API_STATUS_FAIL

        return self.result
Example #25
0
def create(self, planet_name, service_name, tag, registration, provider, stacks, **kwargs):

    try:
        logger.info('attempt to instantiate update state db record ({0}, {1})'.format(id, kwargs))

        # attempt to read state db record from local resources
        result = skybase.actions.state.local.create(planet_name, service_name, tag, registration, provider, stacks, **kwargs)

    except skybase.exceptions.SkyBaseError as e:
        logger.info('failed to create ServiceRegistryRecord({0})'.format(id))
        result = simple_error_format(e)

    return result
Example #26
0
    def pollwait(self, url, timeout=None, retry_interval=RETRY):

        if timeout is None:
            timeout = min(
                self.cli_cfg.data.get('result_fetch_timeout',
                                      SkyCmd.TIMEOUT_DEFAULT),
                SkyCmd.TIMEOUT_MAX)

        # wait for celery task status SUCCESS over timeout interval
        start_time = time.time()

        while time.time() - start_time < timeout:
            execute_result = self.probe(url)

            try:
                status = execute_result['metadata']['task_status']
            except KeyError as e:
                raise SkyBaseResponseError(
                    '{0} when accessing response status'.format(
                        simple_error_format(e)))

            if status == 'PENDING':
                # TODO: progress bar would be nice, but needs to not interfere with json prettyprint
                time.sleep(retry_interval)

            elif status == 'SUCCESS':
                # return execute task results data if exists
                try:
                    return execute_result
                except KeyError as e:
                    raise SkyBaseResponseError(
                        '{0} when accessing response results'.format(
                            simple_error_format(e)))
            else:
                raise SkyBaseError('unknown task status: {0}'.format(status))

        raise SkyBaseTimeOutError(
            'attempt to fetch results failed after {0}s'.format(timeout))
Example #27
0
def delete_chef_nodes(planet, runtime, nodes):
    result = dict()

    for node in nodes:
        result[node] = dict()
        try:
            if runtime.apply:
                try:
                    result[node]['delete_node'] = skybase.actions.sky_chef.delete_node(planet=planet, node=node)
                except Exception as e:
                    result[node]['delete_node'] = simple_error_format(e)
                else:
                    try:
                        result[node]['delete_client'] = skybase.actions.sky_chef.delete_client(planet=planet, client=node)
                    except Exception as e:
                        result[node]['delete_client'] = simple_error_format(e)
            else:
                result[node]['get_node'] = skybase.actions.sky_chef.get_node(planet=planet, node=node)

        except Exception as e:
            result[node] = simple_error_format(e)

    return result
Example #28
0
    def preflight_check(self):
        # initialize results container
        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))))

        self.preflight_check_result.set_output(preflight_result)
        return self.preflight_check_result
Example #29
0
    def init_from_file(cls, schema_name, config_dir=CONFIG_DIR):
        # prepare configuration filename
        config_file_name = '/'.join([config_dir, schema_name + '.yaml'])
        config_file = os.path.expanduser(config_file_name)

        # read in target configuration filea and attempt to init class
        try:
            runner_config_data = read_yaml_from_file(config_file)
        except (IOError, ScannerError, ParserError) as e:
            # wrap all expected errors as SkyBaseError type
            raise SkyBaseConfigurationError(simple_error_format(e))

        cfg = cls(schema_name, runner_config_data)

        return cfg
Example #30
0
    def preflight_check(self):
        preflight_result = []

        # require that username exists before resetting secret
        if not unique_user_exists(self.username):
            self.preflight_check_result.status = 'FAIL'
            preflight_result.append(simple_error_format(
                skybase.exceptions.SkyBaseUserIdNotFoundError(
                    'username {0} not found'.format(self.username))))

        if not self.secret:
            self.secret = generate_random_key()

        self.preflight_check_result.set_output(preflight_result)
        return self.preflight_check_result
Example #31
0
    def init_from_file(cls, schema_name, config_dir=CONFIG_DIR):
        # prepare configuration filename
        config_file_name = '/'.join([config_dir, schema_name + '.yaml'])
        config_file = os.path.expanduser(config_file_name)

        # read in target configuration filea and attempt to init class
        try:
            runner_config_data = read_yaml_from_file(config_file)
        except (IOError, ScannerError, ParserError) as e:
            # wrap all expected errors as SkyBaseError type
            raise SkyBaseConfigurationError(simple_error_format(e))

        cfg = cls(schema_name, runner_config_data)

        return cfg
Example #32
0
    def preflight_check(self):
        # initialize results container
        preflight_result = []

        # validate that username doesn't exist
        if unique_user_exists(self.username):
            self.preflight_check_result.status = 'FAIL'
            preflight_result.append(simple_error_format(
                SkyBaseUserAuthorizationError(
                    'username {0} exists'.format(self.username))))

        if not self.secret:
            # if secret not defined, generate a secret key
            self.secret = generate_random_key()

        self.preflight_check_result.set_output(preflight_result)
        return self.preflight_check_result
Example #33
0
 def execute(self):
     """
     reset secret for existing user.
     """
     self.result.format = skytask.output_format_json
     if self.apply:
         try:
             reset_password(self.username, self.secret)
             self.result.output = 'user secret for {0}: {1}'.format(self.username, self.secret)
             self.result.status = sky_cfg.API_STATUS_SUCCESS
         except (skybase.exceptions.SkyBaseError, sqlite3.Error) as e:
             self.result.output = '{0}; (username, secret) = ({1}, {2})'.format(simple_error_format(e), self.username, self.secret)
             self.result.status = sky_cfg.API_STATUS_FAIL
     else:
         self.result.output = 'user secret target for {0}: {1}; --apply required'.format(self.username, self.secret)
         self.result.status = sky_cfg.API_STATUS_SUCCESS
     return self.result
Example #34
0
    def preflight_check(self):
        # initialize results container
        preflight_result = []

        # validate that username doesn't exist
        if unique_user_exists(self.username):
            self.preflight_check_result.status = 'FAIL'
            preflight_result.append(
                simple_error_format(
                    SkyBaseUserAuthorizationError('username {0} exists'.format(
                        self.username))))

        if not self.secret:
            # if secret not defined, generate a secret key
            self.secret = generate_random_key()

        self.preflight_check_result.set_output(preflight_result)
        return self.preflight_check_result
Example #35
0
    def preflight_check(self):
        # initialize results container
        preflight_result = []

        # validate that username exists
        if not unique_user_exists(self.username):
            self.preflight_check_result.status = 'FAIL'
            preflight_result.append(simple_error_format(
                SkyBaseUserAuthorizationError(
                    'cannot find username: {0}'.format(self.username))))

        # require at least something to update
        if self.role is None and self.email is None:
            self.preflight_check_result.status = 'FAIL'
            preflight_result.append('choose at least one update option: --role, --email')

        self.preflight_check_result.set_output(preflight_result)
        return self.preflight_check_result
Example #36
0
 def update(self):
     try:
         self.metadata.update()
         self.blueprint.update()
         # TODO: COOKBOOK_ONLY first and only update type supported.  will eventually derive from --plan option and artiball config
         log_entry = '{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}\n'.format(
             basic_timestamp(),
             'UPDATE_RERUN',
             self.service,
             self.metadata.version,
             self.metadata.build,
             self.tag,
             self.metadata.artiball,
         )
         self.log.update(log_entry)
         return True
     except Exception as e:
         return simple_error_format(e)
Example #37
0
    def execute(self):
        self.result.output = dict()
        self.result.format = skytask.output_format_json

        self.result.output["chef_update"] = skybase.actions.skychef.chef_update(
            planet=self.planet, service=self.source_service, runtime=self.runtime, config=self.runner_cfg
        )

        self.result.output["package_transfer"] = skybase.actions.skycloud.package_transfer(
            planet=self.planet, service=self.source_service, runtime=self.runtime, system=self.system
        )

        self.result.output["salt_grains_transfer"] = skybase.actions.skycloud.salt_grains_transfer(
            planet=self.planet, service=self.source_service, runtime=self.runtime, system=self.system
        )

        self.result.output["salt_update_service"] = skybase.actions.salt.update_service(
            service=self.target_service,
            stacks=self.source_service.deploy.stack_launch_list,
            runtime=self.runtime,
            update_plan=self.update_plan,
            authtoken=self.authtoken,
        )

        # modify service registry record on successful update
        if self.runtime.apply:
            self.target_service.metadata.version = self.source_service.manifest.get("app_version")
            self.target_service.metadata.build = self.source_service.manifest.get("build_id")
            self.target_service.metadata.artiball = self.source_artiball

            # attempt to update state db record
            try:
                self.result.output["update_service_registry"] = skybase.actions.state.update(
                    mode=self.mode,
                    record_id=self.id,
                    service_record=self.target_service.serialize_as_yaml(),
                    credentials=sky_cfg.SkyConfig.init_from_file("credentials").data,
                )
            except SkyBaseError as e:
                self.result.output["update_service_registry"] = simple_error_format(e)

        self.result.format = skytask.output_format_json
        return self.result
Example #38
0
    def preflight_check(self):
        # initialize results container
        preflight_result = []

        # validate that username exists
        if not unique_user_exists(self.username):
            self.preflight_check_result.status = 'FAIL'
            preflight_result.append(
                simple_error_format(
                    SkyBaseUserAuthorizationError(
                        'cannot find username: {0}'.format(self.username))))

        # require at least something to update
        if self.role is None and self.email is None:
            self.preflight_check_result.status = 'FAIL'
            preflight_result.append(
                'choose at least one update option: --role, --email')

        self.preflight_check_result.set_output(preflight_result)
        return self.preflight_check_result
Example #39
0
    def submit_http_request(self):
        # prepare request data/body
        data = {
            'args': vars(self.args),
            'metadata': self.prepare_job_metadata()
        }

        # sign data request body with user credentials
        request_signature = skybase.api.create_signature(
            self.sky_credentials.data['key'], json.dumps(data))

        # prepare request header
        headers = {
            sky_cfg.API_HTTP_HEADER_ACCESS_KEY:
            self.sky_credentials.data['user_id'],
            sky_cfg.API_HTTP_HEADER_SIGNATURE:
            request_signature,
        }

        # get default restapi task url
        restapi_url = skybase.api.create_api_url(
            server=self.cli_cfg.get_data_value(
                'restapi_server_url', data_default=sky_cfg.API_SERVER),
            route=sky_cfg.API_ROUTES.get('task'),
        )

        # gather query parameter string
        params = self.get_request_params()

        # post request to restapi
        try:
            response = requests.post(
                restapi_url,
                params=params,
                headers=headers,
                data=json.dumps(data),
            )
        except requests.exceptions.ConnectionError as e:
            raise SkyBaseRestAPIError(simple_error_format(e))

        return response
Example #40
0
    def execute(self):

        # attempt to read state db record
        try:
            result = skybase.actions.state.read(
                mode=self.mode,
                record_id=self.id,
                credentials=sky_cfg.SkyConfig.init_from_file('credentials').data,
                format=self.format
            )
        except skybase.exceptions.SkyBaseError as e:
            result = simple_error_format(e)

        # set result output mode; --format default = json
        if self.format == 'yaml':
            self.result.format = skytask.output_format_raw
        else:
            self.result.format = skytask.output_format_json

        self.result.output = result

        return self.result
Example #41
0
    def submit_http_request(self):
        # prepare request data/body
        data = {
            'args': vars(self.args),
            'metadata': self.prepare_job_metadata()
        }

        # sign data request body with user credentials
        request_signature = skybase.api.create_signature(self.sky_credentials.data['key'], json.dumps(data))

        # prepare request header
        headers = {
            sky_cfg.API_HTTP_HEADER_ACCESS_KEY: self.sky_credentials.data['user_id'],
            sky_cfg.API_HTTP_HEADER_SIGNATURE: request_signature,
        }

        # get default restapi task url
        restapi_url = skybase.api.create_api_url(
            server=self.cli_cfg.get_data_value('restapi_server_url', data_default=sky_cfg.API_SERVER),
            route=sky_cfg.API_ROUTES.get('task'),
        )

        # gather query parameter string
        params = self.get_request_params()

        # post request to restapi
        try:
            response = requests.post(
                restapi_url,
                params=params,
                headers=headers,
                data=json.dumps(data),
            )
        except requests.exceptions.ConnectionError as e:
            raise SkyBaseRestAPIError(simple_error_format(e))

        return response
Example #42
0
    def preflight_check(self):
        # initialize results container
        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))))

        self.preflight_check_result.set_output(preflight_result)
        return self.preflight_check_result
Example #43
0
    def preflight_check(self):
        preflight_result = []

        # TODO: move reusable preflight functions/tests to skybase.skytask.service
        # instantiate planet from --planet option
        try:
            self.planet = Planet(self.planet_name)
        except Exception as e:
            self.preflight_check_result.status = "FAIL"
            preflight_result.append(SkyBaseValidationError("source planet init: {0}".format(simple_error_format(e))))

        try:
            # attempt transfer artiball to worker
            if not os.path.exists(
                os.path.join(self.runner_cfg.data["artiball_data_dir"], self.args.get("source_artiball"))
            ):
                artiball_transfer(
                    artiball_key=self.args.get("source_artiball"),
                    bucket_name=self.runner_cfg.data["buckets"]["cache"]["name"],
                    profile=self.runner_cfg.data["buckets"]["cache"]["profile"],
                    release_dir=self.runner_cfg.data["artiball_data_dir"],
                )
        except boto.exception.S3ResponseError as e:
            self.preflight_check_result.status = "FAIL"
            preflight_result.append(
                SkyBaseValidationError("artiball transfer: {0}: {1}".format(type(e).__name__, str(e.message)))
            )
        except Exception as e:
            self.preflight_check_result.status = "FAIL"
            preflight_result.append(SkyBaseValidationError("artiball transfer: {0}".format(simple_error_format(e))))
        else:
            # initialize SkyService from source artiball
            try:
                self.source_service = SkyService().init_from_artiball(
                    artiball_name=self.source_artiball, artiball_data_dir=self.runner_cfg.data["artiball_data_dir"]
                )
                self.chef_type = self.source_service.deploy.definition.get("chef_type", "server")
            except Exception as e:
                self.preflight_check_result.status = "FAIL"
                preflight_result.append(SkyBaseValidationError("sky service init: {0}".format(simple_error_format(e))))
            else:

                # test CLI stack option values against SkyService stacks
                try:
                    bad_stacks = []
                    for stack in self.args["stack_list"]:
                        if stack not in self.source_service.deploy.stack_ids:
                            bad_stacks.append(stack)

                    if bad_stacks:
                        self.preflight_check_result.status = "FAIL"
                        preflight_result.append(
                            SkyBaseValidationError(
                                "source service {0}: unknown stacks {1}".format(self.source_service.name, bad_stacks)
                            )
                        )
                    else:
                        # given all good stacks, prepare stack launch list target
                        self.source_service.deploy.stack_launch_list = (
                            self.args["stack_list"] if self.args["stack_list"] else self.source_service.deploy.stack_ids
                        )

                except Exception as e:
                    self.preflight_check_result.status = "FAIL"
                    preflight_result.append(
                        SkyBaseValidationError("source stack verification: {0}".format(simple_error_format(e)))
                    )

        # attempt to read state db record
        try:
            serialized_record = skybase.actions.state.read(
                mode=self.mode,
                record_id=self.id,
                credentials=sky_cfg.SkyConfig.init_from_file("credentials").data,
                format="yaml",
            )

            # DECISION: need general method for processing API in-flight errors
            if serialized_record.startswith("StateDBRecordNotFoundError"):
                raise StateDBRecordNotFoundError(self.id)

        except Exception as e:
            self.preflight_check_result.status = "FAIL"
            preflight_result.append(SkyBaseValidationError(simple_error_format(e)))
        else:
            try:
                self.target_service = yaml.load(serialized_record)
                self.runtime.tag = self.target_service.tag
            except Exception as e:
                self.preflight_check_result.status = "FAIL"
                preflight_result.append(
                    SkyBaseValidationError("service registry init: {0}".format(simple_error_format(e)))
                )
            else:
                try:
                    bad_stacks = []
                    for stack in self.source_service.deploy.stack_launch_list:
                        if stack not in self.target_service.stacks.deployed_stacks:
                            bad_stacks.append(stack)

                    if bad_stacks:
                        self.preflight_check_result.status = "FAIL"
                        preflight_result.append(
                            SkyBaseValidationError(
                                "target service {0}: stacks not deployed {1}".format(
                                    self.target_service.service, bad_stacks
                                )
                            )
                        )

                except Exception as e:
                    self.preflight_check_result.status = "FAIL"
                    preflight_result.append(
                        SkyBaseValidationError("target stack verification: {0}".format(simple_error_format(e)))
                    )

            # instantiate planet based on service registry value
            try:
                self.target_planet = Planet(self.target_service.planet)
            except Exception as e:
                self.preflight_check_result.status = "FAIL"
                preflight_result.append(
                    SkyBaseValidationError("target planet init: {0}".format(simple_error_format(e)))
                )
            else:
                if self.planet.planet_name != self.target_planet.planet_name:
                    self.preflight_check_result.status = "FAIL"
                    preflight_result.append(
                        "source planet {0} not equal target planet {1}".format(
                            self.planet.planet_name, self.target_planet.planet_name
                        )
                    )

            # test if existing service can be updated
            if self.source_service and self.target_service:
                # TODO: test that target and source service names match!
                is_version_ok = self.source_service.manifest.get("app_version") >= self.target_service.metadata.version
                if not is_version_ok:
                    self.preflight_check_result.status = "FAIL"
                    preflight_result.append(
                        SkyBaseValidationError(
                            "source < target service version: {0} < {1}".format(
                                self.source_service.manifest.get("app_version"), self.target_service.metadata.version
                            )
                        )
                    )
            else:
                self.preflight_check_result.status = "FAIL"
                preflight_result.append(
                    SkyBaseValidationError(
                        "cannot update service: missing (target / source): ({0} / {1})".format(
                            self.target_service == None, self.source_service == None
                        )
                    )
                )

        try:
            # acquire salt API authtoken
            self.authtoken = skybase.actions.salt.get_saltapi_authtoken(
                runner_cfg=self.runner_cfg, planet_name=self.target_service.planet
            )
            if self.authtoken is None:
                self.preflight_check_result.status = "FAIL"
                preflight_result.append(SkyBaseValidationError("failed to login to salt API"))
        except Exception as e:
            self.preflight_check_result.status = "FAIL"
            preflight_result.append(
                SkyBaseValidationError("failed to acquire salt API authtoken: {0}".format(simple_error_format(e)))
            )

        else:

            for stack in self.source_service.deploy.stack_launch_list:
                stack_roles = self.target_service.blueprint.get_stack_roles(stack)

                for role in stack_roles:
                    stack_role_grain = self.target_service.stacks.stacks[stack].get_stack_role_salt_grain_skybase_id(
                        role
                    )

                    try:
                        saltapi_result = skybase.actions.salt.test_ping_by_grain(
                            grain=stack_role_grain, authtoken=self.authtoken, planet_name=self.target_service.planet
                        )

                    except Exception as e:
                        self.preflight_check_result.status = "FAIL"
                        preflight_result.append(
                            SkyBaseValidationError("saltapi test.ping: {0}".format(simple_error_format(e)))
                        )

                    else:
                        # verify that some minions were targeted
                        if saltapi_result[0] != SkySaltAPI.NO_MINIONS:
                            # verify all minions reply returned True to ping
                            if not all(saltapi_result[0].values()):
                                self.preflight_check_result.status = "FAIL"
                                preflight_result.append(
                                    SkyBaseValidationError(
                                        "unreachable salt minions for stack-role {0}-{1} using grain {2}: {3}".format(
                                            stack, role, stack_role_grain, saltapi_result
                                        )
                                    )
                                )
                        else:
                            self.preflight_check_result.status = "FAIL"
                            preflight_result.append(
                                SkyBaseValidationError(
                                    "{0} using grain: {1}".format(SkySaltAPI.NO_MINIONS, stack_role_grain)
                                )
                            )

        self.preflight_check_result.set_output(preflight_result)
        return self.preflight_check_result
Example #44
0
    def preflight_check(self):
        # initialize results container
        preflight_result = []

        # instantiate planet
        try:
            self.planet = Planet(self.args.get('destination_planet'))
        except Exception as e:
            self.preflight_check_result.status = 'FAIL'
            preflight_result.append(skybase.exceptions.SkyBaseValidationError('planet init: {0}'.format(simple_error_format(e))))

        # TODO: should artiball transfer  *always* occur? OR attempt comparison timestamp / fingerprint to limit?
        # attempt transfer artiball to worker
        try:
            if not os.path.exists(os.path.join(self.runner_cfg.data['artiball_data_dir'], self.args.get('source_artiball'))):
                skybase.actions.skyenv.artiball_transfer(
                    artiball_key=self.args.get('source_artiball'),
                    bucket_name=self.runner_cfg.data['buckets']['cache']['name'],
                    profile=self.runner_cfg.data['buckets']['cache']['profile'],
                    release_dir=self.runner_cfg.data['artiball_data_dir']
                )
        except Exception as e:
            self.preflight_check_result.status = 'FAIL'
            preflight_result.append(skybase.exceptions.SkyBaseValidationError('artiball transfer: {0}'.format(simple_error_format(e))))

        # initialize SkyService using --artiball value
        try:
            self.service = SkyService().init_from_artiball(
                artiball_name=self.args.get('source_artiball'),
                artiball_data_dir=self.runner_cfg.data['artiball_data_dir']
            )
            # check planet trusted chef cookbook source against artiball's metadata when running chef-server mode
            if self.service.deploy.definition.get('chef_type', 'server') == 'server':
                cookbook_source = self.service.manifest['chef_cookbook_source']
                trusted_cookbook_source = self.planet._yaml_data['services']['chefserver']['trusted_chef_cookbook_source']
                if cookbook_source not in trusted_cookbook_source:
                    self.preflight_check_result.status = 'FAIL'
                    preflight_result.append('untrusted chef cookbook source in artiball: ' + cookbook_source)
        except Exception as e:
            self.preflight_check_result.status = 'FAIL'
            preflight_result.append(skybase.exceptions.SkyBaseValidationError('sky service init: {0}'.format(simple_error_format(e))))


        # test CLI stack option values against SkyService stacks
        try:
            bad_stacks = []
            for stack in self.args['stack_list']:
                if stack not in self.service.deploy.stack_ids:
                    bad_stacks.append(stack)

            if bad_stacks:
                self.preflight_check_result.status = 'FAIL'
                preflight_result.append(skybase.exceptions.SkyBaseValidationError('service {0}: unknown stacks {1}'.format(self.service.name, bad_stacks)))
            else:
                # given all good stacks, prepare stack launch list target
                self.service.deploy.stack_launch_list = self.args['stack_list'] if self.args['stack_list'] else self.service.deploy.stack_ids

        except Exception as e:
            self.preflight_check_result.status = 'FAIL'
            preflight_result.append(skybase.exceptions.SkyBaseValidationError('stack verification: {0}'.format(simple_error_format(e))))

        # prepare runtime
        try:
            # push client runtime options into runtime object
            runtime_unpacked = dict(attr.split('=') for attr in self.args.get('runtime'))
            self.runtime.set_attrs(**runtime_unpacked)

        except Exception as e:
            self.preflight_check_result.status = 'FAIL'
            preflight_result.append(skybase.exceptions.SkyBaseValidationError('runtime: {0}'.format(simple_error_format(e))))

        self.preflight_check_result.set_output(preflight_result)
        return self.preflight_check_result
Example #45
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))))

        # TODO: test if state record id exists

        return self.preflight_check_result
Example #46
0
    def execute(self):

        try:
            sky_chef_actions.delete_node(self.planet, self.args.get('node'), self.logger)
        except Exception as e:
            self.result.status = sky_cfg.API_STATUS_FAIL
            raise skybase.exceptions.SkyBaseResponseError('Could not delete node "{0}" from Chef: {1}'.format(self.args.get('node'), simple_error_format(e)))

        try:
            sky_chef_actions.delete_client(self.planet, self.args.get('node'), self.logger)
        except Exception as e:
            self.result.status = sky_cfg.API_STATUS_FAIL
            raise skybase.exceptions.SkyBaseResponseError('Could not delete node client "{0}" from Chef: {1}'.format(self.args.get('node'), simple_error_format(e)))

        self.result.status = sky_cfg.API_STATUS_SUCCESS
        self.result.output = 'Node "{0}" has been deleted from Chef'.format(self.args.get('node'))

        return self.result
Example #47
0
    def run(self):
        '''
        For the record:

        set mode:
        a) restapi = submit, get JobID, forget                      = task is sent away
        b) local.sync = do something local in sync mode             = task has actions executed local
        c) local.async.wait = submit, get jobID, go into WAIT loop  = task submitted, but reply has to be reported back to cli
        d) local.async.nowait = submit, get jobID, forget           = task executed locally, but no wait for systems outside SB
        '''

        # Do a quick & dirty presubmit check. This is meant for allowing a
        # simple 'yes/no' or 'are you sure' type verification check
        try:
            precheck_runner = sky_runner.Runner(self.current_task_name,
                                                vars(self.args))
            precheck_runner.task.presubmit_check()
        except SkyBasePresubmitCheckError as e:
            raise e
        except Exception:
            pass

        if self.args.exec_mode == 'local':
            # call runner for current skytask with arguments
            runner = sky_runner.Runner(self.current_task_name, vars(self.args))

            # init results containers
            result_main = None
            result_next = None

            try:
                result_main = runner.execute()
            except Exception as e:
                raise SkyBaseResponseError(
                    '{0} when accessing execution results'.format(
                        simple_error_format(e)))

            has_next_task = len(result_main.next_task_name) > 0

            if has_next_task:
                runner = sky_runner.Runner(result_main.next_task_name,
                                           result_main.next_args)
                try:
                    result_next = runner.execute()
                except Exception as e:
                    raise SkyBaseResponseError(
                        '{0} when accessing execution results'.format(
                            simple_error_format(e)))

            if result_main.format == skybase.skytask.output_format_json:
                if has_next_task:
                    # prepare multiple result for output as single JSON blob
                    summary_result = []
                    summary_result.append(
                        {self.current_task_name: result_main.output})
                    summary_result.append(
                        {result_main.next_task_name: result_next.output})
                    print skybase.utils.json_pretty_print(summary_result)
                else:
                    # print main results separately
                    result_main.print_result()
            else:
                # print results separately
                result_main.print_result()
                if has_next_task:
                    result_next.print_result()

        elif self.args.exec_mode == 'restapi':
            response = self.submit()

            if self.args.nowait:
                print response
            else:
                # deserialize request response
                response_as_json = json.loads(response)

                # check restapi status; if success, attempt to extract results
                if response_as_json.get(
                        'status') == sky_cfg.API_STATUS_SUCCESS:
                    result = self.get_restapi_execute_result(response_as_json)
                    taskresult = skybase.skytask.TaskResult.init_from_json(
                        result)
                else:
                    # ... if not success, report message containing error
                    taskresult = skybase.skytask.TaskResult(
                        an_output=response_as_json.get('message'),
                        a_format=skybase.skytask.output_format_json,
                    )
                taskresult.print_result()
Example #48
0
    def preflight_check(self):
        # initialize results container
        preflight_result = []

        # instantiate planet
        try:
            self.planet = Planet(self.args.get('destination_planet'))
        except Exception as e:
            self.preflight_check_result.status = 'FAIL'
            preflight_result.append(
                skybase.exceptions.SkyBaseValidationError(
                    'planet init: {0}'.format(simple_error_format(e))))

        # TODO: should artiball transfer  *always* occur? OR attempt comparison timestamp / fingerprint to limit?
        # attempt transfer artiball to worker
        try:
            if not os.path.exists(
                    os.path.join(self.runner_cfg.data['artiball_data_dir'],
                                 self.args.get('source_artiball'))):
                skybase.actions.skyenv.artiball_transfer(
                    artiball_key=self.args.get('source_artiball'),
                    bucket_name=self.runner_cfg.data['buckets']['cache']
                    ['name'],
                    profile=self.runner_cfg.data['buckets']['cache']
                    ['profile'],
                    release_dir=self.runner_cfg.data['artiball_data_dir'])
        except Exception as e:
            self.preflight_check_result.status = 'FAIL'
            preflight_result.append(
                skybase.exceptions.SkyBaseValidationError(
                    'artiball transfer: {0}'.format(simple_error_format(e))))

        # initialize SkyService using --artiball value
        try:
            self.service = SkyService().init_from_artiball(
                artiball_name=self.args.get('source_artiball'),
                artiball_data_dir=self.runner_cfg.data['artiball_data_dir'])
            # check planet trusted chef cookbook source against artiball's metadata when running chef-server mode
            if self.service.deploy.definition.get('chef_type',
                                                  'server') == 'server':
                cookbook_source = self.service.manifest['chef_cookbook_source']
                trusted_cookbook_source = self.planet._yaml_data['services'][
                    'chefserver']['trusted_chef_cookbook_source']
                if cookbook_source not in trusted_cookbook_source:
                    self.preflight_check_result.status = 'FAIL'
                    preflight_result.append(
                        'untrusted chef cookbook source in artiball: ' +
                        cookbook_source)
        except Exception as e:
            self.preflight_check_result.status = 'FAIL'
            preflight_result.append(
                skybase.exceptions.SkyBaseValidationError(
                    'sky service init: {0}'.format(simple_error_format(e))))

        # test CLI stack option values against SkyService stacks
        try:
            bad_stacks = []
            for stack in self.args['stack_list']:
                if stack not in self.service.deploy.stack_ids:
                    bad_stacks.append(stack)

            if bad_stacks:
                self.preflight_check_result.status = 'FAIL'
                preflight_result.append(
                    skybase.exceptions.SkyBaseValidationError(
                        'service {0}: unknown stacks {1}'.format(
                            self.service.name, bad_stacks)))
            else:
                # given all good stacks, prepare stack launch list target
                self.service.deploy.stack_launch_list = self.args[
                    'stack_list'] if self.args[
                        'stack_list'] else self.service.deploy.stack_ids

        except Exception as e:
            self.preflight_check_result.status = 'FAIL'
            preflight_result.append(
                skybase.exceptions.SkyBaseValidationError(
                    'stack verification: {0}'.format(simple_error_format(e))))

        # prepare runtime
        try:
            # push client runtime options into runtime object
            runtime_unpacked = dict(
                attr.split('=') for attr in self.args.get('runtime'))
            self.runtime.set_attrs(**runtime_unpacked)

        except Exception as e:
            self.preflight_check_result.status = 'FAIL'
            preflight_result.append(
                skybase.exceptions.SkyBaseValidationError(
                    'runtime: {0}'.format(simple_error_format(e))))

        self.preflight_check_result.set_output(preflight_result)
        return self.preflight_check_result
Example #49
0
    def run(self):
        '''
        For the record:

        set mode:
        a) restapi = submit, get JobID, forget                      = task is sent away
        b) local.sync = do something local in sync mode             = task has actions executed local
        c) local.async.wait = submit, get jobID, go into WAIT loop  = task submitted, but reply has to be reported back to cli
        d) local.async.nowait = submit, get jobID, forget           = task executed locally, but no wait for systems outside SB
        '''

        # Do a quick & dirty presubmit check. This is meant for allowing a
        # simple 'yes/no' or 'are you sure' type verification check
        try:
            precheck_runner = sky_runner.Runner(self.current_task_name, vars(self.args))
            precheck_runner.task.presubmit_check()
        except SkyBasePresubmitCheckError as e:
            raise e
        except Exception:
            pass

        if self.args.exec_mode == 'local':
            # call runner for current skytask with arguments
            runner = sky_runner.Runner(self.current_task_name, vars(self.args))

            # init results containers
            result_main = None
            result_next = None

            try:
                result_main = runner.execute()
            except Exception as e:
                raise SkyBaseResponseError('{0} when accessing execution results'.format(simple_error_format(e)))

            has_next_task = len(result_main.next_task_name) > 0

            if has_next_task:
                runner = sky_runner.Runner(result_main.next_task_name, result_main.next_args)
                try:
                    result_next = runner.execute()
                except Exception as e:
                    raise SkyBaseResponseError('{0} when accessing execution results'.format(simple_error_format(e)))

            if result_main.format == skybase.skytask.output_format_json:
                if has_next_task:
                    # prepare multiple result for output as single JSON blob
                    summary_result = []
                    summary_result.append({self.current_task_name: result_main.output})
                    summary_result.append({result_main.next_task_name: result_next.output})
                    print skybase.utils.json_pretty_print(summary_result)
                else:
                    # print main results separately
                    result_main.print_result()
            else:
                # print results separately
                result_main.print_result()
                if has_next_task:
                    result_next.print_result()

        elif self.args.exec_mode == 'restapi':
            response = self.submit()

            if self.args.nowait:
                print response
            else:
                # deserialize request response
                response_as_json = json.loads(response)

                # check restapi status; if success, attempt to extract results
                if response_as_json.get('status') == sky_cfg.API_STATUS_SUCCESS:
                    result = self.get_restapi_execute_result(response_as_json)
                    taskresult = skybase.skytask.TaskResult.init_from_json(result)
                else:
                    # ... if not success, report message containing error
                    taskresult = skybase.skytask.TaskResult(
                        an_output=response_as_json.get('message'),
                        a_format=skybase.skytask.output_format_json,
                    )
                taskresult.print_result()
Example #50
0
    def preflight_check(self):
        # initialize results container
        preflight_result = []

        # instantiate planet
        try:
            self.planet = Planet(self.args.get('planet'))
        except Exception as e:
            self.preflight_check_result.status = 'FAIL'
            preflight_result.append(skybase.exceptions.SkyBaseValidationError('planet init: {0}'.format(simple_error_format(e))))

        try:
            self.node = sky_chef_actions.get_node(self.planet, self.args.get('node'), self.logger)
        except Exception as e:
            self.preflight_check_result.status = 'FAIL'
            preflight_result.append(skybase.exceptions.SkyBaseValidationError('could not find node "{0}": {1}'.format(self.args.get('node'), simple_error_format(e))))

        self.preflight_check_result.set_output(preflight_result)
        return self.preflight_check_result
Example #51
0
    def pollwait(self,
                 url,
                 timeout=None,
                 retry_interval=RETRY):

        if timeout is None:
            timeout = min(self.cli_cfg.data.get('result_fetch_timeout', SkyCmd.TIMEOUT_DEFAULT), SkyCmd.TIMEOUT_MAX)

        # wait for celery task status SUCCESS over timeout interval
        start_time = time.time()

        while time.time() - start_time < timeout:
            execute_result = self.probe(url)

            try:
                status = execute_result['metadata']['task_status']
            except KeyError as e:
                raise SkyBaseResponseError('{0} when accessing response status'.format(simple_error_format(e)))

            if status == 'PENDING':
                # TODO: progress bar would be nice, but needs to not interfere with json prettyprint
                time.sleep(retry_interval)

            elif status == 'SUCCESS':
                # return execute task results data if exists
                try:
                    return execute_result
                except KeyError as e:
                    raise SkyBaseResponseError('{0} when accessing response results'.format(simple_error_format(e)))
            else:
                raise SkyBaseError('unknown task status: {0}'.format(status))

        raise SkyBaseTimeOutError('attempt to fetch results failed after {0}s'.format(timeout))
Example #52
0
    def preflight_check(self):
        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 stacks for errors before writing to service state registry
        try:
            are_stacks_valid = skybase.actions.skycloud.are_stacks_valid(
                self.planet.orchestration_engine,
                self.stacks)

            if not are_stacks_valid:
                self.preflight_check_result.status = 'FAIL'
                preflight_result.append(skybase.exceptions.SkyBaseValidationError('cannot write service state record with invalid stacks'))

        except Exception as e:
            self.preflight_check_result.status = 'FAIL'
            preflight_result.append(skybase.exceptions.SkyBaseValidationError('test for valid stacks: {0}'.format(simple_error_format(e))))

        self.preflight_check_result.set_output(preflight_result)
        return self.preflight_check_result
Example #53
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
Example #54
0
    def preflight_check(self):
        preflight_result = []

        # TODO: move reusable preflight functions/tests to skybase.skytask.service
        # instantiate planet from --planet option
        try:
            self.planet = Planet(self.planet_name)
        except Exception as e:
            self.preflight_check_result.status = 'FAIL'
            preflight_result.append(
                SkyBaseValidationError('source planet init: {0}'.format(
                    simple_error_format(e))))

        try:
            # attempt transfer artiball to worker
            if not os.path.exists(
                    os.path.join(self.runner_cfg.data['artiball_data_dir'],
                                 self.args.get('source_artiball'))):
                artiball_transfer(
                    artiball_key=self.args.get('source_artiball'),
                    bucket_name=self.runner_cfg.data['buckets']['cache']
                    ['name'],
                    profile=self.runner_cfg.data['buckets']['cache']
                    ['profile'],
                    release_dir=self.runner_cfg.data['artiball_data_dir'])
        except boto.exception.S3ResponseError as e:
            self.preflight_check_result.status = 'FAIL'
            preflight_result.append(
                SkyBaseValidationError('artiball transfer: {0}: {1}'.format(
                    type(e).__name__, str(e.message))))
        except Exception as e:
            self.preflight_check_result.status = 'FAIL'
            preflight_result.append(
                SkyBaseValidationError('artiball transfer: {0}'.format(
                    simple_error_format(e))))
        else:
            # initialize SkyService from source artiball
            try:
                self.source_service = SkyService().init_from_artiball(
                    artiball_name=self.source_artiball,
                    artiball_data_dir=self.runner_cfg.data['artiball_data_dir']
                )
                self.chef_type = self.source_service.deploy.definition.get(
                    'chef_type', 'server')
            except Exception as e:
                self.preflight_check_result.status = 'FAIL'
                preflight_result.append(
                    SkyBaseValidationError('sky service init: {0}'.format(
                        simple_error_format(e))))
            else:

                # test CLI stack option values against SkyService stacks
                try:
                    bad_stacks = []
                    for stack in self.args['stack_list']:
                        if stack not in self.source_service.deploy.stack_ids:
                            bad_stacks.append(stack)

                    if bad_stacks:
                        self.preflight_check_result.status = 'FAIL'
                        preflight_result.append(
                            SkyBaseValidationError(
                                'source service {0}: unknown stacks {1}'.
                                format(self.source_service.name, bad_stacks)))
                    else:
                        # given all good stacks, prepare stack launch list target
                        self.source_service.deploy.stack_launch_list = self.args[
                            'stack_list'] if self.args[
                                'stack_list'] else self.source_service.deploy.stack_ids

                except Exception as e:
                    self.preflight_check_result.status = 'FAIL'
                    preflight_result.append(
                        SkyBaseValidationError(
                            'source stack verification: {0}'.format(
                                simple_error_format(e))))

        # attempt to read state db record
        try:
            serialized_record = skybase.actions.state.read(
                mode=self.mode,
                record_id=self.id,
                credentials=sky_cfg.SkyConfig.init_from_file(
                    'credentials').data,
                format='yaml')

            # DECISION: need general method for processing API in-flight errors
            if serialized_record.startswith('StateDBRecordNotFoundError'):
                raise StateDBRecordNotFoundError(self.id)

        except Exception as e:
            self.preflight_check_result.status = 'FAIL'
            preflight_result.append(
                SkyBaseValidationError(simple_error_format(e)))
        else:
            try:
                self.target_service = yaml.load(serialized_record)
                self.runtime.tag = self.target_service.tag
            except Exception as e:
                self.preflight_check_result.status = 'FAIL'
                preflight_result.append(
                    SkyBaseValidationError('service registry init: {0}'.format(
                        simple_error_format(e))))
            else:
                try:
                    bad_stacks = []
                    for stack in self.source_service.deploy.stack_launch_list:
                        if stack not in self.target_service.stacks.deployed_stacks:
                            bad_stacks.append(stack)

                    if bad_stacks:
                        self.preflight_check_result.status = 'FAIL'
                        preflight_result.append(
                            SkyBaseValidationError(
                                'target service {0}: stacks not deployed {1}'.
                                format(self.target_service.service,
                                       bad_stacks)))

                except Exception as e:
                    self.preflight_check_result.status = 'FAIL'
                    preflight_result.append(
                        SkyBaseValidationError(
                            'target stack verification: {0}'.format(
                                simple_error_format(e))))

            # instantiate planet based on service registry value
            try:
                self.target_planet = Planet(self.target_service.planet)
            except Exception as e:
                self.preflight_check_result.status = 'FAIL'
                preflight_result.append(
                    SkyBaseValidationError('target planet init: {0}'.format(
                        simple_error_format(e))))
            else:
                if self.planet.planet_name != self.target_planet.planet_name:
                    self.preflight_check_result.status = 'FAIL'
                    preflight_result.append(
                        'source planet {0} not equal target planet {1}'.format(
                            self.planet.planet_name,
                            self.target_planet.planet_name))

            # test if existing service can be updated
            if self.source_service and self.target_service:
                # TODO: test that target and source service names match!
                is_version_ok = (
                    self.source_service.manifest.get('app_version') >=
                    self.target_service.metadata.version)
                if not is_version_ok:
                    self.preflight_check_result.status = 'FAIL'
                    preflight_result.append(
                        SkyBaseValidationError(
                            'source < target service version: {0} < {1}'.
                            format(
                                self.source_service.manifest.get(
                                    'app_version'),
                                self.target_service.metadata.version)))
            else:
                self.preflight_check_result.status = 'FAIL'
                preflight_result.append(
                    SkyBaseValidationError(
                        'cannot update service: missing (target / source): ({0} / {1})'
                        .format(self.target_service == None,
                                self.source_service == None)))

        try:
            # acquire salt API authtoken
            self.authtoken = skybase.actions.salt.get_saltapi_authtoken(
                runner_cfg=self.runner_cfg,
                planet_name=self.target_service.planet)
            if self.authtoken is None:
                self.preflight_check_result.status = 'FAIL'
                preflight_result.append(
                    SkyBaseValidationError('failed to login to salt API'))
        except Exception as e:
            self.preflight_check_result.status = 'FAIL'
            preflight_result.append(
                SkyBaseValidationError(
                    'failed to acquire salt API authtoken: {0}'.format(
                        simple_error_format(e))))

        else:

            for stack in self.source_service.deploy.stack_launch_list:
                stack_roles = self.target_service.blueprint.get_stack_roles(
                    stack)

                for role in stack_roles:
                    stack_role_grain = self.target_service.stacks.stacks[
                        stack].get_stack_role_salt_grain_skybase_id(role)

                    try:
                        saltapi_result = skybase.actions.salt.test_ping_by_grain(
                            grain=stack_role_grain,
                            authtoken=self.authtoken,
                            planet_name=self.target_service.planet,
                        )

                    except Exception as e:
                        self.preflight_check_result.status = 'FAIL'
                        preflight_result.append(
                            SkyBaseValidationError(
                                'saltapi test.ping: {0}'.format(
                                    simple_error_format(e))))

                    else:
                        # verify that some minions were targeted
                        if saltapi_result[0] != SkySaltAPI.NO_MINIONS:
                            # verify all minions reply returned True to ping
                            if not all(saltapi_result[0].values()):
                                self.preflight_check_result.status = 'FAIL'
                                preflight_result.append(
                                    SkyBaseValidationError(
                                        'unreachable salt minions for stack-role {0}-{1} using grain {2}: {3}'
                                        .format(stack, role, stack_role_grain,
                                                saltapi_result)))
                        else:
                            self.preflight_check_result.status = 'FAIL'
                            preflight_result.append(
                                SkyBaseValidationError(
                                    '{0} using grain: {1}'.format(
                                        SkySaltAPI.NO_MINIONS,
                                        stack_role_grain)))

        self.preflight_check_result.set_output(preflight_result)
        return self.preflight_check_result