114 lines
3.7 KiB
Python
114 lines
3.7 KiB
Python
|
|
#!/usr/bin/env python3
|
||
|
|
import json
|
||
|
|
import sys
|
||
|
|
import os
|
||
|
|
import yaml
|
||
|
|
from pathlib import Path
|
||
|
|
|
||
|
|
def generate_inventory(discovery_data):
|
||
|
|
hostname = discovery_data.get("hostname", "unknown-node")
|
||
|
|
host_dir = Path(f"hosts/{hostname}")
|
||
|
|
host_dir.mkdir(parents=True, exist_ok=True)
|
||
|
|
|
||
|
|
# 1. host.yaml
|
||
|
|
host_yaml = {
|
||
|
|
"hostname": hostname,
|
||
|
|
"roles": ["unassigned"],
|
||
|
|
"network": {
|
||
|
|
"tailscale_ip": discovery_data["network"]["tailscale"]["ip"]
|
||
|
|
},
|
||
|
|
"runtime": {
|
||
|
|
"root": "/opt/homelab"
|
||
|
|
},
|
||
|
|
"deployment": {
|
||
|
|
"mode": "pull",
|
||
|
|
"managed_by": "saturn"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
with open(host_dir / "host.yaml", "w") as f:
|
||
|
|
yaml.dump(host_yaml, f, sort_keys=False)
|
||
|
|
|
||
|
|
# 2. capabilities.yaml
|
||
|
|
capabilities_yaml = {
|
||
|
|
"capabilities": {
|
||
|
|
"hardware": {
|
||
|
|
"cpu": {
|
||
|
|
"arch": discovery_data["os"]["arch"],
|
||
|
|
"cores": discovery_data["hardware"]["cpu"]["cores"],
|
||
|
|
"threads": discovery_data["hardware"]["cpu"]["threads"]
|
||
|
|
},
|
||
|
|
"memory": {
|
||
|
|
"total_gb": discovery_data["hardware"]["memory"]["total_gb"]
|
||
|
|
},
|
||
|
|
"acceleration": {
|
||
|
|
"type": "gpu" if discovery_data["hardware"]["gpu"]["present"] else "none"
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"virtualization": {
|
||
|
|
"supported": discovery_data["virtualization"]["supported"],
|
||
|
|
"type": discovery_data["virtualization"]["type"]
|
||
|
|
},
|
||
|
|
"storage": {
|
||
|
|
"persistence": "persistent",
|
||
|
|
"type": "ssd", # Default assumption
|
||
|
|
"capacity_gb": sum([float(d["size"].rstrip("G")) for d in discovery_data["hardware"]["disks"] if "G" in d["size"]]) # Very rough estimate
|
||
|
|
},
|
||
|
|
"networking": {
|
||
|
|
"reachability": "tailscale-only" if discovery_data["network"]["tailscale"]["status"] == "active" else "direct",
|
||
|
|
"ingress_suitability": False,
|
||
|
|
"bandwidth": "unknown"
|
||
|
|
},
|
||
|
|
"runtime": {
|
||
|
|
"container_engine": "docker" if discovery_data["docker"]["available"] else "none",
|
||
|
|
"os": discovery_data["os"]["distro"]
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
with open(host_dir / "capabilities.yaml", "w") as f:
|
||
|
|
yaml.dump(capabilities_yaml, f, sort_keys=False)
|
||
|
|
|
||
|
|
# 3. paths.yaml
|
||
|
|
paths_yaml = {
|
||
|
|
"host": hostname,
|
||
|
|
"runtime_root": "/opt/homelab",
|
||
|
|
"conventions": {
|
||
|
|
"services": "/opt/homelab/services",
|
||
|
|
"data": "/opt/homelab/data",
|
||
|
|
"config": "/opt/homelab/config",
|
||
|
|
"logs": "/opt/homelab/logs"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
with open(host_dir / "paths.yaml", "w") as f:
|
||
|
|
yaml.dump(paths_yaml, f, sort_keys=False)
|
||
|
|
|
||
|
|
# 4. networking.yaml
|
||
|
|
networking_yaml = {
|
||
|
|
"host": hostname,
|
||
|
|
"uplink": {
|
||
|
|
"type": "unknown",
|
||
|
|
"connectivity": "unknown"
|
||
|
|
},
|
||
|
|
"tailscale": {
|
||
|
|
"enabled": True if discovery_data["network"]["tailscale"]["status"] == "active" else False,
|
||
|
|
"host_ip": discovery_data["network"]["tailscale"]["ip"],
|
||
|
|
"role": "internal-management"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
with open(host_dir / "networking.yaml", "w") as f:
|
||
|
|
yaml.dump(networking_yaml, f, sort_keys=False)
|
||
|
|
|
||
|
|
print(f"Inventory generated for {hostname} in {host_dir}")
|
||
|
|
|
||
|
|
def main():
|
||
|
|
if len(sys.argv) > 1:
|
||
|
|
with open(sys.argv[1], "r") as f:
|
||
|
|
data = json.load(f)
|
||
|
|
else:
|
||
|
|
# Read from stdin
|
||
|
|
data = json.load(sys.stdin)
|
||
|
|
|
||
|
|
generate_inventory(data)
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
main()
|