mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-07 17:28:15 +00:00
qemu: don't leave shutdown inhibited on attach failure
While debugging a failure of 'virsh qemu-attach', I noticed that we were leaking the count of active domains on failure. This means that a libvirtd session that is supposed to quit after active domains disappear will hang around forever. * src/qemu/qemu_process.c (qemuProcessAttach): Undo count of active domains on failure. Signed-off-by: Eric Blake <eblake@redhat.com>
This commit is contained in:
parent
2b1ef11c6c
commit
93e599750e
@ -4362,6 +4362,7 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
|
|||||||
const char *model;
|
const char *model;
|
||||||
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
|
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
|
||||||
virCapsPtr caps = NULL;
|
virCapsPtr caps = NULL;
|
||||||
|
bool active = false;
|
||||||
|
|
||||||
VIR_DEBUG("Beginning VM attach process");
|
VIR_DEBUG("Beginning VM attach process");
|
||||||
|
|
||||||
@ -4373,7 +4374,7 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
|
if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
|
||||||
goto cleanup;
|
goto error;
|
||||||
|
|
||||||
/* 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
|
||||||
@ -4381,60 +4382,59 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
|
|||||||
*/
|
*/
|
||||||
VIR_DEBUG("Setting current domain def as transient");
|
VIR_DEBUG("Setting current domain def as transient");
|
||||||
if (virDomainObjSetDefTransient(caps, driver->xmlopt, vm, true) < 0)
|
if (virDomainObjSetDefTransient(caps, driver->xmlopt, vm, true) < 0)
|
||||||
goto cleanup;
|
goto error;
|
||||||
|
|
||||||
vm->def->id = qemuDriverAllocateID(driver);
|
vm->def->id = qemuDriverAllocateID(driver);
|
||||||
|
|
||||||
if (virAtomicIntInc(&driver->nactive) == 1 && driver->inhibitCallback)
|
if (virAtomicIntInc(&driver->nactive) == 1 && driver->inhibitCallback)
|
||||||
driver->inhibitCallback(true, driver->inhibitOpaque);
|
driver->inhibitCallback(true, driver->inhibitOpaque);
|
||||||
|
active = true;
|
||||||
|
|
||||||
if (virFileMakePath(cfg->logDir) < 0) {
|
if (virFileMakePath(cfg->logDir) < 0) {
|
||||||
virReportSystemError(errno,
|
virReportSystemError(errno,
|
||||||
_("cannot create log directory %s"),
|
_("cannot create log directory %s"),
|
||||||
cfg->logDir);
|
cfg->logDir);
|
||||||
goto cleanup;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
VIR_FREE(priv->pidfile);
|
VIR_FREE(priv->pidfile);
|
||||||
if (VIR_STRDUP(priv->pidfile, pidfile) < 0)
|
if (VIR_STRDUP(priv->pidfile, pidfile) < 0)
|
||||||
goto cleanup;
|
goto error;
|
||||||
|
|
||||||
VIR_DEBUG("Detect security driver config");
|
VIR_DEBUG("Detect security driver config");
|
||||||
sec_managers = virSecurityManagerGetNested(driver->securityManager);
|
sec_managers = virSecurityManagerGetNested(driver->securityManager);
|
||||||
if (sec_managers == NULL) {
|
if (sec_managers == NULL)
|
||||||
goto cleanup;
|
goto error;
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; sec_managers[i]; i++) {
|
for (i = 0; sec_managers[i]; i++) {
|
||||||
model = virSecurityManagerGetModel(sec_managers[i]);
|
model = virSecurityManagerGetModel(sec_managers[i]);
|
||||||
seclabeldef = virDomainDefGetSecurityLabelDef(vm->def, model);
|
seclabeldef = virDomainDefGetSecurityLabelDef(vm->def, model);
|
||||||
if (seclabeldef == NULL) {
|
if (seclabeldef == NULL)
|
||||||
goto cleanup;
|
goto error;
|
||||||
}
|
|
||||||
seclabeldef->type = VIR_DOMAIN_SECLABEL_STATIC;
|
seclabeldef->type = VIR_DOMAIN_SECLABEL_STATIC;
|
||||||
if (VIR_ALLOC(seclabel) < 0)
|
if (VIR_ALLOC(seclabel) < 0)
|
||||||
goto cleanup;
|
goto error;
|
||||||
if (virSecurityManagerGetProcessLabel(driver->securityManager,
|
if (virSecurityManagerGetProcessLabel(driver->securityManager,
|
||||||
vm->def, vm->pid, seclabel) < 0)
|
vm->def, vm->pid, seclabel) < 0)
|
||||||
goto cleanup;
|
goto error;
|
||||||
|
|
||||||
if (VIR_STRDUP(seclabeldef->model, model) < 0)
|
if (VIR_STRDUP(seclabeldef->model, model) < 0)
|
||||||
goto cleanup;
|
goto error;
|
||||||
|
|
||||||
if (VIR_STRDUP(seclabeldef->label, seclabel->label) < 0)
|
if (VIR_STRDUP(seclabeldef->label, seclabel->label) < 0)
|
||||||
goto cleanup;
|
goto error;
|
||||||
VIR_FREE(seclabel);
|
VIR_FREE(seclabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
VIR_DEBUG("Creating domain log file");
|
VIR_DEBUG("Creating domain log file");
|
||||||
if ((logfile = qemuDomainCreateLog(driver, vm, false)) < 0)
|
if ((logfile = qemuDomainCreateLog(driver, vm, false)) < 0)
|
||||||
goto cleanup;
|
goto error;
|
||||||
|
|
||||||
VIR_DEBUG("Determining emulator version");
|
VIR_DEBUG("Determining emulator version");
|
||||||
virObjectUnref(priv->qemuCaps);
|
virObjectUnref(priv->qemuCaps);
|
||||||
if (!(priv->qemuCaps = virQEMUCapsCacheLookupCopy(driver->qemuCapsCache,
|
if (!(priv->qemuCaps = virQEMUCapsCacheLookupCopy(driver->qemuCapsCache,
|
||||||
vm->def->emulator)))
|
vm->def->emulator)))
|
||||||
goto cleanup;
|
goto error;
|
||||||
|
|
||||||
VIR_DEBUG("Preparing monitor state");
|
VIR_DEBUG("Preparing monitor state");
|
||||||
priv->monConfig = monConfig;
|
priv->monConfig = monConfig;
|
||||||
@ -4453,11 +4453,11 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
|
|||||||
if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
|
if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
|
||||||
VIR_DEBUG("Assigning domain PCI addresses");
|
VIR_DEBUG("Assigning domain PCI addresses");
|
||||||
if ((qemuDomainAssignAddresses(vm->def, priv->qemuCaps, vm)) < 0)
|
if ((qemuDomainAssignAddresses(vm->def, priv->qemuCaps, vm)) < 0)
|
||||||
goto cleanup;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((timestamp = virTimeStringNow()) == NULL) {
|
if ((timestamp = virTimeStringNow()) == NULL) {
|
||||||
goto cleanup;
|
goto error;
|
||||||
} else {
|
} else {
|
||||||
if (safewrite(logfile, timestamp, strlen(timestamp)) < 0 ||
|
if (safewrite(logfile, timestamp, strlen(timestamp)) < 0 ||
|
||||||
safewrite(logfile, ATTACH_POSTFIX, strlen(ATTACH_POSTFIX)) < 0) {
|
safewrite(logfile, ATTACH_POSTFIX, strlen(ATTACH_POSTFIX)) < 0) {
|
||||||
@ -4474,7 +4474,7 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
|
|||||||
|
|
||||||
VIR_DEBUG("Waiting for monitor to show up");
|
VIR_DEBUG("Waiting for monitor to show up");
|
||||||
if (qemuProcessWaitForMonitor(driver, vm, priv->qemuCaps, -1) < 0)
|
if (qemuProcessWaitForMonitor(driver, vm, priv->qemuCaps, -1) < 0)
|
||||||
goto cleanup;
|
goto error;
|
||||||
|
|
||||||
/* Failure to connect to agent shouldn't be fatal */
|
/* Failure to connect to agent shouldn't be fatal */
|
||||||
if (qemuConnectAgent(driver, vm) < 0) {
|
if (qemuConnectAgent(driver, vm) < 0) {
|
||||||
@ -4486,34 +4486,34 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
|
|||||||
|
|
||||||
VIR_DEBUG("Detecting VCPU PIDs");
|
VIR_DEBUG("Detecting VCPU PIDs");
|
||||||
if (qemuProcessDetectVcpuPIDs(driver, vm) < 0)
|
if (qemuProcessDetectVcpuPIDs(driver, vm) < 0)
|
||||||
goto cleanup;
|
goto error;
|
||||||
|
|
||||||
/* If we have -device, then addresses are assigned explicitly.
|
/* If we have -device, then addresses are assigned explicitly.
|
||||||
* If not, then we have to detect dynamic ones here */
|
* If not, then we have to detect dynamic ones here */
|
||||||
if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
|
if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
|
||||||
VIR_DEBUG("Determining domain device PCI addresses");
|
VIR_DEBUG("Determining domain device PCI addresses");
|
||||||
if (qemuProcessInitPCIAddresses(driver, vm) < 0)
|
if (qemuProcessInitPCIAddresses(driver, vm) < 0)
|
||||||
goto cleanup;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
VIR_DEBUG("Getting initial memory amount");
|
VIR_DEBUG("Getting initial memory amount");
|
||||||
qemuDomainObjEnterMonitor(driver, vm);
|
qemuDomainObjEnterMonitor(driver, vm);
|
||||||
if (qemuMonitorGetBalloonInfo(priv->mon, &vm->def->mem.cur_balloon) < 0) {
|
if (qemuMonitorGetBalloonInfo(priv->mon, &vm->def->mem.cur_balloon) < 0) {
|
||||||
qemuDomainObjExitMonitor(driver, vm);
|
qemuDomainObjExitMonitor(driver, vm);
|
||||||
goto cleanup;
|
goto error;
|
||||||
}
|
}
|
||||||
if (qemuMonitorGetStatus(priv->mon, &running, &reason) < 0) {
|
if (qemuMonitorGetStatus(priv->mon, &running, &reason) < 0) {
|
||||||
qemuDomainObjExitMonitor(driver, vm);
|
qemuDomainObjExitMonitor(driver, vm);
|
||||||
goto cleanup;
|
goto error;
|
||||||
}
|
}
|
||||||
if (qemuMonitorGetVirtType(priv->mon, &vm->def->virtType) < 0) {
|
if (qemuMonitorGetVirtType(priv->mon, &vm->def->virtType) < 0) {
|
||||||
qemuDomainObjExitMonitor(driver, vm);
|
qemuDomainObjExitMonitor(driver, vm);
|
||||||
goto cleanup;
|
goto error;
|
||||||
}
|
}
|
||||||
qemuDomainObjExitMonitor(driver, vm);
|
qemuDomainObjExitMonitor(driver, vm);
|
||||||
|
|
||||||
if (!virDomainObjIsActive(vm))
|
if (!virDomainObjIsActive(vm))
|
||||||
goto cleanup;
|
goto error;
|
||||||
|
|
||||||
if (running) {
|
if (running) {
|
||||||
virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
|
virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
|
||||||
@ -4530,7 +4530,7 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
|
|||||||
|
|
||||||
VIR_DEBUG("Writing domain status to disk");
|
VIR_DEBUG("Writing domain status to disk");
|
||||||
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
|
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
|
||||||
goto cleanup;
|
goto error;
|
||||||
|
|
||||||
/* Run an hook to allow admins to do some magic */
|
/* Run an hook to allow admins to do some magic */
|
||||||
if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) {
|
if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) {
|
||||||
@ -4546,7 +4546,7 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
|
|||||||
* If the script raised an error abort the launch
|
* If the script raised an error abort the launch
|
||||||
*/
|
*/
|
||||||
if (hookret < 0)
|
if (hookret < 0)
|
||||||
goto cleanup;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
VIR_FORCE_CLOSE(logfile);
|
VIR_FORCE_CLOSE(logfile);
|
||||||
@ -4557,10 +4557,13 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
cleanup:
|
error:
|
||||||
/* We jump here if we failed to start the VM for any reason, or
|
/* We jump here if we failed to attach to the VM for any reason.
|
||||||
* if we failed to initialize the now running VM. kill it off and
|
* Leave the domain running, but pretend we never attempted to
|
||||||
* pretend we never started it */
|
* attach to it. */
|
||||||
|
if (active && virAtomicIntDecAndTest(&driver->nactive) &&
|
||||||
|
driver->inhibitCallback)
|
||||||
|
driver->inhibitCallback(false, driver->inhibitOpaque);
|
||||||
VIR_FORCE_CLOSE(logfile);
|
VIR_FORCE_CLOSE(logfile);
|
||||||
VIR_FREE(seclabel);
|
VIR_FREE(seclabel);
|
||||||
VIR_FREE(sec_managers);
|
VIR_FREE(sec_managers);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user