We can now replace the existing NVRAM file on startup when the API requests this. Signed-off-by: Daniel P. Berrangé <berrange@xxxxxxxxxx> --- src/qemu/qemu_driver.c | 24 ++++++++++++++++++------ src/qemu/qemu_process.c | 8 +++++--- src/qemu/qemu_process.h | 1 + src/qemu/qemu_saveimage.c | 9 +++++++-- src/qemu/qemu_saveimage.h | 1 + src/qemu/qemu_snapshot.c | 6 +++++- 6 files changed, 37 insertions(+), 12 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 698f57f00e..4831a81a78 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -1589,7 +1589,8 @@ static virDomainPtr qemuDomainCreateXML(virConnectPtr conn, virCheckFlags(VIR_DOMAIN_START_PAUSED | VIR_DOMAIN_START_AUTODESTROY | - VIR_DOMAIN_START_VALIDATE, NULL); + VIR_DOMAIN_START_VALIDATE | + VIR_DOMAIN_START_RESET_NVRAM, NULL); if (flags & VIR_DOMAIN_START_VALIDATE) parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA; @@ -1597,6 +1598,8 @@ static virDomainPtr qemuDomainCreateXML(virConnectPtr conn, start_flags |= VIR_QEMU_PROCESS_START_PAUSED; if (flags & VIR_DOMAIN_START_AUTODESTROY) start_flags |= VIR_QEMU_PROCESS_START_AUTODESTROY; + if (flags & VIR_DOMAIN_START_RESET_NVRAM) + start_flags |= VIR_QEMU_PROCESS_START_RESET_NVRAM; virNWFilterReadLockFilterUpdates(); @@ -5754,11 +5757,15 @@ qemuDomainRestoreFlags(virConnectPtr conn, virQEMUSaveData *data = NULL; virFileWrapperFd *wrapperFd = NULL; bool hook_taint = false; + bool reset_nvram = false; virCheckFlags(VIR_DOMAIN_SAVE_BYPASS_CACHE | VIR_DOMAIN_SAVE_RUNNING | - VIR_DOMAIN_SAVE_PAUSED, -1); + VIR_DOMAIN_SAVE_PAUSED | + VIR_DOMAIN_SAVE_RESET_NVRAM, -1); + if (flags & VIR_DOMAIN_SAVE_RESET_NVRAM) + reset_nvram = true; virNWFilterReadLockFilterUpdates(); @@ -5820,7 +5827,7 @@ qemuDomainRestoreFlags(virConnectPtr conn, goto cleanup; ret = qemuSaveImageStartVM(conn, driver, vm, &fd, data, path, - false, QEMU_ASYNC_JOB_START); + false, reset_nvram, QEMU_ASYNC_JOB_START); qemuProcessEndJob(driver, vm); @@ -6029,6 +6036,7 @@ qemuDomainObjRestore(virConnectPtr conn, const char *path, bool start_paused, bool bypass_cache, + bool reset_nvram, qemuDomainAsyncJob asyncJob) { g_autoptr(virDomainDef) def = NULL; @@ -6087,7 +6095,7 @@ qemuDomainObjRestore(virConnectPtr conn, virDomainObjAssignDef(vm, &def, true, NULL); ret = qemuSaveImageStartVM(conn, driver, vm, &fd, data, path, - start_paused, asyncJob); + start_paused, reset_nvram, asyncJob); cleanup: virQEMUSaveDataFree(data); @@ -6299,11 +6307,13 @@ qemuDomainObjStart(virConnectPtr conn, bool autodestroy = (flags & VIR_DOMAIN_START_AUTODESTROY) != 0; bool bypass_cache = (flags & VIR_DOMAIN_START_BYPASS_CACHE) != 0; bool force_boot = (flags & VIR_DOMAIN_START_FORCE_BOOT) != 0; + bool reset_nvram = (flags & VIR_DOMAIN_START_RESET_NVRAM) != 0; unsigned int start_flags = VIR_QEMU_PROCESS_START_COLD; qemuDomainObjPrivate *priv = vm->privateData; start_flags |= start_paused ? VIR_QEMU_PROCESS_START_PAUSED : 0; start_flags |= autodestroy ? VIR_QEMU_PROCESS_START_AUTODESTROY : 0; + start_flags |= reset_nvram ? VIR_QEMU_PROCESS_START_RESET_NVRAM : 0; /* * If there is a managed saved state restore it instead of starting @@ -6328,7 +6338,8 @@ qemuDomainObjStart(virConnectPtr conn, priv->job.current->operation = VIR_DOMAIN_JOB_OPERATION_RESTORE; ret = qemuDomainObjRestore(conn, driver, vm, managed_save, - start_paused, bypass_cache, asyncJob); + start_paused, bypass_cache, + reset_nvram, asyncJob); if (ret == 0) { if (unlink(managed_save) < 0) @@ -6380,7 +6391,8 @@ qemuDomainCreateWithFlags(virDomainPtr dom, unsigned int flags) virCheckFlags(VIR_DOMAIN_START_PAUSED | VIR_DOMAIN_START_AUTODESTROY | VIR_DOMAIN_START_BYPASS_CACHE | - VIR_DOMAIN_START_FORCE_BOOT, -1); + VIR_DOMAIN_START_FORCE_BOOT | + VIR_DOMAIN_START_RESET_NVRAM, -1); virNWFilterReadLockFilterUpdates(); diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index bc7c2a4dbc..659fba8672 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -4411,7 +4411,8 @@ qemuProcessUpdateCPU(virQEMUDriver *driver, static int qemuPrepareNVRAM(virQEMUDriver *driver, - virDomainObj *vm) + virDomainObj *vm, + bool reset_nvram) { g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); int ret = -1; @@ -4423,7 +4424,8 @@ qemuPrepareNVRAM(virQEMUDriver *driver, ssize_t r; g_autofree char *tmp_dst_path = NULL; - if (!loader || !loader->nvram || virFileExists(loader->nvram)) + if (!loader || !loader->nvram || + (virFileExists(loader->nvram) && !reset_nvram)) return 0; master_nvram_path = loader->templt; @@ -6973,7 +6975,7 @@ qemuProcessPrepareHost(virQEMUDriver *driver, qemuProcessMakeDir(driver, vm, priv->channelTargetDir) < 0) return -1; - if (qemuPrepareNVRAM(driver, vm) < 0) + if (qemuPrepareNVRAM(driver, vm, flags & VIR_QEMU_PROCESS_START_RESET_NVRAM) < 0) return -1; if (vm->def->vsock) { diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h index 1b1cc489f0..f6c0d63d11 100644 --- a/src/qemu/qemu_process.h +++ b/src/qemu/qemu_process.h @@ -79,6 +79,7 @@ typedef enum { VIR_QEMU_PROCESS_START_PRETEND = 1 << 3, VIR_QEMU_PROCESS_START_NEW = 1 << 4, /* internal, new VM is starting */ VIR_QEMU_PROCESS_START_GEN_VMID = 1 << 5, /* Generate a new VMID */ + VIR_QEMU_PROCESS_START_RESET_NVRAM = 1 << 5, /* Re-initialize NVRAM from template */ } qemuProcessStartFlags; int qemuProcessStart(virConnectPtr conn, diff --git a/src/qemu/qemu_saveimage.c b/src/qemu/qemu_saveimage.c index 557ee2cd21..c0139041eb 100644 --- a/src/qemu/qemu_saveimage.c +++ b/src/qemu/qemu_saveimage.c @@ -577,6 +577,7 @@ qemuSaveImageStartVM(virConnectPtr conn, virQEMUSaveData *data, const char *path, bool start_paused, + bool reset_nvram, qemuDomainAsyncJob asyncJob) { qemuDomainObjPrivate *priv = vm->privateData; @@ -590,6 +591,11 @@ qemuSaveImageStartVM(virConnectPtr conn, virQEMUSaveHeader *header = &data->header; g_autoptr(qemuDomainSaveCookie) cookie = NULL; int rc = 0; + unsigned int start_flags = VIR_QEMU_PROCESS_START_PAUSED | + VIR_QEMU_PROCESS_START_GEN_VMID; + + if (reset_nvram) + start_flags |= VIR_QEMU_PROCESS_START_RESET_NVRAM; if (virSaveCookieParseString(data->cookie, (virObject **)&cookie, virDomainXMLOptionGetSaveCookie(driver->xmlopt)) < 0) @@ -628,8 +634,7 @@ qemuSaveImageStartVM(virConnectPtr conn, if (qemuProcessStart(conn, driver, vm, cookie ? cookie->cpu : NULL, asyncJob, "stdio", *fd, path, NULL, VIR_NETDEV_VPORT_PROFILE_OP_RESTORE, - VIR_QEMU_PROCESS_START_PAUSED | - VIR_QEMU_PROCESS_START_GEN_VMID) == 0) + start_flags) == 0) started = true; if (intermediatefd != -1) { diff --git a/src/qemu/qemu_saveimage.h b/src/qemu/qemu_saveimage.h index 45c5f35e11..a0daa4ad2b 100644 --- a/src/qemu/qemu_saveimage.h +++ b/src/qemu/qemu_saveimage.h @@ -67,6 +67,7 @@ qemuSaveImageStartVM(virConnectPtr conn, virQEMUSaveData *data, const char *path, bool start_paused, + bool reset_nvram, qemuDomainAsyncJob asyncJob) ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5) ATTRIBUTE_NONNULL(6); diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c index 1887c70708..a99f1246e0 100644 --- a/src/qemu/qemu_snapshot.c +++ b/src/qemu/qemu_snapshot.c @@ -2243,7 +2243,11 @@ qemuSnapshotRevert(virDomainObj *vm, virCheckFlags(VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING | VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED | - VIR_DOMAIN_SNAPSHOT_REVERT_FORCE, -1); + VIR_DOMAIN_SNAPSHOT_REVERT_FORCE | + VIR_DOMAIN_SNAPSHOT_REVERT_RESET_NVRAM, -1); + + if (flags & VIR_DOMAIN_SNAPSHOT_REVERT_RESET_NVRAM) + start_flags |= VIR_QEMU_PROCESS_START_RESET_NVRAM; /* We have the following transitions, which create the following events: * 1. inactive -> inactive: none -- 2.34.1