From a9d637e71e37c4f6fdb7f163e273bfb3007da402 Mon Sep 17 00:00:00 2001 From: Pavel Hrdina Date: Wed, 11 Oct 2017 15:57:16 +0200 Subject: [PATCH] qemu: move detection whether to use -no-reboot to qemu_domain This will be used later on in implementation of new API virDomainSetLifecycleAction(). In order to use it, we need to store the value in status XML to not lose the information if libvirtd is restarted. If some guest was started by old libvirt where it was not possible to change the lifecycle action for running guest, we can safely detect it based on the current actions from the status XML. Reviewed-by: John Ferlan Signed-off-by: Pavel Hrdina --- src/qemu/qemu_command.c | 10 ++-------- src/qemu/qemu_domain.c | 40 ++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_domain.h | 1 + src/qemu/qemu_process.c | 30 ++++++++++++++++++++++++++++++ tests/qemuxml2xmltest.c | 3 ++- 5 files changed, 75 insertions(+), 9 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 87e762bb51..c12e657859 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6509,23 +6509,17 @@ qemuBuildPMCommandLine(virCommandPtr cmd, const virDomainDef *def, qemuDomainObjPrivatePtr priv) { - bool allowReboot = true; virQEMUCapsPtr qemuCaps = priv->qemuCaps; /* Only add -no-reboot option if each event destroys domain */ - if (def->onReboot == VIR_DOMAIN_LIFECYCLE_ACTION_DESTROY && - def->onPoweroff == VIR_DOMAIN_LIFECYCLE_ACTION_DESTROY && - (def->onCrash == VIR_DOMAIN_LIFECYCLE_ACTION_DESTROY || - def->onCrash == VIR_DOMAIN_LIFECYCLE_ACTION_COREDUMP_DESTROY)) { - allowReboot = false; + if (priv->allowReboot == VIR_TRISTATE_BOOL_NO) virCommandAddArg(cmd, "-no-reboot"); - } /* If JSON monitor is enabled, we can receive an event * when QEMU stops. If we use no-shutdown, then we can * watch for this event and do a soft/warm reboot. */ - if (priv->monJSON && allowReboot && + if (priv->monJSON && priv->allowReboot == VIR_TRISTATE_BOOL_YES && virQEMUCapsGet(qemuCaps, QEMU_CAPS_NO_SHUTDOWN)) { virCommandAddArg(cmd, "-no-shutdown"); } diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 05e8b96aa4..26f65e2d9b 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -1767,6 +1767,7 @@ qemuDomainObjPrivateDataClear(qemuDomainObjPrivatePtr priv) priv->namespaces = NULL; priv->reconnectBlockjobs = VIR_TRISTATE_BOOL_ABSENT; + priv->allowReboot = VIR_TRISTATE_BOOL_ABSENT; } @@ -1876,6 +1877,16 @@ qemuDomainObjPrivateXMLFormatBlockjobs(virBufferPtr buf, } +static void +qemuDomainObjPrivateXMLFormatAllowReboot(virBufferPtr buf, + virTristateBool allowReboot) +{ + virBufferAsprintf(buf, "\n", + virTristateBoolTypeToString(allowReboot)); + +} + + static int qemuDomainObjPrivateXMLFormat(virBufferPtr buf, virDomainObjPtr vm) @@ -1998,6 +2009,8 @@ qemuDomainObjPrivateXMLFormat(virBufferPtr buf, if (priv->chardevStdioLogd) virBufferAddLit(buf, "\n"); + qemuDomainObjPrivateXMLFormatAllowReboot(buf, priv->allowReboot); + if (qemuDomainObjPrivateXMLFormatBlockjobs(buf, vm) < 0) return -1; @@ -2108,6 +2121,31 @@ qemuDomainObjPrivateXMLParseBlockjobs(qemuDomainObjPrivatePtr priv, } +static int +qemuDomainObjPrivateXMLParseAllowReboot(xmlXPathContextPtr ctxt, + virTristateBool *allowReboot) +{ + int ret = -1; + int val; + char *valStr; + + if ((valStr = virXPathString("string(./allowReboot/@value)", ctxt))) { + if ((val = virTristateBoolTypeFromString(valStr)) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("invalid allowReboot value '%s'"), valStr); + goto cleanup; + } + *allowReboot = val; + } + + ret = 0; + + cleanup: + VIR_FREE(valStr); + return ret; +} + + static int qemuDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt, virDomainObjPtr vm, @@ -2323,6 +2361,8 @@ qemuDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt, priv->chardevStdioLogd = virXPathBoolean("boolean(./chardevStdioLogd)", ctxt) == 1; + qemuDomainObjPrivateXMLParseAllowReboot(ctxt, &priv->allowReboot); + if (qemuDomainObjPrivateXMLParseBlockjobs(priv, ctxt) < 0) goto error; diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index a29dd76037..afe979d2ed 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -261,6 +261,7 @@ struct _qemuDomainObjPrivate { char *lockState; bool fakeReboot; + virTristateBool allowReboot; int jobs_queued; diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 7f833e940b..66e81bbe51 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -5309,6 +5309,26 @@ qemuProcessPrepareDomainStorage(virConnectPtr conn, } +static void +qemuProcessPrepareAllowReboot(virDomainObjPtr vm) +{ + virDomainDefPtr def = vm->def; + qemuDomainObjPrivatePtr priv = vm->privateData; + + if (priv->allowReboot != VIR_TRISTATE_BOOL_ABSENT) + return; + + if (def->onReboot == VIR_DOMAIN_LIFECYCLE_ACTION_DESTROY && + def->onPoweroff == VIR_DOMAIN_LIFECYCLE_ACTION_DESTROY && + (def->onCrash == VIR_DOMAIN_LIFECYCLE_ACTION_DESTROY || + def->onCrash == VIR_DOMAIN_LIFECYCLE_ACTION_COREDUMP_DESTROY)) { + priv->allowReboot = VIR_TRISTATE_BOOL_NO; + } else { + priv->allowReboot = VIR_TRISTATE_BOOL_YES; + } +} + + /** * qemuProcessPrepareDomain: * @conn: connection object (for looking up storage volumes) @@ -5365,6 +5385,8 @@ qemuProcessPrepareDomain(virConnectPtr conn, priv->chardevStdioLogd = true; } + qemuProcessPrepareAllowReboot(vm); + /* * Normally PCI addresses are assigned in the virDomainCreate * or virDomainDefine methods. We might still need to assign @@ -6618,6 +6640,10 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED, priv->gotShutdown = false; + /* Attaching to running QEMU so we need to detect whether it was started + * with -no-reboot. */ + qemuProcessPrepareAllowReboot(vm); + /* * Normally PCI addresses are assigned in the virDomainCreate * or virDomainDefine methods. We might still need to assign @@ -6994,6 +7020,10 @@ qemuProcessReconnect(void *opaque) if (qemuDomainMasterKeyReadFile(priv) < 0) goto error; + /* If we are connecting to a guest started by old libvirt there is no + * allowReboot in status XML and we need to initialize it. */ + qemuProcessPrepareAllowReboot(obj); + VIR_DEBUG("Reconnect monitor to %p '%s'", obj, obj->def->name); /* XXX check PID liveliness & EXE path */ diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 14f5b58fe9..2185532a6c 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -109,7 +109,8 @@ static const char testStatusXMLPrefixBodyStatic[] = "\n" "\n" "\n" -"\n"; +"\n" +"\n"; static const char testStatusXMLSuffix[] = "\n"; -- GitLab