Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug 1883388: Show maintenance and power status in BMH status card #7764

Merged
merged 1 commit into from Jan 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -52,48 +52,55 @@ const BareMetalHostStatus: React.FC<BareMetalHostStatusProps> = ({
descriptionKey,
host,
nodeMaintenance,
className,
}) => {
const { t } = useTranslation();
const statusTitle = t(titleKey) || status;
const action = hostStatusActions(t)[status]?.(host);
switch (true) {
case [NODE_STATUS_STARTING_MAINTENANCE, NODE_STATUS_UNDER_MAINTENANCE].includes(status):
return <MaintenancePopover title={statusTitle} nodeMaintenance={nodeMaintenance} />;
return (
<MaintenancePopover
title={statusTitle}
nodeMaintenance={nodeMaintenance}
className={className}
/>
);
case [NODE_STATUS_STOPPING_MAINTENANCE, ...HOST_PROGRESS_STATES].includes(status):
return (
<ProgressStatus title={statusTitle}>
{t(descriptionKey)}
<ProgressStatus title={statusTitle} className={className}>
{descriptionKey && t(descriptionKey)}
{action}
</ProgressStatus>
);
case HOST_ERROR_STATES.includes(status):
return (
<ErrorStatus title={statusTitle}>
<ErrorStatus title={statusTitle} className={className}>
<p>{t(descriptionKey)}</p>
<p>{getHostErrorMessage(host)}</p>
{action}
</ErrorStatus>
);
case HOST_SUCCESS_STATES.includes(status):
return (
<SuccessStatus title={statusTitle}>
{t(descriptionKey)}
<SuccessStatus title={statusTitle} className={className}>
{descriptionKey && t(descriptionKey)}
{action}
</SuccessStatus>
);
case HOST_INFO_STATES.includes(status):
return (
<InfoStatus title={statusTitle}>
{t(descriptionKey)}
<InfoStatus title={statusTitle} className={className}>
{descriptionKey && t(descriptionKey)}
{action}
</InfoStatus>
);
default: {
const statusBody = <Status status={status} title={statusTitle} />;
const statusBody = <Status status={status} title={statusTitle} className={className} />;

return descriptionKey || action ? (
<PopoverStatus title={statusTitle} statusBody={statusBody}>
{t(descriptionKey)}
{descriptionKey && t(descriptionKey)}
{action}
</PopoverStatus>
) : (
Expand All @@ -106,6 +113,7 @@ const BareMetalHostStatus: React.FC<BareMetalHostStatusProps> = ({
type BareMetalHostStatusProps = StatusProps & {
host?: BareMetalHostKind;
nodeMaintenance?: K8sResourceKind;
className?: string;
};

export default BareMetalHostStatus;
Expand Up @@ -2,9 +2,9 @@ import * as React from 'react';
import Dashboard from '@console/shared/src/components/dashboard/Dashboard';
import DashboardGrid from '@console/shared/src/components/dashboard/DashboardGrid';
import { getMachineNode } from '@console/shared/src/selectors/machine';
import { MachineKind, NodeKind } from '@console/internal/module/k8s';
import { K8sResourceKind, MachineKind, NodeKind } from '@console/internal/module/k8s';
import { BareMetalHostKind } from '../../../types';
import { getHostMachine } from '../../../selectors';
import { findNodeMaintenance, getHostMachine } from '../../../selectors';
import { BareMetalHostDashboardContext } from './BareMetalHostDashboardContext';
import StatusCard from './StatusCard';
import UtilizationCard from './UtilizationCard';
Expand All @@ -16,14 +16,17 @@ const BareMetalHostDashboard: React.FC<BareMetalHostDashboardProps> = ({
obj,
machines,
nodes,
nodeMaintenances,
loaded,
}) => {
const machine = getHostMachine(obj, machines);
const node = getMachineNode(machine, nodes);
const nodeMaintenance = findNodeMaintenance(nodeMaintenances, node?.metadata?.name);
const context = {
obj,
machine,
node,
nodeMaintenance,
loaded,
};

Expand All @@ -44,6 +47,7 @@ type BareMetalHostDashboardProps = {
obj: BareMetalHostKind;
machines: MachineKind[];
nodes: NodeKind[];
nodeMaintenances: K8sResourceKind[];
loaded: boolean;
};

Expand Down
@@ -1,5 +1,5 @@
import * as React from 'react';
import { MachineKind, NodeKind } from '@console/internal/module/k8s';
import { K8sResourceKind, MachineKind, NodeKind } from '@console/internal/module/k8s';
import { BareMetalHostKind } from '../../../types';

export const BareMetalHostDashboardContext = React.createContext<BareMetalDashboardContext>({});
Expand All @@ -8,5 +8,6 @@ type BareMetalDashboardContext = {
obj?: BareMetalHostKind;
machine?: MachineKind;
node?: NodeKind;
nodeMaintenance?: K8sResourceKind;
loaded?: boolean;
};
Expand Up @@ -2,6 +2,7 @@ import * as React from 'react';
import { useTranslation } from 'react-i18next';
import * as _ from 'lodash';
import { Gallery, GalleryItem } from '@patternfly/react-core';
import { RebootingIcon } from '@patternfly/react-icons';
import { Link } from 'react-router-dom';
import {
DashboardItemProps,
Expand All @@ -17,47 +18,31 @@ import { HealthState } from '@console/shared/src/components/dashboard/status-car
import AlertsBody from '@console/shared/src/components/dashboard/status-card/AlertsBody';
import { Alert } from '@console/internal/components/monitoring/types';
import { alertURL } from '@console/internal/components/monitoring/utils';
import { BlueInfoCircleIcon } from '@console/shared';
import { BlueInfoCircleIcon, StatusIconAndText } from '@console/shared';
import AlertItem, {
StatusItem,
} from '@console/shared/src/components/dashboard/status-card/AlertItem';
import { resourcePathFromModel } from '@console/internal/components/utils';
import { getBareMetalHostStatus } from '../../../status/host-status';
import { getBareMetalHostStatus, getHostStatus } from '../../../status/host-status';
import {
HOST_STATUS_DESCRIPTION_KEYS,
HOST_SUCCESS_STATES,
HOST_ERROR_STATES,
HOST_PROGRESS_STATES,
HOST_HARDWARE_ERROR_STATES,
HOST_STATUS_UNMANAGED,
HOST_INFO_STATES,
HOST_REGISTERING_STATES,
} from '../../../constants';
import { BareMetalHostKind } from '../../../types';
import { BareMetalHostDashboardContext } from './BareMetalHostDashboardContext';
import { BareMetalHostModel } from '../../../models';
import { hasPowerManagement } from '../../../selectors';

const getHostHealthState = (obj: BareMetalHostKind): HostHealthState => {
const { status, titleKey } = getBareMetalHostStatus(obj);
let state: HealthState = HealthState.UNKNOWN;

if ([...HOST_SUCCESS_STATES, ...HOST_INFO_STATES].includes(status)) {
state = HealthState.OK;
}

if (HOST_ERROR_STATES.includes(status)) {
state = HealthState.ERROR;
}
import {
getHostPowerStatus,
getHostProvisioningState,
hasPowerManagement,
isHostScheduledForRestart,
} from '../../../selectors';
import BareMetalHostStatus from '../BareMetalHostStatus';

if (HOST_PROGRESS_STATES.includes(status)) {
state = HealthState.PROGRESS;
}

return {
titleKey,
state,
};
};
import './status.scss';
import BareMetalHostPowerStatusIcon from '../BareMetalHostPowerStatusIcon';

const getHostHardwareHealthState = (obj): HostHealthState => {
const { status, titleKey } = getBareMetalHostStatus(obj);
Expand All @@ -82,19 +67,25 @@ const HealthCard: React.FC<HealthCardProps> = ({
notificationAlerts,
}) => {
const { t } = useTranslation();
const { obj } = React.useContext(BareMetalHostDashboardContext);
const { obj, machine, node, nodeMaintenance } = React.useContext(BareMetalHostDashboardContext);

React.useEffect(() => {
watchAlerts();
return () => stopWatchAlerts();
}, [watchAlerts, stopWatchAlerts]);

const health = getHostHealthState(obj);
const status = getHostStatus({ host: obj, machine, node, nodeMaintenance });

const hwHealth = getHostHardwareHealthState(obj);

const { data, loaded, loadError } = notificationAlerts || {};
const alerts = React.useMemo(() => filterAlerts(data), [data]);

const hasPowerMgmt = hasPowerManagement(obj);
const provisioningState = getHostProvisioningState(obj);
const powerStatus = getHostPowerStatus(obj);
const restartScheduled = isHostScheduledForRestart(obj);

return (
<DashboardCard gradient>
<DashboardCardHeader>
Expand All @@ -103,8 +94,13 @@ const HealthCard: React.FC<HealthCardProps> = ({
<DashboardCardBody>
<HealthBody>
<Gallery className="co-overview-status__health" hasGutter>
<GalleryItem>
<HealthItem title={t(health.titleKey)} state={health.state} />
<GalleryItem className="bmh-health__status-item">
<BareMetalHostStatus
{...status}
nodeMaintenance={nodeMaintenance}
host={obj}
className="bmh-health__status"
/>
</GalleryItem>
<GalleryItem>
<HealthItem
Expand All @@ -113,10 +109,32 @@ const HealthCard: React.FC<HealthCardProps> = ({
details={t(hwHealth.titleKey)}
/>
</GalleryItem>
{!HOST_REGISTERING_STATES.includes(provisioningState) && (
<GalleryItem>
{!hasPowerMgmt ? (
<HealthItem
title={t('metal3-plugin~No power management')}
state={HealthState.NOT_AVAILABLE}
/>
) : (
<StatusIconAndText
title={restartScheduled ? t('metal3-plugin~Restart pending') : powerStatus}
icon={
restartScheduled ? (
<RebootingIcon />
) : (
<BareMetalHostPowerStatusIcon powerStatus={powerStatus} />
)
}
className="bmh-health__status"
/>
)}
</GalleryItem>
)}
</Gallery>
</HealthBody>
<AlertsBody error={!_.isEmpty(loadError)}>
{!hasPowerManagement(obj) && (
{!hasPowerMgmt && (
<StatusItem
Icon={BlueInfoCircleIcon}
message={t(HOST_STATUS_DESCRIPTION_KEYS[HOST_STATUS_UNMANAGED])}
Expand Down
@@ -0,0 +1,14 @@
.bmh-health__status {
height: 100%;
align-items: center;
.co-icon-and-text__icon {
margin-right: var(--pf-global--spacer--md);
top: 0;
font-size: 1.2rem;
}
}

.bmh-health__status-item {
display: flex;
}