* libxl_set_vcpuonline()
* libxl_retrieve_domain_configuration()
* libxl_qemu_monitor_command()
+ * libxl_domain_shutdown()
+ * libxl_domain_reboot()
*/
#define LIBXL_HAVE_FN_USING_QMP_ASYNC 1
const libxl_asyncop_how *ao_how)
LIBXL_EXTERNAL_CALLERS_ONLY;
-int libxl_domain_shutdown(libxl_ctx *ctx, uint32_t domid);
-int libxl_domain_reboot(libxl_ctx *ctx, uint32_t domid);
+int libxl_domain_shutdown(libxl_ctx *ctx, uint32_t domid,
+ const libxl_asyncop_how *ao_how)
+ LIBXL_EXTERNAL_CALLERS_ONLY;
+int libxl_domain_reboot(libxl_ctx *ctx, uint32_t domid,
+ const libxl_asyncop_how *ao_how)
+ LIBXL_EXTERNAL_CALLERS_ONLY;
+#if defined(LIBXL_API_VERSION) && LIBXL_API_VERSION < 0x041300
+static inline int libxl_domain_shutdown_0x041200(libxl_ctx *ctx,
+ uint32_t domid)
+{
+ return libxl_domain_shutdown(ctx, domid, NULL);
+}
+#define libxl_domain_shutdown libxl_domain_shutdown_0x041200
+static inline int libxl_domain_reboot_0x041200(libxl_ctx *ctx,
+ uint32_t domid)
+{
+ return libxl_domain_reboot(ctx, domid, NULL);
+}
+#define libxl_domain_reboot libxl_domain_reboot_0x041200
+#endif
+
int libxl_domain_destroy(libxl_ctx *ctx, uint32_t domid,
const libxl_asyncop_how *ao_how)
LIBXL_EXTERNAL_CALLERS_ONLY;
LOGD(DEBUG, domid, "issuing %s suspend request via XenBus control node",
dsps->type != LIBXL_DOMAIN_TYPE_PV ? "PVH/HVM" : "PV");
- libxl__domain_pvcontrol_write(gc, XBT_NULL, domid, "suspend");
-
- dsps->pvcontrol.path = libxl__domain_pvcontrol_xspath(gc, domid);
- if (!dsps->pvcontrol.path) { rc = ERROR_FAIL; goto err; }
-
dsps->pvcontrol.ao = ao;
- dsps->pvcontrol.what = "guest acknowledgement of suspend request";
- dsps->pvcontrol.timeout_ms = 60 * 1000;
dsps->pvcontrol.callback = domain_suspend_common_pvcontrol_suspending;
- libxl__xswait_start(gc, &dsps->pvcontrol);
+ rc = libxl__domain_pvcontrol(egc, &dsps->pvcontrol, domid, "suspend");
+ if (rc) goto err;
+
return;
err:
return libxl__xs_read(gc, t, shutdown_path);
}
-int libxl__domain_pvcontrol_write(libxl__gc *gc, xs_transaction_t t,
- uint32_t domid, const char *cmd)
+int libxl__domain_pvcontrol(libxl__egc *egc, libxl__xswait_state *pvcontrol,
+ domid_t domid, const char *cmd)
{
+ STATE_AO_GC(pvcontrol->ao);
const char *shutdown_path;
+ int rc;
+
+ rc = libxl__domain_pvcontrol_available(gc, domid);
+ if (rc < 0)
+ return rc;
shutdown_path = libxl__domain_pvcontrol_xspath(gc, domid);
if (!shutdown_path)
return ERROR_FAIL;
- return libxl__xs_printf(gc, t, shutdown_path, "%s", cmd);
+ rc = libxl__xs_printf(gc, XBT_NULL, shutdown_path, "%s", cmd);
+ if (rc)
+ return rc;
+
+ pvcontrol->path = shutdown_path;
+ pvcontrol->what = GCSPRINTF("guest acknowledgement of %s request", cmd);
+ pvcontrol->timeout_ms = 60 * 1000;
+ rc = libxl__xswait_start(gc, pvcontrol);
+ if (rc)
+ return rc;
+
+ return 0;
}
-static int libxl__domain_pvcontrol(libxl__gc *gc, uint32_t domid,
- const char *cmd)
+static bool pvcontrol_acked(const char *state)
{
- int ret;
+ if (!state || !strcmp(state,""))
+ return true;
- ret = libxl__domain_pvcontrol_available(gc, domid);
- if (ret < 0)
- return ret;
+ return false;
+}
- if (!ret)
- return ERROR_NOPARAVIRT;
+/* Xenstore watch callback prototype for the reboot/poweroff operations. */
+static void pvcontrol_cb(libxl__egc *egc, libxl__xswait_state *xswa, int rc,
+ const char *state);
- return libxl__domain_pvcontrol_write(gc, XBT_NULL, domid, cmd);
+int libxl_domain_shutdown(libxl_ctx *ctx, uint32_t domid,
+ const libxl_asyncop_how *ao_how)
+{
+ AO_CREATE(ctx, domid, ao_how);
+ libxl__xswait_state *pvcontrol;
+ int rc;
+
+ GCNEW(pvcontrol);
+ pvcontrol->ao = ao;
+ pvcontrol->callback = pvcontrol_cb;
+ rc = libxl__domain_pvcontrol(egc, pvcontrol, domid, "poweroff");
+
+ return rc ? AO_CREATE_FAIL(rc) : AO_INPROGRESS;
}
-int libxl_domain_shutdown(libxl_ctx *ctx, uint32_t domid)
+int libxl_domain_reboot(libxl_ctx *ctx, uint32_t domid,
+ const libxl_asyncop_how *ao_how)
{
- GC_INIT(ctx);
- int ret;
- ret = libxl__domain_pvcontrol(gc, domid, "poweroff");
- GC_FREE;
- return ret;
+ AO_CREATE(ctx, domid, ao_how);
+ libxl__xswait_state *pvcontrol;
+ int rc;
+
+ GCNEW(pvcontrol);
+ pvcontrol->ao = ao;
+ pvcontrol->callback = pvcontrol_cb;
+ rc = libxl__domain_pvcontrol(egc, pvcontrol, domid, "reboot");
+
+ return rc ? AO_CREATE_FAIL(rc) : AO_INPROGRESS;
}
-int libxl_domain_reboot(libxl_ctx *ctx, uint32_t domid)
+static void pvcontrol_cb(libxl__egc *egc, libxl__xswait_state *xswa, int rc,
+ const char *state)
{
- GC_INIT(ctx);
- int ret;
- ret = libxl__domain_pvcontrol(gc, domid, "reboot");
- GC_FREE;
- return ret;
+ STATE_AO_GC(xswa->ao);
+
+ if (!rc && !pvcontrol_acked(state))
+ return;
+
+ libxl__xswait_stop(gc, xswa);
+
+ if (rc)
+ LOG(ERROR, "guest didn't acknowledge control request: %d", rc);
+
+ libxl__ao_complete(egc, ao, rc);
}
static void domain_death_occurred(libxl__egc *egc,
_hidden const char *libxl__domain_pvcontrol_xspath(libxl__gc*, uint32_t domid);
_hidden char * libxl__domain_pvcontrol_read(libxl__gc *gc,
xs_transaction_t t, uint32_t domid);
-_hidden int libxl__domain_pvcontrol_write(libxl__gc *gc, xs_transaction_t t,
- uint32_t domid, const char *cmd);
/* from xl_device */
_hidden char *libxl__device_disk_string_of_backend(libxl_disk_backend backend);
_hidden void libxl__ev_devlock_lock(libxl__egc *, libxl__ev_devlock *);
_hidden void libxl__ev_devlock_unlock(libxl__gc *, libxl__ev_devlock *);
+/* Send control commands over xenstore and wait for an Ack. */
+_hidden int libxl__domain_pvcontrol(libxl__egc *egc,
+ libxl__xswait_state *pvcontrol,
+ domid_t domid, const char *cmd);
+
#endif
/*
external create_new : ctx -> Domain_config.t -> ?async:'a -> unit -> domid = "stub_libxl_domain_create_new"
external create_restore : ctx -> Domain_config.t -> (Unix.file_descr * Domain_restore_params.t) ->
?async:'a -> unit -> domid = "stub_libxl_domain_create_restore"
- external shutdown : ctx -> domid -> unit = "stub_libxl_domain_shutdown"
- external reboot : ctx -> domid -> unit = "stub_libxl_domain_reboot"
+ external shutdown : ctx -> domid -> ?async:'a -> unit -> unit = "stub_libxl_domain_shutdown"
+ external reboot : ctx -> domid -> ?async:'a -> unit -> unit = "stub_libxl_domain_reboot"
external destroy : ctx -> domid -> ?async:'a -> unit -> unit = "stub_libxl_domain_destroy"
external suspend : ctx -> domid -> Unix.file_descr -> ?async:'a -> unit -> unit = "stub_libxl_domain_suspend"
external pause : ctx -> domid -> ?async:'a -> unit = "stub_libxl_domain_pause"
external create_new : ctx -> Domain_config.t -> ?async:'a -> unit -> domid = "stub_libxl_domain_create_new"
external create_restore : ctx -> Domain_config.t -> (Unix.file_descr * Domain_restore_params.t) ->
?async:'a -> unit -> domid = "stub_libxl_domain_create_restore"
- external shutdown : ctx -> domid -> unit = "stub_libxl_domain_shutdown"
- external reboot : ctx -> domid -> unit = "stub_libxl_domain_reboot"
+ external shutdown : ctx -> domid -> ?async:'a -> unit -> unit = "stub_libxl_domain_shutdown"
+ external reboot : ctx -> domid -> ?async:'a -> unit -> unit = "stub_libxl_domain_reboot"
external destroy : ctx -> domid -> ?async:'a -> unit -> unit = "stub_libxl_domain_destroy"
external suspend : ctx -> domid -> Unix.file_descr -> ?async:'a -> unit -> unit = "stub_libxl_domain_suspend"
external pause : ctx -> domid -> ?async:'a -> unit = "stub_libxl_domain_pause"
CAMLreturn(Val_int(c_domid));
}
-value stub_libxl_domain_shutdown(value ctx, value domid)
+value stub_libxl_domain_shutdown(value ctx, value domid, value async, value unit)
{
- CAMLparam2(ctx, domid);
+ CAMLparam4(ctx, domid, async, unit);
int ret;
uint32_t c_domid = Int_val(domid);
+ libxl_asyncop_how *ao_how = aohow_val(async);
caml_enter_blocking_section();
- ret = libxl_domain_shutdown(CTX, c_domid);
+ ret = libxl_domain_shutdown(CTX, c_domid, ao_how);
caml_leave_blocking_section();
+ free(ao_how);
+
if (ret != 0)
failwith_xl(ret, "domain_shutdown");
CAMLreturn(Val_unit);
}
-value stub_libxl_domain_reboot(value ctx, value domid)
+value stub_libxl_domain_reboot(value ctx, value domid, value async, value unit)
{
- CAMLparam2(ctx, domid);
+ CAMLparam4(ctx, domid, async, unit);
int ret;
uint32_t c_domid = Int_val(domid);
+ libxl_asyncop_how *ao_how = aohow_val(async);
caml_enter_blocking_section();
- ret = libxl_domain_reboot(CTX, c_domid);
+ ret = libxl_domain_reboot(CTX, c_domid, ao_how);
caml_leave_blocking_section();
+ free(ao_how);
+
if (ret != 0)
failwith_xl(ret, "domain_reboot");
int rc;
fprintf(stderr, "Rebooting domain %u\n", domid);
- rc=libxl_domain_reboot(ctx, domid);
+ rc = libxl_domain_reboot(ctx, domid, NULL);
if (rc == ERROR_NOPARAVIRT) {
if (fallback_trigger) {
fprintf(stderr, "PV control interface not available:"
int rc;
fprintf(stderr, "Shutting down domain %u\n", domid);
- rc=libxl_domain_shutdown(ctx, domid);
+ rc = libxl_domain_shutdown(ctx, domid, NULL);
if (rc == ERROR_NOPARAVIRT) {
if (fallback_trigger) {
fprintf(stderr, "PV control interface not available:"