Exemplo n.º 1
0
    def initialize_jobs(self):
        new_queue = []
        failed_ids = []
        for job in self.job_queue:
            if job.id in failed_ids:
                # Don't try to initialize a job if another job with the same ID
                # (i.e. same job spec) has failed - we can assume it will fail
                # too.
                self.skip_job(job)
                continue

            try:
                job.initialize(self)
            except WorkloadError as e:
                self.set_job_status(job, Status.FAILED, write=False)
                log.log_error(e, self.logger)
                failed_ids.append(job.id)

                if self.cm.run_config.bail_on_init_failure:
                    raise
            else:
                new_queue.append(job)

        self.job_queue = new_queue
        self.write_state()
Exemplo n.º 2
0
    def run(self):
        try:
            self.initialize_run()
            self.send(signal.RUN_INITIALIZED)

            with signal.wrap('JOB_QUEUE_EXECUTION', self, self.context):
                while self.context.job_queue:
                    if self.context.run_interrupted:
                        raise KeyboardInterrupt()
                    self.run_next_job(self.context)

        except KeyboardInterrupt as e:
            log.log_error(e, self.logger)
            self.logger.info('Skipping remaining jobs.')
            self.context.skip_remaining_jobs()
        except Exception as e:
            message = e.args[0] if e.args else str(e)
            log.log_error(e, self.logger)
            self.logger.error(
                'Skipping remaining jobs due to "{}".'.format(message))
            self.context.skip_remaining_jobs()
            raise e
        finally:
            self.finalize_run()
            self.send(signal.RUN_FINALIZED)
 def do_for_each_proc(self, method_name, message, *args):
     with indentcontext():
         for proc in self.processors:
             if proc.is_enabled:
                 proc_func = getattr(proc, method_name, None)
                 if proc_func is None:
                     continue
                 try:
                     self.logger.info(message.format(proc.name))
                     proc_func(*args)
                 except Exception as e:  # pylint: disable=broad-except
                     if isinstance(e, KeyboardInterrupt):
                         raise
                     log_error(e, self.logger)
 def do_for_each_proc(self, method_name, message, *args):
     with indentcontext():
         for proc in self.processors:
             if proc.is_enabled:
                 proc_func = getattr(proc, method_name, None)
                 if proc_func is None:
                     continue
                 try:
                     self.logger.info(message.format(proc.name))
                     proc_func(*args)
                 except Exception as e:  # pylint: disable=broad-except
                     if isinstance(e, KeyboardInterrupt):
                         raise
                     log_error(e, self.logger)
Exemplo n.º 5
0
    def execute(self, config_manager, output):
        """
        Execute the run specified by an agenda. Optionally, selectors may be
        used to only execute a subset of the specified agenda.

        Params::

            :state: a ``ConfigManager`` containing processed configuration
            :output: an initialized ``RunOutput`` that will be used to
                     store the results.

        """
        signal.connect(self._error_signalled_callback, signal.ERROR_LOGGED)
        signal.connect(self._warning_signalled_callback, signal.WARNING_LOGGED)

        self.logger.info('Initializing run')
        self.logger.debug('Finalizing run configuration.')
        config = config_manager.finalize()
        output.write_config(config)

        self.target_manager = TargetManager(config.run_config.device,
                                            config.run_config.device_config,
                                            output.basepath)

        self.logger.info('Initializing execution context')
        context = ExecutionContext(config_manager, self.target_manager, output)

        try:
            self.do_execute(context)
        except KeyboardInterrupt as e:
            context.run_output.status = Status.ABORTED
            log.log_error(e, self.logger)
            context.write_output()
            raise
        except Exception as e:
            context.run_output.status = Status.FAILED
            log.log_error(e, self.logger)
            context.write_output()
            raise
        finally:
            context.finalize()
            self.execute_postamble(context, output)
            signal.send(signal.RUN_COMPLETED, self, context)
Exemplo n.º 6
0
    def execute(self, config_manager, output):
        """
        Execute the run specified by an agenda. Optionally, selectors may be
        used to only selecute a subset of the specified agenda.

        Params::

            :state: a ``ConfigManager`` containing processed configuration
            :output: an initialized ``RunOutput`` that will be used to
                     store the results.

        """
        signal.connect(self._error_signalled_callback, signal.ERROR_LOGGED)
        signal.connect(self._warning_signalled_callback, signal.WARNING_LOGGED)

        self.logger.info('Initializing run')
        self.logger.debug('Finalizing run configuration.')
        config = config_manager.finalize()
        output.write_config(config)

        self.target_manager = TargetManager(config.run_config.device,
                                            config.run_config.device_config,
                                            output.basepath)

        self.logger.info('Initializing execution context')
        context = ExecutionContext(config_manager, self.target_manager, output)

        try:
            self.do_execute(context)
        except KeyboardInterrupt as e:
            context.run_output.status = 'ABORTED'
            log.log_error(e, self.logger)
            context.write_output()
            raise
        except Exception as e:
            context.run_output.status = 'FAILED'
            log.log_error(e, self.logger)
            context.write_output()
            raise
        finally:
            context.finalize()
            self.execute_postamble(context, output)
            signal.send(signal.RUN_COMPLETED, self, context)
Exemplo n.º 7
0
    def run_next_job(self, context):
        job = context.start_job()
        self.logger.info('Running job {}'.format(job.id))

        try:
            log.indent()
            if self.context.reboot_policy.reboot_on_each_job:
                self.logger.info('Rebooting on new job.')
                self.context.tm.reboot(context)
            elif self.context.reboot_policy.reboot_on_each_spec and context.spec_changed:
                self.logger.info('Rebooting on new spec.')
                self.context.tm.reboot(context)

            with signal.wrap('JOB', self, context):
                context.tm.start()
                self.do_run_job(job, context)
                context.set_job_status(job, Status.OK)
        except (Exception, KeyboardInterrupt) as e:  # pylint: disable=broad-except
            log.log_error(e, self.logger)
            if isinstance(e, KeyboardInterrupt):
                context.run_interrupted = True
                context.set_job_status(job, Status.ABORTED)
                raise e
            else:
                context.set_job_status(job, Status.FAILED)
            if isinstance(e, TargetNotRespondingError):
                raise e
            elif isinstance(e, TargetError):
                context.tm.verify_target_responsive(context)
        finally:
            self.logger.info('Completing job {}'.format(job.id))
            self.send(signal.JOB_COMPLETED)
            context.tm.stop()
            context.end_job()

            log.dedent()
            self.check_job(job)
Exemplo n.º 8
0
    def run_next_job(self, context):
        job = context.start_job()
        self.logger.info('Running job {}'.format(job.id))

        try:
            log.indent()
            if self.context.reboot_policy.reboot_on_each_job:
                self.logger.info('Rebooting on new job.')
                self.context.tm.reboot(context)
            elif self.context.reboot_policy.reboot_on_each_spec and context.spec_changed:
                self.logger.info('Rebooting on new spec.')
                self.context.tm.reboot(context)

            with signal.wrap('JOB', self, context):
                context.tm.start()
                self.do_run_job(job, context)
                job.set_status(Status.OK)
        except (Exception, KeyboardInterrupt) as e:  # pylint: disable=broad-except
            log.log_error(e, self.logger)
            if isinstance(e, KeyboardInterrupt):
                context.run_interrupted = True
                job.set_status(Status.ABORTED)
                raise e
            else:
                job.set_status(Status.FAILED)
            if isinstance(e, TargetNotRespondingError):
                raise e
            elif isinstance(e, TargetError):
                context.tm.verify_target_responsive(context)
        finally:
            self.logger.info('Completing job {}'.format(job.id))
            self.send(signal.JOB_COMPLETED)
            context.tm.stop()
            context.end_job()

            log.dedent()
            self.check_job(job)
Exemplo n.º 9
0
 def __call__(self, context):
     if self.instrument.is_enabled:
         try:
             if not context.tm.is_responsive and not self.is_hostside:
                 logger.debug("Target unresponsive; skipping callback {}".format(self.callback))
                 return
             self.callback(context)
         except (KeyboardInterrupt, TargetNotRespondingError, TimeoutError):  # pylint: disable=W0703
             raise
         except Exception as e:  # pylint: disable=W0703
             logger.error('Error in instrument {}'.format(self.instrument.name))
             global failures_detected  # pylint: disable=W0603
             failures_detected = True
             log_error(e, logger)
             context.add_event(e.args[0] if e.args else str(e))
             if isinstance(e, WorkloadError):
                 context.set_status('FAILED')
             elif isinstance(e, (TargetError, TimeoutError)):
                 context.tm.verify_target_responsive(context)
             else:
                 if context.current_job:
                     context.set_status('PARTIAL')
                 else:
                     raise
Exemplo n.º 10
0
    def run(self):
        try:
            self.initialize_run()
            self.send(signal.RUN_INITIALIZED)

            with signal.wrap('JOB_QUEUE_EXECUTION', self, self.context):
                while self.context.job_queue:
                    if self.context.run_interrupted:
                        raise KeyboardInterrupt()
                    self.run_next_job(self.context)

        except KeyboardInterrupt as e:
            log.log_error(e, self.logger)
            self.logger.info('Skipping remaining jobs.')
            self.context.skip_remaining_jobs()
        except Exception as e:
            message = e.args[0] if e.args else str(e)
            log.log_error(e, self.logger)
            self.logger.error('Skipping remaining jobs due to "{}".'.format(message))
            self.context.skip_remaining_jobs()
            raise e
        finally:
            self.finalize_run()
            self.send(signal.RUN_FINALIZED)
Exemplo n.º 11
0
    def initialize_jobs(self):
        new_queue = []
        failed_ids = []
        for job in self.job_queue:
            if job.id in failed_ids:
                # Don't try to initialize a job if another job with the same ID
                # (i.e. same job spec) has failed - we can assume it will fail
                # too.
                self.skip_job(job)
                continue

            try:
                job.initialize(self)
            except WorkloadError as e:
                job.set_status(Status.FAILED)
                log.log_error(e, self.logger)
                failed_ids.append(job.id)

                if self.cm.run_config.bail_on_init_failure:
                    raise
            else:
                new_queue.append(job)

        self.job_queue = new_queue
Exemplo n.º 12
0
    def do_run_job(self, job, context):
        # pylint: disable=too-many-branches,too-many-statements
        rc = self.context.cm.run_config
        if job.workload.phones_home and not rc.allow_phone_home:
            self.logger.warning(
                'Skipping job {} ({}) due to allow_phone_home=False'.format(
                    job.id, job.workload.name))
            self.context.skip_job(job)
            return

        context.set_job_status(job, Status.RUNNING)
        self.send(signal.JOB_STARTED)

        job.configure_augmentations(context, self.pm)

        with signal.wrap('JOB_TARGET_CONFIG', self, context):
            job.configure_target(context)

        try:
            job.setup(context)
        except Exception as e:
            context.set_job_status(job, Status.FAILED)
            log.log_error(e, self.logger)
            if isinstance(e, (TargetError, TimeoutError)):
                context.tm.verify_target_responsive(context)
            self.context.record_ui_state('setup-error')
            raise e

        try:

            try:
                job.run(context)
            except KeyboardInterrupt:
                context.run_interrupted = True
                context.set_job_status(job, Status.ABORTED)
                raise
            except Exception as e:
                context.set_job_status(job, Status.FAILED)
                log.log_error(e, self.logger)
                if isinstance(e, (TargetError, TimeoutError)):
                    context.tm.verify_target_responsive(context)
                self.context.record_ui_state('run-error')
                raise e
            finally:
                try:
                    with signal.wrap('JOB_OUTPUT_PROCESSED', self, context):
                        job.process_output(context)
                        self.pm.process_job_output(context)
                    self.pm.export_job_output(context)
                except Exception as e:
                    context.set_job_status(job, Status.PARTIAL)
                    if isinstance(e, (TargetError, TimeoutError)):
                        context.tm.verify_target_responsive(context)
                    self.context.record_ui_state('output-error')
                    raise

        except KeyboardInterrupt:
            context.run_interrupted = True
            context.set_status(Status.ABORTED)
            raise
        finally:
            # If setup was successfully completed, teardown must
            # run even if the job failed
            job.teardown(context)
Exemplo n.º 13
0
def main():
    if not os.path.exists(settings.user_directory):
        init_user_directory()
    if not os.path.exists(os.path.join(settings.user_directory,
                                       'config.yaml')):
        init_config()

    try:

        description = (
            "Execute automated workloads on a remote device and process "
            "the resulting output.\n\nUse \"wa <subcommand> -h\" to see "
            "help for individual subcommands.")
        parser = argparse.ArgumentParser(
            description=format_body(description, 80),
            prog='wa',
            formatter_class=argparse.RawDescriptionHelpFormatter,
        )
        init_argument_parser(parser)

        # load_commands will trigger plugin enumeration, and we want logging
        # to be enabled for that, which requires the verbosity setting; however
        # full argument parsing cannot be completed until the commands are loaded; so
        # parse just the base args for now so we can get verbosity.
        argv = split_joined_options(sys.argv[1:])

        # 'Parse_known_args' automatically displays the default help and exits
        # if '-h' or '--help' is detected, we want our custom help messages so
        # ensure these are never passed as parameters.
        filtered_argv = list(argv)
        if '-h' in filtered_argv:
            filtered_argv.remove('-h')
        elif '--help' in filtered_argv:
            filtered_argv.remove('--help')

        args, _ = parser.parse_known_args(filtered_argv)
        settings.set("verbosity", args.verbose)
        log.init(settings.verbosity)
        logger.debug('Version: {}'.format(get_wa_version_with_commit()))
        logger.debug('devlib version: {}'.format(devlib.__full_version__))
        logger.debug('Command Line: {}'.format(' '.join(sys.argv)))
        check_devlib_version()

        # each command will add its own subparser
        subparsers = parser.add_subparsers(dest='command')
        subparsers.required = True
        commands = load_commands(subparsers)
        args = parser.parse_args(argv)

        config = ConfigManager()
        config.load_config_file(settings.user_config_file)
        for config_file in args.config:
            if not os.path.exists(config_file):
                raise ConfigError(
                    "Config file {} not found".format(config_file))
            config.load_config_file(config_file)

        command = commands[args.command]
        sys.exit(command.execute(config, args))

    except KeyboardInterrupt as e:
        log.log_error(e, logger)
        sys.exit(3)
    except Exception as e:  # pylint: disable=broad-except
        log.log_error(e, logger)
        sys.exit(2)
Exemplo n.º 14
0
    def do_run_job(self, job, context):
        # pylint: disable=too-many-branches,too-many-statements
        rc = self.context.cm.run_config
        if job.workload.phones_home and not rc.allow_phone_home:
            self.logger.warning('Skipping job {} ({}) due to allow_phone_home=False'
                                .format(job.id, job.workload.name))
            self.context.skip_job(job)
            return

        job.set_status(Status.RUNNING)
        self.send(signal.JOB_STARTED)

        job.configure_augmentations(context, self.pm)

        with signal.wrap('JOB_TARGET_CONFIG', self, context):
            job.configure_target(context)

        try:
            job.setup(context)
        except Exception as e:
            job.set_status(Status.FAILED)
            log.log_error(e, self.logger)
            if isinstance(e, (TargetError, TimeoutError)):
                context.tm.verify_target_responsive(context)
            self.context.record_ui_state('setup-error')
            raise e

        try:

            try:
                job.run(context)
            except KeyboardInterrupt:
                context.run_interrupted = True
                job.set_status(Status.ABORTED)
                raise
            except Exception as e:
                job.set_status(Status.FAILED)
                log.log_error(e, self.logger)
                if isinstance(e, (TargetError, TimeoutError)):
                    context.tm.verify_target_responsive(context)
                self.context.record_ui_state('run-error')
                raise e
            finally:
                try:
                    with signal.wrap('JOB_OUTPUT_PROCESSED', self, context):
                        job.process_output(context)
                        self.pm.process_job_output(context)
                    self.pm.export_job_output(context)
                except Exception as e:
                    job.set_status(Status.PARTIAL)
                    if isinstance(e, (TargetError, TimeoutError)):
                        context.tm.verify_target_responsive(context)
                    self.context.record_ui_state('output-error')
                    raise

        except KeyboardInterrupt:
            context.run_interrupted = True
            job.set_status(Status.ABORTED)
            raise
        finally:
            # If setup was successfully completed, teardown must
            # run even if the job failed
            job.teardown(context)
Exemplo n.º 15
0
def main():
    if not os.path.exists(settings.user_directory):
        init_user_directory()
    if not os.path.exists(os.path.join(settings.user_directory, 'config.yaml')):
        init_config()

    try:

        description = ("Execute automated workloads on a remote device and process "
                       "the resulting output.\n\nUse \"wa <subcommand> -h\" to see "
                       "help for individual subcommands.")
        parser = argparse.ArgumentParser(description=format_body(description, 80),
                                         prog='wa',
                                         formatter_class=argparse.RawDescriptionHelpFormatter,
                                         )
        init_argument_parser(parser)

        # load_commands will trigger plugin enumeration, and we want logging
        # to be enabled for that, which requires the verbosity setting; however
        # full argument parsing cannot be completed until the commands are loaded; so
        # parse just the base args for now so we can get verbosity.
        argv = split_joined_options(sys.argv[1:])

        # 'Parse_known_args' automatically displays the default help and exits
        # if '-h' or '--help' is detected, we want our custom help messages so
        # ensure these are never passed as parameters.
        filtered_argv = list(argv)
        if '-h' in filtered_argv:
            filtered_argv.remove('-h')
        elif '--help' in filtered_argv:
            filtered_argv.remove('--help')

        args, _ = parser.parse_known_args(filtered_argv)
        settings.set("verbosity", args.verbose)
        log.init(settings.verbosity)
        logger.debug('Version: {}'.format(get_wa_version_with_commit()))
        logger.debug('devlib version: {}'.format(devlib.__full_version__))
        logger.debug('Command Line: {}'.format(' '.join(sys.argv)))

        # each command will add its own subparser
        subparsers = parser.add_subparsers(dest='command')
        subparsers.required = True
        commands = load_commands(subparsers)
        args = parser.parse_args(argv)

        config = ConfigManager()
        config.load_config_file(settings.user_config_file)
        for config_file in args.config:
            if not os.path.exists(config_file):
                raise ConfigError("Config file {} not found".format(config_file))
            config.load_config_file(config_file)

        command = commands[args.command]
        sys.exit(command.execute(config, args))

    except KeyboardInterrupt as e:
        log.log_error(e, logger)
        sys.exit(3)
    except Exception as e:  # pylint: disable=broad-except
        log.log_error(e, logger)
        sys.exit(2)