Einstieg Schritt 1: Art der Organisation bringt Standard-Workspace mit, Ausrollstufe stabil heißt testing

Migration 0073: kundengruppen.standard_workspace_id (Schule: Schulcomputer
(Mint)); neue Organisationen bekommen Bereitstellungsvorlage und Workspace an
"Neue Geräte". Ausrollstufe 'stabil' -> 'testing' (Repo/Spiegel bleiben).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
adminandClaude Opus 5.5 committed 2026-10-25 12:36:55 +01:00
1 parent 2a734497ed
commit 5210186126
2 files changed
+86 -4

No files matched your search

+55 -4
View File
@@ -48,7 +48,11 @@ ANSIBLE_CONTENT_REPO = os.environ.get("TUXFLOTTE_ANSIBLE_CONTENT_REPO", "")
ANSIBLE_CONTENT_REPO_STABIL = os.environ.get("TUXFLOTTE_ANSIBLE_CONTENT_REPO_STABIL", "") or (
re.sub(r"(\.git)?$", r"-stabil\1", ANSIBLE_CONTENT_REPO, count=1) if ANSIBLE_CONTENT_REPO else ""
)
AUSROLLSTUFEN = ("stabil", "vorab")
# Seit 25.10.2026 (Migration 0073) heißt die freigegebene Stufe "testing"
# (Testschulen); Spiegel und Repo heißen weiter "stabil". Eine Stufe
# "stabil" für zahlende Kunden, die selbst über das Einspielen entscheiden,
# kommt später (platform-docs roadmap/einstieg-vereinfachen.md).
AUSROLLSTUFEN = ("testing", "vorab")
# Spiegel für Geräte (ADR-0046, 20.10.2026): anode hält Spiegel von
# ansible-content (je Ausrollstufe) und provisioning-agent, erzeugt je Stand
# ein Archiv und liefert beides nur gegen das Agent-Secret aus. Damit hängen
@@ -3888,7 +3892,11 @@ def fetch_organizations():
]
def ausrollstufe_fuer_geraet(device_id: str) -> str:
"""Ausrollstufe der Organisation des Geräts. Unbekanntes Gerät: stabil."""
"""
Spiegel-Stufe für das Gerät: "vorab" oder "stabil" (das freigegebene
Repo, für Organisationen mit Ausrollstufe "testing"). Unbekanntes Gerät:
stabil.
"""
with get_database_connection() as conn:
with conn.cursor() as cur:
@@ -4141,6 +4149,7 @@ def fetch_organization(organization_id: str):
def create_organization(name: str, kundengruppe_id: str | None = None):
organization_id = uuid4()
standard_oe_id = uuid4()
with get_database_connection() as conn:
with conn.cursor() as cur:
@@ -4157,10 +4166,52 @@ def create_organization(name: str, kundengruppe_id: str | None = None):
INSERT INTO organisationseinheiten (id, organization_id, parent_id, name, ist_standard)
VALUES (%s, %s, NULL, %s, TRUE)
""",
(uuid4(), organization_id, STANDARD_OE_NAME),
(standard_oe_id, organization_id, STANDARD_OE_NAME),
)
standard = standard_ausstattung_anlegen(cur, organization_id, standard_oe_id, kundengruppe_id)
return {"id": str(organization_id), "name": name}
return {"id": str(organization_id), "name": name, "standard_workspace": standard}
def standard_ausstattung_anlegen(cur, organization_id, standard_oe_id, kundengruppe_id) -> str | None:
"""
Einstieg vereinfachen, Schritt 1 (25.10.2026): Hat die Art der
Organisation (Kundengruppe) einen Standard-Workspace, bekommt die neue
Organisation sofort eine Bereitstellungsvorlage dafür (Distro des
Workspace, eine Partition, ext4) und den Workspace an "Neue Geräte".
Der Kunde kann damit gleich ein Medium bauen. Gibt den Namen des
Workspace zurück oder None.
"""
if not kundengruppe_id:
return None
cur.execute(
"""
SELECT w.id, w.name, w.backend_id
FROM kundengruppen k JOIN workspaces w ON w.id = k.standard_workspace_id
WHERE k.id = %s AND w.backend_id IS NOT NULL
""",
(kundengruppe_id,),
)
row = cur.fetchone()
if row is None:
return None
workspace_id, workspace_name, backend_id = row
partitioning = {"scheme": "single", "root_filesystem": "ext4", "target_disk_rank": 1, "extra_partitions": []}
cur.execute(
"""
INSERT INTO bereitstellungsvorlagen
(id, organization_id, workspace_id, backend_id, label, is_default,
disk_encryption, partitioning, secure_boot_required)
VALUES (%s, %s, %s, %s, %s, TRUE, FALSE, %s, FALSE)
""",
(uuid4(), organization_id, workspace_id, backend_id, workspace_name, Jsonb(partitioning)),
)
cur.execute(
"UPDATE organisationseinheiten SET workspace_id = %s, automatisch_aktualisieren = TRUE WHERE id = %s",
(workspace_id, standard_oe_id),
)
return workspace_name
def update_organization(organization_id: str, name: str, kontaktfelder: dict):
with get_database_connection() as conn:
@@ -0,0 +1,31 @@
BEGIN;
-- Einstieg vereinfachen, Schritt 1 (platform-docs roadmap/einstieg-
-- vereinfachen.md, Entscheidungen 25.10.2026).
--
-- 1. Jede Art von Organisation (Kundengruppe) bekommt einen Standard-
-- Workspace. Eine neue Organisation dieser Art bekommt damit beim Anlegen
-- ihre Bereitstellungsvorlage und den Workspace an "Neue Geräte", ohne
-- weitere Handgriffe. Schule: "Schulcomputer (Mint)"; Unternehmen noch
-- keiner.
-- 2. Drei Ausrollstufen: Vorab (Tuxflotte), Testing (Testschulen), Stabil
-- (zahlende Kunden, kommt später). Die bisherige Stufe "stabil" ist
-- inhaltlich "Testing" und wird umbenannt; Repo und Spiegel bleiben.
ALTER TABLE kundengruppen
ADD COLUMN standard_workspace_id UUID REFERENCES workspaces(id) ON DELETE SET NULL;
UPDATE kundengruppen
SET standard_workspace_id = (
SELECT id FROM workspaces
WHERE name = 'Schulcomputer (Mint)' AND organization_id IS NULL AND backend_id IS NOT NULL
)
WHERE key = 'schule';
ALTER TABLE organizations DROP CONSTRAINT organizations_ausrollstufe_check;
UPDATE organizations SET ausrollstufe = 'testing' WHERE ausrollstufe = 'stabil';
ALTER TABLE organizations ALTER COLUMN ausrollstufe SET DEFAULT 'testing';
ALTER TABLE organizations ADD CONSTRAINT organizations_ausrollstufe_check
CHECK (ausrollstufe IN ('testing', 'vorab'));
COMMIT;