blob: 8280d7189aa4265d6b7204863d8d9d5c24d8820d [file] [log] [blame]
aliguori5bb79102008-10-13 03:12:02 +00001/*
2 * QEMU live migration
3 *
4 * Copyright IBM, Corp. 2008
5 *
6 * Authors:
7 * Anthony Liguori <aliguori@us.ibm.com>
8 *
9 * This work is licensed under the terms of the GNU GPL, version 2. See
10 * the COPYING file in the top-level directory.
11 *
12 */
13
14#include "qemu-common.h"
15#include "migration.h"
aliguori376253e2009-03-05 23:01:23 +000016#include "monitor.h"
aliguori065e2812008-11-11 16:46:33 +000017#include "buffered_file.h"
18#include "sysemu.h"
19#include "block.h"
20#include "qemu_socket.h"
Jan Kiszka25f23642009-11-30 18:21:21 +010021#include "block-migration.h"
Luiz Capitulino791e7c82011-09-13 17:37:16 -030022#include "qmp-commands.h"
aliguori065e2812008-11-11 16:46:33 +000023
24//#define DEBUG_MIGRATION
25
26#ifdef DEBUG_MIGRATION
malcd0f2c4c2010-02-07 02:03:50 +030027#define DPRINTF(fmt, ...) \
aliguori065e2812008-11-11 16:46:33 +000028 do { printf("migration: " fmt, ## __VA_ARGS__); } while (0)
29#else
malcd0f2c4c2010-02-07 02:03:50 +030030#define DPRINTF(fmt, ...) \
aliguori065e2812008-11-11 16:46:33 +000031 do { } while (0)
32#endif
aliguori5bb79102008-10-13 03:12:02 +000033
Juan Quintela7dc688e2011-02-23 00:48:46 +010034enum {
35 MIG_STATE_ERROR,
36 MIG_STATE_SETUP,
37 MIG_STATE_CANCELLED,
38 MIG_STATE_ACTIVE,
39 MIG_STATE_COMPLETED,
40};
aliguori5bb79102008-10-13 03:12:02 +000041
Juan Quintelad0ae46c2011-02-23 00:33:19 +010042#define MAX_THROTTLE (32 << 20) /* Migration speed throttling */
aliguori5bb79102008-10-13 03:12:02 +000043
Gerd Hoffmann99a0db92010-12-13 17:30:12 +010044static NotifierList migration_state_notifiers =
45 NOTIFIER_LIST_INITIALIZER(migration_state_notifiers);
46
Juan Quintela17549e82011-10-05 13:50:43 +020047/* When we add fault tolerance, we could have several
48 migrations at once. For now we don't need to add
49 dynamic creation of migration */
50
51static MigrationState *migrate_get_current(void)
52{
53 static MigrationState current_migration = {
54 .state = MIG_STATE_SETUP,
Juan Quintelad0ae46c2011-02-23 00:33:19 +010055 .bandwidth_limit = MAX_THROTTLE,
Juan Quintela17549e82011-10-05 13:50:43 +020056 };
57
58 return &current_migration;
59}
60
Juan Quintela8ca5e802010-06-09 14:10:54 +020061int qemu_start_incoming_migration(const char *uri)
aliguori5bb79102008-10-13 03:12:02 +000062{
aliguori34c9dd82008-10-13 03:14:31 +000063 const char *p;
Juan Quintela8ca5e802010-06-09 14:10:54 +020064 int ret;
aliguori34c9dd82008-10-13 03:14:31 +000065
66 if (strstart(uri, "tcp:", &p))
Juan Quintela8ca5e802010-06-09 14:10:54 +020067 ret = tcp_start_incoming_migration(p);
aliguori065e2812008-11-11 16:46:33 +000068#if !defined(WIN32)
69 else if (strstart(uri, "exec:", &p))
Juan Quintela8ca5e802010-06-09 14:10:54 +020070 ret = exec_start_incoming_migration(p);
Chris Lalancette4951f652009-08-05 17:24:29 +020071 else if (strstart(uri, "unix:", &p))
Juan Quintela8ca5e802010-06-09 14:10:54 +020072 ret = unix_start_incoming_migration(p);
Paolo Bonzini5ac1fad2009-08-18 15:56:25 +020073 else if (strstart(uri, "fd:", &p))
Juan Quintela8ca5e802010-06-09 14:10:54 +020074 ret = fd_start_incoming_migration(p);
aliguori065e2812008-11-11 16:46:33 +000075#endif
Juan Quintela8ca5e802010-06-09 14:10:54 +020076 else {
aliguori34c9dd82008-10-13 03:14:31 +000077 fprintf(stderr, "unknown migration protocol: %s\n", uri);
Juan Quintela8ca5e802010-06-09 14:10:54 +020078 ret = -EPROTONOSUPPORT;
79 }
80 return ret;
aliguori5bb79102008-10-13 03:12:02 +000081}
82
Juan Quintela511c0232010-06-09 14:10:55 +020083void process_incoming_migration(QEMUFile *f)
84{
85 if (qemu_loadvm_state(f) < 0) {
86 fprintf(stderr, "load of migration failed\n");
87 exit(0);
88 }
89 qemu_announce_self();
90 DPRINTF("successfully loaded vm state\n");
91
Anthony Liguori0f154232011-11-14 15:09:45 -060092 /* Make sure all file formats flush their mutable metadata */
93 bdrv_invalidate_cache_all();
94
Luiz Capitulinof5bbfba2011-07-29 15:04:45 -030095 if (autostart) {
Juan Quintela511c0232010-06-09 14:10:55 +020096 vm_start();
Luiz Capitulinof5bbfba2011-07-29 15:04:45 -030097 } else {
Luiz Capitulino0461d5a2011-09-30 14:45:27 -030098 runstate_set(RUN_STATE_PRELAUNCH);
Luiz Capitulinof5bbfba2011-07-29 15:04:45 -030099 }
Juan Quintela511c0232010-06-09 14:10:55 +0200100}
101
Glauber Costaa0a3fd62009-05-28 15:22:57 -0400102/* amount of nanoseconds we are willing to wait for migration to be down.
103 * the choice of nanoseconds is because it is the maximum resolution that
104 * get_clock() can achieve. It is an internal measure. All user-visible
105 * units must be in seconds */
106static uint64_t max_downtime = 30000000;
107
108uint64_t migrate_max_downtime(void)
109{
110 return max_downtime;
111}
112
Luiz Capitulino791e7c82011-09-13 17:37:16 -0300113MigrationInfo *qmp_query_migrate(Error **errp)
aliguori5bb79102008-10-13 03:12:02 +0000114{
Luiz Capitulino791e7c82011-09-13 17:37:16 -0300115 MigrationInfo *info = g_malloc0(sizeof(*info));
Juan Quintela17549e82011-10-05 13:50:43 +0200116 MigrationState *s = migrate_get_current();
aliguori376253e2009-03-05 23:01:23 +0000117
Juan Quintela17549e82011-10-05 13:50:43 +0200118 switch (s->state) {
119 case MIG_STATE_SETUP:
120 /* no migration has happened ever */
121 break;
122 case MIG_STATE_ACTIVE:
Luiz Capitulino791e7c82011-09-13 17:37:16 -0300123 info->has_status = true;
124 info->status = g_strdup("active");
Luiz Capitulinoc86a6682009-12-10 17:16:05 -0200125
Luiz Capitulino791e7c82011-09-13 17:37:16 -0300126 info->has_ram = true;
127 info->ram = g_malloc0(sizeof(*info->ram));
128 info->ram->transferred = ram_bytes_transferred();
129 info->ram->remaining = ram_bytes_remaining();
130 info->ram->total = ram_bytes_total();
Luiz Capitulinoc86a6682009-12-10 17:16:05 -0200131
Juan Quintela17549e82011-10-05 13:50:43 +0200132 if (blk_mig_active()) {
Luiz Capitulino791e7c82011-09-13 17:37:16 -0300133 info->has_disk = true;
134 info->disk = g_malloc0(sizeof(*info->disk));
135 info->disk->transferred = blk_mig_bytes_transferred();
136 info->disk->remaining = blk_mig_bytes_remaining();
137 info->disk->total = blk_mig_bytes_total();
aliguoriff8d81d2008-10-24 22:10:31 +0000138 }
Juan Quintela17549e82011-10-05 13:50:43 +0200139 break;
140 case MIG_STATE_COMPLETED:
Luiz Capitulino791e7c82011-09-13 17:37:16 -0300141 info->has_status = true;
142 info->status = g_strdup("completed");
Juan Quintela17549e82011-10-05 13:50:43 +0200143 break;
144 case MIG_STATE_ERROR:
Luiz Capitulino791e7c82011-09-13 17:37:16 -0300145 info->has_status = true;
146 info->status = g_strdup("failed");
Juan Quintela17549e82011-10-05 13:50:43 +0200147 break;
148 case MIG_STATE_CANCELLED:
Luiz Capitulino791e7c82011-09-13 17:37:16 -0300149 info->has_status = true;
150 info->status = g_strdup("cancelled");
Juan Quintela17549e82011-10-05 13:50:43 +0200151 break;
aliguori5bb79102008-10-13 03:12:02 +0000152 }
Luiz Capitulino791e7c82011-09-13 17:37:16 -0300153
154 return info;
aliguori5bb79102008-10-13 03:12:02 +0000155}
156
aliguori065e2812008-11-11 16:46:33 +0000157/* shared migration helpers */
158
Juan Quintela0edda1c2010-05-11 16:28:39 +0200159static void migrate_fd_monitor_suspend(MigrationState *s, Monitor *mon)
aliguori731b0362009-03-05 23:01:42 +0000160{
Jan Kiszkaf327aa02009-11-30 18:21:21 +0100161 if (monitor_suspend(mon) == 0) {
malcd0f2c4c2010-02-07 02:03:50 +0300162 DPRINTF("suspending monitor\n");
Jan Kiszkaf327aa02009-11-30 18:21:21 +0100163 } else {
164 monitor_printf(mon, "terminal does not allow synchronous "
aliguoricde76ee2009-03-05 23:01:51 +0000165 "migration, continuing detached\n");
Jan Kiszkaf327aa02009-11-30 18:21:21 +0100166 }
aliguori731b0362009-03-05 23:01:42 +0000167}
168
Juan Quintela8b6b99b2011-09-11 20:28:22 +0200169static int migrate_fd_cleanup(MigrationState *s)
aliguori065e2812008-11-11 16:46:33 +0000170{
Anthony Liguori41ef56e2010-06-02 14:55:25 -0500171 int ret = 0;
172
aliguori065e2812008-11-11 16:46:33 +0000173 qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
174
175 if (s->file) {
malcd0f2c4c2010-02-07 02:03:50 +0300176 DPRINTF("closing file\n");
Anthony Liguori41ef56e2010-06-02 14:55:25 -0500177 if (qemu_fclose(s->file) != 0) {
178 ret = -1;
179 }
Jan Kiszka5d39c792009-11-30 18:21:19 +0100180 s->file = NULL;
Jan Kiszka84ec6552011-08-05 09:11:26 +0200181 } else {
182 if (s->mon) {
183 monitor_resume(s->mon);
184 }
aliguori065e2812008-11-11 16:46:33 +0000185 }
186
Jan Kiszka84ec6552011-08-05 09:11:26 +0200187 if (s->fd != -1) {
aliguori065e2812008-11-11 16:46:33 +0000188 close(s->fd);
Jan Kiszka84ec6552011-08-05 09:11:26 +0200189 s->fd = -1;
Jan Kiszkaf327aa02009-11-30 18:21:21 +0100190 }
aliguori065e2812008-11-11 16:46:33 +0000191
Anthony Liguori41ef56e2010-06-02 14:55:25 -0500192 return ret;
aliguori065e2812008-11-11 16:46:33 +0000193}
194
Juan Quintela8b6b99b2011-09-11 20:28:22 +0200195void migrate_fd_error(MigrationState *s)
aliguori065e2812008-11-11 16:46:33 +0000196{
Juan Quintela8b6b99b2011-09-11 20:28:22 +0200197 DPRINTF("setting error state\n");
198 s->state = MIG_STATE_ERROR;
Juan Quintelae0eb7392011-10-05 14:27:52 +0200199 notifier_list_notify(&migration_state_notifiers, s);
Juan Quintela8b6b99b2011-09-11 20:28:22 +0200200 migrate_fd_cleanup(s);
201}
202
Juan Quintela458cf282011-02-22 23:32:54 +0100203static void migrate_fd_completed(MigrationState *s)
204{
205 DPRINTF("setting completed state\n");
206 if (migrate_fd_cleanup(s) < 0) {
207 s->state = MIG_STATE_ERROR;
208 } else {
209 s->state = MIG_STATE_COMPLETED;
210 runstate_set(RUN_STATE_POSTMIGRATE);
211 }
Juan Quintelae0eb7392011-10-05 14:27:52 +0200212 notifier_list_notify(&migration_state_notifiers, s);
Juan Quintela458cf282011-02-22 23:32:54 +0100213}
214
Juan Quintela8b6b99b2011-09-11 20:28:22 +0200215static void migrate_fd_put_notify(void *opaque)
aliguori065e2812008-11-11 16:46:33 +0000216{
Juan Quintela22f00a42010-05-11 15:56:35 +0200217 MigrationState *s = opaque;
aliguori065e2812008-11-11 16:46:33 +0000218
219 qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
220 qemu_file_put_notify(s->file);
Luiz Capitulino1fdc11c2011-10-28 14:59:52 -0200221 if (s->file && qemu_file_get_error(s->file)) {
Yoshiaki Tamura2350e132011-02-23 00:01:24 +0900222 migrate_fd_error(s);
223 }
aliguori065e2812008-11-11 16:46:33 +0000224}
225
Juan Quintela8b6b99b2011-09-11 20:28:22 +0200226static ssize_t migrate_fd_put_buffer(void *opaque, const void *data,
227 size_t size)
aliguori065e2812008-11-11 16:46:33 +0000228{
Juan Quintela22f00a42010-05-11 15:56:35 +0200229 MigrationState *s = opaque;
aliguori065e2812008-11-11 16:46:33 +0000230 ssize_t ret;
231
Juan Quintelafdbecb52011-09-21 22:37:29 +0200232 if (s->state != MIG_STATE_ACTIVE) {
233 return -EIO;
234 }
235
aliguori065e2812008-11-11 16:46:33 +0000236 do {
237 ret = s->write(s, data, size);
Uri Lublin95b134e2009-05-19 14:08:53 +0300238 } while (ret == -1 && ((s->get_error(s)) == EINTR));
aliguori065e2812008-11-11 16:46:33 +0000239
240 if (ret == -1)
241 ret = -(s->get_error(s));
242
Marcelo Tosattie447b1a2010-08-19 10:18:39 -0300243 if (ret == -EAGAIN) {
aliguori065e2812008-11-11 16:46:33 +0000244 qemu_set_fd_handler2(s->fd, NULL, NULL, migrate_fd_put_notify, s);
Marcelo Tosattie447b1a2010-08-19 10:18:39 -0300245 }
aliguori065e2812008-11-11 16:46:33 +0000246
247 return ret;
248}
249
Juan Quintela8b6b99b2011-09-11 20:28:22 +0200250static void migrate_fd_put_ready(void *opaque)
aliguori065e2812008-11-11 16:46:33 +0000251{
Juan Quintela22f00a42010-05-11 15:56:35 +0200252 MigrationState *s = opaque;
aliguori065e2812008-11-11 16:46:33 +0000253 int ret;
254
aliguori065e2812008-11-11 16:46:33 +0000255 if (s->state != MIG_STATE_ACTIVE) {
malcd0f2c4c2010-02-07 02:03:50 +0300256 DPRINTF("put_ready returning because of non-active state\n");
aliguori065e2812008-11-11 16:46:33 +0000257 return;
258 }
259
malcd0f2c4c2010-02-07 02:03:50 +0300260 DPRINTF("iterate\n");
Juan Quintela39346382011-09-22 11:02:14 +0200261 ret = qemu_savevm_state_iterate(s->mon, s->file);
262 if (ret < 0) {
263 migrate_fd_error(s);
264 } else if (ret == 1) {
Luiz Capitulino13548692011-07-29 15:36:43 -0300265 int old_vm_running = runstate_is_running();
Anthony Liguorieeb34af2009-07-09 13:25:47 -0500266
malcd0f2c4c2010-02-07 02:03:50 +0300267 DPRINTF("done iterating\n");
Luiz Capitulino8a9236f2011-10-14 11:18:09 -0300268 vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
aliguori065e2812008-11-11 16:46:33 +0000269
Juan Quintela67afff72011-02-22 23:18:20 +0100270 if (qemu_savevm_state_complete(s->mon, s->file) < 0) {
271 migrate_fd_error(s);
aliguorib161d122009-04-05 19:30:33 +0000272 } else {
Juan Quintela458cf282011-02-22 23:32:54 +0100273 migrate_fd_completed(s);
aliguorib161d122009-04-05 19:30:33 +0000274 }
Juan Quintela48a2f4d2010-05-11 23:28:53 +0200275 if (s->state != MIG_STATE_COMPLETED) {
Anthony Liguori41ef56e2010-06-02 14:55:25 -0500276 if (old_vm_running) {
277 vm_start();
278 }
Anthony Liguori41ef56e2010-06-02 14:55:25 -0500279 }
aliguori065e2812008-11-11 16:46:33 +0000280 }
281}
282
Juan Quintela0edda1c2010-05-11 16:28:39 +0200283static void migrate_fd_cancel(MigrationState *s)
aliguori065e2812008-11-11 16:46:33 +0000284{
aliguori065e2812008-11-11 16:46:33 +0000285 if (s->state != MIG_STATE_ACTIVE)
286 return;
287
malcd0f2c4c2010-02-07 02:03:50 +0300288 DPRINTF("cancelling migration\n");
aliguori065e2812008-11-11 16:46:33 +0000289
290 s->state = MIG_STATE_CANCELLED;
Juan Quintelae0eb7392011-10-05 14:27:52 +0200291 notifier_list_notify(&migration_state_notifiers, s);
Jan Kiszkaf327aa02009-11-30 18:21:21 +0100292 qemu_savevm_state_cancel(s->mon, s->file);
aliguori065e2812008-11-11 16:46:33 +0000293
294 migrate_fd_cleanup(s);
295}
296
Juan Quintela8b6b99b2011-09-11 20:28:22 +0200297static void migrate_fd_wait_for_unfreeze(void *opaque)
aliguori065e2812008-11-11 16:46:33 +0000298{
Juan Quintela22f00a42010-05-11 15:56:35 +0200299 MigrationState *s = opaque;
aliguori065e2812008-11-11 16:46:33 +0000300 int ret;
301
malcd0f2c4c2010-02-07 02:03:50 +0300302 DPRINTF("wait for unfreeze\n");
aliguori065e2812008-11-11 16:46:33 +0000303 if (s->state != MIG_STATE_ACTIVE)
304 return;
305
306 do {
307 fd_set wfds;
308
309 FD_ZERO(&wfds);
310 FD_SET(s->fd, &wfds);
311
312 ret = select(s->fd + 1, NULL, &wfds, NULL, NULL);
313 } while (ret == -1 && (s->get_error(s)) == EINTR);
Juan Quintelaaf509452011-09-21 22:46:36 +0200314
315 if (ret == -1) {
Juan Quinteladcd1d222011-09-21 23:01:54 +0200316 qemu_file_set_error(s->file, -s->get_error(s));
Juan Quintelaaf509452011-09-21 22:46:36 +0200317 }
aliguori065e2812008-11-11 16:46:33 +0000318}
319
Juan Quintela8b6b99b2011-09-11 20:28:22 +0200320static int migrate_fd_close(void *opaque)
aliguori065e2812008-11-11 16:46:33 +0000321{
Juan Quintela22f00a42010-05-11 15:56:35 +0200322 MigrationState *s = opaque;
Uri Lubline19252d2009-06-08 14:28:01 +0300323
Jan Kiszka84ec6552011-08-05 09:11:26 +0200324 if (s->mon) {
325 monitor_resume(s->mon);
326 }
Uri Lubline19252d2009-06-08 14:28:01 +0300327 qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
aliguori065e2812008-11-11 16:46:33 +0000328 return s->close(s);
329}
Gerd Hoffmann99a0db92010-12-13 17:30:12 +0100330
331void add_migration_state_change_notifier(Notifier *notify)
332{
333 notifier_list_add(&migration_state_notifiers, notify);
334}
335
336void remove_migration_state_change_notifier(Notifier *notify)
337{
338 notifier_list_remove(&migration_state_notifiers, notify);
339}
340
Gerd Hoffmannafe2df62011-10-25 13:50:11 +0200341bool migration_is_active(MigrationState *s)
342{
343 return s->state == MIG_STATE_ACTIVE;
344}
345
Juan Quintela70736932011-02-23 00:43:59 +0100346bool migration_has_finished(MigrationState *s)
Gerd Hoffmann99a0db92010-12-13 17:30:12 +0100347{
Juan Quintela70736932011-02-23 00:43:59 +0100348 return s->state == MIG_STATE_COMPLETED;
Gerd Hoffmann99a0db92010-12-13 17:30:12 +0100349}
Juan Quintela0edda1c2010-05-11 16:28:39 +0200350
Gerd Hoffmannafe2df62011-10-25 13:50:11 +0200351bool migration_has_failed(MigrationState *s)
352{
353 return (s->state == MIG_STATE_CANCELLED ||
354 s->state == MIG_STATE_ERROR);
355}
356
Juan Quintela8b6b99b2011-09-11 20:28:22 +0200357void migrate_fd_connect(MigrationState *s)
358{
359 int ret;
360
Juan Quintelad5934dd2010-05-11 23:01:53 +0200361 s->state = MIG_STATE_ACTIVE;
Juan Quintela8b6b99b2011-09-11 20:28:22 +0200362 s->file = qemu_fopen_ops_buffered(s,
363 s->bandwidth_limit,
364 migrate_fd_put_buffer,
365 migrate_fd_put_ready,
366 migrate_fd_wait_for_unfreeze,
367 migrate_fd_close);
368
369 DPRINTF("beginning savevm\n");
370 ret = qemu_savevm_state_begin(s->mon, s->file, s->blk, s->shared);
371 if (ret < 0) {
372 DPRINTF("failed, %d\n", ret);
373 migrate_fd_error(s);
374 return;
aliguori5bb79102008-10-13 03:12:02 +0000375 }
Juan Quintela8b6b99b2011-09-11 20:28:22 +0200376 migrate_fd_put_ready(s);
377}
378
Juan Quintelad0ae46c2011-02-23 00:33:19 +0100379static MigrationState *migrate_init(Monitor *mon, int detach, int blk, int inc)
Juan Quintela0edda1c2010-05-11 16:28:39 +0200380{
Juan Quintela17549e82011-10-05 13:50:43 +0200381 MigrationState *s = migrate_get_current();
Juan Quintelad0ae46c2011-02-23 00:33:19 +0100382 int64_t bandwidth_limit = s->bandwidth_limit;
Juan Quintela0edda1c2010-05-11 16:28:39 +0200383
Juan Quintela17549e82011-10-05 13:50:43 +0200384 memset(s, 0, sizeof(*s));
Juan Quintelad0ae46c2011-02-23 00:33:19 +0100385 s->bandwidth_limit = bandwidth_limit;
Juan Quintela0edda1c2010-05-11 16:28:39 +0200386 s->blk = blk;
387 s->shared = inc;
Juan Quintela1299c632011-11-09 21:29:01 +0100388
389 /* s->mon is used for two things:
390 - pass fd in fd migration
391 - suspend/resume monitor for not detached migration
392 */
393 s->mon = mon;
Juan Quintela0edda1c2010-05-11 16:28:39 +0200394 s->bandwidth_limit = bandwidth_limit;
Juan Quintelad5934dd2010-05-11 23:01:53 +0200395 s->state = MIG_STATE_SETUP;
Juan Quintela0edda1c2010-05-11 16:28:39 +0200396
397 if (!detach) {
398 migrate_fd_monitor_suspend(s, mon);
399 }
400
401 return s;
402}
Juan Quintelacab30142011-02-22 23:54:21 +0100403
Anthony Liguorifa2756b2011-11-14 15:09:43 -0600404static GSList *migration_blockers;
405
406void migrate_add_blocker(Error *reason)
407{
408 migration_blockers = g_slist_prepend(migration_blockers, reason);
409}
410
411void migrate_del_blocker(Error *reason)
412{
413 migration_blockers = g_slist_remove(migration_blockers, reason);
414}
415
Juan Quintelacab30142011-02-22 23:54:21 +0100416int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
417{
Juan Quintela17549e82011-10-05 13:50:43 +0200418 MigrationState *s = migrate_get_current();
Juan Quintelacab30142011-02-22 23:54:21 +0100419 const char *p;
420 int detach = qdict_get_try_bool(qdict, "detach", 0);
421 int blk = qdict_get_try_bool(qdict, "blk", 0);
422 int inc = qdict_get_try_bool(qdict, "inc", 0);
423 const char *uri = qdict_get_str(qdict, "uri");
424 int ret;
425
Juan Quintela17549e82011-10-05 13:50:43 +0200426 if (s->state == MIG_STATE_ACTIVE) {
Juan Quintelacab30142011-02-22 23:54:21 +0100427 monitor_printf(mon, "migration already in progress\n");
428 return -1;
429 }
430
431 if (qemu_savevm_state_blocked(mon)) {
432 return -1;
433 }
434
Anthony Liguorifa2756b2011-11-14 15:09:43 -0600435 if (migration_blockers) {
436 Error *err = migration_blockers->data;
437 qerror_report_err(err);
438 return -1;
439 }
440
Juan Quintelad0ae46c2011-02-23 00:33:19 +0100441 s = migrate_init(mon, detach, blk, inc);
Juan Quintelacab30142011-02-22 23:54:21 +0100442
443 if (strstart(uri, "tcp:", &p)) {
444 ret = tcp_start_outgoing_migration(s, p);
445#if !defined(WIN32)
446 } else if (strstart(uri, "exec:", &p)) {
447 ret = exec_start_outgoing_migration(s, p);
448 } else if (strstart(uri, "unix:", &p)) {
449 ret = unix_start_outgoing_migration(s, p);
450 } else if (strstart(uri, "fd:", &p)) {
451 ret = fd_start_outgoing_migration(s, p);
452#endif
453 } else {
454 monitor_printf(mon, "unknown migration protocol: %s\n", uri);
455 ret = -EINVAL;
Juan Quintelacab30142011-02-22 23:54:21 +0100456 }
457
458 if (ret < 0) {
Juan Quintela17549e82011-10-05 13:50:43 +0200459 monitor_printf(mon, "migration failed: %s\n", strerror(-ret));
460 return ret;
Juan Quintelacab30142011-02-22 23:54:21 +0100461 }
462
Juan Quintela1299c632011-11-09 21:29:01 +0100463 if (detach) {
464 s->mon = NULL;
465 }
466
Juan Quintelae0eb7392011-10-05 14:27:52 +0200467 notifier_list_notify(&migration_state_notifiers, s);
Juan Quintelacab30142011-02-22 23:54:21 +0100468 return 0;
Juan Quintelacab30142011-02-22 23:54:21 +0100469}
470
471int do_migrate_cancel(Monitor *mon, const QDict *qdict, QObject **ret_data)
472{
Juan Quintela17549e82011-10-05 13:50:43 +0200473 migrate_fd_cancel(migrate_get_current());
Juan Quintelacab30142011-02-22 23:54:21 +0100474 return 0;
475}
476
477int do_migrate_set_speed(Monitor *mon, const QDict *qdict, QObject **ret_data)
478{
479 int64_t d;
480 MigrationState *s;
481
482 d = qdict_get_int(qdict, "value");
483 if (d < 0) {
484 d = 0;
485 }
Juan Quintelacab30142011-02-22 23:54:21 +0100486
Juan Quintela17549e82011-10-05 13:50:43 +0200487 s = migrate_get_current();
Juan Quintelad0ae46c2011-02-23 00:33:19 +0100488 s->bandwidth_limit = d;
489 qemu_file_set_rate_limit(s->file, s->bandwidth_limit);
Juan Quintelacab30142011-02-22 23:54:21 +0100490
491 return 0;
492}
493
494int do_migrate_set_downtime(Monitor *mon, const QDict *qdict,
495 QObject **ret_data)
496{
497 double d;
498
499 d = qdict_get_double(qdict, "value") * 1e9;
500 d = MAX(0, MIN(UINT64_MAX, d));
501 max_downtime = (uint64_t)d;
502
503 return 0;
aliguori5bb79102008-10-13 03:12:02 +0000504}