Skip to content

Commit

Permalink
MGMT-20061: Add OpenShift AI AMD bundle
Browse files Browse the repository at this point in the history
This patch adds the operators needed by the OpenShift AI AMD bundle: AMD
GPU and KMM.

Related: https://issues.redhat.com/browse/MGMT-20061
Signed-off-by: Juan Hernandez <juan.hernandez@redhat.com>
  • Loading branch information
jhernand committed Feb 27, 2025
1 parent dc57eee commit 9ad894d
Show file tree
Hide file tree
Showing 13 changed files with 194 additions and 3 deletions.
4 changes: 4 additions & 0 deletions libs/locales/lib/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@
"ai:Allocate IPs via DHCP server": "Allocate IPs using DHCP server",
"ai:Already approved": "Already approved",
"ai:Also note that each host's disk write speed should meet the minimum requirements to run OpenShift. ": "Also note that the disk write speed of each host must meet the minimum requirements to run OpenShift. ",
"ai:AMD GPU": "AMD GPU",
"ai:AMD GPU requirements": "AMD GPU requirements",
"ai:An error occured": "An error occured.",
"ai:An error occured while approving agents": "An error occured while approving agents.",
"ai:An error occured while starting installation.": "An error occured while starting installation.",
Expand Down Expand Up @@ -472,6 +474,8 @@
"ai:Keep the Discovery ISO media connected to the device throughout the installation process and set each host to boot <bold>only one time</bold> from this device. ": "Keep the Discovery ISO media connected to the device throughout the installation process and set each host to boot <bold>only one time</bold> from this device. ",
"ai:Keep the Discovery ISO media connected to the device throughout the installation process and set each host to boot <bold>only one time</bold> from this device. _plural": "Keep the Discovery ISO media connected to the device throughout the installation process and set each host to boot <bold>only one time</bold> from this device. ",
"ai:Keep the field empty to match <bold>any</bold> location.": "Keep the field empty to match <bold>any</bold> location.",
"ai:Kernel Module Management": "Kernel Module Management",
"ai:Kernel Module Management requirements": "Kernel Module Management requirements",
"ai:Kubeconfig is empty.": "Kubeconfig is empty.",
"ai:Labels": "Labels",
"ai:Labels matching hosts": "Labels matching hosts",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ const operatorValidations = [
status: 'success',
message: 'osc is disabled',
},
{
id: 'amd-gpu-requirements-satisfied',
status: 'success',
message: 'amd-gpu is disabled',
},
];

const hostValidationsInfo = {
Expand Down
12 changes: 12 additions & 0 deletions libs/ui-lib/lib/common/config/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ export const hostValidationLabels = (t: TFunction): { [key in HostValidationId]:
'mtu-valid': t('ai:MTU requirements'),
'authorino-requirements-satisfied': '',
'nmstate-requirements-satisfied': '',
'amd-gpu-requirements-satisfied': t('ai:AMD GPU requirements'),
'kmm-requirements-satisfied': t('ai:Kernel Module Management requirements'),
});

export const hostValidationFailureHints = (
Expand Down Expand Up @@ -198,6 +200,8 @@ export const hostValidationFailureHints = (
'authorino-requirements-satisfied': '',
'mtu-valid': '',
'nmstate-requirements-satisfied': '',
'amd-gpu-requirements-satisfied': '',
'kmm-requirements-satisfied': '',
});

export const clusterValidationLabels = (
Expand Down Expand Up @@ -301,6 +305,8 @@ export const OPERATOR_NAME_OPENSHIFT_AI = 'openshift-ai';
export const OPERATOR_NAME_OSC = 'osc';
export const OPERATOR_NAME_NMSTATE = 'nmstate';
export const OPERATOR_NAME_AUTHORINO = 'authorino';
export const OPERATOR_NAME_AMD_GPU = 'amd-gpu';
export const OPERATOR_NAME_KMM = 'kmm';

const OperatorNames = [
OPERATOR_NAME_CNV,
Expand All @@ -319,6 +325,8 @@ const OperatorNames = [
OPERATOR_NAME_OSC,
OPERATOR_NAME_NMSTATE,
OPERATOR_NAME_AUTHORINO,
OPERATOR_NAME_AMD_GPU,
OPERATOR_NAME_KMM,
];
export const ExposedOperatorNames = [
OPERATOR_NAME_CNV,
Expand All @@ -336,6 +344,8 @@ export const ExposedOperatorNames = [
OPERATOR_NAME_OSC,
OPERATOR_NAME_NMSTATE,
OPERATOR_NAME_AUTHORINO,
OPERATOR_NAME_AMD_GPU,
OPERATOR_NAME_KMM,
];

export type OperatorName = (typeof OperatorNames)[number];
Expand Down Expand Up @@ -381,6 +391,8 @@ export const operatorLabels = (
[OPERATOR_NAME_MTV]: t('ai:Migration Toolkit for Virtualization'),
[OPERATOR_NAME_NMSTATE]: t('ai:NMState'),
[OPERATOR_NAME_AUTHORINO]: t('ai:Authorino'),
[OPERATOR_NAME_AMD_GPU]: t('ai:AMD GPU'),
[OPERATOR_NAME_KMM]: t('ai:Kernel Module Management'),
};
};

Expand Down
2 changes: 2 additions & 0 deletions libs/ui-lib/lib/common/types/clusters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ export type OperatorsValues = V2ClusterUpdateParams & {
usePipelines: boolean;
useServicemesh: boolean;
useNvidiaGpu: boolean;
useAmdGpu: boolean;
useKmm: boolean;
};

export type SupportedPlatformType = Extract<PlatformType, 'vsphere' | 'nutanix' | 'external'>;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import React, { useState } from 'react';
import { FormGroup, HelperText, HelperTextItem, Tooltip } from '@patternfly/react-core';
import { getFieldId, PopoverIcon } from '../../../../common';
import { OcmCheckboxField } from '../../ui/OcmFormFields';
import { useNewFeatureSupportLevel } from '../../../../common/components/newFeatureSupportLevels';
import NewFeatureSupportLevelBadge from '../../../../common/components/newFeatureSupportLevels/NewFeatureSupportLevelBadge';
import { SupportLevel } from '@openshift-assisted/types/./assisted-installer-service';

const AMDGPU_FIELD_NAME = 'useAmdGpu';

const AmdGpuLabel = ({
disabledReason,
supportLevel,
}: {
disabledReason?: string;
supportLevel?: SupportLevel;
}) => {
return (
<>
<Tooltip hidden={!disabledReason} content={disabledReason}>
<span>Install AMD GPU </span>
</Tooltip>
<PopoverIcon
id={AMDGPU_FIELD_NAME}
component={'a'}
bodyContent={'Requires at least one supported AMD GPU'}
/>
<NewFeatureSupportLevelBadge featureId="AMD_GPU" supportLevel={supportLevel} />
</>
);
};

const AmdGpuHelperText = () => {
return (
<HelperText>
<HelperTextItem variant="indeterminate">
Automate the management of AMD software components needed to provision and monitor GPUs.{' '}
</HelperTextItem>
</HelperText>
);
};

const AmdGpuCheckbox = ({ disabledReason }: { disabledReason?: string }) => {
const fieldId = getFieldId(AMDGPU_FIELD_NAME, 'input');
const featureSupportLevel = useNewFeatureSupportLevel();
const [disabledReasonAmdGpu, setDisabledReason] = useState<string | undefined>();

React.useEffect(() => {
const reason = featureSupportLevel.getFeatureDisabledReason('AMD_GPU');
setDisabledReason(reason);
}, [featureSupportLevel]);

return (
<FormGroup isInline fieldId={fieldId}>
<OcmCheckboxField
name={AMDGPU_FIELD_NAME}
label={
<AmdGpuLabel
disabledReason={disabledReason ? disabledReason : disabledReasonAmdGpu}
supportLevel={featureSupportLevel.getFeatureSupportLevel('AMD_GPU')}
/>
}
helperText={<AmdGpuHelperText />}
isDisabled={!!disabledReason || !!disabledReasonAmdGpu}
/>
</FormGroup>
);
};

export default AmdGpuCheckbox;
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import React, { useState } from 'react';
import { FormGroup, HelperText, HelperTextItem, Tooltip } from '@patternfly/react-core';
import { getFieldId, PopoverIcon } from '../../../../common';
import { OcmCheckboxField } from '../../ui/OcmFormFields';
import { useNewFeatureSupportLevel } from '../../../../common/components/newFeatureSupportLevels';
import NewFeatureSupportLevelBadge from '../../../../common/components/newFeatureSupportLevels/NewFeatureSupportLevelBadge';
import { SupportLevel } from '@openshift-assisted/types/./assisted-installer-service';

const KMM_FIELD_NAME = 'useKmm';

const KmmLabel = ({
disabledReason,
supportLevel,
}: {
disabledReason?: string;
supportLevel?: SupportLevel;
}) => {
return (
<>
<Tooltip hidden={!disabledReason} content={disabledReason}>
<span>Install Kernel Module Management </span>
</Tooltip>
<PopoverIcon
id={KMM_FIELD_NAME}
component={'a'}
bodyContent={'No additional requirements needed'}
/>
<NewFeatureSupportLevelBadge featureId="KMM" supportLevel={supportLevel} />
</>
);
};

const KmmHelperText = () => {
return (
<HelperText>
<HelperTextItem variant="indeterminate">Management of kernel modules. </HelperTextItem>
</HelperText>
);
};

const KmmCheckbox = ({ disabledReason }: { disabledReason?: string }) => {
const fieldId = getFieldId(KMM_FIELD_NAME, 'input');
const featureSupportLevel = useNewFeatureSupportLevel();
const [disabledReasonKmm, setDisabledReason] = useState<string | undefined>();

React.useEffect(() => {
const reason = featureSupportLevel.getFeatureDisabledReason('KMM');
setDisabledReason(reason);
}, [featureSupportLevel]);

return (
<FormGroup isInline fieldId={fieldId}>
<OcmCheckboxField
name={KMM_FIELD_NAME}
label={
<KmmLabel
disabledReason={disabledReason ? disabledReason : disabledReasonKmm}
supportLevel={featureSupportLevel.getFeatureSupportLevel('KMM')}
/>
}
helperText={<KmmHelperText />}
isDisabled={!!disabledReason || !!disabledReasonKmm}
/>
</FormGroup>
);
};

export default KmmCheckbox;
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const NvidiaGpuLabel = ({
<PopoverIcon
id={NVIDIAGPU_FIELD_NAME}
component={'a'}
bodyContent={'No additional requirements needed'}
bodyContent={'Requires at least one supported NVIDIA GPU'}
/>
<NewFeatureSupportLevelBadge featureId="NVIDIA_GPU" supportLevel={supportLevel} />
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,14 @@ import AuthorinoCheckbox from './AuthorinoCheckbox';
import PipelinesCheckbox from './PipelinesChekbox';
import ServiceMeshCheckbox from './ServicemeshCheckbox';
import NvidiaGpuCheckbox from './NvidiaGpuCheckbox';
import AmdGpuCheckbox from './AmdGpuCheckbox';
import KmmCheckbox from './KmmCheckbox';
import {
FeatureId,
OPERATOR_NAME_AMD_GPU,
OPERATOR_NAME_AUTHORINO,
OPERATOR_NAME_CNV,
OPERATOR_NAME_KMM,
OPERATOR_NAME_LSO,
OPERATOR_NAME_LVM,
OPERATOR_NAME_MCE,
Expand Down Expand Up @@ -66,6 +70,8 @@ export const operatorComponentMap: Record<string, (props: OperatorProps) => JSX.
pipelines: (props) => <PipelinesCheckbox {...props} />,
servicemesh: (props) => <ServiceMeshCheckbox {...props} />,
'nvidia-gpu': (props) => <NvidiaGpuCheckbox {...props} />,
'amd-gpu': (props) => <AmdGpuCheckbox {...props} />,
kmm: (props) => <KmmCheckbox {...props} />,
};

export const mapOperatorsToFieldIds: { [key: string]: string } = {
Expand All @@ -84,6 +90,8 @@ export const mapOperatorsToFieldIds: { [key: string]: string } = {
[OPERATOR_NAME_PIPELINES]: 'usePipelines',
[OPERATOR_NAME_SERVICEMESH]: 'useServicemesh',
[OPERATOR_NAME_NVIDIA_GPU]: 'useNvidiaGpu',
[OPERATOR_NAME_AMD_GPU]: 'useAmdGpu',
[OPERATOR_NAME_KMM]: 'useKmm',
};

export const mapOperatorIdToFeatureId: { [key: string]: FeatureId } = {
Expand Down
4 changes: 4 additions & 0 deletions libs/ui-lib/lib/ocm/components/clusterWizard/Operators.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import { Formik, FormikConfig, useFormikContext } from 'formik';
import {
ClusterWizardStep,
getFormikErrorFields,
OPERATOR_NAME_AMD_GPU,
OPERATOR_NAME_AUTHORINO,
OPERATOR_NAME_CNV,
OPERATOR_NAME_KMM,
OPERATOR_NAME_LSO,
OPERATOR_NAME_LVM,
OPERATOR_NAME_MCE,
Expand Down Expand Up @@ -56,6 +58,8 @@ export const getOperatorsInitialValues = (
usePipelines: isOperatorEnabled([OPERATOR_NAME_PIPELINES]),
useServicemesh: isOperatorEnabled([OPERATOR_NAME_SERVICEMESH]),
useNvidiaGpu: isOperatorEnabled([OPERATOR_NAME_NVIDIA_GPU]),
useAmdGpu: isOperatorEnabled([OPERATOR_NAME_AMD_GPU]),
useKmm: isOperatorEnabled([OPERATOR_NAME_KMM]),
};
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,8 @@ export const OperatorsStep = (props: ClusterOperatorProps) => {
{/* Mostrar bundles como tarjetas */}
<Gallery hasGutter minWidths={{ default: '350px' }} maxWidths={{ default: '2fr' }}>
{filteredBundles.map((bundle) => {
const isSnoAndBlockedBundle = isSNO && bundle.id === 'openshift-ai-nvidia';
const isSnoAndBlockedBundle =
isSNO && (bundle.id === 'openshift-ai-nvidia' || bundle.id === 'openshift-ai-amd');

const tooltipContent = hasUnsupportedOperators
? 'Some operators in this bundle are not supported with the current configuration.'
Expand Down Expand Up @@ -375,7 +376,8 @@ export const OperatorsStep = (props: ClusterOperatorProps) => {

{/* Badge aligned to the bottom-left */}
<div style={{ marginTop: '10px', alignSelf: 'flex-end', height: '25px' }}>
{bundle.id === 'openshift-ai-nvidia' && (
{(bundle.id === 'openshift-ai-nvidia' ||
bundle.id === 'openshift-ai-amd') && (
<NewFeatureSupportLevelBadge
featureId="OPENSHIFT_AI"
supportLevel="dev-preview"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,11 @@ const validationInfoHostsDisovery: ValidationsInfo = {
message: 'a validation unrelated to the canNextHostDiscovery',
status: 'error',
},
{
id: 'amd-gpu-requirements-satisfied',
message: 'a validation message',
status: 'success',
},
],
};

Expand Down Expand Up @@ -205,6 +210,11 @@ const flatValidationHostsDiscovery: HostValidation[] = [
message: 'a host validation message',
status: 'success',
},
{
id: 'amd-gpu-requirements-satisfied',
message: 'a host validation message',
status: 'success',
},
];

const flatValidationHostsStorage: HostValidation[] = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ const hostDiscoveryStepValidationsMap: WizardStepValidationMap = {
'nvidia-gpu-requirements-satisfied',
'openshift-ai-requirements-satisfied',
'osc-requirements-satisfied',
'amd-gpu-requirements-satisfied',
],
},
host: {
Expand All @@ -189,6 +190,7 @@ const hostDiscoveryStepValidationsMap: WizardStepValidationMap = {
'nvidia-gpu-requirements-satisfied',
'openshift-ai-requirements-satisfied',
'osc-requirements-satisfied',
'amd-gpu-requirements-satisfied',
],
},
softValidationIds: ['no-skip-installation-disk', 'no-skip-missing-disk', 'compatible-agent'],
Expand Down
4 changes: 4 additions & 0 deletions libs/ui-lib/lib/ocm/services/OperatorsService.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import {
OPERATOR_NAME_PIPELINES,
OPERATOR_NAME_SERVICEMESH,
OPERATOR_NAME_NVIDIA_GPU,
OPERATOR_NAME_AMD_GPU,
OPERATOR_NAME_KMM,
} from '../../common';
import { getOlmOperatorCreateParamsByName } from '../components/clusters/utils';
import {
Expand Down Expand Up @@ -52,6 +54,8 @@ const OperatorsService = {
setOperator(OPERATOR_NAME_PIPELINES, values.usePipelines);
setOperator(OPERATOR_NAME_SERVICEMESH, values.useServicemesh);
setOperator(OPERATOR_NAME_NVIDIA_GPU, values.useNvidiaGpu);
setOperator(OPERATOR_NAME_AMD_GPU, values.useAmdGpu);
setOperator(OPERATOR_NAME_KMM, values.useKmm);

return Object.values(enabledOlmOperatorsByName);
},
Expand Down

0 comments on commit 9ad894d

Please sign in to comment.