Push Tracker
ria-ran--sim-drop/scripts/sync_subscribers.py
A ashkan@beigi.net 8672b0de6b Add Phase-1 eSIM provisioning implementation
Full working closed-loop eSIM provisioning stack (spec in claude.md / plan/):
Flask API, SQLite subscriber store, credential/profile generator, Open5GS
and free5gc core adapters, captive portal, operational scripts, systemd
units, network configs, and a 44-test suite.

Profile generation currently returns a mock JSON profile; real SGP.22
generation via pySim is the planned Phase-2 upgrade.

Fixes two bugs found while getting the suite green:
- generate_imsi hardcoded a 10-digit MSIN, producing 16-digit IMSIs for a
  3-digit MNC; MSIN length is now 15 - len(mcc) - len(mnc).
- check_rate_limit compared timestamps as strings across mismatched formats
  (SQLite CURRENT_TIMESTAMP vs Python isoformat); both sides now normalized
  via SQLite datetime() so the window check is chronologically correct.

Add .gitignore for venv, caches, runtime config.yaml, and databases.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 05:56:31 +00:00

46 lines
1.4 KiB
Python

#!/usr/bin/env python3
"""Sync unsynced subscribers from SQLite to the configured core network."""
import logging
import os
import sys
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from server.core_adapters import get_adapter
from server.database import get_connection, list_unsynced, mark_synced
from server.utils import load_config
logging.basicConfig(level=logging.INFO, format="%(levelname)s %(message)s")
logger = logging.getLogger(__name__)
def main():
config_path = os.environ.get("CONFIG_PATH", "config.yaml")
cfg = load_config(config_path)
adapter = get_adapter(cfg)
if adapter is None:
logger.error("No core adapter configured. Set core.type to 'open5gs' or 'free5gc' in config.")
sys.exit(1)
conn = get_connection(cfg["database"]["path"])
unsynced = list_unsynced(conn)
logger.info(f"Found {len(unsynced)} unsynced subscriber(s)")
success = 0
for sub in unsynced:
try:
adapter.add_subscriber(sub.imsi, sub.ki, sub.opc)
mark_synced(conn, sub.imsi)
success += 1
logger.info(f" Synced {sub.imsi}")
except Exception as exc:
logger.error(f" Failed to sync {sub.imsi}: {exc}")
conn.close()
logger.info(f"Sync complete: {success}/{len(unsynced)} succeeded")
if __name__ == "__main__":
main()