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 | 65 +++++++++++++++++++++++++++++++++++++++++-
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, 177 insertions(+), 10 deletions(-)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index e436f3c..27546af 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -1148,7 +1148,22 @@ virDomainPtr virDomainLookupByUUID (virConnectPtr
conn,
virDomainPtr virDomainLookupByUUIDString (virConnectPtr conn,
const char *uuid);
+typedef enum {
+ VIR_DOMAIN_SHUTDOWN_DEFAULT = 0,
+ VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN = (1 << 0),
+ VIR_DOMAIN_SHUTDOWN_GUEST_AGENT = (1 << 1),
+} virDomainShutdownFlagValues;
+
int virDomainShutdown (virDomainPtr domain);
+int virDomainShutdownFlags (virDomainPtr domain,
+ unsigned int flags);
+
+typedef enum {
+ VIR_DOMAIN_REBOOT_DEFAULT = 0,
+ VIR_DOMAIN_REBOOT_ACPI_POWER_BTN = (1 << 0),
+ VIR_DOMAIN_REBOOT_GUEST_AGENT = (1 << 1),
+} 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 1e424eb..4ad7a37 100644
--- a/src/esx/esx_driver.c
+++ b/src/esx/esx_driver.c
@@ -1886,7 +1886,7 @@ esxDomainResume(virDomainPtr domain)
static int
-esxDomainShutdown(virDomainPtr domain)
+esxDomainShutdownFlags(virDomainPtr domain, unsigned int flags)
{
int result = -1;
esxPrivate *priv = domain->conn->privateData;
@@ -1894,6 +1894,8 @@ esxDomainShutdown(virDomainPtr domain)
esxVI_String *propertyNameList = NULL;
esxVI_VirtualMachinePowerState powerState;
+ virCheckFlags(0, -1);
+
if (esxVI_EnsureSession(priv->primary) < 0) {
return -1;
}
@@ -1927,6 +1929,12 @@ esxDomainShutdown(virDomainPtr domain)
}
+static int
+esxDomainShutdown(virDomainPtr domain)
+{
+ return esxDomainShutdownFlags(domain, 0);
+}
+
static int
esxDomainReboot(virDomainPtr domain, unsigned int flags)
@@ -4960,6 +4968,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 a540424..9409a24 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -3106,14 +3106,77 @@ 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 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 one of the virDomainRebootFlagValues.
+ *
* 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 0500ed0..e2b174e 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;
@@ -3877,6 +3886,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 ca739ff..a9049ce 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -2348,6 +2348,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. -----*/
@@ -2653,7 +2658,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 2a98e7e..f12112e 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -1541,13 +1541,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);
@@ -1584,6 +1587,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)
@@ -5528,6 +5536,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 20671c0..5cbbecd 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