Esempio n. 1
0
    def _get_conf(self, section, option):
        """
        _get_conf - get the option from the section, raising
        BadConfig Error if it is empty, return the option value as a string.
        """
        try:
            option_val = self.conf.get(section, option)
        except (NoOptionError, NoSectionError) as exc:
            raise BadConfig(str(exc))
        else:
            if not option_val:
                raise BadConfig(f"option {option} in section {section} is empty")

        return option_val
Esempio n. 2
0
    def __init__(self, cfg_name):
        # Enumerate the list of files
        config_files = configtools.file_list(cfg_name)
        config_files.reverse()
        self.conf = ConfigParser()
        self.files = self.conf.read(config_files)

        try:
            self.logger_type = self.conf.get("logging", "logger_type")
        except (NoOptionError, NoSectionError):
            self.logger_type = "devlog"
        else:
            if self.logger_type == "hostport":
                try:
                    self.logger_host = self.conf.get("logging", "logger_host")
                    self.logger_port = self.conf.get("logging", "logger_port")
                except (NoOptionError) as exc:
                    raise BadConfig(str(exc))

        try:
            self.default_logging_level = self.conf.get("logging",
                                                       "logging_level")
        except (NoOptionError, NoSectionError):
            self.default_logging_level = "INFO"

        # Constants

        # Force UTC everywhere
        self.TZ = "UTC"
Esempio n. 3
0
    def _get_valid_dir_option(self, req_val, section, option):
        """_get_valid_dir_option - get the directory option from the
        given section, raising BadConfig Error if the path is not resolved
        or is not a directory, returning a Path directory object.
        """
        dir_val = self._get_conf(section, option)
        dir_path = self._get_valid_path(req_val, dir_val, None)
        if not dir_path:
            raise BadConfig(f"Bad {req_val}={dir_val}")

        return dir_path
Esempio n. 4
0
    def __init__(self, cfg_name):
        # Enumerate the list of files
        config_files = configtools.file_list(cfg_name)
        config_files.reverse()
        self.conf = ConfigParser()
        self.files = self.conf.read(config_files)

        try:
            self.logger_type = self.conf.get("logging", "logger_type")
        except (NoOptionError, NoSectionError):
            self.logger_type = "devlog"
        else:
            if self.logger_type == "hostport":
                try:
                    self.logger_host = self.conf.get("logging", "logger_host")
                    self.logger_port = self.conf.get("logging", "logger_port")
                except (NoOptionError) as exc:
                    raise BadConfig(str(exc))

        try:
            self.log_dir = self.conf.get("logging", "log_dir")
        except (NoOptionError, NoSectionError):
            # Allow for compatibility with previous configuration files.  Any
            # sub-class of this base class can change the log directory as
            # necessary.  Note that this class ONLY records the value found in
            # the configuration file, it does not take any actions on it.
            self.log_dir = None

        # The Agent and Server classes behave a bit differently with respect
        # to logging when using the "file" logger type. While this is not
        # derived from a configuration file, we keep track of the behavioral
        # attribute with the configuration.  The sub-classes will override the
        # value as necessary.
        self.log_using_caller_directory = False

        try:
            self.default_logging_level = self.conf.get("logging",
                                                       "logging_level")
        except (NoOptionError, NoSectionError):
            self.default_logging_level = "INFO"

        try:
            # We don't document the "log_format" parameter since it is really
            # only present to facilitate easier unit testing.
            self.log_fmt = self.conf.get("logging", "log_format")
        except (NoOptionError, NoSectionError):
            self.log_fmt = None

        # Constants

        # Force UTC everywhere
        self.TZ = "UTC"
Esempio n. 5
0
def get_pbench_logger(caller, config):
    """Fetch the logger specifed by "caller", and add a specific handler
    based on the logging configuration requested.

    We also return a logger that supports "brace" style message formatting,
    e.g. logger.warning("that = {}", that)
    """

    pbench_logger = logging.getLogger(caller)
    if caller not in _handlers:
        try:
            logging_level = config.get(caller, "logging_level")
        except (NoSectionError, NoOptionError):
            logging_level = config.default_logging_level
        pbench_logger.setLevel(logging_level)

        if config.logger_type == "file":
            log_dir = Path(config.log_dir)
            if config.log_using_caller_directory:
                log_dir = log_dir / caller
            try:
                log_dir.mkdir()
            except FileExistsError:
                # directory already exists, ignore
                pass
            handler = logging.FileHandler(log_dir / f"{caller}.log")
        elif config.logger_type == "devlog":
            handler = logging.handlers.SysLogHandler(address=_devlog)
        elif (config.logger_type == "hostport"
              ):  # hostport logger type uses UDP-based logging
            handler = logging.handlers.SysLogHandler(
                address=(config.logger_host, int(config.logger_port)))
        else:
            raise BadConfig("Unsupported logger type")

        handler.setLevel(logging.DEBUG)
        if config.log_fmt is None:
            logfmt = "{asctime} {levelname} {process} {thread} {name}.{module} {funcName} {lineno} -- {message}"
        else:
            logfmt = config.log_fmt
        formatter = _PbenchLogFormatter(fmt=logfmt)
        handler.setFormatter(formatter)
        _handlers[caller] = handler
        pbench_logger.addHandler(handler)
    return _StyleAdapter(pbench_logger)
Esempio n. 6
0
    def __init__(self, cfg_name):
        super().__init__(cfg_name)

        try:
            # Provide a few convenience attributes.
            self.agent = self.conf["pbench-agent"]
            self.results = self.conf["results"]
            # Now fetch some default common pbench settings that are required.
            self.pbench_run = Path(
                self.conf.get("pbench-agent",
                              "pbench_run",
                              fallback=DEFAULT_PBENCH_AGENT_RUN_DIR))
            self.pbench_tmp = self.pbench_run / "tmp"
            self.pbench_log = Path(
                self.conf.get(
                    "pbench-agent",
                    "pbench_log",
                    fallback=str(self.pbench_run / "pbench.log"),
                ))
            self.pbench_install_dir = Path(
                self.conf.get(
                    "pbench-agent",
                    "install-dir",
                    fallback=DEFAULT_PBENCH_AGENT_INSTALL_DIR,
                ))
        except (NoOptionError, NoSectionError, KeyError) as exc:
            raise BadConfig(f"{exc}: {self.files}")
        else:
            if not self.pbench_install_dir.is_dir():
                raise BadConfig(
                    "pbench installation directory,"
                    f" '{self.pbench_install_dir}', does not exist")
            try:
                self.pbench_tmp.mkdir(parents=True, exist_ok=True)
            except OSError as exc:
                raise BadConfig(str(exc))
            self.pbench_bspp_dir = (self.pbench_install_dir / "bench-scripts" /
                                    "postprocess")
            self.pbench_lib_dir = self.pbench_install_dir / "lib"

        if self.logger_type == "file" and self.log_dir is None:
            # The configuration file has a logging section configured to use
            # "file" logging, but no log directory is set.  We'll set the log
            # directory to be the directory of the legacy ${pbench_log} value
            # determined above.
            self.log_dir = str(self.pbench_log.parent)

        try:
            self.ssh_opts = self.conf.get("results",
                                          "ssh_opts",
                                          fallback=DEFAULT_SSH_OPTS)
        except (NoOptionError, NoSectionError):
            self.ssh_opts = DEFAULT_SSH_OPTS

        try:
            self.scp_opts = self.conf.get("results",
                                          "scp_opts",
                                          fallback=DEFAULT_SCP_OPTS)
        except (NoOptionError, NoSectionError):
            self.scp_opts = DEFAULT_SCP_OPTS

        try:
            self.prom_reg = self.conf.get("container-registry",
                                          "prometheus",
                                          fallback=DEFAULT_PROM_REG)
        except (NoOptionError, NoSectionError):
            self.prom_reg = DEFAULT_PROM_REG

        try:
            self.pmlogger_reg = self.conf.get("container-registry",
                                              "pcp_pmlogger",
                                              fallback=DEFAULT_PMLOGGER_REG)
        except (NoOptionError, NoSectionError):
            self.pmlogger_reg = DEFAULT_PMLOGGER_REG

        try:
            self.pmcd_reg = self.conf.get("container-registry",
                                          "pcp_pmcd",
                                          fallback=DEFAULT_PMCD_REG)
        except (NoOptionError, NoSectionError):
            self.pmcd_reg = DEFAULT_PMCD_REG

        try:
            self._unittests = self.conf.get("pbench-agent", "debug_unittest")
        except Exception:
            self._unittests = False
        else:
            self._unittests = bool(self._unittests)

        try:
            self._debug = self.conf.get("pbench-agent", "debug")
        except Exception:
            self._debug = False
        else:
            self._debug = bool(self._debug)
Esempio n. 7
0
    def __init__(self, cfg_name):
        super().__init__(cfg_name)

        try:
            # Provide a few convenience attributes.
            self.agent = self.conf["pbench-agent"]
            self.results = self.conf["results"]
            # Now fetch some default common pbench settings that are required.
            self.pbench_run = Path(
                self.conf.get("pbench-agent",
                              "pbench_run",
                              fallback=DEFAULT_PBENCH_AGENT_RUN_DIR))
            self.pbench_tmp = self.pbench_run / "tmp"
            self.pbench_log = Path(
                self.conf.get(
                    "pbench-agent",
                    "pbench_log",
                    fallback=str(self.pbench_run / "pbench.log"),
                ))
            self.pbench_install_dir = Path(
                self.conf.get(
                    "pbench-agent",
                    "install-dir",
                    fallback=DEFAULT_PBENCH_AGENT_INSTALL_DIR,
                ))
        except (NoOptionError, NoSectionError, KeyError) as exc:
            raise BadConfig(f"{exc}: {self.files}")
        else:
            if not self.pbench_install_dir.is_dir():
                raise BadConfig(
                    "pbench installation directory,"
                    f" '{self.pbench_install_dir}', does not exist")
            try:
                self.pbench_tmp.mkdir(parents=True, exist_ok=True)
            except OSError as exc:
                raise BadConfig(str(exc))
            self.pbench_bspp_dir = (self.pbench_install_dir / "bench-scripts" /
                                    "postprocess")
            self.pbench_lib_dir = self.pbench_install_dir / "lib"
            self.LOGSDIR = self.pbench_log

        try:
            self.ssh_opts = self.conf.get("results",
                                          "ssh_opts",
                                          fallback=DEFAULT_SSH_OPTS)
        except (NoOptionError, NoSectionError):
            self.ssh_opts = DEFAULT_SSH_OPTS

        try:
            self.scp_opts = self.conf.get("results",
                                          "scp_opts",
                                          fallback=DEFAULT_SCP_OPTS)
        except (NoOptionError, NoSectionError):
            self.scp_opts = DEFAULT_SCP_OPTS

        try:
            self._unittests = self.conf.get("pbench-agent", "debug_unittest")
        except Exception:
            self._unittests = False
        else:
            self._unittests = bool(self._unittests)

        try:
            self._debug = self.conf.get("pbench-agent", "debug")
        except Exception:
            self._debug = False
        else:
            self._debug = bool(self._debug)
Esempio n. 8
0
    def __init__(self, cfg_name):
        super().__init__(cfg_name)

        # Now fetch some default common pbench settings that are required.
        try:
            self.TOP = Path(self.conf.get("pbench-server", "pbench-top-dir"))
            if not self.TOP.is_dir():
                raise BadConfig(f"Bad TOP={self.TOP}")
            self.TMP = Path(self.conf.get("pbench-server", "pbench-tmp-dir"))
            if not self.TMP.is_dir():
                raise BadConfig(f"Bad TMP={self.TMP}")
            self.LOGSDIR = Path(
                self.conf.get("pbench-server", "pbench-logs-dir"))
            if not self.LOGSDIR.is_dir():
                raise BadConfig(f"Bad LOGSDIR={self.LOGSDIR}")
            self.BINDIR = Path(self.conf.get("pbench-server", "script-dir"))
            if not self.BINDIR.is_dir():
                raise BadConfig(f"Bad BINDIR={self.BINDIR}")
            self.LIBDIR = Path(self.conf.get("pbench-server", "lib-dir"))
            if not self.LIBDIR.is_dir():
                raise BadConfig(f"Bad LIBDIR={self.LIBDIR}")
            # the scripts may use this to send status messages
            self.mail_recipients = self.conf.get("pbench-server", "mailto")
            self.ARCHIVE = Path(
                self.conf.get("pbench-server", "pbench-archive-dir"))
        except (NoOptionError, NoSectionError) as exc:
            raise BadConfig(str(exc))
        else:
            self.INCOMING = self.TOP / "public_html" / "incoming"
            # this is where the symlink forest is going to go
            self.RESULTS = self.TOP / "public_html" / "results"
            self.USERS = self.TOP / "public_html" / "users"

        try:
            self.PBENCH_ENV = self.conf.get("pbench-server", "environment")
        except NoOptionError:
            self.PBENCH_ENV = ""

        try:
            self.COMMIT_ID = self.conf.get("pbench-server", "commit_id")
        except NoOptionError:
            self.COMMIT_ID = "(unknown)"

        try:
            self._unittests = self.conf.get("pbench-server", "debug_unittest")
        except Exception:
            self._unittests = False
        else:
            self._unittests = bool(self._unittests)

        if self._unittests:

            def mocked_time():
                return 42.00

            global _time
            _time = mocked_time

            try:
                ref_dt_str = self.conf.get("pbench-server",
                                           "debug_ref_datetime")
            except Exception:
                ref_dt_str = "1970-01-02T00:00:00.000000"
            self._ref_datetime = datetime.strptime(ref_dt_str,
                                                   _STD_DATETIME_FMT)
        else:
            self._ref_datetime = None

        # Constants

        # Initial common timestamp format
        self.TS = f"run-{self.timestamp()}"
        # Make all the state directories for the pipeline and any others
        # needed.  Every related state directories are paired together with
        # their final state at the end.
        self.LINKDIRS = (
            "TODO BAD-MD5"
            " TO-UNPACK UNPACKED WONT-UNPACK"
            " TO-SYNC SYNCED"
            " TO-LINK"
            " TO-INDEX TO-RE-INDEX TO-INDEX-TOOL INDEXED WONT-INDEX"
            " TO-COPY-SOS COPIED-SOS"
            " TO-BACKUP BACKED-UP BACKUP-FAILED"
            " SATELLITE-MD5-PASSED SATELLITE-MD5-FAILED"
            " TO-DELETE SATELLITE-DONE")
        # List of the state directories which will be excluded during rsync.
        # Note that range(1,12) generates the sequence [1..11] inclusively.
        self.EXCLUDE_DIRS = (
            "_QUARANTINED " + self.LINKDIRS + " " +
            " ".join([f"WONT-INDEX.{i:d}" for i in range(1, 12)]))