Skip to content

Commit

Permalink
CNV-36798: Provisioning percentage
Browse files Browse the repository at this point in the history
  • Loading branch information
upalatucci committed Mar 12, 2024
1 parent 3edd128 commit fb71410
Show file tree
Hide file tree
Showing 12 changed files with 200 additions and 24 deletions.
3 changes: 3 additions & 0 deletions locales/en/plugin__kubevirt-plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,7 @@
"Copy SSH command": "Copy SSH command",
"Copy template's boot source disk": "Copy template's boot source disk",
"Copy to clipboard": "Copy to clipboard",
"Copying files": "Copying files",
"Could not create persistent volume claim": "Could not create persistent volume claim",
"CPU": "CPU",
"CPU | Memory": "CPU | Memory",
Expand Down Expand Up @@ -888,6 +889,7 @@
"Project name to clone the template to": "Project name to clone the template to",
"Project selector": "Project selector",
"Provider": "Provider",
"Provisioning": "Provisioning",
"Public SSH key": "Public SSH key",
"Put the VirtualMachine behind a NAT Proxy for high compatibility with different network providers. The VirtualMachines IP will differ from the IP seen on the pod network": "Put the VirtualMachine behind a NAT Proxy for high compatibility with different network providers. The VirtualMachines IP will differ from the IP seen on the pod network",
"PVC": "PVC",
Expand Down Expand Up @@ -1308,6 +1310,7 @@
"VirtualMachine details": "VirtualMachine details",
"VirtualMachine hotplug volume": "VirtualMachine hotplug volume",
"VirtualMachine is currently {{ status }}": "VirtualMachine is currently {{ status }}",
"VirtualMachine is currently provisioning": "VirtualMachine is currently provisioning",
"VirtualMachine is not running": "VirtualMachine is not running",
"VirtualMachine is not running.": "VirtualMachine is not running.",
"VirtualMachine labels": "VirtualMachine labels",
Expand Down
51 changes: 51 additions & 0 deletions src/utils/resources/vm/hooks/useProvisioningPercentage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { DataVolumeModelGroupVersionKind } from '@kubevirt-ui/kubevirt-api/console';
import type { V1beta1DataVolume } from '@kubevirt-ui/kubevirt-api/containerized-data-importer/models';
import { V1VirtualMachine } from '@kubevirt-ui/kubevirt-api/kubevirt';
import { getNamespace } from '@kubevirt-utils/resources/shared';
import { getVolumes } from '@kubevirt-utils/resources/vm';
import { useK8sWatchResources, WatchK8sResource } from '@openshift-console/dynamic-plugin-sdk';
import { printableVMStatus } from '@virtualmachines/utils';

export type NameWithPercentages = { [name in string]: string };

type UseProvisioningPercentageType = (vmi: V1VirtualMachine) => {
loaded: boolean;
percentages: NameWithPercentages;
};

const useProvisioningPercentage: UseProvisioningPercentageType = (vm) => {
const volumes = getVolumes(vm);
const namespace = getNamespace(vm);

const dataVolumeNames =
volumes?.filter((v) => v.dataVolume).map((dvVolume) => dvVolume.dataVolume?.name) || [];

const watchRequest = dataVolumeNames.reduce((acc, current) => {
acc[current] = {
groupVersionKind: DataVolumeModelGroupVersionKind,
name: current,
namespace: namespace,
};
return acc;
}, {} as { [key in string]: WatchK8sResource });

const vmPrintableStatus = vm?.status?.printableStatus;

const dataVolumeWatch = useK8sWatchResources<{
[key in string]: V1beta1DataVolume;
}>(vmPrintableStatus === printableVMStatus.Provisioning ? watchRequest : {});

const loaded = Object.values(dataVolumeWatch || {}).every(
(watchResource) => watchResource.loaded || watchResource.loadError,
);

const percentages = Object.keys(dataVolumeWatch || {}).reduce((acc, dataVolumeName) => {
acc[dataVolumeName] = dataVolumeWatch[dataVolumeName]?.data?.status?.progress;

return acc;
}, {} as NameWithPercentages);

return { loaded, percentages };
};

export default useProvisioningPercentage;
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { useModal } from '@kubevirt-utils/components/ModalProvider/ModalProvider
import WindowsDrivers from '@kubevirt-utils/components/WindowsDrivers/WindowsDrivers';
import { useKubevirtTranslation } from '@kubevirt-utils/hooks/useKubevirtTranslation';
import useDisksTableData from '@kubevirt-utils/resources/vm/hooks/disk/useDisksTableData';
import useProvisioningPercentage from '@kubevirt-utils/resources/vm/hooks/useProvisioningPercentage';
import {
ListPageCreateButton,
ListPageFilter,
Expand All @@ -34,6 +35,9 @@ const DiskList: FC<DiskListProps> = ({ vm, vmi }) => {
const [disks, loaded, loadError] = useDisksTableData(vm, vmi);
const filters = useDisksFilters();
const [data, filteredData, onFilterChange] = useListPageFilter(disks, filters);

const { percentages: provisioningPercentages } = useProvisioningPercentage(vm);

const headerText =
vm?.status?.printableStatus === printableVMStatus.Running
? t('Add disk (hot plugged)')
Expand Down Expand Up @@ -80,7 +84,7 @@ const DiskList: FC<DiskListProps> = ({ vm, vmi }) => {
loaded={loaded}
loadError={loadError}
Row={DiskRow}
rowData={{ vm, vmi }}
rowData={{ provisioningPercentages, vm, vmi }}
unfilteredData={data}
/>
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,50 @@ import React, { FC } from 'react';
import { V1VirtualMachine, V1VirtualMachineInstance } from '@kubevirt-ui/kubevirt-api/kubevirt';
import { useKubevirtTranslation } from '@kubevirt-utils/hooks/useKubevirtTranslation';
import { modelToGroupVersionKind, PersistentVolumeClaimModel } from '@kubevirt-utils/models';
import { NameWithPercentages } from '@kubevirt-utils/resources/vm/hooks/useProvisioningPercentage';
import { DiskRowDataLayout } from '@kubevirt-utils/resources/vm/utils/disk/constants';
import { readableSizeUnit } from '@kubevirt-utils/utils/units';
import { ResourceLink, RowProps, TableData } from '@openshift-console/dynamic-plugin-sdk';
import { Label, Stack, StackItem } from '@patternfly/react-core';
import { Label, Stack, StackItem, Tooltip, TooltipPosition } from '@patternfly/react-core';

import { isPVCSource } from './utils/helpers';
import DiskRowActions from './DiskRowActions';
import { HotplugLabel } from './HotplugLabel';

const DiskRow: FC<
RowProps<DiskRowDataLayout, { vm: V1VirtualMachine; vmi?: V1VirtualMachineInstance }>
> = ({ activeColumnIDs, obj, rowData: { vm, vmi } }) => {
RowProps<
DiskRowDataLayout,
{
provisioningPercentages: NameWithPercentages;
vm: V1VirtualMachine;
vmi?: V1VirtualMachineInstance;
}
>
> = ({ activeColumnIDs, obj, rowData: { provisioningPercentages, vm, vmi } }) => {
const { t } = useKubevirtTranslation();

const provisioningPercentage = provisioningPercentages?.[obj?.source];

return (
<>
<TableData activeColumnIDs={activeColumnIDs} id="name">
<Stack>
<StackItem>
{obj?.name} <HotplugLabel diskName={obj?.name} vm={vm} vmi={vmi} />
{provisioningPercentage ? (
<Tooltip
content={
<>
{t('Provisioning')} {provisioningPercentage}
</>
}
position={TooltipPosition.right}
>
<span> {obj?.name}</span>
</Tooltip>
) : (
obj?.name
)}{' '}
<HotplugLabel diskName={obj?.name} vm={vm} vmi={vmi} />
</StackItem>
{obj?.isBootDisk && (
<StackItem>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,10 @@ import VMNotMigratableLabel from '@virtualmachines/list/components/VMNotMigratab
import { printableVMStatus } from '@virtualmachines/utils';

import InstanceTypeDescription from './components/InstanceTypeDescription';
import MigrationProgressPopover from './components/MigrationProgressPopover/MigrationProgressPopover';
import StatusPopoverButton from './components/StatusPopoverButton/StatusPopoverButton';
import TemplateDescription from './components/TemplateDescription';
import VirtualMachineMigrationPercentage from './components/VirtualMachineMigrationPercentage';
import VirtualMachineOverviewStatus from './components/VirtualMachineOverviewStatus/VirtualMachineOverviewStatus';
import VirtualMachinesOverviewTabDetailsConsole from './components/VirtualMachinesOverviewTabDetailsConsole';
import StatusPopover from './components/VirtualMachineStatusWithPopover/VirtualMachineStatusWithPopover';

import './virtual-machines-overview-tab-details.scss';

Expand Down Expand Up @@ -119,15 +117,9 @@ const VirtualMachinesOverviewTabDetails: FC<VirtualMachinesOverviewTabDetailsPro
descriptionData={
<Split hasGutter isWrappable>
<SplitItem>
{vmPrintableStatus !== printableVMStatus.Migrating ? (
<VirtualMachineOverviewStatus vmPrintableStatus={vmPrintableStatus} />
) : (
<>
<MigrationProgressPopover vmi={vmi}>
<StatusPopoverButton vmPrintableStatus={vmPrintableStatus} />
</MigrationProgressPopover>
<VirtualMachineMigrationPercentage vm={vm} />
</>
<StatusPopover vm={vm} vmi={vmi} />
{vmPrintableStatus === printableVMStatus.Migrating && (
<VirtualMachineMigrationPercentage vm={vm} />
)}
</SplitItem>
<VMNotMigratableLabel vm={vm} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ const MigrationProgressPopover: React.FC<MigrationProgressPopoverProps> = ({ chi
setMinutes(0);
}
}, [vmi?.status?.migrationState?.endTimestamp, vmi?.status?.migrationState?.startTimestamp]);

return (
<Popover
bodyContent={
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,20 @@ import React, { FC } from 'react';
import { Link } from 'react-router-dom-v5-compat';
import { useLocation } from 'react-router-dom-v5-compat';

import { V1VirtualMachine } from '@kubevirt-ui/kubevirt-api/kubevirt';
import { useKubevirtTranslation } from '@kubevirt-utils/hooks/useKubevirtTranslation';
import { NO_DATA_DASH } from '@kubevirt-utils/resources/vm/utils/constants';
import { Popover, PopoverPosition, Text } from '@patternfly/react-core';
import { createURL } from '@virtualmachines/details/tabs/overview/utils/utils';

import StatusPopoverButton from '../StatusPopoverButton/StatusPopoverButton';

type VirtualMachineOverviewStatusProps = {
vmPrintableStatus: string;
vm: V1VirtualMachine;
};

const VirtualMachineOverviewStatus: FC<VirtualMachineOverviewStatusProps> = ({
vmPrintableStatus,
}) => {
const VirtualMachineOverviewStatus: FC<VirtualMachineOverviewStatusProps> = ({ children, vm }) => {
const { t } = useKubevirtTranslation();
const location = useLocation();
const vmPrintableStatus = vm?.status?.printableStatus;

if (!vmPrintableStatus) return <>{NO_DATA_DASH}</>;

Expand All @@ -40,7 +38,7 @@ const VirtualMachineOverviewStatus: FC<VirtualMachineOverviewStatusProps> = ({
headerContent={vmPrintableStatus}
position={PopoverPosition.right}
>
<StatusPopoverButton vmPrintableStatus={vmPrintableStatus} />
<>{children}</>
</Popover>
</>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import React, { FC } from 'react';
import { Link } from 'react-router-dom-v5-compat';
import { useLocation } from 'react-router-dom-v5-compat';

import { V1VirtualMachine } from '@kubevirt-ui/kubevirt-api/kubevirt';
import { useKubevirtTranslation } from '@kubevirt-utils/hooks/useKubevirtTranslation';
import { Popover, PopoverPosition, Progress, ProgressSize, Text } from '@patternfly/react-core';
import { createURL } from '@virtualmachines/details/tabs/overview/utils/utils';

import useProvisioningPercentage from '../../../../../../../../../utils/resources/vm/hooks/useProvisioningPercentage';

import './virtualmachine-provisioning-status.scss';

type VirtualMachineProvisioningStatusProps = {
vm: V1VirtualMachine;
};

const VirtualMachineProvisioningStatus: FC<VirtualMachineProvisioningStatusProps> = ({
children,
vm,
}) => {
const vmPrintableStatus = vm?.status?.printableStatus;

const { t } = useKubevirtTranslation();
const { percentages } = useProvisioningPercentage(vm);

const numberOfProvisioningDisks = Object.keys(percentages).length;

const location = useLocation();

return (
<>
<Popover
bodyContent={
<>
<Text>{t('VirtualMachine is currently provisioning')}</Text>
<br />

{Object.keys(percentages).map((diskName) => (
<Progress
className="progress"
key={diskName}
size={ProgressSize.lg}
title={numberOfProvisioningDisks > 1 ? diskName : t('Copying files')}
value={parseFloat(percentages[diskName])}
/>
))}
<br />
<Text>
<Link to={createURL('diagnostics', location?.pathname)}>{t('View diagnostic')}</Link>
</Text>
</>
}
className="virtualmachine-privisioning-status"
headerContent={vmPrintableStatus}
position={PopoverPosition.right}
>
<>{children}</>
</Popover>
</>
);
};

export default VirtualMachineProvisioningStatus;
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React, { FC } from 'react';

import { V1VirtualMachine, V1VirtualMachineInstance } from '@kubevirt-ui/kubevirt-api/kubevirt';
import { printableVMStatus } from '@virtualmachines/utils';

import MigrationProgressPopover from './MigrationProgressPopover';
import StatusPopoverButton from './StatusPopoverButton';
import VirtualMachineOverviewStatus from './VirtualMachineOverviewStatus';
import VirtualMachineProvisioningStatus from './VirtualMachineProvisioningStatus';

const Popovers = {
[printableVMStatus.Migrating]: MigrationProgressPopover,
[printableVMStatus.Provisioning]: VirtualMachineProvisioningStatus,
};

type StatusWithPopoverProps = {
vm: V1VirtualMachine;
vmi: V1VirtualMachineInstance;
};

const StatusWithPopover: FC<StatusWithPopoverProps> = ({ vm, vmi }) => {
const vmPrintableStatus = vm?.status?.printableStatus;

const Popover: FC<StatusWithPopoverProps> =
Popovers[vmPrintableStatus] || VirtualMachineOverviewStatus;

return (
<Popover vm={vm} vmi={vmi}>
<StatusPopoverButton vmPrintableStatus={vmPrintableStatus} />
</Popover>
);
};

export default StatusWithPopover;
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.virtualmachine-privisioning-status {
.progress:not(:first-child) {
margin-top: var(--pf-global--spacer--sm);
}
}

0 comments on commit fb71410

Please sign in to comment.