Push Tracker
ria-ran--sim-drop/plan/07-scripts.md

160 lines
4.3 KiB
Markdown
Raw Normal View History

# Unit 07 — Operational Scripts
## Goal
CLI scripts for database initialization, subscriber sync, JSON export, and Raspberry Pi WiFi AP setup.
## Files
- `scripts/init_db.py`
- `scripts/sync_subscribers.py`
- `scripts/export_subscribers.py`
- `scripts/setup_wifi_ap.sh`
---
## `scripts/init_db.py`
```python
#!/usr/bin/env python3
"""Initialize the SQLite subscriber database."""
import sys, os
sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
from server.utils import load_config
from server.database import init_db
def main():
config_path = os.environ.get("CONFIG_PATH", "config.yaml")
cfg = load_config(config_path)
db_path = cfg["database"]["path"]
os.makedirs(os.path.dirname(db_path), exist_ok=True)
init_db(db_path)
print(f"Database initialized at {db_path}")
if __name__ == "__main__":
main()
```
---
## `scripts/sync_subscribers.py`
```python
#!/usr/bin/env python3
"""Sync unsynced subscribers to the configured core network."""
import sys, os, logging
sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
from server.utils import load_config
from server.database import get_connection, list_unsynced, mark_synced
from server.core_adapters import get_adapter
logging.basicConfig(level=logging.INFO)
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 in config.")
sys.exit(1)
conn = get_connection(cfg["database"]["path"])
unsynced = list_unsynced(conn)
logger.info(f"Found {len(unsynced)} unsynced subscribers")
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 e:
logger.error(f"Failed to sync {sub.imsi}: {e}")
conn.close()
logger.info(f"Sync complete: {success}/{len(unsynced)} succeeded")
if __name__ == "__main__":
main()
```
---
## `scripts/export_subscribers.py`
```python
#!/usr/bin/env python3
"""Export all subscribers to JSON on stdout."""
import sys, os, json
from datetime import datetime
sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
from server.utils import load_config
from server.database import get_connection, export_all
def main():
config_path = os.environ.get("CONFIG_PATH", "config.yaml")
cfg = load_config(config_path)
conn = get_connection(cfg["database"]["path"])
subscribers = export_all(conn)
conn.close()
output = {
"exported_at": datetime.utcnow().isoformat() + "Z",
"count": len(subscribers),
"subscribers": subscribers
}
print(json.dumps(output, indent=2, default=str))
if __name__ == "__main__":
main()
```
---
## `scripts/setup_wifi_ap.sh`
Raspberry Pi WiFi AP setup. Must be run as root.
Steps:
1. Install packages: `hostapd dnsmasq nginx python3 python3-pip`
2. Configure static IP on `wlan0`: `/etc/dhcpcd.conf` entry `interface wlan0 static ip_address=192.168.4.1/24`
3. Write `/etc/hostapd/hostapd.conf` (SSID=Emergency-5G, open auth, channel 6)
4. Write `/etc/dnsmasq.conf` (DHCP range 192.168.4.10-250, `address=/#/192.168.4.1`)
5. Write nginx site config (proxy `/api/` → Flask, serve portal static)
6. Enable `net.ipv4.ip_forward=1` in `/etc/sysctl.conf`
7. Add iptables rules: all port 80 from `wlan0``192.168.4.1:80` (captive portal)
8. Enable and start: `hostapd`, `dnsmasq`, `nginx`, `esim-provisioning`
9. Install Python dependencies: `pip3 install -r /opt/esim-provisioning/requirements.txt`
10. Print success message and next steps
Script structure:
```bash
#!/bin/bash
set -euo pipefail
[ "$(id -u)" = "0" ] || { echo "Must run as root"; exit 1; }
SSID="Emergency-5G"
CHANNEL=6
AP_IP="192.168.4.1"
DHCP_RANGE="192.168.4.10,192.168.4.250,24h"
INSTALL_DIR="/opt/esim-provisioning"
...
```
---
## Verification
```bash
# init_db
CONFIG_PATH=config.yaml python scripts/init_db.py
# export (after some provisioning)
CONFIG_PATH=config.yaml python scripts/export_subscribers.py | python -m json.tool
# sync (requires core adapter running)
CONFIG_PATH=config.yaml python scripts/sync_subscribers.py
```