ok

Mini Shell

Direktori : /proc/self/root/lib/fm-agent/plugins/
Upload File :
Current File : //proc/self/root/lib/fm-agent/plugins/io_stats.py

import agent_util
from sys import platform, exc_info
import logging
import re
from agent_util import float


class DevicePathManager:
    def __init__(self, execute_function=None):
        if not execute_function:
            self._execute_function = agent_util.execute_command
        else:
            self._execute_function = execute_function
        try:
            command = "lsblk --pairs"
            if "darwin" in platform:
                disk_util = agent_util.which("diskutil")
                command = "{} list".format(disk_util)
            self._output = self._execute_function(command)
            self._output = self._output[1].split("\n")
        except Exception:
            logging.exception("Error getting devices")
            self._output = []

    def find_path(self, device):
        if "darwin" in platform:
            for line in self._output:
                if line.startswith("/"):
                    mp = line.split(" ")[0]
                    if mp[len("/dev/") :] == device:
                        return mp
            return None
        else:
            for line in self._output:
                expression = r'^NAME="(%s)".*MOUNTPOINT="(.*)"$' % (device)
                match = re.match(expression, line)
                if match:
                    matched_mountpoint = match.groups()[1]
                    if matched_mountpoint == "":
                        # Some devices don't show a mountpoint, in those
                        # cases, return the same device.
                        return device
                    else:
                        return matched_mountpoint


class IOStatPlugin(agent_util.Plugin):
    textkey = "iostat"
    label = "IO"
    metrics_list = [
        "rrqm/s",
        "wrqm/s",
        "r/s",
        "w/s",
        "svctm",
        "rkB/s",
        "wkB/s",
        "%w",
        "%b",
        "wait",
        "actv",
        "kr/s",
        "kw/s",
        "svc_t",
        "%util",
    ]
    metrics_labels = {
        "rrqm/s": "Read requests queued",
        "wrqm/s": "Write requests queued",
        "r/s": "Read requests",
        "w/s": "Write requests",
        "svctm": "Average I/O request service time",
        "%w": "% of time transactions are waiting",
        "%b": "Percent of time the disk is busy",
        "wait": "Average transactions waiting for service",
        "actv": "Average transactions being serviced",
        "kr/s": "Data read rate",
        "kw/s": "Data write rate",
        "svc_t": "Average response time",
        "%util": "% of I/O CPU time",
    }
    metrics_units = {
        "rrqm/s": "requests/second",
        "wrqm/s": "requests/second",
        "r/s": "requests/second",
        "w/s": "requests/second",
        "svctm": "ms",
        "%w": "percent",
        "%b": "percent",
        "wait": "transactions",
        "actv": "transactions",
        "kr/s": "KB/s",
        "kw/s": "KB/s",
        "svc_t": "Average response time",
        "%util": "% of I/O CPU time",
    }

    darwinMetricsMap = {"kbpt": "KB/t", "tps": "tps", "mbps": "MB/s"}

    @classmethod
    def get_metadata(self, config):
        status = agent_util.SUPPORTED
        msg = None
        iostat_bin = agent_util.which("iostat")
        if not iostat_bin:
            self.log.info("iostat not found")
            status = agent_util.MISCONFIGURED
            msg = "Install iostat."
            return {}
        self.log.debug("Starting IOStat")
        # get our devices to monitor
        devices = []
        data = {}
        output = None
        header = []
        options_schema = {"resource": "string", "mountpoint": "string"}
        device_path_manager = DevicePathManager()

        if "hp-ux" in platform:
            ret, out = agent_util.execute_command("%s | sed '/^loop/d' " % iostat_bin)
            lines = out.strip().splitlines()
            for line in lines:
                if line.startswith("device") or line == "" or not line:
                    continue
                device = line.split()[0]
                mountpoint = device_path_manager.find_path(device)
                devices.append(
                    {
                        "resource": device,
                        "mountpoint": mountpoint,
                    }
                )
            self.log.debug("Devices found: %s" % devices)
            metdata = {
                "bps": {
                    "label": "kilobytes per second",
                    "options": devices,
                    "status": status,
                    "error_message": msg,
                    "unit": "kb",
                    "options_schema": options_schema,
                },
                "sps": {
                    "label": "disk seeks per second",
                    "options": devices,
                    "status": status,
                    "error_message": msg,
                    "unit": "",
                    "options_schema": options_schema,
                },
            }
            return metdata

        elif "darwin" in platform:
            ret, out = agent_util.execute_command("%s -d" % iostat_bin)
            if 0 != ret:
                status = agent_util.MISCONFIGURED
                msg = "iostat failure code {}".format(ret)
            else:
                lines = out.strip().splitlines()
                devs = lines[0].strip().split()
                for device in devs:
                    mp = device_path_manager.find_path(device)
                    if mp:
                        devices.append({"resource": device, "mountpoint": mp})
                    else:
                        status = agent_util.MISCONFIGURED
                        msg = "Could not map device"
                        break

            metadata = {
                "kbpt": {
                    "label": "Kilobytes per transfer",
                    "options": devices,
                    "status": status,
                    "error_msg": msg,
                    "unit": "KB/s",
                    "options_schema": options_schema,
                },
                "tps": {
                    "label": "Transfers per second",
                    "options": devices,
                    "status": status,
                    "error_msg": msg,
                    "unit": "transfers/s",
                    "options_schema": options_schema,
                },
                "mbps": {
                    "label": "Megabytes per second",
                    "options": devices,
                    "status": status,
                    "error_msg": msg,
                    "unit": "MB/s",
                    "options_schema": options_schema,
                },
            }
            return metadata

        else:
            ret_code, output = agent_util.execute_command(
                "%s -dx | sed '/^loop/d' " % iostat_bin
            )
            output = output.strip().splitlines()
            self.log.debug("#####################################################")
            self.log.debug("IO stats command '%s -dx' output:" % iostat_bin)
            self.log.debug(str(output))
            self.log.debug("#####################################################")
            for line in reversed(output):
                if line.lower().startswith("device"):
                    header = line.split()
                    break
                fields = line.strip().split()
                dev = fields[0]
                if dev.lower().startswith("dm-"):
                    continue
                mountpoint = device_path_manager.find_path(dev)
                devices.append({"resource": dev, "mountpoint": mountpoint})
                self.log.debug("Devices: %s" % str(devices))

        # no devices?  no resources to monitor then
        if not devices:
            status = agent_util.MISCONFIGURED
            msg = "No devices found from iostat."

        for metric in header:
            self.log.debug("###########\nMetric: %s" % str(metric))
            if metric in self.metrics_list:
                self.log.debug(
                    "metric %s has the index value of %s"
                    % (str(metric), str(header.index(metric)))
                )
                data[str(metric)] = {
                    "label": self.metrics_labels.get(str(metric), str(metric)),
                    "options": devices,
                    "options_schema": options_schema,
                    "status": status,
                    "error_message": msg,
                }
                if str(metric) in self.metrics_units:
                    data[str(metric)]["unit"] = self.metrics_units.get(str(metric))

        return data

    def check(self, textkey, device, config):
        metrics_index = {}

        iostat_bin = agent_util.which("iostat")
        second_line = False
        header_line = 2
        if "freebsd" in platform:
            header_line = 1

        if "sunos" in platform:
            second_line = True
            ret, output = agent_util.execute_command(
                "%s -dx 1 2 | sed '/^loop/d'" % (iostat_bin),
                cache_timeout=agent_util.DEFAULT_CACHE_TIMEOUT,
            )
            header = output.strip().splitlines()[1].split()
        elif "hp-ux" in platform:
            ret, out = agent_util.execute_command(
                "iostat 1 2 | sed '/^loop/d'",
                cache_timeout=agent_util.DEFAULT_CACHE_TIMEOUT,
            )
            lines = out.strip().splitlines()
            previously_seen = False
            for line in lines:
                line = line.strip()
                if previously_seen is False and line.startswith(device):
                    previously_seen = True
                    self.log.debug("Found first instance of disk %s" % device)
                elif previously_seen is True and line.startswith(device):
                    self.log.debug("Found second instance of disk %s" % device)
                    self.log.debug(line)
                    l = line.split()
                    if textkey == "bps":
                        return float(l[1])
                    elif textkey == "sps":
                        return float(l[2])
                    else:
                        return None
        elif "darwin" in platform:
            try:
                outputKey = self.darwinMetricsMap.get(textkey, None)
                if outputKey is None:
                    raise Exception("Unrecognized textkey {}".format(textkey))
                ret, output = agent_util.execute_command(
                    "%s -d -c 2" % iostat_bin,
                    cache_timeout=agent_util.DEFAULT_CACHE_TIMEOUT,
                )
                if 0 != ret:
                    raise Exception("iostat failure, error {}".format(ret))
                metricsCount = len(self.darwinMetricsMap)
                lines = output.strip().split("\n")
                if 4 != len(lines):
                    self.log.error("Unrecognized iostat output")
                    self.log.error(output)
                    raise Exception("Unrecognized iostat output")

                devices = lines[0].split()
                metrics = lines[1].split()
                metric_values = lines[3].split()
                devIndex = devices.index(device)
                si = devIndex * metricsCount
                ei = si + metricsCount
                deviceMetrics = metrics[si:ei]
                di = deviceMetrics.index(outputKey)
                return float(metric_values[si:ei][di])

            except Exception:
                err = exc_info()[1]
                error = str(err)
                self.log.error(
                    "Collection error {}, {}: {}".format(device, textkey, error)
                )
                return None

        else:
            second_line = True
            cmd_to_run = "%s -dx 1 2 | sed '/^loop/d'" % (iostat_bin)
            ret, output = agent_util.execute_command(
                cmd_to_run, cache_timeout=agent_util.DEFAULT_CACHE_TIMEOUT
            )
            if ret != 0:
                self.log.error("{} failed with status {}".format(cmd_to_run, ret))
                return None
            header = output.strip().splitlines()[header_line].split()

        splitted_lines = output.strip().split("\n")
        full = list(
            filter(lambda x: re.match(r"^%s .*$" % (device), x), splitted_lines)
        )
        if full:
            if second_line:
                full = full[1]
            else:
                full = full[0]
        else:
            self.log.error("Device %s could not be found in output!" % device)
            return None
        if not header:
            self.log.error("Device %s no longer exists!" % device)
            return None

        for metric in header:
            self.log.debug("###########\nMetric: %s" % str(metric))
            if metric in self.metrics_list:
                metrics_index[str(metric)] = header.index(str(metric))

        self.log.debug("#####################################################")
        self.log.debug(
            "IO stats command '%s -dx %s 1 2' output:" % (iostat_bin, device)
        )
        self.log.debug(str(full))
        self.log.debug("#####################################################")
        self.log.debug("iostat -dx output: %s" % str(output))

        j = full.strip().split()
        if device in j[0]:
            return float(j[int(metrics_index[str(textkey.split(".")[-1])])])

        return 0

Zerion Mini Shell 1.0