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

Re: [Xen-devel] [PATCH 0 of 3] xl and hotplug: Introduce and use shutdown and reboot xm compatibility options



Tuesday, September 25, 2012, 5:29:09 PM, you wrote:

> On Tue, 2012-09-25 at 16:11 +0100, Sander Eikelenboom wrote:

>> The only relative simple implementation i thought of was direct
>> shutting down all, and when the -w parameter was set, just loop and
>> wait on events until the only running domain is domain-0.
>> Although this exactly does what has to be done, it somehow sounds a
>> bit dirty.

> I think you can allocate an array of libxl_evenable_domain_death*, of
> nr_doms in size and then as you shutdown each domain call
> libxl_evenable_domain_death for it too.

> Then you loop waiting for destroy events, calling
> libxl_evdisable_domain_death as each domain dies, while counting back
> from nr_doms until 0. When it reaches 0 everything you asked for has
> been shutdown.

> Or something like that, I've not actually implemented it ;-)

> Ian.

It's time to call defeat, without proper C skills it seems a bit too hard to 
figure it out.
Can't seem to get the hang of how to keep a reference to 
libxl_evgen_domain_death
and use it to check if the domid of the event is the same as that from a domain 
we are waiting to shutdown.
The rest of the code doesn't give me much pointers since all commands seem to 
operate on a single domid at once.

The concoction below leads to:
xl_cmdimpl.c: In function Ãshutdown_domainÃ:
xl_cmdimpl.c:2766: error: dereferencing pointer to incomplete type


--------------------------- tools/libxl/xl_cmdimpl.c ---------------------------
index 1627cac..b900811 100644
@@ -2684,67 +2684,98 @@ static void destroy_domain(uint32_t domid)
     }
     rc = libxl_domain_destroy(ctx, domid, 0);
     if (rc) { fprintf(stderr,"destroy failed (rc=%d)\n",rc); exit(-1); }
 }
 
-static void shutdown_domain(uint32_t domid, int wait_for_it,
-                            int fallback_trigger)
+static int shutdown_domain(const libxl_dominfo *dominfo, int nb_domain,
+                            int wait_for_it, int fallback_trigger)
 {
-    int rc;
-    libxl_event *event;
+    int i, rc, nb_shutdown_pending;
+    int ret = 0;
+    libxl_evgen_domain_death *domains_wait_shutdown[nb_domain];
+       
+    for (i = 0; i < nb_domain; i++) {
+        uint32_t domid = dominfo[i].domid;
+        if(!libxl_domid_valid_guest(domid))
+            continue;
 
-    rc=libxl_domain_shutdown(ctx, domid);
-    if (rc == ERROR_NOPARAVIRT) {
-        if (fallback_trigger) {
-            fprintf(stderr, "PV control interface not available:"
-                    " sending ACPI power button event.\n");
-            rc = libxl_send_trigger(ctx, domid, LIBXL_TRIGGER_POWER, 0);
-        } else {
-            fprintf(stderr, "PV control interface not available:"
-                    " external graceful shutdown not possible.\n");
-            fprintf(stderr, "Use \"-F\" to fallback to ACPI power event.\n");
+        rc = libxl_domain_shutdown(ctx, domid);
+
+        if (rc == ERROR_NOPARAVIRT) {
+            if (fallback_trigger) {
+                fprintf(stderr, "PV control interface not available:"
+                        " sending ACPI power button event.\n");
+                rc = libxl_send_trigger(ctx, domid, LIBXL_TRIGGER_POWER, 0);
+            } else {
+                fprintf(stderr, "PV control interface not available:"
+                        " external graceful shutdown not possible.\n");
+                fprintf(stderr,
+                    "Use \"-F\" to fallback to ACPI power event.\n");
+            }
+        }
+        
+        if (rc) {
+            fprintf(stderr,"shutdown of domain %d failed (rc=%d)\n", domid, 
rc);
+            ret = -1;
+            continue;
+        }
+
+        if (wait_for_it) {
+            rc = libxl_evenable_domain_death(ctx, domid, 0, 
&domains_wait_shutdown[i]);
+            if (rc) {
+                fprintf(stderr,"wait for death of domain %d failed"
+                    " (evgen, rc=%d)\n", domid, rc);
+                ret = -1;
+            } else {
+                nb_shutdown_pending++;
+            } 
         }
-    }
-    if (rc) {
-        fprintf(stderr,"shutdown failed (rc=%d)\n",rc);exit(-1);
     }
 
     if (wait_for_it) {
-        libxl_evgen_domain_death *deathw;
+        while (nb_shutdown_pending > 0) {
+            libxl_event *event;
+            rc = libxl_event_wait(ctx, &event, LIBXL_EVENTMASK_ALL, 0,0);
+            if (rc) {
+                LOG("Failed to get event (rc=%d)", rc);
+                return -1;
+            }
 
-        rc = libxl_evenable_domain_death(ctx, domid, 0, &deathw);
-        if (rc) {
-            fprintf(stderr,"wait for death failed (evgen, rc=%d)\n",rc);
-            exit(-1);
-        }
+            uint32_t event_domid = event->domid;
+            switch (event->type) {
 
-        for (;;) {
-            rc = domain_wait_event(domid, &event);
-            if (rc) exit(-1);
+                case LIBXL_EVENT_TYPE_DOMAIN_DEATH:
+                    LOG("Domain %d has been destroyed", event_domid);
+                    break;
 
-            switch (event->type) {
+                case LIBXL_EVENT_TYPE_DOMAIN_SHUTDOWN:
+                    LOG("Domain %d has been shut down, reason code %d %x",
+                        event_domid,
+                        event->u.domain_shutdown.shutdown_reason,
+                        event->u.domain_shutdown.shutdown_reason);
+                    break;
 
-            case LIBXL_EVENT_TYPE_DOMAIN_DEATH:
-                LOG("Domain %d has been destroyed", domid);
-                goto done;
+                default:
+                    continue;
+                    break;
+            }
 
-            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;
+            for (i = 0; i < nb_domain; i++) {
+                if (!domains_wait_shutdown[i])
+                    continue;
 
-            default:
-                LOG("Unexpected event type %d", event->type);
-                break;
+                if (domains_wait_shutdown[i]->domid == event_domid){
+                    libxl_evdisable_domain_death(ctx, 
domains_wait_shutdown[i]);
+                    domains_wait_shutdown[i] = NULL;
+                    nb_shutdown_pending--;
+                }
             }
             libxl_event_free(ctx, event);
         }
-    done:
-        libxl_event_free(ctx, event);
-        libxl_evdisable_domain_death(ctx, deathw);
     }
+
+    return ret;
 }
 
 static void reboot_domain(uint32_t domid, int fallback_trigger)
 {
     int rc;
@@ -3674,29 +3705,82 @@ int main_destroy(int argc, char **argv)
     return 0;
 }
 
 int main_shutdown(int argc, char **argv)
 {
+    libxl_dominfo dominfo_buf;
+    libxl_dominfo *dominfo, *dominfo_free = NULL;
+    int nb_domain, rc;
     int opt;
+    int option_index = 0;
+    int all = 0;
     int wait_for_it = 0;
     int fallback_trigger = 0;
+    static struct option long_options[] = {
+        {"all", 0, 0, 'a'},
+        {"wait", 0, 0, 'w'},
+        {0, 0, 0, 0}
+    };
 
-    while ((opt = def_getopt(argc, argv, "wF", "shutdown", 1)) != -1) {
+    while ((opt = getopt_long(argc, argv, "awF", long_options, &option_index)) 
!= -1) {
         switch (opt) {
         case 0: case 2:
             return opt;
+        case 'a':
+            all = 1;
+            break;
         case 'w':
             wait_for_it = 1;
             break;
         case 'F':
             fallback_trigger = 1;
             break;
         }
     }
 
-    shutdown_domain(find_domain(argv[optind]), wait_for_it, fallback_trigger);
-    return 0;
+    if (!argv[optind] && !all) {
+        fprintf(stderr, "You must specify -a or a valid domain id.\n\n");
+        return opt;
+    }
+
+    if (all) {
+        dominfo = libxl_list_domain(ctx, &nb_domain);
+        if (!dominfo) {
+            fprintf(stderr, "libxl_domain_infolist failed.\n");
+            return -1;
+        }
+        dominfo_free = dominfo;
+    } else {
+        uint32_t domid = find_domain(argv[optind]);
+        if (domid == 0) {
+            fprintf(stderr, "Error: Domain-0 can't be shutdown by this 
command\n");
+            return -1;
+        }
+
+        rc = libxl_domain_info(ctx, &dominfo_buf, domid);
+
+        if (rc == ERROR_INVAL) {
+            fprintf(stderr, "Error: Domain \'%s\' does not exist.\n",
+                argv[optind]);
+            return -rc;
+        }
+        if (rc) {
+            fprintf(stderr, "libxl_domain_info failed (code %d).\n", rc);
+            return -rc;
+        }
+        dominfo = &dominfo_buf;
+        nb_domain = 1;
+    }
+
+    rc = shutdown_domain(dominfo, nb_domain, wait_for_it, fallback_trigger);
+
+    if (dominfo_free)
+        libxl_dominfo_list_free(dominfo_free, nb_domain);
+    else
+        libxl_dominfo_dispose(dominfo);
+
+    return -rc;
 }
 
 int main_reboot(int argc, char **argv)
 {
     int opt;




Attachment: patch.diff
Description: Binary data

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel

 


Rackspace

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