Skip to main content
Version: 028-rc11

xconnect Example Containers

The pv-examples containers in recipes-containers/pv-examples/ demonstrate pv-xconnect service mesh patterns. For the underlying xconnect concepts and manifest format, see the pantavisor xconnect overview and reference.

Overview

PatternProviderConsumer(s)Description
Unix Socketpv-example-unix-serverpv-example-unix-clientRaw Unix domain socket proxy
RESTpv-example-rest-serverpv-example-rest-clientHTTP-over-UDS with identity injection
D-Buspv-example-dbus-serverpv-example-dbus-clientPolicy-aware D-Bus proxy
DRMpv-example-drm-providerpv-example-drm-master, pv-example-drm-renderDevice node injection
Waylandpv-example-wayland-serverpv-example-wayland-clientWayland compositor access

Auto-recovery containers:

ContainerGroupDescription
pv-example-recoveryrootCrashes after 10s, on-failure with backoff_policy="10min"
pv-example-stabilizerootFails 3× then stabilizes, backoff_policy="reboot"
pv-example-randomrootRandom exit timing, always policy
pv-example-app-crashappInherits app group's auto_recovery

Building Example Containers

# Build specific containers
./kas-container build .github/configs/release/docker-x86_64-scarthgap.yaml \
--target pv-example-unix-server --target pv-example-unix-client

# Build with workspace (when iterating on pantavisor source)
./kas-container build .github/configs/release/docker-x86_64-scarthgap.yaml:kas/with-workspace.yaml \
--target pv-example-unix-server --target pv-example-unix-client

Output: build/tmp-scarthgap/deploy/images/docker-x86_64/<name>.pvrexport.tgz

Quick Test Setup

mkdir -p pvtx.d
cp build/tmp-scarthgap/deploy/images/docker-x86_64/pv-example-*.pvrexport.tgz pvtx.d/

docker rm -f pva-test 2>/dev/null; docker volume rm storage-test 2>/dev/null
docker run --name pva-test -d --privileged \
-v $(pwd)/pvtx.d:/usr/lib/pantavisor/pvtx.d \
-v storage-test:/var/pantavisor/storage \
--entrypoint /bin/sh pantavisor-appengine:latest -c "sleep infinity"

docker exec pva-test sh -c 'pv-appengine &'
sleep 15
docker exec pva-test lxc-ls -f
docker exec pva-test pvcontrol graph ls

Unix Socket Example

Demonstrates raw Unix domain socket proxying between containers.

Provider pv-example-unix-server — creates /run/example/raw.sock Consumer pv-example-unix-client — expects socket at /run/pv/services/raw.sock

Configuration

Provider services.json:

[
{"name": "raw", "type": "unix", "socket": "/run/example/raw.sock"}
]

Consumer args.json:

{
"PV_SERVICES_REQUIRED": [
{"name": "raw", "target": "/run/pv/services/raw.sock"}
]
}

Build and Verify

./kas-container build .github/configs/release/docker-x86_64-scarthgap.yaml \
--target pv-example-unix-server --target pv-example-unix-client
cp build/tmp-scarthgap/deploy/images/docker-x86_64/pv-example-unix-*.pvrexport.tgz pvtx.d/

After containers start:

docker exec pva-test pvcontrol graph ls # shows unix link
CLIENT_PID=$(docker exec pva-test lxc-info -n pv-example-unix-client -p | awk '{print $2}')
docker exec pva-test ls -la /proc/$CLIENT_PID/root/run/pv/services/ # injected socket

REST Example

Demonstrates HTTP-over-UDS with identity header injection (X-PV-Client, X-PV-Role).

Provider services.json:

[
{"name": "api", "type": "rest", "socket": "/run/example/api.sock"}
]

Consumer args.json:

{
"PV_SERVICES_REQUIRED": [
{"name": "api", "target": "/run/pv/services/api.sock"}
]
}

Build

./kas-container build .github/configs/release/docker-x86_64-scarthgap.yaml \
--target pv-example-rest-server --target pv-example-rest-client

D-Bus Example

Demonstrates policy-aware D-Bus proxying with role-to-UID mapping.

Provider runs a local dbus-daemon and Python service, publishing org.pantavisor.Example.

Provider D-Bus policy (org.pantavisor.Example.conf):

<busconfig>
<policy user="root">
<allow own="org.pantavisor.Example"/>
<allow send_destination="org.pantavisor.Example"/>
</policy>
<policy context="default">
<allow send_destination="org.pantavisor.Example"/>
</policy>
</busconfig>

Provider services.json:

[{"name": "system-bus", "type": "dbus", "socket": "/run/dbus/system_bus_socket"}]

Consumer args.json:

{
"PV_SERVICES_REQUIRED": [
{
"name": "system-bus",
"type": "dbus",
"interface": "org.pantavisor.Example",
"target": "/run/dbus/system_bus_socket"
}
]
}

Build and Verify

./kas-container build .github/configs/release/docker-x86_64-scarthgap.yaml \
--target pv-example-dbus-server --target pv-example-dbus-client

Check client logs for successful D-Bus call:

docker exec pva-test tail -f /var/pantavisor/storage/logs/0/pv-example-dbus-client/lxc/console.log
# Expected: method return with org.pantavisor.Example response

DRM Example

Demonstrates DRM device node injection for graphics access.

Provider pv-example-drm-provider — exports DRM devices Consumer pv-example-drm-master — requests /dev/dri/card0 (KMS) Consumer pv-example-drm-render — requests /dev/dri/renderD128 (GPU rendering)

Provider services.json:

[
{"name": "drm-master", "type": "drm", "socket": "/dev/dri/card0"},
{"name": "drm-render", "type": "drm", "socket": "/dev/dri/renderD128"}
]

Consumer args.json (drm-master):

{
"PV_SERVICES_REQUIRED": [{"name": "drm-master", "target": "/dev/dri/card0"}]
}

Testing with VKMS

sudo modprobe vkms
ls -la /dev/dri/ # card0 (VKMS does not create renderD* nodes)
DeviceVKMSUse case
/dev/dri/card0YesKMS/display
/dev/dri/renderD128NoGPU compute

Build and Run

./kas-container build .github/configs/release/docker-x86_64-scarthgap.yaml \
--target pv-example-drm-provider --target pv-example-drm-master
cp build/tmp-scarthgap/deploy/images/docker-x86_64/pv-example-drm-*.pvrexport.tgz pvtx.d/

# Run with DRM device passthrough
docker run --name pva-test -d --privileged \
--device /dev/dri:/dev/dri \
-v $(pwd)/pvtx.d:/usr/lib/pantavisor/pvtx.d \
-v storage-test:/var/pantavisor/storage \
--entrypoint /bin/sh pantavisor-appengine:latest -c "sleep infinity"

Verify injection:

MASTER_PID=$(docker exec pva-test lxc-info -n pv-example-drm-master -p | awk '{print $2}')
docker exec pva-test ls -la /proc/$MASTER_PID/root/dev/dri/ # expect card0 226:0

Wayland Example

Demonstrates Wayland compositor access. Requires DRM.

Provider pv-example-wayland-server — Weston compositor (requires DRM from drm-provider) Consumer pv-example-wayland-client — Wayland client

Provider services.json:

[{"name": "wayland-0", "type": "wayland", "socket": "/run/wayland/wayland-0"}]

Provider args.json (requires DRM):

{
"PV_SERVICES_REQUIRED": [{"name": "drm-master", "target": "/dev/dri/card0"}]
}

Consumer args.json:

{
"PV_SERVICES_REQUIRED": [{"name": "wayland-0", "target": "/run/wayland/wayland-0"}]
}
./kas-container build .github/configs/release/docker-x86_64-scarthgap.yaml \
--target pv-example-drm-provider \
--target pv-example-wayland-server \
--target pv-example-wayland-client

VKMS provides card0 but won't produce actual display output. Full Wayland testing requires real GPU hardware.


Debugging Tips

# Container status
docker exec pva-test lxc-ls -f

# Enter a container
docker exec -it pva-test pventer -c <container_name>

# Container namespace inspection
docker exec pva-test lxc-info -n <container_name> -p
docker exec pva-test ls -la /proc/<PID>/root/run/

# Common issues
SymptomCauseFix
Container exits immediatelyMissing DRM deviceAdd --device /dev/dri:/dev/dri
Socket not injectedpv-xconnect not runningdocker exec pva-test pvcontrol daemons ls
"Connection refused"Provider not readyWait for provider container RUNNING status
Device not foundWrong major:minorstat /dev/dri/card0 on host
# Cleanup between tests
docker rm -f pva-test
docker volume rm storage-test