diff --git a/pkg/harvester/detail/harvesterhci.io.virtualmachineimage/index.vue b/pkg/harvester/detail/harvesterhci.io.virtualmachineimage/index.vue index 0776d940ebe..0416e6d5f9a 100644 --- a/pkg/harvester/detail/harvesterhci.io.virtualmachineimage/index.vue +++ b/pkg/harvester/detail/harvesterhci.io.virtualmachineimage/index.vue @@ -2,7 +2,8 @@ import CopyToClipboardText from '@shell/components/CopyToClipboardText'; import LabelValue from '@shell/components/LabelValue'; import { DESCRIPTION } from '@shell/config/labels-annotations'; -import { HCI } from '@pkg/harvester/config/labels-annotations'; +import { HCI as HCI_ANNOTATIONS } from '@pkg/harvester/config/labels-annotations'; +import { HCI } from '../../types'; import Tabbed from '@shell/components/Tabbed'; import Tab from '@shell/components/Tabbed/Tab'; import { findBy } from '@shell/utils/array'; @@ -31,10 +32,14 @@ export default { const inStore = this.$store.getters['currentProduct'].inStore; this.secrets = await this.$store.dispatch(`${ inStore }/findAll`, { type: SECRET }); + this.images = await this.$store.dispatch(`${ inStore }/findAll`, { type: HCI.IMAGE }); }, data() { - return { secrets: [] }; + return { + secrets: [], + images: [] + }; }, computed: { @@ -64,6 +69,34 @@ export default { return this.value?.spec?.sourceType === 'upload'; }, + sourceImage() { + const { sourceImageName, sourceImageNamespace } = this.value?.spec?.securityParameters || {}; + + if (sourceImageNamespace && sourceImageName) { + const imageId = `${ sourceImageNamespace }/${ sourceImageName }`; + + return this.images.find(image => image.id === imageId); + } + + return null; + }, + + sourceImageLink() { + return this.sourceImage?.detailLocation; + }, + + sourceImageId() { + if (this.sourceImage) { + return `${ this.sourceImage.namespace }/${ this.sourceImage.displayName }`; + } + + return ''; + }, + + isEncryptedOrDecrypted() { + return ['encrypt', 'decrypt'].includes(this.value?.spec?.securityParameters?.cryptoOperation); + }, + encryptionSecret() { if (!this.value.isEncrypted) { return '-'; @@ -80,7 +113,7 @@ export default { }, imageName() { - return this.value?.metadata?.annotations?.[HCI.IMAGE_NAME] || '-'; + return this.value?.metadata?.annotations?.[HCI_ANNOTATIONS.IMAGE_NAME] || '-'; }, } }; @@ -144,7 +177,7 @@ export default { -
raw
and qcow2
image formats which are supported by qemu. Bootable ISO images can also be used and are treated like raw
images.'
fileName: File Name
uploadFile: Upload File
- source: Source
+ source: Source Type
sourceType:
download: URL
upload: File
diff --git a/pkg/harvester/models/harvesterhci.io.virtualmachineimage.js b/pkg/harvester/models/harvesterhci.io.virtualmachineimage.js
index 5f9e44a16cd..2db06826470 100644
--- a/pkg/harvester/models/harvesterhci.io.virtualmachineimage.js
+++ b/pkg/harvester/models/harvesterhci.io.virtualmachineimage.js
@@ -58,6 +58,20 @@ export default class HciVmImage extends HarvesterResource {
label: this.t('harvester.action.createVM'),
disabled: !this.isReady,
},
+ {
+ action: 'encryptImage',
+ enabled: !this.isEncrypted,
+ icon: 'icon icon-lock',
+ label: this.t('harvester.action.encryptImage'),
+ disabled: !this.isReady,
+ },
+ {
+ action: 'decryptImage',
+ enabled: this.isEncrypted,
+ icon: 'icon icon-unlock',
+ label: this.t('harvester.action.decryptImage'),
+ disabled: !this.isReady,
+ },
{
action: 'download',
enabled: this.links?.download,
@@ -68,6 +82,36 @@ export default class HciVmImage extends HarvesterResource {
];
}
+ encryptImage() {
+ const router = this.currentRouter();
+
+ router.push({
+ name: `${ HARVESTER_PRODUCT }-c-cluster-resource-create`,
+ params: { resource: HCI.IMAGE },
+ query: {
+ image: this,
+ fromPage: HCI.IMAGE,
+ sourceType: 'clone',
+ cryptoOperation: 'encrypt'
+ }
+ });
+ }
+
+ decryptImage() {
+ const router = this.currentRouter();
+
+ router.push({
+ name: `${ HARVESTER_PRODUCT }-c-cluster-resource-create`,
+ params: { resource: HCI.IMAGE },
+ query: {
+ image: this,
+ fromPage: HCI.IMAGE,
+ sourceType: 'clone',
+ cryptoOperation: 'decrypt'
+ }
+ });
+ }
+
applyDefaults(resources = this, realMode) {
if (realMode !== _CLONE) {
Vue.set(this.metadata, 'labels', { [HCI_ANNOTATIONS.OS_TYPE]: '', [HCI_ANNOTATIONS.IMAGE_SUFFIX]: '' });