[libvirt] [PATCH 4/7] Virsh commands vol-clone and vol-create-from

Cole Robinson crobinso at redhat.com
Mon May 4 17:42:59 UTC 2009


vol-clone is a convenience function, requiring only a volume to clone and a
new name.

vol-create-from is a direct mapping to the public API, which allows cloning
across pools, converting between formats, etc, but requires an xml file to be
passed

Signed-off-by: Cole Robinson <crobinso at redhat.com>
---
 src/virsh.c |  177 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 175 insertions(+), 2 deletions(-)

diff --git a/src/virsh.c b/src/virsh.c
index 2e41c02..5d46c0a 100644
--- a/src/virsh.c
+++ b/src/virsh.c
@@ -3970,8 +3970,6 @@ cmdPoolUuid(vshControl *ctl, const vshCmd *cmd)
 }
 
 
-
-
 /*
  * "vol-create" command
  */
@@ -4031,6 +4029,179 @@ cmdVolCreate(vshControl *ctl, const vshCmd *cmd)
 }
 
 /*
+ * "vol-create-from" command
+ */
+static const vshCmdInfo info_vol_create_from[] = {
+    {"help", gettext_noop("create a vol, using another volume as input")},
+    {"desc", gettext_noop("Create a vol from an existing volume.")},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_vol_create_from[] = {
+    {"pool", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("pool name")},
+    {"file", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("file containing an XML vol description")},
+    {"inputpool", VSH_OT_STRING, 0, gettext_noop("pool name or uuid of the input volume's pool")},
+    {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("input vol name or key")},
+    {NULL, 0, 0, NULL}
+};
+
+static int
+cmdVolCreateFrom(vshControl *ctl, const vshCmd *cmd)
+{
+    virStoragePoolPtr pool = NULL;
+    virStorageVolPtr newvol = NULL, inputvol = NULL;
+    char *from;
+    int found;
+    int ret = FALSE;
+    char *buffer = NULL;
+
+    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+        goto cleanup;
+
+    if (!(pool = vshCommandOptPoolBy(ctl, cmd, "pool", NULL, VSH_BYNAME)))
+        goto cleanup;
+
+    from = vshCommandOptString(cmd, "file", &found);
+    if (!found) {
+        goto cleanup;
+    }
+
+    if (!(inputvol = vshCommandOptVol(ctl, cmd, "vol", "inputpool", NULL)))
+        goto cleanup;
+
+    if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) {
+        goto cleanup;
+    }
+
+    newvol = virStorageVolCreateXMLFrom(pool, buffer, 0, inputvol);
+
+    if (newvol != NULL) {
+        vshPrint(ctl, _("Vol %s created from input vol %s\n"),
+                 virStorageVolGetName(newvol), virStorageVolGetName(inputvol));
+    } else {
+        vshError(ctl, FALSE, _("Failed to create vol from %s"), from);
+        goto cleanup;
+    }
+
+    ret = TRUE;
+cleanup:
+    free (buffer);
+    if (pool)
+        virStoragePoolFree(pool);
+    if (inputvol)
+        virStorageVolFree(inputvol);
+    return ret;
+}
+
+static xmlChar *
+makeCloneXML(char *origxml, char *newname) {
+
+    xmlDocPtr doc;
+    xmlXPathContextPtr ctxt;
+    xmlXPathObjectPtr obj;
+    xmlChar *newxml = NULL;
+    int size;
+
+    doc = xmlReadDoc((const xmlChar *) origxml, "domain.xml", NULL,
+                     XML_PARSE_NOENT | XML_PARSE_NONET | XML_PARSE_NOWARNING);
+    if (!doc)
+        goto cleanup;
+    ctxt = xmlXPathNewContext(doc);
+    if (!ctxt)
+        goto cleanup;
+
+    obj = xmlXPathEval(BAD_CAST "/volume/name", ctxt);
+    if ((obj == NULL) || (obj->nodesetval == NULL) ||
+        (obj->nodesetval->nodeTab == NULL))
+        goto cleanup;
+
+    xmlNodeSetContent(obj->nodesetval->nodeTab[0], (const xmlChar *)newname);
+    xmlDocDumpMemory(doc, &newxml, &size);
+
+cleanup:
+    xmlXPathFreeObject(obj);
+    xmlXPathFreeContext(ctxt);
+    xmlFreeDoc(doc);
+    return newxml;
+}
+
+/*
+ * "vol-clone" command
+ */
+static const vshCmdInfo info_vol_clone[] = {
+    {"help", gettext_noop("clone a volume.")},
+    {"desc", gettext_noop("Clone an existing volume.")},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_vol_clone[] = {
+    {"pool", VSH_OT_STRING, 0, gettext_noop("pool name or uuid")},
+    {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("orig vol name or key")},
+    {"newname", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("clone name")},
+    {NULL, 0, 0, NULL}
+};
+
+static int
+cmdVolClone(vshControl *ctl, const vshCmd *cmd)
+{
+    virStoragePoolPtr origpool = NULL;
+    virStorageVolPtr origvol = NULL, newvol = NULL;
+    char *name, *origxml = NULL;
+    xmlChar *newxml = NULL;
+    int found;
+    int ret = FALSE;
+
+    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+        goto cleanup;
+
+    if (!(origvol = vshCommandOptVol(ctl, cmd, "vol", "pool", NULL)))
+        goto cleanup;
+
+    origpool = virStoragePoolLookupByVolume(origvol);
+    if (!origpool) {
+        vshError(ctl, FALSE, _("failed to get parent pool"));
+        goto cleanup;
+    }
+
+    name = vshCommandOptString(cmd, "newname", &found);
+    if (!found)
+        goto cleanup;
+
+    origxml = virStorageVolGetXMLDesc(origvol, 0);
+    if (!origxml)
+        goto cleanup;
+
+    newxml = makeCloneXML(origxml, name);
+    if (!newxml) {
+        vshPrint(ctl, "%s", _("Failed to allocate XML buffer"));
+        goto cleanup;
+    }
+
+    newvol = virStorageVolCreateXMLFrom(origpool, (char *) newxml, 0, origvol);
+
+    if (newvol != NULL) {
+        vshPrint(ctl, _("Vol %s cloned from %s\n"),
+                 virStorageVolGetName(newvol), virStorageVolGetName(origvol));
+        virStorageVolFree(newvol);
+    } else {
+        vshError(ctl, FALSE, _("Failed to clone vol from %s"),
+                 virStorageVolGetName(origvol));
+        goto cleanup;
+    }
+
+    ret = TRUE;
+
+cleanup:
+    free(origxml);
+    xmlFree(newxml);
+    if (origvol)
+        virStorageVolFree(origvol);
+    if (origpool)
+        virStoragePoolFree(origpool);
+    return ret;
+}
+
+/*
  * "vol-delete" command
  */
 static const vshCmdInfo info_vol_delete[] = {
@@ -5931,7 +6102,9 @@ static const vshCmdDef commands[] = {
     {"uri", cmdURI, NULL, info_uri},
 
     {"vol-create", cmdVolCreate, opts_vol_create, info_vol_create},
+    {"vol-create-from", cmdVolCreateFrom, opts_vol_create_from, info_vol_create_from},
     {"vol-create-as", cmdVolCreateAs, opts_vol_create_as, info_vol_create_as},
+    {"vol-clone", cmdVolClone, opts_vol_clone, info_vol_clone},
     {"vol-delete", cmdVolDelete, opts_vol_delete, info_vol_delete},
     {"vol-dumpxml", cmdVolDumpXML, opts_vol_dumpxml, info_vol_dumpxml},
     {"vol-info", cmdVolInfo, opts_vol_info, info_vol_info},
-- 
1.6.0.6




More information about the libvir-list mailing list