diff --git a/frontend/packages/metal3-plugin/src/components/host-status.tsx b/frontend/packages/metal3-plugin/src/components/host-status.tsx
new file mode 100644
index 00000000000..c4cebe967b8
--- /dev/null
+++ b/frontend/packages/metal3-plugin/src/components/host-status.tsx
@@ -0,0 +1,59 @@
+import * as React from 'react';
+import { Button } from 'patternfly-react';
+
+import { K8sResourceKind } from '@console/internal/module/k8s';
+import { StatusIconAndText } from '@console/internal/components/utils/status-icon';
+import { RequireCreatePermission } from '@console/internal/components/utils';
+import { getHostStatus } from '../utils/host-status';
+
+import {
+ HOST_STATUS_DISCOVERED,
+ HOST_PROGRESS_STATES,
+ HOST_ERROR_STATES,
+ HOST_SUCCESS_STATES,
+} from '../constants';
+import { BaremetalHostModel } from '../models';
+
+// TODO(jtomasek): Update this with onClick handler once add discovered host functionality
+// is available
+export const AddDiscoveredHostButton: React.FC<{ host: K8sResourceKind }> = (
+ { host }, // eslint-disable-line @typescript-eslint/no-unused-vars
+) => {
+ const {
+ metadata: { namespace },
+ } = host;
+
+ return (
+
+
+
+ );
+};
+
+type BaremetalHostStatusProps = {
+ host: K8sResourceKind;
+ machine?: K8sResourceKind;
+ node?: K8sResourceKind;
+};
+
+const BaremetalHostStatus = ({ host }: BaremetalHostStatusProps) => {
+ const hostStatus = getHostStatus(host);
+ const { status, title } = hostStatus;
+
+ switch (true) {
+ case status === HOST_STATUS_DISCOVERED:
+ return ;
+ case HOST_PROGRESS_STATES.includes(status):
+ return ;
+ case HOST_SUCCESS_STATES.includes(status):
+ return ;
+ case HOST_ERROR_STATES.includes(status):
+ return ;
+ default:
+ return ;
+ }
+};
+
+export default BaremetalHostStatus;
diff --git a/frontend/packages/metal3-plugin/src/components/host.tsx b/frontend/packages/metal3-plugin/src/components/host.tsx
index ee99dc115e9..1b1e3aa30fa 100644
--- a/frontend/packages/metal3-plugin/src/components/host.tsx
+++ b/frontend/packages/metal3-plugin/src/components/host.tsx
@@ -19,9 +19,10 @@ import { BaremetalHostModel } from '../models';
import { getHostBMCAddress, getHostMachine } from '../selectors';
import { BaremetalHostRole } from './host-role';
import MachineCell from './machine-cell';
+import BaremetalHostStatus from './host-status';
const tableColumnClasses = [
- classNames('col-lg-5', 'col-md-8', 'col-sm-12', 'col-xs-12'),
+ classNames('col-lg-3', 'col-md-4', 'col-sm-12', 'col-xs-12'),
classNames('col-lg-2', 'col-md-4', 'col-sm-6', 'hidden-xs'),
classNames('col-lg-3', 'col-md-4', 'hidden-sm', 'hidden-xs'),
classNames('col-lg-2', 'hidden-md', 'hidden-sm', 'hidden-xs'),
@@ -36,6 +37,13 @@ const HostsTableHeader = () => [
transforms: [sortable],
props: { className: tableColumnClasses[0] },
},
+ {
+ title: 'Status',
+ // TODO(jtomasek): enable this once it is possible to pass sort function
+ // sortFunc: getSimpleHostStatus,
+ // transforms: [sortable],
+ props: { className: tableColumnClasses[1] },
+ },
{
title: 'Machine',
sortField: 'spec.machineRef.name',
@@ -72,7 +80,7 @@ const HostsTableRow: React.FC = ({ obj: host, index, key, st
const namespace = getNamespace(host);
// const machineName = getHostMachineName(host);
const address = getHostBMCAddress(host);
- const { machine } = host;
+ const { machine, node } = host;
// TODO(jtomasek): other resource references will be updated as a subsequent change
// const machineResource = {
@@ -102,9 +110,9 @@ const HostsTableRow: React.FC = ({ obj: host, index, key, st
namespace={namespace}
/>
- {/*
-
- */}
+
+
+
@@ -120,13 +128,7 @@ const HostsTableRow: React.FC = ({ obj: host, index, key, st
};
const HostList: React.FC> = (props) => (
-
+
);
// TODO(jtomasek): re-enable filters once the extension point for list.tsx is in place
diff --git a/frontend/packages/metal3-plugin/src/components/machine-cell.tsx b/frontend/packages/metal3-plugin/src/components/machine-cell.tsx
index 75cfd60883a..d0ab62cacdb 100644
--- a/frontend/packages/metal3-plugin/src/components/machine-cell.tsx
+++ b/frontend/packages/metal3-plugin/src/components/machine-cell.tsx
@@ -1,13 +1,17 @@
import * as React from 'react';
-// import { Link } from 'react-router-dom';
-// import { Icon } from 'patternfly-react';
+import { Link } from 'react-router-dom';
import { DASH } from '@console/shared';
import { MachineModel } from '@console/internal/models';
-import { ResourceLink /* , RequireCreatePermission */ } from '@console/internal/components/utils';
+import {
+ ResourceLink,
+ RequireCreatePermission,
+ StatusIconAndText,
+} from '@console/internal/components/utils';
import { referenceForModel, K8sResourceKind } from '@console/internal/module/k8s';
import { getHostMachineName } from '../selectors';
+import { canHostAddMachine } from '../utils/host-status';
interface MachineCellProps {
host: K8sResourceKind;
@@ -30,21 +34,17 @@ const MachineCell: React.FC = ({ host }) => {
/>
);
}
- // TODO(jtomasek): Re-enable this once host status is added
- // if (canHostAddMachine(host)) {
- // const ns = namespace || 'default';
- // const href = `/k8s/ns/${ns}/${referenceForModel(MachineModel)}/~new`;
- // return (
- //
- //
- //
- //
- // Add machine
- //
- //
- //
- // );
- // }
+ if (canHostAddMachine(host)) {
+ const ns = namespace || 'default';
+ const href = `/k8s/ns/${ns}/${referenceForModel(MachineModel)}/~new`;
+ return (
+
+
+
+
+
+ );
+ }
return <>{DASH}>;
};
diff --git a/frontend/packages/metal3-plugin/src/constants.ts b/frontend/packages/metal3-plugin/src/constants.ts
new file mode 100644
index 00000000000..c500be2e2c7
--- /dev/null
+++ b/frontend/packages/metal3-plugin/src/constants.ts
@@ -0,0 +1,74 @@
+export const HOST_STATUS_READY = 'ready';
+export const HOST_STATUS_DISCOVERED = 'discovered';
+export const HOST_STATUS_OK = 'OK';
+export const HOST_STATUS_EXTERNALLY_PROVISIONED = 'externally provisioned';
+export const HOST_STATUS_PROVISIONED = 'provisioned';
+export const HOST_STATUS_DEPROVISIONED = 'deprovisioned';
+export const HOST_STATUS_REGISTERING = 'registering';
+export const HOST_STATUS_INSPECTING = 'inspecting';
+export const HOST_STATUS_PREPARING_TO_PROVISION = 'preparing to provision';
+export const HOST_STATUS_PROVISIONING = 'provisioning';
+export const HOST_STATUS_DEPROVISIONING = 'deprovisioning';
+export const HOST_STATUS_MAKING_HOST_AVAILABLE = 'making host available';
+export const HOST_STATUS_MATCH_PROFILE = 'match profile';
+export const HOST_STATUS_STARTING_MAINTENANCE = 'starting maintenance';
+export const HOST_STATUS_STOPPING_MAINTENANCE = 'stopping maintenance';
+export const HOST_STATUS_MAINTENANCE = 'maintenance';
+export const HOST_STATUS_VALIDATION_ERROR = 'validation error';
+export const HOST_STATUS_REGISTRATION_ERROR = 'registration error';
+export const HOST_STATUS_PROVISIONING_ERROR = 'provisioning error';
+export const HOST_STATUS_POWER_MANAGEMENT_ERROR = 'power management error';
+
+export const HOST_STATUS_TITLES = {
+ [HOST_STATUS_READY]: 'Ready',
+ [HOST_STATUS_DISCOVERED]: 'Discovered',
+ [HOST_STATUS_OK]: 'OK',
+ [HOST_STATUS_PROVISIONED]: 'Provisioned',
+ [HOST_STATUS_EXTERNALLY_PROVISIONED]: 'Externally provisioned',
+ [HOST_STATUS_DEPROVISIONED]: 'Deprovisioned',
+ [HOST_STATUS_REGISTERING]: 'Registering',
+ [HOST_STATUS_INSPECTING]: 'Inspecting',
+ [HOST_STATUS_PREPARING_TO_PROVISION]: 'Preparing to provision',
+ [HOST_STATUS_PROVISIONING]: 'Provisioning',
+ [HOST_STATUS_DEPROVISIONING]: 'Deprovisioning',
+ [HOST_STATUS_MAKING_HOST_AVAILABLE]: 'Making host available',
+ [HOST_STATUS_VALIDATION_ERROR]: 'Validation Error(s)',
+ [HOST_STATUS_REGISTRATION_ERROR]: 'Registration Error',
+ [HOST_STATUS_PROVISIONING_ERROR]: 'Provisioning Error',
+ [HOST_STATUS_POWER_MANAGEMENT_ERROR]: 'Power Management Error',
+ [HOST_STATUS_STARTING_MAINTENANCE]: 'Starting maintenance',
+ [HOST_STATUS_STOPPING_MAINTENANCE]: 'Stopping maintenance',
+ [HOST_STATUS_MAINTENANCE]: 'Maintenance',
+ [HOST_STATUS_MATCH_PROFILE]: 'Matching profile',
+};
+
+export const HOST_ERROR_STATES = [
+ HOST_STATUS_REGISTRATION_ERROR,
+ HOST_STATUS_PROVISIONING_ERROR,
+ HOST_STATUS_VALIDATION_ERROR,
+ HOST_STATUS_POWER_MANAGEMENT_ERROR,
+];
+
+export const HOST_WARN_STATES = [];
+
+export const HOST_PROGRESS_STATES = [
+ HOST_STATUS_INSPECTING,
+ HOST_STATUS_PREPARING_TO_PROVISION,
+ HOST_STATUS_PREPARING_TO_PROVISION,
+ HOST_STATUS_PROVISIONING,
+ HOST_STATUS_DEPROVISIONING,
+ HOST_STATUS_MAKING_HOST_AVAILABLE,
+ HOST_STATUS_REGISTERING,
+ HOST_STATUS_STARTING_MAINTENANCE,
+ HOST_STATUS_STOPPING_MAINTENANCE,
+ HOST_STATUS_MATCH_PROFILE,
+];
+
+export const HOST_SUCCESS_STATES = [
+ HOST_STATUS_READY,
+ HOST_STATUS_DISCOVERED,
+ HOST_STATUS_OK,
+ HOST_STATUS_PROVISIONED,
+ HOST_STATUS_EXTERNALLY_PROVISIONED,
+ HOST_STATUS_DEPROVISIONED,
+];
diff --git a/frontend/packages/metal3-plugin/src/selectors/index.ts b/frontend/packages/metal3-plugin/src/selectors/index.ts
index 275fbd56e1f..f6de8701870 100644
--- a/frontend/packages/metal3-plugin/src/selectors/index.ts
+++ b/frontend/packages/metal3-plugin/src/selectors/index.ts
@@ -3,19 +3,25 @@ import * as _ from 'lodash';
import { K8sResourceKind, MachineKind } from '@console/internal/module/k8s';
import { getName } from '@console/shared';
-export const getOperationalStatus = (host) => _.get(host, 'status.operationalStatus');
-export const getProvisioningState = (host) => _.get(host, 'status.provisioning.state');
-export const getHostMachineName = (host) => _.get(host, 'spec.machineRef.name');
-export const getHostBMCAddress = (host) => _.get(host, 'spec.bmc.address');
-export const isHostOnline = (host) => _.get(host, 'spec.online', false);
-export const getHostNICs = (host) => _.get(host, 'status.hardware.nics', []);
-export const getHostStorage = (host) => _.get(host, 'status.hardware.storage', []);
-export const getHostCPU = (host) => _.get(host, 'status.hardware.cpu', {});
-export const getHostRAM = (host) => _.get(host, 'status.hardware.ramGiB');
-export const getHostErrorMessage = (host) => _.get(host, 'status.errorMessage');
-export const getHostDescription = (host) => _.get(host, 'spec.description', '');
-export const isHostPoweredOn = (host) => _.get(host, 'status.poweredOn', false);
-export const getHostTotalStorageCapacity = (host) =>
- _.reduce(getHostStorage(host), (sum, disk) => sum + disk.sizeGiB, 0);
+type BaremetalHostDisk = {
+ sizeGiB: number;
+};
+
+export const getHostOperationalStatus = (host: K8sResourceKind) =>
+ _.get(host, 'status.operationalStatus');
+export const getHostProvisioningState = (host: K8sResourceKind) =>
+ _.get(host, 'status.provisioning.state');
+export const getHostMachineName = (host: K8sResourceKind) => _.get(host, 'spec.machineRef.name');
+export const getHostBMCAddress = (host: K8sResourceKind) => _.get(host, 'spec.bmc.address');
+export const isHostOnline = (host: K8sResourceKind) => _.get(host, 'spec.online', false);
+export const getHostNICs = (host: K8sResourceKind) => _.get(host, 'status.hardware.nics', []);
+export const getHostStorage = (host: K8sResourceKind) => _.get(host, 'status.hardware.storage', []);
+export const getHostCPU = (host: K8sResourceKind) => _.get(host, 'status.hardware.cpu', {});
+export const getHostRAM = (host: K8sResourceKind) => _.get(host, 'status.hardware.ramGiB');
+export const getHostErrorMessage = (host: K8sResourceKind) => _.get(host, 'status.errorMessage');
+export const getHostDescription = (host: K8sResourceKind) => _.get(host, 'spec.description', '');
+export const isHostPoweredOn = (host: K8sResourceKind) => _.get(host, 'status.poweredOn', false);
+export const getHostTotalStorageCapacity = (host: K8sResourceKind) =>
+ _.reduce(getHostStorage(host), (sum: number, disk: BaremetalHostDisk) => sum + disk.sizeGiB, 0);
export const getHostMachine = (host: K8sResourceKind, machines: MachineKind[]) =>
- machines.find((machine) => getHostMachineName(host) === getName(machine));
+ machines.find((machine: MachineKind) => getHostMachineName(host) === getName(machine));
diff --git a/frontend/packages/metal3-plugin/src/utils/host-status.ts b/frontend/packages/metal3-plugin/src/utils/host-status.ts
new file mode 100644
index 00000000000..4dbf298aa45
--- /dev/null
+++ b/frontend/packages/metal3-plugin/src/utils/host-status.ts
@@ -0,0 +1,59 @@
+import { K8sResourceKind } from '@console/internal/module/k8s';
+
+import {
+ getHostOperationalStatus,
+ getHostProvisioningState,
+ getHostErrorMessage,
+ // isNodeUnschedulable,
+} from '../selectors';
+
+import {
+ HOST_STATUS_TITLES,
+ HOST_STATUS_READY,
+ // HOST_STATUS_STARTING_MAINTENANCE,
+} from '../constants';
+
+// import { NOT_HANDLED } from '../common';
+
+// const isStartingMaintenance = (node) => {
+// if (isNodeUnschedulable(node)) {
+// return {
+// status: HOST_STATUS_STARTING_MAINTENANCE,
+// text: HOST_STATUS_TITLES[HOST_STATUS_STARTING_MAINTENANCE],
+// };
+// }
+// return NOT_HANDLED;
+// };
+
+const getBaremetalHostStatus = (host: K8sResourceKind) => {
+ const operationalStatus = getHostOperationalStatus(host);
+ const provisioningState = getHostProvisioningState(host);
+
+ const hostStatus = provisioningState || operationalStatus || undefined;
+ return {
+ status: hostStatus,
+ title: HOST_STATUS_TITLES[hostStatus] || hostStatus,
+ errorMessage: getHostErrorMessage(host),
+ };
+};
+
+export const getHostStatus = (
+ host: K8sResourceKind,
+ // machine?: MachineKind,
+ // node?: NodeKind,
+) => {
+ // TODO(jtomasek): make this more robust by including node/machine status
+ // return isStartingMaintenance(node) || getBaremetalHostStatus(host);
+ return getBaremetalHostStatus(host);
+};
+
+export const getSimpleHostStatus = (
+ host: K8sResourceKind,
+ // machine?: MachineKind,
+ // node?: NodeKind,
+): string => getHostStatus(host).status;
+
+export const canHostAddMachine = (host: K8sResourceKind): boolean =>
+ [HOST_STATUS_READY].includes(getSimpleHostStatus(host));
+// export const canHostStartMaintenance = (hostNode: NodeKind) => hostNode && !isNodeUnschedulable(hostNode);
+// export const canHostStopMaintenance = (hostNode: NodeKind) => isNodeUnschedulable(hostNode);