[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH RFC] Live migration for VMs with QEMU backed local storage
On Fri, Jun 23, 2017 at 03:31:16AM -0400, Bruno Alvisio wrote: > This patch is the first attempt on adding live migration of instances with > local > storage to Xen. This patch just handles very restricted case of fully > virtualized HVMs. The code uses the "drive-mirror" capability provided by > QEMU. > A new "-l" option is introduced to "xl migrate" command. If provided, the > local > disk should be mirrored during the migration process. If the option is set, > during the VM creation a qemu NBD server is started on the destination. After > the instance is suspended on the source, the QMP "disk-mirror" command is > issued > to mirror the disk to destination. Once the mirroring job is complete, the > migration process continues as before. Finally, the NBD server is stopped > after > the instance is successfully resumed on the destination node. > > A major problem with this patch is that the mirroring of the disk is performed > only after the memory stream is completed and the VM is suspended on the > source; > thus the instance is frozen for a long period of time. The reason this happens > is that the QEMU process (needed for the disk mirroring) is started on the > destination node only after the memory copying is completed. One possibility I > was considering to solve this issue (if it is decided that this capability > should be used): Could a "helper" QEMU process be started on the destination > node at the beginning of the migration sequence with the sole purpose of > handling the disk mirroring and kill it at the end of the migration sequence? > > From the suggestions given by Konrad Wilk and Paul Durrant the preferred > approach would be to handle the mirroring of disks by QEMU instead of directly > being handled directly by, for example, blkback. It would be very helpful for > me > to have a mental map of all the scenarios that can be encountered regarding > local disk (Xen could start supporting live migration of certain types of > local > disks). This are the ones I can think of: > - Fully Virtualized HVM: QEMU emulation > - blkback > - blktap / blktap2 You are missing 'qdisk' which is the QEMU implemenation of blkback. > > > I have included TODOs in the code. I am sending this patch as is because I > first > wanted to get an initial feedback if this is the path the should be pursued. > Any > suggestions and ideas on this patch or on how to make a more generic solution > would be really appreciated. > > Signed-off-by: Bruno Alvisio <bruno.alvisio@xxxxxxxxx> > > --- > tools/libxl/libxl.h | 16 ++++- > tools/libxl/libxl_create.c | 87 +++++++++++++++++++++++++- > tools/libxl/libxl_internal.h | 16 +++++ > tools/libxl/libxl_qmp.c | 115 > ++++++++++++++++++++++++++++++++++- > tools/ocaml/libs/xl/xenlight_stubs.c | 2 +- > tools/xl/xl.h | 1 + > tools/xl/xl_migrate.c | 79 +++++++++++++++++++++--- > tools/xl/xl_vmcontrol.c | 2 +- > 8 files changed, 303 insertions(+), 15 deletions(-) > > diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h > index cf8687a..81fb2dc 100644 > --- a/tools/libxl/libxl.h > +++ b/tools/libxl/libxl.h > @@ -1294,6 +1294,15 @@ int libxl_ctx_alloc(libxl_ctx **pctx, int version, > xentoollog_logger *lg); > int libxl_ctx_free(libxl_ctx *ctx /* 0 is OK */); > > +int libxl__drive_mirror(libxl_ctx *ctx, int domid, const char* device, const > char* target, const char* format) LIBXL_EXTERNAL_CALLERS_ONLY; > + > +int libxl__query_block_jobs(libxl_ctx *ctx, int domid, bool *is_ready) > LIBXL_EXTERNAL_CALLERS_ONLY; > + > +int libxl__query_block(libxl_ctx *ctx, int domid, char *device_names) > LIBXL_EXTERNAL_CALLERS_ONLY; > + > +int libxl__nbd_server_stop(libxl_ctx *ctx, int domid) > LIBXL_EXTERNAL_CALLERS_ONLY; > + > + > /* domain related functions */ > > /* If the result is ERROR_ABORTED, the domain may or may not exist > @@ -1307,7 +1316,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 copy_local_disks, > const libxl_domain_restore_params *params, > const libxl_asyncop_how *ao_how, > const libxl_asyncprogress_how > *aop_console_how) > @@ -1348,7 +1357,7 @@ static inline int libxl_domain_create_restore_0x040400( > LIBXL_EXTERNAL_CALLERS_ONLY > { > 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 > @@ -1387,6 +1396,9 @@ int libxl_domain_suspend(libxl_ctx *ctx, uint32_t > domid, int fd, > #define LIBXL_SUSPEND_DEBUG 1 > #define LIBXL_SUSPEND_LIVE 2 > > +#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 > * must support this. > diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c > index bffbc45..ef99f03 100644 > --- a/tools/libxl/libxl_create.c > +++ b/tools/libxl/libxl_create.c > @@ -27,6 +27,40 @@ > > #include <xen-xsm/flask/flask.h> > > +//TODO: These functions were created to be able to call qmp commands from xl. > +//TODO: These functions should be removed since they won't be called from xl. > +int libxl__drive_mirror(libxl_ctx *ctx, int domid, const char* device, const > char* target, const char* format){ > + GC_INIT(ctx); > + int rc; > + rc = libxl__qmp_drive_mirror(gc, domid, device, target, format); > + GC_FREE; > + return rc; > +} > + > +int libxl__query_block_jobs(libxl_ctx *ctx, int domid, bool *is_ready){ > + GC_INIT(ctx); > + int rc; > + rc = libxl__qmp_query_block_jobs(gc, domid, is_ready); > + GC_FREE; > + return rc; > +} > + > +int libxl__nbd_server_stop(libxl_ctx *ctx, int domid){ > + GC_INIT(ctx); > + int rc; > + rc = libxl__qmp_nbd_server_stop(gc, domid); > + GC_FREE; > + return rc; > +} > + > +int libxl__query_block(libxl_ctx *ctx, int domid, char *device_names){ > + GC_INIT(ctx); > + int rc; > + rc = libxl__qmp_query_block(gc, domid, device_names); > + GC_FREE; > + return rc; > +} > + > int libxl__domain_create_info_setdefault(libxl__gc *gc, > libxl_domain_create_info *c_info) > { > @@ -1355,6 +1389,51 @@ static void domcreate_launch_dm(libxl__egc *egc, > libxl__multidev *multidev, > else > libxl__spawn_local_dm(egc, &dcs->sdss.dm); > > + > + if(dcs->restore_fd >= 0 && dcs->copy_local_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) > + * > + * Current implementation performs the disk mirroring after the > + * VM in the source has been suspended. Thus, the VM is frozen > + * for a long period of time. > + * Consider doing the mirroring of the drive before the memory > + * stream is performed. > + * Consider a solution that handles multiple types of VM > configurations > + * > + * 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 > + */ > + > + fprintf(stderr, "Starting NBD Server\n"); > + ret = libxl__qmp_nbd_server_start(gc, domid, "::", > QEMU_DRIVE_MIRROR_PORT); > + if (ret) { > + ret = ERROR_FAIL; > + fprintf(stderr, "Failed to start NBD Server\n"); > + goto skip_nbd; > + }else{ > + fprintf(stderr, "Started NBD Server Successfully\n"); > + } > + > + ret = libxl__qmp_nbd_server_add(gc, domid, > QEMU_DRIVE_MIRROR_DEVICE); > + > + if (ret) { > + ret = ERROR_FAIL; > + fprintf(stderr, "Failed to add NBD Server\n"); > + goto skip_nbd; > + } else { > + fprintf(stderr, "NBD Add Successful\n"); > + } > + } > + > +skip_nbd: > /* > * Handle the domain's (and the related stubdomain's) access to > * the VGA framebuffer. > @@ -1602,6 +1681,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 copy_local_disks, > const libxl_domain_restore_params *params, > const libxl_asyncop_how *ao_how, > const libxl_asyncprogress_how *aop_console_how) > @@ -1617,6 +1697,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.copy_local_disks = copy_local_disks; > if (restore_fd > -1) { > cdcs->dcs.restore_params = *params; > rc = libxl__fd_flags_modify_save(gc, cdcs->dcs.restore_fd, > @@ -1845,13 +1926,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 copy_local_disks, > const libxl_domain_restore_params *params, > const libxl_asyncop_how *ao_how, > const libxl_asyncprogress_how > *aop_console_how) > @@ -1863,7 +1944,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); > + copy_local_disks, params, ao_how, > aop_console_how); > } > > int libxl_domain_soft_reset(libxl_ctx *ctx, > diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h > index afe6652..938481a 100644 > --- a/tools/libxl/libxl_internal.h > +++ b/tools/libxl/libxl_internal.h > @@ -1835,6 +1835,21 @@ _hidden int libxl__qmp_nbd_server_add(libxl__gc *gc, > int domid, > /* 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); > + > +/* 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); > + > /* 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 */ > @@ -3695,6 +3710,7 @@ struct libxl__domain_create_state { > int restore_fd, libxc_fd; > int restore_fdfl; /* original flags of restore_fd */ > int send_back_fd; > + int copy_local_disks; > libxl_domain_restore_params restore_params; > uint32_t domid_soft_reset; > libxl__domain_create_cb *callback; > diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c > index eab993a..cbfcf77 100644 > --- a/tools/libxl/libxl_qmp.c > +++ b/tools/libxl/libxl_qmp.c > @@ -347,7 +347,9 @@ static libxl__qmp_handler *qmp_init_handler(libxl__gc > *gc, uint32_t domid) > } > qmp->ctx = CTX; > qmp->domid = domid; > - qmp->timeout = 5; > + //TODO: Changed default timeout because drive-mirror command takes a long > + //TODO: to return. Consider timeout to be passed as param. > + qmp->timeout = 600; > > LIBXL_STAILQ_INIT(&qmp->callback_list); > > @@ -1069,6 +1071,117 @@ int libxl__qmp_nbd_server_add(libxl__gc *gc, int > domid, const char *disk) > return qmp_run_command(gc, domid, "nbd-server-add", args, NULL, NULL); > } > > +int libxl__qmp_drive_mirror(libxl__gc *gc, int domid, const char* device, > const char* target, const char* format) > +{ > + libxl__json_object *args = NULL; > + //TODO: Allow method to receive "sync", "speed", "mode", "granurality", > "buf-size" > + qmp_parameters_add_string(gc, &args, "device", device); > + qmp_parameters_add_string(gc, &args, "target", target); > + qmp_parameters_add_string(gc, &args, "sync", "full"); > + qmp_parameters_add_string(gc, &args, "format", format); > + qmp_parameters_add_string(gc, &args, "mode", "existing"); > + qmp_parameters_add_integer(gc, &args, "granularity", 0); > + qmp_parameters_add_integer(gc, &args, "buf-size", 0); > + > + return qmp_run_command(gc, domid, "drive-mirror", args, NULL, NULL); > +} > + > +static int query_block_callback(libxl__qmp_handler *qmp, > + const libxl__json_object *response, > + void *opaque) > +{ > + const libxl__json_object *blockinfo = NULL; > + GC_INIT(qmp->ctx); > + int i, rc = -1; > + > + for (i = 0; (blockinfo = libxl__json_array_get(response, i)); i++) { > + const libxl__json_object *d; > + const char* device_name; > + d = libxl__json_map_get("device", blockinfo, JSON_STRING); > + if(!d){ > + goto out; > + } > + device_name = libxl__json_object_get_string(d); > + } > + > + rc = 0; > +out: > + GC_FREE; > + return rc; > +} > + > +static int query_block_jobs_callback(libxl__qmp_handler *qmp, > + const libxl__json_object *response, > + void *opaque) > +{ > + const libxl__json_object *blockjobinfo = NULL; > + GC_INIT(qmp->ctx); > + int i, rc = -1; > + bool empty = true; > + > + for (i = 0; (blockjobinfo = libxl__json_array_get(response, i)); i++) { > + empty = false; > + const char *bjtype; > + const char *bjdevice; > + unsigned int bjlen; > + unsigned int bjoffset; > + bool bjbusy; > + bool bjpaused; > + const char *bjiostatus; > + bool bjready; > + > + const libxl__json_object *type = NULL; > + const libxl__json_object *device = NULL; > + const libxl__json_object *len = NULL; > + const libxl__json_object *offset = NULL; > + const libxl__json_object *busy = NULL; > + const libxl__json_object *paused = NULL; > + const libxl__json_object *io_status = NULL; > + const libxl__json_object *ready = NULL; > + > + type = libxl__json_map_get("type", blockjobinfo, JSON_STRING); > + device = libxl__json_map_get("device", blockjobinfo, JSON_STRING); > + len = libxl__json_map_get("len", blockjobinfo, JSON_INTEGER); > + offset = libxl__json_map_get("offset", blockjobinfo, JSON_INTEGER); > + busy = libxl__json_map_get("busy", blockjobinfo, JSON_BOOL); > + paused = libxl__json_map_get("type", blockjobinfo, JSON_BOOL); > + io_status = libxl__json_map_get("io-status", blockjobinfo, > JSON_STRING); > + ready = libxl__json_map_get("ready", blockjobinfo, JSON_BOOL); > + > + bjtype = libxl__json_object_get_string(type); > + bjdevice = libxl__json_object_get_string(device); > + bjlen = libxl__json_object_get_integer(len); > + bjoffset = libxl__json_object_get_integer(offset); > + bjbusy = libxl__json_object_get_bool(len); > + bjpaused = libxl__json_object_get_bool(paused); > + bjiostatus = libxl__json_object_get_string(io_status); > + bjready = libxl__json_object_get_bool(ready); > + > + bool *is_ready = opaque; > + *is_ready = bjready; > + } > + > + if(empty){ > + bool *is_ready = opaque; > + *is_ready = true; > + } > + > + rc = 0; > + > + GC_FREE; > + return rc; > +} > + > +int libxl__qmp_query_block(libxl__gc *gc, int domid, char *device_names) > +{ > + return qmp_run_command(gc, domid, "query-block", NULL, > query_block_callback, device_names); > +} > + > +int libxl__qmp_query_block_jobs(libxl__gc *gc, int domid, bool *is_ready) > +{ > + return qmp_run_command(gc, domid, "query-block-jobs", NULL, > query_block_jobs_callback, is_ready); > +} > + > int libxl__qmp_start_replication(libxl__gc *gc, int domid, bool primary) > { > libxl__json_object *args = NULL; > diff --git a/tools/ocaml/libs/xl/xenlight_stubs.c > b/tools/ocaml/libs/xl/xenlight_stubs.c > index 98b52b9..8791175 100644 > --- a/tools/ocaml/libs/xl/xenlight_stubs.c > +++ b/tools/ocaml/libs/xl/xenlight_stubs.c > @@ -538,7 +538,7 @@ value stub_libxl_domain_create_restore(value ctx, value > domain_config, value par > > caml_enter_blocking_section(); > ret = libxl_domain_create_restore(CTX, &c_dconfig, &c_domid, restore_fd, > - -1, &c_params, ao_how, NULL); > + -1, 0, &c_params, ao_how, NULL); > caml_leave_blocking_section(); > > free(ao_how); > diff --git a/tools/xl/xl.h b/tools/xl/xl.h > index aa95b77..dcdb80d 100644 > --- a/tools/xl/xl.h > +++ b/tools/xl/xl.h > @@ -35,6 +35,7 @@ struct domain_create { > int daemonize; > int monitor; /* handle guest reboots etc */ > int paused; > + int copy_local_disks; > int dryrun; > int quiet; > int vnc; > diff --git a/tools/xl/xl_migrate.c b/tools/xl/xl_migrate.c > index 1f0e87d..62b78ea 100644 > --- a/tools/xl/xl_migrate.c > +++ b/tools/xl/xl_migrate.c > @@ -177,7 +177,8 @@ static void migrate_do_preamble(int send_fd, int recv_fd, > pid_t child, > } > > static void migrate_domain(uint32_t domid, const char *rune, int debug, > - const char *override_config_file) > + const char *override_config_file, > + int copy_local_disks, const char* hostname) > { > pid_t child = -1; > int rc; > @@ -186,6 +187,7 @@ static void migrate_domain(uint32_t domid, const char > *rune, int debug, > char rc_buf; > uint8_t *config_data; > int config_len, flags = LIBXL_SUSPEND_LIVE; > + char* target; > > save_domain_core_begin(domid, override_config_file, > &config_data, &config_len); > @@ -232,6 +234,47 @@ static void migrate_domain(uint32_t domid, const char > *rune, int debug, > > fprintf(stderr, "migration sender: Target has acknowledged transfer.\n"); > > + > + /* > + * If the -l 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. > + */ > + if(copy_local_disks) { > + fprintf(stderr, "Starting mirror-drive of device %s\n", > QEMU_DRIVE_MIRROR_DEVICE); > + xasprintf(&target, "nbd:%s:%s:exportname=%s", hostname, > QEMU_DRIVE_MIRROR_PORT, QEMU_DRIVE_MIRROR_DEVICE); > + rc = libxl__drive_mirror(ctx, domid, QEMU_DRIVE_MIRROR_DEVICE, > target, "raw"); > + if (!rc) { > + fprintf(stderr, "Drive mirror command returned successfully\n"); > + }else{ > + fprintf(stderr, "Sending drive mirror command failed\n"); > + 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?) > + */ > + bool job_is_ready = false; > + while(!job_is_ready) { > + fprintf(stderr, "Checking for drive-mirror job"); > + rc = libxl__query_block_jobs(ctx, domid, &job_is_ready); > + if(rc){ > + fprintf(stderr, "Checking block job failed\n"); > + goto cont; > + }else{ > + fprintf(stderr, "Checking block job succeeded\n"); > + } > + if(!job_is_ready){ > + fprintf(stderr, "Sleeping 5 sec\n"); > + sleep(5); > + } > + } > + } > +cont: > + > if (common_domname) { > xasprintf(&away_domname, "%s--migratedaway", common_domname); > rc = libxl_domain_rename(ctx, domid, common_domname, away_domname); > @@ -316,7 +359,7 @@ static void migrate_domain(uint32_t domid, const char > *rune, int debug, > } > > static void migrate_receive(int debug, int daemonize, int monitor, > - int pause_after_migration, > + int pause_after_migration, int copy_local_disks, > int send_fd, int recv_fd, > libxl_checkpointed_stream checkpointed, > char *colo_proxy_script, > @@ -343,6 +386,7 @@ static void migrate_receive(int debug, int daemonize, int > monitor, > dom_info.daemonize = daemonize; > dom_info.monitor = monitor; > dom_info.paused = 1; > + dom_info.copy_local_disks = copy_local_disks; > dom_info.migrate_fd = recv_fd; > dom_info.send_back_fd = send_fd; > dom_info.migration_domname_r = &migration_domname; > @@ -423,6 +467,14 @@ static void migrate_receive(int debug, int daemonize, > int monitor, > > fprintf(stderr, "migration target: Got permission, starting domain.\n"); > > + fprintf(stderr, "Stopping NBD server\n"); > + rc = libxl__nbd_server_stop(ctx, domid); > + if (rc){ > + fprintf(stderr, "Failed to stop NBD server\n"); > + }else{ > + fprintf(stderr, "Stopped NBD server successfully\n"); > + } > + > if (migration_domname) { > rc = libxl_domain_rename(ctx, domid, migration_domname, > common_domname); > if (rc) goto perhaps_destroy_notify_rc; > @@ -478,6 +530,7 @@ static void migrate_receive(int debug, int daemonize, int > monitor, > int main_migrate_receive(int argc, char **argv) > { > int debug = 0, daemonize = 1, monitor = 1, pause_after_migration = 0; > + int copy_local_disks = 0; > libxl_checkpointed_stream checkpointed = LIBXL_CHECKPOINTED_STREAM_NONE; > int opt; > bool userspace_colo_proxy = false; > @@ -490,7 +543,7 @@ int main_migrate_receive(int argc, char **argv) > COMMON_LONG_OPTS > }; > > - SWITCH_FOREACH_OPT(opt, "Fedrp", opts, "migrate-receive", 0) { > + SWITCH_FOREACH_OPT(opt, "Fedrpl", opts, "migrate-receive", 0) { > case 'F': > daemonize = 0; > break; > @@ -516,6 +569,9 @@ int main_migrate_receive(int argc, char **argv) > case 'p': > pause_after_migration = 1; > break; > + case 'l': > + copy_local_disks = 1; > + break; > } > > if (argc-optind != 0) { > @@ -523,7 +579,7 @@ int main_migrate_receive(int argc, char **argv) > return EXIT_FAILURE; > } > migrate_receive(debug, daemonize, monitor, pause_after_migration, > - STDOUT_FILENO, STDIN_FILENO, > + copy_local_disks, STDOUT_FILENO, STDIN_FILENO, > checkpointed, script, userspace_colo_proxy); > > return EXIT_SUCCESS; > @@ -536,14 +592,16 @@ int main_migrate(int argc, char **argv) > const char *ssh_command = "ssh"; > char *rune = NULL; > char *host; > + char *hostname; > int opt, daemonize = 1, monitor = 1, debug = 0, pause_after_migration = > 0; > + int copy_local_disks = 0; > static struct option opts[] = { > {"debug", 0, 0, 0x100}, > {"live", 0, 0, 0x200}, > COMMON_LONG_OPTS > }; > > - SWITCH_FOREACH_OPT(opt, "FC:s:ep", opts, "migrate", 2) { > + SWITCH_FOREACH_OPT(opt, "FC:s:epl", opts, "migrate", 2) { > case 'C': > config_filename = optarg; > break; > @@ -560,6 +618,9 @@ int main_migrate(int argc, char **argv) > case 'p': > pause_after_migration = 1; > break; > + case 'l': > + copy_local_disks = 1; > + break; > case 0x100: /* --debug */ > debug = 1; > break; > @@ -571,6 +632,9 @@ int main_migrate(int argc, char **argv) > domid = find_domain(argv[optind]); > host = argv[optind + 1]; > > + hostname = strchr(host, '@'); > + hostname++; > + > bool pass_tty_arg = progress_use_cr || (isatty(2) > 0); > > if (!ssh_command[0]) { > @@ -587,16 +651,17 @@ int main_migrate(int argc, char **argv) > } else { > verbose_len = (minmsglevel_default - minmsglevel) + 2; > } > - xasprintf(&rune, "exec %s %s xl%s%.*s migrate-receive%s%s%s", > + xasprintf(&rune, "exec %s %s xl%s%.*s migrate-receive%s%s%s%s", > ssh_command, host, > pass_tty_arg ? " -t" : "", > verbose_len, verbose_buf, > daemonize ? "" : " -e", > debug ? " -d" : "", > + copy_local_disks ? " -l" : "", > pause_after_migration ? " -p" : ""); > } > > - migrate_domain(domid, rune, debug, config_filename); > + migrate_domain(domid, rune, debug, config_filename, copy_local_disks, > hostname); > return EXIT_SUCCESS; > } > > diff --git a/tools/xl/xl_vmcontrol.c b/tools/xl/xl_vmcontrol.c > index 89c2b25..5ffbfb7 100644 > --- a/tools/xl/xl_vmcontrol.c > +++ b/tools/xl/xl_vmcontrol.c > @@ -882,7 +882,7 @@ start: > > ret = libxl_domain_create_restore(ctx, &d_config, > &domid, restore_fd, > - send_back_fd, ¶ms, > + send_back_fd, > dom_info->copy_local_disks, ¶ms, > 0, autoconnect_console_how); > > libxl_domain_restore_params_dispose(¶ms); > -- > 2.7.4 > > > _______________________________________________ > Xen-devel mailing list > Xen-devel@xxxxxxxxxxxxx > https://lists.xen.org/xen-devel _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |