예제 #1
0
    def parse_args(self, argv=None):
        conf_parser = argparse.ArgumentParser(add_help=False)

        # We have two parsers so we have correct --help, we need -c in both
        conf_parser.add_argument("-c", "--config-file", help="Configuration File",
                                 metavar="FILE")

        args, remaining_args = conf_parser.parse_known_args(argv)
        defaults = {}
        config = configparser.SafeConfigParser()
        config.read([os.path.expanduser("~/.op-test-framework.conf")])
        if args.config_file:
            if os.access(args.config_file, os.R_OK):
                config.read([args.config_file])
            else:
                raise OSError(errno.ENOENT, os.strerror(
                    errno.ENOENT), args.config_file)
        try:
            defaults = dict(config.items('op-test'))
        except configparser.NoSectionError:
            pass

        parser = get_parser()
        parser.set_defaults(**defaults)

        if defaults.get('qemu_binary'):
            qemu_default = defaults['qemu_binary']

        if defaults.get('mambo_binary'):
            mambo_default = defaults['mambo_binary']
        if defaults.get('mambo_initial_run_script'):
            mambo_default = defaults['mambo_initial_run_script']

        parser.add_argument("--check-ssh-keys", action='store_true', default=False,
                            help="Check remote host keys when using SSH (auto-yes on new)")
        parser.add_argument("--known-hosts-file",
                            help="Specify a custom known_hosts file")

        self.args, self.remaining_args = parser.parse_known_args(
            remaining_args)

        args_dict = vars(self.args)

        # if we have a bmc_type we start with appropriate template
        if args_dict.get('bmc_type') is not None:
            dict_merge = default_templates.get(
                args_dict.get('bmc_type').lower())
            if dict_merge is not None:
                # overlays dict merge on top of default_val
                default_val.update(dict_merge)

        for key in default_val:
            if args_dict.get(key) is None:
                args_dict[key] = default_val[key]

        stateMap = {'UNKNOWN': common.OpTestSystem.OpSystemState.UNKNOWN,
                    'UNKNOWN_BAD': common.OpTestSystem.OpSystemState.UNKNOWN_BAD,
                    'OFF': common.OpTestSystem.OpSystemState.OFF,
                    'PETITBOOT': common.OpTestSystem.OpSystemState.PETITBOOT,
                    'PETITBOOT_SHELL': common.OpTestSystem.OpSystemState.PETITBOOT_SHELL,
                    'OS': common.OpTestSystem.OpSystemState.OS
                    }

        # Some quick sanity checking
        if self.args.known_hosts_file and not self.args.check_ssh_keys:
            parser.error("--known-hosts-file requires --check-ssh-keys")

        # Setup some defaults for the output options
        # Order of precedence
        # 1. cmdline arg
        # 2. env variable
        # 3. default path
        if (self.args.output):
            outdir = self.args.output
        elif ("OP_TEST_OUTPUT" in os.environ):
            outdir = os.environ["OP_TEST_OUTPUT"]
        else:
            outdir = os.path.join(self.basedir, "test-reports")

        self.outsuffix = "test-run-%s" % self.get_suffix()
        outdir = os.path.join(outdir, self.outsuffix)

        # Normalize the path to fully qualified and create if not there
        self.output = os.path.abspath(outdir)
        if (not os.path.exists(self.output)):
            os.makedirs(self.output)

        if (self.args.logdir):
            logdir = self.args.logdir
        elif ("OP_TEST_LOGDIR" in os.environ):
            logdir = os.environ["OP_TEST_LOGDIR"]
        else:
            logdir = self.output

        self.logdir = os.path.abspath(logdir)
        if (not os.path.exists(self.logdir)):
            os.makedirs(self.logdir)

        print(("Logs in: {}".format(self.logdir)))

        OpTestLogger.optest_logger_glob.logdir = self.logdir

        # Grab the suffix, if not given use current time
        self.outsuffix = self.get_suffix()

        # set up where all the logs go
        logfile = os.path.join(self.output, "%s.log" % self.outsuffix)

        logcmd = "tee %s" % (logfile)
        # we use 'cat -v' to convert control characters
        # to something that won't affect the user's terminal
        if self.args.quiet:
            logcmd = logcmd + "> /dev/null"
            # save sh_level for later refresh loggers
            OpTestLogger.optest_logger_glob.sh_level = logging.ERROR
            OpTestLogger.optest_logger_glob.sh.setLevel(logging.ERROR)
        else:
            logcmd = logcmd + "| sed -u -e 's/\\r$//g'|cat -v"
            # save sh_level for later refresh loggers
            OpTestLogger.optest_logger_glob.sh_level = logging.INFO
            OpTestLogger.optest_logger_glob.sh.setLevel(logging.INFO)

        OpTestLogger.optest_logger_glob.setUpLoggerFile(
            datetime.utcnow().strftime("%Y%m%d%H%M%S%f")+'.main.log')
        OpTestLogger.optest_logger_glob.setUpLoggerDebugFile(
            datetime.utcnow().strftime("%Y%m%d%H%M%S%f")+'.debug.log')
        OpTestLogger.optest_logger_glob.optest_logger.info(
            'TestCase Log files: {}/*'.format(self.output))
        OpTestLogger.optest_logger_glob.optest_logger.info(
            'StreamHandler setup {}'.format('quiet' if self.args.quiet else 'normal'))

        self.logfile_proc = subprocess.Popen(logcmd,
                                             stdin=subprocess.PIPE,
                                             stderr=sys.stderr,
                                             stdout=sys.stdout,
                                             shell=True,
                                             universal_newlines=True,
                                             encoding='utf-8')
        self.logfile = self.logfile_proc.stdin

        # we have enough setup to allow
        # signal handler cleanup to run
        self.signal_ready = True
        # atexit viable for cleanup to run
        self.atexit_ready = True
        # now that we have loggers, dump conf file to help debug later
        OpTestLogger.optest_logger_glob.optest_logger.debug(
            "conf file defaults={}".format(defaults))
        cmd = "git describe --always"
        try:
            git_output = subprocess.check_output(cmd.split())
            # log for triage of how dated the repo is
            OpTestLogger.optest_logger_glob.optest_logger.debug(
                "op-test-framework git level = {}".format(git_output))
        except Exception as e:
            OpTestLogger.optest_logger_glob.optest_logger.debug(
                "Unable to get git describe")
        # setup AES and Hostlocker configs after the logging is setup
        locker_timeout = time.time() + 60*self.args.locker_wait
        locker_code = errno.ETIME  # 62
        locker_message = ("OpTestSystem waited {} minutes but was unable"
                          " to lock environment/host requested,"
                          " either pick another environment/host or increase "
                          "--locker-wait, try --aes q with options for "
                          "--aes-search-args to view availability, or as"
                          " appropriate for your hostlocker"
                          .format(self.args.locker_wait))
        locker_exit_exception = OpExit(message=locker_message,
                                       code=locker_code)
        while True:
            try:
                rollup_flag = False
                self.util.check_lockers()
                break
            except Exception as e:
                OpTestLogger.optest_logger_glob.optest_logger.debug(
                    "locker_wait Exception={}".format(e))
                if "unable to lock" in e.message:
                    self.aes_print_helpers = False
                    # SystemExit exception needs message to print
                    rollup_message = locker_exit_exception.message
                    rollup_exception = locker_exit_exception
                else:
                    rollup_message = e.message
                    rollup_exception = e
                    rollup_flag = True  # bubble exception out
                if time.time() > locker_timeout or rollup_flag:
                    # if not "unable to lock" we bubble up underlying exception
                    OpTestLogger.optest_logger_glob.optest_logger.warning(
                        "{}".format(rollup_message))
                    raise rollup_exception
                else:
                    OpTestLogger.optest_logger_glob.optest_logger.info(
                        "OpTestSystem waiting for requested environment/host"
                        " total time to wait is {} minutes, we will check"
                        " every minute"
                        .format(self.args.locker_wait))
                    time.sleep(60)

        if self.args.machine_state == None:
            if self.args.bmc_type in ['qemu', 'mambo']:
                # Force UNKNOWN_BAD so that we don't try to setup the console early
                self.startState = common.OpTestSystem.OpSystemState.UNKNOWN_BAD
            else:
                self.startState = common.OpTestSystem.OpSystemState.UNKNOWN
        else:
            self.startState = stateMap[self.args.machine_state]
        return self.args, self.remaining_args
    def do_testing_setup(self):
        # Setup some defaults for the output options
        # Order of precedence
        # 1. cmdline arg
        # 2. env variable
        # 3. default path
        if (self.args.output):
            outdir = self.args.output
        elif ("OP_TEST_OUTPUT" in os.environ):
            outdir = os.environ["OP_TEST_OUTPUT"]
        else:
            outdir = os.path.join(self.basedir, "test-reports")

        self.outsuffix = "test-run-%s" % self.get_suffix()
        outdir = os.path.join(outdir, self.outsuffix)

        # Normalize the path to fully qualified and create if not there
        self.output = os.path.abspath(outdir)
        if (not os.path.exists(self.output)):
            os.makedirs(self.output)

        if (self.args.logdir):
            logdir = self.args.logdir
        elif ("OP_TEST_LOGDIR" in os.environ):
            logdir = os.environ["OP_TEST_LOGDIR"]
        else:
            logdir = self.output

        self.logdir = os.path.abspath(logdir)
        if (not os.path.exists(self.logdir)):
            os.makedirs(self.logdir)

        print(("Logs in: {}".format(self.logdir)))

        OpTestLogger.optest_logger_glob.logdir = self.logdir

        # Grab the suffix, if not given use current time
        self.outsuffix = self.get_suffix()

        # set up where all the logs go
        logfile = os.path.join(self.output, "%s.log" % self.outsuffix)

        logcmd = "tee %s" % (logfile)
        # we use 'cat -v' to convert control characters
        # to something that won't affect the user's terminal
        if self.args.quiet:
            logcmd = logcmd + "> /dev/null"
            # save sh_level for later refresh loggers
            OpTestLogger.optest_logger_glob.sh_level = logging.ERROR
            OpTestLogger.optest_logger_glob.sh.setLevel(logging.ERROR)
        else:
            logcmd = logcmd + "| sed -u -e 's/\\r$//g'|cat -v"
            # save sh_level for later refresh loggers
            OpTestLogger.optest_logger_glob.sh_level = logging.INFO
            OpTestLogger.optest_logger_glob.sh.setLevel(logging.INFO)

        OpTestLogger.optest_logger_glob.setUpLoggerFile(
            datetime.utcnow().strftime("%Y%m%d%H%M%S%f") + '.main.log')
        OpTestLogger.optest_logger_glob.setUpLoggerDebugFile(
            datetime.utcnow().strftime("%Y%m%d%H%M%S%f") + '.debug.log')
        OpTestLogger.optest_logger_glob.optest_logger.info(
            'TestCase Log files: {}/*'.format(self.output))
        OpTestLogger.optest_logger_glob.optest_logger.info(
            'StreamHandler setup {}'.format(
                'quiet' if self.args.quiet else 'normal'))

        self.logfile_proc = subprocess.Popen(logcmd,
                                             stdin=subprocess.PIPE,
                                             stderr=sys.stderr,
                                             stdout=sys.stdout,
                                             shell=True,
                                             universal_newlines=True,
                                             encoding='utf-8')
        self.logfile = self.logfile_proc.stdin

        # we have enough setup to allow
        # signal handler cleanup to run
        self.signal_ready = True
        # atexit viable for cleanup to run
        self.atexit_ready = True
        # now that we have loggers, dump conf file to help debug later
        OpTestLogger.optest_logger_glob.optest_logger.debug(
            "conf file defaults={}".format(self.defaults))
        cmd = "git describe --always"
        try:
            git_output = subprocess.check_output(cmd.split())
            # log for triage of how dated the repo is
            OpTestLogger.optest_logger_glob.optest_logger.debug(
                "op-test-framework git level = {}".format(git_output))
        except Exception as e:
            OpTestLogger.optest_logger_glob.optest_logger.debug(
                "Unable to get git describe")

        # MTU Check here post handler and logging setup
        try:
            self.util.PingMTUCheck(
                self.args.bmc_ip,
                totalSleepTime=BMC_CONST.PING_RETRY_FOR_STABILITY)
        except Exception as e:
            OpTestLogger.optest_logger_glob.optest_logger.warning(
                "Check that the BMC is healthy, maybe the Broadcom bug, Exception={}"
                .format(e))

        # setup AES and Hostlocker configs after the logging is setup
        locker_timeout = time.time() + 60 * self.args.locker_wait
        locker_code = errno.ETIME  # 62
        locker_message = ("OpTestSystem waited {} minutes but was unable"
                          " to lock environment/host requested,"
                          " either pick another environment/host or increase "
                          "--locker-wait, try --aes q with options for "
                          "--aes-search-args to view availability, or as"
                          " appropriate for your hostlocker".format(
                              self.args.locker_wait))
        locker_exit_exception = OpExit(message=locker_message,
                                       code=locker_code)
        while True:
            try:
                rollup_flag = False
                self.util.check_lockers()
                break
            except Exception as e:
                OpTestLogger.optest_logger_glob.optest_logger.debug(
                    "locker_wait Exception={}".format(e))
                if "unable to lock" in e.message:
                    self.aes_print_helpers = False
                    # SystemExit exception needs message to print
                    rollup_message = locker_exit_exception.message
                    rollup_exception = locker_exit_exception
                else:
                    rollup_message = e.message
                    rollup_exception = e
                    rollup_flag = True  # bubble exception out
                if time.time() > locker_timeout or rollup_flag:
                    # if not "unable to lock" we bubble up underlying exception
                    OpTestLogger.optest_logger_glob.optest_logger.warning(
                        "{}".format(rollup_message))
                    raise rollup_exception
                else:
                    OpTestLogger.optest_logger_glob.optest_logger.info(
                        "OpTestSystem waiting for requested environment/host"
                        " total time to wait is {} minutes, we will check"
                        " every minute".format(self.args.locker_wait))
                    time.sleep(60)