[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 9 of 9] xl: support on_{poweroff, reboot, crash} domain configuration options



# 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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.