nvram: generate it's path in qemuDomainDefPostParse

The postParse callback is the correct place to generate default values
that should be present in offline XML.

Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
This commit is contained in:
Pavel Hrdina 2016-03-09 16:10:54 +01:00
parent 5b9e77883b
commit 15ad2ecf11
2 changed files with 70 additions and 101 deletions

View File

@ -1398,6 +1398,7 @@ qemuDomainDefPostParse(virDomainDefPtr def,
void *opaque) void *opaque)
{ {
virQEMUDriverPtr driver = opaque; virQEMUDriverPtr driver = opaque;
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
virQEMUCapsPtr qemuCaps = NULL; virQEMUCapsPtr qemuCaps = NULL;
int ret = -1; int ret = -1;
@ -1413,6 +1414,15 @@ qemuDomainDefPostParse(virDomainDefPtr def,
return ret; return ret;
} }
if (def->os.loader &&
def->os.loader->type == VIR_DOMAIN_LOADER_TYPE_PFLASH &&
def->os.loader->readonly == VIR_TRISTATE_SWITCH_ON &&
!def->os.loader->nvram) {
if (virAsprintf(&def->os.loader->nvram, "%s/%s_VARS.fd",
cfg->nvramDir, def->name) < 0)
goto cleanup;
}
/* check for emulator and create a default one if needed */ /* check for emulator and create a default one if needed */
if (!def->emulator && if (!def->emulator &&
!(def->emulator = virDomainDefGetDefaultEmulator(def, caps))) !(def->emulator = virDomainDefGetDefaultEmulator(def, caps)))

View File

@ -3931,119 +3931,84 @@ qemuProcessVerifyGuestCPU(virQEMUDriverPtr driver,
static int static int
qemuPrepareNVRAM(virQEMUDriverConfigPtr cfg, qemuPrepareNVRAM(virQEMUDriverConfigPtr cfg,
virCapsPtr caps, virDomainObjPtr vm)
virDomainObjPtr vm,
bool migrated)
{ {
int ret = -1; int ret = -1;
int srcFD = -1; int srcFD = -1;
int dstFD = -1; int dstFD = -1;
virDomainLoaderDefPtr loader = vm->def->os.loader; virDomainLoaderDefPtr loader = vm->def->os.loader;
bool generated = false;
bool created = false; bool created = false;
const char *master_nvram_path;
ssize_t r;
/* Unless domain has RO loader of pflash type, we have if (!loader || !loader->nvram || virFileExists(loader->nvram))
* nothing to do here. If the loader is RW then it's not
* using split code and vars feature, so no nvram file needs
* to be created. */
if (!loader || loader->type != VIR_DOMAIN_LOADER_TYPE_PFLASH ||
loader->readonly != VIR_TRISTATE_SWITCH_ON)
return 0; return 0;
/* If the nvram path is configured already, there's nothing master_nvram_path = loader->templt;
* we need to do. Unless we are starting the destination side if (!loader->templt) {
* of migration in which case nvram is configured in the size_t i;
* domain XML but the file doesn't exist yet. Moreover, after for (i = 0; i < cfg->nloader; i++) {
* the migration is completed, qemu will invoke a if (STREQ(cfg->loader[i], loader->path)) {
* synchronization write into the nvram file so we don't have master_nvram_path = cfg->nvram[i];
* to take care about transmitting the real data on the other break;
* side. */ }
if (loader->nvram && !migrated) }
return 0;
/* Autogenerate nvram path if needed.*/
if (!loader->nvram) {
if (virAsprintf(&loader->nvram,
"%s/%s_VARS.fd",
cfg->nvramDir, vm->def->name) < 0)
goto cleanup;
generated = true;
if (vm->persistent &&
virDomainSaveConfig(cfg->configDir, caps, vm->def) < 0)
goto cleanup;
} }
if (!virFileExists(loader->nvram)) { if (!master_nvram_path) {
const char *master_nvram_path = loader->templt; virReportError(VIR_ERR_OPERATION_FAILED,
ssize_t r; _("unable to find any master var store for "
"loader: %s"), loader->path);
goto cleanup;
}
if (!loader->templt) { if ((srcFD = virFileOpenAs(master_nvram_path, O_RDONLY,
size_t i; 0, -1, -1, 0)) < 0) {
for (i = 0; i < cfg->nloader; i++) { virReportSystemError(-srcFD,
if (STREQ(cfg->loader[i], loader->path)) { _("Failed to open file '%s'"),
master_nvram_path = cfg->nvram[i]; master_nvram_path);
break; goto cleanup;
} }
} if ((dstFD = virFileOpenAs(loader->nvram,
} O_WRONLY | O_CREAT | O_EXCL,
S_IRUSR | S_IWUSR,
cfg->user, cfg->group, 0)) < 0) {
virReportSystemError(-dstFD,
_("Failed to create file '%s'"),
loader->nvram);
goto cleanup;
}
created = true;
if (!master_nvram_path) { do {
virReportError(VIR_ERR_OPERATION_FAILED, char buf[1024];
_("unable to find any master var store for "
"loader: %s"), loader->path);
goto cleanup;
}
if ((srcFD = virFileOpenAs(master_nvram_path, O_RDONLY, if ((r = saferead(srcFD, buf, sizeof(buf))) < 0) {
0, -1, -1, 0)) < 0) { virReportSystemError(errno,
virReportSystemError(-srcFD, _("Unable to read from file '%s'"),
_("Failed to open file '%s'"),
master_nvram_path); master_nvram_path);
goto cleanup; goto cleanup;
} }
if ((dstFD = virFileOpenAs(loader->nvram,
O_WRONLY | O_CREAT | O_EXCL, if (safewrite(dstFD, buf, r) < 0) {
S_IRUSR | S_IWUSR, virReportSystemError(errno,
cfg->user, cfg->group, 0)) < 0) { _("Unable to write to file '%s'"),
virReportSystemError(-dstFD,
_("Failed to create file '%s'"),
loader->nvram); loader->nvram);
goto cleanup; goto cleanup;
} }
created = true; } while (r);
do { if (VIR_CLOSE(srcFD) < 0) {
char buf[1024]; virReportSystemError(errno,
_("Unable to close file '%s'"),
if ((r = saferead(srcFD, buf, sizeof(buf))) < 0) { master_nvram_path);
virReportSystemError(errno, goto cleanup;
_("Unable to read from file '%s'"), }
master_nvram_path); if (VIR_CLOSE(dstFD) < 0) {
goto cleanup; virReportSystemError(errno,
} _("Unable to close file '%s'"),
loader->nvram);
if (safewrite(dstFD, buf, r) < 0) { goto cleanup;
virReportSystemError(errno,
_("Unable to write to file '%s'"),
loader->nvram);
goto cleanup;
}
} while (r);
if (VIR_CLOSE(srcFD) < 0) {
virReportSystemError(errno,
_("Unable to close file '%s'"),
master_nvram_path);
goto cleanup;
}
if (VIR_CLOSE(dstFD) < 0) {
virReportSystemError(errno,
_("Unable to close file '%s'"),
loader->nvram);
goto cleanup;
}
} }
ret = 0; ret = 0;
@ -4053,8 +4018,6 @@ qemuPrepareNVRAM(virQEMUDriverConfigPtr cfg,
if (ret < 0) { if (ret < 0) {
if (created) if (created)
unlink(loader->nvram); unlink(loader->nvram);
if (generated)
VIR_FREE(loader->nvram);
} }
VIR_FORCE_CLOSE(srcFD); VIR_FORCE_CLOSE(srcFD);
@ -4474,13 +4437,6 @@ qemuProcessInit(virQEMUDriverPtr driver,
if (qemuProcessStartValidate(vm->def, priv->qemuCaps, migration, snap) < 0) if (qemuProcessStartValidate(vm->def, priv->qemuCaps, migration, snap) < 0)
goto cleanup; goto cleanup;
/* Some things, paths, ... are generated here and we want them to persist.
* Fill them in prior to setting the domain def as transient. */
VIR_DEBUG("Generating paths");
if (qemuPrepareNVRAM(cfg, caps, vm, migration) < 0)
goto stop;
/* Do this upfront, so any part of the startup process can add /* Do this upfront, so any part of the startup process can add
* runtime state to vm->def that won't be persisted. This let's us * runtime state to vm->def that won't be persisted. This let's us
* report implicit runtime defaults in the XML, like vnc listen/socket * report implicit runtime defaults in the XML, like vnc listen/socket
@ -4489,6 +4445,9 @@ qemuProcessInit(virQEMUDriverPtr driver,
if (virDomainObjSetDefTransient(caps, driver->xmlopt, vm, true) < 0) if (virDomainObjSetDefTransient(caps, driver->xmlopt, vm, true) < 0)
goto stop; goto stop;
if (qemuPrepareNVRAM(cfg, vm) < 0)
goto stop;
vm->def->id = qemuDriverAllocateID(driver); vm->def->id = qemuDriverAllocateID(driver);
qemuDomainSetFakeReboot(driver, vm, false); qemuDomainSetFakeReboot(driver, vm, false);
virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_STARTING_UP); virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_STARTING_UP);