Initial resurrection kit — 81 scripts, 62 references, configs, systemd units, crons, Docker compose files, Caddy config, master README
This commit is contained in:
Executable
+60
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Create a snapshot of ALL running servers in the Hetzner account."""
|
||||
import urllib.request, json, os, sys, time
|
||||
|
||||
API = "https://api.hetzner.cloud/v1"
|
||||
|
||||
# Read token from file to avoid shell issues
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
token_file = os.path.join(script_dir, ".hetzner_token")
|
||||
try:
|
||||
with open(token_file) as f:
|
||||
TOKEN = f.read().strip()
|
||||
except FileNotFoundError:
|
||||
print(f"HETZNER_TOKEN file not found at {token_file}")
|
||||
sys.exit(1)
|
||||
|
||||
HEADERS = {"Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json"}
|
||||
|
||||
def api(path, data=None, method=None):
|
||||
req = urllib.request.Request(f"{API}/{path}", headers=HEADERS, method=method)
|
||||
if data:
|
||||
req.data = json.dumps(data).encode()
|
||||
try:
|
||||
resp = urllib.request.urlopen(req)
|
||||
return json.loads(resp.read()) if resp.status != 204 else {}
|
||||
except urllib.error.HTTPError as e:
|
||||
body = e.read().decode()
|
||||
print(f" ERROR {e.code}: {body}")
|
||||
return None
|
||||
|
||||
# Get all servers
|
||||
servers = api("servers") or {"servers": []}
|
||||
if not servers["servers"]:
|
||||
print("No servers found.")
|
||||
sys.exit(0)
|
||||
|
||||
print(f"Found {len(servers['servers'])} servers\n")
|
||||
for s in servers["servers"]:
|
||||
name = s["name"]
|
||||
sid = s["id"]
|
||||
status = s["status"]
|
||||
|
||||
if status != "running":
|
||||
print(f" SKIP {name:30s} — {status}")
|
||||
continue
|
||||
|
||||
print(f" SNAPSHOT {name:30s} (ID: {sid}) ...", end=" ", flush=True)
|
||||
|
||||
result = api(f"servers/{sid}/actions/create_image", {
|
||||
"type": "snapshot",
|
||||
"description": f"auto-weekly-{name}-{time.strftime('%Y-%m-%d')}"
|
||||
}, method="POST")
|
||||
|
||||
if result:
|
||||
action = result.get("action", {})
|
||||
print(f"started (action {action.get('id', '?')})")
|
||||
else:
|
||||
print("FAILED")
|
||||
|
||||
print("\nDone.")
|
||||
Reference in New Issue
Block a user