int hyperxl_domain_start(libxl_ctx* ctx, hyperxl_domain_config* config) { int i, ret = -1; uint32_t domid = 0; libxl_domain_config d_config; libxl_domain_config_init(&d_config); //init create info libxl_domain_create_info* c_info = &d_config.c_info; libxl_domain_create_info_init(c_info); if (config->hvm) c_info->type = LIBXL_DOMAIN_TYPE_HVM; else c_info->type = LIBXL_DOMAIN_TYPE_PV; libxl_uuid_generate(&c_info->uuid); c_info->name = strdup(config->name); libxl_defbool_set(&c_info->run_hotplug_scripts, false); //init_build_info libxl_domain_build_info* b_info = &d_config.b_info; if (config->hvm) libxl_domain_build_info_init_type(b_info, LIBXL_DOMAIN_TYPE_HVM); else { // currently only hvm is supported. pv mode will be enabled // whenever we can insert several serial ports and filesystem // into pv domain. goto cleanup; } // currently, we do not change vcpu and memory only, will add this // feature later. b_info->max_vcpus = config->max_vcpus; if (libxl_cpu_bitmap_alloc(ctx, &b_info->avail_vcpus, config->max_vcpus)) goto cleanup; libxl_bitmap_set_none(&b_info->avail_vcpus); for (i = 0; i < config->max_vcpus; i++) libxl_bitmap_set((&b_info->avail_vcpus), i); b_info->sched_params.weight = 1000; b_info->max_memkb = config->max_memory_kb; b_info->target_memkb = config->max_memory_kb; b_info->video_memkb = 0; // currently, we only initialize hvm fields if (config->hvm) { libxl_defbool_set(&b_info->u.hvm.pae, true); libxl_defbool_set(&b_info->u.hvm.apic, false); libxl_defbool_set(&b_info->u.hvm.acpi, true); b_info->u.hvm.boot = strdup("c"); b_info->cmdline = strdup(config->cmdline); b_info->kernel = strdup(config->kernel); b_info->ramdisk = strdup(config->initrd); b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_NONE; libxl_defbool_set(&b_info->u.hvm.nographic, 1); libxl_defbool_set(&b_info->u.hvm.vnc.enable, 0); libxl_defbool_set(&b_info->u.hvm.sdl.enable, 0); b_info->u.hvm.serial = strdup(config->console_sock); libxl_string_list_copy(ctx, &b_info->extra, (libxl_string_list*)config->extra); /* * comments from libvirt and libxenlight: * * The following comment and calculation were taken directly from * libxenlight's internal function libxl_get_required_shadow_memory(): * * 256 pages (1MB) per vcpu, plus 1 page per MiB of RAM for the P2M map, * plus 1 page per MiB of RAM to shadow the resident processes. */ b_info->shadow_memkb = 4 * (256 * libxl_bitmap_count_set(&b_info->avail_vcpus) + 2 * (b_info->max_memkb / 1024)); } if (libxl_domain_create_new(ctx, &d_config, &domid, NULL, NULL)) { goto cleanup; } libxl_evgen_domain_death* e_death = NULL; if (libxl_evenable_domain_death(ctx, domid, 0, &e_death)) { goto cleanup; } libxl_domain_unpause(ctx, domid); config->domid = domid; config->ev = e_death; ret = 0; cleanup: libxl_domain_config_dispose(&d_config); return ret; }
void *testcase(struct test *tc) { int count; libxl_domain_config dc; uint32_t domid = -2; struct event ev; init_domain_config(&dc, "test_domain_suspend", "resources/vmlinuz-4.0.4-301.fc22.x86_64", "resources/initrd.xen-4.0.4-301.fc22.x86_64", "resources/Fedora-Cloud-Base-22-20150521.x86_64.qcow2", "resources/cloudinit.iso"); do_domain_create(tc, &dc, &domid); wait_for(tc, EV_LIBXL_CALLBACK, &ev); assert(ev.u.callback_event.rc == 0); assert(domid != (uint32_t) -2); printf("domid: %d\n", domid); libxl_domain_unpause(tc->ctx, domid); printf("domain %d unpaused\n", domid); printf("waiting for domain to boot\n"); wait_for_n(tc, EV_EVENTLOOP, 10, &ev); /* Most of the work of suspending a domain is done by helper processes. The helper processes generate hundreds of FD events, so the test tries to cancel after batches of 100 FD events, as well as after every non-FD event. */ for (count = 1; count < 100; count++) { int rc; FILE *suspend_file; int suspend_fd; printf("\n****** Will cancel after %d events ******\n", count); suspend_file = tmpfile(); if (!suspend_file) { perror("tmpfile"); break; } suspend_fd = fileno(suspend_file); do_domain_suspend(tc, domid, suspend_fd); if (wait_until_n(tc, EV_LIBXL_CALLBACK, count, &ev, 50)) { /* The API call returned before we could cancel it. It should have returned successfully. */ fclose(suspend_file); printf("libxl_domain_suspend returned %d\n", ev.u.callback_event.rc); assert(ev.u.callback_event.rc == 0); /* No operation in progress - cancelling should return an error */ rc = libxl_ao_cancel(tc->ctx, &tc->ao_how); printf("libxl_ao_cancel returned %d\n", rc); assert(rc == ERROR_NOTFOUND); break; } /* The wait_until_n() call did not receive a calback event, so we will try to cancel the asynchronous operation */ printf("Cancelling asynchronous operation\n"); rc = libxl_ao_cancel(tc->ctx, &tc->ao_how); /* Calling cancel on a cancellable operation should not return an error, unless the operation happened to complete in the meantime. */ printf("libxl_ao_cancel returned %d\n", rc); assert(rc == ERROR_NOTFOUND || rc == 0); /* The API call's return code should indicate that it was cancelled */ wait_for(tc, EV_LIBXL_CALLBACK, &ev); fclose(suspend_file); printf("libxl_domain_suspend returned %d\n", ev.u.callback_event.rc); assert(ev.u.callback_event.rc == ERROR_CANCELLED || ev.u.callback_event.rc == 0); /* Suspend was cancelled - the domain should still be running */ assert(!libxl_domain_info(tc->ctx, NULL, domid)); } libxl_domain_destroy(tc->ctx, domid, 0); libxl_domain_config_dispose(&dc); test_exit(); return NULL; }
/* * Set the maximum memory size of the domain in the hypervisor. There is no * change of the current memory size involved. The specified memory size can * even be above the configured maxmem size of the domain, but the related * Xenstore entry memory/static-max isn't modified! */ int libxl_domain_setmaxmem(libxl_ctx *ctx, uint32_t domid, uint64_t max_memkb) { GC_INIT(ctx); char *mem, *endptr; uint64_t memorykb, size; char *dompath = libxl__xs_get_dompath(gc, domid); int rc = 1; libxl__domain_userdata_lock *lock = NULL; libxl_domain_config d_config; libxl_domain_config_init(&d_config); CTX_LOCK; lock = libxl__lock_domain_userdata(gc, domid); if (!lock) { rc = ERROR_LOCK_FAIL; goto out; } mem = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/memory/target", dompath)); if (!mem) { LOGED(ERROR, domid, "Cannot get memory info from %s/memory/target", dompath); goto out; } memorykb = strtoull(mem, &endptr, 10); if (*endptr != '\0') { LOGED(ERROR, domid, "Invalid memory %s from %s/memory/target\n", mem, dompath); goto out; } if (max_memkb < memorykb) { LOGED(ERROR, domid, "memory_static_max must be greater than or or equal to memory_dynamic_max"); goto out; } rc = libxl__get_domain_configuration(gc, domid, &d_config); if (rc < 0) { LOGE(ERROR, "unable to retrieve domain configuration"); goto out; } rc = libxl__arch_extra_memory(gc, &d_config.b_info, &size); if (rc < 0) { LOGE(ERROR, "Couldn't get arch extra constant memory size"); goto out; } rc = xc_domain_setmaxmem(ctx->xch, domid, max_memkb + size); if (rc != 0) { LOGED(ERROR, domid, "xc_domain_setmaxmem domid=%d memkb=%"PRIu64" failed ""rc=%d\n", domid, max_memkb + size, rc); goto out; } rc = 0; out: libxl_domain_config_dispose(&d_config); if (lock) libxl__unlock_domain_userdata(lock); CTX_UNLOCK; GC_FREE; return rc; }
static void libxl__device_nic_add(libxl__egc *egc, uint32_t domid, libxl_device_nic *nic, libxl__ao_device *aodev) { STATE_AO_GC(aodev->ao); flexarray_t *front; flexarray_t *back; libxl__device *device; int rc; xs_transaction_t t = XBT_NULL; libxl_domain_config d_config; libxl_device_nic nic_saved; libxl__domain_userdata_lock *lock = NULL; libxl_domain_config_init(&d_config); libxl_device_nic_init(&nic_saved); libxl_device_nic_copy(CTX, &nic_saved, nic); rc = libxl__device_nic_setdefault(gc, nic, domid, aodev->update_json); if (rc) goto out; front = flexarray_make(gc, 16, 1); back = flexarray_make(gc, 18, 1); if (nic->devid == -1) { if ((nic->devid = libxl__device_nextid(gc, domid, "vif")) < 0) { rc = ERROR_FAIL; goto out; } } libxl__update_config_nic(gc, &nic_saved, nic); GCNEW(device); rc = libxl__device_from_nic(gc, domid, nic, device); if ( rc != 0 ) goto out; flexarray_append(back, "frontend-id"); flexarray_append(back, GCSPRINTF("%d", domid)); flexarray_append(back, "online"); flexarray_append(back, "1"); flexarray_append(back, "state"); flexarray_append(back, GCSPRINTF("%d", XenbusStateInitialising)); if (nic->script) flexarray_append_pair(back, "script", libxl__abs_path(gc, nic->script, libxl__xen_script_dir_path())); if (nic->ifname) { flexarray_append(back, "vifname"); flexarray_append(back, nic->ifname); } if (nic->coloft_forwarddev) { flexarray_append(back, "forwarddev"); flexarray_append(back, nic->coloft_forwarddev); } flexarray_append(back, "mac"); flexarray_append(back,GCSPRINTF(LIBXL_MAC_FMT, LIBXL_MAC_BYTES(nic->mac))); if (nic->ip) { flexarray_append(back, "ip"); flexarray_append(back, libxl__strdup(gc, nic->ip)); } if (nic->gatewaydev) { flexarray_append(back, "gatewaydev"); flexarray_append(back, libxl__strdup(gc, nic->gatewaydev)); } if (nic->rate_interval_usecs > 0) { flexarray_append(back, "rate"); flexarray_append(back, GCSPRINTF("%"PRIu64",%"PRIu32"", nic->rate_bytes_per_interval, nic->rate_interval_usecs)); } flexarray_append(back, "bridge"); flexarray_append(back, libxl__strdup(gc, nic->bridge)); flexarray_append(back, "handle"); flexarray_append(back, GCSPRINTF("%d", nic->devid)); flexarray_append(back, "type"); flexarray_append(back, libxl__strdup(gc, libxl_nic_type_to_string(nic->nictype))); flexarray_append(front, "backend-id"); flexarray_append(front, GCSPRINTF("%d", nic->backend_domid)); flexarray_append(front, "state"); flexarray_append(front, GCSPRINTF("%d", XenbusStateInitialising)); flexarray_append(front, "handle"); flexarray_append(front, GCSPRINTF("%d", nic->devid)); flexarray_append(front, "mac"); flexarray_append(front, GCSPRINTF( LIBXL_MAC_FMT, LIBXL_MAC_BYTES(nic->mac))); if (aodev->update_json) { lock = libxl__lock_domain_userdata(gc, domid); if (!lock) { rc = ERROR_LOCK_FAIL; goto out; } rc = libxl__get_domain_configuration(gc, domid, &d_config); if (rc) goto out; DEVICE_ADD(nic, nics, domid, &nic_saved, COMPARE_DEVID, &d_config); rc = libxl__dm_check_start(gc, &d_config, domid); if (rc) goto out; } for (;;) { rc = libxl__xs_transaction_start(gc, &t); if (rc) goto out; rc = libxl__device_exists(gc, t, device); if (rc < 0) goto out; if (rc == 1) { /* already exists in xenstore */ LOG(ERROR, "device already exists in xenstore"); aodev->action = LIBXL__DEVICE_ACTION_ADD; /* for error message */ rc = ERROR_DEVICE_EXISTS; goto out; } if (aodev->update_json) { rc = libxl__set_domain_configuration(gc, domid, &d_config); if (rc) goto out; } libxl__device_generic_add(gc, t, device, libxl__xs_kvs_of_flexarray(gc, back, back->count), libxl__xs_kvs_of_flexarray(gc, front, front->count), NULL); rc = libxl__xs_transaction_commit(gc, &t); if (!rc) break; if (rc < 0) goto out; } aodev->dev = device; aodev->action = LIBXL__DEVICE_ACTION_ADD; libxl__wait_device_connection(egc, aodev); rc = 0; out: libxl__xs_transaction_abort(gc, &t); if (lock) libxl__unlock_domain_userdata(lock); libxl_device_nic_dispose(&nic_saved); libxl_domain_config_dispose(&d_config); aodev->rc = rc; if (rc) aodev->callback(egc, aodev); return; }
int libxl_set_memory_target(libxl_ctx *ctx, uint32_t domid, int64_t target_memkb, int relative, int enforce) { GC_INIT(ctx); int rc, r, lrc, abort_transaction = 0; uint64_t memorykb, size; uint64_t videoram = 0; uint64_t current_target_memkb = 0, new_target_memkb = 0; uint64_t current_max_memkb = 0; char *memmax, *endptr, *videoram_s = NULL, *target = NULL; char *dompath = libxl__xs_get_dompath(gc, domid); xc_domaininfo_t info; libxl_dominfo ptr; char *uuid; xs_transaction_t t; libxl__domain_userdata_lock *lock; libxl_domain_config d_config; libxl_domain_config_init(&d_config); CTX_LOCK; lock = libxl__lock_domain_userdata(gc, domid); if (!lock) { rc = ERROR_LOCK_FAIL; goto out_no_transaction; } rc = libxl__get_domain_configuration(gc, domid, &d_config); if (rc < 0) { LOGE(ERROR, "unable to retrieve domain configuration"); goto out_no_transaction; } rc = libxl__arch_extra_memory(gc, &d_config.b_info, &size); if (rc < 0) { LOGE(ERROR, "Couldn't get arch extra constant memory size"); goto out_no_transaction; } retry_transaction: t = xs_transaction_start(ctx->xsh); target = libxl__xs_read(gc, t, GCSPRINTF("%s/memory/target", dompath)); if (!target && !domid) { if (!xs_transaction_end(ctx->xsh, t, 1)) { rc = ERROR_FAIL; goto out_no_transaction; } lrc = libxl__fill_dom0_memory_info(gc, ¤t_target_memkb, ¤t_max_memkb); if (lrc < 0) { rc = ERROR_FAIL; goto out_no_transaction; } goto retry_transaction; } else if (!target) { LOGED(ERROR, domid, "Cannot get target memory info from %s/memory/target", dompath); abort_transaction = 1; rc = ERROR_FAIL; goto out; } else { current_target_memkb = strtoull(target, &endptr, 10); if (*endptr != '\0') { LOGED(ERROR, domid, "Invalid memory target %s from %s/memory/target\n", target, dompath); abort_transaction = 1; rc = ERROR_FAIL; goto out; } } memmax = libxl__xs_read(gc, t, GCSPRINTF("%s/memory/static-max", dompath)); if (!memmax) { LOGED(ERROR, domid, "Cannot get memory info from %s/memory/static-max", dompath); abort_transaction = 1; rc = ERROR_FAIL; goto out; } memorykb = strtoull(memmax, &endptr, 10); if (*endptr != '\0') { LOGED(ERROR, domid, "Invalid max memory %s from %s/memory/static-max\n", memmax, dompath); abort_transaction = 1; rc = ERROR_FAIL; goto out; } videoram_s = libxl__xs_read(gc, t, GCSPRINTF("%s/memory/videoram", dompath)); videoram = videoram_s ? atoi(videoram_s) : 0; if (relative) { if (target_memkb < 0 && llabs(target_memkb) > current_target_memkb) new_target_memkb = 0; else new_target_memkb = current_target_memkb + target_memkb; } else new_target_memkb = target_memkb - videoram; if (new_target_memkb > memorykb) { LOGD(ERROR, domid, "memory_dynamic_max must be less than or equal to" " memory_static_max\n"); abort_transaction = 1; rc = ERROR_INVAL; goto out; } if (!domid && new_target_memkb < LIBXL_MIN_DOM0_MEM) { LOGD(ERROR, domid, "New target %"PRIu64" for dom0 is below the minimum threshold", new_target_memkb); abort_transaction = 1; rc = ERROR_INVAL; goto out; } if (enforce) { memorykb = new_target_memkb + videoram; r = xc_domain_setmaxmem(ctx->xch, domid, memorykb + size); if (r != 0) { LOGED(ERROR, domid, "xc_domain_setmaxmem memkb=%"PRIu64" failed ""rc=%d\n", memorykb + size, r); abort_transaction = 1; rc = ERROR_FAIL; goto out; } } r = xc_domain_set_pod_target(ctx->xch, domid, (new_target_memkb + size) / 4, NULL, NULL, NULL); if (r != 0) { LOGED(ERROR, domid, "xc_domain_set_pod_target memkb=%"PRIu64" failed rc=%d\n", (new_target_memkb + size) / 4, r); abort_transaction = 1; rc = ERROR_FAIL; goto out; } libxl__xs_printf(gc, t, GCSPRINTF("%s/memory/target", dompath), "%"PRIu64, new_target_memkb); r = xc_domain_getinfolist(ctx->xch, domid, 1, &info); if (r != 1 || info.domain != domid) { abort_transaction = 1; rc = ERROR_FAIL; goto out; } libxl_dominfo_init(&ptr); libxl__xcinfo2xlinfo(ctx, &info, &ptr); uuid = libxl__uuid2string(gc, ptr.uuid); libxl__xs_printf(gc, t, GCSPRINTF("/vm/%s/memory", uuid), "%"PRIu64, new_target_memkb / 1024); libxl_dominfo_dispose(&ptr); rc = 0; out: if (!xs_transaction_end(ctx->xsh, t, abort_transaction) && !abort_transaction) if (errno == EAGAIN) goto retry_transaction; out_no_transaction: libxl_domain_config_dispose(&d_config); if (lock) libxl__unlock_domain_userdata(lock); CTX_UNLOCK; GC_FREE; return rc; }