import { ReactElement, useMemo } from 'react'; import FlexBox from '../FlexBox'; import Grid from '../Grid'; import InputWithRef from '../InputWithRef'; import MessageBox from '../MessageBox'; import OutlinedInputWithLabel from '../OutlinedInputWithLabel'; import { InnerPanel, InnerPanelBody, InnerPanelHeader } from '../Panels'; import SwitchWithLabel from '../SwitchWithLabel'; import { buildIPAddressTestBatch, buildPeacefulStringTestBatch, } from '../../lib/test_input'; import { BodyText } from '../Text'; const INPUT_ID_PREFIX_AN_HOST = 'an-host-input'; const INPUT_CELL_ID_PREFIX_AH = `${INPUT_ID_PREFIX_AN_HOST}-cell`; const INPUT_LABEL_AH_IPMI_IP = 'IPMI IP'; const MAP_TO_AH_INPUT_HANDLER: MapToManifestFormInputHandler = { fence: (container, input) => { const { dataset: { hostId = '', fenceId = '', fenceName = '' }, value: fencePort, } = input; const { hostConfig: { hosts: { [hostId]: host }, }, } = container; const { fences = {} } = host; fences[fenceId] = { fenceName, fencePort, }; host.fences = fences; }, host: (container, input) => { const { dataset: { hostId = '', hostNumber: rawHostNumber = '', hostType = '' }, } = input; const hostNumber = Number.parseInt(rawHostNumber, 10); container.hostConfig.hosts[hostId] = { hostNumber, hostType, }; }, ipmi: (container, input) => { const { dataset: { hostId = '' }, value: ipmiIp, } = input; const { hostConfig: { hosts: { [hostId]: host }, }, } = container; host.ipmiIp = ipmiIp; }, network: (container, input) => { const { dataset: { hostId = '', networkId = '', networkNumber: rawNetworkNumber = '', networkType = '', }, value: networkIp, } = input; const { hostConfig: { hosts: { [hostId]: host }, }, } = container; const { networks = {} } = host; const networkNumber = Number.parseInt(rawNetworkNumber, 10); networks[networkId] = { networkIp, networkNumber, networkType, }; host.networks = networks; }, ups: (container, input) => { const { checked: isUsed, dataset: { hostId = '', upsId = '', upsName = '' }, } = input; const { hostConfig: { hosts: { [hostId]: host }, }, } = container; const { upses = {} } = host; upses[upsId] = { isUsed, upsName, }; host.upses = upses; }, }; const GRID_COLUMNS = { xs: 1, sm: 2, md: 3 }; const GRID_SPACING = '1em'; const buildInputIdAHFencePort = (hostId: string, fenceId: string): string => `${INPUT_ID_PREFIX_AN_HOST}-${hostId}-${fenceId}-port`; const buildInputIdAHIpmiIp = (hostId: string): string => `${INPUT_ID_PREFIX_AN_HOST}-${hostId}-ipmi-ip`; const buildInputIdAHNetworkIp = (hostId: string, networkId: string): string => `${INPUT_ID_PREFIX_AN_HOST}-${hostId}-${networkId}-ip`; const buildInputIdAHUpsPowerHost = (hostId: string, upsId: string): string => `${INPUT_ID_PREFIX_AN_HOST}-${hostId}-${upsId}-power-host`; const AnHostInputGroup = ({ formUtils: { buildFinishInputTestBatchFunction, buildInputFirstRenderFunction, buildInputUnmountFunction, setMessage, }, hostId, hostNumber, hostType, previous: { fences: fenceList = {}, ipmiIp: previousIpmiIp, networks: networkList = {}, upses: upsList = {}, } = {}, // Props that depend on others. hostLabel = `${hostType.replace('node', 'subnode')} ${hostNumber}`, }: AnHostInputGroupProps): ReactElement => { const fenceListEntries = useMemo( () => Object.entries(fenceList), [fenceList], ); const networkListEntries = useMemo( () => Object.entries(networkList), [networkList], ); const upsListEntries = useMemo(() => Object.entries(upsList), [upsList]); const isShowUpsListGrid = useMemo( () => Boolean(upsListEntries.length), [upsListEntries.length], ); const inputIdAHHost = useMemo( () => `${INPUT_ID_PREFIX_AN_HOST}-${hostId}`, [hostId], ); const inputIdAHIpmiIp = useMemo(() => buildInputIdAHIpmiIp(hostId), [hostId]); const inputCellIdAHIpmiIp = useMemo( () => `${INPUT_CELL_ID_PREFIX_AH}-${hostId}-ipmi-ip`, [hostId], ); const fenceListGridLayout = useMemo( () => fenceListEntries.reduce( (previous, [fenceId, { fenceName, fencePort }]) => { const cellId = `${INPUT_CELL_ID_PREFIX_AH}-${hostId}-${fenceId}-port`; const inputId = buildInputIdAHFencePort(hostId, fenceId); const inputLabel = `Port on ${fenceName}`; previous[cellId] = { children: ( } inputTestBatch={buildPeacefulStringTestBatch( `${hostId} ${inputLabel}`, () => { setMessage(inputId); }, { onFinishBatch: buildFinishInputTestBatchFunction(inputId) }, (message) => { setMessage(inputId, { children: message }); }, )} onFirstRender={buildInputFirstRenderFunction(inputId)} /> ), }; return previous; }, {}, ), [ buildFinishInputTestBatchFunction, buildInputFirstRenderFunction, fenceListEntries, hostId, setMessage, ], ); const networkListGridLayout = useMemo( () => networkListEntries.reduce( (previous, [networkId, { networkIp, networkNumber, networkType }]) => { const cellId = `${INPUT_CELL_ID_PREFIX_AH}-${hostId}-${networkId}-ip`; const inputId = buildInputIdAHNetworkIp(hostId, networkId); const inputLabel = `${networkType.toUpperCase()} ${networkNumber} IP`; previous[cellId] = { children: ( } inputTestBatch={buildIPAddressTestBatch( `${hostId} ${inputLabel}`, () => { setMessage(inputId); }, { onFinishBatch: buildFinishInputTestBatchFunction(inputId) }, (message) => { setMessage(inputId, { children: message }); }, )} onFirstRender={buildInputFirstRenderFunction(inputId)} onUnmount={buildInputUnmountFunction(inputId)} required /> ), }; return previous; }, {}, ), [ networkListEntries, hostId, buildFinishInputTestBatchFunction, buildInputFirstRenderFunction, buildInputUnmountFunction, setMessage, ], ); const upsListGridLayout = useMemo( () => upsListEntries.reduce( (previous, [upsId, { isUsed, upsName }]) => { const cellId = `${INPUT_CELL_ID_PREFIX_AH}-${hostId}-${upsId}-power-host`; const inputId = buildInputIdAHUpsPowerHost(hostId, upsId); const inputLabel = `Uses ${upsName}`; previous[cellId] = { children: ( } valueType="boolean" /> ), }; return previous; }, {}, ), [hostId, upsListEntries], ); const upsListGrid = useMemo( () => isShowUpsListGrid && ( ), [isShowUpsListGrid, upsListGridLayout], ); return ( {hostLabel} It is recommended to provide 2 fence device ports. ), width: '100%', xs: 0, }, ...networkListGridLayout, [inputCellIdAHIpmiIp]: { children: ( } inputTestBatch={buildIPAddressTestBatch( `${hostId} ${INPUT_LABEL_AH_IPMI_IP}`, () => { setMessage(inputIdAHIpmiIp); }, { onFinishBatch: buildFinishInputTestBatchFunction(inputIdAHIpmiIp), }, (message) => { setMessage(inputIdAHIpmiIp, { children: message }); }, )} onFirstRender={buildInputFirstRenderFunction( inputIdAHIpmiIp, )} onUnmount={buildInputUnmountFunction(inputIdAHIpmiIp)} /> ), }, ...fenceListGridLayout, }} spacing={GRID_SPACING} /> {upsListGrid} ); }; export { INPUT_ID_PREFIX_AN_HOST, MAP_TO_AH_INPUT_HANDLER, buildInputIdAHFencePort, buildInputIdAHIpmiIp, buildInputIdAHNetworkIp, buildInputIdAHUpsPowerHost, }; export default AnHostInputGroup;