You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Three more replica-lifecycle pieces:
1. ResourceDefinitionReconciler now maintains the tiebreaker
invariant: an RD with exactly 2 diskful replicas in a 3+ node
cluster auto-gains a DISKLESS witness on a healthy node not
already hosting a replica. Without it, a 1-vs-1 network
partition freezes both replicas — neither can tell which side
is the majority. The witness votes in the quorum without
storing data. Idempotent, EVICTED/LOST-aware, deterministic
tiebreaker placement (lowest-name first) so reconcile races
converge.
2. Resource activate / deactivate endpoints. POST .../activate
clears the INACTIVE flag, .../deactivate sets it. Satellite
reconciler reads the flag and runs `drbdadm down` instead of
the normal apply path, preserving the .res file + port +
node-id allocations so the operator can flip it back without
re-syncing. Used by piraeus-operator during node maintenance.
3. AutoSelectFilter.DisklessOnRemaining is wired through (was
accepted on the wire but ignored). After diskful place_count
is satisfied, every healthy non-replica node gets a DISKLESS
replica — the "cluster-wide attachable PVC" pattern. Filter
respects EVICTED/LOST same as the diskful path.
Tests:
- TestTiebreakerCreated: 3-node cluster, 2 diskful → 1 tiebreaker
on the third node
- TestTiebreakerSkipsThreeReplicas: no tiebreaker when majority
already guaranteed
- TestTiebreakerSkipsTwoNodeCluster: no spare node → no-op
- TestTiebreakerSkipsEvictedNode: never lands on EVICTED
- TestResourceDeactivate: flag set is idempotent, activate clears
- TestResourceActivateUnknown: 404 on missing replica
- TestAutoplaceDisklessOnRemaining: 4 nodes, place_count=2 →
2 diskful + 2 diskless witnesses
Phase 8.3 closes (auto-diskful is the lone remaining item — it
needs runtime metric tracking that's a separate piece of work).
Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
Copy file name to clipboardExpand all lines: PLAN.md
+3-3Lines changed: 3 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -413,9 +413,9 @@ The phases above closed the MVP slice and the csi-sanity REST contract. A deep a
413
413
-[x]**`linstor node evacuate` actually migrates replicas** (2026-05-09). New `internal/controller.NodeReconciler` watches Node CRDs and on EVICTED enumerates every Resource on the affected node, runs the shared `pkg/placer.Place` to create a replacement on a non-disabled peer (honouring the parent RG's topology constraints), and leaves the source replica in place — the operator decides when to remove it (typically once the replacement is UpToDate). The placer's "existing replicas" count now excludes EVICTED/LOST nodes so a 2-replica RD with one evicted source actually triggers the migration. Test: `TestNodeReconciler_EvictedTriggersMigration` pins the 3-node migration path.
414
414
-[x]**`linstor node lost` recovery** (2026-05-09): the same NodeReconciler also detects LOST. Migration runs as for EVICTED, then the source Resource CRD is deleted via the K8s API path so the Resource controller's finalizer cleans up. The TCP-port/node-id allocations stored on the source Resource Status free naturally on delete (the per-node port allocator scans live Resources). Test: `TestNodeReconciler_LostDeletesSourceResource`. **e2e** (hard-kill a satellite pod) sits on the 8.8 checklist.
415
415
-[ ]**auto-diskful / auto-diskful-cleanup**. Upstream watches Resource access patterns and auto-promotes a diskless to diskful when a node uses it heavily, reverses on idle. Implement the controller-side metric collection + threshold. Pin via simulation test that drives synthetic access counts.
416
-
-[]**Tiebreaker auto-creation**. 2-replica RDs in a 3+ node cluster need a 3rd diskless replica for `quorum:majority`. Today: no auto-tiebreaker. Add a controller-side reconciler that maintains exactly-one tiebreaker on a separate failure domain.
417
-
-[]**Resource activate / deactivate** (`POST /v1/resource-definitions/{rd}/resources/{node}/{activate,deactivate}`). Used by piraeus-operator during node maintenance; today we 404. Implement as drbdadm up/down on the satellite without removing the Resource CRD.
418
-
-[]**Diskless replicas as first-class autoplace candidates**. `candidatePools` skips DISKLESS pools entirely. Add a `--diskless` flag and the diskless-on-remaining behaviour upstream has, so manual `linstor resource create --diskless` and the autoplace `diskless_on_remaining=true` path both work.
416
+
-[x]**Tiebreaker auto-creation** (2026-05-09). New `internal/controller.ResourceDefinitionReconciler` watches RDs; an RD with exactly 2 diskful replicas auto-gains a 3rd DISKLESS replica on a healthy non-replica node so DRBD's `quorum:majority` always has a majority on a 1-vs-1 partition. Idempotent (re-running on a 3-replica or already-witnessed RD is a no-op), respects EVICTED/LOST node flags, picks deterministically (lowest-name first) so reconcile races converge. The witness carries the `TIE_BREAKER` flag for cleanup tracking. Tests: `TestTiebreakerCreated`, `TestTiebreakerSkipsThreeReplicas`, `TestTiebreakerSkipsTwoNodeCluster`, `TestTiebreakerSkipsEvictedNode`.
417
+
-[x]**Resource activate / deactivate** (2026-05-09): `POST /v1/resource-definitions/{rd}/resources/{node}/{activate,deactivate}` toggles the `INACTIVE` flag on the Resource. Idempotent. Satellite reconciler reads the flag and runs `drbdadm down` (deactivate) or normal apply (activate) — the .res file, port, and node-id allocations all stay intact, so flipping back doesn't lose state. Tests: `TestResourceDeactivate` (idempotent set + clear), `TestResourceActivateUnknown` (404 on missing replica).
418
+
-[x]**Diskless replicas as first-class autoplace candidates** (2026-05-09): `AutoSelectFilter.DisklessOnRemaining` now actually does what the field name promises. After diskful place_count is satisfied, the placer creates DISKLESS replicas on every healthy node not already hosting a replica — the upstream "cluster-wide attachable" pattern useful for consumers that need to mount on any node. Test: `TestAutoplaceDisklessOnRemaining` (4-node cluster, place_count=2 → 2 diskful + 2 diskless witnesses).
0 commit comments