PageSourceSearch

https://docs.pantavisor.io/assets/js/756306b2.bb46221e.js

js pantavisor.io collected 2026-10-04 00:18:52 UTC 25,266 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunkpantavisor_docs=self.webpackChunkpantavisor_docs||[]).push([["14893"],{24599(e,n,s){s.r(n),s.d(n,{metadata:()=>r,default:()=>x,frontMatter:()=>c,contentTitle:()=>a,toc:()=>t,assets:()=>l});var r=JSON.parse('{"id":"meta-pantavisor/overview/examples/xconnect-examples","title":"xconnect Example Containers","description":"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.","source":"@site/reference_versioned_docs/version-030-rc1/meta-pantavisor/overview/examples/xconnect-examples.md","sourceDirName":"meta-pantavisor/overview/examples","slug":"/meta-pantavisor/overview/examples/xconnect-examples","permalink":"/030-rc1/meta-pantavisor/overview/examples/xconnect-examples","draft":false,"unlisted":false,"tags":[],"version":"030-rc1","sidebarPosition":1,"frontMatter":{"sidebar_position":1},"sidebar":"metaPantavisorOverviewSidebar","previous":{"title":"Examples","permalink":"/030-rc1/meta-pantavisor/overview/examples/"},"next":{"title":"pvwificonnect \u2014 WiFi Provisioning Container","permalink":"/030-rc1/meta-pantavisor/overview/examples/pvwificonnect"}}'),d=s(74848),i=s(28453);let c={sidebar_position:1},a="xconnect Example Containers",l={},t=[{value:"Overview",id:"overview",level:2},{value:"Building Example Containers",id:"building-example-containers",level:2},{value:"Quick Test Setup",id:"quick-test-setup",level:2},{value:"Unix Socket Example",id:"unix-socket-example",level:2},{value:"Configuration",id:"configuration",level:3},{value:"Build and Verify",id:"build-and-verify",level:3},{value:"REST Example",id:"rest-example",level:2},{value:"Build",id:"build",level:3},{value:"D-Bus Example",id:"d-bus-example",level:2},{value:"Build and Verify",id:"build-and-verify-1",level:3},{value:"Hosted System Bus Example",id:"hosted-system-bus-example",level:2},{value:"Build and Verify",id:"build-and-verify-2",level:3},{value:"DRM Example",id:"drm-example",level:2},{value:"Testing with VKMS",id:"testing-with-vkms",level:3},{value:"Build and Run",id:"build-and-run",level:3},{value:"Wayland Example",id:"wayland-example",level:2},{value:"Debugging Tips",id:"debugging-tips",level:2}];function o(e){let n={a:"a",blockquote:"blockquote",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",hr:"hr",li:"li",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,i.R)(),...e.components};return(0,d.jsxs)(d.Fragment,{children:[(0,d.jsx)(n.header,{children:(0,d.jsx)(n.h1,{id:"xconnect-example-containers",children:"xconnect Example Containers"})}),"\n",(0,d.jsxs)(n.p,{children:["The ",(0,d.jsx)(n.code,{children:"pv-examples"})," containers in ",(0,d.jsx)(n.code,{children:"recipes-containers/pv-examples/"})," demonstrate pv-xconnect service mesh patterns. For the underlying xconnect concepts and manifest format, see the ",(0,d.jsx)(n.a,{href:"/030-rc1/pantavisor/overview/xconnect",children:"pantavisor xconnect overview"})," and ",(0,d.jsx)(n.a,{href:"/030-rc1/pantavisor/reference/pantavisor-xconnect",children:"reference"}),"."]}),"\n",(0,d.jsx)(n.h2,{id:"overview",children:"Overview"}),"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",(0,d.jsxs)(n.table,{children:[(0,d.jsx)(n.thead,{children:(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.th,{children:"Pattern"}),(0,d.jsx)(n.th,{children:"Provider"}),(0,d.jsx)(n.th,{children:"Consumer(s)"}),(0,d.jsx)(n.th,{children:"Description"})]})}),(0,d.jsxs)(n.tbody,{children:[(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.td,{children:"Unix Socket"}),(0,d.jsx)(n.td,{children:(0,d.jsx)(n.code,{children:"pv-example-unix-server"})}),(0,d.jsx)(n.td,{children:(0,d.jsx)(n.code,{children:"pv-example-unix-client"})}),(0,d.jsx)(n.td,{children:"Raw Unix domain socket proxy"})]}),(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.td,{children:"REST"}),(0,d.jsx)(n.td,{children:(0,d.jsx)(n.code,{children:"pv-example-rest-server"})}),(0,d.jsx)(n.td,{children:(0,d.jsx)(n.code,{children:"pv-example-rest-client"})}),(0,d.jsx)(n.td,{children:"HTTP-over-UDS with identity injection"})]}),(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.td,{children:"D-Bus"}),(0,d.jsx)(n.td,{children:(0,d.jsx)(n.code,{children:"pv-example-dbus-server"})}),(0,d.jsx)(n.td,{children:(0,d.jsx)(n.code,{children:"pv-example-dbus-client"})}),(0,d.jsx)(n.td,{children:"Policy-aware D-Bus proxy"})]}),(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.td,{children:"D-Bus (hosted)"}),(0,d.jsx)(n.td,{children:(0,d.jsx)(n.code,{children:"pv-example-system-dbus-server"})}),(0,d.jsx)(n.td,{children:(0,d.jsx)(n.code,{children:"pv-example-system-dbus-client"})}),(0,d.jsx)(n.td,{children:"Pantavisor-hosted system bus, single-pid apps"})]}),(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.td,{children:"DRM"}),(0,d.jsx)(n.td,{children:(0,d.jsx)(n.code,{children:"pv-example-drm-provider"})}),(0,d.jsxs)(n.td,{children:[(0,d.jsx)(n.code,{children:"pv-example-drm-master"}),", ",(0,d.jsx)(n.code,{children:"pv-example-drm-render"})]}),(0,d.jsx)(n.td,{children:"Device node injection"})]}),(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.td,{children:"Wayland"}),(0,d.jsx)(n.td,{children:(0,d.jsx)(n.code,{children:"pv-example-wayland-server"})}),(0,d.jsx)(n.td,{children:(0,d.jsx)(n.code,{children:"pv-example-wayland-client"})}),(0,d.jsx)(n.td,{children:"Wayland compositor access"})]})]})]}),"\n",(0,d.jsx)(n.p,{children:"Auto-recovery containers:"}),"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",(0,d.jsxs)(n.table,{children:[(0,d.jsx)(n.thead,{children:(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.th,{children:"Container"}),(0,d.jsx)(n.th,{children:"Group"}),(0,d.jsx)(n.th,{children:"Description"})]})}),(0,d.jsxs)(n.tbody,{children:[(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.td,{children:(0,d.jsx)(n.code,{children:"pv-example-recovery"})}),(0,d.jsx)(n.td,{children:"root"}),(0,d.jsxs)(n.td,{children:["Crashes after 10s, ",(0,d.jsx)(n.code,{children:"on-failure"})," with ",(0,d.jsx)(n.code,{children:'backoff_policy="10min"'})]})]}),(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.td,{children:(0,d.jsx)(n.code,{children:"pv-example-stabilize"})}),(0,d.jsx)(n.td,{children:"root"}),(0,d.jsxs)(n.td,{children:["Fails 3\xd7 then stabilizes, ",(0,d.jsx)(n.code,{children:'backoff_policy="reboot"'})]})]}),(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.td,{children:(0,d.jsx)(n.code,{children:"pv-example-random"})}),(0,d.jsx)(n.td,{children:"root"}),(0,d.jsxs)(n.td,{children:["Random exit timing, ",(0,d.jsx)(n.code,{children:"always"})," policy"]})]}),(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.td,{children:(0,d.jsx)(n.code,{children:"pv-example-app-crash"})}),(0,d.jsx)(n.td,{children:"app"}),(0,d.jsx)(n.td,{children:"Inherits app group's auto_recovery"})]})]})]}),"\n",(0,d.jsx)(n.h2,{id:"building-example-containers",children:"Building Example Containers"}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-bash",children:"# Build specific containers\n./kas-container build kas/build-configs/release/docker-x86_64-scarthgap.yaml \\\n    --target pv-example-unix-server --target pv-example-unix-client\n\n# Build with workspace (when iterating on pantavisor source)\n./kas-container build kas/build-configs/release/docker-x86_64-scarthgap.yaml:kas/with-wor
1kspace.yaml \\\n    --target pv-example-unix-server --target pv-example-unix-client\n"})}),"\n",(0,d.jsxs)(n.p,{children:["Output: ",(0,d.jsx)(n.code,{children:"build/tmp-scarthgap/deploy/images/docker-x86_64/<name>.pvrexport.tgz"})]}),"\n",(0,d.jsx)(n.h2,{id:"quick-test-setup",children:"Quick Test Setup"}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-bash",children:"mkdir -p pvtx.d\ncp build/tmp-scarthgap/deploy/images/docker-x86_64/pv-example-*.pvrexport.tgz pvtx.d/\n\ndocker rm -f pva-test 2>/dev/null; docker volume rm storage-test 2>/dev/null\ndocker run --name pva-test -d --privileged \\\n    -v $(pwd)/pvtx.d:/usr/lib/pantavisor/pvtx.d \\\n    -v storage-test:/var/pantavisor/storage \\\n    --entrypoint /bin/sh pantavisor-appengine:latest -c \"sleep infinity\"\n\ndocker exec pva-test sh -c 'pv-appengine &'\nsleep 15\ndocker exec pva-test lxc-ls -f\ndocker exec pva-test pvcontrol graph ls\n"})}),"\n",(0,d.jsx)(n.hr,{}),"\n",(0,d.jsx)(n.h2,{id:"unix-socket-example",children:"Unix Socket Example"}),"\n",(0,d.jsx)(n.p,{children:"Demonstrates raw Unix domain socket proxying between containers."}),"\n",(0,d.jsxs)(n.p,{children:[(0,d.jsx)(n.strong,{children:"Provider"})," ",(0,d.jsx)(n.code,{children:"pv-example-unix-server"})," \u2014 creates ",(0,d.jsx)(n.code,{children:"/run/example/raw.sock"}),"\n",(0,d.jsx)(n.strong,{children:"Consumer"})," ",(0,d.jsx)(n.code,{children:"pv-example-unix-client"})," \u2014 expects socket at ",(0,d.jsx)(n.code,{children:"/run/pv/services/raw.sock"})]}),"\n",(0,d.jsx)(n.h3,{id:"configuration",children:"Configuration"}),"\n",(0,d.jsx)(n.p,{children:(0,d.jsxs)(n.strong,{children:["Provider ",(0,d.jsx)(n.code,{children:"services.json"}),":"]})}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-json",children:'[\n  {"name": "raw", "type": "unix", "socket": "/run/example/raw.sock"}\n]\n'})}),"\n",(0,d.jsx)(n.p,{children:(0,d.jsxs)(n.strong,{children:["Consumer ",(0,d.jsx)(n.code,{children:"args.json"}),":"]})}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-json",children:'{\n  "PV_SERVICES_REQUIRED": [\n    {"name": "raw", "target": "/run/pv/services/raw.sock"}\n  ]\n}\n'})}),"\n",(0,d.jsx)(n.h3,{id:"build-and-verify",children:"Build and Verify"}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-bash",children:"./kas-container build kas/build-configs/release/docker-x86_64-scarthgap.yaml \\\n    --target pv-example-unix-server --target pv-example-unix-client\ncp build/tmp-scarthgap/deploy/images/docker-x86_64/pv-example-unix-*.pvrexport.tgz pvtx.d/\n"})}),"\n",(0,d.jsx)(n.p,{children:"After containers start:"}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-bash",children:"docker exec pva-test pvcontrol graph ls   # shows unix link\nCLIENT_PID=$(docker exec pva-test lxc-info -n pv-example-unix-client -p | awk '{print $2}')\ndocker exec pva-test ls -la /proc/$CLIENT_PID/root/run/pv/services/   # injected socket\n"})}),"\n",(0,d.jsx)(n.hr,{}),"\n",(0,d.jsx)(n.h2,{id:"rest-example",children:"REST Example"}),"\n",(0,d.jsxs)(n.p,{children:["Demonstrates HTTP-over-UDS with identity header injection (",(0,d.jsx)(n.code,{children:"X-PV-Client"}),", ",(0,d.jsx)(n.code,{children:"X-PV-Role"}),")."]}),"\n",(0,d.jsx)(n.p,{children:(0,d.jsxs)(n.strong,{children:["Provider ",(0,d.jsx)(n.code,{children:"services.json"}),":"]})}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-json",children:'[\n  {"name": "api", "type": "rest", "socket": "/run/example/api.sock"}\n]\n'})}),"\n",(0,d.jsx)(n.p,{children:(0,d.jsxs)(n.strong,{children:["Consumer ",(0,d.jsx)(n.code,{children:"args.json"}),":"]})}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-json",children:'{\n  "PV_SERVICES_REQUIRED": [\n    {"name": "api", "target": "/run/pv/services/api.sock"}\n  ]\n}\n'})}),"\n",(0,d.jsx)(n.h3,{id:"build",children:"Build"}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-bash",children:"./kas-container build kas/build-configs/release/docker-x86_64-scarthgap.yaml \\\n    --target pv-example-rest-server --target pv-example-rest-client\n"})}),"\n",(0,d.jsx)(n.hr,{}),"\n",(0,d.jsx)(n.h2,{id:"d-bus-example",children:"D-Bus Example"}),"\n",(0,d.jsx)(n.p,{children:"Demonstrates policy-aware D-Bus proxying with role-to-UID mapping."}),"\n",(0,d.jsxs)(n.p,{children:[(0,d.jsx)(n.strong,{children:"Provider"})," runs a local ",(0,d.jsx)(n.code,{children:"dbus-daemon"})," and Python service, publishing ",(0,d.jsx)(n.code,{children:"org.pantavisor.Example"}),"."]}),"\n",(0,d.jsx)(n.p,{children:(0,d.jsxs)(n.strong,{children:["Provider D-Bus policy (",(0,d.jsx)(n.code,{children:"org.pantavisor.Example.conf"}),"):"]})}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-xml",children:'<busconfig>\n  <policy user="root">\n    <allow own="org.pantavisor.Example"/>\n    <allow send_destination="org.pantavisor.Example"/>\n  </policy>\n  <policy context="default">\n    <allow send_destination="org.pantavisor.Example"/>\n  </policy>\n</busconfig>\n'})}),"\n",(0,d.jsx)(n.p,{children:(0,d.jsxs)(n.strong,{children:["Provider ",(0,d.jsx)(n.code,{children:"services.json"}),":"]})}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-json",children:'[{"name": "system-bus", "type": "dbus", "socket": "/run/dbus/system_bus_socket"}]\n'})}),"\n",(0,d.jsx)(n.p,{children:(0,d.jsxs)(n.strong,{children:["Consumer ",(0,d.jsx)(n.code,{children:"args.json"}),":"]})}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-json",children:'{\n  "PV_SERVICES_REQUIRED": [\n    {\n      "name": "system-bus",\n      "type": "dbus",\n      "interface": "org.pantavisor.Example",\n      "target": "/run/dbus/system_bus_socket"\n    }\n  ]\n}\n'})}),"\n",(0,d.jsx)(n.h3,{id:"build-and-verify-1",children:"Build and Verify"}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-bash",children:"./kas-container build kas/build-configs/release/docker-x86_64-scarthgap.yaml \\\n    --target pv-example-dbus-server --target pv-example-dbus-client\n"})}),"\n",(0,d.jsx)(n.p,{children:"Check client logs for successful D-Bus call:"}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-bash",children:"docker exec pva-test tail -f /var/pantavisor/storage/logs/0/pv-example-dbus-client/lxc/console.log\n# Expected: method return with org.pantavisor.Example response\n"})}),"\n",(0,d.jsx)(n.hr,{}),"\n",(0,d.jsx)(n.h2,{id:"hosted-system-bus-example",children:"Hosted System Bus Example"}),"\n",(0,d.jsxs)(n.p,{children:["Demonstrates the ",(0,d.jsx)(n.strong,{children:"pantavisor-hosted"})," D-Bus system bus: both provider and\nconsumer are single-pid containers \u2014 no ",(0,d.jsx)(n.code,{children:"dbus-daemon"}),", policy XML or\n",(0,d.jsx)(n.code,{children:"/etc/passwd"})," to ship. Pantavisor runs one shared bus (gated by the\n",(0,d.jsx)(n.code,{children:"xconnect-dbus-systembus"})," build feature and the ",(0,d.jsx)(n.code,{children:"xconnect.dbus.systembus.enabled"}),"\nconfig key, default on) and generates the bus policy from the manifests."]}),"\n",(0,d.jsxs)(n.p,{children:[(0,d.jsx)(n.strong,{children:"Provider"})," (",(0,d.jsx)(n.code,{children:"pv-example-system-dbus-server"}),") declares the name it owns and the\ncaller roles allowed to reach it, in ",(0,d.jsx)(n.code,{children:"services.json"}),":"]}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-json",children:'{\n  "#spec": "service-manifest-xconnect@1",\n  "services": [\n    { "type": "dbus", "bus": "system-bus", "owns": "org.pantavisor.Example",\n      "role": "example-service", "allow": ["operator", "monitor"] }\n  ]\n}\n'})}),"\n",(0,d.jsxs)(n.p,{children:["Provider and consumers attach to the bus with a ",(0,d.jsx)(n.code,{children:"system-bus"})," requirement under\ntheir role (provider as ",(0,d.jsx)(n.code,{children:"example-service"}),", consumer as ",(0,d.jsx)(n.code,{children:"operator"}),"):"]}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-json",children:'{ "name": "system-bus", "type": "dbus", "role": "operator",\n  "target": "/run/dbus/system_bus_socket" }\n'})}),"\n",(0,d.jsx)(n.p,{children:"Two consumer containers demonstrate the allow list from both 
1sides:"}),"\n",(0,d.jsxs)(n.ul,{children:["\n",(0,d.jsxs)(n.li,{children:[(0,d.jsx)(n.code,{children:"pv-example-system-dbus-client"})," attaches under the ",(0,d.jsx)(n.code,{children:"operator"})," role, which is\nin the provider's ",(0,d.jsx)(n.code,{children:"allow"})," list, so its calls are ",(0,d.jsx)(n.strong,{children:"permitted"}),"."]}),"\n",(0,d.jsxs)(n.li,{children:[(0,d.jsx)(n.code,{children:"pv-example-system-dbus-client-denied"})," attaches under the ",(0,d.jsx)(n.code,{children:"stranger"})," role,\nwhich is ",(0,d.jsx)(n.strong,{children:"not"})," in the ",(0,d.jsx)(n.code,{children:"allow"})," list, so the generated default-deny policy\n",(0,d.jsx)(n.strong,{children:"refuses"})," its otherwise-identical calls."]}),"\n"]}),"\n",(0,d.jsx)(n.h3,{id:"build-and-verify-2",children:"Build and Verify"}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-bash",children:"./kas-container build kas/build-configs/release/docker-x86_64-scarthgap.yaml \\\n    --target pv-example-system-dbus-server --target pv-example-system-dbus-client \\\n    --target pv-example-system-dbus-client-denied\n"})}),"\n",(0,d.jsxs)(n.p,{children:["Pantavisor allocates a stable UID per role, generates a default-deny policy\nunder ",(0,d.jsx)(n.code,{children:"/run/pv/dbus/policy.d"}),", and the proxy masquerades each connection to its\nrole UID. Check the consumer logs for a successful call:"]}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-bash",children:"docker exec pva-test tail -f /var/pantavisor/storage/logs/0/pv-example-system-dbus-client/lxc/console.log\n# Expected: method return with org.pantavisor.Example response\n"})}),"\n",(0,d.jsxs)(n.p,{children:["A container requesting a role not in the ",(0,d.jsx)(n.code,{children:"allow"})," list is denied by the generated\npolicy (",(0,d.jsx)(n.code,{children:"AccessDenied"}),"), and a state that exports the reserved ",(0,d.jsx)(n.code,{children:"system-bus"})," name\nor double-owns a well-known name is rejected at validation."]}),"\n",(0,d.jsx)(n.hr,{}),"\n",(0,d.jsx)(n.h2,{id:"drm-example",children:"DRM Example"}),"\n",(0,d.jsx)(n.p,{children:"Demonstrates DRM device node injection for graphics access."}),"\n",(0,d.jsxs)(n.p,{children:[(0,d.jsx)(n.strong,{children:"Provider"})," ",(0,d.jsx)(n.code,{children:"pv-example-drm-provider"})," \u2014 exports DRM devices\n",(0,d.jsx)(n.strong,{children:"Consumer"})," ",(0,d.jsx)(n.code,{children:"pv-example-drm-master"})," \u2014 requests ",(0,d.jsx)(n.code,{children:"/dev/dri/card0"})," (KMS)\n",(0,d.jsx)(n.strong,{children:"Consumer"})," ",(0,d.jsx)(n.code,{children:"pv-example-drm-render"})," \u2014 requests ",(0,d.jsx)(n.code,{children:"/dev/dri/renderD128"})," (GPU rendering)"]}),"\n",(0,d.jsx)(n.p,{children:(0,d.jsxs)(n.strong,{children:["Provider ",(0,d.jsx)(n.code,{children:"services.json"}),":"]})}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-json",children:'[\n  {"name": "drm-master", "type": "drm", "socket": "/dev/dri/card0"},\n  {"name": "drm-render", "type": "drm", "socket": "/dev/dri/renderD128"}\n]\n'})}),"\n",(0,d.jsx)(n.p,{children:(0,d.jsxs)(n.strong,{children:["Consumer ",(0,d.jsx)(n.code,{children:"args.json"})," (drm-master):"]})}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-json",children:'{\n  "PV_SERVICES_REQUIRED": [{"name": "drm-master", "target": "/dev/dri/card0"}]\n}\n'})}),"\n",(0,d.jsx)(n.h3,{id:"testing-with-vkms",children:"Testing with VKMS"}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-bash",children:"sudo modprobe vkms\nls -la /dev/dri/   # card0 (VKMS does not create renderD* nodes)\n"})}),"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",(0,d.jsxs)(n.table,{children:[(0,d.jsx)(n.thead,{children:(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.th,{children:"Device"}),(0,d.jsx)(n.th,{children:"VKMS"}),(0,d.jsx)(n.th,{children:"Use case"})]})}),(0,d.jsxs)(n.tbody,{children:[(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.td,{children:(0,d.jsx)(n.code,{children:"/dev/dri/card0"})}),(0,d.jsx)(n.td,{children:"Yes"}),(0,d.jsx)(n.td,{children:"KMS/display"})]}),(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.td,{children:(0,d.jsx)(n.code,{children:"/dev/dri/renderD128"})}),(0,d.jsx)(n.td,{children:"No"}),(0,d.jsx)(n.td,{children:"GPU compute"})]})]})]}),"\n",(0,d.jsx)(n.h3,{id:"build-and-run",children:"Build and Run"}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-bash",children:'./kas-container build kas/build-configs/release/docker-x86_64-scarthgap.yaml \\\n    --target pv-example-drm-provider --target pv-example-drm-master\ncp build/tmp-scarthgap/deploy/images/docker-x86_64/pv-example-drm-*.pvrexport.tgz pvtx.d/\n\n# Ru
1n with DRM device passthrough\ndocker run --name pva-test -d --privileged \\\n    --device /dev/dri:/dev/dri \\\n    -v $(pwd)/pvtx.d:/usr/lib/pantavisor/pvtx.d \\\n    -v storage-test:/var/pantavisor/storage \\\n    --entrypoint /bin/sh pantavisor-appengine:latest -c "sleep infinity"\n'})}),"\n",(0,d.jsx)(n.p,{children:"Verify injection:"}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-bash",children:"MASTER_PID=$(docker exec pva-test lxc-info -n pv-example-drm-master -p | awk '{print $2}')\ndocker exec pva-test ls -la /proc/$MASTER_PID/root/dev/dri/   # expect card0 226:0\n"})}),"\n",(0,d.jsx)(n.hr,{}),"\n",(0,d.jsx)(n.h2,{id:"wayland-example",children:"Wayland Example"}),"\n",(0,d.jsx)(n.p,{children:"Demonstrates Wayland compositor access. Requires DRM."}),"\n",(0,d.jsxs)(n.p,{children:[(0,d.jsx)(n.strong,{children:"Provider"})," ",(0,d.jsx)(n.code,{children:"pv-example-wayland-server"})," \u2014 Weston compositor (requires DRM from drm-provider)\n",(0,d.jsx)(n.strong,{children:"Consumer"})," ",(0,d.jsx)(n.code,{children:"pv-example-wayland-client"})," \u2014 Wayland client"]}),"\n",(0,d.jsx)(n.p,{children:(0,d.jsxs)(n.strong,{children:["Provider ",(0,d.jsx)(n.code,{children:"services.json"}),":"]})}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-json",children:'[{"name": "wayland-0", "type": "wayland", "socket": "/run/wayland/wayland-0"}]\n'})}),"\n",(0,d.jsx)(n.p,{children:(0,d.jsxs)(n.strong,{children:["Provider ",(0,d.jsx)(n.code,{children:"args.json"})," (requires DRM):"]})}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-json",children:'{\n  "PV_SERVICES_REQUIRED": [{"name": "drm-master", "target": "/dev/dri/card0"}]\n}\n'})}),"\n",(0,d.jsx)(n.p,{children:(0,d.jsxs)(n.strong,{children:["Consumer ",(0,d.jsx)(n.code,{children:"args.json"}),":"]})}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-json",children:'{\n  "PV_SERVICES_REQUIRED": [{"name": "wayland-0", "target": "/run/wayland/wayland-0"}]\n}\n'})}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-bash",children:"./kas-container build kas/build-configs/release/docker-x86_64-scarthgap.yaml \\\n    --target pv-example-drm-provider \\\n    --target pv-example-wayland-server \\\n    --target pv-example-wayland-client\n"})}),"\n",(0,d.jsxs)(n.blockquote,{children:["\n",(0,d.jsxs)(n.p,{children:["VKMS provides ",(0,d.jsx)(n.code,{children:"card0"})," but won't produce actual display output. Full Wayland testing requires real GPU hardware."]}),"\n"]}),"\n",(0,d.jsx)(n.hr,{}),"\n",(0,d.jsx)(n.h2,{id:"debugging-tips",children:"Debugging Tips"}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-bash",children:"# Container status\ndocker exec pva-test lxc-ls -f\n\n# Enter a container\ndocker exec -it pva-test pventer -c <container_name>\n\n# Container namespace inspection\ndocker exec pva-test lxc-info -n <container_name> -p\ndocker exec pva-test ls -la /proc/<PID>/root/run/\n\n# Common issues\n"})}),"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",(0,d.jsxs)(n.table,{children:[(0,d.jsx)(n.thead,{children:(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.th,{children:"Symptom"}),(0,d.jsx)(n.th,{children:"Cause"}),(0,d.jsx)(n.th,{children:"Fix"})]})}),(0,d.jsxs)(n.tbody,{children:[(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.td,{children:"Container exits immediately"}),(0,d.jsx)(n.td,{children:"Missing DRM device"}),(0,d.jsxs)(n.td,{children:["Add ",(0,d.jsx)(n.code,{children:"--device /dev/dri:/dev/dri"})]})]}),(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.td,{children:"Socket not injected"}),(0,d.jsx)(n.td,{children:"pv-xconnect not running"}),(0,d.jsx)(n.td,{children:(0,d.jsx)(n.code,{children:"docker exec pva-test pvcontrol daemons ls"})})]}),(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.td,{children:'"Connection refused"'}),(0,d.jsx)(n.td,{children:"Provider not ready"}),(0,d.jsx)(n.td,{children:"Wait for provider container RUNNING status"})]}),(0,d.jsxs)(n.tr,{children:[(0,d.jsx)(n.td,{children:"Device not found"}),(0,d.jsx)(n.td,{children:"Wrong major:minor"}),(0,d.jsxs)(n.td,{children:[(0,d.jsx)(n.code,{children:"stat /dev/dri/card0"})," on host"]})]})]})]}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-bash",children:"# Cleanup between tests\ndocker rm -f pva-test\ndocker volume rm storage-test\n"})})]})}function x(e={}){let{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,d.jsx)(n,{...e,children:(0,d.jsx)(o,{...e})}):o(e)}},28453(e,n,s){s.d(n,{R:()=>c,x:()=>a});var r=s(96540);let d={},i=r.createContext(d);function c(e){let n=r.useContext(i);return r.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(d):e.components||d:c(e.components),r.createElement(i.Provider,{value:n},e.children)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.