[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH RFC v2 3/8] Adapted libxl to handle migration of instance with qemu based disks
--- tools/libxl/libxl.h | 11 ++- tools/libxl/libxl_create.c | 191 ++++++++++++++++++++++++++++++++++++--- tools/libxl/libxl_dm.c | 26 ++++-- tools/libxl/libxl_dom_save.c | 85 ++++++++++++++++- tools/libxl/libxl_domain.c | 4 +- tools/libxl/libxl_internal.h | 60 ++++++++++-- tools/libxl/libxl_save_callout.c | 38 +++++--- tools/libxl/libxl_save_helper.c | 4 +- tools/libxl/libxl_stream_read.c | 17 +++- tools/libxl/libxl_stream_write.c | 28 +++++- 10 files changed, 406 insertions(+), 58 deletions(-) diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h index 91408b4..4022c37 100644 --- a/tools/libxl/libxl.h +++ b/tools/libxl/libxl.h @@ -1333,7 +1333,7 @@ int libxl_domain_create_new(libxl_ctx *ctx, libxl_domain_config *d_config, LIBXL_EXTERNAL_CALLERS_ONLY; int libxl_domain_create_restore(libxl_ctx *ctx, libxl_domain_config *d_config, uint32_t *domid, int restore_fd, - int send_back_fd, + int send_back_fd, int mirror_qemu_disks, const libxl_domain_restore_params *params, const libxl_asyncop_how *ao_how, const libxl_asyncprogress_how *aop_console_how) @@ -1373,8 +1373,9 @@ static inline int libxl_domain_create_restore_0x040400( const libxl_asyncprogress_how *aop_console_how) LIBXL_EXTERNAL_CALLERS_ONLY { + //TODO: balvisio: Review return libxl_domain_create_restore(ctx, d_config, domid, restore_fd, - -1, params, ao_how, aop_console_how); + -1, 0, params, ao_how, aop_console_how); } #define libxl_domain_create_restore libxl_domain_create_restore_0x040400 @@ -1408,10 +1409,16 @@ int libxl_retrieve_domain_configuration(libxl_ctx *ctx, uint32_t domid, int libxl_domain_suspend(libxl_ctx *ctx, uint32_t domid, int fd, int flags, /* LIBXL_SUSPEND_* */ + const char* hostname, const libxl_asyncop_how *ao_how) LIBXL_EXTERNAL_CALLERS_ONLY; #define LIBXL_SUSPEND_DEBUG 1 #define LIBXL_SUSPEND_LIVE 2 +#define LIBXL_SUSPEND_MIRROR_QEMU_DISKS 4 + +//TODO: balvisio: DO NOT HARD-CODE THIS PARAMS +#define QEMU_DRIVE_MIRROR_PORT "11000" +#define QEMU_DRIVE_MIRROR_DEVICE "ide0-hd0" /* @param suspend_cancel [from xenctrl.h:xc_domain_resume( @param fast )] * If this parameter is true, use co-operative resume. The guest diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c index 9123585..f10f2ce 100644 --- a/tools/libxl/libxl_create.c +++ b/tools/libxl/libxl_create.c @@ -744,6 +744,10 @@ static int store_libxl_entry(libxl__gc *gc, uint32_t domid, static void domcreate_devmodel_started(libxl__egc *egc, libxl__dm_spawn_state *dmss, int rc); + +static void start_nbd_server(libxl__egc *egc, libxl__dm_spawn_state *dmss, + int ret); + static void domcreate_bootloader_console_available(libxl__egc *egc, libxl__bootloader_state *bl); static void domcreate_bootloader_done(libxl__egc *egc, @@ -760,10 +764,17 @@ static void domcreate_stream_done(libxl__egc *egc, libxl__stream_read_state *srs, int ret); +static void domcreate_pre_build(libxl__egc *egc, + libxl__domain_create_state *dcs, + int ret); + static void domcreate_rebuild_done(libxl__egc *egc, libxl__domain_create_state *dcs, int ret); +static void domcreate_multidev_begin(libxl__egc *egc, + libxl__domain_create_state *dcs); + /* Our own function to clean up and call the user's callback. * The final call in the sequence. */ static void domcreate_complete(libxl__egc *egc, @@ -1016,6 +1027,64 @@ static void libxl__colo_restore_setup_done(libxl__egc *egc, libxl__stream_read_start(egc, &dcs->srs); } +static void start_nbd_server(libxl__egc *egc, libxl__dm_spawn_state *dmss, + int ret){ + + libxl__domain_create_state *dcs = CONTAINER_OF(dmss, *dcs, sdss.dm); + STATE_AO_GC(dmss->spawn.ao); + const uint32_t domid = dcs->guest_domid; + dcs->sdss.dm.guest_domid = domid; + + if (ret) { + LOGD(ERROR, domid, "device model did not start: %d", ret); + goto error_out; + } + + if(dcs->restore_fd >= 0 && dcs->mirror_qemu_disks) { + /* + * Start and add the NBD server + * Host is set it to "::" for now + * Port we hard code a port for now + + * This code just handles the case when -M pc is used. + * (The config xen_platform_pci = 0) + * + * TODO: Current implementation only works with upstream qemu + * TODO: consider the case when qemu-xen-traditional is used. + * TODO: Check and copy only those disks which are local + * TODO: Assign port dynamically + */ + + LOGD(DEBUG, "Starting NBD Server\n"); + ret = libxl__qmp_nbd_server_start(gc, domid, "::", QEMU_DRIVE_MIRROR_PORT); + if (ret) { + ret = ERROR_FAIL; + LOGD(ERROR, "Failed to start NBD Server\n"); + goto skip_nbd; + }else{ + LOGD(INFO, "Started NBD Server Successfully\n"); + } + + ret = libxl__qmp_nbd_server_add(gc, domid, QEMU_DRIVE_MIRROR_DEVICE); + + if (ret) { + ret = ERROR_FAIL; + LOGD(ERROR, "Failed to add NBD Server\n"); + goto skip_nbd; + } else { + LOGD(INFO, "NBD Add Successful\n"); + } + } + +skip_nbd: + libxl__stream_read_start(egc, &dcs->srs); + return; + +error_out: + assert(ret); + domcreate_complete(egc, dcs, ret); +} + static void domcreate_bootloader_done(libxl__egc *egc, libxl__bootloader_state *bl, int rc) @@ -1033,6 +1102,8 @@ static void domcreate_bootloader_done(libxl__egc *egc, libxl_domain_build_info *const info = &d_config->b_info; libxl__srm_restore_autogen_callbacks *const callbacks = &dcs->srs.shs.callbacks.restore.a; + libxl__srm_restore_autogen_callbacks *const callbacks_mirror_qemu_disks = + &dcs->srs_local_disks.shs.callbacks.restore.a; if (rc) { domcreate_rebuild_done(egc, dcs, rc); @@ -1050,8 +1121,41 @@ static void domcreate_bootloader_done(libxl__egc *egc, dcs->sdss.dm.spawn.ao = ao; dcs->sdss.dm.guest_config = dcs->guest_config; dcs->sdss.dm.build_state = &dcs->build_state; - dcs->sdss.dm.callback = domcreate_devmodel_started; - dcs->sdss.callback = domcreate_devmodel_started; + if(!dcs->mirror_qemu_disks) { + dcs->sdss.dm.callback = domcreate_devmodel_started; + dcs->sdss.callback = domcreate_devmodel_started; + }else{ + /* + Original calling sequence: + 0. domcreate_bootloader_done + 1. MEMORY STREAM + 2. domcreate_stream_done + 3. domcreate_pre_build + 4. domcreate_rebuild_done + 5. domcreate_multidev_begin + 6. domcreate_launch_dm + 7. domcreate_devmodel_started + + In the case of local_disk domcreate_devmodel_started will be called: + through the following sequence: + 0. domcreate_bootloader_done + 1. 1st MEMORY STREAM + 2. domcreate_stream_done + 3. domcreate_pre_build + 4. domcreate_rebuild_done + 5. domcreate_multidev_begin + 6. domcreate_launch_dm + 7. start_nbd_server + 8. 2nd MEMORY STREAM + 9. domcreate_stream_done + 9.a. Calls -incoming to start QEMU process + 10. domcreate_devmodel_started + */ + + dcs->sdss.dm.callback = start_nbd_server; + dcs->sdss.callback = start_nbd_server; + } + if (restore_fd < 0 && dcs->domid_soft_reset == INVALID_DOMID) { rc = libxl__domain_build(gc, d_config, domid, state); @@ -1061,6 +1165,7 @@ static void domcreate_bootloader_done(libxl__egc *egc, /* Restore */ callbacks->restore_results = libxl__srm_callout_callback_restore_results; + callbacks_mirror_qemu_disks->restore_results = libxl__srm_callout_callback_restore_results; /* COLO only supports HVM now because it does not work very * well with pv drivers: @@ -1087,6 +1192,7 @@ static void domcreate_bootloader_done(libxl__egc *egc, dcs->srs.legacy = (dcs->restore_params.stream_version == 1); dcs->srs.back_channel = false; dcs->srs.completion_callback = domcreate_stream_done; + dcs->srs.mirror_qemu_disks = 0; if (restore_fd >= 0) { switch (checkpointed_stream) { @@ -1104,7 +1210,20 @@ static void domcreate_bootloader_done(libxl__egc *egc, libxl__remus_restore_setup(egc, dcs); /* fall through */ case LIBXL_CHECKPOINTED_STREAM_NONE: - libxl__stream_read_start(egc, &dcs->srs); + if (dcs->mirror_qemu_disks) { + /* Spawn the local_dm process before reading the memory stream */ + dcs->srs_mirror_qemu_disks.ao = ao; + dcs->srs_mirror_qemu_disks.dcs = dcs; + dcs->srs_mirror_qemu_disks.fd = restore_fd; + dcs->srs_mirror_qemu_disks.legacy = (dcs->restore_params.stream_version == 1); + dcs->srs_mirror_qemu_disks.back_channel = false; + dcs->srs_mirror_qemu_disks.completion_callback = domcreate_stream_done; + dcs->srs_mirror_qemu_disks.mirror_qemu_disks = 1; + + libxl__stream_read_start(egc, &dcs->srs_mirror_qemu_disks); + } else { + libxl__stream_read_start(egc, &dcs->srs); + } } return; } @@ -1132,6 +1251,35 @@ static void domcreate_stream_done(libxl__egc *egc, { libxl__domain_create_state *dcs = srs->dcs; STATE_AO_GC(dcs->ao); + + const uint32_t domid = dcs->guest_domid; + const char* uri; + const char* state_file = GCSPRINTF( + LIBXL_DEVICE_MODEL_RESTORE_FILE".%d", domid); + + if(!dcs->mirror_qemu_disks || srs->mirror_qemu_disks){ + domcreate_pre_build(egc, dcs, ret); + }else{ + //Stop NBD server + fprintf(stderr, "Stopping NBD server\n"); + rc = libxl__qmp_nbd_server_stop(gc, domid); + if (rc){ + fprintf(stderr, "Failed to stop NBD server\n"); + }else{ + fprintf(stderr, "Stopped NBD server successfully\n"); + } + uri = GCSPRINTF("exec: /bin/cat %s", (&dcs->sdss.dm)->build_state->saved_state); + libxl__qmp_migrate_incoming(gc, domid, uri); + domcreate_devmodel_started(egc, &dcs->sdss.dm, 0); + } + return; +} + +static void domcreate_pre_build(libxl__egc *egc, + libxl__domain_create_state *dcs, + int ret) +{ + STATE_AO_GC(dcs->ao); libxl_ctx *ctx = libxl__gc_owner(gc); char **vments = NULL, **localents = NULL; struct timeval start_time; @@ -1185,7 +1333,7 @@ static void domcreate_stream_done(libxl__egc *egc, if (ret) goto out; - if (info->type == LIBXL_DOMAIN_TYPE_HVM) { + if (info->type == LIBXL_DOMAIN_TYPE_HVM && !dcs->mirror_qemu_disks) { state->saved_state = GCSPRINTF( LIBXL_DEVICE_MODEL_RESTORE_FILE".%d", domid); } @@ -1223,10 +1371,7 @@ static void domcreate_rebuild_done(libxl__egc *egc, store_libxl_entry(gc, domid, &d_config->b_info); - libxl__multidev_begin(ao, &dcs->multidev); - dcs->multidev.callback = domcreate_launch_dm; - libxl__add_disks(egc, ao, domid, d_config, &dcs->multidev); - libxl__multidev_prepared(egc, &dcs->multidev, 0); + domcreate_multidev_begin(egc, dcs); return; @@ -1235,6 +1380,24 @@ static void domcreate_rebuild_done(libxl__egc *egc, domcreate_complete(egc, dcs, ret); } +static void domcreate_multidev_begin(libxl__egc *egc, + libxl__domain_create_state *dcs){ + + STATE_AO_GC(dcs->ao); + + /* convenience aliases */ + const uint32_t domid = dcs->guest_domid; + libxl_domain_config *const d_config = dcs->guest_config; + + libxl__multidev_begin(ao, &dcs->multidev); + dcs->multidev.callback = domcreate_launch_dm; + + libxl__add_disks(egc, ao, domid, d_config, &dcs->multidev); + libxl__multidev_prepared(egc, &dcs->multidev, 0); + + return; +} + static void domcreate_launch_dm(libxl__egc *egc, libxl__multidev *multidev, int ret) { @@ -1355,7 +1518,7 @@ static void domcreate_launch_dm(libxl__egc *egc, libxl__multidev *multidev, if (libxl_defbool_val(d_config->b_info.device_model_stubdomain)) libxl__spawn_stub_dm(egc, &dcs->sdss); else - libxl__spawn_local_dm(egc, &dcs->sdss.dm); + libxl__spawn_local_dm(egc, &dcs->sdss.dm, dcs->mirror_qemu_disks); /* * Handle the domain's (and the related stubdomain's) access to @@ -1387,7 +1550,7 @@ static void domcreate_launch_dm(libxl__egc *egc, libxl__multidev *multidev, goto error_out; if (ret) { dcs->sdss.dm.guest_domid = domid; - libxl__spawn_local_dm(egc, &dcs->sdss.dm); + libxl__spawn_local_dm(egc, &dcs->sdss.dm, 0); return; } else { assert(!dcs->sdss.dm.guest_domid); @@ -1604,6 +1767,7 @@ static void domain_create_cb(libxl__egc *egc, static int do_domain_create(libxl_ctx *ctx, libxl_domain_config *d_config, uint32_t *domid, int restore_fd, int send_back_fd, + int mirror_qemu_disks, const libxl_domain_restore_params *params, const libxl_asyncop_how *ao_how, const libxl_asyncprogress_how *aop_console_how) @@ -1619,6 +1783,7 @@ static int do_domain_create(libxl_ctx *ctx, libxl_domain_config *d_config, libxl_domain_config_copy(ctx, &cdcs->dcs.guest_config_saved, d_config); cdcs->dcs.restore_fd = cdcs->dcs.libxc_fd = restore_fd; cdcs->dcs.send_back_fd = send_back_fd; + cdcs->dcs.mirror_qemu_disks = mirror_qemu_disks; if (restore_fd > -1) { cdcs->dcs.restore_params = *params; rc = libxl__fd_flags_modify_save(gc, cdcs->dcs.restore_fd, @@ -1847,13 +2012,13 @@ int libxl_domain_create_new(libxl_ctx *ctx, libxl_domain_config *d_config, const libxl_asyncprogress_how *aop_console_how) { unset_disk_colo_restore(d_config); - return do_domain_create(ctx, d_config, domid, -1, -1, NULL, + return do_domain_create(ctx, d_config, domid, -1, -1, 0, NULL, ao_how, aop_console_how); } int libxl_domain_create_restore(libxl_ctx *ctx, libxl_domain_config *d_config, uint32_t *domid, int restore_fd, - int send_back_fd, + int send_back_fd, int mirror_qemu_disks, const libxl_domain_restore_params *params, const libxl_asyncop_how *ao_how, const libxl_asyncprogress_how *aop_console_how) @@ -1865,7 +2030,7 @@ int libxl_domain_create_restore(libxl_ctx *ctx, libxl_domain_config *d_config, } return do_domain_create(ctx, d_config, domid, restore_fd, send_back_fd, - params, ao_how, aop_console_how); + mirror_qemu_disks, params, ao_how, aop_console_how); } int libxl_domain_soft_reset(libxl_ctx *ctx, diff --git a/tools/libxl/libxl_dm.c b/tools/libxl/libxl_dm.c index e0e6a99..ff6721d 100644 --- a/tools/libxl/libxl_dm.c +++ b/tools/libxl/libxl_dm.c @@ -915,7 +915,7 @@ static int libxl__build_device_model_args_new(libxl__gc *gc, const libxl_domain_config *guest_config, char ***args, char ***envs, const libxl__domain_build_state *state, - int *dm_state_fd) + int *dm_state_fd, int mirror_qemu_disks) { const libxl_domain_create_info *c_info = &guest_config->c_info; const libxl_domain_build_info *b_info = &guest_config->b_info; @@ -1396,12 +1396,18 @@ static int libxl__build_device_model_args_new(libxl__gc *gc, } } - if (state->saved_state) { + if (state->saved_state && !mirror_qemu_disks) { /* This file descriptor is meant to be used by QEMU */ *dm_state_fd = open(state->saved_state, O_RDONLY); flexarray_append(dm_args, "-incoming"); flexarray_append(dm_args, GCSPRINTF("fd:%d",*dm_state_fd)); } + + if(mirror_qemu_disks) { + flexarray_append(dm_args, "-incoming"); + flexarray_append(dm_args, "defer"); + } + for (i = 0; b_info->extra && b_info->extra[i] != NULL; i++) flexarray_append(dm_args, b_info->extra[i]); @@ -1664,7 +1670,7 @@ static int libxl__build_device_model_args(libxl__gc *gc, const libxl_domain_config *guest_config, char ***args, char ***envs, const libxl__domain_build_state *state, - int *dm_state_fd) + int *dm_state_fd, int mirror_qemu_disks) /* dm_state_fd may be NULL iff caller knows we are using old stubdom * and therefore will be passing a filename rather than a fd. */ { @@ -1680,7 +1686,8 @@ static int libxl__build_device_model_args(libxl__gc *gc, return libxl__build_device_model_args_new(gc, dm, guest_domid, guest_config, args, envs, - state, dm_state_fd); + state, dm_state_fd, + mirror_qemu_disks); default: LOGED(ERROR, guest_domid, "unknown device model version %d", guest_config->b_info.device_model_version); @@ -1897,7 +1904,7 @@ void libxl__spawn_stub_dm(libxl__egc *egc, libxl__stub_dm_spawn_state *sdss) ret = libxl__build_device_model_args(gc, "stubdom-dm", guest_domid, guest_config, &args, NULL, - d_state, NULL); + d_state, NULL, 0); if (ret) { ret = ERROR_FAIL; goto out; @@ -2055,7 +2062,7 @@ static void spawn_stub_launch_dm(libxl__egc *egc, /* If dom0 qemu not needed, do not launch it */ spawn_stubdom_pvqemu_cb(egc, &sdss->pvqemu, 0); } else { - libxl__spawn_local_dm(egc, &sdss->pvqemu); + libxl__spawn_local_dm(egc, &sdss->pvqemu, 0); } return; @@ -2160,7 +2167,8 @@ static void device_model_spawn_outcome(libxl__egc *egc, libxl__dm_spawn_state *dmss, int rc); -void libxl__spawn_local_dm(libxl__egc *egc, libxl__dm_spawn_state *dmss) +void libxl__spawn_local_dm(libxl__egc *egc, libxl__dm_spawn_state *dmss, + int mirror_qemu_disks) { /* convenience aliases */ const int domid = dmss->guest_domid; @@ -2200,7 +2208,7 @@ void libxl__spawn_local_dm(libxl__egc *egc, libxl__dm_spawn_state *dmss) } rc = libxl__build_device_model_args(gc, dm, domid, guest_config, &args, &envs, state, - &dm_state_fd); + &dm_state_fd, mirror_qemu_disks); if (rc) goto out; @@ -2330,7 +2338,7 @@ static void device_model_confirm(libxl__egc *egc, libxl__spawn_state *spawn, if (!xsdata) return; - if (strcmp(xsdata, "running")) + if (strcmp(xsdata, "running") && strcmp(xsdata, "inmigrate")) return; libxl__spawn_initiate_detach(gc, spawn); diff --git a/tools/libxl/libxl_dom_save.c b/tools/libxl/libxl_dom_save.c index 77fe30e..a2730f5 100644 --- a/tools/libxl/libxl_dom_save.c +++ b/tools/libxl/libxl_dom_save.c @@ -408,18 +408,97 @@ void libxl__domain_save(libxl__egc *egc, libxl__domain_save_state *dss) dss->sws.fd = dss->fd; dss->sws.back_channel = false; dss->sws.completion_callback = stream_done; - - libxl__stream_write_start(egc, &dss->sws); + dss->sws.mirror_qemu_disks = 0; + + if(!dss->mirror_qemu_disks) { + libxl__stream_write_start(egc, &dss->sws); + } else { + dss->sws_mirror_qemu_disks.ao = dss->ao; + dss->sws_mirror_qemu_disks.dss = dss; + dss->sws_mirror_qemu_disks.fd = dss->fd; + dss->sws_mirror_qemu_disks.back_channel = false; + dss->sws_mirror_qemu_disks.mirror_qemu_disks = 1; + dss->sws_mirror_qemu_disks.completion_callback = stream_done; + libxl__stream_write_start(egc, &dss->sws_mirror_qemu_disks); + } return; out: domain_save_done(egc, dss, rc); } +static void mirror_qemu_disks(libxl__egc *egc, libxl__stream_write_state *sws, + int rc) +{ + int counter = 20; + char* target; + bool job_is_ready = false; + libxl__domain_save_state *dss = sws->dss; + const uint32_t domid = dss->domid; + STATE_AO_GC(dss->ao); + + if (dss->mirror_qemu_disks) { + /* + * If the -q was provided, the drive-mirror job is started. + * TODO: Move the following code as part of the domain_suspend + * TODO: The port should be sent by the destination. + */ +start_mirror: + LOGD(DEBUG, domid, "Sleeping for a bit so that source can start NBD\n"); + sleep(30); + LOGD(DEBUG, "Starting mirror-drive of device %s\n", + QEMU_DRIVE_MIRROR_DEVICE); + target = GCSPRINTF("nbd:%s:%s:exportname=%s", dss->hostname, + QEMU_DRIVE_MIRROR_PORT, QEMU_DRIVE_MIRROR_DEVICE); + rc = libxl__qmp_drive_mirror(gc, dss->domid, QEMU_DRIVE_MIRROR_DEVICE, + target, "raw"); + if (!rc) { + LOGD(INFO, domid, "Drive mirror command returned successfully\n"); + }else{ + LOGD(ERROR, domid, "Sending drive mirror command failed\n"); + if(counter > 0){ + LOGD(INFO, domid, "Counter: %d. Sleeping for 10 sec and retry\n", counter); + sleep(10); + counter--; + goto start_mirror; + }else{ + goto cont; + } + } + + /* + * Query job status until it is ready + * TODO: This code is just an inefficient busy wait. QMP sends an + * TODO: asynchronous message when mirroring job is completed. Consider + * TODO: adding the capability to handle asynchronous QMP messages (already done?) + */ + while(!job_is_ready) { + LOGD(INFO, domid, "Checking for drive-mirror job"); + rc = libxl__qmp_query_block_jobs(gc, dss->domid, &job_is_ready); + if(rc){ + LOGD(ERROR, domid, "Checking block job failed\n"); + goto cont; + }else{ + LOGD(INFO, domid, "Checking block job succeeded\n"); + } + if(!job_is_ready){ + LOGD(INFO, domid, "Sleeping 5 sec\n"); + sleep(5); + } + } + } +cont: + libxl__stream_write_start(egc, &sws->dss->sws); +} + static void stream_done(libxl__egc *egc, libxl__stream_write_state *sws, int rc) { - domain_save_done(egc, sws->dss, rc); + if(!sws->dss->mirror_qemu_disks || !sws->mirror_qemu_disks) { + domain_save_done(egc, sws->dss, rc); + } else { + mirror_qemu_disks(egc, sws, rc); + } } static void domain_save_done(libxl__egc *egc, diff --git a/tools/libxl/libxl_domain.c b/tools/libxl/libxl_domain.c index 08eccd0..76c6d3d 100644 --- a/tools/libxl/libxl_domain.c +++ b/tools/libxl/libxl_domain.c @@ -487,7 +487,7 @@ static void domain_suspend_cb(libxl__egc *egc, } int libxl_domain_suspend(libxl_ctx *ctx, uint32_t domid, int fd, int flags, - const libxl_asyncop_how *ao_how) + const char* hostname, const libxl_asyncop_how *ao_how) { AO_CREATE(ctx, domid, ao_how); int rc; @@ -509,6 +509,8 @@ int libxl_domain_suspend(libxl_ctx *ctx, uint32_t domid, int fd, int flags, dss->type = type; dss->live = flags & LIBXL_SUSPEND_LIVE; dss->debug = flags & LIBXL_SUSPEND_DEBUG; + dss->mirror_qemu_disks = flags & LIBXL_SUSPEND_MIRROR_QEMU_DISKS; + dss->hostname = hostname; dss->checkpointed_stream = LIBXL_CHECKPOINTED_STREAM_NONE; rc = libxl__fd_flags_modify_save(gc, dss->fd, diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index 1349a8f..16a476f 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -1840,19 +1840,42 @@ _hidden int libxl__qmp_start_replication(libxl__gc *gc, int domid, _hidden int libxl__qmp_nbd_server_add(libxl__gc *gc, int domid, const char *disk); +/* Add a disk to NBD server */ +_hidden int libxl__qmp_nbd_server_add(libxl__gc *gc, int domid, + const char *disk); +/* Start replication */ +_hidden int libxl__qmp_start_replication(libxl__gc *gc, int domid, + bool primary); +/* Add a disk to NBD server */ + _hidden int libxl__qmp_nbd_server_add(libxl__gc *gc, int domid, + const char *disk); /* Mirror disk drive */ -_hidden int libxl__qmp_drive_mirror(libxl__gc *gc, int domid, const char* device, - const char* target, const char* format); - +_hidden int libxl__qmp_drive_mirror(libxl__gc *gc, int domid, + const char* device, const char* target, + const char* format); /* Query block devices */ -_hidden int libxl__qmp_query_block(libxl__gc *gc, int domid, char *device_names); - +_hidden int libxl__qmp_query_block(libxl__gc *gc, int domid, + char *device_names); /* Query existing block jobs*/ -_hidden int libxl__qmp_query_block_jobs(libxl__gc *gc, int domid, bool *is_ready); - +_hidden int libxl__qmp_query_block_jobs(libxl__gc *gc, int domid, + bool *is_ready); /* Resume QEMU process started with -incoming defer */ -_hidden int libxl__qmp_migrate_incoming(libxl__gc *gc, int domid, const char* uri); +_hidden int libxl__qmp_migrate_incoming(libxl__gc *gc, int domid, + const char* uri); +/* Mirror disk drive */ +_hidden int libxl__qmp_drive_mirror(libxl__gc *gc, int domid, + const char* device, const char* target, + const char* format); +/* Query block devices */ +_hidden int libxl__qmp_query_block(libxl__gc *gc, int domid, + char *device_names); +/* Query existing block jobs*/ +_hidden int libxl__qmp_query_block_jobs(libxl__gc *gc, int domid, + bool *is_ready); +/* Resume QEMU process started with -incoming defer */ +_hidden int libxl__qmp_migrate_incoming(libxl__gc *gc, int domid, + const char* uri); /* Get replication error that occurs when the vm is running */ _hidden int libxl__qmp_query_xen_replication_status(libxl__gc *gc, int domid); /* Do checkpoint */ @@ -3142,6 +3165,7 @@ struct libxl__stream_read_state { int fd; bool legacy; bool back_channel; + int mirror_qemu_disks; void (*completion_callback)(libxl__egc *egc, libxl__stream_read_state *srs, int rc); @@ -3220,6 +3244,7 @@ struct libxl__stream_write_state { libxl__domain_save_state *dss; int fd; bool back_channel; + int mirror_qemu_disks; void (*completion_callback)(libxl__egc *egc, libxl__stream_write_state *sws, int rc); @@ -3319,6 +3344,8 @@ struct libxl__domain_save_state { libxl_domain_type type; int live; int debug; + int mirror_qemu_disks; + const char* hostname; int checkpointed_stream; const libxl_domain_remus_info *remus; /* private */ @@ -3334,6 +3361,7 @@ struct libxl__domain_save_state { }; libxl__checkpoint_devices_state cds; libxl__stream_write_state sws; + libxl__stream_write_state sws_mirror_qemu_disks; libxl__logdirty_switch logdirty; }; @@ -3668,6 +3696,7 @@ struct libxl__dm_spawn_state { libxl__spawn_state spawn; /* filled in by user, must remain valid: */ uint32_t guest_domid; /* domain being served */ + int mirror_qemu_disks; libxl_domain_config *guest_config; libxl__domain_build_state *build_state; /* relates to guest_domid */ libxl__dm_spawn_cb *callback; @@ -3713,6 +3742,7 @@ struct libxl__domain_create_state { int restore_fd, libxc_fd; int restore_fdfl; /* original flags of restore_fd */ int send_back_fd; + int mirror_qemu_disks; libxl_domain_restore_params restore_params; uint32_t domid_soft_reset; libxl__domain_create_cb *callback; @@ -3729,6 +3759,7 @@ struct libxl__domain_create_state { /* If we're not doing stubdom, we use only dmss.dm, * for the non-stubdom device model. */ libxl__stream_read_state srs; + libxl__stream_read_state srs_local_disks; /* necessary if the domain creation failed and we have to destroy it */ libxl__domain_destroy_state dds; libxl__multidev multidev; @@ -3748,13 +3779,17 @@ _hidden void libxl__domain_save(libxl__egc *egc, /* calls libxl__xc_domain_suspend_done when done */ _hidden void libxl__xc_domain_save(libxl__egc *egc, libxl__domain_save_state *dss, - libxl__save_helper_state *shs); + libxl__save_helper_state *shs, + int mirror_qemu_disks); /* If rc==0 then retval is the return value from xc_domain_save * and errnoval is the errno value it provided. * If rc!=0, retval and errnoval are undefined. */ _hidden void libxl__xc_domain_save_done(libxl__egc*, void *dss_void, int rc, int retval, int errnoval); +_hidden void libxl__xc_mirror_disks_save_done(libxl__egc *egc, void *dss_void, + int rc, int retval, int errnoval); + /* Used by asynchronous callbacks: ie ones which xc regards as * returning a value, but which we want to handle asynchronously. * Such functions' actual callback function return void in libxl @@ -3778,13 +3813,18 @@ _hidden int libxl__restore_emulator_xenstore_data _hidden void libxl__xc_domain_restore(libxl__egc *egc, libxl__domain_create_state *dcs, libxl__save_helper_state *shs, - int hvm, int pae); + int hvm, int pae, int mirror_qemu_disks); /* If rc==0 then retval is the return value from xc_domain_save * and errnoval is the errno value it provided. * If rc!=0, retval and errnoval are undefined. */ _hidden void libxl__xc_domain_restore_done(libxl__egc *egc, void *dcs_void, int rc, int retval, int errnoval); +_hidden void libxl__xc_mirror_disks_restore_done(libxl__egc *egc, + void *dcs_void, + int rc, int retval, + int errnoval); + _hidden void libxl__save_helper_init(libxl__save_helper_state *shs); _hidden void libxl__save_helper_abort(libxl__egc *egc, libxl__save_helper_state *shs); diff --git a/tools/libxl/libxl_save_callout.c b/tools/libxl/libxl_save_callout.c index 891c669..290d91d 100644 --- a/tools/libxl/libxl_save_callout.c +++ b/tools/libxl/libxl_save_callout.c @@ -43,7 +43,7 @@ static void helper_done(libxl__egc *egc, libxl__save_helper_state *shs); void libxl__xc_domain_restore(libxl__egc *egc, libxl__domain_create_state *dcs, libxl__save_helper_state *shs, - int hvm, int pae) + int hvm, int pae, int mirror_qemu_disks) { STATE_AO_GC(dcs->ao); @@ -63,16 +63,22 @@ void libxl__xc_domain_restore(libxl__egc *egc, libxl__domain_create_state *dcs, state->console_domid, hvm, pae, cbflags, dcs->restore_params.checkpointed_stream, + mirror_qemu_disks, }; shs->ao = ao; shs->domid = domid; shs->recv_callback = libxl__srm_callout_received_restore; if (dcs->restore_params.checkpointed_stream == - LIBXL_CHECKPOINTED_STREAM_COLO) + LIBXL_CHECKPOINTED_STREAM_COLO) { shs->completion_callback = libxl__colo_restore_teardown; - else - shs->completion_callback = libxl__xc_domain_restore_done; + } else { + if(!mirror_qemu_disks){ + shs->completion_callback = libxl__xc_domain_restore_done; + } else { + shs->completion_callback = libxl__xc_hvm_params_restore_done; + } + } shs->caller_state = dcs; shs->need_results = 1; @@ -81,7 +87,7 @@ void libxl__xc_domain_restore(libxl__egc *egc, libxl__domain_create_state *dcs, } void libxl__xc_domain_save(libxl__egc *egc, libxl__domain_save_state *dss, - libxl__save_helper_state *shs) + libxl__save_helper_state *shs, int mirror_qemu_disks) { STATE_AO_GC(dss->ao); @@ -90,13 +96,17 @@ void libxl__xc_domain_save(libxl__egc *egc, libxl__domain_save_state *dss, const unsigned long argnums[] = { dss->domid, 0, 0, dss->xcflags, dss->hvm, - cbflags, dss->checkpointed_stream, + cbflags, dss->checkpointed_stream, mirror_qemu_disks, }; shs->ao = ao; shs->domid = dss->domid; shs->recv_callback = libxl__srm_callout_received_save; - shs->completion_callback = libxl__xc_domain_save_done; + if(!mirror_qemu_disks){ + shs->completion_callback = libxl__xc_domain_save_done; + }else{ + shs->completion_callback = libxl__xc_hvm_params_save_done; + } shs->caller_state = dss; shs->need_results = 0; @@ -336,13 +346,13 @@ static void helper_exited(libxl__egc *egc, libxl__ev_child *ch, if (!shs->rc) shs->rc = ERROR_FAIL; } - - if (shs->need_results) { - if (!shs->rc) { - LOGD(ERROR,shs->domid,"%s exited without providing results",what); - shs->rc = ERROR_FAIL; - } - } +// balvisio: TODO: FIX +// if (shs->need_results) { +// if (!shs->rc) { +// LOGD(ERROR,shs->domid,"%s exited without providing results",what); +// shs->rc = ERROR_FAIL; +// } +// } if (!shs->completed) { if (!shs->rc) { diff --git a/tools/libxl/libxl_save_helper.c b/tools/libxl/libxl_save_helper.c index 1dece23..cfc9279 100644 --- a/tools/libxl/libxl_save_helper.c +++ b/tools/libxl/libxl_save_helper.c @@ -257,6 +257,7 @@ int main(int argc, char **argv) int hvm = atoi(NEXTARG); unsigned cbflags = strtoul(NEXTARG,0,10); xc_migration_stream_t stream_type = strtoul(NEXTARG,0,10); + int mirror_qemu_disks = atoi(NEXTARG); assert(!*++argv); helper_setcallbacks_save(&helper_save_callbacks, cbflags); @@ -266,7 +267,7 @@ int main(int argc, char **argv) r = xc_domain_save(xch, io_fd, dom, max_iters, max_factor, flags, &helper_save_callbacks, hvm, stream_type, - recv_fd); + recv_fd, mirror_qemu_disks); complete(r); } else if (!strcmp(mode,"--restore-domain")) { @@ -282,6 +283,7 @@ int main(int argc, char **argv) unsigned int pae = strtoul(NEXTARG,0,10); unsigned cbflags = strtoul(NEXTARG,0,10); xc_migration_stream_t stream_type = strtoul(NEXTARG,0,10); + int mirror_qemu_disks = atoi(NEXTARG); assert(!*++argv); helper_setcallbacks_restore(&helper_restore_callbacks, cbflags); diff --git a/tools/libxl/libxl_stream_read.c b/tools/libxl/libxl_stream_read.c index 4838750..ea5ffd3 100644 --- a/tools/libxl/libxl_stream_read.c +++ b/tools/libxl/libxl_stream_read.c @@ -561,6 +561,7 @@ static bool process_record(libxl__egc *egc, { STATE_AO_GC(stream->ao); libxl__domain_create_state *dcs = stream->dcs; + int create_mirror_qemu_disks = stream->dcs->mirror_qemu_disks; libxl__sr_record_buf *rec; libxl_sr_checkpoint_state *srcs; bool further_action_needed = false; @@ -580,7 +581,9 @@ static bool process_record(libxl__egc *egc, break; case REC_TYPE_LIBXC_CONTEXT: - libxl__xc_domain_restore(egc, dcs, &stream->shs, 0, 0); + libxl__xc_domain_restore(egc, dcs, &stream->shs, 0, 0, + stream->mirror_qemu_disks + + create_mirror_qemu_disks); break; case REC_TYPE_EMULATOR_XENSTORE_DATA: @@ -835,6 +838,18 @@ static void stream_done(libxl__egc *egc, } } +void libxl__xc_mirror_disks_restore_done(libxl__egc *egc, void *dcs_void, + int rc, int retval, int errnoval) +{ + libxl__domain_create_state *dcs = dcs_void; + libxl__stream_read_state *stream = &dcs->srs_mirror_qemu_disks; + STATE_AO_GC(dcs->ao); + + check_all_finished(egc, stream, rc); + + stream_continue(egc, stream); +} + void libxl__xc_domain_restore_done(libxl__egc *egc, void *dcs_void, int rc, int retval, int errnoval) { diff --git a/tools/libxl/libxl_stream_write.c b/tools/libxl/libxl_stream_write.c index c96a6a2..ad312ed 100644 --- a/tools/libxl/libxl_stream_write.c +++ b/tools/libxl/libxl_stream_write.c @@ -335,7 +335,24 @@ static void stream_header_done(libxl__egc *egc, static void libxc_header_done(libxl__egc *egc, libxl__stream_write_state *stream) { - libxl__xc_domain_save(egc, stream->dss, &stream->shs); + int save_mirror_qemu_disks = stream->dss->local_disks; + libxl__xc_domain_save(egc, stream->dss, &stream->shs, + save_mirror_qemu_disks + stream->mirror_qemu_disks); +} + +void libxl__xc_mirror_disks_save_done(libxl__egc *egc, void *dss_void, + int rc, int retval, int errnoval) +{ + libxl__domain_save_state *dss = dss_void; + libxl__stream_write_state *stream = &dss->sws_mirror_qemu_disks; + STATE_AO_GC(dss->ao); + + check_all_finished(egc, stream, rc); + + if (stream->in_checkpoint) + write_checkpoint_end_record(egc, stream); + else + write_emulator_xenstore_record(egc, stream); } void libxl__xc_domain_save_done(libxl__egc *egc, void *dss_void, @@ -429,9 +446,12 @@ static void emulator_xenstore_record_done(libxl__egc *egc, { libxl__domain_save_state *dss = stream->dss; - if (dss->type == LIBXL_DOMAIN_TYPE_HVM) - write_emulator_context_record(egc, stream); - else { + if (dss->type == LIBXL_DOMAIN_TYPE_HVM) { + if(!stream->mirror_qemu_disks) + write_emulator_context_record(egc, stream); + else + write_end_record(egc, stream); + } else { if (stream->in_checkpoint) write_checkpoint_end_record(egc, stream); else -- 2.3.2 (Apple Git-55) _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |