2010/4/3 Chris Lalancette <clalance@xxxxxxxxxx>: > Signed-off-by: Chris Lalancette <clalance@xxxxxxxxxx> > --- > 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list