The default installation is available via PyPI:
$ pip install labgrid
or by cloning the repository and installing manually:
$ git clone https://github.com/labgrid-project/labgrid $ cd labgrid && python3 setup.py install
Labgrid supports different extras:
- onewire: install onewire support, requires
onewire>=0.0.2from PyPI and additionally
libow-devon Debian based distributions.
- coordinator: installs required depencies to start a crossbar coordinator
The extras can be selected by passing them after the package name in square brackets:
$ pip install labgrid[onewire]
or to enable both:
$ pip install labgrid[onewire,coordinator]
Depending on the used shell settings, the brackets may have to be escaped via
Labgrid can be used in several ways:
- on the command line to control individual embedded systems during development (“board farm”)
- via a pytest plugin to automate testing of embedded systems
- as a python library in other programs
In the labgrid library, a controllable embedded system is represented as a
Targets normally have several
which are used to store the board-specific information and to implement actions
on different abstraction levels.
For cases where a board needs to be transitioned to specific states (such as
off, in bootloader, in Linux shell), a
Strategy (a special kind of
Driver) can be added to the Target.
While labgrid comes with implementations for some resources, drivers and strategies, custom implementations for these can be registered at runtime. It is expected that for complex use-cases, the user would implement and register a custom Strategy and possibly some higher-level Drivers.
An important type of Resources are
While normal Resources are always considered available for use and have fixed
properties (such as the
/dev/ttyUSB0 device name for a
RawSerialPort), the ManagedResources are used to represent interfaces
which are discoverable in some way.
They can appear/disappear at runtime and have different properties each time
they are discovered.
The most common examples of ManagedResources are the various USB resources
discovered using udev, such as
Drivers and Protocols¶
Driver uses one (or more) Resources and/or other, lower-level
Drivers to perform a set of actions on a Target.
For example, the
NetworkPowerDriver uses a
resource to control the Target’s power supply.
In this case, the actions are “on”, “off”, “cycle” and “get”.
As another example, the
ShellDriver uses any driver implementing the
ConsoleProtocol (such as a
SerialDriver, see below).
The ConsoleProtocol allows the ShellDriver to work with any specific method
of accessing the board’s console (locally via USB, over the network using a
console server or even an external program).
At the ConsoleProtocol level, characters are sent to and received from the
target, but they are not yet interpreted as specific commands or their output.
The ShellDriver implements the higher-level
actions such as “run” or “run_check”.
Internally, it interacts with the Linux shell on the target board.
For example, it:
- waits for the login prompt
- enters user name and password
- runs the requested shell command (delimited by marker strings)
- parses the output
- retrieves the exit status
Other drivers, such as the
SSHDriver, also implement the
This way, higher-level code (such as a test suite), can be independent of the
concrete control method on a given board.
Binding and Activation¶
When a Target is configured, each driver is “bound” to the resources (or other drivers) required by it. Each Driver class has a “bindings” attribute, which declares which Resources or Protocols it needs and under which name they should be available to the Driver instance. The binding resolution is handled by the Target during the initial configuration and results in a directed, acyclic graph of resources and drivers. During the lifetime of a Target, the bindings are considered static.
In most non-trivial target configurations, some drivers are mutually exclusive.
For example, a Target may have both a
ShellDriver and a
Both bind to a driver implementing the ConsoleProtocol and provide the
Obviously, the board cannot be in the bootloader and in Linux at the same time,
which is represented in labgrid via the
If, during activation of a driver, any other driver in its bindings is not
active, they will be activated as well.
Activating and deactivating Drivers is also used to handle ManagedResources becoming available/unavailable at runtime. If some resources bound to by the activating drivers are currently unavailable, the Target will wait for them to appear (with a per resource timeout). A realistic sequence of activation might look like this:
- enable power (
- activate the
IMXUSBDriverdriver on the target (this will wait for the
IMXUSBLoaderresource to be available)
- load the bootloader (
- activate the
AndroidFastbootDriverdriver on the target (this will wait for the
AndroidFastbootresource to be available)
- boot the kernel (
- activate the
ShellDriverdriver on the target (this will wait for the
USBSerialPortresource to be available and log in)
Any ManagedResources which become unavailable at runtime will automatically deactivate the dependent drivers.
Especially when using labgrid from pytest, explicitly controlling the board’s
boot process can distract from the individual test case.
Strategy implements the board- or project-specific actions necessary to
transition from one state to another.
Labgrid includes the
BareboxStrategy and the
can be used as-is for simple cases or serve as an example for implementing a
Strategies themselves are not activated/deactivated. Instead, they control the states of the other drivers explicitly and execute actions to bring the target into the requested state.
See the strategy example (
examples/strategy) and the included strategies in
labgrid/strategy for some more information.
For more information on the reasons behind labgrid’s architecture, see Design Decisions.
Remote Resources and Places¶
Labgrid contains components for accessing resources which are not directly accessible on the local machine. The main parts of this are:
- labgrid-coordinator (crossbar component)
- Clients and exporters connect to the coordinator to publish resources, manage place configuration and handle mutual exclusion.
- labgrid-exporter (CLI)
- Exports explicitly configured local resources to the coordinator and monitors these for changes in availability or parameters.
- labgrid-client (CLI)
- Configures places (consisting of exported resources) and allows command line access to some actions (such as power control, bootstrap, fastboot and the console).
- RemotePlace (managed resource)
- When used in a Target, the RemotePlace expands to the resources configured for the named places.
The Coordinator is implemented as a Crossbar component and is started by the router. It provides separate RPC methods for the exporters and clients.
The coordinator keeps a list of all resources for clients and notifies them of changes as they occur. The resource access from clients does not pass through the coordinator, but is instead done directly from client to exporter, avoiding the need to specify new interfaces for each resource type.
The coordinator also manages the registry of “places”. These are used to configure which resources belong together from the user’s point of view. A place can be a generic rack location, where different boards are connected to a static set of interfaces (resources such as power, network, serial console, …).
Alternatively, a place can also be created for a specific board, for example when special interfaces such as GPIO buttons need to be controlled and they are not available in the generic locations.
Each place can have aliases to simplify accessing a specific board (which might be moved between generic places). It also has a comment, which is used to store a short description of the connected board.
Finally, a place is configured with one or more resource matches.
A resource match pattern has the format
each component may be replaced with the wildcard
Some commonly used match patterns are:
- Matches all resources in groups named 1001 from all exporters.
- Matches only the NetworkPowerPort resource in groups named 1001 from all exporters. This is useful to exclude a NetworkSerialPort in group 1001 in cases where the serial console is connected somewhere else (such as via USB on a different exporter).
- Matches all resources exported from exporter1 in the group hub1-port1. This is an easy way to match several USB resources related to the same board (such as a USB ROM-Loader interface, Android fastboot and a USB serial gadget in Linux).
To avoid conflicting access to the same resources, a place must be aquired before it is used and the coordinator also keeps track of which user on which client host has currently acquired the place. The resource matches are only evaluated while a place is being acquired and cannot be changed until it is released again.
An exporters registers all its configured resources when it connects to the
router and updates the resource parameters when they change (such as
(dis-)connection of USB devices).
Internally, the exporter uses the normal
ManagedResource) classes as the rest of labgrid.
By using ManagedResources, availability and parameters for resources such as
USB serial ports are tracked and sent to the coordinator.
For some specific resources (such as
the exporter uses external tools to allow access by clients (
ser2net in the
serial port case).
Resources which do not need explicit support in the exporter, are just published as declared in the configuration file. This is useful to register externally configured resources such as network power switches or serial port servers with a labgrid coordinator.
The client requests the current lists of resources and places from the
coordinator when it connects to it and then registers for change events.
Most of its functionality is exposed via the labgrid-client CLI tool.
It is also used by the
RemotePlace resource (see below).
Besides viewing the list of resources, the client is used to configure and access places on the coordinator. For more information on using the CLI, see the manual page for labgrid-client.
To use the resources configured for a place to control the corresponding
board (whether in pytest or directly with the labgrid library), the
RemotePlace resource should be used.
When a RemotePlace is configured for a Target, it will create a client
connection to the coordinator, create additional resource objects for those
configured for that place and keep them updated at runtime.
The additional resource objects can be bound to by drivers as normal and the drivers do not need to be aware that they were provided by the coordinator. For resource types which do not have an existing, network-transparent protocol (such as USB ROM loaders or JTAG interfaces), the driver needs to be aware of the mapping done by the exporter.
For generic USB resources, the exporter for example maps a
AndroidFastboot resource to a
NetworkAndroidFastboot resource and
adds a hostname property which needs to be used by the client to connect to the
To avoid the need for additional remote access protocols and authentication,
labgrid currently expects that the hosts are accessible via SSH and that any
file names refer to a shared filesystem (such as NFS or SMB).
Using SSH’s session sharing (
makes RemotePlaces easy to use even for exporters with require passwords or
more complex login procedures.
For exporters which are not directly accessible via SSH, add the host to your .ssh/config file, with a ProxyCommand when need.