Skip to content

tomkane-dls/usbip-web

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

usbip recovery

A small page hosted on the Raspberry Pi that shows what usbip devices are exported and lets an operator flush a stale export (unbind → rebind) without physically reaching the bus.

It exists to supply the one operation the DRA driver can't: recovering a device left wedged in exported/used state after a node client dies uncleanly (the Device busy (exported) / FailedPrepareDynamicResources crash loop). Flush the device on the Pi and the driver's own retry loop reattaches it — the cluster heals itself.

What it does and doesn't claim

The Pi can only see mechanical state, never cluster intent, so the page is deliberately honest about its blind spot:

  • available (status 1) — in the pool. Unambiguous.
  • in use (status 2, no extra evidence) — could be a healthy attachment or a stale ghost; the status value alone can't tell them apart. Flushable, but the UI asks you to confirm a node is actually crash-looping first.
  • likely stale (amber) — status 2 plus either a surplus (more devices in use than there are live connections, so at least one is provably a ghost) or repeated attach failures naming that busid in usbipd's own journal.

The operator bridges Pi state and cluster intent — read the failing claim / ArgoCD error for the busid, then flush. The page never touches Kubernetes.

Setup (Pi, Debian Bookworm, Python 3.13)

System pip is absent and Python is externally-managed, so use a venv:

sudo apt install -y python3-venv          # if venv creation complains
git clone <this> /home/local/usbip-web    # or copy the files there
cd /home/local/usbip-web
python3 -m venv venv
./venv/bin/pip install fastapi uvicorn

Run it directly to try it:

./venv/bin/uvicorn app:app --host 0.0.0.0 --port 8080

Then visit http://<pi-ip>:8080/.

Install as a service

sudo cp usbip-web.service /etc/systemd/system/
# EDIT the file first: pin --host to the Pi's beamline IP, fix paths/user.
sudo systemctl daemon-reload
sudo systemctl enable --now usbip-web

Develop / demo without a Pi

FakeBackend serves a representative device set (the real ambiguous beamline case plus a nested extender hub) and mutates on flush, so the whole UI works on a laptop:

./venv/bin/python app.py --fake          # or USBIP_WEB_FAKE=1 uvicorn app:app ...

Tests

python3 test_usbip.py

All logic runs against FakeBackend, so no hardware is needed. The only thing to verify on a real Pi is that RealBackend's five primitives read the box correctly (sysfs status, ss connection count, journalctl lines, device descriptors, and the usbip flush).

Security model

No authentication — being on the beamline network is the gate. That is only safe because the only privileged action exposed is flushing a device the Pi currently sees. The real boundary is in the code, not a login page:

  • the busid is validated against the live device set before any usbip command runs (a busid the Pi doesn't currently see is refused);
  • commands are always argv lists, never a shell — no user string reaches a shell.

This matters because the service account has passwordless-root sudo, so input validation is what keeps "no auth" safe. Hardening worth doing: narrow that sudo to just the two usbip commands rather than ALL, e.g.

local ALL=(root) NOPASSWD: /usr/sbin/usbip unbind -b *, /usr/sbin/usbip bind -b *

so even a bug in the app can't run arbitrary root commands.

Files

  • backend.py — the system seam: UsbipBackend + RealBackend + FakeBackend
  • usbip.py — pure logic: topology tree, classification, log correlation
  • app.py — FastAPI: the page + three endpoints
  • index.html — the operator page
  • test_usbip.py — unit tests
  • usbip-web.service — systemd unit

About

fastapi web interface for monitoring usbip dra devices on a raspberry pi

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors