Beispiel #1
0
    def _get_agent_info_program(self, commandline, command_stdin):
        exepath = commandline.split()[0]  # for error message, hide options!

        self._logger.debug("Calling external program %r" % (commandline))
        p = None
        try:
            if config.monitoring_core == "cmc":
                p = subprocess.Popen(  # nosec
                    commandline,
                    shell=True,
                    stdin=subprocess.PIPE if command_stdin else open(os.devnull),
                    stdout=subprocess.PIPE,
                    stderr=subprocess.PIPE,
                    preexec_fn=os.setsid,
                    close_fds=True,
                    encoding="utf-8",
                )
            else:
                # We can not create a separate process group when running Nagios
                # Upon reaching the service_check_timeout Nagios only kills the process
                # group of the active check.
                p = subprocess.Popen(  # nosec
                    commandline,
                    shell=True,
                    stdin=subprocess.PIPE if command_stdin else open(os.devnull),
                    stdout=subprocess.PIPE,
                    stderr=subprocess.PIPE,
                    close_fds=True,
                    encoding="utf-8",
                )

            if command_stdin:
                stdout, stderr = p.communicate(input=ensure_unicode(command_stdin))
            else:
                stdout, stderr = p.communicate()
            exitstatus = p.returncode

        except MKTimeout:
            # On timeout exception try to stop the process to prevent child process "leakage"
            if p:
                os.killpg(os.getpgid(p.pid), signal.SIGTERM)
                p.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 p:
                p.stdout.close()
                p.stderr.close()

        if exitstatus:
            if exitstatus == 127:
                raise MKAgentError("Program '%s' not found (exit code 127)" % exepath)
            else:
                raise MKAgentError("Agent exited with code %d: %s" % (exitstatus, stderr))

        return stdout
Beispiel #2
0
    def _execute(self):
        connection = None
        try:
            connection = self._create_ipmi_connection()

            output = ""
            output += self._fetch_ipmi_sensors_section(connection)
            output += self._fetch_ipmi_firmware_section(connection)

            return output
        except Exception as e:
            if cmk.utils.debug.enabled():
                raise

            # Improve bad exceptions thrown by pyghmi e.g. in case of connection issues
            if isinstance(e, IpmiException) and "%s" % e == "None":
                raise MKAgentError("IPMI communication failed: %r" % e)
            else:
                raise
        finally:
            if connection:
                connection.ipmi_session.logout()
Beispiel #3
0
    def _get_raw_data(self):
        """Returns the current raw data of this data source

        It either uses previously cached raw data of this data source or
        executes the data source to get new data.

        The "raw data" is the raw byte string returned by the source for
        CheckMKAgentDataSource sources. The SNMPDataSource source already
        return the final info data structure.
        """
        raw_data = self._read_cache_file()
        if raw_data:
            self._logger.log(VERBOSE, "Use cached data")
            return raw_data, True

        elif raw_data is None and config.simulation_mode:
            raise MKAgentError("Got no data (Simulation mode enabled and no cachefile present)")

        self._logger.log(VERBOSE, "Execute data source")
        raw_data = self._execute()
        self._write_cache_file(raw_data)
        return raw_data, False
Beispiel #4
0
    def _execute(self):
        if self._use_only_cache:
            raise MKAgentError("Got no data: No usable cache file present at %s" %
                               self._cache_file_path())

        self._verify_ipaddress()

        port = self._get_port()

        encryption_settings = self._host_config.agent_encryption

        socktype = (socket.AF_INET6 if self._host_config.is_ipv6_primary else socket.AF_INET)
        s = socket.socket(socktype, socket.SOCK_STREAM)

        timeout = self._get_timeout()

        output = []
        self._logger.debug("Connecting via TCP to %s:%d (%ss timeout)" %
                           (self._ipaddress, port, timeout))
        try:
            s.settimeout(timeout)
            s.connect((self._ipaddress, port))
            s.settimeout(None)

            self._logger.debug("Reading data from agent")

            while True:
                data = s.recv(4096, socket.MSG_WAITALL)

                if data and len(data) > 0:
                    output.append(data)
                else:
                    break
        except MKTerminate:
            raise

        except socket.error as e:
            if cmk.utils.debug.enabled():
                raise
            raise MKAgentError("Communication failed: %s" % e)
        finally:
            s.close()
        output = ''.join(output)

        if len(output) == 0:  # may be caused by xinetd not allowing our address
            raise MKEmptyAgentData("Empty output from agent at TCP port %d" % port)

        elif len(output) < 16:
            raise MKAgentError("Too short output from agent: %r" % output)

        output_is_plaintext = output.startswith("<<<")
        if encryption_settings["use_regular"] == "enforce" and output_is_plaintext:
            raise MKAgentError(
                "Agent output is plaintext but encryption is enforced by configuration")
        if not output_is_plaintext and encryption_settings["use_regular"] in ["enforce", "allow"]:
            try:
                # simply check if the protocol is an actual number
                protocol = int(output[0:2])

                output = self._decrypt_package(output[2:], encryption_settings["passphrase"],
                                               protocol)
            except ValueError:
                raise MKAgentError("Unsupported protocol version: %s" % output[:2])
            except Exception as e:
                if encryption_settings["use_regular"] == "enforce":
                    raise MKAgentError("Failed to decrypt agent output: %s" % e)
                else:
                    # of course the package might indeed have been encrypted but
                    # in an incorrect format, but how would we find that out?
                    # In this case processing the output will fail
                    pass

        return output