[libvirt] [PATCH 02/13] virsh: Split cmds for domain monitoring from virsh.c

Osier Yang jyang at redhat.com
Tue Jul 24 09:18:24 UTC 2012


This splits commands commands to monitor domain status into
virsh-domain-monitor.c. The helpers not for common use are moved too.
Standard copyright is added.

* tools/virsh.c:
  Remove commands for domain monitoring group and a few helpers (
  vshDomainIOErrorToString, vshGetDomainDescription,
  vshDomainControlStateToString, vshDomainStateToString) not for
  common use.

* tools/virsh-domain-monitor.c:
  New file, filled with commands of domain monitor group.
---
 tools/virsh-domain-monitor.c | 1685 +++++++++++++++++++++++++++++++++++++
 tools/virsh.c                | 1904 +++---------------------------------------
 2 files changed, 1807 insertions(+), 1782 deletions(-)
 create mode 100644 tools/virsh-domain-monitor.c

diff --git a/tools/virsh-domain-monitor.c b/tools/virsh-domain-monitor.c
new file mode 100644
index 0000000..1a61f62
--- /dev/null
+++ b/tools/virsh-domain-monitor.c
@@ -0,0 +1,1685 @@
+/*
+ * virsh-domain.c: Commands to monitor domain status
+ *
+ * Copyright (C) 2005, 2007-2012 Red Hat, Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ *  Daniel Veillard <veillard at redhat.com>
+ *  Karel Zak <kzak at redhat.com>
+ *  Daniel P. Berrange <berrange at redhat.com>
+ *
+ */
+
+static const char *
+vshDomainIOErrorToString(int error)
+{
+    switch ((virDomainDiskErrorCode) error) {
+    case VIR_DOMAIN_DISK_ERROR_NONE:
+        return _("no error");
+    case VIR_DOMAIN_DISK_ERROR_UNSPEC:
+        return _("unspecified error");
+    case VIR_DOMAIN_DISK_ERROR_NO_SPACE:
+        return _("no space");
+    case VIR_DOMAIN_DISK_ERROR_LAST:
+        ;
+    }
+
+    return _("unknown error");
+}
+
+/* extract description or title from domain xml */
+static char *
+vshGetDomainDescription(vshControl *ctl, virDomainPtr dom, bool title,
+                        unsigned int flags)
+{
+    char *desc = NULL;
+    char *domxml = NULL;
+    virErrorPtr err = NULL;
+    xmlDocPtr doc = NULL;
+    xmlXPathContextPtr ctxt = NULL;
+    int type;
+
+    if (title)
+        type = VIR_DOMAIN_METADATA_TITLE;
+    else
+        type = VIR_DOMAIN_METADATA_DESCRIPTION;
+
+    if ((desc = virDomainGetMetadata(dom, type, NULL, flags))) {
+        return desc;
+    } else {
+        err = virGetLastError();
+
+        if (err && err->code == VIR_ERR_NO_DOMAIN_METADATA) {
+            desc = vshStrdup(ctl, "");
+            virResetLastError();
+            return desc;
+        }
+
+        if (err && err->code != VIR_ERR_NO_SUPPORT)
+            return desc;
+    }
+
+    /* fall back to xml */
+    /* get domain's xml description and extract the title/description */
+    if (!(domxml = virDomainGetXMLDesc(dom, flags))) {
+        vshError(ctl, "%s", _("Failed to retrieve domain XML"));
+        goto cleanup;
+    }
+    doc = virXMLParseStringCtxt(domxml, _("(domain_definition)"), &ctxt);
+    if (!doc) {
+        vshError(ctl, "%s", _("Couldn't parse domain XML"));
+        goto cleanup;
+    }
+    if (title)
+        desc = virXPathString("string(./title[1])", ctxt);
+    else
+        desc = virXPathString("string(./description[1])", ctxt);
+
+    if (!desc)
+        desc = vshStrdup(ctl, "");
+
+cleanup:
+    VIR_FREE(domxml);
+    xmlXPathFreeContext(ctxt);
+    xmlFreeDoc(doc);
+
+    return desc;
+}
+static const char *
+vshDomainControlStateToString(int state)
+{
+    switch ((virDomainControlState) state) {
+    case VIR_DOMAIN_CONTROL_OK:
+        return N_("ok");
+    case VIR_DOMAIN_CONTROL_JOB:
+        return N_("background job");
+    case VIR_DOMAIN_CONTROL_OCCUPIED:
+        return N_("occupied");
+    case VIR_DOMAIN_CONTROL_ERROR:
+        return N_("error");
+    default:
+        ;
+    }
+
+    return N_("unknown");
+}
+
+static const char *
+vshDomainStateToString(int state)
+{
+    /* Can't use virDomainStateTypeToString, because we want to mark
+ *      * strings for translation.  */
+    switch ((virDomainState) state) {
+    case VIR_DOMAIN_RUNNING:
+        return N_("running");
+    case VIR_DOMAIN_BLOCKED:
+        return N_("idle");
+    case VIR_DOMAIN_PAUSED:
+        return N_("paused");
+    case VIR_DOMAIN_SHUTDOWN:
+        return N_("in shutdown");
+    case VIR_DOMAIN_SHUTOFF:
+        return N_("shut off");
+    case VIR_DOMAIN_CRASHED:
+        return N_("crashed");
+    case VIR_DOMAIN_PMSUSPENDED:
+        return N_("pmsuspended");
+    case VIR_DOMAIN_NOSTATE:
+    default:
+        ;/*FALLTHROUGH*/
+    }
+    return N_("no state");  /* = dom0 state */
+}
+
+static const char *
+vshDomainStateReasonToString(int state, int reason)
+{
+    switch ((virDomainState) state) {
+    case VIR_DOMAIN_NOSTATE:
+        switch ((virDomainNostateReason) reason) {
+        case VIR_DOMAIN_NOSTATE_UNKNOWN:
+        case VIR_DOMAIN_NOSTATE_LAST:
+            ;
+        }
+        break;
+
+    case VIR_DOMAIN_RUNNING:
+        switch ((virDomainRunningReason) reason) {
+        case VIR_DOMAIN_RUNNING_BOOTED:
+            return N_("booted");
+        case VIR_DOMAIN_RUNNING_MIGRATED:
+            return N_("migrated");
+        case VIR_DOMAIN_RUNNING_RESTORED:
+            return N_("restored");
+        case VIR_DOMAIN_RUNNING_FROM_SNAPSHOT:
+            return N_("from snapshot");
+        case VIR_DOMAIN_RUNNING_UNPAUSED:
+            return N_("unpaused");
+        case VIR_DOMAIN_RUNNING_MIGRATION_CANCELED:
+            return N_("migration canceled");
+        case VIR_DOMAIN_RUNNING_SAVE_CANCELED:
+            return N_("save canceled");
+        case VIR_DOMAIN_RUNNING_WAKEUP:
+            return N_("event wakeup");
+        case VIR_DOMAIN_RUNNING_UNKNOWN:
+        case VIR_DOMAIN_RUNNING_LAST:
+            ;
+        }
+        break;
+
+    case VIR_DOMAIN_BLOCKED:
+        switch ((virDomainBlockedReason) reason) {
+        case VIR_DOMAIN_BLOCKED_UNKNOWN:
+        case VIR_DOMAIN_BLOCKED_LAST:
+            ;
+        }
+        break;
+
+    case VIR_DOMAIN_PAUSED:
+        switch ((virDomainPausedReason) reason) {
+        case VIR_DOMAIN_PAUSED_USER:
+            return N_("user");
+        case VIR_DOMAIN_PAUSED_MIGRATION:
+            return N_("migrating");
+        case VIR_DOMAIN_PAUSED_SAVE:
+            return N_("saving");
+        case VIR_DOMAIN_PAUSED_DUMP:
+            return N_("dumping");
+        case VIR_DOMAIN_PAUSED_IOERROR:
+            return N_("I/O error");
+        case VIR_DOMAIN_PAUSED_WATCHDOG:
+            return N_("watchdog");
+        case VIR_DOMAIN_PAUSED_FROM_SNAPSHOT:
+            return N_("from snapshot");
+        case VIR_DOMAIN_PAUSED_SHUTTING_DOWN:
+            return N_("shutting down");
+        case VIR_DOMAIN_PAUSED_UNKNOWN:
+        case VIR_DOMAIN_PAUSED_LAST:
+            ;
+        }
+        break;
+
+    case VIR_DOMAIN_SHUTDOWN:
+        switch ((virDomainShutdownReason) reason) {
+        case VIR_DOMAIN_SHUTDOWN_USER:
+            return N_("user");
+        case VIR_DOMAIN_SHUTDOWN_UNKNOWN:
+        case VIR_DOMAIN_SHUTDOWN_LAST:
+            ;
+        }
+        break;
+
+    case VIR_DOMAIN_SHUTOFF:
+        switch ((virDomainShutoffReason) reason) {
+        case VIR_DOMAIN_SHUTOFF_SHUTDOWN:
+            return N_("shutdown");
+        case VIR_DOMAIN_SHUTOFF_DESTROYED:
+            return N_("destroyed");
+        case VIR_DOMAIN_SHUTOFF_CRASHED:
+            return N_("crashed");
+        case VIR_DOMAIN_SHUTOFF_MIGRATED:
+            return N_("migrated");
+        case VIR_DOMAIN_SHUTOFF_SAVED:
+            return N_("saved");
+        case VIR_DOMAIN_SHUTOFF_FAILED:
+            return N_("failed");
+        case VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT:
+            return N_("from snapshot");
+        case VIR_DOMAIN_SHUTOFF_UNKNOWN:
+        case VIR_DOMAIN_SHUTOFF_LAST:
+            ;
+        }
+        break;
+
+    case VIR_DOMAIN_CRASHED:
+        switch ((virDomainCrashedReason) reason) {
+        case VIR_DOMAIN_CRASHED_UNKNOWN:
+        case VIR_DOMAIN_CRASHED_LAST:
+            ;
+        }
+        break;
+
+    case VIR_DOMAIN_PMSUSPENDED:
+        switch ((virDomainPMSuspendedReason) reason) {
+        case VIR_DOMAIN_PMSUSPENDED_UNKNOWN:
+        case VIR_DOMAIN_PMSUSPENDED_LAST:
+            ;
+        }
+        break;
+
+    case VIR_DOMAIN_LAST:
+        ;
+    }
+
+    return N_("unknown");
+}
+
+/*
+ * "dommemstats" command
+ */
+static const vshCmdInfo info_dommemstat[] = {
+    {"help", N_("get memory statistics for a domain")},
+    {"desc", N_("Get memory statistics for a running domain.")},
+    {NULL,NULL}
+};
+
+static const vshCmdOptDef opts_dommemstat[] = {
+    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
+    {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdDomMemStat(vshControl *ctl, const vshCmd *cmd)
+{
+    virDomainPtr dom;
+    const char *name;
+    struct _virDomainMemoryStat stats[VIR_DOMAIN_MEMORY_STAT_NR];
+    unsigned int nr_stats, i;
+
+    if (!vshConnectionUsability(ctl, ctl->conn))
+        return false;
+
+    if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
+        return false;
+
+    nr_stats = virDomainMemoryStats(dom, stats, VIR_DOMAIN_MEMORY_STAT_NR, 0);
+    if (nr_stats == -1) {
+        vshError(ctl, _("Failed to get memory statistics for domain %s"), name);
+        virDomainFree(dom);
+        return false;
+    }
+
+    for (i = 0; i < nr_stats; i++) {
+        if (stats[i].tag == VIR_DOMAIN_MEMORY_STAT_SWAP_IN)
+            vshPrint(ctl, "swap_in %llu\n", stats[i].val);
+        if (stats[i].tag == VIR_DOMAIN_MEMORY_STAT_SWAP_OUT)
+            vshPrint(ctl, "swap_out %llu\n", stats[i].val);
+        if (stats[i].tag == VIR_DOMAIN_MEMORY_STAT_MAJOR_FAULT)
+            vshPrint(ctl, "major_fault %llu\n", stats[i].val);
+        if (stats[i].tag == VIR_DOMAIN_MEMORY_STAT_MINOR_FAULT)
+            vshPrint(ctl, "minor_fault %llu\n", stats[i].val);
+        if (stats[i].tag == VIR_DOMAIN_MEMORY_STAT_UNUSED)
+            vshPrint(ctl, "unused %llu\n", stats[i].val);
+        if (stats[i].tag == VIR_DOMAIN_MEMORY_STAT_AVAILABLE)
+            vshPrint(ctl, "available %llu\n", stats[i].val);
+        if (stats[i].tag == VIR_DOMAIN_MEMORY_STAT_ACTUAL_BALLOON)
+            vshPrint(ctl, "actual %llu\n", stats[i].val);
+        if (stats[i].tag == VIR_DOMAIN_MEMORY_STAT_RSS)
+            vshPrint(ctl, "rss %llu\n", stats[i].val);
+    }
+
+    virDomainFree(dom);
+    return true;
+}
+
+/*
+ * "domblkinfo" command
+ */
+static const vshCmdInfo info_domblkinfo[] = {
+    {"help", N_("domain block device size information")},
+    {"desc", N_("Get block device size info for a domain.")},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_domblkinfo[] = {
+    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
+    {"device", VSH_OT_DATA, VSH_OFLAG_REQ, N_("block device")},
+    {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdDomblkinfo(vshControl *ctl, const vshCmd *cmd)
+{
+    virDomainBlockInfo info;
+    virDomainPtr dom;
+    bool ret = true;
+    const char *device = NULL;
+
+    if (!vshConnectionUsability(ctl, ctl->conn))
+        return false;
+
+    if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+        return false;
+
+    if (vshCommandOptString(cmd, "device", &device) <= 0) {
+        virDomainFree(dom);
+        return false;
+    }
+
+    if (virDomainGetBlockInfo(dom, device, &info, 0) < 0) {
+        virDomainFree(dom);
+        return false;
+    }
+
+    vshPrint(ctl, "%-15s %llu\n", _("Capacity:"), info.capacity);
+    vshPrint(ctl, "%-15s %llu\n", _("Allocation:"), info.allocation);
+    vshPrint(ctl, "%-15s %llu\n", _("Physical:"), info.physical);
+
+    virDomainFree(dom);
+    return ret;
+}
+
+/*
+ * "domblklist" command
+ */
+static const vshCmdInfo info_domblklist[] = {
+    {"help", N_("list all domain blocks")},
+    {"desc", N_("Get the summary of block devices for a domain.")},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_domblklist[] = {
+    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
+    {"inactive", VSH_OT_BOOL, 0,
+     N_("get inactive rather than running configuration")},
+    {"details", VSH_OT_BOOL, 0,
+     N_("additionally display the type and device value")},
+    {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdDomblklist(vshControl *ctl, const vshCmd *cmd)
+{
+    virDomainPtr dom;
+    bool ret = false;
+    unsigned int flags = 0;
+    char *xml = NULL;
+    xmlDocPtr xmldoc = NULL;
+    xmlXPathContextPtr ctxt = NULL;
+    int ndisks;
+    xmlNodePtr *disks = NULL;
+    int i;
+    bool details = false;
+
+    if (vshCommandOptBool(cmd, "inactive"))
+        flags |= VIR_DOMAIN_XML_INACTIVE;
+
+    details = vshCommandOptBool(cmd, "details");
+
+    if (!vshConnectionUsability(ctl, ctl->conn))
+        return false;
+
+    if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+        return false;
+
+    xml = virDomainGetXMLDesc(dom, flags);
+    if (!xml)
+        goto cleanup;
+
+    xmldoc = virXMLParseStringCtxt(xml, _("(domain_definition)"), &ctxt);
+    if (!xmldoc)
+        goto cleanup;
+
+    ndisks = virXPathNodeSet("./devices/disk", ctxt, &disks);
+    if (ndisks < 0)
+        goto cleanup;
+
+    if (details)
+        vshPrint(ctl, "%-10s %-10s %-10s %s\n", _("Type"),
+                 _("Device"), _("Target"), _("Source"));
+    else
+        vshPrint(ctl, "%-10s %s\n", _("Target"), _("Source"));
+
+    vshPrint(ctl, "------------------------------------------------\n");
+
+    for (i = 0; i < ndisks; i++) {
+        char *type;
+        char *device;
+        char *target;
+        char *source;
+
+        ctxt->node = disks[i];
+
+        if (details) {
+            type = virXPathString("string(./@type)", ctxt);
+            device = virXPathString("string(./@device)", ctxt);
+        }
+
+        target = virXPathString("string(./target/@dev)", ctxt);
+        if (!target) {
+            vshError(ctl, "unable to query block list");
+            goto cleanup;
+        }
+        source = virXPathString("string(./source/@file"
+                                "|./source/@dev"
+                                "|./source/@dir"
+                                "|./source/@name)", ctxt);
+        if (details) {
+            vshPrint(ctl, "%-10s %-10s %-10s %s\n", type, device,
+                     target, source ? source : "-");
+            VIR_FREE(type);
+            VIR_FREE(device);
+        } else {
+            vshPrint(ctl, "%-10s %s\n", target, source ? source : "-");
+        }
+
+        VIR_FREE(target);
+        VIR_FREE(source);
+    }
+
+    ret = true;
+
+cleanup:
+    VIR_FREE(disks);
+    virDomainFree(dom);
+    VIR_FREE(xml);
+    xmlFreeDoc(xmldoc);
+    xmlXPathFreeContext(ctxt);
+    return ret;
+}
+
+/*
+ * "domiflist" command
+ */
+static const vshCmdInfo info_domiflist[] = {
+    {"help", N_("list all domain virtual interfaces")},
+    {"desc", N_("Get the summary of virtual interfaces for a domain.")},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_domiflist[] = {
+    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
+    {"inactive", VSH_OT_BOOL, 0,
+     N_("get inactive rather than running configuration")},
+    {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdDomiflist(vshControl *ctl, const vshCmd *cmd)
+{
+    virDomainPtr dom;
+    bool ret = false;
+    unsigned int flags = 0;
+    char *xml = NULL;
+    xmlDocPtr xmldoc = NULL;
+    xmlXPathContextPtr ctxt = NULL;
+    int ninterfaces;
+    xmlNodePtr *interfaces = NULL;
+    int i;
+
+    if (vshCommandOptBool(cmd, "inactive"))
+        flags |= VIR_DOMAIN_XML_INACTIVE;
+
+    if (!vshConnectionUsability(ctl, ctl->conn))
+        return false;
+
+    if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+        return false;
+
+    xml = virDomainGetXMLDesc(dom, flags);
+    if (!xml)
+        goto cleanup;
+
+    xmldoc = virXMLParseStringCtxt(xml, _("(domain_definition)"), &ctxt);
+    if (!xmldoc)
+        goto cleanup;
+
+    ninterfaces = virXPathNodeSet("./devices/interface", ctxt, &interfaces);
+    if (ninterfaces < 0)
+        goto cleanup;
+
+    vshPrint(ctl, "%-10s %-10s %-10s %-11s %s\n", _("Interface"), _("Type"),
+             _("Source"), _("Model"), _("MAC"));
+    vshPrint(ctl, "-------------------------------------------------------\n");
+
+    for (i = 0; i < ninterfaces; i++) {
+        char *type = NULL;
+        char *source = NULL;
+        char *target = NULL;
+        char *model = NULL;
+        char *mac = NULL;
+
+        ctxt->node = interfaces[i];
+        type = virXPathString("string(./@type)", ctxt);
+
+        source = virXPathString("string(./source/@bridge"
+                                "|./source/@dev"
+                                "|./source/@network"
+                                "|./source/@name)", ctxt);
+
+        target = virXPathString("string(./target/@dev)", ctxt);
+        model = virXPathString("string(./model/@type)", ctxt);
+        mac = virXPathString("string(./mac/@address)", ctxt);
+
+        vshPrint(ctl, "%-10s %-10s %-10s %-11s %-10s\n",
+                 target ? target : "-",
+                 type,
+                 source ? source : "-",
+                 model ? model : "-",
+                 mac ? mac : "-");
+
+        VIR_FREE(type);
+        VIR_FREE(source);
+        VIR_FREE(target);
+        VIR_FREE(model);
+        VIR_FREE(mac);
+    }
+
+    ret = true;
+
+cleanup:
+    VIR_FREE(interfaces);
+    virDomainFree(dom);
+    VIR_FREE(xml);
+    xmlFreeDoc(xmldoc);
+    xmlXPathFreeContext(ctxt);
+    return ret;
+}
+
+/*
+ * "domif-getlink" command
+ */
+static const vshCmdInfo info_domif_getlink[] = {
+    {"help", N_("get link state of a virtual interface")},
+    {"desc", N_("Get link state of a domain's virtual interface.")},
+    {NULL,NULL}
+};
+
+static const vshCmdOptDef opts_domif_getlink[] = {
+    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
+    {"interface", VSH_OT_DATA, VSH_OFLAG_REQ, N_("interface device (MAC Address)")},
+    {"persistent", VSH_OT_ALIAS, 0, "config"},
+    {"config", VSH_OT_BOOL, 0, N_("Get persistent interface state")},
+    {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdDomIfGetLink(vshControl *ctl, const vshCmd *cmd)
+{
+    virDomainPtr dom;
+    const char *iface = NULL;
+    int flags = 0;
+    char *state = NULL;
+    char *value = NULL;
+    virMacAddr macaddr;
+    const char *element;
+    const char *attr;
+    bool ret = false;
+    int i;
+    char *desc;
+    xmlDocPtr xml = NULL;
+    xmlXPathContextPtr ctxt = NULL;
+    xmlNodePtr cur = NULL;
+    xmlXPathObjectPtr obj = NULL;
+
+    if (!vshConnectionUsability(ctl, ctl->conn))
+        return false;
+
+    if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+        return false;
+
+    if (vshCommandOptString(cmd, "interface", &iface) <= 0) {
+        virDomainFree(dom);
+        return false;
+    }
+
+    if (vshCommandOptBool(cmd, "config"))
+        flags = VIR_DOMAIN_XML_INACTIVE;
+
+    desc = virDomainGetXMLDesc(dom, flags);
+    if (desc == NULL) {
+        vshError(ctl, _("Failed to get domain description xml"));
+        goto cleanup;
+    }
+
+    xml = virXMLParseStringCtxt(desc, _("(domain_definition)"), &ctxt);
+    VIR_FREE(desc);
+    if (!xml) {
+        vshError(ctl, _("Failed to parse domain description xml"));
+        goto cleanup;
+    }
+
+    obj = xmlXPathEval(BAD_CAST "/domain/devices/interface", ctxt);
+    if (obj == NULL || obj->type != XPATH_NODESET ||
+        obj->nodesetval == NULL || obj->nodesetval->nodeNr == 0) {
+        vshError(ctl, _("Failed to extract interface information or no interfaces found"));
+        goto cleanup;
+    }
+
+    if (virMacAddrParse(iface, &macaddr) == 0) {
+        element = "mac";
+        attr = "address";
+    } else {
+        element = "target";
+        attr = "dev";
+    }
+
+    /* find interface with matching mac addr */
+    for (i = 0; i < obj->nodesetval->nodeNr; i++) {
+        cur = obj->nodesetval->nodeTab[i]->children;
+
+        while (cur) {
+            if (cur->type == XML_ELEMENT_NODE &&
+                xmlStrEqual(cur->name, BAD_CAST element)) {
+
+                value = virXMLPropString(cur, attr);
+
+                if (STRCASEEQ(value, iface)) {
+                    VIR_FREE(value);
+                    goto hit;
+                }
+                VIR_FREE(value);
+            }
+            cur = cur->next;
+        }
+    }
+
+    vshError(ctl, _("Interface (%s: %s) not found."), element, iface);
+    goto cleanup;
+
+hit:
+    cur = obj->nodesetval->nodeTab[i]->children;
+    while (cur) {
+        if (cur->type == XML_ELEMENT_NODE &&
+            xmlStrEqual(cur->name, BAD_CAST "link")) {
+
+            state = virXMLPropString(cur, "state");
+            vshPrint(ctl, "%s %s", iface, state);
+            VIR_FREE(state);
+
+            goto cleanup;
+        }
+        cur = cur->next;
+    }
+
+    /* attribute not found */
+    vshPrint(ctl, "%s default", iface);
+
+    ret = true;
+cleanup:
+    xmlXPathFreeObject(obj);
+    xmlXPathFreeContext(ctxt);
+    xmlFreeDoc(xml);
+    if (dom)
+        virDomainFree(dom);
+
+    return ret;
+}
+
+/*
+ * "domcontrol" command
+ */
+static const vshCmdInfo info_domcontrol[] = {
+    {"help", N_("domain control interface state")},
+    {"desc", N_("Returns state of a control interface to the domain.")},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_domcontrol[] = {
+    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
+    {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdDomControl(vshControl *ctl, const vshCmd *cmd)
+{
+    virDomainPtr dom;
+    bool ret = true;
+    virDomainControlInfo info;
+
+    if (!vshConnectionUsability(ctl, ctl->conn))
+        return false;
+
+    if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+        return false;
+
+    if (virDomainGetControlInfo(dom, &info, 0) < 0) {
+        ret = false;
+        goto cleanup;
+    }
+
+    if (info.state != VIR_DOMAIN_CONTROL_OK &&
+        info.state != VIR_DOMAIN_CONTROL_ERROR) {
+        vshPrint(ctl, "%s (%0.3fs)\n",
+                 _(vshDomainControlStateToString(info.state)),
+                 info.stateTime / 1000.0);
+    } else {
+        vshPrint(ctl, "%s\n",
+                 _(vshDomainControlStateToString(info.state)));
+    }
+
+cleanup:
+    virDomainFree(dom);
+    return ret;
+}
+
+/*
+ * "domblkstat" command
+ */
+static const vshCmdInfo info_domblkstat[] = {
+    {"help", N_("get device block stats for a domain")},
+    {"desc", N_("Get device block stats for a running domain. See man page or "
+                "use --human for explanation of fields")},
+    {NULL,NULL}
+};
+
+static const vshCmdOptDef opts_domblkstat[] = {
+    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
+    {"device", VSH_OT_DATA, VSH_OFLAG_REQ, N_("block device")},
+    {"human",  VSH_OT_BOOL, 0, N_("print a more human readable output")},
+    {NULL, 0, 0, NULL}
+};
+
+struct _domblkstat_sequence {
+    const char *field;  /* field name */
+    const char *legacy; /* legacy name from previous releases */
+    const char *human;  /* human-friendly explanation */
+};
+
+/* sequence of values for output to honor legacy format from previous
+ * versions */
+static const struct _domblkstat_sequence domblkstat_output[] = {
+    { VIR_DOMAIN_BLOCK_STATS_READ_REQ,          "rd_req",
+      N_("number of read operations:") }, /* 0 */
+    { VIR_DOMAIN_BLOCK_STATS_READ_BYTES,        "rd_bytes",
+      N_("number of bytes read:") }, /* 1 */
+    { VIR_DOMAIN_BLOCK_STATS_WRITE_REQ,         "wr_req",
+      N_("number of write operations:") }, /* 2 */
+    { VIR_DOMAIN_BLOCK_STATS_WRITE_BYTES,       "wr_bytes",
+      N_("number of bytes written:") }, /* 3 */
+    { VIR_DOMAIN_BLOCK_STATS_ERRS,              "errs",
+      N_("error count:") }, /* 4 */
+    { VIR_DOMAIN_BLOCK_STATS_FLUSH_REQ,         NULL,
+      N_("number of flush operations:") }, /* 5 */
+    { VIR_DOMAIN_BLOCK_STATS_READ_TOTAL_TIMES,  NULL,
+      N_("total duration of reads (ns):") }, /* 6 */
+    { VIR_DOMAIN_BLOCK_STATS_WRITE_TOTAL_TIMES, NULL,
+      N_("total duration of writes (ns):") }, /* 7 */
+    { VIR_DOMAIN_BLOCK_STATS_FLUSH_TOTAL_TIMES, NULL,
+      N_("total duration of flushes (ns):") }, /* 8 */
+    { NULL, NULL, NULL }
+};
+
+#define DOMBLKSTAT_LEGACY_PRINT(ID, VALUE)              \
+    if (VALUE >= 0)                                     \
+        vshPrint(ctl, "%s %-*s %lld\n", device,         \
+                 human ? 31 : 0,                        \
+                 human ? _(domblkstat_output[ID].human) \
+                 : domblkstat_output[ID].legacy,        \
+                 VALUE);
+
+static bool
+cmdDomblkstat(vshControl *ctl, const vshCmd *cmd)
+{
+    virDomainPtr dom;
+    const char *name = NULL, *device = NULL;
+    struct _virDomainBlockStats stats;
+    virTypedParameterPtr params = NULL;
+    virTypedParameterPtr par = NULL;
+    char *value = NULL;
+    const char *field = NULL;
+    int rc, nparams = 0;
+    int i = 0;
+    bool ret = false;
+    bool human = vshCommandOptBool(cmd, "human"); /* human readable output */
+
+    if (!vshConnectionUsability(ctl, ctl->conn))
+        return false;
+
+    if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
+        return false;
+
+    if (vshCommandOptString(cmd, "device", &device) <= 0)
+        goto cleanup;
+
+    rc = virDomainBlockStatsFlags(dom, device, NULL, &nparams, 0);
+
+    /* It might fail when virDomainBlockStatsFlags is not
+     * supported on older libvirt, fallback to use virDomainBlockStats
+     * then.
+     */
+    if (rc < 0) {
+        /* try older API if newer is not supported */
+        if (last_error->code != VIR_ERR_NO_SUPPORT)
+            goto cleanup;
+
+        virFreeError(last_error);
+        last_error = NULL;
+
+        if (virDomainBlockStats(dom, device, &stats,
+                                sizeof(stats)) == -1) {
+            vshError(ctl, _("Failed to get block stats %s %s"),
+                     name, device);
+            goto cleanup;
+        }
+
+        /* human friendly output */
+        if (human) {
+            vshPrint(ctl, N_("Device: %s\n"), device);
+            device = "";
+        }
+
+        DOMBLKSTAT_LEGACY_PRINT(0, stats.rd_req);
+        DOMBLKSTAT_LEGACY_PRINT(1, stats.rd_bytes);
+        DOMBLKSTAT_LEGACY_PRINT(2, stats.wr_req);
+        DOMBLKSTAT_LEGACY_PRINT(3, stats.wr_bytes);
+        DOMBLKSTAT_LEGACY_PRINT(4, stats.errs);
+    } else {
+        params = vshCalloc(ctl, nparams, sizeof(*params));
+
+        if (virDomainBlockStatsFlags(dom, device, params, &nparams, 0) < 0) {
+            vshError(ctl, _("Failed to get block stats %s %s"), name, device);
+            goto cleanup;
+        }
+
+        /* set for prettier output */
+        if (human) {
+            vshPrint(ctl, N_("Device: %s\n"), device);
+            device = "";
+        }
+
+        /* at first print all known values in desired order */
+        for (i = 0; domblkstat_output[i].field != NULL; i++) {
+            if (!(par = vshFindTypedParamByName(domblkstat_output[i].field,
+                                                params,
+                                                nparams)))
+                continue;
+
+            value = vshGetTypedParamValue(ctl, par);
+
+            /* to print other not supported fields, mark the already printed */
+            par->field[0] = '\0'; /* set the name to empty string */
+
+            /* translate into human readable or legacy spelling */
+            field = NULL;
+            if (human)
+                field = _(domblkstat_output[i].human);
+            else
+                field = domblkstat_output[i].legacy;
+
+            /* use the provided spelling if no translation is available */
+            if (!field)
+                field = domblkstat_output[i].field;
+
+            vshPrint(ctl, "%s %-*s %s\n", device,
+                     human ? 31 : 0, field, value);
+
+            VIR_FREE(value);
+        }
+
+        /* go through the fields again, for remaining fields */
+        for (i = 0; i < nparams; i++) {
+            if (!*params[i].field)
+                continue;
+
+            value = vshGetTypedParamValue(ctl, params+i);
+            vshPrint(ctl, "%s %s %s\n", device, params[i].field, value);
+            VIR_FREE(value);
+        }
+    }
+
+    ret = true;
+
+cleanup:
+    VIR_FREE(params);
+    virDomainFree(dom);
+    return ret;
+}
+#undef DOMBLKSTAT_LEGACY_PRINT
+
+/*
+ * "domifstat" command
+ */
+static const vshCmdInfo info_domifstat[] = {
+    {"help", N_("get network interface stats for a domain")},
+    {"desc", N_("Get network interface stats for a running domain.")},
+    {NULL,NULL}
+};
+
+static const vshCmdOptDef opts_domifstat[] = {
+    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
+    {"interface", VSH_OT_DATA, VSH_OFLAG_REQ, N_("interface device")},
+    {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdDomIfstat(vshControl *ctl, const vshCmd *cmd)
+{
+    virDomainPtr dom;
+    const char *name = NULL, *device = NULL;
+    struct _virDomainInterfaceStats stats;
+
+    if (!vshConnectionUsability(ctl, ctl->conn))
+        return false;
+
+    if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
+        return false;
+
+    if (vshCommandOptString(cmd, "interface", &device) <= 0) {
+        virDomainFree(dom);
+        return false;
+    }
+
+    if (virDomainInterfaceStats(dom, device, &stats, sizeof(stats)) == -1) {
+        vshError(ctl, _("Failed to get interface stats %s %s"), name, device);
+        virDomainFree(dom);
+        return false;
+    }
+
+    if (stats.rx_bytes >= 0)
+        vshPrint(ctl, "%s rx_bytes %lld\n", device, stats.rx_bytes);
+
+    if (stats.rx_packets >= 0)
+        vshPrint(ctl, "%s rx_packets %lld\n", device, stats.rx_packets);
+
+    if (stats.rx_errs >= 0)
+        vshPrint(ctl, "%s rx_errs %lld\n", device, stats.rx_errs);
+
+    if (stats.rx_drop >= 0)
+        vshPrint(ctl, "%s rx_drop %lld\n", device, stats.rx_drop);
+
+    if (stats.tx_bytes >= 0)
+        vshPrint(ctl, "%s tx_bytes %lld\n", device, stats.tx_bytes);
+
+    if (stats.tx_packets >= 0)
+        vshPrint(ctl, "%s tx_packets %lld\n", device, stats.tx_packets);
+
+    if (stats.tx_errs >= 0)
+        vshPrint(ctl, "%s tx_errs %lld\n", device, stats.tx_errs);
+
+    if (stats.tx_drop >= 0)
+        vshPrint(ctl, "%s tx_drop %lld\n", device, stats.tx_drop);
+
+    virDomainFree(dom);
+    return true;
+}
+
+/*
+ * "domblkerror" command
+ */
+static const vshCmdInfo info_domblkerror[] = {
+    {"help", N_("Show errors on block devices")},
+    {"desc", N_("Show block device errors")},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_domblkerror[] = {
+    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id, or uuid")},
+    {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdDomBlkError(vshControl *ctl, const vshCmd *cmd)
+{
+    virDomainPtr dom;
+    virDomainDiskErrorPtr disks = NULL;
+    unsigned int ndisks;
+    int i;
+    int count;
+    bool ret = false;
+
+    if (!vshConnectionUsability(ctl, ctl->conn))
+        return false;
+
+    if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+        return false;
+
+    if ((count = virDomainGetDiskErrors(dom, NULL, 0, 0)) < 0)
+        goto cleanup;
+    ndisks = count;
+
+    if (ndisks) {
+        if (VIR_ALLOC_N(disks, ndisks) < 0)
+            goto cleanup;
+
+        if ((count = virDomainGetDiskErrors(dom, disks, ndisks, 0)) == -1)
+            goto cleanup;
+    }
+
+    if (count == 0) {
+        vshPrint(ctl, _("No errors found\n"));
+    } else {
+        for (i = 0; i < count; i++) {
+            vshPrint(ctl, "%s: %s\n",
+                     disks[i].disk,
+                     vshDomainIOErrorToString(disks[i].error));
+        }
+    }
+
+    ret = true;
+
+cleanup:
+    VIR_FREE(disks);
+    virDomainFree(dom);
+    return ret;
+}
+
+/*
+ * "dominfo" command
+ */
+static const vshCmdInfo info_dominfo[] = {
+    {"help", N_("domain information")},
+    {"desc", N_("Returns basic information about the domain.")},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_dominfo[] = {
+    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
+    {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdDominfo(vshControl *ctl, const vshCmd *cmd)
+{
+    virDomainInfo info;
+    virDomainPtr dom;
+    virSecurityModel secmodel;
+    virSecurityLabelPtr seclabel;
+    int persistent = 0;
+    bool ret = true;
+    int autostart;
+    unsigned int id;
+    char *str, uuid[VIR_UUID_STRING_BUFLEN];
+    int has_managed_save = 0;
+
+    if (!vshConnectionUsability(ctl, ctl->conn))
+        return false;
+
+    if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+        return false;
+
+    id = virDomainGetID(dom);
+    if (id == ((unsigned int)-1))
+        vshPrint(ctl, "%-15s %s\n", _("Id:"), "-");
+    else
+        vshPrint(ctl, "%-15s %d\n", _("Id:"), id);
+    vshPrint(ctl, "%-15s %s\n", _("Name:"), virDomainGetName(dom));
+
+    if (virDomainGetUUIDString(dom, &uuid[0])==0)
+        vshPrint(ctl, "%-15s %s\n", _("UUID:"), uuid);
+
+    if ((str = virDomainGetOSType(dom))) {
+        vshPrint(ctl, "%-15s %s\n", _("OS Type:"), str);
+        VIR_FREE(str);
+    }
+
+    if (virDomainGetInfo(dom, &info) == 0) {
+        vshPrint(ctl, "%-15s %s\n", _("State:"),
+                 _(vshDomainStateToString(info.state)));
+
+        vshPrint(ctl, "%-15s %d\n", _("CPU(s):"), info.nrVirtCpu);
+
+        if (info.cpuTime != 0) {
+            double cpuUsed = info.cpuTime;
+
+            cpuUsed /= 1000000000.0;
+
+            vshPrint(ctl, "%-15s %.1lfs\n", _("CPU time:"), cpuUsed);
+        }
+
+        if (info.maxMem != UINT_MAX)
+            vshPrint(ctl, "%-15s %lu KiB\n", _("Max memory:"),
+                 info.maxMem);
+        else
+            vshPrint(ctl, "%-15s %s\n", _("Max memory:"),
+                 _("no limit"));
+
+        vshPrint(ctl, "%-15s %lu KiB\n", _("Used memory:"),
+                 info.memory);
+
+    } else {
+        ret = false;
+    }
+
+    /* Check and display whether the domain is persistent or not */
+    persistent = virDomainIsPersistent(dom);
+    vshDebug(ctl, VSH_ERR_DEBUG, "Domain persistent flag value: %d\n",
+             persistent);
+    if (persistent < 0)
+        vshPrint(ctl, "%-15s %s\n", _("Persistent:"), _("unknown"));
+    else
+        vshPrint(ctl, "%-15s %s\n", _("Persistent:"), persistent ? _("yes") : _("no"));
+
+    /* Check and display whether the domain autostarts or not */
+    if (!virDomainGetAutostart(dom, &autostart)) {
+        vshPrint(ctl, "%-15s %s\n", _("Autostart:"),
+                 autostart ? _("enable") : _("disable") );
+    }
+
+    has_managed_save = virDomainHasManagedSaveImage(dom, 0);
+    if (has_managed_save < 0)
+        vshPrint(ctl, "%-15s %s\n", _("Managed save:"), _("unknown"));
+    else
+        vshPrint(ctl, "%-15s %s\n", _("Managed save:"),
+                 has_managed_save ? _("yes") : _("no"));
+
+    /* Security model and label information */
+    memset(&secmodel, 0, sizeof(secmodel));
+    if (virNodeGetSecurityModel(ctl->conn, &secmodel) == -1) {
+        if (last_error->code != VIR_ERR_NO_SUPPORT) {
+            virDomainFree(dom);
+            return false;
+        } else {
+            virFreeError(last_error);
+            last_error = NULL;
+        }
+    } else {
+        /* Only print something if a security model is active */
+        if (secmodel.model[0] != '\0') {
+            vshPrint(ctl, "%-15s %s\n", _("Security model:"), secmodel.model);
+            vshPrint(ctl, "%-15s %s\n", _("Security DOI:"), secmodel.doi);
+
+            /* Security labels are only valid for active domains */
+            if (VIR_ALLOC(seclabel) < 0) {
+                virDomainFree(dom);
+                return false;
+            }
+
+            if (virDomainGetSecurityLabel(dom, seclabel) == -1) {
+                virDomainFree(dom);
+                VIR_FREE(seclabel);
+                return false;
+            } else {
+                if (seclabel->label[0] != '\0')
+                    vshPrint(ctl, "%-15s %s (%s)\n", _("Security label:"),
+                             seclabel->label, seclabel->enforcing ? "enforcing" : "permissive");
+            }
+
+            VIR_FREE(seclabel);
+        }
+    }
+    virDomainFree(dom);
+    return ret;
+}
+
+/*
+ * "domstate" command
+ */
+static const vshCmdInfo info_domstate[] = {
+    {"help", N_("domain state")},
+    {"desc", N_("Returns state about a domain.")},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_domstate[] = {
+    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
+    {"reason", VSH_OT_BOOL, 0, N_("also print reason for the state")},
+    {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdDomstate(vshControl *ctl, const vshCmd *cmd)
+{
+    virDomainPtr dom;
+    bool ret = true;
+    bool showReason = vshCommandOptBool(cmd, "reason");
+    int state, reason;
+
+    if (!vshConnectionUsability(ctl, ctl->conn))
+        return false;
+
+    if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+        return false;
+
+    if ((state = vshDomainState(ctl, dom, &reason)) < 0) {
+        ret = false;
+        goto cleanup;
+    }
+
+    if (showReason) {
+        vshPrint(ctl, "%s (%s)\n",
+                 _(vshDomainStateToString(state)),
+                 vshDomainStateReasonToString(state, reason));
+    } else {
+        vshPrint(ctl, "%s\n",
+                 _(vshDomainStateToString(state)));
+    }
+
+cleanup:
+    virDomainFree(dom);
+    return ret;
+}
+
+/*
+ * "list" command
+ */
+static const vshCmdInfo info_list[] = {
+    {"help", N_("list domains")},
+    {"desc", N_("Returns list of domains.")},
+    {NULL, NULL}
+};
+
+/* compare domains, pack NULLed ones at the end*/
+static int
+vshDomainSorter(const void *a, const void *b)
+{
+    virDomainPtr *da = (virDomainPtr *) a;
+    virDomainPtr *db = (virDomainPtr *) b;
+    unsigned int ida;
+    unsigned int idb;
+    unsigned int inactive = (unsigned int) -1;
+
+    if (*da && !*db)
+        return -1;
+
+    if (!*da)
+        return *db != NULL;
+
+    ida = virDomainGetID(*da);
+    idb = virDomainGetID(*db);
+
+    if (ida == inactive && idb == inactive)
+        return strcasecmp(virDomainGetName(*da), virDomainGetName(*db));
+
+    if (ida != inactive && idb != inactive) {
+        if (ida > idb)
+            return 1;
+        else if (ida < idb)
+            return -1;
+    }
+
+    if (ida != inactive)
+        return -1;
+    else
+        return 1;
+}
+
+struct vshDomainList {
+    virDomainPtr *domains;
+    size_t ndomains;
+};
+typedef struct vshDomainList *vshDomainListPtr;
+
+static void
+vshDomainListFree(vshDomainListPtr domlist)
+{
+    int i;
+
+    if (domlist && domlist->domains) {
+        for (i = 0; i < domlist->ndomains; i++) {
+            if (domlist->domains[i])
+                virDomainFree(domlist->domains[i]);
+        }
+        VIR_FREE(domlist->domains);
+    }
+    VIR_FREE(domlist);
+}
+
+#define MATCH(FLAG) (flags & (FLAG))
+static vshDomainListPtr
+vshDomainListCollect(vshControl *ctl, unsigned int flags)
+{
+    vshDomainListPtr list = vshMalloc(ctl, sizeof(*list));
+    int i;
+    int ret;
+    int *ids = NULL;
+    int nids = 0;
+    char **names = NULL;
+    int nnames = 0;
+    virDomainPtr dom;
+    bool success = false;
+    size_t deleted = 0;
+    int persistent;
+    int autostart;
+    int state;
+    int nsnap;
+    int mansave;
+
+    /* try the list with flags support (0.9.13 and later) */
+    if ((ret = virConnectListAllDomains(ctl->conn, &list->domains,
+                                        flags)) >= 0) {
+        list->ndomains = ret;
+        goto finished;
+    }
+
+    /* check if the command is actually supported */
+    if (last_error && last_error->code == VIR_ERR_NO_SUPPORT) {
+        virFreeError(last_error);
+        last_error = NULL;
+        goto fallback;
+    }
+
+    if (last_error && last_error->code ==  VIR_ERR_INVALID_ARG) {
+        /* try the new API again but mask non-guaranteed flags */
+        unsigned int newflags = flags & (VIR_CONNECT_LIST_DOMAINS_ACTIVE |
+                                         VIR_CONNECT_LIST_DOMAINS_INACTIVE);
+
+        virFreeError(last_error);
+        last_error = NULL;
+        if ((ret = virConnectListAllDomains(ctl->conn, &list->domains,
+                                            newflags)) >= 0) {
+            list->ndomains = ret;
+            goto filter;
+        }
+    }
+
+    /* there was an error during the first or second call */
+    vshError(ctl, "%s", _("Failed to list domains"));
+    goto cleanup;
+
+
+fallback:
+    /* fall back to old method (0.9.12 and older) */
+    virResetLastError();
+
+    /* list active domains, if necessary */
+    if (!MATCH(VIR_CONNECT_LIST_FILTERS_ACTIVE) ||
+        MATCH(VIR_CONNECT_LIST_DOMAINS_ACTIVE)) {
+        if ((nids = virConnectNumOfDomains(ctl->conn)) < 0) {
+            vshError(ctl, "%s", _("Failed to list active domains"));
+            goto cleanup;
+        }
+
+        if (nids) {
+            ids = vshMalloc(ctl, sizeof(int) * nids);
+
+            if ((nids = virConnectListDomains(ctl->conn, ids, nids)) < 0) {
+                vshError(ctl, "%s", _("Failed to list active domains"));
+                goto cleanup;
+            }
+        }
+    }
+
+    if (!MATCH(VIR_CONNECT_LIST_FILTERS_ACTIVE) ||
+        MATCH(VIR_CONNECT_LIST_DOMAINS_INACTIVE)) {
+        if ((nnames = virConnectNumOfDefinedDomains(ctl->conn)) < 0) {
+            vshError(ctl, "%s", _("Failed to list inactive domains"));
+            goto cleanup;
+        }
+
+        if (nnames) {
+            names = vshMalloc(ctl, sizeof(char *) * nnames);
+
+            if ((nnames = virConnectListDefinedDomains(ctl->conn, names,
+                                                      nnames)) < 0) {
+                vshError(ctl, "%s", _("Failed to list inactive domains"));
+                goto cleanup;
+            }
+        }
+    }
+
+    list->domains = vshMalloc(ctl, sizeof(virDomainPtr) * (nids + nnames));
+    list->ndomains = 0;
+
+    /* get active domains */
+    for (i = 0; i < nids; i++) {
+        if (!(dom = virDomainLookupByID(ctl->conn, ids[i])))
+            continue;
+        list->domains[list->ndomains++] = dom;
+    }
+
+    /* get inactive domains */
+    for (i = 0; i < nnames; i++) {
+        if (!(dom = virDomainLookupByName(ctl->conn, names[i])))
+            continue;
+        list->domains[list->ndomains++] = dom;
+    }
+
+    /* truncate domains that weren't found */
+    deleted = (nids + nnames) - list->ndomains;
+
+filter:
+    /* filter list the list if the list was acquired by fallback means */
+    for (i = 0; i < list->ndomains; i++) {
+        dom = list->domains[i];
+
+        /* persistence filter */
+        if (MATCH(VIR_CONNECT_LIST_FILTERS_PERSISTENT)) {
+            if ((persistent = virDomainIsPersistent(dom)) < 0) {
+                vshError(ctl, "%s", _("Failed to get domain persistence info"));
+                goto cleanup;
+            }
+
+            if (!((MATCH(VIR_CONNECT_LIST_DOMAINS_PERSISTENT) && persistent) ||
+                  (MATCH(VIR_CONNECT_LIST_DOMAINS_TRANSIENT) && !persistent)))
+                goto remove_entry;
+        }
+
+        /* domain state filter */
+        if (MATCH(VIR_CONNECT_LIST_FILTERS_STATE)) {
+            if (virDomainGetState(dom, &state, NULL, 0) < 0) {
+                vshError(ctl, "%s", _("Failed to get domain state"));
+                goto cleanup;
+            }
+
+            if (!((MATCH(VIR_CONNECT_LIST_DOMAINS_RUNNING) &&
+                   state == VIR_DOMAIN_RUNNING) ||
+                  (MATCH(VIR_CONNECT_LIST_DOMAINS_PAUSED) &&
+                   state == VIR_DOMAIN_PAUSED) ||
+                  (MATCH(VIR_CONNECT_LIST_DOMAINS_SHUTOFF) &&
+                   state == VIR_DOMAIN_SHUTOFF) ||
+                  (MATCH(VIR_CONNECT_LIST_DOMAINS_OTHER) &&
+                   (state != VIR_DOMAIN_RUNNING &&
+                    state != VIR_DOMAIN_PAUSED &&
+                    state != VIR_DOMAIN_SHUTOFF))))
+                goto remove_entry;
+        }
+
+        /* autostart filter */
+        if (MATCH(VIR_CONNECT_LIST_FILTERS_AUTOSTART)) {
+            if (virDomainGetAutostart(dom, &autostart) < 0) {
+                vshError(ctl, "%s", _("Failed to get domain autostart state"));
+                goto cleanup;
+            }
+
+            if (!((MATCH(VIR_CONNECT_LIST_DOMAINS_AUTOSTART) && autostart) ||
+                  (MATCH(VIR_CONNECT_LIST_DOMAINS_NO_AUTOSTART) && !autostart)))
+                goto remove_entry;
+        }
+
+        /* managed save filter */
+        if (MATCH(VIR_CONNECT_LIST_FILTERS_MANAGEDSAVE)) {
+            if ((mansave = virDomainHasManagedSaveImage(dom, 0)) < 0) {
+                vshError(ctl, "%s",
+                         _("Failed to check for managed save image"));
+                goto cleanup;
+            }
+
+            if (!((MATCH(VIR_CONNECT_LIST_DOMAINS_MANAGEDSAVE) && mansave) ||
+                  (MATCH(VIR_CONNECT_LIST_DOMAINS_NO_MANAGEDSAVE) && !mansave)))
+                goto remove_entry;
+        }
+
+        /* snapshot filter */
+        if (MATCH(VIR_CONNECT_LIST_FILTERS_SNAPSHOT)) {
+            if ((nsnap = virDomainSnapshotNum(dom, 0)) < 0) {
+                vshError(ctl, "%s", _("Failed to get snapshot count"));
+                goto cleanup;
+            }
+            if (!((MATCH(VIR_CONNECT_LIST_DOMAINS_HAS_SNAPSHOT) && nsnap > 0) ||
+                  (MATCH(VIR_CONNECT_LIST_DOMAINS_NO_SNAPSHOT) && nsnap == 0)))
+                goto remove_entry;
+        }
+
+        /* the domain matched all filters, it may stay */
+        continue;
+
+remove_entry:
+        /* the domain has to be removed as it failed one of the filters */
+        virDomainFree(list->domains[i]);
+        list->domains[i] = NULL;
+        deleted++;
+    }
+
+finished:
+    /* sort the list */
+    if (list->domains && list->ndomains)
+        qsort(list->domains, list->ndomains, sizeof(*list->domains),
+              vshDomainSorter);
+
+    /* truncate the list if filter simulation deleted entries */
+    if (deleted)
+        VIR_SHRINK_N(list->domains, list->ndomains, deleted);
+
+    success = true;
+
+cleanup:
+    for (i = 0; i < nnames; i++)
+        VIR_FREE(names[i]);
+
+    if (!success) {
+        vshDomainListFree(list);
+        list = NULL;
+    }
+
+    VIR_FREE(names);
+    VIR_FREE(ids);
+    return list;
+}
+#undef MATCH
+
+static const vshCmdOptDef opts_list[] = {
+    {"inactive", VSH_OT_BOOL, 0, N_("list inactive domains")},
+    {"all", VSH_OT_BOOL, 0, N_("list inactive & active domains")},
+    {"transient", VSH_OT_BOOL, 0, N_("list transient domains")},
+    {"persistent", VSH_OT_BOOL, 0, N_("list persistent domains")},
+    {"with-snapshot", VSH_OT_BOOL, 0,
+     N_("list domains with existing snapshot")},
+    {"without-snapshot", VSH_OT_BOOL, 0,
+     N_("list domains without a snapshot")},
+    {"state-running", VSH_OT_BOOL, 0, N_("list domains in running state")},
+    {"state-paused", VSH_OT_BOOL, 0, N_("list domains in paused state")},
+    {"state-shutoff", VSH_OT_BOOL, 0, N_("list domains in shutoff state")},
+    {"state-other", VSH_OT_BOOL, 0, N_("list domains in other states")},
+    {"autostart", VSH_OT_BOOL, 0, N_("list domains with autostart enabled")},
+    {"no-autostart", VSH_OT_BOOL, 0,
+     N_("list domains with autostart disabled")},
+    {"with-managed-save", VSH_OT_BOOL, 0,
+     N_("list domains with managed save state")},
+    {"without-managed-save", VSH_OT_BOOL, 0,
+     N_("list domains without managed save")},
+    {"uuid", VSH_OT_BOOL, 0, N_("list uuid's only")},
+    {"name", VSH_OT_BOOL, 0, N_("list domain names only")},
+    {"table", VSH_OT_BOOL, 0, N_("list table (default)")},
+    {"managed-save", VSH_OT_BOOL, 0,
+     N_("mark inactive domains with managed save state")},
+    {"title", VSH_OT_BOOL, 0, N_("show short domain description")},
+    {NULL, 0, 0, NULL}
+};
+
+#define FILTER(NAME, FLAG)              \
+    if (vshCommandOptBool(cmd, NAME))   \
+        flags |= (FLAG)
+static bool
+cmdList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
+{
+    bool managed = vshCommandOptBool(cmd, "managed-save");
+    bool optTitle = vshCommandOptBool(cmd, "title");
+    bool optTable = vshCommandOptBool(cmd, "table");
+    bool optUUID = vshCommandOptBool(cmd, "uuid");
+    bool optName = vshCommandOptBool(cmd, "name");
+    int i;
+    char *title;
+    char uuid[VIR_UUID_STRING_BUFLEN];
+    int state;
+    bool ret = false;
+    vshDomainListPtr list = NULL;
+    virDomainPtr dom;
+    char id_buf[INT_BUFSIZE_BOUND(unsigned int)];
+    unsigned int id;
+    unsigned int flags = VIR_CONNECT_LIST_DOMAINS_ACTIVE;
+
+    /* construct filter flags */
+    if (vshCommandOptBool(cmd, "inactive"))
+        flags = VIR_CONNECT_LIST_DOMAINS_INACTIVE;
+
+    if (vshCommandOptBool(cmd, "all"))
+        flags = VIR_CONNECT_LIST_DOMAINS_INACTIVE |
+                VIR_CONNECT_LIST_DOMAINS_ACTIVE;
+
+    FILTER("persistent", VIR_CONNECT_LIST_DOMAINS_PERSISTENT);
+    FILTER("transient",  VIR_CONNECT_LIST_DOMAINS_TRANSIENT);
+
+    FILTER("with-managed-save",    VIR_CONNECT_LIST_DOMAINS_MANAGEDSAVE);
+    FILTER("without-managed-save", VIR_CONNECT_LIST_DOMAINS_NO_MANAGEDSAVE);
+
+    FILTER("autostart",    VIR_CONNECT_LIST_DOMAINS_AUTOSTART);
+    FILTER("no-autostart", VIR_CONNECT_LIST_DOMAINS_NO_AUTOSTART);
+
+    FILTER("with-snapshot",    VIR_CONNECT_LIST_DOMAINS_HAS_SNAPSHOT);
+    FILTER("without-snapshot", VIR_CONNECT_LIST_DOMAINS_NO_SNAPSHOT);
+
+    FILTER("state-running", VIR_CONNECT_LIST_DOMAINS_RUNNING);
+    FILTER("state-paused",  VIR_CONNECT_LIST_DOMAINS_PAUSED);
+    FILTER("state-shutoff", VIR_CONNECT_LIST_DOMAINS_SHUTOFF);
+    FILTER("state-other",   VIR_CONNECT_LIST_DOMAINS_OTHER);
+
+    if (optTable + optName + optUUID > 1) {
+        vshError(ctl, "%s",
+                 _("Only one argument from --table, --name and --uuid "
+                   "may be specified."));
+        return false;
+    }
+
+    if (!optUUID && !optName)
+        optTable = true;
+
+    if (!vshConnectionUsability(ctl, ctl->conn))
+        return false;
+
+    if (!(list = vshDomainListCollect(ctl, flags)))
+        goto cleanup;
+
+    /* print table header in legacy mode */
+    if (optTable) {
+        if (optTitle)
+            vshPrintExtra(ctl, " %-5s %-30s %-10s %-20s\n%s\n",
+                          _("Id"), _("Name"), _("State"), _("Title"),
+                          "-----------------------------------------"
+                          "-----------------------------------------");
+        else
+            vshPrintExtra(ctl, " %-5s %-30s %s\n%s\n",
+                          _("Id"), _("Name"), _("State"),
+                          "-----------------------------------------"
+                          "-----------");
+    }
+
+    for (i = 0; i < list->ndomains; i++) {
+        dom = list->domains[i];
+        id = virDomainGetID(dom);
+        if (id != (unsigned int) -1)
+            snprintf(id_buf, sizeof(id_buf), "%d", id);
+        else
+            ignore_value(virStrcpyStatic(id_buf, "-"));
+
+        state = vshDomainState(ctl, dom, NULL);
+        if (optTable && managed && state == VIR_DOMAIN_SHUTOFF &&
+            virDomainHasManagedSaveImage(dom, 0) > 0)
+            state = -2;
+
+        if (optTable) {
+            if (optTitle) {
+                if (!(title = vshGetDomainDescription(ctl, dom, true, 0)))
+                    goto cleanup;
+
+                vshPrint(ctl, " %-5s %-30s %-10s %-20s\n", id_buf,
+                         virDomainGetName(dom),
+                         state == -2 ? _("saved") : _(vshDomainStateToString(state)),
+                         title);
+
+                VIR_FREE(title);
+            } else {
+                vshPrint(ctl, " %-5s %-30s %s\n", id_buf,
+                         virDomainGetName(dom),
+                         state == -2 ? _("saved") : _(vshDomainStateToString(state)));
+            }
+        } else if (optUUID) {
+            if (virDomainGetUUIDString(dom, uuid) < 0) {
+                vshError(ctl, "%s", _("Failed to get domain's UUID"));
+                goto cleanup;
+            }
+            vshPrint(ctl, "%s\n", uuid);
+        } else if (optName) {
+            vshPrint(ctl, "%s\n", virDomainGetName(dom));
+        }
+    }
+
+    ret = true;
+cleanup:
+    vshDomainListFree(list);
+    return ret;
+}
+#undef FILTER
diff --git a/tools/virsh.c b/tools/virsh.c
index 81976a0..85c171b 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -976,450 +976,6 @@ cleanup:
 
 #endif /* WIN32 */
 
-
-/*
- * "list" command
- */
-static const vshCmdInfo info_list[] = {
-    {"help", N_("list domains")},
-    {"desc", N_("Returns list of domains.")},
-    {NULL, NULL}
-};
-
-/* compare domains, pack NULLed ones at the end*/
-static int
-vshDomainSorter(const void *a, const void *b)
-{
-    virDomainPtr *da = (virDomainPtr *) a;
-    virDomainPtr *db = (virDomainPtr *) b;
-    unsigned int ida;
-    unsigned int idb;
-    unsigned int inactive = (unsigned int) -1;
-
-    if (*da && !*db)
-        return -1;
-
-    if (!*da)
-        return *db != NULL;
-
-    ida = virDomainGetID(*da);
-    idb = virDomainGetID(*db);
-
-    if (ida == inactive && idb == inactive)
-        return strcasecmp(virDomainGetName(*da), virDomainGetName(*db));
-
-    if (ida != inactive && idb != inactive) {
-        if (ida > idb)
-            return 1;
-        else if (ida < idb)
-            return -1;
-    }
-
-    if (ida != inactive)
-        return -1;
-    else
-        return 1;
-}
-
-struct vshDomainList {
-    virDomainPtr *domains;
-    size_t ndomains;
-};
-typedef struct vshDomainList *vshDomainListPtr;
-
-static void
-vshDomainListFree(vshDomainListPtr domlist)
-{
-    int i;
-
-    if (domlist && domlist->domains) {
-        for (i = 0; i < domlist->ndomains; i++) {
-            if (domlist->domains[i])
-                virDomainFree(domlist->domains[i]);
-        }
-        VIR_FREE(domlist->domains);
-    }
-    VIR_FREE(domlist);
-}
-
-#define MATCH(FLAG) (flags & (FLAG))
-static vshDomainListPtr
-vshDomainListCollect(vshControl *ctl, unsigned int flags)
-{
-    vshDomainListPtr list = vshMalloc(ctl, sizeof(*list));
-    int i;
-    int ret;
-    int *ids = NULL;
-    int nids = 0;
-    char **names = NULL;
-    int nnames = 0;
-    virDomainPtr dom;
-    bool success = false;
-    size_t deleted = 0;
-    int persistent;
-    int autostart;
-    int state;
-    int nsnap;
-    int mansave;
-
-    /* try the list with flags support (0.9.13 and later) */
-    if ((ret = virConnectListAllDomains(ctl->conn, &list->domains,
-                                        flags)) >= 0) {
-        list->ndomains = ret;
-        goto finished;
-    }
-
-    /* check if the command is actually supported */
-    if (last_error && last_error->code == VIR_ERR_NO_SUPPORT) {
-        virFreeError(last_error);
-        last_error = NULL;
-        goto fallback;
-    }
-
-    if (last_error && last_error->code ==  VIR_ERR_INVALID_ARG) {
-        /* try the new API again but mask non-guaranteed flags */
-        unsigned int newflags = flags & (VIR_CONNECT_LIST_DOMAINS_ACTIVE |
-                                         VIR_CONNECT_LIST_DOMAINS_INACTIVE);
-
-        virFreeError(last_error);
-        last_error = NULL;
-        if ((ret = virConnectListAllDomains(ctl->conn, &list->domains,
-                                            newflags)) >= 0) {
-            list->ndomains = ret;
-            goto filter;
-        }
-    }
-
-    /* there was an error during the first or second call */
-    vshError(ctl, "%s", _("Failed to list domains"));
-    goto cleanup;
-
-
-fallback:
-    /* fall back to old method (0.9.12 and older) */
-    virResetLastError();
-
-    /* list active domains, if necessary */
-    if (!MATCH(VIR_CONNECT_LIST_FILTERS_ACTIVE) ||
-        MATCH(VIR_CONNECT_LIST_DOMAINS_ACTIVE)) {
-        if ((nids = virConnectNumOfDomains(ctl->conn)) < 0) {
-            vshError(ctl, "%s", _("Failed to list active domains"));
-            goto cleanup;
-        }
-
-        if (nids) {
-            ids = vshMalloc(ctl, sizeof(int) * nids);
-
-            if ((nids = virConnectListDomains(ctl->conn, ids, nids)) < 0) {
-                vshError(ctl, "%s", _("Failed to list active domains"));
-                goto cleanup;
-            }
-        }
-    }
-
-    if (!MATCH(VIR_CONNECT_LIST_FILTERS_ACTIVE) ||
-        MATCH(VIR_CONNECT_LIST_DOMAINS_INACTIVE)) {
-        if ((nnames = virConnectNumOfDefinedDomains(ctl->conn)) < 0) {
-            vshError(ctl, "%s", _("Failed to list inactive domains"));
-            goto cleanup;
-        }
-
-        if (nnames) {
-            names = vshMalloc(ctl, sizeof(char *) * nnames);
-
-            if ((nnames = virConnectListDefinedDomains(ctl->conn, names,
-                                                      nnames)) < 0) {
-                vshError(ctl, "%s", _("Failed to list inactive domains"));
-                goto cleanup;
-            }
-        }
-    }
-
-    list->domains = vshMalloc(ctl, sizeof(virDomainPtr) * (nids + nnames));
-    list->ndomains = 0;
-
-    /* get active domains */
-    for (i = 0; i < nids; i++) {
-        if (!(dom = virDomainLookupByID(ctl->conn, ids[i])))
-            continue;
-        list->domains[list->ndomains++] = dom;
-    }
-
-    /* get inactive domains */
-    for (i = 0; i < nnames; i++) {
-        if (!(dom = virDomainLookupByName(ctl->conn, names[i])))
-            continue;
-        list->domains[list->ndomains++] = dom;
-    }
-
-    /* truncate domains that weren't found */
-    deleted = (nids + nnames) - list->ndomains;
-
-filter:
-    /* filter list the list if the list was acquired by fallback means */
-    for (i = 0; i < list->ndomains; i++) {
-        dom = list->domains[i];
-
-        /* persistence filter */
-        if (MATCH(VIR_CONNECT_LIST_FILTERS_PERSISTENT)) {
-            if ((persistent = virDomainIsPersistent(dom)) < 0) {
-                vshError(ctl, "%s", _("Failed to get domain persistence info"));
-                goto cleanup;
-            }
-
-            if (!((MATCH(VIR_CONNECT_LIST_DOMAINS_PERSISTENT) && persistent) ||
-                  (MATCH(VIR_CONNECT_LIST_DOMAINS_TRANSIENT) && !persistent)))
-                goto remove_entry;
-        }
-
-        /* domain state filter */
-        if (MATCH(VIR_CONNECT_LIST_FILTERS_STATE)) {
-            if (virDomainGetState(dom, &state, NULL, 0) < 0) {
-                vshError(ctl, "%s", _("Failed to get domain state"));
-                goto cleanup;
-            }
-
-            if (!((MATCH(VIR_CONNECT_LIST_DOMAINS_RUNNING) &&
-                   state == VIR_DOMAIN_RUNNING) ||
-                  (MATCH(VIR_CONNECT_LIST_DOMAINS_PAUSED) &&
-                   state == VIR_DOMAIN_PAUSED) ||
-                  (MATCH(VIR_CONNECT_LIST_DOMAINS_SHUTOFF) &&
-                   state == VIR_DOMAIN_SHUTOFF) ||
-                  (MATCH(VIR_CONNECT_LIST_DOMAINS_OTHER) &&
-                   (state != VIR_DOMAIN_RUNNING &&
-                    state != VIR_DOMAIN_PAUSED &&
-                    state != VIR_DOMAIN_SHUTOFF))))
-                goto remove_entry;
-        }
-
-        /* autostart filter */
-        if (MATCH(VIR_CONNECT_LIST_FILTERS_AUTOSTART)) {
-            if (virDomainGetAutostart(dom, &autostart) < 0) {
-                vshError(ctl, "%s", _("Failed to get domain autostart state"));
-                goto cleanup;
-            }
-
-            if (!((MATCH(VIR_CONNECT_LIST_DOMAINS_AUTOSTART) && autostart) ||
-                  (MATCH(VIR_CONNECT_LIST_DOMAINS_NO_AUTOSTART) && !autostart)))
-                goto remove_entry;
-        }
-
-        /* managed save filter */
-        if (MATCH(VIR_CONNECT_LIST_FILTERS_MANAGEDSAVE)) {
-            if ((mansave = virDomainHasManagedSaveImage(dom, 0)) < 0) {
-                vshError(ctl, "%s",
-                         _("Failed to check for managed save image"));
-                goto cleanup;
-            }
-
-            if (!((MATCH(VIR_CONNECT_LIST_DOMAINS_MANAGEDSAVE) && mansave) ||
-                  (MATCH(VIR_CONNECT_LIST_DOMAINS_NO_MANAGEDSAVE) && !mansave)))
-                goto remove_entry;
-        }
-
-        /* snapshot filter */
-        if (MATCH(VIR_CONNECT_LIST_FILTERS_SNAPSHOT)) {
-            if ((nsnap = virDomainSnapshotNum(dom, 0)) < 0) {
-                vshError(ctl, "%s", _("Failed to get snapshot count"));
-                goto cleanup;
-            }
-            if (!((MATCH(VIR_CONNECT_LIST_DOMAINS_HAS_SNAPSHOT) && nsnap > 0) ||
-                  (MATCH(VIR_CONNECT_LIST_DOMAINS_NO_SNAPSHOT) && nsnap == 0)))
-                goto remove_entry;
-        }
-
-        /* the domain matched all filters, it may stay */
-        continue;
-
-remove_entry:
-        /* the domain has to be removed as it failed one of the filters */
-        virDomainFree(list->domains[i]);
-        list->domains[i] = NULL;
-        deleted++;
-    }
-
-finished:
-    /* sort the list */
-    if (list->domains && list->ndomains)
-        qsort(list->domains, list->ndomains, sizeof(*list->domains),
-              vshDomainSorter);
-
-    /* truncate the list if filter simulation deleted entries */
-    if (deleted)
-        VIR_SHRINK_N(list->domains, list->ndomains, deleted);
-
-    success = true;
-
-cleanup:
-    for (i = 0; i < nnames; i++)
-        VIR_FREE(names[i]);
-
-    if (!success) {
-        vshDomainListFree(list);
-        list = NULL;
-    }
-
-    VIR_FREE(names);
-    VIR_FREE(ids);
-    return list;
-}
-#undef MATCH
-
-
-static const vshCmdOptDef opts_list[] = {
-    {"inactive", VSH_OT_BOOL, 0, N_("list inactive domains")},
-    {"all", VSH_OT_BOOL, 0, N_("list inactive & active domains")},
-    {"transient", VSH_OT_BOOL, 0, N_("list transient domains")},
-    {"persistent", VSH_OT_BOOL, 0, N_("list persistent domains")},
-    {"with-snapshot", VSH_OT_BOOL, 0,
-     N_("list domains with existing snapshot")},
-    {"without-snapshot", VSH_OT_BOOL, 0,
-     N_("list domains without a snapshot")},
-    {"state-running", VSH_OT_BOOL, 0, N_("list domains in running state")},
-    {"state-paused", VSH_OT_BOOL, 0, N_("list domains in paused state")},
-    {"state-shutoff", VSH_OT_BOOL, 0, N_("list domains in shutoff state")},
-    {"state-other", VSH_OT_BOOL, 0, N_("list domains in other states")},
-    {"autostart", VSH_OT_BOOL, 0, N_("list domains with autostart enabled")},
-    {"no-autostart", VSH_OT_BOOL, 0,
-     N_("list domains with autostart disabled")},
-    {"with-managed-save", VSH_OT_BOOL, 0,
-     N_("list domains with managed save state")},
-    {"without-managed-save", VSH_OT_BOOL, 0,
-     N_("list domains without managed save")},
-    {"uuid", VSH_OT_BOOL, 0, N_("list uuid's only")},
-    {"name", VSH_OT_BOOL, 0, N_("list domain names only")},
-    {"table", VSH_OT_BOOL, 0, N_("list table (default)")},
-    {"managed-save", VSH_OT_BOOL, 0,
-     N_("mark inactive domains with managed save state")},
-    {"title", VSH_OT_BOOL, 0, N_("show short domain description")},
-    {NULL, 0, 0, NULL}
-};
-
-
-#define FILTER(NAME, FLAG)              \
-    if (vshCommandOptBool(cmd, NAME))   \
-        flags |= (FLAG)
-static bool
-cmdList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
-{
-    bool managed = vshCommandOptBool(cmd, "managed-save");
-    bool optTitle = vshCommandOptBool(cmd, "title");
-    bool optTable = vshCommandOptBool(cmd, "table");
-    bool optUUID = vshCommandOptBool(cmd, "uuid");
-    bool optName = vshCommandOptBool(cmd, "name");
-    int i;
-    char *title;
-    char uuid[VIR_UUID_STRING_BUFLEN];
-    int state;
-    bool ret = false;
-    vshDomainListPtr list = NULL;
-    virDomainPtr dom;
-    char id_buf[INT_BUFSIZE_BOUND(unsigned int)];
-    unsigned int id;
-    unsigned int flags = VIR_CONNECT_LIST_DOMAINS_ACTIVE;
-
-    /* construct filter flags */
-    if (vshCommandOptBool(cmd, "inactive"))
-        flags = VIR_CONNECT_LIST_DOMAINS_INACTIVE;
-
-    if (vshCommandOptBool(cmd, "all"))
-        flags = VIR_CONNECT_LIST_DOMAINS_INACTIVE |
-                VIR_CONNECT_LIST_DOMAINS_ACTIVE;
-
-    FILTER("persistent", VIR_CONNECT_LIST_DOMAINS_PERSISTENT);
-    FILTER("transient",  VIR_CONNECT_LIST_DOMAINS_TRANSIENT);
-
-    FILTER("with-managed-save",    VIR_CONNECT_LIST_DOMAINS_MANAGEDSAVE);
-    FILTER("without-managed-save", VIR_CONNECT_LIST_DOMAINS_NO_MANAGEDSAVE);
-
-    FILTER("autostart",    VIR_CONNECT_LIST_DOMAINS_AUTOSTART);
-    FILTER("no-autostart", VIR_CONNECT_LIST_DOMAINS_NO_AUTOSTART);
-
-    FILTER("with-snapshot",    VIR_CONNECT_LIST_DOMAINS_HAS_SNAPSHOT);
-    FILTER("without-snapshot", VIR_CONNECT_LIST_DOMAINS_NO_SNAPSHOT);
-
-    FILTER("state-running", VIR_CONNECT_LIST_DOMAINS_RUNNING);
-    FILTER("state-paused",  VIR_CONNECT_LIST_DOMAINS_PAUSED);
-    FILTER("state-shutoff", VIR_CONNECT_LIST_DOMAINS_SHUTOFF);
-    FILTER("state-other",   VIR_CONNECT_LIST_DOMAINS_OTHER);
-
-    if (optTable + optName + optUUID > 1) {
-        vshError(ctl, "%s",
-                 _("Only one argument from --table, --name and --uuid "
-                   "may be specified."));
-        return false;
-    }
-
-    if (!optUUID && !optName)
-        optTable = true;
-
-    if (!vshConnectionUsability(ctl, ctl->conn))
-        return false;
-
-    if (!(list = vshDomainListCollect(ctl, flags)))
-        goto cleanup;
-
-    /* print table header in legacy mode */
-    if (optTable) {
-        if (optTitle)
-            vshPrintExtra(ctl, " %-5s %-30s %-10s %-20s\n%s\n",
-                          _("Id"), _("Name"), _("State"), _("Title"),
-                          "-----------------------------------------"
-                          "-----------------------------------------");
-        else
-            vshPrintExtra(ctl, " %-5s %-30s %s\n%s\n",
-                          _("Id"), _("Name"), _("State"),
-                          "-----------------------------------------"
-                          "-----------");
-    }
-
-    for (i = 0; i < list->ndomains; i++) {
-        dom = list->domains[i];
-        id = virDomainGetID(dom);
-        if (id != (unsigned int) -1)
-            snprintf(id_buf, sizeof(id_buf), "%d", id);
-        else
-            ignore_value(virStrcpyStatic(id_buf, "-"));
-
-        state = vshDomainState(ctl, dom, NULL);
-        if (optTable && managed && state == VIR_DOMAIN_SHUTOFF &&
-            virDomainHasManagedSaveImage(dom, 0) > 0)
-            state = -2;
-
-        if (optTable) {
-            if (optTitle) {
-                if (!(title = vshGetDomainDescription(ctl, dom, true, 0)))
-                    goto cleanup;
-
-                vshPrint(ctl, " %-5s %-30s %-10s %-20s\n", id_buf,
-                         virDomainGetName(dom),
-                         state == -2 ? _("saved") : _(vshDomainStateToString(state)),
-                         title);
-
-                VIR_FREE(title);
-            } else {
-                vshPrint(ctl, " %-5s %-30s %s\n", id_buf,
-                         virDomainGetName(dom),
-                         state == -2 ? _("saved") : _(vshDomainStateToString(state)));
-            }
-        } else if (optUUID) {
-            if (virDomainGetUUIDString(dom, uuid) < 0) {
-                vshError(ctl, "%s", _("Failed to get domain's UUID"));
-                goto cleanup;
-            }
-            vshPrint(ctl, "%s\n", uuid);
-        } else if (optName) {
-            vshPrint(ctl, "%s\n", virDomainGetName(dom));
-        }
-    }
-
-    ret = true;
-cleanup:
-    vshDomainListFree(list);
-    return ret;
-}
-#undef FILTER
-
 /*
  * "desc" command for managing domain description and title
  */
@@ -1576,28 +1132,43 @@ cleanup:
     return ret;
 }
 
-/*
- * "domstate" command
+/* "domif-setlink" command
  */
-static const vshCmdInfo info_domstate[] = {
-    {"help", N_("domain state")},
-    {"desc", N_("Returns state about a domain.")},
-    {NULL, NULL}
+static const vshCmdInfo info_domif_setlink[] = {
+    {"help", N_("set link state of a virtual interface")},
+    {"desc", N_("Set link state of a domain's virtual interface. This command wraps usage of update-device command.")},
+    {NULL,NULL}
 };
 
-static const vshCmdOptDef opts_domstate[] = {
+static const vshCmdOptDef opts_domif_setlink[] = {
     {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
-    {"reason", VSH_OT_BOOL, 0, N_("also print reason for the state")},
+    {"interface", VSH_OT_DATA, VSH_OFLAG_REQ, N_("interface device (MAC Address)")},
+    {"state", VSH_OT_DATA, VSH_OFLAG_REQ, N_("new state of the device")},
+    {"persistent", VSH_OT_ALIAS, 0, "config"},
+    {"config", VSH_OT_BOOL, 0, N_("affect next boot")},
     {NULL, 0, 0, NULL}
 };
 
 static bool
-cmdDomstate(vshControl *ctl, const vshCmd *cmd)
+cmdDomIfSetLink(vshControl *ctl, const vshCmd *cmd)
 {
     virDomainPtr dom;
-    bool ret = true;
-    bool showReason = vshCommandOptBool(cmd, "reason");
-    int state, reason;
+    const char *iface;
+    const char *state;
+    const char *value;
+    const char *desc;
+    virMacAddr macaddr;
+    const char *element;
+    const char *attr;
+    bool config;
+    bool ret = false;
+    unsigned int flags = 0;
+    int i;
+    xmlDocPtr xml = NULL;
+    xmlXPathContextPtr ctxt = NULL;
+    xmlXPathObjectPtr obj = NULL;
+    xmlNodePtr cur = NULL;
+    xmlBufferPtr xml_buf = NULL;
 
     if (!vshConnectionUsability(ctl, ctl->conn))
         return false;
@@ -1605,382 +1176,33 @@ cmdDomstate(vshControl *ctl, const vshCmd *cmd)
     if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
         return false;
 
-    if ((state = vshDomainState(ctl, dom, &reason)) < 0) {
-        ret = false;
+    if (vshCommandOptString(cmd, "interface", &iface) <= 0)
         goto cleanup;
-    }
-
-    if (showReason) {
-        vshPrint(ctl, "%s (%s)\n",
-                 _(vshDomainStateToString(state)),
-                 vshDomainStateReasonToString(state, reason));
-    } else {
-        vshPrint(ctl, "%s\n",
-                 _(vshDomainStateToString(state)));
-    }
-
-cleanup:
-    virDomainFree(dom);
-    return ret;
-}
-
-/*
- * "domcontrol" command
- */
-static const vshCmdInfo info_domcontrol[] = {
-    {"help", N_("domain control interface state")},
-    {"desc", N_("Returns state of a control interface to the domain.")},
-    {NULL, NULL}
-};
-
-static const vshCmdOptDef opts_domcontrol[] = {
-    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
-    {NULL, 0, 0, NULL}
-};
-
-static bool
-cmdDomControl(vshControl *ctl, const vshCmd *cmd)
-{
-    virDomainPtr dom;
-    bool ret = true;
-    virDomainControlInfo info;
 
-    if (!vshConnectionUsability(ctl, ctl->conn))
-        return false;
+    if (vshCommandOptString(cmd, "state", &state) <= 0)
+        goto cleanup;
 
-    if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
-        return false;
+    config = vshCommandOptBool(cmd, "config");
 
-    if (virDomainGetControlInfo(dom, &info, 0) < 0) {
-        ret = false;
+    if (STRNEQ(state, "up") && STRNEQ(state, "down")) {
+        vshError(ctl, _("invalid link state '%s'"), state);
         goto cleanup;
     }
 
-    if (info.state != VIR_DOMAIN_CONTROL_OK &&
-        info.state != VIR_DOMAIN_CONTROL_ERROR) {
-        vshPrint(ctl, "%s (%0.3fs)\n",
-                 _(vshDomainControlStateToString(info.state)),
-                 info.stateTime / 1000.0);
-    } else {
-        vshPrint(ctl, "%s\n",
-                 _(vshDomainControlStateToString(info.state)));
+    /* get persistent or live description of network device */
+    desc = virDomainGetXMLDesc(dom, config ? VIR_DOMAIN_XML_INACTIVE : 0);
+    if (desc == NULL) {
+        vshError(ctl, _("Failed to get domain description xml"));
+        goto cleanup;
     }
 
-cleanup:
-    virDomainFree(dom);
-    return ret;
-}
+    if (config)
+        flags = VIR_DOMAIN_AFFECT_CONFIG;
+    else
+        flags = VIR_DOMAIN_AFFECT_LIVE;
 
-/* "domblkstat" command
- */
-static const vshCmdInfo info_domblkstat[] = {
-    {"help", N_("get device block stats for a domain")},
-    {"desc", N_("Get device block stats for a running domain. See man page or "
-                "use --human for explanation of fields")},
-    {NULL,NULL}
-};
-
-static const vshCmdOptDef opts_domblkstat[] = {
-    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
-    {"device", VSH_OT_DATA, VSH_OFLAG_REQ, N_("block device")},
-    {"human",  VSH_OT_BOOL, 0, N_("print a more human readable output")},
-    {NULL, 0, 0, NULL}
-};
-
-struct _domblkstat_sequence {
-    const char *field;  /* field name */
-    const char *legacy; /* legacy name from previous releases */
-    const char *human;  /* human-friendly explanation */
-};
-
-/* sequence of values for output to honor legacy format from previous
- * versions */
-static const struct _domblkstat_sequence domblkstat_output[] = {
-    { VIR_DOMAIN_BLOCK_STATS_READ_REQ,          "rd_req",
-      N_("number of read operations:") }, /* 0 */
-    { VIR_DOMAIN_BLOCK_STATS_READ_BYTES,        "rd_bytes",
-      N_("number of bytes read:") }, /* 1 */
-    { VIR_DOMAIN_BLOCK_STATS_WRITE_REQ,         "wr_req",
-      N_("number of write operations:") }, /* 2 */
-    { VIR_DOMAIN_BLOCK_STATS_WRITE_BYTES,       "wr_bytes",
-      N_("number of bytes written:") }, /* 3 */
-    { VIR_DOMAIN_BLOCK_STATS_ERRS,              "errs",
-      N_("error count:") }, /* 4 */
-    { VIR_DOMAIN_BLOCK_STATS_FLUSH_REQ,         NULL,
-      N_("number of flush operations:") }, /* 5 */
-    { VIR_DOMAIN_BLOCK_STATS_READ_TOTAL_TIMES,  NULL,
-      N_("total duration of reads (ns):") }, /* 6 */
-    { VIR_DOMAIN_BLOCK_STATS_WRITE_TOTAL_TIMES, NULL,
-      N_("total duration of writes (ns):") }, /* 7 */
-    { VIR_DOMAIN_BLOCK_STATS_FLUSH_TOTAL_TIMES, NULL,
-      N_("total duration of flushes (ns):") }, /* 8 */
-    { NULL, NULL, NULL }
-};
-
-#define DOMBLKSTAT_LEGACY_PRINT(ID, VALUE)              \
-    if (VALUE >= 0)                                     \
-        vshPrint(ctl, "%s %-*s %lld\n", device,         \
-                 human ? 31 : 0,                        \
-                 human ? _(domblkstat_output[ID].human) \
-                 : domblkstat_output[ID].legacy,        \
-                 VALUE);
-
-static bool
-cmdDomblkstat(vshControl *ctl, const vshCmd *cmd)
-{
-    virDomainPtr dom;
-    const char *name = NULL, *device = NULL;
-    struct _virDomainBlockStats stats;
-    virTypedParameterPtr params = NULL;
-    virTypedParameterPtr par = NULL;
-    char *value = NULL;
-    const char *field = NULL;
-    int rc, nparams = 0;
-    int i = 0;
-    bool ret = false;
-    bool human = vshCommandOptBool(cmd, "human"); /* human readable output */
-
-    if (!vshConnectionUsability(ctl, ctl->conn))
-        return false;
-
-    if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
-        return false;
-
-    if (vshCommandOptString(cmd, "device", &device) <= 0)
-        goto cleanup;
-
-    rc = virDomainBlockStatsFlags(dom, device, NULL, &nparams, 0);
-
-    /* It might fail when virDomainBlockStatsFlags is not
-     * supported on older libvirt, fallback to use virDomainBlockStats
-     * then.
-     */
-    if (rc < 0) {
-        /* try older API if newer is not supported */
-        if (last_error->code != VIR_ERR_NO_SUPPORT)
-            goto cleanup;
-
-        virFreeError(last_error);
-        last_error = NULL;
-
-        if (virDomainBlockStats(dom, device, &stats,
-                                sizeof(stats)) == -1) {
-            vshError(ctl, _("Failed to get block stats %s %s"),
-                     name, device);
-            goto cleanup;
-        }
-
-        /* human friendly output */
-        if (human) {
-            vshPrint(ctl, N_("Device: %s\n"), device);
-            device = "";
-        }
-
-        DOMBLKSTAT_LEGACY_PRINT(0, stats.rd_req);
-        DOMBLKSTAT_LEGACY_PRINT(1, stats.rd_bytes);
-        DOMBLKSTAT_LEGACY_PRINT(2, stats.wr_req);
-        DOMBLKSTAT_LEGACY_PRINT(3, stats.wr_bytes);
-        DOMBLKSTAT_LEGACY_PRINT(4, stats.errs);
-    } else {
-        params = vshCalloc(ctl, nparams, sizeof(*params));
-
-        if (virDomainBlockStatsFlags(dom, device, params, &nparams, 0) < 0) {
-            vshError(ctl, _("Failed to get block stats %s %s"), name, device);
-            goto cleanup;
-        }
-
-        /* set for prettier output */
-        if (human) {
-            vshPrint(ctl, N_("Device: %s\n"), device);
-            device = "";
-        }
-
-        /* at first print all known values in desired order */
-        for (i = 0; domblkstat_output[i].field != NULL; i++) {
-            if (!(par = vshFindTypedParamByName(domblkstat_output[i].field,
-                                                params,
-                                                nparams)))
-                continue;
-
-            value = vshGetTypedParamValue(ctl, par);
-
-            /* to print other not supported fields, mark the already printed */
-            par->field[0] = '\0'; /* set the name to empty string */
-
-            /* translate into human readable or legacy spelling */
-            field = NULL;
-            if (human)
-                field = _(domblkstat_output[i].human);
-            else
-                field = domblkstat_output[i].legacy;
-
-            /* use the provided spelling if no translation is available */
-            if (!field)
-                field = domblkstat_output[i].field;
-
-            vshPrint(ctl, "%s %-*s %s\n", device,
-                     human ? 31 : 0, field, value);
-
-            VIR_FREE(value);
-        }
-
-        /* go through the fields again, for remaining fields */
-        for (i = 0; i < nparams; i++) {
-            if (!*params[i].field)
-                continue;
-
-            value = vshGetTypedParamValue(ctl, params+i);
-            vshPrint(ctl, "%s %s %s\n", device, params[i].field, value);
-            VIR_FREE(value);
-        }
-    }
-
-    ret = true;
-
-cleanup:
-    VIR_FREE(params);
-    virDomainFree(dom);
-    return ret;
-}
-#undef DOMBLKSTAT_LEGACY_PRINT
-
-/* "domifstat" command
- */
-static const vshCmdInfo info_domifstat[] = {
-    {"help", N_("get network interface stats for a domain")},
-    {"desc", N_("Get network interface stats for a running domain.")},
-    {NULL,NULL}
-};
-
-static const vshCmdOptDef opts_domifstat[] = {
-    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
-    {"interface", VSH_OT_DATA, VSH_OFLAG_REQ, N_("interface device")},
-    {NULL, 0, 0, NULL}
-};
-
-static bool
-cmdDomIfstat(vshControl *ctl, const vshCmd *cmd)
-{
-    virDomainPtr dom;
-    const char *name = NULL, *device = NULL;
-    struct _virDomainInterfaceStats stats;
-
-    if (!vshConnectionUsability(ctl, ctl->conn))
-        return false;
-
-    if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
-        return false;
-
-    if (vshCommandOptString(cmd, "interface", &device) <= 0) {
-        virDomainFree(dom);
-        return false;
-    }
-
-    if (virDomainInterfaceStats(dom, device, &stats, sizeof(stats)) == -1) {
-        vshError(ctl, _("Failed to get interface stats %s %s"), name, device);
-        virDomainFree(dom);
-        return false;
-    }
-
-    if (stats.rx_bytes >= 0)
-        vshPrint(ctl, "%s rx_bytes %lld\n", device, stats.rx_bytes);
-
-    if (stats.rx_packets >= 0)
-        vshPrint(ctl, "%s rx_packets %lld\n", device, stats.rx_packets);
-
-    if (stats.rx_errs >= 0)
-        vshPrint(ctl, "%s rx_errs %lld\n", device, stats.rx_errs);
-
-    if (stats.rx_drop >= 0)
-        vshPrint(ctl, "%s rx_drop %lld\n", device, stats.rx_drop);
-
-    if (stats.tx_bytes >= 0)
-        vshPrint(ctl, "%s tx_bytes %lld\n", device, stats.tx_bytes);
-
-    if (stats.tx_packets >= 0)
-        vshPrint(ctl, "%s tx_packets %lld\n", device, stats.tx_packets);
-
-    if (stats.tx_errs >= 0)
-        vshPrint(ctl, "%s tx_errs %lld\n", device, stats.tx_errs);
-
-    if (stats.tx_drop >= 0)
-        vshPrint(ctl, "%s tx_drop %lld\n", device, stats.tx_drop);
-
-    virDomainFree(dom);
-    return true;
-}
-
-/* "domif-setlink" command
- */
-static const vshCmdInfo info_domif_setlink[] = {
-    {"help", N_("set link state of a virtual interface")},
-    {"desc", N_("Set link state of a domain's virtual interface. This command wraps usage of update-device command.")},
-    {NULL,NULL}
-};
-
-static const vshCmdOptDef opts_domif_setlink[] = {
-    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
-    {"interface", VSH_OT_DATA, VSH_OFLAG_REQ, N_("interface device (MAC Address)")},
-    {"state", VSH_OT_DATA, VSH_OFLAG_REQ, N_("new state of the device")},
-    {"persistent", VSH_OT_ALIAS, 0, "config"},
-    {"config", VSH_OT_BOOL, 0, N_("affect next boot")},
-    {NULL, 0, 0, NULL}
-};
-
-static bool
-cmdDomIfSetLink(vshControl *ctl, const vshCmd *cmd)
-{
-    virDomainPtr dom;
-    const char *iface;
-    const char *state;
-    const char *value;
-    const char *desc;
-    virMacAddr macaddr;
-    const char *element;
-    const char *attr;
-    bool config;
-    bool ret = false;
-    unsigned int flags = 0;
-    int i;
-    xmlDocPtr xml = NULL;
-    xmlXPathContextPtr ctxt = NULL;
-    xmlXPathObjectPtr obj = NULL;
-    xmlNodePtr cur = NULL;
-    xmlBufferPtr xml_buf = NULL;
-
-    if (!vshConnectionUsability(ctl, ctl->conn))
-        return false;
-
-    if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
-        return false;
-
-    if (vshCommandOptString(cmd, "interface", &iface) <= 0)
-        goto cleanup;
-
-    if (vshCommandOptString(cmd, "state", &state) <= 0)
-        goto cleanup;
-
-    config = vshCommandOptBool(cmd, "config");
-
-    if (STRNEQ(state, "up") && STRNEQ(state, "down")) {
-        vshError(ctl, _("invalid link state '%s'"), state);
-        goto cleanup;
-    }
-
-    /* get persistent or live description of network device */
-    desc = virDomainGetXMLDesc(dom, config ? VIR_DOMAIN_XML_INACTIVE : 0);
-    if (desc == NULL) {
-        vshError(ctl, _("Failed to get domain description xml"));
-        goto cleanup;
-    }
-
-    if (config)
-        flags = VIR_DOMAIN_AFFECT_CONFIG;
-    else
-        flags = VIR_DOMAIN_AFFECT_LIVE;
-
-    if (virDomainIsActive(dom) == 0)
-        flags = VIR_DOMAIN_AFFECT_CONFIG;
+    if (virDomainIsActive(dom) == 0)
+        flags = VIR_DOMAIN_AFFECT_CONFIG;
 
     /* extract current network device description */
     xml = virXMLParseStringCtxt(desc, _("(domain_definition)"), &ctxt);
@@ -2050,166 +1272,37 @@ hit:
                           BAD_CAST "link",
                           NULL);
         if (!cur)
-            goto cleanup;
-
-        if (xmlNewProp(cur, BAD_CAST "state", BAD_CAST state) == NULL)
-            goto cleanup;
-    }
-
-    xml_buf = xmlBufferCreate();
-    if (!xml_buf) {
-        vshError(ctl, _("Failed to allocate memory"));
-        goto cleanup;
-    }
-
-    if (xmlNodeDump(xml_buf, xml, obj->nodesetval->nodeTab[i], 0, 0) < 0 ) {
-        vshError(ctl, _("Failed to create XML"));
-        goto cleanup;
-    }
-
-    if (virDomainUpdateDeviceFlags(dom, (char *)xmlBufferContent(xml_buf), flags) < 0) {
-        vshError(ctl, _("Failed to update interface link state"));
-        goto cleanup;
-    } else {
-        vshPrint(ctl, "%s", _("Device updated successfully\n"));
-        ret = true;
-    }
-
-cleanup:
-    xmlXPathFreeObject(obj);
-    xmlXPathFreeContext(ctxt);
-    xmlFreeDoc(xml);
-    xmlBufferFree(xml_buf);
-
-    if (dom)
-        virDomainFree(dom);
-
-    return ret;
-}
-
-/* "domif-getlink" command
- */
-static const vshCmdInfo info_domif_getlink[] = {
-    {"help", N_("get link state of a virtual interface")},
-    {"desc", N_("Get link state of a domain's virtual interface.")},
-    {NULL,NULL}
-};
-
-static const vshCmdOptDef opts_domif_getlink[] = {
-    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
-    {"interface", VSH_OT_DATA, VSH_OFLAG_REQ, N_("interface device (MAC Address)")},
-    {"persistent", VSH_OT_ALIAS, 0, "config"},
-    {"config", VSH_OT_BOOL, 0, N_("Get persistent interface state")},
-    {NULL, 0, 0, NULL}
-};
-
-static bool
-cmdDomIfGetLink(vshControl *ctl, const vshCmd *cmd)
-{
-    virDomainPtr dom;
-    const char *iface = NULL;
-    int flags = 0;
-    char *state = NULL;
-    char *value = NULL;
-    virMacAddr macaddr;
-    const char *element;
-    const char *attr;
-    bool ret = false;
-    int i;
-    char *desc;
-    xmlDocPtr xml = NULL;
-    xmlXPathContextPtr ctxt = NULL;
-    xmlNodePtr cur = NULL;
-    xmlXPathObjectPtr obj = NULL;
-
-    if (!vshConnectionUsability(ctl, ctl->conn))
-        return false;
-
-    if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
-        return false;
-
-    if (vshCommandOptString(cmd, "interface", &iface) <= 0) {
-        virDomainFree(dom);
-        return false;
-    }
-
-    if (vshCommandOptBool(cmd, "config"))
-        flags = VIR_DOMAIN_XML_INACTIVE;
-
-    desc = virDomainGetXMLDesc(dom, flags);
-    if (desc == NULL) {
-        vshError(ctl, _("Failed to get domain description xml"));
-        goto cleanup;
-    }
-
-    xml = virXMLParseStringCtxt(desc, _("(domain_definition)"), &ctxt);
-    VIR_FREE(desc);
-    if (!xml) {
-        vshError(ctl, _("Failed to parse domain description xml"));
-        goto cleanup;
-    }
-
-    obj = xmlXPathEval(BAD_CAST "/domain/devices/interface", ctxt);
-    if (obj == NULL || obj->type != XPATH_NODESET ||
-        obj->nodesetval == NULL || obj->nodesetval->nodeNr == 0) {
-        vshError(ctl, _("Failed to extract interface information or no interfaces found"));
-        goto cleanup;
-    }
-
-    if (virMacAddrParse(iface, &macaddr) == 0) {
-        element = "mac";
-        attr = "address";
-    } else {
-        element = "target";
-        attr = "dev";
-    }
-
-    /* find interface with matching mac addr */
-    for (i = 0; i < obj->nodesetval->nodeNr; i++) {
-        cur = obj->nodesetval->nodeTab[i]->children;
-
-        while (cur) {
-            if (cur->type == XML_ELEMENT_NODE &&
-                xmlStrEqual(cur->name, BAD_CAST element)) {
-
-                value = virXMLPropString(cur, attr);
-
-                if (STRCASEEQ(value, iface)) {
-                    VIR_FREE(value);
-                    goto hit;
-                }
-                VIR_FREE(value);
-            }
-            cur = cur->next;
-        }
-    }
-
-    vshError(ctl, _("Interface (%s: %s) not found."), element, iface);
-    goto cleanup;
-
-hit:
-    cur = obj->nodesetval->nodeTab[i]->children;
-    while (cur) {
-        if (cur->type == XML_ELEMENT_NODE &&
-            xmlStrEqual(cur->name, BAD_CAST "link")) {
-
-            state = virXMLPropString(cur, "state");
-            vshPrint(ctl, "%s %s", iface, state);
-            VIR_FREE(state);
+            goto cleanup;
 
+        if (xmlNewProp(cur, BAD_CAST "state", BAD_CAST state) == NULL)
             goto cleanup;
-        }
-        cur = cur->next;
     }
 
-    /* attribute not found */
-    vshPrint(ctl, "%s default", iface);
+    xml_buf = xmlBufferCreate();
+    if (!xml_buf) {
+        vshError(ctl, _("Failed to allocate memory"));
+        goto cleanup;
+    }
+
+    if (xmlNodeDump(xml_buf, xml, obj->nodesetval->nodeTab[i], 0, 0) < 0 ) {
+        vshError(ctl, _("Failed to create XML"));
+        goto cleanup;
+    }
+
+    if (virDomainUpdateDeviceFlags(dom, (char *)xmlBufferContent(xml_buf), flags) < 0) {
+        vshError(ctl, _("Failed to update interface link state"));
+        goto cleanup;
+    } else {
+        vshPrint(ctl, "%s", _("Device updated successfully\n"));
+        ret = true;
+    }
 
-    ret = true;
 cleanup:
     xmlXPathFreeObject(obj);
     xmlXPathFreeContext(ctxt);
     xmlFreeDoc(xml);
+    xmlBufferFree(xml_buf);
+
     if (dom)
         virDomainFree(dom);
 
@@ -2345,381 +1438,69 @@ cmdDomIftune(vshControl *ctl, const vshCmd *cmd)
         /* set the interface parameters */
         params = vshCalloc(ctl, nparams, sizeof(*params));
         if (!params) {
-            virReportOOMError();
-            goto cleanup;
-        }
-
-        for (i = 0; i < nparams; i++)
-            params[i].type = VIR_TYPED_PARAM_UINT;
-
-        i = 0;
-        if (inbound.average && i < nparams) {
-            if (!virStrcpy(params[i].field, VIR_DOMAIN_BANDWIDTH_IN_AVERAGE,
-                           sizeof(params[i].field)))
-                goto cleanup;
-            params[i].value.ui = inbound.average;
-            i++;
-        }
-        if (inbound.peak && i < nparams) {
-            if (!virStrcpy(params[i].field, VIR_DOMAIN_BANDWIDTH_IN_PEAK,
-                           sizeof(params[i].field)))
-                goto cleanup;
-            params[i].value.ui = inbound.peak;
-            i++;
-        }
-        if (inbound.burst && i < nparams) {
-            if (!virStrcpy(params[i].field, VIR_DOMAIN_BANDWIDTH_IN_BURST,
-                           sizeof(params[i].field)))
-                goto cleanup;
-            params[i].value.ui = inbound.burst;
-            i++;
-        }
-        if (outbound.average && i < nparams) {
-            if (!virStrcpy(params[i].field, VIR_DOMAIN_BANDWIDTH_OUT_AVERAGE,
-                           sizeof(params[i].field)))
-                goto cleanup;
-            params[i].value.ui = outbound.average;
-            i++;
-        }
-        if (outbound.peak && i < nparams) {
-            if (!virStrcpy(params[i].field, VIR_DOMAIN_BANDWIDTH_OUT_PEAK,
-                           sizeof(params[i].field)))
-                goto cleanup;
-            params[i].value.ui = outbound.peak;
-            i++;
-        }
-        if (outbound.burst && i < nparams) {
-            if (!virStrcpy(params[i].field, VIR_DOMAIN_BANDWIDTH_OUT_BURST,
-                           sizeof(params[i].field)))
-                goto cleanup;
-            params[i].value.ui = outbound.burst;
-            i++;
-        }
-
-        if (virDomainSetInterfaceParameters(dom, device, params, nparams, flags) != 0) {
-            vshError(ctl, "%s", _("Unable to set interface parameters"));
-            goto cleanup;
-        }
-    }
-
-    ret = true;
-
-cleanup:
-    virTypedParameterArrayClear(params, nparams);
-    VIR_FREE(params);
-    virDomainFree(dom);
-    return ret;
-}
-
-/*
- * "dommemstats" command
- */
-static const vshCmdInfo info_dommemstat[] = {
-    {"help", N_("get memory statistics for a domain")},
-    {"desc", N_("Get memory statistics for a running domain.")},
-    {NULL,NULL}
-};
-
-static const vshCmdOptDef opts_dommemstat[] = {
-    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
-    {NULL, 0, 0, NULL}
-};
-
-static bool
-cmdDomMemStat(vshControl *ctl, const vshCmd *cmd)
-{
-    virDomainPtr dom;
-    const char *name;
-    struct _virDomainMemoryStat stats[VIR_DOMAIN_MEMORY_STAT_NR];
-    unsigned int nr_stats, i;
-
-    if (!vshConnectionUsability(ctl, ctl->conn))
-        return false;
-
-    if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
-        return false;
-
-    nr_stats = virDomainMemoryStats(dom, stats, VIR_DOMAIN_MEMORY_STAT_NR, 0);
-    if (nr_stats == -1) {
-        vshError(ctl, _("Failed to get memory statistics for domain %s"), name);
-        virDomainFree(dom);
-        return false;
-    }
-
-    for (i = 0; i < nr_stats; i++) {
-        if (stats[i].tag == VIR_DOMAIN_MEMORY_STAT_SWAP_IN)
-            vshPrint(ctl, "swap_in %llu\n", stats[i].val);
-        if (stats[i].tag == VIR_DOMAIN_MEMORY_STAT_SWAP_OUT)
-            vshPrint(ctl, "swap_out %llu\n", stats[i].val);
-        if (stats[i].tag == VIR_DOMAIN_MEMORY_STAT_MAJOR_FAULT)
-            vshPrint(ctl, "major_fault %llu\n", stats[i].val);
-        if (stats[i].tag == VIR_DOMAIN_MEMORY_STAT_MINOR_FAULT)
-            vshPrint(ctl, "minor_fault %llu\n", stats[i].val);
-        if (stats[i].tag == VIR_DOMAIN_MEMORY_STAT_UNUSED)
-            vshPrint(ctl, "unused %llu\n", stats[i].val);
-        if (stats[i].tag == VIR_DOMAIN_MEMORY_STAT_AVAILABLE)
-            vshPrint(ctl, "available %llu\n", stats[i].val);
-        if (stats[i].tag == VIR_DOMAIN_MEMORY_STAT_ACTUAL_BALLOON)
-            vshPrint(ctl, "actual %llu\n", stats[i].val);
-        if (stats[i].tag == VIR_DOMAIN_MEMORY_STAT_RSS)
-            vshPrint(ctl, "rss %llu\n", stats[i].val);
-    }
-
-    virDomainFree(dom);
-    return true;
-}
-
-/*
- * "domblkinfo" command
- */
-static const vshCmdInfo info_domblkinfo[] = {
-    {"help", N_("domain block device size information")},
-    {"desc", N_("Get block device size info for a domain.")},
-    {NULL, NULL}
-};
-
-static const vshCmdOptDef opts_domblkinfo[] = {
-    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
-    {"device", VSH_OT_DATA, VSH_OFLAG_REQ, N_("block device")},
-    {NULL, 0, 0, NULL}
-};
-
-static bool
-cmdDomblkinfo(vshControl *ctl, const vshCmd *cmd)
-{
-    virDomainBlockInfo info;
-    virDomainPtr dom;
-    bool ret = true;
-    const char *device = NULL;
-
-    if (!vshConnectionUsability(ctl, ctl->conn))
-        return false;
-
-    if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
-        return false;
-
-    if (vshCommandOptString(cmd, "device", &device) <= 0) {
-        virDomainFree(dom);
-        return false;
-    }
-
-    if (virDomainGetBlockInfo(dom, device, &info, 0) < 0) {
-        virDomainFree(dom);
-        return false;
-    }
-
-    vshPrint(ctl, "%-15s %llu\n", _("Capacity:"), info.capacity);
-    vshPrint(ctl, "%-15s %llu\n", _("Allocation:"), info.allocation);
-    vshPrint(ctl, "%-15s %llu\n", _("Physical:"), info.physical);
-
-    virDomainFree(dom);
-    return ret;
-}
-
-/*
- * "domblklist" command
- */
-static const vshCmdInfo info_domblklist[] = {
-    {"help", N_("list all domain blocks")},
-    {"desc", N_("Get the summary of block devices for a domain.")},
-    {NULL, NULL}
-};
-
-static const vshCmdOptDef opts_domblklist[] = {
-    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
-    {"inactive", VSH_OT_BOOL, 0,
-     N_("get inactive rather than running configuration")},
-    {"details", VSH_OT_BOOL, 0,
-     N_("additionally display the type and device value")},
-    {NULL, 0, 0, NULL}
-};
-
-static bool
-cmdDomblklist(vshControl *ctl, const vshCmd *cmd)
-{
-    virDomainPtr dom;
-    bool ret = false;
-    unsigned int flags = 0;
-    char *xml = NULL;
-    xmlDocPtr xmldoc = NULL;
-    xmlXPathContextPtr ctxt = NULL;
-    int ndisks;
-    xmlNodePtr *disks = NULL;
-    int i;
-    bool details = false;
-
-    if (vshCommandOptBool(cmd, "inactive"))
-        flags |= VIR_DOMAIN_XML_INACTIVE;
-
-    details = vshCommandOptBool(cmd, "details");
-
-    if (!vshConnectionUsability(ctl, ctl->conn))
-        return false;
-
-    if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
-        return false;
-
-    xml = virDomainGetXMLDesc(dom, flags);
-    if (!xml)
-        goto cleanup;
-
-    xmldoc = virXMLParseStringCtxt(xml, _("(domain_definition)"), &ctxt);
-    if (!xmldoc)
-        goto cleanup;
-
-    ndisks = virXPathNodeSet("./devices/disk", ctxt, &disks);
-    if (ndisks < 0)
-        goto cleanup;
-
-    if (details)
-        vshPrint(ctl, "%-10s %-10s %-10s %s\n", _("Type"),
-                 _("Device"), _("Target"), _("Source"));
-    else
-        vshPrint(ctl, "%-10s %s\n", _("Target"), _("Source"));
-
-    vshPrint(ctl, "------------------------------------------------\n");
-
-    for (i = 0; i < ndisks; i++) {
-        char *type;
-        char *device;
-        char *target;
-        char *source;
-
-        ctxt->node = disks[i];
-
-        if (details) {
-            type = virXPathString("string(./@type)", ctxt);
-            device = virXPathString("string(./@device)", ctxt);
-        }
-
-        target = virXPathString("string(./target/@dev)", ctxt);
-        if (!target) {
-            vshError(ctl, "unable to query block list");
-            goto cleanup;
-        }
-        source = virXPathString("string(./source/@file"
-                                "|./source/@dev"
-                                "|./source/@dir"
-                                "|./source/@name)", ctxt);
-        if (details) {
-            vshPrint(ctl, "%-10s %-10s %-10s %s\n", type, device,
-                     target, source ? source : "-");
-            VIR_FREE(type);
-            VIR_FREE(device);
-        } else {
-            vshPrint(ctl, "%-10s %s\n", target, source ? source : "-");
-        }
-
-        VIR_FREE(target);
-        VIR_FREE(source);
-    }
-
-    ret = true;
-
-cleanup:
-    VIR_FREE(disks);
-    virDomainFree(dom);
-    VIR_FREE(xml);
-    xmlFreeDoc(xmldoc);
-    xmlXPathFreeContext(ctxt);
-    return ret;
-}
-
-/*
- * "domiflist" command
- */
-static const vshCmdInfo info_domiflist[] = {
-    {"help", N_("list all domain virtual interfaces")},
-    {"desc", N_("Get the summary of virtual interfaces for a domain.")},
-    {NULL, NULL}
-};
-
-static const vshCmdOptDef opts_domiflist[] = {
-    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
-    {"inactive", VSH_OT_BOOL, 0,
-     N_("get inactive rather than running configuration")},
-    {NULL, 0, 0, NULL}
-};
-
-static bool
-cmdDomiflist(vshControl *ctl, const vshCmd *cmd)
-{
-    virDomainPtr dom;
-    bool ret = false;
-    unsigned int flags = 0;
-    char *xml = NULL;
-    xmlDocPtr xmldoc = NULL;
-    xmlXPathContextPtr ctxt = NULL;
-    int ninterfaces;
-    xmlNodePtr *interfaces = NULL;
-    int i;
-
-    if (vshCommandOptBool(cmd, "inactive"))
-        flags |= VIR_DOMAIN_XML_INACTIVE;
-
-    if (!vshConnectionUsability(ctl, ctl->conn))
-        return false;
-
-    if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
-        return false;
-
-    xml = virDomainGetXMLDesc(dom, flags);
-    if (!xml)
-        goto cleanup;
-
-    xmldoc = virXMLParseStringCtxt(xml, _("(domain_definition)"), &ctxt);
-    if (!xmldoc)
-        goto cleanup;
-
-    ninterfaces = virXPathNodeSet("./devices/interface", ctxt, &interfaces);
-    if (ninterfaces < 0)
-        goto cleanup;
-
-    vshPrint(ctl, "%-10s %-10s %-10s %-11s %s\n", _("Interface"), _("Type"),
-             _("Source"), _("Model"), _("MAC"));
-    vshPrint(ctl, "-------------------------------------------------------\n");
-
-    for (i = 0; i < ninterfaces; i++) {
-        char *type = NULL;
-        char *source = NULL;
-        char *target = NULL;
-        char *model = NULL;
-        char *mac = NULL;
-
-        ctxt->node = interfaces[i];
-        type = virXPathString("string(./@type)", ctxt);
-
-        source = virXPathString("string(./source/@bridge"
-                                "|./source/@dev"
-                                "|./source/@network"
-                                "|./source/@name)", ctxt);
+            virReportOOMError();
+            goto cleanup;
+        }
 
-        target = virXPathString("string(./target/@dev)", ctxt);
-        model = virXPathString("string(./model/@type)", ctxt);
-        mac = virXPathString("string(./mac/@address)", ctxt);
+        for (i = 0; i < nparams; i++)
+            params[i].type = VIR_TYPED_PARAM_UINT;
 
-        vshPrint(ctl, "%-10s %-10s %-10s %-11s %-10s\n",
-                 target ? target : "-",
-                 type,
-                 source ? source : "-",
-                 model ? model : "-",
-                 mac ? mac : "-");
+        i = 0;
+        if (inbound.average && i < nparams) {
+            if (!virStrcpy(params[i].field, VIR_DOMAIN_BANDWIDTH_IN_AVERAGE,
+                           sizeof(params[i].field)))
+                goto cleanup;
+            params[i].value.ui = inbound.average;
+            i++;
+        }
+        if (inbound.peak && i < nparams) {
+            if (!virStrcpy(params[i].field, VIR_DOMAIN_BANDWIDTH_IN_PEAK,
+                           sizeof(params[i].field)))
+                goto cleanup;
+            params[i].value.ui = inbound.peak;
+            i++;
+        }
+        if (inbound.burst && i < nparams) {
+            if (!virStrcpy(params[i].field, VIR_DOMAIN_BANDWIDTH_IN_BURST,
+                           sizeof(params[i].field)))
+                goto cleanup;
+            params[i].value.ui = inbound.burst;
+            i++;
+        }
+        if (outbound.average && i < nparams) {
+            if (!virStrcpy(params[i].field, VIR_DOMAIN_BANDWIDTH_OUT_AVERAGE,
+                           sizeof(params[i].field)))
+                goto cleanup;
+            params[i].value.ui = outbound.average;
+            i++;
+        }
+        if (outbound.peak && i < nparams) {
+            if (!virStrcpy(params[i].field, VIR_DOMAIN_BANDWIDTH_OUT_PEAK,
+                           sizeof(params[i].field)))
+                goto cleanup;
+            params[i].value.ui = outbound.peak;
+            i++;
+        }
+        if (outbound.burst && i < nparams) {
+            if (!virStrcpy(params[i].field, VIR_DOMAIN_BANDWIDTH_OUT_BURST,
+                           sizeof(params[i].field)))
+                goto cleanup;
+            params[i].value.ui = outbound.burst;
+            i++;
+        }
 
-        VIR_FREE(type);
-        VIR_FREE(source);
-        VIR_FREE(target);
-        VIR_FREE(model);
-        VIR_FREE(mac);
+        if (virDomainSetInterfaceParameters(dom, device, params, nparams, flags) != 0) {
+            vshError(ctl, "%s", _("Unable to set interface parameters"));
+            goto cleanup;
+        }
     }
 
     ret = true;
 
 cleanup:
-    VIR_FREE(interfaces);
+    virTypedParameterArrayClear(params, nparams);
+    VIR_FREE(params);
     virDomainFree(dom);
-    VIR_FREE(xml);
-    xmlFreeDoc(xmldoc);
-    xmlXPathFreeContext(ctxt);
     return ret;
 }
 
@@ -4731,144 +3512,6 @@ cmdDestroy(vshControl *ctl, const vshCmd *cmd)
 }
 
 /*
- * "dominfo" command
- */
-static const vshCmdInfo info_dominfo[] = {
-    {"help", N_("domain information")},
-    {"desc", N_("Returns basic information about the domain.")},
-    {NULL, NULL}
-};
-
-static const vshCmdOptDef opts_dominfo[] = {
-    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
-    {NULL, 0, 0, NULL}
-};
-
-static bool
-cmdDominfo(vshControl *ctl, const vshCmd *cmd)
-{
-    virDomainInfo info;
-    virDomainPtr dom;
-    virSecurityModel secmodel;
-    virSecurityLabelPtr seclabel;
-    int persistent = 0;
-    bool ret = true;
-    int autostart;
-    unsigned int id;
-    char *str, uuid[VIR_UUID_STRING_BUFLEN];
-    int has_managed_save = 0;
-
-    if (!vshConnectionUsability(ctl, ctl->conn))
-        return false;
-
-    if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
-        return false;
-
-    id = virDomainGetID(dom);
-    if (id == ((unsigned int)-1))
-        vshPrint(ctl, "%-15s %s\n", _("Id:"), "-");
-    else
-        vshPrint(ctl, "%-15s %d\n", _("Id:"), id);
-    vshPrint(ctl, "%-15s %s\n", _("Name:"), virDomainGetName(dom));
-
-    if (virDomainGetUUIDString(dom, &uuid[0])==0)
-        vshPrint(ctl, "%-15s %s\n", _("UUID:"), uuid);
-
-    if ((str = virDomainGetOSType(dom))) {
-        vshPrint(ctl, "%-15s %s\n", _("OS Type:"), str);
-        VIR_FREE(str);
-    }
-
-    if (virDomainGetInfo(dom, &info) == 0) {
-        vshPrint(ctl, "%-15s %s\n", _("State:"),
-                 _(vshDomainStateToString(info.state)));
-
-        vshPrint(ctl, "%-15s %d\n", _("CPU(s):"), info.nrVirtCpu);
-
-        if (info.cpuTime != 0) {
-            double cpuUsed = info.cpuTime;
-
-            cpuUsed /= 1000000000.0;
-
-            vshPrint(ctl, "%-15s %.1lfs\n", _("CPU time:"), cpuUsed);
-        }
-
-        if (info.maxMem != UINT_MAX)
-            vshPrint(ctl, "%-15s %lu KiB\n", _("Max memory:"),
-                 info.maxMem);
-        else
-            vshPrint(ctl, "%-15s %s\n", _("Max memory:"),
-                 _("no limit"));
-
-        vshPrint(ctl, "%-15s %lu KiB\n", _("Used memory:"),
-                 info.memory);
-
-    } else {
-        ret = false;
-    }
-
-    /* Check and display whether the domain is persistent or not */
-    persistent = virDomainIsPersistent(dom);
-    vshDebug(ctl, VSH_ERR_DEBUG, "Domain persistent flag value: %d\n",
-             persistent);
-    if (persistent < 0)
-        vshPrint(ctl, "%-15s %s\n", _("Persistent:"), _("unknown"));
-    else
-        vshPrint(ctl, "%-15s %s\n", _("Persistent:"), persistent ? _("yes") : _("no"));
-
-    /* Check and display whether the domain autostarts or not */
-    if (!virDomainGetAutostart(dom, &autostart)) {
-        vshPrint(ctl, "%-15s %s\n", _("Autostart:"),
-                 autostart ? _("enable") : _("disable") );
-    }
-
-    has_managed_save = virDomainHasManagedSaveImage(dom, 0);
-    if (has_managed_save < 0)
-        vshPrint(ctl, "%-15s %s\n", _("Managed save:"), _("unknown"));
-    else
-        vshPrint(ctl, "%-15s %s\n", _("Managed save:"),
-                 has_managed_save ? _("yes") : _("no"));
-
-    /* Security model and label information */
-    memset(&secmodel, 0, sizeof(secmodel));
-    if (virNodeGetSecurityModel(ctl->conn, &secmodel) == -1) {
-        if (last_error->code != VIR_ERR_NO_SUPPORT) {
-            virDomainFree(dom);
-            return false;
-        } else {
-            virFreeError(last_error);
-            last_error = NULL;
-        }
-    } else {
-        /* Only print something if a security model is active */
-        if (secmodel.model[0] != '\0') {
-            vshPrint(ctl, "%-15s %s\n", _("Security model:"), secmodel.model);
-            vshPrint(ctl, "%-15s %s\n", _("Security DOI:"), secmodel.doi);
-
-            /* Security labels are only valid for active domains */
-            if (VIR_ALLOC(seclabel) < 0) {
-                virDomainFree(dom);
-                return false;
-            }
-
-            if (virDomainGetSecurityLabel(dom, seclabel) == -1) {
-                virDomainFree(dom);
-                VIR_FREE(seclabel);
-                return false;
-            } else {
-                if (seclabel->label[0] != '\0')
-                    vshPrint(ctl, "%-15s %s (%s)\n", _("Security label:"),
-                             seclabel->label, seclabel->enforcing ? "enforcing" : "permissive");
-            }
-
-            VIR_FREE(seclabel);
-        }
-    }
-    virDomainFree(dom);
-    return ret;
-}
-
-/*
  * "domjobinfo" command
  */
 static const vshCmdInfo info_domjobinfo[] = {
@@ -17995,83 +16638,6 @@ cleanup:
 }
 
 /*
- * "domblkerror" command
- */
-static const char *
-vshDomainIOErrorToString(int error)
-{
-    switch ((virDomainDiskErrorCode) error) {
-    case VIR_DOMAIN_DISK_ERROR_NONE:
-        return _("no error");
-    case VIR_DOMAIN_DISK_ERROR_UNSPEC:
-        return _("unspecified error");
-    case VIR_DOMAIN_DISK_ERROR_NO_SPACE:
-        return _("no space");
-    case VIR_DOMAIN_DISK_ERROR_LAST:
-        ;
-    }
-
-    return _("unknown error");
-}
-
-static const vshCmdInfo info_domblkerror[] = {
-    {"help", N_("Show errors on block devices")},
-    {"desc", N_("Show block device errors")},
-    {NULL, NULL}
-};
-
-static const vshCmdOptDef opts_domblkerror[] = {
-    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id, or uuid")},
-    {NULL, 0, 0, NULL}
-};
-
-static bool
-cmdDomBlkError(vshControl *ctl, const vshCmd *cmd)
-{
-    virDomainPtr dom;
-    virDomainDiskErrorPtr disks = NULL;
-    unsigned int ndisks;
-    int i;
-    int count;
-    bool ret = false;
-
-    if (!vshConnectionUsability(ctl, ctl->conn))
-        return false;
-
-    if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
-        return false;
-
-    if ((count = virDomainGetDiskErrors(dom, NULL, 0, 0)) < 0)
-        goto cleanup;
-    ndisks = count;
-
-    if (ndisks) {
-        if (VIR_ALLOC_N(disks, ndisks) < 0)
-            goto cleanup;
-
-        if ((count = virDomainGetDiskErrors(dom, disks, ndisks, 0)) == -1)
-            goto cleanup;
-    }
-
-    if (count == 0) {
-        vshPrint(ctl, _("No errors found\n"));
-    } else {
-        for (i = 0; i < count; i++) {
-            vshPrint(ctl, "%s: %s\n",
-                     disks[i].disk,
-                     vshDomainIOErrorToString(disks[i].error));
-        }
-    }
-
-    ret = true;
-
-cleanup:
-    VIR_FREE(disks);
-    virDomainFree(dom);
-    return ret;
-}
-
-/*
  * "qemu-monitor-command" command
  */
 static const vshCmdInfo info_qemu_monitor_command[] = {
@@ -19536,215 +18102,6 @@ vshDomainState(vshControl *ctl, virDomainPtr dom, int *reason)
         return info.state;
 }
 
-static const char *
-vshDomainStateToString(int state)
-{
-    /* Can't use virDomainStateTypeToString, because we want to mark
-     * strings for translation.  */
-    switch ((virDomainState) state) {
-    case VIR_DOMAIN_RUNNING:
-        return N_("running");
-    case VIR_DOMAIN_BLOCKED:
-        return N_("idle");
-    case VIR_DOMAIN_PAUSED:
-        return N_("paused");
-    case VIR_DOMAIN_SHUTDOWN:
-        return N_("in shutdown");
-    case VIR_DOMAIN_SHUTOFF:
-        return N_("shut off");
-    case VIR_DOMAIN_CRASHED:
-        return N_("crashed");
-    case VIR_DOMAIN_PMSUSPENDED:
-        return N_("pmsuspended");
-    case VIR_DOMAIN_NOSTATE:
-    default:
-        ;/*FALLTHROUGH*/
-    }
-    return N_("no state");  /* = dom0 state */
-}
-
-static const char *
-vshDomainStateReasonToString(int state, int reason)
-{
-    switch ((virDomainState) state) {
-    case VIR_DOMAIN_NOSTATE:
-        switch ((virDomainNostateReason) reason) {
-        case VIR_DOMAIN_NOSTATE_UNKNOWN:
-        case VIR_DOMAIN_NOSTATE_LAST:
-            ;
-        }
-        break;
-
-    case VIR_DOMAIN_RUNNING:
-        switch ((virDomainRunningReason) reason) {
-        case VIR_DOMAIN_RUNNING_BOOTED:
-            return N_("booted");
-        case VIR_DOMAIN_RUNNING_MIGRATED:
-            return N_("migrated");
-        case VIR_DOMAIN_RUNNING_RESTORED:
-            return N_("restored");
-        case VIR_DOMAIN_RUNNING_FROM_SNAPSHOT:
-            return N_("from snapshot");
-        case VIR_DOMAIN_RUNNING_UNPAUSED:
-            return N_("unpaused");
-        case VIR_DOMAIN_RUNNING_MIGRATION_CANCELED:
-            return N_("migration canceled");
-        case VIR_DOMAIN_RUNNING_SAVE_CANCELED:
-            return N_("save canceled");
-        case VIR_DOMAIN_RUNNING_WAKEUP:
-            return N_("event wakeup");
-        case VIR_DOMAIN_RUNNING_UNKNOWN:
-        case VIR_DOMAIN_RUNNING_LAST:
-            ;
-        }
-        break;
-
-    case VIR_DOMAIN_BLOCKED:
-        switch ((virDomainBlockedReason) reason) {
-        case VIR_DOMAIN_BLOCKED_UNKNOWN:
-        case VIR_DOMAIN_BLOCKED_LAST:
-            ;
-        }
-        break;
-
-    case VIR_DOMAIN_PAUSED:
-        switch ((virDomainPausedReason) reason) {
-        case VIR_DOMAIN_PAUSED_USER:
-            return N_("user");
-        case VIR_DOMAIN_PAUSED_MIGRATION:
-            return N_("migrating");
-        case VIR_DOMAIN_PAUSED_SAVE:
-            return N_("saving");
-        case VIR_DOMAIN_PAUSED_DUMP:
-            return N_("dumping");
-        case VIR_DOMAIN_PAUSED_IOERROR:
-            return N_("I/O error");
-        case VIR_DOMAIN_PAUSED_WATCHDOG:
-            return N_("watchdog");
-        case VIR_DOMAIN_PAUSED_FROM_SNAPSHOT:
-            return N_("from snapshot");
-        case VIR_DOMAIN_PAUSED_SHUTTING_DOWN:
-            return N_("shutting down");
-        case VIR_DOMAIN_PAUSED_UNKNOWN:
-        case VIR_DOMAIN_PAUSED_LAST:
-            ;
-        }
-        break;
-
-    case VIR_DOMAIN_SHUTDOWN:
-        switch ((virDomainShutdownReason) reason) {
-        case VIR_DOMAIN_SHUTDOWN_USER:
-            return N_("user");
-        case VIR_DOMAIN_SHUTDOWN_UNKNOWN:
-        case VIR_DOMAIN_SHUTDOWN_LAST:
-            ;
-        }
-        break;
-
-    case VIR_DOMAIN_SHUTOFF:
-        switch ((virDomainShutoffReason) reason) {
-        case VIR_DOMAIN_SHUTOFF_SHUTDOWN:
-            return N_("shutdown");
-        case VIR_DOMAIN_SHUTOFF_DESTROYED:
-            return N_("destroyed");
-        case VIR_DOMAIN_SHUTOFF_CRASHED:
-            return N_("crashed");
-        case VIR_DOMAIN_SHUTOFF_MIGRATED:
-            return N_("migrated");
-        case VIR_DOMAIN_SHUTOFF_SAVED:
-            return N_("saved");
-        case VIR_DOMAIN_SHUTOFF_FAILED:
-            return N_("failed");
-        case VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT:
-            return N_("from snapshot");
-        case VIR_DOMAIN_SHUTOFF_UNKNOWN:
-        case VIR_DOMAIN_SHUTOFF_LAST:
-            ;
-        }
-        break;
-
-    case VIR_DOMAIN_CRASHED:
-        switch ((virDomainCrashedReason) reason) {
-        case VIR_DOMAIN_CRASHED_UNKNOWN:
-        case VIR_DOMAIN_CRASHED_LAST:
-            ;
-        }
-        break;
-
-    case VIR_DOMAIN_PMSUSPENDED:
-        switch ((virDomainPMSuspendedReason) reason) {
-        case VIR_DOMAIN_PMSUSPENDED_UNKNOWN:
-        case VIR_DOMAIN_PMSUSPENDED_LAST:
-            ;
-        }
-        break;
-
-    case VIR_DOMAIN_LAST:
-        ;
-    }
-
-    return N_("unknown");
-}
-
-/* extract description or title from domain xml */
-static char *
-vshGetDomainDescription(vshControl *ctl, virDomainPtr dom, bool title,
-                        unsigned int flags)
-{
-    char *desc = NULL;
-    char *domxml = NULL;
-    virErrorPtr err = NULL;
-    xmlDocPtr doc = NULL;
-    xmlXPathContextPtr ctxt = NULL;
-    int type;
-
-    if (title)
-        type = VIR_DOMAIN_METADATA_TITLE;
-    else
-        type = VIR_DOMAIN_METADATA_DESCRIPTION;
-
-    if ((desc = virDomainGetMetadata(dom, type, NULL, flags))) {
-        return desc;
-    } else {
-        err = virGetLastError();
-
-        if (err && err->code == VIR_ERR_NO_DOMAIN_METADATA) {
-            desc = vshStrdup(ctl, "");
-            virResetLastError();
-            return desc;
-        }
-
-        if (err && err->code != VIR_ERR_NO_SUPPORT)
-            return desc;
-    }
-
-    /* fall back to xml */
-    /* get domain's xml description and extract the title/description */
-    if (!(domxml = virDomainGetXMLDesc(dom, flags))) {
-        vshError(ctl, "%s", _("Failed to retrieve domain XML"));
-        goto cleanup;
-    }
-    doc = virXMLParseStringCtxt(domxml, _("(domain_definition)"), &ctxt);
-    if (!doc) {
-        vshError(ctl, "%s", _("Couldn't parse domain XML"));
-        goto cleanup;
-    }
-    if (title)
-        desc = virXPathString("string(./title[1])", ctxt);
-    else
-        desc = virXPathString("string(./description[1])", ctxt);
-
-    if (!desc)
-        desc = vshStrdup(ctl, "");
-
-cleanup:
-    VIR_FREE(domxml);
-    xmlXPathFreeContext(ctxt);
-    xmlFreeDoc(doc);
-
-    return desc;
-}
-
 /* Return a non-NULL string representation of a typed parameter; exit
  * if we are out of memory.  */
 static char *
@@ -19814,25 +18171,6 @@ vshFindTypedParamByName(const char *name, virTypedParameterPtr list, int count)
 }
 
 static const char *
-vshDomainControlStateToString(int state)
-{
-    switch ((virDomainControlState) state) {
-    case VIR_DOMAIN_CONTROL_OK:
-        return N_("ok");
-    case VIR_DOMAIN_CONTROL_JOB:
-        return N_("background job");
-    case VIR_DOMAIN_CONTROL_OCCUPIED:
-        return N_("occupied");
-    case VIR_DOMAIN_CONTROL_ERROR:
-        return N_("error");
-    default:
-        ;
-    }
-
-    return N_("unknown");
-}
-
-static const char *
 vshDomainVcpuStateToString(int state)
 {
     switch (state) {
@@ -20815,6 +19153,8 @@ static const vshCmdDef domManagementCmds[] = {
     {NULL, NULL, NULL, NULL, 0}
 };
 
+#include "virsh-domain-monitor.c"
+
 static const vshCmdDef domMonitoringCmds[] = {
     {"domblkerror", cmdDomBlkError, opts_domblkerror, info_domblkerror, 0},
     {"domblkinfo", cmdDomblkinfo, opts_domblkinfo, info_domblkinfo, 0},
-- 
1.7.7.3




More information about the libvir-list mailing list