Ejemplo n.º 1
0
def do_check_nagiosconfig():
    command = [
        cmk.utils.paths.nagios_binary, "-vp",
        cmk.utils.paths.nagios_config_file
    ]
    cmk_base.console.verbose("Running '%s'\n" %
                             subprocess.list2cmdline(command))
    cmk_base.console.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:
        cmk_base.console.output(tty.ok + "\n")
        return True

    cmk_base.console.output("ERROR:\n")
    cmk_base.console.output(stdout, stderr)
    return False
Ejemplo n.º 2
0
    def walk(self,
             snmp_config,
             oid,
             check_plugin_name=None,
             table_base_oid=None,
             context_name=None):
        # type: (SNMPHostConfig, str, Optional[str], Optional[str], Optional[str]) -> SNMPRowInfo
        protospec = self._snmp_proto_spec(snmp_config)

        ipaddress = snmp_config.ipaddress
        if snmp_config.is_ipv6_primary:
            ipaddress = "[" + ipaddress + "]"

        portspec = self._snmp_port_spec(snmp_config)
        command = self._snmp_walk_command(snmp_config, context_name)
        command += [
            "-OQ", "-OU", "-On", "-Ot",
            "%s%s%s" % (protospec, ipaddress, portspec), oid
        ]
        console.vverbose("Running '%s'\n" % subprocess.list2cmdline(command))

        snmp_process = None
        exitstatus = None
        rowinfo = []  # type: SNMPRowInfo
        try:
            snmp_process = subprocess.Popen(command,
                                            close_fds=True,
                                            stdin=open(os.devnull),
                                            stdout=subprocess.PIPE,
                                            stderr=subprocess.PIPE,
                                            encoding="utf-8")

            rowinfo = self._get_rowinfo_from_snmp_process(snmp_process)

        except MKTimeout:
            # On timeout exception try to stop the process to prevent child process "leakage"
            if snmp_process:
                os.kill(snmp_process.pid, signal.SIGTERM)
                snmp_process.wait()
            raise

        finally:
            # The stdout and stderr pipe are not closed correctly on a MKTimeout
            # Normally these pipes getting closed after p.communicate finishes
            # Closing them a second time in a OK scenario won't hurt neither..
            if snmp_process:
                exitstatus = snmp_process.wait()
                if snmp_process.stderr:
                    error = snmp_process.stderr.read()
                    snmp_process.stderr.close()
                if snmp_process.stdout:
                    snmp_process.stdout.close()

        if exitstatus:
            console.verbose(tty.red + tty.bold + "ERROR: " + tty.normal +
                            "SNMP error: %s\n" % six.ensure_str(error).strip())
            raise MKSNMPError(
                "SNMP Error on %s: %s (Exit-Code: %d)" %
                (ipaddress, six.ensure_str(error).strip(), exitstatus))
        return rowinfo
Ejemplo n.º 3
0
    def get(self, snmp_config, oid, context_name=None):
        # type: (SNMPHostConfig, OID, Optional[ContextName]) -> Optional[RawValue]
        if oid.endswith(".*"):
            oid_prefix = oid[:-2]
            commandtype = "getnext"
        else:
            oid_prefix = oid
            commandtype = "get"

        protospec = self._snmp_proto_spec(snmp_config)
        ipaddress = snmp_config.ipaddress
        if snmp_config.is_ipv6_primary:
            ipaddress = "[" + ipaddress + "]"
        portspec = self._snmp_port_spec(snmp_config)
        command = (
            self._snmp_base_command(commandtype, snmp_config, context_name) + [
                "-On", "-OQ", "-Oe", "-Ot",
                "%s%s%s" % (protospec, ipaddress, portspec), oid_prefix
            ])

        console.vverbose("Running '%s'\n" % subprocess.list2cmdline(command))

        snmp_process = subprocess.Popen(
            command,
            close_fds=True,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            encoding="utf-8",
        )
        exitstatus = snmp_process.wait()
        if snmp_process.stderr is None or snmp_process.stdout is None:
            raise TypeError()
        if exitstatus:
            console.verbose(tty.red + tty.bold + "ERROR: " + tty.normal +
                            "SNMP error\n")
            console.verbose(snmp_process.stderr.read() + "\n")
            return None

        line = snmp_process.stdout.readline().strip()
        if not line:
            console.verbose("Error in response to snmpget.\n")
            return None

        parts = line.split("=", 1)
        if len(parts) != 2:
            return None
        item = parts[0]
        value = parts[1].strip()
        console.vverbose("SNMP answer: ==> [%s]\n" % value)
        if value.startswith('No more variables') or \
           value.startswith('End of MIB') or \
           value.startswith('No Such Object available') or \
           value.startswith('No Such Instance currently exists'):
            return None

        # In case of .*, check if prefix is the one we are looking for
        if commandtype == "getnext" and not item.startswith(oid_prefix + "."):
            return None

        return strip_snmp_value(value)
Ejemplo n.º 4
0
def _local_automation_failure(command, cmdline, code=None, out=None, err=None, exc=None):
    call = subprocess.list2cmdline(cmdline) if config.debug else command
    msg = "Error running automation call <tt>%s<tt>" % call
    if code:
        msg += " (exit code %d)" % code
    if out:
        msg += ", output: <pre>%s</pre>" % _hilite_errors(out)
    if err:
        msg += ", error: <pre>%s</pre>" % _hilite_errors(err)
    if exc:
        msg += ": %s" % exc
    return MKGeneralException(msg)
Ejemplo n.º 5
0
def _git_command(args):
    command = ["git"] + [six.ensure_str(a) for a in args]
    logger.debug("GIT: Execute in %s: %s", cmk.utils.paths.default_config_dir,
                 subprocess.list2cmdline(command))
    try:
        p = subprocess.Popen(command,
                             cwd=cmk.utils.paths.default_config_dir,
                             stdout=subprocess.PIPE,
                             stderr=subprocess.STDOUT,
                             encoding="utf-8")
    except OSError as e:
        if e.errno == errno.ENOENT:
            raise MKGeneralException(
                _("Error executing GIT command <tt>%s</tt>:<br><br>%s") %
                (subprocess.list2cmdline(command), e))
        raise

    status = p.wait()
    if status != 0:
        out = u"" if p.stdout is None else six.ensure_text(p.stdout.read())
        raise MKGeneralException(
            _("Error executing GIT command <tt>%s</tt>:<br><br>%s") %
            (subprocess.list2cmdline(command), out.replace("\n", "<br>\n")))
Ejemplo n.º 6
0
def main(sys_argv=None):
    if sys_argv is None:
        sys_argv = sys.argv[1:]

    short_options = 'u:p:l:D:k:'
    long_options = [
        'help', 'debug', 'ipmi-command=', 'quiet-cache', 'sdr-cache-recreate',
        'interpret-oem-data', 'output-sensor-state',
        'ignore-not-available-sensors', 'driver-type=',
        'output-sensor-thresholds'
    ]

    opt_debug = False
    hostname = None
    username = None
    password = None
    privilege_lvl = None
    ipmi_cmd_type = None

    try:
        opts, args = getopt.getopt(sys_argv, short_options, long_options)
    except getopt.GetoptError as err:
        sys.stderr.write("%s\n" % err)
        return 1

    additional_opts = []
    for o, a in opts:
        if o in ['--help']:
            agent_ipmi_sensors_usage()
            return 1
        if o in ['--debug']:
            opt_debug = True

        # Common options
        elif o in ['--ipmi-command']:
            ipmi_cmd_type = a
        elif o in ['-u']:
            username = a
        elif o in ['-p']:
            password = a
        elif o in ['-l']:
            privilege_lvl = a

        # FreeIPMI options
        elif o in ['-D']:
            additional_opts += ["%s" % o, "%s" % a]
        elif o in ['--driver-type']:
            additional_opts += ["%s=%s" % (o, a)]
        elif o in ['-k']:
            additional_opts += ["%s" % o, "%s" % a]
        elif o in ['--quiet-cache']:
            additional_opts.append(o)
        elif o in ['--sdr-cache-recreate']:
            additional_opts.append(o)
        elif o in ['--interpret-oem-data']:
            additional_opts.append(o)
        elif o in ['--output-sensor-state']:
            additional_opts.append(o)
        elif o in ['--ignore-not-available-sensors']:
            additional_opts.append(o)
        elif o in ['--output-sensor-thresholds']:
            additional_opts.append(o)

    if len(args) == 1:
        hostname = args[0]
    else:
        sys.stderr.write("ERROR: Please specify exactly one host.\n")
        return 1

    if not (username and password and privilege_lvl):
        sys.stderr.write("ERROR: Credentials are missing.\n")
        return 1

    os.environ[
        "PATH"] = "/usr/local/sbin:/usr/sbin:/sbin:" + os.environ["PATH"]

    if ipmi_cmd_type in [None, 'freeipmi']:
        ipmi_cmd = [ "ipmi-sensors",
                     "-h", hostname, "-u", username,
                     "-p", password, "-l", privilege_lvl ] + \
                     additional_opts
        queries = {
            "_sensors": ([], [])
        }  # type: Dict[str, Tuple[List[str], List[str]]]
    elif ipmi_cmd_type == 'ipmitool':
        ipmi_cmd = [
            "ipmitool", "-H", hostname, "-U", username, "-P", password, "-L",
            privilege_lvl
        ]
        # As in check_mk_agent
        queries = {
            "": (["sensor", "list"], ['command failed', 'discrete']),
            "_discrete": (["sdr", "elist", "compact"], [])
        }

    else:
        sys.stderr.write("ERROR: Unknown IPMI command '%s'.\n" % ipmi_cmd_type)
        return 1

    ipmi_cmd_str = subprocess.list2cmdline(ipmi_cmd)

    if opt_debug:
        sys.stderr.write("Executing: '%s'\n" % ipmi_cmd_str)

    errors = []
    for section, (types, excludes) in queries.items():
        sys.stdout.write("<<<ipmi%s:sep(124)>>>\n" % section)
        try:
            try:
                p = subprocess.Popen(
                    ipmi_cmd + types,
                    close_fds=True,
                    stdin=open(os.devnull),
                    stdout=subprocess.PIPE,
                    stderr=subprocess.PIPE,
                    encoding="utf-8",
                )
            except OSError as e:
                if e.errno == errno.ENOENT:  # No such file or directory
                    raise Exception("Could not find '%s' command (PATH: %s)" %
                                    (ipmi_cmd_type, os.environ.get("PATH")))
                raise

            stdout, stderr = p.communicate()
            if stderr:
                errors.append(stderr)
            parse_data(stdout.splitlines(), excludes)
        except Exception as e:
            errors.append(str(e))

    if errors:
        msg = "ERROR: '%s'.\n" % ", ".join(errors)
        sys.stderr.write(six.ensure_str(msg))
        return 1
    return 0
Ejemplo n.º 7
0
def check_mk_local_automation(command,
                              args=None,
                              indata="",
                              stdin_data=None,
                              timeout=None):
    # type: (str, Optional[Sequence[Union[str, Text]]], Any, Optional[str], Optional[int]) -> Any
    if args is None:
        args = []
    new_args = [six.ensure_str(a) for a in args]

    if stdin_data is None:
        stdin_data = repr(indata)

    if timeout:
        new_args = ["--timeout", "%d" % timeout] + new_args

    cmd = ['check_mk', '--automation', command] + new_args
    if command in ['restart', 'reload']:
        call_hook_pre_activate_changes()

    cmd = [six.ensure_str(a) for a in cmd]
    try:
        # This debug output makes problems when doing bulk inventory, because
        # it garbles the non-HTML response output
        # if config.debug:
        #     html.write("<div class=message>Running <tt>%s</tt></div>\n" % subprocess.list2cmdline(cmd))
        auto_logger.info("RUN: %s" % subprocess.list2cmdline(cmd))
        p = subprocess.Popen(cmd,
                             stdin=subprocess.PIPE,
                             stdout=subprocess.PIPE,
                             stderr=subprocess.PIPE,
                             close_fds=True,
                             encoding="utf-8")
    except Exception as e:
        raise _local_automation_failure(command=command, cmdline=cmd, exc=e)

    assert p.stdin is not None
    assert p.stdout is not None
    assert p.stderr is not None

    auto_logger.info("STDIN: %r" % stdin_data)
    p.stdin.write(stdin_data)
    p.stdin.close()

    outdata = p.stdout.read()
    exitcode = p.wait()
    auto_logger.info("FINISHED: %d" % exitcode)
    auto_logger.debug("OUTPUT: %r" % outdata)
    errdata = p.stderr.read()
    if errdata:
        auto_logger.warning("'%s' returned '%s'" % (" ".join(cmd), errdata))
    if exitcode != 0:
        auto_logger.error("Error running %r (exit code %d)" %
                          (subprocess.list2cmdline(cmd), exitcode))
        raise _local_automation_failure(command=command,
                                        cmdline=cmd,
                                        code=exitcode,
                                        out=outdata,
                                        err=errdata)

    # On successful "restart" command execute the activate changes hook
    if command in ['restart', 'reload']:
        call_hook_activate_changes()

    try:
        return ast.literal_eval(outdata)
    except SyntaxError as e:
        raise _local_automation_failure(command=command,
                                        cmdline=cmd,
                                        out=outdata,
                                        exc=e)
Ejemplo n.º 8
0
def scan_parents_of(config_cache, hosts, silent=False, settings=None):
    # type: (config.ConfigCache, List[HostName], bool, Optional[Dict[str, int]]) -> Gateways
    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 = []  # type: List[Tuple[HostName, Optional[HostAddress], Union[str, subprocess.Popen]]]
    for host in hosts:
        console.verbose("%s " % host)
        try:
            ip = ip_lookup.lookup_ipv4_address(host)
            if ip is None:
                raise RuntimeError()
            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,
                                           encoding="utf-8")))
        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'):
        # type: (str, str) -> None
        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 = []  # type: 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()
            if proc_or_error.stdout is None:
                raise RuntimeError()
            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

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

        if 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 = []  # type: List[Optional[str]]
        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.
        if 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
        this_route = None  # type: Optional[HostAddress]
        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
            this_route = r
            break
        if not this_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 = this_route
        gateway = _ip_to_hostname(config_cache, this_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