diff --git a/cmd/cinder-csi-plugin/main.go b/cmd/cinder-csi-plugin/main.go
index 5bb50621ca..e177b46413 100644
--- a/cmd/cinder-csi-plugin/main.go
+++ b/cmd/cinder-csi-plugin/main.go
@@ -40,6 +40,7 @@ var (
httpEndpoint string
provideControllerService bool
provideNodeService bool
+ noClient bool
)
func main() {
@@ -75,6 +76,7 @@ func main() {
cmd.PersistentFlags().BoolVar(&provideControllerService, "provide-controller-service", true, "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(&noClient, "node-service-no-os-client", false, "If set to true then the CSI driver node service will not use the OpenStack client (default: false)")
openstack.AddExtraFlags(pflag.CommandLine)
@@ -87,21 +89,32 @@ func handle() {
d := cinder.NewDriver(&cinder.DriverOpts{Endpoint: endpoint, ClusterID: cluster})
openstack.InitOpenStackProvider(cloudConfig, httpEndpoint)
- var err error
- clouds := make(map[string]openstack.IOpenStack)
- for _, cloudName := range cloudNames {
- clouds[cloudName], err = openstack.GetOpenStackProvider(cloudName)
- if err != nil {
- klog.Warningf("Failed to GetOpenStackProvider %s: %v", cloudName, err)
- return
- }
- }
if provideControllerService {
+ var err error
+ clouds := make(map[string]openstack.IOpenStack)
+ for _, cloudName := range cloudNames {
+ clouds[cloudName], err = openstack.GetOpenStackProvider(cloudName, false)
+ if err != nil {
+ klog.Warningf("Failed to GetOpenStackProvider %s: %v", cloudName, err)
+ return
+ }
+ }
+
d.SetupControllerService(clouds)
}
if provideNodeService {
+ var err error
+ clouds := make(map[string]openstack.IOpenStack)
+ for _, cloudName := range cloudNames {
+ clouds[cloudName], err = openstack.GetOpenStackProvider(cloudName, noClient)
+ if err != nil {
+ klog.Warningf("Failed to GetOpenStackProvider %s: %v", cloudName, err)
+ return
+ }
+ }
+
//Initialize mount
mount := mount.GetMountProvider()
diff --git a/docs/cinder-csi-plugin/using-cinder-csi-plugin.md b/docs/cinder-csi-plugin/using-cinder-csi-plugin.md
index 210d26a2c4..3fc6867e3b 100644
--- a/docs/cinder-csi-plugin/using-cinder-csi-plugin.md
+++ b/docs/cinder-csi-plugin/using-cinder-csi-plugin.md
@@ -111,6 +111,13 @@ In addition to the standard set of klog flags, `cinder-csi-plugin` accepts the f
The default is to provide the node service.
+
+
--node-service-no-os-client <disabled>
+
+ If set to true then the CSI driver does not provide the OpenStack client in the node service.
+
+ The default is to provide the OpenStack client in the node service.
+
## Driver Config
diff --git a/pkg/csi/cinder/openstack/noop_openstack.go b/pkg/csi/cinder/openstack/noop_openstack.go
new file mode 100644
index 0000000000..c2f563c0b2
--- /dev/null
+++ b/pkg/csi/cinder/openstack/noop_openstack.go
@@ -0,0 +1,144 @@
+/*
+Copyright 2024 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package openstack
+
+import (
+ "fmt"
+
+ "github.com/gophercloud/gophercloud/v2/openstack/blockstorage/v3/backups"
+ "github.com/gophercloud/gophercloud/v2/openstack/blockstorage/v3/snapshots"
+ "github.com/gophercloud/gophercloud/v2/openstack/blockstorage/v3/volumes"
+ "github.com/gophercloud/gophercloud/v2/openstack/compute/v2/servers"
+ "k8s.io/cloud-provider-openstack/pkg/util/metadata"
+)
+
+type NoopOpenStack struct {
+ bsOpts BlockStorageOpts
+ metadataOpts metadata.Opts
+}
+
+func (os *NoopOpenStack) CreateVolume(name string, size int, vtype, availability string, snapshotID string, sourceVolID string, sourceBackupID string, tags map[string]string) (*volumes.Volume, error) {
+ return nil, fmt.Errorf("CreateVolume is not implemented for ephemeral storage in this configuration")
+}
+
+func (os *NoopOpenStack) ListVolumes(limit int, startingToken string) ([]volumes.Volume, string, error) {
+ return nil, "", nil
+}
+
+func (os *NoopOpenStack) GetVolumesByName(n string) ([]volumes.Volume, error) {
+ return nil, nil
+}
+
+func (os *NoopOpenStack) DeleteVolume(volumeID string) error {
+ return nil
+}
+
+func (os *NoopOpenStack) GetVolume(volumeID string) (*volumes.Volume, error) {
+ return &volumes.Volume{ID: volumeID}, nil
+}
+
+func (os *NoopOpenStack) AttachVolume(instanceID, volumeID string) (string, error) {
+ return volumeID, nil
+}
+
+func (os *NoopOpenStack) WaitDiskAttached(instanceID string, volumeID string) error {
+ return nil
+}
+
+func (os *NoopOpenStack) WaitVolumeTargetStatus(volumeID string, tStatus []string) error {
+ return nil
+}
+
+func (os *NoopOpenStack) DetachVolume(instanceID, volumeID string) error {
+ return nil
+}
+
+func (os *NoopOpenStack) WaitDiskDetached(instanceID string, volumeID string) error {
+ return nil
+}
+
+func (os *NoopOpenStack) GetAttachmentDiskPath(instanceID, volumeID string) (string, error) {
+ return "", nil
+}
+
+func (os *NoopOpenStack) ExpandVolume(volumeID string, status string, newSize int) error {
+ return nil
+}
+
+func (os *NoopOpenStack) GetMaxVolLimit() int64 {
+ if os.bsOpts.NodeVolumeAttachLimit > 0 && os.bsOpts.NodeVolumeAttachLimit <= 256 {
+ return os.bsOpts.NodeVolumeAttachLimit
+ }
+
+ return defaultMaxVolAttachLimit
+}
+
+func (os *NoopOpenStack) GetBlockStorageOpts() BlockStorageOpts {
+ return os.bsOpts
+}
+
+func (os *NoopOpenStack) GetMetadataOpts() metadata.Opts {
+ return os.metadataOpts
+}
+
+func (os *NoopOpenStack) CreateBackup(name, volID, snapshotID, availabilityZone string, tags map[string]string) (*backups.Backup, error) {
+ return &backups.Backup{}, nil
+}
+
+func (os *NoopOpenStack) BackupsAreEnabled() (bool, error) {
+ return false, nil
+}
+
+func (os *NoopOpenStack) DeleteBackup(backupID string) error {
+ return nil
+}
+
+func (os *NoopOpenStack) CreateSnapshot(name, volID string, tags map[string]string) (*snapshots.Snapshot, error) {
+ return &snapshots.Snapshot{}, nil
+}
+
+func (os *NoopOpenStack) DeleteSnapshot(snapID string) error {
+ return nil
+}
+
+func (os *NoopOpenStack) GetSnapshotByID(snapshotID string) (*snapshots.Snapshot, error) {
+ return &snapshots.Snapshot{ID: snapshotID}, nil
+}
+
+func (os *NoopOpenStack) ListSnapshots(filters map[string]string) ([]snapshots.Snapshot, string, error) {
+ return nil, "", nil
+}
+
+func (os *NoopOpenStack) WaitSnapshotReady(snapshotID string) (string, error) {
+ return "", nil
+}
+
+func (os *NoopOpenStack) GetBackupByID(backupID string) (*backups.Backup, error) {
+ return &backups.Backup{ID: backupID}, nil
+}
+
+func (os *NoopOpenStack) ListBackups(filters map[string]string) ([]backups.Backup, error) {
+ return nil, nil
+}
+
+func (os *NoopOpenStack) WaitBackupReady(backupID string, snapshotSize int, backupMaxDurationSecondsPerGB int) (string, error) {
+ return "", nil
+}
+
+func (os *NoopOpenStack) GetInstanceByID(instanceID string) (*servers.Server, error) {
+ return &servers.Server{ID: instanceID}, nil
+}
diff --git a/pkg/csi/cinder/openstack/openstack.go b/pkg/csi/cinder/openstack/openstack.go
index dbf10dd11d..6bcfe43762 100644
--- a/pkg/csi/cinder/openstack/openstack.go
+++ b/pkg/csi/cinder/openstack/openstack.go
@@ -144,10 +144,12 @@ func GetConfigFromFiles(configFilePaths []string) (Config, error) {
const defaultMaxVolAttachLimit int64 = 256
var OsInstances map[string]IOpenStack
+var NoopInstances map[string]IOpenStack
var configFiles = []string{"/etc/cloud.conf"}
func InitOpenStackProvider(cfgFiles []string, httpEndpoint string) {
OsInstances = make(map[string]IOpenStack)
+ NoopInstances = make(map[string]IOpenStack)
metrics.RegisterMetrics("cinder-csi")
if httpEndpoint != "" {
mux := http.NewServeMux()
@@ -166,7 +168,7 @@ func InitOpenStackProvider(cfgFiles []string, httpEndpoint string) {
}
// CreateOpenStackProvider creates Openstack Instance with custom Global config param
-func CreateOpenStackProvider(cloudName string) (IOpenStack, error) {
+func CreateOpenStackProvider(cloudName string, noClient bool) (IOpenStack, error) {
// Get config from file
cfg, err := GetConfigFromFiles(configFiles)
if err != nil {
@@ -179,6 +181,21 @@ func CreateOpenStackProvider(cloudName string) (IOpenStack, error) {
return nil, fmt.Errorf("GetConfigFromFiles cloud name \"%s\" not found in configuration files: %s", cloudName, configFiles)
}
+ // if no search order given, use default
+ if len(cfg.Metadata.SearchOrder) == 0 {
+ cfg.Metadata.SearchOrder = fmt.Sprintf("%s,%s", metadata.ConfigDriveID, metadata.MetadataID)
+ }
+
+ if noClient {
+ // Init OpenStack
+ NoopInstances[cloudName] = &NoopOpenStack{
+ bsOpts: cfg.BlockStorage,
+ metadataOpts: cfg.Metadata,
+ }
+
+ return NoopInstances[cloudName], nil
+ }
+
provider, err := client.NewOpenStackClient(cfg.Global[cloudName], "cinder-csi-plugin", userAgentData...)
if err != nil {
return nil, err
@@ -201,11 +218,6 @@ func CreateOpenStackProvider(cloudName string) (IOpenStack, error) {
return nil, err
}
- // if no search order given, use default
- if len(cfg.Metadata.SearchOrder) == 0 {
- cfg.Metadata.SearchOrder = fmt.Sprintf("%s,%s", metadata.ConfigDriveID, metadata.MetadataID)
- }
-
// Init OpenStack
OsInstances[cloudName] = &OpenStack{
compute: computeclient,
@@ -219,12 +231,25 @@ func CreateOpenStackProvider(cloudName string) (IOpenStack, error) {
}
// GetOpenStackProvider returns Openstack Instance
-func GetOpenStackProvider(cloudName string) (IOpenStack, error) {
+func GetOpenStackProvider(cloudName string, noClient bool) (IOpenStack, error) {
+ if noClient {
+ NoopInstance, NoopInstanceDefined := NoopInstances[cloudName]
+ if NoopInstanceDefined {
+ return NoopInstance, nil
+ }
+ NoopInstance, err := CreateOpenStackProvider(cloudName, noClient)
+ if err != nil {
+ return nil, err
+ }
+
+ return NoopInstance, nil
+ }
+
OsInstance, OsInstanceDefined := OsInstances[cloudName]
if OsInstanceDefined {
return OsInstance, nil
}
- OsInstance, err := CreateOpenStackProvider(cloudName)
+ OsInstance, err := CreateOpenStackProvider(cloudName, noClient)
if err != nil {
return nil, err
}