]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
Implement domain state reason
authorJiri Denemark <jdenemar@redhat.com>
Wed, 4 May 2011 09:07:01 +0000 (11:07 +0200)
committerJiri Denemark <jdenemar@redhat.com>
Mon, 16 May 2011 11:36:08 +0000 (13:36 +0200)
Only in drivers which use virDomainObj, drivers that query hypervisor
for domain status need to be updated separately in case their hypervisor
supports this functionality.

The reason is also saved into domain state XML so if a domain is not
running (i.e., no state XML exists) the reason will be lost by libvirtd
restart. I think this is an acceptable limitation.

15 files changed:
src/conf/domain_conf.c
src/conf/domain_conf.h
src/libvirt_private.syms
src/libxl/libxl_driver.c
src/lxc/lxc_driver.c
src/openvz/openvz_conf.c
src/openvz/openvz_driver.c
src/qemu/qemu_driver.c
src/qemu/qemu_migration.c
src/qemu/qemu_process.c
src/qemu/qemu_process.h
src/test/test_driver.c
src/uml/uml_driver.c
src/vmware/vmware_conf.c
src/vmware/vmware_driver.c

index a0eb43eb0dbc3a75c7e927baa5130c8f9043919d..498438a4899f2dc7a77166dfee277ca96b4478e5 100644 (file)
@@ -376,6 +376,56 @@ VIR_ENUM_IMPL(virDomainState, VIR_DOMAIN_CRASHED+1,
               "shutoff",
               "crashed")
 
+#define VIR_DOMAIN_NOSTATE_LAST (VIR_DOMAIN_NOSTATE_UNKNOWN + 1)
+VIR_ENUM_IMPL(virDomainNostateReason, VIR_DOMAIN_NOSTATE_LAST,
+              "unknown")
+
+#define VIR_DOMAIN_RUNNING_LAST (VIR_DOMAIN_RUNNING_SAVE_CANCELED + 1)
+VIR_ENUM_IMPL(virDomainRunningReason, VIR_DOMAIN_RUNNING_LAST,
+              "unknown",
+              "booted",
+              "migrated",
+              "restored",
+              "from snapshot",
+              "unpaused",
+              "migration canceled",
+              "save canceled")
+
+#define VIR_DOMAIN_BLOCKED_LAST (VIR_DOMAIN_BLOCKED_UNKNOWN + 1)
+VIR_ENUM_IMPL(virDomainBlockedReason, VIR_DOMAIN_BLOCKED_LAST,
+              "unknown")
+
+#define VIR_DOMAIN_PAUSED_LAST (VIR_DOMAIN_PAUSED_FROM_SNAPSHOT + 1)
+VIR_ENUM_IMPL(virDomainPausedReason, VIR_DOMAIN_PAUSED_LAST,
+              "unknown",
+              "user",
+              "migration",
+              "save",
+              "dump",
+              "ioerror",
+              "watchdog",
+              "from snapshot")
+
+#define VIR_DOMAIN_SHUTDOWN_LAST (VIR_DOMAIN_SHUTDOWN_USER + 1)
+VIR_ENUM_IMPL(virDomainShutdownReason, VIR_DOMAIN_SHUTDOWN_LAST,
+              "unknown",
+              "user")
+
+#define VIR_DOMAIN_SHUTOFF_LAST (VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT + 1)
+VIR_ENUM_IMPL(virDomainShutoffReason, VIR_DOMAIN_SHUTOFF_LAST,
+              "unknown",
+              "shutdown",
+              "destroyed",
+              "crashed",
+              "migrated",
+              "saved",
+              "failed",
+              "from snapshot")
+
+#define VIR_DOMAIN_CRASHED_LAST (VIR_DOMAIN_CRASHED_UNKNOWN + 1)
+VIR_ENUM_IMPL(virDomainCrashedReason, VIR_DOMAIN_CRASHED_LAST,
+              "unknown")
+
 VIR_ENUM_IMPL(virDomainSeclabel, VIR_DOMAIN_SECLABEL_LAST,
               "dynamic",
               "static")
@@ -1080,7 +1130,8 @@ static virDomainObjPtr virDomainObjNew(virCapsPtr caps)
     }
 
     virDomainObjLock(domain);
-    domain->state = VIR_DOMAIN_SHUTOFF;
+    virDomainObjSetState(domain, VIR_DOMAIN_SHUTOFF,
+                                 VIR_DOMAIN_SHUTOFF_UNKNOWN);
     domain->refs = 1;
 
     virDomainSnapshotObjListInit(&domain->snapshots);
@@ -6240,6 +6291,8 @@ static virDomainObjPtr virDomainObjParseXML(virCapsPtr caps,
     virDomainObjPtr obj;
     xmlNodePtr *nodes = NULL;
     int i, n;
+    int state;
+    int reason = 0;
 
     if (!(obj = virDomainObjNew(caps)))
         return NULL;
@@ -6263,7 +6316,7 @@ static virDomainObjPtr virDomainObjParseXML(virCapsPtr caps,
                              "%s", _("missing domain state"));
         goto error;
     }
-    if ((obj->state = virDomainStateTypeFromString(tmp)) < 0) {
+    if ((state = virDomainStateTypeFromString(tmp)) < 0) {
         virDomainReportError(VIR_ERR_INTERNAL_ERROR,
                              _("invalid domain state '%s'"), tmp);
         VIR_FREE(tmp);
@@ -6271,6 +6324,18 @@ static virDomainObjPtr virDomainObjParseXML(virCapsPtr caps,
     }
     VIR_FREE(tmp);
 
+    if ((tmp = virXPathString("string(./@reason)", ctxt))) {
+        if ((reason = virDomainStateReasonFromString(state, tmp)) < 0) {
+            virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+                                 _("invalid domain state reason '%s'"), tmp);
+            VIR_FREE(tmp);
+            goto error;
+        }
+        VIR_FREE(tmp);
+    }
+
+    virDomainObjSetState(obj, state, reason);
+
     if ((virXPathLong("string(./@pid)", ctxt, &val)) < 0) {
         virDomainReportError(VIR_ERR_INTERNAL_ERROR,
                              "%s", _("invalid pid"));
@@ -8463,10 +8528,14 @@ static char *virDomainObjFormat(virCapsPtr caps,
 {
     char *config_xml = NULL;
     virBuffer buf = VIR_BUFFER_INITIALIZER;
+    int state;
+    int reason;
     int i;
 
-    virBufferAsprintf(&buf, "<domstatus state='%s' pid='%d'>\n",
-                      virDomainStateTypeToString(obj->state),
+    state = virDomainObjGetState(obj, &reason);
+    virBufferAsprintf(&buf, "<domstatus state='%s' reason='%s' pid='%d'>\n",
+                      virDomainStateTypeToString(state),
+                      virDomainStateReasonToString(state, reason),
                       obj->pid);
 
     for (i = 0 ; i < VIR_DOMAIN_TAINT_LAST ; i++) {
@@ -9559,3 +9628,89 @@ virDomainObjCopyPersistentDef(virCapsPtr caps, virDomainObjPtr dom)
     VIR_FREE(xml);
     return ret;
 }
+
+
+virDomainState
+virDomainObjGetState(virDomainObjPtr dom, int *reason)
+{
+    if (reason)
+        *reason = dom->state.reason;
+
+    return dom->state.state;
+}
+
+
+void
+virDomainObjSetState(virDomainObjPtr dom, virDomainState state, int reason)
+{
+    int last = -1;
+
+    switch (state) {
+    case VIR_DOMAIN_NOSTATE:    last = VIR_DOMAIN_NOSTATE_LAST;     break;
+    case VIR_DOMAIN_RUNNING:    last = VIR_DOMAIN_RUNNING_LAST;     break;
+    case VIR_DOMAIN_BLOCKED:    last = VIR_DOMAIN_BLOCKED_LAST;     break;
+    case VIR_DOMAIN_PAUSED:     last = VIR_DOMAIN_PAUSED_LAST;      break;
+    case VIR_DOMAIN_SHUTDOWN:   last = VIR_DOMAIN_SHUTDOWN_LAST;    break;
+    case VIR_DOMAIN_SHUTOFF:    last = VIR_DOMAIN_SHUTOFF_LAST;     break;
+    case VIR_DOMAIN_CRASHED:    last = VIR_DOMAIN_CRASHED_LAST;     break;
+    }
+
+    if (last < 0) {
+        VIR_ERROR(_("invalid domain state: %d"), state);
+        return;
+    }
+
+    dom->state.state = state;
+    if (reason > 0 && reason < last)
+        dom->state.reason = reason;
+    else
+        dom->state.reason = 0;
+}
+
+
+const char *
+virDomainStateReasonToString(virDomainState state, int reason)
+{
+    switch (state) {
+    case VIR_DOMAIN_NOSTATE:
+        return virDomainNostateReasonTypeToString(reason);
+    case VIR_DOMAIN_RUNNING:
+        return virDomainRunningReasonTypeToString(reason);
+    case VIR_DOMAIN_BLOCKED:
+        return virDomainBlockedReasonTypeToString(reason);
+    case VIR_DOMAIN_PAUSED:
+        return virDomainPausedReasonTypeToString(reason);
+    case VIR_DOMAIN_SHUTDOWN:
+        return virDomainShutdownReasonTypeToString(reason);
+    case VIR_DOMAIN_SHUTOFF:
+        return virDomainShutoffReasonTypeToString(reason);
+    case VIR_DOMAIN_CRASHED:
+        return virDomainCrashedReasonTypeToString(reason);
+    }
+
+    return NULL;
+}
+
+
+int
+virDomainStateReasonFromString(virDomainState state, const char *reason)
+{
+    switch (state) {
+    case VIR_DOMAIN_NOSTATE:
+        return virDomainNostateReasonTypeFromString(reason);
+    case VIR_DOMAIN_RUNNING:
+        return virDomainRunningReasonTypeFromString(reason);
+    case VIR_DOMAIN_BLOCKED:
+        return virDomainBlockedReasonTypeFromString(reason);
+    case VIR_DOMAIN_PAUSED:
+        return virDomainPausedReasonTypeFromString(reason);
+    case VIR_DOMAIN_SHUTDOWN:
+        return virDomainShutdownReasonTypeFromString(reason);
+    case VIR_DOMAIN_SHUTOFF:
+        return virDomainShutoffReasonTypeFromString(reason);
+    case VIR_DOMAIN_CRASHED:
+        return virDomainCrashedReasonTypeFromString(reason);
+    }
+
+    return -1;
+}
index a0f820cf74570feb5f2e9a005b8578ec630634d2..fe42f21dad5520616c9e50825ac3db11f3343e24 100644 (file)
@@ -1193,6 +1193,12 @@ enum virDomainTaintFlags {
 };
 
 /* Guest VM runtime state */
+typedef struct _virDomainStateReason virDomainStateReason;
+struct _virDomainStateReason {
+    int state;
+    int reason;
+};
+
 typedef struct _virDomainObj virDomainObj;
 typedef virDomainObj *virDomainObjPtr;
 struct _virDomainObj {
@@ -1200,7 +1206,7 @@ struct _virDomainObj {
     int refs;
 
     int pid;
-    int state;
+    virDomainStateReason state;
 
     unsigned int autostart : 1;
     unsigned int persistent : 1;
@@ -1440,6 +1446,13 @@ int virDomainDiskDefForeachPath(virDomainDiskDefPtr disk,
                                 virDomainDiskDefPathIterator iter,
                                 void *opaque);
 
+void
+virDomainObjSetState(virDomainObjPtr obj, virDomainState state, int reason)
+        ATTRIBUTE_NONNULL(1);
+virDomainState
+virDomainObjGetState(virDomainObjPtr obj, int *reason)
+        ATTRIBUTE_NONNULL(1);
+
 typedef const char* (*virLifecycleToStringFunc)(int type);
 typedef int (*virLifecycleFromStringFunc)(const char *type);
 
@@ -1494,6 +1507,17 @@ VIR_ENUM_DECL(virDomainGraphicsSpiceZlibCompression)
 VIR_ENUM_DECL(virDomainGraphicsSpicePlaybackCompression)
 /* from libvirt.h */
 VIR_ENUM_DECL(virDomainState)
+VIR_ENUM_DECL(virDomainNostateReason)
+VIR_ENUM_DECL(virDomainRunningReason)
+VIR_ENUM_DECL(virDomainBlockedReason)
+VIR_ENUM_DECL(virDomainPausedReason)
+VIR_ENUM_DECL(virDomainShutdownReason)
+VIR_ENUM_DECL(virDomainShutoffReason)
+VIR_ENUM_DECL(virDomainCrashedReason)
+
+const char *virDomainStateReasonToString(virDomainState state, int reason);
+int virDomainStateReasonFromString(virDomainState state, const char *reason);
+
 VIR_ENUM_DECL(virDomainSeclabel)
 VIR_ENUM_DECL(virDomainClockOffset)
 
index 21a65ad601762fa94053ef251af27a8845287e6c..809715496051e916dea936ebad7128ea246af8e9 100644 (file)
@@ -294,6 +294,7 @@ virDomainNetTypeToString;
 virDomainObjAssignDef;
 virDomainObjCopyPersistentDef;
 virDomainObjGetPersistentDef;
+virDomainObjGetState;
 virDomainObjIsDuplicate;
 virDomainObjListDeinit;
 virDomainObjListGetActiveIDs;
@@ -303,6 +304,7 @@ virDomainObjListNumOfDomains;
 virDomainObjLock;
 virDomainObjRef;
 virDomainObjSetDefTransient;
+virDomainObjSetState;
 virDomainObjTaint;
 virDomainObjUnlock;
 virDomainObjUnref;
@@ -326,6 +328,8 @@ virDomainSnapshotObjListRemove;
 virDomainSoundDefFree;
 virDomainSoundModelTypeFromString;
 virDomainSoundModelTypeToString;
+virDomainStateReasonFromString;
+virDomainStateReasonToString;
 virDomainStateTypeFromString;
 virDomainStateTypeToString;
 virDomainTaintTypeFromString;
index 895ff28f0e288e6c3f298f7ed70f26395992178e..1d7d1550b3eccad6c8e30dfc6aec7e61bee7919d 100644 (file)
@@ -225,7 +225,9 @@ libxlDoNodeGetInfo(libxlDriverPrivatePtr driver, virNodeInfoPtr info)
  * virDomainObjPtr should be locked on invocation
  */
 static void
-libxlVmCleanup(libxlDriverPrivatePtr driver, virDomainObjPtr vm)
+libxlVmCleanup(libxlDriverPrivatePtr driver,
+               virDomainObjPtr vm,
+               virDomainShutoffReason reason)
 {
     libxlDomainObjPrivatePtr priv = vm->privateData;
     int vnc_port;
@@ -245,7 +247,7 @@ libxlVmCleanup(libxlDriverPrivatePtr driver, virDomainObjPtr vm)
 
     if (vm->persistent) {
         vm->def->id = -1;
-        vm->state = VIR_DOMAIN_SHUTOFF;
+        virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, reason);
     }
 
     if ((vm->def->ngraphics == 1) &&
@@ -282,7 +284,10 @@ libxlVmCleanup(libxlDriverPrivatePtr driver, virDomainObjPtr vm)
  * virDomainObjPtr should be locked on invocation
  */
 static int
-libxlVmReap(libxlDriverPrivatePtr driver, virDomainObjPtr vm, int force)
+libxlVmReap(libxlDriverPrivatePtr driver,
+            virDomainObjPtr vm,
+            int force,
+            virDomainShutoffReason reason)
 {
     libxlDomainObjPrivatePtr priv = vm->privateData;
 
@@ -292,7 +297,7 @@ libxlVmReap(libxlDriverPrivatePtr driver, virDomainObjPtr vm, int force)
         return -1;
     }
 
-    libxlVmCleanup(driver, vm);
+    libxlVmCleanup(driver, vm, reason);
     return 0;
 }
 
@@ -333,6 +338,8 @@ static void libxlEventHandler(int watch,
         goto cleanup;
 
     if (event.type == LIBXL_EVENT_DOMAIN_DEATH) {
+        virDomainShutoffReason reason;
+
         /* libxl_event_get_domain_death_info returns 1 if death
          * event was for this domid */
         if (libxl_event_get_domain_death_info(&priv->ctx,
@@ -346,18 +353,22 @@ static void libxlEventHandler(int watch,
         switch (info.shutdown_reason) {
             case SHUTDOWN_poweroff:
             case SHUTDOWN_crash:
-                if (info.shutdown_reason == SHUTDOWN_crash)
+                if (info.shutdown_reason == SHUTDOWN_crash) {
                     dom_event = virDomainEventNewFromObj(vm,
                                               VIR_DOMAIN_EVENT_STOPPED,
                                               VIR_DOMAIN_EVENT_STOPPED_CRASHED);
-                libxlVmReap(driver, vm, 0);
+                    reason = VIR_DOMAIN_SHUTOFF_CRASHED;
+                } else {
+                    reason = VIR_DOMAIN_SHUTOFF_SHUTDOWN;
+                }
+                libxlVmReap(driver, vm, 0, reason);
                 if (!vm->persistent) {
                     virDomainRemoveInactive(&driver->domains, vm);
                     vm = NULL;
                 }
                 break;
             case SHUTDOWN_reboot:
-                libxlVmReap(driver, vm, 0);
+                libxlVmReap(driver, vm, 0, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
                 libxlVmStart(driver, vm, 0);
                 break;
             default:
@@ -576,9 +587,9 @@ libxlVmStart(libxlDriverPrivatePtr driver,
 
     if (!start_paused) {
         libxl_domain_unpause(&priv->ctx, domid);
-        vm->state = VIR_DOMAIN_RUNNING;
+        virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_BOOTED);
     } else {
-        vm->state = VIR_DOMAIN_PAUSED;
+        virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER);
     }
 
 
@@ -597,7 +608,7 @@ error:
     if (domid > 0) {
         libxl_domain_destroy(&priv->ctx, domid, 0);
         def->id = -1;
-        vm->state = VIR_DOMAIN_SHUTOFF;
+        virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, VIR_DOMAIN_SHUTOFF_FAILED);
     }
     libxl_domain_config_destroy(&d_config);
     VIR_FREE(dom_xml);
@@ -642,7 +653,7 @@ libxlReconnectDomain(void *payload,
 
     /* Update domid in case it changed (e.g. reboot) while we were gone? */
     vm->def->id = d_info.domid;
-    vm->state = VIR_DOMAIN_RUNNING;
+    virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_UNKNOWN);
 
     /* Recreate domain death et. al. events */
     libxlCreateDomEvents(vm);
@@ -650,7 +661,7 @@ libxlReconnectDomain(void *payload,
     return;
 
 out:
-    libxlVmCleanup(driver, vm);
+    libxlVmCleanup(driver, vm, VIR_DOMAIN_SHUTOFF_UNKNOWN);
     if (!vm->persistent)
         virDomainRemoveInactive(&driver->domains, vm);
     else
@@ -1187,7 +1198,7 @@ libxlDomainSuspend(virDomainPtr dom)
 
     priv = vm->privateData;
 
-    if (vm->state != VIR_DOMAIN_PAUSED) {
+    if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_PAUSED) {
         if (libxl_domain_pause(&priv->ctx, dom->id) != 0) {
             libxlError(VIR_ERR_INTERNAL_ERROR,
                        _("Failed to suspend domain '%d' with libxenlight"),
@@ -1195,7 +1206,7 @@ libxlDomainSuspend(virDomainPtr dom)
             goto cleanup;
         }
 
-        vm->state = VIR_DOMAIN_PAUSED;
+        virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER);
 
         event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_SUSPENDED,
                                          VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
@@ -1246,7 +1257,7 @@ libxlDomainResume(virDomainPtr dom)
 
     priv = vm->privateData;
 
-    if (vm->state == VIR_DOMAIN_PAUSED) {
+    if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
         if (libxl_domain_unpause(&priv->ctx, dom->id) != 0) {
             libxlError(VIR_ERR_INTERNAL_ERROR,
                        _("Failed to resume domain '%d' with libxenlight"),
@@ -1254,7 +1265,8 @@ libxlDomainResume(virDomainPtr dom)
             goto cleanup;
         }
 
-        vm->state = VIR_DOMAIN_RUNNING;
+        virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
+                             VIR_DOMAIN_RUNNING_UNPAUSED);
 
         event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_RESUMED,
                                          VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
@@ -1387,7 +1399,7 @@ libxlDomainDestroy(virDomainPtr dom)
     event = virDomainEventNewFromObj(vm,VIR_DOMAIN_EVENT_STOPPED,
                                      VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
 
-    if (libxlVmReap(driver, vm, 1) != 0) {
+    if (libxlVmReap(driver, vm, 1, VIR_DOMAIN_SHUTOFF_DESTROYED) != 0) {
         libxlError(VIR_ERR_INTERNAL_ERROR,
                    _("Failed to destroy domain '%d'"), dom->id);
         goto cleanup;
@@ -1570,7 +1582,7 @@ libxlDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info)
         info->memory = d_info.current_memkb;
     }
 
-    info->state = vm->state;
+    info->state = virDomainObjGetState(vm, NULL);
     info->maxMem = vm->def->mem.max_balloon;
     info->nrVirtCpu = vm->def->vcpus;
     ret = 0;
@@ -1603,10 +1615,7 @@ libxlDomainGetState(virDomainPtr dom,
         goto cleanup;
     }
 
-    *state = vm->state;
-    if (reason)
-        *reason = 0;
-
+    *state = virDomainObjGetState(vm, reason);
     ret = 0;
 
   cleanup:
index 17274657b582c929650272a371004a095e1c684b..1c55aee5c4a751ee12f98d639470322e697d2273 100644 (file)
@@ -525,7 +525,7 @@ static int lxcDomainGetInfo(virDomainPtr dom,
         goto cleanup;
     }
 
-    info->state = vm->state;
+    info->state = virDomainObjGetState(vm, NULL);
 
     if (!virDomainObjIsActive(vm) || driver->cgroup == NULL) {
         info->cpuTime = 0;
@@ -591,10 +591,7 @@ lxcDomainGetState(virDomainPtr dom,
         goto cleanup;
     }
 
-    *state = vm->state;
-    if (reason)
-        *reason = 0;
-
+    *state = virDomainObjGetState(vm, reason);
     ret = 0;
 
 cleanup:
@@ -987,15 +984,16 @@ cleanup:
 
 /**
  * lxcVmCleanup:
- * @conn: pointer to connection
  * @driver: pointer to driver structure
  * @vm: pointer to VM to clean up
+ * @reason: reason for switching the VM to shutoff state
  *
  * Cleanout resources associated with the now dead VM
  *
  */
 static void lxcVmCleanup(lxc_driver_t *driver,
-                        virDomainObjPtr  vm)
+                         virDomainObjPtr vm,
+                         virDomainShutoffReason reason)
 {
     virCgroupPtr cgroup;
     int i;
@@ -1017,7 +1015,7 @@ static void lxcVmCleanup(lxc_driver_t *driver,
     virFileDeletePid(driver->stateDir, vm->def->name);
     virDomainDeleteConfig(driver->stateDir, NULL, vm);
 
-    vm->state = VIR_DOMAIN_SHUTOFF;
+    virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, reason);
     vm->pid = -1;
     vm->def->id = -1;
     priv->monitor = -1;
@@ -1201,7 +1199,8 @@ error:
 
 
 static int lxcVmTerminate(lxc_driver_t *driver,
-                          virDomainObjPtr vm)
+                          virDomainObjPtr vm,
+                          virDomainShutoffReason reason)
 {
     virCgroupPtr group = NULL;
     int rc;
@@ -1228,7 +1227,7 @@ static int lxcVmTerminate(lxc_driver_t *driver,
         rc = -1;
         goto cleanup;
     }
-    lxcVmCleanup(driver, vm);
+    lxcVmCleanup(driver, vm, reason);
 
     rc = 0;
 
@@ -1258,7 +1257,7 @@ static void lxcMonitorEvent(int watch,
         goto cleanup;
     }
 
-    if (lxcVmTerminate(driver, vm) < 0) {
+    if (lxcVmTerminate(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN) < 0) {
         virEventRemoveHandle(watch);
     } else {
         event = virDomainEventNewFromObj(vm,
@@ -1392,6 +1391,7 @@ cleanup:
  * @conn: pointer to connection
  * @driver: pointer to driver structure
  * @vm: pointer to virtual machine structure
+ * @reason: reason for switching vm to running state
  *
  * Starts a vm
  *
@@ -1399,7 +1399,8 @@ cleanup:
  */
 static int lxcVmStart(virConnectPtr conn,
                       lxc_driver_t * driver,
-                      virDomainObjPtr  vm)
+                      virDomainObjPtr vm,
+                      virDomainRunningReason reason)
 {
     int rc = -1, r;
     unsigned int i;
@@ -1499,14 +1500,14 @@ static int lxcVmStart(virConnectPtr conn,
     }
 
     vm->def->id = vm->pid;
-    vm->state = VIR_DOMAIN_RUNNING;
+    virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, reason);
 
     if ((priv->monitorWatch = virEventAddHandle(
              priv->monitor,
              VIR_EVENT_HANDLE_ERROR | VIR_EVENT_HANDLE_HANGUP,
              lxcMonitorEvent,
              vm, NULL)) < 0) {
-        lxcVmTerminate(driver, vm);
+        lxcVmTerminate(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED);
         goto cleanup;
     }
 
@@ -1579,7 +1580,7 @@ static int lxcDomainStartWithFlags(virDomainPtr dom, unsigned int flags)
         goto cleanup;
     }
 
-    ret = lxcVmStart(dom->conn, driver, vm);
+    ret = lxcVmStart(dom->conn, driver, vm, VIR_DOMAIN_RUNNING_BOOTED);
 
     if (ret == 0)
         event = virDomainEventNewFromObj(vm,
@@ -1650,7 +1651,7 @@ lxcDomainCreateAndStart(virConnectPtr conn,
         goto cleanup;
     def = NULL;
 
-    if (lxcVmStart(conn, driver, vm) < 0) {
+    if (lxcVmStart(conn, driver, vm, VIR_DOMAIN_RUNNING_BOOTED) < 0) {
         virDomainRemoveInactive(&driver->domains, vm);
         vm = NULL;
         goto cleanup;
@@ -1815,7 +1816,7 @@ static int lxcDomainDestroy(virDomainPtr dom)
         goto cleanup;
     }
 
-    ret = lxcVmTerminate(driver, vm);
+    ret = lxcVmTerminate(driver, vm, VIR_DOMAIN_SHUTOFF_DESTROYED);
     event = virDomainEventNewFromObj(vm,
                                      VIR_DOMAIN_EVENT_STOPPED,
                                      VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
@@ -1863,7 +1864,8 @@ lxcAutostartDomain(void *payload, const void *name ATTRIBUTE_UNUSED, void *opaqu
     virDomainObjLock(vm);
     if (vm->autostart &&
         !virDomainObjIsActive(vm)) {
-        int ret = lxcVmStart(data->conn, data->driver, vm);
+        int ret = lxcVmStart(data->conn, data->driver, vm,
+                             VIR_DOMAIN_RUNNING_BOOTED);
         if (ret < 0) {
             virErrorPtr err = virGetLastError();
             VIR_ERROR(_("Failed to autostart VM '%s': %s"),
@@ -1937,14 +1939,15 @@ lxcReconnectVM(void *payload, const void *name ATTRIBUTE_UNUSED, void *opaque)
 
     if (vm->pid != 0) {
         vm->def->id = vm->pid;
-        vm->state = VIR_DOMAIN_RUNNING;
+        virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
+                             VIR_DOMAIN_RUNNING_UNKNOWN);
 
         if ((priv->monitorWatch = virEventAddHandle(
                  priv->monitor,
                  VIR_EVENT_HANDLE_ERROR | VIR_EVENT_HANDLE_HANGUP,
                  lxcMonitorEvent,
                  vm, NULL)) < 0) {
-            lxcVmTerminate(driver, vm);
+            lxcVmTerminate(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED);
             goto cleanup;
         }
     } else {
@@ -2551,13 +2554,13 @@ static int lxcDomainSuspend(virDomainPtr dom)
         goto cleanup;
     }
 
-    if (vm->state != VIR_DOMAIN_PAUSED) {
+    if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_PAUSED) {
         if (lxcFreezeContainer(driver, vm) < 0) {
             lxcError(VIR_ERR_OPERATION_FAILED,
                      "%s", _("Suspend operation failed"));
             goto cleanup;
         }
-        vm->state = VIR_DOMAIN_PAUSED;
+        virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER);
 
         event = virDomainEventNewFromObj(vm,
                                          VIR_DOMAIN_EVENT_SUSPENDED,
@@ -2616,13 +2619,14 @@ static int lxcDomainResume(virDomainPtr dom)
         goto cleanup;
     }
 
-    if (vm->state == VIR_DOMAIN_PAUSED) {
+    if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
         if (lxcUnfreezeContainer(driver, vm) < 0) {
             lxcError(VIR_ERR_OPERATION_FAILED,
                      "%s", _("Resume operation failed"));
             goto cleanup;
         }
-        vm->state = VIR_DOMAIN_RUNNING;
+        virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
+                             VIR_DOMAIN_RUNNING_UNPAUSED);
 
         event = virDomainEventNewFromObj(vm,
                                          VIR_DOMAIN_EVENT_RESUMED,
index 45bc398764dcd197a2ad7050dcfc0023db324466..c02d1311004be2e92af01e6218afa9c128f694d1 100644 (file)
@@ -486,14 +486,20 @@ int openvzLoadDomains(struct openvz_driver *driver) {
         if (VIR_ALLOC(dom->def) < 0)
             goto no_memory;
 
-        if (STREQ(status, "stopped"))
-            dom->state = VIR_DOMAIN_SHUTOFF;
-        else
-            dom->state = VIR_DOMAIN_RUNNING;
+        if (STREQ(status, "stopped")) {
+            virDomainObjSetState(dom, VIR_DOMAIN_SHUTOFF,
+                                 VIR_DOMAIN_SHUTOFF_UNKNOWN);
+        } else {
+            virDomainObjSetState(dom, VIR_DOMAIN_RUNNING,
+                                 VIR_DOMAIN_RUNNING_UNKNOWN);
+        }
 
         dom->refs = 1;
         dom->pid = veid;
-        dom->def->id = dom->state == VIR_DOMAIN_SHUTOFF ? -1 : veid;
+        if (virDomainObjGetState(dom, NULL) == VIR_DOMAIN_SHUTOFF)
+            dom->def->id = -1;
+        else
+            dom->def->id = veid;
         /* XXX OpenVZ doesn't appear to have concept of a transient domain */
         dom->persistent = 1;
 
index 51631273d2cd91a8e58a222f1a2100540cef3759..897211b37162d07b0ad7e8f80afe5d8e955f7b9d 100644 (file)
@@ -353,7 +353,7 @@ static int openvzDomainGetInfo(virDomainPtr dom,
         goto cleanup;
     }
 
-    info->state = vm->state;
+    info->state = virDomainObjGetState(vm, NULL);
 
     if (!virDomainObjIsActive(vm)) {
         info->cpuTime = 0;
@@ -399,10 +399,7 @@ openvzDomainGetState(virDomainPtr dom,
         goto cleanup;
     }
 
-    *state = vm->state;
-    if (reason)
-        *reason = 0;
-
+    *state = virDomainObjGetState(vm, reason);
     ret = 0;
 
 cleanup:
@@ -525,12 +522,12 @@ static int openvzDomainSuspend(virDomainPtr dom) {
         goto cleanup;
     }
 
-    if (vm->state != VIR_DOMAIN_PAUSED) {
+    if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_PAUSED) {
         openvzSetProgramSentinal(prog, vm->def->name);
         if (virRun(prog, NULL) < 0) {
             goto cleanup;
         }
-        vm->state = VIR_DOMAIN_PAUSED;
+        virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER);
     }
 
     ret = 0;
@@ -563,12 +560,12 @@ static int openvzDomainResume(virDomainPtr dom) {
       goto cleanup;
   }
 
-  if (vm->state == VIR_DOMAIN_PAUSED) {
+  if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
       openvzSetProgramSentinal(prog, vm->def->name);
       if (virRun(prog, NULL) < 0) {
           goto cleanup;
       }
-      vm->state = VIR_DOMAIN_RUNNING;
+      virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_UNPAUSED);
   }
 
   ret = 0;
@@ -596,7 +593,7 @@ static int openvzDomainShutdown(virDomainPtr dom) {
     }
 
     openvzSetProgramSentinal(prog, vm->def->name);
-    if (vm->state != VIR_DOMAIN_RUNNING) {
+    if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_RUNNING) {
         openvzError(VIR_ERR_INTERNAL_ERROR, "%s",
                     _("domain is not in running state"));
         goto cleanup;
@@ -606,7 +603,7 @@ static int openvzDomainShutdown(virDomainPtr dom) {
         goto cleanup;
 
     vm->def->id = -1;
-    vm->state = VIR_DOMAIN_SHUTOFF;
+    virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
     dom->id = -1;
     ret = 0;
 
@@ -634,7 +631,7 @@ static int openvzDomainReboot(virDomainPtr dom,
     }
 
     openvzSetProgramSentinal(prog, vm->def->name);
-    if (vm->state != VIR_DOMAIN_RUNNING) {
+    if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_RUNNING) {
         openvzError(VIR_ERR_INTERNAL_ERROR, "%s",
                     _("domain is not in running state"));
         goto cleanup;
@@ -644,6 +641,8 @@ static int openvzDomainReboot(virDomainPtr dom,
         goto cleanup;
     ret = 0;
 
+    virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_BOOTED);
+
 cleanup:
     if (vm)
         virDomainObjUnlock(vm);
@@ -1008,7 +1007,7 @@ openvzDomainCreateXML(virConnectPtr conn, const char *xml,
 
     vm->pid = strtoI(vm->def->name);
     vm->def->id = vm->pid;
-    vm->state = VIR_DOMAIN_RUNNING;
+    virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_BOOTED);
 
     if (vm->def->maxvcpus > 0) {
         if (openvzDomainSetVcpusInternal(vm, vm->def->maxvcpus) < 0) {
@@ -1050,7 +1049,7 @@ openvzDomainCreateWithFlags(virDomainPtr dom, unsigned int flags)
         goto cleanup;
     }
 
-    if (vm->state != VIR_DOMAIN_SHUTOFF) {
+    if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_SHUTOFF) {
         openvzError(VIR_ERR_OPERATION_DENIED, "%s",
                     _("domain is not in shutoff state"));
         goto cleanup;
@@ -1064,7 +1063,7 @@ openvzDomainCreateWithFlags(virDomainPtr dom, unsigned int flags)
     vm->pid = strtoI(vm->def->name);
     vm->def->id = vm->pid;
     dom->id = vm->pid;
-    vm->state = VIR_DOMAIN_RUNNING;
+    virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_BOOTED);
     ret = 0;
 
 cleanup:
index 21d79a281e96173b4d2951a1f1107d6e34750653..27951f46f415c8768cae24055c03e14888d1e105 100644 (file)
@@ -1320,7 +1320,7 @@ static int qemudDomainSuspend(virDomainPtr dom) {
     priv = vm->privateData;
 
     if (priv->jobActive == QEMU_JOB_MIGRATION_OUT) {
-        if (vm->state != VIR_DOMAIN_PAUSED) {
+        if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_PAUSED) {
             VIR_DEBUG("Requesting domain pause on %s",
                       vm->def->name);
             priv->jobSignals |= QEMU_JOB_SIGNAL_SUSPEND;
@@ -1336,8 +1336,8 @@ static int qemudDomainSuspend(virDomainPtr dom) {
                             "%s", _("domain is not running"));
             goto endjob;
         }
-        if (vm->state != VIR_DOMAIN_PAUSED) {
-            if (qemuProcessStopCPUs(driver, vm) < 0) {
+        if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_PAUSED) {
+            if (qemuProcessStopCPUs(driver, vm, VIR_DOMAIN_PAUSED_USER) < 0) {
                 goto endjob;
             }
             event = virDomainEventNewFromObj(vm,
@@ -1389,8 +1389,9 @@ static int qemudDomainResume(virDomainPtr dom) {
                         "%s", _("domain is not running"));
         goto endjob;
     }
-    if (vm->state == VIR_DOMAIN_PAUSED) {
-        if (qemuProcessStartCPUs(driver, vm, dom->conn) < 0) {
+    if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
+        if (qemuProcessStartCPUs(driver, vm, dom->conn,
+                                 VIR_DOMAIN_RUNNING_UNPAUSED) < 0) {
             if (virGetLastError() == NULL)
                 qemuReportError(VIR_ERR_OPERATION_FAILED,
                                 "%s", _("resume operation failed"));
@@ -1493,7 +1494,7 @@ static int qemudDomainDestroy(virDomainPtr dom) {
         goto endjob;
     }
 
-    qemuProcessStop(driver, vm, 0);
+    qemuProcessStop(driver, vm, 0, VIR_DOMAIN_SHUTOFF_DESTROYED);
     event = virDomainEventNewFromObj(vm,
                                      VIR_DOMAIN_EVENT_STOPPED,
                                      VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
@@ -1771,7 +1772,7 @@ static int qemudDomainGetInfo(virDomainPtr dom,
         goto cleanup;
     }
 
-    info->state = vm->state;
+    info->state = virDomainObjGetState(vm, NULL);
 
     if (!virDomainObjIsActive(vm)) {
         info->cpuTime = 0;
@@ -1853,10 +1854,7 @@ qemuDomainGetState(virDomainPtr dom,
         goto cleanup;
     }
 
-    *state = vm->state;
-    if (reason)
-        *reason = 0;
-
+    *state = virDomainObjGetState(vm, reason);
     ret = 0;
 
 cleanup:
@@ -1982,9 +1980,9 @@ static int qemudDomainSaveFlag(struct qemud_driver *driver, virDomainPtr dom,
     priv->jobInfo.type = VIR_DOMAIN_JOB_UNBOUNDED;
 
     /* Pause */
-    if (vm->state == VIR_DOMAIN_RUNNING) {
+    if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
         header.was_running = 1;
-        if (qemuProcessStopCPUs(driver, vm) < 0)
+        if (qemuProcessStopCPUs(driver, vm, VIR_DOMAIN_PAUSED_SAVE) < 0)
             goto endjob;
 
         if (!virDomainObjIsActive(vm)) {
@@ -2131,7 +2129,7 @@ static int qemudDomainSaveFlag(struct qemud_driver *driver, virDomainPtr dom,
     ret = 0;
 
     /* Shut it down */
-    qemuProcessStop(driver, vm, 0);
+    qemuProcessStop(driver, vm, 0, VIR_DOMAIN_SHUTOFF_SAVED);
     qemuAuditDomainStop(vm, "saved");
     event = virDomainEventNewFromObj(vm,
                                      VIR_DOMAIN_EVENT_STOPPED,
@@ -2147,7 +2145,8 @@ endjob:
     if (vm) {
         if (ret != 0) {
             if (header.was_running && virDomainObjIsActive(vm)) {
-                rc = qemuProcessStartCPUs(driver, vm, dom->conn);
+                rc = qemuProcessStartCPUs(driver, vm, dom->conn,
+                                          VIR_DOMAIN_RUNNING_SAVE_CANCELED);
                 if (rc < 0)
                     VIR_WARN("Unable to resume guest CPUs after save failure");
             }
@@ -2459,11 +2458,12 @@ static int qemudDomainCoreDump(virDomainPtr dom,
 
     /* Migrate will always stop the VM, so the resume condition is
        independent of whether the stop command is issued.  */
-    resume = (vm->state == VIR_DOMAIN_RUNNING);
+    resume = virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING;
 
     /* Pause domain for non-live dump */
-    if (!(flags & VIR_DUMP_LIVE) && vm->state == VIR_DOMAIN_RUNNING) {
-        if (qemuProcessStopCPUs(driver, vm) < 0)
+    if (!(flags & VIR_DUMP_LIVE) &&
+        virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
+        if (qemuProcessStopCPUs(driver, vm, VIR_DOMAIN_PAUSED_DUMP) < 0)
             goto endjob;
         paused = 1;
 
@@ -2482,7 +2482,7 @@ static int qemudDomainCoreDump(virDomainPtr dom,
 
 endjob:
     if ((ret == 0) && (flags & VIR_DUMP_CRASH)) {
-        qemuProcessStop(driver, vm, 0);
+        qemuProcessStop(driver, vm, 0, VIR_DOMAIN_SHUTOFF_CRASHED);
         qemuAuditDomainStop(vm, "crashed");
         event = virDomainEventNewFromObj(vm,
                                          VIR_DOMAIN_EVENT_STOPPED,
@@ -2493,7 +2493,8 @@ endjob:
        will support synchronous operations so we always get here after
        the migration is complete.  */
     else if (resume && paused && virDomainObjIsActive(vm)) {
-        if (qemuProcessStartCPUs(driver, vm, dom->conn) < 0) {
+        if (qemuProcessStartCPUs(driver, vm, dom->conn,
+                                 VIR_DOMAIN_RUNNING_UNPAUSED) < 0) {
             if (virGetLastError() == NULL)
                 qemuReportError(VIR_ERR_OPERATION_FAILED,
                                 "%s", _("resuming after dump failed"));
@@ -2647,7 +2648,8 @@ static void processWatchdogEvent(void *data, void *opaque)
                 qemuReportError(VIR_ERR_OPERATION_FAILED,
                                 "%s", _("Dump failed"));
 
-            ret = qemuProcessStartCPUs(driver, wdEvent->vm, NULL);
+            ret = qemuProcessStartCPUs(driver, wdEvent->vm, NULL,
+                                       VIR_DOMAIN_RUNNING_UNPAUSED);
 
             if (ret < 0)
                 qemuReportError(VIR_ERR_OPERATION_FAILED,
@@ -3345,7 +3347,8 @@ qemuDomainSaveImageStartVM(virConnectPtr conn,
 
     /* If it was running before, resume it now. */
     if (header->was_running) {
-        if (qemuProcessStartCPUs(driver, vm, conn) < 0) {
+        if (qemuProcessStartCPUs(driver, vm, conn,
+                                 VIR_DOMAIN_RUNNING_RESTORED) < 0) {
             if (virGetLastError() == NULL)
                 qemuReportError(VIR_ERR_OPERATION_FAILED,
                                 "%s", _("failed to resume domain"));
@@ -6474,12 +6477,12 @@ qemuDomainSnapshotCreateActive(virConnectPtr conn,
     if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0)
         return -1;
 
-    if (vm->state == VIR_DOMAIN_RUNNING) {
+    if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
         /* savevm monitor command pauses the domain emitting an event which
          * confuses libvirt since it's not notified when qemu resumes the
          * domain. Thus we stop and start CPUs ourselves.
          */
-        if (qemuProcessStopCPUs(driver, vm) < 0)
+        if (qemuProcessStopCPUs(driver, vm, VIR_DOMAIN_PAUSED_SAVE) < 0)
             goto cleanup;
 
         resume = true;
@@ -6496,7 +6499,8 @@ qemuDomainSnapshotCreateActive(virConnectPtr conn,
 
 cleanup:
     if (resume && virDomainObjIsActive(vm) &&
-        qemuProcessStartCPUs(driver, vm, conn) < 0 &&
+        qemuProcessStartCPUs(driver, vm, conn,
+                             VIR_DOMAIN_RUNNING_UNPAUSED) < 0 &&
         virGetLastError() == NULL) {
         qemuReportError(VIR_ERR_OPERATION_FAILED, "%s",
                         _("resuming after snapshot failed"));
@@ -6546,7 +6550,7 @@ static virDomainSnapshotPtr qemuDomainSnapshotCreateXML(virDomainPtr domain,
     if (!(snap = virDomainSnapshotAssignDef(&vm->snapshots, def)))
         goto cleanup;
 
-    snap->def->state = vm->state;
+    snap->def->state = virDomainObjGetState(vm, NULL);
 
     /* actually do the snapshot */
     if (!virDomainObjIsActive(vm)) {
@@ -6846,9 +6850,13 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
             /* qemu unconditionally starts the domain running again after
              * loadvm, so let's pause it to keep consistency
              */
-            rc = qemuProcessStopCPUs(driver, vm);
+            rc = qemuProcessStopCPUs(driver, vm,
+                                     VIR_DOMAIN_PAUSED_FROM_SNAPSHOT);
             if (rc < 0)
                 goto endjob;
+        } else {
+            virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
+                                 VIR_DOMAIN_RUNNING_FROM_SNAPSHOT);
         }
 
         event = virDomainEventNewFromObj(vm,
@@ -6867,7 +6875,7 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
          */
 
         if (virDomainObjIsActive(vm)) {
-            qemuProcessStop(driver, vm, 0);
+            qemuProcessStop(driver, vm, 0, VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT);
             qemuAuditDomainStop(vm, "from-snapshot");
             event = virDomainEventNewFromObj(vm,
                                              VIR_DOMAIN_EVENT_STOPPED,
@@ -6884,8 +6892,6 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
             goto endjob;
     }
 
-    vm->state = snap->def->state;
-
     ret = 0;
 
 endjob:
index 3214d38dfbd179daee7191165219ba949b994b32..0e971ef75626ae29aaae51b154cce042865a0e4b 100644 (file)
@@ -65,7 +65,7 @@ qemuMigrationSetOffline(struct qemud_driver *driver,
 {
     int ret;
 
-    ret = qemuProcessStopCPUs(driver, vm);
+    ret = qemuProcessStopCPUs(driver, vm, VIR_DOMAIN_PAUSED_MIGRATION);
     if (ret == 0) {
         virDomainEventPtr event;
 
@@ -325,7 +325,7 @@ qemuMigrationPrepareTunnel(struct qemud_driver *driver,
 
     if (virFDStreamOpen(st, dataFD[1]) < 0) {
         qemuAuditDomainStart(vm, "migrated", false);
-        qemuProcessStop(driver, vm, 0);
+        qemuProcessStop(driver, vm, 0, VIR_DOMAIN_SHUTOFF_FAILED);
         if (!vm->persistent) {
             if (qemuDomainObjEndJob(vm) > 0)
                 virDomainRemoveInactive(&driver->domains, vm);
@@ -1047,8 +1047,9 @@ int qemuMigrationPerform(struct qemud_driver *driver,
     memset(&priv->jobInfo, 0, sizeof(priv->jobInfo));
     priv->jobInfo.type = VIR_DOMAIN_JOB_UNBOUNDED;
 
-    resume = vm->state == VIR_DOMAIN_RUNNING;
-    if (!(flags & VIR_MIGRATE_LIVE) && vm->state == VIR_DOMAIN_RUNNING) {
+    resume = virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING;
+    if (!(flags & VIR_MIGRATE_LIVE) &&
+        virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
         if (qemuMigrationSetOffline(driver, vm) < 0)
             goto endjob;
     }
@@ -1063,7 +1064,7 @@ int qemuMigrationPerform(struct qemud_driver *driver,
     }
 
     /* Clean up the source domain. */
-    qemuProcessStop(driver, vm, 1);
+    qemuProcessStop(driver, vm, 1, VIR_DOMAIN_SHUTOFF_MIGRATED);
     qemuAuditDomainStop(vm, "migrated");
     resume = 0;
 
@@ -1079,9 +1080,10 @@ int qemuMigrationPerform(struct qemud_driver *driver,
     ret = 0;
 
 endjob:
-    if (resume && vm->state == VIR_DOMAIN_PAUSED) {
+    if (resume && virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
         /* we got here through some sort of failure; start the domain again */
-        if (qemuProcessStartCPUs(driver, vm, conn) < 0) {
+        if (qemuProcessStartCPUs(driver, vm, conn,
+                                 VIR_DOMAIN_RUNNING_MIGRATION_CANCELED) < 0) {
             /* Hm, we already know we are in error here.  We don't want to
              * overwrite the previous error, though, so we just throw something
              * to the logs and hope for the best
@@ -1220,7 +1222,8 @@ qemuMigrationFinish(struct qemud_driver *driver,
              * >= 0.10.6 to work properly.  This isn't strictly necessary on
              * older qemu's, but it also doesn't hurt anything there
              */
-            if (qemuProcessStartCPUs(driver, vm, dconn) < 0) {
+            if (qemuProcessStartCPUs(driver, vm, dconn,
+                                     VIR_DOMAIN_RUNNING_MIGRATED) < 0) {
                 if (virGetLastError() == NULL)
                     qemuReportError(VIR_ERR_INTERNAL_ERROR,
                                     "%s", _("resume operation failed"));
@@ -1231,7 +1234,8 @@ qemuMigrationFinish(struct qemud_driver *driver,
         event = virDomainEventNewFromObj(vm,
                                          VIR_DOMAIN_EVENT_RESUMED,
                                          VIR_DOMAIN_EVENT_RESUMED_MIGRATED);
-        if (vm->state == VIR_DOMAIN_PAUSED) {
+        if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
+            virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER);
             qemuDomainEventQueue(driver, event);
             event = virDomainEventNewFromObj(vm,
                                              VIR_DOMAIN_EVENT_SUSPENDED,
@@ -1242,7 +1246,7 @@ qemuMigrationFinish(struct qemud_driver *driver,
             goto endjob;
         }
     } else {
-        qemuProcessStop(driver, vm, 1);
+        qemuProcessStop(driver, vm, 1, VIR_DOMAIN_SHUTOFF_FAILED);
         qemuAuditDomainStop(vm, "failed");
         event = virDomainEventNewFromObj(vm,
                                          VIR_DOMAIN_EVENT_STOPPED,
index f745aead0a2c4e10b95895d483b966eedbc089a9..3beb666eacf68ce5695ed07f6bca7d009de176ea 100644 (file)
@@ -132,7 +132,10 @@ qemuProcessHandleMonitorEOF(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
                                      VIR_DOMAIN_EVENT_STOPPED_FAILED :
                                      VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
 
-    qemuProcessStop(driver, vm, 0);
+    qemuProcessStop(driver, vm, 0,
+                    hasError ?
+                    VIR_DOMAIN_SHUTOFF_CRASHED :
+                    VIR_DOMAIN_SHUTOFF_SHUTDOWN);
     qemuAuditDomainStop(vm, hasError ? "failed" : "shutdown");
 
     if (!vm->persistent)
@@ -340,11 +343,11 @@ qemuProcessHandleStop(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
     virDomainEventPtr event = NULL;
 
     virDomainObjLock(vm);
-    if (vm->state == VIR_DOMAIN_RUNNING) {
+    if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
         VIR_DEBUG("Transitioned guest %s to paused state due to unknown event",
                   vm->def->name);
 
-        vm->state = VIR_DOMAIN_PAUSED;
+        virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_UNKNOWN);
         event = virDomainEventNewFromObj(vm,
                                          VIR_DOMAIN_EVENT_SUSPENDED,
                                          VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
@@ -409,10 +412,10 @@ qemuProcessHandleWatchdog(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
     watchdogEvent = virDomainEventWatchdogNewFromObj(vm, action);
 
     if (action == VIR_DOMAIN_EVENT_WATCHDOG_PAUSE &&
-        vm->state == VIR_DOMAIN_RUNNING) {
+        virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
         VIR_DEBUG("Transitioned guest %s to paused state due to watchdog", vm->def->name);
 
-        vm->state = VIR_DOMAIN_PAUSED;
+        virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_WATCHDOG);
         lifecycleEvent = virDomainEventNewFromObj(vm,
                                                   VIR_DOMAIN_EVENT_SUSPENDED,
                                                   VIR_DOMAIN_EVENT_SUSPENDED_WATCHDOG);
@@ -488,10 +491,10 @@ qemuProcessHandleIOError(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
     ioErrorEvent2 = virDomainEventIOErrorReasonNewFromObj(vm, srcPath, devAlias, action, reason);
 
     if (action == VIR_DOMAIN_EVENT_IO_ERROR_PAUSE &&
-        vm->state == VIR_DOMAIN_RUNNING) {
+        virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
         VIR_DEBUG("Transitioned guest %s to paused state due to IO error", vm->def->name);
 
-        vm->state = VIR_DOMAIN_PAUSED;
+        virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_IOERROR);
         lifecycleEvent = virDomainEventNewFromObj(vm,
                                                   VIR_DOMAIN_EVENT_SUSPENDED,
                                                   VIR_DOMAIN_EVENT_SUSPENDED_IOERROR);
@@ -1816,7 +1819,7 @@ qemuProcessPrepareMonitorChr(struct qemud_driver *driver,
 
 int
 qemuProcessStartCPUs(struct qemud_driver *driver, virDomainObjPtr vm,
-                     virConnectPtr conn)
+                     virConnectPtr conn, virDomainRunningReason reason)
 {
     int ret;
     qemuDomainObjPrivatePtr priv = vm->privateData;
@@ -1824,27 +1827,32 @@ qemuProcessStartCPUs(struct qemud_driver *driver, virDomainObjPtr vm,
     qemuDomainObjEnterMonitorWithDriver(driver, vm);
     ret = qemuMonitorStartCPUs(priv->mon, conn);
     qemuDomainObjExitMonitorWithDriver(driver, vm);
-    if (ret == 0) {
-        vm->state = VIR_DOMAIN_RUNNING;
-    }
+
+    if (ret == 0)
+        virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, reason);
 
     return ret;
 }
 
 
-int qemuProcessStopCPUs(struct qemud_driver *driver, virDomainObjPtr vm)
+int qemuProcessStopCPUs(struct qemud_driver *driver, virDomainObjPtr vm,
+                        virDomainPausedReason reason)
 {
     int ret;
-    int oldState = vm->state;
+    int oldState;
+    int oldReason;
     qemuDomainObjPrivatePtr priv = vm->privateData;
 
-    vm->state = VIR_DOMAIN_PAUSED;
+    oldState = virDomainObjGetState(vm, &oldReason);
+    virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, reason);
+
     qemuDomainObjEnterMonitorWithDriver(driver, vm);
     ret = qemuMonitorStopCPUs(priv->mon);
     qemuDomainObjExitMonitorWithDriver(driver, vm);
-    if (ret < 0) {
-        vm->state = oldState;
-    }
+
+    if (ret < 0)
+        virDomainObjSetState(vm, oldState, oldReason);
+
     return ret;
 }
 
@@ -1950,7 +1958,7 @@ error:
         /* We can't get the monitor back, so must kill the VM
          * to remove danger of it ending up running twice if
          * user tries to start it again later */
-        qemuProcessStop(driver, obj, 0);
+        qemuProcessStop(driver, obj, 0, VIR_DOMAIN_SHUTOFF_FAILED);
         if (!obj->persistent)
             virDomainRemoveInactive(&driver->domains, obj);
         else
@@ -2289,7 +2297,6 @@ int qemuProcessStart(virConnectPtr conn,
 
     if (migrateFrom)
         start_paused = true;
-    vm->state = start_paused ? VIR_DOMAIN_PAUSED : VIR_DOMAIN_RUNNING;
 
     if (ret == -1) /* The VM failed to start; tear filters before taps */
         virDomainConfVMNWFilterTeardown(vm);
@@ -2333,15 +2340,20 @@ int qemuProcessStart(virConnectPtr conn,
     if (!start_paused) {
         VIR_DEBUG("Starting domain CPUs");
         /* Allow the CPUS to start executing */
-        if (qemuProcessStartCPUs(driver, vm, conn) < 0) {
+        if (qemuProcessStartCPUs(driver, vm, conn,
+                                 VIR_DOMAIN_RUNNING_BOOTED) < 0) {
             if (virGetLastError() == NULL)
                 qemuReportError(VIR_ERR_INTERNAL_ERROR,
                                 "%s", _("resume operation failed"));
             goto cleanup;
         }
+    } else {
+        virDomainObjSetState(vm, VIR_DOMAIN_PAUSED,
+                             migrateFrom ?
+                             VIR_DOMAIN_PAUSED_MIGRATION :
+                             VIR_DOMAIN_PAUSED_USER);
     }
 
-
     VIR_DEBUG("Writing domain status to disk");
     if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
         goto cleanup;
@@ -2357,7 +2369,7 @@ cleanup:
      * pretend we never started it */
     virCommandFree(cmd);
     VIR_FORCE_CLOSE(logfile);
-    qemuProcessStop(driver, vm, 0);
+    qemuProcessStop(driver, vm, 0, VIR_DOMAIN_SHUTOFF_FAILED);
 
     return -1;
 }
@@ -2405,7 +2417,8 @@ void qemuProcessKill(virDomainObjPtr vm)
 
 void qemuProcessStop(struct qemud_driver *driver,
                      virDomainObjPtr vm,
-                     int migrated)
+                     int migrated,
+                     virDomainShutoffReason reason)
 {
     int ret;
     int retries = 0;
@@ -2556,7 +2569,7 @@ retry:
     vm->taint = 0;
     vm->pid = -1;
     vm->def->id = -1;
-    vm->state = VIR_DOMAIN_SHUTOFF;
+    virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, reason);
     VIR_FREE(priv->vcpupids);
     priv->nvcpupids = 0;
     qemuCapsFree(priv->qemuCaps);
index d8afab0f189d25557f875d8d6cb2a30cb6fba7f2..7ec9d7d70d0d51a807e49921124cc900387fc496 100644 (file)
@@ -28,8 +28,13 @@ int qemuProcessPrepareMonitorChr(struct qemud_driver *driver,
                                  virDomainChrSourceDefPtr monConfig,
                                  const char *vm);
 
-int qemuProcessStartCPUs(struct qemud_driver *driver, virDomainObjPtr vm, virConnectPtr conn);
-int qemuProcessStopCPUs(struct qemud_driver *driver, virDomainObjPtr vm);
+int qemuProcessStartCPUs(struct qemud_driver *driver,
+                         virDomainObjPtr vm,
+                         virConnectPtr conn,
+                         virDomainRunningReason reason);
+int qemuProcessStopCPUs(struct qemud_driver *driver,
+                        virDomainObjPtr vm,
+                        virDomainPausedReason reason);
 
 void qemuProcessAutostartAll(struct qemud_driver *driver);
 void qemuProcessReconnectAll(virConnectPtr conn, struct qemud_driver *driver);
@@ -47,7 +52,8 @@ int qemuProcessStart(virConnectPtr conn,
 
 void qemuProcessStop(struct qemud_driver *driver,
                      virDomainObjPtr vm,
-                     int migrated);
+                     int migrated,
+                     virDomainShutoffReason reason);
 
 void qemuProcessKill(virDomainObjPtr vm);
 
index ab74ef5674e31640476b48a49df587a82fb86d5e..a9c9846ce8a49b3c8ca3d0d220c4d3485eb2d5b4 100644 (file)
@@ -454,7 +454,8 @@ cleanup:
 
 static void
 testDomainShutdownState(virDomainPtr domain,
-                        virDomainObjPtr privdom)
+                        virDomainObjPtr privdom,
+                        virDomainShutoffReason reason)
 {
     if (privdom->newDef) {
         virDomainDefFree(privdom->def);
@@ -462,7 +463,7 @@ testDomainShutdownState(virDomainPtr domain,
         privdom->newDef = NULL;
     }
 
-    privdom->state = VIR_DOMAIN_SHUTOFF;
+    virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF, reason);
     privdom->def->id = -1;
     if (domain)
         domain->id = -1;
@@ -471,7 +472,8 @@ testDomainShutdownState(virDomainPtr domain,
 /* Set up domain runtime state */
 static int
 testDomainStartState(virConnectPtr conn,
-                     virDomainObjPtr dom)
+                     virDomainObjPtr dom,
+                     virDomainRunningReason reason)
 {
     testConnPtr privconn = conn->privateData;
     int ret = -1;
@@ -479,7 +481,7 @@ testDomainStartState(virConnectPtr conn,
     if (testDomainUpdateVCPUs(conn, dom, dom->def->vcpus, 1) < 0)
         goto cleanup;
 
-    dom->state = VIR_DOMAIN_RUNNING;
+    virDomainObjSetState(dom, VIR_DOMAIN_RUNNING, reason);
     dom->def->id = privconn->nextDomID++;
 
     if (virDomainObjSetDefTransient(privconn->caps, dom, false) < 0) {
@@ -489,7 +491,7 @@ testDomainStartState(virConnectPtr conn,
     ret = 0;
 cleanup:
     if (ret < 0)
-        testDomainShutdownState(NULL, dom);
+        testDomainShutdownState(NULL, dom, VIR_DOMAIN_SHUTOFF_FAILED);
     return ret;
 }
 
@@ -560,7 +562,7 @@ static int testOpenDefault(virConnectPtr conn) {
     domdef = NULL;
 
     domobj->persistent = 1;
-    if (testDomainStartState(conn, domobj) < 0) {
+    if (testDomainStartState(conn, domobj, VIR_DOMAIN_RUNNING_BOOTED) < 0) {
         virDomainObjUnlock(domobj);
         goto error;
     }
@@ -905,7 +907,7 @@ static int testOpenFromFile(virConnectPtr conn,
         }
 
         dom->persistent = 1;
-        if (testDomainStartState(conn, dom) < 0) {
+        if (testDomainStartState(conn, dom, VIR_DOMAIN_RUNNING_BOOTED) < 0) {
             virDomainObjUnlock(dom);
             goto error;
         }
@@ -1297,7 +1299,7 @@ testDomainCreateXML(virConnectPtr conn, const char *xml,
         goto cleanup;
     def = NULL;
 
-    if (testDomainStartState(conn, dom) < 0)
+    if (testDomainStartState(conn, dom, VIR_DOMAIN_RUNNING_BOOTED) < 0)
         goto cleanup;
 
     event = virDomainEventNewFromObj(dom,
@@ -1427,7 +1429,7 @@ static int testDestroyDomain (virDomainPtr domain)
         goto cleanup;
     }
 
-    testDomainShutdownState(domain, privdom);
+    testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_DESTROYED);
     event = virDomainEventNewFromObj(privdom,
                                      VIR_DOMAIN_EVENT_STOPPED,
                                      VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
@@ -1465,13 +1467,14 @@ static int testResumeDomain (virDomainPtr domain)
         goto cleanup;
     }
 
-    if (privdom->state != VIR_DOMAIN_PAUSED) {
+    if (virDomainObjGetState(privdom, NULL) != VIR_DOMAIN_PAUSED) {
         testError(VIR_ERR_INTERNAL_ERROR, _("domain '%s' not paused"),
                   domain->name);
         goto cleanup;
     }
 
-    privdom->state = VIR_DOMAIN_RUNNING;
+    virDomainObjSetState(privdom, VIR_DOMAIN_RUNNING,
+                         VIR_DOMAIN_RUNNING_UNPAUSED);
     event = virDomainEventNewFromObj(privdom,
                                      VIR_DOMAIN_EVENT_RESUMED,
                                      VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
@@ -1494,6 +1497,7 @@ static int testPauseDomain (virDomainPtr domain)
     virDomainObjPtr privdom;
     virDomainEventPtr event = NULL;
     int ret = -1;
+    int state;
 
     testDriverLock(privconn);
     privdom = virDomainFindByName(&privconn->domains,
@@ -1505,14 +1509,14 @@ static int testPauseDomain (virDomainPtr domain)
         goto cleanup;
     }
 
-    if (privdom->state == VIR_DOMAIN_SHUTOFF ||
-        privdom->state == VIR_DOMAIN_PAUSED) {
+    state = virDomainObjGetState(privdom, NULL);
+    if (state == VIR_DOMAIN_SHUTOFF || state == VIR_DOMAIN_PAUSED) {
         testError(VIR_ERR_INTERNAL_ERROR, _("domain '%s' not running"),
                   domain->name);
         goto cleanup;
     }
 
-    privdom->state = VIR_DOMAIN_PAUSED;
+    virDomainObjSetState(privdom, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER);
     event = virDomainEventNewFromObj(privdom,
                                      VIR_DOMAIN_EVENT_SUSPENDED,
                                      VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
@@ -1546,13 +1550,13 @@ static int testShutdownDomain (virDomainPtr domain)
         goto cleanup;
     }
 
-    if (privdom->state == VIR_DOMAIN_SHUTOFF) {
+    if (virDomainObjGetState(privdom, NULL) == VIR_DOMAIN_SHUTOFF) {
         testError(VIR_ERR_INTERNAL_ERROR,
                   _("domain '%s' not running"), domain->name);
         goto cleanup;
     }
 
-    testDomainShutdownState(domain, privdom);
+    testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
     event = virDomainEventNewFromObj(privdom,
                                      VIR_DOMAIN_EVENT_STOPPED,
                                      VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
@@ -1591,31 +1595,38 @@ static int testRebootDomain (virDomainPtr domain,
         goto cleanup;
     }
 
-    privdom->state = VIR_DOMAIN_SHUTDOWN;
+    virDomainObjSetState(privdom, VIR_DOMAIN_SHUTDOWN,
+                         VIR_DOMAIN_SHUTDOWN_USER);
+
     switch (privdom->def->onReboot) {
     case VIR_DOMAIN_LIFECYCLE_DESTROY:
-        privdom->state = VIR_DOMAIN_SHUTOFF;
+        virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF,
+                             VIR_DOMAIN_SHUTOFF_SHUTDOWN);
         break;
 
     case VIR_DOMAIN_LIFECYCLE_RESTART:
-        privdom->state = VIR_DOMAIN_RUNNING;
+        virDomainObjSetState(privdom, VIR_DOMAIN_RUNNING,
+                             VIR_DOMAIN_RUNNING_BOOTED);
         break;
 
     case VIR_DOMAIN_LIFECYCLE_PRESERVE:
-        privdom->state = VIR_DOMAIN_SHUTOFF;
+        virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF,
+                             VIR_DOMAIN_SHUTOFF_SHUTDOWN);
         break;
 
     case VIR_DOMAIN_LIFECYCLE_RESTART_RENAME:
-        privdom->state = VIR_DOMAIN_RUNNING;
+        virDomainObjSetState(privdom, VIR_DOMAIN_RUNNING,
+                             VIR_DOMAIN_RUNNING_BOOTED);
         break;
 
     default:
-        privdom->state = VIR_DOMAIN_SHUTOFF;
+        virDomainObjSetState(privdom, VIR_DOMAIN_SHUTOFF,
+                             VIR_DOMAIN_SHUTOFF_SHUTDOWN);
         break;
     }
 
-    if (privdom->state == VIR_DOMAIN_SHUTOFF) {
-        testDomainShutdownState(domain, privdom);
+    if (virDomainObjGetState(privdom, NULL) == VIR_DOMAIN_SHUTOFF) {
+        testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
         event = virDomainEventNewFromObj(privdom,
                                          VIR_DOMAIN_EVENT_STOPPED,
                                          VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
@@ -1661,7 +1672,7 @@ static int testGetDomainInfo (virDomainPtr domain,
         goto cleanup;
     }
 
-    info->state = privdom->state;
+    info->state = virDomainObjGetState(privdom, NULL);
     info->memory = privdom->def->mem.cur_balloon;
     info->maxMem = privdom->def->mem.max_balloon;
     info->nrVirtCpu = privdom->def->vcpus;
@@ -1696,10 +1707,7 @@ testDomainGetState(virDomainPtr domain,
         goto cleanup;
     }
 
-    *state = privdom->state;
-    if (reason)
-        *reason = 0;
-
+    *state = virDomainObjGetState(privdom, reason);
     ret = 0;
 
 cleanup:
@@ -1774,7 +1782,7 @@ static int testDomainSave(virDomainPtr domain,
     }
     fd = -1;
 
-    testDomainShutdownState(domain, privdom);
+    testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_SAVED);
     event = virDomainEventNewFromObj(privdom,
                                      VIR_DOMAIN_EVENT_STOPPED,
                                      VIR_DOMAIN_EVENT_STOPPED_SAVED);
@@ -1872,7 +1880,7 @@ static int testDomainRestore(virConnectPtr conn,
         goto cleanup;
     def = NULL;
 
-    if (testDomainStartState(conn, dom) < 0)
+    if (testDomainStartState(conn, dom, VIR_DOMAIN_RUNNING_RESTORED) < 0)
         goto cleanup;
 
     event = virDomainEventNewFromObj(dom,
@@ -1931,7 +1939,7 @@ static int testDomainCoreDump(virDomainPtr domain,
     }
 
     if (flags & VIR_DUMP_CRASH) {
-        testDomainShutdownState(domain, privdom);
+        testDomainShutdownState(domain, privdom, VIR_DOMAIN_SHUTOFF_CRASHED);
         event = virDomainEventNewFromObj(privdom,
                                          VIR_DOMAIN_EVENT_STOPPED,
                                          VIR_DOMAIN_EVENT_STOPPED_CRASHED);
@@ -2484,13 +2492,14 @@ static int testDomainCreateWithFlags(virDomainPtr domain, unsigned int flags) {
         goto cleanup;
     }
 
-    if (privdom->state != VIR_DOMAIN_SHUTOFF) {
+    if (virDomainObjGetState(privdom, NULL) != VIR_DOMAIN_SHUTOFF) {
         testError(VIR_ERR_INTERNAL_ERROR,
                   _("Domain '%s' is already running"), domain->name);
         goto cleanup;
     }
 
-    if (testDomainStartState(domain->conn, privdom) < 0)
+    if (testDomainStartState(domain->conn, privdom,
+                             VIR_DOMAIN_RUNNING_BOOTED) < 0)
         goto cleanup;
     domain->id = privdom->def->id;
 
@@ -2527,13 +2536,12 @@ static int testDomainUndefine(virDomainPtr domain) {
         goto cleanup;
     }
 
-    if (privdom->state != VIR_DOMAIN_SHUTOFF) {
+    if (virDomainObjGetState(privdom, NULL) != VIR_DOMAIN_SHUTOFF) {
         testError(VIR_ERR_INTERNAL_ERROR,
                   _("Domain '%s' is still running"), domain->name);
         goto cleanup;
     }
 
-    privdom->state = VIR_DOMAIN_SHUTOFF;
     event = virDomainEventNewFromObj(privdom,
                                      VIR_DOMAIN_EVENT_UNDEFINED,
                                      VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
index 3840d3467a1591b1d694d44f0c6bd8b1cb9085da..5a941fa2aabcbf488abde505eccf3d4d105a8cbd 100644 (file)
@@ -133,7 +133,8 @@ static int umlStartVMDaemon(virConnectPtr conn,
 
 static void umlShutdownVMDaemon(virConnectPtr conn,
                                 struct uml_driver *driver,
-                                virDomainObjPtr vm);
+                                virDomainObjPtr vm,
+                                virDomainShutoffReason reason);
 
 
 static int umlMonitorCommand(const struct uml_driver *driver,
@@ -305,7 +306,7 @@ reread:
                 continue;
             }
 
-            umlShutdownVMDaemon(NULL, driver, dom);
+            umlShutdownVMDaemon(NULL, driver, dom, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
         } else if (e->mask & (IN_CREATE | IN_MODIFY)) {
             VIR_DEBUG("Got inotify domain startup '%s'", name);
             if (virDomainObjIsActive(dom)) {
@@ -319,14 +320,17 @@ reread:
             }
 
             dom->def->id = driver->nextvmid++;
-            dom->state = VIR_DOMAIN_RUNNING;
+            virDomainObjSetState(dom, VIR_DOMAIN_RUNNING,
+                                 VIR_DOMAIN_RUNNING_BOOTED);
 
             if (umlOpenMonitor(driver, dom) < 0) {
                 VIR_WARN("Could not open monitor for new domain");
-                umlShutdownVMDaemon(NULL, driver, dom);
+                umlShutdownVMDaemon(NULL, driver, dom,
+                                    VIR_DOMAIN_SHUTOFF_FAILED);
             } else if (umlIdentifyChrPTY(driver, dom) < 0) {
                 VIR_WARN("Could not identify charater devices for new domain");
-                umlShutdownVMDaemon(NULL, driver, dom);
+                umlShutdownVMDaemon(NULL, driver, dom,
+                                    VIR_DOMAIN_SHUTOFF_FAILED);
             }
         }
         virDomainObjUnlock(dom);
@@ -515,7 +519,7 @@ umlShutdownOneVM(void *payload, const void *name ATTRIBUTE_UNUSED, void *opaque)
 
     virDomainObjLock(dom);
     if (virDomainObjIsActive(dom))
-        umlShutdownVMDaemon(NULL, driver, dom);
+        umlShutdownVMDaemon(NULL, driver, dom, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
     virDomainObjUnlock(dom);
 }
 
@@ -907,7 +911,8 @@ cleanup:
 
 static void umlShutdownVMDaemon(virConnectPtr conn ATTRIBUTE_UNUSED,
                                 struct uml_driver *driver ATTRIBUTE_UNUSED,
-                                virDomainObjPtr vm)
+                                virDomainObjPtr vm,
+                                virDomainShutoffReason reason)
 {
     int ret;
     umlDomainObjPrivatePtr priv = vm->privateData;
@@ -926,7 +931,7 @@ static void umlShutdownVMDaemon(virConnectPtr conn ATTRIBUTE_UNUSED,
 
     vm->pid = -1;
     vm->def->id = -1;
-    vm->state = VIR_DOMAIN_SHUTOFF;
+    virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, reason);
 
     virDomainConfVMNWFilterTeardown(vm);
     umlCleanupTapDevices(conn, vm);
@@ -1345,7 +1350,7 @@ static int umlDomainDestroy(virDomainPtr dom) {
         goto cleanup;
     }
 
-    umlShutdownVMDaemon(dom->conn, driver, vm);
+    umlShutdownVMDaemon(dom->conn, driver, vm, VIR_DOMAIN_SHUTOFF_DESTROYED);
     if (!vm->persistent) {
         virDomainRemoveInactive(&driver->domains,
                                 vm);
@@ -1498,7 +1503,7 @@ static int umlDomainGetInfo(virDomainPtr dom,
         goto cleanup;
     }
 
-    info->state = vm->state;
+    info->state = virDomainObjGetState(vm, NULL);
 
     if (!virDomainObjIsActive(vm)) {
         info->cpuTime = 0;
@@ -1544,10 +1549,7 @@ umlDomainGetState(virDomainPtr dom,
         goto cleanup;
     }
 
-    *state = vm->state;
-    if (reason)
-        *reason = 0;
-
+    *state = virDomainObjGetState(vm, reason);
     ret = 0;
 
 cleanup:
index 6339248a9ed709da625730d3473e8a4b94a535ad..4ec33aebde122a99d3668804fcc33ccda38c8dec 100644 (file)
@@ -185,7 +185,8 @@ vmwareLoadDomains(struct vmware_driver *driver)
         if ((vm->def->id = vmwareExtractPid(vmxPath)) < 0)
             goto cleanup;
         /* vmrun list only reports running vms */
-        vm->state = VIR_DOMAIN_RUNNING;
+        virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
+                             VIR_DOMAIN_RUNNING_UNKNOWN);
         vm->persistent = 1;
 
         virDomainObjUnlock(vm);
index 93ba5bdb8978e9419a8621c8eff194ffb6c10cd3..a086ca6647a41934299fa68f9b9c25fb201a495e 100644 (file)
@@ -178,7 +178,9 @@ vmwareGetVersion(virConnectPtr conn, unsigned long *version)
 }
 
 static int
-vmwareStopVM(struct vmware_driver *driver, virDomainObjPtr vm)
+vmwareStopVM(struct vmware_driver *driver,
+             virDomainObjPtr vm,
+             virDomainShutoffReason reason)
 {
     const char *cmd[] = {
         VMRUN, "-T", PROGRAM_SENTINAL, "stop",
@@ -193,7 +195,7 @@ vmwareStopVM(struct vmware_driver *driver, virDomainObjPtr vm)
     }
 
     vm->def->id = -1;
-    vm->state = VIR_DOMAIN_SHUTOFF;
+    virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, reason);
 
     return 0;
 }
@@ -207,7 +209,7 @@ vmwareStartVM(struct vmware_driver *driver, virDomainObjPtr vm)
     };
     const char *vmxPath = ((vmwareDomainPtr) vm->privateData)->vmxPath;
 
-    if (vm->state != VIR_DOMAIN_SHUTOFF) {
+    if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_SHUTOFF) {
         vmwareError(VIR_ERR_OPERATION_INVALID, "%s",
                     _("domain is not in shutoff state"));
         return -1;
@@ -225,11 +227,11 @@ vmwareStartVM(struct vmware_driver *driver, virDomainObjPtr vm)
     }
 
     if ((vm->def->id = vmwareExtractPid(vmxPath)) < 0) {
-        vmwareStopVM(driver, vm);
+        vmwareStopVM(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED);
         return -1;
     }
 
-    vm->state = VIR_DOMAIN_RUNNING;
+    virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_BOOTED);
 
     return 0;
 }
@@ -322,13 +324,13 @@ vmwareDomainShutdown(virDomainPtr dom)
         goto cleanup;
     }
 
-    if (vm->state != VIR_DOMAIN_RUNNING) {
+    if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_RUNNING) {
         vmwareError(VIR_ERR_INTERNAL_ERROR, "%s",
                     _("domain is not in running state"));
         goto cleanup;
     }
 
-    if (vmwareStopVM(driver, vm) < 0)
+    if (vmwareStopVM(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN) < 0)
         goto cleanup;
 
     if (!vm->persistent) {
@@ -375,7 +377,7 @@ vmwareDomainSuspend(virDomainPtr dom)
 
     vmwareSetSentinal(cmd, vmw_types[driver->type]);
     vmwareSetSentinal(cmd, ((vmwareDomainPtr) vm->privateData)->vmxPath);
-    if (vm->state != VIR_DOMAIN_RUNNING) {
+    if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_RUNNING) {
         vmwareError(VIR_ERR_INTERNAL_ERROR, "%s",
                     _("domain is not in running state"));
         goto cleanup;
@@ -384,7 +386,7 @@ vmwareDomainSuspend(virDomainPtr dom)
     if (virRun(cmd, NULL) < 0)
         goto cleanup;
 
-    vm->state = VIR_DOMAIN_PAUSED;
+    virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER);
     ret = 0;
 
   cleanup:
@@ -424,7 +426,7 @@ vmwareDomainResume(virDomainPtr dom)
 
     vmwareSetSentinal(cmd, vmw_types[driver->type]);
     vmwareSetSentinal(cmd, ((vmwareDomainPtr) vm->privateData)->vmxPath);
-    if (vm->state != VIR_DOMAIN_PAUSED) {
+    if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_PAUSED) {
         vmwareError(VIR_ERR_INTERNAL_ERROR, "%s",
                     _("domain is not in suspend state"));
         goto cleanup;
@@ -433,7 +435,7 @@ vmwareDomainResume(virDomainPtr dom)
     if (virRun(cmd, NULL) < 0)
         goto cleanup;
 
-    vm->state = VIR_DOMAIN_RUNNING;
+    virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_UNPAUSED);
     ret = 0;
 
   cleanup:
@@ -470,7 +472,7 @@ vmwareDomainReboot(virDomainPtr dom, unsigned int flags ATTRIBUTE_UNUSED)
     vmwareSetSentinal(cmd, vmxPath);
 
 
-    if (vm->state != VIR_DOMAIN_RUNNING) {
+    if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_RUNNING) {
         vmwareError(VIR_ERR_INTERNAL_ERROR, "%s",
                     _("domain is not in running state"));
         goto cleanup;
@@ -883,7 +885,7 @@ vmwareDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info)
         goto cleanup;
     }
 
-    info->state = vm->state;
+    info->state = virDomainObjGetState(vm, NULL);
     info->cpuTime = 0;
     info->maxMem = vm->def->mem.max_balloon;
     info->memory = vm->def->mem.cur_balloon;
@@ -918,10 +920,7 @@ vmwareDomainGetState(virDomainPtr dom,
         goto cleanup;
     }
 
-    *state = vm->state;
-    if (reason)
-        *reason = 0;
-
+    *state = virDomainObjGetState(vm, reason);
     ret = 0;
 
   cleanup: