coupled-migrate

Treat N coupled nodes as one migration subject. Where cluster-migrate groups independent hosts by similarity, coupled-migrate handles nodes that share state — a replicated database, a quorum cluster — and must move as a unit. The manifest keeps the <name> <kind> <locator> [target] shape and adds role= and from= to express the topology. A directed, asynchronous single-primary topology is plannable end to end; a quorum topology (Galera and similar) is named as one subject but the ring is not executed, and single-node dump/restore stays refused.

Emitting per-node attestations needs a --target. A directed-async edge is attested from a --soak window: without a soak record the cluster stays Inconclusive and is not billed. A quorum subject does not reconstitute from a soak — the soak attests an edge, not a mesh.

Billing follows migrate: each node that produces a migration attestation records one depersonalized migration usage event, billable per your plan and target (see Accounts, quota & billing). A node left Inconclusive for want of a soak, or a quorum ring that is not executed, is not migrated and records nothing.

vrtmv coupled-migrate --manifest topology.txt --target rocky9 -o out/
vrtmv coupled-migrate --manifest topology.txt --target rocky9 --soak edge-soak.json -o out/
FlagPurpose
--manifest <path>Topology-aware manifest, with role= / from= on each line.
-o, --out <path>Output directory for the cluster record and per-node attestations (default vrtmv-coupled).
--target <os>Target OS (e.g. rocky9). Required to emit per-node attestations.
--soak <path>A SoakRecord from vrtmv soak summarise --out for the edge window. Without it the cluster stays Inconclusive and is not billed.

Services the roles will not start

Each node's role is the one migrate writes, so it fails at its last task while the node's source started services at boot that the role will not start. The runbook's plays stop the sequence at the first failure. Left to the roles, a cutover would stop after its first node, with that node applied and the others not.

So when any node has such services, coupled-migrate prints the count for each node, and cluster-migrate.yml begins with a play that runs on the controller and refuses the cutover before any node is touched. It names each node, how many services, and the role file that lists them with reasons. Read those lists, then run the playbook with -e vrtmv_services_not_started_acknowledged=true: the first play passes and so does each role's last task. The one variable accepts every node's list.

The first play is not written when no node has such services. It needs localhost to be reachable by the playbook run: a --limit that leaves localhost out skips it, and each role then fails at its own last task as above.

Nodes that report one identity

Each node is billed by its identity (see identity). When two nodes of the manifest report one identity, they are clones of one image or one node listed twice. The cluster is one subject, so the whole run is refused before the cluster record, the attestations, the runbook or any usage report is written. The refusal names the nodes and the file the identity came from. Run vrtmv identity on each clone, or fix the manifest, and run again.