---
tools/virsh.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
tools/virsh.pod | 11 +++++
2 files changed, 122 insertions(+), 0 deletions(-)
diff --git a/tools/virsh.c b/tools/virsh.c
index d635b56..92029fd 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -15809,6 +15809,116 @@ cleanup:
}
/*
+ * "domioerror" command
+ */
+static const char *
+vshDomainIOErrorToString(int error)
+{
+ switch ((virDomainIoError) error) {
+ case VIR_DOMAIN_IOERROR_NONE:
+ return _("no error");
+ case VIR_DOMAIN_IOERROR_NO_SPACE:
+ return _("no space");
+ case VIR_DOMAIN_IOERROR_UNSPEC:
+ return _("unspecified error");
+ case VIR_DOMAIN_IOERROR_LAST:
+ ;
+ }
+
+ return _("unknown error");
+}
+
+static const vshCmdInfo info_domioerror[] = {
+ {"help", N_("Show I/O error on a disk device")},
+ {"desc", N_("Show I/O error")},
+ {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_domioerror[] = {
+ {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id, or
uuid")},
+ {"disk", VSH_OT_DATA, 0, N_("disk device")},
+ {"all", VSH_OT_BOOL, 0, N_("show error on all attached disks")},
+ {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdDomIOError(vshControl *ctl, const vshCmd *cmd)
+{
+ virDomainPtr dom;
+ const char *dev = NULL;
+ bool all = vshCommandOptBool(cmd, "all");
+ char *xml;
+ xmlDocPtr xmldoc = NULL;
+ xmlXPathContextPtr ctxt = NULL;
+ xmlNodePtr *disks = NULL;
+ int ndisks;
+ int i;
+ int result;
+ bool ret = false;
+
+ if (!vshConnectionUsability(ctl, ctl->conn))
+ return false;
+
+ if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ return false;
+
+ if (vshCommandOptString(cmd, "disk", &dev) < 0)
+ goto cleanup;
+ if (dev && all) {
+ vshError(ctl, "%s",
+ _("--disk and --all options are mutually exclusive"));
+ goto cleanup;
+ }
+
+ if (all) {
+ if (!(xml = virDomainGetXMLDesc(dom, 0)))
+ goto cleanup;
+
+ xmldoc = virXMLParseStringCtxt(xml, _("(domain_definition)"),
&ctxt);
+ VIR_FREE(xml);
+ if (!xmldoc)
+ goto cleanup;
+
+ ndisks = virXPathNodeSet("./devices/disk/target", ctxt, &disks);
+ if (ndisks < 0)
+ goto cleanup;
+
+ for (i = 0; i < ndisks; i++) {
+ char *disk;
+
+ if (!(disk = virXMLPropString(disks[i], "dev")))
+ continue;
+
+ if ((result = virDomainGetIoError(dom, disk, 0)) < 0) {
+ VIR_FREE(disk);
+ goto cleanup;
+ }
+
+ vshPrint(ctl, "%s: %s\n", disk, vshDomainIOErrorToString(result));
+ VIR_FREE(disk);
+ }
+ } else {
+ if ((result = virDomainGetIoError(dom, dev, 0)) == -1)
+ goto cleanup;
+ if (result == -2) {
+ vshError(ctl, _("there are multiple devices with error"));
+ goto cleanup;
+ }
+
+ vshPrint(ctl, "%s", vshDomainIOErrorToString(result));
+ }
+
+ ret = true;
+
+cleanup:
+ VIR_FREE(disks);
+ xmlXPathFreeContext(ctxt);
+ xmlFreeDoc(xmldoc);
+ virDomainFree(dom);
+ return ret;
+}
+
+/*
* "qemu-monitor-command" command
*/
static const vshCmdInfo info_qemu_monitor_command[] = {
@@ -16014,6 +16124,7 @@ static const vshCmdDef domMonitoringCmds[] = {
{"domiflist", cmdDomiflist, opts_domiflist, info_domiflist, 0},
{"domifstat", cmdDomIfstat, opts_domifstat, info_domifstat, 0},
{"dominfo", cmdDominfo, opts_dominfo, info_dominfo, 0},
+ {"domioerror", cmdDomIOError, opts_domioerror, info_domioerror, 0},
{"dommemstat", cmdDomMemStat, opts_dommemstat, info_dommemstat, 0},
{"domstate", cmdDomstate, opts_domstate, info_domstate, 0},
{"list", cmdList, opts_list, info_list, 0},
diff --git a/tools/virsh.pod b/tools/virsh.pod
index 67f93a9..a8574a5 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -595,6 +595,17 @@ new size in kilobytes
Returns basic information about the domain.
+=item B<domioerror> I<domain-id> { [I<--all>] | [I<disk>] }
+
+Show domain I/O error. This command usually comes handy when B<domstate>
+command says that a domain was paused due to I/O error. The B<domioerror>
+command works in three modes. With I<--all> option, it prints all disk
+devices configured for the domain and I/O errors associated with them. In
+case I<disk> is specified, this command only prints the I/O error associated
+with the specified disk. When neither I<--all> nor I<disk> is specified and
+there is at most one disk device in I/O error state, the command prints it.
+Otherwise the command fails.
+
=item B<domuuid> I<domain-name-or-id>
Convert a domain name or id to domain UUID
--
1.7.8.4