mirror of https://github.com/xqemu/xqemu.git
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
This commit is contained in:
parent
39b65c2e31
commit
5bb7910af0
|
@ -474,7 +474,7 @@ endif #CONFIG_DARWIN_USER
|
||||||
ifndef CONFIG_USER_ONLY
|
ifndef CONFIG_USER_ONLY
|
||||||
|
|
||||||
OBJS=vl.o osdep.o monitor.o pci.o loader.o isa_mmio.o machine.o net-checksum.o
|
OBJS=vl.o osdep.o monitor.o pci.o loader.o isa_mmio.o machine.o net-checksum.o
|
||||||
OBJS+=fw_cfg.o aio.o buffered_file.o
|
OBJS+=fw_cfg.o aio.o buffered_file.o migration.o
|
||||||
ifdef CONFIG_WIN32
|
ifdef CONFIG_WIN32
|
||||||
OBJS+=block-raw-win32.o
|
OBJS+=block-raw-win32.o
|
||||||
else
|
else
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
/*
|
||||||
|
* QEMU live migration
|
||||||
|
*
|
||||||
|
* Copyright IBM, Corp. 2008
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Anthony Liguori <aliguori@us.ibm.com>
|
||||||
|
*
|
||||||
|
* This work is licensed under the terms of the GNU GPL, version 2. See
|
||||||
|
* the COPYING file in the top-level directory.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "qemu-common.h"
|
||||||
|
#include "migration.h"
|
||||||
|
#include "console.h"
|
||||||
|
|
||||||
|
/* Migration speed throttling */
|
||||||
|
static uint32_t max_throttle = (32 << 20);
|
||||||
|
|
||||||
|
static MigrationState *current_migration;
|
||||||
|
|
||||||
|
void qemu_start_incoming_migration(const char *uri)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "unknown migration protocol: %s\n", uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
void do_migrate(int detach, const char *uri)
|
||||||
|
{
|
||||||
|
term_printf("unknown migration protocol: %s\n", uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
void do_migrate_cancel(void)
|
||||||
|
{
|
||||||
|
MigrationState *s = current_migration;
|
||||||
|
|
||||||
|
if (s)
|
||||||
|
s->cancel(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void do_migrate_set_speed(const char *value)
|
||||||
|
{
|
||||||
|
double d;
|
||||||
|
char *ptr;
|
||||||
|
|
||||||
|
d = strtod(value, &ptr);
|
||||||
|
switch (*ptr) {
|
||||||
|
case 'G': case 'g':
|
||||||
|
d *= 1024;
|
||||||
|
case 'M': case 'm':
|
||||||
|
d *= 1024;
|
||||||
|
case 'K': case 'k':
|
||||||
|
d *= 1024;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
max_throttle = (uint32_t)d;
|
||||||
|
}
|
||||||
|
|
||||||
|
void do_info_migrate(void)
|
||||||
|
{
|
||||||
|
MigrationState *s = current_migration;
|
||||||
|
|
||||||
|
if (s) {
|
||||||
|
term_printf("Migration status: ");
|
||||||
|
switch (s->get_status(s)) {
|
||||||
|
case MIG_STATE_ACTIVE:
|
||||||
|
term_printf("active\n");
|
||||||
|
break;
|
||||||
|
case MIG_STATE_COMPLETED:
|
||||||
|
term_printf("completed\n");
|
||||||
|
break;
|
||||||
|
case MIG_STATE_ERROR:
|
||||||
|
term_printf("failed\n");
|
||||||
|
break;
|
||||||
|
case MIG_STATE_CANCELLED:
|
||||||
|
term_printf("cancelled\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* QEMU live migration
|
||||||
|
*
|
||||||
|
* Copyright IBM, Corp. 2008
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Anthony Liguori <aliguori@us.ibm.com>
|
||||||
|
*
|
||||||
|
* This work is licensed under the terms of the GNU GPL, version 2. See
|
||||||
|
* the COPYING file in the top-level directory.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef QEMU_MIGRATION_H
|
||||||
|
#define QEMU_MIGRATION_H
|
||||||
|
|
||||||
|
#define MIG_STATE_ERROR -1
|
||||||
|
#define MIG_STATE_COMPLETED 0
|
||||||
|
#define MIG_STATE_CANCELLED 1
|
||||||
|
#define MIG_STATE_ACTIVE 2
|
||||||
|
|
||||||
|
typedef struct MigrationState MigrationState;
|
||||||
|
|
||||||
|
struct MigrationState
|
||||||
|
{
|
||||||
|
/* FIXME: add more accessors to print migration info */
|
||||||
|
void (*cancel)(MigrationState *s);
|
||||||
|
int (*get_status)(MigrationState *s);
|
||||||
|
void (*release)(MigrationState *s);
|
||||||
|
};
|
||||||
|
|
||||||
|
void qemu_start_incoming_migration(const char *uri);
|
||||||
|
|
||||||
|
void do_migrate(int detach, const char *uri);
|
||||||
|
|
||||||
|
void do_migrate_cancel(void);
|
||||||
|
|
||||||
|
void do_migrate_set_speed(const char *value);
|
||||||
|
|
||||||
|
void do_info_migrate(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include "disas.h"
|
#include "disas.h"
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include "qemu-timer.h"
|
#include "qemu-timer.h"
|
||||||
|
#include "migration.h"
|
||||||
|
|
||||||
//#define DEBUG
|
//#define DEBUG
|
||||||
//#define DEBUG_COMPLETION
|
//#define DEBUG_COMPLETION
|
||||||
|
@ -1454,6 +1455,12 @@ static const term_cmd_t term_cmds[] = {
|
||||||
{ "nmi", "i", do_inject_nmi,
|
{ "nmi", "i", do_inject_nmi,
|
||||||
"cpu", "inject an NMI on the given CPU", },
|
"cpu", "inject an NMI on the given CPU", },
|
||||||
#endif
|
#endif
|
||||||
|
{ "migrate", "-ds", do_migrate,
|
||||||
|
"[-d] uri", "migrate to URI (using -d to not wait for completion)" },
|
||||||
|
{ "migrate_cancel", "", do_migrate_cancel,
|
||||||
|
"", "cancel the current VM migration" },
|
||||||
|
{ "migrate_set_speed", "s", do_migrate_set_speed,
|
||||||
|
"value", "set maximum speed (in bytes) for migrations" },
|
||||||
{ NULL, NULL, },
|
{ NULL, NULL, },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1516,6 +1523,7 @@ static const term_cmd_t info_cmds[] = {
|
||||||
{ "slirp", "", do_info_slirp,
|
{ "slirp", "", do_info_slirp,
|
||||||
"", "show SLIRP statistics", },
|
"", "show SLIRP statistics", },
|
||||||
#endif
|
#endif
|
||||||
|
{ "migrate", "", do_info_migrate, "", "show migration status" },
|
||||||
{ NULL, NULL, },
|
{ NULL, NULL, },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -31,5 +31,6 @@ int inet_aton(const char *cp, struct in_addr *ia);
|
||||||
#endif /* !_WIN32 */
|
#endif /* !_WIN32 */
|
||||||
|
|
||||||
void socket_set_nonblock(int fd);
|
void socket_set_nonblock(int fd);
|
||||||
|
int parse_host_port(struct sockaddr_in *saddr, const char *str);
|
||||||
|
|
||||||
#endif /* QEMU_SOCKET_H */
|
#endif /* QEMU_SOCKET_H */
|
||||||
|
|
15
vl.c
15
vl.c
|
@ -38,6 +38,7 @@
|
||||||
#include "qemu-char.h"
|
#include "qemu-char.h"
|
||||||
#include "block.h"
|
#include "block.h"
|
||||||
#include "audio/audio.h"
|
#include "audio/audio.h"
|
||||||
|
#include "migration.h"
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
@ -3364,7 +3365,6 @@ static void udp_chr_update_read_handler(CharDriverState *chr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int parse_host_port(struct sockaddr_in *saddr, const char *str);
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
static int parse_unix_path(struct sockaddr_un *uaddr, const char *str);
|
static int parse_unix_path(struct sockaddr_un *uaddr, const char *str);
|
||||||
#endif
|
#endif
|
||||||
|
@ -6766,6 +6766,8 @@ int qemu_savevm_state(QEMUFile *f)
|
||||||
saved_vm_running = vm_running;
|
saved_vm_running = vm_running;
|
||||||
vm_stop(0);
|
vm_stop(0);
|
||||||
|
|
||||||
|
bdrv_flush_all();
|
||||||
|
|
||||||
ret = qemu_savevm_state_begin(f);
|
ret = qemu_savevm_state_begin(f);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -8338,6 +8340,7 @@ enum {
|
||||||
QEMU_OPTION_tb_size,
|
QEMU_OPTION_tb_size,
|
||||||
QEMU_OPTION_icount,
|
QEMU_OPTION_icount,
|
||||||
QEMU_OPTION_uuid,
|
QEMU_OPTION_uuid,
|
||||||
|
QEMU_OPTION_incoming,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct QEMUOption {
|
typedef struct QEMUOption {
|
||||||
|
@ -8450,6 +8453,7 @@ static const QEMUOption qemu_options[] = {
|
||||||
{ "startdate", HAS_ARG, QEMU_OPTION_startdate },
|
{ "startdate", HAS_ARG, QEMU_OPTION_startdate },
|
||||||
{ "tb-size", HAS_ARG, QEMU_OPTION_tb_size },
|
{ "tb-size", HAS_ARG, QEMU_OPTION_tb_size },
|
||||||
{ "icount", HAS_ARG, QEMU_OPTION_icount },
|
{ "icount", HAS_ARG, QEMU_OPTION_icount },
|
||||||
|
{ "incoming", HAS_ARG, QEMU_OPTION_incoming },
|
||||||
{ NULL },
|
{ NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -8742,6 +8746,7 @@ int main(int argc, char **argv)
|
||||||
const char *pid_file = NULL;
|
const char *pid_file = NULL;
|
||||||
VLANState *vlan;
|
VLANState *vlan;
|
||||||
int autostart;
|
int autostart;
|
||||||
|
const char *incoming = NULL;
|
||||||
|
|
||||||
LIST_INIT (&vm_change_state_head);
|
LIST_INIT (&vm_change_state_head);
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
@ -9349,6 +9354,9 @@ int main(int argc, char **argv)
|
||||||
icount_time_shift = strtol(optarg, NULL, 0);
|
icount_time_shift = strtol(optarg, NULL, 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case QEMU_OPTION_incoming:
|
||||||
|
incoming = optarg;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9691,6 +9699,11 @@ int main(int argc, char **argv)
|
||||||
if (loadvm)
|
if (loadvm)
|
||||||
do_loadvm(loadvm);
|
do_loadvm(loadvm);
|
||||||
|
|
||||||
|
if (incoming) {
|
||||||
|
autostart = 0; /* fixme how to deal with -daemonize */
|
||||||
|
qemu_start_incoming_migration(incoming);
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
/* XXX: simplify init */
|
/* XXX: simplify init */
|
||||||
read_passwords();
|
read_passwords();
|
||||||
|
|
Loading…
Reference in New Issue