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(); | ... | ... |