diff --git a/pkg/harvester/config/feature-flags.js b/pkg/harvester/config/feature-flags.js index ed611205..c9b504b2 100644 --- a/pkg/harvester/config/feature-flags.js +++ b/pkg/harvester/config/feature-flags.js @@ -51,7 +51,8 @@ const featuresV150 = [ 'tpmPersistentState', 'efiPersistentState', 'untaggedNetworkSetting', - 'skipSingleReplicaDetachedVol' + 'skipSingleReplicaDetachedVol', + 'thirdPartyStorage' ]; export const RELEASE_FEATURES = { diff --git a/pkg/harvester/edit/harvesterhci.io.virtualmachineimage.vue b/pkg/harvester/edit/harvesterhci.io.virtualmachineimage.vue index 094dafc8..b7871c38 100644 --- a/pkg/harvester/edit/harvesterhci.io.virtualmachineimage.vue +++ b/pkg/harvester/edit/harvesterhci.io.virtualmachineimage.vue @@ -16,6 +16,7 @@ import { STORAGE_CLASS } from '@shell/config/types'; import { VM_IMAGE_FILE_FORMAT } from '../validators/vm-image'; import { OS } from '../mixins/harvester-vm'; import { HCI } from '../types'; +import { LVM_DRIVER } from '../models/harvester/storage.k8s.io.storageclass'; const ENCRYPT = 'encrypt'; const DECRYPT = 'decrypt'; @@ -161,9 +162,10 @@ export default { storageClassOptions() { const storages = this.value.spec?.securityParameters?.cryptoOperation === ENCRYPT ? this.encryptedStorageClasses : this.nonEncryptedStorageClasses; + const filteredStorages = this.value.thirdPartyStorageFeatureEnabled ? storages.filter((s) => !s.parameters?.backingImage) : storages + .filter((s) => !s.parameters?.backingImage && s.provisioner !== LVM_DRIVER) ; - return storages - .filter((s) => !s.parameters?.backingImage) + return filteredStorages .map((s) => { const label = s.isDefault ? `${ s.name } (${ this.t('generic.default') })` : s.name; @@ -181,7 +183,9 @@ export default { set(nue) { this.value.metadata.annotations[HCI_ANNOTATIONS.STORAGE_CLASS] = nue; - this.value.spec.targetStorageClassName = nue; + if (this.value.thirdPartyStorageFeatureEnabled) { + this.value.spec.targetStorageClassName = nue; + } } }, sourceImageOptions() { @@ -264,7 +268,7 @@ export default { 'storageClassName'(neu) { const storageClass = this.storages.find((s) => s.id === neu); - if (storageClass) { + if (storageClass && this.value.thirdPartyStorageFeatureEnabled) { this.value.spec.backend = storageClass.isLonghornV1 ? 'backingimage' : 'cdi'; } } diff --git a/pkg/harvester/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/vmImage.vue b/pkg/harvester/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/vmImage.vue index a6980b18..80250c2a 100644 --- a/pkg/harvester/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/vmImage.vue +++ b/pkg/harvester/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/vmImage.vue @@ -90,7 +90,7 @@ export default { imagesOption() { return this.images.filter((c) => c.isReady).sort((a, b) => a.creationTimestamp > b.creationTimestamp ? -1 : 1).map( (I) => { return { - label: `${ I.metadata.namespace }/${ I.spec.displayName } (${ I.imageStorageClass } / ${ I.virtualSize })`, + label: this.imageOptionLabel(I), value: I.id }; }); @@ -116,6 +116,10 @@ export default { }); }, + thirdPartyStorageEnabled() { + return this.$store.getters['harvester-common/getFeatureEnabled']('thirdPartyStorage'); + }, + isLonghornV2() { return this.value.pvc?.isLonghornV2 || this.value.pvc?.storageClass?.isLonghornV2; }, @@ -131,7 +135,7 @@ export default { diskSize() { const size = this.value?.size || '0'; - return `${ size.replace('Gi', '') } GiB`; + return `${ size.replace('Gi', '') } GB`; }, imageVirtualSizeInByte() { @@ -143,6 +147,10 @@ export default { }, showDiskTooSmallError() { + if (!this.thirdPartyStorageEnabled ) { + return false; + } + return this.imageVirtualSizeInByte > this.diskSizeInByte; } }, @@ -184,6 +192,15 @@ export default { }, methods: { + imageOptionLabel(image) { + let label = `${ image.metadata.namespace }/${ image.spec.displayName }`; + + if (this.thirdPartyStorageEnabled) { + label += ` (${ image.imageStorageClass } / ${ image.virtualSize })`; + } + + return label; + }, update() { this.value.hasDiskError = this.showDiskTooSmallError; this.$emit('update'); diff --git a/pkg/harvester/models/harvester/storage.k8s.io.storageclass.js b/pkg/harvester/models/harvester/storage.k8s.io.storageclass.js index 65fafd54..2470e542 100644 --- a/pkg/harvester/models/harvester/storage.k8s.io.storageclass.js +++ b/pkg/harvester/models/harvester/storage.k8s.io.storageclass.js @@ -77,4 +77,8 @@ export default class HciStorageClass extends StorageClass { get volumeEncryptionFeatureEnabled() { return this.$rootGetters['harvester-common/getFeatureEnabled']('volumeEncryption'); } + + get thirdPartyStorageFeatureEnabled() { + return this.$rootGetters['harvester-common/getFeatureEnabled']('thirdPartyStorage'); + } } diff --git a/pkg/harvester/models/harvesterhci.io.virtualmachineimage.js b/pkg/harvester/models/harvesterhci.io.virtualmachineimage.js index 89935ccc..1410775f 100644 --- a/pkg/harvester/models/harvesterhci.io.virtualmachineimage.js +++ b/pkg/harvester/models/harvesterhci.io.virtualmachineimage.js @@ -243,8 +243,8 @@ export default class HciVmImage extends HarvesterResource { return formatSi(size, { increment: 1024, maxPrecision: 2, - suffix: 'iB', - firstSuffix: 'iB', + suffix: 'B', + firstSuffix: 'B', }); } @@ -258,8 +258,8 @@ export default class HciVmImage extends HarvesterResource { return formatSi(virtualSize, { increment: 1024, maxPrecision: 2, - suffix: 'iB', - firstSuffix: 'iB', + suffix: 'B', + firstSuffix: 'B', }); } @@ -389,6 +389,10 @@ export default class HciVmImage extends HarvesterResource { return this.$rootGetters['harvester-common/getFeatureEnabled']('volumeEncryption'); } + get thirdPartyStorageFeatureEnabled() { + return this.$rootGetters['harvester-common/getFeatureEnabled']('thirdPartyStorage'); + } + download() { window.location.href = this.links.download; } diff --git a/pkg/harvester/models/kubevirt.io.virtualmachine.js b/pkg/harvester/models/kubevirt.io.virtualmachine.js index 103e32ba..cc23dcc0 100644 --- a/pkg/harvester/models/kubevirt.io.virtualmachine.js +++ b/pkg/harvester/models/kubevirt.io.virtualmachine.js @@ -1183,6 +1183,10 @@ export default class VirtVm extends HarvesterResource { return this.$rootGetters['harvester-common/getFeatureEnabled']('efiPersistentState'); } + get thirdPartyStorageFeatureEnabled() { + return this.$rootGetters['harvester-common/getFeatureEnabled']('thirdPartyStorage'); + } + setInstanceLabels(val) { if ( !this.spec?.template?.metadata?.labels ) { set(this, 'spec.template.metadata.labels', {});