def _retrieve_adviser_inputs_statistics(
        adviser_files: Dict[str, Any], ) -> List[Dict[str, Any]]:
        """Retrieve adviser inputs statistics.

        :param adviser_files: adviser documents
        """
        adviser_inputs_collected: List[Dict[str, Any]] = []

        for document_id, document in adviser_files.items():

            datetime_advise_run = document["metadata"].get("datetime")
            datetime_object = datetime.strptime(datetime_advise_run,
                                                "%Y-%m-%dT%H:%M:%S.%f")

            cli_arguments = document["metadata"]["arguments"]["thoth-adviser"]
            source_type = (cli_arguments.get("metadata")
                           or {}).get("source_type")
            source_type = source_type.upper() if source_type else None

            parameters = document["result"]["parameters"]

            runtime_environment = parameters["project"].get(
                "runtime_environment")
            os = runtime_environment.get("operating_system", {})
            if os:
                os_name = runtime_environment["operating_system"].get("name")
                if os_name:
                    runtime_environment["operating_system"][
                        "name"] = map_os_name(
                            os_name=runtime_environment["operating_system"]
                            ["name"], )

            # Recommendation type
            recommendation_type = parameters["recommendation_type"].upper()

            # Solver
            os = runtime_environment.get("operating_system", {})
            os_name = os.get("name")
            os_version = normalize_os_version(os.get("name"),
                                              os.get("version"))
            python_interpreter = runtime_environment.get("python_version")

            # Base image
            base_image = runtime_environment.get("base_image", None)
            # Hardware
            hardware = runtime_environment.get("hardware", {})
            adviser_inputs_collected.append(
                {
                    "document_id": document_id,
                    "date": datetime_object,
                    "source_type": source_type,
                    "recommendation_type": recommendation_type,
                    "base_image": base_image,
                    "solver":
                    f'{os_name}-{os_version}-py{python_interpreter.replace(".", "")}',
                    "cpu_model": hardware.get("cpu_model", None),
                    "cpu_family": hardware.get("cpu_family", None),
                }, )

        return adviser_inputs_collected
    def should_include(
        cls, builder_context: "PipelineBuilderContext"
    ) -> Generator[Dict[str, Any], None, None]:
        """Register self if users use runtime environments not matching solvers in the configmap."""
        if not cls._SOLVERS_CONFIGURED or builder_context.is_included(cls):
            yield from ()
            return None

        runtime_environment = (
            builder_context.project.runtime_environment.operating_system.name,
            normalize_os_version(
                builder_context.project.runtime_environment.operating_system.
                name,
                builder_context.project.runtime_environment.operating_system.
                version,
            ),
            builder_context.project.python_version,
        )
        for solver_name in cls._SOLVERS_CONFIGURED.splitlines():
            solver_name = solver_name.strip()

            if not solver_name:
                continue

            try:
                solver_info = OpenShift.parse_python_solver_name(solver_name)
            except SolverNameParseError:
                _LOGGER.exception(
                    "Please report this error to Thoth service administrator")
                yield from ()
                return None

            if runtime_environment == (
                    solver_info["os_name"],
                    solver_info["os_version"],
                    solver_info["python_version"],
            ):
                break
        else:
            yield {}
            return None

        yield from ()
        return None
示例#3
0
    def check_runtime_environment(
            self, runtime_environment_name: str) -> List[Dict[str, Any]]:
        """Check the given runtime environment entry."""
        runtime_environment = self.get_runtime_environment(
            runtime_environment_name)

        result = []

        # CUDA
        cuda_version = discover_cuda_version()
        conf_cuda_version = runtime_environment.get("cuda_version")
        if conf_cuda_version != cuda_version:
            if (cuda_version is None or isinstance(cuda_version, str)
                    and isinstance(conf_cuda_version, str)):
                message_type = "ERROR"
            else:
                message_type = "WARNING"

            result.append({
                "type":
                message_type,
                "runtime_environment":
                runtime_environment_name,
                "message":
                f"CUDA version declared in the configuration file "
                f"({conf_cuda_version!r}) does not match the one detected ({cuda_version!r})",
            })

        # Operating system
        conf_operating_system = runtime_environment.get("operating_system")
        if conf_operating_system:
            conf_os_name = map_os_name(conf_operating_system.get("name"))
            conf_os_version = normalize_os_version(
                conf_os_name, conf_operating_system.get("version"))

            if conf_os_name == "ubi":
                result.append({
                    "type":
                    "INFO",
                    "runtime_environment":
                    runtime_environment_name,
                    "message":
                    "UBI container images are ABI compatible with RHEL container images",
                })
                conf_os_name = "rhel"

            os_name, os_version = discover_distribution()
            os_name = map_os_name(os_name)
            os_version = normalize_os_version(os_name, os_version)
            if conf_os_name != os_name:
                result.append({
                    "type":
                    "ERROR",
                    "runtime_environment":
                    runtime_environment_name,
                    "message":
                    f"Operating system name stated in the configuration file ({conf_os_name!r}) "
                    f"does not match the one detected ({os_name!r})",
                })
            elif conf_os_version != os_version:
                result.append({
                    "type":
                    "ERROR",
                    "runtime_environment":
                    runtime_environment_name,
                    "message":
                    f"Operating system version stated in the configuration file ({conf_os_version!r}) "
                    f"does not match the one detected ({os_version!r})",
                })

        # Python version
        python_version = discover_python_version()
        conf_python_version = runtime_environment.get("python_version")
        if python_version != conf_python_version:
            result.append({
                "type":
                "ERROR",
                "runtime_environment":
                runtime_environment_name,
                "message":
                f"Python version detected ({python_version!r}) does not match the one stated in the "
                f"configuration file ({conf_python_version!r})",
            })

        # Check hardware
        conf_cpu_family = runtime_environment.get("hardware",
                                                  {}).get("cpu_family")
        conf_cpu_model = runtime_environment.get("hardware",
                                                 {}).get("cpu_model")
        cpu_info = discover_cpu()
        if cpu_info.get("cpu_family") != conf_cpu_family:
            result.append({
                "type":
                "ERROR" if conf_cpu_family is not None else "WARNING",
                "runtime_environment":
                runtime_environment_name,
                "message":
                f"CPU family stated in the configuration file ({conf_cpu_family}) does not match the "
                f"one detected ({cpu_info.get('cpu_family')})",
            })

        if cpu_info.get("cpu_model") != conf_cpu_model:
            result.append({
                "type":
                "ERROR" if conf_cpu_model is not None else "WARNING",
                "runtime_environment":
                runtime_environment_name,
                "message":
                f"CPU model stated in the configuration file ({conf_cpu_model}) does not match the "
                f"one detected ({cpu_info.get('cpu_model')})",
            })

        return result
示例#4
0
    def create_default_config(self,
                              template: str = None,
                              nowrite: bool = False) -> Optional[dict]:
        """Place default configuration into the current directory."""
        if not os.path.isdir(".git"):
            _LOGGER.warning(
                "Configuration file is not created in the root of git repo")

        template = template or self.DEFAULT_THOTH_CONFIG
        _LOGGER.debug("Reading configuration from %r", template)
        with open(template, "r") as default_config_file:
            default_config = default_config_file.read()

        _LOGGER.info("Discovering host runtime environment")

        cpu_info = discover_cpu()
        cuda_version = discover_cuda_version()
        # Add quotes for textual representation in the config file.
        cuda_version = f"'{cuda_version}'" if cuda_version is not None else "null"
        os_name, os_version = discover_distribution()
        os_name = map_os_name(os_name)
        os_version = normalize_os_version(os_name, os_version)
        python_version = discover_python_version()
        platform = discover_platform()
        base_image = discover_base_image()
        base_image = base_image if base_image is not None else "null"

        runtime_environment_name = re.sub(r"[^0-9a-zA-Z-]", "-",
                                          f"{os_name}-{os_version}")

        requirements_format = os.getenv("THAMOS_REQUIREMENTS_FORMAT",
                                        self._DEFAULT_REQUIREMENTS_FORMAT)
        if requirements_format not in self.REQUIREMENTS_FORMATS:
            # This avoids possibly dangerous environment variable expansion.
            _LOGGER.warning(
                "Unknown requirements format specified, forcing %r: %r",
                self._DEFAULT_REQUIREMENTS_FORMAT,
                requirements_format,
            )
            requirements_format = self._DEFAULT_REQUIREMENTS_FORMAT

        expand_env = bool(int(os.getenv("THAMOS_CONFIG_EXPAND_ENV", 0)))
        default_config = default_config.format(
            runtime_environment_name=runtime_environment_name,
            cuda_version=cuda_version,
            os_name=os_name,
            os_version=os_version,
            python_version=python_version,
            platform=platform,
            requirements_format=requirements_format,
            base_image=base_image,
            cpu_family=cpu_info["cpu_family"] or "null",
            cpu_model=cpu_info["cpu_model"] or "null",
            cpu_model_name=cpu_info["cpu_model_name"]
            or "CPU detection failed",
            **(dict(os.environ) if expand_env else {}),
        )

        if not nowrite:
            _LOGGER.debug(
                "Writing configuration file to %r",
                os.path.join(os.getcwd(), self.CONFIG_NAME),
            )

            with open(self.CONFIG_NAME, "w") as config_file:
                config_file.write(default_config)
            return None
        else:
            return yaml.safe_load(default_config)