ok

Mini Shell

Direktori : /usr/lib/fm-agent/plugins/
Upload File :
Current File : //usr/lib/fm-agent/plugins/dem_plugin.py

import agent_util
import ipc_client

from datetime import datetime
import json
import logging
import sys


class DEMPlugin(agent_util.Plugin):
    textkey = "dem"
    label = "Digital Experience"
    log = logging.getLogger(__name__)
    wifi_client = ipc_client.DEMClient(dem_port="demservice")

    @classmethod
    def get_metadata(self, config):
        status = agent_util.SUPPORTED
        msg = None

        dem_configured = True
        if config.get("enabled", "false").lower() != "true":
            status = agent_util.UNSUPPORTED
            msg = "DEM not configured"
            dem_configured = False

        if dem_configured:
            info = self.wifi_client.get_dem_wifi_info()
            if not info:
                status = agent_util.UNSUPPORTED
                msg = "No wifi info found"

        metadata = {
            "dem.agrCtlRSSI": {
                "label": "Wifi signal strength",
                "options": None,
                "status": status,
                "error_msg": msg,
                "unit": "dBm",
            },
            "dem.downloadspeed": {
                "label": "Download Speed",
                "options": None,
                "status": agent_util.SUPPORTED,
                "error_msg": None,
                "unit": "Mbit/s",
            },
        }
        if "darwin" == sys.platform:
            metadata["dem.lastTxRate"] = {
                "label": "Last transmission rate",
                "options": None,
                "status": status,
                "error_msg": msg,
                "unit": "mbps/s",
            }
            metadata["dem.agrCtlNoise"] = {
                "label": "Noise",
                "options": None,
                "status": status,
                "error_msg": msg,
                "unit": "dBm",
            }
            metadata["dem.MCS"] = {
                "label": "MCS Index",
                "options": None,
                "status": status,
                "error_msg": msg,
                "unit": "index",
            }

        speedtest_upload = agent_util.SUPPORTED
        speedtest_msg = None
        if (
            config.get("speedtest_mode", "speedtest").lower() != "iperf3"
            or not dem_configured
            or "darwin" != sys.platform
        ):
            speedtest_upload = agent_util.UNSUPPORTED
            speedtest_msg = "Upload speed not supported"

        metadata["dem.uploadspeed"] = {
            "label": "Upload Speed",
            "options": None,
            "status": speedtest_upload,
            "error_msg": speedtest_msg,
            "unit": "Mbit/s",
        }

        battery_status = agent_util.SUPPORTED
        battery_msg = None
        if not dem_configured:
            battery_status = agent_util.UNSUPPORTED
            battery_msg = "DEM not configured"
        else:
            battery_pct = self.get_battery_remaining()
            if battery_pct is None:
                battery_status = agent_util.UNSUPPORTED
                battery_msg = "Battery metric unavailable"
        metadata["dem.battery_percent_remaining"] = {
            "label": "Battery Percent Remaining",
            "options": None,
            "status": battery_status,
            "error_msg": battery_msg,
            "unit": "percent",
        }
        return metadata

    def check(self, textkey, data, config):
        if config.get("enabled", "false").lower() != "true":
            return None
        if textkey in ("dem.downloadspeed", "dem.uploadspeed"):
            return self._measureNetworkSpeed(textkey, config)

        if "dem.battery_percent_remaining" == textkey:
            return self.get_battery_remaining()

        try:
            info = self.wifi_client.get_dem_wifi_info()
            if not info:
                raise Exception("No wifi info received")
            key = textkey[len("dem.") :]
            metric_value = info.get(key, None)
            if metric_value is None:
                raise Exception("Missing key {}".format(key))
            return float(metric_value)
        except Exception as e:
            self.log.error("Wifi metrics error: {}".format(str(e)))
            return None

    def _run_iperf3_test(self, textkey, config):
        speedtest_bin = "/usr/local/FortiMonitor/agent/latest/bin/iperf3"
        try:
            start_url = config.get("iperf3_start_url", None)
            from iperf3 import Iperf3Runner

            runner = Iperf3Runner(iperf3_bin=speedtest_bin, start_url=start_url)
            result = None
            if "dem.downloadspeed" == textkey:
                result = runner.get_download_speed()
            elif "dem.uploadspeed" == textkey:
                result = runner.get_upload_speed()
            return float(result / (1000 * 1000))
        except:
            self.log.exception("Iperf3 error:")

    def _measureNetworkSpeed(self, textkey, config):
        if config.get("speedtest_mode", "speedtest").lower() == "iperf3":
            return self._run_iperf3_test(textkey, config)

        if "dem.uploadspeed" == textkey:
            raise Exception("Service does not support upload speed")
        try:
            import speedtest

            start = datetime.now()
            s = speedtest.Speedtest()
            s.get_best_server()
            k = s.download()
            rv = float(k / 1000000)
            self.log.info(
                "Download speed {} in {:.2f}".format(
                    rv, (datetime.now() - start).total_seconds()
                )
            )
            return rv
        except Exception as ste:
            self.log.error("Speedtest exception: {}".format(ste))
            return None

    @classmethod
    def get_battery_remaining(self):
        if "darwin" == sys.platform:
            try:
                sp = agent_util.which("system_profiler")
                power_tk = "SPPowerDataType"
                output = agent_util.run_command([sp, "-json", power_tk])
                data = json.loads(output)
                for d in data[power_tk]:
                    if d.get("_name", "") == "spbattery_information":
                        mv = d.get("sppower_battery_charge_info", None)
                        if not mv:
                            return None
                        return float(mv["sppower_battery_state_of_charge"])

                return None
            except Exception as e:
                self.log.exception(e)
                return None
        elif "linux" == sys.platform:
            return self.get_battery_percent_linux()
        else:
            return None

    @classmethod
    def get_battery_percent_linux(self):
        try:
            proc_args = ["upower", "-i", "/org/freedesktop/UPower/devices/battery_BAT0"]
            output = agent_util.run_command(proc_args).strip().splitlines()
            seen_battery = False
            seen_present = False
            percentage = None
            for line in output:
                line = line.strip()
                if "battery" == line:
                    seen_battery = True
                elif "present:" in line:
                    seen_present = True
                elif "percentage:" in line:
                    percentage = line.split(":")[1].strip().rstrip("%")
                    break

            if seen_battery and seen_present:
                return float(percentage)

            return None

        except Exception as e:
            self.log.exception(e)
            return None

Zerion Mini Shell 1.0