Skip to content

Commit 6c5810c

Browse files
authored
Merge pull request kubernetes#74542 from gnufied/make-cinder-limits-via-openshift-conf
Allow cinder volume limits to be configurable
2 parents 33a0afa + 7a46b30 commit 6c5810c

File tree

5 files changed

+118
-3
lines changed

5 files changed

+118
-3
lines changed

pkg/cloudprovider/providers/openstack/openstack.go

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,10 @@ type LoadBalancerOpts struct {
110110

111111
// BlockStorageOpts is used to talk to Cinder service
112112
type BlockStorageOpts struct {
113-
BSVersion string `gcfg:"bs-version"` // overrides autodetection. v1 or v2. Defaults to auto
114-
TrustDevicePath bool `gcfg:"trust-device-path"` // See Issue #33128
115-
IgnoreVolumeAZ bool `gcfg:"ignore-volume-az"`
113+
BSVersion string `gcfg:"bs-version"` // overrides autodetection. v1 or v2. Defaults to auto
114+
TrustDevicePath bool `gcfg:"trust-device-path"` // See Issue #33128
115+
IgnoreVolumeAZ bool `gcfg:"ignore-volume-az"`
116+
NodeVolumeAttachLimit int `gcfg:"node-volume-attach-limit"` // override volume attach limit for Cinder. Default is : 256
116117
}
117118

118119
// RouterOpts is used for Neutron routes
@@ -369,6 +370,32 @@ func newOpenStack(cfg Config) (*OpenStack, error) {
369370
return &os, nil
370371
}
371372

373+
// NewFakeOpenStackCloud creates and returns an instance of Openstack cloudprovider.
374+
// Mainly for use in tests that require instantiating Openstack without having
375+
// to go through cloudprovider interface.
376+
func NewFakeOpenStackCloud(cfg Config) (*OpenStack, error) {
377+
provider, err := openstack.NewClient(cfg.Global.AuthURL)
378+
if err != nil {
379+
return nil, err
380+
}
381+
emptyDuration := MyDuration{}
382+
if cfg.Metadata.RequestTimeout == emptyDuration {
383+
cfg.Metadata.RequestTimeout.Duration = time.Duration(defaultTimeOut)
384+
}
385+
provider.HTTPClient.Timeout = cfg.Metadata.RequestTimeout.Duration
386+
387+
os := OpenStack{
388+
provider: provider,
389+
region: cfg.Global.Region,
390+
lbOpts: cfg.LoadBalancer,
391+
bsOpts: cfg.BlockStorage,
392+
routeOpts: cfg.Route,
393+
metadataOpts: cfg.Metadata,
394+
}
395+
396+
return &os, nil
397+
}
398+
372399
// Initialize passes a Kubernetes clientBuilder interface to the cloud provider
373400
func (os *OpenStack) Initialize(clientBuilder cloudprovider.ControllerClientBuilder, stop <-chan struct{}) {
374401
}

pkg/cloudprovider/providers/openstack/openstack_volumes.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -695,6 +695,11 @@ func (os *OpenStack) ShouldTrustDevicePath() bool {
695695
return os.bsOpts.TrustDevicePath
696696
}
697697

698+
// NodeVolumeAttachLimit specifies number of cinder volumes that can be attached to this node.
699+
func (os *OpenStack) NodeVolumeAttachLimit() int {
700+
return os.bsOpts.NodeVolumeAttachLimit
701+
}
702+
698703
// GetLabelsForVolume implements PVLabeler.GetLabelsForVolume
699704
func (os *OpenStack) GetLabelsForVolume(ctx context.Context, pv *v1.PersistentVolume) (map[string]string, error) {
700705
// Ignore if not Cinder.

pkg/volume/cinder/BUILD

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,11 @@ go_test(
4949
],
5050
embed = [":go_default_library"],
5151
deps = [
52+
"//pkg/cloudprovider/providers/openstack:go_default_library",
5253
"//pkg/util/mount:go_default_library",
5354
"//pkg/volume:go_default_library",
5455
"//pkg/volume/testing:go_default_library",
56+
"//pkg/volume/util:go_default_library",
5557
"//staging/src/k8s.io/api/core/v1:go_default_library",
5658
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
5759
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",

pkg/volume/cinder/cinder.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,12 @@ func (plugin *cinderPlugin) GetVolumeLimits() (map[string]int64, error) {
143143
if cloud.ProviderName() != openstack.ProviderName {
144144
return nil, fmt.Errorf("Expected Openstack cloud, found %s", cloud.ProviderName())
145145
}
146+
147+
openstackCloud, ok := cloud.(*openstack.OpenStack)
148+
if ok && openstackCloud.NodeVolumeAttachLimit() > 0 {
149+
volumeLimits[util.CinderVolumeLimitKey] = int64(openstackCloud.NodeVolumeAttachLimit())
150+
}
151+
146152
return volumeLimits, nil
147153
}
148154

pkg/volume/cinder/cinder_test.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,11 @@ import (
2626
"k8s.io/api/core/v1"
2727
"k8s.io/apimachinery/pkg/types"
2828
utiltesting "k8s.io/client-go/util/testing"
29+
"k8s.io/kubernetes/pkg/cloudprovider/providers/openstack"
2930
"k8s.io/kubernetes/pkg/util/mount"
3031
"k8s.io/kubernetes/pkg/volume"
3132
volumetest "k8s.io/kubernetes/pkg/volume/testing"
33+
"k8s.io/kubernetes/pkg/volume/util"
3234
)
3335

3436
func TestCanSupport(t *testing.T) {
@@ -255,3 +257,76 @@ func TestPlugin(t *testing.T) {
255257
t.Errorf("Deleter() failed: %v", err)
256258
}
257259
}
260+
261+
func TestGetVolumeLimit(t *testing.T) {
262+
tmpDir, err := utiltesting.MkTmpdir("cinderTest")
263+
if err != nil {
264+
t.Fatalf("can't make a temp dir: %v", err)
265+
}
266+
267+
cloud, err := getOpenstackCloudProvider()
268+
if err != nil {
269+
t.Fatalf("can not instantiate openstack cloudprovider : %v", err)
270+
}
271+
272+
defer os.RemoveAll(tmpDir)
273+
plugMgr := volume.VolumePluginMgr{}
274+
volumeHost := volumetest.NewFakeVolumeHostWithCloudProvider(tmpDir, nil, nil, cloud)
275+
plugMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, volumeHost)
276+
277+
plug, err := plugMgr.FindPluginByName("kubernetes.io/cinder")
278+
if err != nil {
279+
t.Fatalf("Can't find the plugin by name")
280+
}
281+
attachablePlugin, ok := plug.(volume.VolumePluginWithAttachLimits)
282+
if !ok {
283+
t.Fatalf("plugin %s is not of attachable type", plug.GetPluginName())
284+
}
285+
286+
limits, err := attachablePlugin.GetVolumeLimits()
287+
if err != nil {
288+
t.Errorf("error fetching limits : %v", err)
289+
}
290+
if len(limits) == 0 {
291+
t.Fatalf("expecting limit from openstack got none")
292+
}
293+
limit, _ := limits[util.CinderVolumeLimitKey]
294+
if limit != 10 {
295+
t.Fatalf("expected volume limit to be 10 got %d", limit)
296+
}
297+
}
298+
299+
func getOpenstackCloudProvider() (*openstack.OpenStack, error) {
300+
cfg := getOpenstackConfig()
301+
return openstack.NewFakeOpenStackCloud(cfg)
302+
}
303+
304+
func getOpenstackConfig() openstack.Config {
305+
cfg := openstack.Config{
306+
Global: struct {
307+
AuthURL string `gcfg:"auth-url"`
308+
Username string
309+
UserID string `gcfg:"user-id"`
310+
Password string
311+
TenantID string `gcfg:"tenant-id"`
312+
TenantName string `gcfg:"tenant-name"`
313+
TrustID string `gcfg:"trust-id"`
314+
DomainID string `gcfg:"domain-id"`
315+
DomainName string `gcfg:"domain-name"`
316+
Region string
317+
CAFile string `gcfg:"ca-file"`
318+
}{
319+
Username: "user",
320+
Password: "pass",
321+
TenantID: "foobar",
322+
DomainID: "2a73b8f597c04551a0fdc8e95544be8a",
323+
DomainName: "local",
324+
AuthURL: "http://auth.url",
325+
UserID: "user",
326+
},
327+
BlockStorage: openstack.BlockStorageOpts{
328+
NodeVolumeAttachLimit: 10,
329+
},
330+
}
331+
return cfg
332+
}

0 commit comments

Comments
 (0)