[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH V3] libxl: add migration support



Opps, forgot --subject-prefix="PATCH V3" when sending this patch...

Regards,
Jim

Jim Fehlig wrote:
> This patch adds initial migration support to the libxl driver,
> using the VIR_DRV_FEATURE_MIGRATION_PARAMS family of migration
> functions.
>
> Signed-off-by: Jim Fehlig <jfehlig@xxxxxxxx>
> ---
>
> V3 of patch to add migration support to the libxl driver.  V2 is here
>
> https://www.redhat.com/archives/libvir-list/2014-March/msg00880.html
>
> Patches 1-12 in the original series have been pushed, leaving only
> this patch to complete the migration support.
>
> This version adds a simple, extensible messaging protocol to coordinate
> transfer of migration data between libxl hosts.  Michal Privoznik
> noted the even simpler protocol in V2 was not extensible, which in the
> end was a good point IMO so I've tried to address that with V3.
>
> Comments welcome.  Thanks!
>
>  po/POTFILES.in              |   1 +
>  src/Makefile.am             |   3 +-
>  src/libxl/libxl_conf.h      |   6 +
>  src/libxl/libxl_domain.h    |   1 +
>  src/libxl/libxl_driver.c    | 221 +++++++++++
>  src/libxl/libxl_migration.c | 920 
> ++++++++++++++++++++++++++++++++++++++++++++
>  src/libxl/libxl_migration.h |  78 ++++
>  7 files changed, 1229 insertions(+), 1 deletion(-)
>
> diff --git a/po/POTFILES.in b/po/POTFILES.in
> index 122b853..5618631 100644
> --- a/po/POTFILES.in
> +++ b/po/POTFILES.in
> @@ -73,6 +73,7 @@ src/lxc/lxc_process.c
>  src/libxl/libxl_domain.c
>  src/libxl/libxl_driver.c
>  src/libxl/libxl_conf.c
> +src/libxl/libxl_migration.c
>  src/network/bridge_driver.c
>  src/network/bridge_driver_linux.c
>  src/node_device/node_device_driver.c
> diff --git a/src/Makefile.am b/src/Makefile.am
> index 21d56fc..f0dd4ae 100644
> --- a/src/Makefile.am
> +++ b/src/Makefile.am
> @@ -702,7 +702,8 @@ XENAPI_DRIVER_SOURCES =                                   
>         \
>  LIBXL_DRIVER_SOURCES =                                               \
>               libxl/libxl_conf.c libxl/libxl_conf.h           \
>               libxl/libxl_domain.c libxl/libxl_domain.h       \
> -             libxl/libxl_driver.c libxl/libxl_driver.h
> +             libxl/libxl_driver.c libxl/libxl_driver.h       \
> +             libxl/libxl_migration.c libxl/libxl_migration.h
>  
>  UML_DRIVER_SOURCES =                                         \
>               uml/uml_conf.c uml/uml_conf.h                   \
> diff --git a/src/libxl/libxl_conf.h b/src/libxl/libxl_conf.h
> index 24e1720..b798567 100644
> --- a/src/libxl/libxl_conf.h
> +++ b/src/libxl/libxl_conf.h
> @@ -43,6 +43,9 @@
>  # define LIBXL_VNC_PORT_MIN  5900
>  # define LIBXL_VNC_PORT_MAX  65535
>  
> +# define LIBXL_MIGRATION_PORT_MIN  49152
> +# define LIBXL_MIGRATION_PORT_MAX  49216
> +
>  # define LIBXL_CONFIG_DIR SYSCONFDIR "/libvirt/libxl"
>  # define LIBXL_AUTOSTART_DIR LIBXL_CONFIG_DIR "/autostart"
>  # define LIBXL_STATE_DIR LOCALSTATEDIR "/run/libvirt/libxl"
> @@ -115,6 +118,9 @@ struct _libxlDriverPrivate {
>      /* Immutable pointer, self-locking APIs */
>      virPortAllocatorPtr reservedVNCPorts;
>  
> +    /* Immutable pointer, self-locking APIs */
> +    virPortAllocatorPtr migrationPorts;
> +
>      /* Immutable pointer, lockless APIs*/
>      virSysinfoDefPtr hostsysinfo;
>  };
> diff --git a/src/libxl/libxl_domain.h b/src/libxl/libxl_domain.h
> index 979ce2a..9d48049 100644
> --- a/src/libxl/libxl_domain.h
> +++ b/src/libxl/libxl_domain.h
> @@ -69,6 +69,7 @@ struct _libxlDomainObjPrivate {
>      virChrdevsPtr devs;
>      libxl_evgen_domain_death *deathW;
>      libxlDriverPrivatePtr driver;
> +    unsigned short migrationPort;
>  
>      struct libxlDomainJobObj job;
>  };
> diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
> index a6ae8a1..acf68b8 100644
> --- a/src/libxl/libxl_driver.c
> +++ b/src/libxl/libxl_driver.c
> @@ -45,6 +45,7 @@
>  #include "libxl_domain.h"
>  #include "libxl_driver.h"
>  #include "libxl_conf.h"
> +#include "libxl_migration.h"
>  #include "xen_xm.h"
>  #include "xen_sxpr.h"
>  #include "virtypedparam.h"
> @@ -209,6 +210,7 @@ libxlStateCleanup(void)
>      virObjectUnref(libxl_driver->xmlopt);
>      virObjectUnref(libxl_driver->domains);
>      virObjectUnref(libxl_driver->reservedVNCPorts);
> +    virObjectUnref(libxl_driver->migrationPorts);
>  
>      virObjectEventStateFree(libxl_driver->domainEventState);
>      virSysinfoDefFree(libxl_driver->hostsysinfo);
> @@ -296,6 +298,13 @@ libxlStateInitialize(bool privileged,
>                                LIBXL_VNC_PORT_MAX)))
>          goto error;
>  
> +    /* Allocate bitmap for migration port reservation */
> +    if (!(libxl_driver->migrationPorts =
> +          virPortAllocatorNew(_("migration"),
> +                              LIBXL_MIGRATION_PORT_MIN,
> +                              LIBXL_MIGRATION_PORT_MAX)))
> +        goto error;
> +
>      if (!(libxl_driver->domains = virDomainObjListNew()))
>          goto error;
>  
> @@ -4120,6 +4129,7 @@ libxlConnectSupportsFeature(virConnectPtr conn, int 
> feature)
>  
>      switch (feature) {
>      case VIR_DRV_FEATURE_TYPED_PARAM_STRING:
> +    case VIR_DRV_FEATURE_MIGRATION_PARAMS:
>          return 1;
>      default:
>          return 0;
> @@ -4298,6 +4308,212 @@ libxlNodeDeviceReset(virNodeDevicePtr dev)
>      return ret;
>  }
>  
> +static char *
> +libxlDomainMigrateBegin3Params(virDomainPtr domain,
> +                               virTypedParameterPtr params,
> +                               int nparams,
> +                               char **cookieout ATTRIBUTE_UNUSED,
> +                               int *cookieoutlen ATTRIBUTE_UNUSED,
> +                               unsigned int flags)
> +{
> +    const char *xmlin = NULL;
> +    virDomainObjPtr vm = NULL;
> +
> +    virCheckFlags(LIBXL_MIGRATION_FLAGS, NULL);
> +    if (virTypedParamsValidate(params, nparams, LIBXL_MIGRATION_PARAMETERS) 
> < 0)
> +        return NULL;
> +
> +    if (virTypedParamsGetString(params, nparams,
> +                                VIR_MIGRATE_PARAM_DEST_XML,
> +                                &xmlin) < 0)
> +        return NULL;
> +
> +    if (!(vm = libxlDomObjFromDomain(domain)))
> +        return NULL;
> +
> +    if (virDomainMigrateBegin3ParamsEnsureACL(domain->conn, vm->def) < 0) {
> +        virObjectUnlock(vm);
> +        return NULL;
> +    }
> +
> +    if (!virDomainObjIsActive(vm)) {
> +        virReportError(VIR_ERR_OPERATION_INVALID,
> +                       "%s", _("domain is not running"));
> +        virObjectUnlock(vm);
> +        return NULL;
> +    }
> +
> +    return libxlDomainMigrationBegin(domain->conn, vm, xmlin);
> +}
> +
> +static int
> +libxlDomainMigratePrepare3Params(virConnectPtr dconn,
> +                                 virTypedParameterPtr params,
> +                                 int nparams,
> +                                 const char *cookiein ATTRIBUTE_UNUSED,
> +                                 int cookieinlen ATTRIBUTE_UNUSED,
> +                                 char **cookieout ATTRIBUTE_UNUSED,
> +                                 int *cookieoutlen ATTRIBUTE_UNUSED,
> +                                 char **uri_out,
> +                                 unsigned int flags)
> +{
> +    libxlDriverPrivatePtr driver = dconn->privateData;
> +    virDomainDefPtr def = NULL;
> +    const char *dom_xml = NULL;
> +    const char *dname = NULL;
> +    const char *uri_in = NULL;
> +
> +    virCheckFlags(LIBXL_MIGRATION_FLAGS, -1);
> +    if (virTypedParamsValidate(params, nparams, LIBXL_MIGRATION_PARAMETERS) 
> < 0)
> +        goto error;
> +
> +    if (virTypedParamsGetString(params, nparams,
> +                                VIR_MIGRATE_PARAM_DEST_XML,
> +                                &dom_xml) < 0 ||
> +        virTypedParamsGetString(params, nparams,
> +                                VIR_MIGRATE_PARAM_DEST_NAME,
> +                                &dname) < 0 ||
> +        virTypedParamsGetString(params, nparams,
> +                                VIR_MIGRATE_PARAM_URI,
> +                                &uri_in) < 0)
> +
> +        goto error;
> +
> +    if (!(def = libxlDomainMigrationPrepareDef(driver, dom_xml, dname)))
> +        goto error;
> +
> +    if (virDomainMigratePrepare3ParamsEnsureACL(dconn, def) < 0)
> +        goto error;
> +
> +    if (libxlDomainMigrationPrepare(dconn, def, uri_in, uri_out) < 0)
> +        goto error;
> +
> +    return 0;
> +
> + error:
> +    virDomainDefFree(def);
> +    return -1;
> +}
> +
> +static int
> +libxlDomainMigratePerform3Params(virDomainPtr dom,
> +                                 const char *dconnuri,
> +                                 virTypedParameterPtr params,
> +                                 int nparams,
> +                                 const char *cookiein ATTRIBUTE_UNUSED,
> +                                 int cookieinlen ATTRIBUTE_UNUSED,
> +                                 char **cookieout ATTRIBUTE_UNUSED,
> +                                 int *cookieoutlen ATTRIBUTE_UNUSED,
> +                                 unsigned int flags)
> +{
> +    libxlDriverPrivatePtr driver = dom->conn->privateData;
> +    virDomainObjPtr vm = NULL;
> +    const char *dom_xml = NULL;
> +    const char *dname = NULL;
> +    const char *uri = NULL;
> +    int ret = -1;
> +
> +    virCheckFlags(LIBXL_MIGRATION_FLAGS, -1);
> +    if (virTypedParamsValidate(params, nparams, LIBXL_MIGRATION_PARAMETERS) 
> < 0)
> +        goto cleanup;
> +
> +    if (virTypedParamsGetString(params, nparams,
> +                                VIR_MIGRATE_PARAM_DEST_XML,
> +                                &dom_xml) < 0 ||
> +        virTypedParamsGetString(params, nparams,
> +                                VIR_MIGRATE_PARAM_DEST_NAME,
> +                                &dname) < 0 ||
> +        virTypedParamsGetString(params, nparams,
> +                                VIR_MIGRATE_PARAM_URI,
> +                                &uri) < 0)
> +
> +        goto cleanup;
> +
> +    if (!(vm = libxlDomObjFromDomain(dom)))
> +        goto cleanup;
> +
> +    if (virDomainMigratePerform3ParamsEnsureACL(dom->conn, vm->def) < 0)
> +        goto cleanup;
> +
> +    if (libxlDomainMigrationPerform(driver, vm, dom_xml, dconnuri,
> +                                    uri, dname, flags) < 0)
> +        goto cleanup;
> +
> +    ret = 0;
> +
> + cleanup:
> +    if (vm)
> +        virObjectUnlock(vm);
> +    return ret;
> +}
> +
> +static virDomainPtr
> +libxlDomainMigrateFinish3Params(virConnectPtr dconn,
> +                                virTypedParameterPtr params,
> +                                int nparams,
> +                                const char *cookiein ATTRIBUTE_UNUSED,
> +                                int cookieinlen ATTRIBUTE_UNUSED,
> +                                char **cookieout ATTRIBUTE_UNUSED,
> +                                int *cookieoutlen ATTRIBUTE_UNUSED,
> +                                unsigned int flags,
> +                                int cancelled)
> +{
> +    libxlDriverPrivatePtr driver = dconn->privateData;
> +    virDomainObjPtr vm = NULL;
> +    const char *dname = NULL;
> +
> +    virCheckFlags(LIBXL_MIGRATION_FLAGS, NULL);
> +    if (virTypedParamsValidate(params, nparams, LIBXL_MIGRATION_PARAMETERS) 
> < 0)
> +        return NULL;
> +
> +    if (virTypedParamsGetString(params, nparams,
> +                                VIR_MIGRATE_PARAM_DEST_NAME,
> +                                &dname) < 0)
> +        return NULL;
> +
> +    if (!dname ||
> +        !(vm = virDomainObjListFindByName(driver->domains, dname))) {
> +        virReportError(VIR_ERR_NO_DOMAIN,
> +                       _("no domain with matching name '%s'"),
> +                       NULLSTR(dname));
> +        return NULL;
> +    }
> +
> +    if (virDomainMigrateFinish3ParamsEnsureACL(dconn, vm->def) < 0) {
> +        virObjectUnlock(vm);
> +        return NULL;
> +    }
> +
> +    return libxlDomainMigrationFinish(dconn, vm, flags, cancelled);
> +}
> +
> +static int
> +libxlDomainMigrateConfirm3Params(virDomainPtr domain,
> +                                 virTypedParameterPtr params,
> +                                 int nparams,
> +                                 const char *cookiein ATTRIBUTE_UNUSED,
> +                                 int cookieinlen ATTRIBUTE_UNUSED,
> +                                 unsigned int flags,
> +                                 int cancelled)
> +{
> +    libxlDriverPrivatePtr driver = domain->conn->privateData;
> +    virDomainObjPtr vm = NULL;
> +
> +    virCheckFlags(LIBXL_MIGRATION_FLAGS, -1);
> +    if (virTypedParamsValidate(params, nparams, LIBXL_MIGRATION_PARAMETERS) 
> < 0)
> +        return -1;
> +
> +    if (!(vm = libxlDomObjFromDomain(domain)))
> +        return -1;
> +
> +    if (virDomainMigrateConfirm3ParamsEnsureACL(domain->conn, vm->def) < 0) {
> +        virObjectUnlock(vm);
> +        return -1;
> +    }
> +
> +    return libxlDomainMigrationConfirm(driver, vm, flags, cancelled);
> +}
> +
>  
>  static virDriver libxlDriver = {
>      .no = VIR_DRV_LIBXL,
> @@ -4388,6 +4604,11 @@ static virDriver libxlDriver = {
>      .nodeDeviceDetachFlags = libxlNodeDeviceDetachFlags, /* 1.2.3 */
>      .nodeDeviceReAttach = libxlNodeDeviceReAttach, /* 1.2.3 */
>      .nodeDeviceReset = libxlNodeDeviceReset, /* 1.2.3 */
> +    .domainMigrateBegin3Params = libxlDomainMigrateBegin3Params, /* 1.2.3 */
> +    .domainMigratePrepare3Params = libxlDomainMigratePrepare3Params, /* 
> 1.2.3 */
> +    .domainMigratePerform3Params = libxlDomainMigratePerform3Params, /* 
> 1.2.3 */
> +    .domainMigrateFinish3Params = libxlDomainMigrateFinish3Params, /* 1.2.3 
> */
> +    .domainMigrateConfirm3Params = libxlDomainMigrateConfirm3Params, /* 
> 1.2.3 */
>  };
>  
>  static virStateDriver libxlStateDriver = {
> diff --git a/src/libxl/libxl_migration.c b/src/libxl/libxl_migration.c
> new file mode 100644
> index 0000000..4b74ef4
> --- /dev/null
> +++ b/src/libxl/libxl_migration.c
> @@ -0,0 +1,920 @@
> +/*
> + * libxl_migration.c: methods for handling migration with libxenlight
> + *
> + * Copyright (C) 2014 SUSE LINUX Products GmbH, Nuernberg, Germany.
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library.  If not, see
> + * <http://www.gnu.org/licenses/>.
> + *
> + * Authors:
> + *     Jim Fehlig <jfehlig@xxxxxxxx>
> + *     Chunyan Liu <cyliu@xxxxxxxx>
> + */
> +
> +#include <config.h>
> +
> +#include "internal.h"
> +#include "virlog.h"
> +#include "virerror.h"
> +#include "virconf.h"
> +#include "datatypes.h"
> +#include "virfile.h"
> +#include "viralloc.h"
> +#include "viruuid.h"
> +#include "vircommand.h"
> +#include "virstring.h"
> +#include "rpc/virnetsocket.h"
> +#include "libxl_domain.h"
> +#include "libxl_driver.h"
> +#include "libxl_conf.h"
> +#include "libxl_migration.h"
> +
> +#define VIR_FROM_THIS VIR_FROM_LIBXL
> +
> +VIR_LOG_INIT("libxl.libxl_migration");
> +
> +#define LIBXL_MIGRATION_PROTO_VERSION 1
> +
> +typedef struct _libxlMigrateReceiveArgs {
> +    virConnectPtr conn;
> +    virDomainObjPtr vm;
> +
> +    /* for freeing listen sockets */
> +    virNetSocketPtr *socks;
> +    size_t nsocks;
> +} libxlMigrateReceiveArgs;
> +
> +/*
> + * For future extensibility, a simple messaging protocol used to send 
> migration
> + * data between libxl hosts.  The message is encapsulated in json and 
> currently
> + * includes the following entries:
> + *
> + * {"libvirt-libxl-mig-msg" :
> + *   {"version" : $ver},
> + *   {"state" : $state},
> + *   {"status" : $status}
> + * }
> + *
> + * Possible $state values are "negotiate-version", "send-binary-data",
> + * "sending-binary-data", "received-binary-data", "done", and "error".
> + *
> + * Migration between source and destination libxl hosts is performed with the
> + * following message exchange:
> + *
> + * - src->dst: connect
> + * - dst->src: state="negotiate-version", 
> version=LIBXL_MIGRATION_PROTO_VERSION
> + * - src->dst: state-"negotiate-version",
> + *             version=min(dst ver,  LIBXL_MIGRATION_PROTO_VERSION)
> + * - dst->src: state="send-binary-data", version=negotiatedversion
> + * - src->dst: state="sending-binary-data", version=negotiatedversion
> + * _ src->dst: binary migration data
> + * - dst->src: state="received-binary-data", version=negotiatedversion
> + * - src->dst: state="done", version=negotiatedversion
> + *
> + */
> +
> +static virJSONValuePtr
> +libxlMigrationMsgNew(const char *state)
> +{
> +    virJSONValuePtr msg;
> +    virJSONValuePtr body;
> +
> +    if (!(msg = virJSONValueNewObject()))
> +        return NULL;
> +
> +    if (!(body = virJSONValueNewObject())) {
> +        virJSONValueFree(msg);
> +        return NULL;
> +    }
> +
> +    virJSONValueObjectAppendNumberInt(body, "version",
> +                                      LIBXL_MIGRATION_PROTO_VERSION);
> +    virJSONValueObjectAppendString(body, "state", state);
> +    virJSONValueObjectAppendNumberInt(body, "status", 0);
> +
> +    virJSONValueObjectAppend(msg, "libvirt-libxl-mig-msg", body);
> +
> +    return msg;
> +}
> +
> +static bool
> +libxlMigrationMsgIsState(virJSONValuePtr message, const char *state)
> +{
> +    virJSONValuePtr body;
> +    const char *msg_state;
> +
> +    if (!(body = virJSONValueObjectGet(message, "libvirt-libxl-mig-msg")))
> +        return false;
> +
> +    msg_state = virJSONValueObjectGetString(body, "state");
> +    if (!msg_state || STRNEQ(msg_state, state))
> +        return false;
> +
> +    return true;
> +}
> +
> +static int
> +libxlMigrationMsgSetState(virJSONValuePtr message, const char *state)
> +{
> +    virJSONValuePtr body;
> +
> +    if (!(body = virJSONValueObjectGet(message, "libvirt-libxl-mig-msg")))
> +        return -1;
> +
> +    virJSONValueObjectRemoveKey(body, "state", NULL);
> +    virJSONValueObjectAppendString(body, "state", state);
> +
> +    return 0;
> +}
> +
> +
> +static int
> +libxlMigrationMsgSend(int fd, virJSONValuePtr message, int status)
> +{
> +    int ret = -1;
> +    virJSONValuePtr body;
> +    int len;
> +    char *msgstr;
> +
> +    if (!(body = virJSONValueObjectGet(message, "libvirt-libxl-mig-msg")))
> +        return -1;
> +
> +    virJSONValueObjectRemoveKey(body, "status", NULL);
> +    virJSONValueObjectAppendNumberInt(body, "status", status);
> +
> +    if (!(msgstr = virJSONValueToString(message, false)))
> +        return -1;
> +
> +    VIR_DEBUG("Sending migration message %s", msgstr);
> +    len = strlen(msgstr) + 1;
> +    if (safewrite(fd, msgstr, len) != len) {
> +        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
> +                       _("Failed to send migration message"));
> +        goto cleanup;
> +    }
> +
> +    ret = 0;
> +
> + cleanup:
> +    VIR_FREE(msgstr);
> +    return ret;
> +}
> +
> +static virJSONValuePtr
> +libxlMigrationMsgReceive(int fd)
> +{
> +    char buf[512];
> +    int ret;
> +    virJSONValuePtr msg = NULL;
> +    virJSONValuePtr body;
> +    int status;
> +    size_t i;
> +
> +    for (i = 0; i < sizeof(buf);) {
> +        ret = saferead(fd, &(buf[i]), 1);
> +        if (ret == -1 && errno != EAGAIN)
> +            goto error;
> +        if (ret == 1) {
> +            if (buf[i] == '\0')
> +                break;
> +            i++;
> +        }
> +    }
> +
> +    VIR_DEBUG("Received migration message %s", buf);
> +    if (!(msg = virJSONValueFromString(buf)))
> +        return NULL;
> +
> +    if (!(body = virJSONValueObjectGet(msg, "libvirt-libxl-mig-msg")))
> +        goto error;
> +
> +    if (virJSONValueObjectGetNumberInt(body, "status", &status) < 0)
> +        goto error;
> +
> +    if (status != 0)
> +        goto error;
> +
> +    return msg;
> +
> + error:
> +    virReportError(VIR_ERR_OPERATION_FAILED, "%s",
> +                   _("Failed to receive migration message"));
> +    virJSONValueFree(msg);
> +    return NULL;
> +}
> +
> +static int
> +libxlMigrationSrcNegotiate(int fd)
> +{
> +    int ret = -1;
> +    virJSONValuePtr msg;
> +    virJSONValuePtr body;
> +    int ver;
> +
> +    if (!(msg = libxlMigrationMsgReceive(fd)))
> +        return -1;
> +
> +    if (!libxlMigrationMsgIsState(msg, "negotiate-version"))
> +        goto cleanup;
> +    /*
> +     * ACK by returning the message, with version set to
> +     * min(dest ver, src ver)
> +     */
> +    if (!(body = virJSONValueObjectGet(msg, "libvirt-libxl-mig-msg")))
> +        goto cleanup;
> +
> +    if (virJSONValueObjectGetNumberInt(body, "version", &ver) < 0)
> +        goto cleanup;
> +    if (ver > LIBXL_MIGRATION_PROTO_VERSION) {
> +        virJSONValueObjectRemoveKey(body, "version", NULL);
> +        virJSONValueObjectAppendNumberInt(body,
> +                                          "version",
> +                                          LIBXL_MIGRATION_PROTO_VERSION);
> +    }
> +
> +    if (libxlMigrationMsgSend(fd, msg, 0) < 0)
> +        goto cleanup;
> +
> +    ret = 0;
> +
> + cleanup:
> +    virJSONValueFree(msg);
> +    return ret;
> +}
> +
> +static int
> +libxlMigrationDstNegotiate(int fd, virJSONValuePtr *message)
> +{
> +    virJSONValuePtr msg;
> +
> +    if (!(msg = libxlMigrationMsgNew("negotiate-version")))
> +            return -1;
> +
> +    if (libxlMigrationMsgSend(fd, msg, 0) < 0) {
> +        virJSONValueFree(msg);
> +        return -1;
> +    }
> +
> +    /*
> +     * Receive ACK.  src set version=min(dst ver, highest src ver),
> +     * which is the negotiated version.  Use this message with
> +     * negotiated version throughout the transaction.
> +     */
> +    virJSONValueFree(msg);
> +    if (!(msg = libxlMigrationMsgReceive(fd)))
> +        return -1;
> +
> +    *message = msg;
> +    return 0;
> +}
> +
> +static int
> +libxlMigrationSrcReady(int fd)
> +{
> +    int ret = -1;
> +    virJSONValuePtr msg;
> +
> +    if (!(msg = libxlMigrationMsgReceive(fd)))
> +        return -1;
> +
> +    if (!libxlMigrationMsgIsState(msg, "send-binary-data"))
> +        goto cleanup;
> +
> +    /* ACK by returning the message with state sending */
> +    libxlMigrationMsgSetState(msg, "sending-binary-data");
> +    if (libxlMigrationMsgSend(fd, msg, 0) < 0)
> +        goto cleanup;
> +
> +    ret = 0;
> +
> + cleanup:
> +    virJSONValueFree(msg);
> +    return ret;
> +}
> +
> +static int
> +libxlMigrationDstReady(int fd, virJSONValuePtr msg)
> +{
> +    int ret = -1;
> +    virJSONValuePtr tmp = NULL;
> +
> +    libxlMigrationMsgSetState(msg, "send-binary-data");
> +    if (libxlMigrationMsgSend(fd, msg, 0) < 0)
> +        return -1;
> +
> +    /* Receive ACK, state sending */
> +    if (!(tmp = libxlMigrationMsgReceive(fd)))
> +            return -1;
> +    if (!libxlMigrationMsgIsState(tmp, "sending-binary-data"))
> +        goto cleanup;
> +
> +    ret = 0;
> +
> + cleanup:
> +    virJSONValueFree(tmp);
> +    return ret;
> +}
> +
> +static int
> +libxlMigrationSrcDone(int fd)
> +{
> +    int ret = -1;
> +    virJSONValuePtr msg;
> +
> +    if (!(msg = libxlMigrationMsgReceive(fd)))
> +        return -1;
> +
> +    if (!libxlMigrationMsgIsState(msg, "received-binary-data"))
> +        goto cleanup;
> +
> +    /* ACK by returning the message with state done */
> +    libxlMigrationMsgSetState(msg, "done");
> +    if (libxlMigrationMsgSend(fd, msg, 0) < 0)
> +        goto cleanup;
> +
> +    ret = 0;
> +
> + cleanup:
> +    virJSONValueFree(msg);
> +    return ret;
> +}
> +
> +static int
> +libxlMigrationDestDone(int fd, virJSONValuePtr msg)
> +{
> +    int ret = -1;
> +    virJSONValuePtr tmp;
> +
> +    libxlMigrationMsgSetState(msg, "received-binary-data");
> +    if (libxlMigrationMsgSend(fd, msg, 0) < 0)
> +        return -1;
> +
> +    /* Receive ACK, state done */
> +    if (!(tmp = libxlMigrationMsgReceive(fd)))
> +        return -1;
> +    if (!libxlMigrationMsgIsState(tmp, "done"))
> +        goto cleanup;
> +
> +    ret = 0;
> +
> + cleanup:
> +    virJSONValueFree(tmp);
> +    return ret;
> +}
> +
> +static void
> +libxlMigrationSrcFailed(int fd, int status)
> +{
> +    virJSONValuePtr msg;
> +
> +    if (!(msg = libxlMigrationMsgNew("error")))
> +            return;
> +    libxlMigrationMsgSend(fd, msg, status);
> +    virJSONValueFree(msg);
> +}
> +
> +static void
> +libxlMigrationDstFailed(int fd, virJSONValuePtr msg, int status)
> +{
> +    libxlMigrationMsgSetState(msg, "error");
> +    libxlMigrationMsgSend(fd, msg, status);
> +}
> +
> +static void
> +libxlDoMigrateReceive(virNetSocketPtr sock,
> +                      int events ATTRIBUTE_UNUSED,
> +                      void *opaque)
> +{
> +    libxlMigrateReceiveArgs *data = opaque;
> +    virConnectPtr conn = data->conn;
> +    virDomainObjPtr vm = data->vm;
> +    libxlDomainObjPrivatePtr priv = vm->privateData;
> +    virNetSocketPtr *socks = data->socks;
> +    size_t nsocks = data->nsocks;
> +    libxlDriverPrivatePtr driver = conn->privateData;
> +    virNetSocketPtr client_sock;
> +    virJSONValuePtr mig_msg = NULL;
> +    int recvfd;
> +    size_t i;
> +    int ret;
> +
> +    virNetSocketAccept(sock, &client_sock);
> +    if (client_sock == NULL) {
> +        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
> +                       _("Fail to accept migration connection"));
> +        goto cleanup;
> +    }
> +    VIR_DEBUG("Accepted migration connection\n");
> +    recvfd = virNetSocketDupFD(client_sock, true);
> +    virObjectUnref(client_sock);
> +
> +    if (libxlMigrationDstNegotiate(recvfd, &mig_msg) < 0)
> +        goto cleanup;
> +
> +    if (libxlMigrationDstReady(recvfd, mig_msg) < 0)
> +        goto cleanup;
> +
> +    virObjectLock(vm);
> +    ret = libxlDomainStart(driver, vm, false, recvfd);
> +    virObjectUnlock(vm);
> +
> +    if (ret < 0) {
> +        libxlMigrationDstFailed(recvfd, mig_msg, ret);
> +        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                       _("Failed to restore domain with libxenlight"));
> +        if (!vm->persistent)
> +            virDomainObjListRemove(driver->domains, vm);
> +        goto cleanup;
> +    }
> +
> +    if (libxlMigrationDestDone(recvfd, mig_msg) < 0) {
> +        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
> +                       _("Failed to notify sender that migration 
> completed"));
> +        goto cleanup_dom;
> +    }
> +
> +    /* Remove all listen socks from event handler, and close them. */
> +    for (i = 0; i < nsocks; i++) {
> +        virNetSocketUpdateIOCallback(socks[i], 0);
> +        virNetSocketRemoveIOCallback(socks[i]);
> +        virNetSocketClose(socks[i]);
> +        virObjectUnref(socks[i]);
> +    }
> +    VIR_FREE(socks);
> +    goto cleanup;
> +
> + cleanup_dom:
> +    libxl_domain_destroy(priv->ctx, vm->def->id, NULL);
> +    vm->def->id = -1;
> +    if (!vm->persistent)
> +        virDomainObjListRemove(driver->domains, vm);
> +
> + cleanup:
> +    VIR_FORCE_CLOSE(recvfd);
> +    virJSONValueFree(mig_msg);
> +    VIR_FREE(opaque);
> +    return;
> +}
> +
> +static int
> +libxlDoMigrateSend(libxlDriverPrivatePtr driver,
> +                   virDomainObjPtr vm,
> +                   unsigned long flags,
> +                   int sockfd)
> +{
> +    libxlDomainObjPrivatePtr priv;
> +    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
> +    virObjectEventPtr event = NULL;
> +    int xl_flags = 0;
> +    int ret = -1;
> +
> +    if (flags & VIR_MIGRATE_LIVE)
> +        xl_flags = LIBXL_SUSPEND_LIVE;
> +
> +    priv = vm->privateData;
> +
> +    if (libxlMigrationSrcNegotiate(sockfd) < 0)
> +        goto cleanup;
> +
> +    if (libxlMigrationSrcReady(sockfd) < 0)
> +        goto cleanup;
> +
> +    if (libxl_domain_suspend(priv->ctx, vm->def->id,
> +                             sockfd, xl_flags, NULL) != 0) {
> +        libxlMigrationSrcFailed(sockfd, ret);
> +        virReportError(VIR_ERR_INTERNAL_ERROR,
> +                       _("Failed to save domain '%d' with libxenlight"),
> +                       vm->def->id);
> +        goto cleanup;
> +    }
> +
> +    if (libxlMigrationSrcDone(sockfd) < 0) {
> +        if (libxl_domain_resume(priv->ctx, vm->def->id, 0, 0) != 0) {
> +            VIR_DEBUG("Failed to resume domain '%d' with libxenlight",
> +                      vm->def->id);
> +            virDomainObjSetState(vm, VIR_DOMAIN_PAUSED,
> +                                 VIR_DOMAIN_PAUSED_MIGRATION);
> +            event = virDomainEventLifecycleNewFromObj(vm, 
> VIR_DOMAIN_EVENT_SUSPENDED,
> +                                             
> VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED);
> +            if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
> +                goto cleanup;
> +        }
> +        goto cleanup;
> +    }
> +
> +    ret = 0;
> +
> + cleanup:
> +    if (event)
> +        libxlDomainEventQueue(driver, event);
> +    virObjectUnref(cfg);
> +    return ret;
> +}
> +
> +static bool
> +libxlDomainMigrationIsAllowed(virDomainDefPtr def)
> +{
> +    /* Migration is not allowed if definition contains any hostdevs */
> +    if (def->nhostdevs > 0) {
> +        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
> +                       _("domain has assigned host devices"));
> +        return false;
> +    }
> +
> +    return true;
> +}
> +
> +char *
> +libxlDomainMigrationBegin(virConnectPtr conn,
> +                          virDomainObjPtr vm,
> +                          const char *xmlin)
> +{
> +    libxlDriverPrivatePtr driver = conn->privateData;
> +    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
> +    virDomainDefPtr tmpdef = NULL;
> +    virDomainDefPtr def;
> +    char *xml = NULL;
> +
> +    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
> +        goto cleanup;
> +
> +    if (xmlin) {
> +        if (!(tmpdef = virDomainDefParseString(xmlin, cfg->caps,
> +                                               driver->xmlopt,
> +                                               1 << VIR_DOMAIN_VIRT_XEN,
> +                                               VIR_DOMAIN_XML_INACTIVE)))
> +            goto endjob;
> +
> +        def = tmpdef;
> +    } else {
> +        def = vm->def;
> +    }
> +
> +    if (!libxlDomainMigrationIsAllowed(def))
> +        goto endjob;
> +
> +    xml = virDomainDefFormat(def, VIR_DOMAIN_XML_SECURE);
> +
> + cleanup:
> +    if (vm)
> +        virObjectUnlock(vm);
> +
> +    virDomainDefFree(tmpdef);
> +    virObjectUnref(cfg);
> +    return xml;
> +
> + endjob:
> +    if (!libxlDomainObjEndJob(driver, vm))
> +        vm = NULL;
> +    goto cleanup;
> +}
> +
> +virDomainDefPtr
> +libxlDomainMigrationPrepareDef(libxlDriverPrivatePtr driver,
> +                               const char *dom_xml,
> +                               const char *dname)
> +{
> +    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
> +    virDomainDefPtr def;
> +    char *name = NULL;
> +
> +    if (!dom_xml) {
> +        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                       _("no domain XML passed"));
> +        return NULL;
> +    }
> +
> +    if (!(def = virDomainDefParseString(dom_xml, cfg->caps, driver->xmlopt,
> +                                        1 << VIR_DOMAIN_VIRT_XEN,
> +                                        VIR_DOMAIN_XML_INACTIVE)))
> +        goto cleanup;
> +
> +    if (dname) {
> +        name = def->name;
> +        if (VIR_STRDUP(def->name, dname) < 0) {
> +            virDomainDefFree(def);
> +            def = NULL;
> +        }
> +    }
> +
> + cleanup:
> +    virObjectUnref(cfg);
> +    VIR_FREE(name);
> +    return def;
> +}
> +
> +int
> +libxlDomainMigrationPrepare(virConnectPtr dconn,
> +                            virDomainDefPtr def,
> +                            const char *uri_in,
> +                            char **uri_out)
> +{
> +    libxlDriverPrivatePtr driver = dconn->privateData;
> +    virDomainObjPtr vm = NULL;
> +    char *hostname = NULL;
> +    unsigned short port;
> +    char portstr[100];
> +    virURIPtr uri = NULL;
> +    virNetSocketPtr *socks = NULL;
> +    size_t nsocks = 0;
> +    int nsocks_listen = 0;
> +    libxlMigrateReceiveArgs *args;
> +    size_t i;
> +    int ret = -1;
> +
> +    if (!(vm = virDomainObjListAdd(driver->domains, def,
> +                                   driver->xmlopt,
> +                                   VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
> +                                   VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
> +                                   NULL)))
> +        goto cleanup;
> +
> +    /* Create socket connection to receive migration data */
> +    if (!uri_in) {
> +        if ((hostname = virGetHostname()) == NULL)
> +            goto cleanup;
> +
> +        if (STRPREFIX(hostname, "localhost")) {
> +            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                           _("hostname on destination resolved to localhost,"
> +                             " but migration requires an FQDN"));
> +            goto cleanup;
> +        }
> +
> +        if (virPortAllocatorAcquire(driver->migrationPorts, &port) < 0)
> +            goto cleanup;
> +
> +        if (virAsprintf(uri_out, "tcp://%s:%d", hostname, port) < 0)
> +            goto cleanup;
> +    } else {
> +        if (!(STRPREFIX(uri_in, "tcp://"))) {
> +            /* not full URI, add prefix tcp:// */
> +            char *tmp;
> +            if (virAsprintf(&tmp, "tcp://%s", uri_in) < 0)
> +                goto cleanup;
> +            uri = virURIParse(tmp);
> +            VIR_FREE(tmp);
> +        } else {
> +            uri = virURIParse(uri_in);
> +        }
> +
> +        if (uri == NULL) {
> +            virReportError(VIR_ERR_INVALID_ARG,
> +                           _("unable to parse URI: %s"),
> +                           uri_in);
> +            goto cleanup;
> +        }
> +
> +        if (uri->server == NULL) {
> +            virReportError(VIR_ERR_INVALID_ARG,
> +                           _("missing host in migration URI: %s"),
> +                           uri_in);
> +            goto cleanup;
> +        } else {
> +            hostname = uri->server;
> +        }
> +
> +        if (uri->port == 0) {
> +            if (virPortAllocatorAcquire(driver->migrationPorts, &port) < 0)
> +                goto cleanup;
> +
> +        } else {
> +            port = uri->port;
> +        }
> +
> +        if (virAsprintf(uri_out, "tcp://%s:%d", hostname, port) < 0)
> +            goto cleanup;
> +    }
> +
> +    snprintf(portstr, sizeof(portstr), "%d", port);
> +
> +    if (virNetSocketNewListenTCP(hostname, portstr, &socks, &nsocks) < 0) {
> +        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
> +                       _("Fail to create socket for incoming migration"));
> +        goto cleanup;
> +    }
> +
> +    if (VIR_ALLOC(args) < 0)
> +        goto cleanup;
> +
> +    args->conn = dconn;
> +    args->vm = vm;
> +    args->socks = socks;
> +    args->nsocks = nsocks;
> +
> +    for (i = 0; i < nsocks; i++) {
> +        if (virNetSocketSetBlocking(socks[i], true) < 0)
> +             continue;
> +
> +        if (virNetSocketListen(socks[i], 1) < 0)
> +            continue;
> +
> +        if (virNetSocketAddIOCallback(socks[i],
> +                                      0,
> +                                      libxlDoMigrateReceive,
> +                                      args,
> +                                      NULL) < 0) {
> +            continue;
> +        }
> +
> +        virNetSocketUpdateIOCallback(socks[i], VIR_EVENT_HANDLE_READABLE);
> +        nsocks_listen++;
> +    }
> +
> +    if (!nsocks_listen)
> +        goto cleanup;
> +
> +    ret = 0;
> +    goto done;
> +
> + cleanup:
> +    for (i = 0; i < nsocks; i++) {
> +        virNetSocketClose(socks[i]);
> +        virObjectUnref(socks[i]);
> +    }
> +    VIR_FREE(socks);
> +
> + done:
> +    virURIFree(uri);
> +    if (vm)
> +        virObjectUnlock(vm);
> +    return ret;
> +}
> +
> +int
> +libxlDomainMigrationPerform(libxlDriverPrivatePtr driver,
> +                            virDomainObjPtr vm,
> +                            const char *dom_xml ATTRIBUTE_UNUSED,
> +                            const char *dconnuri ATTRIBUTE_UNUSED,
> +                            const char *uri_str,
> +                            const char *dname ATTRIBUTE_UNUSED,
> +                            unsigned int flags)
> +{
> +    char *hostname = NULL;
> +    unsigned short port = 0;
> +    char portstr[100];
> +    virURIPtr uri = NULL;
> +    virNetSocketPtr sock;
> +    int sockfd = -1;
> +    int saved_errno = EINVAL;
> +    int ret = -1;
> +
> +    /* parse dst host:port from uri */
> +    uri = virURIParse(uri_str);
> +    if (uri == NULL || uri->server == NULL || uri->port == 0)
> +        goto cleanup;
> +
> +    hostname = uri->server;
> +    port = uri->port;
> +    snprintf(portstr, sizeof(portstr), "%d", port);
> +
> +    /* socket connect to dst host:port */
> +    if (virNetSocketNewConnectTCP(hostname, portstr, &sock) < 0) {
> +        virReportSystemError(saved_errno,
> +                             _("unable to connect to '%s:%s'"),
> +                             hostname, portstr);
> +        goto cleanup;
> +    }
> +
> +    if (virNetSocketSetBlocking(sock, true) < 0) {
> +        virObjectUnref(sock);
> +        goto cleanup;
> +    }
> +
> +    sockfd = virNetSocketDupFD(sock, true);
> +    virObjectUnref(sock);
> +
> +    /* suspend vm and send saved data to dst through socket fd */
> +    virObjectUnlock(vm);
> +    ret = libxlDoMigrateSend(driver, vm, flags, sockfd);
> +    virObjectLock(vm);
> +
> + cleanup:
> +    VIR_FORCE_CLOSE(sockfd);
> +    virURIFree(uri);
> +    return ret;
> +}
> +
> +virDomainPtr
> +libxlDomainMigrationFinish(virConnectPtr dconn,
> +                           virDomainObjPtr vm,
> +                           unsigned int flags,
> +                           int cancelled)
> +{
> +    libxlDriverPrivatePtr driver = dconn->privateData;
> +    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
> +    libxlDomainObjPrivatePtr priv = vm->privateData;
> +    virObjectEventPtr event = NULL;
> +    virDomainPtr dom = NULL;
> +
> +    virPortAllocatorRelease(driver->migrationPorts, priv->migrationPort);
> +    priv->migrationPort = 0;
> +
> +    if (cancelled)
> +        goto cleanup;
> +
> +    if (!(flags & VIR_MIGRATE_PAUSED)) {
> +        if (libxl_domain_unpause(priv->ctx, vm->def->id) != 0) {
> +            virReportError(VIR_ERR_OPERATION_FAILED, "%s",
> +                           _("Failed to unpause domain"));
> +            goto cleanup;
> +        }
> +
> +        virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
> +                             VIR_DOMAIN_RUNNING_MIGRATED);
> +        event = virDomainEventLifecycleNewFromObj(vm,
> +                                         VIR_DOMAIN_EVENT_RESUMED,
> +                                         VIR_DOMAIN_EVENT_RESUMED_MIGRATED);
> +    } else {
> +        virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER);
> +        event = virDomainEventLifecycleNewFromObj(vm,
> +                                         VIR_DOMAIN_EVENT_SUSPENDED,
> +                                         VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
> +    }
> +
> +    if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
> +        goto cleanup;
> +
> +    dom = virGetDomain(dconn, vm->def->name, vm->def->uuid);
> +
> +    if (dom == NULL) {
> +        libxl_domain_destroy(priv->ctx, vm->def->id, NULL);
> +        libxlDomainCleanup(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED);
> +        event = virDomainEventLifecycleNewFromObj(vm, 
> VIR_DOMAIN_EVENT_STOPPED,
> +                                         VIR_DOMAIN_EVENT_STOPPED_FAILED);
> +        libxlDomainEventQueue(driver, event);
> +    }
> +
> + cleanup:
> +    if (event)
> +        libxlDomainEventQueue(driver, event);
> +    if (vm)
> +        virObjectUnlock(vm);
> +    virObjectUnref(cfg);
> +    return dom;
> +}
> +
> +int
> +libxlDomainMigrationConfirm(libxlDriverPrivatePtr driver,
> +                            virDomainObjPtr vm,
> +                            unsigned int flags,
> +                            int cancelled)
> +{
> +    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
> +    libxlDomainObjPrivatePtr priv = vm->privateData;
> +    virObjectEventPtr event = NULL;
> +    int ret = -1;
> +
> +    if (cancelled) {
> +        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                   _("migration failed, attempting to resume on source 
> host"));
> +        if (libxl_domain_resume(priv->ctx, vm->def->id, 1, 0) == 0) {
> +            ret = 0;
> +        } else {
> +            VIR_DEBUG("Unable to resume domain '%s' after failed migration",
> +                      vm->def->name);
> +            virDomainObjSetState(vm, VIR_DOMAIN_PAUSED,
> +                                 VIR_DOMAIN_PAUSED_MIGRATION);
> +            event = virDomainEventLifecycleNewFromObj(vm, 
> VIR_DOMAIN_EVENT_SUSPENDED,
> +                                     VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED);
> +            ignore_value(virDomainSaveStatus(driver->xmlopt, cfg->stateDir, 
> vm));
> +        }
> +        goto cleanup;
> +    }
> +
> +    libxl_domain_destroy(priv->ctx, vm->def->id, NULL);
> +    libxlDomainCleanup(driver, vm, VIR_DOMAIN_SHUTOFF_MIGRATED);
> +    event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
> +                                              
> VIR_DOMAIN_EVENT_STOPPED_MIGRATED);
> +
> +    VIR_DEBUG("Domain '%s' successfully migrated", vm->def->name);
> +
> +    if (flags & VIR_MIGRATE_UNDEFINE_SOURCE)
> +        virDomainDeleteConfig(cfg->configDir, cfg->autostartDir, vm);
> +
> +    if (!vm->persistent || (flags & VIR_MIGRATE_UNDEFINE_SOURCE))
> +        virDomainObjListRemove(driver->domains, vm);
> +
> +    ret = 0;
> +
> + cleanup:
> +    if (!libxlDomainObjEndJob(driver, vm))
> +        vm = NULL;
> +    if (event)
> +        libxlDomainEventQueue(driver, event);
> +    if (vm)
> +        virObjectUnlock(vm);
> +    virObjectUnref(cfg);
> +    return ret;
> +}
> diff --git a/src/libxl/libxl_migration.h b/src/libxl/libxl_migration.h
> new file mode 100644
> index 0000000..63d8bdc
> --- /dev/null
> +++ b/src/libxl/libxl_migration.h
> @@ -0,0 +1,78 @@
> +/*
> + * libxl_migration.h: methods for handling migration with libxenlight
> + *
> + * Copyright (c) 2014 SUSE LINUX Products GmbH, Nuernberg, Germany.
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library.  If not, see
> + * <http://www.gnu.org/licenses/>.
> + *
> + * Authors:
> + *     Jim Fehlig <jfehlig@xxxxxxxx>
> + */
> +
> +#ifndef LIBXL_MIGRATION_H
> +# define LIBXL_MIGRATION_H
> +
> +# include "libxl_conf.h"
> +
> +# define LIBXL_MIGRATION_FLAGS                  \
> +    (VIR_MIGRATE_LIVE |                         \
> +     VIR_MIGRATE_UNDEFINE_SOURCE |              \
> +     VIR_MIGRATE_PAUSED)
> +
> +/* All supported migration parameters and their types. */
> +# define LIBXL_MIGRATION_PARAMETERS                             \
> +    VIR_MIGRATE_PARAM_URI,              VIR_TYPED_PARAM_STRING, \
> +    VIR_MIGRATE_PARAM_DEST_NAME,        VIR_TYPED_PARAM_STRING, \
> +    VIR_MIGRATE_PARAM_DEST_XML,         VIR_TYPED_PARAM_STRING, \
> +    NULL
> +
> +char *
> +libxlDomainMigrationBegin(virConnectPtr conn,
> +                          virDomainObjPtr vm,
> +                          const char *xmlin);
> +
> +virDomainDefPtr
> +libxlDomainMigrationPrepareDef(libxlDriverPrivatePtr driver,
> +                               const char *dom_xml,
> +                               const char *dname);
> +
> +int
> +libxlDomainMigrationPrepare(virConnectPtr dconn,
> +                            virDomainDefPtr def,
> +                            const char *uri_in,
> +                            char **uri_out);
> +
> +int
> +libxlDomainMigrationPerform(libxlDriverPrivatePtr driver,
> +                            virDomainObjPtr vm,
> +                            const char *dom_xml,
> +                            const char *dconnuri,
> +                            const char *uri_str,
> +                            const char *dname,
> +                            unsigned int flags);
> +
> +virDomainPtr
> +libxlDomainMigrationFinish(virConnectPtr dconn,
> +                           virDomainObjPtr vm,
> +                           unsigned int flags,
> +                           int cancelled);
> +
> +int
> +libxlDomainMigrationConfirm(libxlDriverPrivatePtr driver,
> +                            virDomainObjPtr vm,
> +                            unsigned int flags,
> +                            int cancelled);
> +
> +#endif /* LIBXL_DRIVER_H */
>   

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.