Skip to content

Commit dcd162b

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 dcd162b

File tree

6 files changed

+175
-60
lines changed

6 files changed

+175
-60
lines changed

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,9 @@ The options in `Global` section are used for openstack-cloud-controller-manager
113113
* `password`
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`
116-
Required. Keystone region name.
116+
Required. Keystone region name. The name of region will be set in the `topology.kubernetes.io/region` label of the node.
117+
* `regions`
118+
Optional. Keystone region name, which is used to specify regions for the cloud provider where the instance is running. Can be specified multiple times.The region name may or may not be the same as the region name in the `region` option. They merge together at runtime.
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)