From 5ce6b10b7f6befe3983024ac90e763018956168b Mon Sep 17 00:00:00 2001 From: k8s-infra-cherrypick-robot <90416843+k8s-infra-cherrypick-robot@users.noreply.github.com> Date: Wed, 18 Sep 2024 23:10:44 -0700 Subject: [PATCH] allow node service to run without openstack client (#2671) Co-authored-by: kayrus --- cmd/cinder-csi-plugin/main.go | 19 ++- .../using-cinder-csi-plugin.md | 7 + pkg/csi/cinder/openstack/noop_openstack.go | 144 ++++++++++++++++++ pkg/csi/cinder/openstack/openstack.go | 40 ++++- 4 files changed, 197 insertions(+), 13 deletions(-) create mode 100644 pkg/csi/cinder/openstack/noop_openstack.go diff --git a/cmd/cinder-csi-plugin/main.go b/cmd/cinder-csi-plugin/main.go index 1673bda4e1..b07b7433fe 100644 --- a/cmd/cinder-csi-plugin/main.go +++ b/cmd/cinder-csi-plugin/main.go @@ -38,6 +38,7 @@ var ( httpEndpoint string provideControllerService bool provideNodeService bool + noClient bool ) func main() { @@ -70,6 +71,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) @@ -82,17 +84,24 @@ func handle() { d := cinder.NewDriver(&cinder.DriverOpts{Endpoint: endpoint, ClusterID: cluster}) openstack.InitOpenStackProvider(cloudConfig, httpEndpoint) - cloud, err := openstack.GetOpenStackProvider() - if err != nil { - klog.Warningf("Failed to GetOpenStackProvider: %v", err) - return - } if provideControllerService { + cloud, err := openstack.GetOpenStackProvider(false) + if err != nil { + klog.Warningf("Failed to GetOpenStackProvider: %v", err) + return + } + d.SetupControllerService(cloud) } if provideNodeService { + cloud, err := openstack.GetOpenStackProvider(noClient) + if err != nil { + klog.Warningf("Failed to GetOpenStackProvider: %v", 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 c3a3656ffd..b2aac7ca46 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..4cd5c231d6 --- /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/openstack/blockstorage/extensions/backups" + "github.com/gophercloud/gophercloud/openstack/blockstorage/v3/snapshots" + "github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes" + "github.com/gophercloud/gophercloud/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, 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) 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 e3a76a167f..fd8f3f8914 100644 --- a/pkg/csi/cinder/openstack/openstack.go +++ b/pkg/csi/cinder/openstack/openstack.go @@ -132,6 +132,7 @@ func GetConfigFromFiles(configFilePaths []string) (Config, error) { const defaultMaxVolAttachLimit int64 = 256 var OsInstance IOpenStack +var NoopInstance IOpenStack var configFiles = []string{"/etc/cloud.conf"} func InitOpenStackProvider(cfgFiles []string, httpEndpoint string) { @@ -153,7 +154,7 @@ func InitOpenStackProvider(cfgFiles []string, httpEndpoint string) { } // CreateOpenStackProvider creates Openstack Instance -func CreateOpenStackProvider() (IOpenStack, error) { +func CreateOpenStackProvider(noClient bool) (IOpenStack, error) { // Get config from file cfg, err := GetConfigFromFiles(configFiles) if err != nil { @@ -162,6 +163,21 @@ func CreateOpenStackProvider() (IOpenStack, error) { } logcfg(cfg) + // 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 + NoopInstance = &NoopOpenStack{ + bsOpts: cfg.BlockStorage, + metadataOpts: cfg.Metadata, + } + + return NoopInstance, nil + } + provider, err := client.NewOpenStackClient(&cfg.Global, "cinder-csi-plugin", userAgentData...) if err != nil { return nil, err @@ -184,11 +200,6 @@ func CreateOpenStackProvider() (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 OsInstance = &OpenStack{ compute: computeclient, @@ -202,12 +213,25 @@ func CreateOpenStackProvider() (IOpenStack, error) { } // GetOpenStackProvider returns Openstack Instance -func GetOpenStackProvider() (IOpenStack, error) { +func GetOpenStackProvider(noClient bool) (IOpenStack, error) { + if noClient { + if NoopInstance != nil { + return NoopInstance, nil + } + var err error + NoopInstance, err = CreateOpenStackProvider(noClient) + if err != nil { + return nil, err + } + + return NoopInstance, nil + } + if OsInstance != nil { return OsInstance, nil } var err error - OsInstance, err = CreateOpenStackProvider() + OsInstance, err = CreateOpenStackProvider(noClient) if err != nil { return nil, err }