From 3a6610a0eeb7c2176b2391068f2ac6f57c5e5252 Mon Sep 17 00:00:00 2001 From: Niclas Schad Date: Wed, 12 Nov 2025 10:04:53 +0100 Subject: [PATCH 1/3] Add support for legacy storage operations Signed-off-by: Niclas Schad --- cmd/stackit-csi-plugin/main.go | 13 ++++++++++-- pkg/csi/blockstorage/controllerserver.go | 19 +++++++++++++----- pkg/csi/blockstorage/driver.go | 25 ++++++++++++++++-------- pkg/csi/blockstorage/nodeserver.go | 7 ++++++- 4 files changed, 48 insertions(+), 16 deletions(-) diff --git a/cmd/stackit-csi-plugin/main.go b/cmd/stackit-csi-plugin/main.go index d952bd60..3290b7de 100644 --- a/cmd/stackit-csi-plugin/main.go +++ b/cmd/stackit-csi-plugin/main.go @@ -24,6 +24,7 @@ var ( httpEndpoint string provideControllerService bool provideNodeService bool + legacyStorageMode bool ) func main() { @@ -72,6 +73,8 @@ func main() { "If set to true then the CSI driver does provide the controller service (default: true)") cmd.PersistentFlags().BoolVar(&provideNodeService, "provide-node-service", true, "If set to true then the CSI driver does provide the node service (default: true)") + cmd.PersistentFlags().BoolVar(&legacyStorageMode, "legacy-storage-mode", false, + "Configures the CSI to listen to the legacy storage driverName cinder.csi.openstack.org instead") stackit.AddExtraFlags(pflag.CommandLine) @@ -81,11 +84,17 @@ func main() { func handle() { // Initialize cloud - d := blockstorage.NewDriver(&blockstorage.DriverOpts{ + driverOpts := &blockstorage.DriverOpts{ Endpoint: endpoint, ClusterID: cluster, PVCLister: csi.GetPVCLister(), - }) + } + + if legacyStorageMode { + driverOpts.LegacyDriverName = true + } + + d := blockstorage.NewDriver(driverOpts) if provideControllerService { var err error diff --git a/pkg/csi/blockstorage/controllerserver.go b/pkg/csi/blockstorage/controllerserver.go index 8de6237e..0b13c921 100644 --- a/pkg/csi/blockstorage/controllerserver.go +++ b/pkg/csi/blockstorage/controllerserver.go @@ -112,7 +112,11 @@ func (cs *controllerServer) CreateVolume(ctx context.Context, req *csi.CreateVol accessibleTopologyReq := req.GetAccessibilityRequirements() // Check from topology if accessibleTopologyReq != nil { - volAvailability = sharedcsi.GetAZFromTopology(topologyKey, accessibleTopologyReq) + if cs.Driver.legacyDriver { + volAvailability = sharedcsi.GetAZFromTopology(legacyTopologyKey, accessibleTopologyReq) + } else { + volAvailability = sharedcsi.GetAZFromTopology(topologyKey, accessibleTopologyReq) + } } } @@ -131,7 +135,7 @@ func (cs *controllerServer) CreateVolume(ctx context.Context, req *csi.CreateVol return nil, status.Error(codes.Internal, fmt.Sprintf("Volume %s is not in available state", *vols[0].Id)) } klog.V(4).Infof("Volume %s already exists in Availability Zone: %s of size %d GiB", *vols[0].Id, vols[0].AvailabilityZone, *vols[0].Size) - return getCreateVolumeResponse(&vols[0]), nil + return cs.getCreateVolumeResponse(&vols[0]), nil } else if len(vols) > 1 { klog.V(3).Infof("found multiple existing volumes with selected name (%s) during create", volName) return nil, status.Error(codes.Internal, "Multiple volumes reported by Cinder with same name") @@ -274,7 +278,7 @@ func (cs *controllerServer) CreateVolume(ctx context.Context, req *csi.CreateVol klog.V(4).Infof("CreateVolume: Successfully created volume %s in Availability Zone: %s of size %d GiB", *vol.Id, vol.AvailabilityZone, *vol.Size) - return getCreateVolumeResponse(vol), nil + return cs.getCreateVolumeResponse(vol), nil } func setVolumeEncryptionParameters(opts *iaas.CreateVolumePayload, volParams *stackitParameterConfig) error { @@ -961,7 +965,7 @@ func (cs *controllerServer) ControllerExpandVolume(ctx context.Context, req *csi }, nil } -func getCreateVolumeResponse(vol *iaas.Volume) *csi.CreateVolumeResponse { +func (cs *controllerServer) getCreateVolumeResponse(vol *iaas.Volume) *csi.CreateVolumeResponse { var volsrc *csi.VolumeContentSource var volumeSourceType stackit.VolumeSourceTypes volCnx := map[string]string{} @@ -1002,9 +1006,14 @@ func getCreateVolumeResponse(vol *iaas.Volume) *csi.CreateVolumeResponse { } } + topoKey := topologyKey + if cs.Driver.legacyDriver { + topoKey = legacyTopologyKey + } + accessibleTopology := []*csi.Topology{ { - Segments: map[string]string{topologyKey: vol.AvailabilityZone}, + Segments: map[string]string{topoKey: vol.AvailabilityZone}, }, } diff --git a/pkg/csi/blockstorage/driver.go b/pkg/csi/blockstorage/driver.go index 56fd1818..265ead93 100644 --- a/pkg/csi/blockstorage/driver.go +++ b/pkg/csi/blockstorage/driver.go @@ -15,8 +15,10 @@ import ( ) const ( - driverName = "block-storage.csi.stackit.cloud" - topologyKey = "topology." + driverName + "/zone" + driverName = "block-storage.csi.stackit.cloud" + legacyDriverName = "cinder.csi.openstack.org" + topologyKey = "topology." + driverName + "/zone" + legacyTopologyKey = "topology." + legacyDriverName + "/zone" // ResizeRequired parameter, if set to true, will trigger a resize on mount operation ResizeRequired = driverName + "/resizeRequired" @@ -29,10 +31,11 @@ var ( ) type Driver struct { - name string - fqVersion string // Fully qualified version in format {Version}@{CPO version} - endpoint string - clusterID string + name string + fqVersion string // Fully qualified version in format {Version}@{CPO version} + endpoint string + clusterID string + legacyDriver bool ids *identityServer cs *controllerServer @@ -47,8 +50,9 @@ type Driver struct { } type DriverOpts struct { - ClusterID string - Endpoint string + ClusterID string + Endpoint string + LegacyDriverName bool PVCLister corev1.PersistentVolumeClaimLister } @@ -62,6 +66,11 @@ func NewDriver(o *DriverOpts) *Driver { pvcLister: o.PVCLister, } + if o.LegacyDriverName { + d.name = legacyDriverName + d.legacyDriver = true + } + klog.Info("Driver: ", d.name) klog.Info("Driver version: ", d.fqVersion) klog.Info("CSI Spec version: ", specVersion) diff --git a/pkg/csi/blockstorage/nodeserver.go b/pkg/csi/blockstorage/nodeserver.go index 648e5df3..34625f6f 100644 --- a/pkg/csi/blockstorage/nodeserver.go +++ b/pkg/csi/blockstorage/nodeserver.go @@ -322,9 +322,14 @@ func (ns *nodeServer) NodeGetInfo(ctx context.Context, _ *csi.NodeGetInfoRequest return nil, status.Errorf(codes.Internal, "[NodeGetInfo] Unable to retrieve availability zone of node %v", err) } + topoKey := topologyKey + if ns.Driver.legacyDriver { + topoKey = legacyTopologyKey + } + //TODO: support well-known topology key "topology.kubernetes.io/zone" segments := map[string]string{ - topologyKey: zone, + topoKey: zone, } nodeInfo.AccessibleTopology = &csi.Topology{Segments: segments} From 7efefccb41bb288e4b22e35415ecd8b10f29ed3a Mon Sep 17 00:00:00 2001 From: Niclas Schad Date: Tue, 28 Apr 2026 11:01:48 +0200 Subject: [PATCH 2/3] add flag to block volume creation Signed-off-by: Niclas Schad --- cmd/stackit-csi-plugin/main.go | 6 ++++++ pkg/csi/blockstorage/controllerserver.go | 8 ++++++++ pkg/csi/blockstorage/driver.go | 22 ++++++++++++++-------- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/cmd/stackit-csi-plugin/main.go b/cmd/stackit-csi-plugin/main.go index 3290b7de..06933db6 100644 --- a/cmd/stackit-csi-plugin/main.go +++ b/cmd/stackit-csi-plugin/main.go @@ -25,6 +25,7 @@ var ( provideControllerService bool provideNodeService bool legacyStorageMode bool + blockVolumeCreation bool ) func main() { @@ -75,6 +76,7 @@ func main() { "If set to true then the CSI driver does provide the node service (default: true)") cmd.PersistentFlags().BoolVar(&legacyStorageMode, "legacy-storage-mode", false, "Configures the CSI to listen to the legacy storage driverName cinder.csi.openstack.org instead") + cmd.PersistentFlags().BoolVar(&blockVolumeCreation, "block-volume-creation", false, "Block volume creation") stackit.AddExtraFlags(pflag.CommandLine) @@ -94,6 +96,10 @@ func handle() { driverOpts.LegacyDriverName = true } + if blockVolumeCreation { + driverOpts.BlockVolumeCreation = true + } + d := blockstorage.NewDriver(driverOpts) if provideControllerService { diff --git a/pkg/csi/blockstorage/controllerserver.go b/pkg/csi/blockstorage/controllerserver.go index 0b13c921..0e150047 100644 --- a/pkg/csi/blockstorage/controllerserver.go +++ b/pkg/csi/blockstorage/controllerserver.go @@ -77,6 +77,10 @@ func (cs *controllerServer) CreateVolume(ctx context.Context, req *csi.CreateVol cloud := cs.Instance + if cs.Driver.blockVolumeCreation { + return nil, status.Error(codes.FailedPrecondition, "CSI driver is in read/update-only mode") + } + // Volume Name volName := req.GetName() volCapabilities := req.GetVolumeCapabilities() @@ -476,6 +480,10 @@ func (cs *controllerServer) CreateSnapshot(ctx context.Context, req *csi.CreateS cloud := cs.Instance + if cs.Driver.blockVolumeCreation { + return nil, status.Error(codes.FailedPrecondition, "The old driver is update/read-only mode please migrate to the new driver") + } + name := req.Name volumeID := req.GetSourceVolumeId() snapshotType := req.Parameters[stackit.SnapshotType] diff --git a/pkg/csi/blockstorage/driver.go b/pkg/csi/blockstorage/driver.go index 265ead93..73d92bb1 100644 --- a/pkg/csi/blockstorage/driver.go +++ b/pkg/csi/blockstorage/driver.go @@ -31,11 +31,12 @@ var ( ) type Driver struct { - name string - fqVersion string // Fully qualified version in format {Version}@{CPO version} - endpoint string - clusterID string - legacyDriver bool + name string + fqVersion string // Fully qualified version in format {Version}@{CPO version} + endpoint string + clusterID string + legacyDriver bool + blockVolumeCreation bool ids *identityServer cs *controllerServer @@ -50,9 +51,10 @@ type Driver struct { } type DriverOpts struct { - ClusterID string - Endpoint string - LegacyDriverName bool + ClusterID string + Endpoint string + LegacyDriverName bool + BlockVolumeCreation bool PVCLister corev1.PersistentVolumeClaimLister } @@ -71,6 +73,10 @@ func NewDriver(o *DriverOpts) *Driver { d.legacyDriver = true } + if o.BlockVolumeCreation { + d.blockVolumeCreation = true + } + klog.Info("Driver: ", d.name) klog.Info("Driver version: ", d.fqVersion) klog.Info("CSI Spec version: ", specVersion) From e6e8545bf2fb4e9c643bd42c351cb834bbd487a7 Mon Sep 17 00:00:00 2001 From: Niclas Schad Date: Wed, 29 Apr 2026 09:34:16 +0200 Subject: [PATCH 3/3] update error text Signed-off-by: Niclas Schad --- pkg/csi/blockstorage/controllerserver.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/csi/blockstorage/controllerserver.go b/pkg/csi/blockstorage/controllerserver.go index 0e150047..e71cfee2 100644 --- a/pkg/csi/blockstorage/controllerserver.go +++ b/pkg/csi/blockstorage/controllerserver.go @@ -78,7 +78,7 @@ func (cs *controllerServer) CreateVolume(ctx context.Context, req *csi.CreateVol cloud := cs.Instance if cs.Driver.blockVolumeCreation { - return nil, status.Error(codes.FailedPrecondition, "CSI driver is in read/update-only mode") + return nil, status.Errorf(codes.FailedPrecondition, "The %s driver is update/read-only mode please migrate to the new driver", legacyDriverName) } // Volume Name @@ -481,7 +481,7 @@ func (cs *controllerServer) CreateSnapshot(ctx context.Context, req *csi.CreateS cloud := cs.Instance if cs.Driver.blockVolumeCreation { - return nil, status.Error(codes.FailedPrecondition, "The old driver is update/read-only mode please migrate to the new driver") + return nil, status.Errorf(codes.FailedPrecondition, "The %s driver is update/read-only mode please migrate to the new driver", legacyDriverName) } name := req.Name