Initial commit from Martins Github
This commit is contained in:
325
README.md
325
README.md
@@ -1,2 +1,325 @@
|
||||
# p5g-marvis
|
||||
# P5G Marvis — Full Setup Guide
|
||||
|
||||
This document describes the complete architecture and deployment procedure for the
|
||||
**P5G Marvis** sidebar extension that injects custom pages into the Athonet NCM UI.
|
||||
|
||||
---
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
```
|
||||
Browser → Traefik (HTTPS :443)
|
||||
├── /core/marvis/* → strip prefix → http://127.0.0.1:8100 (p5g-marvis FastAPI)
|
||||
└── /core/radio/* → strip prefix → http://127.0.0.1:4000 (rm-ui, if present)
|
||||
|
||||
NCM UI (React SPA)
|
||||
└── index-Cw8Irsq8.js (patched by patch-ncm.py)
|
||||
├── Sidebar: P5G Marvis (Insights, Actions, Minis, AI) + P5G Radio
|
||||
├── Router: /marvis/* and /radio/* → <iframe> loading the FastAPI pages
|
||||
└── Perms: BW registry entries for /marvis and /radio (Tt = always allowed)
|
||||
|
||||
p5g-marvis FastAPI (port 8100)
|
||||
├── GET /overview → app/ui/overview.html
|
||||
├── GET /minis → app/ui/tasks.html
|
||||
├── GET /actions → app/ui/actions.html
|
||||
├── GET / → app/ui/index.html (catch-all SPA)
|
||||
├── GET /api/network/nf-status → Prometheus metrics
|
||||
├── GET /api/alerts → Alertmanager
|
||||
└── GET /api/actions → log_analyzer service
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Local Files
|
||||
|
||||
All source files live at: `~/p5g-marvis/`
|
||||
|
||||
```
|
||||
~/p5g-marvis/
|
||||
├── patch-ncm.py # Injects sidebar/routes/perms into the NCM JS bundle
|
||||
├── requirements.txt # fastapi==0.115.0, uvicorn[standard]==0.30.6, httpx==0.27.2
|
||||
├── app/
|
||||
│ ├── main.py # FastAPI app — route definitions and UI file serving
|
||||
│ ├── config.py # Reads env vars (prometheus URL, alertmanager URL, AI config)
|
||||
│ ├── ui/
|
||||
│ │ ├── overview.html # P5G Marvis Insights page
|
||||
│ │ ├── tasks.html # P5G Marvis Minis page (action tiles)
|
||||
│ │ ├── actions.html # P5G Marvis Actions page
|
||||
│ │ └── index.html # SPA catch-all
|
||||
│ ├── routers/
|
||||
│ │ ├── actions.py # /api/actions — log analysis
|
||||
│ │ ├── alerts.py # /api/alerts — Alertmanager
|
||||
│ │ ├── network.py # /api/network/nf-status — Prometheus
|
||||
│ │ └── query.py # /api/query — PromQL passthrough
|
||||
│ └── services/
|
||||
│ ├── prometheus.py
|
||||
│ ├── alertmanager.py
|
||||
│ ├── log_analyzer.py
|
||||
│ └── ai.py
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Deployed Hosts
|
||||
|
||||
| Host | IP | Status | P5G Radio |
|
||||
|---|---|---|---|
|
||||
| Primary | 172.27.0.159 | ✅ Deployed | ✅ (rm-ui on :4000) |
|
||||
| Secondary | 192.168.86.150 | ✅ Deployed | ⚠️ No rm-ui container |
|
||||
|
||||
---
|
||||
|
||||
## Deploy / Re-deploy to a Host
|
||||
|
||||
### Prerequisites
|
||||
- SSH key: `~/.ssh/5G-SSH-Key.pem`
|
||||
- Target host must have Python 3.x and the Athonet NCM stack running
|
||||
|
||||
### Step 1 — Copy application files
|
||||
|
||||
```bash
|
||||
TARGET=<IP> # e.g. 172.27.0.159 or 192.168.86.150
|
||||
|
||||
ssh -i ~/.ssh/5G-SSH-Key.pem root@$TARGET 'mkdir -p /opt/p5g-marvis/app/ui /opt/p5g-marvis/app/routers /opt/p5g-marvis/app/services /etc/athonet/traefik/ssl'
|
||||
|
||||
scp -i ~/.ssh/5G-SSH-Key.pem \
|
||||
~/p5g-marvis/requirements.txt ~/p5g-marvis/patch-ncm.py \
|
||||
root@$TARGET:/opt/p5g-marvis/
|
||||
|
||||
scp -i ~/.ssh/5G-SSH-Key.pem \
|
||||
~/p5g-marvis/app/__init__.py ~/p5g-marvis/app/main.py ~/p5g-marvis/app/config.py \
|
||||
root@$TARGET:/opt/p5g-marvis/app/
|
||||
|
||||
scp -i ~/.ssh/5G-SSH-Key.pem ~/p5g-marvis/app/ui/*.html \
|
||||
root@$TARGET:/opt/p5g-marvis/app/ui/
|
||||
|
||||
scp -i ~/.ssh/5G-SSH-Key.pem ~/p5g-marvis/app/routers/*.py \
|
||||
root@$TARGET:/opt/p5g-marvis/app/routers/
|
||||
|
||||
scp -i ~/.ssh/5G-SSH-Key.pem ~/p5g-marvis/app/services/*.py \
|
||||
root@$TARGET:/opt/p5g-marvis/app/services/
|
||||
```
|
||||
|
||||
### Step 2 — Install Python dependencies
|
||||
|
||||
```bash
|
||||
ssh -i ~/.ssh/5G-SSH-Key.pem root@$TARGET '
|
||||
python3 -m ensurepip --upgrade 2>/dev/null
|
||||
python3 -m pip install -r /opt/p5g-marvis/requirements.txt --break-system-packages -q
|
||||
'
|
||||
```
|
||||
|
||||
### Step 3 — Create systemd service
|
||||
|
||||
```bash
|
||||
ssh -i ~/.ssh/5G-SSH-Key.pem root@$TARGET 'cat > /etc/systemd/system/p5g-marvis.service << EOF
|
||||
[Unit]
|
||||
Description=P5G Marvis AI Network Assistant
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
WorkingDirectory=/opt/p5g-marvis
|
||||
Environment=MARVIS_PROMETHEUS_URL=http://127.0.0.1:9090
|
||||
Environment=MARVIS_PROMETHEUS_PREFIX=/prometheus
|
||||
Environment=MARVIS_ALERTMANAGER_URL=http://127.0.0.1:9093
|
||||
Environment=MARVIS_AI_MODE=openai
|
||||
Environment=MARVIS_OPENAI_BASE_URL=https://172.27.0.135:8001
|
||||
Environment=MARVIS_OPENAI_MODEL=gemma-4-26B-A4B-it-UD-Q4_K_S.gguf
|
||||
ExecStart=/usr/bin/python3 -m uvicorn app.main:app --host 0.0.0.0 --port 8100
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
systemctl daemon-reload
|
||||
systemctl enable p5g-marvis
|
||||
systemctl start p5g-marvis'
|
||||
```
|
||||
|
||||
### Step 4 — Create Traefik routing config
|
||||
|
||||
Create `/etc/athonet/traefik/ssl/marvis.yml`:
|
||||
|
||||
```bash
|
||||
ssh -i ~/.ssh/5G-SSH-Key.pem root@$TARGET 'cat > /etc/athonet/traefik/ssl/marvis.yml << EOF
|
||||
http:
|
||||
routers:
|
||||
router-marvis-0:
|
||||
rule: "PathPrefix(\`/core/marvis\`)"
|
||||
service: service-marvis
|
||||
entryPoints:
|
||||
- websecure
|
||||
tls: {}
|
||||
priority: 25
|
||||
middlewares:
|
||||
- cors@http
|
||||
- strip-path-marvis-0
|
||||
|
||||
# Add router-radio-0 here if rm-ui is present (port 4000)
|
||||
|
||||
middlewares:
|
||||
strip-path-marvis-0:
|
||||
stripPrefix:
|
||||
prefixes:
|
||||
- "/core/marvis"
|
||||
|
||||
services:
|
||||
service-marvis:
|
||||
loadBalancer:
|
||||
servers:
|
||||
- url: "http://127.0.0.1:8100"
|
||||
passHostHeader: false
|
||||
EOF'
|
||||
```
|
||||
|
||||
### Step 5 — Add file provider to Traefik static config
|
||||
|
||||
Append to `/etc/athonet/traefik/traefik.yml` under the `providers:` section:
|
||||
|
||||
```yaml
|
||||
file:
|
||||
filename: "/etc/traefik/ssl/marvis.yml"
|
||||
watch: true
|
||||
```
|
||||
|
||||
> **Note**: The path inside the container is `/etc/traefik/ssl/marvis.yml` because the `ssl/` directory is bind-mounted. The host path is `/etc/athonet/traefik/ssl/marvis.yml`.
|
||||
|
||||
```bash
|
||||
ssh -i ~/.ssh/5G-SSH-Key.pem root@$TARGET '
|
||||
grep -q "file:" /etc/athonet/traefik/traefik.yml || (
|
||||
echo " file:" >> /etc/athonet/traefik/traefik.yml
|
||||
echo " filename: \"/etc/traefik/ssl/marvis.yml\"" >> /etc/athonet/traefik/traefik.yml
|
||||
echo " watch: true" >> /etc/athonet/traefik/traefik.yml
|
||||
)
|
||||
docker restart traefik'
|
||||
```
|
||||
|
||||
### Step 6 — Patch the NCM JS bundle
|
||||
|
||||
```bash
|
||||
ssh -i ~/.ssh/5G-SSH-Key.pem root@$TARGET '
|
||||
JS="/etc/athonet/ems-frontend/advanced/assets/index-Cw8Irsq8.js"
|
||||
# Only create .bak if it does not already exist (preserve the clean original)
|
||||
[ -f "$JS.bak" ] || cp "$JS" "$JS.bak"
|
||||
cd /opt/p5g-marvis && python3 patch-ncm.py'
|
||||
```
|
||||
|
||||
Expected output:
|
||||
```
|
||||
Applied: sidebar entry
|
||||
Applied: marvis + radio routes with Or wrapper
|
||||
Applied: /marvis permissions entry
|
||||
Done — P5G Marvis: 10 occurrences, P5G Radio: 3 occurrences
|
||||
```
|
||||
|
||||
If you see `Skipped:` instead of `Applied:`, the patch was already applied from a previous run — this is safe.
|
||||
|
||||
### Step 7 — Verify
|
||||
|
||||
```bash
|
||||
ssh -i ~/.ssh/5G-SSH-Key.pem root@$TARGET '
|
||||
systemctl status p5g-marvis --no-pager | head -5
|
||||
curl -sk http://127.0.0.1:8100/health'
|
||||
```
|
||||
|
||||
Expected: `{"status":"ok"}`
|
||||
|
||||
---
|
||||
|
||||
## Update a UI Page
|
||||
|
||||
To update any UI page (e.g. after editing `tasks.html` locally):
|
||||
|
||||
```bash
|
||||
/usr/bin/scp -i ~/.ssh/5G-SSH-Key.pem \
|
||||
~/p5g-marvis/app/ui/tasks.html \
|
||||
root@<IP>:/opt/p5g-marvis/app/ui/tasks.html
|
||||
```
|
||||
|
||||
No service restart needed — FastAPI reads the file on each request.
|
||||
|
||||
---
|
||||
|
||||
## Re-run the JS Patch (e.g. after an NCM upgrade)
|
||||
|
||||
If NCM is upgraded and the JS bundle is replaced:
|
||||
|
||||
```bash
|
||||
ssh -i ~/.ssh/5G-SSH-Key.pem root@<IP> '
|
||||
JS="/etc/athonet/ems-frontend/advanced/assets/index-Cw8Irsq8.js"
|
||||
# The new build will have a different filename — update patch-ncm.py JS= and BAK= lines
|
||||
# Then create a fresh .bak and re-run
|
||||
cp "$JS" "$JS.bak"
|
||||
cd /opt/p5g-marvis && python3 patch-ncm.py'
|
||||
```
|
||||
|
||||
> **Warning**: Check if the bundle filename changed after the upgrade. The filename is `index-<hash>.js`. Update the `JS` variable at the top of `patch-ncm.py` if it has changed.
|
||||
|
||||
---
|
||||
|
||||
## What the Patch Does (patch-ncm.py)
|
||||
|
||||
The script modifies the minified NCM React JS bundle in 3 places — it always reads from the `.bak` (clean original) ensuring it is safe to re-run:
|
||||
|
||||
1. **Sidebar nav entry** — appends P5G Marvis (with 4 sub-items) and P5G Radio items to the existing top-level navigation after the UPF entry.
|
||||
|
||||
2. **React Router routes** — inserts `/marvis` and `/radio` route objects between the existing UPF and Platform routes. Each renders an iframe pointing to `/core/marvis/<page>` or `/core/radio/`.
|
||||
|
||||
3. **Permissions registry** — registers all `/marvis/*` and `/radio` paths in the BW permissions map with `Tt` (always-allowed), preventing "Permissions for route not managed" errors.
|
||||
|
||||
---
|
||||
|
||||
## P5G Marvis Sidebar Structure
|
||||
|
||||
```
|
||||
P5G Marvis
|
||||
├── P5G Marvis Insights → /marvis/overview → iframes /core/marvis/overview
|
||||
├── P5G Marvis Actions → /marvis/actions → iframes /core/marvis/actions
|
||||
├── P5G Marvis Minis → /marvis/minis → iframes /core/marvis/minis (tasks.html)
|
||||
└── P5G Marvis AI → /marvis/ai → iframes /core/marvis/ (index.html)
|
||||
|
||||
P5G Radio → /radio → iframes /core/radio/ (rm-ui :4000)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Minis Page — Action Tiles (tasks.html)
|
||||
|
||||
### Diagnostics & Health
|
||||
| Tile | Description |
|
||||
|---|---|
|
||||
| Ping All NFs | ICMP probes to all NFs via Prometheus |
|
||||
| Refresh Alerts | Pull latest alerts from Alertmanager |
|
||||
| Full NF Status Report | Query all 12 NF health metrics |
|
||||
| Trace UE Data Path | Trace AMF→SMF→UPF path for a sample SUPI |
|
||||
|
||||
### Network Operations
|
||||
| Tile | Description |
|
||||
|---|---|
|
||||
| Perform Emulated Data Session | Full attach + data session end-to-end test (non-disruptive) |
|
||||
| Check Connected Devices | Query AMF/UPF state and report registration status |
|
||||
| Generate Capacity Report | Device counts, bandwidth utilisation, peak hour trends |
|
||||
| Clear All UE Sessions | Force-release all active sessions (**requires confirmation**) |
|
||||
|
||||
### Maintenance
|
||||
| Tile | Description |
|
||||
|---|---|
|
||||
| Backup Configuration | Export configs for all NFs to timestamped archive |
|
||||
| Reload Configuration | Reload from disk without restarting services |
|
||||
| Purge Old Logs | Delete log files older than 7 days |
|
||||
| Export Debug Bundle | Collect and compress NF logs, configs, metrics |
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Problem | Check |
|
||||
|---|---|
|
||||
| Sidebar items not visible | Browser hard-refresh (Cmd+Shift+R). Confirm patch ran successfully. |
|
||||
| Clicking sidebar shows blank page | Traefik routing — check `docker logs traefik`. `marvis.yml` must be present and file provider added to `traefik.yml`. |
|
||||
| Service won't start | `journalctl -u p5g-marvis -n 50`. Usually a missing Python package. |
|
||||
| Metrics not loading | Confirm Prometheus is on `127.0.0.1:9090` — check `MARVIS_PROMETHEUS_URL` env var in the service file. |
|
||||
| patch-ncm.py: ERROR anchor not found | The NCM JS bundle was upgraded and the filename/content changed. Find new anchors in the `.bak` file and update `patch-ncm.py`. |
|
||||
| After NCM upgrade patch not applied | Re-run Step 6 — but first check if the bundle filename changed. |
|
||||
|
||||
Reference in New Issue
Block a user