[libvirt] [PATCH] add migration APIs to libxl driver
Bamvor Jian Zhang
bjzhang at suse.com
Mon Sep 30 06:29:49 UTC 2013
> ---
> src/libxl/libxl_conf.h | 4 +
> src/libxl/libxl_driver.c | 641
> ++++++++++++++++++++++++++++++++++++++++++++++
> src/libxl/libxl_driver.h | 5 +
> 3 files changed, 650 insertions(+), 0 deletions(-)
>
> diff --git a/src/libxl/libxl_conf.h b/src/libxl/libxl_conf.h
> index 8ba0ee4..2041cc2 100644
> --- a/src/libxl/libxl_conf.h
> +++ b/src/libxl/libxl_conf.h
> @@ -41,6 +41,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
> +
there is a overlap between vnc and migration port. althrought, it will try
next port in virPortAllocatorAcquire after bind fail.
> # define LIBXL_CONFIG_DIR SYSCONFDIR "/libvirt/libxl"
> # define LIBXL_AUTOSTART_DIR LIBXL_CONFIG_DIR "/autostart"
> # define LIBXL_STATE_DIR LOCALSTATEDIR "/run/libvirt/libxl"
> @@ -109,6 +112,7 @@ struct _libxlDriverPrivate {
>
> /* Immutable pointer, self-locking APIs */
> virPortAllocatorPtr reservedVNCPorts;
> + virPortAllocatorPtr reservedMigPorts;
>
> /* Immutable pointer, lockless APIs*/
> virSysinfoDefPtr hostsysinfo;
> diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
> index e2a6d44..93b7153 100644
> --- a/src/libxl/libxl_driver.c
> +++ b/src/libxl/libxl_driver.c
> @@ -32,6 +32,12 @@
> #include <libxl_utils.h>
> #include <fcntl.h>
> #include <regex.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 "virlog.h"
> @@ -52,6 +58,7 @@
> #include "virsysinfo.h"
> #include "viraccessapicheck.h"
> #include "viratomic.h"
> +#include "rpc/virnetsocket.h"
>
> #define VIR_FROM_THIS VIR_FROM_LIBXL
>
> @@ -69,6 +76,20 @@
>
> static libxlDriverPrivatePtr libxl_driver = NULL;
>
> +typedef struct _libxlMigrateReceiveArgs {
> + virConnectPtr conn;
> + virDomainObjPtr vm;
> +
> + /* for freeing listen sockets */
> + virNetSocketPtr *socks;
> + size_t nsocks;
> +} libxlMigrateReceiveArgs;
> +
> +static const char libxlMigrateReceiverReady[]=
> + "libvirt libxl migration receiver ready, send binary domain data";
> +static const char libxlMigrateReceiverFinish[]=
> + "domain received, ready to unpause";
> +
> /* Function declarations */
> static int
> libxlDomainManagedSaveLoad(virDomainObjPtr vm,
> @@ -836,6 +857,12 @@ libxlStateInitialize(bool privileged,
> LIBXL_VNC_PORT_MAX)))
> goto error;
>
> + /* Allocate bitmap for migration port reservation */
> + if (!(libxl_driver->reservedMigPorts =
> + virPortAllocatorNew(LIBXL_MIGRATION_PORT_MIN,
> + LIBXL_MIGRATION_PORT_MAX)))
> + goto error;
> +
> if (!(libxl_driver->domains = virDomainObjListNew()))
> goto error;
>
> @@ -4175,11 +4202,620 @@ libxlConnectSupportsFeature(virConnectPtr conn,
> int feature)
> switch (feature) {
> case VIR_DRV_FEATURE_TYPED_PARAM_STRING:
> return 1;
> + case VIR_DRV_FEATURE_MIGRATION_V3:
> + return 1;
> default:
> return 0;
> }
> }
>
> +static int
> +libxlCheckMessageBanner(int fd, const char *banner, int banner_sz)
> +{
> + char buf[banner_sz];
> + int ret = 0;
> +
> + do {
> + ret = saferead(fd, buf, banner_sz);
> + } while (ret == -1 && errno == EAGAIN);
> +
> + if (ret != banner_sz || memcmp(buf, banner, banner_sz)) {
> + return -1;
> + }
> +
> + return 0;
> +}
> +
> +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;
> + libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
> + virDomainObjPtr vm;
> + virDomainDefPtr def = NULL;
> + char *xml = NULL;
> +
> + virCheckFlags(LIBXL_MIGRATION_FLAGS, NULL);
> +
> + vm = virDomainObjListFindByUUID(driver->domains, domain->uuid);
> + if (!vm) {
> + char uuidstr[VIR_UUID_STRING_BUFLEN];
> + virUUIDFormat(domain->uuid, uuidstr);
> + virReportError(VIR_ERR_OPERATION_INVALID,
> + _("no domain with matching uuid '%s'"), uuidstr);
> + goto cleanup;
> + }
libxlDomObjFromDomain is introduced in commit 0d87fd0aa by Jim.
> +
> + if (!virDomainObjIsActive(vm)) {
> + virReportError(VIR_ERR_OPERATION_INVALID, "%s",
> + _("domain is not running"));
> + goto cleanup;
> + }
> +
> + if (virDomainMigrateBegin3EnsureACL(domain->conn, vm->def) < 0)
> + goto cleanup;
> +
> + if (xmlin) {
> + if (!(def = virDomainDefParseString(xmlin, cfg->caps,
> + driver->xmlopt,
> + 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:
> + virDomainDefFree(def);
> + if (vm)
> + virObjectUnlock(vm);
> + virObjectUnref(cfg);
> + return xml;
> +}
> +
> +static void
> +doMigrateReceive(virNetSocketPtr sock,
> + int events ATTRIBUTE_UNUSED,
> + void *opaque)
> +{
> + libxlMigrateReceiveArgs *data = opaque;
> + virConnectPtr conn = data->conn;
> + virDomainObjPtr vm = data->vm;
> + virNetSocketPtr *socks = data->socks;
> + size_t nsocks = data->nsocks;
> + libxlDriverPrivatePtr driver = conn->privateData;
> + virNetSocketPtr client_sock;
> + int recv_fd;
> + int len;
> + 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\n");
> + recv_fd = virNetSocketDupFD(client_sock, true);
> + virObjectUnref(client_sock);
> +
> + len = sizeof(libxlMigrateReceiverReady);
> + if (safewrite(recv_fd, libxlMigrateReceiverReady, len) != len) {
> + virReportError(VIR_ERR_OPERATION_FAILED, "%s",
> + _("Failed to write libxlMigrateReceiverReady"));
> + goto cleanup;
> + }
> +
> + virObjectLock(vm);
> + ret = libxlVmStart(driver, vm, false, recv_fd);
> + virObjectUnlock(vm);
> +
> + if (ret < 0) {
> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("Failed to restore domain with libxenlight"));
> + if (!vm->persistent) {
> + virDomainObjListRemove(driver->domains, vm);
> + vm = NULL;
> + }
> + goto cleanup;
> + }
> +
> + len = sizeof(libxlMigrateReceiverFinish);
> + if (safewrite(recv_fd, libxlMigrateReceiverFinish, len) != len) {
> + virReportError(VIR_ERR_OPERATION_FAILED, "%s",
> + _("Failed to write libxlMigrateReceiverFinish"));
> + }
> +
> + /* Remove all listen socks from event handler, and close them. */
> + if (nsocks) {
> + for (i = 0; i < nsocks; i++) {
> + virNetSocketUpdateIOCallback(socks[i], 0);
> + virNetSocketRemoveIOCallback(socks[i]);
> + virNetSocketClose(socks[i]);
> + virObjectUnref(socks[i]);
> + }
> + VIR_FREE(socks);
> + }
> +
> +cleanup:
> + VIR_FORCE_CLOSE(recv_fd);
> + VIR_FREE(opaque);
> + return;
> +}
> +
> +static int
> +doMigrateSend(libxlDriverPrivatePtr driver,
> + virDomainObjPtr vm,
> + unsigned long flags,
> + int sockfd)
> +{
> + libxlDomainObjPrivatePtr priv;
> + libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
> + virDomainEventPtr event = NULL;
> + int live = 0;
> + int ret = -1;
> +
> + if (flags & VIR_MIGRATE_LIVE)
> + live = LIBXL_SUSPEND_LIVE;
> +
> + priv = vm->privateData;
> +
> + /* read fixed message from dest (ready to receive) */
> + if (libxlCheckMessageBanner(sockfd, libxlMigrateReceiverReady,
> + sizeof(libxlMigrateReceiverReady)))
> + goto cleanup;
> +
> + if (libxl_domain_suspend(priv->ctx, vm->def->id, sockfd, live, NULL)
> != 0) {
> + virReportError(VIR_ERR_INTERNAL_ERROR,
> + _("Failed to save domain '%d' with libxenlight"),
> + vm->def->id);
> + goto cleanup;
> + }
> +
> + /* read fixed message from dest (receive completed) */
> + if (libxlCheckMessageBanner(sockfd, libxlMigrateReceiverFinish,
> + sizeof(libxlMigrateReceiverFinish))) {
> + 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 = virDomainEventNewFromObj(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 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;
> + libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
> + virDomainDefPtr def = NULL;
> + 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;
> +
> + virCheckFlags(LIBXL_MIGRATION_FLAGS, -1);
> +
> + libxlDriverLock(driver);
> + if (!dom_xml) {
> + virReportError(VIR_ERR_OPERATION_INVALID, "%s",
> + _("no domain XML passed"));
> + goto cleanup;
> + }
> + def = virDomainDefParseString(dom_xml, cfg->caps, driver->xmlopt,
> + 1 << VIR_DOMAIN_VIRT_XEN,
> + VIR_DOMAIN_XML_INACTIVE);
> +
> + /* Target domain name, maybe renamed. */
> + if (dname) {
> + if (VIR_STRDUP(def->name, dname) < 0)
> + goto cleanup;
> + }
> +
> + if (!(vm = virDomainObjListAdd(driver->domains, def,
> + driver->xmlopt,
> + VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
> + VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
> + NULL)))
> + goto cleanup;
> +
> + def = NULL;
> +
> + if (virDomainMigratePrepare3EnsureACL(dconn, vm->def) < 0)
> + goto cleanup;
> +
> + /* Create socket connection to receive migration data */
> + if (!uri_in) {
> + hostname = virGetHostname();
> + if (hostname == NULL)
> + goto cleanup;
> +
> + if (virPortAllocatorAcquire(driver->reservedMigPorts, &port) < 0)
> + goto cleanup;
> +
> + if (port == 0) {
> + virReportError(VIR_ERR_INTERNAL_ERROR,
> + "%s", _("Unable to find an unused migrate
> port"));
> + goto cleanup;
> + }
> +
> + if (virAsprintf(uri_out, "tcp://%s:%d", hostname, port) < 0)
> + goto cleanup;
> + } else {
> + if (!strstr(uri_in, "//")) {
> + /* 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->reservedMigPorts, &port) <
> 0)
> + goto cleanup;
> +
> + if (port == 0) {
> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("Unable to find an unused migrate port"));
> + 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,
> + doMigrateReceive,
> + args,
> + NULL) < 0) {
> + continue;
> + }
> +
> + virNetSocketUpdateIOCallback(socks[i], VIR_EVENT_HANDLE_READABLE);
> + nsocks_listen ++;
> + }
> +
> + if (!nsocks_listen)
> + goto cleanup;
> +
> + ret = 0;
> + goto end;
> +
> +cleanup:
> + if (nsocks) {
> + for (i = 0 ; i < nsocks ; i++) {
> + virNetSocketClose(socks[i]);
> + virObjectUnref(socks[i]);
> + }
> + VIR_FREE(socks);
> + }
> +
> +end:
> + virURIFree(uri);
> + if (vm)
> + virObjectUnlock(vm);
> + virObjectUnref(cfg);
> + 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;
> + virDomainObjPtr vm;
> + char *hostname = NULL;
> + unsigned short port = 0;
> + char portstr[100];
> + virURIPtr uri_p = NULL;
> + virNetSocketPtr sock;
> + int sockfd = -1;
> + int saved_errno = EINVAL;
> + int ret = -1;
> +
> + virCheckFlags(LIBXL_MIGRATION_FLAGS, -1);
> +
> + vm = virDomainObjListFindByUUID(driver->domains, dom->uuid);
> + if (!vm) {
> + char uuidstr[VIR_UUID_STRING_BUFLEN];
> + virUUIDFormat(dom->uuid, uuidstr);
> + virReportError(VIR_ERR_OPERATION_INVALID,
> + _("no domain with matching uuid '%s'"), uuidstr);
> + goto cleanup;
> + }
same here.
> +
> + if (virDomainMigratePerform3EnsureACL(dom->conn, vm->def) < 0)
> + goto cleanup;
> +
> + /* parse dst host:port from uri */
> + uri_p = virURIParse(uri);
> + if (uri_p == NULL || uri_p->server == NULL || uri_p->port == 0)
> + goto cleanup;
> +
> + hostname = uri_p->server;
> + port = uri_p->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 */
> + ret = doMigrateSend(driver, vm, flags, sockfd);
> +
> +cleanup:
> + VIR_FORCE_CLOSE(sockfd);
> + virURIFree(uri_p);
> + if (vm)
> + virObjectUnlock(vm);
> + 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,
> + unsigned long flags,
> + int cancelled)
> +{
> + libxlDriverPrivatePtr driver = dconn->privateData;
> + libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
> + unsigned short port = 0;
> + virURIPtr uri_p = NULL;
> + virDomainObjPtr vm = NULL;
> + virDomainPtr dom = NULL;
> + libxlDomainObjPrivatePtr priv;
> + virDomainEventPtr event = NULL;
> + int rc;
> +
> + virCheckFlags(LIBXL_MIGRATION_FLAGS, NULL);
> +
> + uri_p = virURIParse(uri);
> + if (uri_p == NULL || uri_p->port == 0)
> + VIR_DEBUG("Fail to parse port from URI");
> + port = uri_p->port;
> + if (LIBXL_MIGRATION_PORT_MIN <= port && port <
> LIBXL_MIGRATION_PORT_MAX) {
> + if (virPortAllocatorRelease(driver->reservedMigPorts, port) < 0)
> + VIR_DEBUG("Could not mark port %d as unused", port);
> + }
> +
> + vm = virDomainObjListFindByName(driver->domains, dname);
> + if (!vm)
> + goto cleanup;
> +
> + if (virDomainMigrateFinish3EnsureACL(dconn, vm->def) < 0)
> + goto cleanup;
> +
> + if (!cancelled) {
> + if (!(flags & VIR_MIGRATE_PAUSED)) {
> + priv = vm->privateData;
> + rc = libxl_domain_unpause(priv->ctx, vm->def->id);
> + if (rc) {
> + virReportError(VIR_ERR_OPERATION_FAILED, "%s",
> + _("Failed to unpause domain"));
> + goto error;
> + }
> +
> + virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
> VIR_DOMAIN_RUNNING_BOOTED);
> + if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
> + goto error;
> + }
> +
> + dom = virGetDomain(dconn, vm->def->name, vm->def->uuid);
> + goto cleanup;
> + }
> +
> +error:
> + if (libxlVmReap(driver, vm, VIR_DOMAIN_SHUTOFF_SAVED)) {
> + virReportError(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) {
> + virDomainObjListRemove(driver->domains, vm);
> + vm = NULL;
> + }
> +
> +cleanup:
> + virURIFree(uri_p);
> + if (vm)
> + virObjectUnlock(vm);
> + if (event)
> + libxlDomainEventQueue(driver, event);
> + virObjectUnref(cfg);
> + 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;
> + libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
> + virDomainObjPtr vm;
> + libxlDomainObjPrivatePtr priv;
> + virDomainEventPtr event = NULL;
> + int ret = -1;
> +
> + virCheckFlags(LIBXL_MIGRATION_FLAGS, -1);
> +
> + vm = virDomainObjListFindByUUID(driver->domains, domain->uuid);
> + if (!vm) {
> + char uuidstr[VIR_UUID_STRING_BUFLEN];
> + virUUIDFormat(domain->uuid, uuidstr);
> + virReportError(VIR_ERR_NO_DOMAIN,
> + _("no domain with matching uuid '%s'"), uuidstr);
> + goto cleanup;
> + }
here.
> +
> + if (virDomainMigrateConfirm3EnsureACL(domain->conn, vm->def) < 0)
> + goto cleanup;
> +
> + if (cancelled) {
> + priv = vm->privateData;
> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("migration failed, try to resume on our end"));
> + if (!libxl_domain_resume(priv->ctx, vm->def->id, 0, 0)) {
> + ret = 0;
> + } else {
> + VIR_DEBUG("Failed to resume domain '%d' with libxenlight",
> + vm->def->id);
> + virDomainObjSetState(vm, VIR_DOMAIN_PAUSED,
> VIR_DOMAIN_PAUSED_MIGRATION);
> + event = virDomainEventNewFromObj(vm,
> VIR_DOMAIN_EVENT_SUSPENDED,
> +
> VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED);
> + if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
> + goto cleanup;
> + }
> +
> + goto cleanup;
> + }
> +
> + if (libxlVmReap(driver, vm, VIR_DOMAIN_SHUTOFF_SAVED)) {
> + virReportError(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(cfg->configDir, cfg->autostartDir, vm);
> +
> + if (!vm->persistent || (flags & VIR_MIGRATE_UNDEFINE_SOURCE)) {
> + virDomainObjListRemove(driver->domains, vm);
> + vm = NULL;
> + }
> +
> + VIR_DEBUG("Migration successful.\n");
> + ret = 0;
> +
> +cleanup:
> + if (vm)
> + virObjectUnlock(vm);
> + if (event)
> + libxlDomainEventQueue(driver, event);
> + virObjectUnref(cfg);
> + return ret;
> +}
> +
>
> static virDriver libxlDriver = {
> .no = VIR_DRV_LIBXL,
> @@ -4249,6 +4885,11 @@ static virDriver libxlDriver = {
> #ifdef LIBXL_HAVE_DOMAIN_NODEAFFINITY
> .domainGetNumaParameters = libxlDomainGetNumaParameters, /* 1.1.1 */
> #endif
> + .domainMigrateBegin3 = libxlDomainMigrateBegin3, /* 1.1.3 */
> + .domainMigratePrepare3 = libxlDomainMigratePrepare3, /* 1.1.3 */
> + .domainMigratePerform3 = libxlDomainMigratePerform3, /* 1.1.3 */
> + .domainMigrateFinish3 = libxlDomainMigrateFinish3, /* 1.1.3 */
> + .domainMigrateConfirm3 = libxlDomainMigrateConfirm3, /* 1.1.3 */
> .nodeGetFreeMemory = libxlNodeGetFreeMemory, /* 0.9.0 */
> .nodeGetCellsFreeMemory = libxlNodeGetCellsFreeMemory, /* 1.1.1 */
> .connectDomainEventRegister = libxlConnectDomainEventRegister, /*
> 0.9.0 */
> diff --git a/src/libxl/libxl_driver.h b/src/libxl/libxl_driver.h
> index a33d60c..25ac2b8 100644
> --- a/src/libxl/libxl_driver.h
> +++ b/src/libxl/libxl_driver.h
> @@ -24,6 +24,11 @@
> #ifndef LIBXL_DRIVER_H
> # define LIBXL_DRIVER_H
>
> +# define LIBXL_MIGRATION_FLAGS \
> + (VIR_MIGRATE_LIVE | \
> + VIR_MIGRATE_UNDEFINE_SOURCE | \
> + VIR_MIGRATE_PAUSED)
> +
> int libxlRegister(void);
>
> #endif /* LIBXL_DRIVER_H */
> --
> 1.6.0.2
>
> --
> libvir-list mailing list
> libvir-list at redhat.com
> https://www.redhat.com/mailman/listinfo/libvir-list
>
More information about the libvir-list
mailing list