Skip to content

Commit

Permalink
vm overview boot order summary
Browse files Browse the repository at this point in the history
  • Loading branch information
yaacov committed Nov 26, 2019
1 parent a2d27e9 commit 6a6e92c
Show file tree
Hide file tree
Showing 9 changed files with 121 additions and 45 deletions.
14 changes: 0 additions & 14 deletions frontend/packages/kubevirt-plugin/src/components/boot-order.tsx

This file was deleted.

@@ -0,0 +1,7 @@
.kubevirt-boot-order-suammary__expandable.pf-c-expandable .pf-c-expandable__content {
margin-top: 0;
}

.kubevirt-boot-order-suammary__empty-text {
margin-bottom: 0;
}
@@ -0,0 +1,62 @@
import * as React from 'react';
import * as _ from 'lodash';
import { List, ListItem, Expandable, Text, TextVariants } from '@patternfly/react-core';
import { BootableDeviceType } from '../../types';
import { deviceLabel, deviceKey, bootOrderEmptyTitle, bootOrderEmptyMessage } from './constants';

import './boot-order-summary.scss';

export const BootOrderSummary = ({ devices }: BootOrderSummaryProps) => {
const [isExpanded, setIsExpanded] = React.useState<boolean>(false);

const sources = _.sortBy(devices.filter((device) => device.value.bootOrder), 'value.bootOrder');
const options = devices.filter((device) => !device.value.bootOrder);

const onToggle = () => {
setIsExpanded(!isExpanded);
};

// Note(Yaacov): className='text-secondary' is a hack to fix TextVariants being overriden.
const EmptyState: React.FC = () => (
<>
<Text component={TextVariants.p} className="kubevirt-boot-order-suammary__empty-text">
{bootOrderEmptyTitle}
</Text>
<Text component={TextVariants.small} className="text-secondary">
{bootOrderEmptyMessage}
</Text>
{options.length > 0 && (
<Expandable
toggleText={isExpanded ? 'Hide default boot disks' : 'Show default boot disks'}
onToggle={onToggle}
isExpanded={isExpanded}
className="kubevirt-boot-order-suammary__expandable"
>
<List>
{options.map((option) => (
<ListItem key={deviceKey(option)}>{deviceLabel(option)}</ListItem>
))}
</List>
</Expandable>
)}
</>
);

return (
<>
{sources.length === 0 ? (
<EmptyState />
) : (
<List>
{sources.map((source) => (
<ListItem key={deviceKey(source)}>{deviceLabel(source)}</ListItem>
))}
</List>
)}
</>
);
};

export type BootOrderSummaryProps = {
devices: BootableDeviceType[];
};
@@ -0,0 +1,6 @@
export const bootOrderEmptyTitle = 'No resource selected';
export const bootOrderEmptyMessage =
'VM will attempt to boot from disks by order of apearance in YAML file';

export const deviceKey = (device) => `${device.type}-${device.value.name}`;
export const deviceLabel = (device) => `${device.value.name} (${device.typeLabel})`;
@@ -0,0 +1 @@
export * from './boot-order-summary';
Expand Up @@ -17,8 +17,8 @@ import { getFlavorText } from '../flavor-text';
import { EditButton } from '../edit-button';
import { VMDetailsItem } from '../vms/vm-resource';
import { DiskSummary } from '../vm-disks/disk-summary';
import { asVM, getBootableDevicesInOrder } from '../../selectors/vm';
import { BootOrder } from '../boot-order';
import { asVM, getDevices } from '../../selectors/vm';
import { BootOrderSummary } from '../boot-order';
import { VMTemplateLink } from './vm-template-link';
import { TemplateSource } from './vm-template-source';

Expand Down Expand Up @@ -79,18 +79,14 @@ export const VMTemplateDetailsList: React.FC<VMTemplateResourceListProps> = ({
canUpdateTemplate,
}) => {
const id = getBasicID(template);
const sortedBootableDevices = getBootableDevicesInOrder(template);
const devices = getDevices(asVM(template));
const cds = getCDRoms(asVM(template));
const flavorText = getFlavorText(template);

return (
<dl className="co-m-pane__details">
<VMDetailsItem
title="Boot Order"
idValue={prefixedID(id, 'boot-order')}
isNotAvail={sortedBootableDevices.length === 0}
>
<BootOrder bootableDevices={sortedBootableDevices} />
<VMDetailsItem title="Boot Order" idValue={prefixedID(id, 'boot-order')}>
<BootOrderSummary devices={devices} />
</VMDetailsItem>

<VMDetailsItem
Expand Down
Expand Up @@ -17,12 +17,12 @@ import { EditButton } from '../edit-button';
import { getVmiIpAddressesString } from '../ip-addresses';
import { VMStatuses } from '../vm-status';
import { DiskSummary } from '../vm-disks/disk-summary';
import { BootOrder } from '../boot-order';
import { BootOrderSummary } from '../boot-order';
import {
getOperatingSystemName,
getOperatingSystem,
getWorkloadProfile,
getBootableDevicesInOrder,
getDevices,
} from '../../selectors/vm';

import './vm-resource.scss';
Expand Down Expand Up @@ -95,7 +95,7 @@ export const VMDetailsList: React.FC<VMResourceListProps> = ({
const vmStatus = getVMStatus({ vm, vmi, pods, migrations });
const { launcherPod } = vmStatus;
const cds = getCDRoms(vm);
const sortedBootableDevices = getBootableDevicesInOrder(vm);
const devices = getDevices(vm);
const nodeName = getNodeName(launcherPod);
const ipAddrs = getVmiIpAddressesString(vmi, vmStatus);
const workloadProfile = getWorkloadProfile(vm);
Expand All @@ -117,12 +117,8 @@ export const VMDetailsList: React.FC<VMResourceListProps> = ({
)}
</VMDetailsItem>

<VMDetailsItem
title="Boot Order"
idValue={prefixedID(id, 'boot-order')}
isNotAvail={sortedBootableDevices.length === 0}
>
<BootOrder bootableDevices={sortedBootableDevices} />
<VMDetailsItem title="Boot Order" idValue={prefixedID(id, 'boot-order')}>
<BootOrderSummary devices={devices} />
</VMDetailsItem>

<VMDetailsItem
Expand Down
@@ -1,11 +1,19 @@
/* eslint-disable lines-between-class-members */
import * as _ from 'lodash';
import { ValueEnum } from '../../value-enum';

export class DiskType extends ValueEnum<string> {
static readonly DISK = new DiskType('disk');
static readonly CDROM = new DiskType('cdrom');
static readonly CDROM = new DiskType('cdrom', 'CD-ROM');
static readonly FLOPPY = new DiskType('floppy');
static readonly LUN = new DiskType('lun');
static readonly LUN = new DiskType('lun', 'LUN');

private readonly label: string;

protected constructor(value: string, label?: string) {
super(value);
this.label = label || _.capitalize(value);
}

private static readonly ALL = Object.freeze(
ValueEnum.getAllClassEnumProperties<DiskType>(DiskType),
Expand All @@ -25,4 +33,7 @@ export class DiskType extends ValueEnum<string> {
DiskType.fromString(diskType && diskType.value);

static fromString = (model: string): DiskType => DiskType.stringMapper[model];

// Overide ValueEnum's default toString method.
toString = () => this.label;
}
33 changes: 22 additions & 11 deletions frontend/packages/kubevirt-plugin/src/selectors/vm/devices.ts
@@ -1,4 +1,6 @@
import { VMKind, VMLikeEntityKind, BootableDeviceType } from '../../types';
import * as _ from 'lodash';
import { VMLikeEntityKind, BootableDeviceType } from '../../types';
import { DiskWrapper } from '../../k8s/wrapper/vm/disk-wrapper';
import { DEVICE_TYPE_DISK, DEVICE_TYPE_INTERFACE } from '../../constants';
import { getDisks, getInterfaces } from './selectors';
import { asVM } from './vmlike';
Expand All @@ -9,18 +11,27 @@ export const getBootDeviceIndex = (devices, bootOrder) =>
export const getDeviceBootOrder = (device, defaultValue?): number =>
device && device.bootOrder === undefined ? defaultValue : device.bootOrder;

const getBootableDevices = (vm: VMKind): BootableDeviceType[] => {
const disks = getDisks(vm)
.filter((disk) => disk.bootOrder)
.map((disk) => ({ type: DEVICE_TYPE_DISK, value: disk }));
const nics = getInterfaces(vm)
.filter((nic) => nic.bootOrder)
.map((nic) => ({ type: DEVICE_TYPE_INTERFACE, value: nic }));
export const getDevices = (vm: VMLikeEntityKind): BootableDeviceType[] => {
const disks = getDisks(asVM(vm)).map((disk) => ({
type: DEVICE_TYPE_DISK,
typeLabel: DiskWrapper.initialize(disk)
.getType()
.toString(),
value: disk,
}));
const nics = getInterfaces(asVM(vm)).map((nic) => ({
type: DEVICE_TYPE_INTERFACE,
typeLabel: 'NIC',
value: nic,
}));

return [...disks, ...nics];
};

export const getBootableDevicesInOrder = (vmLike: VMLikeEntityKind): BootableDeviceType[] => {
const vm = asVM(vmLike);
return getBootableDevices(vm).sort((a, b) => a.value.bootOrder - b.value.bootOrder);
export const getBootableDevices = (vm: VMLikeEntityKind): BootableDeviceType[] => {
const devices = getDevices(vm).filter((device) => device.value.bootOrder);
return [...devices];
};

export const getBootableDevicesInOrder = (vm: VMLikeEntityKind): BootableDeviceType[] =>
_.sortBy(getBootableDevices(vm), 'value.bootOrder');

0 comments on commit 6a6e92c

Please sign in to comment.