Skip to content

Commit

Permalink
Merge pull request #1774 from jtomasek/add-host-status-column
Browse files Browse the repository at this point in the history
Add host status column
  • Loading branch information
openshift-merge-robot authored Jul 1, 2019
2 parents 1debeda + 9dda2e8 commit 6df9297
Show file tree
Hide file tree
Showing 6 changed files with 245 additions and 45 deletions.
59 changes: 59 additions & 0 deletions frontend/packages/metal3-plugin/src/components/host-status.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<RequireCreatePermission model={BaremetalHostModel} namespace={namespace}>
<Button bsStyle="link">
<StatusIconAndText status="Add host" iconName="add-circle-o" />
</Button>
</RequireCreatePermission>
);
};

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 <AddDiscoveredHostButton host={host} />;
case HOST_PROGRESS_STATES.includes(status):
return <StatusIconAndText status={title} iconName="refresh" />;
case HOST_SUCCESS_STATES.includes(status):
return <StatusIconAndText status={title} iconName="ok" />;
case HOST_ERROR_STATES.includes(status):
return <StatusIconAndText status={title} iconName="error-circle-o" />;
default:
return <StatusIconAndText status={title} iconName="unknown" />;
}
};

export default BaremetalHostStatus;
26 changes: 14 additions & 12 deletions frontend/packages/metal3-plugin/src/components/host.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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'),
Expand All @@ -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',
Expand Down Expand Up @@ -72,7 +80,7 @@ const HostsTableRow: React.FC<HostsTableRowProps> = ({ 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 = {
Expand Down Expand Up @@ -102,9 +110,9 @@ const HostsTableRow: React.FC<HostsTableRowProps> = ({ obj: host, index, key, st
namespace={namespace}
/>
</TableData>
{/* <TableData className={tableColumnClasses[0]}>
<BaremetalHostStatus host={host} />
</TableData> */}
<TableData className={tableColumnClasses[1]}>
<BaremetalHostStatus host={host} machine={machine} node={node} />
</TableData>
<TableData className={tableColumnClasses[2]}>
<MachineCell host={host} />
</TableData>
Expand All @@ -120,13 +128,7 @@ const HostsTableRow: React.FC<HostsTableRowProps> = ({ obj: host, index, key, st
};

const HostList: React.FC<React.ComponentProps<typeof Table>> = (props) => (
<Table
{...props}
aria-label="Baremetal Hosts"
Header={HostsTableHeader}
Row={HostsTableRow}
virtualize
/>
<Table {...props} aria-label="Baremetal Hosts" Header={HostsTableHeader} Row={HostsTableRow} />
);

// TODO(jtomasek): re-enable filters once the extension point for list.tsx is in place
Expand Down
36 changes: 18 additions & 18 deletions frontend/packages/metal3-plugin/src/components/machine-cell.tsx
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -30,21 +34,17 @@ const MachineCell: React.FC<MachineCellProps> = ({ 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 (
// <RequireCreatePermission model={MachineModel} namespace={ns}>
// <Link to={href}>
// <span className="co-icon-and-text">
// <Icon type="pf" name="add-circle-o" className="co-icon-and-text__icon" />
// Add machine
// </span>
// </Link>
// </RequireCreatePermission>
// );
// }
if (canHostAddMachine(host)) {
const ns = namespace || 'default';
const href = `/k8s/ns/${ns}/${referenceForModel(MachineModel)}/~new`;
return (
<RequireCreatePermission model={MachineModel} namespace={ns}>
<Link to={href}>
<StatusIconAndText status="Add machine" iconName="add-circle-o" />
</Link>
</RequireCreatePermission>
);
}
return <>{DASH}</>;
};

Expand Down
74 changes: 74 additions & 0 deletions frontend/packages/metal3-plugin/src/constants.ts
Original file line number Diff line number Diff line change
@@ -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,
];
36 changes: 21 additions & 15 deletions frontend/packages/metal3-plugin/src/selectors/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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));
59 changes: 59 additions & 0 deletions frontend/packages/metal3-plugin/src/utils/host-status.ts
Original file line number Diff line number Diff line change
@@ -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);

0 comments on commit 6df9297

Please sign in to comment.