Commit 5bb7910af031cce09cc619b982d39dc889776f65
1 parent
39b65c2e
Introduce UI for live migration
This patch introduces a command line parameter and monitor command for starting a live migration. The next patch will provide an example of how to use these parameters. Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5476 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
6 changed files
with
150 additions
and
2 deletions
Makefile.target
... | ... | @@ -474,7 +474,7 @@ endif #CONFIG_DARWIN_USER |
474 | 474 | ifndef CONFIG_USER_ONLY |
475 | 475 | |
476 | 476 | OBJS=vl.o osdep.o monitor.o pci.o loader.o isa_mmio.o machine.o net-checksum.o |
477 | -OBJS+=fw_cfg.o aio.o buffered_file.o | |
477 | +OBJS+=fw_cfg.o aio.o buffered_file.o migration.o | |
478 | 478 | ifdef CONFIG_WIN32 |
479 | 479 | OBJS+=block-raw-win32.o |
480 | 480 | else | ... | ... |
migration.c
0 → 100644
1 | +/* | |
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" | |
16 | +#include "console.h" | |
17 | + | |
18 | +/* Migration speed throttling */ | |
19 | +static uint32_t max_throttle = (32 << 20); | |
20 | + | |
21 | +static MigrationState *current_migration; | |
22 | + | |
23 | +void qemu_start_incoming_migration(const char *uri) | |
24 | +{ | |
25 | + fprintf(stderr, "unknown migration protocol: %s\n", uri); | |
26 | +} | |
27 | + | |
28 | +void do_migrate(int detach, const char *uri) | |
29 | +{ | |
30 | + term_printf("unknown migration protocol: %s\n", uri); | |
31 | +} | |
32 | + | |
33 | +void do_migrate_cancel(void) | |
34 | +{ | |
35 | + MigrationState *s = current_migration; | |
36 | + | |
37 | + if (s) | |
38 | + s->cancel(s); | |
39 | +} | |
40 | + | |
41 | +void do_migrate_set_speed(const char *value) | |
42 | +{ | |
43 | + double d; | |
44 | + char *ptr; | |
45 | + | |
46 | + d = strtod(value, &ptr); | |
47 | + switch (*ptr) { | |
48 | + case 'G': case 'g': | |
49 | + d *= 1024; | |
50 | + case 'M': case 'm': | |
51 | + d *= 1024; | |
52 | + case 'K': case 'k': | |
53 | + d *= 1024; | |
54 | + default: | |
55 | + break; | |
56 | + } | |
57 | + | |
58 | + max_throttle = (uint32_t)d; | |
59 | +} | |
60 | + | |
61 | +void do_info_migrate(void) | |
62 | +{ | |
63 | + MigrationState *s = current_migration; | |
64 | + | |
65 | + if (s) { | |
66 | + term_printf("Migration status: "); | |
67 | + switch (s->get_status(s)) { | |
68 | + case MIG_STATE_ACTIVE: | |
69 | + term_printf("active\n"); | |
70 | + break; | |
71 | + case MIG_STATE_COMPLETED: | |
72 | + term_printf("completed\n"); | |
73 | + break; | |
74 | + case MIG_STATE_ERROR: | |
75 | + term_printf("failed\n"); | |
76 | + break; | |
77 | + case MIG_STATE_CANCELLED: | |
78 | + term_printf("cancelled\n"); | |
79 | + break; | |
80 | + } | |
81 | + } | |
82 | +} | |
83 | + | ... | ... |
migration.h
0 → 100644
1 | +/* | |
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 | +#ifndef QEMU_MIGRATION_H | |
15 | +#define QEMU_MIGRATION_H | |
16 | + | |
17 | +#define MIG_STATE_ERROR -1 | |
18 | +#define MIG_STATE_COMPLETED 0 | |
19 | +#define MIG_STATE_CANCELLED 1 | |
20 | +#define MIG_STATE_ACTIVE 2 | |
21 | + | |
22 | +typedef struct MigrationState MigrationState; | |
23 | + | |
24 | +struct MigrationState | |
25 | +{ | |
26 | + /* FIXME: add more accessors to print migration info */ | |
27 | + void (*cancel)(MigrationState *s); | |
28 | + int (*get_status)(MigrationState *s); | |
29 | + void (*release)(MigrationState *s); | |
30 | +}; | |
31 | + | |
32 | +void qemu_start_incoming_migration(const char *uri); | |
33 | + | |
34 | +void do_migrate(int detach, const char *uri); | |
35 | + | |
36 | +void do_migrate_cancel(void); | |
37 | + | |
38 | +void do_migrate_set_speed(const char *value); | |
39 | + | |
40 | +void do_info_migrate(void); | |
41 | + | |
42 | +#endif | |
43 | + | ... | ... |
monitor.c
... | ... | @@ -36,6 +36,7 @@ |
36 | 36 | #include "disas.h" |
37 | 37 | #include <dirent.h> |
38 | 38 | #include "qemu-timer.h" |
39 | +#include "migration.h" | |
39 | 40 | |
40 | 41 | //#define DEBUG |
41 | 42 | //#define DEBUG_COMPLETION |
... | ... | @@ -1454,6 +1455,12 @@ static const term_cmd_t term_cmds[] = { |
1454 | 1455 | { "nmi", "i", do_inject_nmi, |
1455 | 1456 | "cpu", "inject an NMI on the given CPU", }, |
1456 | 1457 | #endif |
1458 | + { "migrate", "-ds", do_migrate, | |
1459 | + "[-d] uri", "migrate to URI (using -d to not wait for completion)" }, | |
1460 | + { "migrate_cancel", "", do_migrate_cancel, | |
1461 | + "", "cancel the current VM migration" }, | |
1462 | + { "migrate_set_speed", "s", do_migrate_set_speed, | |
1463 | + "value", "set maximum speed (in bytes) for migrations" }, | |
1457 | 1464 | { NULL, NULL, }, |
1458 | 1465 | }; |
1459 | 1466 | |
... | ... | @@ -1516,6 +1523,7 @@ static const term_cmd_t info_cmds[] = { |
1516 | 1523 | { "slirp", "", do_info_slirp, |
1517 | 1524 | "", "show SLIRP statistics", }, |
1518 | 1525 | #endif |
1526 | + { "migrate", "", do_info_migrate, "", "show migration status" }, | |
1519 | 1527 | { NULL, NULL, }, |
1520 | 1528 | }; |
1521 | 1529 | ... | ... |
qemu_socket.h
vl.c
... | ... | @@ -38,6 +38,7 @@ |
38 | 38 | #include "qemu-char.h" |
39 | 39 | #include "block.h" |
40 | 40 | #include "audio/audio.h" |
41 | +#include "migration.h" | |
41 | 42 | |
42 | 43 | #include <unistd.h> |
43 | 44 | #include <fcntl.h> |
... | ... | @@ -3364,7 +3365,6 @@ static void udp_chr_update_read_handler(CharDriverState *chr) |
3364 | 3365 | } |
3365 | 3366 | } |
3366 | 3367 | |
3367 | -int parse_host_port(struct sockaddr_in *saddr, const char *str); | |
3368 | 3368 | #ifndef _WIN32 |
3369 | 3369 | static int parse_unix_path(struct sockaddr_un *uaddr, const char *str); |
3370 | 3370 | #endif |
... | ... | @@ -6766,6 +6766,8 @@ int qemu_savevm_state(QEMUFile *f) |
6766 | 6766 | saved_vm_running = vm_running; |
6767 | 6767 | vm_stop(0); |
6768 | 6768 | |
6769 | + bdrv_flush_all(); | |
6770 | + | |
6769 | 6771 | ret = qemu_savevm_state_begin(f); |
6770 | 6772 | if (ret < 0) |
6771 | 6773 | goto out; |
... | ... | @@ -8338,6 +8340,7 @@ enum { |
8338 | 8340 | QEMU_OPTION_tb_size, |
8339 | 8341 | QEMU_OPTION_icount, |
8340 | 8342 | QEMU_OPTION_uuid, |
8343 | + QEMU_OPTION_incoming, | |
8341 | 8344 | }; |
8342 | 8345 | |
8343 | 8346 | typedef struct QEMUOption { |
... | ... | @@ -8450,6 +8453,7 @@ static const QEMUOption qemu_options[] = { |
8450 | 8453 | { "startdate", HAS_ARG, QEMU_OPTION_startdate }, |
8451 | 8454 | { "tb-size", HAS_ARG, QEMU_OPTION_tb_size }, |
8452 | 8455 | { "icount", HAS_ARG, QEMU_OPTION_icount }, |
8456 | + { "incoming", HAS_ARG, QEMU_OPTION_incoming }, | |
8453 | 8457 | { NULL }, |
8454 | 8458 | }; |
8455 | 8459 | |
... | ... | @@ -8742,6 +8746,7 @@ int main(int argc, char **argv) |
8742 | 8746 | const char *pid_file = NULL; |
8743 | 8747 | VLANState *vlan; |
8744 | 8748 | int autostart; |
8749 | + const char *incoming = NULL; | |
8745 | 8750 | |
8746 | 8751 | LIST_INIT (&vm_change_state_head); |
8747 | 8752 | #ifndef _WIN32 |
... | ... | @@ -9349,6 +9354,9 @@ int main(int argc, char **argv) |
9349 | 9354 | icount_time_shift = strtol(optarg, NULL, 0); |
9350 | 9355 | } |
9351 | 9356 | break; |
9357 | + case QEMU_OPTION_incoming: | |
9358 | + incoming = optarg; | |
9359 | + break; | |
9352 | 9360 | } |
9353 | 9361 | } |
9354 | 9362 | } |
... | ... | @@ -9691,6 +9699,11 @@ int main(int argc, char **argv) |
9691 | 9699 | if (loadvm) |
9692 | 9700 | do_loadvm(loadvm); |
9693 | 9701 | |
9702 | + if (incoming) { | |
9703 | + autostart = 0; /* fixme how to deal with -daemonize */ | |
9704 | + qemu_start_incoming_migration(incoming); | |
9705 | + } | |
9706 | + | |
9694 | 9707 | { |
9695 | 9708 | /* XXX: simplify init */ |
9696 | 9709 | read_passwords(); | ... | ... |