---
tools/virsh.c | 195 +++++++++++++++++++++++++++++++++++++++++++++++----------
1 files changed, 162 insertions(+), 33 deletions(-)
diff --git a/tools/virsh.c b/tools/virsh.c
index 5d8b025..6dae9fa 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -223,6 +223,8 @@ typedef struct __vshControl {
int log_fd; /* log file descriptor */
char *historydir; /* readline history directory name */
char *historyfile; /* readline history file name */
+ bool noGetState; /* virDomainGetState is not supported in
+ * current connection */
} __vshControl;
typedef struct vshCmdGrp {
@@ -334,7 +336,9 @@ static void vshDebug(vshControl *ctl, int level, const char *format,
...)
/* XXX: add batch support */
#define vshPrint(_ctl, ...) vshPrintExtra(NULL, __VA_ARGS__)
+static int vshDomainState(vshControl *ctl, virDomainPtr dom, int *reason);
static const char *vshDomainStateToString(int state);
+static const char *vshDomainStateReasonToString(int state, int reason);
static const char *vshDomainVcpuStateToString(int state);
static bool vshConnectionUsability(vshControl *ctl, virConnectPtr conn);
@@ -571,6 +575,7 @@ vshReconnect(vshControl *ctl) {
else
vshError(ctl, "%s", _("Reconnected to the hypervisor"));
disconnected = 0;
+ ctl->noGetState = false;
}
/* ---------------
@@ -717,6 +722,7 @@ cmdConnect(vshControl *ctl, const vshCmd *cmd)
}
ctl->name = vshStrdup(ctl, name);
+ ctl->noGetState = false;
ctl->readonly = ro;
ctl->conn = virConnectOpenAuth(ctl->name, virConnectAuthPtrDefault,
@@ -750,14 +756,14 @@ static bool
cmdRunConsole(vshControl *ctl, virDomainPtr dom, const char *name)
{
bool ret = false;
- virDomainInfo dominfo;
+ int state;
- if (virDomainGetInfo(dom, &dominfo) < 0) {
+ if ((state = vshDomainState(ctl, dom, NULL)) < 0) {
vshError(ctl, "%s", _("Unable to get domain status"));
goto cleanup;
}
- if (dominfo.state == VIR_DOMAIN_SHUTOFF) {
+ if (state == VIR_DOMAIN_SHUTOFF) {
vshError(ctl, "%s", _("The domain is not running"));
goto cleanup;
}
@@ -872,29 +878,20 @@ cmdList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
vshPrintExtra(ctl, "----------------------------------\n");
for (i = 0; i < maxid; i++) {
- virDomainInfo info;
virDomainPtr dom = virDomainLookupByID(ctl->conn, ids[i]);
- const char *state;
/* this kind of work with domains is not atomic operation */
if (!dom)
continue;
- if (virDomainGetInfo(dom, &info) < 0)
- state = _("no state");
- else
- state = _(vshDomainStateToString(info.state));
-
vshPrint(ctl, "%3d %-20s %s\n",
virDomainGetID(dom),
virDomainGetName(dom),
- state);
+ vshDomainStateToString(vshDomainState(ctl, dom, NULL)));
virDomainFree(dom);
}
for (i = 0; i < maxname; i++) {
- virDomainInfo info;
virDomainPtr dom = virDomainLookupByName(ctl->conn, names[i]);
- const char *state;
/* this kind of work with domains is not atomic operation */
if (!dom) {
@@ -902,12 +899,10 @@ cmdList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
continue;
}
- if (virDomainGetInfo(dom, &info) < 0)
- state = _("no state");
- else
- state = _(vshDomainStateToString(info.state));
-
- vshPrint(ctl, "%3s %-20s %s\n", "-", names[i], state);
+ vshPrint(ctl, "%3s %-20s %s\n",
+ "-",
+ names[i],
+ vshDomainStateToString(vshDomainState(ctl, dom, NULL)));
virDomainFree(dom);
VIR_FREE(names[i]);
@@ -928,15 +923,17 @@ static const vshCmdInfo info_domstate[] = {
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)
{
- virDomainInfo info;
virDomainPtr dom;
bool ret = true;
+ int showReason = vshCommandOptBool(cmd, "reason");
+ int state, reason;
if (!vshConnectionUsability(ctl, ctl->conn))
return false;
@@ -944,12 +941,21 @@ cmdDomstate(vshControl *ctl, const vshCmd *cmd)
if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
return false;
- if (virDomainGetInfo(dom, &info) == 0)
- vshPrint(ctl, "%s\n",
- _(vshDomainStateToString(info.state)));
- else
+ 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;
}
@@ -3023,7 +3029,6 @@ static bool
cmdSetmaxmem(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom;
- virDomainInfo info;
int kilobytes = 0;
bool ret = true;
int config = vshCommandOptBool(cmd, "config");
@@ -3063,12 +3068,6 @@ cmdSetmaxmem(vshControl *ctl, const vshCmd *cmd)
return false;
}
- if (virDomainGetInfo(dom, &info) != 0) {
- virDomainFree(dom);
- vshError(ctl, "%s", _("Unable to verify current
MemorySize"));
- return false;
- }
-
if (flags == -1) {
if (virDomainSetMaxMemory(dom, kilobytes) != 0) {
vshError(ctl, "%s", _("Unable to change
MaxMemorySize"));
@@ -12024,10 +12023,38 @@ vshCommandStringParse(vshControl *ctl, char *cmdstr)
* Misc utils
* ---------------
*/
+static int
+vshDomainState(vshControl *ctl, virDomainPtr dom, int *reason)
+{
+ virDomainInfo info;
+
+ if (reason)
+ *reason = -1;
+
+ if (!ctl->noGetState) {
+ int state;
+ if (virDomainGetState(dom, &state, reason) < 0) {
+ virErrorPtr err = virGetLastError();
+ if (err && err->code == VIR_ERR_NO_SUPPORT)
+ ctl->noGetState = true;
+ else
+ return -1;
+ } else {
+ return state;
+ }
+ }
+
+ /* fall back to virDomainGetInfo if virDomainGetState is not supported */
+ if (virDomainGetInfo(dom, &info) < 0)
+ return -1;
+ else
+ return info.state;
+}
+
static const char *
vshDomainStateToString(int state)
{
- switch (state) {
+ switch ((virDomainState) state) {
case VIR_DOMAIN_RUNNING:
return N_("running");
case VIR_DOMAIN_BLOCKED:
@@ -12040,13 +12067,114 @@ vshDomainStateToString(int state)
return N_("shut off");
case VIR_DOMAIN_CRASHED:
return N_("crashed");
- default:
+ case VIR_DOMAIN_NOSTATE:
;/*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:
+ ;
+ }
+ 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_UNKNOWN:
+ ;
+ }
+ break;
+
+ case VIR_DOMAIN_BLOCKED:
+ switch ((virDomainBlockedReason) reason) {
+ case VIR_DOMAIN_BLOCKED_UNKNOWN:
+ ;
+ }
+ 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_UNKNOWN:
+ ;
+ }
+ break;
+
+ case VIR_DOMAIN_SHUTDOWN:
+ switch ((virDomainShutdownReason) reason) {
+ case VIR_DOMAIN_SHUTDOWN_USER:
+ return N_("user");
+ case VIR_DOMAIN_SHUTDOWN_UNKNOWN:
+ ;
+ }
+ 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:
+ ;
+ }
+ break;
+
+ case VIR_DOMAIN_CRASHED:
+ switch ((virDomainCrashedReason) reason) {
+ case VIR_DOMAIN_CRASHED_UNKNOWN:
+ ;
+ }
+ break;
+ }
+
+ return N_("unknown");
+}
+
+static const char *
vshDomainVcpuStateToString(int state)
{
switch (state) {
@@ -12144,6 +12272,7 @@ vshError(vshControl *ctl, const char *format, ...)
VIR_FREE(str);
}
+
/*
* Initialize connection.
*/
--
1.7.5.rc3