diff --git a/libs/locales/lib/en/translation.json b/libs/locales/lib/en/translation.json index 78d52344ed..cecfef81b1 100644 --- a/libs/locales/lib/en/translation.json +++ b/libs/locales/lib/en/translation.json @@ -599,6 +599,7 @@ "ai:Open Virtual Networking (OVN)": "Open Virtual Networking (OVN)", "ai:Opening file": "Opening file", "ai:OpenShift": "OpenShift", + "ai:OpenShift AI": "OpenShift AI", "ai:OpenShift Cluster Manager": "OpenShift Cluster Manager", "ai:OpenShift Data Foundation": "OpenShift Data Foundation", "ai:OpenShift in-place upgrades aren't expected to work with SNO. If an upgrade is needed, your system will need a redeployment.": "OpenShift in-place upgrades are not expected to work with SNO. If an upgrade is needed, your system to be redeployed.", diff --git a/libs/types/assisted-installer-service.d.ts b/libs/types/assisted-installer-service.d.ts index 5ccfc5ebaf..6a40357b22 100644 --- a/libs/types/assisted-installer-service.d.ts +++ b/libs/types/assisted-installer-service.d.ts @@ -182,17 +182,17 @@ export interface Cluster { * Status of the OpenShift cluster. */ status: - | 'insufficient' - | 'ready' - | 'error' - | 'preparing-for-installation' - | 'pending-for-input' - | 'installing' - | 'finalizing' - | 'installed' - | 'adding-hosts' - | 'cancelled' - | 'installing-pending-user-action'; + | 'insufficient' + | 'ready' + | 'error' + | 'preparing-for-installation' + | 'pending-for-input' + | 'installing' + | 'finalizing' + | 'installed' + | 'adding-hosts' + | 'cancelled' + | 'installing-pending-user-action'; /** * Additional information pertaining to the status of the OpenShift cluster. */ @@ -967,6 +967,7 @@ export type FeatureSupportLevelId = | 'SINGLE_NODE_EXPANSION' | 'LVM' | 'ODF' + | 'OAI' | 'LSO' | 'CNV' | 'MCE' @@ -1050,34 +1051,34 @@ export interface Host { */ infraEnvId?: string; // uuid status: - | 'discovering' - | 'known' - | 'disconnected' - | 'insufficient' - | 'disabled' - | 'preparing-for-installation' - | 'preparing-failed' - | 'preparing-successful' - | 'pending-for-input' - | 'installing' - | 'installing-in-progress' - | 'installing-pending-user-action' - | 'resetting-pending-user-action' - | 'installed' - | 'error' - | 'resetting' - | 'added-to-existing-cluster' - | 'cancelled' - | 'binding' - | 'unbinding' - | 'unbinding-pending-user-action' - | 'known-unbound' - | 'disconnected-unbound' - | 'insufficient-unbound' - | 'disabled-unbound' - | 'discovering-unbound' - | 'reclaiming' - | 'reclaiming-rebooting'; + | 'discovering' + | 'known' + | 'disconnected' + | 'insufficient' + | 'disabled' + | 'preparing-for-installation' + | 'preparing-failed' + | 'preparing-successful' + | 'pending-for-input' + | 'installing' + | 'installing-in-progress' + | 'installing-pending-user-action' + | 'resetting-pending-user-action' + | 'installed' + | 'error' + | 'resetting' + | 'added-to-existing-cluster' + | 'cancelled' + | 'binding' + | 'unbinding' + | 'unbinding-pending-user-action' + | 'known-unbound' + | 'disconnected-unbound' + | 'insufficient-unbound' + | 'disabled-unbound' + | 'discovering-unbound' + | 'reclaiming' + | 'reclaiming-rebooting'; statusInfo: string; /** * JSON-formatted string containing the validation results for each validation id grouped by category (network, hardware, etc.) @@ -1257,34 +1258,34 @@ export interface HostRegistrationResponse { */ infraEnvId?: string; // uuid status: - | 'discovering' - | 'known' - | 'disconnected' - | 'insufficient' - | 'disabled' - | 'preparing-for-installation' - | 'preparing-failed' - | 'preparing-successful' - | 'pending-for-input' - | 'installing' - | 'installing-in-progress' - | 'installing-pending-user-action' - | 'resetting-pending-user-action' - | 'installed' - | 'error' - | 'resetting' - | 'added-to-existing-cluster' - | 'cancelled' - | 'binding' - | 'unbinding' - | 'unbinding-pending-user-action' - | 'known-unbound' - | 'disconnected-unbound' - | 'insufficient-unbound' - | 'disabled-unbound' - | 'discovering-unbound' - | 'reclaiming' - | 'reclaiming-rebooting'; + | 'discovering' + | 'known' + | 'disconnected' + | 'insufficient' + | 'disabled' + | 'preparing-for-installation' + | 'preparing-failed' + | 'preparing-successful' + | 'pending-for-input' + | 'installing' + | 'installing-in-progress' + | 'installing-pending-user-action' + | 'resetting-pending-user-action' + | 'installed' + | 'error' + | 'resetting' + | 'added-to-existing-cluster' + | 'cancelled' + | 'binding' + | 'unbinding' + | 'unbinding-pending-user-action' + | 'known-unbound' + | 'disconnected-unbound' + | 'insufficient-unbound' + | 'disabled-unbound' + | 'discovering-unbound' + | 'reclaiming' + | 'reclaiming-rebooting'; statusInfo: string; /** * JSON-formatted string containing the validation results for each validation id grouped by category (network, hardware, etc.) diff --git a/libs/ui-lib/lib/common/config/constants.ts b/libs/ui-lib/lib/common/config/constants.ts index f0cd1a927e..3e7f872b52 100644 --- a/libs/ui-lib/lib/common/config/constants.ts +++ b/libs/ui-lib/lib/common/config/constants.ts @@ -267,6 +267,7 @@ export const OPERATOR_NAME_ODF = 'odf'; export const OPERATOR_NAME_LVM = 'lvm'; export const OPERATOR_NAME_LVMS = 'lvms'; export const OPERATOR_NAME_MCE = 'mce'; +export const OPERATOR_NAME_OAI = 'oai'; const OperatorNames = [ OPERATOR_NAME_CNV, @@ -275,6 +276,7 @@ const OperatorNames = [ OPERATOR_NAME_LVM, OPERATOR_NAME_LVMS, OPERATOR_NAME_MCE, + OPERATOR_NAME_OAI, ]; export const ExposedOperatorNames = [ OPERATOR_NAME_CNV, @@ -282,6 +284,7 @@ export const ExposedOperatorNames = [ OPERATOR_NAME_LVM, OPERATOR_NAME_LVMS, OPERATOR_NAME_MCE, + OPERATOR_NAME_OAI, ]; export type OperatorName = (typeof OperatorNames)[number]; @@ -301,6 +304,7 @@ export const operatorLabelsCim = ( [OPERATOR_NAME_LVM]: useLVMS ? t('ai:Logical Volume Manager Storage') : t('ai:Logical Volume Manager'), + [OPERATOR_NAME_OAI]: t('ai:OpenShift AI'), }; }; @@ -317,6 +321,7 @@ export const operatorLabels = ( ? t('ai:Logical Volume Manager Storage') : t('ai:Logical Volume Manager'), [OPERATOR_NAME_MCE]: t('ai:Multicluster engine'), + [OPERATOR_NAME_OAI]: t('ai:OpenShift AI'), }; }; diff --git a/libs/ui-lib/lib/common/config/docs_links.ts b/libs/ui-lib/lib/common/config/docs_links.ts index f21fd0ec55..e3463a6644 100644 --- a/libs/ui-lib/lib/common/config/docs_links.ts +++ b/libs/ui-lib/lib/common/config/docs_links.ts @@ -75,10 +75,15 @@ export const HOST_REQUIREMENTS_LINK = 'https://access.redhat.com/solutions/48856 export const ODF_REQUIREMENTS_LINK = 'https://docs.redhat.com/en/documentation/red_hat_openshift_data_foundation'; +export const OAI_REQUIREMENTS_LINK = + 'https://docs.redhat.com/en/documentation/red_hat_openshift_data_foundation'; + export const CNV_LINK = 'https://cloud.redhat.com/learn/topics/virtualization/'; export const ODF_LINK = 'https://www.redhat.com/en/resources/openshift-data-foundation-datasheet'; +export const OAI_LINK = 'https://www.redhat.com/en/technologies/cloud-computing/openshift/openshift-ai'; + export const getMceDocsLink = (ocpVersion?: string) => `https://docs.redhat.com/en/documentation/openshift_container_platform/${getShortOpenshiftVersion( ocpVersion, diff --git a/libs/ui-lib/lib/common/types/clusters.ts b/libs/ui-lib/lib/common/types/clusters.ts index 32f32b0f3b..40845da42c 100644 --- a/libs/ui-lib/lib/common/types/clusters.ts +++ b/libs/ui-lib/lib/common/types/clusters.ts @@ -63,6 +63,7 @@ export type OperatorsValues = V2ClusterUpdateParams & { useOdfLogicalVolumeManager: boolean; useContainerNativeVirtualization: boolean; useMultiClusterEngine: boolean; + useOpenShiftAI: boolean; }; export type SupportedPlatformType = Extract; diff --git a/libs/ui-lib/lib/ocm/components/clusterConfiguration/operators/OaiCheckbox.tsx b/libs/ui-lib/lib/ocm/components/clusterConfiguration/operators/OaiCheckbox.tsx new file mode 100644 index 0000000000..a945db6367 --- /dev/null +++ b/libs/ui-lib/lib/ocm/components/clusterConfiguration/operators/OaiCheckbox.tsx @@ -0,0 +1,70 @@ +import React, { useState } from 'react'; +import { FormGroup, HelperText, HelperTextItem, Tooltip } from '@patternfly/react-core'; +import { ExternalLinkAltIcon } from '@patternfly/react-icons/dist/js/icons/external-link-alt-icon'; +import { + getFieldId, + PopoverIcon, + OAI_REQUIREMENTS_LINK, + OAI_LINK, + OperatorsValues, +} from '../../../../common'; +import { OcmCheckboxField } from '../../ui/OcmFormFields'; +import { useNewFeatureSupportLevel } from '../../../../common/components/newFeatureSupportLevels'; +import { useFormikContext } from 'formik'; + +const OAI_FIELD_NAME = 'useOpenShiftAI'; + +const OdfLabel = ({ disabledReason }: { disabledReason?: string }) => ( + <> + + + Learn more about the requirements for OpenShift AI . + + } + /> + +); + +const OdfHelperText = () => { + return ( + + + Train, serve, monitor and manage AI/ML models and applications.{' '} + + {'Learn more'} + + + + ); +}; + +const OaiCheckbox = () => { + const featureSupportLevelContext = useNewFeatureSupportLevel(); + const { values } = useFormikContext(); + const fieldId = getFieldId(OAI_FIELD_NAME, 'input'); + const [disabledReason, setDisabledReason] = useState(); + + React.useEffect(() => { + let disabledReason = featureSupportLevelContext.getFeatureDisabledReason('OAI'); + setDisabledReason(disabledReason); + }, [values, featureSupportLevelContext]); + + return ( + + } + isDisabled={!!disabledReason} + helperText={} + /> + + ); +}; + +export default OaiCheckbox; diff --git a/libs/ui-lib/lib/ocm/components/clusterWizard/Operators.tsx b/libs/ui-lib/lib/ocm/components/clusterWizard/Operators.tsx index 7eae861628..428f91b8b1 100644 --- a/libs/ui-lib/lib/ocm/components/clusterWizard/Operators.tsx +++ b/libs/ui-lib/lib/ocm/components/clusterWizard/Operators.tsx @@ -9,6 +9,7 @@ import { OPERATOR_NAME_LVM, OPERATOR_NAME_MCE, OPERATOR_NAME_ODF, + OPERATOR_NAME_OAI, OperatorsValues, selectMonitoredOperators, useAlerts, @@ -34,6 +35,7 @@ export const getOperatorsInitialValues = ( useOdfLogicalVolumeManager: isOperatorEnabled([OPERATOR_NAME_LVM]), useContainerNativeVirtualization: isOperatorEnabled([OPERATOR_NAME_CNV]), useMultiClusterEngine: isOperatorEnabled([OPERATOR_NAME_MCE]), + useOpenShiftAI: isOperatorEnabled([OPERATOR_NAME_OAI]) }; }; diff --git a/libs/ui-lib/lib/ocm/components/clusterWizard/OperatorsStep.tsx b/libs/ui-lib/lib/ocm/components/clusterWizard/OperatorsStep.tsx index 025761cc1b..084c946c6f 100644 --- a/libs/ui-lib/lib/ocm/components/clusterWizard/OperatorsStep.tsx +++ b/libs/ui-lib/lib/ocm/components/clusterWizard/OperatorsStep.tsx @@ -4,6 +4,7 @@ import { Stack, StackItem } from '@patternfly/react-core'; import { ClusterOperatorProps, ClusterWizardStepHeader } from '../../../common'; import CnvCheckbox from '../clusterConfiguration/operators/CnvCheckbox'; import OdfCheckbox from '../clusterConfiguration/operators/OdfCheckbox'; +import OaiCheckbox from '../clusterConfiguration/operators/OaiCheckbox'; import LvmCheckbox from '../clusterConfiguration/operators/LvmCheckbox'; import MceCheckbox from '../clusterConfiguration/operators/MceCheckbox'; import { selectIsCurrentClusterSNO } from '../../store/slices/current-cluster/selectors'; @@ -38,6 +39,9 @@ export const OperatorsStep = (props: ClusterOperatorProps) => { + + + ) : ( {isSNO ? : } diff --git a/libs/ui-lib/lib/ocm/components/featureSupportLevels/featureStateUtils.ts b/libs/ui-lib/lib/ocm/components/featureSupportLevels/featureStateUtils.ts index 9b2bae04dc..82d4b30ac0 100644 --- a/libs/ui-lib/lib/ocm/components/featureSupportLevels/featureStateUtils.ts +++ b/libs/ui-lib/lib/ocm/components/featureSupportLevels/featureStateUtils.ts @@ -18,6 +18,7 @@ const CNV_OPERATOR_LABEL = 'Openshift Virtualization'; const LVMS_OPERATOR_LABEL = 'Logical Volume Manager Storage'; const LVM_OPERATOR_LABEL = 'Logical Volume Manager'; const ODF_OPERATOR_LABEL = 'OpenShift Data Foundation'; +const OAI_OPERATOR_LABEL = 'OpenShift AI'; export const clusterExistsReason = 'This option is not editable after the draft cluster is created'; @@ -72,6 +73,21 @@ const getOdfDisabledReason = ( return undefined; } + if (!isSupported) { + return `The installer cannot currently enable ${ODF_OPERATOR_LABEL} with the selected OpenShift version, but it can be enabled later through the OpenShift Console once the installation is complete.`; + } + return undefined; +}; + +const getOaiDisabledReason = ( + cluster: Cluster | undefined, + activeFeatureConfiguration: ActiveFeatureConfiguration | undefined, + isSupported: boolean, +) => { + if (!cluster) { + return undefined; + } + const isArm = activeFeatureConfiguration?.underlyingCpuArchitecture === CpuArchitecture.ARM; if (isArm && isSNO(cluster)) { return `${ODF_OPERATOR_LABEL} is not available when using Single Node OpenShift or ARM CPU architecture.`; @@ -88,6 +104,7 @@ const getOdfDisabledReason = ( return undefined; }; + const getCnvDisabledReason = ( activeFeatureConfiguration: ActiveFeatureConfiguration, isSupported: boolean, @@ -105,11 +122,10 @@ const getCnvDisabledReason = ( activeFeatureConfiguration.underlyingCpuArchitecture as SupportedCpuArchitecture ].label; - return `${CNV_OPERATOR_LABEL} is not available when ${ - cpuArchitectureLabel - ? cpuArchitectureLabel - : activeFeatureConfiguration.underlyingCpuArchitecture - } CPU architecture is selected.`; + return `${CNV_OPERATOR_LABEL} is not available when ${cpuArchitectureLabel + ? cpuArchitectureLabel + : activeFeatureConfiguration.underlyingCpuArchitecture + } CPU architecture is selected.`; } else { return undefined; } @@ -189,9 +205,8 @@ export const getNewFeatureDisabledReason = ( return getNetworkTypeSelectionDisabledReason(cluster); } case 'CLUSTER_MANAGED_NETWORKING': { - return `Cluster-managed networking is not supported when using ${ - platformType ? ExternalPlatformLabels[platformType] : '' - }`; + return `Cluster-managed networking is not supported when using ${platformType ? ExternalPlatformLabels[platformType] : '' + }`; } case 'EXTERNAL_PLATFORM_OCI': { return getOciDisabledReason(cpuArchitecture, isSupported); @@ -216,9 +231,8 @@ export const getNewFeatureDisabledReason = ( } case 'USER_MANAGED_NETWORKING': { if (!isSupported) { - return `User-Managed Networking is not supported when using ${ - platformType ? ExternalPlatformLabels[platformType] : '' - }`; + return `User-Managed Networking is not supported when using ${platformType ? ExternalPlatformLabels[platformType] : '' + }`; } } default: { @@ -248,4 +262,4 @@ export const getLvmsIncompatibleWithOdfReason = (operatorValues: OperatorsValues return mustDisableLvms ? `Currently, you cannot install ${LVMS_OPERATOR_LABEL} operator at the same time as ${ODF_OPERATOR_LABEL} operator.` : undefined; -}; +}; \ No newline at end of file diff --git a/libs/ui-lib/lib/ocm/services/OperatorsService.tsx b/libs/ui-lib/lib/ocm/services/OperatorsService.tsx index 7878733469..5e91754753 100644 --- a/libs/ui-lib/lib/ocm/services/OperatorsService.tsx +++ b/libs/ui-lib/lib/ocm/services/OperatorsService.tsx @@ -6,6 +6,7 @@ import { OPERATOR_NAME_LVM, OperatorName, OPERATOR_NAME_MCE, + OPERATOR_NAME_OAI, } from '../../common'; import { getOlmOperatorCreateParamsByName } from '../components/clusters/utils'; import { getKeys } from '../../common/utils'; @@ -35,6 +36,7 @@ const OperatorsService = { setOperator(OPERATOR_NAME_CNV, values.useContainerNativeVirtualization); setOperator(OPERATOR_NAME_ODF, values.useOpenShiftDataFoundation); setOperator(OPERATOR_NAME_MCE, values.useMultiClusterEngine); + setOperator(OPERATOR_NAME_OAI, values.useOpenShiftAI); // TODO: remove following once the LSO option is exposed to the user if (!hasActiveOperators(values)) {