#!/usr/bin/env python import os import psutil from yunohost.diagnosis import Diagnoser class SystemResourcesDiagnoser(Diagnoser): id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1] cache_duration = 300 dependencies = [] def run(self): MB = 1024**2 GB = MB*1024 # # RAM # ram = psutil.virtual_memory() ram_available_percent = 100 * ram.available / ram.total item = dict(meta={"test": "ram"}, data={"total": human_size(ram.total), "available": human_size(ram.available), "available_percent": round_(ram_available_percent)}) if ram.available < 100 * MB or ram_available_percent < 5: item["status"] = "ERROR" item["summary"] = "diagnosis_ram_verylow" elif ram.available < 200 * MB or ram_available_percent < 10: item["status"] = "WARNING" item["summary"] = "diagnosis_ram_low" else: item["status"] = "SUCCESS" item["summary"] = "diagnosis_ram_ok" yield item # # Swap # swap = psutil.swap_memory() item = dict(meta={"test": "swap"}, data={"total": human_size(swap.total), "recommended": "512 MiB"}) if swap.total <= 1 * MB: item["status"] = "INFO" item["summary"] = "diagnosis_swap_none" elif swap.total < 450 * MB: item["status"] = "INFO" item["summary"] = "diagnosis_swap_notsomuch" else: item["status"] = "SUCCESS" item["summary"] = "diagnosis_swap_ok" item["details"] = ["diagnosis_swap_tip"] yield item # FIXME : add a check that swapiness is low if swap is on a sdcard... # # Disks usage # disk_partitions = sorted(psutil.disk_partitions(), key=lambda k: k.mountpoint) for disk_partition in disk_partitions: device = disk_partition.device mountpoint = disk_partition.mountpoint usage = psutil.disk_usage(mountpoint) free_percent = 100 - round_(usage.percent) item = dict(meta={"test": "diskusage", "mountpoint": mountpoint}, data={"device": device, # N.B.: we do not use usage.total because we want # to take into account the 5% security margin # correctly (c.f. the doc of psutil ...) "total": human_size(usage.used+usage.free), "free": human_size(usage.free), "free_percent": free_percent}) # We have an additional absolute constrain on / and /var because # system partitions are critical, having them full may prevent # upgrades etc... if free_percent < 2.5 or (mountpoint in ["/", "/var"] and usage.free < 1 * GB): item["status"] = "ERROR" item["summary"] = "diagnosis_diskusage_verylow" elif free_percent < 5 or (mountpoint in ["/", "/var"] and usage.free < 2 * GB): item["status"] = "WARNING" item["summary"] = "diagnosis_diskusage_low" else: item["status"] = "SUCCESS" item["summary"] = "diagnosis_diskusage_ok" yield item def human_size(bytes_): # Adapted from https://stackoverflow.com/a/1094933 for unit in ['','ki','Mi','Gi','Ti','Pi','Ei','Zi']: if abs(bytes_) < 1024.0: return "%s %sB" % (round_(bytes_), unit) bytes_ /= 1024.0 return "%s %sB" % (round_(bytes_), 'Yi') def round_(n): # round_(22.124) -> 22 # round_(9.45) -> 9.4 n = round(n, 1) if n > 10: n = int(round(n)) return n def main(args, env, loggers): return SystemResourcesDiagnoser(args, env, loggers).diagnose()