# HG changeset patch
# User Ian Campbell <ian.campbell@xxxxxxxxxx>
# Date 1280140563 -3600
# Node ID 113b04a7e60718c8730368a045a49ddd56e64fac
# Parent ee265e700eede4111e429a3c55d2c78f31805028
xl: support on_{poweroff,reboot,crash} domain configuration options.
Adds on_watchdog compared to xend.
I have further plans for struct domain_config so it isn't as pointless
as it first looks.
Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx>
diff -r ee265e700eed -r 113b04a7e607 tools/libxl/xl_cmdimpl.c
--- a/tools/libxl/xl_cmdimpl.c Mon Jul 26 11:36:03 2010 +0100
+++ b/tools/libxl/xl_cmdimpl.c Mon Jul 26 11:36:03 2010 +0100
@@ -99,6 +99,38 @@ struct save_file_header {
uint32_t optional_data_len; /* skip, or skip tail, if not understood */
};
+
+enum action_on_shutdown {
+ ACTION_DESTROY,
+
+ ACTION_RESTART,
+ ACTION_RESTART_RENAME,
+
+ ACTION_PRESERVE,
+
+ ACTION_COREDUMP_DESTROY,
+ ACTION_COREDUMP_RESTART,
+};
+
+static char *action_on_shutdown_names[] = {
+ [ACTION_DESTROY] = "destroy",
+
+ [ACTION_RESTART] = "restart",
+ [ACTION_RESTART_RENAME] = "rename-restart",
+
+ [ACTION_PRESERVE] = "preserve",
+
+ [ACTION_COREDUMP_DESTROY] = "coredump-destroy",
+ [ACTION_COREDUMP_RESTART] = "coredump-restart",
+};
+
+struct domain_config {
+ enum action_on_shutdown on_poweroff;
+ enum action_on_shutdown on_reboot;
+ enum action_on_shutdown on_watchdog;
+ enum action_on_shutdown on_crash;
+};
+
/* Optional data, in order:
* 4 bytes uint32_t config file size
* n bytes config file in Unix text file format
@@ -472,11 +504,28 @@ static void printf_info(int domid,
printf(")\n");
}
+static int parse_action_on_shutdown(const char *buf, enum action_on_shutdown
*a)
+{
+ int i;
+ const char *n;
+
+ for (i = 0; i < sizeof(action_on_shutdown_names) /
sizeof(action_on_shutdown_names[0]); i++) {
+ n = action_on_shutdown_names[i];
+
+ if (strcmp(buf, n) == 0) {
+ *a = i;
+ return 1;
+ }
+ }
+ return 0;
+}
+
static void parse_config_data(const char *configfile_filename_report,
const char *configfile_data,
int configfile_len,
libxl_domain_create_info *c_info,
libxl_domain_build_info *b_info,
+ struct domain_config *d_config,
libxl_device_disk **disks,
int *num_disks,
libxl_device_nic **vifs,
@@ -551,6 +600,35 @@ static void parse_config_data(const char
if (!xlu_cfg_get_long (config, "memory", &l)) {
b_info->max_memkb = l * 1024;
b_info->target_memkb = b_info->max_memkb;
+ }
+
+ if (xlu_cfg_get_string (config, "on_poweroff", &buf))
+ buf = "destroy";
+ if (!parse_action_on_shutdown(buf, &d_config->on_poweroff)) {
+ fprintf(stderr, "Unknown on_poweroff action \"%s\" specified\n", buf);
+ exit(1);
+ }
+
+ if (xlu_cfg_get_string (config, "on_reboot", &buf))
+ buf = "restart";
+ if (!parse_action_on_shutdown(buf, &d_config->on_reboot)) {
+ fprintf(stderr, "Unknown on_reboot action \"%s\" specified\n", buf);
+ exit(1);
+ }
+
+ if (xlu_cfg_get_string (config, "on_watchdog", &buf))
+ buf = "destroy";
+ if (!parse_action_on_shutdown(buf, &d_config->on_watchdog)) {
+ fprintf(stderr, "Unknown on_watchdog action \"%s\" specified\n", buf);
+ exit(1);
+ }
+
+
+ if (xlu_cfg_get_string (config, "on_crash", &buf))
+ buf = "destroy";
+ if (!parse_action_on_shutdown(buf, &d_config->on_crash)) {
+ fprintf(stderr, "Unknown on_crash action \"%s\" specified\n", buf);
+ exit(1);
}
/* libxl_get_required_shadow_memory() must be called after final values
@@ -988,16 +1066,112 @@ int autoconnect_console(int hvm)
_exit(1);
}
-/* Returns 1 if domain should be restarted */
-static int handle_domain_death(struct libxl_ctx *ctx, uint32_t domid,
libxl_event *event, struct libxl_dominfo *info)
-{
- if (info->shutdown_reason != SHUTDOWN_suspend) {
- LOG("Domain %d needs to be clean: destroying the domain", domid);
+/* Returns 1 if domain should be restarted, 2 if domain should be renamed then
restarted */
+static int handle_domain_death(struct libxl_ctx *ctx, uint32_t domid,
libxl_event *event,
+ libxl_domain_create_info *c_info,
+ struct domain_config *d_config, struct
libxl_dominfo *info)
+{
+ int restart = 0;
+ enum action_on_shutdown action;
+
+ switch (info->shutdown_reason) {
+ case LIBXL_SHUTDOWN_POWEROFF:
+ action = d_config->on_poweroff;
+ break;
+ case LIBXL_SHUTDOWN_REBOOT:
+ action = d_config->on_reboot;
+ break;
+ case LIBXL_SHUTDOWN_SUSPEND:
+ return 0;
+ case LIBXL_SHUTDOWN_CRASH:
+ action = d_config->on_crash;
+ break;
+ case LIBXL_SHUTDOWN_WATCHDOG:
+ action = d_config->on_watchdog;
+ break;
+ }
+
+ LOG("Action for shutdown reason code %d is %s", info->shutdown_reason,
action_on_shutdown_names[action]);
+
+ if (action == ACTION_COREDUMP_DESTROY || action ==
ACTION_COREDUMP_RESTART) {
+ char *corefile;
+ int rc;
+
+ if (asprintf(&corefile, "/var/xen/dump/%s", c_info->name) < 0) {
+ LOG("failed to construct core dump path");
+ } else {
+ LOG("dumping core to %s", corefile);
+ rc=libxl_domain_core_dump(ctx, domid, corefile);
+ if (rc) LOG("core dump failed (rc=%d).", rc);
+ }
+ /* No point crying over spilled milk, continue on failure. */
+
+ if (action == ACTION_COREDUMP_DESTROY)
+ action = ACTION_DESTROY;
+ else
+ action = ACTION_RESTART;
+ }
+
+ switch (action) {
+ case ACTION_PRESERVE:
+ break;
+
+ case ACTION_RESTART_RENAME:
+ restart = 2;
+ break;
+
+ case ACTION_RESTART:
+ restart = 1;
+ /* fall-through */
+ case ACTION_DESTROY:
+ LOG("Domain %d needs to be cleaned up: destroying the domain", domid);
libxl_domain_destroy(ctx, domid, 0);
- if (info->shutdown_reason == SHUTDOWN_reboot)
- return 1;
- }
- return 0;
+ break;
+
+ case ACTION_COREDUMP_DESTROY:
+ case ACTION_COREDUMP_RESTART:
+ /* Already handled these above. */
+ abort();
+ }
+
+ return restart;
+}
+
+static int preserve_domain(struct libxl_ctx *ctx, uint32_t domid, libxl_event
*event,
+ libxl_domain_create_info *c_info,
+ struct domain_config *d_config, struct
libxl_dominfo *info)
+{
+ time_t now;
+ struct tm tm;
+ char stime[24];
+
+ uint8_t new_uuid[16];
+
+ int rc;
+
+ now = time(NULL);
+ if (now == ((time_t) -1)) {
+ LOG("Failed to get current time for domain rename");
+ return 0;
+ }
+
+ tzset();
+ if (gmtime_r(&now, &tm) == NULL) {
+ LOG("Failed to convert time to UTC");
+ return 0;
+ }
+
+ if (!strftime(&stime[0], sizeof(stime), "-%Y%m%dT%H%MZ", &tm)) {
+ LOG("Failed to format time as a string");
+ return 0;
+ }
+
+ random_uuid(&new_uuid[0]);
+
+ LOG("Preserving domain %d %s with suffix%s", domid, c_info->name, stime);
+ rc = libxl_domain_preserve(ctx, domid, c_info, stime, new_uuid);
+
+ return rc == 0 ? 1 : 0;
}
struct domain_create {
@@ -1016,6 +1190,8 @@ struct domain_create {
static int create_domain(struct domain_create *dom_info)
{
+ struct domain_config d_config;
+
libxl_domain_create_info c_info;
libxl_domain_build_info b_info;
libxl_domain_build_state state;
@@ -1150,7 +1326,7 @@ static int create_domain(struct domain_c
if (!dom_info->quiet)
printf("Parsing config file %s\n", config_file);
- parse_config_data(config_file, config_data, config_len, &c_info, &b_info,
&disks, &num_disks, &vifs, &num_vifs, &vif2s, &num_vif2s, &pcidevs,
&num_pcidevs, &vfbs, &num_vfbs, &vkbs, &num_vkbs, &dm_info);
+ parse_config_data(config_file, config_data, config_len, &c_info, &b_info,
&d_config, &disks, &num_disks, &vifs, &num_vifs, &vif2s, &num_vif2s, &pcidevs,
&num_pcidevs, &vfbs, &num_vfbs, &vkbs, &num_vkbs, &dm_info);
if (dom_info->dryrun)
return 0;
@@ -1369,13 +1545,20 @@ start:
switch (event.type) {
case LIBXL_EVENT_DOMAIN_DEATH:
ret = libxl_event_get_domain_death_info(&ctx, domid, &event,
&info);
-
if (ret < 0) continue;
LOG("Domain %d is dead", domid);
if (ret) {
- if (handle_domain_death(&ctx, domid, &event, &info)) {
+ switch (handle_domain_death(&ctx, domid, &event, &c_info,
&d_config, &info)) {
+ case 2:
+ if (!preserve_domain(&ctx, domid, &event, &c_info,
&d_config, &info))
+ /* If we fail then exit leaving the old domain in
place. */
+ exit(-1);
+
+ /* Otherwise fall through and restart. */
+ case 1:
+
libxl_free_waiter(w1);
libxl_free_waiter(w2);
free(w1);
@@ -1387,9 +1570,10 @@ start:
LOG("Done. Rebooting now");
sleep(2);
goto start;
+ case 0:
+ LOG("Done. Exiting now");
+ exit(0);
}
- LOG("Done. Exiting now");
- exit(0);
}
break;
case LIBXL_EVENT_DISK_EJECT:
@@ -1898,6 +2082,8 @@ void list_domains_details(void)
void list_domains_details(void)
{
struct libxl_dominfo *info;
+ struct domain_config d_config;
+
char *config_file;
uint8_t *data;
int nb_domain, i, len, rc;
@@ -1923,7 +2109,7 @@ void list_domains_details(void)
if (rc)
continue;
CHK_ERRNO(asprintf(&config_file, "<domid %d data>", info[i].domid));
- parse_config_data(config_file, (char *)data, len, &c_info, &b_info,
&disks, &num_disks, &vifs, &num_vifs, &vif2s, &num_vif2s, &pcidevs,
&num_pcidevs, &vfbs, &num_vfbs, &vkbs, &num_vkbs, &dm_info);
+ parse_config_data(config_file, (char *)data, len, &c_info, &b_info,
&d_config, &disks, &num_disks, &vifs, &num_vifs, &vif2s, &num_vif2s, &pcidevs,
&num_pcidevs, &vfbs, &num_vfbs, &vkbs, &num_vkbs, &dm_info);
printf_info(info[i].domid, &c_info, &b_info, disks, num_disks, vifs,
num_vifs, pcidevs, num_pcidevs, vfbs, num_vfbs, vkbs, num_vkbs, &dm_info);
free(data);
free(config_file);
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|