Signed-off-by: Chris Lalancette <clalance@xxxxxxxxxx> --- tools/virsh.c | 367 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 367 insertions(+), 0 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index 5c56fa6..1eb4bef 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -49,6 +49,7 @@ #include "console.h" #include "util.h" #include "memory.h" +#include "ignore-value.h" static char *progname; @@ -8137,6 +8138,364 @@ cmdQuit(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) } /* + * "snapshot-create" command + */ +static const vshCmdInfo info_snapshot_create[] = { + {"help", N_("Create a snapshot")}, + {"desc", N_("Snapshot create")}, + {NULL, NULL} +}; + +static const vshCmdOptDef opts_snapshot_create[] = { + {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")}, + {"file", VSH_OT_DATA, 0, N_("domain snapshot XML")}, + {NULL, 0, 0, NULL} +}; + +static int +cmdSnapshotCreate(vshControl *ctl, const vshCmd *cmd) +{ + virDomainPtr dom = NULL; + int ret = FALSE; + char *from; + char *buffer = NULL; + virDomainSnapshotPtr snapshot; + + if (!vshConnectionUsability(ctl, ctl->conn, TRUE)) + goto cleanup; + + dom = vshCommandOptDomain(ctl, cmd, NULL); + if (dom == NULL) + goto cleanup; + + from = vshCommandOptString(cmd, "file", NULL); + if (from == NULL) + buffer = strdup("<domainsnapshot/>"); + else + ignore_value(virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer)); + if (buffer == NULL) + goto cleanup; + + snapshot = virDomainSnapshotCreateXML(dom, buffer, 0); + if (snapshot == NULL) + goto cleanup; + + virDomainSnapshotFree(snapshot); + + ret = TRUE; + +cleanup: + VIR_FREE(buffer); + if (dom) + virDomainFree(dom); + + return ret; +} + +/* + * "snapshot-current" command + */ +static const vshCmdInfo info_snapshot_current[] = { + {"help", N_("Get the current snapshot")}, + {"desc", N_("Get the current snapshot")}, + {NULL, NULL} +}; + +static const vshCmdOptDef opts_snapshot_current[] = { + {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")}, + {NULL, 0, 0, NULL} +}; + +static int +cmdSnapshotCurrent(vshControl *ctl, const vshCmd *cmd) +{ + virDomainPtr dom = NULL; + int ret = FALSE; + int current; + virDomainSnapshotPtr snapshot = NULL; + + if (!vshConnectionUsability(ctl, ctl->conn, TRUE)) + goto cleanup; + + dom = vshCommandOptDomain(ctl, cmd, NULL); + if (dom == NULL) + goto cleanup; + + current = virDomainHasCurrentSnapshot(dom, 0); + if (current < 0) + goto cleanup; + else if (current) { + char *xml; + + if (!(snapshot = virDomainSnapshotCurrent(dom, 0))) + goto cleanup; + + xml = virDomainSnapshotGetXMLDesc(snapshot, 0); + if (!xml) + goto cleanup; + + vshPrint(ctl, "%s", xml); + VIR_FREE(xml); + } + + ret = TRUE; + +cleanup: + if (snapshot) + virDomainSnapshotFree(snapshot); + if (dom) + virDomainFree(dom); + + return ret; +} + +/* + * "snapshot-list" command + */ +static const vshCmdInfo info_snapshot_list[] = { + {"help", N_("List snapshots for a domain")}, + {"desc", N_("Snapshot List")}, + {NULL, NULL} +}; + +static const vshCmdOptDef opts_snapshot_list[] = { + {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")}, + {NULL, 0, 0, NULL} +}; + +static int +cmdSnapshotList(vshControl *ctl, const vshCmd *cmd) +{ + virDomainPtr dom = NULL; + int ret = FALSE; + int numsnaps; + char **names = NULL; + int actual; + int i; + + if (!vshConnectionUsability(ctl, ctl->conn, TRUE)) + goto cleanup; + + dom = vshCommandOptDomain(ctl, cmd, NULL); + if (dom == NULL) + goto cleanup; + + numsnaps = virDomainSnapshotNum(dom, 0); + + if (numsnaps < 0) + goto cleanup; + + if (numsnaps) { + if (VIR_ALLOC_N(names, numsnaps) < 0) + goto cleanup; + + actual = virDomainSnapshotListNames(dom, names, numsnaps, 0); + if (actual < 0) + goto cleanup; + + for (i = 0; i < actual; i++) + vshPrint(ctl, "%d: %s\n", i, names[i]); + } + + ret = TRUE; + +cleanup: + VIR_FREE(names); + if (dom) + virDomainFree(dom); + + return ret; +} + +/* + * "snapshot-dumpxml" command + */ +static const vshCmdInfo info_snapshot_dumpxml[] = { + {"help", N_("Dump XML for a domain snapshot")}, + {"desc", N_("Snapshot Dump XML")}, + {NULL, NULL} +}; + +static const vshCmdOptDef opts_snapshot_dumpxml[] = { + {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")}, + {"name", VSH_OT_DATA, VSH_OFLAG_REQ, N_("snapshot name")}, + {NULL, 0, 0, NULL} +}; + +static int +cmdSnapshotDumpXML(vshControl *ctl, const vshCmd *cmd) +{ + virDomainPtr dom = NULL; + int ret = FALSE; + char *name; + virDomainSnapshotPtr snapshot = NULL; + char *xml = NULL; + + if (!vshConnectionUsability(ctl, ctl->conn, TRUE)) + goto cleanup; + + dom = vshCommandOptDomain(ctl, cmd, NULL); + if (dom == NULL) + goto cleanup; + + name = vshCommandOptString(cmd, "name", NULL); + if (name == NULL) + goto cleanup; + + snapshot = virDomainSnapshotLookupByName(dom, name, 0); + if (snapshot == NULL) + goto cleanup; + + xml = virDomainSnapshotGetXMLDesc(snapshot, 0); + if (!xml) + goto cleanup; + + printf("%s", xml); + + ret = TRUE; + +cleanup: + VIR_FREE(xml); + if (snapshot) + virDomainSnapshotFree(snapshot); + if (dom) + virDomainFree(dom); + + return ret; +} + +/* + * "start-from-snapshot" command + */ +static const vshCmdInfo info_start_from_snapshot[] = { + {"help", N_("Start a domain from a snapshot")}, + {"desc", N_("Domain start from snapshot")}, + {NULL, NULL} +}; + +static const vshCmdOptDef opts_start_from_snapshot[] = { + {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")}, + {"name", VSH_OT_DATA, VSH_OFLAG_REQ, N_("snapshot name")}, +#ifndef WIN32 + {"console", VSH_OT_BOOL, 0, N_("attach to console after creation")}, +#endif + {NULL, 0, 0, NULL} +}; + +static int +cmdDomainStartFromSnapshot(vshControl *ctl, const vshCmd *cmd) +{ + virDomainPtr dom = NULL; + int ret = FALSE; + char *name; + virDomainSnapshotPtr snapshot = NULL; +#ifndef WIN32 + int console = vshCommandOptBool(cmd, "console"); +#endif + + if (!vshConnectionUsability(ctl, ctl->conn, TRUE)) + goto cleanup; + + dom = vshCommandOptDomain(ctl, cmd, NULL); + if (dom == NULL) + goto cleanup; + + name = vshCommandOptString(cmd, "name", NULL); + if (name == NULL) + goto cleanup; + + snapshot = virDomainSnapshotLookupByName(dom, name, 0); + if (snapshot == NULL) + goto cleanup; + + if (virDomainCreateFromSnapshot(snapshot, 0) < 0) + goto cleanup; + +#ifndef WIN32 + if (console) + cmdRunConsole(ctl, dom); +#endif + + ret = TRUE; + +cleanup: + if (snapshot) + virDomainSnapshotFree(snapshot); + if (dom) + virDomainFree(dom); + + return ret; +} + +/* + * "snapshot-delete" command + */ +static const vshCmdInfo info_snapshot_delete[] = { + {"help", N_("Delete a domain snapshot")}, + {"desc", N_("Snapshot Delete")}, + {NULL, NULL} +}; + +static const vshCmdOptDef opts_snapshot_delete[] = { + {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")}, + {"name", VSH_OT_DATA, VSH_OFLAG_REQ, N_("snapshot name")}, + {"merge", VSH_OT_BOOL, 0, N_("merge snapshot")}, + {"delete", VSH_OT_BOOL, 0, N_("delete snapshot")}, + {"merge-force", VSH_OT_BOOL, 0, N_("merge snapshot, discard children")}, + {"delete-force", VSH_OT_BOOL, 0, N_("delete snapshot and all children")}, + {NULL, 0, 0, NULL} +}; + +static int +cmdSnapshotDelete(vshControl *ctl, const vshCmd *cmd) +{ + virDomainPtr dom = NULL; + int ret = FALSE; + char *name; + virDomainSnapshotPtr snapshot = NULL; + unsigned int flags = 0; + + if (!vshConnectionUsability(ctl, ctl->conn, TRUE)) + goto cleanup; + + dom = vshCommandOptDomain(ctl, cmd, NULL); + if (dom == NULL) + goto cleanup; + + name = vshCommandOptString(cmd, "name", NULL); + if (name == NULL) + goto cleanup; + + if (vshCommandOptBool(cmd, "merge")) + flags |= VIR_DOMAIN_SNAPSHOT_DELETE_MERGE; + if (vshCommandOptBool(cmd, "delete")) + flags |= VIR_DOMAIN_SNAPSHOT_DELETE_DISCARD; + if (vshCommandOptBool(cmd, "merge-force")) + flags |= VIR_DOMAIN_SNAPSHOT_DELETE_MERGE_FORCE; + if (vshCommandOptBool(cmd, "delete-force")) + flags |= VIR_DOMAIN_SNAPSHOT_DELETE_DISCARD_FORCE; + + /* FIXME: throw an error if more than one flag is passed */ + + snapshot = virDomainSnapshotLookupByName(dom, name, 0); + if (snapshot == NULL) + goto cleanup; + + if (virDomainSnapshotDelete(snapshot, flags) < 0) + goto cleanup; + + ret = TRUE; + +cleanup: + if (snapshot) + virDomainSnapshotFree(snapshot); + if (dom) + virDomainFree(dom); + + return ret; +} + +/* * Commands */ static const vshCmdDef commands[] = { @@ -8288,6 +8647,14 @@ static const vshCmdDef commands[] = { {"vcpupin", cmdVcpupin, opts_vcpupin, info_vcpupin}, {"version", cmdVersion, NULL, info_version}, {"vncdisplay", cmdVNCDisplay, opts_vncdisplay, info_vncdisplay}, + + {"snapshot-create", cmdSnapshotCreate, opts_snapshot_create, info_snapshot_create}, + {"snapshot-current", cmdSnapshotCurrent, opts_snapshot_current, info_snapshot_current}, + {"snapshot-delete", cmdSnapshotDelete, opts_snapshot_delete, info_snapshot_delete}, + {"snapshot-dumpxml", cmdSnapshotDumpXML, opts_snapshot_dumpxml, info_snapshot_dumpxml}, + {"snapshot-list", cmdSnapshotList, opts_snapshot_list, info_snapshot_list}, + {"start-from-snapshot", cmdDomainStartFromSnapshot, opts_start_from_snapshot, info_start_from_snapshot}, + {NULL, NULL, NULL, NULL} }; -- 1.6.6.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list