New container goal STAGED: ready to run, started on demand

Pantavisor master now supports a new container goal, STAGED: the container is fully prepared at boot, with volumes mounted and drivers loaded, but its process is not started. It waits there until something asks for it. This landed in pantavisor#826 and pantavisor#827, with template support in pvr!505.

Background

Every container in a revision has a goal: the state Pantavisor drives it to and waits for before unlocking the next group. Until now there were three:

  • MOUNTED: volumes mounted, never started. Meant for data-only containers.
  • STARTED / READY: started at boot, optionally waiting for a readiness signal.

There was no clean way to say “this container is a normal app, but don’t run it yet.” STAGED closes that gap.

Designed to install on older Pantavisor

A new value in the existing status_goal field would have been a trap: the Pantavisor already running on a device validates an update before installing it, and older versions reject a revision with a goal they don’t know. A single update that brings a new Pantavisor and a STAGED container would then never install.

So STAGED lives in a new field, lifecycle_goal, next to the familiar status_goal:

{
    "status_goal": "MOUNTED",
    "lifecycle_goal": "STAGED"
}
  • Newer Pantavisor uses lifecycle_goal and stages the container.
  • Older Pantavisor ignores the field it doesn’t know and uses status_goal as the fallback. The revision installs normally.

You choose the fallback. MOUNTED keeps the container parked on older devices; STARTED keeps today’s behaviour there, starting it at boot, while newer devices stage it. The same fields work at group level in device.json, and a container’s own setting wins over its group’s.

How to use it

With pvr, set the goal in your container’s args.json:

{
    "PV_LIFECYCLE_GOAL": "STAGED",
    "PV_STATUS_GOAL": "STARTED"
}

PV_STATUS_GOAL is the fallback for older Pantavisor and defaults to MOUNTED when left out. "PV_STATUS_GOAL": "STAGED" on its own is a shorthand for staged with a MOUNTED fallback. pvr app add --lifecycle-goal STAGED does the same from the command line.

At boot a STAGED container counts as done: its group and the device move on immediately without waiting for it. Start it when you need it through the local control socket (the container needs restart_policy: "container", like any API-controlled container):

$ pvcontrol containers start my-app

Because volumes are already mounted, the start goes straight to loading drivers and starting the process. Stopping it afterwards works as usual. Details are in the container docs.

Why it matters: on-demand activation and lazy initialization

STAGED separates preparing a container from running it:

  • Lazy initialization. Software that is only needed occasionally, such as diagnostics, provisioning helpers or rarely used services, no longer has to run from boot. It sits prepared, costs no CPU or memory until it is started, and boot does not wait on it.
  • On-demand activation. The next step, in review, uses STAGED for D-Bus service activation on the Pantavisor-hosted system bus: a service owner such as pv-avahi is parked at STAGED and Pantavisor starts it the first time a client calls its bus name (pantavisor#738). A follow-up extends this to consumers and name-based requirements (pantavisor#820).
  • Fast start when it counts. Mounting and driver setup already happened at boot, so an on-demand start only has to start the process.

A broader rule for the state format

This episode also produced a general rule, in review as pantavisor#828: Pantavisor’s state parser should check structure, not reject a revision because it meets a value or key it doesn’t know yet. New features go into new fields that older versions safely ignore, so upgrading Pantavisor and using a new feature can always happen in one update.

Availability

STAGED is in Pantavisor and pvr master now, and reaches meta-pantavisor builds with the next source updates. Feedback and use cases are welcome in this thread, especially containers you would like to start lazily.