]> xenbits.xensource.com Git - libvirt.git/commitdiff
Added virsh commands for storage management
authorDaniel P. Berrange <berrange@redhat.com>
Wed, 20 Feb 2008 15:27:08 +0000 (15:27 +0000)
committerDaniel P. Berrange <berrange@redhat.com>
Wed, 20 Feb 2008 15:27:08 +0000 (15:27 +0000)
ChangeLog
src/virsh.c

index 2864082027a1096138fb3400c4b872eff76f9d6d..380e78f0f3f622477a9630dff72941a75440bfb2 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+Wed Feb 20 10:22:27 EST 2008 Daniel P. Berrange <berrange@redhat.com>
+
+       * src/virsh.c: Added commands for all storage APIs
+
 Wed Feb 20 10:20:27 EST 2008 Daniel P. Berrange <berrange@redhat.com>
 
        * python/generator.py, python/libvir.c, python/libvirt_wrap.h,
index 730f251b12ec5d9512f2c6c9d337c7a8a52c8eed..cee99c5d2b1f3ca7a65f1a28c424193fe4237726 100644 (file)
@@ -262,6 +262,24 @@ static virNetworkPtr vshCommandOptNetworkBy(vshControl * ctl, vshCmd * cmd,
     vshCommandOptNetworkBy(_ctl, _cmd, _optname, _name,             \
                            VSH_BYUUID|VSH_BYNAME)
 
+static virStoragePoolPtr vshCommandOptPoolBy(vshControl * ctl, vshCmd * cmd,
+                            const char *optname, char **name, int flag);
+
+/* default is lookup by Name and UUID */
+#define vshCommandOptPool(_ctl, _cmd, _optname, _name)           \
+    vshCommandOptPoolBy(_ctl, _cmd, _optname, _name,             \
+                           VSH_BYUUID|VSH_BYNAME)
+
+static virStorageVolPtr vshCommandOptVolBy(vshControl * ctl, vshCmd * cmd,
+                                           const char *optname,
+                                           const char *pooloptname,
+                                           char **name, int flag);
+
+/* default is lookup by Name and UUID */
+#define vshCommandOptVol(_ctl, _cmd,_optname, _pooloptname, _name)   \
+    vshCommandOptVolBy(_ctl, _cmd, _optname, _pooloptname, _name,     \
+                           VSH_BYUUID|VSH_BYNAME)
+
 static void vshPrintExtra(vshControl * ctl, const char *format, ...)
     ATTRIBUTE_FORMAT(printf, 2, 3);
 static void vshDebug(vshControl * ctl, int level, const char *format, ...)
@@ -2724,283 +2742,1386 @@ cmdNetworkUuid(vshControl * ctl, vshCmd * cmd)
 }
 
 
+
+
+
+
+
+
+
+
+
+
+
 /*
- * "version" command
+ * "pool-autostart" command
  */
-static vshCmdInfo info_version[] = {
-    {"syntax", "version"},
-    {"help", gettext_noop("show version")},
-    {"desc", gettext_noop("Display the system version information.")},
+static vshCmdInfo info_pool_autostart[] = {
+    {"syntax", "pool-autostart [--disable] <pool>"},
+    {"help", gettext_noop("autostart a pool")},
+    {"desc",
+     gettext_noop("Configure a pool to be automatically started at boot.")},
     {NULL, NULL}
 };
 
+static vshCmdOptDef opts_pool_autostart[] = {
+    {"pool",  VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("pool name or uuid")},
+    {"disable", VSH_OT_BOOL, 0, gettext_noop("disable autostarting")},
+    {NULL, 0, 0, NULL}
+};
 
 static int
-cmdVersion(vshControl * ctl, vshCmd * cmd ATTRIBUTE_UNUSED)
+cmdPoolAutostart(vshControl * ctl, vshCmd * cmd)
 {
-    unsigned long hvVersion;
-    const char *hvType;
-    unsigned long libVersion;
-    unsigned long includeVersion;
-    unsigned long apiVersion;
-    int ret;
-    unsigned int major;
-    unsigned int minor;
-    unsigned int rel;
+    virStoragePoolPtr pool;
+    char *name;
+    int autostart;
 
     if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
         return FALSE;
 
-    hvType = virConnectGetType(ctl->conn);
-    if (hvType == NULL) {
-        vshError(ctl, FALSE, "%s", _("failed to get hypervisor type"));
+    if (!(pool = vshCommandOptPool(ctl, cmd, "pool", &name)))
         return FALSE;
-    }
 
-    includeVersion = LIBVIR_VERSION_NUMBER;
-    major = includeVersion / 1000000;
-    includeVersion %= 1000000;
-    minor = includeVersion / 1000;
-    rel = includeVersion % 1000;
-    vshPrint(ctl, _("Compiled against library: libvir %d.%d.%d\n"),
-             major, minor, rel);
+    autostart = !vshCommandOptBool(cmd, "disable");
 
-    ret = virGetVersion(&libVersion, hvType, &apiVersion);
-    if (ret < 0) {
-        vshError(ctl, FALSE, "%s", _("failed to get the library version"));
+    if (virStoragePoolSetAutostart(pool, autostart) < 0) {
+        if (autostart)
+           vshError(ctl, FALSE, _("failed to mark pool %s as autostarted"),
+                                   name);
+       else
+           vshError(ctl, FALSE,_("failed to unmark pool %s as autostarted"),
+                                   name);
+        virStoragePoolFree(pool);
         return FALSE;
     }
-    major = libVersion / 1000000;
-    libVersion %= 1000000;
-    minor = libVersion / 1000;
-    rel = libVersion % 1000;
-    vshPrint(ctl, _("Using library: libvir %d.%d.%d\n"),
-             major, minor, rel);
-
-    major = apiVersion / 1000000;
-    apiVersion %= 1000000;
-    minor = apiVersion / 1000;
-    rel = apiVersion % 1000;
-    vshPrint(ctl, _("Using API: %s %d.%d.%d\n"), hvType,
-             major, minor, rel);
 
-    ret = virConnectGetVersion(ctl->conn, &hvVersion);
-    if (ret < 0) {
-        vshError(ctl, FALSE, "%s", _("failed to get the hypervisor version"));
-        return FALSE;
-    }
-    if (hvVersion == 0) {
-        vshPrint(ctl,
-                 _("Cannot extract running %s hypervisor version\n"), hvType);
-    } else {
-        major = hvVersion / 1000000;
-        hvVersion %= 1000000;
-        minor = hvVersion / 1000;
-        rel = hvVersion % 1000;
+    if (autostart)
+       vshPrint(ctl, _("Pool %s marked as autostarted\n"), name);
+    else
+       vshPrint(ctl, _("Pool %s unmarked as autostarted\n"), name);
 
-        vshPrint(ctl, _("Running hypervisor: %s %d.%d.%d\n"),
-                 hvType, major, minor, rel);
-    }
     return TRUE;
 }
 
 /*
- * "hostname" command
+ * "pool-create" command
  */
-static vshCmdInfo info_hostname[] = {
-    {"syntax", "hostname"},
-    {"help", gettext_noop("print the hypervisor hostname")},
+static vshCmdInfo info_pool_create[] = {
+    {"syntax", "create a pool from an XML <file>"},
+    {"help", gettext_noop("create a pool from an XML file")},
+    {"desc", gettext_noop("Create a pool.")},
     {NULL, NULL}
 };
 
+static vshCmdOptDef opts_pool_create[] = {
+    {"file", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("file containing an XML pool description")},
+    {NULL, 0, 0, NULL}
+};
+
 static int
-cmdHostname (vshControl *ctl, vshCmd *cmd ATTRIBUTE_UNUSED)
+cmdPoolCreate(vshControl * ctl, vshCmd * cmd)
 {
-    char *hostname;
+    virStoragePoolPtr pool;
+    char *from;
+    int found;
+    int ret = TRUE;
+    char *buffer;
 
     if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
         return FALSE;
 
-    hostname = virConnectGetHostname (ctl->conn);
-    if (hostname == NULL) {
-        vshError(ctl, FALSE, "%s", _("failed to get hostname"));
+    from = vshCommandOptString(cmd, "file", &found);
+    if (!found)
         return FALSE;
-    }
 
-    vshPrint (ctl, "%s\n", hostname);
-    free (hostname);
+    if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0)
+        return FALSE;
 
-    return TRUE;
+    pool = virStoragePoolCreateXML(ctl->conn, buffer, 0);
+    free (buffer);
+
+    if (pool != NULL) {
+        vshPrint(ctl, _("Pool %s created from %s\n"),
+                 virStoragePoolGetName(pool), from);
+    } else {
+        vshError(ctl, FALSE, _("Failed to create pool from %s"), from);
+        ret = FALSE;
+    }
+    return ret;
 }
 
+
 /*
- * "uri" command
+ * "pool-define" command
  */
-static vshCmdInfo info_uri[] = {
-    {"syntax", "uri"},
-    {"help", gettext_noop("print the hypervisor canonical URI")},
+static vshCmdInfo info_pool_define[] = {
+    {"syntax", "define a pool from an XML <file>"},
+    {"help", gettext_noop("define (but don't start) a pool from an XML file")},
+    {"desc", gettext_noop("Define a pool.")},
     {NULL, NULL}
 };
 
+static vshCmdOptDef opts_pool_define[] = {
+    {"file", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("file containing an XML pool description")},
+    {NULL, 0, 0, NULL}
+};
+
 static int
-cmdURI (vshControl *ctl, vshCmd *cmd ATTRIBUTE_UNUSED)
+cmdPoolDefine(vshControl * ctl, vshCmd * cmd)
 {
-    char *uri;
+    virStoragePoolPtr pool;
+    char *from;
+    int found;
+    int ret = TRUE;
+    char *buffer;
 
     if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
         return FALSE;
 
-    uri = virConnectGetURI (ctl->conn);
-    if (uri == NULL) {
-        vshError(ctl, FALSE, "%s", _("failed to get URI"));
+    from = vshCommandOptString(cmd, "file", &found);
+    if (!found)
         return FALSE;
-    }
 
-    vshPrint (ctl, "%s\n", uri);
-    free (uri);
+    if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0)
+        return FALSE;
 
-    return TRUE;
+    pool = virStoragePoolDefineXML(ctl->conn, buffer, 0);
+    free (buffer);
+
+    if (pool != NULL) {
+        vshPrint(ctl, _("Pool %s defined from %s\n"),
+                 virStoragePoolGetName(pool), from);
+    } else {
+        vshError(ctl, FALSE, _("Failed to define pool from %s"), from);
+        ret = FALSE;
+    }
+    return ret;
 }
 
+
 /*
- * "vncdisplay" command
+ * "pool-build" command
  */
-static vshCmdInfo info_vncdisplay[] = {
-    {"syntax", "vncdisplay <domain>"},
-    {"help", gettext_noop("vnc display")},
-    {"desc", gettext_noop("Output the IP address and port number for the VNC display.")},
+static vshCmdInfo info_pool_build[] = {
+    {"syntax", "pool-build <pool>"},
+    {"help", gettext_noop("build a pool")},
+    {"desc", gettext_noop("Build a given pool.")},
     {NULL, NULL}
 };
 
-static vshCmdOptDef opts_vncdisplay[] = {
-    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
+static vshCmdOptDef opts_pool_build[] = {
+    {"pool", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("pool name or uuid")},
     {NULL, 0, 0, NULL}
 };
 
 static int
-cmdVNCDisplay(vshControl * ctl, vshCmd * cmd)
+cmdPoolBuild(vshControl * ctl, vshCmd * cmd)
 {
-    xmlDocPtr xml = NULL;
-    xmlXPathObjectPtr obj = NULL;
-    xmlXPathContextPtr ctxt = NULL;
-    virDomainPtr dom;
-    int ret = FALSE;
-    int port = 0;
-    char *doc;
+    virStoragePoolPtr pool;
+    int ret = TRUE;
+    char *name;
 
     if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
         return FALSE;
 
-    if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", NULL)))
+    if (!(pool = vshCommandOptPool(ctl, cmd, "pool", &name)))
         return FALSE;
 
-    doc = virDomainGetXMLDesc(dom, 0);
-    if (!doc)
-        goto cleanup;
-
-    xml = xmlReadDoc((const xmlChar *) doc, "domain.xml", NULL,
-                     XML_PARSE_NOENT | XML_PARSE_NONET |
-                     XML_PARSE_NOWARNING);
-    free(doc);
-    if (!xml)
-        goto cleanup;
-    ctxt = xmlXPathNewContext(xml);
-    if (!ctxt)
-        goto cleanup;
-
-    obj = xmlXPathEval(BAD_CAST "string(/domain/devices/graphics[@type='vnc']/@port)", ctxt);
-    if ((obj == NULL) || (obj->type != XPATH_STRING) ||
-        (obj->stringval == NULL) || (obj->stringval[0] == 0)) {
-        goto cleanup;
-    }
-    if (virStrToLong_i((const char *)obj->stringval, NULL, 10, &port) || port < 0)
-        goto cleanup;
-    xmlXPathFreeObject(obj);
-
-    obj = xmlXPathEval(BAD_CAST "string(/domain/devices/graphics[@type='vnc']/@listen)", ctxt);
-    if ((obj == NULL) || (obj->type != XPATH_STRING) ||
-        (obj->stringval == NULL) || (obj->stringval[0] == 0) ||
-        !strcmp((const char*)obj->stringval, "0.0.0.0")) {
-        vshPrint(ctl, ":%d\n", port-5900);
+    if (virStoragePoolBuild(pool, 0) == 0) {
+        vshPrint(ctl, _("Pool %s builded\n"), name);
     } else {
-        vshPrint(ctl, "%s:%d\n", (const char *)obj->stringval, port-5900);
+        vshError(ctl, FALSE, _("Failed to build pool %s"), name);
+        ret = FALSE;
+        virStoragePoolFree(pool);
     }
-    xmlXPathFreeObject(obj);
-    obj = NULL;
-    ret = TRUE;
 
- cleanup:
-    xmlXPathFreeObject(obj);
-    xmlXPathFreeContext(ctxt);
-    if (xml)
-        xmlFreeDoc(xml);
-    virDomainFree(dom);
     return ret;
 }
 
+
 /*
- * "ttyconsole" command
+ * "pool-destroy" command
  */
-static vshCmdInfo info_ttyconsole[] = {
-    {"syntax", "ttyconsole <domain>"},
-    {"help", gettext_noop("tty console")},
-    {"desc", gettext_noop("Output the device for the TTY console.")},
+static vshCmdInfo info_pool_destroy[] = {
+    {"syntax", "pool-destroy <pool>"},
+    {"help", gettext_noop("destroy a pool")},
+    {"desc", gettext_noop("Destroy a given pool.")},
     {NULL, NULL}
 };
 
-static vshCmdOptDef opts_ttyconsole[] = {
-    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
+static vshCmdOptDef opts_pool_destroy[] = {
+    {"pool", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("pool name or uuid")},
     {NULL, 0, 0, NULL}
 };
 
 static int
-cmdTTYConsole(vshControl * ctl, vshCmd * cmd)
+cmdPoolDestroy(vshControl * ctl, vshCmd * cmd)
 {
-    xmlDocPtr xml = NULL;
-    xmlXPathObjectPtr obj = NULL;
-    xmlXPathContextPtr ctxt = NULL;
-    virDomainPtr dom;
-    int ret = FALSE;
-    char *doc;
+    virStoragePoolPtr pool;
+    int ret = TRUE;
+    char *name;
 
     if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
         return FALSE;
 
-    if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", NULL)))
+    if (!(pool = vshCommandOptPool(ctl, cmd, "pool", &name)))
         return FALSE;
 
-    doc = virDomainGetXMLDesc(dom, 0);
-    if (!doc)
-        goto cleanup;
-
-    xml = xmlReadDoc((const xmlChar *) doc, "domain.xml", NULL,
-                     XML_PARSE_NOENT | XML_PARSE_NONET |
-                     XML_PARSE_NOWARNING);
-    free(doc);
-    if (!xml)
-        goto cleanup;
-    ctxt = xmlXPathNewContext(xml);
-    if (!ctxt)
-        goto cleanup;
-
-    obj = xmlXPathEval(BAD_CAST "string(/domain/devices/console/@tty)", ctxt);
-    if ((obj == NULL) || (obj->type != XPATH_STRING) ||
-        (obj->stringval == NULL) || (obj->stringval[0] == 0)) {
-        goto cleanup;
+    if (virStoragePoolDestroy(pool) == 0) {
+        vshPrint(ctl, _("Pool %s destroyed\n"), name);
+    } else {
+        vshError(ctl, FALSE, _("Failed to destroy pool %s"), name);
+        ret = FALSE;
+        virStoragePoolFree(pool);
     }
-    vshPrint(ctl, "%s\n", (const char *)obj->stringval);
 
- cleanup:
-    xmlXPathFreeObject(obj);
-    xmlXPathFreeContext(ctxt);
-    if (xml)
-        xmlFreeDoc(xml);
-    virDomainFree(dom);
     return ret;
 }
 
+
 /*
- * "attach-device" command
+ * "pool-delete" command
+ */
+static vshCmdInfo info_pool_delete[] = {
+    {"syntax", "pool-delete <pool>"},
+    {"help", gettext_noop("delete a pool")},
+    {"desc", gettext_noop("Delete a given pool.")},
+    {NULL, NULL}
+};
+
+static vshCmdOptDef opts_pool_delete[] = {
+    {"pool", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("pool name or uuid")},
+    {NULL, 0, 0, NULL}
+};
+
+static int
+cmdPoolDelete(vshControl * ctl, vshCmd * cmd)
+{
+    virStoragePoolPtr pool;
+    int ret = TRUE;
+    char *name;
+
+    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+        return FALSE;
+
+    if (!(pool = vshCommandOptPool(ctl, cmd, "pool", &name)))
+        return FALSE;
+
+    if (virStoragePoolDelete(pool, 0) == 0) {
+        vshPrint(ctl, _("Pool %s deleteed\n"), name);
+    } else {
+        vshError(ctl, FALSE, _("Failed to delete pool %s"), name);
+        ret = FALSE;
+        virStoragePoolFree(pool);
+    }
+
+    return ret;
+}
+
+
+/*
+ * "pool-refresh" command
+ */
+static vshCmdInfo info_pool_refresh[] = {
+    {"syntax", "pool-refresh <pool>"},
+    {"help", gettext_noop("refresh a pool")},
+    {"desc", gettext_noop("Refresh a given pool.")},
+    {NULL, NULL}
+};
+
+static vshCmdOptDef opts_pool_refresh[] = {
+    {"pool", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("pool name or uuid")},
+    {NULL, 0, 0, NULL}
+};
+
+static int
+cmdPoolRefresh(vshControl * ctl, vshCmd * cmd)
+{
+    virStoragePoolPtr pool;
+    int ret = TRUE;
+    char *name;
+
+    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+        return FALSE;
+
+    if (!(pool = vshCommandOptPool(ctl, cmd, "pool", &name)))
+        return FALSE;
+
+    if (virStoragePoolRefresh(pool, 0) == 0) {
+        vshPrint(ctl, _("Pool %s refreshed\n"), name);
+    } else {
+        vshError(ctl, FALSE, _("Failed to refresh pool %s"), name);
+        ret = FALSE;
+    }
+    virStoragePoolFree(pool);
+
+    return ret;
+}
+
+
+/*
+ * "pool-dumpxml" command
+ */
+static vshCmdInfo info_pool_dumpxml[] = {
+    {"syntax", "pool-dumpxml <pool>"},
+    {"help", gettext_noop("pool information in XML")},
+    {"desc", gettext_noop("Output the pool information as an XML dump to stdout.")},
+    {NULL, NULL}
+};
+
+static vshCmdOptDef opts_pool_dumpxml[] = {
+    {"pool", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("pool name or uuid")},
+    {NULL, 0, 0, NULL}
+};
+
+static int
+cmdPoolDumpXML(vshControl * ctl, vshCmd * cmd)
+{
+    virStoragePoolPtr pool;
+    int ret = TRUE;
+    char *dump;
+
+    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+        return FALSE;
+
+    if (!(pool = vshCommandOptPool(ctl, cmd, "pool", NULL)))
+        return FALSE;
+
+    dump = virStoragePoolGetXMLDesc(pool, 0);
+    if (dump != NULL) {
+        printf("%s", dump);
+        free(dump);
+    } else {
+        ret = FALSE;
+    }
+
+    virStoragePoolFree(pool);
+    return ret;
+}
+
+
+/*
+ * "pool-list" command
+ */
+static vshCmdInfo info_pool_list[] = {
+    {"syntax", "pool-list [ --inactive | --all ]"},
+    {"help", gettext_noop("list pools")},
+    {"desc", gettext_noop("Returns list of pools.")},
+    {NULL, NULL}
+};
+
+static vshCmdOptDef opts_pool_list[] = {
+    {"inactive", VSH_OT_BOOL, 0, gettext_noop("list inactive pools")},
+    {"all", VSH_OT_BOOL, 0, gettext_noop("list inactive & active pools")},
+    {NULL, 0, 0, NULL}
+};
+
+static int
+cmdPoolList(vshControl * ctl, vshCmd * cmd ATTRIBUTE_UNUSED)
+{
+    int inactive = vshCommandOptBool(cmd, "inactive");
+    int all = vshCommandOptBool(cmd, "all");
+    int active = !inactive || all ? 1 : 0;
+    int maxactive = 0, maxinactive = 0, i;
+    char **activeNames = NULL, **inactiveNames = NULL;
+    inactive |= all;
+
+    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+        return FALSE;
+
+    if (active) {
+        maxactive = virConnectNumOfStoragePools(ctl->conn);
+        if (maxactive < 0) {
+            vshError(ctl, FALSE, "%s", _("Failed to list active pools"));
+            return FALSE;
+        }
+        if (maxactive) {
+            activeNames = vshMalloc(ctl, sizeof(char *) * maxactive);
+
+            if ((maxactive = virConnectListStoragePools(ctl->conn, activeNames,
+                                                        maxactive)) < 0) {
+                vshError(ctl, FALSE, "%s", _("Failed to list active pools"));
+                free(activeNames);
+                return FALSE;
+            }
+
+            qsort(&activeNames[0], maxactive, sizeof(char *), namesorter);
+        }
+    }
+    if (inactive) {
+        maxinactive = virConnectNumOfDefinedStoragePools(ctl->conn);
+        if (maxinactive < 0) {
+            vshError(ctl, FALSE, "%s", _("Failed to list inactive pools"));
+            free(activeNames);
+            return FALSE;
+        }
+        if (maxinactive) {
+            inactiveNames = vshMalloc(ctl, sizeof(char *) * maxinactive);
+
+            if ((maxinactive = virConnectListDefinedStoragePools(ctl->conn, inactiveNames, maxinactive)) < 0) {
+                vshError(ctl, FALSE, "%s", _("Failed to list inactive pools"));
+                free(activeNames);
+                free(inactiveNames);
+                return FALSE;
+            }
+
+            qsort(&inactiveNames[0], maxinactive, sizeof(char*), namesorter);
+        }
+    }
+    vshPrintExtra(ctl, "%-20s %-10s %-10s\n", _("Name"), _("State"), _("Autostart"));
+    vshPrintExtra(ctl, "-----------------------------------------\n");
+
+    for (i = 0; i < maxactive; i++) {
+        virStoragePoolPtr pool = virStoragePoolLookupByName(ctl->conn, activeNames[i]);
+        const char *autostartStr;
+        int autostart = 0;
+
+        /* this kind of work with pools is not atomic operation */
+        if (!pool) {
+            free(activeNames[i]);
+            continue;
+        }
+
+        if (virStoragePoolGetAutostart(pool, &autostart) < 0)
+            autostartStr = _("no autostart");
+        else
+            autostartStr = autostart ? "yes" : "no";
+
+        vshPrint(ctl, "%-20s %-10s %-10s\n",
+                 virStoragePoolGetName(pool),
+                 _("active"),
+                 autostartStr);
+        virStoragePoolFree(pool);
+        free(activeNames[i]);
+    }
+    for (i = 0; i < maxinactive; i++) {
+        virStoragePoolPtr pool = virStoragePoolLookupByName(ctl->conn, inactiveNames[i]);
+        const char *autostartStr;
+        int autostart = 0;
+
+        /* this kind of work with pools is not atomic operation */
+        if (!pool) {
+            free(inactiveNames[i]);
+            continue;
+        }
+
+        if (virStoragePoolGetAutostart(pool, &autostart) < 0)
+            autostartStr = _("no autostart");
+        else
+            autostartStr = autostart ? "yes" : "no";
+
+        vshPrint(ctl, "%-20s %-10s %-10s\n",
+                 inactiveNames[i],
+                 _("inactive"),
+                 autostartStr);
+
+        virStoragePoolFree(pool);
+        free(inactiveNames[i]);
+    }
+    free(activeNames);
+    free(inactiveNames);
+    return TRUE;
+}
+
+static double
+prettyCapacity(unsigned long long val,
+               const char **unit) {
+    if (val < 1024) {
+        *unit = "";
+        return (double)val;
+    } else if (val < (1024.0l * 1024.0l)) {
+        *unit = "KB";
+        return (((double)val / 1024.0l));
+    } else if (val < (1024.0l * 1024.0l * 1024.0l)) {
+        *unit = "MB";
+        return ((double)val / (1024.0l * 1024.0l));
+    } else if (val < (1024.0l * 1024.0l * 1024.0l * 1024.0l)) {
+        *unit = "GB";
+        return ((double)val / (1024.0l * 1024.0l * 1024.0l));
+    } else {
+        *unit = "TB";
+        return ((double)val / (1024.0l * 1024.0l * 1024.0l * 1024.0l));
+    }
+}
+
+/*
+ * "pool-info" command
+ */
+static vshCmdInfo info_pool_info[] = {
+    {"syntax", "pool-info <pool>"},
+    {"help", gettext_noop("storage pool information")},
+    {"desc", gettext_noop("Returns basic information about the storage pool.")},
+    {NULL, NULL}
+};
+
+static vshCmdOptDef opts_pool_info[] = {
+    {"pool", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("pool name or uuid")},
+    {NULL, 0, 0, NULL}
+};
+
+static int
+cmdPoolInfo(vshControl * ctl, vshCmd * cmd)
+{
+    virStoragePoolInfo info;
+    virStoragePoolPtr pool;
+    int ret = TRUE;
+    char uuid[VIR_UUID_STRING_BUFLEN];
+
+    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+        return FALSE;
+
+    if (!(pool = vshCommandOptPool(ctl, cmd, "pool", NULL)))
+        return FALSE;
+
+    vshPrint(ctl, "%-15s %s\n", _("Name:"), virStoragePoolGetName(pool));
+
+    if (virStoragePoolGetUUIDString(pool, &uuid[0])==0)
+        vshPrint(ctl, "%-15s %s\n", _("UUID:"), uuid);
+
+    if (virStoragePoolGetInfo(pool, &info) == 0) {
+        double val;
+        const char *unit;
+        switch (info.state) {
+        case VIR_STORAGE_POOL_INACTIVE:
+            vshPrint(ctl, "%-15s %s\n", _("State:"),
+                     _("inactive"));
+            break;
+        case VIR_STORAGE_POOL_BUILDING:
+            vshPrint(ctl, "%-15s %s\n", _("State:"),
+                     _("building"));
+            break;
+        case VIR_STORAGE_POOL_RUNNING:
+            vshPrint(ctl, "%-15s %s\n", _("State:"),
+                     _("running"));
+            break;
+        case VIR_STORAGE_POOL_DEGRADED:
+            vshPrint(ctl, "%-15s %s\n", _("State:"),
+                     _("degraded"));
+            break;
+        }
+
+        if (info.state == VIR_STORAGE_POOL_RUNNING ||
+            info.state == VIR_STORAGE_POOL_DEGRADED) {
+            val = prettyCapacity(info.capacity, &unit);
+            vshPrint(ctl, "%-15s %2.2lf %s\n", _("Capacity:"), val, unit);
+
+            val = prettyCapacity(info.allocation, &unit);
+            vshPrint(ctl, "%-15s %2.2lf %s\n", _("Allocation:"), val, unit);
+
+            val = prettyCapacity(info.available, &unit);
+            vshPrint(ctl, "%-15s %2.2lf %s\n", _("Available:"), val, unit);
+        }
+    } else {
+        ret = FALSE;
+    }
+
+    virStoragePoolFree(pool);
+    return ret;
+}
+
+
+/*
+ * "pool-name" command
+ */
+static vshCmdInfo info_pool_name[] = {
+    {"syntax", "pool-name <pool>"},
+    {"help", gettext_noop("convert a pool UUID to pool name")},
+    {NULL, NULL}
+};
+
+static vshCmdOptDef opts_pool_name[] = {
+    {"pool", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("pool uuid")},
+    {NULL, 0, 0, NULL}
+};
+
+static int
+cmdPoolName(vshControl * ctl, vshCmd * cmd)
+{
+    virStoragePoolPtr pool;
+
+    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+        return FALSE;
+    if (!(pool = vshCommandOptPoolBy(ctl, cmd, "pool", NULL,
+                                          VSH_BYUUID)))
+        return FALSE;
+
+    vshPrint(ctl, "%s\n", virStoragePoolGetName(pool));
+    virStoragePoolFree(pool);
+    return TRUE;
+}
+
+
+/*
+ * "pool-start" command
+ */
+static vshCmdInfo info_pool_start[] = {
+    {"syntax", "start <pool>"},
+    {"help", gettext_noop("start a (previously defined) inactive pool")},
+    {"desc", gettext_noop("Start a pool.")},
+    {NULL, NULL}
+};
+
+static vshCmdOptDef opts_pool_start[] = {
+    {"name", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("name of the inactive pool")},
+    {NULL, 0, 0, NULL}
+};
+
+static int
+cmdPoolStart(vshControl * ctl, vshCmd * cmd)
+{
+    virStoragePoolPtr pool;
+    int ret = TRUE;
+
+    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+        return FALSE;
+
+    if (!(pool = vshCommandOptPoolBy(ctl, cmd, "name", NULL, VSH_BYNAME)))
+         return FALSE;
+
+    if (virStoragePoolCreate(pool, 0) == 0) {
+        vshPrint(ctl, _("Pool %s started\n"),
+                 virStoragePoolGetName(pool));
+    } else {
+        vshError(ctl, FALSE, _("Failed to start pool %s"),
+                 virStoragePoolGetName(pool));
+        ret = FALSE;
+    }
+    return ret;
+}
+
+
+/*
+ * "pool-undefine" command
+ */
+static vshCmdInfo info_pool_undefine[] = {
+    {"syntax", "pool-undefine <pool>"},
+    {"help", gettext_noop("undefine an inactive pool")},
+    {"desc", gettext_noop("Undefine the configuration for an inactive pool.")},
+    {NULL, NULL}
+};
+
+static vshCmdOptDef opts_pool_undefine[] = {
+    {"pool", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("pool name or uuid")},
+    {NULL, 0, 0, NULL}
+};
+
+static int
+cmdPoolUndefine(vshControl * ctl, vshCmd * cmd)
+{
+    virStoragePoolPtr pool;
+    int ret = TRUE;
+    char *name;
+
+    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+        return FALSE;
+
+    if (!(pool = vshCommandOptPool(ctl, cmd, "pool", &name)))
+        return FALSE;
+
+    if (virStoragePoolUndefine(pool) == 0) {
+        vshPrint(ctl, _("Pool %s has been undefined\n"), name);
+    } else {
+        vshError(ctl, FALSE, _("Failed to undefine pool %s"), name);
+        ret = FALSE;
+    }
+
+    return ret;
+}
+
+
+/*
+ * "pool-uuid" command
+ */
+static vshCmdInfo info_pool_uuid[] = {
+    {"syntax", "pool-uuid <pool>"},
+    {"help", gettext_noop("convert a pool name to pool UUID")},
+    {NULL, NULL}
+};
+
+static vshCmdOptDef opts_pool_uuid[] = {
+    {"pool", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("pool name")},
+    {NULL, 0, 0, NULL}
+};
+
+static int
+cmdPoolUuid(vshControl * ctl, vshCmd * cmd)
+{
+    virStoragePoolPtr pool;
+    char uuid[VIR_UUID_STRING_BUFLEN];
+
+    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+        return FALSE;
+
+    if (!(pool = vshCommandOptPoolBy(ctl, cmd, "pool", NULL,
+                                          VSH_BYNAME)))
+        return FALSE;
+
+    if (virStoragePoolGetUUIDString(pool, uuid) != -1)
+        vshPrint(ctl, "%s\n", uuid);
+    else
+        vshError(ctl, FALSE, "%s", _("failed to get pool UUID"));
+
+    return TRUE;
+}
+
+
+
+
+/*
+ * "vol-create" command
+ */
+static vshCmdInfo info_vol_create[] = {
+    {"syntax", "create <file>"},
+    {"help", gettext_noop("create a vol from an XML file")},
+    {"desc", gettext_noop("Create a vol.")},
+    {NULL, NULL}
+};
+
+static vshCmdOptDef opts_vol_create[] = {
+    {"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")},
+    {NULL, 0, 0, NULL}
+};
+
+static int
+cmdVolCreate(vshControl * ctl, vshCmd * cmd)
+{
+    virStoragePoolPtr pool;
+    virStorageVolPtr vol;
+    char *from;
+    int found;
+    int ret = TRUE;
+    char *buffer;
+
+    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+        return FALSE;
+
+    if (!(pool = vshCommandOptPoolBy(ctl, cmd, "pool", NULL,
+                                          VSH_BYNAME)))
+        return FALSE;
+
+    from = vshCommandOptString(cmd, "file", &found);
+    if (!found) {
+        virStoragePoolFree(pool);
+        return FALSE;
+    }
+
+    if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) {
+        virStoragePoolFree(pool);
+        return FALSE;
+    }
+
+    vol = virStorageVolCreateXML(pool, buffer, 0);
+    free (buffer);
+    virStoragePoolFree(pool);
+
+    if (vol != NULL) {
+        vshPrint(ctl, _("Vol %s created from %s\n"),
+                 virStorageVolGetName(vol), from);
+        virStorageVolFree(vol);
+    } else {
+        vshError(ctl, FALSE, _("Failed to create vol from %s"), from);
+        ret = FALSE;
+    }
+    return ret;
+}
+
+/*
+ * "vol-delete" command
+ */
+static vshCmdInfo info_vol_delete[] = {
+    {"syntax", "vol-delete <vol>"},
+    {"help", gettext_noop("delete a vol")},
+    {"desc", gettext_noop("Delete a given vol.")},
+    {NULL, NULL}
+};
+
+static vshCmdOptDef opts_vol_delete[] = {
+    {"pool", VSH_OT_STRING, 0, gettext_noop("pool name or uuid")},
+    {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("vol name, key or path")},
+    {NULL, 0, 0, NULL}
+};
+
+static int
+cmdVolDelete(vshControl * ctl, vshCmd * cmd)
+{
+    virStorageVolPtr vol;
+    int ret = TRUE;
+    char *name;
+
+    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+        return FALSE;
+
+    if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", &name))) {
+        return FALSE;
+    }
+
+    if (virStorageVolDelete(vol, 0) == 0) {
+        vshPrint(ctl, _("Vol %s deleteed\n"), name);
+    } else {
+        vshError(ctl, FALSE, _("Failed to delete vol %s"), name);
+        ret = FALSE;
+        virStorageVolFree(vol);
+    }
+
+    return ret;
+}
+
+
+/*
+ * "vol-info" command
+ */
+static vshCmdInfo info_vol_info[] = {
+    {"syntax", "vol-info <vol>"},
+    {"help", gettext_noop("storage vol information")},
+    {"desc", gettext_noop("Returns basic information about the storage vol.")},
+    {NULL, NULL}
+};
+
+static vshCmdOptDef opts_vol_info[] = {
+    {"pool", VSH_OT_STRING, 0, gettext_noop("pool name or uuid")},
+    {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("vol name, key or path")},
+    {NULL, 0, 0, NULL}
+};
+
+static int
+cmdVolInfo(vshControl * ctl, vshCmd * cmd)
+{
+    virStorageVolInfo info;
+    virStorageVolPtr vol;
+    int ret = TRUE;
+
+    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+        return FALSE;
+
+    if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", NULL)))
+        return FALSE;
+
+    vshPrint(ctl, "%-15s %s\n", _("Name:"), virStorageVolGetName(vol));
+
+    if (virStorageVolGetInfo(vol, &info) == 0) {
+        double val;
+        const char *unit;
+        vshPrint(ctl, "%-15s %s\n", _("Type:"),
+                 info.type == VIR_STORAGE_VOL_FILE ?
+                 _("file") : _("block"));
+
+        val = prettyCapacity(info.capacity, &unit);
+        vshPrint(ctl, "%-15s %2.2lf %s\n", _("Capacity:"), val, unit);
+
+        val = prettyCapacity(info.allocation, &unit);
+        vshPrint(ctl, "%-15s %2.2lf %s\n", _("Allocation:"), val, unit);
+    } else {
+        ret = FALSE;
+    }
+
+    virStorageVolFree(vol);
+    return ret;
+}
+
+
+/*
+ * "vol-dumpxml" command
+ */
+static vshCmdInfo info_vol_dumpxml[] = {
+    {"syntax", "vol-dumpxml <vol>"},
+    {"help", gettext_noop("vol information in XML")},
+    {"desc", gettext_noop("Output the vol information as an XML dump to stdout.")},
+    {NULL, NULL}
+};
+
+static vshCmdOptDef opts_vol_dumpxml[] = {
+    {"pool", VSH_OT_STRING, 0, gettext_noop("pool name or uuid")},
+    {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("vol name, key or path")},
+    {NULL, 0, 0, NULL}
+};
+
+static int
+cmdVolDumpXML(vshControl * ctl, vshCmd * cmd)
+{
+    virStorageVolPtr vol;
+    int ret = TRUE;
+    char *dump;
+
+    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+        return FALSE;
+
+    if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", NULL)))
+        return FALSE;
+
+    dump = virStorageVolGetXMLDesc(vol, 0);
+    if (dump != NULL) {
+        printf("%s", dump);
+        free(dump);
+    } else {
+        ret = FALSE;
+    }
+
+    virStorageVolFree(vol);
+    return ret;
+}
+
+
+/*
+ * "vol-list" command
+ */
+static vshCmdInfo info_vol_list[] = {
+    {"syntax", "vol-list <pool>"},
+    {"help", gettext_noop("list vols")},
+    {"desc", gettext_noop("Returns list of vols by pool.")},
+    {NULL, NULL}
+};
+
+static vshCmdOptDef opts_vol_list[] = {
+    {"pool", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("pool name or uuid")},
+    {NULL, 0, 0, NULL}
+};
+
+static int
+cmdVolList(vshControl * ctl, vshCmd * cmd ATTRIBUTE_UNUSED)
+{
+    virStoragePoolPtr pool;
+    int maxactive = 0, i;
+    char **activeNames = NULL;
+
+    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+        return FALSE;
+
+    if (!(pool = vshCommandOptPool(ctl, cmd, "pool", NULL)))
+        return FALSE;
+
+    maxactive = virStoragePoolNumOfVolumes(pool);
+    if (maxactive < 0) {
+        virStoragePoolFree(pool);
+        vshError(ctl, FALSE, "%s", _("Failed to list active vols"));
+        return FALSE;
+    }
+    if (maxactive) {
+        activeNames = vshMalloc(ctl, sizeof(char *) * maxactive);
+
+        if ((maxactive = virStoragePoolListVolumes(pool, activeNames,
+                                                   maxactive)) < 0) {
+            vshError(ctl, FALSE, "%s", _("Failed to list active vols"));
+            free(activeNames);
+            virStoragePoolFree(pool);
+            return FALSE;
+        }
+
+        qsort(&activeNames[0], maxactive, sizeof(char *), namesorter);
+    }
+    vshPrintExtra(ctl, "%-20s %-40s\n", _("Name"), _("Path"));
+    vshPrintExtra(ctl, "-----------------------------------------\n");
+
+    for (i = 0; i < maxactive; i++) {
+        virStorageVolPtr vol = virStorageVolLookupByName(pool, activeNames[i]);
+        char *path;
+
+        /* this kind of work with vols is not atomic operation */
+        if (!vol) {
+            free(activeNames[i]);
+            continue;
+        }
+
+        if ((path = virStorageVolGetPath(vol)) == NULL) {
+            virStorageVolFree(vol);
+            continue;
+        }
+
+
+        vshPrint(ctl, "%-20s %-40s\n",
+                 virStorageVolGetName(vol),
+                 path);
+        free(path);
+        virStorageVolFree(vol);
+        free(activeNames[i]);
+    }
+    free(activeNames);
+    virStoragePoolFree(pool);
+    return TRUE;
+}
+
+
+/*
+ * "vol-name" command
+ */
+static vshCmdInfo info_vol_name[] = {
+    {"syntax", "vol-name <vol>"},
+    {"help", gettext_noop("convert a vol UUID to vol name")},
+    {NULL, NULL}
+};
+
+static vshCmdOptDef opts_vol_name[] = {
+    {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("vol key or path")},
+    {NULL, 0, 0, NULL}
+};
+
+static int
+cmdVolName(vshControl * ctl, vshCmd * cmd)
+{
+    virStorageVolPtr vol;
+
+    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+        return FALSE;
+
+    if (!(vol = vshCommandOptVolBy(ctl, cmd, "vol", "pool", NULL,
+                                   VSH_BYUUID)))
+        return FALSE;
+
+    vshPrint(ctl, "%s\n", virStorageVolGetName(vol));
+    virStorageVolFree(vol);
+    return TRUE;
+}
+
+
+
+/*
+ * "vol-key" command
+ */
+static vshCmdInfo info_vol_key[] = {
+    {"syntax", "vol-key <vol>"},
+    {"help", gettext_noop("convert a vol UUID to vol key")},
+    {NULL, NULL}
+};
+
+static vshCmdOptDef opts_vol_key[] = {
+    {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("vol uuid")},
+    {NULL, 0, 0, NULL}
+};
+
+static int
+cmdVolKey(vshControl * ctl, vshCmd * cmd)
+{
+    virStorageVolPtr vol;
+
+    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+        return FALSE;
+
+    if (!(vol = vshCommandOptVolBy(ctl, cmd, "vol", NULL, NULL,
+                                   VSH_BYUUID)))
+        return FALSE;
+
+    vshPrint(ctl, "%s\n", virStorageVolGetKey(vol));
+    virStorageVolFree(vol);
+    return TRUE;
+}
+
+
+
+/*
+ * "vol-path" command
+ */
+static vshCmdInfo info_vol_path[] = {
+    {"syntax", "vol-path <pool> <vol>"},
+    {"help", gettext_noop("convert a vol UUID to vol path")},
+    {NULL, NULL}
+};
+
+static vshCmdOptDef opts_vol_path[] = {
+    {"pool", VSH_OT_STRING, 0, gettext_noop("pool name or uuid")},
+    {"vol", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("vol name or key")},
+    {NULL, 0, 0, NULL}
+};
+
+static int
+cmdVolPath(vshControl * ctl, vshCmd * cmd)
+{
+    virStorageVolPtr vol;
+
+    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+        return FALSE;
+    if (!(vol = vshCommandOptVolBy(ctl, cmd, "vol", "pool", NULL,
+                                   VSH_BYUUID)))
+        return FALSE;
+
+    vshPrint(ctl, "%s\n", virStorageVolGetPath(vol));
+    virStorageVolFree(vol);
+    return TRUE;
+}
+
+
+
+
+
+
+
+/*
+ * "version" command
+ */
+static vshCmdInfo info_version[] = {
+    {"syntax", "version"},
+    {"help", gettext_noop("show version")},
+    {"desc", gettext_noop("Display the system version information.")},
+    {NULL, NULL}
+};
+
+
+static int
+cmdVersion(vshControl * ctl, vshCmd * cmd ATTRIBUTE_UNUSED)
+{
+    unsigned long hvVersion;
+    const char *hvType;
+    unsigned long libVersion;
+    unsigned long includeVersion;
+    unsigned long apiVersion;
+    int ret;
+    unsigned int major;
+    unsigned int minor;
+    unsigned int rel;
+
+    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+        return FALSE;
+
+    hvType = virConnectGetType(ctl->conn);
+    if (hvType == NULL) {
+        vshError(ctl, FALSE, "%s", _("failed to get hypervisor type"));
+        return FALSE;
+    }
+
+    includeVersion = LIBVIR_VERSION_NUMBER;
+    major = includeVersion / 1000000;
+    includeVersion %= 1000000;
+    minor = includeVersion / 1000;
+    rel = includeVersion % 1000;
+    vshPrint(ctl, _("Compiled against library: libvir %d.%d.%d\n"),
+             major, minor, rel);
+
+    ret = virGetVersion(&libVersion, hvType, &apiVersion);
+    if (ret < 0) {
+        vshError(ctl, FALSE, "%s", _("failed to get the library version"));
+        return FALSE;
+    }
+    major = libVersion / 1000000;
+    libVersion %= 1000000;
+    minor = libVersion / 1000;
+    rel = libVersion % 1000;
+    vshPrint(ctl, _("Using library: libvir %d.%d.%d\n"),
+             major, minor, rel);
+
+    major = apiVersion / 1000000;
+    apiVersion %= 1000000;
+    minor = apiVersion / 1000;
+    rel = apiVersion % 1000;
+    vshPrint(ctl, _("Using API: %s %d.%d.%d\n"), hvType,
+             major, minor, rel);
+
+    ret = virConnectGetVersion(ctl->conn, &hvVersion);
+    if (ret < 0) {
+        vshError(ctl, FALSE, "%s", _("failed to get the hypervisor version"));
+        return FALSE;
+    }
+    if (hvVersion == 0) {
+        vshPrint(ctl,
+                 _("Cannot extract running %s hypervisor version\n"), hvType);
+    } else {
+        major = hvVersion / 1000000;
+        hvVersion %= 1000000;
+        minor = hvVersion / 1000;
+        rel = hvVersion % 1000;
+
+        vshPrint(ctl, _("Running hypervisor: %s %d.%d.%d\n"),
+                 hvType, major, minor, rel);
+    }
+    return TRUE;
+}
+
+/*
+ * "hostkey" command
+ */
+static vshCmdInfo info_hostname[] = {
+    {"syntax", "hostname"},
+    {"help", gettext_noop("print the hypervisor hostname")},
+    {NULL, NULL}
+};
+
+static int
+cmdHostname (vshControl *ctl, vshCmd *cmd ATTRIBUTE_UNUSED)
+{
+    char *hostname;
+
+    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+        return FALSE;
+
+    hostname = virConnectGetHostname (ctl->conn);
+    if (hostname == NULL) {
+        vshError(ctl, FALSE, "%s", _("failed to get hostname"));
+        return FALSE;
+    }
+
+    vshPrint (ctl, "%s\n", hostname);
+    free (hostname);
+
+    return TRUE;
+}
+
+/*
+ * "uri" command
+ */
+static vshCmdInfo info_uri[] = {
+    {"syntax", "uri"},
+    {"help", gettext_noop("print the hypervisor canonical URI")},
+    {NULL, NULL}
+};
+
+static int
+cmdURI (vshControl *ctl, vshCmd *cmd ATTRIBUTE_UNUSED)
+{
+    char *uri;
+
+    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+        return FALSE;
+
+    uri = virConnectGetURI (ctl->conn);
+    if (uri == NULL) {
+        vshError(ctl, FALSE, "%s", _("failed to get URI"));
+        return FALSE;
+    }
+
+    vshPrint (ctl, "%s\n", uri);
+    free (uri);
+
+    return TRUE;
+}
+
+/*
+ * "vncdisplay" command
+ */
+static vshCmdInfo info_vncdisplay[] = {
+    {"syntax", "vncdisplay <domain>"},
+    {"help", gettext_noop("vnc display")},
+    {"desc", gettext_noop("Output the IP address and port number for the VNC display.")},
+    {NULL, NULL}
+};
+
+static vshCmdOptDef opts_vncdisplay[] = {
+    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
+    {NULL, 0, 0, NULL}
+};
+
+static int
+cmdVNCDisplay(vshControl * ctl, vshCmd * cmd)
+{
+    xmlDocPtr xml = NULL;
+    xmlXPathObjectPtr obj = NULL;
+    xmlXPathContextPtr ctxt = NULL;
+    virDomainPtr dom;
+    int ret = FALSE;
+    int port = 0;
+    char *doc;
+
+    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+        return FALSE;
+
+    if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", NULL)))
+        return FALSE;
+
+    doc = virDomainGetXMLDesc(dom, 0);
+    if (!doc)
+        goto cleanup;
+
+    xml = xmlReadDoc((const xmlChar *) doc, "domain.xml", NULL,
+                     XML_PARSE_NOENT | XML_PARSE_NONET |
+                     XML_PARSE_NOWARNING);
+    free(doc);
+    if (!xml)
+        goto cleanup;
+    ctxt = xmlXPathNewContext(xml);
+    if (!ctxt)
+        goto cleanup;
+
+    obj = xmlXPathEval(BAD_CAST "string(/domain/devices/graphics[@type='vnc']/@port)", ctxt);
+    if ((obj == NULL) || (obj->type != XPATH_STRING) ||
+        (obj->stringval == NULL) || (obj->stringval[0] == 0)) {
+        goto cleanup;
+    }
+    if (virStrToLong_i((const char *)obj->stringval, NULL, 10, &port) || port < 0)
+        goto cleanup;
+    xmlXPathFreeObject(obj);
+
+    obj = xmlXPathEval(BAD_CAST "string(/domain/devices/graphics[@type='vnc']/@listen)", ctxt);
+    if ((obj == NULL) || (obj->type != XPATH_STRING) ||
+        (obj->stringval == NULL) || (obj->stringval[0] == 0) ||
+        !strcmp((const char*)obj->stringval, "0.0.0.0")) {
+        vshPrint(ctl, ":%d\n", port-5900);
+    } else {
+        vshPrint(ctl, "%s:%d\n", (const char *)obj->stringval, port-5900);
+    }
+    xmlXPathFreeObject(obj);
+    obj = NULL;
+    ret = TRUE;
+
+ cleanup:
+    xmlXPathFreeObject(obj);
+    xmlXPathFreeContext(ctxt);
+    if (xml)
+        xmlFreeDoc(xml);
+    virDomainFree(dom);
+    return ret;
+}
+
+/*
+ * "ttyconsole" command
+ */
+static vshCmdInfo info_ttyconsole[] = {
+    {"syntax", "ttyconsole <domain>"},
+    {"help", gettext_noop("tty console")},
+    {"desc", gettext_noop("Output the device for the TTY console.")},
+    {NULL, NULL}
+};
+
+static vshCmdOptDef opts_ttyconsole[] = {
+    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
+    {NULL, 0, 0, NULL}
+};
+
+static int
+cmdTTYConsole(vshControl * ctl, vshCmd * cmd)
+{
+    xmlDocPtr xml = NULL;
+    xmlXPathObjectPtr obj = NULL;
+    xmlXPathContextPtr ctxt = NULL;
+    virDomainPtr dom;
+    int ret = FALSE;
+    char *doc;
+
+    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+        return FALSE;
+
+    if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", NULL)))
+        return FALSE;
+
+    doc = virDomainGetXMLDesc(dom, 0);
+    if (!doc)
+        goto cleanup;
+
+    xml = xmlReadDoc((const xmlChar *) doc, "domain.xml", NULL,
+                     XML_PARSE_NOENT | XML_PARSE_NONET |
+                     XML_PARSE_NOWARNING);
+    free(doc);
+    if (!xml)
+        goto cleanup;
+    ctxt = xmlXPathNewContext(xml);
+    if (!ctxt)
+        goto cleanup;
+
+    obj = xmlXPathEval(BAD_CAST "string(/domain/devices/console/@tty)", ctxt);
+    if ((obj == NULL) || (obj->type != XPATH_STRING) ||
+        (obj->stringval == NULL) || (obj->stringval[0] == 0)) {
+        goto cleanup;
+    }
+    vshPrint(ctl, "%s\n", (const char *)obj->stringval);
+
+ cleanup:
+    xmlXPathFreeObject(obj);
+    xmlXPathFreeContext(ctxt);
+    if (xml)
+        xmlFreeDoc(xml);
+    virDomainFree(dom);
+    return ret;
+}
+
+/*
+ * "attach-device" command
  */
 static vshCmdInfo info_attach_device[] = {
     {"syntax", "attach-device <domain> <file> "},
@@ -3665,6 +4786,7 @@ static vshCmdDef commands[] = {
     {"hostname", cmdHostname, NULL, info_hostname},
     {"list", cmdList, opts_list, info_list},
     {"migrate", cmdMigrate, opts_migrate, info_migrate},
+
     {"net-autostart", cmdNetworkAutostart, opts_network_autostart, info_network_autostart},
     {"net-create", cmdNetworkCreate, opts_network_create, info_network_create},
     {"net-define", cmdNetworkDefine, opts_network_define, info_network_define},
@@ -3676,6 +4798,22 @@ static vshCmdDef commands[] = {
     {"net-undefine", cmdNetworkUndefine, opts_network_undefine, info_network_undefine},
     {"net-uuid", cmdNetworkUuid, opts_network_uuid, info_network_uuid},
     {"nodeinfo", cmdNodeinfo, NULL, info_nodeinfo},
+
+    {"pool-autostart", cmdPoolAutostart, opts_pool_autostart, info_pool_autostart},
+    {"pool-build", cmdPoolBuild, opts_pool_build, info_pool_build},
+    {"pool-create", cmdPoolCreate, opts_pool_create, info_pool_create},
+    {"pool-define", cmdPoolDefine, opts_pool_define, info_pool_define},
+    {"pool-destroy", cmdPoolDestroy, opts_pool_destroy, info_pool_destroy},
+    {"pool-delete", cmdPoolDelete, opts_pool_delete, info_pool_delete},
+    {"pool-dumpxml", cmdPoolDumpXML, opts_pool_dumpxml, info_pool_dumpxml},
+    {"pool-info", cmdPoolInfo, opts_pool_info, info_pool_info},
+    {"pool-list", cmdPoolList, opts_pool_list, info_pool_list},
+    {"pool-name", cmdPoolName, opts_pool_name, info_pool_name},
+    {"pool-refresh", cmdPoolRefresh, opts_pool_refresh, info_pool_refresh},
+    {"pool-start", cmdPoolStart, opts_pool_start, info_pool_start},
+    {"pool-undefine", cmdPoolUndefine, opts_pool_undefine, info_pool_undefine},
+    {"pool-uuid", cmdPoolUuid, opts_pool_uuid, info_pool_uuid},
+
     {"quit", cmdQuit, NULL, info_quit},
     {"reboot", cmdReboot, opts_reboot, info_reboot},
     {"restore", cmdRestore, opts_restore, info_restore},
@@ -3691,6 +4829,16 @@ static vshCmdDef commands[] = {
     {"ttyconsole", cmdTTYConsole, opts_ttyconsole, info_ttyconsole},
     {"undefine", cmdUndefine, opts_undefine, info_undefine},
     {"uri", cmdURI, NULL, info_uri},
+
+    {"vol-create", cmdVolCreate, opts_vol_create, info_vol_create},
+    {"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},
+    {"vol-list", cmdVolList, opts_vol_list, info_vol_list},
+    {"vol-path", cmdVolPath, opts_vol_path, info_vol_path},
+    {"vol-name", cmdVolName, opts_vol_name, info_vol_name},
+    {"vol-key", cmdVolKey, opts_vol_key, info_vol_key},
+
     {"vcpuinfo", cmdVcpuinfo, opts_vcpuinfo, info_vcpuinfo},
     {"vcpupin", cmdVcpupin, opts_vcpupin, info_vcpupin},
     {"version", cmdVersion, NULL, info_version},
@@ -4016,6 +5164,99 @@ vshCommandOptNetworkBy(vshControl * ctl, vshCmd * cmd, const char *optname,
     return network;
 }
 
+static virStoragePoolPtr
+vshCommandOptPoolBy(vshControl * ctl, vshCmd * cmd, const char *optname,
+                    char **name, int flag)
+{
+    virStoragePoolPtr pool = NULL;
+    char *n;
+
+    if (!(n = vshCommandOptString(cmd, optname, NULL))) {
+        vshError(ctl, FALSE, "%s", _("undefined pool name"));
+        return NULL;
+    }
+
+    vshDebug(ctl, 5, "%s: found option <%s>: %s\n",
+             cmd->def->name, optname, n);
+
+    if (name)
+        *name = n;
+
+    /* try it by UUID */
+    if (pool==NULL && (flag & VSH_BYUUID) && strlen(n)==VIR_UUID_STRING_BUFLEN-1) {
+        vshDebug(ctl, 5, "%s: <%s> trying as pool UUID\n",
+                cmd->def->name, optname);
+        pool = virStoragePoolLookupByUUIDString(ctl->conn, n);
+    }
+    /* try it by NAME */
+    if (pool==NULL && (flag & VSH_BYNAME)) {
+        vshDebug(ctl, 5, "%s: <%s> trying as pool NAME\n",
+                 cmd->def->name, optname);
+        pool = virStoragePoolLookupByName(ctl->conn, n);
+    }
+
+    if (!pool)
+        vshError(ctl, FALSE, _("failed to get pool '%s'"), n);
+
+    return pool;
+}
+
+static virStorageVolPtr
+vshCommandOptVolBy(vshControl * ctl, vshCmd * cmd,
+                   const char *optname,
+                   const char *pooloptname,
+                   char **name, int flag)
+{
+    virStorageVolPtr vol = NULL;
+    virStoragePoolPtr pool = NULL;
+    char *n, *p;
+    int found;
+
+    if (!(n = vshCommandOptString(cmd, optname, NULL))) {
+        vshError(ctl, FALSE, "%s", _("undefined vol name"));
+        return NULL;
+    }
+
+    if (!(p = vshCommandOptString(cmd, pooloptname, &found)) && found) {
+        vshError(ctl, FALSE, "%s", _("undefined pool name"));
+        return NULL;
+    }
+
+    if (p)
+        pool = vshCommandOptPoolBy(ctl, cmd, pooloptname, name, flag);
+
+    vshDebug(ctl, 5, "%s: found option <%s>: %s\n",
+             cmd->def->name, optname, n);
+
+    if (name)
+        *name = n;
+
+    /* try it by PATH */
+    if (pool && (flag & VSH_BYNAME)) {
+        vshDebug(ctl, 5, "%s: <%s> trying as vol UUID\n",
+                 cmd->def->name, optname);
+        vol = virStorageVolLookupByName(pool, n);
+    }
+    if (vol == NULL && (flag & VSH_BYUUID)) {
+        vshDebug(ctl, 5, "%s: <%s> trying as vol key\n",
+                 cmd->def->name, optname);
+        vol = virStorageVolLookupByKey(ctl->conn, n);
+    }
+    if (vol == NULL && (flag & VSH_BYUUID)) {
+        vshDebug(ctl, 5, "%s: <%s> trying as vol path\n",
+                 cmd->def->name, optname);
+        vol = virStorageVolLookupByPath(ctl->conn, n);
+    }
+
+    if (!vol)
+        vshError(ctl, FALSE, _("failed to get vol '%s'"), n);
+
+    if (pool)
+        virStoragePoolFree(pool);
+
+    return vol;
+}
+
 /*
  * Executes command(s) and returns return code from last command
  */