mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-23 06:05:27 +00:00
qemu: track quiesced status in qemuDomainSnapshotFSFreeze
Adds 'quiesced' status into qemuDomainObjPrivate that tracks whether FSFreeze is requested in the domain. It modifies error code from qemuDomainSnapshotFSFreeze and qemuDomainSnapshotFSThaw, so that a caller can know whether the command is actually sent to the guest agent. If the error is caused before sending a freeze command, a counterpart thaw command shouldn't be sent either, not to confuse fsfreeze status tracking. Signed-off-by: Tomoki Sekiyama <tomoki.sekiyama@hds.com> Signed-off-by: Eric Blake <eblake@redhat.com>
This commit is contained in:
parent
ca3d07fd45
commit
b6d4dad11b
@ -357,6 +357,9 @@ qemuDomainObjPrivateXMLFormat(virBufferPtr buf, void *data)
|
|||||||
virBufferAddLit(buf, "</devices>\n");
|
virBufferAddLit(buf, "</devices>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (priv->quiesced)
|
||||||
|
virBufferAddLit(buf, "<quiesced/>\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -518,6 +521,8 @@ qemuDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt, void *data)
|
|||||||
}
|
}
|
||||||
VIR_FREE(nodes);
|
VIR_FREE(nodes);
|
||||||
|
|
||||||
|
priv->quiesced = virXPathBoolean("boolean(./quiesced)", ctxt) == 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
@ -176,6 +176,8 @@ struct _qemuDomainObjPrivate {
|
|||||||
char **qemuDevices; /* NULL-terminated list of devices aliases known to QEMU */
|
char **qemuDevices; /* NULL-terminated list of devices aliases known to QEMU */
|
||||||
|
|
||||||
bool hookRun; /* true if there was a hook run over this domain */
|
bool hookRun; /* true if there was a hook run over this domain */
|
||||||
|
|
||||||
|
bool quiesced; /* true if filesystems are quiesced */
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@ -12060,32 +12060,62 @@ qemuDomainPrepareDiskChainElement(virQEMUDriverPtr driver,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Return -1 if request is not sent to agent due to misconfig, -2 if request
|
||||||
|
* is sent but failed, and number of frozen filesystems on success. If -2 is
|
||||||
|
* returned, FSThaw should be called revert the quiesced status. */
|
||||||
static int
|
static int
|
||||||
qemuDomainSnapshotFSFreeze(virDomainObjPtr vm)
|
qemuDomainSnapshotFSFreeze(virQEMUDriverPtr driver,
|
||||||
|
virDomainObjPtr vm)
|
||||||
{
|
{
|
||||||
qemuDomainObjPrivatePtr priv = vm->privateData;
|
qemuDomainObjPrivatePtr priv = vm->privateData;
|
||||||
|
virQEMUDriverConfigPtr cfg;
|
||||||
int freezed;
|
int freezed;
|
||||||
|
|
||||||
|
if (priv->quiesced) {
|
||||||
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
||||||
|
_("domain is already quiesced"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (!qemuDomainAgentAvailable(priv, true))
|
if (!qemuDomainAgentAvailable(priv, true))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
priv->quiesced = true;
|
||||||
|
|
||||||
|
cfg = virQEMUDriverGetConfig(driver);
|
||||||
|
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0) {
|
||||||
|
priv->quiesced = false;
|
||||||
|
virObjectUnref(cfg);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
virObjectUnref(cfg);
|
||||||
|
|
||||||
qemuDomainObjEnterAgent(vm);
|
qemuDomainObjEnterAgent(vm);
|
||||||
freezed = qemuAgentFSFreeze(priv->agent);
|
freezed = qemuAgentFSFreeze(priv->agent);
|
||||||
qemuDomainObjExitAgent(vm);
|
qemuDomainObjExitAgent(vm);
|
||||||
|
return freezed < 0 ? -2 : freezed;
|
||||||
return freezed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return -1 on error, otherwise number of thawed filesystems. */
|
||||||
static int
|
static int
|
||||||
qemuDomainSnapshotFSThaw(virDomainObjPtr vm, bool report)
|
qemuDomainSnapshotFSThaw(virQEMUDriverPtr driver,
|
||||||
|
virDomainObjPtr vm,
|
||||||
|
bool report)
|
||||||
{
|
{
|
||||||
qemuDomainObjPrivatePtr priv = vm->privateData;
|
qemuDomainObjPrivatePtr priv = vm->privateData;
|
||||||
|
virQEMUDriverConfigPtr cfg;
|
||||||
int thawed;
|
int thawed;
|
||||||
virErrorPtr err = NULL;
|
virErrorPtr err = NULL;
|
||||||
|
|
||||||
if (!qemuDomainAgentAvailable(priv, report))
|
if (!qemuDomainAgentAvailable(priv, report))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (!priv->quiesced && report) {
|
||||||
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
||||||
|
_("domain is not quiesced"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
qemuDomainObjEnterAgent(vm);
|
qemuDomainObjEnterAgent(vm);
|
||||||
if (!report)
|
if (!report)
|
||||||
err = virSaveLastError();
|
err = virSaveLastError();
|
||||||
@ -12095,6 +12125,19 @@ qemuDomainSnapshotFSThaw(virDomainObjPtr vm, bool report)
|
|||||||
qemuDomainObjExitAgent(vm);
|
qemuDomainObjExitAgent(vm);
|
||||||
|
|
||||||
virFreeError(err);
|
virFreeError(err);
|
||||||
|
|
||||||
|
if (!report || thawed >= 0) {
|
||||||
|
priv->quiesced = false;
|
||||||
|
|
||||||
|
cfg = virQEMUDriverGetConfig(driver);
|
||||||
|
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0) {
|
||||||
|
/* Revert the statuses when we failed to save them. */
|
||||||
|
priv->quiesced = true;
|
||||||
|
thawed = -1;
|
||||||
|
}
|
||||||
|
virObjectUnref(cfg);
|
||||||
|
}
|
||||||
|
|
||||||
return thawed;
|
return thawed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -13091,17 +13134,18 @@ qemuDomainSnapshotCreateActiveExternal(virConnectPtr conn,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
/* If quiesce was requested, then issue a freeze command, and a
|
/* If quiesce was requested, then issue a freeze command, and a
|
||||||
* counterpart thaw command, no matter what. The command will
|
* counterpart thaw command when it is actually sent to agent.
|
||||||
* fail if the guest is paused or the guest agent is not
|
* The command will fail if the guest is paused or the guest agent
|
||||||
* running. */
|
* is not running, or is already quiesced. */
|
||||||
if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE) {
|
if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE) {
|
||||||
if (qemuDomainSnapshotFSFreeze(vm) < 0) {
|
int freeze = qemuDomainSnapshotFSFreeze(driver, vm);
|
||||||
/* helper reported the error */
|
if (freeze < 0) {
|
||||||
thaw = -1;
|
/* the helper reported the error */
|
||||||
|
if (freeze == -2)
|
||||||
|
thaw = -1; /* the command is sent but agent failed */
|
||||||
goto endjob;
|
goto endjob;
|
||||||
} else {
|
|
||||||
thaw = 1;
|
|
||||||
}
|
}
|
||||||
|
thaw = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We need to track what state the guest is in, since taking the
|
/* We need to track what state the guest is in, since taking the
|
||||||
@ -13242,7 +13286,7 @@ qemuDomainSnapshotCreateActiveExternal(virConnectPtr conn,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
if (vm && thaw != 0 &&
|
if (vm && thaw != 0 &&
|
||||||
qemuDomainSnapshotFSThaw(vm, thaw > 0) < 0) {
|
qemuDomainSnapshotFSThaw(driver, vm, thaw > 0) < 0) {
|
||||||
/* helper reported the error, if it was needed */
|
/* helper reported the error, if it was needed */
|
||||||
if (thaw > 0)
|
if (thaw > 0)
|
||||||
ret = -1;
|
ret = -1;
|
||||||
|
Loading…
Reference in New Issue
Block a user