Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[release-4.17-compatibility] Bug 2311867: Prepare cluster for disaster recovery #1587

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cypress/support.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ Cypress.Commands.add('install', () => {
cy.get('table').get('input[type="checkbox"]').first().check();
cy.get('button').contains('Next').click();
cy.get('button').contains('Next').click();
cy.get('button').contains('Next').click();
cy.get('button')
.contains('Create StorageSystem')
.as('Create StorageSystem Button');
Expand Down
16 changes: 15 additions & 1 deletion locales/en/plugin__odf-console.json
Original file line number Diff line number Diff line change
Expand Up @@ -563,7 +563,7 @@
"Requested capacity": "Requested capacity",
"Expanding StorageCluster": "Expanding StorageCluster",
"Migrating cluster OSDs": "Migrating cluster OSDs",
"{{blueStoreCount}}/{{totalOSDCount}} OSDs migrated:": "{{blueStoreCount}}/{{totalOSDCount}} OSDs migrated:",
"{{blueStoreRdrCount}}/{{totalOSDCount}} OSDs migrated:": "{{blueStoreRdrCount}}/{{totalOSDCount}} OSDs migrated:",
"Upgrading Data Foundation's Operator": "Upgrading Data Foundation's Operator",
"Select a namespace:": "Select a namespace:",
"Only showing PVCs that are being mounted on an active pod": "Only showing PVCs that are being mounted on an active pod",
Expand All @@ -578,7 +578,16 @@
"Estimated days until full": "Estimated days until full",
"Understanding these terms": "Understanding these terms",
"Internal": "Internal",
"Disaster recovery readiness": "Disaster recovery readiness",
"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.",
"Prepare the cluster for Regional DR setup": "Prepare the cluster for Regional DR setup",
"To prepare the cluster for Regional DR setup, you must migrate the OSDs. Migrating OSDs may take some time to complete based on your cluster.": "To prepare the cluster for Regional DR setup, you must migrate the OSDs. Migrating OSDs may take some time to complete based on your cluster.",
"Yes, migrate OSDs": "Yes, migrate OSDs",
"Cluster ready for Regional-DR setup.": "Cluster ready for Regional-DR setup.",
"Setting up disaster recovery": "Setting up disaster recovery",
"{{blueStoreRdrCount}}/{{totalOSDCount}} OSDs migrated": "{{blueStoreRdrCount}}/{{totalOSDCount}} OSDs migrated",
"Could not migrate cluster OSDs. Check logs": "Could not migrate cluster OSDs. Check logs",
"{{ blueStoreRdrCount }}/{{ totalOSD }} remaining": "{{ blueStoreRdrCount }}/{{ totalOSD }} remaining",
"Active health checks": "Active health checks",
"Progressing": "Progressing",
"The Compression Ratio represents the compressible data effectiveness metric inclusive of all compression-enabled pools.": "The Compression Ratio represents the compressible data effectiveness metric inclusive of all compression-enabled pools.",
Expand All @@ -588,6 +597,7 @@
"Performance metrics over time showing IOPS, Latency and more. Each metric is a link to a detailed view of this metric.": "Performance metrics over time showing IOPS, Latency and more. Each metric is a link to a detailed view of this metric.",
"Block and File service is unhealthy": "Block and File service is unhealthy",
"Object service is unhealthy": "Object service is unhealthy",
"(Prepare cluster for DR setup)": "(Prepare cluster for DR setup)",
"Create Storage Pool": "Create Storage Pool",
"Storage pool delete modal": "Storage pool delete modal",
"Delete Storage Pool": "Delete Storage Pool",
Expand Down Expand Up @@ -887,6 +897,8 @@
"Selected versus Available Capacity": "Selected versus Available Capacity",
"Out of {{capacity}}": "Out of {{capacity}}",
"{{displayName}} connection details": "{{displayName}} connection details",
"Prepare cluster for disaster recovery (Regional-DR only)": "Prepare cluster for disaster recovery (Regional-DR only)",
"Set up the storage system for disaster recovery service with the essential configurations in place. This will subsequently allows seamless implementation of the disaster recovery strategies for your workloads.": "Set up the storage system for disaster recovery service with the essential configurations in place. This will subsequently allows seamless implementation of the disaster recovery strategies for your workloads.",
"Not connected": "Not connected",
"Backing storage": "Backing storage",
"Deployment type: {{deployment}}": "Deployment type: {{deployment}}",
Expand All @@ -911,6 +923,8 @@
"Encryption: {{encryptionStatus}}": "Encryption: {{encryptionStatus}}",
"In-transit encryption: {{hasInTransitEncryption}}": "In-transit encryption: {{hasInTransitEncryption}}",
"Network: {{networkType}}": "Network: {{networkType}}",
"Data protection": "Data protection",
"Regional-DR preparation: {{isRDRPreparationEnabled}}": "Regional-DR preparation: {{isRDRPreparationEnabled}}",
"Public Network Interface": "Public Network Interface",
"Select NetworkAttachmentDefinition": "Select NetworkAttachmentDefinition",
"Cluster Network Interface": "Cluster Network Interface",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,9 +197,7 @@ const OngoingActivity = () => {
// If migration is complete, the UI remains empty.
if (
!isProviderMode &&
[OSDMigrationStatus.PENDING, OSDMigrationStatus.IN_PROGRESS].includes(
osdMigrationStatus
)
[OSDMigrationStatus.IN_PROGRESS].includes(osdMigrationStatus)
) {
resourceActivities.push({
resource: cephCluster,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ const cephDataPending: CephClusterKind = {
storage: {
osd: {
storeType: {
bluestore: 0,
'bluestore-rdr': 5,
bluestore: 5,
'bluestore-rdr': 0,
},
},
},
Expand All @@ -21,8 +21,8 @@ const cephDataInProgress: CephClusterKind = {
storage: {
osd: {
storeType: {
bluestore: 3,
'bluestore-rdr': 2,
bluestore: 2,
'bluestore-rdr': 3,
},
},
},
Expand All @@ -34,8 +34,8 @@ const cephDataCompleted: CephClusterKind = {
storage: {
osd: {
storeType: {
bluestore: 5,
'bluestore-rdr': 0,
bluestore: 0,
'bluestore-rdr': 5,
},
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const ClusterMigrationActivity: React.FC<MigrationProps> = ({
resource: cephData,
}) => {
const { t } = useCustomTranslation();
const { blueStoreCount, totalOSDCount, percentageComplete } =
const { blueStoreRdrCount, totalOSDCount, percentageComplete } =
getOSDMigrationMetrics(cephData);

return (
Expand All @@ -17,8 +17,8 @@ export const ClusterMigrationActivity: React.FC<MigrationProps> = ({
<Progress
value={percentageComplete}
size={ProgressSize.sm}
title={t('{{blueStoreCount}}/{{totalOSDCount}} OSDs migrated:', {
blueStoreCount,
title={t('{{blueStoreRdrCount}}/{{totalOSDCount}} OSDs migrated:', {
blueStoreRdrCount,
totalOSDCount,
})}
label={`${percentageComplete}%`}
Expand Down
37 changes: 35 additions & 2 deletions packages/ocs/dashboards/persistent-internal/details-card.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
import * as React from 'react';
import { useODFNamespaceSelector } from '@odf/core/redux';
import { getStorageClusterInNs } from '@odf/core/utils';
import {
getStorageClusterInNs,
getResourceInNs as getCephClusterInNs,
} from '@odf/core/utils';
import { OSDMigrationDetails } from '@odf/ocs/modals/osd-migration/osd-migration-details';
import { ODF_OPERATOR } from '@odf/shared/constants';
import { useK8sGet } from '@odf/shared/hooks/k8s-get-hook';
import { useFetchCsv } from '@odf/shared/hooks/use-fetch-csv';
import { StorageClusterModel } from '@odf/shared/models';
import {
ClusterServiceVersionModel,
InfrastructureModel,
CephClusterModel,
} from '@odf/shared/models';
import { getName } from '@odf/shared/selectors';
import { K8sResourceKind, StorageClusterKind } from '@odf/shared/types';
import {
K8sResourceKind,
StorageClusterKind,
CephClusterKind,
} from '@odf/shared/types';
import { useCustomTranslation } from '@odf/shared/useCustomTranslationHook';
import { getOprVersionFromCSV } from '@odf/shared/utils';
import {
Expand All @@ -35,6 +44,11 @@ const storageClusterResource = {
isList: true,
};

const cephClusterResource = {
kind: referenceForModel(CephClusterModel),
isList: true,
};

const DetailsCard: React.FC = () => {
const { t } = useCustomTranslation();
const { namespace: ocsNs } = useParams<ODFSystemParams>();
Expand All @@ -44,6 +58,9 @@ const DetailsCard: React.FC = () => {
const [infrastructure, infrastructureLoaded, infrastructureError] =
useK8sGet<K8sResourceKind>(InfrastructureModel, 'cluster');

const [cephData, cephLoaded, cephLoadError] =
useK8sWatchResource<CephClusterKind[]>(cephClusterResource);

const [ocsData, ocsLoaded, ocsError] = useK8sWatchResource<
StorageClusterKind[]
>(storageClusterResource);
Expand All @@ -59,6 +76,7 @@ const DetailsCard: React.FC = () => {
ocsData,
ocsNs
);
const cephCluster: CephClusterKind = getCephClusterInNs(cephData, ocsNs);
const ocsName = getName(storageCluster);
const inTransitEncryptionStatus = getNetworkEncryption(storageCluster)
? t('Enabled')
Expand Down Expand Up @@ -124,6 +142,21 @@ const DetailsCard: React.FC = () => {
>
{inTransitEncryptionStatus}
</DetailItem>
{!isProviderMode && (
<DetailItem
key="osd_migration"
title={t('Disaster recovery readiness')}
isLoading={!cephLoaded}
error={cephLoadError as any}
>
<OSDMigrationDetails
loaded={cephLoaded && ocsLoaded}
loadError={cephLoadError || ocsError}
cephData={cephCluster}
ocsData={storageCluster}
/>
</DetailItem>
)}
</DetailsBody>
</CardBody>
</Card>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import * as React from 'react';
import { DISASTER_RECOVERY_TARGET_ANNOTATION_WO_SLASH } from '@odf/core/constants';
import { CommonModalProps, ModalBody, ModalFooter } from '@odf/shared/modals';
import { StorageClusterModel } from '@odf/shared/models';
import { getName, getNamespace } from '@odf/shared/selectors';
import { StorageClusterKind } from '@odf/shared/types';
import { useCustomTranslation } from '@odf/shared/useCustomTranslationHook';
import { k8sPatch } from '@openshift-console/dynamic-plugin-sdk';
import {
Modal,
ModalVariant,
Button,
Alert,
AlertVariant,
ButtonVariant,
} from '@patternfly/react-core';

export const OSDMigrationModal: React.FC<OSDMigrationModalProps> = ({
isOpen,
extraProps,
closeModal,
}) => {
const { t } = useCustomTranslation();
const ocsData = extraProps?.ocsData;
const [errorMessage, setErrorMessage] = React.useState<string>('');

const handleOptimize = () => {
const patch = [
{
op: 'add',
path: `/metadata/annotations/${DISASTER_RECOVERY_TARGET_ANNOTATION_WO_SLASH}`,
value: 'true',
},
];

k8sPatch({
model: StorageClusterModel,
resource: {
metadata: {
name: getName(ocsData),
namespace: getNamespace(ocsData),
},
},
data: patch,
})
.then(() => {
closeModal();
})
.catch((err) => {
setErrorMessage(err.message);
});
};

return (
<Modal
variant={ModalVariant.small}
title={t('Prepare the cluster for Regional DR setup')}
isOpen={isOpen}
onClose={closeModal}
>
{t(
'To prepare the cluster for Regional DR setup, you must migrate the OSDs. Migrating OSDs may take some time to complete based on your cluster.'
)}
<ModalBody>
{!!errorMessage && (
<Alert
isInline
variant={AlertVariant.danger}
title={t('An error occurred')}
>
{errorMessage}
</Alert>
)}
</ModalBody>
<ModalFooter>
<Button
key="close"
variant={ButtonVariant.secondary}
onClick={closeModal}
>
{t('Cancel')}
</Button>
<Button
key="optimize"
variant={ButtonVariant.primary}
onClick={handleOptimize}
>
{t('Yes, migrate OSDs')}
</Button>
</ModalFooter>
</Modal>
);
};

export type OSDMigrationModalProps = CommonModalProps<{
ocsData: StorageClusterKind;
}>;

export default OSDMigrationModal;
Loading
Loading