diff --git a/pkg/harvester/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/container.vue b/pkg/harvester/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/container.vue
index 1c44ca1e..8372665a 100644
--- a/pkg/harvester/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/container.vue
+++ b/pkg/harvester/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/container.vue
@@ -114,7 +114,7 @@ export default {
c.isReady).sort((a, b) => a.creationTimestamp > b.creationTimestamp ? -1 : 1).map( (I) => {
return {
@@ -272,7 +283,7 @@ export default {
diff --git a/pkg/harvester/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/volume.vue b/pkg/harvester/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/volume.vue
index 14914834..5b7e764b 100644
--- a/pkg/harvester/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/volume.vue
+++ b/pkg/harvester/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/volume.vue
@@ -8,6 +8,9 @@ import LabeledSelect from '@shell/components/form/LabeledSelect';
import { PVC, STORAGE_CLASS } from '@shell/config/types';
import { formatSi, parseSi } from '@shell/utils/units';
import { VOLUME_TYPE, InterfaceOption } from '../../../../config/harvester-map';
+import { _VIEW } from '@shell/config/query-params';
+import LabelValue from '@shell/components/LabelValue';
+import { ucFirst } from '@shell/utils/string';
export default {
name: 'HarvesterEditVolume',
@@ -15,7 +18,7 @@ export default {
emits: ['update'],
components: {
- InputOrDisplay, Loading, LabeledInput, LabeledSelect, UnitInput,
+ InputOrDisplay, Loading, LabeledInput, LabeledSelect, UnitInput, LabelValue
},
props: {
@@ -61,6 +64,13 @@ export default {
},
computed: {
+ encryptionValue() {
+ return ucFirst(String(this.value.isEncrypted));
+ },
+
+ isView() {
+ return this.mode === _VIEW;
+ },
pvcsResource() {
const allPVCs = this.$store.getters['harvester/all'](PVC) || [];
@@ -215,7 +225,7 @@ export default {
diff --git a/pkg/harvester/l10n/en-us.yaml b/pkg/harvester/l10n/en-us.yaml
index 90886ba9..a96279cb 100644
--- a/pkg/harvester/l10n/en-us.yaml
+++ b/pkg/harvester/l10n/en-us.yaml
@@ -596,6 +596,10 @@ harvester:
addContainer: Add Container
setFirst: Set as root volume
saveVolume: Update Volume
+ encryption: Encryption
+ lockTooltip:
+ all: All volumes are encrypted
+ partial: Partial volumes are encrypted
title:
vmImage: Image Volume
existingVolume: Existing Volume
@@ -640,10 +644,6 @@ harvester:
userTips: The user to be added must already exist; otherwise, the credentials will not take effect.
duplicatedUser: User already exists.
invalidUser: Invalid Username.
- lockIconTooltip:
- image: Encrypted Image
- volume: Encrypted Volume
- both: Encrypted Image and Encrypted Volume
input:
name: Name
memory: Memory
diff --git a/pkg/harvester/list/kubevirt.io.virtualmachine.vue b/pkg/harvester/list/kubevirt.io.virtualmachine.vue
index f9b499f2..0501a210 100644
--- a/pkg/harvester/list/kubevirt.io.virtualmachine.vue
+++ b/pkg/harvester/list/kubevirt.io.virtualmachine.vue
@@ -173,15 +173,15 @@ export default {
methods: {
lockIconTooltipMessage(row) {
- if (row.isVMImageEncrypted && row.isVolumeEncrypted) {
- return this.t('harvester.virtualMachine.lockIconTooltip.both');
- } else if (row.isVMImageEncrypted) {
- return this.t('harvester.virtualMachine.lockIconTooltip.image');
- } else if (row.isVolumeEncrypted) {
- return this.t('harvester.virtualMachine.lockIconTooltip.volume');
+ const message = '';
+
+ if (row.encryptedVolumeType === 'all') {
+ return this.t('harvester.virtualMachine.volume.lockTooltip.all');
+ } else if (row.encryptedVolumeType === 'partial') {
+ return this.t('harvester.virtualMachine.volume.lockTooltip.partial');
}
- return '';
+ return message;
}
}
};
@@ -213,7 +213,12 @@ export default {
:to="scope.row.detailLocation"
>
{{ scope.row.metadata.name }}
-
+
{{ scope.row.metadata.name }}
@@ -234,6 +239,14 @@ export default {
}
}
+.green-icon {
+ color: var(--success);
+}
+
+.yellow-icon {
+ color: var(--warning);
+}
+
.name-console {
display: flex;
align-items: center;
diff --git a/pkg/harvester/mixins/harvester-vm/index.js b/pkg/harvester/mixins/harvester-vm/index.js
index 6a521a7e..e668add3 100644
--- a/pkg/harvester/mixins/harvester-vm/index.js
+++ b/pkg/harvester/mixins/harvester-vm/index.js
@@ -418,8 +418,10 @@ export default {
let size = '10Gi';
const imageResource = this.images.find( I => this.imageId === I.id);
+
const isIsoImage = /iso$/i.test(imageResource?.imageSuffix);
const imageSize = Math.max(imageResource?.status?.size, imageResource?.status?.virtualSize);
+ const isEncrypted = imageResource?.isEncrypted || false;
if (isIsoImage) {
bus = 'sata';
@@ -447,6 +449,7 @@ export default {
storageClassName: '',
image: this.imageId,
volumeMode: 'Block',
+ isEncrypted
});
} else {
out = _disks.map( (DISK, index) => {
@@ -523,7 +526,11 @@ export default {
minExponent: 3,
});
- const volumeStatus = this.pvcs.find(P => P.id === `${ this.value.metadata.namespace }/${ volumeName }`)?.relatedPV?.metadata?.annotations?.[HCI_ANNOTATIONS.VOLUME_ERROR];
+ const pvc = this.pvcs.find(P => P.id === `${ this.value.metadata.namespace }/${ volumeName }`);
+
+ const volumeStatus = pvc?.relatedPV?.metadata?.annotations?.[HCI_ANNOTATIONS.VOLUME_ERROR];
+
+ const isEncrypted = pvc?.isEncrypted || false;
return {
id: randomStr(5),
@@ -543,7 +550,8 @@ export default {
hotpluggable,
volumeStatus,
dataSource,
- namespace
+ namespace,
+ isEncrypted
};
});
}
diff --git a/pkg/harvester/models/harvester/persistentvolumeclaim.js b/pkg/harvester/models/harvester/persistentvolumeclaim.js
index 645b1586..2394ca4f 100644
--- a/pkg/harvester/models/harvester/persistentvolumeclaim.js
+++ b/pkg/harvester/models/harvester/persistentvolumeclaim.js
@@ -214,7 +214,7 @@ export default class HciPv extends HarvesterResource {
}
get isEncrypted() {
- return this.relatedPV?.spec.csi.volumeAttributes.encrypted || false;
+ return Boolean(this.relatedPV?.spec.csi.volumeAttributes.encrypted) || false;
}
get longhornVolume() {
diff --git a/pkg/harvester/models/kubevirt.io.virtualmachine.js b/pkg/harvester/models/kubevirt.io.virtualmachine.js
index 82652bd0..b274f887 100644
--- a/pkg/harvester/models/kubevirt.io.virtualmachine.js
+++ b/pkg/harvester/models/kubevirt.io.virtualmachine.js
@@ -574,27 +574,20 @@ export default class VirtVm extends HarvesterResource {
return vmis.find(VMI => VMI.id === this.id);
}
- get isVMImageEncrypted() {
- const inStore = this.productInStore;
- const imageList = this.$rootGetters[`${ inStore }/all`](HCI.IMAGE);
- const rootImage = imageList.find(image => this.rootImageId === image.id);
-
- return rootImage?.isEncrypted || false;
- }
-
- get isVolumeEncrypted() {
+ get encryptedVolumeType() {
const inStore = this.productInStore;
const pvcs = this.$rootGetters[`${ inStore }/all`](PVC);
- // filter out the root image PVC
- const nonRootImagePVCs = pvcs.filter(pvc => !pvc.metadata.annotations[HCI_ANNOTATIONS.IMAGE_ID]);
+ const volumeClaimNames = this.spec.template.spec.volumes?.map(v => v.persistentVolumeClaim?.claimName).filter(v => !!v) || [];
+ const volumes = pvcs.filter(pvc => volumeClaimNames.includes(pvc.metadata.name));
- const volumeClaimNames = this.spec.template.spec.volumes?.map(v => v.persistentVolumeClaim?.claimName).map(v => v) || [];
-
- const pvcVolumes = nonRootImagePVCs.filter(pvc => volumeClaimNames.includes(pvc.metadata.name));
-
- // if any non-rootImage PCV volume is encrypted, return true, otherwise return false
- return pvcVolumes.some(pvcVol => pvcVol.isEncrypted) ;
+ if (volumes.every(vol => vol.isEncrypted)) {
+ return 'all';
+ } else if (volumes.some(vol => vol.isEncrypted)) {
+ return 'partial';
+ } else {
+ return 'none';
+ }
}
get isError() {