Skip to content

Commit

Permalink
Provide osd migration status alert for dr brownfield
Browse files Browse the repository at this point in the history
Signed-off-by: Timothy Asir Jeyasingh <[email protected]>
  • Loading branch information
TimothyAsirJeyasing committed Nov 28, 2023
1 parent 5646fc8 commit 64f24be
Show file tree
Hide file tree
Showing 15 changed files with 356 additions and 53 deletions.
8 changes: 7 additions & 1 deletion locales/en/plugin__odf-console.json
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,6 @@
"Review and assign": "Review and assign",
"In use: {{targetClusters}}": "In use: {{targetClusters}}",
"Used: {{targetClusters}}": "Used: {{targetClusters}}",
"View documentation": "View documentation",
"StorageSystems": "StorageSystems",
"StorageSystem details": "StorageSystem details",
"Edit BlockPool": "Edit BlockPool",
Expand Down Expand Up @@ -455,6 +454,12 @@
"This card shows the requested capacity for different Kubernetes resources. The figures shown represent the usable storage, meaning that data replication is not taken into consideration.": "This card shows the requested capacity for different Kubernetes resources. The figures shown represent the usable storage, meaning that data replication is not taken into consideration.",
"Internal": "Internal",
"Raw capacity is the absolute total disk space available to the array subsystem.": "Raw capacity is the absolute total disk space available to the array subsystem.",
"Cluster ready for Regional-DR setup.": "Cluster ready for Regional-DR setup.",
"Setting up disaster recovery": "Setting up disaster recovery",
"Cluster OSDs are being migrated": "Cluster OSDs are being migrated",
"{{ percentageComplete }}% completed ({{ migratedDevices }}/{{ totalOsd }} remaining)": "{{ percentageComplete }}% completed ({{ migratedDevices }}/{{ totalOsd }} remaining)",
"Could not migrate cluster OSDs.": "Could not migrate cluster OSDs.",
"Check documentation": "Check documentation",
"Troubleshoot": "Troubleshoot",
"Active health checks": "Active health checks",
"Progressing": "Progressing",
Expand Down Expand Up @@ -1145,6 +1150,7 @@
"No conditions found": "No conditions found",
"Copied": "Copied",
"Copy to clipboard": "Copy to clipboard",
"View documentation": "View documentation",
"Oh no! Something went wrong.": "Oh no! Something went wrong.",
"Copied to clipboard": "Copied to clipboard",
"Drag to reorder": "Drag to reorder",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import * as React from 'react';
import { DOC_LINKS } from '@odf/mco/constants/doc';
import { ViewDocumentation } from '@odf/shared/utils/doc-utils';
import { TFunction } from 'i18next';
import { Trans } from 'react-i18next';
import { AlertVariant } from '@patternfly/react-core';
import { ViewDocumentation, DOC_LINKS } from '../../../utils';

export enum ErrorMessageType {
// Priority wise error messages
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import * as React from 'react';
import { ViewDocumentation } from '@odf/shared/utils/doc-utils';
import { TFunction } from 'i18next';
import { Trans } from 'react-i18next';
import { AlertVariant } from '@patternfly/react-core';
import { ViewDocumentation, DOC_LINKS } from '../../../../utils/doc-utils';
import { DOC_LINKS } from '../../../../constants/doc';

export enum ErrorMessageType {
// Priority wise error messages
Expand Down
13 changes: 13 additions & 0 deletions packages/mco/constants/doc.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { ODF_DOC_BASE_PATH, ODF_DOC_VERSION } from '@odf/shared/constants/doc';

export const ACM_DOC_VERSION = '2.9';
export const ACM_DOC_HOME = `https://access.redhat.com/documentation/en-us/red_hat_advanced_cluster_management_for_kubernetes/${ACM_DOC_VERSION}`;
export const ACM_DOC_BASE_PATH = `${ACM_DOC_HOME}/html-single`;

export const DOC_LINKS = {
APPLY_POLICY: `${ODF_DOC_BASE_PATH}/configuring_openshift_data_foundation_disaster_recovery_for_openshift_workloads/index#apply-drpolicy-to-sample-application_manage-dr`,
MDR_FAILOVER: `${ODF_DOC_BASE_PATH}/configuring_openshift_data_foundation_disaster_recovery_for_openshift_workloads/index#application-failover-between-managed-clusters_manage-dr`,
MDR_RELOCATE: `${ODF_DOC_BASE_PATH}/configuring_openshift_data_foundation_disaster_recovery_for_openshift_workloads/index#relocating-application-between-managed-clusters_manage-dr`,
DR_RELEASE_NOTES: `${ODF_DOC_BASE_PATH}/${ODF_DOC_VERSION}_release_notes/index#disaster_recovery`,
ACM_OFFLINE_CLUSTER: `${ACM_DOC_BASE_PATH}/troubleshooting/index#troubleshooting-an-offline-cluster`,
};
48 changes: 0 additions & 48 deletions packages/mco/utils/doc-utils.tsx

This file was deleted.

1 change: 0 additions & 1 deletion packages/mco/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
export * from './disaster-recovery';
export * from './common';
export * from './doc-utils';
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import React from 'react';
import { BLUESTORE, BLUESTORE_RDR } from '@odf/core/constants';
import { cleanup, render, screen, waitFor } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect';
import { MemoryRouter } from 'react-router-dom';
import { getOSDMigrationStatus } from '../../../../utils/osd-migration';
import { OSDMigration } from './osd-migration-status';

jest.mock('@odf/shared/status/icons', () => ({
RedExclamationCircleIcon: 'div',
}));

jest.mock('@openshift-console/dynamic-plugin-sdk-internal', () => ({
HealthBody: 'div',
HealthItem: ({ title }) => <div>{title}</div>,
ViewDocumentation: ({ text, doclink }) => <a href={doclink}>{text}</a>,
HealthState: {
OK: 'OK',
},
}));

jest.mock('../../../../utils/osd-migration');
afterEach(cleanup);

describe('OSDMigrationStatus', () => {
test('renders the component with COMPLETED status', async () => {
const cephData = {
status: {
storage: {
osd: {
storeType: {
[BLUESTORE_RDR]: 5,
},
},
},
},
};

getOSDMigrationStatus.mockReturnValue('Completed');

render(
<MemoryRouter>
<OSDMigration cephData={cephData} />
</MemoryRouter>
);

await waitFor(() => {
expect(
screen.getByText('Cluster ready for Regional-DR setup.')
).toBeInTheDocument();
});
});

test('renders the component with PENDING status', async () => {
const cephData = {
status: {
storage: {
osd: {
storeType: {
[BLUESTORE]: 10,
[BLUESTORE_RDR]: 5,
},
},
},
},
};

getOSDMigrationStatus.mockReturnValue('In Progress');

render(
<MemoryRouter>
<OSDMigration cephData={cephData} />
</MemoryRouter>
);

await waitFor(() => {
expect(
screen.getByText('Cluster OSDs are being migrated')
).toBeInTheDocument();
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
import * as React from 'react';
import {
OSDMigrationStatus,
BLUESTORE,
BLUESTORE_RDR,
} from '@odf/core/constants';
import { ODF_DR_DOC_HOME } from '@odf/shared/constants/doc';
import { RedExclamationCircleIcon } from '@odf/shared/status/icons';
import { CephClusterKind } from '@odf/shared/types';
import { useCustomTranslation } from '@odf/shared/useCustomTranslationHook';
import { ViewDocumentation } from '@odf/shared/utils/doc-utils';
import { HealthState } from '@openshift-console/dynamic-plugin-sdk';
import {
HealthBody,
HealthItem,
} from '@openshift-console/dynamic-plugin-sdk-internal';
import { Button, Divider, Flex, FlexItem } from '@patternfly/react-core';
import { CloseIcon, InProgressIcon } from '@patternfly/react-icons';
import { getOSDMigrationStatus } from '../../../../utils/osd-migration';

const calculateOSDMigration = (
cephData: CephClusterKind
): [number, number, number] => {
const migratedDevices =
cephData?.status?.storage?.osd?.storeType?.[BLUESTORE_RDR] || 0;
const totalOsd =
(cephData?.status?.storage?.osd?.storeType?.[BLUESTORE] || 0) +
migratedDevices;
const percentageComplete =
totalOsd !== 0 ? Math.round((migratedDevices / totalOsd) * 100) : 0;

return [migratedDevices, totalOsd, percentageComplete];
};

export const OSDMigration: React.FC<OSDMigrationStatusProps> = ({
cephData,
}) => {
const { t } = useCustomTranslation();
const [isMigrationStatusVisible, setIsMigrationStatusVisible] =
React.useState(true);
const [migratedDevices, totalOsd, percentageComplete] =
calculateOSDMigration(cephData);
const migrationStatus: string = getOSDMigrationStatus(cephData);

const handleClose = () => {
setIsMigrationStatusVisible(false);
};

React.useEffect(() => {
// If it's the initial mount and the status is COMPLETED, hide the migration status
if (
!isMigrationStatusVisible &&
migrationStatus === OSDMigrationStatus.COMPLETED
) {
return;
}
// For updates, trigger visibility
setIsMigrationStatusVisible(true);
}, [isMigrationStatusVisible, migrationStatus]);

return (
<>
{migrationStatus !== OSDMigrationStatus.PENDING &&
isMigrationStatusVisible && <Divider />}
<HealthBody>
<Flex alignItems={{ default: 'alignItemsCenter' }}>
{migrationStatus === OSDMigrationStatus.COMPLETED &&
isMigrationStatusVisible && (
<>
<FlexItem>
<HealthItem
title={t('Cluster ready for Regional-DR setup.')}
state={HealthState.OK}
/>
</FlexItem>
<FlexItem>
<ViewDocumentation
text={t('Setting up disaster recovery')}
doclink={ODF_DR_DOC_HOME}
/>
</FlexItem>
<FlexItem align={{ default: 'alignRight' }}>
<Button onClick={handleClose} variant="plain">
{<CloseIcon />}
</Button>
</FlexItem>
</>
)}

{migrationStatus === OSDMigrationStatus.IN_PROGRESS && (
<>
<FlexItem className="pf-u-mt-xl">
<HealthItem
icon={<InProgressIcon className="co-dashboard-icon" />}
state={HealthState.OK}
title={t('Cluster OSDs are being migrated')}
/>
</FlexItem>
<FlexItem className="pf-u-mt-xl">
{t(
'{{ percentageComplete }}% completed ({{ migratedDevices }}/{{ totalOsd }} remaining)',
{
percentageComplete,
migratedDevices,
totalOsd,
}
)}
</FlexItem>
</>
)}

{migrationStatus === OSDMigrationStatus.FAILED && (
<>
<FlexItem>
<HealthItem
state={HealthState.OK}
icon={
<RedExclamationCircleIcon className="co-dashboard-icon" />
}
title={t('Could not migrate cluster OSDs.')}
/>
</FlexItem>
<FlexItem>
<ViewDocumentation
text={t('Check documentation')}
doclink={ODF_DR_DOC_HOME}
/>
</FlexItem>
<FlexItem align={{ default: 'alignRight' }}>
{t(
'{{ percentageComplete }}% completed ({{ migratedDevices }}/{{ totalOsd }} remaining)',
{
percentageComplete,
migratedDevices,
totalOsd,
}
)}
</FlexItem>
</>
)}
</Flex>
</HealthBody>
</>
);
};

type OSDMigrationStatusProps = {
cephData?: CephClusterKind;
};
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import {
} from '@patternfly/react-core';
import { CephClusterModel } from '../../../models';
import { DATA_RESILIENCY_QUERY, StorageDashboardQuery } from '../../../queries';
import { OSDMigration } from './osd-migration/osd-migration-status';
import { getCephHealthState, getDataResiliencyState } from './utils';
import { whitelistedHealthChecksRef } from './whitelisted-health-checks';
import './healthchecks.scss';
Expand Down Expand Up @@ -183,6 +184,7 @@ export const StatusCard: React.FC = () => {
</GalleryItem>
</Gallery>
</HealthBody>
<OSDMigration cephData={data?.[0]} />
<CephAlerts />
</Card>
);
Expand Down
Loading

0 comments on commit 64f24be

Please sign in to comment.