From ea523386c5d44808d88f6df1d7efd60d1a54265d Mon Sep 17 00:00:00 2001 From: Malay Kumar Parida Date: Thu, 7 Mar 2024 18:59:14 +0530 Subject: [PATCH] Create replica-1 sc for external mode if topology details are provided In external mode if replica-1 is enabled & topology details are provided then create a storage class for replica-1. We construct the TopologyConstrainedPools from the topology details provided in the external cluster details secret. Signed-off-by: Malay Kumar Parida --- .../storagecluster/external_resources.go | 4 +++ controllers/storagecluster/storageclasses.go | 36 +++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/controllers/storagecluster/external_resources.go b/controllers/storagecluster/external_resources.go index f8bdddc176..1b78ddbd7a 100644 --- a/controllers/storagecluster/external_resources.go +++ b/controllers/storagecluster/external_resources.go @@ -30,6 +30,7 @@ const ( cephFsStorageClassName = "cephfs" cephRbdStorageClassName = "ceph-rbd" cephRbdRadosNamespaceStorageClassName = "ceph-rbd-rados-namespace" + cephRbdTopologyStorageClassName = "ceph-rbd-topology" cephRgwStorageClassName = "ceph-rgw" externalCephRgwEndpointKey = "endpoint" cephRgwTLSSecretKey = "ceph-rgw-tls-cert" @@ -380,6 +381,9 @@ func (r *StorageClusterReconciler) createExternalStorageClusterResources(instanc scc = newCephBlockPoolStorageClassConfiguration(instance) // update the storageclass name to rados storagesclass name scc.storageClass.Name = fmt.Sprintf("%s-%s", instance.Name, d.Name) + } else if d.Name == cephRbdTopologyStorageClassName { + scc = newNonResilientCephBlockPoolStorageClassConfiguration(instance) + scc.storageClass.Parameters["topologyConstrainedPools"] = getTopologyConstrainedPoolsExternalMode(d.Data) } else if d.Name == cephRgwStorageClassName { rgwEndpoint := d.Data[externalCephRgwEndpointKey] if err := checkEndpointReachable(rgwEndpoint, 5*time.Second); err != nil { diff --git a/controllers/storagecluster/storageclasses.go b/controllers/storagecluster/storageclasses.go index aa2bc06d20..622f06ed07 100644 --- a/controllers/storagecluster/storageclasses.go +++ b/controllers/storagecluster/storageclasses.go @@ -528,3 +528,39 @@ func getTopologyConstrainedPools(initData *ocsv1.StorageCluster) string { } return string(topologyConstrainedPoolsStr) } + +// getTopologyConstrainedPoolsExternalMode constructs the topologyConstrainedPools string for external mode from the data map +func getTopologyConstrainedPoolsExternalMode(data map[string]string) string { + type topologySegment struct { + DomainLabel string `json:"domainLabel"` + DomainValue string `json:"value"` + } + // TopologyConstrainedPool stores the pool name and a list of its associated topology domain values. + type topologyConstrainedPool struct { + PoolName string `json:"poolName"` + DomainSegments []topologySegment `json:"domainSegments"` + } + var topologyConstrainedPools []topologyConstrainedPool + + domainLabel := data["topologyFailureDomainLabel"] + domainValues := strings.Split(data["topologyFailureDomainValues"], ",") + poolNames := strings.Split(data["topologyPools"], ",") + + for i, poolName := range poolNames { + topologyConstrainedPools = append(topologyConstrainedPools, topologyConstrainedPool{ + PoolName: poolName, + DomainSegments: []topologySegment{ + { + DomainLabel: domainLabel, + DomainValue: domainValues[i], + }, + }, + }) + } + // returning as string as parameters are of type map[string]string + topologyConstrainedPoolsStr, err := json.MarshalIndent(topologyConstrainedPools, "", " ") + if err != nil { + return "" + } + return string(topologyConstrainedPoolsStr) +}