[libvirt] [PATCH v2 8/9] Implement domain state reason
Daniel P. Berrange
berrange at redhat.com
Fri May 13 09:55:42 UTC 2011
On Tue, May 10, 2011 at 03:39:10PM +0200, Jiri Denemark wrote:
> 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.
> ---
> Notes:
> Version 2:
> - rebased
> - fixed || vs && typo
>
> src/conf/domain_conf.c | 163 ++++++++++++++++++++++++++++++++++++++++++-
> src/conf/domain_conf.h | 26 +++++++-
> src/libvirt_private.syms | 4 +
> src/libxl/libxl_driver.c | 53 ++++++++------
> src/lxc/lxc_driver.c | 52 ++++++++-------
> src/openvz/openvz_conf.c | 16 +++--
> src/openvz/openvz_driver.c | 29 ++++----
> src/qemu/qemu_driver.c | 66 ++++++++++--------
> src/qemu/qemu_migration.c | 24 ++++---
> src/qemu/qemu_process.c | 61 ++++++++++-------
> src/qemu/qemu_process.h | 12 +++-
> src/test/test_driver.c | 80 ++++++++++++----------
> src/uml/uml_driver.c | 30 ++++----
> src/vmware/vmware_conf.c | 3 +-
> src/vmware/vmware_driver.c | 33 ++++-----
> 15 files changed, 446 insertions(+), 206 deletions(-)
>
> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
> index d3efec6..bd7c64a 100644
> --- a/src/conf/domain_conf.c
> +++ b/src/conf/domain_conf.c
> @@ -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);
> @@ -6273,6 +6324,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;
> @@ -6296,7 +6349,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);
> @@ -6304,6 +6357,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"));
> @@ -8498,10 +8563,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++) {
> @@ -9604,3 +9673,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;
> +}
> diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
> index a0f820c..fe42f21 100644
> --- a/src/conf/domain_conf.h
> +++ b/src/conf/domain_conf.h
> @@ -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)
>
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index e2e706d..1209315 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -292,6 +292,7 @@ virDomainNetTypeToString;
> virDomainObjAssignDef;
> virDomainObjCopyPersistentDef;
> virDomainObjGetPersistentDef;
> +virDomainObjGetState;
> virDomainObjIsDuplicate;
> virDomainObjListDeinit;
> virDomainObjListGetActiveIDs;
> @@ -301,6 +302,7 @@ virDomainObjListNumOfDomains;
> virDomainObjLock;
> virDomainObjRef;
> virDomainObjSetDefTransient;
> +virDomainObjSetState;
> virDomainObjTaint;
> virDomainObjUnlock;
> virDomainObjUnref;
> @@ -324,6 +326,8 @@ virDomainSnapshotObjListRemove;
> virDomainSoundDefFree;
> virDomainSoundModelTypeFromString;
> virDomainSoundModelTypeToString;
> +virDomainStateReasonFromString;
> +virDomainStateReasonToString;
> virDomainStateTypeFromString;
> virDomainStateTypeToString;
> virDomainTaintTypeFromString;
> diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
> index 1fcf723..6962711 100644
> --- a/src/libxl/libxl_driver.c
> +++ b/src/libxl/libxl_driver.c
> @@ -245,7 +245,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;
> @@ -265,7 +267,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) &&
> @@ -302,7 +304,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;
>
> @@ -312,7 +317,7 @@ libxlVmReap(libxlDriverPrivatePtr driver, virDomainObjPtr vm, int force)
> return -1;
> }
>
> - libxlVmCleanup(driver, vm);
> + libxlVmCleanup(driver, vm, reason);
> return 0;
> }
>
> @@ -353,6 +358,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,
> @@ -366,18 +373,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:
> @@ -596,9 +607,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);
> }
>
>
> @@ -617,7 +628,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);
> @@ -662,7 +673,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);
> @@ -670,7 +681,7 @@ libxlReconnectDomain(void *payload,
> return;
>
> out:
> - libxlVmCleanup(driver, vm);
> + libxlVmCleanup(driver, vm, VIR_DOMAIN_SHUTOFF_UNKNOWN);
> if (!vm->persistent)
> virDomainRemoveInactive(&driver->domains, vm);
> else
> @@ -1213,7 +1224,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"),
> @@ -1221,7 +1232,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);
> @@ -1272,7 +1283,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"),
> @@ -1280,7 +1291,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);
> @@ -1413,7 +1425,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;
> @@ -1596,7 +1608,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;
> @@ -1629,10 +1641,7 @@ libxlDomainGetState(virDomainPtr dom,
> goto cleanup;
> }
>
> - *state = vm->state;
> - if (reason)
> - *reason = 0;
> -
> + *state = virDomainObjGetState(vm, reason);
> ret = 0;
>
> cleanup:
> diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
> index 2d57eb2..aab0c7f 100644
> --- a/src/lxc/lxc_driver.c
> +++ b/src/lxc/lxc_driver.c
> @@ -522,7 +522,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;
> @@ -588,10 +588,7 @@ lxcDomainGetState(virDomainPtr dom,
> goto cleanup;
> }
>
> - *state = vm->state;
> - if (reason)
> - *reason = 0;
> -
> + *state = virDomainObjGetState(vm, reason);
> ret = 0;
>
> cleanup:
> @@ -984,15 +981,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;
> @@ -1014,7 +1012,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;
> @@ -1198,7 +1196,8 @@ error:
>
>
> static int lxcVmTerminate(lxc_driver_t *driver,
> - virDomainObjPtr vm)
> + virDomainObjPtr vm,
> + virDomainShutoffReason reason)
> {
> virCgroupPtr group = NULL;
> int rc;
> @@ -1225,7 +1224,7 @@ static int lxcVmTerminate(lxc_driver_t *driver,
> rc = -1;
> goto cleanup;
> }
> - lxcVmCleanup(driver, vm);
> + lxcVmCleanup(driver, vm, reason);
>
> rc = 0;
>
> @@ -1255,7 +1254,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,
> @@ -1481,6 +1480,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
> *
> @@ -1488,7 +1488,8 @@ cleanup:
> */
> static int lxcVmStart(virConnectPtr conn,
> lxc_driver_t * driver,
> - virDomainObjPtr vm)
> + virDomainObjPtr vm,
> + virDomainRunningReason reason)
> {
> int rc = -1, r;
> unsigned int i;
> @@ -1588,14 +1589,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;
> }
>
> @@ -1668,7 +1669,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,
> @@ -1739,7 +1740,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;
> @@ -1930,7 +1931,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);
> @@ -1978,7 +1979,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"),
> @@ -2052,14 +2054,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 {
> @@ -2673,13 +2676,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,
> @@ -2738,13 +2741,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,
> diff --git a/src/openvz/openvz_conf.c b/src/openvz/openvz_conf.c
> index 88cd4c8..8c6261f 100644
> --- a/src/openvz/openvz_conf.c
> +++ b/src/openvz/openvz_conf.c
> @@ -484,14 +484,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;
>
> diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c
> index 3ab72e8..4ecaea7 100644
> --- a/src/openvz/openvz_driver.c
> +++ b/src/openvz/openvz_driver.c
> @@ -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);
> @@ -1022,7 +1021,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) {
> @@ -1064,7 +1063,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;
> @@ -1078,7 +1077,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:
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index a1617bc..1c5f439 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -1325,7 +1325,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;
> @@ -1341,8 +1341,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,
> @@ -1394,8 +1394,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"));
> @@ -1491,7 +1492,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);
> @@ -1725,7 +1726,7 @@ static int qemudDomainGetInfo(virDomainPtr dom,
> goto cleanup;
> }
>
> - info->state = vm->state;
> + info->state = virDomainObjGetState(vm, NULL);
>
> if (!virDomainObjIsActive(vm)) {
> info->cpuTime = 0;
> @@ -1807,10 +1808,7 @@ qemuDomainGetState(virDomainPtr dom,
> goto cleanup;
> }
>
> - *state = vm->state;
> - if (reason)
> - *reason = 0;
> -
> + *state = virDomainObjGetState(vm, reason);
> ret = 0;
>
> cleanup:
> @@ -1936,9 +1934,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)) {
> @@ -2085,7 +2083,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,
> @@ -2101,7 +2099,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_WARN0("Unable to resume guest CPUs after save failure");
> }
> @@ -2413,11 +2412,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;
>
> @@ -2436,7 +2436,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,
> @@ -2447,7 +2447,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"));
> @@ -2513,7 +2514,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,
> @@ -3211,7 +3213,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"));
> @@ -6345,12 +6348,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;
> @@ -6367,7 +6370,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"));
> @@ -6417,7 +6421,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)) {
> @@ -6717,9 +6721,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,
> @@ -6738,7 +6746,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,
> @@ -6755,8 +6763,6 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
> goto endjob;
> }
>
> - vm->state = snap->def->state;
> -
> ret = 0;
>
> endjob:
> diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
> index 6738a53..b45beb7 100644
> --- a/src/qemu/qemu_migration.c
> +++ b/src/qemu/qemu_migration.c
> @@ -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,
> diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
> index bd7c932..f74122e 100644
> --- a/src/qemu/qemu_process.c
> +++ b/src/qemu/qemu_process.c
> @@ -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_DEBUG0("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_DEBUG0("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;
> }
> @@ -2365,7 +2377,8 @@ cleanup:
>
> void qemuProcessStop(struct qemud_driver *driver,
> virDomainObjPtr vm,
> - int migrated)
> + int migrated,
> + virDomainShutoffReason reason)
> {
> int ret;
> int retries = 0;
> @@ -2523,7 +2536,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);
> diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h
> index f1ab599..40b386d 100644
> --- a/src/qemu/qemu_process.h
> +++ b/src/qemu/qemu_process.h
> @@ -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,6 +52,7 @@ int qemuProcessStart(virConnectPtr conn,
>
> void qemuProcessStop(struct qemud_driver *driver,
> virDomainObjPtr vm,
> - int migrated);
> + int migrated,
> + virDomainShutoffReason reason);
>
> #endif /* __QEMU_PROCESS_H__ */
> diff --git a/src/test/test_driver.c b/src/test/test_driver.c
> index 4ec2852..ca79309 100644
> --- a/src/test/test_driver.c
> +++ b/src/test/test_driver.c
> @@ -459,7 +459,8 @@ cleanup:
>
> static void
> testDomainShutdownState(virDomainPtr domain,
> - virDomainObjPtr privdom)
> + virDomainObjPtr privdom,
> + virDomainShutoffReason reason)
> {
> if (privdom->newDef) {
> virDomainDefFree(privdom->def);
> @@ -467,7 +468,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;
> @@ -476,7 +477,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;
> @@ -484,7 +486,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) {
> @@ -494,7 +496,7 @@ testDomainStartState(virConnectPtr conn,
> ret = 0;
> cleanup:
> if (ret < 0)
> - testDomainShutdownState(NULL, dom);
> + testDomainShutdownState(NULL, dom, VIR_DOMAIN_SHUTOFF_FAILED);
> return ret;
> }
>
> @@ -565,7 +567,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;
> }
> @@ -925,7 +927,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;
> }
> @@ -1327,7 +1329,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,
> @@ -1457,7 +1459,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);
> @@ -1495,13 +1497,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);
> @@ -1523,6 +1526,7 @@ static int testPauseDomain (virDomainPtr domain)
> testConnPtr privconn = domain->conn->privateData;
> virDomainObjPtr privdom;
> virDomainEventPtr event = NULL;
> + int state;
> int ret = -1;
>
> testDriverLock(privconn);
> @@ -1535,14 +1539,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);
> @@ -1576,13 +1580,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);
> @@ -1621,31 +1625,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);
> @@ -1691,7 +1702,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;
> @@ -1726,10 +1737,7 @@ testDomainGetState(virDomainPtr domain,
> goto cleanup;
> }
>
> - *state = privdom->state;
> - if (reason)
> - *reason = 0;
> -
> + *state = virDomainObjGetState(privdom, reason);
> ret = 0;
>
> cleanup:
> @@ -1804,7 +1812,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);
> @@ -1902,7 +1910,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,
> @@ -1961,7 +1969,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);
> @@ -2514,13 +2522,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;
>
> @@ -2557,13 +2566,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);
> diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c
> index e6fe019..eebf4af 100644
> --- a/src/uml/uml_driver.c
> +++ b/src/uml/uml_driver.c
> @@ -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_WARN0("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_WARN0("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:
> diff --git a/src/vmware/vmware_conf.c b/src/vmware/vmware_conf.c
> index 6339248..4ec33ae 100644
> --- a/src/vmware/vmware_conf.c
> +++ b/src/vmware/vmware_conf.c
> @@ -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);
> diff --git a/src/vmware/vmware_driver.c b/src/vmware/vmware_driver.c
> index 743e136..bd3771d 100644
> --- a/src/vmware/vmware_driver.c
> +++ b/src/vmware/vmware_driver.c
> @@ -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:
ACK
Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
More information about the libvir-list
mailing list