qemu/migration-exec.c
<<
>>
Prefs
   1/*
   2 * QEMU live migration
   3 *
   4 * Copyright IBM, Corp. 2008
   5 * Copyright Dell MessageOne 2008
   6 *
   7 * Authors:
   8 *  Anthony Liguori   <aliguori@us.ibm.com>
   9 *  Charles Duffy     <charles_duffy@messageone.com>
  10 *
  11 * This work is licensed under the terms of the GNU GPL, version 2.  See
  12 * the COPYING file in the top-level directory.
  13 *
  14 * Contributions after 2012-01-13 are licensed under the terms of the
  15 * GNU GPL, version 2 or (at your option) any later version.
  16 */
  17
  18#include "qemu-common.h"
  19#include "qemu_socket.h"
  20#include "migration.h"
  21#include "qemu-char.h"
  22#include "buffered_file.h"
  23#include "block.h"
  24#include <sys/types.h>
  25#include <sys/wait.h>
  26
  27//#define DEBUG_MIGRATION_EXEC
  28
  29#ifdef DEBUG_MIGRATION_EXEC
  30#define DPRINTF(fmt, ...) \
  31    do { printf("migration-exec: " fmt, ## __VA_ARGS__); } while (0)
  32#else
  33#define DPRINTF(fmt, ...) \
  34    do { } while (0)
  35#endif
  36
  37static int file_errno(MigrationState *s)
  38{
  39    return errno;
  40}
  41
  42static int file_write(MigrationState *s, const void * buf, size_t size)
  43{
  44    return write(s->fd, buf, size);
  45}
  46
  47static int exec_close(MigrationState *s)
  48{
  49    int ret = 0;
  50    DPRINTF("exec_close\n");
  51    ret = qemu_fclose(s->opaque);
  52    s->opaque = NULL;
  53    s->fd = -1;
  54    if (ret >= 0 && !(WIFEXITED(ret) && WEXITSTATUS(ret) == 0)) {
  55        /* close succeeded, but non-zero exit code: */
  56        ret = -EIO; /* fake errno value */
  57    }
  58    return ret;
  59}
  60
  61void exec_start_outgoing_migration(MigrationState *s, const char *command, Error **errp)
  62{
  63    FILE *f;
  64
  65    f = popen(command, "w");
  66    if (f == NULL) {
  67        error_setg_errno(errp, errno, "failed to popen the migration target");
  68        return;
  69    }
  70
  71    s->fd = fileno(f);
  72    assert(s->fd != -1);
  73    socket_set_nonblock(s->fd);
  74
  75    s->opaque = qemu_popen(f, "w");
  76
  77    s->close = exec_close;
  78    s->get_error = file_errno;
  79    s->write = file_write;
  80
  81    migrate_fd_connect(s);
  82}
  83
  84static void exec_accept_incoming_migration(void *opaque)
  85{
  86    QEMUFile *f = opaque;
  87
  88    qemu_set_fd_handler2(qemu_get_fd(f), NULL, NULL, NULL, NULL);
  89    process_incoming_migration(f);
  90}
  91
  92void exec_start_incoming_migration(const char *command, Error **errp)
  93{
  94    QEMUFile *f;
  95
  96    DPRINTF("Attempting to start an incoming migration\n");
  97    f = qemu_popen_cmd(command, "r");
  98    if(f == NULL) {
  99        error_setg_errno(errp, errno, "failed to popen the migration source");
 100        return;
 101    }
 102
 103    qemu_set_fd_handler2(qemu_get_fd(f), NULL,
 104                         exec_accept_incoming_migration, NULL, f);
 105}
 106