Exemple #1
0
    def abort(cls, task_uuid, soft=False, is_async=True):
        """Abort running task.

        :param task_uuid: The UUID of the task
        :type task_uuid: str
        :param soft: If set to True, task should be aborted after execution of
                     current scenario, otherwise as soon as possible before
                     all the scenario iterations finish [Default: False]
        :type soft: bool
        :param is_async: don't wait until task became in 'running' state
                      [Default: False]
        :type is_async: bool
        """

        if not is_async:
            current_status = objects.Task.get_status(task_uuid)
            if current_status in objects.Task.NOT_IMPLEMENTED_STAGES_FOR_ABORT:
                LOG.info(
                    _LI("Task status is '%s'. Should wait until it became"
                        " 'running'") % current_status)
                while (current_status
                       in objects.Task.NOT_IMPLEMENTED_STAGES_FOR_ABORT):
                    time.sleep(1)
                    current_status = objects.Task.get_status(task_uuid)

        objects.Task.get(task_uuid).abort(soft=soft)

        if not is_async:
            LOG.info(_LI("Waiting until the task stops."))
            finished_stages = [
                consts.TaskStatus.ABORTED, consts.TaskStatus.FINISHED,
                consts.TaskStatus.FAILED
            ]
            while objects.Task.get_status(task_uuid) not in finished_stages:
                time.sleep(1)
Exemple #2
0
    def configure(self, extra_options=None):
        """Configure a verifier.

        :param extra_options: a dictionary with external verifier specific
            options for configuration.
        :raises NotImplementedError: This feature is verifier-specific, so you
            should override this method in your plugin if it supports
            configuration
        """
        raise NotImplementedError(
            _LI("'%s' verifiers don't support configuration at all.") %
            self.get_name())
Exemple #3
0
    def report(self, uuids, output_type, output_dest=None):
        """Generate a report for a verification or a few verifications.

        :param uuids: List of verifications UUIDs
        :param output_type: Plugin name of verification reporter
        :param output_dest: Destination for verification report
        """
        verifications = [self._get(uuid) for uuid in uuids]

        reporter_cls = vreporter.VerificationReporter.get(output_type)
        reporter_cls.validate(output_dest)

        LOG.info("Building '%s' report for the following verification(s): "
                 "'%s'.", output_type, "', '".join(uuids))
        result = vreporter.VerificationReporter.make(reporter_cls,
                                                     verifications,
                                                     output_dest)
        LOG.info(_LI("The report has been successfully built."))
        return result
Exemple #4
0
class Task(object):
    @classmethod
    def render_template(cls, task_template, template_dir="./", **kwargs):
        """Render jinja2 task template to Rally input task.

        :param task_template: String that contains template
        :param template_dir: The path of directory contain template files
        :param kwargs: Dict with template arguments
        :returns: rendered template str
        """
        def is_really_missing(mis, task_template):
            # NOTE(boris-42): Removing variables that have default values from
            #                 missing. Construction that won't be properly
            #                 checked is {% set x = x or 1}
            if re.search(mis.join(["{%\s*set\s+", "\s*=\s*", "[^\w]+"]),
                         task_template):
                return False
            # NOTE(jlk): Also check for a default filter which can show up as
            #            a missing variable
            if re.search(mis + "\s*\|\s*default\(", task_template):
                return False
            return True

        # NOTE(boris-42): We have to import builtins to get the full list of
        #                 builtin functions (e.g. range()). Unfortunately,
        #                 __builtins__ doesn't return them (when it is not
        #                 main module)
        from six.moves import builtins

        env = jinja2.Environment(
            loader=jinja2.FileSystemLoader(template_dir, encoding="utf8"))
        ast = env.parse(task_template)
        required_kwargs = jinja2.meta.find_undeclared_variables(ast)

        missing = set(required_kwargs) - set(kwargs) - set(dir(builtins))
        real_missing = [
            mis for mis in missing if is_really_missing(mis, task_template)
        ]

        if real_missing:
            multi_msg = _("Please specify next template task arguments: %s")
            single_msg = _("Please specify template task argument: %s")

            raise TypeError(
                (len(real_missing) > 1 and multi_msg or single_msg) %
                ", ".join(real_missing))

        return env.from_string(task_template).render(**kwargs)

    @classmethod
    def create(cls, deployment, tag):
        """Create a task without starting it.

        Task is a list of benchmarks that will be called one by one, results of
        execution will be stored in DB.

        :param deployment: UUID or name of the deployment
        :param tag: tag for this task
        :returns: Task object
        """

        deployment_uuid = objects.Deployment.get(deployment)["uuid"]
        return objects.Task(deployment_uuid=deployment_uuid, tag=tag)

    @classmethod
    def validate(cls, deployment, config, task_instance=None):
        """Validate a task config against specified deployment.

        :param deployment: UUID or name of the deployment
        :param config: a dict with a task configuration
        """
        deployment = objects.Deployment.get(deployment)
        task = task_instance or objects.Task(
            deployment_uuid=deployment["uuid"], temporary=True)
        benchmark_engine = engine.BenchmarkEngine(config,
                                                  task,
                                                  admin=deployment["admin"],
                                                  users=deployment["users"])

        benchmark_engine.validate()

    @classmethod
    def start(cls, deployment, config, task=None, abort_on_sla_failure=False):
        """Start a task.

        Task is a list of benchmarks that will be called one by one, results of
        execution will be stored in DB.

        :param deployment: UUID or name of the deployment
        :param config: a dict with a task configuration
        :param task: Task object. If None, it will be created
        :param abort_on_sla_failure: if True, the execution of a benchmark
                                     scenario will stop when any SLA check
                                     for it fails
        """
        deployment = objects.Deployment.get(deployment)
        task = task or objects.Task(deployment_uuid=deployment["uuid"])

        if task.is_temporary:
            raise ValueError(
                _("Unable to run a temporary task. Please check your code."))

        LOG.info("Benchmark Task %s on Deployment %s" %
                 (task["uuid"], deployment["uuid"]))
        benchmark_engine = engine.BenchmarkEngine(
            config,
            task,
            admin=deployment["admin"],
            users=deployment["users"],
            abort_on_sla_failure=abort_on_sla_failure)

        try:
            benchmark_engine.run()
        except Exception:
            deployment.update_status(consts.DeployStatus.DEPLOY_INCONSISTENT)
            raise

    @classmethod
    def abort(cls, task_uuid, soft=False, async=True):
        """Abort running task.

        :param task_uuid: The UUID of the task
        :type task_uuid: str
        :param soft: if set to True, task should be aborted after execution of
                     current scenario, otherwise as soon as possible before
                     all the scenario iterations finish [Default: False]
        :type soft: bool
        :param async: don't wait until task became in 'running' state
                      [Default: False]
        :type async: bool
        """

        if not async:
            current_status = objects.Task.get_status(task_uuid)
            if current_status in objects.Task.NOT_IMPLEMENTED_STAGES_FOR_ABORT:
                LOG.info(
                    _LI("Task status is '%s'. Should wait until it became"
                        " 'running'") % current_status)
                while (current_status
                       in objects.Task.NOT_IMPLEMENTED_STAGES_FOR_ABORT):
                    time.sleep(1)
                    current_status = objects.Task.get_status(task_uuid)

        objects.Task.get(task_uuid).abort(soft=soft)

        if not async:
            LOG.info(_LI("Waiting until the task stops."))
            finished_stages = [
                consts.TaskStatus.ABORTED, consts.TaskStatus.FINISHED,
                consts.TaskStatus.FAILED
            ]
            while objects.Task.get_status(task_uuid) not in finished_stages:
                time.sleep(1)
Exemple #5
0
class _Task(object):

    TASK_RESULT_SCHEMA = objects.task.TASK_RESULT_SCHEMA

    @staticmethod
    def list(**filters):
        return objects.Task.list(**filters)

    @staticmethod
    def get(task_id):
        return objects.Task.get(task_id)

    @staticmethod
    def get_detailed(task_id, extended_results=False):
        """Get detailed task data.

        :param task_id: str task UUID
        :param extended_results: whether to return task data as dict
                                 with extended results
        :returns: rally.common.db.sqlalchemy.models.Task
        :returns: dict
        """
        task = objects.Task.get_detailed(task_id)
        if task and extended_results:
            task = dict(task)
            task["results"] = objects.Task.extend_results(task["results"])
        return task

    @classmethod
    def render_template(cls, task_template, template_dir="./", **kwargs):
        """Render jinja2 task template to Rally input task.

        :param task_template: String that contains template
        :param template_dir: The path of directory contain template files
        :param kwargs: Dict with template arguments
        :returns: rendered template str
        """
        def is_really_missing(mis, task_template):
            # NOTE(boris-42): Removing variables that have default values from
            #                 missing. Construction that won't be properly
            #                 checked is {% set x = x or 1}
            if re.search(mis.join(["{%\s*set\s+", "\s*=\s*", "[^\w]+"]),
                         task_template):
                return False
            # NOTE(jlk): Also check for a default filter which can show up as
            #            a missing variable
            if re.search(mis + "\s*\|\s*default\(", task_template):
                return False
            return True

        # NOTE(boris-42): We have to import builtins to get the full list of
        #                 builtin functions (e.g. range()). Unfortunately,
        #                 __builtins__ doesn't return them (when it is not
        #                 main module)
        from six.moves import builtins

        env = jinja2.Environment(
            loader=jinja2.FileSystemLoader(template_dir, encoding="utf8"))
        env.globals.update(cls.create_template_functions())
        ast = env.parse(task_template)
        # NOTE(Julia Varigina):
        # Bug in jinja2.meta.find_undeclared_variables
        #
        # The method shows inconsistent behavior:
        # it does not return undeclared variables that appear
        # in included templates only (via {%- include "some_template.yaml"-%})
        # and in the same time is declared in jinja2.Environment.globals.
        #
        # This is different for undeclared variables that appear directly
        # in task_template. The method jinja2.meta.find_undeclared_variables
        # returns an undeclared variable that is used in task_template
        # and is set in jinja2.Environment.globals.
        #
        # Despite this bug, jinja resolves values
        # declared in jinja2.Environment.globals for both types of undeclared
        # variables and successfully renders templates in both cases.
        required_kwargs = jinja2.meta.find_undeclared_variables(ast)
        missing = (set(required_kwargs) - set(kwargs) - set(dir(builtins)) -
                   set(env.globals))
        real_missing = [
            mis for mis in missing if is_really_missing(mis, task_template)
        ]
        if real_missing:
            multi_msg = _("Please specify next template task arguments: %s")
            single_msg = _("Please specify template task argument: %s")

            raise TypeError(
                (len(real_missing) > 1 and multi_msg or single_msg) %
                ", ".join(real_missing))

        return env.from_string(task_template).render(**kwargs)

    @classmethod
    def create_template_functions(cls):
        def template_min(int1, int2):
            return min(int1, int2)

        def template_max(int1, int2):
            return max(int1, int2)

        def template_round(float1):
            return int(round(float1))

        def template_ceil(float1):
            import math
            return int(math.ceil(float1))

        return {
            "min": template_min,
            "max": template_max,
            "ceil": template_ceil,
            "round": template_round
        }

    @classmethod
    def create(cls, deployment, tag):
        """Create a task without starting it.

        Task is a list of benchmarks that will be called one by one, results of
        execution will be stored in DB.

        :param deployment: UUID or name of the deployment
        :param tag: tag for this task
        :returns: Task object
        """

        deployment = objects.Deployment.get(deployment)
        if deployment["status"] != consts.DeployStatus.DEPLOY_FINISHED:
            raise exceptions.DeploymentNotFinishedStatus(
                name=deployment["name"],
                uuid=deployment["uuid"],
                status=deployment["status"])

        return objects.Task(deployment_uuid=deployment["uuid"], tag=tag)

    @classmethod
    def validate(cls, deployment, config, task_instance=None):
        """Validate a task config against specified deployment.

        :param deployment: UUID or name of the deployment
        :param config: a dict with a task configuration
        """
        deployment = objects.Deployment.get(deployment)
        task = task_instance or objects.Task(
            deployment_uuid=deployment["uuid"], temporary=True)
        benchmark_engine = engine.TaskEngine(config, task, deployment)

        benchmark_engine.validate()

    @classmethod
    def start(cls, deployment, config, task=None, abort_on_sla_failure=False):
        """Start a task.

        Task is a list of benchmarks that will be called one by one, results of
        execution will be stored in DB.

        :param deployment: UUID or name of the deployment
        :param config: a dict with a task configuration
        :param task: Task object. If None, it will be created
        :param abort_on_sla_failure: If set to True, the task execution will
                                     stop when any SLA check for it fails
        """
        deployment = objects.Deployment.get(deployment)

        task = task or objects.Task(deployment_uuid=deployment["uuid"])

        if task.is_temporary:
            raise ValueError(
                _("Unable to run a temporary task. Please check your code."))

        LOG.info("Benchmark Task %s on Deployment %s" %
                 (task["uuid"], deployment["uuid"]))

        benchmark_engine = engine.TaskEngine(
            config,
            task,
            deployment,
            abort_on_sla_failure=abort_on_sla_failure)

        try:
            benchmark_engine.run()
        except Exception:
            deployment.update_status(consts.DeployStatus.DEPLOY_INCONSISTENT)
            raise

    @classmethod
    def abort(cls, task_uuid, soft=False, async=True):
        """Abort running task.

        :param task_uuid: The UUID of the task
        :type task_uuid: str
        :param soft: If set to True, task should be aborted after execution of
                     current scenario, otherwise as soon as possible before
                     all the scenario iterations finish [Default: False]
        :type soft: bool
        :param async: don't wait until task became in 'running' state
                      [Default: False]
        :type async: bool
        """

        if not async:
            current_status = objects.Task.get_status(task_uuid)
            if current_status in objects.Task.NOT_IMPLEMENTED_STAGES_FOR_ABORT:
                LOG.info(
                    _LI("Task status is '%s'. Should wait until it became"
                        " 'running'") % current_status)
                while (current_status
                       in objects.Task.NOT_IMPLEMENTED_STAGES_FOR_ABORT):
                    time.sleep(1)
                    current_status = objects.Task.get_status(task_uuid)

        objects.Task.get(task_uuid).abort(soft=soft)

        if not async:
            LOG.info(_LI("Waiting until the task stops."))
            finished_stages = [
                consts.TaskStatus.ABORTED, consts.TaskStatus.FINISHED,
                consts.TaskStatus.CRASHED
            ]
            while objects.Task.get_status(task_uuid) not in finished_stages:
                time.sleep(1)