Skip to content

Commit

Permalink
CNV-23832: Apply boot StorageClass from Template's boot source
Browse files Browse the repository at this point in the history
Signed-off-by: Aviv Turgeman <[email protected]>
  • Loading branch information
avivtur committed Sep 12, 2023
1 parent efc7e34 commit 7729ed6
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ export const useVmTemplateSource = (template: V1Template): useVmTemplateSourceVa
setTemplateBootSource({
source: {
pvc: dataSource?.spec?.source?.pvc,
sourceRef: {
kind: dataSource?.kind,
name,
namespace,
},
},
storageClassName: pvc?.spec?.storageClassName,
type: BOOT_SOURCE.DATA_SOURCE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
LABEL_USED_TEMPLATE_NAME,
LABEL_USED_TEMPLATE_NAMESPACE,
} from '@kubevirt-utils/resources/template';
import { TemplateBootSource } from '@kubevirt-utils/resources/template/hooks/useVmTemplateSource/utils';
import { getMemoryCPU } from '@kubevirt-utils/resources/vm';
import { ensurePath, isEmpty } from '@kubevirt-utils/utils/utils';
import { k8sCreate } from '@openshift-console/dynamic-plugin-sdk';
Expand Down Expand Up @@ -61,6 +62,7 @@ type TemplatesCatalogDrawerCreateFormProps = {
onCancel: () => void;
subscriptionData: RHELAutomaticSubscriptionData;
template: V1Template;
templateBootSource: TemplateBootSource;
};

export const TemplatesCatalogDrawerCreateForm: FC<TemplatesCatalogDrawerCreateFormProps> = memo(
Expand All @@ -73,6 +75,7 @@ export const TemplatesCatalogDrawerCreateForm: FC<TemplatesCatalogDrawerCreateFo
onCancel,
subscriptionData,
template,
templateBootSource,
}) => {
const history = useHistory();
const { t } = useKubevirtTranslation();
Expand All @@ -90,7 +93,7 @@ export const TemplatesCatalogDrawerCreateForm: FC<TemplatesCatalogDrawerCreateFo
verb: 'create',
});

const onQuickCreate = () => {
const onQuickCreate = async () => {
setIsQuickCreating(true);
setQuickCreateError(undefined);

Expand Down Expand Up @@ -126,7 +129,14 @@ export const TemplatesCatalogDrawerCreateForm: FC<TemplatesCatalogDrawerCreateFo

quickCreateVM({
models,
overrides: { authorizedSSHKey, name: vmName, namespace, startVM, subscriptionData },
overrides: {
authorizedSSHKey,
name: vmName,
namespace,
startVM,
subscriptionData,
templateBootSource,
},
template: templateToProcess,
})
.then((quickCreatedVM) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,12 @@ export const TemplatesCatalogDrawerFooter: FC<TemplateCatalogDrawerFooterProps>
template,
}) => {
const { t } = useKubevirtTranslation();
const { isBootSourceAvailable, loaded: bootSourceLoaded } = useVmTemplateSource(template);
const {
isBootSourceAvailable,
loaded: bootSourceLoaded,
templateBootSource,
} = useVmTemplateSource(template);

const [authorizedSSHKeys, updateAuthorizedSSHKeys, userSettingsLoaded] =
useKubevirtUserSettings('ssh');
const { loaded: loadedRHELSubscription, subscriptionData } = useRHELAutomaticSubscription();
Expand Down Expand Up @@ -109,6 +114,7 @@ export const TemplatesCatalogDrawerFooter: FC<TemplateCatalogDrawerFooterProps>
onCancel={onCancel}
subscriptionData={subscriptionData}
template={template}
templateBootSource={templateBootSource}
/>
</Stack>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { StorageClassModel } from '@kubevirt-ui/kubevirt-api/console';
import { IoK8sApiStorageV1StorageClassList } from '@kubevirt-ui/kubevirt-api/kubernetes';
import { V1VirtualMachine } from '@kubevirt-ui/kubevirt-api/kubevirt';
import { isDefaultStorageClass } from '@kubevirt-utils/components/DiskModal/DiskFormFields/utils/helpers';
import { getDataVolumeTemplates } from '@kubevirt-utils/resources/vm';
import { isEmpty } from '@kubevirt-utils/utils/utils';
import { k8sGet } from '@openshift-console/dynamic-plugin-sdk';

export const hasStorageClass = async (vm: V1VirtualMachine) => {
const vmSCExists = getDataVolumeTemplates(vm)?.some(
(dvt) => !!dvt?.spec?.storage?.storageClassName,
);
if (vmSCExists) return true;

const storageClasses = await k8sGet<IoK8sApiStorageV1StorageClassList>({
model: StorageClassModel,
});

const defaultSC = storageClasses?.items?.find((item) => isDefaultStorageClass(item));

return !isEmpty(defaultSC);
};
31 changes: 29 additions & 2 deletions src/views/catalog/utils/quick-create-vm.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import produce from 'immer';

import { hasStorageClass } from '@catalog/templatescatalog/components/TemplatesCatalogDrawer/utils/helpers';
import { ProcessedTemplatesModel, V1Template } from '@kubevirt-ui/kubevirt-api/console';
import VirtualMachineModel from '@kubevirt-ui/kubevirt-api/console/models/VirtualMachineModel';
import { V1VirtualMachine } from '@kubevirt-ui/kubevirt-api/kubevirt';
import { V1DataVolumeTemplateSpec, V1VirtualMachine } from '@kubevirt-ui/kubevirt-api/kubevirt';
import { updateCloudInitRHELSubscription } from '@kubevirt-utils/components/CloudinitModal/utils/cloudinit-utils';
import { isEqualObject } from '@kubevirt-utils/components/NodeSelectorModal/utils/helpers';
import { applyCloudDriveCloudInitVolume } from '@kubevirt-utils/components/SSHSecretSection/utils/utils';
import { addSecretToVM } from '@kubevirt-utils/components/SSHSecretSection/utils/utils';
import { DEFAULT_NAMESPACE } from '@kubevirt-utils/constants/constants';
Expand All @@ -13,7 +15,9 @@ import {
LABEL_USED_TEMPLATE_NAMESPACE,
replaceTemplateVM,
} from '@kubevirt-utils/resources/template';
import { TemplateBootSource } from '@kubevirt-utils/resources/template/hooks/useVmTemplateSource/utils';
import { getTemplateVirtualMachineObject } from '@kubevirt-utils/resources/template/utils/selectors';
import { getDataVolumeTemplates } from '@kubevirt-utils/resources/vm';
import { isEmpty } from '@kubevirt-utils/utils/utils';
import { k8sCreate, K8sModel } from '@openshift-console/dynamic-plugin-sdk';

Expand All @@ -27,13 +31,21 @@ type QuickCreateVMType = (inputs: {
namespace: string;
startVM: boolean;
subscriptionData: RHELAutomaticSubscriptionData;
templateBootSource: TemplateBootSource;
};
template: V1Template;
}) => Promise<V1VirtualMachine>;

export const quickCreateVM: QuickCreateVMType = async ({
models,
overrides: { authorizedSSHKey, name, namespace = DEFAULT_NAMESPACE, startVM, subscriptionData },
overrides: {
authorizedSSHKey,
name,
namespace = DEFAULT_NAMESPACE,
startVM,
subscriptionData,
templateBootSource,
},
template,
}) => {
const processedTemplate = await k8sCreate<V1Template>({
Expand All @@ -47,6 +59,8 @@ export const quickCreateVM: QuickCreateVMType = async ({

const vm = getTemplateVirtualMachineObject(processedTemplate);

const hasSC = await hasStorageClass(vm);

const overridedVM = produce(vm, (draftVM) => {
draftVM.metadata.namespace = namespace;
draftVM.metadata.name = name;
Expand All @@ -57,6 +71,19 @@ export const quickCreateVM: QuickCreateVMType = async ({
draftVM.spec.running = true;
}

if (!hasSC && templateBootSource?.storageClassName) {
const dataVolumeTemplates: V1DataVolumeTemplateSpec[] = getDataVolumeTemplates(vm).map(
(dvt) =>
isEqualObject(dvt?.spec?.sourceRef, templateBootSource?.source?.sourceRef)
? produce(dvt, (draftDVT) => {
draftDVT.spec.storage.storageClassName = templateBootSource?.storageClassName;
})
: dvt,
);

draftVM.spec.dataVolumeTemplates = dataVolumeTemplates;
}

const updatedVolumes = applyCloudDriveCloudInitVolume(vm);
draftVM.spec.template.spec.volumes = isRHELTemplate(processedTemplate)
? updateCloudInitRHELSubscription(updatedVolumes, subscriptionData)
Expand Down

0 comments on commit 7729ed6

Please sign in to comment.