Skip to content

Commit

Permalink
Merge pull request #10438 from afreen23/release-4.9
Browse files Browse the repository at this point in the history
[release-4.9]Bug 2022303: Fix creation of ibm storage system at backing storage step
  • Loading branch information
openshift-merge-robot committed Nov 23, 2021
2 parents 6c0dbfe + dc0af95 commit 1175ba4
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 75 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ const CreateStorageSystem: React.FC<CreateStorageSystemProps> = ({ match }) => {
state={state}
hasOCS={hasOCS}
dispatch={dispatch}
storageSystems={ssList?.items}
disableNext={!ssLoaded || !!ssLoadError}
/>
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ import {
import { history } from '@console/internal/components/utils';
import { OCS_ATTACHED_DEVICES_FLAG } from '@console/local-storage-operator-plugin/src/features';
import { setFlag } from '@console/internal/actions/features';

import { WizardCommonProps, WizardState } from './reducer';
import {
createExternalSubSystem,
createMCGStorageCluster,
createStorageCluster,
createStorageSystem,
labelNodes,
waitforCRD,
} from './payloads';
import {
BackingStorageType,
Expand All @@ -39,7 +39,7 @@ import {
getExternalSubSystemName,
} from '../../utils/create-storage-system';
import { MINIMUM_NODES, OCS_EXTERNAL_CR_NAME, OCS_INTERNAL_CR_NAME } from '../../constants';
import { NetworkType, StorageSystemKind } from '../../types';
import { NetworkType } from '../../types';
import { labelOCSNamespace } from '../ocs-install/ocs-request-data';
import { createClusterKmsResources } from '../kms-config/utils';
import { OCS_CONVERGED_FLAG, OCS_INDEPENDENT_FLAG, OCS_FLAG } from '../../features';
Expand Down Expand Up @@ -130,47 +130,11 @@ export const setActionFlags = (
}
};

const handleBackingStorageNext = async (
backingStorage: WizardState['backingStorage'],
handleError: (err: string, showError: boolean) => void,
moveToNextStep: () => void,
isSSPresent: boolean,
) => {
const { externalStorage, type, deployment } = backingStorage;
const { model, displayName } = getExternalStorage(externalStorage) || {
model: { kind: '', apiVersion: '', apiGroup: '' },
displayName: '',
};
const isRhcs = externalStorage === OCSServiceModel.kind;

try {
/*
* Creating storage system for an external vendor other than RHCS.
* The created storage system will create a subscription for
* external vendor operator.
*/
if (
type === BackingStorageType.EXTERNAL &&
!isRhcs &&
!isSSPresent &&
deployment !== DeploymentType.MCG
) {
const subSystemName = getExternalSubSystemName(displayName);
const externalSystemKind = getStorageSystemKind(model);
await createStorageSystem(subSystemName, externalSystemKind);
moveToNextStep();
} else moveToNextStep();
} catch (err) {
handleError(err.message, true);
}
};

const handleReviewAndCreateNext = async (
state: WizardState,
hasOCS: boolean,
handleError: (err: string, showError: boolean) => void,
flagDispatcher: any,
externalSystem: StorageSystemKind,
) => {
const { connectionDetails, createStorageClass, storageClass, nodes } = state;
const { externalStorage, deployment, type } = state.backingStorage;
Expand All @@ -192,34 +156,26 @@ const handleReviewAndCreateNext = async (
} else if (type === BackingStorageType.EXTERNAL) {
const { createPayload, model, displayName } = getExternalStorage(externalStorage) || {};

const firstExternalSystemName = getExternalSubSystemName(displayName);
const hasAnExternalSystem = externalSystem?.metadata?.name === firstExternalSystemName;

const subSystemName = isRhcs
? OCS_EXTERNAL_CR_NAME
: hasAnExternalSystem
? `${firstExternalSystemName}-${storageClass.name}`.substring(0, 230)
: firstExternalSystemName;
const externalSystemName = getExternalSubSystemName(displayName, storageClass.name);

const subSystemName = isRhcs ? OCS_EXTERNAL_CR_NAME : externalSystemName;
const subSystemState = isRhcs ? connectionDetails : createStorageClass;
const subSystemKind = getStorageSystemKind(model);

const subSystemPayloads = createPayload(
subSystemName,
subSystemState,
model,
storageClass.name,
);

await createExternalSubSystem(subSystemPayloads);
await labelOCSNamespace();
// Create storage cluster if one is not present except for external RHCS
await createStorageSystem(subSystemName, subSystemKind);
if (!hasOCS && !isRhcs) {
await labelNodes(nodes);
await createStorageCluster(state);
}
// Create a new storage system for non RHCS external vendor if one is not present
if (hasAnExternalSystem) await createStorageSystem(subSystemName, subSystemKind);
if (!isRhcs) await waitforCRD(model);
await createExternalSubSystem(subSystemPayloads);
}
// These flags control the enablement of dashboards and other ODF UI components in console
setActionFlags(isMCG ? BackingStorageType.EXISTING : type, flagDispatcher, isRhcs);
Expand All @@ -234,7 +190,6 @@ export const CreateStorageSystemFooter: React.FC<CreateStorageSystemFooterProps>
state,
disableNext,
hasOCS,
storageSystems,
}) => {
const { t } = useTranslation();
const { activeStep, onNext, onBack } = React.useContext<WizardContextType>(WizardContext);
Expand All @@ -248,11 +203,6 @@ export const CreateStorageSystemFooter: React.FC<CreateStorageSystemFooterProps>

const jumpToNextStep = canJumpToNextStep(stepName, state, t);

const { model } = getExternalStorage(state.backingStorage.externalStorage) || {
model: { kind: '', apiVersion: '', apiGroup: '' },
};
const externalSystem = storageSystems?.find((ss) => ss.spec.kind === getStorageSystemKind(model));

const moveToNextStep = () => {
dispatch({
type: 'wizard/setStepIdReached',
Expand All @@ -268,16 +218,6 @@ export const CreateStorageSystemFooter: React.FC<CreateStorageSystemFooterProps>

const handleNext = async () => {
switch (stepName) {
case StepsName(t)[Steps.BackingStorage]:
setRequestInProgress(true);
await handleBackingStorageNext(
state.backingStorage,
handleError,
moveToNextStep,
!!externalSystem,
);
setRequestInProgress(false);
break;
case StepsName(t)[Steps.CreateLocalVolumeSet]:
dispatch({
type: 'wizard/setCreateLocalVolumeSet',
Expand All @@ -286,7 +226,7 @@ export const CreateStorageSystemFooter: React.FC<CreateStorageSystemFooterProps>
break;
case StepsName(t)[Steps.ReviewAndCreate]:
setRequestInProgress(true);
await handleReviewAndCreateNext(state, hasOCS, handleError, flagDispatcher, externalSystem);
await handleReviewAndCreateNext(state, hasOCS, handleError, flagDispatcher);
setRequestInProgress(false);
break;
default:
Expand Down Expand Up @@ -323,11 +263,11 @@ export const CreateStorageSystemFooter: React.FC<CreateStorageSystemFooterProps>
<Button
variant="secondary"
onClick={onBack}
isDisabled={stepName === StepsName(t)[Steps.BackingStorage]}
isDisabled={stepName === StepsName(t)[Steps.BackingStorage] || requestInProgress}
>
{t('ceph-storage-plugin~Back')}
</Button>
<Button variant="link" onClick={history.goBack}>
<Button variant="link" onClick={history.goBack} isDisabled={requestInProgress}>
{t('ceph-storage-plugin~Cancel')}
</Button>
</WizardFooter>
Expand All @@ -338,5 +278,4 @@ export const CreateStorageSystemFooter: React.FC<CreateStorageSystemFooterProps>
type CreateStorageSystemFooterProps = WizardCommonProps & {
disableNext: boolean;
hasOCS: boolean;
storageSystems: StorageSystemKind[];
};
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import {
apiVersionForModel,
k8sCreate,
k8sGet,
k8sPatchByName,
K8sResourceKind,
} from '@console/internal/module/k8s';
import { NodeModel, SecretModel } from '@console/internal/models';
import { CustomResourceDefinitionModel, NodeModel, SecretModel } from '@console/internal/models';
import { K8sKind } from 'packages/console-dynamic-plugin-sdk/src';
import { WizardNodeState, WizardState } from './reducer';
import { Payload } from './external-storage/types';
Expand Down Expand Up @@ -139,3 +140,37 @@ export const createExternalSubSystem = async (subSystemPayloads: Payload[]) => {
throw err;
}
};

/**
* The crd status field should be available to proceed with CR creation.
*/
const isCRDAvailable = (crd: K8sResourceKind, plural: string) =>
crd?.status?.acceptedNames?.plural === plural;

export const waitforCRD = async (model, maxAttempts = 30) => {
const crdName = [model.plural, model.apiGroup].join('.');
const POLLING_INTERVAL = 5000;
let attempts = 0;
/**
* This will poll the CRD for an interval of 5s.
* This times out after 150s.
*/
const pollCRD = async (resolve, reject) => {
try {
attempts++;
const crd = await k8sGet(CustomResourceDefinitionModel, crdName);
return isCRDAvailable(crd, model.plural)
? resolve()
: setTimeout(pollCRD, POLLING_INTERVAL, resolve, reject);
} catch (err) {
if (err?.response?.status === 404) {
if (attempts === maxAttempts)
return reject(new Error(`CustomResourceDefintion '${crdName}' not found.`));
return setTimeout(pollCRD, POLLING_INTERVAL, resolve, reject);
}
return reject(err);
}
};

return new Promise(pollCRD);
};
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ export const getSupportedVendors = (csv: ClusterServiceVersionKind): string[] =>
export const getStorageSystemKind = ({ kind, apiVersion, apiGroup }) =>
`${kind.toLowerCase()}.${apiGroup}/${apiVersion}`;

export const getExternalSubSystemName = (name: string = '') =>
name.toLowerCase().replace(/\s/g, '-');
export const getExternalSubSystemName = (name: string = '', storageClassName: string) =>
`${name.toLowerCase().replace(/\s/g, '-')}-${storageClassName}`.substring(0, 230);

export const getExternalStorage = (id: WizardState['backingStorage']['externalStorage'] = '') =>
SUPPORTED_EXTERNAL_STORAGE.find((p) => p.model.kind === id);
Expand Down

0 comments on commit 1175ba4

Please sign in to comment.