WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH] libxenlight: implement cdrom insert\eject

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH] libxenlight: implement cdrom insert\eject
From: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
Date: Mon, 7 Dec 2009 15:58:11 +0000
Delivery-date: Mon, 07 Dec 2009 07:54:43 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Alpine 2.00 (DEB 1167 2008-08-23)
Hi all,
this patch implements functions in libxenlight to change the cdrom in a
VM at run time and to handle cdrom eject requests from guests.

This patch adds two new commands to xl: cd-insert and cd-eject; it also
modifies xl to handle cdrom eject requests coming from guests (actually
coming from qemu).

Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>

---

diff -r b07a720e30de tools/libxl/libxl.c
--- a/tools/libxl/libxl.c       Mon Dec 07 15:19:24 2009 +0000
+++ b/tools/libxl/libxl.c       Mon Dec 07 15:20:05 2009 +0000
@@ -460,25 +460,80 @@
     return 0;
 }
 
-int libxl_wait_for_domain_death(struct libxl_ctx *ctx, uint32_t domid, int *fd)
+int libxl_get_wait_fd(struct libxl_ctx *ctx, int *fd)
 {
-    if (!xs_watch(ctx->xsh, "@releaseDomain", "domain_death"))
-        return -1;
     *fd = xs_fileno(ctx->xsh);
     return 0;
 }
 
-int libxl_is_domain_dead(struct libxl_ctx *ctx, uint32_t domid, xc_dominfo_t 
*info)
+int libxl_wait_for_domain_death(struct libxl_ctx *ctx, uint32_t domid, 
libxl_waiter *waiter)
+{
+    waiter->path = strdup("@releaseDomain");
+    asprintf(&(waiter->token), "%d", DOMAIN_DEATH);
+    if (!xs_watch(ctx->xsh, waiter->path, waiter->token))
+        return -1;
+    return 0;
+}
+
+int libxl_wait_for_disk_ejects(struct libxl_ctx *ctx, uint32_t guest_domid, 
libxl_device_disk *disks, int num_disks, libxl_waiter *waiter)
+{
+    int i;
+    uint32_t domid = libxl_get_stubdom_id(ctx, guest_domid);
+
+    if (!domid)
+        domid = guest_domid;
+
+    for (i = 0; i < num_disks; i++) {
+        asprintf(&(waiter[i].path), "%s/device/vbd/%d/eject", 
libxl_xs_get_dompath(ctx, domid), device_disk_dev_number(disks[i].virtpath));
+        asprintf(&(waiter[i].token), "%d", DISK_EJECT);
+        xs_watch(ctx->xsh, waiter->path, waiter->token);
+    }
+    return 0;
+}
+
+int libxl_get_event(struct libxl_ctx *ctx, libxl_event *event)
 {
     unsigned int num;
+    char **events = xs_read_watch(ctx->xsh, &num);
+    if (num != 2) {
+        free(events);
+        return -1;
+    }
+    event->path = strdup(events[XS_WATCH_PATH]);
+    event->token = strdup(events[XS_WATCH_TOKEN]);
+    event->type = atoi(event->token);
+    free(events);
+    return 0; 
+}
+
+int libxl_stop_waiting(struct libxl_ctx *ctx, libxl_waiter *waiter)
+{
+    if (!xs_unwatch(ctx->xsh, waiter->path, waiter->token))
+        return -1;
+    else
+        return 0;
+}
+
+int libxl_free_event(libxl_event *event)
+{
+    free(event->path);
+    free(event->token);
+    return 0; 
+}
+
+int libxl_free_waiter(libxl_waiter *waiter)
+{
+    free(waiter->path);
+    free(waiter->token);
+    return 0; 
+}
+
+int libxl_event_get_domain_death_info(struct libxl_ctx *ctx, uint32_t domid, 
libxl_event *event, xc_dominfo_t *info)
+{
     int nb_domain, i, rc = 0;
-    char **vec = NULL;
     xc_dominfo_t *list = NULL;
 
-    vec = xs_read_watch(ctx->xsh, &num);
-    if (!vec)
-        return 0;
-    if (!strcmp(vec[XS_WATCH_TOKEN], "domain_death")) {
+    if (event && event->type == DOMAIN_DEATH) {
         list = libxl_domain_infolist(ctx, &nb_domain);
         for (i = 0; i < nb_domain; i++) {
             if (domid == list[i].domid) {
@@ -493,11 +548,39 @@
         rc = 1;
         goto out;
     }
-
 out:
     free(list);
-    free(vec);
     return rc;
+}
+
+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) {
+        char *path;
+        char *backend;
+        char *value = libxl_xs_read(ctx, XBT_NULL, event->path);
+
+        if (!value || strcmp(value,  "eject"))
+            return 0;
+
+        path = strdup(event->path);
+        path[strlen(path) - 6] = '\0';
+        backend = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/backend", path));
+
+        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;
+    }
+    return 0;
 }
 
 static int libxl_destroy_device_model(struct libxl_ctx *ctx, uint32_t domid)
@@ -1419,6 +1502,95 @@
 int libxl_device_vkb_hard_shutdown(struct libxl_ctx *ctx, uint32_t domid)
 {
     return ERROR_NI;
+}
+
+libxl_device_disk *libxl_device_disk_list(struct libxl_ctx *ctx, uint32_t 
domid, int *num)
+{
+    char *be_path_tap, *be_path_vbd;
+    libxl_device_disk *disks = NULL;
+    char **l = NULL;
+    unsigned int numl;
+    int num_disks = 0, i;
+    char *type;
+
+    be_path_vbd = libxl_sprintf(ctx, "%s/backend/vbd/%d", 
libxl_xs_get_dompath(ctx, 0), domid);
+    be_path_tap = libxl_sprintf(ctx, "%s/backend/tap/%d", 
libxl_xs_get_dompath(ctx, 0), domid);
+
+    l = libxl_xs_directory(ctx, XBT_NULL, be_path_vbd, &numl);
+    if (l) {
+        num_disks += numl;
+        disks = realloc(disks, sizeof(libxl_device_disk) * num_disks);
+        for (i = 0; i < numl; i++) {
+            disks[i].backend_domid = 0;
+            disks[i].domid = domid;
+            disks[i].physpath = libxl_xs_read(ctx, XBT_NULL, 
libxl_sprintf(ctx, "%s/%s/params", be_path_vbd, l[i]));
+            libxl_string_to_phystype(ctx, libxl_xs_read(ctx, XBT_NULL, 
libxl_sprintf(ctx, "%s/%s/type", be_path_vbd, l[i])), &(disks[i].phystype));
+            disks[i].virtpath = libxl_xs_read(ctx, XBT_NULL, 
libxl_sprintf(ctx, "%s/%s/dev", be_path_vbd, l[i]));
+            disks[i].unpluggable = atoi(libxl_xs_read(ctx, XBT_NULL, 
libxl_sprintf(ctx, "%s/%s/removable", be_path_vbd, l[i])));
+            if (!strcmp(libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/%s/mode", be_path_vbd, l[i])), "w"))
+                disks[i].readwrite = 1;
+            else
+                disks[i].readwrite = 0;
+            type = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/device-type", libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/%s/frontend", be_path_vbd, l[i]))));
+            disks[i].is_cdrom = !strcmp(type, "cdrom");
+        }
+        free(l);
+    }
+    l = libxl_xs_directory(ctx, XBT_NULL, be_path_tap, &numl);
+    if (l) {
+        num_disks += numl;
+        disks = realloc(disks, sizeof(libxl_device_disk) * num_disks);
+        for (i = 0; i < numl; i++) {
+            disks[i].backend_domid = 0;
+            disks[i].domid = domid;
+            disks[i].physpath = libxl_xs_read(ctx, XBT_NULL, 
libxl_sprintf(ctx, "%s/%s/params", be_path_tap, l[i]));
+            libxl_string_to_phystype(ctx, libxl_xs_read(ctx, XBT_NULL, 
libxl_sprintf(ctx, "%s/%s/type", be_path_tap, l[i])), &(disks[i].phystype));
+            disks[i].virtpath = libxl_xs_read(ctx, XBT_NULL, 
libxl_sprintf(ctx, "%s/%s/dev", be_path_tap, l[i]));
+            disks[i].unpluggable = atoi(libxl_xs_read(ctx, XBT_NULL, 
libxl_sprintf(ctx, "%s/%s/removable", be_path_tap, l[i])));
+            if (!strcmp(libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/%s/mode", be_path_tap, l[i])), "w"))
+                disks[i].readwrite = 1;
+            else
+                disks[i].readwrite = 0;
+            type = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/device-type", libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/%s/frontend", be_path_vbd, l[i]))));
+            disks[i].is_cdrom = !strcmp(type, "cdrom");
+        }
+        free(l);
+    }
+    *num = num_disks;
+    return disks;
+}
+
+int libxl_cdrom_insert(struct libxl_ctx *ctx, uint32_t domid, 
libxl_device_disk *disk)
+{
+    int num, i;
+    uint32_t stubdomid;
+    libxl_device_disk *disks;
+
+    if (!disk->physpath) {
+        disk->physpath = "";
+        disk->phystype = PHYSTYPE_PHY;
+    }
+    disks = libxl_device_disk_list(ctx, domid, &num);
+    for (i = 0; i < num; i++) {
+        if (disks[i].is_cdrom && !strcmp(disk->virtpath, disks[i].virtpath))
+            /* found */
+            break;
+    }
+    if (i == num) {
+        XL_LOG(ctx, XL_LOG_ERROR, "Virtual device not found");
+        return -1;
+    }
+    libxl_device_disk_del(ctx, disks + i, 1);
+    libxl_device_disk_add(ctx, domid, disk);
+    stubdomid = libxl_get_stubdom_id(ctx, domid);
+    if (stubdomid) {
+        disk_info_domid_fixup(disks + i, stubdomid);
+        libxl_device_disk_del(ctx, disks + i, 1);
+        disk_info_domid_fixup(disk, stubdomid);
+        libxl_device_disk_add(ctx, stubdomid, disk);
+        disk_info_domid_fixup(disk, domid);
+    }
+    return 0;
 }
 
 
/******************************************************************************/
diff -r b07a720e30de tools/libxl/libxl.h
--- a/tools/libxl/libxl.h       Mon Dec 07 15:19:24 2009 +0000
+++ b/tools/libxl/libxl.h       Mon Dec 07 15:20:05 2009 +0000
@@ -267,8 +267,40 @@
 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_wait_for_domain_death(struct libxl_ctx *ctx, uint32_t domid, int 
*fd);
-int libxl_is_domain_dead(struct libxl_ctx *ctx, uint32_t domid, xc_dominfo_t 
*info);
+/* events handling */
+
+typedef enum {
+    DOMAIN_DEATH,
+    DISK_EJECT,
+} libxl_event_type;
+
+typedef struct {
+    /* event type */
+    libxl_event_type type;
+    /* data for internal use of the library */
+    char *path;
+    char *token;
+} libxl_event;
+
+typedef struct {
+    char *path;
+    char *token;
+} libxl_waiter;
+
+
+int libxl_get_wait_fd(struct libxl_ctx *ctx, int *fd);
+/* waiter is allocated by the caller */
+int libxl_wait_for_domain_death(struct libxl_ctx *ctx, uint32_t domid, 
libxl_waiter *waiter);
+/* waiter is a preallocated array of num_disks libxl_waiter elements */
+int libxl_wait_for_disk_ejects(struct libxl_ctx *ctx, uint32_t domid, 
libxl_device_disk *disks, int num_disks, libxl_waiter *waiter);
+int libxl_get_event(struct libxl_ctx *ctx, libxl_event *event);
+int libxl_stop_waiting(struct libxl_ctx *ctx, libxl_waiter *waiter);
+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_dominfo_t *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_pause(struct libxl_ctx *ctx, uint32_t domid);
 int libxl_domain_unpause(struct libxl_ctx *ctx, uint32_t domid);
@@ -299,6 +331,8 @@
 
 int libxl_device_disk_add(struct libxl_ctx *ctx, uint32_t domid, 
libxl_device_disk *disk);
 int libxl_device_disk_del(struct libxl_ctx *ctx, libxl_device_disk *disk, int 
wait);
+libxl_device_disk *libxl_device_disk_list(struct libxl_ctx *ctx, uint32_t 
domid, int *num);
+int libxl_cdrom_insert(struct libxl_ctx *ctx, uint32_t domid, 
libxl_device_disk *disk);
 
 int libxl_device_nic_add(struct libxl_ctx *ctx, uint32_t domid, 
libxl_device_nic *nic);
 int libxl_device_nic_del(struct libxl_ctx *ctx, libxl_device_nic *nic, int 
wait);
diff -r b07a720e30de tools/libxl/libxl_device.c
--- a/tools/libxl/libxl_device.c        Mon Dec 07 15:19:24 2009 +0000
+++ b/tools/libxl/libxl_device.c        Mon Dec 07 15:20:05 2009 +0000
@@ -26,7 +26,7 @@
 #include "libxl.h"
 #include "libxl_internal.h"
 
-char *string_of_kinds[] = {
+const char *string_of_kinds[] = {
     [DEVICE_VIF] = "vif",
     [DEVICE_VBD] = "vbd",
     [DEVICE_TAP] = "tap",
diff -r b07a720e30de tools/libxl/libxl_internal.h
--- a/tools/libxl/libxl_internal.h      Mon Dec 07 15:19:24 2009 +0000
+++ b/tools/libxl/libxl_internal.h      Mon Dec 07 15:20:05 2009 +0000
@@ -44,6 +44,8 @@
     DEVICE_VKBD,
     DEVICE_CONSOLE,
 } libxl_device_kinds;
+
+extern const char *string_of_kinds[];
 
 typedef struct {
     uint32_t backend_devid;
diff -r b07a720e30de tools/libxl/libxl_utils.c
--- a/tools/libxl/libxl_utils.c Mon Dec 07 15:19:24 2009 +0000
+++ b/tools/libxl/libxl_utils.c Mon Dec 07 15:20:05 2009 +0000
@@ -214,3 +214,33 @@
     return 0;
 }
 
+int libxl_string_to_phystype(struct libxl_ctx *ctx, char *s, 
libxl_disk_phystype *phystype)
+{
+    char *p;
+    int rc = 0;
+
+    if (!strcmp(s, "phy")) {
+        *phystype = PHYSTYPE_PHY;
+    } else if (!strcmp(s, "file")) {
+        *phystype = PHYSTYPE_FILE;
+    } else if (!strcmp(s, "tap")) {
+        p = strchr(s, ':');
+        if (!p) {
+            rc = -1;
+            goto out;
+        }
+        p++;
+        if (!strcmp(p, "aio")) {
+            *phystype = PHYSTYPE_AIO;
+        } else if (!strcmp(p, "vhd")) {
+            *phystype = PHYSTYPE_VHD;
+        } else if (!strcmp(p, "qcow")) {
+            *phystype = PHYSTYPE_QCOW;
+        } else if (!strcmp(p, "qcow2")) {
+            *phystype = PHYSTYPE_QCOW2;
+        }
+    }
+out:
+    return rc;
+}
+
diff -r b07a720e30de tools/libxl/libxl_utils.h
--- a/tools/libxl/libxl_utils.h Mon Dec 07 15:19:24 2009 +0000
+++ b/tools/libxl/libxl_utils.h Mon Dec 07 15:20:05 2009 +0000
@@ -32,6 +32,7 @@
 int libxl_get_stubdom_id(struct libxl_ctx *ctx, int guest_domid);
 int libxl_is_stubdom(struct libxl_ctx *ctx, int domid);
 int libxl_create_logfile(struct libxl_ctx *ctx, char *name, char **full_name);
+int libxl_string_to_phystype(struct libxl_ctx *ctx, char *s, 
libxl_disk_phystype *phystype);
 
 #endif
 
diff -r b07a720e30de tools/libxl/xl.c
--- a/tools/libxl/xl.c  Mon Dec 07 15:19:24 2009 +0000
+++ b/tools/libxl/xl.c  Mon Dec 07 15:20:05 2009 +0000
@@ -356,12 +356,14 @@
             if (p2 == NULL) {
                 (*disks)[*num_disks].virtpath = strdup(p);
                 (*disks)[*num_disks].is_cdrom = 0;
+                (*disks)[*num_disks].unpluggable = 1;
             } else {
                 *p2 = '\0';
                 (*disks)[*num_disks].virtpath = strdup(p);
-                if (!strcmp(p2 + 1, "cdrom"))
+                if (!strcmp(p2 + 1, "cdrom")) {
                     (*disks)[*num_disks].is_cdrom = 1;
-                else
+                    (*disks)[*num_disks].unpluggable = 1;
+                } else
                     (*disks)[*num_disks].is_cdrom = 0;
             }
             p = strtok(NULL, ",");
@@ -594,6 +596,7 @@
     int i, fd;
     int need_daemon = 1;
     libxl_device_model_starting *dm_starting = 0;
+    libxl_waiter *w1 = NULL, *w2 = NULL;
     memset(&dm_info, 0x00, sizeof(dm_info));
 
     printf("Parsing config file %s\n", config_file);
@@ -671,12 +674,17 @@
         need_daemon = 0;
     }
     XL_LOG(&ctx, XL_LOG_DEBUG, "Waiting for domain %s (domid %d) to die", 
info1.name, domid);
-    
-    libxl_wait_for_domain_death(&ctx, domid, &fd);
+    w1 = (libxl_waiter*) malloc(sizeof(libxl_waiter) * num_disks);
+    w2 = (libxl_waiter*) malloc(sizeof(libxl_waiter));
+    libxl_wait_for_disk_ejects(&ctx, domid, disks, num_disks, w1);
+    libxl_wait_for_domain_death(&ctx, domid, w2);
+    libxl_get_wait_fd(&ctx, &fd);
     while (1) {
         int ret;
         fd_set rfds;
         xc_dominfo_t info;
+        libxl_event event;
+        libxl_device_disk disk;
         memset(&info, 0x00, sizeof(xc_dominfo_t));
 
         FD_ZERO(&rfds);
@@ -685,21 +693,35 @@
         ret = select(fd + 1, &rfds, NULL, NULL, NULL);
         if (!ret)
             continue;
-        if (libxl_is_domain_dead(&ctx, domid, &info)) {
-            XL_LOG(&ctx, XL_LOG_DEBUG, "Domain %d is dead", domid);
-            if (info.crashed || info.dying || (info.shutdown && 
(info.shutdown_reason != SHUTDOWN_suspend))) {
-                XL_LOG(&ctx, XL_LOG_DEBUG, "Domain %d needs to be clean: 
destroying the domain", domid);
-                libxl_domain_destroy(&ctx, domid, 0);
-                if (info.shutdown && (info.shutdown_reason == 
SHUTDOWN_reboot)) {
-                    libxl_ctx_free(&ctx);
-                    XL_LOG(&ctx, XL_LOG_DEBUG, "Done. Rebooting now");
-                    goto start;
+        libxl_get_event(&ctx, &event);
+        switch (event.type) {
+            case DOMAIN_DEATH:
+                if (libxl_event_get_domain_death_info(&ctx, domid, &event, 
&info)) {
+                    XL_LOG(&ctx, XL_LOG_DEBUG, "Domain %d is dead", domid);
+                    if (info.crashed || info.dying || (info.shutdown && 
(info.shutdown_reason != SHUTDOWN_suspend))) {
+                        XL_LOG(&ctx, XL_LOG_DEBUG, "Domain %d needs to be 
clean: destroying the domain", domid);
+                        libxl_domain_destroy(&ctx, domid, 0);
+                        if (info.shutdown && (info.shutdown_reason == 
SHUTDOWN_reboot)) {
+                            libxl_free_waiter(w1);
+                            libxl_free_waiter(w2);
+                            free(w1);
+                            free(w2);
+                            libxl_ctx_free(&ctx);
+                            XL_LOG(&ctx, XL_LOG_DEBUG, "Done. Rebooting now");
+                            goto start;
+                        }
+                        XL_LOG(&ctx, XL_LOG_DEBUG, "Done. Exiting now");
+                    }
+                    XL_LOG(&ctx, XL_LOG_DEBUG, "Domain %d does not need to be 
clean, exiting now", domid);
+                    exit(0);
                 }
-                XL_LOG(&ctx, XL_LOG_DEBUG, "Done. Exiting now");
-            }
-            XL_LOG(&ctx, XL_LOG_DEBUG, "Domain %d does not need to be clean, 
exiting now", domid);
-            exit(0);
+                break;
+            case DISK_EJECT:
+                if (libxl_event_get_disk_eject_info(&ctx, domid, &event, 
&disk))
+                    libxl_cdrom_insert(&ctx, domid, &disk);
+                break;
         }
+        libxl_free_event(&event);
     }
 
     close(logfile);
@@ -730,6 +752,8 @@
         printf(" console                       attach to domain's 
console\n\n");
         printf(" save                          save a domain state to restore 
later\n\n");
         printf(" restore                       restore a domain from a saved 
state\n\n");
+        printf(" cd-insert                     insert a cdrom into a guest's 
cd drive\n\n");
+        printf(" cd-eject                      eject a cdrom from a guest's cd 
drive\n\n");
     } else if(!strcmp(command, "create")) {
         printf("Usage: xl create <ConfigFile> [options] [vars]\n\n");
         printf("Create a domain based on <ConfigFile>.\n\n");
@@ -772,6 +796,12 @@
     } else if (!strcmp(command, "console")) {
         printf("Usage: xl console <Domain>\n\n");
         printf("Attach to domain's console.\n\n");
+    } else if (!strcmp(command, "cd-insert")) {
+        printf("Usage: xl cd-insert <Domain> <VirtualDevice> <type:path>\n\n");
+        printf("Insert a cdrom into a guest's cd drive.\n\n");
+    } else if (!strcmp(command, "cd-eject")) {
+        printf("Usage: xl cd-eject <Domain> <VirtualDevice>\n\n");
+        printf("Eject a cdrom from a guest's cd drive.\n\n");
     }
 }
 
@@ -788,6 +818,108 @@
         exit(2);
     }
     libxl_console_attach(&ctx, domid, cons_num);
+}
+
+void cd_insert(char *dom, char *virtdev, char *phys)
+{
+    struct libxl_ctx ctx;
+    uint32_t domid;
+    libxl_device_disk disk;
+    char *p;
+
+    libxl_ctx_init(&ctx);
+    libxl_ctx_set_log(&ctx, log_callback, NULL);
+
+    if (libxl_param_to_domid(&ctx, dom, &domid) < 0) {
+        fprintf(stderr, "%s is an invalid domain identifier\n", dom);
+        exit(2);
+    }
+
+    disk.backend_domid = 0;
+    disk.domid = domid;
+    if (phys) {
+        p = strchr(phys, ':');
+        if (!p) {
+            fprintf(stderr, "No type specified, ");
+            disk.physpath = phys;
+            if (!strncmp(phys, "/dev", 4)) {
+                fprintf(stderr, "assuming phy:\n");
+                disk.phystype = PHYSTYPE_PHY;
+            } else {
+                fprintf(stderr, "assuming file:\n");
+                disk.phystype = PHYSTYPE_FILE;
+            }
+        } else {
+            p = '\0';
+            disk.physpath = strdup(p);
+            p++;
+            libxl_string_to_phystype(&ctx, p, &disk.phystype);
+        }
+    } else {
+            disk.physpath = NULL;
+            disk.phystype = 0;
+    }
+    disk.virtpath = virtdev;
+    disk.unpluggable = 1;
+    disk.readwrite = 0;
+    disk.is_cdrom = 1;
+
+    libxl_cdrom_insert(&ctx, domid, &disk);
+}
+
+int main_cd_eject(int argc, char **argv)
+{
+    int opt = 0;
+    char *p = NULL, *virtdev;
+
+    while ((opt = getopt(argc, argv, "hn:")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("cd-eject");
+            exit(0);
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+    if (optind >= argc - 1) {
+        help("cd-eject");
+        exit(2);
+    }
+
+    p = argv[optind];
+    virtdev = argv[optind + 1];
+
+    cd_insert(p, virtdev, NULL);
+    exit(0);
+}
+
+int main_cd_insert(int argc, char **argv)
+{
+    int opt = 0;
+    char *p = NULL, *file = NULL, *virtdev;
+
+    while ((opt = getopt(argc, argv, "hn:")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("cd-insert");
+            exit(0);
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+    if (optind >= argc - 2) {
+        help("cd-insert");
+        exit(2);
+    }
+
+    p = argv[optind];
+    virtdev = argv[optind + 1];
+    file = argv[optind + 2];
+
+    cd_insert(p, virtdev, file);
+    exit(0);
 }
 
 int main_console(int argc, char **argv)
@@ -1298,6 +1430,10 @@
         main_save(argc - 1, argv + 1);
     } else if (!strcmp(argv[1], "restore")) {
         main_restore(argc - 1, argv + 1);
+    } else if (!strcmp(argv[1], "cd-insert")) {
+        main_cd_insert(argc - 1, argv + 1);
+    } else if (!strcmp(argv[1], "cd-eject")) {
+        main_cd_eject(argc - 1, argv + 1);
     } else if (!strcmp(argv[1], "help")) {
         if (argc > 2)
             help(argv[2]);

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-devel] [PATCH] libxenlight: implement cdrom insert\eject, Stefano Stabellini <=