Files
seaweedfs/weed/storage/blockvol/csi/cmd/block-csi/main.go
T
Ping QiuandClaude Opus 4.6 5a9a52f2d0 feat: Phase 6 CP6-2 -- CSI control-plane integration + csi-sanity/k3s validation
CP6-2 wires the CSI driver to SeaweedFS master/volume-server control plane:
- Proto: block volume messages in master.proto/volume_server.proto, codegen
- Master registry: in-memory BlockVolumeRegistry with Pending->Active status,
  full/delta heartbeat, inflight lock, placement (fewest volumes)
- VS gRPC: AllocateBlockVolume/DeleteBlockVolume handlers, shared naming
- Master RPCs: CreateBlockVolume (retry up to 3 servers), Delete, Lookup
- Heartbeat: block volume fields wired into bidirectional stream
- CSI Controller: VolumeBackend interface (Local + Master), returns volume_context
- CSI Node: reads volume_context for remote targets, staged map + IQN derivation
- Mode flag: --mode=controller/node/all, --master for control-plane
- K8s manifests: csi-driver.yaml, csi-controller.yaml, csi-node.yaml

csi-sanity conformance (33 pass, 58 skip) found 6 bugs:
- BUG-SANITY-1/2/3: missing VolumeCapabilities/VolumeCapability validation
- BUG-SANITY-4: NodePublish used mount instead of bind mount
- BUG-SANITY-5: NodeUnpublish didn't remove target path
- BUG-SANITY-6: NodeUnpublish failed on unmounted path

k3s Level 4 (PVC->Pod data persistence) found 1 bug:
- BUG-K3S-1: IsLoggedIn didn't handle iscsiadm exit code 21

226 CSI tests + 54 server tests = 280 new tests, all passing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 11:01:08 -08:00

69 lines
2.0 KiB
Go

// block-csi is the SeaweedFS BlockVol CSI driver.
// It embeds a BlockVol engine and iSCSI target in-process, serving
// CSI Identity, Controller, and Node services on a Unix socket.
package main
import (
"flag"
"fmt"
"log"
"os"
"os/signal"
"syscall"
blockcsi "github.com/seaweedfs/seaweedfs/weed/storage/blockvol/csi"
)
func main() {
endpoint := flag.String("endpoint", "unix:///csi/csi.sock", "CSI endpoint (unix socket)")
dataDir := flag.String("data-dir", "/var/lib/sw-block", "volume data directory")
iscsiAddr := flag.String("iscsi-addr", "127.0.0.1:3260", "local iSCSI target listen address")
iqnPrefix := flag.String("iqn-prefix", "iqn.2024.com.seaweedfs", "IQN prefix for volumes")
nodeID := flag.String("node-id", "", "node identifier (required)")
masterAddr := flag.String("master", "", "master address for control-plane mode (e.g. master:9333)")
mode := flag.String("mode", "all", "driver mode: controller, node, or all")
flag.Parse()
if *nodeID == "" {
fmt.Fprintln(os.Stderr, "error: -node-id is required")
flag.Usage()
os.Exit(1)
}
if *mode == "controller" && *masterAddr == "" {
fmt.Fprintln(os.Stderr, "error: -master is required in controller mode")
flag.Usage()
os.Exit(1)
}
logger := log.New(os.Stdout, "[block-csi] ", log.LstdFlags)
driver, err := blockcsi.NewCSIDriver(blockcsi.DriverConfig{
Endpoint: *endpoint,
DataDir: *dataDir,
ISCSIAddr: *iscsiAddr,
IQNPrefix: *iqnPrefix,
NodeID: *nodeID,
MasterAddr: *masterAddr,
Mode: *mode,
Logger: logger,
})
if err != nil {
log.Fatalf("create CSI driver: %v", err)
}
// Graceful shutdown on signal.
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
go func() {
sig := <-sigCh
logger.Printf("received %v, shutting down...", sig)
driver.Stop()
}()
logger.Printf("starting block-csi driver: node=%s endpoint=%s", *nodeID, *endpoint)
if err := driver.Run(); err != nil {
log.Fatalf("CSI driver: %v", err)
}
logger.Println("block-csi driver stopped")
}