debuggers.hg

changeset 20637:91555131e235

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@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Dec 08 07:47:52 2009 +0000 (2009-12-08)
parents d988dd0f05f2
children cf4f3e2f425c
files tools/libxl/libxl.c tools/libxl/libxl.h tools/libxl/libxl_device.c tools/libxl/libxl_internal.h tools/libxl/libxl_utils.c tools/libxl/libxl_utils.h tools/libxl/xl.c
line diff
     1.1 --- a/tools/libxl/libxl.c	Tue Dec 08 07:45:15 2009 +0000
     1.2 +++ b/tools/libxl/libxl.c	Tue Dec 08 07:47:52 2009 +0000
     1.3 @@ -460,25 +460,80 @@ int libxl_domain_shutdown(struct libxl_c
     1.4      return 0;
     1.5  }
     1.6  
     1.7 -int libxl_wait_for_domain_death(struct libxl_ctx *ctx, uint32_t domid, int *fd)
     1.8 +int libxl_get_wait_fd(struct libxl_ctx *ctx, int *fd)
     1.9  {
    1.10 -    if (!xs_watch(ctx->xsh, "@releaseDomain", "domain_death"))
    1.11 -        return -1;
    1.12      *fd = xs_fileno(ctx->xsh);
    1.13      return 0;
    1.14  }
    1.15  
    1.16 -int libxl_is_domain_dead(struct libxl_ctx *ctx, uint32_t domid, xc_dominfo_t *info)
    1.17 +int libxl_wait_for_domain_death(struct libxl_ctx *ctx, uint32_t domid, libxl_waiter *waiter)
    1.18 +{
    1.19 +    waiter->path = strdup("@releaseDomain");
    1.20 +    asprintf(&(waiter->token), "%d", DOMAIN_DEATH);
    1.21 +    if (!xs_watch(ctx->xsh, waiter->path, waiter->token))
    1.22 +        return -1;
    1.23 +    return 0;
    1.24 +}
    1.25 +
    1.26 +int libxl_wait_for_disk_ejects(struct libxl_ctx *ctx, uint32_t guest_domid, libxl_device_disk *disks, int num_disks, libxl_waiter *waiter)
    1.27 +{
    1.28 +    int i;
    1.29 +    uint32_t domid = libxl_get_stubdom_id(ctx, guest_domid);
    1.30 +
    1.31 +    if (!domid)
    1.32 +        domid = guest_domid;
    1.33 +
    1.34 +    for (i = 0; i < num_disks; i++) {
    1.35 +        asprintf(&(waiter[i].path), "%s/device/vbd/%d/eject", libxl_xs_get_dompath(ctx, domid), device_disk_dev_number(disks[i].virtpath));
    1.36 +        asprintf(&(waiter[i].token), "%d", DISK_EJECT);
    1.37 +        xs_watch(ctx->xsh, waiter->path, waiter->token);
    1.38 +    }
    1.39 +    return 0;
    1.40 +}
    1.41 +
    1.42 +int libxl_get_event(struct libxl_ctx *ctx, libxl_event *event)
    1.43  {
    1.44      unsigned int num;
    1.45 +    char **events = xs_read_watch(ctx->xsh, &num);
    1.46 +    if (num != 2) {
    1.47 +        free(events);
    1.48 +        return -1;
    1.49 +    }
    1.50 +    event->path = strdup(events[XS_WATCH_PATH]);
    1.51 +    event->token = strdup(events[XS_WATCH_TOKEN]);
    1.52 +    event->type = atoi(event->token);
    1.53 +    free(events);
    1.54 +    return 0;
    1.55 +}
    1.56 +
    1.57 +int libxl_stop_waiting(struct libxl_ctx *ctx, libxl_waiter *waiter)
    1.58 +{
    1.59 +    if (!xs_unwatch(ctx->xsh, waiter->path, waiter->token))
    1.60 +        return -1;
    1.61 +    else
    1.62 +        return 0;
    1.63 +}
    1.64 +
    1.65 +int libxl_free_event(libxl_event *event)
    1.66 +{
    1.67 +    free(event->path);
    1.68 +    free(event->token);
    1.69 +    return 0;
    1.70 +}
    1.71 +
    1.72 +int libxl_free_waiter(libxl_waiter *waiter)
    1.73 +{
    1.74 +    free(waiter->path);
    1.75 +    free(waiter->token);
    1.76 +    return 0;
    1.77 +}
    1.78 +
    1.79 +int libxl_event_get_domain_death_info(struct libxl_ctx *ctx, uint32_t domid, libxl_event *event, xc_dominfo_t *info)
    1.80 +{
    1.81      int nb_domain, i, rc = 0;
    1.82 -    char **vec = NULL;
    1.83      xc_dominfo_t *list = NULL;
    1.84  
    1.85 -    vec = xs_read_watch(ctx->xsh, &num);
    1.86 -    if (!vec)
    1.87 -        return 0;
    1.88 -    if (!strcmp(vec[XS_WATCH_TOKEN], "domain_death")) {
    1.89 +    if (event && event->type == DOMAIN_DEATH) {
    1.90          list = libxl_domain_infolist(ctx, &nb_domain);
    1.91          for (i = 0; i < nb_domain; i++) {
    1.92              if (domid == list[i].domid) {
    1.93 @@ -493,13 +548,41 @@ int libxl_is_domain_dead(struct libxl_ct
    1.94          rc = 1;
    1.95          goto out;
    1.96      }
    1.97 -
    1.98  out:
    1.99      free(list);
   1.100 -    free(vec);
   1.101      return rc;
   1.102  }
   1.103  
   1.104 +int libxl_event_get_disk_eject_info(struct libxl_ctx *ctx, uint32_t domid, libxl_event *event, libxl_device_disk *disk)
   1.105 +{
   1.106 +    if (event && event->type == DISK_EJECT) {
   1.107 +        char *path;
   1.108 +        char *backend;
   1.109 +        char *value = libxl_xs_read(ctx, XBT_NULL, event->path);
   1.110 +
   1.111 +        if (!value || strcmp(value,  "eject"))
   1.112 +            return 0;
   1.113 +
   1.114 +        path = strdup(event->path);
   1.115 +        path[strlen(path) - 6] = '\0';
   1.116 +        backend = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/backend", path));
   1.117 +
   1.118 +        disk->backend_domid = 0;
   1.119 +        disk->domid = domid;
   1.120 +        disk->physpath = NULL;
   1.121 +        disk->phystype = 0;
   1.122 +        /* this value is returned to the user: do not free right away */
   1.123 +        disk->virtpath = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/dev", backend));
   1.124 +        disk->unpluggable = 1;
   1.125 +        disk->readwrite = 0;
   1.126 +        disk->is_cdrom = 1;
   1.127 +
   1.128 +        free(path);
   1.129 +        return 1;
   1.130 +    }
   1.131 +    return 0;
   1.132 +}
   1.133 +
   1.134  static int libxl_destroy_device_model(struct libxl_ctx *ctx, uint32_t domid)
   1.135  {
   1.136      char *pid;
   1.137 @@ -1421,6 +1504,95 @@ int libxl_device_vkb_hard_shutdown(struc
   1.138      return ERROR_NI;
   1.139  }
   1.140  
   1.141 +libxl_device_disk *libxl_device_disk_list(struct libxl_ctx *ctx, uint32_t domid, int *num)
   1.142 +{
   1.143 +    char *be_path_tap, *be_path_vbd;
   1.144 +    libxl_device_disk *disks = NULL;
   1.145 +    char **l = NULL;
   1.146 +    unsigned int numl;
   1.147 +    int num_disks = 0, i;
   1.148 +    char *type;
   1.149 +
   1.150 +    be_path_vbd = libxl_sprintf(ctx, "%s/backend/vbd/%d", libxl_xs_get_dompath(ctx, 0), domid);
   1.151 +    be_path_tap = libxl_sprintf(ctx, "%s/backend/tap/%d", libxl_xs_get_dompath(ctx, 0), domid);
   1.152 +
   1.153 +    l = libxl_xs_directory(ctx, XBT_NULL, be_path_vbd, &numl);
   1.154 +    if (l) {
   1.155 +        num_disks += numl;
   1.156 +        disks = realloc(disks, sizeof(libxl_device_disk) * num_disks);
   1.157 +        for (i = 0; i < numl; i++) {
   1.158 +            disks[i].backend_domid = 0;
   1.159 +            disks[i].domid = domid;
   1.160 +            disks[i].physpath = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/params", be_path_vbd, l[i]));
   1.161 +            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));
   1.162 +            disks[i].virtpath = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/dev", be_path_vbd, l[i]));
   1.163 +            disks[i].unpluggable = atoi(libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/removable", be_path_vbd, l[i])));
   1.164 +            if (!strcmp(libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/mode", be_path_vbd, l[i])), "w"))
   1.165 +                disks[i].readwrite = 1;
   1.166 +            else
   1.167 +                disks[i].readwrite = 0;
   1.168 +            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]))));
   1.169 +            disks[i].is_cdrom = !strcmp(type, "cdrom");
   1.170 +        }
   1.171 +        free(l);
   1.172 +    }
   1.173 +    l = libxl_xs_directory(ctx, XBT_NULL, be_path_tap, &numl);
   1.174 +    if (l) {
   1.175 +        num_disks += numl;
   1.176 +        disks = realloc(disks, sizeof(libxl_device_disk) * num_disks);
   1.177 +        for (i = 0; i < numl; i++) {
   1.178 +            disks[i].backend_domid = 0;
   1.179 +            disks[i].domid = domid;
   1.180 +            disks[i].physpath = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/params", be_path_tap, l[i]));
   1.181 +            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));
   1.182 +            disks[i].virtpath = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/dev", be_path_tap, l[i]));
   1.183 +            disks[i].unpluggable = atoi(libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/removable", be_path_tap, l[i])));
   1.184 +            if (!strcmp(libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/mode", be_path_tap, l[i])), "w"))
   1.185 +                disks[i].readwrite = 1;
   1.186 +            else
   1.187 +                disks[i].readwrite = 0;
   1.188 +            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]))));
   1.189 +            disks[i].is_cdrom = !strcmp(type, "cdrom");
   1.190 +        }
   1.191 +        free(l);
   1.192 +    }
   1.193 +    *num = num_disks;
   1.194 +    return disks;
   1.195 +}
   1.196 +
   1.197 +int libxl_cdrom_insert(struct libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk)
   1.198 +{
   1.199 +    int num, i;
   1.200 +    uint32_t stubdomid;
   1.201 +    libxl_device_disk *disks;
   1.202 +
   1.203 +    if (!disk->physpath) {
   1.204 +        disk->physpath = "";
   1.205 +        disk->phystype = PHYSTYPE_PHY;
   1.206 +    }
   1.207 +    disks = libxl_device_disk_list(ctx, domid, &num);
   1.208 +    for (i = 0; i < num; i++) {
   1.209 +        if (disks[i].is_cdrom && !strcmp(disk->virtpath, disks[i].virtpath))
   1.210 +            /* found */
   1.211 +            break;
   1.212 +    }
   1.213 +    if (i == num) {
   1.214 +        XL_LOG(ctx, XL_LOG_ERROR, "Virtual device not found");
   1.215 +        return -1;
   1.216 +    }
   1.217 +    libxl_device_disk_del(ctx, disks + i, 1);
   1.218 +    libxl_device_disk_add(ctx, domid, disk);
   1.219 +    stubdomid = libxl_get_stubdom_id(ctx, domid);
   1.220 +    if (stubdomid) {
   1.221 +        disk_info_domid_fixup(disks + i, stubdomid);
   1.222 +        libxl_device_disk_del(ctx, disks + i, 1);
   1.223 +        disk_info_domid_fixup(disk, stubdomid);
   1.224 +        libxl_device_disk_add(ctx, stubdomid, disk);
   1.225 +        disk_info_domid_fixup(disk, domid);
   1.226 +    }
   1.227 +    return 0;
   1.228 +}
   1.229 +
   1.230  /******************************************************************************/
   1.231  static int libxl_build_xenpv_qemu_args(struct libxl_ctx *ctx,
   1.232                                         libxl_device_vfb *vfb,
     2.1 --- a/tools/libxl/libxl.h	Tue Dec 08 07:45:15 2009 +0000
     2.2 +++ b/tools/libxl/libxl.h	Tue Dec 08 07:47:52 2009 +0000
     2.3 @@ -267,8 +267,40 @@ int libxl_domain_resume(struct libxl_ctx
     2.4  int libxl_domain_shutdown(struct libxl_ctx *ctx, uint32_t domid, int req);
     2.5  int libxl_domain_destroy(struct libxl_ctx *ctx, uint32_t domid, int force);
     2.6  
     2.7 -int libxl_wait_for_domain_death(struct libxl_ctx *ctx, uint32_t domid, int *fd);
     2.8 -int libxl_is_domain_dead(struct libxl_ctx *ctx, uint32_t domid, xc_dominfo_t *info);
     2.9 +/* events handling */
    2.10 +
    2.11 +typedef enum {
    2.12 +    DOMAIN_DEATH,
    2.13 +    DISK_EJECT,
    2.14 +} libxl_event_type;
    2.15 +
    2.16 +typedef struct {
    2.17 +    /* event type */
    2.18 +    libxl_event_type type;
    2.19 +    /* data for internal use of the library */
    2.20 +    char *path;
    2.21 +    char *token;
    2.22 +} libxl_event;
    2.23 +
    2.24 +typedef struct {
    2.25 +    char *path;
    2.26 +    char *token;
    2.27 +} libxl_waiter;
    2.28 +
    2.29 +
    2.30 +int libxl_get_wait_fd(struct libxl_ctx *ctx, int *fd);
    2.31 +/* waiter is allocated by the caller */
    2.32 +int libxl_wait_for_domain_death(struct libxl_ctx *ctx, uint32_t domid, libxl_waiter *waiter);
    2.33 +/* waiter is a preallocated array of num_disks libxl_waiter elements */
    2.34 +int libxl_wait_for_disk_ejects(struct libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disks, int num_disks, libxl_waiter *waiter);
    2.35 +int libxl_get_event(struct libxl_ctx *ctx, libxl_event *event);
    2.36 +int libxl_stop_waiting(struct libxl_ctx *ctx, libxl_waiter *waiter);
    2.37 +int libxl_free_event(libxl_event *event);
    2.38 +int libxl_free_waiter(libxl_waiter *waiter);
    2.39 +
    2.40 +int libxl_event_get_domain_death_info(struct libxl_ctx *ctx, uint32_t domid, libxl_event *event, xc_dominfo_t *info);
    2.41 +int libxl_event_get_disk_eject_info(struct libxl_ctx *ctx, uint32_t domid, libxl_event *event, libxl_device_disk *disk);
    2.42 +
    2.43  
    2.44  int libxl_domain_pause(struct libxl_ctx *ctx, uint32_t domid);
    2.45  int libxl_domain_unpause(struct libxl_ctx *ctx, uint32_t domid);
    2.46 @@ -299,6 +331,8 @@ int libxl_detach_device_model(struct lib
    2.47  
    2.48  int libxl_device_disk_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk);
    2.49  int libxl_device_disk_del(struct libxl_ctx *ctx, libxl_device_disk *disk, int wait);
    2.50 +libxl_device_disk *libxl_device_disk_list(struct libxl_ctx *ctx, uint32_t domid, int *num);
    2.51 +int libxl_cdrom_insert(struct libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk);
    2.52  
    2.53  int libxl_device_nic_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic);
    2.54  int libxl_device_nic_del(struct libxl_ctx *ctx, libxl_device_nic *nic, int wait);
     3.1 --- a/tools/libxl/libxl_device.c	Tue Dec 08 07:45:15 2009 +0000
     3.2 +++ b/tools/libxl/libxl_device.c	Tue Dec 08 07:47:52 2009 +0000
     3.3 @@ -26,7 +26,7 @@
     3.4  #include "libxl.h"
     3.5  #include "libxl_internal.h"
     3.6  
     3.7 -char *string_of_kinds[] = {
     3.8 +const char *string_of_kinds[] = {
     3.9      [DEVICE_VIF] = "vif",
    3.10      [DEVICE_VBD] = "vbd",
    3.11      [DEVICE_TAP] = "tap",
     4.1 --- a/tools/libxl/libxl_internal.h	Tue Dec 08 07:45:15 2009 +0000
     4.2 +++ b/tools/libxl/libxl_internal.h	Tue Dec 08 07:47:52 2009 +0000
     4.3 @@ -45,6 +45,8 @@ typedef enum {
     4.4      DEVICE_CONSOLE,
     4.5  } libxl_device_kinds;
     4.6  
     4.7 +extern const char *string_of_kinds[];
     4.8 +
     4.9  typedef struct {
    4.10      uint32_t backend_devid;
    4.11      uint32_t backend_domid;
     5.1 --- a/tools/libxl/libxl_utils.c	Tue Dec 08 07:45:15 2009 +0000
     5.2 +++ b/tools/libxl/libxl_utils.c	Tue Dec 08 07:47:52 2009 +0000
     5.3 @@ -214,3 +214,33 @@ int libxl_create_logfile(struct libxl_ct
     5.4      return 0;
     5.5  }
     5.6  
     5.7 +int libxl_string_to_phystype(struct libxl_ctx *ctx, char *s, libxl_disk_phystype *phystype)
     5.8 +{
     5.9 +    char *p;
    5.10 +    int rc = 0;
    5.11 +
    5.12 +    if (!strcmp(s, "phy")) {
    5.13 +        *phystype = PHYSTYPE_PHY;
    5.14 +    } else if (!strcmp(s, "file")) {
    5.15 +        *phystype = PHYSTYPE_FILE;
    5.16 +    } else if (!strcmp(s, "tap")) {
    5.17 +        p = strchr(s, ':');
    5.18 +        if (!p) {
    5.19 +            rc = -1;
    5.20 +            goto out;
    5.21 +        }
    5.22 +        p++;
    5.23 +        if (!strcmp(p, "aio")) {
    5.24 +            *phystype = PHYSTYPE_AIO;
    5.25 +        } else if (!strcmp(p, "vhd")) {
    5.26 +            *phystype = PHYSTYPE_VHD;
    5.27 +        } else if (!strcmp(p, "qcow")) {
    5.28 +            *phystype = PHYSTYPE_QCOW;
    5.29 +        } else if (!strcmp(p, "qcow2")) {
    5.30 +            *phystype = PHYSTYPE_QCOW2;
    5.31 +        }
    5.32 +    }
    5.33 +out:
    5.34 +    return rc;
    5.35 +}
    5.36 +
     6.1 --- a/tools/libxl/libxl_utils.h	Tue Dec 08 07:45:15 2009 +0000
     6.2 +++ b/tools/libxl/libxl_utils.h	Tue Dec 08 07:47:52 2009 +0000
     6.3 @@ -32,6 +32,7 @@ int libxl_param_to_domid(struct libxl_ct
     6.4  int libxl_get_stubdom_id(struct libxl_ctx *ctx, int guest_domid);
     6.5  int libxl_is_stubdom(struct libxl_ctx *ctx, int domid);
     6.6  int libxl_create_logfile(struct libxl_ctx *ctx, char *name, char **full_name);
     6.7 +int libxl_string_to_phystype(struct libxl_ctx *ctx, char *s, libxl_disk_phystype *phystype);
     6.8  
     6.9  #endif
    6.10  
     7.1 --- a/tools/libxl/xl.c	Tue Dec 08 07:45:15 2009 +0000
     7.2 +++ b/tools/libxl/xl.c	Tue Dec 08 07:47:52 2009 +0000
     7.3 @@ -356,12 +356,14 @@ static void parse_config_file(const char
     7.4              if (p2 == NULL) {
     7.5                  (*disks)[*num_disks].virtpath = strdup(p);
     7.6                  (*disks)[*num_disks].is_cdrom = 0;
     7.7 +                (*disks)[*num_disks].unpluggable = 1;
     7.8              } else {
     7.9                  *p2 = '\0';
    7.10                  (*disks)[*num_disks].virtpath = strdup(p);
    7.11 -                if (!strcmp(p2 + 1, "cdrom"))
    7.12 +                if (!strcmp(p2 + 1, "cdrom")) {
    7.13                      (*disks)[*num_disks].is_cdrom = 1;
    7.14 -                else
    7.15 +                    (*disks)[*num_disks].unpluggable = 1;
    7.16 +                } else
    7.17                      (*disks)[*num_disks].is_cdrom = 0;
    7.18              }
    7.19              p = strtok(NULL, ",");
    7.20 @@ -594,6 +596,7 @@ static void create_domain(int debug, con
    7.21      int i, fd;
    7.22      int need_daemon = 1;
    7.23      libxl_device_model_starting *dm_starting = 0;
    7.24 +    libxl_waiter *w1 = NULL, *w2 = NULL;
    7.25      memset(&dm_info, 0x00, sizeof(dm_info));
    7.26  
    7.27      printf("Parsing config file %s\n", config_file);
    7.28 @@ -671,12 +674,17 @@ start:
    7.29          need_daemon = 0;
    7.30      }
    7.31      XL_LOG(&ctx, XL_LOG_DEBUG, "Waiting for domain %s (domid %d) to die", info1.name, domid);
    7.32 -    
    7.33 -    libxl_wait_for_domain_death(&ctx, domid, &fd);
    7.34 +    w1 = (libxl_waiter*) malloc(sizeof(libxl_waiter) * num_disks);
    7.35 +    w2 = (libxl_waiter*) malloc(sizeof(libxl_waiter));
    7.36 +    libxl_wait_for_disk_ejects(&ctx, domid, disks, num_disks, w1);
    7.37 +    libxl_wait_for_domain_death(&ctx, domid, w2);
    7.38 +    libxl_get_wait_fd(&ctx, &fd);
    7.39      while (1) {
    7.40          int ret;
    7.41          fd_set rfds;
    7.42          xc_dominfo_t info;
    7.43 +        libxl_event event;
    7.44 +        libxl_device_disk disk;
    7.45          memset(&info, 0x00, sizeof(xc_dominfo_t));
    7.46  
    7.47          FD_ZERO(&rfds);
    7.48 @@ -685,21 +693,35 @@ start:
    7.49          ret = select(fd + 1, &rfds, NULL, NULL, NULL);
    7.50          if (!ret)
    7.51              continue;
    7.52 -        if (libxl_is_domain_dead(&ctx, domid, &info)) {
    7.53 -            XL_LOG(&ctx, XL_LOG_DEBUG, "Domain %d is dead", domid);
    7.54 -            if (info.crashed || info.dying || (info.shutdown && (info.shutdown_reason != SHUTDOWN_suspend))) {
    7.55 -                XL_LOG(&ctx, XL_LOG_DEBUG, "Domain %d needs to be clean: destroying the domain", domid);
    7.56 -                libxl_domain_destroy(&ctx, domid, 0);
    7.57 -                if (info.shutdown && (info.shutdown_reason == SHUTDOWN_reboot)) {
    7.58 -                    libxl_ctx_free(&ctx);
    7.59 -                    XL_LOG(&ctx, XL_LOG_DEBUG, "Done. Rebooting now");
    7.60 -                    goto start;
    7.61 +        libxl_get_event(&ctx, &event);
    7.62 +        switch (event.type) {
    7.63 +            case DOMAIN_DEATH:
    7.64 +                if (libxl_event_get_domain_death_info(&ctx, domid, &event, &info)) {
    7.65 +                    XL_LOG(&ctx, XL_LOG_DEBUG, "Domain %d is dead", domid);
    7.66 +                    if (info.crashed || info.dying || (info.shutdown && (info.shutdown_reason != SHUTDOWN_suspend))) {
    7.67 +                        XL_LOG(&ctx, XL_LOG_DEBUG, "Domain %d needs to be clean: destroying the domain", domid);
    7.68 +                        libxl_domain_destroy(&ctx, domid, 0);
    7.69 +                        if (info.shutdown && (info.shutdown_reason == SHUTDOWN_reboot)) {
    7.70 +                            libxl_free_waiter(w1);
    7.71 +                            libxl_free_waiter(w2);
    7.72 +                            free(w1);
    7.73 +                            free(w2);
    7.74 +                            libxl_ctx_free(&ctx);
    7.75 +                            XL_LOG(&ctx, XL_LOG_DEBUG, "Done. Rebooting now");
    7.76 +                            goto start;
    7.77 +                        }
    7.78 +                        XL_LOG(&ctx, XL_LOG_DEBUG, "Done. Exiting now");
    7.79 +                    }
    7.80 +                    XL_LOG(&ctx, XL_LOG_DEBUG, "Domain %d does not need to be clean, exiting now", domid);
    7.81 +                    exit(0);
    7.82                  }
    7.83 -                XL_LOG(&ctx, XL_LOG_DEBUG, "Done. Exiting now");
    7.84 -            }
    7.85 -            XL_LOG(&ctx, XL_LOG_DEBUG, "Domain %d does not need to be clean, exiting now", domid);
    7.86 -            exit(0);
    7.87 +                break;
    7.88 +            case DISK_EJECT:
    7.89 +                if (libxl_event_get_disk_eject_info(&ctx, domid, &event, &disk))
    7.90 +                    libxl_cdrom_insert(&ctx, domid, &disk);
    7.91 +                break;
    7.92          }
    7.93 +        libxl_free_event(&event);
    7.94      }
    7.95  
    7.96      close(logfile);
    7.97 @@ -730,6 +752,8 @@ static void help(char *command)
    7.98          printf(" console                       attach to domain's console\n\n");
    7.99          printf(" save                          save a domain state to restore later\n\n");
   7.100          printf(" restore                       restore a domain from a saved state\n\n");
   7.101 +        printf(" cd-insert                     insert a cdrom into a guest's cd drive\n\n");
   7.102 +        printf(" cd-eject                      eject a cdrom from a guest's cd drive\n\n");
   7.103      } else if(!strcmp(command, "create")) {
   7.104          printf("Usage: xl create <ConfigFile> [options] [vars]\n\n");
   7.105          printf("Create a domain based on <ConfigFile>.\n\n");
   7.106 @@ -772,6 +796,12 @@ static void help(char *command)
   7.107      } else if (!strcmp(command, "console")) {
   7.108          printf("Usage: xl console <Domain>\n\n");
   7.109          printf("Attach to domain's console.\n\n");
   7.110 +    } else if (!strcmp(command, "cd-insert")) {
   7.111 +        printf("Usage: xl cd-insert <Domain> <VirtualDevice> <type:path>\n\n");
   7.112 +        printf("Insert a cdrom into a guest's cd drive.\n\n");
   7.113 +    } else if (!strcmp(command, "cd-eject")) {
   7.114 +        printf("Usage: xl cd-eject <Domain> <VirtualDevice>\n\n");
   7.115 +        printf("Eject a cdrom from a guest's cd drive.\n\n");
   7.116      }
   7.117  }
   7.118  
   7.119 @@ -790,6 +820,108 @@ void console(char *p, int cons_num)
   7.120      libxl_console_attach(&ctx, domid, cons_num);
   7.121  }
   7.122  
   7.123 +void cd_insert(char *dom, char *virtdev, char *phys)
   7.124 +{
   7.125 +    struct libxl_ctx ctx;
   7.126 +    uint32_t domid;
   7.127 +    libxl_device_disk disk;
   7.128 +    char *p;
   7.129 +
   7.130 +    libxl_ctx_init(&ctx);
   7.131 +    libxl_ctx_set_log(&ctx, log_callback, NULL);
   7.132 +
   7.133 +    if (libxl_param_to_domid(&ctx, dom, &domid) < 0) {
   7.134 +        fprintf(stderr, "%s is an invalid domain identifier\n", dom);
   7.135 +        exit(2);
   7.136 +    }
   7.137 +
   7.138 +    disk.backend_domid = 0;
   7.139 +    disk.domid = domid;
   7.140 +    if (phys) {
   7.141 +        p = strchr(phys, ':');
   7.142 +        if (!p) {
   7.143 +            fprintf(stderr, "No type specified, ");
   7.144 +            disk.physpath = phys;
   7.145 +            if (!strncmp(phys, "/dev", 4)) {
   7.146 +                fprintf(stderr, "assuming phy:\n");
   7.147 +                disk.phystype = PHYSTYPE_PHY;
   7.148 +            } else {
   7.149 +                fprintf(stderr, "assuming file:\n");
   7.150 +                disk.phystype = PHYSTYPE_FILE;
   7.151 +            }
   7.152 +        } else {
   7.153 +            p = '\0';
   7.154 +            disk.physpath = strdup(p);
   7.155 +            p++;
   7.156 +            libxl_string_to_phystype(&ctx, p, &disk.phystype);
   7.157 +        }
   7.158 +    } else {
   7.159 +            disk.physpath = NULL;
   7.160 +            disk.phystype = 0;
   7.161 +    }
   7.162 +    disk.virtpath = virtdev;
   7.163 +    disk.unpluggable = 1;
   7.164 +    disk.readwrite = 0;
   7.165 +    disk.is_cdrom = 1;
   7.166 +
   7.167 +    libxl_cdrom_insert(&ctx, domid, &disk);
   7.168 +}
   7.169 +
   7.170 +int main_cd_eject(int argc, char **argv)
   7.171 +{
   7.172 +    int opt = 0;
   7.173 +    char *p = NULL, *virtdev;
   7.174 +
   7.175 +    while ((opt = getopt(argc, argv, "hn:")) != -1) {
   7.176 +        switch (opt) {
   7.177 +        case 'h':
   7.178 +            help("cd-eject");
   7.179 +            exit(0);
   7.180 +        default:
   7.181 +            fprintf(stderr, "option not supported\n");
   7.182 +            break;
   7.183 +        }
   7.184 +    }
   7.185 +    if (optind >= argc - 1) {
   7.186 +        help("cd-eject");
   7.187 +        exit(2);
   7.188 +    }
   7.189 +
   7.190 +    p = argv[optind];
   7.191 +    virtdev = argv[optind + 1];
   7.192 +
   7.193 +    cd_insert(p, virtdev, NULL);
   7.194 +    exit(0);
   7.195 +}
   7.196 +
   7.197 +int main_cd_insert(int argc, char **argv)
   7.198 +{
   7.199 +    int opt = 0;
   7.200 +    char *p = NULL, *file = NULL, *virtdev;
   7.201 +
   7.202 +    while ((opt = getopt(argc, argv, "hn:")) != -1) {
   7.203 +        switch (opt) {
   7.204 +        case 'h':
   7.205 +            help("cd-insert");
   7.206 +            exit(0);
   7.207 +        default:
   7.208 +            fprintf(stderr, "option not supported\n");
   7.209 +            break;
   7.210 +        }
   7.211 +    }
   7.212 +    if (optind >= argc - 2) {
   7.213 +        help("cd-insert");
   7.214 +        exit(2);
   7.215 +    }
   7.216 +
   7.217 +    p = argv[optind];
   7.218 +    virtdev = argv[optind + 1];
   7.219 +    file = argv[optind + 2];
   7.220 +
   7.221 +    cd_insert(p, virtdev, file);
   7.222 +    exit(0);
   7.223 +}
   7.224 +
   7.225  int main_console(int argc, char **argv)
   7.226  {
   7.227      int opt = 0, cons_num = 0;
   7.228 @@ -1298,6 +1430,10 @@ int main(int argc, char **argv)
   7.229          main_save(argc - 1, argv + 1);
   7.230      } else if (!strcmp(argv[1], "restore")) {
   7.231          main_restore(argc - 1, argv + 1);
   7.232 +    } else if (!strcmp(argv[1], "cd-insert")) {
   7.233 +        main_cd_insert(argc - 1, argv + 1);
   7.234 +    } else if (!strcmp(argv[1], "cd-eject")) {
   7.235 +        main_cd_eject(argc - 1, argv + 1);
   7.236      } else if (!strcmp(argv[1], "help")) {
   7.237          if (argc > 2)
   7.238              help(argv[2]);