virDomainPtr virDomainLookupByUUIDString (virConnectPtr conn,
const char *uuid);
+typedef enum {
+ VIR_DOMAIN_SHUTDOWN_DEFAULT = 0, /* hypervisor choice */
+ 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 choice */
+ 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,
virTypedParameterPtr params,
int *nparams,
unsigned int flags);
+typedef int
+ (*virDrvDomainShutdownFlags)(virDomainPtr domain,
+ unsigned int flags);
+
/**
* _virDriver:
virDrvDomainSuspend domainSuspend;
virDrvDomainResume domainResume;
virDrvDomainShutdown domainShutdown;
+ virDrvDomainShutdownFlags domainShutdownFlags;
virDrvDomainReboot domainReboot;
virDrvDomainReset domainReset;
virDrvDomainDestroy domainDestroy;
static int
-esxDomainShutdown(virDomainPtr domain)
+esxDomainShutdownFlags(virDomainPtr domain, unsigned int flags)
{
int result = -1;
esxPrivate *priv = domain->conn->privateData;
esxVI_String *propertyNameList = NULL;
esxVI_VirtualMachinePowerState powerState;
+ virCheckFlags(0, -1);
+
if (esxVI_EnsureSession(priv->primary) < 0) {
return -1;
}
}
+static int
+esxDomainShutdown(virDomainPtr domain)
+{
+ return esxDomainShutdownFlags(domain, 0);
+}
+
static int
esxDomainReboot(virDomainPtr domain, unsigned int flags)
.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 */
return -1;
}
+/**
+ * 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 choose 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;
+ }
+
+ /* At most one of these two flags should be set. */
+ if ((flags & VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN) &&
+ (flags & VIR_DOMAIN_SHUTDOWN_GUEST_AGENT)) {
+ virLibDomainError(VIR_ERR_INVALID_ARG, __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 choose 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
goto error;
}
+ /* At most one of these two flags should be set. */
+ if ((flags & VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN) &&
+ (flags & VIR_DOMAIN_SHUTDOWN_GUEST_AGENT)) {
+ virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__);
+ goto error;
+ }
+
conn = domain->conn;
if (conn->driver->domainReboot) {
virDomainSetNumaParameters;
} LIBVIRT_0.9.8;
+LIBVIRT_0.9.10 {
+ global:
+ virDomainShutdownFlags;
+} LIBVIRT_0.9.9;
# .... define new API here using predicted next version number ....
}
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) {
return ret;
}
+static int
+libxlDomainShutdown(virDomainPtr dom)
+{
+ return libxlDomainShutdownFlags(dom, 0);
+}
+
+
static int
libxlDomainReboot(virDomainPtr dom, unsigned int flags)
{
.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 */
.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 */
.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 */
unsigned int flags;
};
+struct remote_domain_shutdown_flags_args {
+ remote_nonnull_domain dom;
+ unsigned int flags;
+};
+
/*----- Protocol. -----*/
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 ?
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,
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,
};
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);
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)
.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 */
}
-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);
return ret;
}
+static int
+umlDomainShutdown(virDomainPtr dom)
+{
+ return umlDomainShutdownFlags(dom, 0);
+}
static int
umlDomainDestroyFlags(virDomainPtr dom,
.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 */
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;
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)) {
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);
.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 */
.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 */
}
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)
{
.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 */
* 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,
return -1;
}
+static int
+xenapiDomainShutdown(virDomainPtr dom)
+{
+ return xenapiDomainShutdownFlags(dom, 0);
+}
+
/*
* xenapiDomainReboot
*
.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 */