changes to the deletion process

This commit is contained in:
2026-08-28 16:11:53 +02:00
parent 01d1fbce92
commit e224741092
2 changed files with 166 additions and 3 deletions
+101
View File
@@ -35,6 +35,7 @@ from datetime import timezone, datetime
import string
import traceback
import io
import time
app = Flask(__name__)
app.secret_key = "ASDfhbsdfseiufhgildsrfrjg874368546987s6e8468f4!?FAUS/&s"
@@ -2334,6 +2335,72 @@ def background_booking_provisioning(
finally:
req_client.close()
def background_tenant_removal(
app_instance,
instance_id,
subdomain
):
"""Hintergrund-Worker, der den Tenant vom Host entfernt und den Status auf 'storniert' setzt."""
with app_instance.app_context():
inst_client, inst_col = _get_collection("instances")
req_client, req_col = _get_collection("instance_requests")
try:
# 1. Zwischenstatus in der Instanz-Collection setzen
inst_col.update_one(
{"_id": ObjectId(instance_id)},
{"$set": {"status": "storniert_wird_entfernt", "nginx_status": "removing"}}
)
# 2. Trigger-Datei für den Host-Watcher erstellen (führt "manage-tenant.sh remove [slug]" aus)
os.makedirs(TRIGGER_DIR, exist_ok=True)
timestamp = int(time.time())
trigger_file = os.path.join(TRIGGER_DIR, f"remove_{subdomain}_{timestamp}.json")
trigger_payload = {
"action": "remove",
"slug": subdomain
}
with open(trigger_file, "w") as f:
json.dump(trigger_payload, f)
print(f"[INFO] Trigger-Datei für Host-Watcher erstellt: {trigger_file}")
# 3. Status der Instanz in 'instances' auf 'storniert' setzen
inst_col.update_one(
{"_id": ObjectId(instance_id)},
{"$set": {
"status": "storniert",
"nginx_status": "inaktiv",
"last_message": "Instanz wurde vom Host entfernt und storniert.",
"updated_at": _utc_now_iso()
}}
)
# 4. Zugehörige Anfrage/Rechnung in 'instance_requests' als gekündigt markieren
# Sucht nach der Verknüpfung über instance_id oder subdomain
req_col.update_many(
{"$or": [{"instance_id": str(instance_id)}, {"subdomain": subdomain}]},
{"$set": {
"provision_status": "gekündigt",
"cancelled_at": _utc_now_iso(),
"last_error": None
}}
)
print(f"[SUCCESS] Instanz {subdomain} erfolgreich storniert/gekündigt.")
except Exception as e:
print(f"[ERROR] Entfernen/Stornieren fehlgeschlagen für {subdomain}:")
traceback.print_exc()
inst_col.update_one(
{"_id": ObjectId(instance_id)},
{"$set": {"status": "error_removing", "last_message": str(e)}}
)
finally:
inst_client.close()
req_client.close()
@app.route('/booking/payment', methods=['GET', 'POST'])
@login_required
@@ -3474,6 +3541,40 @@ def tenant_status():
return jsonify({"status": "pending"}), 200
@app.route('/admin/instances/cancel/<instance_id>', methods=['POST'])
@login_required
def admin_cancel_instance(instance_id):
if not session.get("is_admin") and session.get("role") != "admin":
flash("Zugriff verweigert.", "error")
return redirect(url_for('my_instance_management'))
inst_client, inst_col = _get_collection("instances")
try:
instance = inst_col.find_one({"_id": ObjectId(instance_id)})
if instance:
subdomain = instance.get("subdomain")
# Async-Prozess im Hintergrund starten
app_instance = current_app._get_current_object()
t = threading.Thread(
target=background_tenant_removal,
args=(app_instance, instance_id, subdomain)
)
t.start()
flash(f"Stornierung für '{subdomain}' wurde eingeleitet. Die Instanz wird gelöscht.", "success")
else:
flash("Fehler: Instanz konnte nicht gefunden werden.", "error")
except Exception as e:
print(f"[ERROR] Fehler beim Einleiten der Stornierung: {e}")
flash("Ein Datenbankfehler ist aufgetreten.", "error")
finally:
inst_client.close()
return redirect(url_for('admin_instances'))
@app.route('/admin/test/drop_all_instances', methods=['POST'])
@login_required