Initial provisioning client

This commit is contained in:
Thomas Stallinger 2026-06-14 21:29:45 +02:00
commit 37e8bb1d55
2 changed files with 113 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
__pycache__/
*.pyc
/tmp/

110
provisioning-client.py Normal file
View File

@ -0,0 +1,110 @@
import json
import socket
import urllib.request
BASE_URL = "https://anode.stallinux.de"
CLIENT_VERSION = "0.1.0"
SELECTION_PATH = "/tmp/provisioning-selection.json"
def get_machine_id():
try:
with open("/etc/machine-id", "r", encoding="utf-8") as f:
return f.read().strip()
except FileNotFoundError:
return "unknown"
def request_json(method, path, data=None):
body = None
headers = {"Content-Type": "application/json"}
if data is not None:
body = json.dumps(data).encode("utf-8")
req = urllib.request.Request(
BASE_URL + path,
data=body,
headers=headers,
method=method,
)
with urllib.request.urlopen(req, timeout=15) as response:
return json.loads(response.read().decode("utf-8"))
hostname = socket.gethostname()
machine_id = get_machine_id()
activation_code = input("Aktivierungscode: ").strip()
activate_payload = {
"activation_code": activation_code,
"hostname": hostname,
"machine_id": machine_id,
"client_version": CLIENT_VERSION,
}
result = request_json("POST", "/api/v1/activate", activate_payload)
if not result.get("success"):
print("Aktivierung fehlgeschlagen:")
print(result.get("message", "Unbekannter Fehler"))
raise SystemExit(1)
profiles = result["profiles"]
print()
print("Aktivierung erfolgreich.")
print("Kunde:", result["customer"]["name"])
print()
print("Verfügbare Profile:")
for index, profile in enumerate(profiles, start=1):
print(f"{index}) {profile['label']} ({profile['distribution']} {profile['version']})")
print()
choice = input("Profil wählen: ").strip()
try:
choice_index = int(choice) - 1
selected_profile = profiles[choice_index]
except (ValueError, IndexError):
print("Ungültige Auswahl.")
raise SystemExit(1)
bootstrap_result = request_json(
"GET",
f"/api/v1/profiles/{selected_profile['id']}/bootstrap"
)
if not bootstrap_result.get("success"):
print("Bootstrap-Konfiguration konnte nicht geladen werden:")
print(bootstrap_result.get("message", "Unbekannter Fehler"))
raise SystemExit(1)
selection = {
"customer_id": result["customer"]["id"],
"customer_name": result["customer"]["name"],
"hostname": hostname,
"machine_id": machine_id,
"profile": bootstrap_result["profile"],
"installer": bootstrap_result["installer"],
"ansible": bootstrap_result["ansible"],
"ssh": bootstrap_result["ssh"]
}
with open(SELECTION_PATH, "w", encoding="utf-8") as f:
json.dump(selection, f, indent=2)
print()
print("Bootstrap-Konfiguration geladen.")
print("Auswahl gespeichert:")
print(SELECTION_PATH)
print()
print("Profil:", selection["profile"]["label"])
print("Installer:", selection["installer"]["type"])
print("Installer URL:", selection["installer"]["url"])
print("Ansible Repo:", selection["ansible"]["repo"])