mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-08-18 21:26:56 +00:00
docs(p15): add G15a CSI static MVP port plan
This commit is contained in:
@@ -0,0 +1,216 @@
|
||||
# V3 Phase 15 — G15a CSI Static MVP Mini-Plan
|
||||
|
||||
**Date**: 2026-05-03
|
||||
**Status**: architect draft; code must start from this plan, not from direct V2 copy
|
||||
**Branch**: proposed `p15-g15a/csi-static-mvp` off `origin/phase-15`
|
||||
**Goal**: make Kubernetes CSI consume an already-provisioned V3 block assignment and mount it through the Linux node path.
|
||||
|
||||
---
|
||||
|
||||
## §1 Scope
|
||||
|
||||
G15a is not dynamic provisioning. It is the first CSI product loop:
|
||||
|
||||
```
|
||||
cluster-spec / product-loop assignment
|
||||
-> blockmaster publishes target facts
|
||||
-> CSI ControllerPublish returns publish_context
|
||||
-> CSI NodeStage logs in / connects and mounts
|
||||
-> CSI NodePublish bind-mounts into pod path
|
||||
```
|
||||
|
||||
The claim is: **a pre-provisioned V3 volume can be consumed by CSI without CSI minting authority or owning storage**.
|
||||
|
||||
---
|
||||
|
||||
## §2 V2 Port Discipline
|
||||
|
||||
Port V2 execution code where it is mechanism:
|
||||
|
||||
| V2 source | Decision | Reason |
|
||||
|---|---|---|
|
||||
| `csi/identity.go` | PORT-AS-IS | CSI spec mechanism. |
|
||||
| `csi/server.go` endpoint/service registration | PORT-REBIND | Keep gRPC/endpoint shape; replace V2 local manager/backend wiring. |
|
||||
| `csi/node.go` NodeStage/Publish/Unstage core | PORT-REBIND, mostly complete | Linux attach/mount mechanism is valuable and already QA-hardened. Remove local `VolumeManager` fallback for G15a. |
|
||||
| `csi/iscsi_util.go` | PORT-AS-IS | OS initiator + mount mechanism; injectable for tests. |
|
||||
| `csi/nvme_util.go` | PORT-AS-IS but optional in G15a | Keep shape; G15a may default to iSCSI-first if NVMe hardware confidence is lower. |
|
||||
| `csi/controller.go` ControllerPublish/Unpublish/Capabilities/Validate only | PORT-REBIND | Keep CSI request validation and response shape; backend is V3 assignment/status lookup. |
|
||||
| `csi/volume_backend.go` interface concept | REWRITE-TINY | V3 backend should expose lookup/publish facts from blockmaster, not V2 master RPC. |
|
||||
| `csi/volume_manager.go` | SKIP | V2 storage/target ownership; violates V3 boundary. |
|
||||
| snapshots / expand / CreateVolume | SKIP for G15a | Dynamic lifecycle belongs after product API/placement allocation is ratified. |
|
||||
|
||||
---
|
||||
|
||||
## §3 iSCSI / NVMe / CSI Unification Rule
|
||||
|
||||
CSI must not invent target identity. The V3 iSCSI/NVMe frontends already own protocol identity and target serving:
|
||||
|
||||
- `cmd/blockvolume --iscsi-listen --iscsi-iqn` starts `core/frontend/iscsi.Target`.
|
||||
- `cmd/blockvolume --nvme-listen --nvme-subsysnqn` starts `core/frontend/nvme.Target`.
|
||||
- iSCSI and NVMe target packages own wire/session semantics, VPD/Identify identity, capacity, and backend opening.
|
||||
|
||||
CSI is only the Kubernetes attach/mount layer. It consumes a **published frontend target fact**:
|
||||
|
||||
```
|
||||
volume_id
|
||||
replica_id
|
||||
authority epoch / endpoint_version
|
||||
protocol = iscsi | nvme
|
||||
target address
|
||||
iqn or subsys_nqn
|
||||
lun or nsid
|
||||
capacity / block size (optional read-only evidence)
|
||||
```
|
||||
|
||||
Current V3 gap: `AssignmentFact` carries data/ctrl addresses, and `cmd/blockvolume` prints `iscsi-listening` / `nvme-listening` lines for tests, but the master status API does not yet expose frontend target facts to a CSI controller. G15a must either:
|
||||
|
||||
1. add a read-only observation/status path for frontend target facts, or
|
||||
2. constrain the first L2 CSI smoke to a test backend that receives the same facts from subprocess ready lines.
|
||||
|
||||
The product direction is option 1. The test-only bridge in option 2 is allowed only as a temporary pre-product slice and must be named as such.
|
||||
|
||||
Boundary rules:
|
||||
|
||||
- CSI package may import CSI spec, OS attach helpers, and a narrow V3 publish-target lookup interface.
|
||||
- CSI package must not import `core/authority`.
|
||||
- CSI package must not construct `AssignmentAsk`, `AssignmentFact`, `adapter.AssignmentInfo`, Epoch, or EndpointVersion.
|
||||
- CSI package must not derive IQN/NQN from volume ID when a publish target fact is available.
|
||||
- IQN/NQN derivation, if needed for defaults, belongs in one shared helper used by `cmd/blockvolume` and CSI tests, not duplicated independently.
|
||||
|
||||
Loopback note:
|
||||
|
||||
Current `cmd/blockvolume` rejects non-loopback iSCSI/NVMe binds because frontends are unauthenticated. G15a has two valid modes:
|
||||
|
||||
- same-node/static MVP: CSI node plugin connects to a loopback target on the same node;
|
||||
- real multi-node Kubernetes: requires a separate security/bind ratification before exposing iSCSI/NVMe on routable addresses.
|
||||
|
||||
Do not silently turn off the loopback guard inside CSI.
|
||||
|
||||
---
|
||||
|
||||
## §4 Red Tests
|
||||
|
||||
The first code slice must land tests before or with implementation:
|
||||
|
||||
1. `ControllerPublish` fails closed when the V3 assignment/status backend has no verified frontend target for `volume_id`.
|
||||
2. `ControllerPublish` returns `iscsiAddr` + `iqn` from V3 assignment/status facts, not from cluster-spec directly.
|
||||
3. CSI package does not import `core/authority` and does not call `Publisher` / mint assignment facts.
|
||||
4. `NodeStageVolume` uses `PublishContext` before `VolumeContext`.
|
||||
5. `NodeStageVolume` is idempotent when the staging path is already mounted.
|
||||
6. `NodeStageVolume` cleans up login/connect if format/mount fails.
|
||||
7. `NodeUnstageVolume` preserves staged state on unmount/logout failure for retry.
|
||||
8. `.transport` restart recovery picks the correct disconnect path and rejects garbage transport values.
|
||||
9. `NodePublishVolume` bind-mounts staging to target and is idempotent.
|
||||
10. `CreateVolume`, snapshots, and expand return `Unimplemented` or are not advertised in G15a capabilities.
|
||||
11. CSI publish target lookup uses the same IQN/NQN as `cmd/blockvolume` frontend flags / frontend target facts.
|
||||
12. CSI attach must fail closed if the current authority target has no frontend target fact yet.
|
||||
13. CSI must not bypass the current authority line by using a stale endpoint from `VolumeContext`.
|
||||
|
||||
---
|
||||
|
||||
## §5 Slices
|
||||
|
||||
### G15a-1 — CSI package skeleton + boundary guards
|
||||
|
||||
Code:
|
||||
- New V3 CSI package, likely `core/csi` or `core/frontend/csi`.
|
||||
- Identity service.
|
||||
- Endpoint parser and service registration.
|
||||
- Controller capability surface with dynamic operations omitted.
|
||||
|
||||
Tests:
|
||||
- Identity nil request behavior.
|
||||
- endpoint parse tests.
|
||||
- no authority import / no publisher call guard.
|
||||
- Controller capabilities advertise only G15a-supported operations.
|
||||
|
||||
### G15a-2 — Node iSCSI attach/mount mechanism
|
||||
|
||||
Code:
|
||||
- Port V2 `node.go` iSCSI path and `iscsi_util.go` / mount helpers.
|
||||
- Remove local V2 manager fallback.
|
||||
- Keep `PublishContext` > `VolumeContext`.
|
||||
- Keep staged map, `.transport`, cleanup, idempotency.
|
||||
|
||||
Tests:
|
||||
- Port V2 node tests that do not rely on `VolumeManager`.
|
||||
- Port V2 adversarial cleanup tests.
|
||||
|
||||
### G15a-3 — ControllerPublish V3 backend
|
||||
|
||||
Code:
|
||||
- Define V3 CSI backend interface: `LookupPublishTarget(ctx, volumeID, nodeID)`.
|
||||
- Implement read-only backend against current blockmaster status / assignment surface plus frontend target facts, or a testable adapter around the existing product-loop state.
|
||||
- Return `publish_context` with iSCSI first; NVMe optional.
|
||||
|
||||
Tests:
|
||||
- found/missing target.
|
||||
- no direct cluster-spec shortcut.
|
||||
- no authority minting.
|
||||
- target fact must match the frontend fact reported by blockvolume.
|
||||
|
||||
### G15a-4 — L2 subprocess CSI smoke
|
||||
|
||||
Code:
|
||||
- `cmd/blockcsi` or `cmd/block-csi` binary.
|
||||
- Flags: endpoint, mode, node-id, master/status address, default transport.
|
||||
|
||||
Test:
|
||||
- blockmaster + blockvolume + CSI controller/node subprocess.
|
||||
- ControllerPublish gets target facts.
|
||||
- NodeStage/Publish uses mockable or real privileged path depending environment.
|
||||
- Non-privileged CI can stop at fake `ISCSIUtil` / `MountUtil`; M01/k8s executes real path.
|
||||
|
||||
### G15a-5 — Kubernetes YAML skeleton
|
||||
|
||||
Code/docs:
|
||||
- Port V2 deploy YAML with V3 image/flags/driver name.
|
||||
- Static PV/PVC example for pre-provisioned volume.
|
||||
|
||||
Test:
|
||||
- QA instruction only unless k8s lab is available.
|
||||
|
||||
---
|
||||
|
||||
## §6 Non-Claims
|
||||
|
||||
G15a does not claim:
|
||||
- dynamic CSI provisioning (`CreateVolume`);
|
||||
- snapshot or expansion support;
|
||||
- replica auto-repair under Kubernetes faults;
|
||||
- pod remount after primary kill;
|
||||
- multi-node network partition behavior;
|
||||
- NVMe as the default attach path.
|
||||
|
||||
Those belong to G15b/G15c after the static CSI path is stable.
|
||||
|
||||
---
|
||||
|
||||
## §7 QA Instructions
|
||||
|
||||
Default CI:
|
||||
|
||||
```powershell
|
||||
go test ./core/csi ./cmd/blockcsi ./cmd/blockvolume ./cmd/blockmaster -count=1
|
||||
```
|
||||
|
||||
If the package/binary names differ, update this section in the first implementation commit.
|
||||
|
||||
M01 / privileged Linux:
|
||||
|
||||
1. Start blockmaster with cluster-spec.
|
||||
2. Start blockvolume primary with iSCSI enabled.
|
||||
3. Start CSI controller/node.
|
||||
4. Run CSI ControllerPublish for the existing volume.
|
||||
5. Run NodeStage/NodePublish.
|
||||
6. Write/read through mounted filesystem.
|
||||
7. NodeUnpublish/NodeUnstage must clean up mount and session.
|
||||
|
||||
---
|
||||
|
||||
## §8 Forward-Carry
|
||||
|
||||
- G15b: dynamic `CreateVolume` backed by desired-volume + placement allocation.
|
||||
- G15c: Kubernetes node down/up, pod reschedule, primary kill, replica catch-up/rebuild, and data continuity.
|
||||
- G15d: NVMe attach path as first-class CSI transport.
|
||||
- G15e: snapshots/expand once V3 product APIs exist.
|
||||
@@ -0,0 +1,207 @@
|
||||
# V3 Phase 15 — G15a (CSI MVP) port survey
|
||||
|
||||
**Date**: 2026-04-28; code-read addendum 2026-05-03
|
||||
**Status**: Layer 1 topology + 2026-05-03 V2 code-read addendum complete; G15a scope not yet ratified
|
||||
**Owner**: QA (read-only port-survey assignment per architect 2026-04-28 ratification)
|
||||
**Scope**: pre-ratification scoping only; not a code commitment; per `feedback_porting_discipline.md`
|
||||
|
||||
**Methodology — top-down**:
|
||||
- Sources: directory listings, V2 design doc `v3-csi-iscsi-nvme-block-overview.md`, repo memory, k8s CSI v1.5 spec
|
||||
- Goal: identify high-level modules + dependency graph, classify port disposition at module granularity
|
||||
- Anti-pattern guard: Layer 1 did not open V2 `.go` files. The 2026-05-03 addendum below does open selected V2 `.go` files and records actual port disposition.
|
||||
|
||||
---
|
||||
|
||||
## Layer 1 — V2 CSI module topology
|
||||
|
||||
### V2 code locations (inventory only)
|
||||
|
||||
| Path | Contents |
|
||||
|---|---|
|
||||
| `weed/storage/blockvol/csi/` | 9 `.go` source files + 9 `_test.go` files + `cmd/` + `deploy/` |
|
||||
| `weed/storage/blockvol/csi/cmd/block-csi/` | Driver binary entry point |
|
||||
| `weed/storage/blockvol/csi/deploy/` | 6 k8s YAMLs (controller, node, driver, rbac, storageclass, example-pvc) |
|
||||
| `weed/storage/blockvol/testrunner/` | Test runner platform: engine, agent, coordinator, baseline; `actions/` (k8s, iscsi, block, io, metrics, fault); `infra/` (target, ha_target, iscsi_client, node, artifacts, fault) |
|
||||
| `weed/storage/blockvol/testrunner/scenarios/` | 16+ YAML scenarios incl. `coord-smoke-iscsi`, `coord-ha-failover`, `cp103-nvme-*`, `cp83-snapshot-expand`, `cp84-soak-4h`, `cp85-chaos-disk-full` |
|
||||
|
||||
### Top-level modules (Layer 1)
|
||||
|
||||
Seven distinct modules, classified by their primary coupling:
|
||||
|
||||
| # | Module | What it does (1-line) | Primary coupling |
|
||||
|---|---|---|---|
|
||||
| 1 | **CSI gRPC service layer** (controller.go, node.go, identity.go, server.go) | Implements k8s CSI v1.5 spec gRPC services: Controller / Node / Identity | k8s CSI spec (protobuf) |
|
||||
| 2 | **Transport adapter layer** (iscsi_util.go, nvme_util.go) | OS-level orchestration of iSCSI initiator (iscsiadm) and NVMe-oF initiator (nvme-cli); device-path resolution; format/mount glue | OS / Linux kernel |
|
||||
| 3 | **Volume backend bridge** (referenced as `VolumeBackend` in design doc, called from controller.go) | Talks to V2 master to create/delete BlockVol; receives IQN/NQN + addresses to put in PublishContext | **V2 wire** ← THIS IS THE PORT EDGE |
|
||||
| 4 | **Snapshot ID encoding** (snapshot_ids.go) | Encodes/decodes snapshot identifiers across CSI/backend boundary | Internal Go interface |
|
||||
| 5 | **Main binary** (cmd/block-csi/) | Wires gRPC server + transport adapters + volume backend; CLI flags | Internal wiring |
|
||||
| 6 | **K8s deployment artifacts** (deploy/) | k8s YAMLs: csi-controller, csi-node, csi-driver, rbac, storageclass, example-pvc | k8s API |
|
||||
| 7 | **Test corpus** (`*_test.go` + testrunner YAML scenarios) | In-package unit tests (controller, node, identity, snapshot, qa_*) + sw-test-runner end-to-end YAML scenarios driving CSI gRPC + iSCSI/NVMe device flows in a real (or simulated) cluster | Mixed (some k8s-spec, some V2-wire, some OS) |
|
||||
|
||||
### Dependency graph
|
||||
|
||||
```
|
||||
┌──────────────────┐
|
||||
│ cmd/block-csi │ (entrypoint, wires everything)
|
||||
└────────┬─────────┘
|
||||
│
|
||||
┌─────────────────┼─────────────────┐
|
||||
▼ ▼ ▼
|
||||
┌─────────────┐ ┌────────────────┐ ┌──────────────────┐
|
||||
│ gRPC svc │ │ Volume backend │ │ Transport │
|
||||
│ (Controller │──▶│ bridge │ │ adapters │
|
||||
│ Node │ │ (★ V2 wire ★) │ │ (iSCSI / NVMe) │
|
||||
│ Identity) │ └────────┬───────┘ └────────┬─────────┘
|
||||
└──────┬──────┘ │ │
|
||||
│ ▼ ▼
|
||||
▼ ┌──────────────┐ ┌──────────────┐
|
||||
k8s CSI spec │ V2 master / │ │ OS / kernel │
|
||||
(protobuf) │ volume gRPC │ │ (iscsiadm, │
|
||||
└──────────────┘ │ nvme cli, │
|
||||
│ mount) │
|
||||
└──────────────┘
|
||||
(deployment artifacts: (snapshot IDs:
|
||||
deploy/*.yaml, pure Go,
|
||||
k8s API only) no external coupling)
|
||||
```
|
||||
|
||||
**Key observations:**
|
||||
- Module 3 (Volume backend bridge) is the **only** module with hard V2 wire coupling. Everything else couples to k8s CSI spec or OS — both stable across V2/V3.
|
||||
- Modules 1, 2, 4 are protocol/spec-bound and don't know V2 vs V3 exists.
|
||||
- Module 6 (deployment YAMLs) couples only to driver name + image name — trivial edits.
|
||||
- Module 7 (tests) splits along the same lines as the modules they exercise: protocol-level tests (most) are V2/V3-agnostic; wire-level QA tests (`qa_cp62`, `qa_cp83`) need rewire matching new backend.
|
||||
|
||||
### Layer 1 disposition (preliminary — Layer 4 will refine)
|
||||
|
||||
| # | Module | Preliminary disposition | Why |
|
||||
|---|---|---|---|
|
||||
| 1 | CSI gRPC service layer | **port-as-is** | k8s CSI v1.5 spec is stable; gRPC handlers shape doesn't change |
|
||||
| 2 | Transport adapter layer | **port-as-is** | OS/kernel interface unchanged; iscsiadm + nvme-cli identical between V2/V3 |
|
||||
| 3 | Volume backend bridge | **port-with-rewire** | Same shape (CreateVolume → backend, DeleteVolume → backend), but the backend interface implementation must be replaced to call V3 master/replication APIs instead of V2 master |
|
||||
| 4 | Snapshot ID encoding | **port-as-is** | Pure Go encoding, no external deps |
|
||||
| 5 | Main binary | **port-with-light-rewrite** | Wiring code: same module composition, new flag set possibly; minor edits |
|
||||
| 6 | K8s deployment artifacts | **port-with-light-rewrite** | Update image name, driver name, possibly RBAC for V3-specific service accounts; YAML structure unchanged |
|
||||
| 7 | Test corpus | **mixed** — split per Layer 2 | Most tests follow their module's disposition; QA wire-level tests need rewire |
|
||||
|
||||
### Layer 1 estimated split (rough)
|
||||
|
||||
- **port-as-is**: ~50-60% of LOC (modules 1, 2, 4 + most of 7)
|
||||
- **port-with-light-rewrite**: ~10-15% (modules 5, 6 + a few tests)
|
||||
- **port-with-rewire**: ~25-35% (module 3 + wire-level QA tests in 7)
|
||||
- **rewrite-required**: should be near 0% — would surface in Layer 4 if found
|
||||
|
||||
### Layer 1 cross-checks (sanity)
|
||||
|
||||
| Cross-check | Result |
|
||||
|---|---|
|
||||
| **Architect's discipline** ("port from V2 is heavy reuse, not rewrite") | ✅ consistent — Layer 1 estimates ~75% port-as-is or light-rewrite |
|
||||
| **NVMe support preservation** (user's concern, 2026-04-28) | ✅ Module 2 includes `nvme_util.go`; transport adapter layer is multi-protocol by design |
|
||||
| **CSI v1.5 spec stability across V2/V3** | ✅ k8s CSI spec is independent of any storage backend |
|
||||
| **Existing k8s e2e scenarios reusable** | ✅ 16+ YAML scenarios in testrunner/scenarios/ exercise full CSI flows; most should port-as-is |
|
||||
|
||||
### Layer 1 open questions (deferred to Layer 2-5)
|
||||
|
||||
1. **Volume backend interface** (Module 3): how thin is the V2-wire surface? If it's ≤10 method calls into V2 master, port is mechanical. If it's deeply intertwined with V2 master state shapes, may need redesign of the interface.
|
||||
2. **NodeStageVolume flow**: how is "prefer NVMe over iSCSI" implemented today? Is it config or auto-detect? V3 needs the same flexibility.
|
||||
3. **Snapshot ID semantics**: Module 4 ID encoding may assume V2 snapshot model; V3 snapshot lifecycle may differ when G10/G15b lands.
|
||||
4. **Test corpus split**: of the 9 `_test.go` files, how many touch V2 wire vs are pure protocol/encoding tests? Affects port effort estimate.
|
||||
|
||||
---
|
||||
|
||||
## 2026-05-03 code-read addendum — actual V2 CSI port disposition
|
||||
|
||||
Selected V2 files read:
|
||||
|
||||
| V2 file | Finding | Disposition for V3 |
|
||||
|---|---|---|
|
||||
| `csi/controller.go` | CSI Controller service shape is spec-bound: create/delete/publish/unpublish/capability/expand/snapshot handlers translate CSI requests into a `VolumeBackend` interface. | **M / port selective**. Keep CSI request validation, idempotency, `VolumeContext` / `PublishContext` shape. Do not initially port snapshots/expand into G15a static MVP. |
|
||||
| `csi/node.go` | NodeStage/Publish/Unstage uses `PublishContext` / `VolumeContext`, chooses NVMe if available, otherwise iSCSI, runs OS initiator commands, formats/mounts, persists `.transport`, and is idempotent on already-mounted paths. | **M / port complete for Node path**. This is the first useful CSI MVP surface because it tests real Linux attach/mount/read/write. Rebind imports and keep OS utilities injectable for tests. |
|
||||
| `csi/iscsi_util.go` | Pure OS adapter: `iscsiadm`, device discovery under `/dev/disk/by-path`, mount/mkfs/resize helpers, mock utilities for unit tests. | **M / port complete**. This is directly reusable for Linux node plugin. |
|
||||
| `csi/nvme_util.go` | Pure OS adapter: `nvme connect/disconnect/list-subsys/ns-rescan`, JSON parsing, mock utilities. | **M / port complete but G15a may default iSCSI-first**. NVMe is reusable after frontend/NVMe m01 confidence is high. |
|
||||
| `csi/identity.go` | CSI Identity service constants and readiness. | **M / port complete**. Minimal and safe. |
|
||||
| `csi/server.go` | Wires CSI Identity/Controller/Node services and local V2 `VolumeManager` / master client modes. | **M* / port shell only**. Keep endpoint parsing and service registration; replace local manager/master backend with V3-specific backends. |
|
||||
| `csi/volume_backend.go` | Abstract `VolumeBackend`, local V2 `VolumeManager` backend, and V2 master gRPC client. | **M* + E split**. Keep the interface shape concept; do not port V2 master client. V3 backend must read from cluster-spec/product-loop assignment facts or a future blockmaster volume API. |
|
||||
| `csi/volume_manager.go` | Embeds V2 `BlockVol` and V2 iSCSI `TargetServer`; creates local `.blk` files and exposes them. | **E / do not port** for V3 product mode. V3 blockvolume already owns frontend/export and durable storage. |
|
||||
| `csi/cmd/block-csi/main.go` | CLI entry point for CSI driver. | **M* / rewrite-thin**. Keep flag style and signal handling; wire V3 backend and no local V2 manager. |
|
||||
| `csi/deploy/*.yaml` | Kubernetes CSI controller/node/driver/rbac/storageclass/example PVC. | **M* / port with image/name/flag edits**. Useful as G15a deployment skeleton after binary exists. |
|
||||
|
||||
### Key architecture conclusion
|
||||
|
||||
V2 CSI should not be ported as "create volume + embedded BlockVol + local target" for V3. That path would bypass the P15 product loop we just built.
|
||||
|
||||
For V3 the first CSI gate should be:
|
||||
|
||||
```
|
||||
cluster-spec / existing placement
|
||||
-> blockmaster product loop
|
||||
-> authority assignment
|
||||
-> blockvolume exposes iSCSI/NVMe
|
||||
-> CSI ControllerPublish returns publish_context
|
||||
-> CSI NodeStage attaches OS initiator and mounts
|
||||
-> pod writes filesystem
|
||||
```
|
||||
|
||||
This tests the real V3 control/data boundary without reintroducing V2 storage ownership into the CSI driver.
|
||||
|
||||
### Recommended G15a split
|
||||
|
||||
| Slice | Claim | Code scope | Test scope |
|
||||
|---|---|---|---|
|
||||
| G15a-0 CSI service skeleton | CSI binary starts; Identity works; Controller/Node capability shape correct; no authority minting. | New `cmd/blockcsi` or `cmd/block-csi`; `core/csi` package; Identity; endpoint parsing; mocks. | Unit tests only. |
|
||||
| G15a-1 static/pre-provisioned iSCSI Node path | Given publish_context from an existing V3 blockvolume assignment, CSI NodeStage/Publish can attach, format, mount, bind, unpublish, unstage. | Port V2 `node.go`, `iscsi_util.go`, mount helpers; no CreateVolume. | Mock unit tests + optional privileged M01 test. |
|
||||
| G15a-2 ControllerPublish from blockmaster assignment | CSI ControllerPublish/Validate can look up existing volume target info from V3 blockmaster/status and return `iscsiAddr` + `iqn`. | V3 `VolumeBackend` backed by blockmaster query/status, not V2 master RPC. | L2 subprocess with real blockmaster + blockvolume; no Kubernetes yet. |
|
||||
| G15a-3 Kubernetes smoke | K8s static PV/PVC + CSI node plugin can mount a V3 iSCSI volume and read/write. | Deploy YAMLs; container/image flags; node privileged mounts. | M01 or k8s lab only. |
|
||||
| G15b dynamic provisioning | CSI CreateVolume creates desired volume + placement intent, waits for assignment readiness, then returns volume. | New product API for desired volume creation and placement allocation. | Requires G9/G10 product-loop maturity; not G15a. |
|
||||
| G15c fault-domain validation | Node down/up, network partition, replica repair, pod remount/recover. | Mostly harness + policy, not CSI-only. | Hardware/k8s failure matrix. |
|
||||
|
||||
### Red-test anchors for G15a
|
||||
|
||||
1. `ControllerPublish` must fail closed if blockmaster has no verified assignment for the requested volume.
|
||||
2. `ControllerPublish` must return publish_context from authority/product assignment facts, not from cluster-spec directly.
|
||||
3. `NodeStageVolume` must be idempotent when the staging path is already mounted.
|
||||
4. `NodeStageVolume` must clean up iSCSI/NVMe sessions if format/mount fails.
|
||||
5. `NodeUnstageVolume` must recover transport identity from `.transport` after CSI plugin restart.
|
||||
6. `NodePublishVolume` must bind-mount staging to pod target and be idempotent.
|
||||
7. CSI package must not import `core/authority` or mint assignments.
|
||||
8. Dynamic `CreateVolume` must be explicitly unimplemented in G15a unless a V3 product API is ratified.
|
||||
|
||||
### What this means for "real domain" testing
|
||||
|
||||
CSI is the right next user-facing integration layer, but it should not be asked to prove every recovery property at once.
|
||||
|
||||
- **G15a proves**: Kubernetes/node attach path can consume existing V3 assignment and mount a real block device.
|
||||
- **G15c/G16 prove**: node down/up, network interruption, replica auto-repair, remount behavior, and pod-level data continuity.
|
||||
- **G9/G10 continue to own**: placement, readiness, recovery decisions, and authority minting. CSI consumes those facts; it does not decide them.
|
||||
|
||||
## Layer 2-5 — superseded by 2026-05-03 addendum; original next-step notes retained
|
||||
|
||||
Per `v3-batch-process.md` discipline + architect 2026-04-28 ratification: Layer 1 (this section) is **read-only scoping** allowed without commitment. Layers 2-5 require the dogfood spine ratification before further work, since the "should we port at all + when" question depends on the schedule architect picks.
|
||||
|
||||
If/when ratified, Layer 2-5 plan:
|
||||
- **Layer 2** (sub-modules + call graph within each Layer 1 module): 1 hour
|
||||
- **Layer 3** (interface inventory per sub-module): 1 hour
|
||||
- **Layer 4** (per-interface disposition: port-as-is / port-with-rewire / port-with-light-rewrite / rewrite-required / n/a): 30 min
|
||||
- **Layer 5** (open V2 code — first time — and verify Layer 1-4 against actual implementation): 1-2 hours
|
||||
- **Total** Layer 2-5: ~3-4 hours QA work
|
||||
|
||||
### Methodology guard for Layer 2-5
|
||||
|
||||
Per `feedback_porting_discipline.md`:
|
||||
- No "顺便重构" (incidental refactor) during port
|
||||
- No rewrite based on "this code looks unfamiliar"
|
||||
- Rewrite-required disposition (Layer 4) requires explicit architect sign-off, not QA judgment alone
|
||||
|
||||
---
|
||||
|
||||
## Survey output for sw + architect at G15a kickoff
|
||||
|
||||
When G15a §1.A scope is being bound, this survey provides:
|
||||
|
||||
1. **Module count + dependency graph** (Layer 1 — already in this doc)
|
||||
2. **Volume backend interface surface** (Layer 3 — TBD)
|
||||
3. **Per-interface port disposition** (Layer 4 — TBD)
|
||||
4. **LOC + test count estimate** (Layer 5 — TBD)
|
||||
5. **NVMe + iSCSI dual-transport coverage assertion** (Layer 4)
|
||||
6. **Reusable test scenarios from testrunner/scenarios/** (Layer 4)
|
||||
|
||||
These six artifacts let architect bind G15a scope without sw guessing port effort.
|
||||
Reference in New Issue
Block a user