Skip to content

Commit b96fe9c

Browse files
kvapsclaude
andcommitted
docs(plan): track Phase 9 layer-stack work (no-DRBD + LUKS layering)
The MVP scope hardcoded the layer chain to STORAGE→DRBD; the project's stated goals include single-replica local mode (no DRBD) and a LUKS encryption layer. Capture the gap explicitly so it doesn't drift; phase outline includes the satellite-side stack walker, the CSI shape, the test matrix, and an open question about passphrase rotation interaction. Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
1 parent 1481d4a commit b96fe9c

1 file changed

Lines changed: 22 additions & 0 deletions

File tree

PLAN.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,28 @@ The dev stand has been Talos+QEMU loopfile-backed. Production parity needs:
473473

474474
---
475475

476+
## Phase 9 — Layer stack (no-DRBD + LUKS layering)
477+
478+
The project's stated goal includes "ability to run without DRBD, as pure local storage (single-replica diskful or diskless)" and a LUKS encryption layer at the volume level. Today's satellite always renders a `.res` and shells out to `drbdadm`; LUKS exists in `pkg/luks` but isn't wired through `applyStorage`. To match upstream LINSTOR's `layer_list` semantics:
479+
480+
- [ ] **`ResourceDefinition.Spec.LayerStack` (or per-RD prop)** — array of layers, default `["DRBD","STORAGE"]`. Valid values: `STORAGE`, `LUKS`, `DRBD`. Order matters: `[LUKS,STORAGE]` = LUKS-on-LV, no DRBD; `[DRBD,LUKS,STORAGE]` = DRBD-over-LUKS-over-LV (per-volume cipher with replication on top).
481+
- [ ] **Satellite-side stack execution** — in `applyResource`, walk the layer stack:
482+
- `STORAGE` always runs — provider creates the backing block device
483+
- `LUKS` (when present) — `pkg/luks.Format` (first activation), `Open` to /dev/mapper/<rd>-<volnum>, `Close` on teardown. Key material from a per-RD passphrase (KV-store under `Cryptokeys/<rd>`)
484+
- `DRBD` (when present) — render `.res` against the highest-layer device path (storage device if just `[DRBD,STORAGE]`, mapper device if `[DRBD,LUKS,STORAGE]`); `drbdadm create-md/adjust`. Skip entirely when DRBD isn't in the stack.
485+
- [ ] **CSI shape** — linstor-csi reads `layer_list` on RD; pass it through unchanged so existing piraeus-operator flows keep working when they configure `LinstorSatelliteConfiguration.spec.storageClasses[*].layerList`.
486+
- [ ] **Tests**:
487+
- unit: layer stack decoder rejects unknown layers, defaults to `[DRBD,STORAGE]` when empty
488+
- satellite contract: `[STORAGE]` apply renders no `.res` and never invokes `drbdadm`
489+
- satellite contract: `[LUKS,STORAGE]` apply runs `cryptsetup luksFormat` once, `cryptsetup open` on subsequent reconciles, never DRBD
490+
- satellite contract: `[DRBD,LUKS,STORAGE]` apply layers all three; `.res` points at /dev/mapper/<rd>-0, not the raw LV
491+
- e2e: `tests/e2e/no-drbd.sh` (single-replica ZFS-backed PVC, write/read), `tests/e2e/luks-layer.sh` (encrypted single-replica PVC + reboot remount), `tests/e2e/drbd-luks-stack.sh` (3-replica encrypted)
492+
- [ ] **Documentation**`docs/layer-stack.md` with the upstream LINSTOR layer model, the supported subset, and how it maps to cozystack StorageClasses.
493+
494+
Open question: cluster passphrase rotation (`POST /v1/encryption/passphrase`) already lands in Phase 7 — its interaction with the LUKS layer needs to be pinned (re-encrypt all volumes vs. just rotate the wrapping key).
495+
496+
---
497+
476498
## Workflow
477499

478500
### Daily loop

0 commit comments

Comments
 (0)