Skip to content

Commit

Permalink
show volume encryption in vm detail volume tab
Browse files Browse the repository at this point in the history
Signed-off-by: andy.lee <andy.lee@suse.com>
  • Loading branch information
a110605 committed Sep 21, 2024
1 parent c7f4e3e commit 4f9bab7
Show file tree
Hide file tree
Showing 9 changed files with 99 additions and 35 deletions.
1 change: 1 addition & 0 deletions pkg/harvester/detail/kubevirt.io.virtualmachine/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ export default {
...mapGetters(['currentCluster']),
totalSnapshotSize() {
console.log('🚀 ~ handler ~ diskRows:', this.diskRows);

Check warning on line 101 in pkg/harvester/detail/kubevirt.io.virtualmachine/index.vue

View workflow job for this annotation

GitHub Actions / lint

Unexpected console statement
if (this.value.snapshotSizeQuota === undefined || this.value.snapshotSizeQuota === null) {
return ' - ';
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ export default {

<div
data-testid="input-hec-bus"
class="col span-3"
class="col span-6"
>
<InputOrDisplay
:name="t('harvester.virtualMachine.volume.bus')"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,15 @@ import { PVC } from '@shell/config/types';
import { HCI } from '../../../../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: 'HarvesterEditVMImage',
components: {
UnitInput, LabeledInput, LabeledSelect, InputOrDisplay
UnitInput, LabeledInput, LabeledSelect, InputOrDisplay, LabelValue
},
props: {
Expand Down Expand Up @@ -73,6 +76,14 @@ export default {
},
computed: {
encryptionValue() {
return ucFirst(String(this.value.isEncrypted));
},
isView() {
return this.mode === _VIEW;
},
imagesOption() {
return this.images.filter(c => c.isReady).sort((a, b) => a.creationTimestamp > b.creationTimestamp ? -1 : 1).map( (I) => {
return {
Expand All @@ -85,6 +96,9 @@ export default {
imageName() {
const image = this.imagesOption.find(I => I.value === this.value.image);
console.log(`this.mode=${ this.mode }`);

Check warning on line 99 in pkg/harvester/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/vmImage.vue

View workflow job for this annotation

GitHub Actions / lint

Unexpected console statement
console.log('this.value=', this.value);

Check warning on line 100 in pkg/harvester/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/vmImage.vue

View workflow job for this annotation

GitHub Actions / lint

Unexpected console statement
return image ? image.label : '-';
},
Expand Down Expand Up @@ -270,7 +284,7 @@ export default {
<div class="row mb-20">
<div
data-testid="input-hevi-bus"
class="col span-3"
class="col span-6"
>
<InputOrDisplay
:name="t('harvester.virtualMachine.volume.bus')"
Expand All @@ -286,6 +300,15 @@ export default {
/>
</InputOrDisplay>
</div>
<div
v-if="isView"
class="col span-6"
>
<LabelValue
:name="t('harvester.virtualMachine.volume.encryption')"
:value="encryptionValue"
/>
</div>
</div>
</div>
</template>
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@ 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',
components: {
InputOrDisplay, Loading, LabeledInput, LabeledSelect, UnitInput,
InputOrDisplay, Loading, LabeledInput, LabeledSelect, UnitInput, LabelValue
},
props: {
Expand Down Expand Up @@ -58,6 +61,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) || [];
Expand Down Expand Up @@ -212,7 +222,7 @@ export default {
<div class="row mb-20">
<div
data-testid="input-hev-bus"
class="col span-3"
class="col span-6"
>
<InputOrDisplay :name="t('harvester.virtualMachine.volume.bus')" :value="value.bus" :mode="mode">
<LabeledSelect
Expand All @@ -225,6 +235,15 @@ export default {
/>
</InputOrDisplay>
</div>
<div
v-if="isView"
class="col span-6"
>
<LabelValue
:name="t('harvester.virtualMachine.volume.encryption')"
:value="encryptionValue"
/>
</div>
</div>
</div>
</template>
8 changes: 4 additions & 4 deletions pkg/harvester/l10n/en-us.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,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
Expand Down Expand Up @@ -595,10 +599,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
Expand Down
29 changes: 21 additions & 8 deletions pkg/harvester/list/kubevirt.io.virtualmachine.vue
Original file line number Diff line number Diff line change
Expand Up @@ -172,15 +172,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;
}
}
};
Expand Down Expand Up @@ -212,7 +212,12 @@ export default {
:to="scope.row.detailLocation"
>
{{ scope.row.metadata.name }}
<i v-if="lockIconTooltipMessage(scope.row)" v-tooltip="lockIconTooltipMessage(scope.row)" class="icon icon-lock" />
<i
v-if="lockIconTooltipMessage(scope.row)"
v-tooltip="lockIconTooltipMessage(scope.row)"
class="icon icon-lock"
:class="{'green-icon': scope.row.encryptedVolumeType === 'all', 'yellow-icon': scope.row.encryptedVolumeType === 'partial'}"
/>
</n-link>
<span v-else>
{{ scope.row.metadata.name }}
Expand All @@ -233,6 +238,14 @@ export default {
}
}
.green-icon {
color: var(--success);
}
.yellow-icon {
color: var(--warning);
}
.name-console {
display: flex;
align-items: center;
Expand Down
12 changes: 10 additions & 2 deletions pkg/harvester/mixins/harvester-vm/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -420,8 +420,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';
Expand Down Expand Up @@ -449,6 +451,7 @@ export default {
storageClassName: '',
image: this.imageId,
volumeMode: 'Block',
isEncrypted
});
} else {
out = _disks.map( (DISK, index) => {
Expand Down Expand Up @@ -525,7 +528,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),
Expand All @@ -545,7 +552,8 @@ export default {
hotpluggable,
volumeStatus,
dataSource,
namespace
namespace,
isEncrypted
};
});
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/harvester/models/harvester/persistentvolumeclaim.js
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,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() {
Expand Down
30 changes: 15 additions & 15 deletions pkg/harvester/models/kubevirt.io.virtualmachine.js
Original file line number Diff line number Diff line change
Expand Up @@ -575,27 +575,27 @@ 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);
// get rootImage() {
// const inStore = this.productInStore;
// const imageList = this.$rootGetters[`${ inStore }/all`](HCI.IMAGE);

return rootImage?.isEncrypted || false;
}
// return imageList.find(image => this.rootImageId === image.id);
// }

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).map(v => v) || [];
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 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() {
Expand Down

0 comments on commit 4f9bab7

Please sign in to comment.