[libvirt] [PATCH 6/6] Snapshot virsh implementation.

Matthias Bolte matthias.bolte at googlemail.com
Sat Apr 3 15:30:39 UTC 2010


2010/4/3 Chris Lalancette <clalance at redhat.com>:
> Signed-off-by: Chris Lalancette <clalance at 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




More information about the libvir-list mailing list