Skip to content

Commit

Permalink
Bug 2100684: Edit workload vm
Browse files Browse the repository at this point in the history
  • Loading branch information
upalatucci committed Jul 7, 2022
1 parent a57518e commit 625f0dd
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 22 deletions.
Original file line number Diff line number Diff line change
@@ -1,29 +1,23 @@
import * as React from 'react';
import { getTemplateWorkload } from 'src/views/templates/utils/selectors';

import { V1Template } from '@kubevirt-ui/kubevirt-api/console';
import TabModal from '@kubevirt-utils/components/TabModal/TabModal';
import { useKubevirtTranslation } from '@kubevirt-utils/hooks/useKubevirtTranslation';
import { WORKLOADS, WORKLOADS_LABELS } from '@kubevirt-utils/resources/template';
import { K8sResourceCommon } from '@openshift-console/dynamic-plugin-sdk';
import { Form, FormGroup, Select, SelectOption } from '@patternfly/react-core';

import './cpu-memory-modal.scss';

type WorkloadProfileModalProps = {
obj: V1Template;
initialWorkload: string;
isOpen: boolean;
onClose: () => void;
onSubmit: (workload: string) => Promise<void | K8sResourceCommon>;
};

const WorkloadProfileModal: React.FC<WorkloadProfileModalProps> = React.memo(
({ obj, isOpen, onClose, onSubmit }) => {
({ initialWorkload, isOpen, onClose, onSubmit }) => {
const { t } = useKubevirtTranslation();
const [isDropdownOpen, setIsDropdownOpen] = React.useState<boolean>(false);
const [workload, setWorkload] = React.useState<string>(
getTemplateWorkload(obj) || WORKLOADS.desktop,
);
const [workload, setWorkload] = React.useState<string>(initialWorkload || WORKLOADS.desktop);

const handleChange = (event: React.ChangeEvent<HTMLSelectElement>, value: WORKLOADS) => {
event.preventDefault();
Expand All @@ -35,7 +29,6 @@ const WorkloadProfileModal: React.FC<WorkloadProfileModalProps> = React.memo(
<TabModal
headerText={t('Edit Workload profile')}
isOpen={isOpen}
obj={obj}
onClose={onClose}
onSubmit={() => onSubmit(workload)}
>
Expand Down
10 changes: 10 additions & 0 deletions src/utils/resources/vm/utils/selectors.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { V1Disk, V1VirtualMachine } from '@kubevirt-ui/kubevirt-api/kubevirt';
import { getAnnotation } from '@kubevirt-utils/resources/shared';

import { VM_WORKLOAD_ANNOTATION } from './annotations';

/**
* A selector for the virtual machine's networks
Expand Down Expand Up @@ -126,3 +129,10 @@ export const getBootDisk = (vm: V1VirtualMachine): V1Disk =>
*/
export const getMachineType = (vm: V1VirtualMachine): string =>
vm?.spec?.template?.spec?.domain?.machine?.type;

/**
* A selector that returns the workload of a given virtual machine
* @param {V1VirtualMachine} vm the virtual machine
*/
export const getWorkload = (vm: V1VirtualMachine): string =>
getAnnotation(vm?.spec?.template, VM_WORKLOAD_ANNOTATION);
31 changes: 29 additions & 2 deletions src/views/catalog/wizard/tabs/overview/WizardOverviewTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,17 @@ import FirmwareBootloaderModal from '@kubevirt-utils/components/FirmwareBootload
import { getBootloaderTitleFromVM } from '@kubevirt-utils/components/FirmwareBootloaderModal/utils/utils';
import HardwareDevices from '@kubevirt-utils/components/HardwareDevices/HardwareDevices';
import { useModal } from '@kubevirt-utils/components/ModalProvider/ModalProvider';
import WorkloadProfileModal from '@kubevirt-utils/components/WorkloadProfileModal/WorkloadProfileModal';
import { useKubevirtTranslation } from '@kubevirt-utils/hooks/useKubevirtTranslation';
import { getAnnotation } from '@kubevirt-utils/resources/shared';
import { getVmCPUMemory, WORKLOADS_LABELS } from '@kubevirt-utils/resources/template';
import { getGPUDevices, getHostDevices, getMachineType } from '@kubevirt-utils/resources/vm';
import {
getGPUDevices,
getHostDevices,
getMachineType,
getWorkload,
VM_WORKLOAD_ANNOTATION,
} from '@kubevirt-utils/resources/vm';
import { readableSizeUnit } from '@kubevirt-utils/utils/units';
import { DescriptionList, Grid, GridItem } from '@patternfly/react-core';

Expand All @@ -30,7 +37,7 @@ const WizardOverviewTab: WizardTab = ({ vm, tabsData, updateVM }) => {

const { cpuCount, memory } = getVmCPUMemory(vm);
const description = getAnnotation(vm, 'description');
const workloadAnnotation = vm?.spec?.template?.metadata?.annotations?.['vm.kubevirt.io/workload'];
const workloadAnnotation = getWorkload(vm);
const networks = vm?.spec?.template?.spec?.networks;
const interfaces = vm?.spec?.template?.spec?.domain?.devices?.interfaces;
const disks = vm?.spec?.template?.spec?.domain?.devices?.disks;
Expand All @@ -40,6 +47,15 @@ const WizardOverviewTab: WizardTab = ({ vm, tabsData, updateVM }) => {
const gpusCount = getGPUDevices(vm)?.length || 0;
const nDevices = hostDevicesCount + gpusCount;

const updateWorkload = async (newWorkload: string) => {
return updateVM((draftVM) => {
if (!draftVM.spec.template.metadata?.annotations)
draftVM.spec.template.metadata.annotations = {};

draftVM.spec.template.metadata.annotations[VM_WORKLOAD_ANNOTATION] = newWorkload;
});
};

return (
<div className="co-m-pane__body">
<Grid hasGutter>
Expand Down Expand Up @@ -141,6 +157,17 @@ const WizardOverviewTab: WizardTab = ({ vm, tabsData, updateVM }) => {
<WizardDescriptionItem
className="wizard-overview-description-left-column"
title={t('Workload profile')}
isEdit
onEditClick={() =>
createModal(({ isOpen, onClose }) => (
<WorkloadProfileModal
initialWorkload={workloadAnnotation}
isOpen={isOpen}
onClose={onClose}
onSubmit={updateWorkload}
/>
))
}
description={WORKLOADS_LABELS?.[workloadAnnotation] ?? t('Other')}
testId="wizard-overview-workload-profile"
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ import { getWorkloadProfile } from 'src/views/templates/utils/selectors';
import { TemplateModel } from '@kubevirt-ui/kubevirt-api/console';
import VirtualMachineModel from '@kubevirt-ui/kubevirt-api/console/models/VirtualMachineModel';
import { useModal } from '@kubevirt-utils/components/ModalProvider/ModalProvider';
import WorkloadProfileModal from '@kubevirt-utils/components/WorkloadProfileModal/WorkloadProfileModal';
import { useKubevirtTranslation } from '@kubevirt-utils/hooks/useKubevirtTranslation';
import {
getTemplateWorkload,
TEMPLATE_WORKLOAD_LABEL,
WORKLOADS,
} from '@kubevirt-utils/resources/template';
import { getWorkload } from '@kubevirt-utils/resources/vm';
import { k8sPatch } from '@openshift-console/dynamic-plugin-sdk';
import {
Button,
Expand All @@ -21,8 +23,6 @@ import { PencilAltIcon } from '@patternfly/react-icons';

import { TemplateDetailsGridProps } from '../TemplateDetailsPage';

import WorkloadProfileModal from './WorkloadProfileModal';

const WorkloadProfile: React.FC<TemplateDetailsGridProps> = ({ template, editable }) => {
const { createModal } = useModal();
const { t } = useKubevirtTranslation();
Expand All @@ -32,10 +32,7 @@ const WorkloadProfile: React.FC<TemplateDetailsGridProps> = ({ template, editabl
const vmObjectIndex = template?.objects.findIndex(
(obj) => obj.kind === VirtualMachineModel.kind,
);
const hasWorkload =
template?.objects?.[vmObjectIndex]?.spec?.template?.metadata?.annotations?.[
'vm.kubevirt.io/workload'
];
const hasWorkload = getWorkload(template?.objects?.[vmObjectIndex]);
const workloadPath = `/objects/${vmObjectIndex}/spec/template/metadata/annotations/vm.kubevirt.io~1workload`;

return k8sPatch({
Expand Down Expand Up @@ -63,7 +60,7 @@ const WorkloadProfile: React.FC<TemplateDetailsGridProps> = ({ template, editabl
const onEditClick = () =>
createModal(({ isOpen, onClose }) => (
<WorkloadProfileModal
obj={template}
initialWorkload={getTemplateWorkload(template)}
isOpen={isOpen}
onClose={onClose}
onSubmit={updateWorkload}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as React from 'react';
import produce from 'immer';

import { NodeModel } from '@kubevirt-ui/kubevirt-api/console';
import VirtualMachineModel from '@kubevirt-ui/kubevirt-api/console/models/VirtualMachineModel';
Expand All @@ -9,9 +10,10 @@ import HardwareDevices from '@kubevirt-utils/components/HardwareDevices/Hardware
import { useModal } from '@kubevirt-utils/components/ModalProvider/ModalProvider';
import MutedTextSpan from '@kubevirt-utils/components/MutedTextSpan/MutedTextSpan';
import SSHAccessModal from '@kubevirt-utils/components/SSHAccess/SSHAccessModal';
import WorkloadProfileModal from '@kubevirt-utils/components/WorkloadProfileModal/WorkloadProfileModal';
import { useKubevirtTranslation } from '@kubevirt-utils/hooks/useKubevirtTranslation';
import { getAnnotation } from '@kubevirt-utils/resources/shared';
import { VM_WORKLOAD_ANNOTATION } from '@kubevirt-utils/resources/vm';
import { WORKLOADS, WORKLOADS_LABELS } from '@kubevirt-utils/resources/template';
import { getWorkload, VM_WORKLOAD_ANNOTATION } from '@kubevirt-utils/resources/vm';
import { k8sUpdate, K8sVerb, useAccessReview } from '@openshift-console/dynamic-plugin-sdk';
import { DescriptionList, GridItem } from '@patternfly/react-core';

Expand Down Expand Up @@ -52,6 +54,27 @@ const VirtualMachineDetailsRightGridLayout: React.FC<VirtualMachineDetailsRightG
}),
[],
);

const vmWorkload = getWorkload(vm);

const updateWorkload = (newWorkload: WORKLOADS) => {
if (vmWorkload === newWorkload) return Promise.resolve();

const updateVM = produce(vm, (draftVM) => {
if (!draftVM.spec.template.metadata?.annotations)
draftVM.spec.template.metadata.annotations = {};

draftVM.spec.template.metadata.annotations[VM_WORKLOAD_ANNOTATION] = newWorkload;
});

return k8sUpdate({
model: VirtualMachineModel,
data: updateVM,
ns: updateVM?.metadata?.namespace,
name: updateVM?.metadata?.name,
});
};

return (
<GridItem span={5}>
<DescriptionList>
Expand Down Expand Up @@ -103,10 +126,23 @@ const VirtualMachineDetailsRightGridLayout: React.FC<VirtualMachineDetailsRightG
)}
<VirtualMachineDescriptionItem
descriptionData={
getAnnotation(vm?.spec?.template, VM_WORKLOAD_ANNOTATION) || (
vmWorkload ? (
WORKLOADS_LABELS[vmWorkload] || vmWorkload
) : (
<MutedTextSpan text={t('Not available')} />
)
}
isEdit
onEditClick={() =>
createModal(({ isOpen, onClose }) => (
<WorkloadProfileModal
initialWorkload={vmWorkload}
isOpen={isOpen}
onClose={onClose}
onSubmit={updateWorkload}
/>
))
}
descriptionHeader={t('Workload Profile')}
data-test-id={`${vm?.metadata?.name}-workload-profile`}
/>
Expand Down

0 comments on commit 625f0dd

Please sign in to comment.