[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 0 of 3] Refactor libxl domain creation
Just thought of a fourth patch for this series. It leaves libxl.c ~800 lines slimmer and looking good for it. -- xl: Move device model functions in to a separate file No functional changes. Signed-off-by: Gianni Tedesco <gianni.tedesco@xxxxxxxxxx> # HG changeset patch # Parent 1ff6243eba261a0ae731b62a5c55bcbb18b6069a diff -r 1ff6243eba26 tools/libxl/Makefile --- a/tools/libxl/Makefile Tue Jan 04 16:27:45 2011 +0000 +++ b/tools/libxl/Makefile Tue Jan 04 17:44:26 2011 +0000 @@ -29,7 +29,7 @@ endif LIBXL_OBJS-$(CONFIG_X86) += libxl_cpuid.o LIBXL_OBJS-$(CONFIG_IA64) += libxl_nocpuid.o -LIBXL_OBJS = libxl.o libxl_create.o libxl_pci.o libxl_dom.o libxl_exec.o libxl_xshelp.o libxl_device.o libxl_internal.o libxl_utils.o $(LIBXL_OBJS-y) +LIBXL_OBJS = libxl.o libxl_create.o libxl_dm.o libxl_pci.o libxl_dom.o libxl_exec.o libxl_xshelp.o libxl_device.o libxl_internal.o libxl_utils.o $(LIBXL_OBJS-y) LIBXL_OBJS += _libxl_types.o AUTOINCS= libxlu_cfg_y.h libxlu_cfg_l.h diff -r 1ff6243eba26 tools/libxl/libxl.c --- a/tools/libxl/libxl.c Tue Jan 04 16:27:45 2011 +0000 +++ b/tools/libxl/libxl.c Tue Jan 04 17:44:26 2011 +0000 @@ -659,46 +659,6 @@ int libxl_event_get_disk_eject_info(libx return 1; } -static int libxl_destroy_device_model(libxl_ctx *ctx, uint32_t domid) -{ - libxl__gc gc = LIBXL_INIT_GC(ctx); - char *pid; - int ret; - - pid = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "/local/domain/%d/image/device-model-pid", domid)); - if (!pid) { - int stubdomid = libxl_get_stubdom_id(ctx, domid); - if (!stubdomid) { - LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "Couldn't find device model's pid"); - ret = ERROR_INVAL; - goto out; - } - LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Device model is a stubdom, domid=%d\n", stubdomid); - ret = libxl_domain_destroy(ctx, stubdomid, 0); - if (ret) - goto out; - } else { - ret = kill(atoi(pid), SIGHUP); - if (ret < 0 && errno == ESRCH) { - LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Device Model already exited"); - ret = 0; - } else if (ret == 0) { - LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Device Model signaled"); - ret = 0; - } else { - LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "failed to kill Device Model [%d]", - atoi(pid)); - ret = ERROR_FAIL; - goto out; - } - } - xs_rm(ctx->xsh, XBT_NULL, libxl__sprintf(&gc, "/local/domain/0/device-model/%d", domid)); - -out: - libxl__free_all(&gc); - return ret; -} - int libxl_domain_destroy(libxl_ctx *ctx, uint32_t domid, int force) { libxl__gc gc = LIBXL_INIT_GC(ctx); @@ -732,8 +692,8 @@ int libxl_domain_destroy(libxl_ctx *ctx, LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc, "xc_domain_pause failed for %d", domid); } if (dm_present) { - if (libxl_destroy_device_model(ctx, domid) < 0) - LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "libxl_destroy_device_model failed for %d", domid); + if (libxl__destroy_device_model(ctx, domid) < 0) + LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "libxl__destroy_device_model failed for %d", domid); } if (libxl__devices_destroy(ctx, domid, force) < 0) LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "libxl_destroy_devices failed for %d", domid); @@ -864,695 +824,6 @@ skip_autopass: return 0; } -static char ** libxl_build_device_model_args_old(libxl__gc *gc, - libxl_device_model_info *info, - libxl_device_nic *vifs, - int num_vifs) -{ - int num = 0, i; - flexarray_t *dm_args; - dm_args = flexarray_make(16, 1); - - if (!dm_args) - return NULL; - - flexarray_set(dm_args, num++, "qemu-dm"); - flexarray_set(dm_args, num++, "-d"); - - flexarray_set(dm_args, num++, libxl__sprintf(gc, "%d", info->domid)); - - if (info->dom_name) { - flexarray_set(dm_args, num++, "-domain-name"); - flexarray_set(dm_args, num++, info->dom_name); - } - if (info->vnc || info->vncdisplay || info->vnclisten || info->vncunused) { - flexarray_set(dm_args, num++, "-vnc"); - if (info->vncdisplay) { - if (info->vnclisten && strchr(info->vnclisten, ':') == NULL) { - flexarray_set( - dm_args, num++, - libxl__sprintf(gc, "%s:%d%s", - info->vnclisten, - info->vncdisplay, - info->vncpasswd ? ",password" : "")); - } else { - flexarray_set(dm_args, num++, libxl__sprintf(gc, "127.0.0.1:%d", info->vncdisplay)); - } - } else if (info->vnclisten) { - if (strchr(info->vnclisten, ':') != NULL) { - flexarray_set(dm_args, num++, info->vnclisten); - } else { - flexarray_set(dm_args, num++, libxl__sprintf(gc, "%s:0", info->vnclisten)); - } - } else { - flexarray_set(dm_args, num++, "127.0.0.1:0"); - } - if (info->vncunused) { - flexarray_set(dm_args, num++, "-vncunused"); - } - } - if (info->sdl) { - flexarray_set(dm_args, num++, "-sdl"); - if (!info->opengl) { - flexarray_set(dm_args, num++, "-disable-opengl"); - } - } - if (info->keymap) { - flexarray_set(dm_args, num++, "-k"); - flexarray_set(dm_args, num++, info->keymap); - } - if (info->nographic && (!info->sdl && !info->vnc)) { - flexarray_set(dm_args, num++, "-nographic"); - } - if (info->serial) { - flexarray_set(dm_args, num++, "-serial"); - flexarray_set(dm_args, num++, info->serial); - } - if (info->type == XENFV) { - int ioemu_vifs = 0; - - if (info->videoram) { - flexarray_set(dm_args, num++, "-videoram"); - flexarray_set(dm_args, num++, libxl__sprintf(gc, "%d", info->videoram)); - } - if (info->stdvga) { - flexarray_set(dm_args, num++, "-std-vga"); - } - - if (info->boot) { - flexarray_set(dm_args, num++, "-boot"); - flexarray_set(dm_args, num++, info->boot); - } - if (info->usb || info->usbdevice) { - flexarray_set(dm_args, num++, "-usb"); - if (info->usbdevice) { - flexarray_set(dm_args, num++, "-usbdevice"); - flexarray_set(dm_args, num++, info->usbdevice); - } - } - if (info->soundhw) { - flexarray_set(dm_args, num++, "-soundhw"); - flexarray_set(dm_args, num++, info->soundhw); - } - if (info->apic) { - flexarray_set(dm_args, num++, "-acpi"); - } - if (info->vcpus > 1) { - flexarray_set(dm_args, num++, "-vcpus"); - flexarray_set(dm_args, num++, libxl__sprintf(gc, "%d", info->vcpus)); - } - if (info->vcpu_avail) { - flexarray_set(dm_args, num++, "-vcpu_avail"); - flexarray_set(dm_args, num++, libxl__sprintf(gc, "0x%x", info->vcpu_avail)); - } - for (i = 0; i < num_vifs; i++) { - if (vifs[i].nictype == NICTYPE_IOEMU) { - char *smac = libxl__sprintf(gc, "%02x:%02x:%02x:%02x:%02x:%02x", - vifs[i].mac[0], vifs[i].mac[1], vifs[i].mac[2], - vifs[i].mac[3], vifs[i].mac[4], vifs[i].mac[5]); - char *ifname; - if (!vifs[i].ifname) - ifname = libxl__sprintf(gc, "tap%d.%d", info->domid, vifs[i].devid); - else - ifname = vifs[i].ifname; - flexarray_set(dm_args, num++, "-net"); - flexarray_set(dm_args, num++, libxl__sprintf(gc, "nic,vlan=%d,macaddr=%s,model=%s", - vifs[i].devid, smac, vifs[i].model)); - flexarray_set(dm_args, num++, "-net"); - flexarray_set(dm_args, num++, libxl__sprintf(gc, "tap,vlan=%d,ifname=%s,bridge=%s,script=no", - vifs[i].devid, ifname, vifs[i].bridge)); - ioemu_vifs++; - } - } - /* If we have no emulated nics, tell qemu not to create any */ - if ( ioemu_vifs == 0 ) { - flexarray_set(dm_args, num++, "-net"); - flexarray_set(dm_args, num++, "none"); - } - } - if (info->saved_state) { - flexarray_set(dm_args, num++, "-loadvm"); - flexarray_set(dm_args, num++, info->saved_state); - } - for (i = 0; info->extra && info->extra[i] != NULL; i++) - flexarray_set(dm_args, num++, info->extra[i]); - flexarray_set(dm_args, num++, "-M"); - if (info->type == XENPV) - flexarray_set(dm_args, num++, "xenpv"); - else - flexarray_set(dm_args, num++, "xenfv"); - flexarray_set(dm_args, num++, NULL); - return (char **) flexarray_contents(dm_args); -} - -static char ** libxl_build_device_model_args_new(libxl__gc *gc, - libxl_device_model_info *info, - libxl_device_nic *vifs, - int num_vifs) -{ - int num = 0, i; - flexarray_t *dm_args; - int nb; - libxl_device_disk *disks; - - dm_args = flexarray_make(16, 1); - if (!dm_args) - return NULL; - - flexarray_set(dm_args, num++, libxl__strdup(gc, info->device_model)); - - flexarray_set(dm_args, num++, "-xen-domid"); - flexarray_set(dm_args, num++, libxl__sprintf(gc, "%d", info->domid)); - - if (info->type == XENPV) { - flexarray_set(dm_args, num++, "-xen-attach"); - } - - if (info->dom_name) { - flexarray_set(dm_args, num++, "-name"); - flexarray_set(dm_args, num++, info->dom_name); - } - if (info->vnc || info->vncdisplay || info->vnclisten || info->vncunused) { - int display = 0; - const char *listen = "127.0.0.1"; - - flexarray_set(dm_args, num++, "-vnc"); - - if (info->vncdisplay) { - display = info->vncdisplay; - if (info->vnclisten && strchr(info->vnclisten, ':') == NULL) { - listen = info->vnclisten; - } - } else if (info->vnclisten) { - listen = info->vnclisten; - } - - if (strchr(listen, ':') != NULL) - flexarray_set(dm_args, num++, - libxl__sprintf(gc, "%s%s", listen, - info->vncunused ? ",to=99" : "")); - else - flexarray_set(dm_args, num++, - libxl__sprintf(gc, "%s:%d%s", listen, display, - info->vncunused ? ",to=99" : "")); - } - if (info->sdl) { - flexarray_set(dm_args, num++, "-sdl"); - } - - if (info->type == XENPV && !info->nographic) { - flexarray_set(dm_args, num++, "-vga"); - flexarray_set(dm_args, num++, "xenfb"); - } - - if (info->keymap) { - flexarray_set(dm_args, num++, "-k"); - flexarray_set(dm_args, num++, info->keymap); - } - if (info->nographic && (!info->sdl && !info->vnc)) { - flexarray_set(dm_args, num++, "-nographic"); - } - if (info->serial) { - flexarray_set(dm_args, num++, "-serial"); - flexarray_set(dm_args, num++, info->serial); - } - if (info->type == XENFV) { - int ioemu_vifs = 0; - - if (info->stdvga) { - flexarray_set(dm_args, num++, "-vga"); - flexarray_set(dm_args, num++, "std"); - } - - if (info->boot) { - flexarray_set(dm_args, num++, "-boot"); - flexarray_set(dm_args, num++, libxl__sprintf(gc, "order=%s", info->boot)); - } - if (info->usb || info->usbdevice) { - flexarray_set(dm_args, num++, "-usb"); - if (info->usbdevice) { - flexarray_set(dm_args, num++, "-usbdevice"); - flexarray_set(dm_args, num++, info->usbdevice); - } - } - if (info->soundhw) { - flexarray_set(dm_args, num++, "-soundhw"); - flexarray_set(dm_args, num++, info->soundhw); - } - if (!info->apic) { - flexarray_set(dm_args, num++, "-no-acpi"); - } - if (info->vcpus > 1) { - flexarray_set(dm_args, num++, "-smp"); - if (info->vcpu_avail) - flexarray_set(dm_args, num++, libxl__sprintf(gc, "%d,maxcpus=%d", info->vcpus, info->vcpu_avail)); - else - flexarray_set(dm_args, num++, libxl__sprintf(gc, "%d", info->vcpus)); - } - for (i = 0; i < num_vifs; i++) { - if (vifs[i].nictype == NICTYPE_IOEMU) { - char *smac = libxl__sprintf(gc, "%02x:%02x:%02x:%02x:%02x:%02x", - vifs[i].mac[0], vifs[i].mac[1], vifs[i].mac[2], - vifs[i].mac[3], vifs[i].mac[4], vifs[i].mac[5]); - char *ifname; - if (!vifs[i].ifname) { - ifname = libxl__sprintf(gc, "tap%d.%d", info->domid, vifs[i].devid); - } else { - ifname = vifs[i].ifname; - } - flexarray_set(dm_args, num++, "-net"); - flexarray_set(dm_args, num++, libxl__sprintf(gc, "nic,vlan=%d,macaddr=%s,model=%s", - vifs[i].devid, smac, vifs[i].model)); - flexarray_set(dm_args, num++, "-net"); - flexarray_set(dm_args, num++, libxl__sprintf(gc, "tap,vlan=%d,ifname=%s,script=no", - vifs[i].devid, ifname)); - ioemu_vifs++; - } - } - /* If we have no emulated nics, tell qemu not to create any */ - if ( ioemu_vifs == 0 ) { - flexarray_set(dm_args, num++, "-net"); - flexarray_set(dm_args, num++, "none"); - } - } - if (info->saved_state) { - flexarray_set(dm_args, num++, "-loadvm"); - flexarray_set(dm_args, num++, info->saved_state); - } - for (i = 0; info->extra && info->extra[i] != NULL; i++) - flexarray_set(dm_args, num++, info->extra[i]); - flexarray_set(dm_args, num++, "-M"); - if (info->type == XENPV) - flexarray_set(dm_args, num++, "xenpv"); - else - flexarray_set(dm_args, num++, "xenfv"); - - if (info->type == XENFV) { - disks = libxl_device_disk_list(libxl__gc_owner(gc), info->domid, &nb); - for (i; i < nb; i++) { - if (disks[i].is_cdrom) { - flexarray_set(dm_args, num++, "-cdrom"); - flexarray_set(dm_args, num++, libxl__strdup(gc, disks[i].physpath)); - } else { - flexarray_set(dm_args, num++, libxl__sprintf(gc, "-%s", disks[i].virtpath)); - flexarray_set(dm_args, num++, libxl__strdup(gc, disks[i].physpath)); - } - libxl_device_disk_destroy(&disks[i]); - } - } - free(disks); - flexarray_set(dm_args, num++, NULL); - return (char **) flexarray_contents(dm_args); -} - -static char ** libxl_build_device_model_args(libxl__gc *gc, - libxl_device_model_info *info, - libxl_device_nic *vifs, - int num_vifs) -{ - libxl_ctx *ctx = libxl__gc_owner(gc); - int new_qemu; - - new_qemu = libxl_check_device_model_version(ctx, info->device_model); - - if (new_qemu == 1) { - return libxl_build_device_model_args_new(gc, info, vifs, num_vifs); - } else { - return libxl_build_device_model_args_old(gc, info, vifs, num_vifs); - } -} - -static void dm_xenstore_record_pid(void *for_spawn, pid_t innerchild) -{ - libxl__device_model_starting *starting = for_spawn; - struct xs_handle *xsh; - char *path = NULL, *pid = NULL; - int len; - - if (asprintf(&path, "%s/%s", starting->dom_path, "image/device-model-pid") < 0) - goto out; - - len = asprintf(&pid, "%d", innerchild); - if (len < 0) - goto out; - - /* we mustn't use the parent's handle in the child */ - xsh = xs_daemon_open(); - - xs_write(xsh, XBT_NULL, path, pid, len); - - xs_daemon_close(xsh); -out: - free(path); - free(pid); -} - -static int libxl_vfb_and_vkb_from_device_model_info(libxl_ctx *ctx, - libxl_device_model_info *info, - libxl_device_vfb *vfb, - libxl_device_vkb *vkb) -{ - memset(vfb, 0x00, sizeof(libxl_device_vfb)); - memset(vkb, 0x00, sizeof(libxl_device_vkb)); - - vfb->backend_domid = 0; - vfb->devid = 0; - vfb->vnc = info->vnc; - vfb->vnclisten = info->vnclisten; - vfb->vncdisplay = info->vncdisplay; - vfb->vncunused = info->vncunused; - vfb->vncpasswd = info->vncpasswd; - vfb->keymap = info->keymap; - vfb->sdl = info->sdl; - vfb->opengl = info->opengl; - - vkb->backend_domid = 0; - vkb->devid = 0; - return 0; -} - -static int libxl_write_dmargs(libxl_ctx *ctx, int domid, int guest_domid, char **args) -{ - libxl__gc gc = LIBXL_INIT_GC(ctx); - int i; - char *vm_path; - char *dmargs, *path; - int dmargs_size; - struct xs_permissions roperm[2]; - xs_transaction_t t; - - roperm[0].id = 0; - roperm[0].perms = XS_PERM_NONE; - roperm[1].id = domid; - roperm[1].perms = XS_PERM_READ; - - vm_path = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "/local/domain/%d/vm", guest_domid)); - - i = 0; - dmargs_size = 0; - while (args[i] != NULL) { - dmargs_size = dmargs_size + strlen(args[i]) + 1; - i++; - } - dmargs_size++; - dmargs = (char *) malloc(dmargs_size); - i = 1; - dmargs[0] = '\0'; - while (args[i] != NULL) { - if (strcmp(args[i], "-sdl") && strcmp(args[i], "-M") && strcmp(args[i], "xenfv")) { - strcat(dmargs, " "); - strcat(dmargs, args[i]); - } - i++; - } - path = libxl__sprintf(&gc, "%s/image/dmargs", vm_path); - -retry_transaction: - t = xs_transaction_start(ctx->xsh); - xs_write(ctx->xsh, t, path, dmargs, strlen(dmargs)); - xs_set_permissions(ctx->xsh, t, path, roperm, ARRAY_SIZE(roperm)); - xs_set_permissions(ctx->xsh, t, libxl__sprintf(&gc, "%s/rtc/timeoffset", vm_path), roperm, ARRAY_SIZE(roperm)); - if (!xs_transaction_end(ctx->xsh, t, 0)) - if (errno == EAGAIN) - goto retry_transaction; - free(dmargs); - libxl__free_all(&gc); - return 0; -} - -static int libxl_create_stubdom(libxl_ctx *ctx, - libxl_device_model_info *info, - libxl_device_disk *disks, int num_disks, - libxl_device_nic *vifs, int num_vifs, - libxl_device_vfb *vfb, - libxl_device_vkb *vkb, - libxl__device_model_starting **starting_r) -{ - libxl__gc gc = LIBXL_INIT_GC(ctx); - int i, num_console = 1, ret; - libxl_device_console *console; - libxl_domain_create_info c_info; - libxl_domain_build_info b_info; - libxl_domain_build_state state; - uint32_t domid; - char **args; - struct xs_permissions perm[2]; - xs_transaction_t t; - libxl__device_model_starting *dm_starting = 0; - - args = libxl_build_device_model_args(&gc, info, vifs, num_vifs); - if (!args) { - ret = ERROR_FAIL; - goto out; - } - - memset(&c_info, 0x00, sizeof(libxl_domain_create_info)); - c_info.hvm = 0; - c_info.name = libxl__sprintf(&gc, "%s-dm", libxl__domid_to_name(&gc, info->domid)); - - libxl_uuid_copy(&c_info.uuid, &info->uuid); - - memset(&b_info, 0x00, sizeof(libxl_domain_build_info)); - b_info.max_vcpus = 1; - b_info.max_memkb = 32 * 1024; - b_info.target_memkb = b_info.max_memkb; - b_info.kernel.path = libxl__abs_path(&gc, "ioemu-stubdom.gz", libxl_xenfirmwaredir_path()); - b_info.pv.cmdline = libxl__sprintf(&gc, " -d %d", info->domid); - b_info.pv.ramdisk.path = ""; - b_info.pv.features = ""; - b_info.is_hvm = 0; - - ret = libxl__domain_make(ctx, &c_info, &domid); - if (ret) - goto out_free; - ret = libxl__domain_build(ctx, &b_info, domid, &state); - if (ret) - goto out_free; - - libxl_write_dmargs(ctx, domid, info->domid, args); - libxl__xs_write(&gc, XBT_NULL, - libxl__sprintf(&gc, "%s/image/device-model-domid", libxl__xs_get_dompath(&gc, info->domid)), - "%d", domid); - libxl__xs_write(&gc, XBT_NULL, - libxl__sprintf(&gc, "%s/target", libxl__xs_get_dompath(&gc, domid)), - "%d", info->domid); - ret = xc_domain_set_target(ctx->xch, domid, info->domid); - if (ret<0) { - LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "setting target domain %d -> %d", domid, info->domid); - ret = ERROR_FAIL; - goto out_free; - } - xs_set_target(ctx->xsh, domid, info->domid); - - perm[0].id = domid; - perm[0].perms = XS_PERM_NONE; - perm[1].id = info->domid; - perm[1].perms = XS_PERM_READ; -retry_transaction: - t = xs_transaction_start(ctx->xsh); - xs_mkdir(ctx->xsh, t, libxl__sprintf(&gc, "/local/domain/0/device-model/%d", info->domid)); - xs_set_permissions(ctx->xsh, t, libxl__sprintf(&gc, "/local/domain/0/device-model/%d", info->domid), perm, ARRAY_SIZE(perm)); - xs_mkdir(ctx->xsh, t, libxl__sprintf(&gc, "/local/domain/%d/device/vfs", domid)); - xs_set_permissions(ctx->xsh, t, libxl__sprintf(&gc, "/local/domain/%d/device/vfs",domid), perm, ARRAY_SIZE(perm)); - if (!xs_transaction_end(ctx->xsh, t, 0)) - if (errno == EAGAIN) - goto retry_transaction; - - for (i = 0; i < num_disks; i++) { - disks[i].domid = domid; - ret = libxl_device_disk_add(ctx, domid, &disks[i]); - if (ret) - goto out_free; - } - for (i = 0; i < num_vifs; i++) { - vifs[i].domid = domid; - ret = libxl_device_nic_add(ctx, domid, &vifs[i]); - if (ret) - goto out_free; - } - vfb->domid = domid; - ret = libxl_device_vfb_add(ctx, domid, vfb); - if (ret) - goto out_free; - vkb->domid = domid; - ret = libxl_device_vkb_add(ctx, domid, vkb); - if (ret) - goto out_free; - - if (info->serial) - num_console++; - - console = libxl__calloc(&gc, num_console, sizeof(libxl_device_console)); - if (!console) { - ret = ERROR_NOMEM; - goto out_free; - } - - for (i = 0; i < num_console; i++) { - console[i].devid = i; - console[i].consback = LIBXL_CONSBACK_IOEMU; - console[i].domid = domid; - if (!i) { - char *filename; - char *name = libxl__sprintf(&gc, "qemu-dm-%s", libxl_domid_to_name(ctx, info->domid)); - libxl_create_logfile(ctx, name, &filename); - console[i].output = libxl__sprintf(&gc, "file:%s", filename); - console[i].build_state = &state; - free(filename); - } else - console[i].output = "pty"; - ret = libxl_device_console_add(ctx, domid, &console[i]); - if (ret) - goto out_free; - } - if (libxl__create_xenpv_qemu(ctx, domid, vfb, &dm_starting) < 0) { - ret = ERROR_FAIL; - goto out_free; - } - if (libxl__confirm_device_model_startup(ctx, dm_starting) < 0) { - ret = ERROR_FAIL; - goto out_free; - } - - libxl_domain_unpause(ctx, domid); - - if (starting_r) { - *starting_r = calloc(sizeof(libxl__device_model_starting), 1); - (*starting_r)->domid = info->domid; - (*starting_r)->dom_path = libxl__xs_get_dompath(&gc, info->domid); - (*starting_r)->for_spawn = NULL; - } - - ret = 0; - -out_free: - free(args); -out: - libxl__free_all(&gc); - return ret; -} - -int libxl__create_device_model(libxl_ctx *ctx, - libxl_device_model_info *info, - libxl_device_disk *disks, int num_disks, - libxl_device_nic *vifs, int num_vifs, - libxl__device_model_starting **starting_r) -{ - libxl__gc gc = LIBXL_INIT_GC(ctx); - char *path, *logfile; - int logfile_w, null; - int rc; - char **args; - libxl__device_model_starting buf_starting, *p; - xs_transaction_t t; - char *vm_path; - char **pass_stuff; - - if (strstr(info->device_model, "stubdom-dm")) { - libxl_device_vfb vfb; - libxl_device_vkb vkb; - - libxl_vfb_and_vkb_from_device_model_info(ctx, info, &vfb, &vkb); - rc = libxl_create_stubdom(ctx, info, disks, num_disks, vifs, num_vifs, &vfb, &vkb, starting_r); - goto out; - } - - args = libxl_build_device_model_args(&gc, info, vifs, num_vifs); - if (!args) { - rc = ERROR_FAIL; - goto out; - } - - path = libxl__sprintf(&gc, "/local/domain/0/device-model/%d", info->domid); - xs_mkdir(ctx->xsh, XBT_NULL, path); - libxl__xs_write(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/disable_pf", path), "%d", !info->xen_platform_pci); - - libxl_create_logfile(ctx, libxl__sprintf(&gc, "qemu-dm-%s", info->dom_name), &logfile); - logfile_w = open(logfile, O_WRONLY|O_CREAT, 0644); - free(logfile); - null = open("/dev/null", O_RDONLY); - - if (starting_r) { - rc = ERROR_NOMEM; - *starting_r = calloc(sizeof(libxl__device_model_starting), 1); - if (!*starting_r) - goto out_close; - p = *starting_r; - p->for_spawn = calloc(sizeof(libxl__spawn_starting), 1); - } else { - p = &buf_starting; - p->for_spawn = NULL; - } - - p->domid = info->domid; - p->dom_path = libxl__xs_get_dompath(&gc, info->domid); - if (!p->dom_path) { - rc = ERROR_FAIL; - goto out_close; - } - - if (info->vncpasswd) { -retry_transaction: - /* Find uuid and the write the vnc password to xenstore for qemu. */ - t = xs_transaction_start(ctx->xsh); - vm_path = libxl__xs_read(&gc,t,libxl__sprintf(&gc, "%s/vm", p->dom_path)); - if (vm_path) { - /* Now write the vncpassword into it. */ - pass_stuff = libxl__calloc(&gc, 3, sizeof(char *)); - pass_stuff[0] = "vncpasswd"; - pass_stuff[1] = info->vncpasswd; - libxl__xs_writev(&gc,t,vm_path,pass_stuff); - if (!xs_transaction_end(ctx->xsh, t, 0)) - if (errno == EAGAIN) - goto retry_transaction; - } - } - - rc = libxl__spawn_spawn(ctx, p, "device model", dm_xenstore_record_pid); - if (rc < 0) - goto out_close; - if (!rc) { /* inner child */ - libxl__exec(null, logfile_w, logfile_w, - libxl__abs_path(&gc, info->device_model, libxl_libexec_path()), - args); - } - - rc = 0; - -out_close: - close(null); - close(logfile_w); - free(args); -out: - libxl__free_all(&gc); - return rc; -} - -/* DM is detached even if error is returned */ -static int detach_device_model(libxl_ctx *ctx, - libxl__device_model_starting *starting) -{ - int rc; - rc = libxl__spawn_detach(ctx, starting->for_spawn); - if (starting->for_spawn) - free(starting->for_spawn); - free(starting); - return rc; -} - - -int libxl__confirm_device_model_startup(libxl_ctx *ctx, - libxl__device_model_starting *starting) -{ - int problem = libxl__wait_for_device_model(ctx, starting->domid, "running", NULL, NULL); - int detach; - if ( !problem ) - problem = libxl__spawn_check(ctx, starting->for_spawn); - detach = detach_device_model(ctx, starting); - return problem ? problem : detach; -} - - /******************************************************************************/ int libxl_device_disk_add(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk) @@ -2383,47 +1654,6 @@ out: } /******************************************************************************/ -static int libxl_build_xenpv_qemu_args(libxl__gc *gc, - uint32_t domid, - libxl_device_vfb *vfb, - libxl_device_model_info *info) -{ - libxl_ctx *ctx = libxl__gc_owner(gc); - memset(info, 0x00, sizeof(libxl_device_model_info)); - - if (vfb != NULL) { - info->vnc = vfb->vnc; - if (vfb->vnclisten) - info->vnclisten = libxl__strdup(gc, vfb->vnclisten); - info->vncdisplay = vfb->vncdisplay; - info->vncunused = vfb->vncunused; - if (vfb->vncpasswd) - info->vncpasswd = vfb->vncpasswd; - if (vfb->keymap) - info->keymap = libxl__strdup(gc, vfb->keymap); - info->sdl = vfb->sdl; - info->opengl = vfb->opengl; - } else - info->nographic = 1; - info->domid = domid; - info->dom_name = libxl_domid_to_name(ctx, domid); - info->device_model = libxl__abs_path(gc, "qemu-dm", libxl_libexec_path()); - info->type = XENPV; - return 0; -} - -int libxl__create_xenpv_qemu(libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb, - libxl__device_model_starting **starting_r) -{ - libxl__gc gc = LIBXL_INIT_GC(ctx); - libxl_device_model_info info; - - libxl_build_xenpv_qemu_args(&gc, domid, vfb, &info); - libxl__create_device_model(ctx, &info, NULL, 0, NULL, 0, starting_r); - libxl__free_all(&gc); - return 0; -} - int libxl_device_vfb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb) { libxl__gc gc = LIBXL_INIT_GC(ctx); diff -r 1ff6243eba26 tools/libxl/libxl_dm.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/libxl/libxl_dm.c Tue Jan 04 17:44:26 2011 +0000 @@ -0,0 +1,798 @@ +/* + * Copyright (C) 2010 Citrix Ltd. + * Author Vincent Hanquez <vincent.hanquez@xxxxxxxxxxxxx> + * Author Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx> + * Author Gianni Tedesco <gianni.tedesco@xxxxxxxxxx> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; version 2.1 only. with the special + * exception on linking described in file LICENSE. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +#include "libxl_osdeps.h" + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include "libxl.h" +#include "libxl_utils.h" +#include "libxl_internal.h" +#include "flexarray.h" + +static char ** libxl_build_device_model_args_old(libxl__gc *gc, + libxl_device_model_info *info, + libxl_device_nic *vifs, + int num_vifs) +{ + int num = 0, i; + flexarray_t *dm_args; + dm_args = flexarray_make(16, 1); + + if (!dm_args) + return NULL; + + flexarray_set(dm_args, num++, "qemu-dm"); + flexarray_set(dm_args, num++, "-d"); + + flexarray_set(dm_args, num++, libxl__sprintf(gc, "%d", info->domid)); + + if (info->dom_name) { + flexarray_set(dm_args, num++, "-domain-name"); + flexarray_set(dm_args, num++, info->dom_name); + } + if (info->vnc || info->vncdisplay || info->vnclisten || info->vncunused) { + flexarray_set(dm_args, num++, "-vnc"); + if (info->vncdisplay) { + if (info->vnclisten && strchr(info->vnclisten, ':') == NULL) { + flexarray_set( + dm_args, num++, + libxl__sprintf(gc, "%s:%d%s", + info->vnclisten, + info->vncdisplay, + info->vncpasswd ? ",password" : "")); + } else { + flexarray_set(dm_args, num++, libxl__sprintf(gc, "127.0.0.1:%d", info->vncdisplay)); + } + } else if (info->vnclisten) { + if (strchr(info->vnclisten, ':') != NULL) { + flexarray_set(dm_args, num++, info->vnclisten); + } else { + flexarray_set(dm_args, num++, libxl__sprintf(gc, "%s:0", info->vnclisten)); + } + } else { + flexarray_set(dm_args, num++, "127.0.0.1:0"); + } + if (info->vncunused) { + flexarray_set(dm_args, num++, "-vncunused"); + } + } + if (info->sdl) { + flexarray_set(dm_args, num++, "-sdl"); + if (!info->opengl) { + flexarray_set(dm_args, num++, "-disable-opengl"); + } + } + if (info->keymap) { + flexarray_set(dm_args, num++, "-k"); + flexarray_set(dm_args, num++, info->keymap); + } + if (info->nographic && (!info->sdl && !info->vnc)) { + flexarray_set(dm_args, num++, "-nographic"); + } + if (info->serial) { + flexarray_set(dm_args, num++, "-serial"); + flexarray_set(dm_args, num++, info->serial); + } + if (info->type == XENFV) { + int ioemu_vifs = 0; + + if (info->videoram) { + flexarray_set(dm_args, num++, "-videoram"); + flexarray_set(dm_args, num++, libxl__sprintf(gc, "%d", info->videoram)); + } + if (info->stdvga) { + flexarray_set(dm_args, num++, "-std-vga"); + } + + if (info->boot) { + flexarray_set(dm_args, num++, "-boot"); + flexarray_set(dm_args, num++, info->boot); + } + if (info->usb || info->usbdevice) { + flexarray_set(dm_args, num++, "-usb"); + if (info->usbdevice) { + flexarray_set(dm_args, num++, "-usbdevice"); + flexarray_set(dm_args, num++, info->usbdevice); + } + } + if (info->soundhw) { + flexarray_set(dm_args, num++, "-soundhw"); + flexarray_set(dm_args, num++, info->soundhw); + } + if (info->apic) { + flexarray_set(dm_args, num++, "-acpi"); + } + if (info->vcpus > 1) { + flexarray_set(dm_args, num++, "-vcpus"); + flexarray_set(dm_args, num++, libxl__sprintf(gc, "%d", info->vcpus)); + } + if (info->vcpu_avail) { + flexarray_set(dm_args, num++, "-vcpu_avail"); + flexarray_set(dm_args, num++, libxl__sprintf(gc, "0x%x", info->vcpu_avail)); + } + for (i = 0; i < num_vifs; i++) { + if (vifs[i].nictype == NICTYPE_IOEMU) { + char *smac = libxl__sprintf(gc, "%02x:%02x:%02x:%02x:%02x:%02x", + vifs[i].mac[0], vifs[i].mac[1], vifs[i].mac[2], + vifs[i].mac[3], vifs[i].mac[4], vifs[i].mac[5]); + char *ifname; + if (!vifs[i].ifname) + ifname = libxl__sprintf(gc, "tap%d.%d", info->domid, vifs[i].devid); + else + ifname = vifs[i].ifname; + flexarray_set(dm_args, num++, "-net"); + flexarray_set(dm_args, num++, libxl__sprintf(gc, "nic,vlan=%d,macaddr=%s,model=%s", + vifs[i].devid, smac, vifs[i].model)); + flexarray_set(dm_args, num++, "-net"); + flexarray_set(dm_args, num++, libxl__sprintf(gc, "tap,vlan=%d,ifname=%s,bridge=%s,script=no", + vifs[i].devid, ifname, vifs[i].bridge)); + ioemu_vifs++; + } + } + /* If we have no emulated nics, tell qemu not to create any */ + if ( ioemu_vifs == 0 ) { + flexarray_set(dm_args, num++, "-net"); + flexarray_set(dm_args, num++, "none"); + } + } + if (info->saved_state) { + flexarray_set(dm_args, num++, "-loadvm"); + flexarray_set(dm_args, num++, info->saved_state); + } + for (i = 0; info->extra && info->extra[i] != NULL; i++) + flexarray_set(dm_args, num++, info->extra[i]); + flexarray_set(dm_args, num++, "-M"); + if (info->type == XENPV) + flexarray_set(dm_args, num++, "xenpv"); + else + flexarray_set(dm_args, num++, "xenfv"); + flexarray_set(dm_args, num++, NULL); + return (char **) flexarray_contents(dm_args); +} + +static char ** libxl_build_device_model_args_new(libxl__gc *gc, + libxl_device_model_info *info, + libxl_device_nic *vifs, + int num_vifs) +{ + int num = 0, i; + flexarray_t *dm_args; + int nb; + libxl_device_disk *disks; + + dm_args = flexarray_make(16, 1); + if (!dm_args) + return NULL; + + flexarray_set(dm_args, num++, libxl__strdup(gc, info->device_model)); + + flexarray_set(dm_args, num++, "-xen-domid"); + flexarray_set(dm_args, num++, libxl__sprintf(gc, "%d", info->domid)); + + if (info->type == XENPV) { + flexarray_set(dm_args, num++, "-xen-attach"); + } + + if (info->dom_name) { + flexarray_set(dm_args, num++, "-name"); + flexarray_set(dm_args, num++, info->dom_name); + } + if (info->vnc || info->vncdisplay || info->vnclisten || info->vncunused) { + int display = 0; + const char *listen = "127.0.0.1"; + + flexarray_set(dm_args, num++, "-vnc"); + + if (info->vncdisplay) { + display = info->vncdisplay; + if (info->vnclisten && strchr(info->vnclisten, ':') == NULL) { + listen = info->vnclisten; + } + } else if (info->vnclisten) { + listen = info->vnclisten; + } + + if (strchr(listen, ':') != NULL) + flexarray_set(dm_args, num++, + libxl__sprintf(gc, "%s%s", listen, + info->vncunused ? ",to=99" : "")); + else + flexarray_set(dm_args, num++, + libxl__sprintf(gc, "%s:%d%s", listen, display, + info->vncunused ? ",to=99" : "")); + } + if (info->sdl) { + flexarray_set(dm_args, num++, "-sdl"); + } + + if (info->type == XENPV && !info->nographic) { + flexarray_set(dm_args, num++, "-vga"); + flexarray_set(dm_args, num++, "xenfb"); + } + + if (info->keymap) { + flexarray_set(dm_args, num++, "-k"); + flexarray_set(dm_args, num++, info->keymap); + } + if (info->nographic && (!info->sdl && !info->vnc)) { + flexarray_set(dm_args, num++, "-nographic"); + } + if (info->serial) { + flexarray_set(dm_args, num++, "-serial"); + flexarray_set(dm_args, num++, info->serial); + } + if (info->type == XENFV) { + int ioemu_vifs = 0; + + if (info->stdvga) { + flexarray_set(dm_args, num++, "-vga"); + flexarray_set(dm_args, num++, "std"); + } + + if (info->boot) { + flexarray_set(dm_args, num++, "-boot"); + flexarray_set(dm_args, num++, libxl__sprintf(gc, "order=%s", info->boot)); + } + if (info->usb || info->usbdevice) { + flexarray_set(dm_args, num++, "-usb"); + if (info->usbdevice) { + flexarray_set(dm_args, num++, "-usbdevice"); + flexarray_set(dm_args, num++, info->usbdevice); + } + } + if (info->soundhw) { + flexarray_set(dm_args, num++, "-soundhw"); + flexarray_set(dm_args, num++, info->soundhw); + } + if (!info->apic) { + flexarray_set(dm_args, num++, "-no-acpi"); + } + if (info->vcpus > 1) { + flexarray_set(dm_args, num++, "-smp"); + if (info->vcpu_avail) + flexarray_set(dm_args, num++, libxl__sprintf(gc, "%d,maxcpus=%d", info->vcpus, info->vcpu_avail)); + else + flexarray_set(dm_args, num++, libxl__sprintf(gc, "%d", info->vcpus)); + } + for (i = 0; i < num_vifs; i++) { + if (vifs[i].nictype == NICTYPE_IOEMU) { + char *smac = libxl__sprintf(gc, "%02x:%02x:%02x:%02x:%02x:%02x", + vifs[i].mac[0], vifs[i].mac[1], vifs[i].mac[2], + vifs[i].mac[3], vifs[i].mac[4], vifs[i].mac[5]); + char *ifname; + if (!vifs[i].ifname) { + ifname = libxl__sprintf(gc, "tap%d.%d", info->domid, vifs[i].devid); + } else { + ifname = vifs[i].ifname; + } + flexarray_set(dm_args, num++, "-net"); + flexarray_set(dm_args, num++, libxl__sprintf(gc, "nic,vlan=%d,macaddr=%s,model=%s", + vifs[i].devid, smac, vifs[i].model)); + flexarray_set(dm_args, num++, "-net"); + flexarray_set(dm_args, num++, libxl__sprintf(gc, "tap,vlan=%d,ifname=%s,script=no", + vifs[i].devid, ifname)); + ioemu_vifs++; + } + } + /* If we have no emulated nics, tell qemu not to create any */ + if ( ioemu_vifs == 0 ) { + flexarray_set(dm_args, num++, "-net"); + flexarray_set(dm_args, num++, "none"); + } + } + if (info->saved_state) { + flexarray_set(dm_args, num++, "-loadvm"); + flexarray_set(dm_args, num++, info->saved_state); + } + for (i = 0; info->extra && info->extra[i] != NULL; i++) + flexarray_set(dm_args, num++, info->extra[i]); + flexarray_set(dm_args, num++, "-M"); + if (info->type == XENPV) + flexarray_set(dm_args, num++, "xenpv"); + else + flexarray_set(dm_args, num++, "xenfv"); + + if (info->type == XENFV) { + disks = libxl_device_disk_list(libxl__gc_owner(gc), info->domid, &nb); + for (i; i < nb; i++) { + if (disks[i].is_cdrom) { + flexarray_set(dm_args, num++, "-cdrom"); + flexarray_set(dm_args, num++, libxl__strdup(gc, disks[i].physpath)); + } else { + flexarray_set(dm_args, num++, libxl__sprintf(gc, "-%s", disks[i].virtpath)); + flexarray_set(dm_args, num++, libxl__strdup(gc, disks[i].physpath)); + } + libxl_device_disk_destroy(&disks[i]); + } + } + free(disks); + flexarray_set(dm_args, num++, NULL); + return (char **) flexarray_contents(dm_args); +} + +static char ** libxl_build_device_model_args(libxl__gc *gc, + libxl_device_model_info *info, + libxl_device_nic *vifs, + int num_vifs) +{ + libxl_ctx *ctx = libxl__gc_owner(gc); + int new_qemu; + + new_qemu = libxl_check_device_model_version(ctx, info->device_model); + + if (new_qemu == 1) { + return libxl_build_device_model_args_new(gc, info, vifs, num_vifs); + } else { + return libxl_build_device_model_args_old(gc, info, vifs, num_vifs); + } +} + +static void dm_xenstore_record_pid(void *for_spawn, pid_t innerchild) +{ + libxl__device_model_starting *starting = for_spawn; + struct xs_handle *xsh; + char *path = NULL, *pid = NULL; + int len; + + if (asprintf(&path, "%s/%s", starting->dom_path, "image/device-model-pid") < 0) + goto out; + + len = asprintf(&pid, "%d", innerchild); + if (len < 0) + goto out; + + /* we mustn't use the parent's handle in the child */ + xsh = xs_daemon_open(); + + xs_write(xsh, XBT_NULL, path, pid, len); + + xs_daemon_close(xsh); +out: + free(path); + free(pid); +} + +static int libxl_vfb_and_vkb_from_device_model_info(libxl_ctx *ctx, + libxl_device_model_info *info, + libxl_device_vfb *vfb, + libxl_device_vkb *vkb) +{ + memset(vfb, 0x00, sizeof(libxl_device_vfb)); + memset(vkb, 0x00, sizeof(libxl_device_vkb)); + + vfb->backend_domid = 0; + vfb->devid = 0; + vfb->vnc = info->vnc; + vfb->vnclisten = info->vnclisten; + vfb->vncdisplay = info->vncdisplay; + vfb->vncunused = info->vncunused; + vfb->vncpasswd = info->vncpasswd; + vfb->keymap = info->keymap; + vfb->sdl = info->sdl; + vfb->opengl = info->opengl; + + vkb->backend_domid = 0; + vkb->devid = 0; + return 0; +} + +static int libxl_write_dmargs(libxl_ctx *ctx, int domid, int guest_domid, char **args) +{ + libxl__gc gc = LIBXL_INIT_GC(ctx); + int i; + char *vm_path; + char *dmargs, *path; + int dmargs_size; + struct xs_permissions roperm[2]; + xs_transaction_t t; + + roperm[0].id = 0; + roperm[0].perms = XS_PERM_NONE; + roperm[1].id = domid; + roperm[1].perms = XS_PERM_READ; + + vm_path = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "/local/domain/%d/vm", guest_domid)); + + i = 0; + dmargs_size = 0; + while (args[i] != NULL) { + dmargs_size = dmargs_size + strlen(args[i]) + 1; + i++; + } + dmargs_size++; + dmargs = (char *) malloc(dmargs_size); + i = 1; + dmargs[0] = '\0'; + while (args[i] != NULL) { + if (strcmp(args[i], "-sdl") && strcmp(args[i], "-M") && strcmp(args[i], "xenfv")) { + strcat(dmargs, " "); + strcat(dmargs, args[i]); + } + i++; + } + path = libxl__sprintf(&gc, "%s/image/dmargs", vm_path); + +retry_transaction: + t = xs_transaction_start(ctx->xsh); + xs_write(ctx->xsh, t, path, dmargs, strlen(dmargs)); + xs_set_permissions(ctx->xsh, t, path, roperm, ARRAY_SIZE(roperm)); + xs_set_permissions(ctx->xsh, t, libxl__sprintf(&gc, "%s/rtc/timeoffset", vm_path), roperm, ARRAY_SIZE(roperm)); + if (!xs_transaction_end(ctx->xsh, t, 0)) + if (errno == EAGAIN) + goto retry_transaction; + free(dmargs); + libxl__free_all(&gc); + return 0; +} + +static int libxl_create_stubdom(libxl_ctx *ctx, + libxl_device_model_info *info, + libxl_device_disk *disks, int num_disks, + libxl_device_nic *vifs, int num_vifs, + libxl_device_vfb *vfb, + libxl_device_vkb *vkb, + libxl__device_model_starting **starting_r) +{ + libxl__gc gc = LIBXL_INIT_GC(ctx); + int i, num_console = 1, ret; + libxl_device_console *console; + libxl_domain_create_info c_info; + libxl_domain_build_info b_info; + libxl_domain_build_state state; + uint32_t domid; + char **args; + struct xs_permissions perm[2]; + xs_transaction_t t; + libxl__device_model_starting *dm_starting = 0; + + args = libxl_build_device_model_args(&gc, info, vifs, num_vifs); + if (!args) { + ret = ERROR_FAIL; + goto out; + } + + memset(&c_info, 0x00, sizeof(libxl_domain_create_info)); + c_info.hvm = 0; + c_info.name = libxl__sprintf(&gc, "%s-dm", libxl__domid_to_name(&gc, info->domid)); + + libxl_uuid_copy(&c_info.uuid, &info->uuid); + + memset(&b_info, 0x00, sizeof(libxl_domain_build_info)); + b_info.max_vcpus = 1; + b_info.max_memkb = 32 * 1024; + b_info.target_memkb = b_info.max_memkb; + b_info.kernel.path = libxl__abs_path(&gc, "ioemu-stubdom.gz", libxl_xenfirmwaredir_path()); + b_info.pv.cmdline = libxl__sprintf(&gc, " -d %d", info->domid); + b_info.pv.ramdisk.path = ""; + b_info.pv.features = ""; + b_info.is_hvm = 0; + + ret = libxl__domain_make(ctx, &c_info, &domid); + if (ret) + goto out_free; + ret = libxl__domain_build(ctx, &b_info, domid, &state); + if (ret) + goto out_free; + + libxl_write_dmargs(ctx, domid, info->domid, args); + libxl__xs_write(&gc, XBT_NULL, + libxl__sprintf(&gc, "%s/image/device-model-domid", libxl__xs_get_dompath(&gc, info->domid)), + "%d", domid); + libxl__xs_write(&gc, XBT_NULL, + libxl__sprintf(&gc, "%s/target", libxl__xs_get_dompath(&gc, domid)), + "%d", info->domid); + ret = xc_domain_set_target(ctx->xch, domid, info->domid); + if (ret<0) { + LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "setting target domain %d -> %d", domid, info->domid); + ret = ERROR_FAIL; + goto out_free; + } + xs_set_target(ctx->xsh, domid, info->domid); + + perm[0].id = domid; + perm[0].perms = XS_PERM_NONE; + perm[1].id = info->domid; + perm[1].perms = XS_PERM_READ; +retry_transaction: + t = xs_transaction_start(ctx->xsh); + xs_mkdir(ctx->xsh, t, libxl__sprintf(&gc, "/local/domain/0/device-model/%d", info->domid)); + xs_set_permissions(ctx->xsh, t, libxl__sprintf(&gc, "/local/domain/0/device-model/%d", info->domid), perm, ARRAY_SIZE(perm)); + xs_mkdir(ctx->xsh, t, libxl__sprintf(&gc, "/local/domain/%d/device/vfs", domid)); + xs_set_permissions(ctx->xsh, t, libxl__sprintf(&gc, "/local/domain/%d/device/vfs",domid), perm, ARRAY_SIZE(perm)); + if (!xs_transaction_end(ctx->xsh, t, 0)) + if (errno == EAGAIN) + goto retry_transaction; + + for (i = 0; i < num_disks; i++) { + disks[i].domid = domid; + ret = libxl_device_disk_add(ctx, domid, &disks[i]); + if (ret) + goto out_free; + } + for (i = 0; i < num_vifs; i++) { + vifs[i].domid = domid; + ret = libxl_device_nic_add(ctx, domid, &vifs[i]); + if (ret) + goto out_free; + } + vfb->domid = domid; + ret = libxl_device_vfb_add(ctx, domid, vfb); + if (ret) + goto out_free; + vkb->domid = domid; + ret = libxl_device_vkb_add(ctx, domid, vkb); + if (ret) + goto out_free; + + if (info->serial) + num_console++; + + console = libxl__calloc(&gc, num_console, sizeof(libxl_device_console)); + if (!console) { + ret = ERROR_NOMEM; + goto out_free; + } + + for (i = 0; i < num_console; i++) { + console[i].devid = i; + console[i].consback = LIBXL_CONSBACK_IOEMU; + console[i].domid = domid; + if (!i) { + char *filename; + char *name = libxl__sprintf(&gc, "qemu-dm-%s", libxl_domid_to_name(ctx, info->domid)); + libxl_create_logfile(ctx, name, &filename); + console[i].output = libxl__sprintf(&gc, "file:%s", filename); + console[i].build_state = &state; + free(filename); + } else + console[i].output = "pty"; + ret = libxl_device_console_add(ctx, domid, &console[i]); + if (ret) + goto out_free; + } + if (libxl__create_xenpv_qemu(ctx, domid, vfb, &dm_starting) < 0) { + ret = ERROR_FAIL; + goto out_free; + } + if (libxl__confirm_device_model_startup(ctx, dm_starting) < 0) { + ret = ERROR_FAIL; + goto out_free; + } + + libxl_domain_unpause(ctx, domid); + + if (starting_r) { + *starting_r = calloc(sizeof(libxl__device_model_starting), 1); + (*starting_r)->domid = info->domid; + (*starting_r)->dom_path = libxl__xs_get_dompath(&gc, info->domid); + (*starting_r)->for_spawn = NULL; + } + + ret = 0; + +out_free: + free(args); +out: + libxl__free_all(&gc); + return ret; +} + +int libxl__create_device_model(libxl_ctx *ctx, + libxl_device_model_info *info, + libxl_device_disk *disks, int num_disks, + libxl_device_nic *vifs, int num_vifs, + libxl__device_model_starting **starting_r) +{ + libxl__gc gc = LIBXL_INIT_GC(ctx); + char *path, *logfile; + int logfile_w, null; + int rc; + char **args; + libxl__device_model_starting buf_starting, *p; + xs_transaction_t t; + char *vm_path; + char **pass_stuff; + + if (strstr(info->device_model, "stubdom-dm")) { + libxl_device_vfb vfb; + libxl_device_vkb vkb; + + libxl_vfb_and_vkb_from_device_model_info(ctx, info, &vfb, &vkb); + rc = libxl_create_stubdom(ctx, info, disks, num_disks, vifs, num_vifs, &vfb, &vkb, starting_r); + goto out; + } + + args = libxl_build_device_model_args(&gc, info, vifs, num_vifs); + if (!args) { + rc = ERROR_FAIL; + goto out; + } + + path = libxl__sprintf(&gc, "/local/domain/0/device-model/%d", info->domid); + xs_mkdir(ctx->xsh, XBT_NULL, path); + libxl__xs_write(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/disable_pf", path), "%d", !info->xen_platform_pci); + + libxl_create_logfile(ctx, libxl__sprintf(&gc, "qemu-dm-%s", info->dom_name), &logfile); + logfile_w = open(logfile, O_WRONLY|O_CREAT, 0644); + free(logfile); + null = open("/dev/null", O_RDONLY); + + if (starting_r) { + rc = ERROR_NOMEM; + *starting_r = calloc(sizeof(libxl__device_model_starting), 1); + if (!*starting_r) + goto out_close; + p = *starting_r; + p->for_spawn = calloc(sizeof(libxl__spawn_starting), 1); + } else { + p = &buf_starting; + p->for_spawn = NULL; + } + + p->domid = info->domid; + p->dom_path = libxl__xs_get_dompath(&gc, info->domid); + if (!p->dom_path) { + rc = ERROR_FAIL; + goto out_close; + } + + if (info->vncpasswd) { +retry_transaction: + /* Find uuid and the write the vnc password to xenstore for qemu. */ + t = xs_transaction_start(ctx->xsh); + vm_path = libxl__xs_read(&gc,t,libxl__sprintf(&gc, "%s/vm", p->dom_path)); + if (vm_path) { + /* Now write the vncpassword into it. */ + pass_stuff = libxl__calloc(&gc, 3, sizeof(char *)); + pass_stuff[0] = "vncpasswd"; + pass_stuff[1] = info->vncpasswd; + libxl__xs_writev(&gc,t,vm_path,pass_stuff); + if (!xs_transaction_end(ctx->xsh, t, 0)) + if (errno == EAGAIN) + goto retry_transaction; + } + } + + rc = libxl__spawn_spawn(ctx, p, "device model", dm_xenstore_record_pid); + if (rc < 0) + goto out_close; + if (!rc) { /* inner child */ + libxl__exec(null, logfile_w, logfile_w, + libxl__abs_path(&gc, info->device_model, libxl_libexec_path()), + args); + } + + rc = 0; + +out_close: + close(null); + close(logfile_w); + free(args); +out: + libxl__free_all(&gc); + return rc; +} + +/* DM is detached even if error is returned */ +static int detach_device_model(libxl_ctx *ctx, + libxl__device_model_starting *starting) +{ + int rc; + rc = libxl__spawn_detach(ctx, starting->for_spawn); + if (starting->for_spawn) + free(starting->for_spawn); + free(starting); + return rc; +} + + +int libxl__confirm_device_model_startup(libxl_ctx *ctx, + libxl__device_model_starting *starting) +{ + int problem = libxl__wait_for_device_model(ctx, starting->domid, "running", NULL, NULL); + int detach; + if ( !problem ) + problem = libxl__spawn_check(ctx, starting->for_spawn); + detach = detach_device_model(ctx, starting); + return problem ? problem : detach; +} + +static int libxl_build_xenpv_qemu_args(libxl__gc *gc, + uint32_t domid, + libxl_device_vfb *vfb, + libxl_device_model_info *info) +{ + libxl_ctx *ctx = libxl__gc_owner(gc); + memset(info, 0x00, sizeof(libxl_device_model_info)); + + if (vfb != NULL) { + info->vnc = vfb->vnc; + if (vfb->vnclisten) + info->vnclisten = libxl__strdup(gc, vfb->vnclisten); + info->vncdisplay = vfb->vncdisplay; + info->vncunused = vfb->vncunused; + if (vfb->vncpasswd) + info->vncpasswd = vfb->vncpasswd; + if (vfb->keymap) + info->keymap = libxl__strdup(gc, vfb->keymap); + info->sdl = vfb->sdl; + info->opengl = vfb->opengl; + } else + info->nographic = 1; + info->domid = domid; + info->dom_name = libxl_domid_to_name(ctx, domid); + info->device_model = libxl__abs_path(gc, "qemu-dm", libxl_libexec_path()); + info->type = XENPV; + return 0; +} + +int libxl__create_xenpv_qemu(libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb, + libxl__device_model_starting **starting_r) +{ + libxl__gc gc = LIBXL_INIT_GC(ctx); + libxl_device_model_info info; + + libxl_build_xenpv_qemu_args(&gc, domid, vfb, &info); + libxl__create_device_model(ctx, &info, NULL, 0, NULL, 0, starting_r); + libxl__free_all(&gc); + return 0; +} + +int libxl__destroy_device_model(libxl_ctx *ctx, uint32_t domid) +{ + libxl__gc gc = LIBXL_INIT_GC(ctx); + char *pid; + int ret; + + pid = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "/local/domain/%d/image/device-model-pid", domid)); + if (!pid) { + int stubdomid = libxl_get_stubdom_id(ctx, domid); + if (!stubdomid) { + LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "Couldn't find device model's pid"); + ret = ERROR_INVAL; + goto out; + } + LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Device model is a stubdom, domid=%d\n", stubdomid); + ret = libxl_domain_destroy(ctx, stubdomid, 0); + if (ret) + goto out; + } else { + ret = kill(atoi(pid), SIGHUP); + if (ret < 0 && errno == ESRCH) { + LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Device Model already exited"); + ret = 0; + } else if (ret == 0) { + LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Device Model signaled"); + ret = 0; + } else { + LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "failed to kill Device Model [%d]", + atoi(pid)); + ret = ERROR_FAIL; + goto out; + } + } + xs_rm(ctx->xsh, XBT_NULL, libxl__sprintf(&gc, "/local/domain/0/device-model/%d", domid)); + +out: + libxl__free_all(&gc); + return ret; +} + diff -r 1ff6243eba26 tools/libxl/libxl_internal.h --- a/tools/libxl/libxl_internal.h Tue Jan 04 16:27:45 2011 +0000 +++ b/tools/libxl/libxl_internal.h Tue Jan 04 17:44:26 2011 +0000 @@ -222,6 +222,8 @@ _hidden int libxl__spawn_spawn(libxl_ctx libxl__device_model_starting *starting, const char *what, void (*intermediate_hook)(void *for_spawn, pid_t innerchild)); +_hidden int libxl__destroy_device_model(libxl_ctx *ctx, uint32_t domid); + /* Logs errors. A copy of "what" is taken. Return values: * < 0 error, for_spawn need not be detached * +1 caller is the parent, must call detach on *for_spawn eventually _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |