No project description provided
Project description
Remote Lab Manager
Run Netlab topologies on a remote host while keeping your pytest suite local. The service exposes a small REST API that schedules exclusive sessions in a FIFO queue so your CI jobs or multiple developers can share the same infrastructure safely.
✨ Key Points
- One-lab rule – only one Netlab topology may run per host; the manager enforces this with a queue and automatic reference counting.
- Zero-config client – set a single environment variable and your existing fixtures will transparently switch to remote mode.
- Stateless HTTP API – every request is authenticated via an
X-Session-IDheader issued when the session is created. - Python client available – import
RemoteLabClientfor programmatic use.
You to author tests that consume these labs? See the Testing Framework guide: /development/testing-framework/
For secure reachability to the Remote Lab subnet(s) using Tailscale clients managed by a self‑hosted control plane, see: Headscale + Headplane with Docker Compose.
🚀 Quick-Start
1. Start the Server
Native Python
# Install deps (inside a venv)
poetry install --extras remote-lab # includes FastAPI, Uvicorn, etc.
# Run the service
poetry run remote_lab --host 0.0.0.0 --port 8000 --log-level info
2. Configure Your Tests
export REMOTE_LAB_URL=http://<host>:8000
# Hetzner neops-labs VM:
export REMOTE_LAB_URL=http://91.99.184.46:8000
# Optional: put this into a .env file – test suite auto-loads it via python-dotenv
3. Run pytest as usual
pytest tests/function_blocks/
If REMOTE_LAB_URL is set the fixtures automatically use the remote server;
otherwise they fall back to local netlab execution.
🔌 REST API
| Method & Path | Purpose | Notes |
|---|---|---|
POST /session |
Create a new queue entry | Returns 201 with session_id & current position |
GET /session/{id} |
Poll session state | status: waiting/active, queue position |
GET /active-session |
Get active session details | Returns 200 with session_id, status and position |
DELETE /session/{id} |
End a session prematurely | Frees lab if active, returns 204 |
POST /session/heartbeat |
Keep-alive | Must include X-Session-ID header, returns 204 |
POST /lab |
Upload topology & acquire lab | multipart/form-data; `reuse=true |
GET /lab |
Lab status & device list | Only valid for active sessions |
GET /lab/devices |
Shortcut to device list | – |
POST /lab/release |
Decrement ref-count | If it drops to zero the lab becomes idle |
DELETE /lab?force=true |
Destroy lab | 202 accepted; force=false fails if busy |
GET /healthz |
Liveness check | 204 No Content |
⚠️ All
/lab*endpoints require theX-Session-IDheader of an active session. Non-active sessions receive423 Locked.
ℹ️ A debug-only endpoint
GET /debug/healthreturns rich server stats (uptime, queue length, etc.) and is useful during development.
🛠️ Example cURL Session
# 1) Create session
SESSION=$(curl -s -X POST http://localhost:8000/session | jq -r .session_id)
# 2) Wait until it becomes ACTIVE (simplified polling)
while true; do
STATUS=$(curl -s http://localhost:8000/session/$SESSION | jq -r .status)
[[ $STATUS == "active" ]] && break
sleep 2
done
# 3) Upload topology & acquire lab
curl -X POST http://localhost:8000/lab \
-H "X-Session-ID: $SESSION" \
-F "topology=@tests/topologies/simple_frr.yml" \
-F "reuse=true"
# Optionally attach supporting files (repeatable)
# -F "extra_files=@path/to/vars.yml" -F "extra_files=@path/to/your_special_config.yml"
# 4) Release when finished
curl -X POST http://localhost:8000/lab/release -H "X-Session-ID: $SESSION"
# 5) End session
curl -X DELETE http://localhost:8000/session/$SESSION
⚙️ Environment Variables
| Variable | Description | Default |
|---|---|---|
REMOTE_LAB_URL |
Base URL used by client and fixtures | – |
🧹 House-Keeping & Timeouts
- Waiting sessions – dropped after 600 s without a heartbeat.
- Active sessions – deemed stale after 300 s of silence; the lab is cleaned up and the next session in queue is promoted.
- Cleanup cadence – adaptive background task: ~5 s when busy, ~15 s with a single active session, ~30 s when idle.
Constants are defined in neops_worker_sdk/testing/remote_lab/server.py.
🪵 Logging
The server emits structured logs:
2024-05-27 12:34:56 | INFO | remote-lab-server | sid=24f... topo=simple_frr.yml | Created session
Use --log-level debug or the --debug flag when starting the service to see queue promotions and
Netlab command output. The --debug flag also enables streaming of Netlab output via
NEOPS_NETLAB_STREAM_OUTPUT=1. You can override logging with --log-config <yaml>; see
neops_worker_sdk/testing/remote_lab/logging_config.yaml for the default.
🧪 Tests
- Remote lab API:
tests/testing/remote_lab/test_server.py- Covers queueing/promotion, heartbeats, active-session, acquire/release/destroy, status codes (400/409/423/202/204), device listing, and
extra_filesdirectory preservation. Uses a stubbedLabManager; no Netlab required.
- Covers queueing/promotion, heartbeats, active-session, acquire/release/destroy, status codes (400/409/423/202/204), device listing, and
- Fixture selection:
tests/testing/netlab/test_netlab_fixture_logic.py- Verifies
create_netlab_fixturelocal vs remote behavior,REMOTE_LAB_URLauto-selection, and conversion toNetlabDevice.
- Verifies
- Harness:
tests/conftest.py- Loads
.env, defines example fixtures, and adds handy pytest markers.
- Loads
pytest tests/testing/remote_lab/test_server.py
pytest tests/testing/netlab/test_netlab_fixture_logic.py
pytest -m testing # Run all tests with "testing" marker
❓ Troubleshooting
| Symptom | Checklist |
|---|---|
| Server won’t start | netlab --version, correct module path |
| Tests hang in queue | Port 8000 reachable? Heartbeats sent? Check server logs |
| Containers unreachable | Using network_mode: host? Firewall rules? |
| Lab stuck busy | Someone forgot to release? Use DELETE /lab?force=true |
📚 Interactive Docs
Browse http://<host>:8000/docs for an auto-generated, interactive OpenAPI UI
and experiment with the endpoints directly.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file neops_remote_lab-0.0.1b2.tar.gz.
File metadata
- Download URL: neops_remote_lab-0.0.1b2.tar.gz
- Upload date:
- Size: 19.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.2.0 CPython/3.13.7 Linux/6.8.0-51-generic
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8cfc2a08a358e94965fb87cab1db3d2d6c8a6e78e743de2366232e7a24aa5e8a
|
|
| MD5 |
239a469e254984341eccba828b6263fa
|
|
| BLAKE2b-256 |
e11d6439eb5c8fc2139196570e9946be6ee83cb4f2103e621f26a20540574517
|
File details
Details for the file neops_remote_lab-0.0.1b2-py3-none-any.whl.
File metadata
- Download URL: neops_remote_lab-0.0.1b2-py3-none-any.whl
- Upload date:
- Size: 19.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.2.0 CPython/3.13.7 Linux/6.8.0-51-generic
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
48319894ff2441c07e5a2e9998f1e679cde554d832c67b78beb15208c9607f89
|
|
| MD5 |
3066d7a9ebf2fc3583868fa6c4deb6b4
|
|
| BLAKE2b-256 |
706d5c68c49339232e74086bc028b91642005838123d014deefd8f0fa1f12184
|