diff --git a/pkg/harvester/config/feature-flags.js b/pkg/harvester/config/feature-flags.js
index 2cfeb945..ed611205 100644
--- a/pkg/harvester/config/feature-flags.js
+++ b/pkg/harvester/config/feature-flags.js
@@ -49,6 +49,7 @@ const featuresV142 = [
const featuresV150 = [
...featuresV142,
'tpmPersistentState',
+ 'efiPersistentState',
'untaggedNetworkSetting',
'skipSingleReplicaDetachedVol'
];
diff --git a/pkg/harvester/edit/harvesterhci.io.virtualmachinetemplateversion.vue b/pkg/harvester/edit/harvesterhci.io.virtualmachinetemplateversion.vue
index 477cac13..97e8aee0 100644
--- a/pkg/harvester/edit/harvesterhci.io.virtualmachinetemplateversion.vue
+++ b/pkg/harvester/edit/harvesterhci.io.virtualmachinetemplateversion.vue
@@ -478,7 +478,16 @@ export default {
v-model:value="efiEnabled"
class="check"
type="checkbox"
- :label="t('harvester.virtualMachine.efiEnabled')"
+ :label="t('harvester.virtualMachine.advancedOptions.efiEnabled')"
+ :mode="mode"
+ />
+
+
@@ -487,7 +496,7 @@ export default {
v-model:value="secureBoot"
class="check"
type="checkbox"
- :label="t('harvester.virtualMachine.secureBoot')"
+ :label="t('harvester.virtualMachine.advancedOptions.secureBoot')"
:mode="mode"
/>
diff --git a/pkg/harvester/edit/kubevirt.io.virtualmachine/index.vue b/pkg/harvester/edit/kubevirt.io.virtualmachine/index.vue
index 8e67f575..e7f2bfd0 100644
--- a/pkg/harvester/edit/kubevirt.io.virtualmachine/index.vue
+++ b/pkg/harvester/edit/kubevirt.io.virtualmachine/index.vue
@@ -886,7 +886,16 @@ export default {
v-model:value="efiEnabled"
class="check"
type="checkbox"
- :label="t('harvester.virtualMachine.efiEnabled')"
+ :label="t('harvester.virtualMachine.advancedOptions.efiEnabled')"
+ :mode="mode"
+ />
+
+
@@ -895,7 +904,7 @@ export default {
v-model:value="secureBoot"
class="check"
type="checkbox"
- :label="t('harvester.virtualMachine.secureBoot')"
+ :label="t('harvester.virtualMachine.advancedOptions.secureBoot')"
:mode="mode"
/>
diff --git a/pkg/harvester/l10n/en-us.yaml b/pkg/harvester/l10n/en-us.yaml
index 40599984..2aae4357 100644
--- a/pkg/harvester/l10n/en-us.yaml
+++ b/pkg/harvester/l10n/en-us.yaml
@@ -604,11 +604,12 @@ harvester:
prefix: You must enable CPU Manager for at least one node in
middle: 'host page'
suffix: to enable CPU Pinning for VM
+ efiEnabled: Booting in EFI mode
+ efiPersistentState: EFI Persistent State
+ secureBoot: Secure Boot
usbTip: Provides an absolute pointer device which often helps with getting a consistent mouse cursor position in VNC.
sshTitle: Add Public SSH Key
imageTip: An external URL to the .iso, .img, .qcow2 or .raw that the virtual machine should be created from.
- efiEnabled: Booting in EFI mode
- secureBoot: Secure Boot
volume:
dragTip: Drag and drop volumes, or use the volume's arrows, to change the boot order.
volumeTip: The virtual machine only contains a CD-ROM volume. You may want to add additional disk volumes.
diff --git a/pkg/harvester/mixins/harvester-vm/impl.js b/pkg/harvester/mixins/harvester-vm/impl.js
index ffb0e56a..b1d6df83 100644
--- a/pkg/harvester/mixins/harvester-vm/impl.js
+++ b/pkg/harvester/mixins/harvester-vm/impl.js
@@ -144,6 +144,10 @@ export default {
return !!spec?.template?.spec?.domain?.devices?.tpm?.persistent;
},
+ isEFIPersistentStateEnabled(spec) {
+ return !!spec?.template?.spec?.domain?.firmware?.bootloader?.efi?.persistent;
+ },
+
isSecureBoot(spec) {
return !!spec?.template?.spec?.domain?.firmware?.bootloader?.efi?.secureBoot;
},
diff --git a/pkg/harvester/mixins/harvester-vm/index.js b/pkg/harvester/mixins/harvester-vm/index.js
index 062e57d1..b293951a 100644
--- a/pkg/harvester/mixins/harvester-vm/index.js
+++ b/pkg/harvester/mixins/harvester-vm/index.js
@@ -165,6 +165,7 @@ export default {
efiEnabled: false,
tpmEnabled: false,
tpmPersistentStateEnabled: false,
+ efiPersistentStateEnabled: false,
secureBoot: false,
userDataTemplateId: '',
saveUserDataAsClearText: false,
@@ -369,6 +370,7 @@ export default {
const efiEnabled = this.isEfiEnabled(spec);
const tpmEnabled = this.isTpmEnabled(spec);
const tpmPersistentStateEnabled = this.isTPMPersistentStateEnabled(spec);
+ const efiPersistentStateEnabled = this.isEFIPersistentStateEnabled(spec);
const secureBoot = this.isSecureBoot(spec);
const cpuPinning = this.isCpuPinning(spec);
@@ -400,6 +402,7 @@ export default {
this['installUSBTablet'] = installUSBTablet;
this['efiEnabled'] = efiEnabled;
+ this['efiPersistentStateEnabled'] = efiPersistentStateEnabled;
this['tpmEnabled'] = tpmEnabled;
this['tpmPersistentStateEnabled'] = tpmPersistentStateEnabled;
this['secureBoot'] = secureBoot;
@@ -1386,13 +1389,20 @@ export default {
}
},
- setBootMethod(boot = { efi: false, secureBoot: false }) {
- if (boot.efi && boot.secureBoot) {
- set(this.spec.template.spec.domain, 'features.smm.enabled', true);
- set(this.spec.template.spec.domain, 'firmware.bootloader.efi.secureBoot', true);
- } else if (boot.efi && !boot.secureBoot) {
- // set(this.spec.template.spec.domain, 'features.smm.enabled', false);
+ setBootMethod(boot = { efi: false, secureBoot: false, efiPersistentStateEnabled: false }) {
+ if (boot.efi) {
+ set(this.spec.template.spec.domain, 'firmware.bootloader.efi.secureBoot', boot.secureBoot);
+ set(this.spec.template.spec.domain, 'firmware.bootloader.efi.persistent', boot.efiPersistentStateEnabled);
+ } else {
+ delete this.spec.template.spec.domain['firmware'];
+ delete this.spec.template.spec.domain.features['smm'];
+ return;
+ }
+
+ if (boot.secureBoot) {
+ set(this.spec.template.spec.domain, 'features.smm.enabled', true);
+ } else {
try {
delete this.spec.template.spec.domain.features.smm['enabled'];
const noKeys = Object.keys(this.spec.template.spec.domain.features.smm).length === 0;
@@ -1401,10 +1411,6 @@ export default {
delete this.spec.template.spec.domain.features['smm'];
}
} catch (e) {}
- set(this.spec.template.spec.domain, 'firmware.bootloader.efi.secureBoot', false);
- } else {
- delete this.spec.template.spec.domain['firmware'];
- delete this.spec.template.spec.domain.features['smm'];
}
},
@@ -1540,11 +1546,21 @@ export default {
},
efiEnabled(val) {
- this.setBootMethod({ efi: val, secureBoot: this.secureBoot });
+ this.setBootMethod({
+ efi: val, secureBoot: this.secureBoot, efiPersistentStateEnabled: this.efiPersistentStateEnabled
+ });
},
secureBoot(val) {
- this.setBootMethod({ efi: this.efiEnabled, secureBoot: val });
+ this.setBootMethod({
+ efi: this.efiEnabled, secureBoot: val, efiPersistentStateEnabled: this.efiPersistentStateEnabled
+ });
+ },
+
+ efiPersistentStateEnabled(val) {
+ this.setBootMethod({
+ efi: this.efiEnabled, secureBoot: this.secureBoot, efiPersistentStateEnabled: val
+ });
},
cpuPinning(value) {
diff --git a/pkg/harvester/models/harvesterhci.io.virtualmachinetemplateversion.js b/pkg/harvester/models/harvesterhci.io.virtualmachinetemplateversion.js
index fa385dd0..b2036be2 100644
--- a/pkg/harvester/models/harvesterhci.io.virtualmachinetemplateversion.js
+++ b/pkg/harvester/models/harvesterhci.io.virtualmachinetemplateversion.js
@@ -280,4 +280,8 @@ export default class HciVmTemplateVersion extends HarvesterResource {
get tpmPersistentStateFeatureEnabled() {
return this.$rootGetters['harvester-common/getFeatureEnabled']('tpmPersistentState');
}
+
+ get efiPersistentStateFeatureEnabled() {
+ return this.$rootGetters['harvester-common/getFeatureEnabled']('efiPersistentState');
+ }
}
diff --git a/pkg/harvester/models/kubevirt.io.virtualmachine.js b/pkg/harvester/models/kubevirt.io.virtualmachine.js
index 9eea0783..103e32ba 100644
--- a/pkg/harvester/models/kubevirt.io.virtualmachine.js
+++ b/pkg/harvester/models/kubevirt.io.virtualmachine.js
@@ -1179,6 +1179,10 @@ export default class VirtVm extends HarvesterResource {
return this.$rootGetters['harvester-common/getFeatureEnabled']('tpmPersistentState');
}
+ get efiPersistentStateFeatureEnabled() {
+ return this.$rootGetters['harvester-common/getFeatureEnabled']('efiPersistentState');
+ }
+
setInstanceLabels(val) {
if ( !this.spec?.template?.metadata?.labels ) {
set(this, 'spec.template.metadata.labels', {});