-
Notifications
You must be signed in to change notification settings - Fork 31
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Timothy Asir Jeyasingh <[email protected]>
- Loading branch information
1 parent
ee80530
commit 464be9d
Showing
9 changed files
with
312 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import * as React from 'react'; | ||
import { DISASTER_RECOVERY_TARGET_ANNOTATION } from '@odf/core/constants'; | ||
import { CommonModalProps, ModalBody, ModalFooter } from '@odf/shared/modals'; | ||
import { OCSStorageClusterModel } 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 } 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}`, | ||
value: 'true', | ||
}, | ||
]; | ||
|
||
k8sPatch({ | ||
model: OCSStorageClusterModel, | ||
resource: { | ||
metadata: { | ||
name: getName(ocsData), | ||
namespace: getNamespace(ocsData), | ||
}, | ||
}, | ||
data: patch, | ||
}) | ||
.then(() => { | ||
closeModal(); | ||
}) | ||
.catch((err) => { | ||
setErrorMessage(err.message); | ||
}); | ||
}; | ||
|
||
return ( | ||
<Modal | ||
variant={ModalVariant.small} | ||
title={t('Optimise cluster for Regional-DR?')} | ||
isOpen={isOpen} | ||
onClose={closeModal} | ||
> | ||
{t( | ||
'Configure the cluster for a Regional-DR setup by migrating OSDs. Migration may take some time depending on several factors. To learn more about OSDs migration best practices and its consequences refer to the documentation.' | ||
)} | ||
{/* TODO: Show doc link once ViewDocumentation moved to shared */} | ||
<ModalBody> | ||
{!!errorMessage && ( | ||
<Alert isInline variant="danger" title={t('An error occurred')}> | ||
{errorMessage} | ||
</Alert> | ||
)} | ||
</ModalBody> | ||
<ModalFooter> | ||
<Button key="close" variant="secondary" onClick={closeModal}> | ||
{t('Close')} | ||
</Button> | ||
<Button key="optimize" variant="primary" onClick={handleOptimize}> | ||
{t('Optimise')} | ||
</Button> | ||
</ModalFooter> | ||
</Modal> | ||
); | ||
}; | ||
|
||
type OSDMigrationModalProps = CommonModalProps<{ | ||
ocsData: StorageClusterKind; | ||
}>; | ||
|
||
export default OSDMigrationModal; |
91 changes: 91 additions & 0 deletions
91
packages/ocs/modals/osd-migration/osdMigrationDetails.spec.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
import React from 'react'; | ||
import { BLUESTORE, BLUESTORE_RDR } from '@odf/core/constants'; | ||
import { screen, render, waitFor } from '@testing-library/react'; | ||
import '@testing-library/jest-dom/extend-expect'; | ||
import { MemoryRouter } from 'react-router-dom'; | ||
import { OSDMigrationModal } from '../../modals/osd-migration/osd-migration-modal'; | ||
import * as migrationStatus from '../../utils/osd-migration'; | ||
|
||
jest.mock('@odf/shared/selectors', () => ({ | ||
getName: jest.fn().mockReturnValue('test'), | ||
})); | ||
|
||
// Mocking getOSDMigrationStatus | ||
jest.mock('../../utils/osd-migration'); | ||
|
||
jest.mock('@odf/shared/hooks/useK8sList', () => ({ | ||
__esModule: true, | ||
useK8sList: () => [ | ||
[ | ||
{ | ||
metadata: { | ||
name: 'test', | ||
}, | ||
}, | ||
], | ||
true, | ||
undefined, | ||
], | ||
})); | ||
|
||
describe('OptimizeModal Component', () => { | ||
test('renders without errors', async () => { | ||
const cephData = { | ||
status: { | ||
storage: { | ||
osd: { | ||
storeType: { | ||
[BLUESTORE_RDR]: 5, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}; | ||
|
||
// Mock getOSDMigrationStatus to return 'Completed' for this test | ||
migrationStatus.getOSDMigrationStatus.mockReturnValue('Completed'); | ||
|
||
render( | ||
<MemoryRouter> | ||
<OSDMigrationModal cephData={cephData} ocsData={null} isOpen={false} /> | ||
</MemoryRouter> | ||
); | ||
|
||
// Wait for the component to finish rendering (use async/await) | ||
await waitFor(() => { | ||
expect(screen.queryByText('Optimise')).not.toBeInTheDocument(); | ||
}); | ||
}); | ||
|
||
test('renders with migration pending', async () => { | ||
const cephData = { | ||
status: { | ||
storage: { | ||
osd: { | ||
storeType: { | ||
[BLUESTORE]: 5, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}; | ||
|
||
migrationStatus.getOSDMigrationStatus.mockReturnValue('Pending'); | ||
render( | ||
<MemoryRouter> | ||
<OSDMigrationModal cephData={cephData} ocsData={null} isOpen={true} /> | ||
</MemoryRouter> | ||
); | ||
|
||
await waitFor(() => { | ||
expect(screen.queryByText('Optimise')).toBeInTheDocument(); | ||
}); | ||
|
||
// Wait for modal to be visible | ||
await waitFor(() => { | ||
expect( | ||
screen.queryByText('Optimise cluster for Regional-DR?') | ||
).toBeInTheDocument(); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import * as React from 'react'; | ||
import { OSDMigrationStatus } from '@odf/core/constants'; | ||
import { getOSDMigrationStatus } from '@odf/ocs/utils'; | ||
import { CephClusterKind, StorageClusterKind } from '@odf/shared/types'; | ||
import { useCustomTranslation } from '@odf/shared/useCustomTranslationHook'; | ||
import { | ||
RedExclamationCircleIcon, | ||
StatusIconAndText, | ||
useModal, | ||
} from '@openshift-console/dynamic-plugin-sdk'; | ||
import { Button, Flex, FlexItem } from '@patternfly/react-core'; | ||
import OSDMigrationModal from './osd-migration-modal'; | ||
|
||
export const OSDMigrationDetails: React.FC<OSDMigrationDetailsProps> = ({ | ||
cephData, | ||
ocsData, | ||
}) => { | ||
const { t } = useCustomTranslation(); | ||
const osdMigrationStatus: string = getOSDMigrationStatus(cephData); | ||
const launcher = useModal(); | ||
|
||
return ( | ||
<> | ||
<Flex> | ||
<FlexItem> | ||
<StatusIconAndText | ||
title={osdMigrationStatus} | ||
icon={ | ||
osdMigrationStatus === OSDMigrationStatus.FAILED && ( | ||
<RedExclamationCircleIcon /> | ||
) | ||
} | ||
/> | ||
</FlexItem> | ||
<FlexItem> | ||
{osdMigrationStatus === OSDMigrationStatus.PENDING && ( | ||
<Button | ||
variant="link" | ||
onClick={() => | ||
launcher(OSDMigrationModal, { | ||
isOpen: true, | ||
extraProps: { ocsData }, | ||
}) | ||
} | ||
> | ||
{t('Optimise cluster')} | ||
</Button> | ||
)} | ||
</FlexItem> | ||
</Flex> | ||
</> | ||
); | ||
}; | ||
|
||
type OSDMigrationDetailsProps = { | ||
cephData: CephClusterKind; | ||
ocsData: StorageClusterKind; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import { | ||
BLUESTORE, | ||
BLUESTORE_RDR, | ||
OSDMigrationStatus, | ||
} from '@odf/core/constants'; | ||
import { CephClusterKind } from '@odf/shared/types'; | ||
|
||
function getCephStoreType(ceph: CephClusterKind) { | ||
return ceph.status?.storage?.osd?.storeType; | ||
} | ||
|
||
const getBluestoreCount = (ceph: CephClusterKind): number => { | ||
return getCephStoreType(ceph)?.[BLUESTORE] || 0; | ||
}; | ||
|
||
const getBluestoreRdrCount = (ceph: CephClusterKind): number => { | ||
return getCephStoreType(ceph)?.[BLUESTORE_RDR] || 0; | ||
}; | ||
|
||
export const getOSDMigrationStatus = (ceph: CephClusterKind) => { | ||
if (!!ceph) { | ||
const bluestoreCount = getBluestoreCount(ceph); | ||
const bluestoreRdrCount = getBluestoreRdrCount(ceph); | ||
|
||
if (bluestoreCount > 0) { | ||
if (bluestoreRdrCount > 0) { | ||
return OSDMigrationStatus.IN_PROGRESS; | ||
} else { | ||
return OSDMigrationStatus.PENDING; | ||
} | ||
} else if (bluestoreRdrCount > 0) { | ||
return OSDMigrationStatus.COMPLETED; | ||
} | ||
} else { | ||
return OSDMigrationStatus.FAILED; | ||
} // TODO Add condition for migration failure | ||
|
||
return ''; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,12 @@ | ||
export const DISASTER_RECOVERY_TARGET_ANNOTATION = | ||
'ocs.openshift.io/clusterIsDisasterRecoveryTarget'; | ||
|
||
export enum OSDMigrationStatus { | ||
IN_PROGRESS = 'In Progress', | ||
PENDING = 'Pending', | ||
COMPLETED = 'Completed', | ||
FAILED = 'Failed', | ||
} | ||
|
||
export const BLUESTORE_RDR = 'bluestore-rdr'; | ||
export const BLUESTORE = 'bluestore'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters