Skip to content

Commit

Permalink
expose VMI details page
Browse files Browse the repository at this point in the history
  • Loading branch information
yaacov committed Jan 22, 2020
1 parent b39817b commit a546fcc
Show file tree
Hide file tree
Showing 37 changed files with 531 additions and 271 deletions.
Expand Up @@ -17,12 +17,12 @@ import {
withDashboardResources,
DashboardItemProps,
} from '@console/internal/components/dashboard/with-dashboard-resources';
import { VMKind } from '../../../types';
import { VMILikeEntityKind } from '../../../types/types';
import { VirtualMachineModel } from '../../../models';
import { getVmEventsFilters } from '../../../selectors/event';
import { VMDashboardContext } from '../../vms/vm-dashboard-context';

const combinedVmFilter = (vm: VMKind): EventFilterFuncion => (event) =>
const combinedVmFilter = (vm: VMILikeEntityKind): EventFilterFuncion => (event) =>
getVmEventsFilters(vm).some((filter) => filter(event.involvedObject));

const getEventsResource = (namespace: string): FirehoseResource => ({
Expand Down Expand Up @@ -56,13 +56,14 @@ const RecentEvent = withDashboardResources<RecentEventProps>(
);

export const VMActivityCard: React.FC = () => {
const { vm } = React.useContext(VMDashboardContext);
const { vm, vmi } = React.useContext(VMDashboardContext);
const vmLike = vm || vmi;

const [paused, setPaused] = React.useState(false);
const togglePause = React.useCallback(() => setPaused(!paused), [paused]);

const name = getName(vm);
const namespace = getNamespace(vm);
const name = getName(vmLike);
const namespace = getNamespace(vmLike);
const viewEventsLink = `${resourcePath(VirtualMachineModel.kind, name, namespace)}/events`;

return (
Expand All @@ -76,7 +77,7 @@ export const VMActivityCard: React.FC = () => {
</DashboardCardHeader>
<DashboardCardBody>
<ActivityBody>
<RecentEvent vm={vm} paused={paused} setPaused={setPaused} />
<RecentEvent vm={vmLike} paused={paused} setPaused={setPaused} />
</ActivityBody>
</DashboardCardBody>
</DashboardCard>
Expand All @@ -86,7 +87,7 @@ export const VMActivityCard: React.FC = () => {
type EventFilterFuncion = (event: EventKind) => boolean;

type RecentEventProps = DashboardItemProps & {
vm: VMKind;
vm: VMILikeEntityKind;
paused: boolean;
setPaused: (paused: boolean) => void;
};
Expand Up @@ -15,7 +15,7 @@ const isGuestAgentInstalled = (vmi: VMIKind) => {
};

export const VMAlerts: React.FC<VMAlertsProps> = ({ vm, vmi }) => (
<AlertsBody emptyMessage="No VM messages" isLoading={!vm}>
<AlertsBody emptyMessage="No VM messages" isLoading={!(vm || vmi)}>
{vmi && vmi.status && !isGuestAgentInstalled(vmi) && (
<StatusItem
Icon={BlueInfoCircleIcon}
Expand Down
Expand Up @@ -15,24 +15,23 @@ import {
resourcePath,
} from '@console/internal/components/utils';
import { VMDashboardContext } from '../../vms/vm-dashboard-context';
import { isVMRunning } from '../../../selectors/vm';
import { getVMStatus } from '../../../statuses/vm/vm';
import { VirtualMachineModel } from '../../../models';
import { getVmiIpAddressesString } from '../../ip-addresses';
import { getVmiIpAddresses } from '../../../selectors/vmi/ip-address';
import { VM_DETAIL_OVERVIEW_HREF } from '../../../constants';
import { findVMPod } from '../../../selectors/pod/selectors';

export const VMDetailsCard: React.FC<VMDetailsCardProps> = () => {
const vmDashboardContext = React.useContext(VMDashboardContext);
const { vm, vmi, pods, migrations } = vmDashboardContext;
const { vm, vmi, pods } = vmDashboardContext;
const vmLike = vm || vmi;

const vmStatus = getVMStatus({ vm, vmi, pods, migrations });
const { launcherPod } = vmStatus;
const launcherPod = findVMPod(vmLike, pods);

const ipAddrs = getVmiIpAddressesString(vmi, vmStatus);
const ipAddrs = getVmiIpAddresses(vmi).join(', ');

const isNodeLoading = !vm || !pods || !vmStatus;
const name = getName(vm);
const namespace = getNamespace(vm);
const isNodeLoading = !vmLike || !pods;
const name = getName(vmLike);
const namespace = getNamespace(vmLike);

const viewAllLink = `${resourcePath(
VirtualMachineModel.kind,
Expand All @@ -48,26 +47,32 @@ export const VMDetailsCard: React.FC<VMDetailsCardProps> = () => {
</DashboardCardHeader>
<DashboardCardBody isLoading={false}>
<DetailsBody>
<DetailItem title="Name" error={false} isLoading={!vm} valueClassName="co-select-to-copy">
<DetailItem
title="Name"
error={false}
isLoading={!vmLike}
valueClassName="co-select-to-copy"
>
{name}
</DetailItem>
<DetailItem title="Namespace" error={false} isLoading={!vm}>
<ResourceLink kind="Namespace" name={namespace} title={getUID(vm)} namespace={null} />
<DetailItem title="Namespace" error={false} isLoading={!vmLike}>
<ResourceLink
kind="Namespace"
name={namespace}
title={getUID(vmLike)}
namespace={null}
/>
</DetailItem>
<DetailItem title="Created" error={false} isLoading={!vm}>
<Timestamp timestamp={getCreationTimestamp(vm)} />
<DetailItem title="Created" error={false} isLoading={!vmLike}>
<Timestamp timestamp={getCreationTimestamp(vmLike)} />
</DetailItem>
<DetailItem
title="Node"
error={!isNodeLoading && (!launcherPod || !isVMRunning(vm))}
isLoading={isNodeLoading}
>
<DetailItem title="Node" error={!isNodeLoading && !launcherPod} isLoading={isNodeLoading}>
{launcherPod && <NodeLink name={getNodeName(launcherPod)} />}
</DetailItem>
<DetailItem
title="IP Address"
error={!ipAddrs}
isLoading={!vm}
isLoading={!vmLike}
valueClassName="co-select-to-copy"
>
{ipAddrs}
Expand Down
Expand Up @@ -9,25 +9,26 @@ import { getName, getNamespace } from '@console/shared';
import InventoryItem from '@console/shared/src/components/dashboard/inventory-card/InventoryItem';
import { resourcePath } from '@console/internal/components/utils';
import { VMDashboardContext } from '../../vms/vm-dashboard-context';
import { getVMLikeModel } from '../../../selectors/vm/vmlike';
import { getNetworks, getDisks } from '../../../selectors/vm';
import { getVMINetworks, getVMIDisks } from '../../../selectors/vmi';
import { VirtualMachineModel } from '../../../models';
import { VM_DETAIL_DISKS_HREF, VM_DETAIL_NETWORKS_HREF } from '../../../constants';

export const VMInventoryCard: React.FC<VMInventoryCardProps> = () => {
const vmDashboardContext = React.useContext(VMDashboardContext);
const { vm, vmi } = vmDashboardContext;
const vmLike = vm || vmi;

const isLoading = !vm;
const name = getName(vm);
const namespace = getNamespace(vm);
const isLoading = !vmLike;
const name = getName(vmLike);
const namespace = getNamespace(vmLike);

// prefer vmi over vm if available (means: is running)
const nicCount = vmi && vmi.spec ? getVMINetworks(vmi).length : getNetworks(vm).length;
const diskCount = vmi && vmi.spec ? getVMIDisks(vmi).length : getDisks(vm).length;
const nicCount = vm ? getNetworks(vm).length : getVMINetworks(vmi).length;
const diskCount = vm ? getDisks(vm).length : getVMIDisks(vmi).length;
// TODO: per design, snapshots should be added here (snapshots are not implemented at all atm)

const basePath = resourcePath(VirtualMachineModel.kind, name, namespace);
const basePath = resourcePath(getVMLikeModel(vmLike).kind, name, namespace);
const DisksTitle = React.useCallback(
({ children }) => <Link to={`${basePath}/${VM_DETAIL_DISKS_HREF}`}>{children}</Link>,
[basePath],
Expand Down
Expand Up @@ -15,8 +15,8 @@ import {
Duration,
} from '@console/shared/src/components/dashboard/duration-hook';
import { VMDashboardContext } from '../../vms/vm-dashboard-context';
import { findVMPod } from '../../../selectors/pod/selectors';
import { getUtilizationQueries, VMQueries } from './queries';
import { findVMPod } from '../../../selectors/pod/selectors';

// TODO: extend humanizeCpuCores() from @console/internal for the flexibility of space
const humanizeCpuCores = (v) => {
Expand All @@ -30,10 +30,11 @@ const humanizeCpuCores = (v) => {
export const VMUtilizationCard: React.FC = () => {
const [timestamps, setTimestamps] = React.useState<Date[]>();
const [duration, setDuration] = useMetricDuration();
const { vm, pods } = React.useContext(VMDashboardContext);
const vmName = getName(vm);
const namespace = getNamespace(vm);
const launcherPodName = getName(findVMPod(vm, pods));
const { vm, vmi, pods } = React.useContext(VMDashboardContext);
const vmLike = vm || vmi;
const vmName = getName(vmLike);
const namespace = getNamespace(vmLike);
const launcherPodName = getName(findVMPod(vmLike, pods));
const queries = React.useMemo(
() =>
getUtilizationQueries({
Expand Down
10 changes: 0 additions & 10 deletions frontend/packages/kubevirt-plugin/src/components/ip-addresses.ts

This file was deleted.

Expand Up @@ -10,8 +10,8 @@ import {
} from '@console/internal/components/factory';
import { k8sPatch } from '@console/internal/module/k8s';
import { getDescription } from '../../../selectors/selectors';
import { VMLikeEntityKind } from '../../../types';
import { getVMLikeModel } from '../../../selectors/vm';
import { VMGenericLikeEntityKind } from '../../../types';
import { getVMLikeModel, isVMI } from '../../../selectors/vm';
import { getUpdateDescriptionPatches } from '../../../k8s/patches/vm/vm-patches';

// TODO: should be moved under kubevirt-plugin/src/style.scss
Expand All @@ -25,7 +25,9 @@ export const VMDescriptionModal = withHandlePromise((props: VMDescriptionModalPr
const submit = (e) => {
e.preventDefault();

const patches = getUpdateDescriptionPatches(vmLikeEntity, description);
const patches = isVMI(vmLikeEntity)
? []
: getUpdateDescriptionPatches(vmLikeEntity, description);
if (patches.length === 0) {
close();
} else {
Expand Down Expand Up @@ -57,7 +59,7 @@ export const VMDescriptionModal = withHandlePromise((props: VMDescriptionModalPr

export type VMDescriptionModalProps = HandlePromiseProps &
ModalComponentProps & {
vmLikeEntity: VMLikeEntityKind;
vmLikeEntity: VMGenericLikeEntityKind;
};

export const vmDescriptionModal = createModalLauncher(VMDescriptionModal);
Expand Up @@ -10,7 +10,7 @@ import { DASH, dimensifyRow, getDeletetionTimestamp } from '@console/shared';
import { TemplateModel } from '@console/internal/models';
import { deleteDeviceModal, DeviceType } from '../modals/delete-device-modal';
import { VMLikeEntityKind } from '../../types';
import { asVM, isVM, isVMRunning } from '../../selectors/vm';
import { asVM, isVM, isVMI, isVMRunning } from '../../selectors/vm';
import { VirtualMachineModel } from '../../models';
import { ValidationCell } from '../table/validation-cell';
import { VMNicRowActionOpts } from '../vm-nics/types';
Expand Down Expand Up @@ -74,7 +74,7 @@ const getActions = (
opts: VMStorageRowActionOpts,
) => {
const actions = [];
if (isVMRunning(asVM(vmLikeEntity))) {
if (isVMI(vmLikeEntity) || isVMRunning(asVM(vmLikeEntity))) {
return actions;
}

Expand Down Expand Up @@ -163,7 +163,10 @@ export const DiskRow: React.FC<VMDiskRowProps> = ({
withProgress,
})}
isDisabled={
isDisabled || !!getDeletetionTimestamp(vmLikeEntity) || isVMRunning(asVM(vmLikeEntity))
isDisabled ||
isVMI(vmLikeEntity) ||
!!getDeletetionTimestamp(vmLikeEntity) ||
isVMRunning(asVM(vmLikeEntity))
}
id={`kebab-for-${disk.getName()}`}
/>
Expand Down
Expand Up @@ -19,6 +19,7 @@ import { VHW_TYPES } from '../create-vm-wizard/tabs/virtual-hardware-tab/types';
import { StorageBundle } from './types';
import { DiskRow } from './disk-row';
import { diskTableColumnClasses } from './utils';
import { isVMI } from '../../selectors/vm';

const getStoragesData = ({
vmLikeEntity,
Expand Down Expand Up @@ -120,25 +121,27 @@ export const VMDisks: React.FC<VMDisksProps> = ({ vmLikeEntity, pvcs, datavolume
const withProgress = wrapWithProgress(setIsLocked);
return (
<div className="co-m-list">
<div className="co-m-pane__filter-bar">
<div className="co-m-pane__filter-bar-group">
<Button
variant={ButtonVariant.primary}
id="create-disk-btn"
onClick={() =>
withProgress(
diskModalEnhanced({
blocking: true,
vmLikeEntity,
}).result,
)
}
isDisabled={isLocked}
>
Create Disk
</Button>
{!isVMI(vmLikeEntity) && (
<div className="co-m-pane__filter-bar">
<div className="co-m-pane__filter-bar-group">
<Button
variant={ButtonVariant.primary}
id="create-disk-btn"
onClick={() =>
withProgress(
diskModalEnhanced({
blocking: true,
vmLikeEntity,
}).result,
)
}
isDisabled={isLocked}
>
Create Disk
</Button>
</div>
</div>
</div>
)}
<div className="co-m-pane__body">
<VMDisksTable
data={getStoragesData({ vmLikeEntity, pvcs, datavolumes })}
Expand Down
Expand Up @@ -5,7 +5,7 @@ import { TemplateModel } from '@console/internal/models';
import { DASH, dimensifyRow, getDeletetionTimestamp } from '@console/shared';
import { deleteDeviceModal, DeviceType } from '../modals/delete-device-modal';
import { VirtualMachineModel } from '../../models';
import { asVM, isVM, isVMRunning } from '../../selectors/vm';
import { asVM, isVM, isVMI, isVMRunning } from '../../selectors/vm';
import { VMLikeEntityKind } from '../../types';
import { nicModalEnhanced } from '../modals/nic-modal/nic-modal-enhanced';
import { ValidationCell } from '../table/validation-cell';
Expand Down Expand Up @@ -63,7 +63,7 @@ const menuActionDelete = (
});

const getActions = (nic, network, vmLikeEntity: VMLikeEntityKind, opts: VMNicRowActionOpts) => {
if (isVMRunning(asVM(vmLikeEntity))) {
if (isVMI(vmLikeEntity) || isVMRunning(asVM(vmLikeEntity))) {
return [];
}
const actions = [menuActionEdit, menuActionDelete];
Expand Down Expand Up @@ -135,7 +135,10 @@ export const NicRow: React.FC<VMNicRowProps> = ({
<Kebab
options={getActions(nic, network, vmLikeEntity, { withProgress })}
isDisabled={
isDisabled || !!getDeletetionTimestamp(vmLikeEntity) || isVMRunning(asVM(vmLikeEntity))
isDisabled ||
isVMI(vmLikeEntity) ||
!!getDeletetionTimestamp(vmLikeEntity) ||
isVMRunning(asVM(vmLikeEntity))
}
id={`kebab-for-${name}`}
/>
Expand Down

0 comments on commit a546fcc

Please sign in to comment.