Skip to content

Commit bfce454

Browse files
committed
feat(occm): support multi region cluster
Currently, it supports only single auth section. Set the regions in config as: [Global] region=REGION1 regions=REGION1 regions=REGION2 regions=REGION3
1 parent bbb82f4 commit bfce454

File tree

6 files changed

+174
-59
lines changed

6 files changed

+174
-59
lines changed

docs/openstack-cloud-controller-manager/using-openstack-cloud-controller-manager.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ The options in `Global` section are used for openstack-cloud-controller-manager
114114
Keystone user password. If you are using [Keystone application credential](https://docs.openstack.org/keystone/latest/user/application_credentials.html), this option is not required.
115115
* `region`
116116
Required. Keystone region name.
117+
* `regions`
118+
Optional. Keystone region name, which is used to specify regions for the cloud provider where the instance is running. Region is default region name. Can be specified multiple times.
117119
* `domain-id`
118120
Keystone user domain ID. If you are using [Keystone application credential](https://docs.openstack.org/keystone/latest/user/application_credentials.html), this option is not required.
119121
* `domain-name`
@@ -317,7 +319,7 @@ Although the openstack-cloud-controller-manager was initially implemented with N
317319
call](https://docs.openstack.org/api-ref/load-balancer/v2/?expanded=create-a-load-balancer-detail#creating-a-fully-populated-load-balancer).
318320
Setting this option to true will create loadbalancers using serial API calls which first create an unpopulated
319321
loadbalancer, then populate its listeners, pools and members. This is a compatibility option at the expense of
320-
increased load on the OpenStack API. Default: false
322+
increased load on the OpenStack API. Default: false
321323
322324
NOTE:
323325

pkg/client/client.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"fmt"
2424
"net/http"
2525
"runtime"
26+
"slices"
2627
"strings"
2728

2829
"github.com/gophercloud/gophercloud/v2"
@@ -53,6 +54,7 @@ type AuthOpts struct {
5354
UserDomainID string `gcfg:"user-domain-id" mapstructure:"user-domain-id" name:"os-userDomainID" value:"optional"`
5455
UserDomainName string `gcfg:"user-domain-name" mapstructure:"user-domain-name" name:"os-userDomainName" value:"optional"`
5556
Region string `name:"os-region"`
57+
Regions []string `name:"os-regions" value:"optional"`
5658
EndpointType gophercloud.Availability `gcfg:"os-endpoint-type" mapstructure:"os-endpoint-type" name:"os-endpointType" value:"optional"`
5759
CAFile string `gcfg:"ca-file" mapstructure:"ca-file" name:"os-certAuthorityPath" value:"optional"`
5860
TLSInsecure string `gcfg:"tls-insecure" mapstructure:"tls-insecure" name:"os-TLSInsecure" value:"optional" matches:"^true|false$"`
@@ -87,6 +89,7 @@ func LogCfg(authOpts AuthOpts) {
8789
klog.V(5).Infof("UserDomainID: %s", authOpts.UserDomainID)
8890
klog.V(5).Infof("UserDomainName: %s", authOpts.UserDomainName)
8991
klog.V(5).Infof("Region: %s", authOpts.Region)
92+
klog.V(5).Infof("Regions: %s", authOpts.Regions)
9093
klog.V(5).Infof("EndpointType: %s", authOpts.EndpointType)
9194
klog.V(5).Infof("CAFile: %s", authOpts.CAFile)
9295
klog.V(5).Infof("CertFile: %s", authOpts.CertFile)
@@ -232,6 +235,20 @@ func ReadClouds(authOpts *AuthOpts) error {
232235
authOpts.ApplicationCredentialName = replaceEmpty(authOpts.ApplicationCredentialName, cloud.AuthInfo.ApplicationCredentialName)
233236
authOpts.ApplicationCredentialSecret = replaceEmpty(authOpts.ApplicationCredentialSecret, cloud.AuthInfo.ApplicationCredentialSecret)
234237

238+
regions := strings.Split(authOpts.Region, ",")
239+
if len(regions) > 1 {
240+
authOpts.Region = regions[0]
241+
}
242+
243+
for _, r := range cloud.Regions {
244+
// Support only single auth section in clouds.yaml
245+
if r.Values.AuthInfo == nil && r.Name != authOpts.Region && !slices.Contains(regions, r.Name) {
246+
regions = append(regions, r.Name)
247+
}
248+
}
249+
250+
authOpts.Regions = regions
251+
235252
return nil
236253
}
237254

pkg/csi/cinder/openstack/openstack.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"fmt"
2121
"net/http"
2222
"os"
23+
"slices"
2324

2425
"github.com/gophercloud/gophercloud/v2"
2526
"github.com/gophercloud/gophercloud/v2/openstack"
@@ -126,7 +127,7 @@ func GetConfigFromFiles(configFilePaths []string) (Config, error) {
126127
}
127128
}
128129

129-
for _, global := range cfg.Global {
130+
for idx, global := range cfg.Global {
130131
// Update the config with data from clouds.yaml if UseClouds is enabled
131132
if global.UseClouds {
132133
if global.CloudsFile != "" {
@@ -138,6 +139,15 @@ func GetConfigFromFiles(configFilePaths []string) (Config, error) {
138139
}
139140
klog.V(5).Infof("Credentials are loaded from %s:", global.CloudsFile)
140141
}
142+
143+
regions := []string{global.Region}
144+
for _, region := range cfg.Global[idx].Regions {
145+
if !slices.Contains(regions, region) {
146+
regions = append(regions, region)
147+
}
148+
}
149+
150+
cfg.Global[idx].Regions = regions
141151
}
142152

143153
return cfg, nil

pkg/csi/cinder/openstack/openstack_test.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ tenant-id=` + fakeTenantID + `
6868
domain-id=` + fakeDomainID + `
6969
ca-file=` + fakeCAfile + `
7070
region=` + fakeRegion + `
71+
regions=` + fakeRegion + `
7172
[Global "cloud2"]
7273
username=` + fakeUserName_cloud2 + `
7374
password=` + fakePassword_cloud2 + `
@@ -76,6 +77,8 @@ tenant-id=` + fakeTenantID_cloud2 + `
7677
domain-id=` + fakeDomainID_cloud2 + `
7778
ca-file=` + fakeCAfile_cloud2 + `
7879
region=` + fakeRegion_cloud2 + `
80+
regions=` + fakeRegion_cloud2 + `
81+
regions=` + fakeRegion_cloud2 + `
7982
[Global "cloud3"]
8083
username=` + fakeUserName_cloud3 + `
8184
password=` + fakePassword_cloud3 + `
@@ -112,6 +115,7 @@ rescan-on-resize=true`
112115
CAFile: fakeCAfile,
113116
TenantID: fakeTenantID,
114117
Region: fakeRegion,
118+
Regions: []string{fakeRegion},
115119
}
116120
expectedOpts.Global["cloud2"] = &client.AuthOpts{
117121
Username: fakeUserName_cloud2,
@@ -121,6 +125,7 @@ rescan-on-resize=true`
121125
CAFile: fakeCAfile_cloud2,
122126
TenantID: fakeTenantID_cloud2,
123127
Region: fakeRegion_cloud2,
128+
Regions: []string{fakeRegion_cloud2},
124129
}
125130
expectedOpts.Global["cloud3"] = &client.AuthOpts{
126131
Username: fakeUserName_cloud3,
@@ -130,6 +135,7 @@ rescan-on-resize=true`
130135
CAFile: fakeCAfile_cloud3,
131136
TenantID: fakeTenantID_cloud3,
132137
Region: fakeRegion_cloud3,
138+
Regions: []string{fakeRegion_cloud3},
133139
}
134140

135141
expectedOpts.BlockStorage.RescanOnResize = true
@@ -224,6 +230,7 @@ rescan-on-resize=true`
224230
CAFile: fakeCAfile,
225231
TenantID: fakeTenantID,
226232
Region: fakeRegion,
233+
Regions: []string{fakeRegion},
227234
EndpointType: gophercloud.AvailabilityPublic,
228235
UseClouds: true,
229236
CloudsFile: wd + "/fixtures/clouds.yaml",
@@ -237,6 +244,7 @@ rescan-on-resize=true`
237244
CAFile: fakeCAfile_cloud2,
238245
TenantID: fakeTenantID_cloud2,
239246
Region: fakeRegion_cloud2,
247+
Regions: []string{fakeRegion_cloud2},
240248
EndpointType: gophercloud.AvailabilityPublic,
241249
UseClouds: true,
242250
CloudsFile: wd + "/fixtures/clouds.yaml",
@@ -250,6 +258,7 @@ rescan-on-resize=true`
250258
CAFile: fakeCAfile_cloud3,
251259
TenantID: fakeTenantID_cloud3,
252260
Region: fakeRegion_cloud3,
261+
Regions: []string{fakeRegion_cloud3},
253262
EndpointType: gophercloud.AvailabilityPublic,
254263
UseClouds: true,
255264
CloudsFile: wd + "/fixtures/clouds.yaml",

0 commit comments

Comments
 (0)