def wrapped_check_func(hostname: HostName, *args: Any, **kwargs: Any) -> int: host_config = config.get_config_cache().get_host_config(hostname) exit_spec = host_config.exit_code_spec() status, infotexts, long_infotexts, perfdata = 0, [], [], [] try: status, infotexts, long_infotexts, perfdata = check_func( hostname, *args, **kwargs) except MKTimeout: if _in_keepalive_mode(): raise infotexts.append("Timed out") status = max(status, exit_spec.get("timeout", 2)) except (MKAgentError, MKFetcherError, MKSNMPError, MKIPAddressLookupError) as e: infotexts.append("%s" % e) status = exit_spec.get("connection", 2) except MKGeneralException as e: infotexts.append("%s" % e) status = max(status, exit_spec.get("exception", 3)) except Exception: if cmk.utils.debug.enabled(): raise crash_output = cmk.base.crash_reporting.create_check_crash_dump( host_name=hostname, service_name=description, plugin_name=check_plugin_name, plugin_kwargs={}, is_manual=False, ) infotexts.append( crash_output.replace("Crash dump:\n", "Crash dump:\\n")) status = max(status, exit_spec.get("exception", 3)) # Produce the service check result output output_txt = ", ".join(infotexts) if perfdata: output_txt += " | %s" % " ".join(perfdata) if long_infotexts: output_txt = "%s\n%s" % (output_txt, "\n".join(long_infotexts)) output_txt += "\n" if _in_keepalive_mode(): if not cmk_version.is_raw_edition(): import cmk.base.cee.keepalive as keepalive # pylint: disable=no-name-in-module else: keepalive = None # type: ignore[assignment] keepalive.add_active_check_result(hostname, output_txt) console.verbose(ensure_str(output_txt)) else: out.output(ensure_str(output_txt)) return status
def _get_filepaths(self): # type: () -> List[Path] out.output("Collect diagnostics information:\n") filepaths = [] for element in self.elements: filepath = element.add_or_get_file(self.tmp_dump_folder) if filepath is None: console.verbose(" %s: No informations\n" % element.ident) continue out.output(" %s\n" % element.description) filepaths.append(filepath) return filepaths
def do_create_config(core, with_agents): # type: (MonitoringCore, bool) -> None out.output("Generating configuration for core (type %s)..." % config.monitoring_core) create_core_config(core) out.output(tty.ok + "\n") if with_agents: try: import cmk.base.cee.agent_bakery # pylint: disable=redefined-outer-name,import-outside-toplevel cmk.base.cee.agent_bakery.bake_on_restart() except ImportError: pass
def wrapped_check_func(hostname, *args, **kwargs): # type: (HostName, Any, Any) -> int host_config = config.get_config_cache().get_host_config(hostname) exit_spec = host_config.exit_code_spec() status, infotexts, long_infotexts, perfdata = 0, [], [], [] try: status, infotexts, long_infotexts, perfdata = check_func( hostname, *args, **kwargs) except MKTimeout: if _in_keepalive_mode(): raise infotexts.append("Timed out") status = max(status, cast(int, exit_spec.get("timeout", 2))) except (MKAgentError, MKSNMPError, MKIPAddressLookupError) as e: infotexts.append("%s" % e) status = cast(int, exit_spec.get("connection", 2)) except MKGeneralException as e: infotexts.append("%s" % e) status = max(status, cast(int, exit_spec.get("exception", 3))) except Exception: if cmk.utils.debug.enabled(): raise crash_output = cmk.base.crash_reporting.create_check_crash_dump( hostname, check_plugin_name, None, False, None, description, []) infotexts.append( crash_output.replace("Crash dump:\n", "Crash dump:\\n")) status = max(status, cast(int, exit_spec.get("exception", 3))) # Produce the service check result output output_txt = "%s - %s" % (defines.short_service_state_name(status), ", ".join(infotexts)) if perfdata: output_txt += " | %s" % " ".join(perfdata) if long_infotexts: output_txt = "%s\n%s" % (output_txt, "\n".join(long_infotexts)) output_txt += "\n" if _in_keepalive_mode(): keepalive.add_keepalive_active_check_result( hostname, output_txt) console.verbose(six.ensure_str(output_txt)) else: out.output(six.ensure_str(output_txt)) return status
def do_check_nagiosconfig() -> bool: """Execute nagios config verification to ensure the created check_mk_objects.cfg is valid""" command = [ cmk.utils.paths.nagios_binary, "-vp", cmk.utils.paths.nagios_config_file ] console.verbose("Running '%s'\n" % subprocess.list2cmdline(command)) out.output("Validating Nagios configuration...") p = subprocess.Popen( # pylint:disable=consider-using-with command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=True, encoding="utf-8", ) stdout = p.communicate()[0] exit_status = p.returncode if not exit_status: out.output(tty.ok + "\n") return True out.output("ERROR:\n") out.output(stdout, stream=sys.stderr) return False
def do_check_nagiosconfig(): # type: () -> bool command = [ cmk.utils.paths.nagios_binary, "-vp", cmk.utils.paths.nagios_config_file ] console.verbose("Running '%s'\n" % subprocess.list2cmdline(command)) out.output("Validating Nagios configuration...") p = subprocess.Popen( command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True, encoding="utf-8", ) stdout, stderr = p.communicate() exit_status = p.returncode if not exit_status: out.output(tty.ok + "\n") return True out.output("ERROR:\n") out.output(stdout, stderr) return False
def do_create_config(core: MonitoringCore) -> None: """Creating the monitoring core configuration and additional files Ensures that everything needed by the monitoring core and it's helper processes is up-to-date and available for starting the monitoring. """ out.output("Generating configuration for core (type %s)..." % core.name()) try: _create_core_config(core) out.output(tty.ok + "\n") except Exception as e: if cmk.utils.debug.enabled(): raise raise MKGeneralException("Error creating configuration: %s" % e) _bake_on_restart()
def wrapped_check_func(hostname: HostName, *args: Any, **kwargs: Any) -> int: host_config = config.get_config_cache().get_host_config(hostname) exit_spec = host_config.exit_code_spec() try: status, output_text = _combine_texts( check_func(hostname, *args, **kwargs)) except MKTimeout: if _in_keepalive_mode(): raise status = exit_spec.get("timeout", 2) output_text = "Timed out\n" except (MKAgentError, MKFetcherError, MKSNMPError, MKIPAddressLookupError) as e: status = exit_spec.get("connection", 2) output_text = f"{e}\n" except MKGeneralException as e: status = exit_spec.get("exception", 3) output_text = f"{e}\n" except Exception: if cmk.utils.debug.enabled(): raise status = exit_spec.get("exception", 3) output_text = cmk.base.crash_reporting.create_check_crash_dump( host_name=hostname, service_name=description, plugin_name=check_plugin_name, plugin_kwargs={}, is_manual=False, ).replace("Crash dump:\n", "Crash dump:\\n") if _in_keepalive_mode(): import cmk.base.cee.keepalive as keepalive # pylint: disable=no-name-in-module keepalive.add_active_check_result(hostname, output_text) console.verbose(output_text) else: out.output(output_text) return status
def execute(self, cmd: str, args: List[str]) -> Any: self._handle_generic_arguments(args) try: try: automation = self._automations[cmd] except KeyError: raise MKAutomationError("Automation command '%s' is not implemented." % cmd) if automation.needs_checks: with redirect_stdout(open(os.devnull, "w")): log.setup_console_logging() config.load_all_agent_based_plugins( check_api.get_check_api_context, inventory_plugins.load_legacy_inventory_plugins, ) if automation.needs_config: config.load(validate_hosts=False) result = automation.execute(args) except (MKAutomationError, MKTimeout) as e: console.error("%s\n" % e) if cmk.utils.debug.enabled(): raise return 1 except Exception as e: if cmk.utils.debug.enabled(): raise console.error("%s\n" % e) return 2 finally: profiling.output_profile() out.output(result.serialize()) out.output("\n") return 0
def do_create_config(core: MonitoringCore, hosts_to_update: HostsToUpdate = None) -> None: """Creating the monitoring core configuration and additional files Ensures that everything needed by the monitoring core and it's helper processes is up-to-date and available for starting the monitoring. """ out.output("Generating configuration for core (type %s)...\n" % core.name()) if hosts_to_update is not None: out.output( "Reuse old configuration, create new configuration for %s and dependant hosts\n" % ", ".join(hosts_to_update) ) try: _create_core_config(core, hosts_to_update=hosts_to_update) except Exception as e: if cmk.utils.debug.enabled(): raise raise MKGeneralException("Error creating configuration: %s" % e) _bake_on_restart()
def do_core_action(action: CoreAction, quiet: bool = False) -> None: if not quiet: out.output("%sing monitoring core..." % action.value.title()) if config.monitoring_core == "nagios": os.putenv("CORE_NOVERIFY", "yes") command = ["%s/etc/init.d/core" % cmk.utils.paths.omd_root, action.value] else: command = ["omd", action.value, "cmc"] completed_process = subprocess.run( command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=True, check=False, ) if completed_process.returncode != 0: if not quiet: out.output("ERROR: %r\n" % completed_process.stdout) raise MKGeneralException( "Cannot %s the monitoring core: %r" % (action.value, completed_process.stdout) ) if not quiet: out.output(tty.ok + "\n")
def do_core_action(action: CoreAction, quiet: bool = False) -> None: if not quiet: out.output("%sing monitoring core..." % action.value.title()) if config.monitoring_core == "nagios": os.putenv("CORE_NOVERIFY", "yes") command = [ "%s/etc/init.d/core" % cmk.utils.paths.omd_root, action.value ] else: command = ["omd", action.value, "cmc"] p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=True) result = p.wait() if result != 0: assert p.stdout is not None output = p.stdout.read() if not quiet: out.output("ERROR: %r\n" % output) raise MKGeneralException("Cannot %s the monitoring core: %r" % (action.value, output)) if not quiet: out.output(tty.ok + "\n")
def output_profile() -> None: if not _profile: return _profile.dump_stats(str(_profile_path)) show_profile = _profile_path.with_name("show_profile.py") with show_profile.open("w") as f: f.write("""#!/usr/bin/env python3 import sys import pstats try: profile_file = sys.argv[1] except IndexError: profile_file = "%s" stats = pstats.Stats(profile_file) stats.sort_stats('time').print_stats()""" % _profile_path) show_profile.chmod(0o755) out.output("Profile '%s' written. Please run %s.\n" % (_profile_path, show_profile), stream=sys.stderr)
def execute(self, cmd: str, args: List[str]) -> Any: self._handle_generic_arguments(args) try: try: automation = self._automations[cmd] except KeyError: raise MKAutomationError( "Automation command '%s' is not implemented." % cmd) if automation.needs_checks: config.load_all_agent_based_plugins( check_api.get_check_api_context) if automation.needs_config: config.load(validate_hosts=False) result = automation.execute(args) except (MKAutomationError, MKTimeout) as e: console.error("%s\n" % e) if cmk.utils.debug.enabled(): raise return 1 except Exception as e: if cmk.utils.debug.enabled(): raise console.error("%s\n" % e) return 2 finally: profiling.output_profile() out.output(python_printer.pformat(result)) out.output('\n') return 0
def do_create_config(core: MonitoringCore) -> None: """Creating the monitoring core configuration and additional files Ensures that everything needed by the monitoring core and it's helper processes is up-to-date and available for starting the monitoring. """ with _backup_objects_file(core): out.output("Generating configuration for core (type %s)..." % config.monitoring_core) try: _create_core_config(core) out.output(tty.ok + "\n") except Exception as e: if cmk.utils.debug.enabled(): raise raise MKGeneralException("Error creating configuration: %s" % e) core.precompile() try: import cmk.base.cee.bakery.agent_bakery # pylint: disable=redefined-outer-name,import-outside-toplevel cmk.base.cee.bakery.agent_bakery.bake_on_restart() except ImportError: pass
def do_check_nagiosconfig() -> bool: """Execute nagios config verification to ensure the created check_mk_objects.cfg is valid""" command = [ cmk.utils.paths.nagios_binary, "-vp", cmk.utils.paths.nagios_config_file ] console.verbose("Running '%s'\n" % subprocess.list2cmdline(command)) out.output("Validating Nagios configuration...") completed_process = subprocess.run( command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=True, encoding="utf-8", check=False, ) if not completed_process.returncode: out.output(tty.ok + "\n") return True out.output("ERROR:\n") out.output(completed_process.stdout, stream=sys.stderr) return False
def test_output_with_args(stream): out.output("hello %s %i", "bob", 42, stream=stream) assert read(stream) == "hello bob 42"
def test_output_without_args(stream): out.output("hello", stream=stream) assert read(stream) == "hello"
def dot(color, dot='o'): # type: (str, str) -> None if not silent: out.output(tty.bold + color + dot + tty.normal)
def dump_host(hostname: HostName) -> None: config_cache = config.get_config_cache() host_config = config_cache.get_host_config(hostname) out.output("\n") if host_config.is_cluster: nodes = host_config.nodes if nodes is None: raise RuntimeError() color = tty.bgmagenta add_txt = " (cluster of " + (", ".join(nodes)) + ")" else: color = tty.bgblue add_txt = "" out.output("%s%s%s%-78s %s\n" % (color, tty.bold, tty.white, hostname + add_txt, tty.normal)) ipaddress = _ip_address_for_dump_host( host_config, family=host_config.default_address_family) addresses: Optional[str] = "" if not host_config.is_ipv4v6_host: addresses = ipaddress else: try: secondary = _ip_address_for_dump_host( host_config, family=socket.AF_INET if host_config.is_ipv6_primary else socket.AF_INET6, ) except Exception: secondary = "X.X.X.X" addresses = "%s, %s" % (ipaddress, secondary) if host_config.is_ipv6_primary: addresses += " (Primary: IPv6)" else: addresses += " (Primary: IPv4)" out.output(tty.yellow + "Addresses: " + tty.normal + (addresses if addresses is not None else "No IP") + "\n") tag_template = tty.bold + "[" + tty.normal + "%s" + tty.bold + "]" + tty.normal tags = [(tag_template % ":".join(t)) for t in sorted(host_config.tag_groups.items())] out.output(tty.yellow + "Tags: " + tty.normal + ", ".join(tags) + "\n") labels = [ tag_template % ":".join(l) for l in sorted(host_config.labels.items()) ] out.output(tty.yellow + "Labels: " + tty.normal + ", ".join(labels) + "\n") # TODO: Clean this up once cluster parent handling has been moved to HostConfig if host_config.is_cluster: parents_list = host_config.nodes if parents_list is None: raise RuntimeError() else: parents_list = host_config.parents if len(parents_list) > 0: out.output(tty.yellow + "Parents: " + tty.normal + ", ".join(parents_list) + "\n") out.output(tty.yellow + "Host groups: " + tty.normal + ", ".join(host_config.hostgroups) + "\n") out.output(tty.yellow + "Contact groups: " + tty.normal + ", ".join(host_config.contactgroups) + "\n") agenttypes = [ source.description for source in sources.make_sources(host_config, ipaddress) ] if host_config.is_ping_host: agenttypes.append("PING only") out.output(tty.yellow + "Agent mode: " + tty.normal) out.output(host_config.agent_description + "\n") out.output(tty.yellow + "Type of agent: " + tty.normal) if len(agenttypes) == 1: out.output(agenttypes[0] + "\n") else: out.output("\n ") out.output("\n ".join(agenttypes) + "\n") out.output(tty.yellow + "Services:" + tty.normal + "\n") headers = ["checktype", "item", "params", "description", "groups"] colors = [tty.normal, tty.blue, tty.normal, tty.green, tty.normal] table_data = [] for service in sorted(check_table.get_check_table(hostname).values(), key=lambda s: s.description): table_data.append([ str(service.check_plugin_name), str(service.item), _evaluate_params(service.parameters), service.description, ",".join( config_cache.servicegroups_of_service(hostname, service.description)), ]) tty.print_table(headers, colors, table_data, " ")
def dot(color: str, dot: str = 'o') -> None: if not silent: out.output(tty.bold + color + dot + tty.normal)
def do_scan_parents(hosts: List[HostName]) -> None: config_cache = config.get_config_cache() if not hosts: hosts = list(sorted(config_cache.all_active_realhosts())) parent_hosts = [] parent_ips: Dict[HostName, HostAddress] = {} parent_rules = [] gateway_hosts: Set[HostName] = set() if config.max_num_processes < 1: config.max_num_processes = 1 outfilename = cmk.utils.paths.check_mk_config_dir + "/parents.mk" if not traceroute_available(): raise MKGeneralException('The program "traceroute" was not found.\n' 'The parent scan needs this program.\n' 'Please install it and try again.') if os.path.exists(outfilename): first_line = open(outfilename, "r").readline() if not first_line.startswith( '# Automatically created by --scan-parents at'): raise MKGeneralException( "conf.d/parents.mk seems to be created manually.\n\n" "The --scan-parents function would overwrite this file.\n" "Please rename it to keep the configuration or delete " "the file and try again.") out.output("Scanning for parents (%d processes)..." % config.max_num_processes) while hosts: chunk: List[HostName] = [] while len(chunk) < config.max_num_processes and len(hosts) > 0: host = hosts.pop() host_config = config_cache.get_host_config(host) # skip hosts that already have a parent if host_config.parents: console.verbose("(manual parent) ") continue chunk.append(host) gws = scan_parents_of(config_cache, chunk) for host, (gw, _unused_state, _unused_ping_fails, _unused_message) in zip(chunk, gws): if gw: gateway, gateway_ip, dns_name = gw if not gateway: # create artificial host if dns_name: gateway = dns_name else: gateway = "gw-%s" % (gateway_ip.replace(".", "-")) if gateway not in gateway_hosts: gateway_hosts.add(gateway) parent_hosts.append("%s|parent|ping" % gateway) parent_ips[gateway] = gateway_ip if config.monitoring_host: parent_rules.append( (config.monitoring_host, [gateway])) # make Nagios a parent of gw parent_rules.append((gateway, [host])) elif host != config.monitoring_host and config.monitoring_host: # make monitoring host the parent of all hosts without real parent parent_rules.append((config.monitoring_host, [host])) with open(outfilename, "w") as file: file.write("# Automatically created by --scan-parents at %s\n\n" % time.asctime()) file.write("# Do not edit this file. If you want to convert an\n") file.write("# artificial gateway host into a permanent one, then\n") file.write("# move its definition into another *.mk file\n") file.write("# Parents which are not listed in your all_hosts:\n") file.write("all_hosts += %s\n\n" % pprint.pformat(parent_hosts)) file.write("# IP addresses of parents not listed in all_hosts:\n") file.write("ipaddresses.update(%s)\n\n" % pprint.pformat(parent_ips)) file.write("# Parent definitions\n") file.write("parents += %s\n\n" % pprint.pformat(parent_rules)) out.output("\nWrote %s\n" % outfilename)
def test_output_with_wrong_args(stream): with pytest.raises(TypeError): out.output("hello %s %i", "wrong", "args", stream=stream)
def test_output_ignores_stream_errors(stream, mocker, monkeypatch): mock = mocker.Mock(side_effect=IOError("bad luck")) monkeypatch.setattr(stream, "flush", mock) out.output("hello", stream=stream) assert read(stream) == "hello"
def create_diagnostics_dump(): # type: () -> None dump = DiagnosticsDump() dump.create() out.output("Created diagnostics dump:\n") out.output(" '%s'\n" % _get_short_filepath(dump.tarfile_path))