예제 #1
0
파일: snmp.py 프로젝트: howie-f/checkmk
    def translate(lines):
        # type: (List[bytes]) -> List[Tuple[bytes, bytes]]
        result_lines = []
        try:
            oids_for_command = []
            for line in lines:
                oids_for_command.append(line.split(" ")[0])

            command = [
                "snmptranslate", "-m", "ALL",
                "-M+%s" % cmk.utils.paths.local_mib_dir
            ] + oids_for_command
            p = subprocess.Popen(command,
                                 stdout=subprocess.PIPE,
                                 stderr=open(os.devnull, "w"),
                                 close_fds=True)
            p.wait()
            if p.stdout is None:
                raise RuntimeError()
            output = p.stdout.read()
            result = output.split("\n")[0::2]
            for idx, line in enumerate(result):
                result_lines.append((line.strip(), lines[idx].strip()))

        except Exception as e:
            console.error("%s\n" % e)

        return result_lines
예제 #2
0
def load_plugins(get_check_api_context, get_inventory_context):
    # type: (config.GetCheckApiContext, config.GetInventoryApiContext) -> None
    loaded_files = set()  # type: Set[str]
    filelist = config.get_plugin_paths(
        str(cmk.utils.paths.local_inventory_dir),
        cmk.utils.paths.inventory_dir)

    for f in filelist:
        if f[0] == "." or f[-1] == "~":
            continue  # ignore editor backup / temp files

        file_name = os.path.basename(f)
        if file_name in loaded_files:
            continue  # skip already loaded files (e.g. from local)

        try:
            plugin_context = _new_inv_context(get_check_api_context,
                                              get_inventory_context)
            known_plugins = inv_info

            _load_plugin_includes(f, plugin_context)

            exec(open(f).read(), plugin_context)
            loaded_files.add(file_name)
        except Exception as e:
            console.error("Error in inventory plugin file %s: %s\n", f, e)
            if cmk.utils.debug.enabled():
                raise
            continue

        # Now store the check context for all plugins found in this file
        for check_plugin_name in set(inv_info).difference(known_plugins):
            _plugin_contexts[check_plugin_name] = plugin_context
예제 #3
0
파일: snmp.py 프로젝트: stefan927/checkmk
def _execute_walks_for_dump(snmp_config, oids):
    for oid in oids:
        try:
            console.verbose("Walk on \"%s\"..." % oid)
            yield walk_for_export(snmp_config, oid)
        except Exception as e:
            console.error("Error: %s\n" % e)
            if cmk.utils.debug.enabled():
                raise
예제 #4
0
def _load_plugin_includes(check_file_path, plugin_context):
    for name in config.includes_of_plugin(check_file_path):
        path = _include_file_path(name)
        try:
            exec(open(path).read(), plugin_context)
        except Exception as e:
            console.error("Error in include file %s: %s\n", path, e)
            if cmk.utils.debug.enabled():
                raise
예제 #5
0
파일: snmp.py 프로젝트: howie-f/checkmk
def _execute_walks_for_dump(snmp_config, oids):
    # type: (SNMPHostConfig, List[OID]) -> Iterable[SNMPRowInfo]
    for oid in oids:
        try:
            console.verbose("Walk on \"%s\"..." % oid)
            yield walk_for_export(snmp_config, oid)
        except Exception as e:
            console.error("Error: %s\n" % e)
            if cmk.utils.debug.enabled():
                raise
예제 #6
0
def do_update(core, with_precompile):
    try:
        do_create_config(core, with_agents=with_precompile)
        if with_precompile:
            core.precompile()

    except Exception as e:
        console.error("Configuration Error: %s\n" % e)
        if cmk.utils.debug.enabled():
            raise
        sys.exit(1)
예제 #7
0
def precompile_hostchecks():
    console.verbose("Creating precompiled host check config...\n")
    config.PackedConfig().save()

    if not os.path.exists(cmk.utils.paths.precompiled_hostchecks_dir):
        os.makedirs(cmk.utils.paths.precompiled_hostchecks_dir)

    config_cache = config.get_config_cache()

    console.verbose("Precompiling host checks...\n")
    for host in config_cache.all_active_hosts():
        try:
            _precompile_hostcheck(config_cache, host)
        except Exception as e:
            if cmk.utils.debug.enabled():
                raise
            console.error("Error precompiling checks for host %s: %s\n" %
                          (host, e))
            sys.exit(5)
예제 #8
0
def gather_snmp_check_plugin_names(host_config,
                                   on_error,
                                   do_snmp_scan,
                                   for_inventory=False,
                                   for_mgmt_board=False):
    check_plugin_names = set()

    try:
        check_plugin_names.update(
            _snmp_scan(host_config,
                       on_error=on_error,
                       do_snmp_scan=do_snmp_scan,
                       for_inv=for_inventory,
                       for_mgmt_board=for_mgmt_board))
    except Exception as e:
        if on_error == "raise":
            raise
        elif on_error == "warn":
            console.error("SNMP scan failed: %s\n" % e)

    return list(check_plugin_names)
예제 #9
0
    def execute(self, cmd, args):
        # type: (str, 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_checks(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()

        if cmk.utils.debug.enabled():
            console.output(pprint.pformat(result) + "\n")
        else:
            console.output("%r\n" % (result, ))

        return 0
예제 #10
0
def gather_snmp_check_plugin_names(host_config,
                                   on_error,
                                   do_snmp_scan,
                                   for_inventory=False,
                                   for_mgmt_board=False):
    # type: (SNMPHostConfig, str, bool, bool, bool) -> Set[CheckPluginName]
    check_plugin_names = set()  # type: Set[CheckPluginName]

    try:
        check_plugin_names.update(
            _snmp_scan(host_config,
                       on_error=on_error,
                       do_snmp_scan=do_snmp_scan,
                       for_inv=for_inventory,
                       for_mgmt_board=for_mgmt_board))
    except Exception as e:
        if on_error == "raise":
            raise
        if on_error == "warn":
            console.error("SNMP scan failed: %s\n" % e)

    return check_plugin_names
예제 #11
0
def do_snmptranslate(walk_filename):
    # type: (str) -> None
    if not walk_filename:
        raise MKGeneralException("Please provide the name of a SNMP walk file")

    walk_path = "%s/%s" % (cmk.utils.paths.snmpwalks_dir, walk_filename)
    if not os.path.exists(walk_path):
        raise MKGeneralException("The walk '%s' does not exist" % walk_path)

    def translate(lines):
        # type: (List[bytes]) -> List[Tuple[bytes, bytes]]
        result_lines = []
        try:
            oids_for_command = []
            for line in lines:
                oids_for_command.append(line.split(b" ")[0])

            command = [
                b"snmptranslate", b"-m", b"ALL",
                b"-M+%s" % cmk.utils.paths.local_mib_dir
            ] + oids_for_command
            p = subprocess.Popen(command,
                                 stdout=subprocess.PIPE,
                                 stderr=open(os.devnull, "w"),
                                 close_fds=True)
            p.wait()
            if p.stdout is None:
                raise RuntimeError()
            output = p.stdout.read()
            result = output.split(b"\n")[0::2]
            for idx, line in enumerate(result):
                result_lines.append((line.strip(), lines[idx].strip()))

        except Exception as e:
            console.error("%s\n" % e)

        return result_lines

    # Translate n-oid's per cycle
    entries_per_cycle = 500
    translated_lines = []  # type: List[Tuple[bytes, bytes]]

    walk_lines = open(walk_path).readlines()
    console.error("Processing %d lines.\n" % len(walk_lines))

    i = 0
    while i < len(walk_lines):
        console.error("\r%d to go...    " % (len(walk_lines) - i))
        process_lines = walk_lines[i:i + entries_per_cycle]
        # FIXME: This encoding ping-pong os horrible...
        translated = translate([six.ensure_binary(pl) for pl in process_lines])
        i += len(translated)
        translated_lines += translated
    console.error("\rfinished.                \n")

    # Output formatted
    for translation, line in translated_lines:
        console.output("%s --> %s\n" %
                       (six.ensure_str(line), six.ensure_str(translation)))
예제 #12
0
def do_snmpwalk(options, hostnames):
    # type: (SNMPWalkOptions, List[HostName]) -> None
    if "oids" in options and "extraoids" in options:
        raise MKGeneralException("You cannot specify --oid and --extraoid at the same time.")

    if not hostnames:
        raise MKBailOut("Please specify host names to walk on.")

    if not os.path.exists(cmk.utils.paths.snmpwalks_dir):
        os.makedirs(cmk.utils.paths.snmpwalks_dir)

    for hostname in hostnames:
        #TODO: What about SNMP management boards?
        snmp_config = create_snmp_host_config(hostname)

        try:
            _do_snmpwalk_on(snmp_config, options, cmk.utils.paths.snmpwalks_dir + "/" + hostname)
        except Exception as e:
            console.error("Error walking %s: %s\n" % (hostname, e))
            if cmk.utils.debug.enabled():
                raise
        cmk.base.cleanup.cleanup_globals()
예제 #13
0
파일: snmp.py 프로젝트: stefan927/checkmk
def do_snmptranslate(walk_filename):
    if not walk_filename:
        raise MKGeneralException("Please provide the name of a SNMP walk file")

    walk_path = "%s/%s" % (cmk.utils.paths.snmpwalks_dir, walk_filename)
    if not os.path.exists(walk_path):
        raise MKGeneralException("The walk '%s' does not exist" % walk_path)

    def translate(lines):
        result_lines = []
        try:
            oids_for_command = []
            for line in lines:
                oids_for_command.append(line.split(" ")[0])

            command = [
                "snmptranslate", "-m", "ALL",
                "-M+%s" % cmk.utils.paths.local_mib_dir
            ] + oids_for_command
            p = subprocess.Popen(command,
                                 stdout=subprocess.PIPE,
                                 stderr=open(os.devnull, "w"),
                                 close_fds=True)
            p.wait()
            output = p.stdout.read()
            result = output.split("\n")[0::2]
            for idx, line in enumerate(result):
                result_lines.append((line.strip(), lines[idx].strip()))

        except Exception as e:
            console.error("%s\n" % e)

        return result_lines

    # Translate n-oid's per cycle
    entries_per_cycle = 500
    translated_lines = []

    walk_lines = open(walk_path).readlines()
    console.error("Processing %d lines.\n" % len(walk_lines))

    i = 0
    while i < len(walk_lines):
        console.error("\r%d to go...    " % (len(walk_lines) - i))
        process_lines = walk_lines[i:i + entries_per_cycle]
        translated = translate(process_lines)
        i += len(translated)
        translated_lines += translated
    console.error("\rfinished.                \n")

    # Output formatted
    for translation, line in translated_lines:
        console.output("%s --> %s\n" % (line, translation))
예제 #14
0
def do_restart(core, only_reload=False):
    # type: (MonitoringCore, bool) -> None
    try:
        backup_path = None

        if try_get_activation_lock():
            # TODO: Replace by MKBailOut()/MKTerminate()?
            console.error("Other restart currently in progress. Aborting.\n")
            sys.exit(1)

        # Save current configuration
        if os.path.exists(cmk.utils.paths.nagios_objects_file):
            backup_path = cmk.utils.paths.nagios_objects_file + ".save"
            console.verbose("Renaming %s to %s\n",
                            cmk.utils.paths.nagios_objects_file,
                            backup_path,
                            stream=sys.stderr)
            os.rename(cmk.utils.paths.nagios_objects_file, backup_path)
        else:
            backup_path = None

        try:
            core_config.do_create_config(core, with_agents=True)
        except Exception as e:
            # TODO: Replace by MKBailOut()/MKTerminate()?
            console.error("Error creating configuration: %s\n" % e)
            if backup_path:
                os.rename(backup_path, cmk.utils.paths.nagios_objects_file)
            if cmk.utils.debug.enabled():
                raise
            sys.exit(1)

        if config.monitoring_core == "cmc" or cmk.base.nagios_utils.do_check_nagiosconfig(
        ):
            if backup_path:
                os.remove(backup_path)

            core.precompile()

            do_core_action(only_reload and "reload" or "restart")
        else:
            # TODO: Replace by MKBailOut()/MKTerminate()?
            console.error(
                "Configuration for monitoring core is invalid. Rolling back.\n"
            )

            broken_config_path = "%s/check_mk_objects.cfg.broken" % cmk.utils.paths.tmp_dir
            open(broken_config_path,
                 "w").write(open(cmk.utils.paths.nagios_objects_file).read())
            console.error(
                "The broken file has been copied to \"%s\" for analysis.\n" %
                broken_config_path)

            if backup_path:
                os.rename(backup_path, cmk.utils.paths.nagios_objects_file)
            else:
                os.remove(cmk.utils.paths.nagios_objects_file)
            sys.exit(1)

    except Exception as e:
        if backup_path:
            try:
                os.remove(backup_path)
            except OSError as oe:
                if oe.errno != errno.ENOENT:
                    raise
        if cmk.utils.debug.enabled():
            raise
        # TODO: Replace by MKBailOut()/MKTerminate()?
        console.error("An error occurred: %s\n" % e)
        sys.exit(1)
예제 #15
0
def scan_parents_of(config_cache, hosts, silent=False, settings=None):
    if settings is None:
        settings = {}

    if config.monitoring_host:
        nagios_ip = ip_lookup.lookup_ipv4_address(config.monitoring_host)
    else:
        nagios_ip = None

    os.putenv("LANG", "")
    os.putenv("LC_ALL", "")

    # Start processes in parallel
    procs = []
    for host in hosts:
        console.verbose("%s " % host)
        try:
            ip = ip_lookup.lookup_ipv4_address(host)
            command = [
                "traceroute", "-w",
                "%d" % settings.get("timeout", 8), "-q",
                "%d" % settings.get("probes", 2), "-m",
                "%d" % settings.get("max_ttl", 10), "-n", ip
            ]
            console.vverbose("Running '%s'\n" %
                             subprocess.list2cmdline(command))

            procs.append((host, ip,
                          subprocess.Popen(command,
                                           stdout=subprocess.PIPE,
                                           stderr=subprocess.STDOUT,
                                           close_fds=True)))
        except Exception as e:
            if cmk.utils.debug.enabled():
                raise
            procs.append((host, None, "ERROR: %s" % e))

    # Output marks with status of each single scan
    def dot(color, dot='o'):
        if not silent:
            console.output(tty.bold + color + dot + tty.normal)

    # Now all run and we begin to read the answers. For each host
    # we add a triple to gateways: the gateway, a scan state  and a diagnostic output
    gateways = []
    for host, ip, proc_or_error in procs:
        if isinstance(proc_or_error, six.string_types):
            lines = [proc_or_error]
            exitstatus = 1
        else:
            exitstatus = proc_or_error.wait()
            lines = [l.strip() for l in proc_or_error.stdout.readlines()]

        if exitstatus:
            dot(tty.red, '*')
            gateways.append(
                (None, "failed", 0,
                 "Traceroute failed with exit code %d" % (exitstatus & 255)))
            continue

        if len(lines) == 1 and lines[0].startswith("ERROR:"):
            message = lines[0][6:].strip()
            console.verbose("%s: %s\n", host, message, stream=sys.stderr)
            dot(tty.red, "D")
            gateways.append((None, "dnserror", 0, message))
            continue

        elif len(lines) == 0:
            if cmk.utils.debug.enabled():
                raise MKGeneralException(
                    "Cannot execute %s. Is traceroute installed? Are you root?"
                    % command)
            else:
                dot(tty.red, '!')
            continue

        elif len(lines) < 2:
            if not silent:
                console.error("%s: %s\n" % (host, ' '.join(lines)))
            gateways.append((None, "garbled", 0,
                             "The output of traceroute seem truncated:\n%s" %
                             ("".join(lines))))
            dot(tty.blue)
            continue

        # Parse output of traceroute:
        # traceroute to 8.8.8.8 (8.8.8.8), 30 hops max, 40 byte packets
        #  1  * * *
        #  2  10.0.0.254  0.417 ms  0.459 ms  0.670 ms
        #  3  172.16.0.254  0.967 ms  1.031 ms  1.544 ms
        #  4  217.0.116.201  23.118 ms  25.153 ms  26.959 ms
        #  5  217.0.76.134  32.103 ms  32.491 ms  32.337 ms
        #  6  217.239.41.106  32.856 ms  35.279 ms  36.170 ms
        #  7  74.125.50.149  45.068 ms  44.991 ms *
        #  8  * 66.249.94.86  41.052 ms 66.249.94.88  40.795 ms
        #  9  209.85.248.59  43.739 ms  41.106 ms 216.239.46.240  43.208 ms
        # 10  216.239.48.53  45.608 ms  47.121 ms 64.233.174.29  43.126 ms
        # 11  209.85.255.245  49.265 ms  40.470 ms  39.870 ms
        # 12  8.8.8.8  28.339 ms  28.566 ms  28.791 ms
        routes = []
        for line in lines[1:]:
            parts = line.split()
            route = parts[1]
            if route.count('.') == 3:
                routes.append(route)
            elif route == '*':
                routes.append(None)  # No answer from this router
            else:
                if not silent:
                    console.error(
                        "%s: invalid output line from traceroute: '%s'\n" %
                        (host, line))

        if len(routes) == 0:
            error = "incomplete output from traceroute. No routes found."
            console.error("%s: %s\n" % (host, error))
            gateways.append((None, "garbled", 0, error))
            dot(tty.red)
            continue

        # Only one entry -> host is directly reachable and gets nagios as parent -
        # if nagios is not the parent itself. Problem here: How can we determine
        # if the host in question is the monitoring host? The user must configure
        # this in monitoring_host.
        elif len(routes) == 1:
            if ip == nagios_ip:
                gateways.append(
                    (None, "root", 0, ""))  # We are the root-monitoring host
                dot(tty.white, 'N')
            elif config.monitoring_host:
                gateways.append(((config.monitoring_host, nagios_ip, None),
                                 "direct", 0, ""))
                dot(tty.cyan, 'L')
            else:
                gateways.append((None, "direct", 0, ""))
            continue

        # Try far most route which is not identical with host itself
        ping_probes = settings.get("ping_probes", 5)
        skipped_gateways = 0
        route = None
        for r in routes[::-1]:
            if not r or (r == ip):
                continue
            # Do (optional) PING check in order to determine if that
            # gateway can be monitored via the standard host check
            if ping_probes:
                if not gateway_reachable_via_ping(r, ping_probes):
                    console.verbose("(not using %s, not reachable)\n",
                                    r,
                                    stream=sys.stderr)
                    skipped_gateways += 1
                    continue
            route = r
            break
        if not route:
            error = "No usable routing information"
            if not silent:
                console.error("%s: %s\n" % (host, error))
            gateways.append((None, "notfound", 0, error))
            dot(tty.blue)
            continue

        # TTLs already have been filtered out)
        gateway_ip = route
        gateway = _ip_to_hostname(config_cache, route)
        if gateway:
            console.verbose("%s(%s) ", gateway, gateway_ip)
        else:
            console.verbose("%s ", gateway_ip)

        # Try to find DNS name of host via reverse DNS lookup
        dns_name = _ip_to_dnsname(gateway_ip)
        gateways.append(
            ((gateway, gateway_ip, dns_name), "gateway", skipped_gateways, ""))
        dot(tty.green, 'G')
    return gateways