Skip to content

Commit 868c17d

Browse files
authored
createvolume changes for multiple clusters per zone (#3413)
calculcate volume accessible topology from create volume response
1 parent 1100ada commit 868c17d

File tree

15 files changed

+878
-431
lines changed

15 files changed

+878
-431
lines changed

go.mod

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@ require (
2525
github.com/stretchr/testify v1.10.0
2626
github.com/vmware-tanzu/vm-operator/api v1.8.7-0.20250509154507-b93e51fc90fa
2727
github.com/vmware-tanzu/vm-operator/external/byok v0.0.0-20250509154507-b93e51fc90fa
28-
github.com/vmware/govmomi v0.52.0-alpha.0.0.20250624230355-39c6f0f94465
28+
github.com/vmware/govmomi v0.52.0-alpha.0.0.20250702012001-bedcaadc5399
2929
go.uber.org/zap v1.27.0
30-
golang.org/x/crypto v0.36.0
31-
golang.org/x/sync v0.14.0
32-
golang.org/x/sys v0.31.0
30+
golang.org/x/crypto v0.38.0
31+
golang.org/x/sync v0.15.0
32+
golang.org/x/sys v0.33.0
3333
google.golang.org/grpc v1.68.1
3434
google.golang.org/protobuf v1.36.5
3535
gopkg.in/gcfg.v1 v1.2.3
@@ -160,12 +160,12 @@ require (
160160
go.opentelemetry.io/proto/otlp v1.4.0 // indirect
161161
go.uber.org/atomic v1.9.0 // indirect
162162
go.uber.org/multierr v1.11.0 // indirect
163-
golang.org/x/net v0.38.0 // indirect
163+
golang.org/x/net v0.40.0 // indirect
164164
golang.org/x/oauth2 v0.27.0 // indirect
165-
golang.org/x/term v0.30.0 // indirect
166-
golang.org/x/text v0.25.0 // indirect
165+
golang.org/x/term v0.32.0 // indirect
166+
golang.org/x/text v0.26.0 // indirect
167167
golang.org/x/time v0.9.0 // indirect
168-
golang.org/x/tools v0.26.0 // indirect
168+
golang.org/x/tools v0.33.0 // indirect
169169
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
170170
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect
171171
google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 // indirect

go.sum

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -293,8 +293,8 @@ github.com/vmware-tanzu/vm-operator/api v1.8.7-0.20250509154507-b93e51fc90fa h1:
293293
github.com/vmware-tanzu/vm-operator/api v1.8.7-0.20250509154507-b93e51fc90fa/go.mod h1:V0JbH4beGCU+q7yqnWUYYOuDij0ut5i1iBO4cyzg+tM=
294294
github.com/vmware-tanzu/vm-operator/external/byok v0.0.0-20250509154507-b93e51fc90fa h1:4MKu14YJ7J54O6QKmT4ds5EUpysWLLtQRMff73cVkmU=
295295
github.com/vmware-tanzu/vm-operator/external/byok v0.0.0-20250509154507-b93e51fc90fa/go.mod h1:8tiuyYslzjLIUmOlXZuGKQdQP2ZgWGCVhVeyptmZYnk=
296-
github.com/vmware/govmomi v0.52.0-alpha.0.0.20250624230355-39c6f0f94465 h1:BV3/IrRGRMmGWra0T4bK6xpWePsCiwLPOWns7SFREFI=
297-
github.com/vmware/govmomi v0.52.0-alpha.0.0.20250624230355-39c6f0f94465/go.mod h1:3ywivawGRfMP2SDCeyKqxTl2xNIHTXF0ilvp72dot5A=
296+
github.com/vmware/govmomi v0.52.0-alpha.0.0.20250702012001-bedcaadc5399 h1:WhIEqQdAYyAoit0wR2UOhQN682F2pyeWQWYOdFXWGZc=
297+
github.com/vmware/govmomi v0.52.0-alpha.0.0.20250702012001-bedcaadc5399/go.mod h1:ZJ5Zd2wDGRzsTRBqA1jpqtbyoe8mRok1rWiPsrL8c7k=
298298
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
299299
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
300300
github.com/xiang90/probing v0.0.0-20221125231312-a49e3df8f510 h1:S2dVYn90KE98chqDkyE9Z4N61UnQd+KOfgp5Iu53llk=
@@ -357,8 +357,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
357357
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
358358
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
359359
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
360-
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
361-
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
360+
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
361+
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
362362
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
363363
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
364364
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
@@ -372,16 +372,16 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
372372
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
373373
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
374374
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
375-
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
376-
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
375+
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
376+
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
377377
golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M=
378378
golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
379379
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
380380
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
381381
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
382382
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
383-
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
384-
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
383+
golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
384+
golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
385385
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
386386
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
387387
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -392,19 +392,19 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
392392
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
393393
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
394394
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
395-
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
396-
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
395+
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
396+
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
397397
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
398398
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
399399
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
400-
golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=
401-
golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
400+
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
401+
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
402402
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
403403
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
404404
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
405405
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
406-
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
407-
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
406+
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
407+
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
408408
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
409409
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
410410
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -413,8 +413,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
413413
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
414414
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
415415
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
416-
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
417-
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
416+
golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
417+
golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
418418
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
419419
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
420420
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

pkg/common/cns-lib/volume/manager.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ type Manager interface {
158158
type CnsVolumeInfo struct {
159159
DatastoreURL string
160160
VolumeID cnstypes.CnsVolumeId
161+
Clusters []vim25types.ManagedObjectReference
161162
}
162163

163164
type CnsSnapshotInfo struct {
@@ -171,10 +172,11 @@ type CnsSnapshotInfo struct {
171172
// CreateVolumeExtraParams consist of values required by the CreateVolume interface and
172173
// are not present in the CNS CreateVolume spec.
173174
type CreateVolumeExtraParams struct {
174-
VolSizeBytes int64
175-
StorageClassName string
176-
Namespace string
177-
IsPodVMOnStretchSupervisorFSSEnabled bool
175+
VolSizeBytes int64
176+
StorageClassName string
177+
Namespace string
178+
IsPodVMOnStretchSupervisorFSSEnabled bool
179+
IsMultipleClustersPerVsphereZoneEnabled bool
178180
}
179181

180182
// CreateSnapshotExtraParams consist of values required by the CreateSnapshot interface and

pkg/common/cns-lib/volume/util.go

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -304,27 +304,32 @@ func getCnsVolumeInfoFromTaskResult(ctx context.Context, virtualCenter *cnsvsphe
304304
volumeID cnstypes.CnsVolumeId, taskResult cnstypes.BaseCnsVolumeOperationResult) (*CnsVolumeInfo, string, error) {
305305
log := logger.GetLogger(ctx)
306306
var datastoreURL string
307+
var placementClusters []types.ManagedObjectReference
307308
volumeCreateResult := interface{}(taskResult).(*cnstypes.CnsVolumeCreateResult)
308309
log.Debugf("volumeCreateResult.PlacementResults :%v", volumeCreateResult.PlacementResults)
309310
if volumeCreateResult.PlacementResults != nil {
310-
var datastoreMoRef types.ManagedObjectReference
311+
var datastoreMoRef *types.ManagedObjectReference
311312
for _, placementResult := range volumeCreateResult.PlacementResults {
312313
// For the datastore which the volume is provisioned, placementFaults
313314
// will not be set.
314315
if len(placementResult.PlacementFaults) == 0 {
315-
datastoreMoRef = placementResult.Datastore
316+
if len(placementResult.Clusters) != 0 {
317+
placementClusters = placementResult.Clusters
318+
} else {
319+
datastoreMoRef = &placementResult.Datastore
320+
var dsMo mo.Datastore
321+
pc := property.DefaultCollector(virtualCenter.Client.Client)
322+
err := pc.RetrieveOne(ctx, *datastoreMoRef, []string{"summary"}, &dsMo)
323+
faultType := ""
324+
if err != nil {
325+
faultType = ExtractFaultTypeFromErr(ctx, err)
326+
return nil, faultType, logger.LogNewErrorf(log, "failed to retrieve datastore summary property: %v", err)
327+
}
328+
datastoreURL = dsMo.Summary.Url
329+
}
316330
break
317331
}
318332
}
319-
var dsMo mo.Datastore
320-
pc := property.DefaultCollector(virtualCenter.Client.Client)
321-
err := pc.RetrieveOne(ctx, datastoreMoRef, []string{"summary"}, &dsMo)
322-
faultType := ""
323-
if err != nil {
324-
faultType = ExtractFaultTypeFromErr(ctx, err)
325-
return nil, faultType, logger.LogNewErrorf(log, "failed to retrieve datastore summary property: %v", err)
326-
}
327-
datastoreURL = dsMo.Summary.Url
328333
}
329334
log.Infof("Volume created successfully. VolumeName: %q, volumeID: %q",
330335
volumeName, volumeID.Id)
@@ -333,6 +338,7 @@ func getCnsVolumeInfoFromTaskResult(ctx context.Context, virtualCenter *cnsvsphe
333338
return &CnsVolumeInfo{
334339
DatastoreURL: datastoreURL,
335340
VolumeID: volumeID,
341+
Clusters: placementClusters,
336342
}, "", nil
337343
}
338344

pkg/common/unittestcommon/utils.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,16 @@ func (cntrlTopology *mockControllerVolumeTopology) GetAZClustersMap(ctx context.
174174
return nil
175175
}
176176

177+
// GetZonesForNamespace fetches the zones associated with a namespace when
178+
// WorkloadDomainIsolation is supported in supervisor.
179+
func (cntrlTopology *mockControllerVolumeTopology) GetZonesForNamespace(ns string) map[string]struct{} {
180+
return nil
181+
}
182+
183+
func (cntrlTopology *mockControllerVolumeTopology) ZonesWithMultipleClustersExist(ctx context.Context) bool {
184+
return false
185+
}
186+
177187
// GetTopologyInfoFromNodes retrieves the topology information of the given list of node names.
178188
func (cntrlTopology *mockControllerVolumeTopology) GetTopologyInfoFromNodes(ctx context.Context,
179189
reqParams interface{}) ([]map[string]string, error) {
@@ -408,6 +418,11 @@ func (c *FakeK8SOrchestrator) UpdatePersistentVolumeLabel(ctx context.Context, p
408418
return nil
409419
}
410420

421+
func (c *FakeK8SOrchestrator) GetActiveClustersForNamespaceInRequestedZones(ctx context.Context,
422+
targetNS string, requestedZones []string) ([]string, error) {
423+
return nil, nil
424+
}
425+
411426
// configFromVCSim starts a vcsim instance and returns config for use against the
412427
// vcsim instance. The vcsim instance is configured with an empty tls.Config.
413428
func configFromVCSim(vcsimParams VcsimParams, isTopologyEnv bool) (*config.Config, func()) {

pkg/csi/service/common/commonco/coagnostic.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ type COCommonInterface interface {
117117
IsLinkedCloneRequest(ctx context.Context, pvcName string, pvcNamespace string) (bool, error)
118118
// UpdatePersistentVolumeLabel Updates the PV label with the specified key value.
119119
UpdatePersistentVolumeLabel(ctx context.Context, pvName string, key string, value string) error
120+
GetActiveClustersForNamespaceInRequestedZones(ctx context.Context, ns string, zones []string) ([]string, error)
120121
}
121122

122123
// GetContainerOrchestratorInterface returns orchestrator object for a given

pkg/csi/service/common/commonco/k8sorchestrator/topology.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"fmt"
2424
"os"
2525
"reflect"
26+
"slices"
2627
"strconv"
2728
"strings"
2829
"sync"
@@ -504,6 +505,21 @@ func (volTopology *controllerVolumeTopology) GetAZClustersMap(ctx context.Contex
504505
return nil
505506
}
506507

508+
// ZonesWithMultipleClustersExist returns true if zone has more than 1 cluster
509+
func (volTopology *wcpControllerVolumeTopology) ZonesWithMultipleClustersExist(ctx context.Context) bool {
510+
for _, clusters := range volTopology.GetAZClustersMap(ctx) {
511+
if len(clusters) > 1 {
512+
return true
513+
}
514+
}
515+
return false
516+
}
517+
518+
// ZonesWithMultipleClustersExist returns true if zone has more than 1 cluster
519+
func (volTopology *controllerVolumeTopology) ZonesWithMultipleClustersExist(ctx context.Context) bool {
520+
return false
521+
}
522+
507523
// startTopologyCRInformer creates and starts an informer for CSINodeTopology custom resource.
508524
func startTopologyCRInformer(ctx context.Context, cfg *restclient.Config) (*cache.SharedIndexInformer, error) {
509525
log := logger.GetLogger(ctx)
@@ -1820,3 +1836,43 @@ func (c *K8sOrchestrator) GetZonesForNamespace(targetNS string) map[string]struc
18201836
}
18211837
return zonesMap
18221838
}
1839+
1840+
// GetActiveClustersForNamespaceInRequestedZones fetches the active clusters from the zones associated with a namespace
1841+
// for requested zone
1842+
func (c *K8sOrchestrator) GetActiveClustersForNamespaceInRequestedZones(ctx context.Context,
1843+
targetNS string, requestedZones []string) ([]string, error) {
1844+
log := logger.GetLogger(ctx)
1845+
var activeClusters []string
1846+
// Get zones instances from the informer store.
1847+
zones := zoneInformer.GetStore()
1848+
for _, zoneObj := range zones.List() {
1849+
// Only consider zones in targetNS.
1850+
zoneObjUnstructured := zoneObj.(*unstructured.Unstructured)
1851+
// Only get active clusters from zones without a deletion timestamp.
1852+
if zoneObjUnstructured.GetDeletionTimestamp() == nil {
1853+
log.Debugf("skipping zone:%q as it is being deleted", zoneObjUnstructured.GetName())
1854+
continue
1855+
}
1856+
// check if zone belong to namespace specified with targetNS and belong to
1857+
// volume requirement specified with requestedZones
1858+
if zoneObjUnstructured.GetNamespace() != targetNS && !slices.Contains(requestedZones, zoneObjUnstructured.GetName()) {
1859+
log.Debugf("skipping zone: %q as it does not match requested targetNS: %q and requestedZones: %v requirement",
1860+
zoneObjUnstructured.GetName(), targetNS, requestedZones)
1861+
continue
1862+
}
1863+
// capture active cluster on the namespace from zone CR instance
1864+
clusters, found, err := unstructured.NestedStringSlice(zoneObjUnstructured.Object,
1865+
"spec", "namespace", "clusterMoIDs")
1866+
if err != nil {
1867+
return nil, logger.LogNewErrorf(log, "failed to get clusterMoIDs from zone instance :%q. err :%v",
1868+
zoneObj.(*unstructured.Unstructured).GetName(), err)
1869+
}
1870+
if !found {
1871+
return nil, logger.LogNewErrorf(log, "clusterMoIDs not found in zone instance :%q",
1872+
zoneObj.(*unstructured.Unstructured).GetName())
1873+
}
1874+
activeClusters = append(activeClusters, clusters...)
1875+
}
1876+
log.Infof("active clusters: %v for namespace: %q in requested zones: %v", activeClusters, targetNS, requestedZones)
1877+
return activeClusters, nil
1878+
}

pkg/csi/service/common/commonco/types/types.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ type ControllerTopologyService interface {
109109

110110
// GetAZClustersMap returns the zone to clusterMorefs map from the azClustersMap.
111111
GetAZClustersMap(ctx context.Context) map[string][]string
112+
113+
// ZonesWithMultipleClustersExist returns true if zone has more than 1 cluster
114+
ZonesWithMultipleClustersExist(ctx context.Context) bool
112115
}
113116

114117
// NodeTopologyService is an interface which exposes functionality related to

pkg/csi/service/common/constants.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,9 @@ const (
445445
// WorkloadDomainIsolationFSS is FSS for Workload Domain isolation feature
446446
// Used in PVCSI
447447
WorkloadDomainIsolationFSS = "workload-domain-isolation"
448+
// MultipleClustersPerVsphereZone hold WCP capability name which determines if
449+
// multiple vsphere cluster per zone feature is available on a supervisor cluster.
450+
MultipleClustersPerVsphereZone = "supports_multiple_clusters_per_zone"
448451
// VPCCapabilitySupervisor is a supervisor capability indicating if VPC FSS is enabled
449452
VPCCapabilitySupervisor = "VPC_Supported"
450453
// WCP_VMService_BYOK_FSS enables Bring Your Own Key (BYOK) capabilities.

0 commit comments

Comments
 (0)