import docker _client = None def _c(): global _client if _client is None: _client = docker.DockerClient(base_url="unix:///var/run/docker.sock", timeout=15) return _client def host_info(): try: import shutil client = _c() info = client.info() containers = client.containers.list(all=True, sparse=True) running = sum(1 for c in containers if c.status == "running") images = len(client.images.list()) mem_total = info.get("MemTotal", 0) mem_used = 0 try: with open("/proc/meminfo") as f: mem = {} for line in f.read().splitlines(): if ":" in line: parts = line.split() mem[parts[0].rstrip(":")] = int(parts[1]) * 1024 mem_total = mem.get("MemTotal", mem_total) mem_used = mem_total - mem.get("MemAvailable", mem.get("MemFree", 0)) except Exception: pass disk_total = disk_used = 0 try: d = shutil.disk_usage("/") disk_total, disk_used = d.total, d.used except Exception: pass return { "name": info.get("Name", "?"), "os": info.get("OperatingSystem", "?"), "version": info.get("ServerVersion", "?"), "kernel": info.get("KernelVersion", "?"), "cpu": info.get("NCPU", 0), "memory": mem_total, "mem_used": mem_used, "mem_total": mem_total, "running": running, "containers": len(containers), "images": images, "disk_total": disk_total, "disk_used": disk_used, "storage": info.get("DriverStatus", [["?", "?"]])[0][1] if info.get("DriverStatus") else "?", "error": None, } except Exception as e: return {"name": "?", "running": 0, "containers": 0, "images": 0, "error": str(e)} def list_containers(): try: client = _c() return [ { "id": c.short_id, "name": c.name, "image": c.image.tags[0] if c.image.tags else c.image.short_id[:19], "status": c.status, "ports": c.ports, "created": c.attrs.get("Created", "")[:19], } for c in client.containers.list(all=True) ] except Exception as e: return {"error": str(e)} def list_images(): try: client = _c() return [{"id": i.short_id, "tags": i.tags, "size": i.attrs.get("Size", 0)} for i in client.images.list()] except Exception as e: return {"error": str(e)} def container_action(cid, action): try: client = _c() c = client.containers.get(cid) if action == "start": c.start() elif action == "stop": c.stop(timeout=10) elif action == "restart": c.restart(timeout=10) else: return {"error": f"unknown action {action}"} return {"status": f"{action}ed", "name": c.name} except Exception as e: return {"error": str(e)} def container_stats(cid): try: client = _c() c = client.containers.get(cid) s = c.stats(stream=False) mem_usage = s["memory_stats"].get("usage", 0) mem_limit = s["memory_stats"].get("limit", 1) cpu_delta = s["cpu_stats"]["cpu_usage"]["total_usage"] - s["precpu_stats"]["cpu_usage"]["total_usage"] system_delta = s["cpu_stats"]["system_cpu_usage"] - s["precpu_stats"]["system_cpu_usage"] cpu_percent = (cpu_delta / system_delta) * 100.0 * s["cpu_stats"].get("online_cpus", 1) if system_delta > 0 else 0 return { "memory_usage": mem_usage, "memory_limit": mem_limit, "memory_pct": round(mem_usage / mem_limit * 100, 1) if mem_limit else 0, "cpu_pct": round(cpu_percent, 1), "pids": s["pids_stats"].get("current", 0), "network_rx": s.get("networks", {}).get("eth0", {}).get("rx_bytes", 0), "network_tx": s.get("networks", {}).get("eth0", {}).get("tx_bytes", 0), } except Exception as e: return {"error": str(e)}