Add a new API virDomainShutdownFlags and define:
VIR_DOMAIN_SHUTDOWN_DEFAULT = 0,
VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN = (1 << 0),
VIR_DOMAIN_SHUTDOWN_GUEST_AGENT = (1 << 1),
Also define some flags for the reboot API
VIR_DOMAIN_REBOOT_DEFAULT = 0,
VIR_DOMAIN_REBOOT_ACPI_POWER_BTN = (1 << 0),
VIR_DOMAIN_REBOOT_GUEST_AGENT = (1 << 1),
Although these two APIs currently have the same flags, using
separate enums allows them to expand separately in the future.
Add stub impls of the new API for all existing drivers
---
include/libvirt/libvirt.h.in | 15 +++++++++
src/driver.h | 5 +++
src/esx/esx_driver.c | 11 ++++++-
src/libvirt.c | 68 +++++++++++++++++++++++++++++++++++++++++-
src/libvirt_public.syms | 4 ++
src/libxl/libxl_driver.c | 12 +++++++-
src/openvz/openvz_driver.c | 1 +
src/remote/remote_driver.c | 1 +
src/remote/remote_protocol.x | 8 ++++-
src/remote_protocol-structs | 5 +++
src/test/test_driver.c | 11 ++++++-
src/uml/uml_driver.c | 11 ++++++-
src/vbox/vbox_tmpl.c | 11 ++++++-
src/vmware/vmware_driver.c | 1 +
src/xen/xen_driver.c | 14 +++++++-
src/xenapi/xenapi_driver.c | 12 +++++++-
16 files changed, 180 insertions(+), 10 deletions(-)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index 958e5a6..381fcd2 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -1200,7 +1200,22 @@ virDomainPtr virDomainLookupByUUID (virConnectPtr
conn,
virDomainPtr virDomainLookupByUUIDString (virConnectPtr conn,
const char *uuid);
+typedef enum {
+ VIR_DOMAIN_SHUTDOWN_DEFAULT = 0, /* hypervisor to choose */
+ VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN = (1 << 0), /* Send ACPI event */
+ VIR_DOMAIN_SHUTDOWN_GUEST_AGENT = (1 << 1), /* Use guest agent */
+} virDomainShutdownFlagValues;
+
int virDomainShutdown (virDomainPtr domain);
+int virDomainShutdownFlags (virDomainPtr domain,
+ unsigned int flags);
+
+typedef enum {
+ VIR_DOMAIN_REBOOT_DEFAULT = 0, /* hypervisor to choose */
+ VIR_DOMAIN_REBOOT_ACPI_POWER_BTN = (1 << 0), /* Send ACPI event */
+ VIR_DOMAIN_REBOOT_GUEST_AGENT = (1 << 1), /* Use guest agent */
+} virDomainRebootFlagValues;
+
int virDomainReboot (virDomainPtr domain,
unsigned int flags);
int virDomainReset (virDomainPtr domain,
diff --git a/src/driver.h b/src/driver.h
index 24636a4..6222bed 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -793,6 +793,10 @@ typedef int
virTypedParameterPtr params,
int *nparams,
unsigned int flags);
+typedef int
+ (*virDrvDomainShutdownFlags)(virDomainPtr domain,
+ unsigned int flags);
+
/**
* _virDriver:
@@ -829,6 +833,7 @@ struct _virDriver {
virDrvDomainSuspend domainSuspend;
virDrvDomainResume domainResume;
virDrvDomainShutdown domainShutdown;
+ virDrvDomainShutdownFlags domainShutdownFlags;
virDrvDomainReboot domainReboot;
virDrvDomainReset domainReset;
virDrvDomainDestroy domainDestroy;
diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
index 63cdba5..f5e1cc7 100644
--- a/src/esx/esx_driver.c
+++ b/src/esx/esx_driver.c
@@ -1887,7 +1887,7 @@ esxDomainResume(virDomainPtr domain)
static int
-esxDomainShutdown(virDomainPtr domain)
+esxDomainShutdownFlags(virDomainPtr domain, unsigned int flags)
{
int result = -1;
esxPrivate *priv = domain->conn->privateData;
@@ -1895,6 +1895,8 @@ esxDomainShutdown(virDomainPtr domain)
esxVI_String *propertyNameList = NULL;
esxVI_VirtualMachinePowerState powerState;
+ virCheckFlags(0, -1);
+
if (esxVI_EnsureSession(priv->primary) < 0) {
return -1;
}
@@ -1928,6 +1930,12 @@ esxDomainShutdown(virDomainPtr domain)
}
+static int
+esxDomainShutdown(virDomainPtr domain)
+{
+ return esxDomainShutdownFlags(domain, 0);
+}
+
static int
esxDomainReboot(virDomainPtr domain, unsigned int flags)
@@ -4953,6 +4961,7 @@ static virDriver esxDriver = {
.domainSuspend = esxDomainSuspend, /* 0.7.0 */
.domainResume = esxDomainResume, /* 0.7.0 */
.domainShutdown = esxDomainShutdown, /* 0.7.0 */
+ .domainShutdownFlags = esxDomainShutdownFlags, /* 0.9.10 */
.domainReboot = esxDomainReboot, /* 0.7.0 */
.domainDestroy = esxDomainDestroy, /* 0.7.0 */
.domainDestroyFlags = esxDomainDestroyFlags, /* 0.9.4 */
diff --git a/src/libvirt.c b/src/libvirt.c
index 7b8adf7..73eeb6b 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -3106,14 +3106,80 @@ error:
}
/**
+ * virDomainShutdownFlags:
+ * @domain: a domain object
+ * @flags: bitwise-OR of virDomainShutdownFlagValues
+ *
+ * Shutdown a domain, the domain object is still usable thereafter but
+ * the domain OS is being stopped. Note that the guest OS may ignore the
+ * request. For guests that react to a shutdown request, the differences
+ * from virDomainDestroy() are that the guest's disk storage will be in a
+ * stable state rather than having the (virtual) power cord pulled, and
+ * this command returns as soon as the shutdown request is issued rather
+ * than blocking until the guest is no longer running.
+ *
+ * If the domain is transient and has any snapshot metadata (see
+ * virDomainSnapshotNum()), then that metadata will automatically
+ * be deleted when the domain quits.
+ *
+ * If @flags is set to zero, then the hypervisor will chose the
+ * method of shutdown it considers best. To have greater control
+ * pass exactly one of the virDomainShutdownFlagValues.
+ *
+ * Returns 0 in case of success and -1 in case of failure.
+ */
+int
+virDomainShutdownFlags(virDomainPtr domain, unsigned int flags)
+{
+ virConnectPtr conn;
+
+ VIR_DOMAIN_DEBUG(domain);
+
+ virResetLastError();
+
+ if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+ virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+ virDispatchError(NULL);
+ return -1;
+ }
+ if (domain->conn->flags & VIR_CONNECT_RO) {
+ virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+ goto error;
+ }
+
+ conn = domain->conn;
+
+ if (conn->driver->domainShutdownFlags) {
+ int ret;
+ ret = conn->driver->domainShutdownFlags(domain, flags);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+ virDispatchError(domain->conn);
+ return -1;
+}
+
+/**
* virDomainReboot:
* @domain: a domain object
- * @flags: extra flags; not used yet, so callers should always pass 0
+ * @flags: bitwise-OR of virDomainRebootFlagValues
*
* Reboot a domain, the domain object is still usable there after but
* the domain OS is being stopped for a restart.
* Note that the guest OS may ignore the request.
*
+ * If @flags is set to zero, then the hypervisor will chose the
+ * method of shutdown it considers best. To have greater control
+ * pass exactly one of the virDomainRebootFlagValues.
+ *
+ * To use guest agent (VIR_DOMAIN_REBOOT_GUEST_AGENT) the domain XML
+ * must have <channel> configured.
+ *
* Returns 0 in case of success and -1 in case of failure.
*/
int
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index 4ca7216..e0cbdb4 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -516,4 +516,8 @@ LIBVIRT_0.9.9 {
virDomainSetNumaParameters;
} LIBVIRT_0.9.8;
+LIBVIRT_0.9.10 {
+ global:
+ virDomainShutdownFlags;
+} LIBVIRT_0.9.9;
# .... define new API here using predicted next version number ....
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
index f7f45c7..41366e4 100644
--- a/src/libxl/libxl_driver.c
+++ b/src/libxl/libxl_driver.c
@@ -1412,13 +1412,15 @@ cleanup:
}
static int
-libxlDomainShutdown(virDomainPtr dom)
+libxlDomainShutdownFlags(virDomainPtr dom, unsigned int flags)
{
libxlDriverPrivatePtr driver = dom->conn->privateData;
virDomainObjPtr vm;
int ret = -1;
libxlDomainObjPrivatePtr priv;
+ virCheckFlags(0, -1);
+
libxlDriverLock(driver);
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
if (!vm) {
@@ -1456,6 +1458,13 @@ cleanup:
}
static int
+libxlDomainShutdown(virDomainPtr dom)
+{
+ return libxlDomainShutdownFlags(dom, 0);
+}
+
+
+static int
libxlDomainReboot(virDomainPtr dom, unsigned int flags)
{
libxlDriverPrivatePtr driver = dom->conn->privateData;
@@ -3857,6 +3866,7 @@ static virDriver libxlDriver = {
.domainSuspend = libxlDomainSuspend, /* 0.9.0 */
.domainResume = libxlDomainResume, /* 0.9.0 */
.domainShutdown = libxlDomainShutdown, /* 0.9.0 */
+ .domainShutdownFlags = libxlDomainShutdownFlags, /* 0.9.10 */
.domainReboot = libxlDomainReboot, /* 0.9.0 */
.domainDestroy = libxlDomainDestroy, /* 0.9.0 */
.domainDestroyFlags = libxlDomainDestroyFlags, /* 0.9.4 */
diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c
index 03bf21a..b848a88 100644
--- a/src/openvz/openvz_driver.c
+++ b/src/openvz/openvz_driver.c
@@ -1693,6 +1693,7 @@ static virDriver openvzDriver = {
.domainSuspend = openvzDomainSuspend, /* 0.8.3 */
.domainResume = openvzDomainResume, /* 0.8.3 */
.domainShutdown = openvzDomainShutdown, /* 0.3.1 */
+ .domainShutdownFlags = openvzDomainShutdownFlags, /* 0.9.10 */
.domainReboot = openvzDomainReboot, /* 0.3.1 */
.domainDestroy = openvzDomainShutdown, /* 0.3.1 */
.domainDestroyFlags = openvzDomainShutdownFlags, /* 0.9.4 */
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index e28840b..f45a8fe 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -4617,6 +4617,7 @@ static virDriver remote_driver = {
.domainSuspend = remoteDomainSuspend, /* 0.3.0 */
.domainResume = remoteDomainResume, /* 0.3.0 */
.domainShutdown = remoteDomainShutdown, /* 0.3.0 */
+ .domainShutdownFlags = remoteDomainShutdownFlags, /* 0.9.10 */
.domainReboot = remoteDomainReboot, /* 0.3.0 */
.domainReset = remoteDomainReset, /* 0.9.7 */
.domainDestroy = remoteDomainDestroy, /* 0.3.0 */
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index 514b0cc..6a20ae8 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -2349,6 +2349,11 @@ struct remote_node_suspend_for_duration_args {
unsigned int flags;
};
+struct remote_domain_shutdown_flags_args {
+ remote_nonnull_domain dom;
+ unsigned int flags;
+};
+
/*----- Protocol. -----*/
@@ -2654,7 +2659,8 @@ enum remote_procedure {
REMOTE_PROC_DOMAIN_SET_NUMA_PARAMETERS = 254, /* autogen autogen */
REMOTE_PROC_DOMAIN_GET_NUMA_PARAMETERS = 255, /* skipgen skipgen */
REMOTE_PROC_DOMAIN_SET_INTERFACE_PARAMETERS = 256, /* autogen autogen */
- REMOTE_PROC_DOMAIN_GET_INTERFACE_PARAMETERS = 257 /* skipgen skipgen */
+ REMOTE_PROC_DOMAIN_GET_INTERFACE_PARAMETERS = 257, /* skipgen skipgen */
+ REMOTE_PROC_DOMAIN_SHUTDOWN_FLAGS = 258 /* autogen autogen */
/*
* Notice how the entries are grouped in sets of 10 ?
diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs
index 2758315..430d8e4 100644
--- a/src/remote_protocol-structs
+++ b/src/remote_protocol-structs
@@ -1832,6 +1832,10 @@ struct remote_node_suspend_for_duration_args {
uint64_t duration;
u_int flags;
};
+struct remote_domain_shutdown_flags_args {
+ remote_nonnull_domain dom;
+ u_int flags;
+};
enum remote_procedure {
REMOTE_PROC_OPEN = 1,
REMOTE_PROC_CLOSE = 2,
@@ -2090,4 +2094,5 @@ enum remote_procedure {
REMOTE_PROC_DOMAIN_GET_NUMA_PARAMETERS = 255,
REMOTE_PROC_DOMAIN_SET_INTERFACE_PARAMETERS = 256,
REMOTE_PROC_DOMAIN_GET_INTERFACE_PARAMETERS = 257,
+ REMOTE_PROC_DOMAIN_SHUTDOWN_FLAGS = 258,
};
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index c0b2ca6..55b889b 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -1542,13 +1542,16 @@ cleanup:
return ret;
}
-static int testShutdownDomain (virDomainPtr domain)
+static int testShutdownDomainFlags(virDomainPtr domain,
+ unsigned int flags)
{
testConnPtr privconn = domain->conn->privateData;
virDomainObjPtr privdom;
virDomainEventPtr event = NULL;
int ret = -1;
+ virCheckFlags(0, -1);
+
testDriverLock(privconn);
privdom = virDomainFindByName(&privconn->domains,
domain->name);
@@ -1585,6 +1588,11 @@ cleanup:
return ret;
}
+static int testShutdownDomain (virDomainPtr domain)
+{
+ return testShutdownDomainFlags(domain, 0);
+}
+
/* Similar behaviour as shutdown */
static int testRebootDomain (virDomainPtr domain,
unsigned int action ATTRIBUTE_UNUSED)
@@ -5523,6 +5531,7 @@ static virDriver testDriver = {
.domainSuspend = testPauseDomain, /* 0.1.1 */
.domainResume = testResumeDomain, /* 0.1.1 */
.domainShutdown = testShutdownDomain, /* 0.1.1 */
+ .domainShutdownFlags = testShutdownDomainFlags, /* 0.9.10 */
.domainReboot = testRebootDomain, /* 0.1.1 */
.domainDestroy = testDestroyDomain, /* 0.1.1 */
.domainGetOSType = testGetOSType, /* 0.1.9 */
diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c
index 671216e..a4cf945 100644
--- a/src/uml/uml_driver.c
+++ b/src/uml/uml_driver.c
@@ -1513,12 +1513,15 @@ cleanup:
}
-static int umlDomainShutdown(virDomainPtr dom) {
+static int umlDomainShutdownFlags(virDomainPtr dom,
+ unsigned int flags) {
struct uml_driver *driver = dom->conn->privateData;
virDomainObjPtr vm;
char *info = NULL;
int ret = -1;
+ virCheckFlags(0, -1);
+
umlDriverLock(driver);
vm = virDomainFindByID(&driver->domains, dom->id);
umlDriverUnlock(driver);
@@ -1544,6 +1547,11 @@ cleanup:
return ret;
}
+static int
+umlDomainShutdown(virDomainPtr dom)
+{
+ return umlDomainShutdownFlags(dom, 0);
+}
static int
umlDomainDestroyFlags(virDomainPtr dom,
@@ -2533,6 +2541,7 @@ static virDriver umlDriver = {
.domainLookupByUUID = umlDomainLookupByUUID, /* 0.5.0 */
.domainLookupByName = umlDomainLookupByName, /* 0.5.0 */
.domainShutdown = umlDomainShutdown, /* 0.5.0 */
+ .domainShutdownFlags = umlDomainShutdownFlags, /* 0.9.10 */
.domainDestroy = umlDomainDestroy, /* 0.5.0 */
.domainDestroyFlags = umlDomainDestroyFlags, /* 0.9.4 */
.domainGetOSType = umlDomainGetOSType, /* 0.5.0 */
diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index 22712d5..d720432 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -1606,7 +1606,8 @@ cleanup:
return ret;
}
-static int vboxDomainShutdown(virDomainPtr dom) {
+static int vboxDomainShutdownFlags(virDomainPtr dom,
+ unsigned int flags) {
VBOX_OBJECT_CHECK(dom->conn, int, -1);
IMachine *machine = NULL;
vboxIID iid = VBOX_IID_INITIALIZER;
@@ -1615,6 +1616,8 @@ static int vboxDomainShutdown(virDomainPtr dom) {
PRBool isAccessible = PR_FALSE;
nsresult rc;
+ virCheckFlags(0, -1);
+
vboxIIDFromUUID(&iid, dom->uuid);
rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine);
if (NS_FAILED(rc)) {
@@ -1656,6 +1659,11 @@ cleanup:
return ret;
}
+static int vboxDomainShutdown(virDomainPtr dom) {
+ return vboxDomainShutdownFlags(dom, 0);
+}
+
+
static int vboxDomainReboot(virDomainPtr dom, unsigned int flags)
{
VBOX_OBJECT_CHECK(dom->conn, int, -1);
@@ -9112,6 +9120,7 @@ virDriver NAME(Driver) = {
.domainSuspend = vboxDomainSuspend, /* 0.6.3 */
.domainResume = vboxDomainResume, /* 0.6.3 */
.domainShutdown = vboxDomainShutdown, /* 0.6.3 */
+ .domainShutdownFlags = vboxDomainShutdownFlags, /* 0.9.10 */
.domainReboot = vboxDomainReboot, /* 0.6.3 */
.domainDestroy = vboxDomainDestroy, /* 0.6.3 */
.domainDestroyFlags = vboxDomainDestroyFlags, /* 0.9.4 */
diff --git a/src/vmware/vmware_driver.c b/src/vmware/vmware_driver.c
index a9873ba..56e9d2d 100644
--- a/src/vmware/vmware_driver.c
+++ b/src/vmware/vmware_driver.c
@@ -980,6 +980,7 @@ static virDriver vmwareDriver = {
.domainSuspend = vmwareDomainSuspend, /* 0.8.7 */
.domainResume = vmwareDomainResume, /* 0.8.7 */
.domainShutdown = vmwareDomainShutdown, /* 0.8.7 */
+ .domainShutdownFlags = vmwareDomainShutdownFlags, /* 0.9.10 */
.domainReboot = vmwareDomainReboot, /* 0.8.7 */
.domainDestroy = vmwareDomainShutdown, /* 0.8.7 */
.domainDestroyFlags = vmwareDomainShutdownFlags, /* 0.9.4 */
diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c
index 520ec03..12d7eb0 100644
--- a/src/xen/xen_driver.c
+++ b/src/xen/xen_driver.c
@@ -851,21 +851,30 @@ xenUnifiedDomainResume (virDomainPtr dom)
}
static int
-xenUnifiedDomainShutdown (virDomainPtr dom)
+xenUnifiedDomainShutdownFlags(virDomainPtr dom,
+ unsigned int flags)
{
GET_PRIVATE(dom->conn);
int i;
+ virCheckFlags(0, -1);
+
for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
if (priv->opened[i] &&
drivers[i]->xenDomainShutdown &&
- drivers[i]->xenDomainShutdown (dom) == 0)
+ drivers[i]->xenDomainShutdown(dom) == 0)
return 0;
return -1;
}
static int
+xenUnifiedDomainShutdown(virDomainPtr dom)
+{
+ return xenUnifiedDomainShutdownFlags(dom, 0);
+}
+
+static int
xenUnifiedDomainReboot (virDomainPtr dom, unsigned int flags)
{
GET_PRIVATE(dom->conn);
@@ -2187,6 +2196,7 @@ static virDriver xenUnifiedDriver = {
.domainSuspend = xenUnifiedDomainSuspend, /* 0.0.3 */
.domainResume = xenUnifiedDomainResume, /* 0.0.3 */
.domainShutdown = xenUnifiedDomainShutdown, /* 0.0.3 */
+ .domainShutdownFlags = xenUnifiedDomainShutdownFlags, /* 0.9.10 */
.domainReboot = xenUnifiedDomainReboot, /* 0.1.0 */
.domainDestroy = xenUnifiedDomainDestroy, /* 0.0.3 */
.domainDestroyFlags = xenUnifiedDomainDestroyFlags, /* 0.9.4 */
diff --git a/src/xenapi/xenapi_driver.c b/src/xenapi/xenapi_driver.c
index 78137d4..68017bc 100644
--- a/src/xenapi/xenapi_driver.c
+++ b/src/xenapi/xenapi_driver.c
@@ -783,12 +783,15 @@ xenapiDomainResume (virDomainPtr dom)
* Returns 0 on success or -1 in case of error
*/
static int
-xenapiDomainShutdown (virDomainPtr dom)
+xenapiDomainShutdownFlags(virDomainPtr dom, unsigned int flags)
{
/* vm.clean_shutdown */
xen_vm vm;
xen_vm_set *vms;
xen_session *session = ((struct _xenapiPrivate
*)(dom->conn->privateData))->session;
+
+ virCheckFlags(0, -1);
+
if (xen_vm_get_by_name_label(session, &vms, dom->name) && vms->size
> 0) {
if (vms->size != 1) {
xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR,
@@ -811,6 +814,12 @@ xenapiDomainShutdown (virDomainPtr dom)
return -1;
}
+static int
+xenapiDomainShutdown(virDomainPtr dom)
+{
+ return xenapiDomainShutdownFlags(dom, 0);
+}
+
/*
* xenapiDomainReboot
*
@@ -1928,6 +1937,7 @@ static virDriver xenapiDriver = {
.domainSuspend = xenapiDomainSuspend, /* 0.8.0 */
.domainResume = xenapiDomainResume, /* 0.8.0 */
.domainShutdown = xenapiDomainShutdown, /* 0.8.0 */
+ .domainShutdownFlags = xenapiDomainShutdownFlags, /* 0.9.10 */
.domainReboot = xenapiDomainReboot, /* 0.8.0 */
.domainDestroy = xenapiDomainDestroy, /* 0.8.0 */
.domainDestroyFlags = xenapiDomainDestroyFlags, /* 0.9.4 */
--
1.7.3.4