Skip to content

Repository files navigation

swf-remote

External PanDA production monitoring frontend for the ePIC experiment at the Electron Ion Collider. Provides open-internet access to PanDA monitoring services that live behind BNL's firewall.

Live at https://epic-devcloud.org/

Architecture

Browser → epic-devcloud.org (Django/Apache)
              ↓ proxy (full rendered HTML)
          SSH tunnel (autossh, persistent)
              ↓
          swf-monitor (BNL) → PanDA database
  • Web pages — the hub, all PanDA views, and all PCS views — are proxied as full rendered HTML from swf-monitor through the SSH tunnel (remote_app/monitor_client.proxy), which rewrites swf-monitor URLs to local /prod/ paths and swaps in local auth controls. Same URL structure. Only swf-remote's own pages render locally (see Local vs proxied pages).
  • MCP relay at /prod/mcp/ forwards swf-monitor's MCP endpoint, its full tool set, through the tunnel as the signed-in user. Headless clients authenticate with a per-user token (see Live-data access).
  • No local PanDA data — all data comes from swf-monitor in real time.
  • TeamComms — HTTP, MCP and streaming under /prod/teamcomms/, using existing devcloud accounts and tokens. The integration contract describes authentication, AI identity, introspection and deployment.

Sister projects

  • swf-monitor — Django web service at BNL with PanDA DB access, REST API, MCP server
  • swf-testbed — Streaming workflow testbed orchestration and agents
  • swf-common-lib — Shared utilities for SWF agents

Pages

Path Description
/ PanDA Hub — links to all monitoring views
/panda/activity/ Activity overview — job/task counts by status, user, site
/panda/jobs/ Job list with DataTables filtering and search
/panda/jobs/<pandaid>/ Job detail — full record, files, errors, log URLs
/panda/tasks/ JEDI task list with DataTables filtering
/panda/tasks/<taskid>/ Task detail with constituent jobs
/panda/errors/ Error summary — top patterns ranked by frequency
/panda/diagnostics/ Failed jobs with full error details
/snapper/<scope>/report/ Coherent operational state snaps and history
/snapper/<scope>/system/ Snapper capture policy, scheduler, and component registry
/system/ Aggregate SWF system health
/mcp/ MCP relay to swf-monitor (POST JSON-RPC, token only), limited to the external tool set in remote_app/mcp_policy.py; GET serves the self-contained setup page
/account/tokens/ Create and revoke API tokens

Setup

Development

# Clone both repos side by side
git clone https://github.com/BNLNPPS/swf-remote.git
git clone https://github.com/BNLNPPS/swf-monitor.git

# Set up dev environment (venv, symlinks to swf-monitor templates)
cd swf-remote
bash setup-dev.sh

# Set up database and .env
bash setup-server.sh

# Run dev server
cd src && ../.venv/bin/python manage.py runserver

Production

# Full deploy: rsync, venv, deps, symlinks, migrations, Apache, SSL
bash deploy/setup-apache.sh

# SSL (after DNS is pointing to the server)
sudo certbot --apache -d epic-devcloud.org

SSH tunnel

The tunnel is managed by systemd via autossh. See deploy/swf-remote-tunnel.service. Requires SSH key access from the hosting server to swf-monitor's host via an SSH gateway.

sudo cp deploy/swf-remote-tunnel.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now swf-remote-tunnel
sudo systemctl status swf-remote-tunnel

Stack

  • Django 5.2 (Python 3.11) — upgrading to Django 6.0 / Python 3.12 after OS upgrade
  • PostgreSQL (local, for Django internals only)
  • Apache + mod_wsgi
  • httpx for upstream REST calls
  • autossh + systemd for persistent SSH tunnel
  • Let's Encrypt for HTTPS

Configuration

Environment variables prefixed SWF_REMOTE_ to avoid collisions with other apps on the same server. See .env.example.

Live-data access

Every proxied page is built by swf-monitor and fetched over the tunnel, so viewing one requires an account. Anonymous visitors reach a locally rendered landing page, the login path, and static assets; everything else redirects to sign-in. An account is established either by a local username and password or by signing in with GitHub, which creates it on first use. Signing in is all that reading requires. Acting on the production system requires authority, held as two attributes on the account in swf-monitor and enforced there: observed eic organization membership, and granted rights. A command-line client authenticates with a per-user token created on /prod/account/tokens/ and sent as Authorization: Bearer <token>; it reaches swf-monitor as that user. The cross-component policy is defined in Live-data access policy.

Local vs proxied pages

Most pages — the hub, all PanDA views, Alarms, and all PCS views — are served as full rendered HTML proxied from swf-monitor (remote_app/views.py), so they carry swf-monitor's own templates, nav, and styling. swf-remote renders a smaller set itself using its own base.html: the MCP setup page, the tokens page, and the login / password-change pages. Their nav is swf-monitor's own, taken from the production hub through the tunnel (monitor_client.nav_html), rewritten to local paths with local auth controls like every proxied page, and cached for a minute; the last fetched copy stands in during a tunnel outage. swf-remote holds no nav markup, so the monitor's nav is the only one. Alarm code from the old local implementation remains in the tree for rollback/reference, but live /prod/alarms/... pages proxy to swf-monitor.

The proxy (monitor_client.proxy) preserves swf-monitor's page body and <style>, rewriting only URLs and the auth controls — so swf-monitor's own nav and styling reach the browser intact on proxied pages.

swf-remote keeps a symlink to swf-monitor's templates (created by setup-dev.sh) for the shared assets the local pages pull in. URL names use app_name = 'monitor_app' so {% url %} tags resolve to swf-remote's own routes.

About

Streaming workflow remote services

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages