xl: handle domain shutdown/reboot/crash in a user configurable way
PATCH 1/1 xl: handle domain shutdown/reboot/crash in a user configurable way
Add support for on_poweroff, on_reboot and on_crash configuration items. In addition to these options from xend also add on_watchdog.
Since previous posting I have:
* clarified the semantics of libxl_dominfo WRT when shutdown_reason is valid and is not valid
* dropped the crashed bit field from libxl_dominfo
* clarified the when libxl_event_get_domain_death_info returns a valid libxl_dominfo.
* moved libxl_domain_preserve + the restart-rename handling in xl to the end of the series so it can be ommitted if desired
PATCH 1/1 libxl: Add LIBXL_EVENT namespace to enum libxl_event_type
# HG changeset patch
# User Ian Campbell <[email protected]>
# Date 1280140562 -3600
# Node ID 7a0c37f2a9b51ac012a32bcf6ab222580e7cac94 # Parent 74c8b1f2c2da28fe00492add40a32a257e44dca7
libxl: Add LIBXL_EVENT namespace to enum libxl_event_type
tools/libxl/libxl.c +4 -4
@@ -643,7 +643,7 @@ int libxl_wait_for_domain_death(struct lint libxl_wait_for_domain_death (struct libxl_ctx *ctx,uint32_t domid,libxl_waiter *waiter) { waiter->path =strdup ("@releaseDomain" ); -if (asprintf (&(waiter->token),"%d" ,DOMAIN_DEATH ) <0 ) +if (asprintf (&(waiter->token),"%d" ,LIBXL_EVENT_DOMAIN_DEATH ) <0 )return -1 ;if (!xs_watch (ctx->xsh, waiter->path, waiter->token))return -1 ;
@@ -663,7 +663,7 @@ int libxl_wait_for_disk_ejects(struct li libxl_xs_get_dompath(ctx, domid), device_disk_dev_number(disks[i].virtpath)) < 0)return -1 ; -if (asprintf (&(waiter[i].token),"%d" ,DISK_EJECT ) <0 ) +if (asprintf (&(waiter[i].token),"%d" ,LIBXL_EVENT_DISK_EJECT ) <0 )return -1 ;xs_watch (ctx->xsh, waiter->path, waiter->token); }
@@ -711,7 +711,7 @@ int libxl_event_get_domain_death_info(st {int rc =0 , ret; -if (event && event->type ==DOMAIN_DEATH ) { +if (event && event->type ==LIBXL_EVENT_DOMAIN_DEATH ) { ret =xc_domain_getinfolist (ctx->xch, domid,1 , info);if (ret ==1 && info->domain == domid) { if (info->flags & XEN_DOMINF_running ||
@@ -730,7 +730,7 @@ out:int libxl_event_get_disk_eject_info (struct libxl_ctx *ctx,uint32_t domid,libxl_event *event,libxl_device_disk *disk) { -if (event && event->type ==DISK_EJECT ) { +if (event && event->type ==LIBXL_EVENT_DISK_EJECT ) {char *path;char *backend;char *value =libxl_xs_read (ctx,XBT_NULL , event->path);
tools/libxl/libxl.h +2 -2
@@ -357,8 +357,8 @@ char *libxl_uuid2string(struct libxl_ctx/* events handling */ typedef enum { -DOMAIN_DEATH , -DISK_EJECT , +LIBXL_EVENT_DOMAIN_DEATH , +LIBXL_EVENT_DISK_EJECT , }libxl_event_type ; typedef struct {
tools/libxl/xl_cmdimpl.c +2 -2
@@ -1348,7 +1348,7 @@ start:continue ;libxl_get_event (&ctx, &event);switch (event.type) { -case DOMAIN_DEATH : +case LIBXL_EVENT_DOMAIN_DEATH :if (libxl_event_get_domain_death_info (&ctx, domid, &event, &info)) {LOG ("Domain %d is dead" , domid);if (info.flags & XEN_DOMINF_dying || (info.flags & XEN_DOMINF_shutdown && (((info.flags >> XEN_DOMINF_shutdownshift) & XEN_DOMINF_shutdownmask) != SHUTDOWN_suspend))) {
@@ -1374,7 +1374,7 @@ start:exit (0 ); }break ; -case DISK_EJECT : +case LIBXL_EVENT_DISK_EJECT :if (libxl_event_get_disk_eject_info (&ctx, domid, &event, &disk))libxl_cdrom_insert (&ctx, domid, &disk);break ;
PATCH 1/1 libxl: add shutdown reason to libxl_dominfo
In reply to Ian Campbell# HG changeset patch
# User Ian Campbell <[email protected]> # Date 1280225493 -3600
# Node ID 74371f414f2012adebba8a8617ddef957f5e3ae0 # Parent 7a0c37f2a9b51ac012a32bcf6ab222580e7cac94
libxl: add shutdown reason to libxl_dominfo
Removes the need for explicit libxl_dominfo.crashed so remove it.
tools/libxl/libxl.c +4 -9
@@ -405,8 +405,6 @@ static void xcinfo2xlinfo(const xc_domaistatic void xcinfo2xlinfo (const xc_domaininfo_t *xcinfo,struct libxl_dominfo *xlinfo) { -unsigned int shutdown_reason; -memcpy (&(xlinfo->uuid), xcinfo->handle,sizeof (xen_domain_handle_t)); xlinfo->domid = xcinfo->domain;
@@ -415,14 +413,11 @@ static void xcinfo2xlinfo(const xc_domai xlinfo->paused = !!(xcinfo->flags&XEN_DOMINF_paused); xlinfo->blocked = !!(xcinfo->flags&XEN_DOMINF_blocked); xlinfo->running = !!(xcinfo->flags&XEN_DOMINF_running); - xlinfo->crashed =0 ; - shutdown_reason = (xcinfo->flags>>XEN_DOMINF_shutdownshift) & XEN_DOMINF_shutdownmask; - -if ( xlinfo->shutdown && (shutdown_reason == SHUTDOWN_crash) ) { - xlinfo->shutdown =0 ; - xlinfo->crashed =1 ; - } +if (xlinfo->shutdown || xlinfo->dying) + xlinfo->shutdown_reason = (xcinfo->flags>>XEN_DOMINF_shutdownshift) & XEN_DOMINF_shutdownmask; +else + xlinfo->shutdown_reason = ~0 ; xlinfo->max_memkb =PAGE_TO_MEMKB (xcinfo->tot_pages); xlinfo->cpu_time = xcinfo->cpu_time;
tools/libxl/libxl.h +9 -1
@@ -29,8 +29,16 @@ struct libxl_dominfo { uint8_t blocked:1; uint8_t paused:1; uint8_t shutdown:1; - uint8_t crashed:1; uint8_t dying:1; + +/* +* Valid SHUTDOWN_* value from xen/sched.h iff (shutdown||dying). +* +* Otherwise set to a value guaranteed not to clash with any valid +* SHUTDOWN_* constant. +*/ +unsigned int shutdown_reason; +uint64_t max_memkb;uint64_t cpu_time;uint32_t vcpu_max_id;
tools/libxl/xl_cmdimpl.c +1 -1
@@ -1935,7 +1935,7 @@ void list_domains(int verbose) info[i].blocked ?'b' :'-' , info[i].paused ?'p' :'-' , info[i].shutdown ?'s' :'-' , - info[i].crashed ?'c' :'-' , + info[i].shutdown_reason == SHUTDOWN_crash ?'c' :'-' , info[i].dying ?'d' :'-' , ((float)info[i].cpu_time / 1e9));if (verbose) {
PATCH 1/1 libxl: return libxl_dominfo from libxl_event_get_domain_death_info
In reply to Ian Campbell# HG changeset patch
# User Ian Campbell <[email protected]>
# Date 1280225498 -3600
# Node ID 8774eec37219f6f8c1f9dd35e648910e7398a51c
# Parent 74371f414f2012adebba8a8617ddef957f5e3ae0
libxl: return libxl_dominfo from libxl_event_get_domain_death_info
Removes a libxc data type from the libxl interface.
tools/libxl/libxl.c +6 -7
@@ -702,20 +702,19 @@ int libxl_free_waiter(libxl_waiter *waitreturn 0 ; } -int libxl_event_get_domain_death_info (struct libxl_ctx *ctx,uint32_t domid,libxl_event *event,xc_domaininfo_t *info) +int libxl_event_get_domain_death_info (struct libxl_ctx *ctx,uint32_t domid,libxl_event *event,struct libxl_dominfo *info) {int rc =0 , ret; +if (event && event->type ==LIBXL_EVENT_DOMAIN_DEATH ) { + ret =libxl_domain_info (ctx, info, domid); -if (event && event->type ==LIBXL_EVENT_DOMAIN_DEATH ) { - ret =xc_domain_getinfolist (ctx->xch, domid,1 , info); -if (ret ==1 && info->domain == domid) { -if (info->flags & XEN_DOMINF_running || - (!(info->flags & XEN_DOMINF_shutdown) && !(info->flags & XEN_DOMINF_dying))) +if (ret ==0 && info->domid == domid) { +if (info->running || (!info->shutdown && !info->dying)) goto out; rc =1 ; goto out; } -memset (info,0 ,sizeof (xc_dominfo_t)); +memset (info,0 ,sizeof (*info)); rc =1 ; goto out; }
tools/libxl/libxl.h +1 -1
@@ -393,7 +393,7 @@ int libxl_free_event(libxl_event *event)int libxl_free_event (libxl_event *event);int libxl_free_waiter (libxl_waiter *waiter); -int libxl_event_get_domain_death_info (struct libxl_ctx *ctx,uint32_t domid,libxl_event *event,xc_domaininfo_t *info); +int libxl_event_get_domain_death_info (struct libxl_ctx *ctx,uint32_t domid,libxl_event *event,struct libxl_dominfo *info);int libxl_event_get_disk_eject_info (struct libxl_ctx *ctx,uint32_t domid,libxl_event *event,libxl_device_disk *disk); int libxl_domain_rename(struct libxl_ctx *ctx, uint32_t domid,
tools/libxl/xl_cmdimpl.c +3 -4
@@ -1335,7 +1335,7 @@ start:while (1 ) {int ret;fd_set rfds; -xc_domaininfo_t info; +struct libxl_dominfo info;libxl_event event;libxl_device_disk disk;memset (&info,0x00 ,sizeof (xc_domaininfo_t));
@@ -1351,11 +1351,10 @@ start:case LIBXL_EVENT_DOMAIN_DEATH :if (libxl_event_get_domain_death_info (&ctx, domid, &event, &info)) {LOG ("Domain %d is dead" , domid); -if (info.flags & XEN_DOMINF_dying || (info.flags & XEN_DOMINF_shutdown && (((info.flags >> XEN_DOMINF_shutdownshift) & XEN_DOMINF_shutdownmask) != SHUTDOWN_suspend))) { +if (info.dying || (info.shutdown && info.shutdown_reason != SHUTDOWN_suspend)) {LOG ("Domain %d needs to be clean: destroying the domain" , domid);libxl_domain_destroy (&ctx, domid,0 ); -if (info.flags & XEN_DOMINF_shutdown && - (((info.flags >> XEN_DOMINF_shutdownshift) & XEN_DOMINF_shutdownmask) == SHUTDOWN_reboot)) { +if (info.shutdown && info.shutdown_reason == SHUTDOWN_reboot) {libxl_free_waiter (w1);libxl_free_waiter (w2);free (w1);
PATCH 1/1 libxl: signal caller if domain already destroyed on domain death event
In reply to Ian Campbell# HG changeset patch
# User Ian Campbell <[email protected]>
# Date 1280225498 -3600
# Node ID 4e16c19ba1ac7a496198bed29e91a826e4691533
# Parent 8774eec37219f6f8c1f9dd35e648910e7398a51c
libxl: signal caller if domain already destroyed on domain death event
Currently libxl_event_get_domain_death_info returns 0 if the event was not a domain death event and 1 if it was but does not infom the user if someone else has already cleaned up the domain, which means the caller must replicate some of the logic from within libxl.
Instead have the libxl_event_get_XXX_info functions required that the event is of the right type (the caller must have recently switched on event->type anyway).
This allows the return codes to be used in an event specific way and we take advantage of this by returning an error from libxl_event_get_domain_death_info if the domain is not dying.
tools/libxl/libxl.c +27 -37
@@ -704,52 +704,42 @@ int libxl_free_waiter(libxl_waiter *waitint libxl_event_get_domain_death_info (struct libxl_ctx *ctx,uint32_t domid,libxl_event *event,struct libxl_dominfo *info) { -int rc =0 , ret; -if (event && event->type ==LIBXL_EVENT_DOMAIN_DEATH ) { - ret =libxl_domain_info (ctx, info, domid); +if (libxl_domain_info (ctx, info, domid) <0 ) +return 0 ; -if (ret ==0 && info->domid == domid) { -if (info->running || (!info->shutdown && !info->dying)) - goto out; - rc =1 ; - goto out; - } -memset (info,0 ,sizeof (*info)); - rc =1 ; - goto out; - } -out: -return rc; +if (info->running || (!info->shutdown && !info->dying)) +return ERROR_INVAL ; + +return 1 ; }int libxl_event_get_disk_eject_info (struct libxl_ctx *ctx,uint32_t domid,libxl_event *event,libxl_device_disk *disk) { -if (event && event->type ==LIBXL_EVENT_DISK_EJECT ) { -char *path; -char *backend; -char *value =libxl_xs_read (ctx,XBT_NULL , event->path); +char *path; +char *backend; +char *value; -if (!value ||strcmp (value,"eject" )) -return 0 ; + value =libxl_xs_read (ctx,XBT_NULL , event->path); - path =strdup (event->path); - path[strlen (path) -6 ] ='\0' ; - backend =libxl_xs_read (ctx,XBT_NULL ,libxl_sprintf (ctx,"%s/backend" , path)); +if (!value ||strcmp (value,"eject" )) +return 0 ; - disk->backend_domid =0 ; - disk->domid = domid; - disk->physpath =NULL ; - disk->phystype =0 ; -/* this value is returned to the user: do not free right away */ - disk->virtpath =libxl_xs_read (ctx,XBT_NULL ,libxl_sprintf (ctx,"%s/dev" , backend)); - disk->unpluggable =1 ; - disk->readwrite =0 ; - disk->is_cdrom =1 ; + path =strdup (event->path); + path[strlen (path) -6 ] ='\0' ; + backend =libxl_xs_read (ctx,XBT_NULL ,libxl_sprintf (ctx,"%s/backend" , path)); -free (path); -return 1 ; - } -return 0 ; + disk->backend_domid =0 ; + disk->domid = domid; + disk->physpath =NULL ; + disk->phystype =0 ; +/* this value is returned to the user: do not free right away */ + disk->virtpath =libxl_xs_read (ctx,XBT_NULL ,libxl_sprintf (ctx,"%s/dev" , backend)); + disk->unpluggable =1 ; + disk->readwrite =0 ; + disk->is_cdrom =1 ; + +free (path); +return 1 ; }static int libxl_destroy_device_model (struct libxl_ctx *ctx,uint32_t domid)
tools/libxl/libxl.h +17 -0
@@ -393,7 +393,24 @@ int libxl_free_event(libxl_event *event)int libxl_free_event (libxl_event *event);int libxl_free_waiter (libxl_waiter *waiter); +/* +* Returns: +* - 0 if the domain is dead but there is no cleanup to be done. e.g +* because someone else has already done it. +* - 1 if the domain is dead and there is cleanup to be done. +* +* Can return error if the domain exists and is still running. +* +* *info will contain valid domain state iff 1 is returned. In +* particular if 1 is returned then info->shutdown_reason is +* guaranteed to be valid since by definition the domain is +* (shutdown||dying)) +*/ int libxl_event_get_domain_death_info (struct libxl_ctx *ctx,uint32_t domid,libxl_event *event,struct libxl_dominfo *info); + +/* +* Returns true and fills *disk if the caller should eject the disk +*/ int libxl_event_get_disk_eject_info (struct libxl_ctx *ctx,uint32_t domid,libxl_event *event,libxl_device_disk *disk); int libxl_domain_rename(struct libxl_ctx *ctx, uint32_t domid,
tools/libxl/xl_cmdimpl.c +9 -5
@@ -1338,7 +1338,6 @@ start:struct libxl_dominfo info;libxl_event event;libxl_device_disk disk; -memset (&info,0x00 ,sizeof (xc_domaininfo_t));FD_ZERO (&rfds);FD_SET (fd, &rfds);
@@ -1349,12 +1348,17 @@ start:libxl_get_event (&ctx, &event);switch (event.type) {case LIBXL_EVENT_DOMAIN_DEATH : -if (libxl_event_get_domain_death_info (&ctx, domid, &event, &info)) { -LOG ("Domain %d is dead" , domid); -if (info.dying || (info.shutdown && info.shutdown_reason != SHUTDOWN_suspend)) { + ret =libxl_event_get_domain_death_info (&ctx, domid, &event, &info); + +if (ret <0 )continue ; + +LOG ("Domain %d is dead" , domid); + +if (ret) { +if (info.shutdown_reason != SHUTDOWN_suspend) {LOG ("Domain %d needs to be clean: destroying the domain" , domid);libxl_domain_destroy (&ctx, domid,0 ); -if (info.shutdown && info.shutdown_reason == SHUTDOWN_reboot) { +if (info.shutdown_reason == SHUTDOWN_reboot) {libxl_free_waiter (w1);libxl_free_waiter (w2);free (w1);
PATCH 1/1 xl: Add function to generate random uuid and use it
In reply to Ian Campbell# HG changeset patch
# User Ian Campbell <[email protected]> # Date 1280225498 -3600
# Node ID a31105a3eb9d57d03711254bc2142b699cb1c146 # Parent 4e16c19ba1ac7a496198bed29e91a826e4691533
xl: Add function to generate random uuid and use it.
tools/libxl/xl_cmdimpl.c +10 -8
@@ -211,15 +211,19 @@ static void init_build_info(libxl_domain } } +static void random_uuid (uint8_t *uuid) +{ +int i; +for (i =0 ; i <16 ; i++) + uuid[i] =rand (); +} +static void init_dm_info (libxl_device_model_info *dm_info,libxl_domain_create_info *c_info,libxl_domain_build_info *b_info) { -int i;memset (dm_info,'\0' ,sizeof (*dm_info)); -for (i =0 ; i <16 ; i++) { - dm_info->uuid[i] =rand (); - } +random_uuid (&dm_info->uuid[0 ]); dm_info->dom_name = c_info->name; dm_info->device_model ="qemu-dm" ;
@@ -493,7 +497,7 @@ static void parse_config_data(const charXLU_ConfigList *vbds, *nics, *pcis, *cvfbs, *net2s;int pci_power_mgmt =0 ;int pci_msitranslate =1 ; -int i, e; +int e; config=xlu_cfg_init (stderr, configfile_filename_report);if (!config) {
@@ -521,9 +525,7 @@ static void parse_config_data(const char c_info->name =strdup (buf); else c_info->name = "test"; -for (i =0 ; i <16 ; i++) { - c_info->uuid[i] =rand (); - } +random_uuid (&c_info->uuid[0 ]);if (!xlu_cfg_get_long (config,"oos" , &l)) c_info->oos = l;
PATCH 1/1 xl: Factor out domain death handling into a separate function
In reply to Ian Campbell# HG changeset patch
# User Ian Campbell <[email protected]>
# Date 1280225498 -3600
# Node ID b87962af9df2f893b50dcc215770d5c962663d5f
# Parent a31105a3eb9d57d03711254bc2142b699cb1c146
xl: Factor out domain death handling into a separate function.
tools/libxl/xl_cmdimpl.c +25 -18
@@ -988,6 +988,18 @@ 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); +libxl_domain_destroy (ctx, domid,0 ); +if (info->shutdown_reason == SHUTDOWN_reboot) +return 1 ; + } +return 0 ; +} +struct domain_create {int debug;int daemonize;
@@ -1357,25 +1369,20 @@ start:LOG ("Domain %d is dead" , domid);if (ret) { -if (info.shutdown_reason != SHUTDOWN_suspend) { -LOG ("Domain %d needs to be clean: destroying the domain" , domid); -libxl_domain_destroy (&ctx, domid,0 ); -if (info.shutdown_reason == SHUTDOWN_reboot) { -libxl_free_waiter (w1); -libxl_free_waiter (w2); -free (w1); -free (w2); -LOG ("Done. Rebooting now" ); -/* -* XXX FIXME: If this sleep is not there then -* domain re-creation fails sometimes. -*/ -sleep (2 ); - goto start; - } -LOG ("Done. Exiting now" ); +if (handle_domain_death (&ctx, domid, &event, &info)) { +libxl_free_waiter (w1); +libxl_free_waiter (w2); +free (w1); +free (w2); +/* +* XXX FIXME: If this sleep is not there then domain +* re-creation fails sometimes. +*/ +LOG ("Done. Rebooting now" ); +sleep (2 ); + goto start; } -LOG ("Domain %d does not need to be clean, exiting now" , domid); +LOG ("Done. Exiting now" );exit (0 ); }break ;
PATCH 1/1 xl: support on_{poweroff, reboot, crash} domain configuration options
In reply to Ian Campbell# HG changeset patch
# User Ian Campbell <[email protected]>
# Date 1280225498 -3600
# Node ID 1c1b0c8bb58c78dd60f8e79b00c2bf664ea41725
# Parent b87962af9df2f893b50dcc215770d5c962663d5f
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.
tools/libxl/xl_cmdimpl.c +146 -11
@@ -99,6 +99,36 @@ 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_PRESERVE , + +ACTION_COREDUMP_DESTROY , +ACTION_COREDUMP_RESTART , +}; + +static char *action_on_shutdown_names[] = { + [ACTION_DESTROY ] ="destroy" , + + [ACTION_RESTART ] ="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 +502,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 +598,35 @@ static void parse_config_data(const charif (!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
@@ -989,15 +1065,70 @@ int autoconnect_console(int hvm) }/* 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); +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 SHUTDOWN_poweroff: + action = d_config->on_poweroff; +break ; +case SHUTDOWN_reboot: + action = d_config->on_reboot; +break ; +case SHUTDOWN_suspend: +return 0 ; +case SHUTDOWN_crash: + action = d_config->on_crash; +break ; +case 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 : + 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; }struct domain_create {
@@ -1016,6 +1147,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 +1283,7 @@ static int create_domain(struct domain_cif (!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,7 +1502,7 @@ start:LOG ("Domain %d is dead" , domid);if (ret) { -if (handle_domain_death (&ctx, domid, &event, &info)) { +if (handle_domain_death (&ctx, domid, &event, &c_info, &d_config, &info)) {libxl_free_waiter (w1);libxl_free_waiter (w2);free (w1);
@@ -1892,6 +2025,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;
@@ -1917,7 +2052,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);
PATCH 1/1 libxl: add libxl_domain_preserve
In reply to Ian Campbell# HG changeset patch
# User Ian Campbell <[email protected]> # Date 1280225498 -3600
# Node ID d9b5f51a54caa8430b8ea80938ee87eccaed2e37 # Parent 1c1b0c8bb58c78dd60f8e79b00c2bf664ea41725
libxl: add libxl_domain_preserve
This method is intended to preserve an existing domain (for debugging purposes) in such a way that the domain can also be restarted.
There is likely to be more required to achieve this aim than the function currently does.
tools/libxl/libxl.c +55 -0
@@ -399,6 +399,61 @@ int libxl_domain_resume(struct libxl_ctx domid);return ERROR_FAIL ; } +return 0 ; +} + +/* +* Preserves a domain but rewrites xenstore etc to make it unique so +* that the domain can be restarted. +* +* Does not modify info so that it may be reused. +*/ +int libxl_domain_preserve (struct libxl_ctx *ctx,uint32_t domid, +libxl_domain_create_info *info,const char *name_suffix,uint8_t new_uuid[16 ]) +{ +struct xs_permissions roperm[2 ]; +xs_transaction_t t; +char *preserved_name; +char *uuid_string; +char *vm_path; +char *dom_path; + +int rc; + + preserved_name =libxl_sprintf (ctx,"%s%s" , info->name, name_suffix); +if (!preserved_name)return ERROR_NOMEM ; + + uuid_string =libxl_uuid2string (ctx, new_uuid); +if (!uuid_string)return ERROR_NOMEM ; + + dom_path =libxl_xs_get_dompath (ctx, domid); +if (!dom_path)return ERROR_FAIL ; + + vm_path =libxl_sprintf (ctx,"/vm/%s" , uuid_string); +if (!vm_path)return ERROR_FAIL ; + + roperm[0 ].id =0 ; + roperm[0 ].perms =XS_PERM_NONE ; + roperm[1 ].id = domid; + roperm[1 ].perms =XS_PERM_READ ; + + retry_transaction: + t =xs_transaction_start (ctx->xsh); + +xs_rm (ctx->xsh, t, vm_path); +xs_mkdir (ctx->xsh, t, vm_path); +xs_set_permissions (ctx->xsh, t, vm_path, roperm,ARRAY_SIZE (roperm)); + +xs_write (ctx->xsh, t,libxl_sprintf (ctx,"%s/vm" , dom_path), vm_path,strlen (vm_path)); + rc =libxl_domain_rename (ctx, domid, info->name, preserved_name, t); +if (rc)return rc; + +xs_write (ctx->xsh, t,libxl_sprintf (ctx,"%s/uuid" , vm_path), uuid_string,strlen (uuid_string)); + +if (!xs_transaction_end (ctx->xsh, t,0 )) +if (errno ==EAGAIN ) + goto retry_transaction; +return 0 ; }
tools/libxl/libxl.h +1 -0
@@ -338,6 +338,7 @@ int libxl_domain_resume(struct libxl_ctxint libxl_domain_resume (struct libxl_ctx *ctx,uint32_t domid);int libxl_domain_shutdown (struct libxl_ctx *ctx,uint32_t domid,int req);int libxl_domain_destroy (struct libxl_ctx *ctx,uint32_t domid,int force); +int libxl_domain_preserve (struct libxl_ctx *ctx,uint32_t domid,libxl_domain_create_info *info,const char *name_suffix,uint8_t new_uuid[16 ]);int libxl_file_reference_map (struct libxl_ctx *ctx,libxl_file_reference *f);int libxl_file_reference_unmap (struct libxl_ctx *ctx,libxl_file_reference *f);
PATCH 1/1 xl: implement "rename-restart" action for shutdown
In reply to Ian Campbell# HG changeset patch
# User Ian Campbell <[email protected]> # Date 1280225498 -3600
# Node ID 519187e3e2b1bbeb244d64d79153e350ca3ba0bf # Parent d9b5f51a54caa8430b8ea80938ee87eccaed2e37
xl: implement "rename-restart" action for shutdown
tools/libxl/xl_cmdimpl.c +56 -4
@@ -104,6 +104,7 @@ enum action_on_shutdown {ACTION_DESTROY ,ACTION_RESTART , +ACTION_RESTART_RENAME , ACTION_PRESERVE,
@@ -115,6 +116,7 @@ static char *action_on_shutdown_names[] [ACTION_DESTROY] = "destroy", [ACTION_RESTART] = "restart", + [ACTION_RESTART_RENAME] = "rename-restart", [ACTION_PRESERVE] = "preserve",
@@ -1064,7 +1066,7 @@ int autoconnect_console(int hvm)_exit (1 ); } -/* Returns 1 if domain should be restarted */ +/* 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)
@@ -1112,6 +1114,10 @@ static int handle_domain_death(struct liswitch (action) {case ACTION_PRESERVE : +break ; + +case ACTION_RESTART_RENAME : + restart =2 ;break ;case ACTION_RESTART :
@@ -1129,6 +1135,43 @@ static int handle_domain_death(struct li }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 {
@@ -1502,7 +1545,15 @@ start:LOG ("Domain %d is dead" , domid);if (ret) { -if (handle_domain_death (&ctx, domid, &event, &c_info, &d_config, &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);
@@ -1514,9 +1565,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 :
Re: [PATCH 5 of 9] xl: Add function to generate random uuid and use it
In reply to Ian Campbelltools/libxl/xl_cmdimpl.c static void init_build_info(libxl_domain · line 220
Quoted 7 lines · Ian Campbell
tools/libxl/xl_cmdimpl.c +7
-0+static void random_uuid (uint8_t *uuid) +{ +int i; +for (i =0 ; i <16 ; i++) + uuid[i] =rand (); +} +
Nothing wrong with the patch but draws my attention to the fact that this method seems far too likely to collide UUID's, for example in xl invocations started during the same second. Why not use system entropy pool? eg. scanf contents of /proc/sys/kernel/rand/uuid... I'm aware this ought to be portable but PRNG can always be a fallback.
Gianni
Re: [PATCH 5 of 9] xl: Add function to generate random uuid and use it
Gianni Tedesco writes ("Re: [Xen-devel] [PATCH 5 of 9] xl: Add function to generate random uuid and use it"):
Quoted 5 lines
Nothing wrong with the patch but draws my attention to the fact that this method seems far too likely to collide UUID's, for example in xl invocations started during the same second. Why not use system entropy pool? eg. scanf contents of
/proc/sys/kernel/rand/uuid... I'm aware this ought to be portable but PRNG can always be a fallback.
Yes.
We should probably use /dev/urandom (on Linux, or I think /dev/random on BSD). If that's not available then we should use rand_r seeded with time and pid.
Ian.
Re: [PATCH 5 of 9] xl: Add function to generate random uuid and use it
Quoted 7 lines · Ian Jackson
Gianni Tedesco writes ("Re: [Xen-devel] [PATCH 5 of 9] xl: Add function to generate random uuid and use it"):
Quoted 5 lines
Nothing wrong with the patch but draws my attention to the fact that this method seems far too likely to collide UUID's, for example in xl invocations started during the same second. Why not use system entropy pool? eg. scanf contents of
/proc/sys/kernel/rand/uuid... I'm aware this ought to be portable but PRNG can always be a fallback.
Quoted 5 lines
Yes.
We should probably use
/dev/urandom(on Linux, or I think/dev/randomon BSD). If that's not available then we should userand_rseeded with time and pid.
Or perhaps libuuid? It's is used by blktap2 so we already need it, at least on Linux.
Ian.