def _verify_check_mk_version(package: PackageInfo) -> None: """Checks whether or not the minimum required Check_MK version is older than the current Check_MK version. Raises an exception if not. When the Check_MK version can not be parsed or is a daily build, the check is simply passing without error.""" min_version = _normalize_daily_version(package["version.min_required"]) if min_version == "master": return # can not check exact version version = _normalize_daily_version(str(cmk_version.__version__)) if version == "master": return # can not check exact version compatible = True try: compatible = parse_check_mk_version(min_version) <= parse_check_mk_version(version) except Exception: # Be compatible: When a version can not be parsed, then skip this check if cmk.utils.debug.enabled(): raise return if not compatible: raise PackageException( "The package requires Check_MK version %s, " "but you have %s installed." % (min_version, version) )
def _check_min_version( plugins: Iterable[Plugin], levels_str: tuple[str, str], mon_state_unparsable: State, type_: str, ) -> CheckResult: levels = (parse_check_mk_version(levels_str[0]), parse_check_mk_version(levels_str[1])) render_info = {p.version_int: p.version for p in plugins} render_info.update(zip(levels, levels_str)) for plugin in plugins: if plugin.version_int is None: yield Result( state=mon_state_unparsable, summary= f"{type_} {plugin.name!r}: unable to parse version {plugin.version!r}", ) else: yield from check_levels( plugin.version_int, levels_lower=levels, render_func=lambda v: render_info[int(v)], label=f"{type_} {plugin.name!r}", notice_only=True, )
def is_pre_17_remote_site(site_status: SiteStatus) -> bool: """Decide which snapshot format is pushed to the given site The sync snapshot format was changed between 1.6 and 1.7. To support migrations with a new central site and an old remote site, we detect that case here and create the 1.6 snapshots for the old sites. """ version = site_status.get("livestatus_version") if not version: return False return parse_check_mk_version(version) < parse_check_mk_version("1.7.0i1")
def _is_expected_agent_version( agent_version: Optional[str], expected_version: AgentTargetVersion, ) -> bool: try: if agent_version is None: return False if agent_version in ["(unknown)", "None", "unknown"]: return False if isinstance(expected_version, str) and expected_version != agent_version: return False if isinstance(expected_version, tuple) and expected_version[0] == "at_least": spec = cast(Dict[str, str], expected_version[1]) if cmk.utils.misc.is_daily_build_version( agent_version) and "daily_build" in spec: expected = int(spec["daily_build"].replace(".", "")) branch = cmk.utils.misc.branch_of_daily_build( agent_version) if branch == "master": agent = int(agent_version.replace(".", "")) else: # branch build (e.g. 1.2.4-2014.06.01) agent = int( agent_version.split("-")[1].replace(".", "")) if agent < expected: return False elif "release" in spec: if cmk.utils.misc.is_daily_build_version(agent_version): return False if parse_check_mk_version( agent_version) < parse_check_mk_version( spec["release"]): return False return True except Exception as e: if cmk.utils.debug.enabled(): raise raise MKGeneralException( "Unable to check agent version (Agent: %s Expected: %s, Error: %s)" % (agent_version, expected_version, e))
def _parse_version_int(version_str: str) -> Optional[int]: """ >>> _parse_version_int("2.1.0p12") 2010050012 """ try: return parse_check_mk_version(version_str) except ValueError: return None
def reverse_translate_metric_name(canonical_name: str) -> List[Tuple[str, float]]: "Return all known perf data names that are translated into canonical_name with corresponding scaling" current_version = parse_check_mk_version(cmk_version.__version__) possible_translations = [] for trans in check_metrics.values(): for metric, options in trans.items(): if options.get("name", "") == canonical_name: if "deprecated" in options: # From version check used unified metric, and thus deprecates old translation # added a complete stable release, that gives the customer about a year of data # under the appropriate metric name. # We should however get all metrics unified before Cmk 2.1 migration_end = parse_check_mk_version(options["deprecated"]) + 10000000 else: migration_end = current_version if migration_end >= current_version: possible_translations.append((metric, options.get("scale", 1.0))) return [(canonical_name, 1.0)] + sorted(set(possible_translations))
def sort_by_version_and_component(werks): translator = WerkTranslator() return sorted( werks, key=lambda w: ( -parse_check_mk_version(w["version"]), translator.component_of(w), _CLASS_SORTING_VALUE.get(w["class"], 99), -w["level"], _COMPATIBLE_SORTING_VALUE.get(w["compatible"], 99), w["title"], ), )
def _check_min_version(plugins: Iterable[Plugin], levels_str: Tuple[str, str], type_: str) -> Iterable[Result]: levels = (parse_check_mk_version(levels_str[0]), parse_check_mk_version(levels_str[1])) render_info = {p.version_int: p.version for p in plugins} render_info.update(zip(levels, levels_str)) for plugin in plugins: if plugin.version_int is None: yield Result( state=State.UNKNOWN, summary= f"{type_} {plugin.name!r}: unable to parse version {plugin.version!r}", ) else: (result, ) = check_levels( plugin.version_int, levels_lower=levels, render_func=lambda v: render_info[int(v)], label=f"{type_} {plugin.name!r}", ) if result.state is not State.OK: yield result
def _is_outdated(package_name: PackageName, package_info: PackageInfo, version: str) -> bool: """Whether or not the given package is considered outated for the given Checkmk version >>> i = _is_outdated >>> i('a', {'version.usable_until': None}, '1.7.0i1') False >>> i('a', {'version.usable_until': '1.6.0'}, '1.7.0i1') True >>> i('a', {'version.usable_until': '1.7.0'}, '1.7.0i1') False >>> i('a', {'version.usable_until': '1.7.0i1'}, '1.7.0i1') True >>> i('a', {'version.usable_until': '1.7.0i1'}, '1.7.0i2') True >>> i('a', {'version.usable_until': '1.7.0'}, '1.7.0') True >>> i('a', {'version.usable_until': '2010.02.01'}, '1.7.0') False >>> i('a', {'version.usable_until': '1.7.0'}, '2010.02.01') False >>> i('a', {'version.usable_until': '1.6.0'}, '1.6.0-2010.02.01') True >>> i('a', {'version.usable_until': '1.6.0-2010.02.01'}, '1.6.0') True >>> i('a', {'version.usable_until': ''}, '1.6.0') False >>> i('a', {'version.usable_until': '1.6.0'}, '') False # Checkmk 1.6 shipped the first feature pack MKPs which sadly had no # "version.usable_until" attribute set. To be able to disable them automatically # we use a hard coded list of package names below. All of these packages start # with the version number "1.". To ensure the known and possible future packages # are removed, we consider the known packages to be outdated. >>> i('azure_ad', {'version': '1.0', 'version.usable_until': ''}, '1.7.0i1') True >>> i('prometheus', {'version': '1.3', 'version.usable_until': ''}, '1.7.0i1') True >>> i('prometheus', {'version': '2.0', 'version.usable_until': ''}, '1.7.0i1') False """ until_version = package_info["version.usable_until"] if _is_16_feature_pack_package(package_name, package_info): logger.log( VERBOSE, "[%s]: This is a 1.6 feature pack package: It is outdated. ", package_name ) return True if until_version is None: logger.log(VERBOSE, '[%s]: "Until version" is not set', package_name) return False # Normalize daily versions to branch version version = _normalize_daily_version(version) if version == "master": logger.log( VERBOSE, "[%s]: This is a daily build of master branch, can not decide", package_name ) return False until_version = _normalize_daily_version(until_version) if until_version == "master": logger.log( VERBOSE, "[%s]: Until daily build of master branch, can not decide", package_name ) return False try: is_outdated = parse_check_mk_version(version) >= parse_check_mk_version(until_version) except Exception: logger.log( VERBOSE, "[%s]: Could not compare until version %r with current version %r", package_name, until_version, version, exc_info=True, ) return False logger.log(VERBOSE, "[%s]: %s > %s = %s", package_name, version, until_version, is_outdated) return is_outdated
auto_logger = logger.getChild("automations") # Disable python warnings in background job output or logs like "Unverified # HTTPS request is being made". We warn the user using analyze configuration. urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) class MKAutomationException(MKGeneralException): pass def remote_automation_call_came_from_pre21() -> bool: # The header is sent by Checkmk as of 2.0.0p1. In case it is missing, assume we are too old. if not (remote_version := request.headers.get("x-checkmk-version")): return True return parse_check_mk_version(remote_version) < parse_check_mk_version( "2.1.0i1") def check_mk_local_automation_serialized( *, command: str, args: Optional[Sequence[str]] = None, indata: Any = "", stdin_data: Optional[str] = None, timeout: Optional[int] = None, ) -> Tuple[Sequence[str], SerializedResult]: if args is None: args = [] new_args = list(args)
literal = spec.get("literal", site_version) return "" if literal == agent_version else f" (expected {literal})" # spec_type == "at_least" if is_daily_build_version(agent_version) and ( at_least := spec.get("daily_build")) is not None: if int(agent_version.split("-")[-1].replace(".", "")) < int( at_least.replace(".", "")): return f" (expected at least {at_least})" if (at_least := spec.get("release")) is None: return "" return (f" (expected at least {at_least})" if is_daily_build_version(agent_version) or (parse_check_mk_version(agent_version) < parse_check_mk_version(at_least)) else "") def _check_only_from( agent_only_from: Union[None, str, Sequence[str]], config_only_from: Union[None, str, list[str]], fail_state: State, ) -> CheckResult: if agent_only_from is None or config_only_from is None: return # do we really need 'normalize_ip_addresses'? It deals with '{' expansion. allowed_nets = set(normalize_ip_addresses(agent_only_from)) expected_nets = set(normalize_ip_addresses(config_only_from)) if allowed_nets == expected_nets:
def _validate_version(value: str, varprefix: str) -> None: try: parse_check_mk_version(value) except (ValueError, TypeError, KeyError): raise MKUserError(varprefix, _("Can't parse version %r") % value)
def test_old_parse_check_mk_version_equals_new_version_class(version_str): assert ( cmk_version.parse_check_mk_version(version_str) == cmk_version.Version(version_str).parse_to_int() )