[libvirt] [PATCH v2 0/9] Introduce virDomainGetState API

This new API solves several problems: - calling virDomainGetInfo for just getting domain status is an overkill since it may result in sending requests to guest OS - since virDomainGetInfo can hang when guest OS is not responding and it is used by virsh list, listing domains can hang - virDomainGetState provides additional info about what action led to domain's current state, which can be used instead of listening to domain events Version 2: - rebased to current HEAD - unsigned int flags parameter - updated version info in public.syms - noGetState renamed as useGetInfo in virsh.c - simplified implementation in esx driver per Matthias' suggestion - call internal xen drivers directly instead of going through xenUnifiedDriver - fixed || vs && typo in domain_conf.c - new patch 9/9: qemu: Update domain state when reconnecting monitor Jiri Denemark (9): virDomainGetState public API Internal driver API for virDomainGetState virDomainGetState public API implementation Wire protocol format and dispatcher for virDomainGetState virsh: Prefer virDomainGetState over virDomainGetInfo remote: Implement virDomainGetState Implement basic virDomainGetState in all drivers Implement domain state reason qemu: Update domain state when reconnecting monitor daemon/remote.c | 33 +++++++ daemon/remote_generator.pl | 6 +- include/libvirt/libvirt.h.in | 56 +++++++++++ python/generator.py | 1 + python/libvirt-override-api.xml | 6 + python/libvirt-override.c | 30 ++++++ src/conf/domain_conf.c | 163 +++++++++++++++++++++++++++++++- src/conf/domain_conf.h | 26 +++++- src/driver.h | 6 + src/esx/esx_driver.c | 44 +++++++++ src/libvirt.c | 51 ++++++++++ src/libvirt_private.syms | 4 + src/libvirt_public.syms | 5 + src/libxl/libxl_driver.c | 80 ++++++++++++---- src/lxc/lxc_driver.c | 81 ++++++++++++---- src/openvz/openvz_conf.c | 16 ++- src/openvz/openvz_driver.c | 57 +++++++++-- src/phyp/phyp_driver.c | 16 +++ src/qemu/qemu_driver.c | 95 ++++++++++++++----- src/qemu/qemu_migration.c | 24 +++-- src/qemu/qemu_monitor.c | 20 ++++ src/qemu/qemu_monitor.h | 1 + src/qemu/qemu_monitor_json.c | 42 +++++++++ src/qemu/qemu_monitor_json.h | 1 + src/qemu/qemu_monitor_text.c | 30 ++++++ src/qemu/qemu_monitor_text.h | 1 + src/qemu/qemu_process.c | 99 +++++++++++++++----- src/qemu/qemu_process.h | 12 ++- src/remote/remote_driver.c | 34 +++++++ src/remote/remote_protocol.x | 13 +++- src/remote_protocol-structs | 8 ++ src/test/test_driver.c | 107 +++++++++++++++------- src/uml/uml_driver.c | 58 ++++++++++-- src/vbox/vbox_tmpl.c | 60 ++++++++++++ src/vmware/vmware_conf.c | 3 +- src/vmware/vmware_driver.c | 60 ++++++++++--- src/xen/xen_driver.c | 42 +++++++++ src/xen/xen_hypervisor.c | 36 +++++++ src/xen/xen_hypervisor.h | 5 + src/xen/xend_internal.c | 99 +++++++++++++++----- src/xen/xend_internal.h | 4 + src/xen/xm_internal.c | 20 ++++ src/xen/xm_internal.h | 4 + src/xen/xs_internal.c | 34 +++++++ src/xen/xs_internal.h | 4 + src/xenapi/xenapi_driver.c | 49 ++++++++++ tools/virsh.c | 195 ++++++++++++++++++++++++++++++++------- 47 files changed, 1603 insertions(+), 238 deletions(-) -- 1.7.5.rc3

This API is supposed to replace virDomainGetInfo when the only purpose of calling it is getting current domain status. --- Notes: Version 2: - rebased - unsigned int flags parameter - updated version info in public.syms include/libvirt/libvirt.h.in | 56 +++++++++++++++++++++++++++++++++++++++ python/generator.py | 1 + python/libvirt-override-api.xml | 6 ++++ python/libvirt-override.c | 30 +++++++++++++++++++++ src/libvirt_public.syms | 5 +++ 5 files changed, 98 insertions(+), 0 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 5783303..ee636c5 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -89,6 +89,58 @@ typedef enum { VIR_DOMAIN_CRASHED = 6 /* the domain is crashed */ } virDomainState; +typedef enum { + VIR_DOMAIN_NOSTATE_UNKNOWN = 0, +} virDomainNostateReason; + +typedef enum { + VIR_DOMAIN_RUNNING_UNKNOWN = 0, + VIR_DOMAIN_RUNNING_BOOTED = 1, /* normal startup from boot */ + VIR_DOMAIN_RUNNING_MIGRATED = 2, /* migrated from another host */ + VIR_DOMAIN_RUNNING_RESTORED = 3, /* restored from a state file */ + VIR_DOMAIN_RUNNING_FROM_SNAPSHOT = 4, /* restored from snapshot */ + VIR_DOMAIN_RUNNING_UNPAUSED = 5, /* returned from paused state */ + VIR_DOMAIN_RUNNING_MIGRATION_CANCELED = 6, /* returned from migration */ + VIR_DOMAIN_RUNNING_SAVE_CANCELED = 7, /* returned from failed save process */ +} virDomainRunningReason; + +typedef enum { + VIR_DOMAIN_BLOCKED_UNKNOWN = 0, /* the reason is unknown */ +} virDomainBlockedReason; + +typedef enum { + VIR_DOMAIN_PAUSED_UNKNOWN = 0, /* the reason is unknown */ + VIR_DOMAIN_PAUSED_USER = 1, /* paused on user request */ + VIR_DOMAIN_PAUSED_MIGRATION = 2, /* paused for offline migration */ + VIR_DOMAIN_PAUSED_SAVE = 3, /* paused for save */ + VIR_DOMAIN_PAUSED_DUMP = 4, /* paused for offline core dump */ + VIR_DOMAIN_PAUSED_IOERROR = 5, /* paused due to a disk I/O error */ + VIR_DOMAIN_PAUSED_WATCHDOG = 6, /* paused due to a watchdog event */ + VIR_DOMAIN_PAUSED_FROM_SNAPSHOT = 7, /* restored from a snapshot which was + * taken while domain was paused */ +} virDomainPausedReason; + +typedef enum { + VIR_DOMAIN_SHUTDOWN_UNKNOWN = 0, /* the reason is unknown */ + VIR_DOMAIN_SHUTDOWN_USER = 1, /* shutting down on user request */ +} virDomainShutdownReason; + +typedef enum { + VIR_DOMAIN_SHUTOFF_UNKNOWN = 0, /* the reason is unknown */ + VIR_DOMAIN_SHUTOFF_SHUTDOWN = 1, /* normal shutdown */ + VIR_DOMAIN_SHUTOFF_DESTROYED = 2, /* forced poweroff */ + VIR_DOMAIN_SHUTOFF_CRASHED = 3, /* domain crashed */ + VIR_DOMAIN_SHUTOFF_MIGRATED = 4, /* migrated to another host */ + VIR_DOMAIN_SHUTOFF_SAVED = 5, /* saved to a file */ + VIR_DOMAIN_SHUTOFF_FAILED = 6, /* domain failed to start */ + VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT = 7, /* restored from a snapshot which was + * taken while domain was shutoff */ +} virDomainShutoffReason; + +typedef enum { + VIR_DOMAIN_CRASHED_UNKNOWN = 0, /* crashed for unknown reason */ +} virDomainCrashedReason; + /** * virDomainInfoPtr: * @@ -674,6 +726,10 @@ int virDomainCoreDump (virDomainPtr domain, */ int virDomainGetInfo (virDomainPtr domain, virDomainInfoPtr info); +int virDomainGetState (virDomainPtr domain, + int *state, + int *reason, + unsigned int flags); /* * Return scheduler type in effect 'sedf', 'credit', 'linux' diff --git a/python/generator.py b/python/generator.py index 4fa4f65..b395caf 100755 --- a/python/generator.py +++ b/python/generator.py @@ -293,6 +293,7 @@ skip_impl = ( 'virConnGetLastError', 'virGetLastError', 'virDomainGetInfo', + 'virDomainGetState', 'virDomainGetBlockInfo', 'virDomainGetJobInfo', 'virNodeGetInfo', diff --git a/python/libvirt-override-api.xml b/python/libvirt-override-api.xml index 54deeb5..ec08e69 100644 --- a/python/libvirt-override-api.xml +++ b/python/libvirt-override-api.xml @@ -48,6 +48,12 @@ <return type='int *' info='the list of information or None in case of error'/> <arg name='domain' type='virDomainPtr' info='a domain object'/> </function> + <function name='virDomainGetState' file='python'> + <info>Extract domain state.</info> + <return type='int *' info='the list containing state and reason or None in case of error'/> + <arg name='domain' type='virDomainPtr' info='a domain object'/> + <arg name='flags' type='unsigned int' info='additional flags'/> + </function> <function name='virDomainGetBlockInfo' file='python'> <info>Extract information about a domain block device size</info> <return type='int *' info='the list of information or None in case of error'/> diff --git a/python/libvirt-override.c b/python/libvirt-override.c index 4a9b432..11e1d0c 100644 --- a/python/libvirt-override.c +++ b/python/libvirt-override.c @@ -1068,6 +1068,35 @@ libvirt_virDomainGetInfo(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { } static PyObject * +libvirt_virDomainGetState(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) +{ + PyObject *py_retval; + int c_retval; + virDomainPtr domain; + PyObject *pyobj_domain; + int state; + int reason; + unsigned int flags; + + if (!PyArg_ParseTuple(args, (char *)"Oi:virDomainGetState", + &pyobj_domain, &flags)) + return NULL; + + domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); + + LIBVIRT_BEGIN_ALLOW_THREADS; + c_retval = virDomainGetState(domain, &state, &reason, flags); + LIBVIRT_END_ALLOW_THREADS; + if (c_retval < 0) + return VIR_PY_NONE; + + py_retval = PyList_New(2); + PyList_SetItem(py_retval, 0, libvirt_intWrap(state)); + PyList_SetItem(py_retval, 1, libvirt_intWrap(reason)); + return py_retval; +} + +static PyObject * libvirt_virDomainGetBlockInfo(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval; int c_retval; @@ -3527,6 +3556,7 @@ static PyMethodDef libvirtMethods[] = { {(char *) "virConnectDomainEventRegisterAny", libvirt_virConnectDomainEventRegisterAny, METH_VARARGS, NULL}, {(char *) "virConnectDomainEventDeregisterAny", libvirt_virConnectDomainEventDeregisterAny, METH_VARARGS, NULL}, {(char *) "virDomainGetInfo", libvirt_virDomainGetInfo, METH_VARARGS, NULL}, + {(char *) "virDomainGetState", libvirt_virDomainGetState, METH_VARARGS, NULL}, {(char *) "virDomainGetBlockInfo", libvirt_virDomainGetBlockInfo, METH_VARARGS, NULL}, {(char *) "virNodeGetInfo", libvirt_virNodeGetInfo, METH_VARARGS, NULL}, {(char *) "virDomainGetUUID", libvirt_virDomainGetUUID, METH_VARARGS, NULL}, diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index b4aed41..a11e347 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -436,4 +436,9 @@ LIBVIRT_0.9.0 { virStorageVolUpload; } LIBVIRT_0.8.8; +LIBVIRT_0.9.2 { + global: + virDomainGetState; +} LIBVIRT_0.9.0; + # .... define new API here using predicted next version number .... -- 1.7.5.rc3

On Tue, May 10, 2011 at 03:39:03PM +0200, Jiri Denemark wrote:
This API is supposed to replace virDomainGetInfo when the only purpose of calling it is getting current domain status. --- Notes: Version 2: - rebased - unsigned int flags parameter - updated version info in public.syms
include/libvirt/libvirt.h.in | 56 +++++++++++++++++++++++++++++++++++++++ python/generator.py | 1 + python/libvirt-override-api.xml | 6 ++++ python/libvirt-override.c | 30 +++++++++++++++++++++ src/libvirt_public.syms | 5 +++ 5 files changed, 98 insertions(+), 0 deletions(-)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 5783303..ee636c5 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -89,6 +89,58 @@ typedef enum { VIR_DOMAIN_CRASHED = 6 /* the domain is crashed */ } virDomainState;
+typedef enum { + VIR_DOMAIN_NOSTATE_UNKNOWN = 0, +} virDomainNostateReason; + +typedef enum { + VIR_DOMAIN_RUNNING_UNKNOWN = 0, + VIR_DOMAIN_RUNNING_BOOTED = 1, /* normal startup from boot */ + VIR_DOMAIN_RUNNING_MIGRATED = 2, /* migrated from another host */ + VIR_DOMAIN_RUNNING_RESTORED = 3, /* restored from a state file */ + VIR_DOMAIN_RUNNING_FROM_SNAPSHOT = 4, /* restored from snapshot */ + VIR_DOMAIN_RUNNING_UNPAUSED = 5, /* returned from paused state */ + VIR_DOMAIN_RUNNING_MIGRATION_CANCELED = 6, /* returned from migration */ + VIR_DOMAIN_RUNNING_SAVE_CANCELED = 7, /* returned from failed save process */ +} virDomainRunningReason; + +typedef enum { + VIR_DOMAIN_BLOCKED_UNKNOWN = 0, /* the reason is unknown */ +} virDomainBlockedReason; + +typedef enum { + VIR_DOMAIN_PAUSED_UNKNOWN = 0, /* the reason is unknown */ + VIR_DOMAIN_PAUSED_USER = 1, /* paused on user request */ + VIR_DOMAIN_PAUSED_MIGRATION = 2, /* paused for offline migration */ + VIR_DOMAIN_PAUSED_SAVE = 3, /* paused for save */ + VIR_DOMAIN_PAUSED_DUMP = 4, /* paused for offline core dump */ + VIR_DOMAIN_PAUSED_IOERROR = 5, /* paused due to a disk I/O error */ + VIR_DOMAIN_PAUSED_WATCHDOG = 6, /* paused due to a watchdog event */ + VIR_DOMAIN_PAUSED_FROM_SNAPSHOT = 7, /* restored from a snapshot which was + * taken while domain was paused */ +} virDomainPausedReason; + +typedef enum { + VIR_DOMAIN_SHUTDOWN_UNKNOWN = 0, /* the reason is unknown */ + VIR_DOMAIN_SHUTDOWN_USER = 1, /* shutting down on user request */ +} virDomainShutdownReason; + +typedef enum { + VIR_DOMAIN_SHUTOFF_UNKNOWN = 0, /* the reason is unknown */ + VIR_DOMAIN_SHUTOFF_SHUTDOWN = 1, /* normal shutdown */ + VIR_DOMAIN_SHUTOFF_DESTROYED = 2, /* forced poweroff */ + VIR_DOMAIN_SHUTOFF_CRASHED = 3, /* domain crashed */ + VIR_DOMAIN_SHUTOFF_MIGRATED = 4, /* migrated to another host */ + VIR_DOMAIN_SHUTOFF_SAVED = 5, /* saved to a file */ + VIR_DOMAIN_SHUTOFF_FAILED = 6, /* domain failed to start */ + VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT = 7, /* restored from a snapshot which was + * taken while domain was shutoff */ +} virDomainShutoffReason; + +typedef enum { + VIR_DOMAIN_CRASHED_UNKNOWN = 0, /* crashed for unknown reason */ +} virDomainCrashedReason; + /** * virDomainInfoPtr: * @@ -674,6 +726,10 @@ int virDomainCoreDump (virDomainPtr domain, */ int virDomainGetInfo (virDomainPtr domain, virDomainInfoPtr info); +int virDomainGetState (virDomainPtr domain, + int *state, + int *reason, + unsigned int flags);
/* * Return scheduler type in effect 'sedf', 'credit', 'linux' diff --git a/python/generator.py b/python/generator.py index 4fa4f65..b395caf 100755 --- a/python/generator.py +++ b/python/generator.py @@ -293,6 +293,7 @@ skip_impl = ( 'virConnGetLastError', 'virGetLastError', 'virDomainGetInfo', + 'virDomainGetState', 'virDomainGetBlockInfo', 'virDomainGetJobInfo', 'virNodeGetInfo', diff --git a/python/libvirt-override-api.xml b/python/libvirt-override-api.xml index 54deeb5..ec08e69 100644 --- a/python/libvirt-override-api.xml +++ b/python/libvirt-override-api.xml @@ -48,6 +48,12 @@ <return type='int *' info='the list of information or None in case of error'/> <arg name='domain' type='virDomainPtr' info='a domain object'/> </function> + <function name='virDomainGetState' file='python'> + <info>Extract domain state.</info> + <return type='int *' info='the list containing state and reason or None in case of error'/> + <arg name='domain' type='virDomainPtr' info='a domain object'/> + <arg name='flags' type='unsigned int' info='additional flags'/> + </function> <function name='virDomainGetBlockInfo' file='python'> <info>Extract information about a domain block device size</info> <return type='int *' info='the list of information or None in case of error'/> diff --git a/python/libvirt-override.c b/python/libvirt-override.c index 4a9b432..11e1d0c 100644 --- a/python/libvirt-override.c +++ b/python/libvirt-override.c @@ -1068,6 +1068,35 @@ libvirt_virDomainGetInfo(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { }
static PyObject * +libvirt_virDomainGetState(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) +{ + PyObject *py_retval; + int c_retval; + virDomainPtr domain; + PyObject *pyobj_domain; + int state; + int reason; + unsigned int flags; + + if (!PyArg_ParseTuple(args, (char *)"Oi:virDomainGetState", + &pyobj_domain, &flags)) + return NULL; + + domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); + + LIBVIRT_BEGIN_ALLOW_THREADS; + c_retval = virDomainGetState(domain, &state, &reason, flags); + LIBVIRT_END_ALLOW_THREADS; + if (c_retval < 0) + return VIR_PY_NONE; + + py_retval = PyList_New(2); + PyList_SetItem(py_retval, 0, libvirt_intWrap(state)); + PyList_SetItem(py_retval, 1, libvirt_intWrap(reason)); + return py_retval; +} + +static PyObject * libvirt_virDomainGetBlockInfo(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval; int c_retval; @@ -3527,6 +3556,7 @@ static PyMethodDef libvirtMethods[] = { {(char *) "virConnectDomainEventRegisterAny", libvirt_virConnectDomainEventRegisterAny, METH_VARARGS, NULL}, {(char *) "virConnectDomainEventDeregisterAny", libvirt_virConnectDomainEventDeregisterAny, METH_VARARGS, NULL}, {(char *) "virDomainGetInfo", libvirt_virDomainGetInfo, METH_VARARGS, NULL}, + {(char *) "virDomainGetState", libvirt_virDomainGetState, METH_VARARGS, NULL}, {(char *) "virDomainGetBlockInfo", libvirt_virDomainGetBlockInfo, METH_VARARGS, NULL}, {(char *) "virNodeGetInfo", libvirt_virNodeGetInfo, METH_VARARGS, NULL}, {(char *) "virDomainGetUUID", libvirt_virDomainGetUUID, METH_VARARGS, NULL}, diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index b4aed41..a11e347 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -436,4 +436,9 @@ LIBVIRT_0.9.0 { virStorageVolUpload; } LIBVIRT_0.8.8;
+LIBVIRT_0.9.2 { + global: + virDomainGetState; +} LIBVIRT_0.9.0; + # .... define new API here using predicted next version number ....
ACK, but needs a rebase for the InjectNMI command 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 :|

--- Notes: Version 2: - rebased - unsigned int flags parameter - avoid changing xenUnifiedDriver internal callback struct src/driver.h | 6 ++++++ src/esx/esx_driver.c | 1 + src/libxl/libxl_driver.c | 1 + src/lxc/lxc_driver.c | 1 + src/openvz/openvz_driver.c | 1 + src/phyp/phyp_driver.c | 1 + src/qemu/qemu_driver.c | 1 + src/remote/remote_driver.c | 1 + src/test/test_driver.c | 1 + src/uml/uml_driver.c | 1 + src/vbox/vbox_tmpl.c | 1 + src/vmware/vmware_driver.c | 1 + src/xen/xen_driver.c | 1 + src/xenapi/xenapi_driver.c | 1 + 14 files changed, 19 insertions(+), 0 deletions(-) diff --git a/src/driver.h b/src/driver.h index a8b79e6..ed9846a 100644 --- a/src/driver.h +++ b/src/driver.h @@ -166,6 +166,11 @@ typedef int (*virDrvDomainGetInfo) (virDomainPtr domain, virDomainInfoPtr info); typedef int + (*virDrvDomainGetState) (virDomainPtr domain, + int *state, + int *reason, + unsigned int flags); +typedef int (*virDrvDomainSave) (virDomainPtr domain, const char *to); typedef int @@ -563,6 +568,7 @@ struct _virDriver { virDrvDomainSetBlkioParameters domainSetBlkioParameters; virDrvDomainGetBlkioParameters domainGetBlkioParameters; virDrvDomainGetInfo domainGetInfo; + virDrvDomainGetState domainGetState; virDrvDomainSave domainSave; virDrvDomainRestore domainRestore; virDrvDomainCoreDump domainCoreDump; diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index 7933f11..ec2aaf9 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -4623,6 +4623,7 @@ static virDriver esxDriver = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ esxDomainGetInfo, /* domainGetInfo */ + NULL, /* domainGetState */ NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index a2c8467..794a9e7 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -2714,6 +2714,7 @@ static virDriver libxlDriver = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ libxlDomainGetInfo, /* domainGetInfo */ + NULL, /* domainGetState */ NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index b94941d..0dcaf4c 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -2829,6 +2829,7 @@ static virDriver lxcDriver = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ lxcDomainGetInfo, /* domainGetInfo */ + NULL, /* domainGetState */ NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c index 0bd007a..48a3aae 100644 --- a/src/openvz/openvz_driver.c +++ b/src/openvz/openvz_driver.c @@ -1591,6 +1591,7 @@ static virDriver openvzDriver = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ openvzDomainGetInfo, /* domainGetInfo */ + NULL, /* domainGetState */ NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index 30d4adf..abd3594 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -3752,6 +3752,7 @@ static virDriver phypDriver = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ phypDomainGetInfo, /* domainGetInfo */ + NULL, /* domainGetState */ NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 0fd0f10..92c7f9a 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -7116,6 +7116,7 @@ static virDriver qemuDriver = { qemuDomainSetBlkioParameters, /* domainSetBlkioParameters */ qemuDomainGetBlkioParameters, /* domainGetBlkioParameters */ qemudDomainGetInfo, /* domainGetInfo */ + NULL, /* domainGetState */ qemudDomainSave, /* domainSave */ qemuDomainRestore, /* domainRestore */ qemudDomainCoreDump, /* domainCoreDump */ diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index d076a90..90d95d6 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -6417,6 +6417,7 @@ static virDriver remote_driver = { remoteDomainSetBlkioParameters, /* domainSetBlkioParameters */ remoteDomainGetBlkioParameters, /* domainGetBlkioParameters */ remoteDomainGetInfo, /* domainGetInfo */ + NULL, /* domainGetState */ remoteDomainSave, /* domainSave */ remoteDomainRestore, /* domainRestore */ remoteDomainCoreDump, /* domainCoreDump */ diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 0978214..6f4ae75 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -5371,6 +5371,7 @@ static virDriver testDriver = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ testGetDomainInfo, /* domainGetInfo */ + NULL, /* domainGetState */ testDomainSave, /* domainSave */ testDomainRestore, /* domainRestore */ testDomainCoreDump, /* domainCoreDump */ diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c index 33849a0..6852a16 100644 --- a/src/uml/uml_driver.c +++ b/src/uml/uml_driver.c @@ -2177,6 +2177,7 @@ static virDriver umlDriver = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ umlDomainGetInfo, /* domainGetInfo */ + NULL, /* domainGetState */ NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 8241d34..d4a8924 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -8566,6 +8566,7 @@ virDriver NAME(Driver) = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ vboxDomainGetInfo, /* domainGetInfo */ + NULL, /* domainGetState */ vboxDomainSave, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ diff --git a/src/vmware/vmware_driver.c b/src/vmware/vmware_driver.c index bbfb1a4..c6c92c6 100644 --- a/src/vmware/vmware_driver.c +++ b/src/vmware/vmware_driver.c @@ -931,6 +931,7 @@ static virDriver vmwareDriver = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ vmwareDomainGetInfo, /* domainGetInfo */ + NULL, /* domainGetState */ NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c index dd94fbc..1646828 100644 --- a/src/xen/xen_driver.c +++ b/src/xen/xen_driver.c @@ -2132,6 +2132,7 @@ static virDriver xenUnifiedDriver = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ xenUnifiedDomainGetInfo, /* domainGetInfo */ + NULL, /* domainGetState */ xenUnifiedDomainSave, /* domainSave */ xenUnifiedDomainRestore, /* domainRestore */ xenUnifiedDomainCoreDump, /* domainCoreDump */ diff --git a/src/xenapi/xenapi_driver.c b/src/xenapi/xenapi_driver.c index 3fbdcc6..83417df 100644 --- a/src/xenapi/xenapi_driver.c +++ b/src/xenapi/xenapi_driver.c @@ -1813,6 +1813,7 @@ static virDriver xenapiDriver = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ xenapiDomainGetInfo, /* domainGetInfo */ + NULL, /* domainGetState */ NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ -- 1.7.5.rc3

On Tue, May 10, 2011 at 03:39:04PM +0200, Jiri Denemark wrote:
--- Notes: Version 2: - rebased - unsigned int flags parameter - avoid changing xenUnifiedDriver internal callback struct
src/driver.h | 6 ++++++ src/esx/esx_driver.c | 1 + src/libxl/libxl_driver.c | 1 + src/lxc/lxc_driver.c | 1 + src/openvz/openvz_driver.c | 1 + src/phyp/phyp_driver.c | 1 + src/qemu/qemu_driver.c | 1 + src/remote/remote_driver.c | 1 + src/test/test_driver.c | 1 + src/uml/uml_driver.c | 1 + src/vbox/vbox_tmpl.c | 1 + src/vmware/vmware_driver.c | 1 + src/xen/xen_driver.c | 1 + src/xenapi/xenapi_driver.c | 1 + 14 files changed, 19 insertions(+), 0 deletions(-)
diff --git a/src/driver.h b/src/driver.h index a8b79e6..ed9846a 100644 --- a/src/driver.h +++ b/src/driver.h @@ -166,6 +166,11 @@ typedef int (*virDrvDomainGetInfo) (virDomainPtr domain, virDomainInfoPtr info); typedef int + (*virDrvDomainGetState) (virDomainPtr domain, + int *state, + int *reason, + unsigned int flags); +typedef int (*virDrvDomainSave) (virDomainPtr domain, const char *to); typedef int @@ -563,6 +568,7 @@ struct _virDriver { virDrvDomainSetBlkioParameters domainSetBlkioParameters; virDrvDomainGetBlkioParameters domainGetBlkioParameters; virDrvDomainGetInfo domainGetInfo; + virDrvDomainGetState domainGetState; virDrvDomainSave domainSave; virDrvDomainRestore domainRestore; virDrvDomainCoreDump domainCoreDump; diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index 7933f11..ec2aaf9 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -4623,6 +4623,7 @@ static virDriver esxDriver = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ esxDomainGetInfo, /* domainGetInfo */ + NULL, /* domainGetState */ NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index a2c8467..794a9e7 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -2714,6 +2714,7 @@ static virDriver libxlDriver = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ libxlDomainGetInfo, /* domainGetInfo */ + NULL, /* domainGetState */ NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index b94941d..0dcaf4c 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -2829,6 +2829,7 @@ static virDriver lxcDriver = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ lxcDomainGetInfo, /* domainGetInfo */ + NULL, /* domainGetState */ NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c index 0bd007a..48a3aae 100644 --- a/src/openvz/openvz_driver.c +++ b/src/openvz/openvz_driver.c @@ -1591,6 +1591,7 @@ static virDriver openvzDriver = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ openvzDomainGetInfo, /* domainGetInfo */ + NULL, /* domainGetState */ NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index 30d4adf..abd3594 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -3752,6 +3752,7 @@ static virDriver phypDriver = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ phypDomainGetInfo, /* domainGetInfo */ + NULL, /* domainGetState */ NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 0fd0f10..92c7f9a 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -7116,6 +7116,7 @@ static virDriver qemuDriver = { qemuDomainSetBlkioParameters, /* domainSetBlkioParameters */ qemuDomainGetBlkioParameters, /* domainGetBlkioParameters */ qemudDomainGetInfo, /* domainGetInfo */ + NULL, /* domainGetState */ qemudDomainSave, /* domainSave */ qemuDomainRestore, /* domainRestore */ qemudDomainCoreDump, /* domainCoreDump */ diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index d076a90..90d95d6 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -6417,6 +6417,7 @@ static virDriver remote_driver = { remoteDomainSetBlkioParameters, /* domainSetBlkioParameters */ remoteDomainGetBlkioParameters, /* domainGetBlkioParameters */ remoteDomainGetInfo, /* domainGetInfo */ + NULL, /* domainGetState */ remoteDomainSave, /* domainSave */ remoteDomainRestore, /* domainRestore */ remoteDomainCoreDump, /* domainCoreDump */ diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 0978214..6f4ae75 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -5371,6 +5371,7 @@ static virDriver testDriver = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ testGetDomainInfo, /* domainGetInfo */ + NULL, /* domainGetState */ testDomainSave, /* domainSave */ testDomainRestore, /* domainRestore */ testDomainCoreDump, /* domainCoreDump */ diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c index 33849a0..6852a16 100644 --- a/src/uml/uml_driver.c +++ b/src/uml/uml_driver.c @@ -2177,6 +2177,7 @@ static virDriver umlDriver = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ umlDomainGetInfo, /* domainGetInfo */ + NULL, /* domainGetState */ NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 8241d34..d4a8924 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -8566,6 +8566,7 @@ virDriver NAME(Driver) = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ vboxDomainGetInfo, /* domainGetInfo */ + NULL, /* domainGetState */ vboxDomainSave, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ diff --git a/src/vmware/vmware_driver.c b/src/vmware/vmware_driver.c index bbfb1a4..c6c92c6 100644 --- a/src/vmware/vmware_driver.c +++ b/src/vmware/vmware_driver.c @@ -931,6 +931,7 @@ static virDriver vmwareDriver = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ vmwareDomainGetInfo, /* domainGetInfo */ + NULL, /* domainGetState */ NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c index dd94fbc..1646828 100644 --- a/src/xen/xen_driver.c +++ b/src/xen/xen_driver.c @@ -2132,6 +2132,7 @@ static virDriver xenUnifiedDriver = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ xenUnifiedDomainGetInfo, /* domainGetInfo */ + NULL, /* domainGetState */ xenUnifiedDomainSave, /* domainSave */ xenUnifiedDomainRestore, /* domainRestore */ xenUnifiedDomainCoreDump, /* domainCoreDump */ diff --git a/src/xenapi/xenapi_driver.c b/src/xenapi/xenapi_driver.c index 3fbdcc6..83417df 100644 --- a/src/xenapi/xenapi_driver.c +++ b/src/xenapi/xenapi_driver.c @@ -1813,6 +1813,7 @@ static virDriver xenapiDriver = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ xenapiDomainGetInfo, /* domainGetInfo */ + NULL, /* domainGetState */ NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */
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 :|

--- Notes: Version 2: - rebased - unsigned int flags src/libvirt.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 51 insertions(+), 0 deletions(-) diff --git a/src/libvirt.c b/src/libvirt.c index abacf85..571eb97 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -3172,6 +3172,57 @@ error: } /** + * virDomainGetState: + * @domain: a domain object + * @state: returned state of the domain (one of virDomainState) + * @reason: returned reason which led to @state (one of virDomain*Reason + * corresponding to the current state); it is allowed to be NULL + * @flags: additional flags, 0 for now. + * + * Extract domain state. Each state can be accompanied with a reason (if known) + * which led to the state. + * + * Returns 0 in case of success and -1 in case of failure. + */ +int +virDomainGetState(virDomainPtr domain, + int *state, + int *reason, + unsigned int flags) +{ + virConnectPtr conn; + + VIR_DOMAIN_DEBUG(domain, "state=%p, reason=%p", state, reason); + + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + if (!state) { + virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + + conn = domain->conn; + if (conn->driver->domainGetState) { + int ret; + ret = conn->driver->domainGetState(domain, state, reason, flags); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(domain->conn); + return -1; +} + +/** * virDomainGetXMLDesc: * @domain: a domain object * @flags: an OR'ed set of virDomainXMLFlags -- 1.7.5.rc3

On Tue, May 10, 2011 at 03:39:05PM +0200, Jiri Denemark wrote:
--- Notes: Version 2: - rebased - unsigned int flags
src/libvirt.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 51 insertions(+), 0 deletions(-)
diff --git a/src/libvirt.c b/src/libvirt.c index abacf85..571eb97 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -3172,6 +3172,57 @@ error: }
/** + * virDomainGetState: + * @domain: a domain object + * @state: returned state of the domain (one of virDomainState) + * @reason: returned reason which led to @state (one of virDomain*Reason + * corresponding to the current state); it is allowed to be NULL + * @flags: additional flags, 0 for now. + * + * Extract domain state. Each state can be accompanied with a reason (if known) + * which led to the state. + * + * Returns 0 in case of success and -1 in case of failure. + */ +int +virDomainGetState(virDomainPtr domain, + int *state, + int *reason, + unsigned int flags) +{ + virConnectPtr conn; + + VIR_DOMAIN_DEBUG(domain, "state=%p, reason=%p", state, reason); + + virResetLastError(); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + if (!state) { + virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + + conn = domain->conn; + if (conn->driver->domainGetState) { + int ret; + ret = conn->driver->domainGetState(domain, state, reason, flags); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(domain->conn); + return -1; +}
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 :|

--- Notes: Version 2: - rebased - unsigned int flags daemon/remote.c | 33 +++++++++++++++++++++++++++++++++ daemon/remote_generator.pl | 3 ++- src/remote/remote_protocol.x | 13 ++++++++++++- src/remote_protocol-structs | 8 ++++++++ 4 files changed, 55 insertions(+), 2 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index 2220655..598862a 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -2816,6 +2816,39 @@ cleanup: } static int +remoteDispatchDomainGetState(struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_get_state_args *args, + remote_domain_get_state_ret *ret) +{ + virDomainPtr dom = NULL; + int rv = -1; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if (virDomainGetState(dom, &ret->state, &ret->reason, args->flags) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} + +static int remoteDispatchDomainEventsRegisterAny(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, diff --git a/daemon/remote_generator.pl b/daemon/remote_generator.pl index 062ccc1..ff279d5 100755 --- a/daemon/remote_generator.pl +++ b/daemon/remote_generator.pl @@ -278,7 +278,8 @@ elsif ($opt_b) { "GetType", "NodeDeviceGetParent", "NodeGetSecurityModel", - "SecretGetValue"); + "SecretGetValue", + "DomainGetState"); } elsif ($structprefix eq "qemu") { @ungeneratable = ("MonitorCommand"); } diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index c706c36..078d7ed 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -1940,6 +1940,16 @@ struct remote_storage_vol_download_args { unsigned int flags; }; +struct remote_domain_get_state_args { + remote_nonnull_domain dom; + unsigned int flags; +}; + +struct remote_domain_get_state_ret { + int state; + int reason; +}; + /*----- Protocol. -----*/ @@ -2176,7 +2186,8 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_GET_BLKIO_PARAMETERS = 206, REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_SPEED = 207, REMOTE_PROC_STORAGE_VOL_UPLOAD = 208, - REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209 + REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209, + REMOTE_PROC_DOMAIN_GET_STATE = 210 /* * Notice how the entries are grouped in sets of 10 ? diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index f904c4d..ca1294f 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -1427,6 +1427,14 @@ struct remote_storage_vol_download_args { uint64_t length; u_int flags; }; +struct remote_domain_get_state_args { + remote_nonnull_domain dom; + u_int flags; +}; +struct remote_domain_get_state_ret { + int state; + int reason; +}; struct remote_message_header { u_int prog; u_int vers; -- 1.7.5.rc3

On Tue, May 10, 2011 at 03:39:06PM +0200, Jiri Denemark wrote:
--- Notes: Version 2: - rebased - unsigned int flags
daemon/remote.c | 33 +++++++++++++++++++++++++++++++++ daemon/remote_generator.pl | 3 ++- src/remote/remote_protocol.x | 13 ++++++++++++- src/remote_protocol-structs | 8 ++++++++ 4 files changed, 55 insertions(+), 2 deletions(-)
diff --git a/daemon/remote.c b/daemon/remote.c index 2220655..598862a 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -2816,6 +2816,39 @@ cleanup: }
static int +remoteDispatchDomainGetState(struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_get_state_args *args, + remote_domain_get_state_ret *ret) +{ + virDomainPtr dom = NULL; + int rv = -1; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if (virDomainGetState(dom, &ret->state, &ret->reason, args->flags) < 0) + goto cleanup; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + if (dom) + virDomainFree(dom); + return rv; +} + +static int remoteDispatchDomainEventsRegisterAny(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, virConnectPtr conn, diff --git a/daemon/remote_generator.pl b/daemon/remote_generator.pl index 062ccc1..ff279d5 100755 --- a/daemon/remote_generator.pl +++ b/daemon/remote_generator.pl @@ -278,7 +278,8 @@ elsif ($opt_b) { "GetType", "NodeDeviceGetParent", "NodeGetSecurityModel", - "SecretGetValue"); + "SecretGetValue", + "DomainGetState"); } elsif ($structprefix eq "qemu") { @ungeneratable = ("MonitorCommand"); }
Needs rebasing
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index c706c36..078d7ed 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -1940,6 +1940,16 @@ struct remote_storage_vol_download_args { unsigned int flags; };
+struct remote_domain_get_state_args { + remote_nonnull_domain dom; + unsigned int flags; +}; + +struct remote_domain_get_state_ret { + int state; + int reason; +}; +
/*----- Protocol. -----*/
@@ -2176,7 +2186,8 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_GET_BLKIO_PARAMETERS = 206, REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_SPEED = 207, REMOTE_PROC_STORAGE_VOL_UPLOAD = 208, - REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209 + REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209, + REMOTE_PROC_DOMAIN_GET_STATE = 210
Need to add annotations here.
/* * Notice how the entries are grouped in sets of 10 ? diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index f904c4d..ca1294f 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -1427,6 +1427,14 @@ struct remote_storage_vol_download_args { uint64_t length; u_int flags; }; +struct remote_domain_get_state_args { + remote_nonnull_domain dom; + u_int flags; +}; +struct remote_domain_get_state_ret { + int state; + int reason; +}; struct remote_message_header { u_int prog; u_int vers;
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 :|

--- Notes: Version 2: - rebased - unsigned int flags - noGetState renamed as useGetInfo tools/virsh.c | 195 +++++++++++++++++++++++++++++++++++++++++++++++---------- 1 files changed, 162 insertions(+), 33 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index 2b16714..4ece6ac 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -223,6 +223,8 @@ typedef struct __vshControl { int log_fd; /* log file descriptor */ char *historydir; /* readline history directory name */ char *historyfile; /* readline history file name */ + bool useGetInfo; /* must use virDomainGetInfo, since + virDomainGetState is not supported */ } __vshControl; typedef struct vshCmdGrp { @@ -334,7 +336,9 @@ static void vshDebug(vshControl *ctl, int level, const char *format, ...) /* XXX: add batch support */ #define vshPrint(_ctl, ...) vshPrintExtra(NULL, __VA_ARGS__) +static int vshDomainState(vshControl *ctl, virDomainPtr dom, int *reason); static const char *vshDomainStateToString(int state); +static const char *vshDomainStateReasonToString(int state, int reason); static const char *vshDomainVcpuStateToString(int state); static bool vshConnectionUsability(vshControl *ctl, virConnectPtr conn); @@ -571,6 +575,7 @@ vshReconnect(vshControl *ctl) { else vshError(ctl, "%s", _("Reconnected to the hypervisor")); disconnected = 0; + ctl->useGetInfo = false; } /* --------------- @@ -717,6 +722,7 @@ cmdConnect(vshControl *ctl, const vshCmd *cmd) } ctl->name = vshStrdup(ctl, name); + ctl->useGetInfo = false; ctl->readonly = ro; ctl->conn = virConnectOpenAuth(ctl->name, virConnectAuthPtrDefault, @@ -750,14 +756,14 @@ static bool cmdRunConsole(vshControl *ctl, virDomainPtr dom, const char *name) { bool ret = false; - virDomainInfo dominfo; + int state; - if (virDomainGetInfo(dom, &dominfo) < 0) { + if ((state = vshDomainState(ctl, dom, NULL)) < 0) { vshError(ctl, "%s", _("Unable to get domain status")); goto cleanup; } - if (dominfo.state == VIR_DOMAIN_SHUTOFF) { + if (state == VIR_DOMAIN_SHUTOFF) { vshError(ctl, "%s", _("The domain is not running")); goto cleanup; } @@ -872,29 +878,20 @@ cmdList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) vshPrintExtra(ctl, "----------------------------------\n"); for (i = 0; i < maxid; i++) { - virDomainInfo info; virDomainPtr dom = virDomainLookupByID(ctl->conn, ids[i]); - const char *state; /* this kind of work with domains is not atomic operation */ if (!dom) continue; - if (virDomainGetInfo(dom, &info) < 0) - state = _("no state"); - else - state = _(vshDomainStateToString(info.state)); - vshPrint(ctl, "%3d %-20s %s\n", virDomainGetID(dom), virDomainGetName(dom), - state); + vshDomainStateToString(vshDomainState(ctl, dom, NULL))); virDomainFree(dom); } for (i = 0; i < maxname; i++) { - virDomainInfo info; virDomainPtr dom = virDomainLookupByName(ctl->conn, names[i]); - const char *state; /* this kind of work with domains is not atomic operation */ if (!dom) { @@ -902,12 +899,10 @@ cmdList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) continue; } - if (virDomainGetInfo(dom, &info) < 0) - state = _("no state"); - else - state = _(vshDomainStateToString(info.state)); - - vshPrint(ctl, "%3s %-20s %s\n", "-", names[i], state); + vshPrint(ctl, "%3s %-20s %s\n", + "-", + names[i], + vshDomainStateToString(vshDomainState(ctl, dom, NULL))); virDomainFree(dom); VIR_FREE(names[i]); @@ -928,15 +923,17 @@ static const vshCmdInfo info_domstate[] = { static const vshCmdOptDef opts_domstate[] = { {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")}, + {"reason", VSH_OT_BOOL, 0, N_("also print reason for the state")}, {NULL, 0, 0, NULL} }; static bool cmdDomstate(vshControl *ctl, const vshCmd *cmd) { - virDomainInfo info; virDomainPtr dom; bool ret = true; + int showReason = vshCommandOptBool(cmd, "reason"); + int state, reason; if (!vshConnectionUsability(ctl, ctl->conn)) return false; @@ -944,12 +941,21 @@ cmdDomstate(vshControl *ctl, const vshCmd *cmd) if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) return false; - if (virDomainGetInfo(dom, &info) == 0) - vshPrint(ctl, "%s\n", - _(vshDomainStateToString(info.state))); - else + if ((state = vshDomainState(ctl, dom, &reason)) < 0) { ret = false; + goto cleanup; + } + + if (showReason) { + vshPrint(ctl, "%s (%s)\n", + _(vshDomainStateToString(state)), + vshDomainStateReasonToString(state, reason)); + } else { + vshPrint(ctl, "%s\n", + _(vshDomainStateToString(state))); + } +cleanup: virDomainFree(dom); return ret; } @@ -3023,7 +3029,6 @@ static bool cmdSetmaxmem(vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom; - virDomainInfo info; int kilobytes = 0; bool ret = true; int config = vshCommandOptBool(cmd, "config"); @@ -3063,12 +3068,6 @@ cmdSetmaxmem(vshControl *ctl, const vshCmd *cmd) return false; } - if (virDomainGetInfo(dom, &info) != 0) { - virDomainFree(dom); - vshError(ctl, "%s", _("Unable to verify current MemorySize")); - return false; - } - if (flags == -1) { if (virDomainSetMaxMemory(dom, kilobytes) != 0) { vshError(ctl, "%s", _("Unable to change MaxMemorySize")); @@ -12024,10 +12023,38 @@ vshCommandStringParse(vshControl *ctl, char *cmdstr) * Misc utils * --------------- */ +static int +vshDomainState(vshControl *ctl, virDomainPtr dom, int *reason) +{ + virDomainInfo info; + + if (reason) + *reason = -1; + + if (!ctl->useGetInfo) { + int state; + if (virDomainGetState(dom, &state, reason, 0) < 0) { + virErrorPtr err = virGetLastError(); + if (err && err->code == VIR_ERR_NO_SUPPORT) + ctl->useGetInfo = true; + else + return -1; + } else { + return state; + } + } + + /* fall back to virDomainGetInfo if virDomainGetState is not supported */ + if (virDomainGetInfo(dom, &info) < 0) + return -1; + else + return info.state; +} + static const char * vshDomainStateToString(int state) { - switch (state) { + switch ((virDomainState) state) { case VIR_DOMAIN_RUNNING: return N_("running"); case VIR_DOMAIN_BLOCKED: @@ -12040,13 +12067,114 @@ vshDomainStateToString(int state) return N_("shut off"); case VIR_DOMAIN_CRASHED: return N_("crashed"); - default: + case VIR_DOMAIN_NOSTATE: ;/*FALLTHROUGH*/ } return N_("no state"); /* = dom0 state */ } static const char * +vshDomainStateReasonToString(int state, int reason) +{ + switch ((virDomainState) state) { + case VIR_DOMAIN_NOSTATE: + switch ((virDomainNostateReason) reason) { + case VIR_DOMAIN_NOSTATE_UNKNOWN: + ; + } + break; + + case VIR_DOMAIN_RUNNING: + switch ((virDomainRunningReason) reason) { + case VIR_DOMAIN_RUNNING_BOOTED: + return N_("booted"); + case VIR_DOMAIN_RUNNING_MIGRATED: + return N_("migrated"); + case VIR_DOMAIN_RUNNING_RESTORED: + return N_("restored"); + case VIR_DOMAIN_RUNNING_FROM_SNAPSHOT: + return N_("from snapshot"); + case VIR_DOMAIN_RUNNING_UNPAUSED: + return N_("unpaused"); + case VIR_DOMAIN_RUNNING_MIGRATION_CANCELED: + return N_("migration canceled"); + case VIR_DOMAIN_RUNNING_SAVE_CANCELED: + return N_("save canceled"); + case VIR_DOMAIN_RUNNING_UNKNOWN: + ; + } + break; + + case VIR_DOMAIN_BLOCKED: + switch ((virDomainBlockedReason) reason) { + case VIR_DOMAIN_BLOCKED_UNKNOWN: + ; + } + break; + + case VIR_DOMAIN_PAUSED: + switch ((virDomainPausedReason) reason) { + case VIR_DOMAIN_PAUSED_USER: + return N_("user"); + case VIR_DOMAIN_PAUSED_MIGRATION: + return N_("migrating"); + case VIR_DOMAIN_PAUSED_SAVE: + return N_("saving"); + case VIR_DOMAIN_PAUSED_DUMP: + return N_("dumping"); + case VIR_DOMAIN_PAUSED_IOERROR: + return N_("I/O error"); + case VIR_DOMAIN_PAUSED_WATCHDOG: + return N_("watchdog"); + case VIR_DOMAIN_PAUSED_FROM_SNAPSHOT: + return N_("from snapshot"); + case VIR_DOMAIN_PAUSED_UNKNOWN: + ; + } + break; + + case VIR_DOMAIN_SHUTDOWN: + switch ((virDomainShutdownReason) reason) { + case VIR_DOMAIN_SHUTDOWN_USER: + return N_("user"); + case VIR_DOMAIN_SHUTDOWN_UNKNOWN: + ; + } + break; + + case VIR_DOMAIN_SHUTOFF: + switch ((virDomainShutoffReason) reason) { + case VIR_DOMAIN_SHUTOFF_SHUTDOWN: + return N_("shutdown"); + case VIR_DOMAIN_SHUTOFF_DESTROYED: + return N_("destroyed"); + case VIR_DOMAIN_SHUTOFF_CRASHED: + return N_("crashed"); + case VIR_DOMAIN_SHUTOFF_MIGRATED: + return N_("migrated"); + case VIR_DOMAIN_SHUTOFF_SAVED: + return N_("saved"); + case VIR_DOMAIN_SHUTOFF_FAILED: + return N_("failed"); + case VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT: + return N_("from snapshot"); + case VIR_DOMAIN_SHUTOFF_UNKNOWN: + ; + } + break; + + case VIR_DOMAIN_CRASHED: + switch ((virDomainCrashedReason) reason) { + case VIR_DOMAIN_CRASHED_UNKNOWN: + ; + } + break; + } + + return N_("unknown"); +} + +static const char * vshDomainVcpuStateToString(int state) { switch (state) { @@ -12144,6 +12272,7 @@ vshError(vshControl *ctl, const char *format, ...) VIR_FREE(str); } + /* * Initialize connection. */ -- 1.7.5.rc3

On Tue, May 10, 2011 at 15:39:07 +0200, Jiri Denemark wrote:
--- Notes: Version 2: - rebased - unsigned int flags - noGetState renamed as useGetInfo
tools/virsh.c | 195 +++++++++++++++++++++++++++++++++++++++++++++++---------- 1 files changed, 162 insertions(+), 33 deletions(-)
Man page update for domstate command is missing so the following patch needs to be squashed in 5/9: tools/virsh.pod | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/virsh.pod b/tools/virsh.pod index 2a708f6..66df3ae 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -426,9 +426,10 @@ Returns information about jobs running on a domain. Convert a domain Id (or UUID) to domain name -=item B<domstate> I<domain-id> +=item B<domstate> I<domain-id> optional I<--reason> -Returns state about a running domain. +Returns state about a domain. I<--reason> tells virsh to also print +reason for the state. =item B<domxml-from-native> I<format> I<config> -- Jirka

On Tue, May 10, 2011 at 03:39:07PM +0200, Jiri Denemark wrote:
--- Notes: Version 2: - rebased - unsigned int flags - noGetState renamed as useGetInfo
tools/virsh.c | 195 +++++++++++++++++++++++++++++++++++++++++++++++---------- 1 files changed, 162 insertions(+), 33 deletions(-)
diff --git a/tools/virsh.c b/tools/virsh.c index 2b16714..4ece6ac 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -223,6 +223,8 @@ typedef struct __vshControl { int log_fd; /* log file descriptor */ char *historydir; /* readline history directory name */ char *historyfile; /* readline history file name */ + bool useGetInfo; /* must use virDomainGetInfo, since + virDomainGetState is not supported */ } __vshControl;
typedef struct vshCmdGrp { @@ -334,7 +336,9 @@ static void vshDebug(vshControl *ctl, int level, const char *format, ...) /* XXX: add batch support */ #define vshPrint(_ctl, ...) vshPrintExtra(NULL, __VA_ARGS__)
+static int vshDomainState(vshControl *ctl, virDomainPtr dom, int *reason); static const char *vshDomainStateToString(int state); +static const char *vshDomainStateReasonToString(int state, int reason); static const char *vshDomainVcpuStateToString(int state); static bool vshConnectionUsability(vshControl *ctl, virConnectPtr conn);
@@ -571,6 +575,7 @@ vshReconnect(vshControl *ctl) { else vshError(ctl, "%s", _("Reconnected to the hypervisor")); disconnected = 0; + ctl->useGetInfo = false; }
/* --------------- @@ -717,6 +722,7 @@ cmdConnect(vshControl *ctl, const vshCmd *cmd) } ctl->name = vshStrdup(ctl, name);
+ ctl->useGetInfo = false; ctl->readonly = ro;
ctl->conn = virConnectOpenAuth(ctl->name, virConnectAuthPtrDefault, @@ -750,14 +756,14 @@ static bool cmdRunConsole(vshControl *ctl, virDomainPtr dom, const char *name) { bool ret = false; - virDomainInfo dominfo; + int state;
- if (virDomainGetInfo(dom, &dominfo) < 0) { + if ((state = vshDomainState(ctl, dom, NULL)) < 0) { vshError(ctl, "%s", _("Unable to get domain status")); goto cleanup; }
- if (dominfo.state == VIR_DOMAIN_SHUTOFF) { + if (state == VIR_DOMAIN_SHUTOFF) { vshError(ctl, "%s", _("The domain is not running")); goto cleanup; } @@ -872,29 +878,20 @@ cmdList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) vshPrintExtra(ctl, "----------------------------------\n");
for (i = 0; i < maxid; i++) { - virDomainInfo info; virDomainPtr dom = virDomainLookupByID(ctl->conn, ids[i]); - const char *state;
/* this kind of work with domains is not atomic operation */ if (!dom) continue;
- if (virDomainGetInfo(dom, &info) < 0) - state = _("no state"); - else - state = _(vshDomainStateToString(info.state)); - vshPrint(ctl, "%3d %-20s %s\n", virDomainGetID(dom), virDomainGetName(dom), - state); + vshDomainStateToString(vshDomainState(ctl, dom, NULL))); virDomainFree(dom); } for (i = 0; i < maxname; i++) { - virDomainInfo info; virDomainPtr dom = virDomainLookupByName(ctl->conn, names[i]); - const char *state;
/* this kind of work with domains is not atomic operation */ if (!dom) { @@ -902,12 +899,10 @@ cmdList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) continue; }
- if (virDomainGetInfo(dom, &info) < 0) - state = _("no state"); - else - state = _(vshDomainStateToString(info.state)); - - vshPrint(ctl, "%3s %-20s %s\n", "-", names[i], state); + vshPrint(ctl, "%3s %-20s %s\n", + "-", + names[i], + vshDomainStateToString(vshDomainState(ctl, dom, NULL)));
virDomainFree(dom); VIR_FREE(names[i]); @@ -928,15 +923,17 @@ static const vshCmdInfo info_domstate[] = {
static const vshCmdOptDef opts_domstate[] = { {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")}, + {"reason", VSH_OT_BOOL, 0, N_("also print reason for the state")}, {NULL, 0, 0, NULL} };
static bool cmdDomstate(vshControl *ctl, const vshCmd *cmd) { - virDomainInfo info; virDomainPtr dom; bool ret = true; + int showReason = vshCommandOptBool(cmd, "reason"); + int state, reason;
if (!vshConnectionUsability(ctl, ctl->conn)) return false; @@ -944,12 +941,21 @@ cmdDomstate(vshControl *ctl, const vshCmd *cmd) if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) return false;
- if (virDomainGetInfo(dom, &info) == 0) - vshPrint(ctl, "%s\n", - _(vshDomainStateToString(info.state))); - else + if ((state = vshDomainState(ctl, dom, &reason)) < 0) { ret = false; + goto cleanup; + } + + if (showReason) { + vshPrint(ctl, "%s (%s)\n", + _(vshDomainStateToString(state)), + vshDomainStateReasonToString(state, reason)); + } else { + vshPrint(ctl, "%s\n", + _(vshDomainStateToString(state))); + }
+cleanup: virDomainFree(dom); return ret; } @@ -3023,7 +3029,6 @@ static bool cmdSetmaxmem(vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom; - virDomainInfo info; int kilobytes = 0; bool ret = true; int config = vshCommandOptBool(cmd, "config"); @@ -3063,12 +3068,6 @@ cmdSetmaxmem(vshControl *ctl, const vshCmd *cmd) return false; }
- if (virDomainGetInfo(dom, &info) != 0) { - virDomainFree(dom); - vshError(ctl, "%s", _("Unable to verify current MemorySize")); - return false; - } - if (flags == -1) { if (virDomainSetMaxMemory(dom, kilobytes) != 0) { vshError(ctl, "%s", _("Unable to change MaxMemorySize")); @@ -12024,10 +12023,38 @@ vshCommandStringParse(vshControl *ctl, char *cmdstr) * Misc utils * --------------- */ +static int +vshDomainState(vshControl *ctl, virDomainPtr dom, int *reason) +{ + virDomainInfo info; + + if (reason) + *reason = -1; + + if (!ctl->useGetInfo) { + int state; + if (virDomainGetState(dom, &state, reason, 0) < 0) { + virErrorPtr err = virGetLastError(); + if (err && err->code == VIR_ERR_NO_SUPPORT) + ctl->useGetInfo = true; + else + return -1; + } else { + return state; + } + } + + /* fall back to virDomainGetInfo if virDomainGetState is not supported */ + if (virDomainGetInfo(dom, &info) < 0) + return -1; + else + return info.state; +} + static const char * vshDomainStateToString(int state) { - switch (state) { + switch ((virDomainState) state) { case VIR_DOMAIN_RUNNING: return N_("running"); case VIR_DOMAIN_BLOCKED: @@ -12040,13 +12067,114 @@ vshDomainStateToString(int state) return N_("shut off"); case VIR_DOMAIN_CRASHED: return N_("crashed"); - default: + case VIR_DOMAIN_NOSTATE: ;/*FALLTHROUGH*/ } return N_("no state"); /* = dom0 state */ }
static const char * +vshDomainStateReasonToString(int state, int reason) +{ + switch ((virDomainState) state) { + case VIR_DOMAIN_NOSTATE: + switch ((virDomainNostateReason) reason) { + case VIR_DOMAIN_NOSTATE_UNKNOWN: + ; + } + break; + + case VIR_DOMAIN_RUNNING: + switch ((virDomainRunningReason) reason) { + case VIR_DOMAIN_RUNNING_BOOTED: + return N_("booted"); + case VIR_DOMAIN_RUNNING_MIGRATED: + return N_("migrated"); + case VIR_DOMAIN_RUNNING_RESTORED: + return N_("restored"); + case VIR_DOMAIN_RUNNING_FROM_SNAPSHOT: + return N_("from snapshot"); + case VIR_DOMAIN_RUNNING_UNPAUSED: + return N_("unpaused"); + case VIR_DOMAIN_RUNNING_MIGRATION_CANCELED: + return N_("migration canceled"); + case VIR_DOMAIN_RUNNING_SAVE_CANCELED: + return N_("save canceled"); + case VIR_DOMAIN_RUNNING_UNKNOWN: + ; + } + break; + + case VIR_DOMAIN_BLOCKED: + switch ((virDomainBlockedReason) reason) { + case VIR_DOMAIN_BLOCKED_UNKNOWN: + ; + } + break; + + case VIR_DOMAIN_PAUSED: + switch ((virDomainPausedReason) reason) { + case VIR_DOMAIN_PAUSED_USER: + return N_("user"); + case VIR_DOMAIN_PAUSED_MIGRATION: + return N_("migrating"); + case VIR_DOMAIN_PAUSED_SAVE: + return N_("saving"); + case VIR_DOMAIN_PAUSED_DUMP: + return N_("dumping"); + case VIR_DOMAIN_PAUSED_IOERROR: + return N_("I/O error"); + case VIR_DOMAIN_PAUSED_WATCHDOG: + return N_("watchdog"); + case VIR_DOMAIN_PAUSED_FROM_SNAPSHOT: + return N_("from snapshot"); + case VIR_DOMAIN_PAUSED_UNKNOWN: + ; + } + break; + + case VIR_DOMAIN_SHUTDOWN: + switch ((virDomainShutdownReason) reason) { + case VIR_DOMAIN_SHUTDOWN_USER: + return N_("user"); + case VIR_DOMAIN_SHUTDOWN_UNKNOWN: + ; + } + break; + + case VIR_DOMAIN_SHUTOFF: + switch ((virDomainShutoffReason) reason) { + case VIR_DOMAIN_SHUTOFF_SHUTDOWN: + return N_("shutdown"); + case VIR_DOMAIN_SHUTOFF_DESTROYED: + return N_("destroyed"); + case VIR_DOMAIN_SHUTOFF_CRASHED: + return N_("crashed"); + case VIR_DOMAIN_SHUTOFF_MIGRATED: + return N_("migrated"); + case VIR_DOMAIN_SHUTOFF_SAVED: + return N_("saved"); + case VIR_DOMAIN_SHUTOFF_FAILED: + return N_("failed"); + case VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT: + return N_("from snapshot"); + case VIR_DOMAIN_SHUTOFF_UNKNOWN: + ; + } + break; + + case VIR_DOMAIN_CRASHED: + switch ((virDomainCrashedReason) reason) { + case VIR_DOMAIN_CRASHED_UNKNOWN: + ; + } + break; + } + + return N_("unknown"); +} + +static const char * vshDomainVcpuStateToString(int state) { switch (state) { @@ -12144,6 +12272,7 @@ vshError(vshControl *ctl, const char *format, ...) VIR_FREE(str); }
+ /* * Initialize connection. */
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 :|

--- Notes: Version 2: - rebased - unsigned int flags daemon/remote_generator.pl | 3 ++- src/remote/remote_driver.c | 35 ++++++++++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/daemon/remote_generator.pl b/daemon/remote_generator.pl index ff279d5..736a352 100755 --- a/daemon/remote_generator.pl +++ b/daemon/remote_generator.pl @@ -780,7 +780,8 @@ elsif ($opt_k) { "GetType", "NodeDeviceGetParent", "NodeGetSecurityModel", - "SecretGetValue"); + "SecretGetValue", + "DomainGetState"); } elsif ($structprefix eq "qemu") { @ungeneratable = ("MonitorCommand"); } diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 90d95d6..e3bfa29 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -2324,6 +2324,39 @@ done: } static int +remoteDomainGetState(virDomainPtr domain, + int *state, + int *reason, + unsigned int flags) +{ + int rv = -1; + remote_domain_get_state_args args; + remote_domain_get_state_ret ret; + struct private_data *priv = domain->conn->privateData; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, domain); + args.flags = flags; + + memset(&ret, 0, sizeof ret); + if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_STATE, + (xdrproc_t) xdr_remote_domain_get_state_args, (char *) &args, + (xdrproc_t) xdr_remote_domain_get_state_ret, (char *) &ret) == -1) + goto done; + + *state = ret.state; + if (reason) + *reason = ret.reason; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int remoteNodeGetSecurityModel (virConnectPtr conn, virSecurityModelPtr secmodel) { remote_node_get_security_model_ret ret; @@ -6417,7 +6450,7 @@ static virDriver remote_driver = { remoteDomainSetBlkioParameters, /* domainSetBlkioParameters */ remoteDomainGetBlkioParameters, /* domainGetBlkioParameters */ remoteDomainGetInfo, /* domainGetInfo */ - NULL, /* domainGetState */ + remoteDomainGetState, /* domainGetState */ remoteDomainSave, /* domainSave */ remoteDomainRestore, /* domainRestore */ remoteDomainCoreDump, /* domainCoreDump */ -- 1.7.5.rc3

On Tue, May 10, 2011 at 03:39:08PM +0200, Jiri Denemark wrote:
--- Notes: Version 2: - rebased - unsigned int flags
daemon/remote_generator.pl | 3 ++- src/remote/remote_driver.c | 35 ++++++++++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 2 deletions(-)
diff --git a/daemon/remote_generator.pl b/daemon/remote_generator.pl index ff279d5..736a352 100755 --- a/daemon/remote_generator.pl +++ b/daemon/remote_generator.pl @@ -780,7 +780,8 @@ elsif ($opt_k) { "GetType", "NodeDeviceGetParent", "NodeGetSecurityModel", - "SecretGetValue"); + "SecretGetValue", + "DomainGetState"); } elsif ($structprefix eq "qemu") { @ungeneratable = ("MonitorCommand"); }
Also needs rebasing
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 90d95d6..e3bfa29 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -2324,6 +2324,39 @@ done: }
static int +remoteDomainGetState(virDomainPtr domain, + int *state, + int *reason, + unsigned int flags) +{ + int rv = -1; + remote_domain_get_state_args args; + remote_domain_get_state_ret ret; + struct private_data *priv = domain->conn->privateData; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, domain); + args.flags = flags; + + memset(&ret, 0, sizeof ret); + if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_STATE, + (xdrproc_t) xdr_remote_domain_get_state_args, (char *) &args, + (xdrproc_t) xdr_remote_domain_get_state_ret, (char *) &ret) == -1) + goto done; + + *state = ret.state; + if (reason) + *reason = ret.reason; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int remoteNodeGetSecurityModel (virConnectPtr conn, virSecurityModelPtr secmodel) { remote_node_get_security_model_ret ret; @@ -6417,7 +6450,7 @@ static virDriver remote_driver = { remoteDomainSetBlkioParameters, /* domainSetBlkioParameters */ remoteDomainGetBlkioParameters, /* domainGetBlkioParameters */ remoteDomainGetInfo, /* domainGetInfo */ - NULL, /* domainGetState */ + remoteDomainGetState, /* domainGetState */ remoteDomainSave, /* domainSave */ remoteDomainRestore, /* domainRestore */ remoteDomainCoreDump, /* domainCoreDump */
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 :|

Reason is currently always set to 0 (i.e., *_UNKNOWN). --- Notes: Version 2: - rebased - unsigned int flags - simplified implementation in esx driver per Matthias' suggestion - call internal xen drivers directly instead of going through xenUnifiedDriver src/esx/esx_driver.c | 45 +++++++++++++++++++- src/libxl/libxl_driver.c | 36 +++++++++++++++- src/lxc/lxc_driver.c | 38 ++++++++++++++++- src/openvz/openvz_driver.c | 37 ++++++++++++++++- src/phyp/phyp_driver.c | 17 +++++++- src/qemu/qemu_driver.c | 38 ++++++++++++++++- src/test/test_driver.c | 36 +++++++++++++++- src/uml/uml_driver.c | 37 ++++++++++++++++- src/vbox/vbox_tmpl.c | 61 ++++++++++++++++++++++++++- src/vmware/vmware_driver.c | 36 +++++++++++++++- src/xen/xen_driver.c | 43 ++++++++++++++++++- src/xen/xen_hypervisor.c | 36 ++++++++++++++++ src/xen/xen_hypervisor.h | 5 ++ src/xen/xend_internal.c | 99 +++++++++++++++++++++++++++++++++----------- src/xen/xend_internal.h | 4 ++ src/xen/xm_internal.c | 20 +++++++++ src/xen/xm_internal.h | 4 ++ src/xen/xs_internal.c | 34 +++++++++++++++ src/xen/xs_internal.h | 4 ++ src/xenapi/xenapi_driver.c | 50 ++++++++++++++++++++++- 20 files changed, 644 insertions(+), 36 deletions(-) diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index ec2aaf9..d333877 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -2452,6 +2452,49 @@ esxDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info) static int +esxDomainGetState(virDomainPtr domain, + int *state, + int *reason, + unsigned int flags) +{ + int result = -1; + esxPrivate *priv = domain->conn->privateData; + esxVI_String *propertyNameList = NULL; + esxVI_ObjectContent *virtualMachine = NULL; + esxVI_VirtualMachinePowerState powerState; + + virCheckFlags(0, -1); + + if (esxVI_EnsureSession(priv->primary) < 0) { + return -1; + } + + if (esxVI_String_AppendValueToList(&propertyNameList, + "runtime.powerState") < 0 || + esxVI_LookupVirtualMachineByUuid(priv->primary, domain->uuid, + propertyNameList, &virtualMachine, + esxVI_Occurrence_RequiredItem) < 0 || + esxVI_GetVirtualMachinePowerState(virtualMachine, &powerState) < 0) { + goto cleanup; + } + + *state = esxVI_VirtualMachinePowerState_ConvertToLibvirt(powerState); + + if (reason) + *reason = 0; + + result = 0; + + cleanup: + esxVI_String_Free(&propertyNameList); + esxVI_ObjectContent_Free(&virtualMachine); + + return result; +} + + + +static int esxDomainSetVcpusFlags(virDomainPtr domain, unsigned int nvcpus, unsigned int flags) { @@ -4623,7 +4666,7 @@ static virDriver esxDriver = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ esxDomainGetInfo, /* domainGetInfo */ - NULL, /* domainGetState */ + esxDomainGetState, /* domainGetState */ NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 794a9e7..1fcf723 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -1608,6 +1608,40 @@ libxlDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info) } static int +libxlDomainGetState(virDomainPtr dom, + int *state, + int *reason, + unsigned int flags) +{ + libxlDriverPrivatePtr driver = dom->conn->privateData; + virDomainObjPtr vm; + int ret = -1; + + virCheckFlags(0, -1); + + libxlDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + libxlDriverUnlock(driver); + + if (!vm) { + libxlError(VIR_ERR_NO_DOMAIN, "%s", + _("no domain with matching uuid")); + goto cleanup; + } + + *state = vm->state; + if (reason) + *reason = 0; + + ret = 0; + + cleanup: + if (vm) + virDomainObjUnlock(vm); + return ret; +} + +static int libxlDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, unsigned int flags) { @@ -2714,7 +2748,7 @@ static virDriver libxlDriver = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ libxlDomainGetInfo, /* domainGetInfo */ - NULL, /* domainGetState */ + libxlDomainGetState, /* domainGetState */ NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 0dcaf4c..2d57eb2 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -564,6 +564,42 @@ cleanup: return ret; } +static int +lxcDomainGetState(virDomainPtr dom, + int *state, + int *reason, + unsigned int flags) +{ + lxc_driver_t *driver = dom->conn->privateData; + virDomainObjPtr vm; + int ret = -1; + + virCheckFlags(0, -1); + + lxcDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + lxcDriverUnlock(driver); + + if (!vm) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(dom->uuid, uuidstr); + lxcError(VIR_ERR_NO_DOMAIN, + _("No domain with matching uuid '%s'"), uuidstr); + goto cleanup; + } + + *state = vm->state; + if (reason) + *reason = 0; + + ret = 0; + +cleanup: + if (vm) + virDomainObjUnlock(vm); + return ret; +} + static char *lxcGetOSType(virDomainPtr dom) { lxc_driver_t *driver = dom->conn->privateData; @@ -2829,7 +2865,7 @@ static virDriver lxcDriver = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ lxcDomainGetInfo, /* domainGetInfo */ - NULL, /* domainGetState */ + lxcDomainGetState, /* domainGetState */ NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c index 48a3aae..3ab72e8 100644 --- a/src/openvz/openvz_driver.c +++ b/src/openvz/openvz_driver.c @@ -377,6 +377,41 @@ cleanup: } +static int +openvzDomainGetState(virDomainPtr dom, + int *state, + int *reason, + unsigned int flags) +{ + struct openvz_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + int ret = -1; + + virCheckFlags(0, -1); + + openvzDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + openvzDriverUnlock(driver); + + if (!vm) { + openvzError(VIR_ERR_NO_DOMAIN, "%s", + _("no domain with matching uuid")); + goto cleanup; + } + + *state = vm->state; + if (reason) + *reason = 0; + + ret = 0; + +cleanup: + if (vm) + virDomainObjUnlock(vm); + return ret; +} + + static int openvzDomainIsActive(virDomainPtr dom) { struct openvz_driver *driver = dom->conn->privateData; @@ -1591,7 +1626,7 @@ static virDriver openvzDriver = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ openvzDomainGetInfo, /* domainGetInfo */ - NULL, /* domainGetState */ + openvzDomainGetState, /* domainGetState */ NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index abd3594..51c19f0 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -3471,6 +3471,21 @@ phypDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info) } static int +phypDomainGetState(virDomainPtr dom, + int *state, + int *reason, + unsigned int flags) +{ + virCheckFlags(0, -1); + + *state = phypGetLparState(dom->conn, dom->id); + if (reason) + *reason = 0; + + return 0; +} + +static int phypDomainDestroy(virDomainPtr dom) { int result = -1; @@ -3752,7 +3767,7 @@ static virDriver phypDriver = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ phypDomainGetInfo, /* domainGetInfo */ - NULL, /* domainGetState */ + phypDomainGetState, /* domainGetState */ NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 92c7f9a..a1617bc 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -1783,6 +1783,42 @@ cleanup: return ret; } +static int +qemuDomainGetState(virDomainPtr dom, + int *state, + int *reason, + unsigned int flags) +{ + struct qemud_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + int ret = -1; + + virCheckFlags(0, -1); + + qemuDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + qemuDriverUnlock(driver); + + if (!vm) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(dom->uuid, uuidstr); + qemuReportError(VIR_ERR_NO_DOMAIN, + _("no domain with matching uuid '%s'"), uuidstr); + goto cleanup; + } + + *state = vm->state; + if (reason) + *reason = 0; + + ret = 0; + +cleanup: + if (vm) + virDomainObjUnlock(vm); + return ret; +} + #define QEMUD_SAVE_MAGIC "LibvirtQemudSave" #define QEMUD_SAVE_VERSION 2 @@ -7116,7 +7152,7 @@ static virDriver qemuDriver = { qemuDomainSetBlkioParameters, /* domainSetBlkioParameters */ qemuDomainGetBlkioParameters, /* domainGetBlkioParameters */ qemudDomainGetInfo, /* domainGetInfo */ - NULL, /* domainGetState */ + qemuDomainGetState, /* domainGetState */ qemudDomainSave, /* domainSave */ qemuDomainRestore, /* domainRestore */ qemudDomainCoreDump, /* domainCoreDump */ diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 6f4ae75..4ec2852 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -1704,6 +1704,40 @@ cleanup: return ret; } +static int +testDomainGetState(virDomainPtr domain, + int *state, + int *reason, + unsigned int flags) +{ + testConnPtr privconn = domain->conn->privateData; + virDomainObjPtr privdom; + int ret = -1; + + virCheckFlags(0, -1); + + testDriverLock(privconn); + privdom = virDomainFindByName(&privconn->domains, + domain->name); + testDriverUnlock(privconn); + + if (privdom == NULL) { + testError(VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + *state = privdom->state; + if (reason) + *reason = 0; + + ret = 0; + +cleanup: + if (privdom) + virDomainObjUnlock(privdom); + return ret; +} + #define TEST_SAVE_MAGIC "TestGuestMagic" static int testDomainSave(virDomainPtr domain, @@ -5371,7 +5405,7 @@ static virDriver testDriver = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ testGetDomainInfo, /* domainGetInfo */ - NULL, /* domainGetState */ + testDomainGetState, /* domainGetState */ testDomainSave, /* domainSave */ testDomainRestore, /* domainRestore */ testDomainCoreDump, /* domainCoreDump */ diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c index 6852a16..e6fe019 100644 --- a/src/uml/uml_driver.c +++ b/src/uml/uml_driver.c @@ -1522,6 +1522,41 @@ cleanup: } +static int +umlDomainGetState(virDomainPtr dom, + int *state, + int *reason, + unsigned int flags) +{ + struct uml_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + int ret = -1; + + virCheckFlags(0, -1); + + umlDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + umlDriverUnlock(driver); + + if (!vm) { + umlReportError(VIR_ERR_NO_DOMAIN, "%s", + _("no domain with matching uuid")); + goto cleanup; + } + + *state = vm->state; + if (reason) + *reason = 0; + + ret = 0; + +cleanup: + if (vm) + virDomainObjUnlock(vm); + return ret; +} + + static char *umlDomainDumpXML(virDomainPtr dom, int flags ATTRIBUTE_UNUSED) { struct uml_driver *driver = dom->conn->privateData; @@ -2177,7 +2212,7 @@ static virDriver umlDriver = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ umlDomainGetInfo, /* domainGetInfo */ - NULL, /* domainGetState */ + umlDomainGetState, /* domainGetState */ NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index d4a8924..9faaf5e 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -1909,6 +1909,65 @@ cleanup: return ret; } +static int +vboxDomainGetState(virDomainPtr dom, + int *state, + int *reason, + unsigned int flags) +{ + VBOX_OBJECT_CHECK(dom->conn, int, -1); + vboxIID domiid = VBOX_IID_INITIALIZER; + IMachine *machine = NULL; + PRUint32 mstate = MachineState_Null; + nsresult rc; + + virCheckFlags(0, -1); + + vboxIIDFromUUID(&domiid, dom->uuid); + rc = VBOX_OBJECT_GET_MACHINE(domiid.value, &machine); + if (NS_FAILED(rc)) { + vboxError(VIR_ERR_NO_DOMAIN, "%s", + _("no domain with matching UUID")); + goto cleanup; + } + + machine->vtbl->GetState(machine, &mstate); + + switch (mstate) { + case MachineState_Running: + *state = VIR_DOMAIN_RUNNING; + break; + case MachineState_Stuck: + *state = VIR_DOMAIN_BLOCKED; + break; + case MachineState_Paused: + *state = VIR_DOMAIN_PAUSED; + break; + case MachineState_Stopping: + *state = VIR_DOMAIN_SHUTDOWN; + break; + case MachineState_PoweredOff: + *state = VIR_DOMAIN_SHUTOFF; + break; + case MachineState_Aborted: + *state = VIR_DOMAIN_CRASHED; + break; + case MachineState_Null: + default: + *state = VIR_DOMAIN_NOSTATE; + break; + } + + if (reason) + *reason = 0; + + ret = 0; + +cleanup: + vboxIIDUnalloc(&domiid); + return ret; +} + static int vboxDomainSave(virDomainPtr dom, const char *path ATTRIBUTE_UNUSED) { VBOX_OBJECT_CHECK(dom->conn, int, -1); IConsole *console = NULL; @@ -8566,7 +8625,7 @@ virDriver NAME(Driver) = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ vboxDomainGetInfo, /* domainGetInfo */ - NULL, /* domainGetState */ + vboxDomainGetState, /* domainGetState */ vboxDomainSave, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ diff --git a/src/vmware/vmware_driver.c b/src/vmware/vmware_driver.c index c6c92c6..743e136 100644 --- a/src/vmware/vmware_driver.c +++ b/src/vmware/vmware_driver.c @@ -896,6 +896,40 @@ vmwareDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info) return ret; } +static int +vmwareDomainGetState(virDomainPtr dom, + int *state, + int *reason, + unsigned int flags) +{ + struct vmware_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + int ret = -1; + + virCheckFlags(0, -1); + + vmwareDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + vmwareDriverUnlock(driver); + + if (!vm) { + vmwareError(VIR_ERR_NO_DOMAIN, "%s", + _("no domain with matching uuid")); + goto cleanup; + } + + *state = vm->state; + if (reason) + *reason = 0; + + ret = 0; + + cleanup: + if (vm) + virDomainObjUnlock(vm); + return ret; +} + static virDriver vmwareDriver = { VIR_DRV_VMWARE, "VMWARE", @@ -931,7 +965,7 @@ static virDriver vmwareDriver = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ vmwareDomainGetInfo, /* domainGetInfo */ - NULL, /* domainGetState */ + vmwareDomainGetState, /* domainGetState */ NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c index 1646828..a2728eb 100644 --- a/src/xen/xen_driver.c +++ b/src/xen/xen_driver.c @@ -1010,6 +1010,47 @@ xenUnifiedDomainGetInfo (virDomainPtr dom, virDomainInfoPtr info) } static int +xenUnifiedDomainGetState(virDomainPtr dom, + int *state, + int *reason, + unsigned int flags) +{ + GET_PRIVATE(dom->conn); + int ret; + + virCheckFlags(0, -1); + + /* trying drivers in the same order as GetInfo for consistent results: + * hypervisor, xend, xs, and xm */ + + if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET]) { + ret = xenHypervisorGetDomainState(dom, state, reason, flags); + if (ret >= 0) + return ret; + } + + if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) { + ret = xenDaemonDomainGetState(dom, state, reason, flags); + if (ret >= 0) + return ret; + } + + if (priv->opened[XEN_UNIFIED_XS_OFFSET]) { + ret = xenStoreDomainGetState(dom, state, reason, flags); + if (ret >= 0) + return ret; + } + + if (priv->opened[XEN_UNIFIED_XM_OFFSET]) { + ret = xenXMDomainGetState(dom, state, reason, flags); + if (ret >= 0) + return ret; + } + + return -1; +} + +static int xenUnifiedDomainSave (virDomainPtr dom, const char *to) { GET_PRIVATE(dom->conn); @@ -2132,7 +2173,7 @@ static virDriver xenUnifiedDriver = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ xenUnifiedDomainGetInfo, /* domainGetInfo */ - NULL, /* domainGetState */ + xenUnifiedDomainGetState, /* domainGetState */ xenUnifiedDomainSave, /* domainSave */ xenUnifiedDomainRestore, /* domainRestore */ xenUnifiedDomainCoreDump, /* domainCoreDump */ diff --git a/src/xen/xen_hypervisor.c b/src/xen/xen_hypervisor.c index 9a5b41d..1a245e5 100644 --- a/src/xen/xen_hypervisor.c +++ b/src/xen/xen_hypervisor.c @@ -3238,6 +3238,42 @@ xenHypervisorGetDomainInfo(virDomainPtr domain, virDomainInfoPtr info) } /** + * xenHypervisorGetDomainState: + * @domain: pointer to the domain block + * @state: returned state of the domain + * @reason: returned reason for the state + * @flags: additional flags, 0 for now + * + * Do a hypervisor call to get the related set of domain information. + * + * Returns 0 in case of success, -1 in case of error. + */ +int +xenHypervisorGetDomainState(virDomainPtr domain, + int *state, + int *reason, + unsigned int flags ATTRIBUTE_UNUSED) +{ + xenUnifiedPrivatePtr priv = domain->conn->privateData; + virDomainInfo info; + + if (domain->conn == NULL) + return -1; + + if (priv->handle < 0 || domain->id < 0) + return -1; + + if (xenHypervisorGetDomInfo(domain->conn, domain->id, &info) < 0) + return -1; + + *state = info.state; + if (reason) + *reason = 0; + + return 0; +} + +/** * xenHypervisorNodeGetCellsFreeMemory: * @conn: pointer to the hypervisor connection * @freeMems: pointer to the array of unsigned long long diff --git a/src/xen/xen_hypervisor.h b/src/xen/xen_hypervisor.h index 6018b84..f7e7699 100644 --- a/src/xen/xen_hypervisor.h +++ b/src/xen/xen_hypervisor.h @@ -66,6 +66,11 @@ int xenHypervisorPauseDomain (virDomainPtr domain) int xenHypervisorGetDomainInfo (virDomainPtr domain, virDomainInfoPtr info) ATTRIBUTE_NONNULL (1); +int xenHypervisorGetDomainState (virDomainPtr domain, + int *state, + int *reason, + unsigned int flags) + ATTRIBUTE_NONNULL (1); int xenHypervisorGetDomInfo (virConnectPtr conn, int id, virDomainInfoPtr info); diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c index a4420d8..2e87bd6 100644 --- a/src/xen/xend_internal.c +++ b/src/xen/xend_internal.c @@ -1020,6 +1020,43 @@ xend_detect_config_version(virConnectPtr conn) { /** + * sexpr_to_xend_domain_state: + * @root: an S-Expression describing a domain + * + * Internal routine getting the domain's state from the domain root provided. + * + * Returns domain's state. + */ +static int +ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) +sexpr_to_xend_domain_state(virDomainPtr domain, const struct sexpr *root) +{ + const char *flags; + int state = VIR_DOMAIN_NOSTATE; + + if ((flags = sexpr_node(root, "domain/state"))) { + if (strchr(flags, 'c')) + state = VIR_DOMAIN_CRASHED; + else if (strchr(flags, 's')) + state = VIR_DOMAIN_SHUTOFF; + else if (strchr(flags, 'd')) + state = VIR_DOMAIN_SHUTDOWN; + else if (strchr(flags, 'p')) + state = VIR_DOMAIN_PAUSED; + else if (strchr(flags, 'b')) + state = VIR_DOMAIN_BLOCKED; + else if (strchr(flags, 'r')) + state = VIR_DOMAIN_RUNNING; + } else if (domain->id < 0) { + /* Inactive domains don't have a state reported, so + mark them SHUTOFF, rather than NOSTATE */ + state = VIR_DOMAIN_SHUTOFF; + } + + return state; +} + +/** * sexpr_to_xend_domain_info: * @root: an S-Expression describing a domain * @info: a info data structure to fill=up @@ -1033,38 +1070,16 @@ static int sexpr_to_xend_domain_info(virDomainPtr domain, const struct sexpr *root, virDomainInfoPtr info) { - const char *flags; int vcpus; if ((root == NULL) || (info == NULL)) return (-1); + info->state = sexpr_to_xend_domain_state(domain, root); info->memory = sexpr_u64(root, "domain/memory") << 10; info->maxMem = sexpr_u64(root, "domain/maxmem") << 10; - flags = sexpr_node(root, "domain/state"); - - if (flags) { - if (strchr(flags, 'c')) - info->state = VIR_DOMAIN_CRASHED; - else if (strchr(flags, 's')) - info->state = VIR_DOMAIN_SHUTOFF; - else if (strchr(flags, 'd')) - info->state = VIR_DOMAIN_SHUTDOWN; - else if (strchr(flags, 'p')) - info->state = VIR_DOMAIN_PAUSED; - else if (strchr(flags, 'b')) - info->state = VIR_DOMAIN_BLOCKED; - else if (strchr(flags, 'r')) - info->state = VIR_DOMAIN_RUNNING; - } else { - /* Inactive domains don't have a state reported, so - mark them SHUTOFF, rather than NOSTATE */ - if (domain->id < 0) - info->state = VIR_DOMAIN_SHUTOFF; - else - info->state = VIR_DOMAIN_NOSTATE; - } info->cpuTime = sexpr_float(root, "domain/cpu_time") * 1000000000; + vcpus = sexpr_int(root, "domain/vcpus"); info->nrVirtCpu = count_one_bits_l(sexpr_u64(root, "domain/vcpu_avail")); if (!info->nrVirtCpu || vcpus < info->nrVirtCpu) @@ -1894,6 +1909,42 @@ xenDaemonDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info) /** + * xenDaemonDomainGetState: + * @domain: a domain object + * @state: returned domain's state + * @reason: returned reason for the state + * @flags: additional flags, 0 for now + * + * This method looks up domain state and reason. + * + * Returns 0 in case of success, -1 in case of error + */ +int +xenDaemonDomainGetState(virDomainPtr domain, + int *state, + int *reason, + unsigned int flags ATTRIBUTE_UNUSED) +{ + xenUnifiedPrivatePtr priv = domain->conn->privateData; + struct sexpr *root; + + if (domain->id < 0 && priv->xendConfigVersion < 3) + return -1; + + root = sexpr_get(domain->conn, "/xend/domain/%s?detail=1", domain->name); + if (!root) + return -1; + + *state = sexpr_to_xend_domain_state(domain, root); + if (reason) + *reason = 0; + + sexpr_free(root); + return 0; +} + + +/** * xenDaemonLookupByName: * @conn: A xend instance * @name: The name of the domain diff --git a/src/xen/xend_internal.h b/src/xen/xend_internal.h index 805cf91..de9b1b9 100644 --- a/src/xen/xend_internal.h +++ b/src/xen/xend_internal.h @@ -110,6 +110,10 @@ int xenDaemonDomainRestore(virConnectPtr conn, const char *filename); int xenDaemonDomainSetMemory(virDomainPtr domain, unsigned long memory); int xenDaemonDomainSetMaxMemory(virDomainPtr domain, unsigned long memory); int xenDaemonDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info); +int xenDaemonDomainGetState(virDomainPtr domain, + int *state, + int *reason, + unsigned int flags); char *xenDaemonDomainDumpXML(virDomainPtr domain, int flags, const char *cpus); unsigned long xenDaemonDomainGetMaxMemory(virDomainPtr domain); char **xenDaemonListDomainsOld(virConnectPtr xend); diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c index 07a0c0f..e68a043 100644 --- a/src/xen/xm_internal.c +++ b/src/xen/xm_internal.c @@ -469,6 +469,26 @@ int xenXMClose(virConnectPtr conn) { } /* + * Since these are all offline domains, the state is always SHUTOFF. + */ +int +xenXMDomainGetState(virDomainPtr domain, + int *state, + int *reason, + unsigned int flags ATTRIBUTE_UNUSED) +{ + if (domain->id != -1) + return -1; + + *state = VIR_DOMAIN_SHUTOFF; + if (reason) + *reason = 0; + + return 0; +} + + +/* * Since these are all offline domains, we only return info about * VCPUs and memory. */ diff --git a/src/xen/xm_internal.h b/src/xen/xm_internal.h index 695bb3e..2d37505 100644 --- a/src/xen/xm_internal.h +++ b/src/xen/xm_internal.h @@ -40,6 +40,10 @@ virDrvOpenStatus xenXMOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags int xenXMClose(virConnectPtr conn); const char *xenXMGetType(virConnectPtr conn); int xenXMDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info); +int xenXMDomainGetState(virDomainPtr domain, + int *state, + int *reason, + unsigned int flags); char *xenXMDomainDumpXML(virDomainPtr domain, int flags); int xenXMDomainSetMemory(virDomainPtr domain, unsigned long memory); int xenXMDomainSetMaxMemory(virDomainPtr domain, unsigned long memory); diff --git a/src/xen/xs_internal.c b/src/xen/xs_internal.c index c318f6c..0db1c9f 100644 --- a/src/xen/xs_internal.c +++ b/src/xen/xs_internal.c @@ -449,6 +449,40 @@ xenStoreGetDomainInfo(virDomainPtr domain, virDomainInfoPtr info) } /** + * xenStoreDomainGetState: + * @domain: pointer to the domain block + * @state: returned domain's state + * @reason: returned state reason + * @flags: additional flags, 0 for now + * + * Returns 0 in case of success, -1 in case of error. + */ +int +xenStoreDomainGetState(virDomainPtr domain, + int *state, + int *reason, + unsigned int flags ATTRIBUTE_UNUSED) +{ + char *running; + + if (domain->id == -1) + return -1; + + running = virDomainDoStoreQuery(domain->conn, domain->id, "running"); + + if (running && *running == '1') + *state = VIR_DOMAIN_RUNNING; + else + *state = VIR_DOMAIN_NOSTATE; + if (reason) + *reason = 0; + + VIR_FREE(running); + + return 0; +} + +/** * xenStoreDomainSetMemory: * @domain: pointer to the domain block * @memory: the max memory size in kilobytes. diff --git a/src/xen/xs_internal.h b/src/xen/xs_internal.h index d58e6c0..efc4f9f 100644 --- a/src/xen/xs_internal.h +++ b/src/xen/xs_internal.h @@ -23,6 +23,10 @@ virDrvOpenStatus xenStoreOpen (virConnectPtr conn, int xenStoreClose (virConnectPtr conn); int xenStoreGetDomainInfo (virDomainPtr domain, virDomainInfoPtr info); +int xenStoreDomainGetState (virDomainPtr domain, + int *state, + int *reason, + unsigned int flags); int xenStoreNumOfDomains (virConnectPtr conn); int xenStoreListDomains (virConnectPtr conn, int *ids, diff --git a/src/xenapi/xenapi_driver.c b/src/xenapi/xenapi_driver.c index 83417df..87bba74 100644 --- a/src/xenapi/xenapi_driver.c +++ b/src/xenapi/xenapi_driver.c @@ -994,6 +994,54 @@ xenapiDomainGetInfo (virDomainPtr dom, virDomainInfoPtr info) return -1; } +/* + * xenapiDomainGetState: + * + * Retrieves domain status and its reason. + * + * Returns 0 on success or -1 in case of error + */ +static int +xenapiDomainGetState(virDomainPtr dom, + int *state, + int *reason, + unsigned int flags) +{ + struct _xenapiPrivate *priv = dom->conn->privateData; + enum xen_vm_power_state powerState = XEN_VM_POWER_STATE_UNDEFINED; + xen_vm_set *vms = NULL; + xen_vm vm; + int ret = -1; + + virCheckFlags(0, -1); + + if (!xen_vm_get_by_name_label(priv->session, &vms, dom->name) || + vms->size == 0) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL); + goto cleanup; + } + + if (vms->size != 1) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, + _("Domain name is not unique")); + goto cleanup; + } + + vm = vms->contents[0]; + xen_vm_get_power_state(priv->session, &powerState, vm); + + *state = mapPowerState(powerState); + if (reason) + *reason = 0; + + ret = 0; + +cleanup: + if (vms) + xen_vm_set_free(vms); + return ret; +} + /* * xenapiDomainSetVcpusFlags @@ -1813,7 +1861,7 @@ static virDriver xenapiDriver = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ xenapiDomainGetInfo, /* domainGetInfo */ - NULL, /* domainGetState */ + xenapiDomainGetState, /* domainGetState */ NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ -- 1.7.5.rc3

On Tue, May 10, 2011 at 03:39:09PM +0200, Jiri Denemark wrote:
Reason is currently always set to 0 (i.e., *_UNKNOWN). --- Notes: Version 2: - rebased - unsigned int flags - simplified implementation in esx driver per Matthias' suggestion - call internal xen drivers directly instead of going through xenUnifiedDriver
src/esx/esx_driver.c | 45 +++++++++++++++++++- src/libxl/libxl_driver.c | 36 +++++++++++++++- src/lxc/lxc_driver.c | 38 ++++++++++++++++- src/openvz/openvz_driver.c | 37 ++++++++++++++++- src/phyp/phyp_driver.c | 17 +++++++- src/qemu/qemu_driver.c | 38 ++++++++++++++++- src/test/test_driver.c | 36 +++++++++++++++- src/uml/uml_driver.c | 37 ++++++++++++++++- src/vbox/vbox_tmpl.c | 61 ++++++++++++++++++++++++++- src/vmware/vmware_driver.c | 36 +++++++++++++++- src/xen/xen_driver.c | 43 ++++++++++++++++++- src/xen/xen_hypervisor.c | 36 ++++++++++++++++ src/xen/xen_hypervisor.h | 5 ++ src/xen/xend_internal.c | 99 +++++++++++++++++++++++++++++++++----------- src/xen/xend_internal.h | 4 ++ src/xen/xm_internal.c | 20 +++++++++ src/xen/xm_internal.h | 4 ++ src/xen/xs_internal.c | 34 +++++++++++++++ src/xen/xs_internal.h | 4 ++ src/xenapi/xenapi_driver.c | 50 ++++++++++++++++++++++- 20 files changed, 644 insertions(+), 36 deletions(-)
diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index ec2aaf9..d333877 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -2452,6 +2452,49 @@ esxDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info)
static int +esxDomainGetState(virDomainPtr domain, + int *state, + int *reason, + unsigned int flags) +{ + int result = -1; + esxPrivate *priv = domain->conn->privateData; + esxVI_String *propertyNameList = NULL; + esxVI_ObjectContent *virtualMachine = NULL; + esxVI_VirtualMachinePowerState powerState; + + virCheckFlags(0, -1); + + if (esxVI_EnsureSession(priv->primary) < 0) { + return -1; + } + + if (esxVI_String_AppendValueToList(&propertyNameList, + "runtime.powerState") < 0 || + esxVI_LookupVirtualMachineByUuid(priv->primary, domain->uuid, + propertyNameList, &virtualMachine, + esxVI_Occurrence_RequiredItem) < 0 || + esxVI_GetVirtualMachinePowerState(virtualMachine, &powerState) < 0) { + goto cleanup; + } + + *state = esxVI_VirtualMachinePowerState_ConvertToLibvirt(powerState); + + if (reason) + *reason = 0; + + result = 0; + + cleanup: + esxVI_String_Free(&propertyNameList); + esxVI_ObjectContent_Free(&virtualMachine); + + return result; +} + + + +static int esxDomainSetVcpusFlags(virDomainPtr domain, unsigned int nvcpus, unsigned int flags) { @@ -4623,7 +4666,7 @@ static virDriver esxDriver = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ esxDomainGetInfo, /* domainGetInfo */ - NULL, /* domainGetState */ + esxDomainGetState, /* domainGetState */ NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 794a9e7..1fcf723 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -1608,6 +1608,40 @@ libxlDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info) }
static int +libxlDomainGetState(virDomainPtr dom, + int *state, + int *reason, + unsigned int flags) +{ + libxlDriverPrivatePtr driver = dom->conn->privateData; + virDomainObjPtr vm; + int ret = -1; + + virCheckFlags(0, -1); + + libxlDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + libxlDriverUnlock(driver); + + if (!vm) { + libxlError(VIR_ERR_NO_DOMAIN, "%s", + _("no domain with matching uuid")); + goto cleanup; + } + + *state = vm->state; + if (reason) + *reason = 0; + + ret = 0; + + cleanup: + if (vm) + virDomainObjUnlock(vm); + return ret; +} + +static int libxlDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, unsigned int flags) { @@ -2714,7 +2748,7 @@ static virDriver libxlDriver = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ libxlDomainGetInfo, /* domainGetInfo */ - NULL, /* domainGetState */ + libxlDomainGetState, /* domainGetState */ NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 0dcaf4c..2d57eb2 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -564,6 +564,42 @@ cleanup: return ret; }
+static int +lxcDomainGetState(virDomainPtr dom, + int *state, + int *reason, + unsigned int flags) +{ + lxc_driver_t *driver = dom->conn->privateData; + virDomainObjPtr vm; + int ret = -1; + + virCheckFlags(0, -1); + + lxcDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + lxcDriverUnlock(driver); + + if (!vm) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(dom->uuid, uuidstr); + lxcError(VIR_ERR_NO_DOMAIN, + _("No domain with matching uuid '%s'"), uuidstr); + goto cleanup; + } + + *state = vm->state; + if (reason) + *reason = 0; + + ret = 0; + +cleanup: + if (vm) + virDomainObjUnlock(vm); + return ret; +} + static char *lxcGetOSType(virDomainPtr dom) { lxc_driver_t *driver = dom->conn->privateData; @@ -2829,7 +2865,7 @@ static virDriver lxcDriver = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ lxcDomainGetInfo, /* domainGetInfo */ - NULL, /* domainGetState */ + lxcDomainGetState, /* domainGetState */ NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c index 48a3aae..3ab72e8 100644 --- a/src/openvz/openvz_driver.c +++ b/src/openvz/openvz_driver.c @@ -377,6 +377,41 @@ cleanup: }
+static int +openvzDomainGetState(virDomainPtr dom, + int *state, + int *reason, + unsigned int flags) +{ + struct openvz_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + int ret = -1; + + virCheckFlags(0, -1); + + openvzDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + openvzDriverUnlock(driver); + + if (!vm) { + openvzError(VIR_ERR_NO_DOMAIN, "%s", + _("no domain with matching uuid")); + goto cleanup; + } + + *state = vm->state; + if (reason) + *reason = 0; + + ret = 0; + +cleanup: + if (vm) + virDomainObjUnlock(vm); + return ret; +} + + static int openvzDomainIsActive(virDomainPtr dom) { struct openvz_driver *driver = dom->conn->privateData; @@ -1591,7 +1626,7 @@ static virDriver openvzDriver = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ openvzDomainGetInfo, /* domainGetInfo */ - NULL, /* domainGetState */ + openvzDomainGetState, /* domainGetState */ NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index abd3594..51c19f0 100644 --- a/src/phyp/phyp_driver.c +++ b/src/phyp/phyp_driver.c @@ -3471,6 +3471,21 @@ phypDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info) }
static int +phypDomainGetState(virDomainPtr dom, + int *state, + int *reason, + unsigned int flags) +{ + virCheckFlags(0, -1); + + *state = phypGetLparState(dom->conn, dom->id); + if (reason) + *reason = 0; + + return 0; +} + +static int phypDomainDestroy(virDomainPtr dom) { int result = -1; @@ -3752,7 +3767,7 @@ static virDriver phypDriver = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ phypDomainGetInfo, /* domainGetInfo */ - NULL, /* domainGetState */ + phypDomainGetState, /* domainGetState */ NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 92c7f9a..a1617bc 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -1783,6 +1783,42 @@ cleanup: return ret; }
+static int +qemuDomainGetState(virDomainPtr dom, + int *state, + int *reason, + unsigned int flags) +{ + struct qemud_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + int ret = -1; + + virCheckFlags(0, -1); + + qemuDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + qemuDriverUnlock(driver); + + if (!vm) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(dom->uuid, uuidstr); + qemuReportError(VIR_ERR_NO_DOMAIN, + _("no domain with matching uuid '%s'"), uuidstr); + goto cleanup; + } + + *state = vm->state; + if (reason) + *reason = 0; + + ret = 0; + +cleanup: + if (vm) + virDomainObjUnlock(vm); + return ret; +} +
#define QEMUD_SAVE_MAGIC "LibvirtQemudSave" #define QEMUD_SAVE_VERSION 2 @@ -7116,7 +7152,7 @@ static virDriver qemuDriver = { qemuDomainSetBlkioParameters, /* domainSetBlkioParameters */ qemuDomainGetBlkioParameters, /* domainGetBlkioParameters */ qemudDomainGetInfo, /* domainGetInfo */ - NULL, /* domainGetState */ + qemuDomainGetState, /* domainGetState */ qemudDomainSave, /* domainSave */ qemuDomainRestore, /* domainRestore */ qemudDomainCoreDump, /* domainCoreDump */ diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 6f4ae75..4ec2852 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -1704,6 +1704,40 @@ cleanup: return ret; }
+static int +testDomainGetState(virDomainPtr domain, + int *state, + int *reason, + unsigned int flags) +{ + testConnPtr privconn = domain->conn->privateData; + virDomainObjPtr privdom; + int ret = -1; + + virCheckFlags(0, -1); + + testDriverLock(privconn); + privdom = virDomainFindByName(&privconn->domains, + domain->name); + testDriverUnlock(privconn); + + if (privdom == NULL) { + testError(VIR_ERR_INVALID_ARG, __FUNCTION__); + goto cleanup; + } + + *state = privdom->state; + if (reason) + *reason = 0; + + ret = 0; + +cleanup: + if (privdom) + virDomainObjUnlock(privdom); + return ret; +} + #define TEST_SAVE_MAGIC "TestGuestMagic"
static int testDomainSave(virDomainPtr domain, @@ -5371,7 +5405,7 @@ static virDriver testDriver = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ testGetDomainInfo, /* domainGetInfo */ - NULL, /* domainGetState */ + testDomainGetState, /* domainGetState */ testDomainSave, /* domainSave */ testDomainRestore, /* domainRestore */ testDomainCoreDump, /* domainCoreDump */ diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c index 6852a16..e6fe019 100644 --- a/src/uml/uml_driver.c +++ b/src/uml/uml_driver.c @@ -1522,6 +1522,41 @@ cleanup: }
+static int +umlDomainGetState(virDomainPtr dom, + int *state, + int *reason, + unsigned int flags) +{ + struct uml_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + int ret = -1; + + virCheckFlags(0, -1); + + umlDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + umlDriverUnlock(driver); + + if (!vm) { + umlReportError(VIR_ERR_NO_DOMAIN, "%s", + _("no domain with matching uuid")); + goto cleanup; + } + + *state = vm->state; + if (reason) + *reason = 0; + + ret = 0; + +cleanup: + if (vm) + virDomainObjUnlock(vm); + return ret; +} + + static char *umlDomainDumpXML(virDomainPtr dom, int flags ATTRIBUTE_UNUSED) { struct uml_driver *driver = dom->conn->privateData; @@ -2177,7 +2212,7 @@ static virDriver umlDriver = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ umlDomainGetInfo, /* domainGetInfo */ - NULL, /* domainGetState */ + umlDomainGetState, /* domainGetState */ NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index d4a8924..9faaf5e 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -1909,6 +1909,65 @@ cleanup: return ret; }
+static int +vboxDomainGetState(virDomainPtr dom, + int *state, + int *reason, + unsigned int flags) +{ + VBOX_OBJECT_CHECK(dom->conn, int, -1); + vboxIID domiid = VBOX_IID_INITIALIZER; + IMachine *machine = NULL; + PRUint32 mstate = MachineState_Null; + nsresult rc; + + virCheckFlags(0, -1); + + vboxIIDFromUUID(&domiid, dom->uuid); + rc = VBOX_OBJECT_GET_MACHINE(domiid.value, &machine); + if (NS_FAILED(rc)) { + vboxError(VIR_ERR_NO_DOMAIN, "%s", + _("no domain with matching UUID")); + goto cleanup; + } + + machine->vtbl->GetState(machine, &mstate); + + switch (mstate) { + case MachineState_Running: + *state = VIR_DOMAIN_RUNNING; + break; + case MachineState_Stuck: + *state = VIR_DOMAIN_BLOCKED; + break; + case MachineState_Paused: + *state = VIR_DOMAIN_PAUSED; + break; + case MachineState_Stopping: + *state = VIR_DOMAIN_SHUTDOWN; + break; + case MachineState_PoweredOff: + *state = VIR_DOMAIN_SHUTOFF; + break; + case MachineState_Aborted: + *state = VIR_DOMAIN_CRASHED; + break; + case MachineState_Null: + default: + *state = VIR_DOMAIN_NOSTATE; + break; + } + + if (reason) + *reason = 0; + + ret = 0; + +cleanup: + vboxIIDUnalloc(&domiid); + return ret; +} + static int vboxDomainSave(virDomainPtr dom, const char *path ATTRIBUTE_UNUSED) { VBOX_OBJECT_CHECK(dom->conn, int, -1); IConsole *console = NULL; @@ -8566,7 +8625,7 @@ virDriver NAME(Driver) = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ vboxDomainGetInfo, /* domainGetInfo */ - NULL, /* domainGetState */ + vboxDomainGetState, /* domainGetState */ vboxDomainSave, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ diff --git a/src/vmware/vmware_driver.c b/src/vmware/vmware_driver.c index c6c92c6..743e136 100644 --- a/src/vmware/vmware_driver.c +++ b/src/vmware/vmware_driver.c @@ -896,6 +896,40 @@ vmwareDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info) return ret; }
+static int +vmwareDomainGetState(virDomainPtr dom, + int *state, + int *reason, + unsigned int flags) +{ + struct vmware_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + int ret = -1; + + virCheckFlags(0, -1); + + vmwareDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + vmwareDriverUnlock(driver); + + if (!vm) { + vmwareError(VIR_ERR_NO_DOMAIN, "%s", + _("no domain with matching uuid")); + goto cleanup; + } + + *state = vm->state; + if (reason) + *reason = 0; + + ret = 0; + + cleanup: + if (vm) + virDomainObjUnlock(vm); + return ret; +} + static virDriver vmwareDriver = { VIR_DRV_VMWARE, "VMWARE", @@ -931,7 +965,7 @@ static virDriver vmwareDriver = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ vmwareDomainGetInfo, /* domainGetInfo */ - NULL, /* domainGetState */ + vmwareDomainGetState, /* domainGetState */ NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */ diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c index 1646828..a2728eb 100644 --- a/src/xen/xen_driver.c +++ b/src/xen/xen_driver.c @@ -1010,6 +1010,47 @@ xenUnifiedDomainGetInfo (virDomainPtr dom, virDomainInfoPtr info) }
static int +xenUnifiedDomainGetState(virDomainPtr dom, + int *state, + int *reason, + unsigned int flags) +{ + GET_PRIVATE(dom->conn); + int ret; + + virCheckFlags(0, -1); + + /* trying drivers in the same order as GetInfo for consistent results: + * hypervisor, xend, xs, and xm */ + + if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET]) { + ret = xenHypervisorGetDomainState(dom, state, reason, flags); + if (ret >= 0) + return ret; + } + + if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) { + ret = xenDaemonDomainGetState(dom, state, reason, flags); + if (ret >= 0) + return ret; + } + + if (priv->opened[XEN_UNIFIED_XS_OFFSET]) { + ret = xenStoreDomainGetState(dom, state, reason, flags); + if (ret >= 0) + return ret; + } + + if (priv->opened[XEN_UNIFIED_XM_OFFSET]) { + ret = xenXMDomainGetState(dom, state, reason, flags); + if (ret >= 0) + return ret; + } + + return -1; +} + +static int xenUnifiedDomainSave (virDomainPtr dom, const char *to) { GET_PRIVATE(dom->conn); @@ -2132,7 +2173,7 @@ static virDriver xenUnifiedDriver = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ xenUnifiedDomainGetInfo, /* domainGetInfo */ - NULL, /* domainGetState */ + xenUnifiedDomainGetState, /* domainGetState */ xenUnifiedDomainSave, /* domainSave */ xenUnifiedDomainRestore, /* domainRestore */ xenUnifiedDomainCoreDump, /* domainCoreDump */ diff --git a/src/xen/xen_hypervisor.c b/src/xen/xen_hypervisor.c index 9a5b41d..1a245e5 100644 --- a/src/xen/xen_hypervisor.c +++ b/src/xen/xen_hypervisor.c @@ -3238,6 +3238,42 @@ xenHypervisorGetDomainInfo(virDomainPtr domain, virDomainInfoPtr info) }
/** + * xenHypervisorGetDomainState: + * @domain: pointer to the domain block + * @state: returned state of the domain + * @reason: returned reason for the state + * @flags: additional flags, 0 for now + * + * Do a hypervisor call to get the related set of domain information. + * + * Returns 0 in case of success, -1 in case of error. + */ +int +xenHypervisorGetDomainState(virDomainPtr domain, + int *state, + int *reason, + unsigned int flags ATTRIBUTE_UNUSED) +{ + xenUnifiedPrivatePtr priv = domain->conn->privateData; + virDomainInfo info; + + if (domain->conn == NULL) + return -1; + + if (priv->handle < 0 || domain->id < 0) + return -1; + + if (xenHypervisorGetDomInfo(domain->conn, domain->id, &info) < 0) + return -1; + + *state = info.state; + if (reason) + *reason = 0; + + return 0; +} + +/** * xenHypervisorNodeGetCellsFreeMemory: * @conn: pointer to the hypervisor connection * @freeMems: pointer to the array of unsigned long long diff --git a/src/xen/xen_hypervisor.h b/src/xen/xen_hypervisor.h index 6018b84..f7e7699 100644 --- a/src/xen/xen_hypervisor.h +++ b/src/xen/xen_hypervisor.h @@ -66,6 +66,11 @@ int xenHypervisorPauseDomain (virDomainPtr domain) int xenHypervisorGetDomainInfo (virDomainPtr domain, virDomainInfoPtr info) ATTRIBUTE_NONNULL (1); +int xenHypervisorGetDomainState (virDomainPtr domain, + int *state, + int *reason, + unsigned int flags) + ATTRIBUTE_NONNULL (1); int xenHypervisorGetDomInfo (virConnectPtr conn, int id, virDomainInfoPtr info); diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c index a4420d8..2e87bd6 100644 --- a/src/xen/xend_internal.c +++ b/src/xen/xend_internal.c @@ -1020,6 +1020,43 @@ xend_detect_config_version(virConnectPtr conn) {
/** + * sexpr_to_xend_domain_state: + * @root: an S-Expression describing a domain + * + * Internal routine getting the domain's state from the domain root provided. + * + * Returns domain's state. + */ +static int +ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) +sexpr_to_xend_domain_state(virDomainPtr domain, const struct sexpr *root) +{ + const char *flags; + int state = VIR_DOMAIN_NOSTATE; + + if ((flags = sexpr_node(root, "domain/state"))) { + if (strchr(flags, 'c')) + state = VIR_DOMAIN_CRASHED; + else if (strchr(flags, 's')) + state = VIR_DOMAIN_SHUTOFF; + else if (strchr(flags, 'd')) + state = VIR_DOMAIN_SHUTDOWN; + else if (strchr(flags, 'p')) + state = VIR_DOMAIN_PAUSED; + else if (strchr(flags, 'b')) + state = VIR_DOMAIN_BLOCKED; + else if (strchr(flags, 'r')) + state = VIR_DOMAIN_RUNNING; + } else if (domain->id < 0) { + /* Inactive domains don't have a state reported, so + mark them SHUTOFF, rather than NOSTATE */ + state = VIR_DOMAIN_SHUTOFF; + } + + return state; +} + +/** * sexpr_to_xend_domain_info: * @root: an S-Expression describing a domain * @info: a info data structure to fill=up @@ -1033,38 +1070,16 @@ static int sexpr_to_xend_domain_info(virDomainPtr domain, const struct sexpr *root, virDomainInfoPtr info) { - const char *flags; int vcpus;
if ((root == NULL) || (info == NULL)) return (-1);
+ info->state = sexpr_to_xend_domain_state(domain, root); info->memory = sexpr_u64(root, "domain/memory") << 10; info->maxMem = sexpr_u64(root, "domain/maxmem") << 10; - flags = sexpr_node(root, "domain/state"); - - if (flags) { - if (strchr(flags, 'c')) - info->state = VIR_DOMAIN_CRASHED; - else if (strchr(flags, 's')) - info->state = VIR_DOMAIN_SHUTOFF; - else if (strchr(flags, 'd')) - info->state = VIR_DOMAIN_SHUTDOWN; - else if (strchr(flags, 'p')) - info->state = VIR_DOMAIN_PAUSED; - else if (strchr(flags, 'b')) - info->state = VIR_DOMAIN_BLOCKED; - else if (strchr(flags, 'r')) - info->state = VIR_DOMAIN_RUNNING; - } else { - /* Inactive domains don't have a state reported, so - mark them SHUTOFF, rather than NOSTATE */ - if (domain->id < 0) - info->state = VIR_DOMAIN_SHUTOFF; - else - info->state = VIR_DOMAIN_NOSTATE; - } info->cpuTime = sexpr_float(root, "domain/cpu_time") * 1000000000; + vcpus = sexpr_int(root, "domain/vcpus"); info->nrVirtCpu = count_one_bits_l(sexpr_u64(root, "domain/vcpu_avail")); if (!info->nrVirtCpu || vcpus < info->nrVirtCpu) @@ -1894,6 +1909,42 @@ xenDaemonDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info)
/** + * xenDaemonDomainGetState: + * @domain: a domain object + * @state: returned domain's state + * @reason: returned reason for the state + * @flags: additional flags, 0 for now + * + * This method looks up domain state and reason. + * + * Returns 0 in case of success, -1 in case of error + */ +int +xenDaemonDomainGetState(virDomainPtr domain, + int *state, + int *reason, + unsigned int flags ATTRIBUTE_UNUSED) +{ + xenUnifiedPrivatePtr priv = domain->conn->privateData; + struct sexpr *root; + + if (domain->id < 0 && priv->xendConfigVersion < 3) + return -1; + + root = sexpr_get(domain->conn, "/xend/domain/%s?detail=1", domain->name); + if (!root) + return -1; + + *state = sexpr_to_xend_domain_state(domain, root); + if (reason) + *reason = 0; + + sexpr_free(root); + return 0; +} + + +/** * xenDaemonLookupByName: * @conn: A xend instance * @name: The name of the domain diff --git a/src/xen/xend_internal.h b/src/xen/xend_internal.h index 805cf91..de9b1b9 100644 --- a/src/xen/xend_internal.h +++ b/src/xen/xend_internal.h @@ -110,6 +110,10 @@ int xenDaemonDomainRestore(virConnectPtr conn, const char *filename); int xenDaemonDomainSetMemory(virDomainPtr domain, unsigned long memory); int xenDaemonDomainSetMaxMemory(virDomainPtr domain, unsigned long memory); int xenDaemonDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info); +int xenDaemonDomainGetState(virDomainPtr domain, + int *state, + int *reason, + unsigned int flags); char *xenDaemonDomainDumpXML(virDomainPtr domain, int flags, const char *cpus); unsigned long xenDaemonDomainGetMaxMemory(virDomainPtr domain); char **xenDaemonListDomainsOld(virConnectPtr xend); diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c index 07a0c0f..e68a043 100644 --- a/src/xen/xm_internal.c +++ b/src/xen/xm_internal.c @@ -469,6 +469,26 @@ int xenXMClose(virConnectPtr conn) { }
/* + * Since these are all offline domains, the state is always SHUTOFF. + */ +int +xenXMDomainGetState(virDomainPtr domain, + int *state, + int *reason, + unsigned int flags ATTRIBUTE_UNUSED) +{ + if (domain->id != -1) + return -1; + + *state = VIR_DOMAIN_SHUTOFF; + if (reason) + *reason = 0; + + return 0; +} + + +/* * Since these are all offline domains, we only return info about * VCPUs and memory. */ diff --git a/src/xen/xm_internal.h b/src/xen/xm_internal.h index 695bb3e..2d37505 100644 --- a/src/xen/xm_internal.h +++ b/src/xen/xm_internal.h @@ -40,6 +40,10 @@ virDrvOpenStatus xenXMOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags int xenXMClose(virConnectPtr conn); const char *xenXMGetType(virConnectPtr conn); int xenXMDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info); +int xenXMDomainGetState(virDomainPtr domain, + int *state, + int *reason, + unsigned int flags); char *xenXMDomainDumpXML(virDomainPtr domain, int flags); int xenXMDomainSetMemory(virDomainPtr domain, unsigned long memory); int xenXMDomainSetMaxMemory(virDomainPtr domain, unsigned long memory); diff --git a/src/xen/xs_internal.c b/src/xen/xs_internal.c index c318f6c..0db1c9f 100644 --- a/src/xen/xs_internal.c +++ b/src/xen/xs_internal.c @@ -449,6 +449,40 @@ xenStoreGetDomainInfo(virDomainPtr domain, virDomainInfoPtr info) }
/** + * xenStoreDomainGetState: + * @domain: pointer to the domain block + * @state: returned domain's state + * @reason: returned state reason + * @flags: additional flags, 0 for now + * + * Returns 0 in case of success, -1 in case of error. + */ +int +xenStoreDomainGetState(virDomainPtr domain, + int *state, + int *reason, + unsigned int flags ATTRIBUTE_UNUSED) +{ + char *running; + + if (domain->id == -1) + return -1; + + running = virDomainDoStoreQuery(domain->conn, domain->id, "running"); + + if (running && *running == '1') + *state = VIR_DOMAIN_RUNNING; + else + *state = VIR_DOMAIN_NOSTATE; + if (reason) + *reason = 0; + + VIR_FREE(running); + + return 0; +} + +/** * xenStoreDomainSetMemory: * @domain: pointer to the domain block * @memory: the max memory size in kilobytes. diff --git a/src/xen/xs_internal.h b/src/xen/xs_internal.h index d58e6c0..efc4f9f 100644 --- a/src/xen/xs_internal.h +++ b/src/xen/xs_internal.h @@ -23,6 +23,10 @@ virDrvOpenStatus xenStoreOpen (virConnectPtr conn, int xenStoreClose (virConnectPtr conn); int xenStoreGetDomainInfo (virDomainPtr domain, virDomainInfoPtr info); +int xenStoreDomainGetState (virDomainPtr domain, + int *state, + int *reason, + unsigned int flags); int xenStoreNumOfDomains (virConnectPtr conn); int xenStoreListDomains (virConnectPtr conn, int *ids, diff --git a/src/xenapi/xenapi_driver.c b/src/xenapi/xenapi_driver.c index 83417df..87bba74 100644 --- a/src/xenapi/xenapi_driver.c +++ b/src/xenapi/xenapi_driver.c @@ -994,6 +994,54 @@ xenapiDomainGetInfo (virDomainPtr dom, virDomainInfoPtr info) return -1; }
+/* + * xenapiDomainGetState: + * + * Retrieves domain status and its reason. + * + * Returns 0 on success or -1 in case of error + */ +static int +xenapiDomainGetState(virDomainPtr dom, + int *state, + int *reason, + unsigned int flags) +{ + struct _xenapiPrivate *priv = dom->conn->privateData; + enum xen_vm_power_state powerState = XEN_VM_POWER_STATE_UNDEFINED; + xen_vm_set *vms = NULL; + xen_vm vm; + int ret = -1; + + virCheckFlags(0, -1); + + if (!xen_vm_get_by_name_label(priv->session, &vms, dom->name) || + vms->size == 0) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_NO_DOMAIN, NULL); + goto cleanup; + } + + if (vms->size != 1) { + xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, + _("Domain name is not unique")); + goto cleanup; + } + + vm = vms->contents[0]; + xen_vm_get_power_state(priv->session, &powerState, vm); + + *state = mapPowerState(powerState); + if (reason) + *reason = 0; + + ret = 0; + +cleanup: + if (vms) + xen_vm_set_free(vms); + return ret; +} +
/* * xenapiDomainSetVcpusFlags @@ -1813,7 +1861,7 @@ static virDriver xenapiDriver = { NULL, /* domainSetBlkioParameters */ NULL, /* domainGetBlkioParameters */ xenapiDomainGetInfo, /* domainGetInfo */ - NULL, /* domainGetState */ + xenapiDomainGetState, /* domainGetState */ NULL, /* domainSave */ NULL, /* domainRestore */ NULL, /* domainCoreDump */
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 :|

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: -- 1.7.5.rc3

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 :|

A qemu domain can get paused when libvirtd is stopped (e.g., because of I/O error) so we should check its current state when reconnecting to it. --- Notes: Version 2: - new patch src/qemu/qemu_monitor.c | 20 ++++++++++++++++++++ src/qemu/qemu_monitor.h | 1 + src/qemu/qemu_monitor_json.c | 42 ++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_monitor_json.h | 1 + src/qemu/qemu_monitor_text.c | 30 ++++++++++++++++++++++++++++++ src/qemu/qemu_monitor_text.h | 1 + src/qemu/qemu_process.c | 38 ++++++++++++++++++++++++++++++++++++++ 7 files changed, 133 insertions(+), 0 deletions(-) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index f89038e..a36a9da 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -981,6 +981,26 @@ qemuMonitorStopCPUs(qemuMonitorPtr mon) } +int +qemuMonitorGetStatus(qemuMonitorPtr mon, bool *running) +{ + int ret; + VIR_DEBUG("mon=%p, running=%p", mon, running); + + if (!mon || !running) { + qemuReportError(VIR_ERR_INVALID_ARG, "%s", + _("both monitor and running must not be NULL")); + return -1; + } + + if (mon->json) + ret = qemuMonitorJSONGetStatus(mon, running); + else + ret = qemuMonitorTextGetStatus(mon, running); + return ret; +} + + int qemuMonitorSystemPowerdown(qemuMonitorPtr mon) { int ret; diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index c90219b..21ed3c3 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -178,6 +178,7 @@ int qemuMonitorEmitGraphics(qemuMonitorPtr mon, int qemuMonitorStartCPUs(qemuMonitorPtr mon, virConnectPtr conn); int qemuMonitorStopCPUs(qemuMonitorPtr mon); +int qemuMonitorGetStatus(qemuMonitorPtr mon, bool *running); int qemuMonitorSystemPowerdown(qemuMonitorPtr mon); diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 20a78e1..d9d5952 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -852,6 +852,48 @@ qemuMonitorJSONStopCPUs(qemuMonitorPtr mon) } +int +qemuMonitorJSONGetStatus(qemuMonitorPtr mon, bool *running) +{ + int ret; + virJSONValuePtr cmd; + virJSONValuePtr reply = NULL; + virJSONValuePtr data; + + if (!(cmd = qemuMonitorJSONMakeCommand("query-status", NULL))) + return -1; + + ret = qemuMonitorJSONCommand(mon, cmd, &reply); + + if (ret == 0) + ret = qemuMonitorJSONCheckError(cmd, reply); + + if (ret < 0) + goto cleanup; + + ret = -1; + + if (!(data = virJSONValueObjectGet(reply, "return"))) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("query-status reply was missing return data")); + goto cleanup; + } + + if (virJSONValueObjectGetBoolean(data, "running", running) < 0) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("query-status reply was missing running state")); + goto cleanup; + } + + ret = 0; + +cleanup: + virJSONValueFree(cmd); + virJSONValueFree(reply); + return ret; +} + + int qemuMonitorJSONSystemPowerdown(qemuMonitorPtr mon) { int ret; diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index 086f0e1..789db49 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -46,6 +46,7 @@ int qemuMonitorJSONCheckHMP(qemuMonitorPtr mon); int qemuMonitorJSONStartCPUs(qemuMonitorPtr mon, virConnectPtr conn); int qemuMonitorJSONStopCPUs(qemuMonitorPtr mon); +int qemuMonitorJSONGetStatus(qemuMonitorPtr mon, bool *running); int qemuMonitorJSONSystemPowerdown(qemuMonitorPtr mon); diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index 53781c8..c839986 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -373,6 +373,36 @@ qemuMonitorTextStopCPUs(qemuMonitorPtr mon) { } +int +qemuMonitorTextGetStatus(qemuMonitorPtr mon, bool *running) +{ + char *reply; + int ret = -1; + + if (qemuMonitorHMPCommand(mon, "info status", &reply) < 0) { + qemuReportError(VIR_ERR_OPERATION_FAILED, + "%s", _("cannot get status info")); + return -1; + } + + if (strstr(reply, "running")) { + *running = true; + } else if (strstr(reply, "paused")) { + *running = false; + } else { + qemuReportError(VIR_ERR_OPERATION_FAILED, + _("unexpected reply from info status: %s"), reply); + goto cleanup; + } + + ret = 0; + +cleanup: + VIR_FREE(reply); + return ret; +} + + int qemuMonitorTextSystemPowerdown(qemuMonitorPtr mon) { char *info; diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h index 0838a2b..298cb3b 100644 --- a/src/qemu/qemu_monitor_text.h +++ b/src/qemu/qemu_monitor_text.h @@ -43,6 +43,7 @@ int qemuMonitorTextCommandWithFd(qemuMonitorPtr mon, int qemuMonitorTextStartCPUs(qemuMonitorPtr mon, virConnectPtr conn); int qemuMonitorTextStopCPUs(qemuMonitorPtr mon); +int qemuMonitorTextGetStatus(qemuMonitorPtr mon, bool *running); int qemuMonitorTextSystemPowerdown(qemuMonitorPtr mon); diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index f74122e..d7a3353 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -1881,6 +1881,37 @@ qemuProcessFiltersInstantiate(virConnectPtr conn, return err; } +static int +qemuProcessUpdateState(struct qemud_driver *driver, virDomainObjPtr vm) +{ + qemuDomainObjPrivatePtr priv = vm->privateData; + virDomainState state; + bool running; + int ret; + + qemuDomainObjEnterMonitorWithDriver(driver, vm); + ret = qemuMonitorGetStatus(priv->mon, &running); + qemuDomainObjExitMonitorWithDriver(driver, vm); + + if (ret < 0 || !virDomainObjIsActive(vm)) + return -1; + + state = virDomainObjGetState(vm, NULL); + + if (state == VIR_DOMAIN_PAUSED && running) { + VIR_DEBUG("Domain %s was unpaused while its monitor was disconnected;" + " changing state to running", vm->def->name); + virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, + VIR_DOMAIN_RUNNING_UNPAUSED); + } else if (state == VIR_DOMAIN_RUNNING && !running) { + VIR_DEBUG("Domain %s was paused while its monitor was disconnected;" + " changing state to paused", vm->def->name); + virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_UNKNOWN); + } + + return 0; +} + struct qemuProcessReconnectData { virConnectPtr conn; struct qemud_driver *driver; @@ -1916,6 +1947,9 @@ qemuProcessReconnect(void *payload, const void *name ATTRIBUTE_UNUSED, void *opa goto error; } + if (qemuProcessUpdateState(driver, obj) < 0) + goto error; + /* If upgrading from old libvirtd we won't have found any * caps in the domain status, so re-query them */ @@ -1939,6 +1973,10 @@ qemuProcessReconnect(void *payload, const void *name ATTRIBUTE_UNUSED, void *opa if (qemuProcessFiltersInstantiate(conn, obj->def)) goto error; + /* update domain state XML with possibly updated state in virDomainObj */ + if (virDomainSaveStatus(driver->caps, driver->stateDir, obj) < 0) + goto error; + if (obj->def->id >= driver->nextvmid) driver->nextvmid = obj->def->id + 1; -- 1.7.5.rc3

On 05/10/2011 07:39 AM, Jiri Denemark wrote:
A qemu domain can get paused when libvirtd is stopped (e.g., because of I/O error) so we should check its current state when reconnecting to it. --- Notes: Version 2: - new patch
Good catch. I see danpb reviewed the rest of the series, but missed this one.
+++ b/src/qemu/qemu_process.c @@ -1881,6 +1881,37 @@ qemuProcessFiltersInstantiate(virConnectPtr conn, return err; }
+static int +qemuProcessUpdateState(struct qemud_driver *driver, virDomainObjPtr vm) +{ + qemuDomainObjPrivatePtr priv = vm->privateData; + virDomainState state; + bool running; + int ret; + + qemuDomainObjEnterMonitorWithDriver(driver, vm); + ret = qemuMonitorGetStatus(priv->mon, &running); + qemuDomainObjExitMonitorWithDriver(driver, vm); + + if (ret < 0 || !virDomainObjIsActive(vm)) + return -1;
I half debated about whether virDomainObjIsActive returning fals can still successfully result in a state update; but I convinced myself that this is tied to a qemu process, and if the process goes away, then elsewhere in the code correctly changes the state, and that this only needs to probe the monitor for a live qemu process. ACK. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On Tue, May 10, 2011 at 15:39:02 +0200, Jiri Denemark wrote:
This new API solves several problems:
- calling virDomainGetInfo for just getting domain status is an overkill since it may result in sending requests to guest OS - since virDomainGetInfo can hang when guest OS is not responding and it is used by virsh list, listing domains can hang - virDomainGetState provides additional info about what action led to domain's current state, which can be used instead of listening to domain events
Version 2: - rebased to current HEAD - unsigned int flags parameter - updated version info in public.syms - noGetState renamed as useGetInfo in virsh.c - simplified implementation in esx driver per Matthias' suggestion - call internal xen drivers directly instead of going through xenUnifiedDriver - fixed || vs && typo in domain_conf.c - new patch 9/9: qemu: Update domain state when reconnecting monitor
I pushed this series now. Thanks for the reviews. Jirka
participants (3)
-
Daniel P. Berrange
-
Eric Blake
-
Jiri Denemark