125 lines
4.2 KiB
Python
125 lines
4.2 KiB
Python
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)}
|