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 }