aboutsummaryrefslogtreecommitdiffstats
path: root/tools/libxl
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2009-12-08 07:47:52 +0000
committerKeir Fraser <keir.fraser@citrix.com>2009-12-08 07:47:52 +0000
commit7b4effff892d18d8e83563a7e6868bb7c7749fc5 (patch)
tree75fff8f77c32c9d773064852abc8b549921c6e85 /tools/libxl
parent4baca0b56014781751a5dcca4eb8abf4c08b16ba (diff)
downloadxen-7b4effff892d18d8e83563a7e6868bb7c7749fc5.tar.gz
xen-7b4effff892d18d8e83563a7e6868bb7c7749fc5.tar.bz2
xen-7b4effff892d18d8e83563a7e6868bb7c7749fc5.zip
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>
Diffstat (limited to 'tools/libxl')
-rw-r--r--tools/libxl/libxl.c194
-rw-r--r--tools/libxl/libxl.h38
-rw-r--r--tools/libxl/libxl_device.c2
-rw-r--r--tools/libxl/libxl_internal.h2
-rw-r--r--tools/libxl/libxl_utils.c30
-rw-r--r--tools/libxl/libxl_utils.h1
-rw-r--r--tools/libxl/xl.c170
7 files changed, 406 insertions, 31 deletions
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 91b07c3bdc..18dae36f1d 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -460,25 +460,80 @@ int libxl_domain_shutdown(struct libxl_ctx *ctx, uint32_t domid, int req)
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,13 +548,41 @@ int libxl_is_domain_dead(struct libxl_ctx *ctx, uint32_t domid, xc_dominfo_t *in
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)
{
char *pid;
@@ -1421,6 +1504,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;
+}
+
/******************************************************************************/
static int libxl_build_xenpv_qemu_args(struct libxl_ctx *ctx,
libxl_device_vfb *vfb,
diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index 900f020c13..f315136b5e 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -267,8 +267,40 @@ int libxl_domain_resume(struct libxl_ctx *ctx, uint32_t domid);
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 libxl_ctx *ctx,
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 --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index 36f36841ab..4929c229b3 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -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 --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index f502bac359..72997940f4 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -45,6 +45,8 @@ typedef enum {
DEVICE_CONSOLE,
} libxl_device_kinds;
+extern const char *string_of_kinds[];
+
typedef struct {
uint32_t backend_devid;
uint32_t backend_domid;
diff --git a/tools/libxl/libxl_utils.c b/tools/libxl/libxl_utils.c
index 3d731ce029..66730c39ff 100644
--- a/tools/libxl/libxl_utils.c
+++ b/tools/libxl/libxl_utils.c
@@ -214,3 +214,33 @@ int libxl_create_logfile(struct libxl_ctx *ctx, char *name, char **full_name)
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 --git a/tools/libxl/libxl_utils.h b/tools/libxl/libxl_utils.h
index cf57b0febb..50fc0f893c 100644
--- a/tools/libxl/libxl_utils.h
+++ b/tools/libxl/libxl_utils.h
@@ -32,6 +32,7 @@ int libxl_param_to_domid(struct libxl_ctx *ctx, char *p, uint32_t *domid);
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 --git a/tools/libxl/xl.c b/tools/libxl/xl.c
index cb19e7129a..434d947f08 100644
--- a/tools/libxl/xl.c
+++ b/tools/libxl/xl.c
@@ -356,12 +356,14 @@ static void parse_config_file(const char *filename,
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, const char *config_file, const char *restor
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");
}
}
@@ -790,6 +820,108 @@ void console(char *p, int cons_num)
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)
{
int opt = 0, cons_num = 0;
@@ -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]);