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:
Eric Blake 2011-08-15 17:25:54 -06:00
parent c111517a88
commit e702b5bab1
6 changed files with 109 additions and 0 deletions

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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)
{ {

View File

@ -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);