Skip to content

Contributing a new lab

Two contribution paths share the same SSH gateway VM and upstream Ansible per-lab coordinator setup, but differ in what the lab must support and which runners execute CI. This page summarizes both so a new contributor picks the minimum setup for the target workflow.


1. Shared foundation

Every contributed lab uses:

  • A local labgrid-coordinator on each lab host (loopback :20408), deployed by the upstream Ansible playbook. The SSH gateway VM (global-coordinator hostname) provides SSH jump access for CI runners and developers.
  • A WireGuard tunnel between the lab host and the SSH gateway VM (for SSH transport).
  • A single inventory in openwrt-tests labnet.yaml listing labs, devices, maintainers, and access lists (SSH keys are fetched from GitHub at deploy time).
  • The openwrt-tests playbook_labgrid.yml applied to the lab host: user labgrid-dev, gateway SSH key in authorized_keys, labgrid-coordinator, labgrid-exporter, labgrid-switch-abstraction via pipx, TFTP, PDUDaemon, netplan, dnsmasq.

The infrastructure is the same; what changes between paths is which CI runner executes tests and which suite expects which resources.

flowchart LR
  subgraph shared [Shared upstream]
    sshgw[SSH gateway VM]
    labnet[labnet.yaml<br/>aparcar/openwrt-tests]
  end

  subgraph labHost [Lab host]
    coord[labgrid-coordinator<br/>loopback :20408]
    exporter[labgrid-exporter]
    switchVlan[switch-vlan CLI<br/>optional]
    duts[DUTs]
  end

  subgraph scenarioA [A  base openwrt-tests]
    runnerA[GitHub-hosted runners<br/>ubuntu-latest]
    suiteA[openwrt-tests suite]
  end

  subgraph scenarioB [B  libremesh mesh]
    runnerB[self-hosted runner<br/>testbed-fcefyn or yours]
    suiteB[libremesh-tests suite]
  end

  exporter -->|gRPC loopback| coord
  runnerA -->|"LG_PROXY (via SSH gateway)"| exporter
  runnerB -->|LG_PROXY| exporter
  suiteA --> runnerA
  suiteB --> runnerB
  runnerA -.->|reads| labnet
  runnerB -.->|reads| labnet
  switchVlan --> duts
  exporter --> duts
Hold "Alt" / "Option" to enable pan & zoom

2. Scenario A: base openwrt-tests lab

Goal: contribute DUTs so upstream aparcar/openwrt-tests CI can flash OpenWrt and run vanilla healthchecks on them. Single-node tests. Managed switch and VLAN switching are optional: if the lab has no managed switch, everything still works on a static topology.

Audience: lab owners who want upstream openwrt-tests coverage on their hardware.

Runners: GitHub-hosted runners (ubuntu-latest) that reach the lab via the SSH gateway VM. No self-hosted runner required.

Steps:

  1. Follow openwrt-tests onboarding: WireGuard, GitHub usernames in access:, PR against aparcar/openwrt-tests with labnet.yaml entry, ansible/files/exporter/<lab>/*, lab doc.
  2. Apply playbook_labgrid.yml on the lab host (gateway SSH key, coordinator, exporter, TFTP, PDUDaemon, dnsmasq, netplan). The playbook now also installs labgrid-switch-abstraction via pipx; labs without a managed switch can ignore the CLI.
  3. Optional: if the lab has a managed switch and wants dynamic VLAN switching in upstream tests, configure switch.conf and dut-config.yaml on the host and opt in per test run with VLAN_SWITCH_ENABLED=1 + LG_MULTI_PLACES. See switch-abstraction.md on the PR branch once PR #218 is merged.

Nothing else is required on the lab side. Upstream CI will start scheduling jobs when labnet.yaml lists the lab.


3. Scenario B: libremesh-capable lab

Goal: run the libremesh-tests suite (single-node LibreMesh, multi-node mesh, virtual mesh) against DUTs in the lab. Requires a managed switch that can move DUT ports between isolated VLANs and the mesh VLAN (200 by default).

Audience: labs that want their DUTs covered by LibreMesh test matrices.

Runners: a self-hosted GitHub runner under the lab's control (not the aparcar runners). The FCEFyN lab uses testbed-fcefyn; other labs should register their own runner so tests run physically close to the DUTs.

Steps:

  1. Complete Scenario A (same upstream onboarding; the inventory, exporter, per-lab coordinator, playbook_labgrid.yml are shared).
  2. Managed switch must be configured. On the lab host:
  3. Credentials in /etc/switch.conf (system-wide, group-readable so any SSH user can run switch-vlan; see switch-config.md#multi-user-setup).
  4. DUT-to-port map in /etc/testbed/dut-config.yaml (or set SWITCH_DUT_CONFIG). DUT names in that file must match the suffix of labgrid place names (see place-to-DUT mapping below).
  5. Confirm switch-vlan --help works as the SSH user.
  6. Register a self-hosted GitHub Actions runner on the lab host (or on another machine with lab access) and label it for the lime-packages CI workflow. The runner should expose the labels [self-hosted, testbed-fcefyn] (or your lab equivalent) — these match the runs-on: of pi-lime-packages/.github/workflows/build-firmware.yml. See CI runner config for details.
  7. The active CI orchestrator is pi-lime-packages/.github/workflows/build-firmware.yml. Each lab declares its hardware in pi-lime-packages/.github/ci/targets.yml (per-target test_places: / test_firmware: / image_format: keys). The legacy libremesh-tests daily/pull_requests workflows were retired in May 2026; only the lint workflow formal.yml remains in that repo.
  8. Local development against the lab: LG_PROXY=labgrid-<lab>, LG_MESH_PLACES=labgrid-<lab>-<dut1>,labgrid-<lab>-<dut2>, PLACE_PREFIX=labgrid-<lab>- (or leave empty for the second-hyphen fallback). See libremesh-tests CONTRIBUTING_LAB.md.

Place-to-DUT mapping

Both suites derive DUT names from labgrid place names by stripping a prefix. Defaults differ:

Suite Default Override
openwrt-tests (PR #218) up to the second hyphen PLACE_PREFIX
libremesh-tests labgrid-fcefyn- PLACE_PREFIX

Set PLACE_PREFIX=labgrid-mylab- when contributing a lab named mylab; PLACE_PREFIX="" disables the default and reverts to the second-hyphen strip.


4. Decision matrix

Requirement Scenario A Scenario B
WireGuard tunnel to SSH gateway VM required required
labnet.yaml entry in openwrt-tests required required
playbook_labgrid.yml applied required required
Self-hosted GitHub runner not needed required
Managed switch optional required
switch.conf and dut-config.yaml on lab host optional required
Target YAML in libremesh-tests no per board that runs LibreMesh
Test suite openwrt-tests libremesh-tests (+ optional openwrt-tests)

A lab can contribute to both paths at once: the infrastructure is shared. Scenario A is a prerequisite for Scenario B.