Skip to content

Commit

Permalink
CNV-43096: Customize disk size instancetype
Browse files Browse the repository at this point in the history
  • Loading branch information
upalatucci committed Jul 16, 2024
1 parent 2ec57bf commit efb3778
Show file tree
Hide file tree
Showing 12 changed files with 180 additions and 32 deletions.
6 changes: 4 additions & 2 deletions src/utils/components/DiskModal/DiskModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import { DiskFormState, DiskModalProps } from './utils/types';

const DiskModal: FC<DiskModalProps> = ({
createOwnerReference = true,
customize = false,
headerText,
initialFormData = null,
isEditingCreatedDisk = false,
Expand Down Expand Up @@ -69,7 +70,8 @@ const DiskModal: FC<DiskModalProps> = ({
}}
onSubmit={() =>
handleSubmit((data) => {
if (isEditingCreatedDisk) return editVMDisk(vm, initialFormData, data, onSubmit);
if (isEditingCreatedDisk || customize)
return editVMDisk(vm, initialFormData, data, onSubmit);

if (!isEmpty(initialFormData))
return editDisk(initialFormData, data, uploadData, {
Expand Down Expand Up @@ -111,7 +113,7 @@ const DiskModal: FC<DiskModalProps> = ({
relevantUpload={upload}
vm={vm}
/>
<DiskSizeInput isEditingCreatedDisk={isEditingCreatedDisk} />
<DiskSizeInput customize={customize} isEditingCreatedDisk={isEditingCreatedDisk} />
<DiskTypeSelect isVMRunning={isVMRunning} />
<DiskInterfaceSelect isVMRunning={isVMRunning} />
<StorageClassAndPreallocation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ import { diskSizeField, diskSourceField } from '../utils/constants';

import DynamicSize from './DynamicSize';

type DiskSizeInputProps = { isEditingCreatedDisk: boolean };
type DiskSizeInputProps = { customize?: boolean; isEditingCreatedDisk: boolean };

const DiskSizeInput: FC<DiskSizeInputProps> = ({ isEditingCreatedDisk }) => {
const DiskSizeInput: FC<DiskSizeInputProps> = ({ customize, isEditingCreatedDisk }) => {
const { t } = useKubevirtTranslation();
const { control, watch } = useFormContext<DiskFormState>();
const diskSource = watch(diskSourceField);

if (SourceTypes.PVC === diskSource || SourceTypes.OTHER === diskSource) {
if (SourceTypes.PVC === diskSource || (SourceTypes.OTHER === diskSource && !customize)) {
return null;
}

Expand Down
14 changes: 14 additions & 0 deletions src/utils/components/DiskModal/utils/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,20 @@ export const editVMDisk = (
delete vmDisks[diskIndexEdited].bootOrder;
}

if (
initialDiskFormState.diskSize !== newDiskFormState.diskSize &&
newDiskFormState.diskSource === SourceTypes.OTHER
) {
const sourceDataVolume = getDataVolumeTemplates(vmDraft)?.find(
(dv) => getName(dv) === volumeEdited?.dataVolume?.name,
);

if (sourceDataVolume)
sourceDataVolume.spec.storage = {
resources: { requests: { storage: newDiskFormState.diskSize } },
};
}

return vmDraft;
});

Expand Down
1 change: 1 addition & 0 deletions src/utils/components/DiskModal/utils/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ export type DiskFormState = {

export type DiskModalProps = {
createOwnerReference?: boolean;
customize?: boolean;
headerText: string;
initialFormData?: DiskFormState;
isEditingCreatedDisk?: boolean;
Expand Down
95 changes: 95 additions & 0 deletions src/utils/resources/vm/hooks/disk/useDisksSources.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { useMemo } from 'react';

import { V1beta1DataSource } from '@kubevirt-ui/kubevirt-api/containerized-data-importer/models';
import { IoK8sApiCoreV1PersistentVolume } from '@kubevirt-ui/kubevirt-api/kubernetes';
import { V1VirtualMachine } from '@kubevirt-ui/kubevirt-api/kubevirt';
import {
DataSourceModelGroupVersionKind,
modelToGroupVersionKind,
PersistentVolumeClaimModel,
} from '@kubevirt-utils/models';
import { isEmpty } from '@kubevirt-utils/utils/utils';
import { useK8sWatchResources } from '@openshift-console/dynamic-plugin-sdk';

import { getDataVolumeTemplates } from '../../utils';

const PersistentVolumeClaimGroupVersionKind = modelToGroupVersionKind(PersistentVolumeClaimModel);

const useDisksSources = (vm: V1VirtualMachine) => {
const dataSourcesWatch = useMemo(
() =>
getDataVolumeTemplates(vm)
?.map((dataVolume) => dataVolume?.spec?.sourceRef)
.filter((sourceRef) => Boolean(sourceRef))
.reduce((acc, dataSource) => {
acc[`${dataSource.name}-${dataSource.namespace}`] = {
groupVersionKind: DataSourceModelGroupVersionKind,
name: dataSource.name,
namespace: dataSource.namespace,
};

return acc;
}, {}),
[vm],
);

const dataSourcesWatchResult = useK8sWatchResources<{ [key: string]: V1beta1DataSource }>(
dataSourcesWatch,
);

const dataSources = useMemo(
() =>
Object.values(dataSourcesWatchResult || [])
.map((watch) => watch.data)
.filter((data) => !isEmpty(data)),
[dataSourcesWatchResult],
);

const pvcWatches = useMemo(() => {
const pvcSources = getDataVolumeTemplates(vm)
?.map((dataVolume) => dataVolume?.spec?.source?.pvc)
.filter((pvcSource) => !isEmpty(pvcSource));

pvcSources.push(
...dataSources
.map((dataSource) => dataSource?.spec?.source?.pvc)
.filter((pvcSource) => !isEmpty(pvcSource)),
);

return pvcSources.reduce((acc, pvcSource) => {
acc[`${pvcSource.name}-${pvcSource.namespace}`] = {
groupVersionKind: PersistentVolumeClaimGroupVersionKind,
name: pvcSource.name,
namespace: pvcSource.namespace,
};

return acc;
}, {});
}, [vm, dataSources]);

const pvcWatchesResult = useK8sWatchResources<{ [key: string]: IoK8sApiCoreV1PersistentVolume }>(
pvcWatches,
);

const pvcs = useMemo(
() =>
Object.values(pvcWatchesResult || [])
.map((watch) => watch.data)
.filter((data) => !isEmpty(data)),
[pvcWatchesResult],
);

const loaded = [
...Object.values(dataSourcesWatchResult),
...Object.values(pvcWatchesResult),
].every((watch) => watch.loaded);

const loadingError = [
...Object.values(dataSourcesWatchResult),
...Object.values(pvcWatchesResult),
].find((watch) => watch.loadError);

return { dataSources, loaded, loadingError, pvcs };
};

export default useDisksSources;
40 changes: 27 additions & 13 deletions src/utils/resources/vm/hooks/disk/useDisksTableData.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
import { useMemo } from 'react';
import { isRunning } from 'src/views/virtualmachines/utils';

import { IoK8sApiCoreV1PersistentVolumeClaim } from '@kubevirt-ui/kubevirt-api/kubernetes';
import { V1VirtualMachine, V1VirtualMachineInstance } from '@kubevirt-ui/kubevirt-api/kubevirt';
import {
getRunningVMMissingDisksFromVMI,
getRunningVMMissingVolumesFromVMI,
} from '@kubevirt-utils/components/DiskModal/utils/helpers';
import { ROOTDISK } from '@kubevirt-utils/constants/constants';
import { PersistentVolumeClaimModel } from '@kubevirt-utils/models';
import { getName, getNamespace } from '@kubevirt-utils/resources/shared';
import { DiskRawData, DiskRowDataLayout } from '@kubevirt-utils/resources/vm/utils/disk/constants';
import { useK8sWatchResource } from '@openshift-console/dynamic-plugin-sdk';

import { getBootDisk, getDisks, getInstanceTypeMatcher, getVolumes } from '../../utils';
import {
getBootDisk,
getDataVolumeTemplates,
getDisks,
getInstanceTypeMatcher,
getVolumes,
} from '../../utils';
import { getDiskRowDataLayout } from '../../utils/disk/rowData';

import useDisksSources from './useDisksSources';

type UseDisksTableDisks = (
vm: V1VirtualMachine,
vmi: V1VirtualMachineInstance,
Expand Down Expand Up @@ -47,12 +53,7 @@ const useDisksTableData: UseDisksTableDisks = (vm, vmi) => {
[vm, vmi, isVMRunning],
);

const [pvcs, loaded, loadingError] = useK8sWatchResource<IoK8sApiCoreV1PersistentVolumeClaim[]>({
isList: true,
kind: PersistentVolumeClaimModel.kind,
namespace: vm?.metadata?.namespace,
namespaced: true,
});
const { dataSources, loaded, loadingError, pvcs } = useDisksSources(vm);

const disks = useMemo(() => {
const isInstanceTypeVM = Boolean(getInstanceTypeMatcher(vm));
Expand All @@ -63,16 +64,29 @@ const useDisksTableData: UseDisksTableDisks = (vm, vmi) => {
? { name: ROOTDISK }
: vmDisks?.find(({ name }) => name === volume?.name);

const dataVolumeTemplate = volume?.dataVolume?.name
? getDataVolumeTemplates(vm)?.find((dv) => getName(dv) === volume.dataVolume.name)
: null;

const sourceRef = dataVolumeTemplate?.spec?.sourceRef;

const dataSource = dataSources.find(
(ds) => getName(ds) === sourceRef?.name && getNamespace(ds) === sourceRef?.namespace,
);

const pvc = pvcs?.find(
({ metadata }) =>
metadata?.name === volume?.persistentVolumeClaim?.claimName ||
metadata?.name === volume?.dataVolume?.name,
metadata?.name === volume?.dataVolume?.name ||
(dataSource?.spec?.source?.pvc?.name === metadata?.name &&
dataSource?.spec?.source?.pvc?.namespace === metadata?.namespace),
);
return { disk, pvc, volume };

return { dataVolumeTemplate, disk, pvc, volume };
});

return getDiskRowDataLayout(diskDevices, getBootDisk(vm));
}, [vmVolumes, vm, vmDisks, pvcs]);
}, [vm, vmVolumes, vmDisks, pvcs, dataSources]);

return [disks || [], loaded, loadingError, isVMRunning ? vmi : null];
};
Expand Down
9 changes: 6 additions & 3 deletions src/utils/resources/vm/utils/disk/rowData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
DYNAMIC,
OTHER,
} from '@kubevirt-utils/components/DiskModal/components/utils/constants';
import { SourceTypes } from '@kubevirt-utils/components/DiskModal/utils/types';
import { VolumeTypes } from '@kubevirt-utils/components/DiskModal/utils/types';
import { DiskRawData, DiskRowDataLayout } from '@kubevirt-utils/resources/vm/utils/disk/constants';
import {
getPrintableDiskDrive,
Expand Down Expand Up @@ -47,12 +47,15 @@ export const getDiskRowDataLayout = (
diskRowDataObject.source = device?.pvc?.metadata?.name;
diskRowDataObject.sourceStatus = device?.pvc?.status?.phase;
diskRowDataObject.size = humanizeBinaryBytes(
convertToBaseValue(device?.pvc?.spec?.resources?.requests?.storage),
convertToBaseValue(
device?.dataVolumeTemplate?.spec?.storage?.resources?.requests?.storage ||
device?.pvc?.spec?.resources?.requests?.storage,
),
).string;
diskRowDataObject.storageClass = device?.pvc?.spec?.storageClassName;
}

if (volumeSource === SourceTypes.EPHEMERAL) {
if (volumeSource === VolumeTypes.CONTAINER_DISK) {
diskRowDataObject.source = CONTAINER_EPHERMAL;
diskRowDataObject.size = DYNAMIC;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ const CustomizeInstanceTypeStorageTab = () => {

return Promise.resolve(vmModified);
}}
customize
vm={vm}
/>
</PageSection>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,13 @@ import DiskRow from './DiskRow';
import './disklist.scss';

type DiskListProps = {
customize?: boolean;
onDiskUpdate?: (updatedVM: V1VirtualMachine) => Promise<V1VirtualMachine>;
vm: V1VirtualMachine;
vmi?: V1VirtualMachineInstance;
};

const DiskList: FC<DiskListProps> = ({ onDiskUpdate, vm, vmi }) => {
const DiskList: FC<DiskListProps> = ({ customize = false, onDiskUpdate, vm, vmi }) => {
const { t } = useKubevirtTranslation();
const { createModal } = useModal();
const columns = useDiskColumns();
Expand Down Expand Up @@ -88,7 +89,7 @@ const DiskList: FC<DiskListProps> = ({ onDiskUpdate, vm, vmi }) => {
loaded={loaded}
loadError={loadError}
Row={DiskRow}
rowData={{ onSubmit, provisioningPercentages, vm, vmi }}
rowData={{ customize, onSubmit, provisioningPercentages, vm, vmi }}
unfilteredData={data}
/>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,18 @@ const DiskRow: FC<
RowProps<
DiskRowDataLayout,
{
customize?: boolean;
onSubmit?: (updatedVM: V1VirtualMachine) => Promise<V1VirtualMachine>;
provisioningPercentages: NameWithPercentages;
vm: V1VirtualMachine;
vmi?: V1VirtualMachineInstance;
}
>
> = ({ activeColumnIDs, obj, rowData: { onSubmit, provisioningPercentages, vm, vmi } }) => {
> = ({
activeColumnIDs,
obj,
rowData: { customize = false, onSubmit, provisioningPercentages, vm, vmi },
}) => {
const { t } = useKubevirtTranslation();

const provisioningPercentage = provisioningPercentages?.[obj?.source];
Expand Down Expand Up @@ -94,7 +99,7 @@ const DiskRow: FC<
className="dropdown-kebab-pf pf-v5-c-table__action"
id=""
>
<DiskRowActions obj={obj} onDiskUpdate={onSubmit} vm={vm} vmi={vmi} />
<DiskRowActions customize={customize} obj={obj} onDiskUpdate={onSubmit} vm={vm} vmi={vmi} />
</TableData>
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,20 @@ import { getEditDiskStates } from './utils/getEditDiskStates';
import { isHotplugVolume, isPVCSource, isPVCStatusBound } from './utils/helpers';

type DiskRowActionsProps = {
customize?: boolean;
obj: DiskRowDataLayout;
onDiskUpdate?: (updatedVM: V1VirtualMachine) => Promise<V1VirtualMachine>;
vm: V1VirtualMachine;
vmi?: V1VirtualMachineInstance;
};

const DiskRowActions: FC<DiskRowActionsProps> = ({ obj, onDiskUpdate, vm, vmi }) => {
const DiskRowActions: FC<DiskRowActionsProps> = ({
customize = false,
obj,
onDiskUpdate,
vm,
vmi,
}) => {
const { t } = useKubevirtTranslation();
const { createModal } = useModal();
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
Expand All @@ -38,7 +45,7 @@ const DiskRowActions: FC<DiskRowActionsProps> = ({ obj, onDiskUpdate, vm, vmi })
const isHotplug = isHotplugVolume(vm, diskName, vmi);
const isEditDisabled = isVMRunning;

const initialFormState = !isEditDisabled && getEditDiskStates(vm, diskName, vmi);
const initialFormState = !isEditDisabled && getEditDiskStates(vm, obj, vmi);
const volumes = isVMRunning ? vmi?.spec?.volumes : getVolumes(vm);
const volume = volumes?.find(({ name }) => name === diskName);

Expand All @@ -56,9 +63,10 @@ const DiskRowActions: FC<DiskRowActionsProps> = ({ obj, onDiskUpdate, vm, vmi })
const createEditDiskModal = () =>
createModal(({ isOpen, onClose }) => (
<DiskModal
customize={customize}
headerText={t('Edit disk')}
initialFormData={initialFormState}
isEditingCreatedDisk={pvcResourceExists}
isEditingCreatedDisk={!customize && pvcResourceExists}
isOpen={isOpen}
onClose={onClose}
onSubmit={onDiskUpdate || updateDisks}
Expand Down
Loading

0 comments on commit efb3778

Please sign in to comment.