def _sanitize_yield_check_result(result: Iterable[Any]) -> ServiceCheckResult: subresults = list(result) # Empty list? Check returned nothing if not subresults: return ITEM_NOT_FOUND # Several sub results issued with multiple yields. Make that worst sub check # decide the total state, join the texts and performance data. Subresults with # an infotext of None are used for adding performance data. perfdata: List[MetricTuple] = [] infotexts: List[ServiceDetails] = [] status: ServiceState = 0 for subresult in subresults: st, text, perf = _sanitize_tuple_check_result(subresult, allow_missing_infotext=True) status = worst_service_state(st, status, default=0) if text: infotexts.append(text + state_markers[st]) if perf is not None: perfdata += perf return status, ", ".join(infotexts), perfdata
def _aggregate_subresults(*subresults: _DiscoverySubresult) -> _DiscoverySubresult: stati, texts, long_texts, perfdata_list = zip(*(result for result, _ in subresults)) return (( worst_service_state(*stati, default=0), sum((list(t) for t in texts), []), sum((list(l) for l in long_texts), []), sum((list(p) for p in perfdata_list), []), ), any(need_rediscovery_flag for _, need_rediscovery_flag in subresults))
def _aggregate_subresults(*subresults: _DiscoverySubresult) -> _DiscoverySubresult: stati, texts, long_texts, perfdata_list, need_rediscovery_flags = zip(*subresults) return ( worst_service_state(*stati, default=0), sum(texts, []), sum(long_texts, []), sum(perfdata_list, []), any(need_rediscovery_flags), )
def _check_data_sources( result: Sequence[Tuple[sources.Source, result_type.Result[HostSections, Exception]]], ) -> _DiscoverySubresult: summaries = [(source, source.summarize(host_sections)) for source, host_sections in result] return ( worst_service_state(*(state for _s, (state, _t) in summaries), default=0), # Do not output informational (state = 0) things. These information # are shown by the "Check_MK" service [f"[{src.id}] {text}" for src, (state, text) in summaries if state != 0], [], [], False, )
def _check_service_lists( *, host_name: HostName, services_by_transition: ServicesByTransition, params: config.DiscoveryCheckParameters, service_filters: _ServiceFilters, discovery_mode: DiscoveryMode, ) -> Tuple[ActiveCheckResult, bool]: status = 0 infotexts = [] long_infotexts = [] need_rediscovery = False for transition, title, params_key, default_state, service_filter in [ ("new", "unmonitored", "severity_unmonitored", config.inventory_check_severity, service_filters.new), ("vanished", "vanished", "severity_vanished", 0, service_filters.vanished), ]: affected_check_plugin_names: Counter[CheckPluginName] = Counter() unfiltered = False for (discovered_service, _found_on_nodes) in services_by_transition.get(transition, []): affected_check_plugin_names[ discovered_service.check_plugin_name] += 1 if not unfiltered and service_filter(host_name, discovered_service): unfiltered = True #TODO In service_filter:we use config.service_description(...) # in order to finalize service_description (translation, etc.). # Why do we use discovered_service.description here? long_infotexts.append(u"%s: %s: %s" % (title, discovered_service.check_plugin_name, discovered_service.description)) if affected_check_plugin_names: info = ", ".join( ["%s:%d" % e for e in affected_check_plugin_names.items()]) st = params.get(params_key, default_state) status = worst_service_state(status, st, default=0) infotexts.append(u"%d %s services (%s)%s" % ( sum(affected_check_plugin_names.values()), title, info, state_markers[st], )) if (unfiltered and ((transition == "new" and discovery_mode in (DiscoveryMode.NEW, DiscoveryMode.FIXALL, DiscoveryMode.REFRESH)) or (transition == "vanished" and discovery_mode in (DiscoveryMode.REMOVE, DiscoveryMode.FIXALL, DiscoveryMode.REFRESH)))): need_rediscovery = True else: infotexts.append(u"no %s services found" % title) for (discovered_service, _found_on_nodes) in services_by_transition.get("ignored", []): long_infotexts.append(u"ignored: %s: %s" % (discovered_service.check_plugin_name, discovered_service.description)) return ActiveCheckResult(status, infotexts, long_infotexts, []), need_rediscovery
def do_check( hostname: HostName, ipaddress: Optional[HostAddress], *, # The following arguments *must* remain optional for Nagios and the `DiscoCheckExecutor`. # See Also: `cmk.base.discovery.check_discovery()` fetcher_messages: Sequence[FetcherMessage] = (), run_plugin_names: Container[CheckPluginName] = EVERYTHING, selected_sections: SectionNameCollection = NO_SELECTION, dry_run: bool = False, show_perfdata: bool = False, ) -> Tuple[int, List[ServiceDetails], List[ServiceAdditionalDetails], List[str]]: console.vverbose("Checkmk version %s\n", cmk_version.__version__) config_cache = config.get_config_cache() host_config = config_cache.get_host_config(hostname) exit_spec = host_config.exit_code_spec() mode = Mode.CHECKING if selected_sections is NO_SELECTION else Mode.FORCE_SECTIONS status: ServiceState = 0 infotexts: List[ServiceDetails] = [] long_infotexts: List[ServiceAdditionalDetails] = [] perfdata: List[str] = [] try: license_usage.try_history_update() # In case of keepalive we always have an ipaddress (can be 0.0.0.0 or :: when # address is unknown). When called as non keepalive ipaddress may be None or # is already an address (2nd argument) if ipaddress is None and not host_config.is_cluster: ipaddress = config.lookup_ip_address(host_config) services_to_check = _get_services_to_check( config_cache=config_cache, host_name=hostname, run_plugin_names=run_plugin_names, ) with CPUTracker() as tracker: broker, source_results = make_broker( config_cache=config_cache, host_config=host_config, ip_address=ipaddress, mode=mode, selected_sections=selected_sections, file_cache_max_age=host_config.max_cachefile_age, fetcher_messages=fetcher_messages, force_snmp_cache_refresh=False, on_scan_error="raise", ) num_success, plugins_missing_data = _do_all_checks_on_host( config_cache, host_config, ipaddress, parsed_sections_broker=broker, services=services_to_check, dry_run=dry_run, show_perfdata=show_perfdata, ) if run_plugin_names is EVERYTHING: inventory.do_inventory_actions_during_checking_for( config_cache, host_config, ipaddress, parsed_sections_broker=broker, ) for source, host_sections in source_results: source_state, source_output = source.summarize(host_sections) if source_output != "": status = worst_service_state(status, source_state, default=3) infotexts.append("[%s] %s" % (source.id, source_output)) if plugins_missing_data: missing_data_status, missing_data_infotext = _check_plugins_missing_data( plugins_missing_data, exit_spec, bool(num_success), ) status = max(status, missing_data_status) infotexts.append(missing_data_infotext) total_times = tracker.duration for msg in fetcher_messages: total_times += msg.stats.duration infotexts.append("execution time %.1f sec" % total_times.process.elapsed) if config.check_mk_perfdata_with_times: perfdata += [ "execution_time=%.3f" % total_times.process.elapsed, "user_time=%.3f" % total_times.process.user, "system_time=%.3f" % total_times.process.system, "children_user_time=%.3f" % total_times.process.children_user, "children_system_time=%.3f" % total_times.process.children_system, ] summary: DefaultDict[str, Snapshot] = defaultdict(Snapshot.null) for msg in fetcher_messages if fetcher_messages else (): if msg.fetcher_type in ( FetcherType.PIGGYBACK, FetcherType.PROGRAM, FetcherType.SNMP, FetcherType.TCP, ): summary[{ FetcherType.PIGGYBACK: "agent", FetcherType.PROGRAM: "ds", FetcherType.SNMP: "snmp", FetcherType.TCP: "agent", }[msg.fetcher_type]] += msg.stats.duration for phase, duration in summary.items(): perfdata.append("cmk_time_%s=%.3f" % (phase, duration.idle)) else: perfdata.append("execution_time=%.3f" % total_times.process.elapsed) return status, infotexts, long_infotexts, perfdata finally: _submit_to_core.finalize()
def test_worst_service_state_unknown(): assert worst_service_state(0, 1, 3, default=0) == 3
def test_worst_service_state_empty(): assert worst_service_state(default=0) == 0 assert worst_service_state(default=1) == 1 assert worst_service_state(default=2) == 2 assert worst_service_state(default=3) == 3
def test_worst_service_state_crit(): assert worst_service_state(0, 1, 2, 3, default=0) == 2
def test_worst_service_state_warn(): assert worst_service_state(0, 1, default=0) == 1
def test_worst_service_state_ok(): assert worst_service_state(0, 0, default=0) == 0
def do_inv_check(hostname: HostName, options: Dict[str, int]) -> ActiveCheckResult: _inv_hw_changes = options.get("hw-changes", 0) _inv_sw_changes = options.get("sw-changes", 0) _inv_sw_missing = options.get("sw-missing", 0) _inv_fail_status = options.get("inv-fail-status", 1) host_config = config.HostConfig.make_host_config(hostname) inv_result = _do_active_inventory_for( host_config=host_config, selected_sections=NO_SELECTION, run_plugin_names=EVERYTHING, ) trees = inv_result.trees status = 0 infotexts: List[str] = [] long_infotexts: List[str] = [] if inv_result.safe_to_write: old_tree = _save_inventory_tree(hostname, trees.inventory) else: old_tree, sources_state = None, 1 status = worst_service_state(status, sources_state, default=3) infotexts.append("Cannot update tree%s" % state_markers[sources_state]) _run_inventory_export_hooks(host_config, trees.inventory) if trees.inventory.is_empty() and trees.status_data.is_empty(): infotexts.append("Found no data") else: infotexts.append("Found %d inventory entries" % trees.inventory.count_entries()) # Node 'software' is always there because _do_inv_for creates this node for cluster info if not trees.inventory.get_sub_container(['software']).has_edge('packages')\ and _inv_sw_missing: infotexts.append("software packages information is missing" + state_markers[_inv_sw_missing]) status = max(status, _inv_sw_missing) if old_tree is not None: if not old_tree.is_equal(trees.inventory, edges=["software"]): infotext = "software changes" if _inv_sw_changes: status = max(status, _inv_sw_changes) infotext += state_markers[_inv_sw_changes] infotexts.append(infotext) if not old_tree.is_equal(trees.inventory, edges=["hardware"]): infotext = "hardware changes" if _inv_hw_changes: status = max(status, _inv_hw_changes) infotext += state_markers[_inv_hw_changes] infotexts.append(infotext) if not trees.status_data.is_empty(): infotexts.append("Found %s status entries" % trees.status_data.count_entries()) for source, host_sections in inv_result.source_results: source_state, source_output = source.summarize(host_sections, mode=Mode.INVENTORY) if source_state != 0: # Do not output informational things (state == 0). Also do not use source states # which would overwrite "State when inventory fails" in the ruleset # "Do hardware/software Inventory". # These information and source states are handled by the "Check_MK" service status = max(_inv_fail_status, status) infotexts.append("[%s] %s" % (source.id, source_output)) return status, infotexts, long_infotexts, []
def _check_service_lists( host_name: HostName, services_by_transition: ServicesByTransition, params: config.DiscoveryCheckParameters, ) -> _DiscoverySubresult: status = 0 infotexts = [] long_infotexts = [] perfdata: List[Tuple] = [] need_rediscovery = False service_filters = _ServiceFilters.from_settings( _get_rediscovery_parameters(params)) rediscovery_mode = _get_rediscovery_mode(params) for transition, title, params_key, default_state, service_filter in [ ("new", "unmonitored", "severity_unmonitored", config.inventory_check_severity, service_filters.new), ("vanished", "vanished", "severity_vanished", 0, service_filters.vanished), ]: affected_check_plugin_names: Counter[CheckPluginName] = Counter() unfiltered = False for (discovered_service, _found_on_nodes) in services_by_transition.get(transition, []): affected_check_plugin_names[ discovered_service.check_plugin_name] += 1 if not unfiltered and service_filter(host_name, discovered_service): unfiltered = True #TODO In service_filter:we use config.service_description(...) # in order to finalize service_description (translation, etc.). # Why do we use discovered_service.description here? long_infotexts.append(u"%s: %s: %s" % (title, discovered_service.check_plugin_name, discovered_service.description)) if affected_check_plugin_names: info = ", ".join( ["%s:%d" % e for e in affected_check_plugin_names.items()]) st = params.get(params_key, default_state) status = worst_service_state(status, st, default=0) infotexts.append(u"%d %s services (%s)%s" % ( sum(affected_check_plugin_names.values()), title, info, state_markers[st], )) if (unfiltered and ((transition == "new" and rediscovery_mode in ("new", "fixall", "refresh")) or (transition == "vanished" and rediscovery_mode in ("remove", "fixall", "refresh")))): need_rediscovery = True else: infotexts.append(u"no %s services found" % title) for (discovered_service, _found_on_nodes) in services_by_transition.get("ignored", []): long_infotexts.append(u"ignored: %s: %s" % (discovered_service.check_plugin_name, discovered_service.description)) return status, infotexts, long_infotexts, perfdata, need_rediscovery