mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-24 22:55:23 +00:00
snapshot: wire up new qemu monitor command
No one uses this yet, but it will be important once virDomainSnapshotCreateXML learns a VIR_DOMAIN_SNAPSHOT_DISK_ONLY flag, and the xml allows passing in the new file names. * src/qemu/qemu_monitor.h (qemuMonitorDiskSnapshot): New prototype. * src/qemu/qemu_monitor_text.h (qemuMonitorTextDiskSnapshot): Likewise. * src/qemu/qemu_monitor_json.h (qemuMonitorJSONDiskSnapshot): Likewise. * src/qemu/qemu_monitor.c (qemuMonitorDiskSnapshot): New function. * src/qemu/qemu_monitor_json.c (qemuMonitorJSONDiskSnapshot): Likewise.
This commit is contained in:
parent
c111517a88
commit
e702b5bab1
@ -2391,6 +2391,30 @@ int qemuMonitorDeleteSnapshot(qemuMonitorPtr mon, const char *name)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Use the snapshot_blkdev command to convert the existing file for
|
||||
* device into a read-only backing file of a new qcow2 image located
|
||||
* at file. */
|
||||
int
|
||||
qemuMonitorDiskSnapshot(qemuMonitorPtr mon, const char *device,
|
||||
const char *file)
|
||||
{
|
||||
int ret;
|
||||
|
||||
VIR_DEBUG("mon=%p, device=%s, file=%s", mon, device, file);
|
||||
|
||||
if (!mon) {
|
||||
qemuReportError(VIR_ERR_INVALID_ARG, "%s",
|
||||
_("monitor must not be NULL"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mon->json)
|
||||
ret = qemuMonitorJSONDiskSnapshot(mon, device, file);
|
||||
else
|
||||
ret = qemuMonitorTextDiskSnapshot(mon, device, file);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int qemuMonitorArbitraryCommand(qemuMonitorPtr mon,
|
||||
const char *cmd,
|
||||
char **reply,
|
||||
|
@ -447,6 +447,10 @@ int qemuMonitorCreateSnapshot(qemuMonitorPtr mon, const char *name);
|
||||
int qemuMonitorLoadSnapshot(qemuMonitorPtr mon, const char *name);
|
||||
int qemuMonitorDeleteSnapshot(qemuMonitorPtr mon, const char *name);
|
||||
|
||||
int qemuMonitorDiskSnapshot(qemuMonitorPtr mon,
|
||||
const char *device,
|
||||
const char *file);
|
||||
|
||||
int qemuMonitorArbitraryCommand(qemuMonitorPtr mon,
|
||||
const char *cmd,
|
||||
char **reply,
|
||||
|
@ -2703,6 +2703,39 @@ cleanup:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
qemuMonitorJSONDiskSnapshot(qemuMonitorPtr mon, const char *device,
|
||||
const char *file)
|
||||
{
|
||||
int ret;
|
||||
virJSONValuePtr cmd;
|
||||
virJSONValuePtr reply = NULL;
|
||||
|
||||
cmd = qemuMonitorJSONMakeCommand("snapshot-blkdev-sync",
|
||||
"s:device", device,
|
||||
"s:snapshot-file", file,
|
||||
NULL);
|
||||
if (!cmd)
|
||||
return -1;
|
||||
|
||||
if ((ret = qemuMonitorJSONCommand(mon, cmd, &reply)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (qemuMonitorJSONHasError(reply, "CommandNotFound") &&
|
||||
qemuMonitorCheckHMP(mon, "snapshot_blkdev")) {
|
||||
VIR_DEBUG("snapshot-blkdev-sync command not found, trying HMP");
|
||||
ret = qemuMonitorTextDiskSnapshot(mon, device, file);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = qemuMonitorJSONCheckError(cmd, reply);
|
||||
|
||||
cleanup:
|
||||
virJSONValueFree(cmd);
|
||||
virJSONValueFree(reply);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int qemuMonitorJSONArbitraryCommand(qemuMonitorPtr mon,
|
||||
const char *cmd_str,
|
||||
char **reply_str,
|
||||
|
@ -210,6 +210,10 @@ int qemuMonitorJSONCreateSnapshot(qemuMonitorPtr mon, const char *name);
|
||||
int qemuMonitorJSONLoadSnapshot(qemuMonitorPtr mon, const char *name);
|
||||
int qemuMonitorJSONDeleteSnapshot(qemuMonitorPtr mon, const char *name);
|
||||
|
||||
int qemuMonitorJSONDiskSnapshot(qemuMonitorPtr mon,
|
||||
const char *device,
|
||||
const char *file);
|
||||
|
||||
int qemuMonitorJSONArbitraryCommand(qemuMonitorPtr mon,
|
||||
const char *cmd_str,
|
||||
char **reply_str,
|
||||
|
@ -2791,6 +2791,46 @@ cleanup:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
qemuMonitorTextDiskSnapshot(qemuMonitorPtr mon, const char *device,
|
||||
const char *file)
|
||||
{
|
||||
char *cmd = NULL;
|
||||
char *reply = NULL;
|
||||
int ret = -1;
|
||||
char *safename;
|
||||
|
||||
if (!(safename = qemuMonitorEscapeArg(file)) ||
|
||||
virAsprintf(&cmd, "snapshot_blkdev %s \"%s\"", device, safename) < 0) {
|
||||
virReportOOMError();
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (qemuMonitorHMPCommand(mon, cmd, &reply)) {
|
||||
qemuReportError(VIR_ERR_OPERATION_FAILED,
|
||||
_("failed to take snapshot using command '%s'"), cmd);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (strstr(reply, "error while creating qcow2") != NULL) {
|
||||
qemuReportError(VIR_ERR_OPERATION_FAILED,
|
||||
_("Failed to take snapshot: %s"), reply);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* XXX Should we scrape 'info block' output for
|
||||
* 'device:... file=name backing_file=oldname' to make sure the
|
||||
* command succeeded? */
|
||||
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
VIR_FREE(safename);
|
||||
VIR_FREE(cmd);
|
||||
VIR_FREE(reply);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int qemuMonitorTextArbitraryCommand(qemuMonitorPtr mon, const char *cmd,
|
||||
char **reply)
|
||||
{
|
||||
|
@ -206,6 +206,10 @@ int qemuMonitorTextCreateSnapshot(qemuMonitorPtr mon, const char *name);
|
||||
int qemuMonitorTextLoadSnapshot(qemuMonitorPtr mon, const char *name);
|
||||
int qemuMonitorTextDeleteSnapshot(qemuMonitorPtr mon, const char *name);
|
||||
|
||||
int qemuMonitorTextDiskSnapshot(qemuMonitorPtr mon,
|
||||
const char *device,
|
||||
const char *file);
|
||||
|
||||
int qemuMonitorTextArbitraryCommand(qemuMonitorPtr mon, const char *cmd,
|
||||
char **reply);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user