diff --git a/locales/en/plugin__odf-console.json b/locales/en/plugin__odf-console.json index 0ce5b7c17..cfbbf23e6 100644 --- a/locales/en/plugin__odf-console.json +++ b/locales/en/plugin__odf-console.json @@ -55,6 +55,8 @@ "We could not retrieve any information about the managed cluster {{names}}. Check the documentation for potential causes and follow the steps mentioned and try again.": "We could not retrieve any information about the managed cluster {{names}}. Check the documentation for potential causes and follow the steps mentioned and try again.", "{{ names }} has either an unsupported Data Foundation version or the Data Foundation operator is missing, install or update to Data Foundation {{ version }} or the latest version to enable DR protection.": "{{ names }} has either an unsupported Data Foundation version or the Data Foundation operator is missing, install or update to Data Foundation {{ version }} or the latest version to enable DR protection.", "{{ names }} is not connected to RHCS": "{{ names }} is not connected to RHCS", + "Cluster not pre-configured for Regional-DR": "Cluster not pre-configured for Regional-DR", + "The selected cluster(s)[{{clusters}}] is not configured for Regional-DR setup. Migrate the OSDs to optimise the cluster for disaster recovery services.": "The selected cluster(s)[{{clusters}}] is not configured for Regional-DR setup. Migrate the OSDs to optimise the cluster for disaster recovery services.", "Sync schedule": "Sync schedule", "Replication policy": "Replication policy", "Information unavailable": "Information unavailable", diff --git a/packages/mco/components/create-dr-policy/create-dr-policy.tsx b/packages/mco/components/create-dr-policy/create-dr-policy.tsx index 67661b83c..803c3deb1 100644 --- a/packages/mco/components/create-dr-policy/create-dr-policy.tsx +++ b/packages/mco/components/create-dr-policy/create-dr-policy.tsx @@ -242,7 +242,7 @@ const CreateDRPolicy: React.FC<{}> = () => { !!state.policyName && !!state.replicationType && state.selectedClusters.length === MAX_ALLOWED_CLUSTERS && - !checkForErrors(state.selectedClusters); + !checkForErrors(state.selectedClusters, state.replicationType); const loaded = mirrorPeerLoaded && policyLoaded; const loadedError = mirrorPeerLoadError || policyLoadedError; @@ -317,7 +317,12 @@ const CreateDRPolicy: React.FC<{}> = () => { label={t('Selected clusters')} > {state.selectedClusters.map((c, i) => ( - + ))} )} diff --git a/packages/mco/components/create-dr-policy/reducer.ts b/packages/mco/components/create-dr-policy/reducer.ts index b43f1c58f..ab2712097 100644 --- a/packages/mco/components/create-dr-policy/reducer.ts +++ b/packages/mco/components/create-dr-policy/reducer.ts @@ -7,6 +7,8 @@ export type StorageClusterInfoType = { storageSystemNamespacedName: string; // Ceph FSID to determine RDR/MDR. cephFSID: string; + // OSDs are migrated for the RDR or not. + isDROptimized: boolean; }; export type ODFConfigInfoType = { diff --git a/packages/mco/components/create-dr-policy/select-cluster-list.tsx b/packages/mco/components/create-dr-policy/select-cluster-list.tsx index e9e13af49..90399d7b1 100644 --- a/packages/mco/components/create-dr-policy/select-cluster-list.tsx +++ b/packages/mco/components/create-dr-policy/select-cluster-list.tsx @@ -93,6 +93,7 @@ const getODFInfo = ( storageClusterNamespace ); const cephFSID = odfInfo?.storageCluster?.cephClusterFSID; + const isDROptimized = odfInfo?.storageCluster?.isDROptimized; return { odfVersion, @@ -105,6 +106,7 @@ const getODFInfo = ( storageClusterNamespacedName, storageSystemNamespacedName, cephFSID, + isDROptimized, }, }; } catch (err) { @@ -119,6 +121,7 @@ const getODFInfo = ( storageClusterNamespacedName: '', storageSystemNamespacedName: '', cephFSID: '', + isDROptimized: false, }, }; } diff --git a/packages/mco/components/create-dr-policy/select-replication-type.tsx b/packages/mco/components/create-dr-policy/select-replication-type.tsx index f9fcce86d..eab7064d6 100644 --- a/packages/mco/components/create-dr-policy/select-replication-type.tsx +++ b/packages/mco/components/create-dr-policy/select-replication-type.tsx @@ -45,7 +45,8 @@ const checkSyncPolicyAlreadyExists = ( }); const getClusterErrorInfo = ( - selectedClusters: ManagedClusterInfoType[] + selectedClusters: ManagedClusterInfoType[], + replicationType: REPLICATION_TYPE ): ClusterErrorType => selectedClusters.reduce( (acc, cluster) => { @@ -62,6 +63,12 @@ const getClusterErrorInfo = ( if (!storageClusterInfo?.cephFSID) { acc.clustersWithUnsuccessfulODF.push(cluster.name); } + if ( + !storageClusterInfo?.isDROptimized && + replicationType === REPLICATION_TYPE.ASYNC + ) { + acc.clustersWithoutDROptimizedODF.push(cluster.name); + } return acc; }, { @@ -69,6 +76,7 @@ const getClusterErrorInfo = ( clustersWithUnsupportedODF: [], clustersWithoutODF: [], clustersWithUnsuccessfulODF: [], + clustersWithoutDROptimizedODF: [], } ); @@ -76,9 +84,13 @@ const getErrorMessage = ( selectedClusters: ManagedClusterInfoType[], requiredODFVersion: string, isSyncPolicyFound: boolean, + replicationType: REPLICATION_TYPE, t: TFunction ): ErrorMessageType => { - const clusterErrorInfo = getClusterErrorInfo(selectedClusters); + const clusterErrorInfo = getClusterErrorInfo( + selectedClusters, + replicationType + ); if (isSyncPolicyFound) { return { message: t('Existing DRPolicy detected'), @@ -117,6 +129,14 @@ const getErrorMessage = ( names: clusterErrorInfo.clustersWithUnsuccessfulODF.join(' & '), }), }; + } else if (!!clusterErrorInfo.clustersWithoutDROptimizedODF.length) { + return { + message: t('Cluster not pre-configured for Regional-DR'), + description: t( + 'The selected cluster(s)[{{clusters}}] is not configured for Regional-DR setup. Migrate the OSDs to optimise the cluster for disaster recovery services.', + { clusters: clusterErrorInfo.clustersWithoutDROptimizedODF.join(', ') } + ), + }; } return null; }; @@ -171,6 +191,7 @@ export const DRReplicationType: React.FC = ({ selectedClusters, requiredODFVersion, isSyncPolicyFound, + replicationType, t ); @@ -276,6 +297,7 @@ type ClusterErrorType = { clustersWithUnsupportedODF: string[]; clustersWithoutODF: string[]; clustersWithUnsuccessfulODF: string[]; + clustersWithoutDROptimizedODF: string[]; }; type ErrorMessageType = { diff --git a/packages/mco/components/create-dr-policy/selected-cluster-view.tsx b/packages/mco/components/create-dr-policy/selected-cluster-view.tsx index 1a70fdfa8..594026db6 100644 --- a/packages/mco/components/create-dr-policy/selected-cluster-view.tsx +++ b/packages/mco/components/create-dr-policy/selected-cluster-view.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +import { REPLICATION_TYPE } from '@odf/mco/constants'; import { parseNamespaceName } from '@odf/mco/utils'; import { RedExclamationCircleIcon } from '@odf/shared/status/icons'; import { useCustomTranslation } from '@odf/shared/useCustomTranslationHook'; @@ -16,32 +17,38 @@ import './create-dr-policy.scss'; type SelectedClusterProps = { id: number; cluster: ManagedClusterInfoType; + replicationType: REPLICATION_TYPE; }; -export const checkForErrors = (clusters: ManagedClusterInfoType[]) => +export const checkForErrors = ( + clusters: ManagedClusterInfoType[], + replicationType: REPLICATION_TYPE +) => clusters.some((cluster) => { const { isManagedClusterAvailable, odfInfo } = cluster; - const { cephFSID, storageSystemNamespacedName } = + const { cephFSID, storageSystemNamespacedName, isDROptimized } = odfInfo.storageClusterInfo; const [storageSystemName] = parseNamespaceName(storageSystemNamespacedName); return ( !isManagedClusterAvailable || !odfInfo?.isValidODFVersion || !storageSystemName || - !cephFSID + !cephFSID || + (replicationType === REPLICATION_TYPE.ASYNC && !isDROptimized) ); }); export const SelectedCluster: React.FC = ({ id, cluster, + replicationType, }) => { const { t } = useCustomTranslation(); const { name, region, odfInfo } = cluster; const [storageSystemName] = parseNamespaceName( odfInfo.storageClusterInfo.storageSystemNamespacedName ); - const anyError = checkForErrors([cluster]); + const anyError = checkForErrors([cluster], replicationType); return (