Пример #1
0
static void stubdom_pvqemu_cb(libxl__egc *egc,
                              libxl__multidev *multidev,
                              int rc)
{
    libxl__stub_dm_spawn_state *sdss = CONTAINER_OF(multidev, *sdss, multidev);
    STATE_AO_GC(sdss->dm.spawn.ao);
    uint32_t dm_domid = sdss->pvqemu.guest_domid;

    if (rc) {
        LOGE(ERROR, "error connecting nics devices");
        goto out;
    }

    rc = libxl_domain_unpause(CTX, dm_domid);
    if (rc) goto out;

 out:
    if (rc) {
        if (dm_domid) {
            sdss->dis.ao = ao;
            sdss->dis.domid = dm_domid;
            sdss->dis.callback = spaw_stubdom_pvqemu_destroy_cb;
            libxl__destroy_domid(egc, &sdss->dis);
            return;
        }
    }
    sdss->callback(egc, &sdss->dm, rc);
}
Пример #2
0
static void colo_preresume_cb(libxl__egc *egc,
                              libxl__checkpoint_devices_state *cds,
                              int rc)
{
    libxl__colo_save_state *css = cds->concrete_data;
    libxl__domain_save_state *dss = CONTAINER_OF(css, *dss, css);

    EGC_GC;

    if (rc) {
        LOGD(ERROR, dss->domid, "preresume fails");
        goto out;
    }

    if (css->qdisk_used && !css->qdisk_setuped) {
        if (libxl__qmp_start_replication(gc, dss->domid, true)) {
            LOGD(ERROR, dss->domid, "starting replication fails");
            goto out;
        }
        css->qdisk_setuped = true;
    }

    if (!css->paused) {
        if (libxl__qmp_colo_do_checkpoint(gc, dss->domid)) {
            LOGD(ERROR, dss->domid, "doing checkpoint fails");
            goto out;
        }
    }

    /* Resumes the domain and the device model */
    if (libxl__domain_resume(gc, dss->domid, /* Fast Suspend */1)) {
        LOGD(ERROR, dss->domid, "cannot resume primary vm");
        goto out;
    }

    /*
     * The guest should be paused before doing colo because there is
     * no disk migration.
     */
    if (css->paused) {
        rc = libxl_domain_unpause(CTX, dss->domid);
        if (rc) {
            LOGD(ERROR, dss->domid, "cannot unpause primary vm");
            goto out;
        }
        css->paused = false;
    }

    /* read CHECKPOINT_SVM_RESUMED */
    css->callback = colo_read_svm_resumed_done;
    css->srs.checkpoint_callback = colo_common_read_stream_done;
    libxl__stream_read_checkpoint_state(egc, &css->srs);

    return;

out:
    libxl__xc_domain_saverestore_async_callback_done(egc, &dss->sws.shs, 0);
}
Пример #3
0
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;
}
Пример #4
0
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;
}
Пример #5
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 = STUBDOM_SPECIAL_CONSOLES, 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.u.pv.cmdline = libxl__sprintf(&gc, " -d %d", info->domid);
    b_info.u.pv.ramdisk.path = "";
    b_info.u.pv.features = "";
    b_info.hvm = 0;

    /* fixme: this function can leak the stubdom if it fails */

    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;
        /* STUBDOM_CONSOLE_LOGGING (console 0) is for minios logging
         * STUBDOM_CONSOLE_SAVE (console 1) is for writing the save file
         * STUBDOM_CONSOLE_RESTORE (console 2) is for reading the save file
         */
        switch (i) {
            char *filename;
            char *name;
            case STUBDOM_CONSOLE_LOGGING:
                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);
                break;
            case STUBDOM_CONSOLE_SAVE:
                console[i].output = libxl__sprintf(&gc, "file:"SAVEFILE".%d", info->domid);
                break;
            case STUBDOM_CONSOLE_RESTORE:
                if (info->saved_state)
                    console[i].output = libxl__sprintf(&gc, "pipe:%s", info->saved_state);
                break;
            default:
                console[i].output = "pty";
                break;
        }
        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;
}