Skip to content

Commit

Permalink
Merge pull request #1116 from GowthamShanmugam/RHSTOR-5121
Browse files Browse the repository at this point in the history
Block RDR policy creation for non-DR optimized cluster
  • Loading branch information
openshift-merge-bot[bot] authored Dec 13, 2023
2 parents b8e0554 + 5bb9977 commit 45bebae
Show file tree
Hide file tree
Showing 8 changed files with 211 additions and 18 deletions.
2 changes: 2 additions & 0 deletions locales/en/plugin__odf-console.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,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 ODF version or the ODF operator is missing, install or update to ODF {{ version }} or the latest version to enable DR protection.": "{{ names }} has either an unsupported ODF version or the ODF operator is missing, install or update to ODF {{ 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 pre-configured for a Regional-DR setup. Migrate the cluster's OSD to optimise it for Disaster recovery services. To learn more about OSDs migration best practices and its consequences refer to the documentation.": "The selected cluster(s)[{{clusters}}] is not pre-configured for a Regional-DR setup. Migrate the cluster's OSD to optimise it for Disaster recovery services. To learn more about OSDs migration best practices and its consequences refer to the documentation.",
"Sync schedule": "Sync schedule",
"Replication policy": "Replication policy",
"Information unavailable": "Information unavailable",
Expand Down
142 changes: 141 additions & 1 deletion packages/mco/components/create-dr-policy/create-dr-policy.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ const managedClusters: ACMManagedClusterKind[] = [
name: 'count.storagecluster.odf.openshift.io',
value: '1',
},
{
name: 'droptimized.odf.openshift.io',
value: 'true',
},
],
conditions: [
{
Expand Down Expand Up @@ -95,6 +99,10 @@ const managedClusters: ACMManagedClusterKind[] = [
name: 'count.storagecluster.odf.openshift.io',
value: '1',
},
{
name: 'droptimized.odf.openshift.io',
value: 'true',
},
],
conditions: [
{
Expand Down Expand Up @@ -201,6 +209,10 @@ const managedClusters: ACMManagedClusterKind[] = [
name: 'count.storagecluster.odf.openshift.io',
value: '2',
},
{
name: 'droptimized.odf.openshift.io',
value: 'true',
},
],
conditions: [
{
Expand Down Expand Up @@ -283,6 +295,10 @@ const managedClusters: ACMManagedClusterKind[] = [
name: 'count.storagecluster.odf.openshift.io',
value: '1',
},
{
name: 'droptimized.odf.openshift.io',
value: 'true',
},
],
conditions: [
{
Expand Down Expand Up @@ -334,6 +350,65 @@ const managedClusters: ACMManagedClusterKind[] = [
name: 'count.storagecluster.odf.openshift.io',
value: '1',
},
{
name: 'droptimized.odf.openshift.io',
value: 'true',
},
],
conditions: [
{
type: 'ManagedClusterJoined',
lastTransitionTime: '2023-11-29T04:30:13Z',
message: 'Managed cluster joined',
reason: 'ManagedClusterJoined',
status: 'True',
},
{
lastTransitionTime: '2023-11-29T04:30:13Z',
message: 'Managed cluster is available',
reason: 'ManagedClusterAvailable',
status: 'True',
type: 'ManagedClusterConditionAvailable',
},
],
},
},
{
apiVersion: 'cluster.open-cluster-management.io/v1',
kind: 'ManagedCluster',
metadata: {
name: 'east-5',
},
status: {
clusterClaims: [
{
name: 'region.open-cluster-management.io',
value: 'us-east-5',
},
{
name: 'cephfsid.odf.openshift.io',
value: 'c1ea826f-1dc2-4faa-87b2-f0fc4665b11a',
},
{
name: 'storageclustername.odf.openshift.io',
value: 'ocs-storagecluster/openshift-storage',
},
{
name: 'storagesystemname.odf.openshift.io',
value: 'ocs-storagecluster-storagesystem/openshift-storage',
},
{
name: 'version.odf.openshift.io',
value: '4.14.0-rhodf',
},
{
name: 'count.storagecluster.odf.openshift.io',
value: '1',
},
{
name: 'droptimized.odf.openshift.io',
value: 'false',
},
],
conditions: [
{
Expand Down Expand Up @@ -466,7 +541,7 @@ describe('Test drpolicy list page', () => {
expect(screen.getByText('Sync schedule')).toBeInTheDocument();
expect(screen.getByText('minutes')).toBeInTheDocument();

// Create button should be disabled
// Create button should be enabled
expect(screen.getByTestId('create-button')).toBeEnabled();
await waitFor(() => fireEvent.click(screen.getByTestId('create-button')));
expect(
Expand All @@ -481,16 +556,28 @@ describe('Test drpolicy list page', () => {

test('Partially imported cluster test', async () => {
let nonExist = false;
// Enter policy name
expect(screen.getByText('Policy name')).toBeInTheDocument();
fireEvent.change(screen.getByTestId('policy-name'), {
target: { value: 'policy-1' },
});
try {
// east-2 is partially imported cluster
screen.getByText('east-2');
} catch (error) {
nonExist = true;
}
expect(nonExist).toBe(true);
// Create button should be disabled
expect(screen.getByTestId('create-button')).toBeDisabled();
});

test('Down cluser selection test', async () => {
// Enter policy name
expect(screen.getByText('Policy name')).toBeInTheDocument();
fireEvent.change(screen.getByTestId('policy-name'), {
target: { value: 'policy-1' },
});
// Select west-2 down cluster
await waitFor(() => fireEvent.click(screen.getByTestId('west-2')));
// Error message for down cluster
Expand All @@ -502,14 +589,28 @@ describe('Test drpolicy list page', () => {
'The status for both the managed clusters must be available for creating a DR policy. To restore a cluster to an available state, refer to the instructions in the ACM documentation.'
)
).toBeInTheDocument();
// Create button should be disabled
expect(screen.getByTestId('create-button')).toBeDisabled();
});

test('Multiple ODF cluster selection test', async () => {
// Enter policy name
expect(screen.getByText('Policy name')).toBeInTheDocument();
fireEvent.change(screen.getByTestId('policy-name'), {
target: { value: 'policy-1' },
});
// East-3 multiple ODF cluster
expect(screen.getByTestId('east-3')).toBeDisabled();
// Create button should be disabled
expect(screen.getByTestId('create-button')).toBeDisabled();
});

test('Non ODF cluster selection test', async () => {
// Enter policy name
expect(screen.getByText('Policy name')).toBeInTheDocument();
fireEvent.change(screen.getByTestId('policy-name'), {
target: { value: 'policy-1' },
});
// Select west-3 non ODF cluster
await waitFor(() => fireEvent.click(screen.getByTestId('west-3')));
// Error message for non ODF detection
Expand All @@ -521,18 +622,32 @@ describe('Test drpolicy list page', () => {
'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.'
)
).toBeInTheDocument();
// Create button should be disabled
expect(screen.getByTestId('create-button')).toBeDisabled();
});

test('Select partially deployed ODF cluster test', async () => {
// Enter policy name
expect(screen.getByText('Policy name')).toBeInTheDocument();
fireEvent.change(screen.getByTestId('policy-name'), {
target: { value: 'policy-1' },
});
// Select west-4 ceph cluster creation inprogress
await waitFor(() => fireEvent.click(screen.getByTestId('west-4')));
// Error message for cephFSID not found
expect(
screen.getByText('{{ names }} is not connected to RHCS')
).toBeInTheDocument();
// Create button should be disabled
expect(screen.getByTestId('create-button')).toBeDisabled();
});

test('Select unsupported ODF version cluster test', async () => {
// Enter policy name
expect(screen.getByText('Policy name')).toBeInTheDocument();
fireEvent.change(screen.getByTestId('policy-name'), {
target: { value: 'policy-1' },
});
// Select east-4 unsupported ODF operator version
await waitFor(() => fireEvent.click(screen.getByTestId('east-4')));
// Error message for unsupported ODF version
Expand All @@ -541,5 +656,30 @@ describe('Test drpolicy list page', () => {
'{{ names }} has either an unsupported ODF version or the ODF operator is missing, install or update to ODF {{ version }} or the latest version to enable DR protection.'
)
).toBeInTheDocument();
// Create button should be disabled
expect(screen.getByTestId('create-button')).toBeDisabled();
});

test('Select non-DR optimized cluster test', async () => {
// Enter policy name
expect(screen.getByText('Policy name')).toBeInTheDocument();
fireEvent.change(screen.getByTestId('policy-name'), {
target: { value: 'policy-1' },
});
// Select east-1 DR optimized ODF
await waitFor(() => fireEvent.click(screen.getByTestId('east-1')));
// Select east-5 none DR optimized ODF
await waitFor(() => fireEvent.click(screen.getByTestId('east-5')));
// Error message for not DR optimized
expect(
screen.getByText('Cluster not pre-configured for Regional-DR')
).toBeInTheDocument();
expect(
screen.getByText(
"The selected cluster(s)[{{clusters}}] is not pre-configured for a Regional-DR setup. Migrate the cluster's OSD to optimise it for Disaster recovery services. To learn more about OSDs migration best practices and its consequences refer to the documentation."
)
).toBeInTheDocument();
// Create button should be disabled
expect(screen.getByTestId('create-button')).toBeDisabled();
});
});
12 changes: 9 additions & 3 deletions packages/mco/components/create-dr-policy/create-dr-policy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import {
} from './reducer';
import { SelectClusterList } from './select-cluster-list';
import { DRReplicationType } from './select-replication-type';
import { SelectedCluster } from './selected-cluster-view';
import { SelectedCluster, checkForErrors } from './selected-cluster-view';
import './create-dr-policy.scss';
import '../../style.scss';

Expand Down Expand Up @@ -179,7 +179,8 @@ export const CreateDRPolicy: React.FC<{}> = () => {
const areDRPolicyInputsValid = () =>
!!state.policyName &&
!!state.replicationType &&
state.selectedClusters.length === MAX_ALLOWED_CLUSTERS;
state.selectedClusters.length === MAX_ALLOWED_CLUSTERS &&
!checkForErrors(state.selectedClusters, state.replicationType);

return (
<div>
Expand Down Expand Up @@ -239,7 +240,12 @@ export const CreateDRPolicy: React.FC<{}> = () => {
{!!state.selectedClusters.length && (
<FormGroup fieldId="selected-clusters" label={t('Selected clusters')}>
{state.selectedClusters.map((c, i) => (
<SelectedCluster key={c.name} id={i + 1} cluster={c} />
<SelectedCluster
key={c.name}
id={i + 1}
cluster={c}
replicationType={state.replicationType}
/>
))}
</FormGroup>
)}
Expand Down
2 changes: 2 additions & 0 deletions packages/mco/components/create-dr-policy/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ const getODFInfo = (
clusterClaims,
ClusterClaimTypes.STORAGE_CLUSTER_COUNT
);
const isDROptimized = getValueFromClusterClaim(
clusterClaims,
ClusterClaimTypes.DR_OPTIMIZED
);
return {
odfVersion: odfVersion,
isValidODFVersion: isMinimumSupportedODFVersion(
Expand All @@ -95,6 +99,7 @@ const getODFInfo = (
storageClusterNamespacedName: storageClusterNamespacedName,
storageSystemNamespacedName: storageSystemNamespacedName,
cephFSID: cephFsid,
isDROptimized: isDROptimized === 'true',
},
};
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { SingleSelectDropdown } from '@odf/shared/dropdown';
import { useCustomTranslation } from '@odf/shared/useCustomTranslationHook';
import { RequestSizeInput } from '@odf/shared/utils/RequestSizeInput';
import { SelectOption } from '@patternfly/react-core/next';
import { TFunction } from 'i18next';
import { FormGroup, Alert, AlertVariant } from '@patternfly/react-core';
import {
REPLICATION_TYPE,
Expand Down Expand Up @@ -42,20 +43,25 @@ const getClusterErrorInfo = (
if (!storageClusterInfo?.cephFSID) {
acc.clustersWithUnsuccessfulODF.push(cluster.name);
}
if (!storageClusterInfo?.isDROptimized) {
acc.clustersWithoutDROptimizedODF.push(cluster.name);
}
return acc;
},
{
unavailableClusters: [],
clustersWithUnsupportedODF: [],
clustersWithoutODF: [],
clustersWithUnsuccessfulODF: [],
clustersWithoutDROptimizedODF: [],
}
);

const getErrorMessage = (
selectedClusters: ManagedClusterInfoType[],
requiredODFVersion: string,
t
replicationType: REPLICATION_TYPE,
t: TFunction
): ErrorMessageType => {
const clusterErrorInfo = getClusterErrorInfo(selectedClusters);
if (!!clusterErrorInfo.unavailableClusters.length) {
Expand Down Expand Up @@ -89,6 +95,15 @@ 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 pre-configured for a Regional-DR setup. Migrate the cluster's OSD to optimise it for Disaster recovery services. To learn more about OSDs migration best practices and its consequences refer to the documentation.",
{ clusters: clusterErrorInfo.clustersWithoutDROptimizedODF.join(', ') }
),
isHidden: replicationType !== REPLICATION_TYPE.ASYNC,
};
}
return null;
};
Expand Down Expand Up @@ -130,7 +145,12 @@ export const DRReplicationType: React.FC<DRReplicationTypeProps> = ({
dispatch,
}) => {
const { t } = useCustomTranslation();
const errorMessage = getErrorMessage(selectedClusters, requiredODFVersion, t);
const errorMessage = getErrorMessage(
selectedClusters,
requiredODFVersion,
replicationType,
t
);

React.useEffect(() => {
if (selectedClusters.length === 2) {
Expand Down Expand Up @@ -174,7 +194,7 @@ export const DRReplicationType: React.FC<DRReplicationTypeProps> = ({

return (
<>
{!!errorMessage ? (
{!!errorMessage && !errorMessage.isHidden ? (
<Alert
data-test="odf-not-found-alert"
className="odf-alert mco-create-data-policy__alert"
Expand Down Expand Up @@ -233,9 +253,11 @@ type ClusterErrorType = {
clustersWithUnsupportedODF: string[];
clustersWithoutODF: string[];
clustersWithUnsuccessfulODF: string[];
clustersWithoutDROptimizedODF: string[];
};

type ErrorMessageType = {
message?: string;
description?: string;
isHidden?: boolean;
};
Loading

0 comments on commit 45bebae

Please sign in to comment.