83 lines
3.0 KiB
Python
83 lines
3.0 KiB
Python
"""ZeroTier reconciliation scheduled job.
|
|
|
|
This module implements the scheduled job for reconciling portal network state
|
|
with the ZeroTier controller. It is designed to be run periodically (every
|
|
1-2 minutes via cron) to:
|
|
|
|
1. Expire activation sessions past their TTL and deauthorize the corresponding ZT members
|
|
2. Sync observed ZeroTier membership state into zerotier_memberships cache
|
|
3. Reconcile portal membership state against ZT controller state
|
|
4. Flag unknown ZT members (not in portal)
|
|
5. Detect and repair drift (ZT says authorized but portal says inactive, and vice versa)
|
|
|
|
Usage:
|
|
python manage.py run_zerotier_reconciliation
|
|
|
|
Or call directly:
|
|
from gatehouse_app.jobs.zerotier_reconciliation_job import run_reconciliation
|
|
run_reconciliation()
|
|
|
|
Cron example (every 2 minutes):
|
|
*/2 * * * * cd /path/to/app && python manage.py run_zerotier_reconciliation
|
|
"""
|
|
|
|
import logging
|
|
from datetime import datetime, timezone
|
|
from typing import Optional
|
|
|
|
from gatehouse_app.services import zerotier_reconciliation_service
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def run_reconciliation() -> dict:
|
|
"""Run full ZeroTier reconciliation across all networks and activations.
|
|
|
|
Returns:
|
|
Dictionary with reconciliation results:
|
|
- expired_activations: number of activation sessions expired
|
|
- networks_processed: number of portal networks reconciled
|
|
- errors: number of networks that had errors
|
|
"""
|
|
logger.info(f"[ZT Reconcile] Starting reconciliation at {datetime.now(timezone.utc).isoformat()}")
|
|
|
|
results = {
|
|
"expired_activations": 0,
|
|
"networks_processed": 0,
|
|
"authorized": 0,
|
|
"deauthorized": 0,
|
|
"deleted_memberships": 0,
|
|
"delete_errors": 0,
|
|
"errors": 0,
|
|
}
|
|
|
|
try:
|
|
expired = zerotier_reconciliation_service.reconcile_expired_activations()
|
|
results["expired_activations"] = expired
|
|
except Exception as exc:
|
|
logger.error(f"[ZT Reconcile] Error expiring activations: {exc}")
|
|
|
|
try:
|
|
summary = zerotier_reconciliation_service.reconcile_all()
|
|
results["networks_processed"] = summary.get("networks_processed", 0)
|
|
results["authorized"] = summary.get("authorized", 0)
|
|
results["deauthorized"] = summary.get("deauthorized", 0)
|
|
results["deleted_memberships"] = summary.get("deleted_memberships", 0)
|
|
results["delete_errors"] = summary.get("delete_errors", 0)
|
|
results["errors"] = summary.get("errors", 0)
|
|
except Exception as exc:
|
|
logger.error(f"[ZT Reconcile] Error during network reconciliation: {exc}")
|
|
results["errors"] += 1
|
|
|
|
logger.info(
|
|
f"[ZT Reconcile] Complete at {datetime.now(timezone.utc).isoformat()}: "
|
|
f"expired={results['expired_activations']} "
|
|
f"networks={results['networks_processed']} "
|
|
f"authorized={results['authorized']} "
|
|
f"deauthorized={results['deauthorized']} "
|
|
f"purged={results['deleted_memberships']} "
|
|
f"errors={results['errors']}"
|
|
)
|
|
|
|
return results
|