RFDs/0014
VM lifecycle operations
Goal
Let authorized operators start, stop, and reboot virtual machines from Renga, where they already see each VM, its hypervisor, and its guest. RFD 1 names VM lifecycle as a later control slice; RFD 11 makes VMs observable read-only. This RFD adds the operations on RFD 9's jobs, with the installation credentials from RFD 13.
Live migration and placement are deliberately later: they need capacity and affinity modeling that this RFD does not attempt.
Operations
vm.power@1 is an operate capability on hypervisor installations running the
RFD 11 libvirt module. Its action parameter is one
of:
-
start; -
shutdown: a graceful ACPI shutdown, waiting up to a timeout; -
reboot: a graceful reboot; -
force_off: immediate power off, the equivalent of pulling the plug; -
reset: immediate reset.
start, shutdown, and force_off converge to a requested power state: asking
to start a running VM succeeds and records that nothing changed. reboot and
reset are imperative, non-idempotent actions; a running state before and after
does not prove whether either action occurred. The job’s result records the
VM’s state before and after from libvirt and whether the action’s outcome is
known.
Each operation has a stable identity (the job ID) across delivery attempts, bound to its approved target and action. The agent durably records execution intent before invoking libvirt and retains known outcomes for duplicate deliveries. This prevents ordinary duplicate execution, but cannot atomically commit an external libvirt effect with the execution record.
This extends RFD 9's retry contract: lease loss for
reboot or reset must not
automatically requeue execution. A crash or lost completion after execution may
have begun records an uncertain outcome (an explicit job outcome/event), not
success or a safe-to-retry failure. Reconciliation or operator investigation
must resolve it; a new attempt requires a new explicitly authorized operation.
Neither an expired lease nor a durable started marker proves no effect occurred.
Convergent actions may retry only against the same valid target after checking
current state and authorization; no retry crosses a changed binding.
Desired and observed state
A VM’s envelope gains a desired power state. Requesting an operation records the desired state and creates the job. The VM’s observed state keeps coming from RFD 11 evidence. When the two disagree for longer than the VM’s freshness window, Renga opens a power-state drift finding.
The first release does not enforce desired state automatically. A VM that is shut down from inside the guest raises drift for an operator to resolve; Renga does not restart it on its own.
Authorization
An operation requires all of these:
-
the hypervisor agent enables
vm.powerlocally and has an approved installation key (RFD 13); -
the organization enables VM operations;
-
the user holds a VM operator grant over a target set containing the VM, created by an owner or admin. Like a terminal grant, it may expire, within the organization’s maximum validity if it sets one (RFD 19). Owners and admins are not granted it implicitly.
The RFD 13 trusted binding includes the VM resource ID, provider installation and approved key, collector ID, hypervisor identity, and libvirt domain UUID. Shared-key VM correlation or placement evidence cannot approve or redirect this binding. Migration or a provider change requires trusted rebinding and fresh authorization, not automatic retargeting of queued work. For active operations, fresh unambiguous placement must agree with the binding. Starting an inactive VM requires a fresh definition on the explicitly approved provider, not arbitrary selection among hosts that retain its definition.
force_off and reset also require a reason and a confirmation that names the
VM. An organization may require a second operator’s approval for them: the job
waits in queued until someone else with a grant approves it, or it expires.
Safety
Before any request, Renga shows a preview with the VM, its hypervisor, current observed state, whether a guest agent is reporting from it, and the resources that list it as a dependency. The preview captures the approved target binding and version with the action. Dispatch and the agent revalidate that target and current domain state immediately before execution. Changed binding, stale or ambiguous placement, or a conflicting state requires a new preview and approval, never silently changing the provider or VM the operator confirmed.
Audit
Every request, approval, job event, and resulting state change appears in the VM’s activity and the organization feed. Desired-state changes are ordinary change events, so the record shows who wanted the VM off and when it actually went off.
Decisions from review
-
Two-operator approval for
force_offandresetis off by default; an organization enables it. A reason and a confirmation naming the VM are always required. -
A request waiting for its second approval expires after 15 minutes, so a stale request cannot be approved against a VM that has since changed.
-
A graceful
shutdownthat times out fails and says so; it never falls back toforce_off. The operator requestsforce_offseparately, with its own reason and confirmation.
Rollout
-
Add desired power state on VM envelopes and the drift finding.
-
Add
vm.power@1to the libvirt module with convergent versus imperative retry rules, uncertain outcomes, and before-and-after state. -
Add organization enablement, VM operator grants, and reasons and confirmation for destructive actions.
-
Add two-operator approval as an organization option.
-
Add the preview and the power controls on the VM page.
Implementation
Progress is tracked in the implementation checklist.