Re: [Qemu-devel] [PATCH 10/10] TCP based live migration

2008-09-10 Thread Anthony Liguori

Blue Swirl wrote:

On 9/9/08, Anthony Liguori <[EMAIL PROTECTED]> wrote:
  

This patch introduces a tcp protocol for live migration.  It can be used as
 follows:

 qemu-system-x86_64 -hda ~/images/linux-test.img -monitor stdio
  
 (qemu) migrate tcp:localhost:1025

 On the same system:

 qemu-system-x86_64 -hda ~/images/linux-test.img -incoming tcp:localhost:1025

 The monitor can be interacted with while waiting for an incoming live 
migration.



With command line switches, you have to know when starting the VM that
it is going to accept an incoming migration. Would it be possible to
change this so that the incoming migration could be triggered from
monitor? For example to migrate back to original host?
  


Yup.  The main reason for an -incoming flag is it makes the ssh: 
protocol easier to implement (not included here).


I'll add a monitor command too.

Regards,

Anthony Liguori


--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [Qemu-devel] [PATCH 10/10] TCP based live migration

2008-09-10 Thread Blue Swirl
On 9/9/08, Anthony Liguori <[EMAIL PROTECTED]> wrote:
> This patch introduces a tcp protocol for live migration.  It can be used as
>  follows:
>
>  qemu-system-x86_64 -hda ~/images/linux-test.img -monitor stdio
>   
>  (qemu) migrate tcp:localhost:1025
>
>  On the same system:
>
>  qemu-system-x86_64 -hda ~/images/linux-test.img -incoming tcp:localhost:1025
>
>  The monitor can be interacted with while waiting for an incoming live 
> migration.

With command line switches, you have to know when starting the VM that
it is going to accept an incoming migration. Would it be possible to
change this so that the incoming migration could be triggered from
monitor? For example to migrate back to original host?
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 10/10] TCP based live migration

2008-09-09 Thread Anthony Liguori
This patch introduces a tcp protocol for live migration.  It can be used as
follows:

qemu-system-x86_64 -hda ~/images/linux-test.img -monitor stdio
 
(qemu) migrate tcp:localhost:1025

On the same system:

qemu-system-x86_64 -hda ~/images/linux-test.img -incoming tcp:localhost:1025

The monitor can be interacted with while waiting for an incoming live migration.

Signed-off-by: Anthony Liguori <[EMAIL PROTECTED]>

diff --git a/Makefile.target b/Makefile.target
index 6bf5229..0fa585c 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -473,7 +473,7 @@ endif #CONFIG_DARWIN_USER
 ifndef CONFIG_USER_ONLY
 
 OBJS=vl.o osdep.o monitor.o pci.o loader.o isa_mmio.o machine.o net-checksum.o
-OBJS+=migration.o
+OBJS+=migration.o migration-tcp.o
 ifdef CONFIG_WIN32
 OBJS+=block-raw-win32.o
 else
diff --git a/migration-tcp.c b/migration-tcp.c
new file mode 100644
index 000..6b46bd4
--- /dev/null
+++ b/migration-tcp.c
@@ -0,0 +1,243 @@
+#include "qemu-common.h"
+#include "qemu_socket.h"
+#include "migration.h"
+#include "qemu-char.h"
+#include "sysemu.h"
+#include "console.h"
+
+/* FIXME resume monitor on error */
+
+
+typedef struct FdMigrationState
+{
+QEMUFile *file;
+int64_t bandwidth_limit;
+int fd;
+} FdMigrationState;
+
+static void fd_put_notify(void *opaque)
+{
+FdMigrationState *s = opaque;
+
+qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
+qemu_file_put_notify(s->file);
+}
+
+static ssize_t fd_put_buffer(void *opaque, const void *data, size_t size)
+{
+FdMigrationState *s = opaque;
+ssize_t ret;
+
+do {
+ret = write(s->fd, data, size);
+} while (ret == -1 && errno == EINTR);
+
+if (ret == -1)
+ret = -errno;
+
+if (ret == -EAGAIN)
+qemu_set_fd_handler2(s->fd, NULL, NULL, fd_put_notify, s);
+
+return ret;
+}
+
+static int fd_close(void *opaque)
+{
+FdMigrationState *s = opaque;
+return close(s->fd);
+}
+
+static void fd_wait_for_unfreeze(void *opaque)
+{
+FdMigrationState *s = opaque;
+int ret;
+
+do {
+fd_set wfds;
+
+FD_ZERO(&wfds);
+FD_SET(s->fd, &wfds);
+
+ret = select(s->fd + 1, NULL, &wfds, NULL, NULL);
+} while (ret == -1 && errno == EINTR);
+}
+
+static void fd_put_ready(void *opaque)
+{
+FdMigrationState *s = opaque;
+
+if (qemu_savevm_state_iterate(s->file) == 1) {
+vm_stop(0);
+qemu_savevm_state_complete(s->file);
+qemu_fclose(s->file);
+qemu_free(s);
+monitor_resume();
+}
+}
+
+static void tcp_connect_migrate(FdMigrationState *s)
+{
+int ret;
+
+s->file = qemu_fopen_ops_buffered(s,
+  s->bandwidth_limit,
+  fd_put_buffer,
+  fd_put_ready,
+  fd_wait_for_unfreeze,
+  fd_close);
+
+ret = qemu_savevm_state_begin(s->file);
+if (ret < 0) {
+fprintf(stderr, "savevm failed %d\n", ret);
+return;
+}
+
+monitor_suspend();
+
+fd_put_ready(s);
+}
+
+static void tcp_wait_for_connect(void *opaque)
+{
+FdMigrationState *s = opaque;
+int val, ret;
+int valsize = sizeof(val);
+
+do {
+ret = getsockopt(s->fd, SOL_SOCKET, SO_ERROR, &val, &valsize);
+} while (ret == -1 && errno == EINTR);
+
+if (ret < 0) {
+fprintf(stderr, "Could not query connect success\n");
+return;
+}
+
+qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
+
+if (val == 0)
+tcp_connect_migrate(s);
+else {
+fprintf(stderr, "failed to connect to host\n");
+close(s->fd);
+qemu_free(s);
+}
+}
+
+int tcp_start_outgoing_migration(const char *host_port, int64_t 
bandwidth_limit)
+{
+struct sockaddr_in addr;
+FdMigrationState *s;
+int ret;
+
+if (parse_host_port(&addr, host_port) < 0) {
+fprintf(stderr, "invalid host/port combination: %s\n", host_port);
+return -EINVAL;
+}
+
+s = qemu_mallocz(sizeof(*s));
+if (s == NULL)
+return -ENOMEM;
+
+s->bandwidth_limit = bandwidth_limit;
+s->fd = socket(PF_INET, SOCK_STREAM, 0);
+if (s->fd == -1) {
+qemu_free(s);
+return -errno;
+}
+
+fcntl(s->fd, F_SETFL, O_NONBLOCK);
+
+do {
+ret = connect(s->fd, (struct sockaddr *)&addr, sizeof(addr));
+if (ret == -1)
+ret = -errno;
+
+if (ret == -EINPROGRESS)
+qemu_set_fd_handler2(s->fd, NULL, NULL, tcp_wait_for_connect, s);
+} while (ret == -EINTR);
+
+if (ret < 0 && ret != -EINPROGRESS) {
+fprintf(stderr, "failed to connect to host\n");
+close(s->fd);
+qemu_free(s);
+} else if (ret >= 0)
+tcp_connect_migrate(s);
+
+return 0;
+}
+
+static void tcp_accept_incoming_migration(void *opaque)
+{
+struct sockaddr_in addr;
+socklen_t addrlen = sizeof(addr);
+int s = (unsigned lo