mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-25 15:15:25 +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;
|
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,
|
int qemuMonitorArbitraryCommand(qemuMonitorPtr mon,
|
||||||
const char *cmd,
|
const char *cmd,
|
||||||
char **reply,
|
char **reply,
|
||||||
|
@ -447,6 +447,10 @@ int qemuMonitorCreateSnapshot(qemuMonitorPtr mon, const char *name);
|
|||||||
int qemuMonitorLoadSnapshot(qemuMonitorPtr mon, const char *name);
|
int qemuMonitorLoadSnapshot(qemuMonitorPtr mon, const char *name);
|
||||||
int qemuMonitorDeleteSnapshot(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,
|
int qemuMonitorArbitraryCommand(qemuMonitorPtr mon,
|
||||||
const char *cmd,
|
const char *cmd,
|
||||||
char **reply,
|
char **reply,
|
||||||
|
@ -2703,6 +2703,39 @@ cleanup:
|
|||||||
return ret;
|
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,
|
int qemuMonitorJSONArbitraryCommand(qemuMonitorPtr mon,
|
||||||
const char *cmd_str,
|
const char *cmd_str,
|
||||||
char **reply_str,
|
char **reply_str,
|
||||||
|
@ -210,6 +210,10 @@ int qemuMonitorJSONCreateSnapshot(qemuMonitorPtr mon, const char *name);
|
|||||||
int qemuMonitorJSONLoadSnapshot(qemuMonitorPtr mon, const char *name);
|
int qemuMonitorJSONLoadSnapshot(qemuMonitorPtr mon, const char *name);
|
||||||
int qemuMonitorJSONDeleteSnapshot(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,
|
int qemuMonitorJSONArbitraryCommand(qemuMonitorPtr mon,
|
||||||
const char *cmd_str,
|
const char *cmd_str,
|
||||||
char **reply_str,
|
char **reply_str,
|
||||||
|
@ -2791,6 +2791,46 @@ cleanup:
|
|||||||
return ret;
|
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,
|
int qemuMonitorTextArbitraryCommand(qemuMonitorPtr mon, const char *cmd,
|
||||||
char **reply)
|
char **reply)
|
||||||
{
|
{
|
||||||
|
@ -206,6 +206,10 @@ int qemuMonitorTextCreateSnapshot(qemuMonitorPtr mon, const char *name);
|
|||||||
int qemuMonitorTextLoadSnapshot(qemuMonitorPtr mon, const char *name);
|
int qemuMonitorTextLoadSnapshot(qemuMonitorPtr mon, const char *name);
|
||||||
int qemuMonitorTextDeleteSnapshot(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,
|
int qemuMonitorTextArbitraryCommand(qemuMonitorPtr mon, const char *cmd,
|
||||||
char **reply);
|
char **reply);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user