changes to the provisioning
This commit is contained in:
+80
-38
@@ -3640,49 +3640,91 @@ def _utc_now_iso():
|
|||||||
return datetime.now(timezone.utc).isoformat()
|
return datetime.now(timezone.utc).isoformat()
|
||||||
|
|
||||||
def run_tenant_provisioning_async(app, user_id, tenant_slug, school_name, user_email, prov_id):
|
def run_tenant_provisioning_async(app, user_id, tenant_slug, school_name, user_email, prov_id):
|
||||||
# WICHTIG: App Context im Thread aktivieren
|
|
||||||
with app.app_context():
|
with app.app_context():
|
||||||
req_client, req_col = _get_collection("instance_requests")
|
# Hilfsfunktion zum Aktualisieren des Status
|
||||||
try:
|
def _update_prov_status(status, extra_fields=None):
|
||||||
# 1. Status auf 'in_progress' setzen
|
req_client, req_col = _get_collection("instance_requests")
|
||||||
req_col.update_one(
|
try:
|
||||||
{"tenant_slug": tenant_slug},
|
update_data = {
|
||||||
{"$set": {"provision_status": "in_progress", "updated_at": _utc_now_iso()}}
|
"provision_status": status,
|
||||||
)
|
|
||||||
|
|
||||||
# --- HIER DEINE SKRIPTE / INSTANZ-ERSTELLUNG ---
|
|
||||||
# z.B. Datenbank anlegen, Nginx-Config schreiben, Admin-Passwort generieren
|
|
||||||
generated_password = "SecurePassword123!"
|
|
||||||
tenant_url = f"https://{tenant_slug}.invario-software.de"
|
|
||||||
# -----------------------------------------------
|
|
||||||
|
|
||||||
# 2. Bei Erfolg Status auf 'ready' setzen & Zugangsdaten speichern
|
|
||||||
req_col.update_one(
|
|
||||||
{"tenant_slug": tenant_slug},
|
|
||||||
{"$set": {
|
|
||||||
"provision_status": "ready",
|
|
||||||
"url": tenant_url,
|
|
||||||
"admin_user": user_email,
|
|
||||||
"admin_pass": generated_password,
|
|
||||||
"updated_at": _utc_now_iso()
|
"updated_at": _utc_now_iso()
|
||||||
}}
|
}
|
||||||
|
if extra_fields:
|
||||||
|
update_data.update(extra_fields)
|
||||||
|
|
||||||
|
req_col.update_one(
|
||||||
|
{"_id": ObjectId(prov_id)},
|
||||||
|
{"$set": update_data}
|
||||||
|
)
|
||||||
|
finally:
|
||||||
|
req_client.close()
|
||||||
|
|
||||||
|
# 1. Status auf "in_progress" setzen
|
||||||
|
_update_prov_status("in_progress")
|
||||||
|
|
||||||
|
# GESAMTEN PROZESS IN TRY-EXCEPT PACKEN
|
||||||
|
try:
|
||||||
|
# 2. Port dynamisch ermitteln
|
||||||
|
existing_tenants = Instance.list()
|
||||||
|
used_ports = [t['port'] for t in existing_tenants if 'port' in t]
|
||||||
|
next_port = max(used_ports) + 1 if used_ports else 10002
|
||||||
|
|
||||||
|
admin_password = generate_secure_password()
|
||||||
|
|
||||||
|
# 3. Skript für Tenant-Erstellung ausführen
|
||||||
|
success = Instance.new(tenant_slug, next_port, admin_password)
|
||||||
|
if not success:
|
||||||
|
_update_prov_status("failed", {"last_error": "Tenant shell creation failed"})
|
||||||
|
return
|
||||||
|
|
||||||
|
# Module aktivieren
|
||||||
|
Instance.edit(tenant_slug, "starter")
|
||||||
|
|
||||||
|
# 4. Instanz in der Datenbank anlegen
|
||||||
|
domain = f"{tenant_slug}.invario-software.de"
|
||||||
|
instance_doc = {
|
||||||
|
"owner_id": user_id,
|
||||||
|
"school_name": school_name,
|
||||||
|
"subdomain": tenant_slug,
|
||||||
|
"domain": domain,
|
||||||
|
"https_port": next_port,
|
||||||
|
"status": "ready",
|
||||||
|
"nginx_status": "active",
|
||||||
|
"admin_username": "admin",
|
||||||
|
"admin_password": admin_password
|
||||||
|
}
|
||||||
|
|
||||||
|
inst_client, inst_col = _get_collection("instances")
|
||||||
|
try:
|
||||||
|
inst_result = inst_col.insert_one(instance_doc)
|
||||||
|
created_inst_id = str(inst_result.inserted_id)
|
||||||
|
finally:
|
||||||
|
inst_client.close()
|
||||||
|
|
||||||
|
# 5. E-Mail versenden (wird vor dem Status-Update gemacht, damit bei Crash 'failed' ausgelöst wird)
|
||||||
|
send_accreditation_email(
|
||||||
|
recipient=user_email,
|
||||||
|
domain=domain,
|
||||||
|
username="admin",
|
||||||
|
password=admin_password,
|
||||||
|
invoice_pdf_path=f"/var/invoices/{tenant_slug}_invoice.pdf",
|
||||||
|
contract_pdf_path=f"/var/contracts/{tenant_slug}_contract.pdf"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# 6. Request als erfolgreich markieren (WICHTIG: Status "ready" und exakte Felder für Frontend)
|
||||||
|
_update_prov_status("ready", {
|
||||||
|
"instance_id": created_inst_id,
|
||||||
|
"url": f"https://{domain}",
|
||||||
|
"username": "admin",
|
||||||
|
"password": admin_password
|
||||||
|
# Optional: "invoice_url": f"/download/invoice/{tenant_slug}" falls du den PDF-Download im Frontend anbietest
|
||||||
|
})
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# Fehler im Terminal ausgeben und Status auf 'failed' setzen
|
# Wenn irgendetwas im Block abstürzt, Frontend informieren!
|
||||||
print(f"[ERROR] Provisioning fehlgeschlagen für {tenant_slug}: {e}")
|
print(f"[ERROR] Provisioning fehlgeschlagen für {tenant_slug}:")
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
_update_prov_status("failed", {"last_error": str(e)})
|
||||||
req_col.update_one(
|
|
||||||
{"tenant_slug": tenant_slug},
|
|
||||||
{"$set": {
|
|
||||||
"provision_status": "failed",
|
|
||||||
"error_message": str(e),
|
|
||||||
"updated_at": _utc_now_iso()
|
|
||||||
}}
|
|
||||||
)
|
|
||||||
finally:
|
|
||||||
req_client.close()
|
|
||||||
|
|
||||||
@app.route('/booking_payment_async', methods=['POST'])
|
@app.route('/booking_payment_async', methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
@@ -3714,7 +3756,7 @@ def booking_payment_async():
|
|||||||
# Asynchronen Thread starten...
|
# Asynchronen Thread starten...
|
||||||
thread = threading.Thread(
|
thread = threading.Thread(
|
||||||
target=run_tenant_provisioning_async,
|
target=run_tenant_provisioning_async,
|
||||||
args=(app, user_id, tenant_slug, school_name, user_email, prov_id)
|
args=(app._get_current_object(), user_id, tenant_slug, school_name, user_email, prov_id)
|
||||||
)
|
)
|
||||||
thread.start()
|
thread.start()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user