[libvirt] [PATCH] Add migration APIs for libxl driver

Chunyan Liu cyliu at suse.com
Fri Mar 2 02:02:07 UTC 2012


Add migration APIs for libxl driver. 
Implemented in migration version 3. Based on xen 4.1.

Signed-off-by: Chunyan Liu <cyliu at suse.com>
---
 src/libxl/libxl_driver.c |  617 ++++++++++++++++++++++++++++++++++++++++++++++
 src/libxl/libxl_driver.h |   17 ++-
 2 files changed, 632 insertions(+), 2 deletions(-)

diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
index d5fa64a..4037635 100644
--- a/src/libxl/libxl_driver.c
+++ b/src/libxl/libxl_driver.c
@@ -30,6 +30,12 @@
 #include <math.h>
 #include <libxl.h>
 #include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netdb.h>
 
 #include "internal.h"
 #include "logging.h"
@@ -60,6 +66,13 @@
 #define XEN_SCHED_CREDIT_NPARAM   2
 
 static libxlDriverPrivatePtr libxl_driver = NULL;
+static virThread migrate_receive_thread;
+
+typedef struct migrate_receive_args {
+    virConnectPtr conn;
+    virDomainObjPtr vm;
+    int sockfd;
+} migrate_receive_args;
 
 /* Function declarations */
 static int
@@ -1095,6 +1108,17 @@ libxlClose(virConnectPtr conn ATTRIBUTE_UNUSED)
     return 0;
 }
 
+static int
+libxlSupportsFeature(virConnectPtr conn ATTRIBUTE_UNUSED, int feature)
+{
+    switch (feature) {
+    case VIR_DRV_FEATURE_MIGRATION_V3:
+        return 1;
+    default:
+        return 0;
+    }
+}
+
 static const char *
 libxlGetType(virConnectPtr conn ATTRIBUTE_UNUSED)
 {
@@ -3842,12 +3866,600 @@ libxlIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED)
     return 1;
 }
 
+static int libxlReadFixedMessage(int fd, const void *msg, int msgsz)
+{
+    char buf[msgsz];
+
+    if (saferead(fd, buf, msgsz) != msgsz || memcmp(buf, msg, msgsz)) {
+        return -1;
+    }
+
+    return 0;
+}
+
+static int doParseURI(const char *uri, char **p_hostname, int *p_port)
+{
+    char *p, *hostname;
+    char port[16] = "0";
+
+    if (strstr (uri, "//")) {   /* Full URI. */
+        virURIPtr uriptr = virURIParse(uri);
+        if (!uriptr) {
+            libxlError(VIR_ERR_INVALID_ARG,
+                           _("Invalid URI"));
+            return -1;
+        }
+        if (uriptr->scheme && STRCASENEQ(uriptr->scheme, "xlmigr")) {
+            libxlError(VIR_ERR_INVALID_ARG,
+                        _("Only xlmigr://"
+                        " migrations are supported by Xen"));
+            xmlFreeURI(uriptr);
+            return -1;
+        }
+        if (!uriptr->server) {
+            libxlError(VIR_ERR_INVALID_ARG,
+                          _("A hostname must be"
+                            " specified in the URI"));
+            xmlFreeURI(uriptr);
+            return -1;
+        }
+        hostname = strdup(uriptr->server);
+        if (!hostname) {
+            virReportOOMError();
+            xmlFreeURI(uriptr);
+            return -1;
+        }
+        if (uriptr->port)
+            snprintf(port, sizeof(port), "%d", uriptr->port);
+        xmlFreeURI(uriptr);
+    }
+    else if ((p = strrchr(uri, ':')) != NULL) { /* "hostname:port" */
+        int port_nr, n;
+
+        if (virStrToLong_i(p+1, NULL, 10, &port_nr) < 0) {
+            libxlError(VIR_ERR_INVALID_ARG,
+                         _("Invalid port number"));
+            return -1;
+        }
+        snprintf(port, sizeof(port), "%d", port_nr);
+
+        /* Get the hostname. */
+        n = p - uri; /* n = Length of hostname in bytes. */
+        hostname = strdup(uri);
+        if (!hostname) {
+            virReportOOMError();
+            return -1;
+        }
+        hostname[n] = '\0';
+    }
+    else {/* "hostname" (or IP address) */
+        hostname = strdup(uri);
+        if (!hostname) {
+            virReportOOMError();
+            return -1;
+        }
+    }
+    *p_hostname = hostname;
+    *p_port = atoi(port);
+    return 0;
+}
+
+static bool libxlMigrationFromIsAllowed(libxlDriverPrivatePtr driver, virDomainObjPtr vm)
+{
+    /* to be extended */
+    VIR_DEBUG("driver=%p, vm=%p", driver, vm);
+    return true;
+}
+
+static bool libxlMigrationToIsAllowed(libxlDriverPrivatePtr driver, virDomainDefPtr def)
+{
+    /* to be extended */
+    VIR_DEBUG("driver=%p, def=%p", driver, def);
+    return true;
+}
+
+static char *
+libxlDomainMigrateBegin3(virDomainPtr domain,
+                          const char *xmlin,
+                          char **cookieout ATTRIBUTE_UNUSED,
+                          int *cookieoutlen ATTRIBUTE_UNUSED,
+                          unsigned long flags,
+                          const char *dname ATTRIBUTE_UNUSED,
+                          unsigned long resource ATTRIBUTE_UNUSED)
+{
+    libxlDriverPrivatePtr driver = domain->conn->privateData;
+    virDomainObjPtr vm;
+    virDomainDefPtr def = NULL;
+    char *xml = NULL;
+
+    virCheckFlags(LIBXL_MIGRATION_FLAGS, NULL);
+
+    libxlDriverLock(driver);
+    vm = virDomainFindByUUID(&driver->domains, domain->uuid);
+    if (!vm) {
+        char uuidstr[VIR_UUID_STRING_BUFLEN];
+        virUUIDFormat(domain->uuid, uuidstr);
+        libxlError(VIR_ERR_OPERATION_INVALID,
+                        _("no domain with matching uuid '%s'"), uuidstr);
+        goto cleanup;
+    }
+
+    if (!virDomainObjIsActive(vm)) {
+        libxlError(VIR_ERR_OPERATION_INVALID,
+                         _("domain is not running"));
+        goto cleanup;
+    }
+
+    if (!libxlMigrationFromIsAllowed(driver, vm)) {
+        libxlError(VIR_ERR_OPERATION_INVALID,
+                         _("domain cannot do migration"));
+        goto cleanup;
+    }
+
+    if (xmlin) {
+        if (!(def = virDomainDefParseString(driver->caps, xml,
+                         1 << VIR_DOMAIN_VIRT_XEN,
+                         VIR_DOMAIN_XML_INACTIVE)))
+            goto cleanup;
+
+        xml = virDomainDefFormat(def, VIR_DOMAIN_XML_SECURE);
+    } else {
+        xml = virDomainDefFormat(vm->def, VIR_DOMAIN_XML_SECURE);
+    }
+
+cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
+    libxlDriverUnlock(driver);
+    return xml;
+}
+
+static void doMigrateReceive(void *opaque)
+{
+    migrate_receive_args *data = opaque;
+    virConnectPtr conn = data->conn;
+    int sockfd = data->sockfd;
+    virDomainObjPtr vm = data->vm;
+    libxlDriverPrivatePtr driver = conn->privateData;
+    int recv_fd;
+    struct sockaddr_in new_addr;
+    socklen_t socklen = sizeof(new_addr);
+    int len;
+
+    do {
+        recv_fd = accept(sockfd, (struct sockaddr *)&new_addr, &socklen);
+    } while(recv_fd < 0 && errno == EINTR);
+
+    VIR_DEBUG("Accepted migration\n");
+    if (recv_fd < 0) {
+        VIR_DEBUG("Could not accept migration connection\n");
+        goto cleanup;
+    }
+
+    len = sizeof(migrate_receiver_banner);
+    if (safewrite(recv_fd, migrate_receiver_banner, len) != len) {
+        libxlError(VIR_ERR_OPERATION_FAILED,
+                         _("Failed to write migrate_receiver_banner"));
+        goto cleanup;
+    }
+
+    if (libxlVmStart(driver, vm, false, recv_fd) < 0) {
+        libxlError(VIR_ERR_INTERNAL_ERROR,
+                    _("Failed to restore domain with libxenlight"));
+        if (!vm->persistent) {
+            virDomainRemoveInactive(&driver->domains, vm);
+            vm = NULL;
+        }
+        goto cleanup;
+    }
+
+    len = sizeof(migrate_receiver_ready);
+    if (safewrite(recv_fd, migrate_receiver_ready, len) != len) {
+        libxlError(VIR_ERR_OPERATION_FAILED,
+                         _("Failed to write migrate_receiver_ready"));
+    }
+
+cleanup:
+    if (VIR_CLOSE(recv_fd) < 0)
+        virReportSystemError(errno, "%s", _("cannot close recv_fd"));
+    if (VIR_CLOSE(sockfd) < 0)
+        virReportSystemError(errno, "%s", _("cannot close sockfd"));
+    if (vm)
+        virDomainObjUnlock(vm);
+    VIR_FREE(opaque);
+    return;
+}
+
+static int doMigrateSend(virDomainPtr dom, unsigned long flags, int sockfd)
+{
+    libxlDriverPrivatePtr driver = dom->conn->privateData;
+    virDomainObjPtr vm;
+    libxlDomainObjPrivatePtr priv;
+    libxl_domain_suspend_info suspinfo;
+    virDomainEventPtr event = NULL;
+    int live = 0;
+    int ret = -1;
+
+    if (flags & VIR_MIGRATE_LIVE)
+        live = 1;
+
+    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    if (!vm) {
+        char uuidstr[VIR_UUID_STRING_BUFLEN];
+        virUUIDFormat(dom->uuid, uuidstr);
+        libxlError(VIR_ERR_OPERATION_INVALID,
+                         _("no domain with matching uuid '%s'"), uuidstr);
+        goto cleanup;
+    }
+
+    priv = vm->privateData;
+
+    /* read fixed message from dest (ready to receive) */
+    if (libxlReadFixedMessage(sockfd, migrate_receiver_banner,
+                              sizeof(migrate_receiver_banner))) {
+        goto cleanup;
+    }
+
+    /* send suspend data */
+    memset(&suspinfo, 0, sizeof(suspinfo));
+    if (live == 1)
+        suspinfo.flags |= XL_SUSPEND_LIVE;
+    if (libxl_domain_suspend(&priv->ctx, &suspinfo, vm->def->id, sockfd) != 0) {
+        libxlError(VIR_ERR_INTERNAL_ERROR,
+                    _("Failed to save domain '%d' with libxenlight"),
+                    vm->def->id);
+        goto cleanup;
+    }
+
+    /* read fixed message from dest (receive completed) */
+    if (libxlReadFixedMessage(sockfd, migrate_receiver_ready,
+                              sizeof(migrate_receiver_ready))) {
+        /* Src side should be resumed, but for ret < 0, virsh won't call Src side
+         * Confirm3, handle it here.
+         */
+        libxl_domain_resume(&priv->ctx, vm->def->id);
+        goto cleanup;
+    }
+
+    ret = 0;
+
+cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
+    if (event)
+        libxlDomainEventQueue(driver, event);
+    return ret;
+}
+
+static int
+libxlDomainMigratePrepare3(virConnectPtr dconn,
+                            const char *cookiein ATTRIBUTE_UNUSED,
+                            int cookieinlen ATTRIBUTE_UNUSED,
+                            char **cookieout ATTRIBUTE_UNUSED,
+                            int *cookieoutlen ATTRIBUTE_UNUSED,
+                            const char *uri_in,
+                            char **uri_out,
+                            unsigned long flags,
+                            const char *dname,
+                            unsigned long resource ATTRIBUTE_UNUSED,
+                            const char *dom_xml)
+{
+    libxlDriverPrivatePtr driver = dconn->privateData;
+    virDomainDefPtr def = NULL;
+    virDomainObjPtr vm = NULL;
+    int port = 0;
+    int sockfd = -1;
+    struct sockaddr_in addr;
+    migrate_receive_args *args;
+    int ret = -1;
+
+    virCheckFlags(LIBXL_MIGRATION_FLAGS, -1);
+
+    libxlDriverLock(driver);
+    if (!dom_xml) {
+        libxlError(VIR_ERR_OPERATION_INVALID,
+                         _("no domain XML passed"));
+        goto cleanup;
+    }
+
+    def = virDomainDefParseString(driver->caps, dom_xml,
+                                 1 << VIR_DOMAIN_VIRT_XEN,
+                                 VIR_DOMAIN_XML_INACTIVE);
+
+    if (!libxlMigrationToIsAllowed(driver, def)) {
+        libxlError(VIR_ERR_OPERATION_INVALID,
+                         _("cannot migrate domain to this host"));
+        goto cleanup;
+    }
+
+    /* Target domain name, maybe renamed. */
+    if (dname) {
+        def->name = strdup(dname);
+        if (def->name == NULL)
+            goto cleanup;
+    }
+
+    if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0)
+        goto cleanup;
+
+    if (!(vm = virDomainAssignDef(driver->caps, &driver->domains, def, true)))
+        goto cleanup;
+
+    def = NULL;
+
+    /* Create socket connection to receive migration data */
+    if (!uri_in) {
+        *uri_out = virGetHostname(dconn);
+        if (*uri_out == NULL)
+            goto cleanup;
+    } else {
+        char *hostname = NULL;
+        doParseURI(uri_in, &hostname, &port);
+        VIR_FREE (hostname);
+    }
+
+    if (port <= 0)
+        port = DEFAULT_MIGRATION_PORT;
+
+    sockfd = socket(AF_INET, SOCK_STREAM, 0);
+    if (sockfd == -1) {
+       libxlError(VIR_ERR_OPERATION_INVALID,
+                        _("Failed to create socket"));
+       goto cleanup;
+    }
+
+    memset(&addr, 0, sizeof(addr));
+    addr.sin_family = AF_INET;
+    addr.sin_port = htons(port);
+    addr.sin_addr.s_addr = htonl(INADDR_ANY);
+
+    if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+        libxlError(VIR_ERR_OPERATION_FAILED,
+                         _("Bind error"));
+        goto cleanup;
+    }
+
+    if (listen(sockfd, MAXCONN_NUM) < 0){
+        libxlError(VIR_ERR_OPERATION_FAILED,
+                         _("Listen error"));
+        goto cleanup;
+    }
+
+    if (VIR_ALLOC(args) < 0) {
+        virReportOOMError();
+        goto cleanup;
+    }
+
+    args->conn = dconn;
+    args->vm = vm;
+    args->sockfd = sockfd;
+    if (virThreadCreate(&migrate_receive_thread,
+                        true,
+                        doMigrateReceive, args) < 0 ) {
+        virReportSystemError(errno, "%s",
+                             _("Unable to create migration thread"));
+        VIR_FREE(args);
+        goto cleanup;
+    }
+
+    ret = 0;
+    goto end;
+
+cleanup:
+    if (VIR_CLOSE(sockfd) < 0)
+        virReportSystemError(errno, "%s", _("cannot close sockfd"));
+    if (vm)
+        virDomainObjUnlock(vm);
+
+end:
+    libxlDriverUnlock(driver);
+    return ret;
+}
+
+static int
+libxlDomainMigratePerform3(virDomainPtr dom,
+                            const char *xmlin ATTRIBUTE_UNUSED,
+                            const char *cookiein ATTRIBUTE_UNUSED,
+                            int cookieinlen ATTRIBUTE_UNUSED,
+                            char **cookieout ATTRIBUTE_UNUSED,
+                            int *cookieoutlen ATTRIBUTE_UNUSED,
+                            const char *dconnuri ATTRIBUTE_UNUSED,
+                            const char *uri,
+                            unsigned long flags,
+                            const char *dname ATTRIBUTE_UNUSED,
+                            unsigned long resource ATTRIBUTE_UNUSED)
+{
+    libxlDriverPrivatePtr driver = dom->conn->privateData;
+    char *hostname = NULL;
+    int port;
+    char *servname = NULL;
+    struct addrinfo hints, *res;
+    int sockfd = -1;
+    int ret = -1;
+
+    virCheckFlags(LIBXL_MIGRATION_FLAGS, -1);
+
+    libxlDriverLock(driver);
+
+    if (doParseURI(uri, &hostname, &port))
+        goto cleanup;
+
+    VIR_DEBUG("hostname = %s, port = %d", hostname, port);
+
+    if (virAsprintf(&servname, "%d", port ? port : DEFAULT_MIGRATION_PORT) < 0) {
+        virReportOOMError();
+        goto cleanup;
+    }
+
+    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ){
+        libxlError(VIR_ERR_OPERATION_FAILED,
+                         _("Failed to create socket"));
+        goto cleanup;
+    }
+
+    memset(&hints, 0, sizeof(hints));
+    hints.ai_family = AF_INET;
+    hints.ai_socktype = SOCK_STREAM;
+    if (getaddrinfo(hostname, servname, &hints, &res) || res == NULL) {
+        libxlError(VIR_ERR_OPERATION_FAILED,
+                         _("IP address lookup failed"));
+        goto cleanup;
+    }
+
+    if (connect(sockfd, res->ai_addr, res->ai_addrlen) < 0) {
+        libxlError(VIR_ERR_OPERATION_FAILED,
+                         _("Connect error"));
+        goto cleanup;
+    }
+
+    ret = doMigrateSend(dom, flags, sockfd);
+
+cleanup:
+    if (VIR_CLOSE(sockfd) < 0)
+        virReportSystemError(errno, "%s", _("cannot close sockfd"));
+    VIR_FREE (hostname);
+    VIR_FREE(servname);
+    freeaddrinfo(res);
+    libxlDriverUnlock(driver);
+    return ret;
+}
+
+static virDomainPtr
+libxlDomainMigrateFinish3(virConnectPtr dconn,
+                           const char *dname,
+                           const char *cookiein ATTRIBUTE_UNUSED,
+                           int cookieinlen ATTRIBUTE_UNUSED,
+                           char **cookieout ATTRIBUTE_UNUSED,
+                           int *cookieoutlen ATTRIBUTE_UNUSED,
+                           const char *dconnuri ATTRIBUTE_UNUSED,
+                           const char *uri ATTRIBUTE_UNUSED,
+                           unsigned long flags,
+                           int cancelled)
+{
+    libxlDriverPrivatePtr driver = dconn->privateData;
+    virDomainObjPtr vm = NULL;
+    virDomainPtr dom = NULL;
+    libxlDomainObjPrivatePtr priv;
+    virDomainEventPtr event = NULL;
+    int rc;
+
+    virCheckFlags(LIBXL_MIGRATION_FLAGS, NULL);
+    virThreadJoin(&migrate_receive_thread);
+
+    libxlDriverLock(driver);
+    vm = virDomainFindByName(&driver->domains, dname);
+    if (!vm)
+        goto cleanup;
+
+    if (!cancelled) {
+        if (!(flags & VIR_MIGRATE_PAUSED)) {
+            priv = vm->privateData;
+            rc = libxl_domain_unpause(&priv->ctx, vm->def->id);
+            if (rc) {
+                libxlError(VIR_ERR_OPERATION_FAILED,
+                           _("Failed to unpause domain"));
+                goto error;
+            }
+
+            virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_BOOTED);
+            if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
+                goto error;
+        }
+
+        dom = virGetDomain (dconn, vm->def->name, vm->def->uuid);
+        goto cleanup;
+    }
+
+error:
+    if (libxlVmReap(driver, vm, 1, VIR_DOMAIN_SHUTOFF_SAVED)) {
+        libxlError(VIR_ERR_INTERNAL_ERROR,
+                    _("Failed to destroy domain '%d'"), vm->def->id);
+        goto cleanup;
+    }
+    event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
+                                         VIR_DOMAIN_EVENT_STOPPED_SAVED);
+    if (!vm->persistent) {
+        virDomainRemoveInactive(&driver->domains, vm);
+        vm = NULL;
+    }
+
+cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
+    if (event)
+        libxlDomainEventQueue(driver, event);
+    libxlDriverUnlock(driver);
+    return dom;
+}
+
+static int
+libxlDomainMigrateConfirm3(virDomainPtr domain,
+                            const char *cookiein ATTRIBUTE_UNUSED,
+                            int cookieinlen ATTRIBUTE_UNUSED,
+                            unsigned long flags,
+                            int cancelled)
+{
+    libxlDriverPrivatePtr driver = domain->conn->privateData;
+    virDomainObjPtr vm;
+    libxlDomainObjPrivatePtr priv;
+    virDomainEventPtr event = NULL;
+    int ret = -1;
+
+    virCheckFlags(LIBXL_MIGRATION_FLAGS, -1);
+
+    libxlDriverLock(driver);
+    vm = virDomainFindByUUID(&driver->domains, domain->uuid);
+    if (!vm) {
+        char uuidstr[VIR_UUID_STRING_BUFLEN];
+        virUUIDFormat(domain->uuid, uuidstr);
+        libxlError(VIR_ERR_NO_DOMAIN,
+                        _("no domain with matching uuid '%s'"), uuidstr);
+        goto cleanup;
+    }
+
+    if (cancelled) {
+        priv = vm->privateData;
+        libxlError(VIR_ERR_INTERNAL_ERROR,
+                         _("migration failed, try to resume on our end"));
+        if (!libxl_domain_resume(&priv->ctx, vm->def->id))
+            ret = 0;
+
+        goto cleanup;
+    }
+
+    if (libxlVmReap(driver, vm, 1, VIR_DOMAIN_SHUTOFF_SAVED)) {
+        libxlError(VIR_ERR_INTERNAL_ERROR,
+                    _("Failed to destroy domain '%d'"), vm->def->id);
+        goto cleanup;
+    }
+
+    event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
+                                         VIR_DOMAIN_EVENT_STOPPED_SAVED);
+
+    if (flags & VIR_MIGRATE_UNDEFINE_SOURCE)
+        virDomainDeleteConfig(driver->configDir, driver->autostartDir, vm);
+
+    if (!vm->persistent || (flags & VIR_MIGRATE_UNDEFINE_SOURCE)) {
+        virDomainRemoveInactive(&driver->domains, vm);
+        vm = NULL;
+    }
+
+    VIR_DEBUG("Migration successful.\n");
+    ret = 0;
+
+cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
+    libxlDriverUnlock(driver);
+    return ret;
+}
 
 static virDriver libxlDriver = {
     .no = VIR_DRV_LIBXL,
     .name = "xenlight",
     .open = libxlOpen, /* 0.9.0 */
     .close = libxlClose, /* 0.9.0 */
+    .supports_feature = libxlSupportsFeature, /* 0.9.9 */
     .type = libxlGetType, /* 0.9.0 */
     .version = libxlGetVersion, /* 0.9.0 */
     .getHostname = virGetHostname, /* 0.9.0 */
@@ -3906,6 +4518,11 @@ static virDriver libxlDriver = {
     .domainGetSchedulerParametersFlags = libxlDomainGetSchedulerParametersFlags, /* 0.9.2 */
     .domainSetSchedulerParameters = libxlDomainSetSchedulerParameters, /* 0.9.0 */
     .domainSetSchedulerParametersFlags = libxlDomainSetSchedulerParametersFlags, /* 0.9.2 */
+    .domainMigrateBegin3 = libxlDomainMigrateBegin3, /* 0.9.9 */
+    .domainMigratePrepare3 = libxlDomainMigratePrepare3, /* 0.9.0 */
+    .domainMigratePerform3 = libxlDomainMigratePerform3, /* 0.9.9 */
+    .domainMigrateFinish3 = libxlDomainMigrateFinish3, /* 0.9.9 */
+    .domainMigrateConfirm3 = libxlDomainMigrateConfirm3, /* 0.9.9 */
     .nodeGetFreeMemory = libxlNodeGetFreeMemory, /* 0.9.0 */
     .domainEventRegister = libxlDomainEventRegister, /* 0.9.0 */
     .domainEventDeregister = libxlDomainEventDeregister, /* 0.9.0 */
diff --git a/src/libxl/libxl_driver.h b/src/libxl/libxl_driver.h
index 4632d33..8a5fa6b 100644
--- a/src/libxl/libxl_driver.h
+++ b/src/libxl/libxl_driver.h
@@ -21,9 +21,22 @@
 /*---------------------------------------------------------------------------*/
 
 #ifndef LIBXL_DRIVER_H
-# define LIBXL_DRIVER_H
+#define LIBXL_DRIVER_H
 
-# include <config.h>
+#include <config.h>
+
+#define LIBXL_MIGRATION_FLAGS                   \
+    (VIR_MIGRATE_LIVE |                         \
+     VIR_MIGRATE_UNDEFINE_SOURCE |              \
+     VIR_MIGRATE_PAUSED)
+
+#define DEFAULT_MIGRATION_PORT 8002
+#define MAXCONN_NUM 10
+
+static const char migrate_receiver_banner[]=
+    "xl migration receiver ready, send binary domain data";
+static const char migrate_receiver_ready[]=
+    "domain received, ready to unpause";
 
 int libxlRegister(void);
 
-- 
1.7.3.4




More information about the libvir-list mailing list