
2010/4/3 Chris Lalancette <clalance@redhat.com>:
Signed-off-by: Chris Lalancette <clalance@redhat.com> --- tools/virsh.c | 451 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 451 insertions(+), 0 deletions(-)
+ +/* + * "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; + xmlDocPtr xml = NULL; + xmlXPathContextPtr ctxt = NULL; + char *doc = NULL; + virDomainSnapshotPtr snapshot = NULL; + char *state = NULL; + long creation; + char timestr[100]; + struct tm time_info; + + 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; + + vshPrint(ctl, " %-20s %-20s %s\n", _("Name"), _("Creation Time"), _("State")); + vshPrint(ctl, "---------------------------------------------------\n"); + + if (numsnaps) { + if (VIR_ALLOC_N(names, numsnaps) < 0) + goto cleanup; + + actual = virDomainSnapshotListNames(dom, names, numsnaps, 0); + if (actual < 0) + goto cleanup; + + qsort(&names[0], actual, sizeof(char*), namesorter); + + for (i = 0; i < actual; i++) { + /* free up memory from previous iterations of the loop */ + VIR_FREE(state); + if (snapshot) + virDomainSnapshotFree(snapshot); + xmlXPathFreeContext(ctxt); + if (xml) + xmlFreeDoc(xml); + VIR_FREE(doc); + + snapshot = virDomainSnapshotLookupByName(dom, names[i], 0); + if (snapshot == NULL) + continue; + + doc = virDomainSnapshotGetXMLDesc(snapshot, 0); + if (!doc) + continue; + + xml = xmlReadDoc((const xmlChar *) doc, "domainsnapshot.xml", NULL, + XML_PARSE_NOENT | XML_PARSE_NONET | + XML_PARSE_NOWARNING); + if (!xml) + continue; + ctxt = xmlXPathNewContext(xml); + if (!ctxt) + continue; + + state = virXPathString("string(/domainsnapshot/state)", ctxt); + if (state == NULL) + continue; + if (virXPathLong("string(/domainsnapshot/creationTime)", ctxt, + &creation) < 0) + continue; + gmtime_r(&creation, &time_info); + strftime(timestr, sizeof(timestr), "%F %T", &time_info);
If we use gmtime_r here then we should indicate that the printed time is in UTC, maybe using strftime(timestr, sizeof(timestr), "%F %T UTC", &time_info); or changing the header line from "Creation Time" to "Creation Time (UTC)", or really use localtime_r instead of gmtime_r and maybe indicate the timezone offset using %z as recommended in RFC 2822: strftime(timestr, sizeof(timestr), "%F %T %z", &time_info);
+ vshPrint(ctl, " %-20s %-20s %s\n", names[i], timestr, state); + } + } + + ret = TRUE; + +cleanup: + /* this frees up memory from the last iteration of the loop */ + VIR_FREE(state); + if (snapshot) + virDomainSnapshotFree(snapshot); + xmlXPathFreeContext(ctxt); + if (xml) + xmlFreeDoc(xml); + VIR_FREE(doc); + VIR_FREE(names); + 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")}, + {"snapshotname", VSH_OT_DATA, VSH_OFLAG_REQ, N_("snapshot name")}, + {"children", 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, "snapshotname", NULL); + if (name == NULL) { + vshError(ctl, "%s", _("cmdDomainRevertToSnapshot: Missing snapshotname"));
Copy&paste error: cmdDomainRevertToSnapshot Actually the error message should not contain the function name. The same goes for the other new functions. ACK. Matthias