templates: add PV_STATUS_MOUNTED=staged for full MOUNTED containers with status_substate STAGED

What

Adds a new template argument PV_STATUS_MOUNTED to pvr's builtin lxc/docker template, only meaningful when PV_STATUS_GOAL=MOUNTED.

Why

Pantavisor is adding STAGED as a substate of the MOUNTED status goal: pantavisor#827. STAGED means volumes mounted, drivers loaded, process not started; startable on demand via pv-ctrl. Older pantavisor ignores status_substate and just keeps the container MOUNTED. The container run.json for it looks like:

{ "status_goal": "MOUNTED", "status_substate": "STAGED", "type": "lxc", "config": "lxc.container.conf", ... }

pvr's run.json template had no path to that: PV_STATUS_GOAL=MOUNTED always rendered a data-only container (no type, no config, no lxc.container.conf) — same treatment as the data runlevel — so there was no way to template a full MOUNTED+STAGED container.

What changes

PV_STATUS_MOUNTED Output
unset / "" / "dataonly" (default) today's data-only rendering — byte-identical to before this MR
"staged" full container (type, config, lxc.container.conf, everything a STARTED container gets), plus "status_substate": "STAGED"
any other value warned on stderr, treated as "dataonly"; never fails the render

PV_STATUS_MOUNTED is ignored entirely when PV_STATUS_GOAL isn't MOUNTED. The data runlevel behaviour is untouched.

Compatibility

Unset (the status quo for every existing args.json) renders byte-identical run.json/lxc.container.conf to before this change — verified in the new test (PV_STATUS_MOUNTED staged renders full container) and confirmed via go test ./....

Example output

PV_STATUS_GOAL=MOUNTED, PV_STATUS_MOUNTED unset/dataonly (unchanged):

{
	"#spec": "service-manifest-run@1",
	"name":"myvolapp",
	"drivers": { "manual":[], "required":[], "optional":[] },
	"services": { "manual":[], "required":[], "optional":[] },
	"status_goal": "MOUNTED",
	"storage":{ "lxc-overlay" : { "persistence": "boot" } },
	"root-volume": "root.squashfs",
	"volumes":[]
}

(lxc.container.conf is empty / not generated.)

PV_STATUS_GOAL=MOUNTED, PV_STATUS_MOUNTED=staged (new):

{
	"#spec": "service-manifest-run@1",
	"name":"myvolapp",
	"config": "lxc.container.conf",
	"drivers": { "manual":[], "required":[], "optional":[] },
	"services": { "manual":[], "required":[], "optional":[] },
	"status_goal": "MOUNTED",
	"status_substate": "STAGED",
	"storage":{ "lxc-overlay" : { "persistence": "boot" } },
	"type":"lxc",
	"root-volume": "root.squashfs",
	"volumes":[]
}

with a real lxc.container.conf generated alongside it.

Test plan

  • go build ./...
  • go test ./... (all packages pass)
  • New table-driven test in templates/compile-template_test.go covering unset/""/dataonly/staged/unrecognized-value/ non-MOUNTED-goal cases for both RUN_JSON and LXC_CONTAINER_CONF.

Merge request reports

Loading
Loading