From: "Daniel P. Berrange" <berrange(a)redhat.com>
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 seperately 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 | 59 ++++++++++++++++++++++++++++++++++++++++++
src/libvirt_public.syms | 1 +
src/libxl/libxl_driver.c | 12 ++++++++-
src/openvz/openvz_driver.c | 1 +
src/remote/remote_driver.c | 1 +
src/remote/remote_protocol.x | 9 +++++-
src/test/test_driver.c | 11 +++++++-
src/uml/uml_driver.c | 11 +++++++-
src/vbox/vbox_tmpl.c | 10 ++++++-
src/vmware/vmware_driver.c | 1 +
src/xen/xen_driver.c | 13 ++++++++-
src/xenapi/xenapi_driver.c | 11 +++++++-
15 files changed, 162 insertions(+), 9 deletions(-)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index bd7a0f7..dba2099 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -1028,7 +1028,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 f85a1b1..86857d5 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -725,6 +725,10 @@ typedef int
(*virDrvDomainBlockPull)(virDomainPtr dom, const char *path,
unsigned long bandwidth, unsigned int flags);
+typedef int
+ (*virDrvDomainShutdownFlags)(virDomainPtr domain,
+ unsigned int flags);
+
/**
* _virDriver:
@@ -881,6 +885,7 @@ struct _virDriver {
virDrvDomainGetBlockJobInfo domainGetBlockJobInfo;
virDrvDomainBlockJobSetSpeed domainBlockJobSetSpeed;
virDrvDomainBlockPull domainBlockPull;
+ virDrvDomainShutdownFlags domainShutdownFlags;
};
typedef int
diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
index 3f26557..b206239 100644
--- a/src/esx/esx_driver.c
+++ b/src/esx/esx_driver.c
@@ -1870,7 +1870,7 @@ esxDomainResume(virDomainPtr domain)
static int
-esxDomainShutdown(virDomainPtr domain)
+esxDomainShutdownFlags(virDomainPtr domain, unsigned int flags)
{
int result = -1;
esxPrivate *priv = domain->conn->privateData;
@@ -1878,6 +1878,8 @@ esxDomainShutdown(virDomainPtr domain)
esxVI_String *propertyNameList = NULL;
esxVI_VirtualMachinePowerState powerState;
+ virCheckFlags(0, -1);
+
if (esxVI_EnsureSession(priv->primary) < 0) {
return -1;
}
@@ -1911,6 +1913,12 @@ esxDomainShutdown(virDomainPtr domain)
}
+static int
+esxDomainShutdown(virDomainPtr domain)
+{
+ return esxDomainShutdownFlags(domain, 0);
+}
+
static int
esxDomainReboot(virDomainPtr domain, unsigned int flags)
@@ -4829,6 +4837,7 @@ static virDriver esxDriver = {
.domainSuspend = esxDomainSuspend, /* 0.7.0 */
.domainResume = esxDomainResume, /* 0.7.0 */
.domainShutdown = esxDomainShutdown, /* 0.7.0 */
+ .domainShutdownFlags = esxDomainShutdownFlags, /* 0.9.7 */
.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 9080b2f..1607b99 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -2970,6 +2970,65 @@ error:
}
/**
+ * virDomainShutdownFlags:
+ * @domain: a domain object
+ * @flags: optional flags
+ *
+ * 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 guests 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 shutdown flags
+ *
+ * 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 for the reboot operation, not used yet
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index afea29b..4186fd8 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -493,6 +493,7 @@ LIBVIRT_0.9.7 {
global:
virDomainReset;
virDomainSnapshotGetParent;
+ virDomainShutdownFlags;
} LIBVIRT_0.9.5;
# .... define new API here using predicted next version number ....
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
index d324632..da1031c 100644
--- a/src/libxl/libxl_driver.c
+++ b/src/libxl/libxl_driver.c
@@ -1440,13 +1440,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) {
@@ -1484,6 +1486,13 @@ cleanup:
}
static int
+libxlDomainShutdown(virDomainPtr dom)
+{
+ return libxlDomainShutdownFlags(dom, 0);
+}
+
+
+static int
libxlDomainReboot(virDomainPtr dom, unsigned int flags)
{
libxlDriverPrivatePtr driver = dom->conn->privateData;
@@ -3895,6 +3904,7 @@ static virDriver libxlDriver = {
.domainSuspend = libxlDomainSuspend, /* 0.9.0 */
.domainResume = libxlDomainResume, /* 0.9.0 */
.domainShutdown = libxlDomainShutdown, /* 0.9.0 */
+ .domainShutdownFlags = libxlDomainShutdownFlags, /* 0.9.7 */
.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 69ff444..32e1bfe 100644
--- a/src/openvz/openvz_driver.c
+++ b/src/openvz/openvz_driver.c
@@ -1689,6 +1689,7 @@ static virDriver openvzDriver = {
.domainSuspend = openvzDomainSuspend, /* 0.8.3 */
.domainResume = openvzDomainResume, /* 0.8.3 */
.domainShutdown = openvzDomainShutdown, /* 0.3.1 */
+ .domainShutdownFlags = openvzDomainShutdownFlags, /* 0.9.7 */
.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 83f4f3c..eaf8bbd 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -4312,6 +4312,7 @@ static virDriver remote_driver = {
.domainSuspend = remoteDomainSuspend, /* 0.3.0 */
.domainResume = remoteDomainResume, /* 0.3.0 */
.domainShutdown = remoteDomainShutdown, /* 0.3.0 */
+ .domainShutdownFlags = remoteDomainShutdownFlags, /* 0.9.7 */
.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 c8a92fd..34e4b2a 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -2234,6 +2234,12 @@ struct remote_domain_get_control_info_ret { /* insert@1 */
unsigned hyper stateTime;
};
+struct remote_domain_shutdown_flags_args {
+ remote_nonnull_domain dom;
+ unsigned int flags;
+};
+
+
/*----- Protocol. -----*/
/* Define the program number, protocol version and procedure numbers here. */
@@ -2525,7 +2531,8 @@ enum remote_procedure {
REMOTE_PROC_DOMAIN_MIGRATE_GET_MAX_SPEED = 242, /* autogen autogen */
REMOTE_PROC_DOMAIN_BLOCK_STATS_FLAGS = 243, /* skipgen skipgen */
REMOTE_PROC_DOMAIN_SNAPSHOT_GET_PARENT = 244, /* autogen autogen */
- REMOTE_PROC_DOMAIN_RESET = 245 /* autogen autogen */
+ REMOTE_PROC_DOMAIN_RESET = 245, /* autogen autogen */
+ REMOTE_PROC_DOMAIN_SHUTDOWN_FLAGS = 246 /* autogen autogen */
/*
* Notice how the entries are grouped in sets of 10 ?
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index b3e24b4..3efed78 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -1533,13 +1533,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);
@@ -1576,6 +1579,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)
@@ -5578,6 +5586,7 @@ static virDriver testDriver = {
.domainSuspend = testPauseDomain, /* 0.1.1 */
.domainResume = testResumeDomain, /* 0.1.1 */
.domainShutdown = testShutdownDomain, /* 0.1.1 */
+ .domainShutdownFlags = testShutdownDomainFlags, /* 0.9.7 */
.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 2b7219a..5a90031 100644
--- a/src/uml/uml_driver.c
+++ b/src/uml/uml_driver.c
@@ -1385,12 +1385,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);
@@ -1416,6 +1419,11 @@ cleanup:
return ret;
}
+static int
+umlDomainShutdown(virDomainPtr dom)
+{
+ return umlDomainShutdownFlags(dom, 0);
+}
static int
umlDomainDestroyFlags(virDomainPtr dom,
@@ -2425,6 +2433,7 @@ static virDriver umlDriver = {
.domainLookupByUUID = umlDomainLookupByUUID, /* 0.5.0 */
.domainLookupByName = umlDomainLookupByName, /* 0.5.0 */
.domainShutdown = umlDomainShutdown, /* 0.5.0 */
+ .domainShutdownFlags = umlDomainShutdownFlags, /* 0.9.7 */
.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 8c53f1f..efa5dd6 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -1590,7 +1590,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;
@@ -1599,6 +1600,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)) {
@@ -1640,6 +1643,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);
diff --git a/src/vmware/vmware_driver.c b/src/vmware/vmware_driver.c
index b2cfdce..6dba82f 100644
--- a/src/vmware/vmware_driver.c
+++ b/src/vmware/vmware_driver.c
@@ -974,6 +974,7 @@ static virDriver vmwareDriver = {
.domainSuspend = vmwareDomainSuspend, /* 0.8.7 */
.domainResume = vmwareDomainResume, /* 0.8.7 */
.domainShutdown = vmwareDomainShutdown, /* 0.8.7 */
+ .domainShutdownFlags = vmwareDomainShutdownFlags, /* 0.9.7 */
.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 9c96fca..51d83af 100644
--- a/src/xen/xen_driver.c
+++ b/src/xen/xen_driver.c
@@ -855,21 +855,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);
diff --git a/src/xenapi/xenapi_driver.c b/src/xenapi/xenapi_driver.c
index 80a706a..49b29b8 100644
--- a/src/xenapi/xenapi_driver.c
+++ b/src/xenapi/xenapi_driver.c
@@ -773,12 +773,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,
@@ -801,6 +804,12 @@ xenapiDomainShutdown (virDomainPtr dom)
return -1;
}
+static int
+xenapiDomainShutdown(virDomainPtr dom)
+{
+ return xenapiDomainShutdownFlags(dom, 0);
+}
+
/*
* xenapiDomainReboot
*
--
1.7.6