aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIan Campbell <ian.campbell@citrix.com>2012-10-18 09:35:10 +0100
committerIan Campbell <ian.campbell@citrix.com>2012-10-18 09:35:10 +0100
commit710820bc4e20ce9750d6dc23412a1c2ba6d0c037 (patch)
treefc7224ff69ccaf5960875367d8484ac534d467f9
parentb3b123b5a943cd2e289c6cb429836f6b16648771 (diff)
downloadxen-710820bc4e20ce9750d6dc23412a1c2ba6d0c037.tar.gz
xen-710820bc4e20ce9750d6dc23412a1c2ba6d0c037.tar.bz2
xen-710820bc4e20ce9750d6dc23412a1c2ba6d0c037.zip
xl: Introduce xl shutdown --all support for xm compatibility
Based on a patch by Sander Eikelenboom Signed-off-by: Sander Eikelenboom <linux@eikelenboom.it> Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Acked-by: Ian Jackson <ian.jackson@eu.citrix.com> [ ijc -- fixed sizeof(foo) vs sizeof(*foo) issue pointed out by Ian J ] Committed-by: Ian Campbell <ian.campbell@citrix.com>
-rw-r--r--docs/man/xl.pod.17
-rw-r--r--tools/libxl/xl_cmdimpl.c121
-rw-r--r--tools/libxl/xl_cmdtable.c5
3 files changed, 94 insertions, 39 deletions
diff --git a/docs/man/xl.pod.1 b/docs/man/xl.pod.1
index dd387c92ff..7b1f2cf314 100644
--- a/docs/man/xl.pod.1
+++ b/docs/man/xl.pod.1
@@ -527,7 +527,7 @@ List specifically for that domain. Otherwise, list for all domains.
=back
-=item B<shutdown> [I<OPTIONS>] I<domain-id>
+=item B<shutdown> [I<OPTIONS>] I<-a|domain-id>
Gracefully shuts down a domain. This coordinates with the domain OS
to perform graceful shutdown, so there is no guarantee that it will
@@ -550,6 +550,11 @@ B<OPTIONS>
=over 4
+=item B<-a>, B<--all>
+
+Shutdown all guest domains. Often used when doing a complete shutdown
+of a Xen system.
+
=item B<-w>, B<--wait>
Wait for the domain to complete shutdown before returning.
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index 389b5f7e4a..c50a7c8fcc 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -2713,12 +2713,46 @@ static void destroy_domain(uint32_t domid)
if (rc) { fprintf(stderr,"destroy failed (rc=%d)\n",rc); exit(-1); }
}
-static void shutdown_domain(uint32_t domid, int wait_for_it,
+static void wait_for_domain_deaths(libxl_evgen_domain_death **deathws, int nr)
+{
+ int rc, count = 0;
+ LOG("Waiting for %d domains to shutdown", nr);
+ while(1 && count < nr) {
+ libxl_event *event;
+ rc = libxl_event_wait(ctx, &event, LIBXL_EVENTMASK_ALL, 0,0);
+ if (rc) {
+ LOG("Failed to get event, quitting (rc=%d)", rc);
+ exit(-1);
+ }
+
+ switch (event->type) {
+ case LIBXL_EVENT_TYPE_DOMAIN_DEATH:
+ LOG("Domain %d has been destroyed", event->domid);
+ libxl_evdisable_domain_death(ctx, deathws[event->for_user]);
+ count++;
+ break;
+ case LIBXL_EVENT_TYPE_DOMAIN_SHUTDOWN:
+ LOG("Domain %d has been shut down, reason code %d",
+ event->domid, event->u.domain_shutdown.shutdown_reason);
+ libxl_evdisable_domain_death(ctx, deathws[event->for_user]);
+ count++;
+ break;
+ default:
+ LOG("Unexpected event type %d", event->type);
+ break;
+ }
+ libxl_event_free(ctx, event);
+ }
+}
+
+static void shutdown_domain(uint32_t domid,
+ libxl_evgen_domain_death **deathw,
+ libxl_ev_user for_user,
int fallback_trigger)
{
int rc;
- libxl_event *event;
+ fprintf(stderr, "Shutting down domain %d\n", domid);
rc=libxl_domain_shutdown(ctx, domid);
if (rc == ERROR_NOPARAVIRT) {
if (fallback_trigger) {
@@ -2731,44 +2765,19 @@ static void shutdown_domain(uint32_t domid, int wait_for_it,
fprintf(stderr, "Use \"-F\" to fallback to ACPI power event.\n");
}
}
+
if (rc) {
fprintf(stderr,"shutdown failed (rc=%d)\n",rc);exit(-1);
}
- if (wait_for_it) {
- libxl_evgen_domain_death *deathw;
-
- rc = libxl_evenable_domain_death(ctx, domid, 0, &deathw);
+ if (deathw) {
+ rc = libxl_evenable_domain_death(ctx, domid, for_user, deathw);
if (rc) {
fprintf(stderr,"wait for death failed (evgen, rc=%d)\n",rc);
exit(-1);
}
-
- for (;;) {
- rc = domain_wait_event(domid, &event);
- if (rc) exit(-1);
-
- switch (event->type) {
-
- case LIBXL_EVENT_TYPE_DOMAIN_DEATH:
- LOG("Domain %d has been destroyed", domid);
- goto done;
-
- case LIBXL_EVENT_TYPE_DOMAIN_SHUTDOWN:
- LOG("Domain %d has been shut down, reason code %d %x", domid,
- event->u.domain_shutdown.shutdown_reason,
- event->u.domain_shutdown.shutdown_reason);
- goto done;
-
- default:
- LOG("Unexpected event type %d", event->type);
- break;
- }
- libxl_event_free(ctx, event);
- }
- done:
- libxl_event_free(ctx, event);
- libxl_evdisable_domain_death(ctx, deathw);
+ printf("Waiting for domain %d death %p %"PRIx64"\n",
+ domid, *deathw, for_user);
}
}
@@ -3706,18 +3715,21 @@ int main_destroy(int argc, char **argv)
int main_shutdown(int argc, char **argv)
{
- int opt;
- int wait_for_it = 0;
+ int opt, i, nb_domain;
+ int wait_for_it = 0, all =0;
int fallback_trigger = 0;
static struct option long_options[] = {
+ {"all", 0, 0, 'a'},
{"wait", 0, 0, 'w'},
{0, 0, 0, 0}
};
- while ((opt = getopt_long(argc, argv, "wF", long_options, NULL)) != -1) {
+ while ((opt = getopt_long(argc, argv, "awF", long_options, NULL)) != -1) {
switch (opt) {
case 0: case 2:
return opt;
+ case 'a':
+ all = 1;
case 'w':
wait_for_it = 1;
break;
@@ -3727,7 +3739,44 @@ int main_shutdown(int argc, char **argv)
}
}
- shutdown_domain(find_domain(argv[optind]), wait_for_it, fallback_trigger);
+ if (!argv[optind] && !all) {
+ fprintf(stderr, "You must specify -a or a domain id.\n\n");
+ return opt;
+ }
+
+ if (all) {
+ libxl_dominfo *dominfo;
+ libxl_evgen_domain_death **deathws = NULL;
+ if (!(dominfo = libxl_list_domain(ctx, &nb_domain))) {
+ fprintf(stderr, "libxl_list_domain failed.\n");
+ return -1;
+ }
+
+ if (wait_for_it)
+ deathws = calloc(nb_domain, sizeof(*deathws));
+
+ for (i = 0; i<nb_domain; i++) {
+ if (dominfo[i].domid == 0)
+ continue;
+ shutdown_domain(dominfo[i].domid,
+ deathws ? &deathws[i] : NULL, i,
+ fallback_trigger);
+ }
+
+ wait_for_domain_deaths(deathws, nb_domain - 1 /* not dom 0 */);
+ libxl_dominfo_list_free(dominfo, nb_domain);
+ } else {
+ libxl_evgen_domain_death *deathw = NULL;
+ uint32_t domid = find_domain(argv[optind]);
+
+ shutdown_domain(domid, wait_for_it ? &deathw : NULL, 0,
+ fallback_trigger);
+
+ if (wait_for_it)
+ wait_for_domain_deaths(&deathw, 1);
+ }
+
+
return 0;
}
diff --git a/tools/libxl/xl_cmdtable.c b/tools/libxl/xl_cmdtable.c
index b398c0a67a..fde7fe3707 100644
--- a/tools/libxl/xl_cmdtable.c
+++ b/tools/libxl/xl_cmdtable.c
@@ -60,11 +60,12 @@ struct cmd_spec cmd_table[] = {
{ "shutdown",
&main_shutdown, 0, 1,
"Issue a shutdown signal to a domain",
- "[options] <Domain>",
+ "[options] <-a|Domain>",
+ "-a, --all Shutdown all guest domains.\n"
"-h Print this help.\n"
"-F Fallback to ACPI power event for HVM guests with\n"
" no PV drivers.\n"
- "-w, --wait Wait for guest to shutdown.\n"
+ "-w, --wait Wait for guest(s) to shutdown.\n"
},
{ "reboot",
&main_reboot, 0, 1,