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

[Xen-changelog] [xen-unstable] libxenlight: implement cdrom insert/eject



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1260258472 0
# Node ID 91555131e235f814e68179dc5ffd6b698be882be
# Parent  d988dd0f05f24ad3c5b1f6b84b28b8b3e93f6005
libxenlight: implement cdrom insert/eject

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>
---
 tools/libxl/libxl.c          |  202 +++++++++++++++++++++++++++++++++++++++----
 tools/libxl/libxl.h          |   38 +++++++-
 tools/libxl/libxl_device.c   |    2 
 tools/libxl/libxl_internal.h |    2 
 tools/libxl/libxl_utils.c    |   30 ++++++
 tools/libxl/libxl_utils.h    |    1 
 tools/libxl/xl.c             |  172 ++++++++++++++++++++++++++++++++----
 7 files changed, 411 insertions(+), 36 deletions(-)

diff -r d988dd0f05f2 -r 91555131e235 tools/libxl/libxl.c
--- a/tools/libxl/libxl.c       Tue Dec 08 07:45:15 2009 +0000
+++ b/tools/libxl/libxl.c       Tue Dec 08 07:47:52 2009 +0000
@@ -460,25 +460,80 @@ int libxl_domain_shutdown(struct libxl_c
     return 0;
 }
 
-int libxl_wait_for_domain_death(struct libxl_ctx *ctx, uint32_t domid, int *fd)
-{
-    if (!xs_watch(ctx->xsh, "@releaseDomain", "domain_death"))
+int libxl_get_wait_fd(struct libxl_ctx *ctx, int *fd)
+{
+    *fd = xs_fileno(ctx->xsh);
+    return 0;
+}
+
+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;
-    *fd = xs_fileno(ctx->xsh);
-    return 0;
-}
-
-int libxl_is_domain_dead(struct libxl_ctx *ctx, uint32_t domid, xc_dominfo_t 
*info)
+    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 @@ int libxl_is_domain_dead(struct libxl_ct
         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(struc
 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 d988dd0f05f2 -r 91555131e235 tools/libxl/libxl.h
--- a/tools/libxl/libxl.h       Tue Dec 08 07:45:15 2009 +0000
+++ b/tools/libxl/libxl.h       Tue Dec 08 07:47:52 2009 +0000
@@ -267,8 +267,40 @@ int libxl_domain_shutdown(struct libxl_c
 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_detach_device_model(struct lib
 
 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 d988dd0f05f2 -r 91555131e235 tools/libxl/libxl_device.c
--- a/tools/libxl/libxl_device.c        Tue Dec 08 07:45:15 2009 +0000
+++ b/tools/libxl/libxl_device.c        Tue Dec 08 07:47:52 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 d988dd0f05f2 -r 91555131e235 tools/libxl/libxl_internal.h
--- a/tools/libxl/libxl_internal.h      Tue Dec 08 07:45:15 2009 +0000
+++ b/tools/libxl/libxl_internal.h      Tue Dec 08 07:47:52 2009 +0000
@@ -44,6 +44,8 @@ typedef enum {
     DEVICE_VKBD,
     DEVICE_CONSOLE,
 } libxl_device_kinds;
+
+extern const char *string_of_kinds[];
 
 typedef struct {
     uint32_t backend_devid;
diff -r d988dd0f05f2 -r 91555131e235 tools/libxl/libxl_utils.c
--- a/tools/libxl/libxl_utils.c Tue Dec 08 07:45:15 2009 +0000
+++ b/tools/libxl/libxl_utils.c Tue Dec 08 07:47:52 2009 +0000
@@ -214,3 +214,33 @@ int libxl_create_logfile(struct libxl_ct
     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 d988dd0f05f2 -r 91555131e235 tools/libxl/libxl_utils.h
--- a/tools/libxl/libxl_utils.h Tue Dec 08 07:45:15 2009 +0000
+++ b/tools/libxl/libxl_utils.h Tue Dec 08 07:47:52 2009 +0000
@@ -32,6 +32,7 @@ int libxl_get_stubdom_id(struct libxl_ct
 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 d988dd0f05f2 -r 91555131e235 tools/libxl/xl.c
--- a/tools/libxl/xl.c  Tue Dec 08 07:45:15 2009 +0000
+++ b/tools/libxl/xl.c  Tue Dec 08 07:47:52 2009 +0000
@@ -356,12 +356,14 @@ static void parse_config_file(const char
             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 @@ static void create_domain(int debug, con
     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 @@ start:
         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 @@ start:
         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 @@ static void help(char *command)
         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 @@ static void help(char *command)
     } 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 @@ void console(char *p, int cons_num)
         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 @@ int main(int argc, char **argv)
         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-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

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