]> Git Repo - qemu.git/blob - migration.c
Monitor: handle optional '-' arg as a bool
[qemu.git] / migration.c
1 /*
2  * QEMU live migration
3  *
4  * Copyright IBM, Corp. 2008
5  *
6  * Authors:
7  *  Anthony Liguori   <[email protected]>
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"
16 #include "monitor.h"
17 #include "buffered_file.h"
18 #include "sysemu.h"
19 #include "block.h"
20 #include "qemu_socket.h"
21 #include "block-migration.h"
22 #include "qemu-objects.h"
23
24 //#define DEBUG_MIGRATION
25
26 #ifdef DEBUG_MIGRATION
27 #define DPRINTF(fmt, ...) \
28     do { printf("migration: " fmt, ## __VA_ARGS__); } while (0)
29 #else
30 #define DPRINTF(fmt, ...) \
31     do { } while (0)
32 #endif
33
34 /* Migration speed throttling */
35 static uint32_t max_throttle = (32 << 20);
36
37 static MigrationState *current_migration;
38
39 int qemu_start_incoming_migration(const char *uri)
40 {
41     const char *p;
42     int ret;
43
44     if (strstart(uri, "tcp:", &p))
45         ret = tcp_start_incoming_migration(p);
46 #if !defined(WIN32)
47     else if (strstart(uri, "exec:", &p))
48         ret =  exec_start_incoming_migration(p);
49     else if (strstart(uri, "unix:", &p))
50         ret = unix_start_incoming_migration(p);
51     else if (strstart(uri, "fd:", &p))
52         ret = fd_start_incoming_migration(p);
53 #endif
54     else {
55         fprintf(stderr, "unknown migration protocol: %s\n", uri);
56         ret = -EPROTONOSUPPORT;
57     }
58     return ret;
59 }
60
61 void process_incoming_migration(QEMUFile *f)
62 {
63     if (qemu_loadvm_state(f) < 0) {
64         fprintf(stderr, "load of migration failed\n");
65         exit(0);
66     }
67     qemu_announce_self();
68     DPRINTF("successfully loaded vm state\n");
69
70     if (autostart)
71         vm_start();
72 }
73
74 int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
75 {
76     MigrationState *s = NULL;
77     const char *p;
78     int detach = qdict_get_try_bool(qdict, "detach", 0);
79     int blk = qdict_get_try_bool(qdict, "blk", 0);
80     int inc = qdict_get_try_bool(qdict, "inc", 0);
81     const char *uri = qdict_get_str(qdict, "uri");
82
83     if (current_migration &&
84         current_migration->get_status(current_migration) == MIG_STATE_ACTIVE) {
85         monitor_printf(mon, "migration already in progress\n");
86         return -1;
87     }
88
89     if (strstart(uri, "tcp:", &p)) {
90         s = tcp_start_outgoing_migration(mon, p, max_throttle, detach,
91                                          blk, inc);
92 #if !defined(WIN32)
93     } else if (strstart(uri, "exec:", &p)) {
94         s = exec_start_outgoing_migration(mon, p, max_throttle, detach,
95                                           blk, inc);
96     } else if (strstart(uri, "unix:", &p)) {
97         s = unix_start_outgoing_migration(mon, p, max_throttle, detach,
98                                           blk, inc);
99     } else if (strstart(uri, "fd:", &p)) {
100         s = fd_start_outgoing_migration(mon, p, max_throttle, detach, 
101                                         blk, inc);
102 #endif
103     } else {
104         monitor_printf(mon, "unknown migration protocol: %s\n", uri);
105         return -1;
106     }
107
108     if (s == NULL) {
109         monitor_printf(mon, "migration failed\n");
110         return -1;
111     }
112
113     if (current_migration) {
114         current_migration->release(current_migration);
115     }
116
117     current_migration = s;
118     return 0;
119 }
120
121 int do_migrate_cancel(Monitor *mon, const QDict *qdict, QObject **ret_data)
122 {
123     MigrationState *s = current_migration;
124
125     if (s)
126         s->cancel(s);
127
128     return 0;
129 }
130
131 int do_migrate_set_speed(Monitor *mon, const QDict *qdict, QObject **ret_data)
132 {
133     double d;
134     FdMigrationState *s;
135
136     d = qdict_get_double(qdict, "value");
137     d = MAX(0, MIN(UINT32_MAX, d));
138     max_throttle = d;
139
140     s = migrate_to_fms(current_migration);
141     if (s && s->file) {
142         qemu_file_set_rate_limit(s->file, max_throttle);
143     }
144
145     return 0;
146 }
147
148 /* amount of nanoseconds we are willing to wait for migration to be down.
149  * the choice of nanoseconds is because it is the maximum resolution that
150  * get_clock() can achieve. It is an internal measure. All user-visible
151  * units must be in seconds */
152 static uint64_t max_downtime = 30000000;
153
154 uint64_t migrate_max_downtime(void)
155 {
156     return max_downtime;
157 }
158
159 int do_migrate_set_downtime(Monitor *mon, const QDict *qdict,
160                             QObject **ret_data)
161 {
162     double d;
163
164     d = qdict_get_double(qdict, "value") * 1e9;
165     d = MAX(0, MIN(UINT64_MAX, d));
166     max_downtime = (uint64_t)d;
167
168     return 0;
169 }
170
171 static void migrate_print_status(Monitor *mon, const char *name,
172                                  const QDict *status_dict)
173 {
174     QDict *qdict;
175
176     qdict = qobject_to_qdict(qdict_get(status_dict, name));
177
178     monitor_printf(mon, "transferred %s: %" PRIu64 " kbytes\n", name,
179                         qdict_get_int(qdict, "transferred") >> 10);
180     monitor_printf(mon, "remaining %s: %" PRIu64 " kbytes\n", name,
181                         qdict_get_int(qdict, "remaining") >> 10);
182     monitor_printf(mon, "total %s: %" PRIu64 " kbytes\n", name,
183                         qdict_get_int(qdict, "total") >> 10);
184 }
185
186 void do_info_migrate_print(Monitor *mon, const QObject *data)
187 {
188     QDict *qdict;
189
190     qdict = qobject_to_qdict(data);
191
192     monitor_printf(mon, "Migration status: %s\n",
193                    qdict_get_str(qdict, "status"));
194
195     if (qdict_haskey(qdict, "ram")) {
196         migrate_print_status(mon, "ram", qdict);
197     }
198
199     if (qdict_haskey(qdict, "disk")) {
200         migrate_print_status(mon, "disk", qdict);
201     }
202 }
203
204 static void migrate_put_status(QDict *qdict, const char *name,
205                                uint64_t trans, uint64_t rem, uint64_t total)
206 {
207     QObject *obj;
208
209     obj = qobject_from_jsonf("{ 'transferred': %" PRId64 ", "
210                                "'remaining': %" PRId64 ", "
211                                "'total': %" PRId64 " }", trans, rem, total);
212     qdict_put_obj(qdict, name, obj);
213 }
214
215 void do_info_migrate(Monitor *mon, QObject **ret_data)
216 {
217     QDict *qdict;
218     MigrationState *s = current_migration;
219
220     if (s) {
221         switch (s->get_status(s)) {
222         case MIG_STATE_ACTIVE:
223             qdict = qdict_new();
224             qdict_put(qdict, "status", qstring_from_str("active"));
225
226             migrate_put_status(qdict, "ram", ram_bytes_transferred(),
227                                ram_bytes_remaining(), ram_bytes_total());
228
229             if (blk_mig_active()) {
230                 migrate_put_status(qdict, "disk", blk_mig_bytes_transferred(),
231                                    blk_mig_bytes_remaining(),
232                                    blk_mig_bytes_total());
233             }
234
235             *ret_data = QOBJECT(qdict);
236             break;
237         case MIG_STATE_COMPLETED:
238             *ret_data = qobject_from_jsonf("{ 'status': 'completed' }");
239             break;
240         case MIG_STATE_ERROR:
241             *ret_data = qobject_from_jsonf("{ 'status': 'failed' }");
242             break;
243         case MIG_STATE_CANCELLED:
244             *ret_data = qobject_from_jsonf("{ 'status': 'cancelled' }");
245             break;
246         }
247     }
248 }
249
250 /* shared migration helpers */
251
252 void migrate_fd_monitor_suspend(FdMigrationState *s, Monitor *mon)
253 {
254     s->mon = mon;
255     if (monitor_suspend(mon) == 0) {
256         DPRINTF("suspending monitor\n");
257     } else {
258         monitor_printf(mon, "terminal does not allow synchronous "
259                        "migration, continuing detached\n");
260     }
261 }
262
263 void migrate_fd_error(FdMigrationState *s)
264 {
265     DPRINTF("setting error state\n");
266     s->state = MIG_STATE_ERROR;
267     migrate_fd_cleanup(s);
268 }
269
270 int migrate_fd_cleanup(FdMigrationState *s)
271 {
272     int ret = 0;
273
274     qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
275
276     if (s->file) {
277         DPRINTF("closing file\n");
278         if (qemu_fclose(s->file) != 0) {
279             ret = -1;
280         }
281         s->file = NULL;
282     }
283
284     if (s->fd != -1)
285         close(s->fd);
286
287     /* Don't resume monitor until we've flushed all of the buffers */
288     if (s->mon) {
289         monitor_resume(s->mon);
290     }
291
292     s->fd = -1;
293
294     return ret;
295 }
296
297 void migrate_fd_put_notify(void *opaque)
298 {
299     FdMigrationState *s = opaque;
300
301     qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
302     qemu_file_put_notify(s->file);
303 }
304
305 ssize_t migrate_fd_put_buffer(void *opaque, const void *data, size_t size)
306 {
307     FdMigrationState *s = opaque;
308     ssize_t ret;
309
310     do {
311         ret = s->write(s, data, size);
312     } while (ret == -1 && ((s->get_error(s)) == EINTR));
313
314     if (ret == -1)
315         ret = -(s->get_error(s));
316
317     if (ret == -EAGAIN)
318         qemu_set_fd_handler2(s->fd, NULL, NULL, migrate_fd_put_notify, s);
319
320     return ret;
321 }
322
323 void migrate_fd_connect(FdMigrationState *s)
324 {
325     int ret;
326
327     s->file = qemu_fopen_ops_buffered(s,
328                                       s->bandwidth_limit,
329                                       migrate_fd_put_buffer,
330                                       migrate_fd_put_ready,
331                                       migrate_fd_wait_for_unfreeze,
332                                       migrate_fd_close);
333
334     DPRINTF("beginning savevm\n");
335     ret = qemu_savevm_state_begin(s->mon, s->file, s->mig_state.blk,
336                                   s->mig_state.shared);
337     if (ret < 0) {
338         DPRINTF("failed, %d\n", ret);
339         migrate_fd_error(s);
340         return;
341     }
342     
343     migrate_fd_put_ready(s);
344 }
345
346 void migrate_fd_put_ready(void *opaque)
347 {
348     FdMigrationState *s = opaque;
349
350     if (s->state != MIG_STATE_ACTIVE) {
351         DPRINTF("put_ready returning because of non-active state\n");
352         return;
353     }
354
355     DPRINTF("iterate\n");
356     if (qemu_savevm_state_iterate(s->mon, s->file) == 1) {
357         int state;
358         int old_vm_running = vm_running;
359
360         DPRINTF("done iterating\n");
361         vm_stop(0);
362
363         qemu_aio_flush();
364         bdrv_flush_all();
365         if ((qemu_savevm_state_complete(s->mon, s->file)) < 0) {
366             if (old_vm_running) {
367                 vm_start();
368             }
369             state = MIG_STATE_ERROR;
370         } else {
371             state = MIG_STATE_COMPLETED;
372         }
373         if (migrate_fd_cleanup(s) < 0) {
374             if (old_vm_running) {
375                 vm_start();
376             }
377             state = MIG_STATE_ERROR;
378         }
379         s->state = state;
380     }
381 }
382
383 int migrate_fd_get_status(MigrationState *mig_state)
384 {
385     FdMigrationState *s = migrate_to_fms(mig_state);
386     return s->state;
387 }
388
389 void migrate_fd_cancel(MigrationState *mig_state)
390 {
391     FdMigrationState *s = migrate_to_fms(mig_state);
392
393     if (s->state != MIG_STATE_ACTIVE)
394         return;
395
396     DPRINTF("cancelling migration\n");
397
398     s->state = MIG_STATE_CANCELLED;
399     qemu_savevm_state_cancel(s->mon, s->file);
400
401     migrate_fd_cleanup(s);
402 }
403
404 void migrate_fd_release(MigrationState *mig_state)
405 {
406     FdMigrationState *s = migrate_to_fms(mig_state);
407
408     DPRINTF("releasing state\n");
409    
410     if (s->state == MIG_STATE_ACTIVE) {
411         s->state = MIG_STATE_CANCELLED;
412         migrate_fd_cleanup(s);
413     }
414     qemu_free(s);
415 }
416
417 void migrate_fd_wait_for_unfreeze(void *opaque)
418 {
419     FdMigrationState *s = opaque;
420     int ret;
421
422     DPRINTF("wait for unfreeze\n");
423     if (s->state != MIG_STATE_ACTIVE)
424         return;
425
426     do {
427         fd_set wfds;
428
429         FD_ZERO(&wfds);
430         FD_SET(s->fd, &wfds);
431
432         ret = select(s->fd + 1, NULL, &wfds, NULL, NULL);
433     } while (ret == -1 && (s->get_error(s)) == EINTR);
434 }
435
436 int migrate_fd_close(void *opaque)
437 {
438     FdMigrationState *s = opaque;
439
440     qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
441     return s->close(s);
442 }
This page took 0.048721 seconds and 4 git commands to generate.