[libvirt] [PATCH 00/13] libxl: add basic support for migration

Based on an earlier patch from Chunyan Liu https://www.redhat.com/archives/libvir-list/2013-September/msg00667.html This patch series adds basic migration support to the libxl driver. Follow-up patches can improve pre-migration checks and add support for additional migration flags. Patches 1-12 are almost exclusively code motion, moving functions from the main driver module into the libxl_domain and libxl_conf modules. Patch13 is rather large and provides the migration implementation. If it is preferred to split patch13 further, I'm open to suggestions on ways to do that. I've done some basic migration testing of this series using NFS shared storage. Error handling only minimally tested though. I attempted a migration to host with a different bridge than the source, verifying the migration failed and the vm was resumed on the source. Jim Fehlig (13): libxl: move libxlDomainEventQueue to libxl_domain libxl: move libxlDomainManagedSavePath to libxl_domain libxl: move libxlSaveImageOpen to libxl_domain libxl: move libxlVmCleanup{,Job} to libxl_domain libxl: move libxlDomEventsRegister to libxl_domain libxl: move libxlDomainAutoCoreDump to libxl_domain libxl: move libxlDoNodeGetInfo to libxl_conf libxl: move libxlDomainSetVcpuAffinities to libxl_domain libxl: move libxlFreeMem to libxl_domain libxl: move libxlVmStart to libxl_domain libxl: include a pointer to the driver in libxlDomainObjPrivate libxl: move domain event handler to libxl_domain libxl: add migration support po/POTFILES.in | 1 + src/Makefile.am | 3 +- src/libxl/libxl_conf.c | 36 ++ src/libxl/libxl_conf.h | 10 + src/libxl/libxl_domain.c | 696 +++++++++++++++++++++++++++++++ src/libxl/libxl_domain.h | 51 ++- src/libxl/libxl_driver.c | 972 +++++++++++--------------------------------- src/libxl/libxl_migration.c | 579 ++++++++++++++++++++++++++ src/libxl/libxl_migration.h | 78 ++++ 9 files changed, 1681 insertions(+), 745 deletions(-) create mode 100644 src/libxl/libxl_migration.c create mode 100644 src/libxl/libxl_migration.h -- 1.8.1.4

Move libxlDomainEventQueue from libxl_driver to libxl_domain for use by other libxl modules. Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- src/libxl/libxl_domain.c | 6 ++++++ src/libxl/libxl_domain.h | 4 ++++ src/libxl/libxl_driver.c | 6 ------ 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c index fdc4661..65219df 100644 --- a/src/libxl/libxl_domain.c +++ b/src/libxl/libxl_domain.c @@ -539,3 +539,9 @@ cleanup: VIR_FREE(log_file); return ret; } + +void +libxlDomainEventQueue(libxlDriverPrivatePtr driver, virObjectEventPtr event) +{ + virObjectEventStateQueue(driver->domainEventState, event); +} diff --git a/src/libxl/libxl_domain.h b/src/libxl/libxl_domain.h index 0a29d38..dd57e57 100644 --- a/src/libxl/libxl_domain.h +++ b/src/libxl/libxl_domain.h @@ -91,4 +91,8 @@ libxlDomainObjEndJob(libxlDriverPrivatePtr driver, virDomainObjPtr obj) ATTRIBUTE_RETURN_CHECK; +void +libxlDomainEventQueue(libxlDriverPrivatePtr driver, + virObjectEventPtr event); + #endif /* LIBXL_DOMAIN_H */ diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index a79efcb..511fde6 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -99,12 +99,6 @@ libxlDomObjFromDomain(virDomainPtr dom) return vm; } -static void -libxlDomainEventQueue(libxlDriverPrivatePtr driver, virObjectEventPtr event) -{ - virObjectEventStateQueue(driver->domainEventState, event); -} - static int libxlAutostartDomain(virDomainObjPtr vm, void *opaque) -- 1.8.1.4

Move libxlDomainManagedSavePath from libxl_driver to libxl_domain for use by other libxl modules. Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- src/libxl/libxl_domain.c | 10 ++++++++++ src/libxl/libxl_domain.h | 4 ++++ src/libxl/libxl_driver.c | 10 ---------- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c index 65219df..b83d1fa 100644 --- a/src/libxl/libxl_domain.c +++ b/src/libxl/libxl_domain.c @@ -545,3 +545,13 @@ libxlDomainEventQueue(libxlDriverPrivatePtr driver, virObjectEventPtr event) { virObjectEventStateQueue(driver->domainEventState, event); } + +char * +libxlDomainManagedSavePath(libxlDriverPrivatePtr driver, virDomainObjPtr vm) { + char *ret; + libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver); + + ignore_value(virAsprintf(&ret, "%s/%s.save", cfg->saveDir, vm->def->name)); + virObjectUnref(cfg); + return ret; +} diff --git a/src/libxl/libxl_domain.h b/src/libxl/libxl_domain.h index dd57e57..5558009 100644 --- a/src/libxl/libxl_domain.h +++ b/src/libxl/libxl_domain.h @@ -95,4 +95,8 @@ void libxlDomainEventQueue(libxlDriverPrivatePtr driver, virObjectEventPtr event); +char * +libxlDomainManagedSavePath(libxlDriverPrivatePtr driver, + virDomainObjPtr vm); + #endif /* LIBXL_DOMAIN_H */ diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 511fde6..ef623d5 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -161,16 +161,6 @@ cleanup: return ret; } -static char * -libxlDomainManagedSavePath(libxlDriverPrivatePtr driver, virDomainObjPtr vm) { - char *ret; - libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver); - - ignore_value(virAsprintf(&ret, "%s/%s.save", cfg->saveDir, vm->def->name)); - virObjectUnref(cfg); - return ret; -} - /* * This internal function expects the driver lock to already be held on * entry. -- 1.8.1.4

Move libxlSaveImageOpen from libxl_driver to libxl_domain for use by other libxl modules. For consistency, rename to libxlDomainSaveImageOpen. Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- src/libxl/libxl_domain.c | 76 +++++++++++++++++++++++++++++++++++++++++++++ src/libxl/libxl_domain.h | 8 +++++ src/libxl/libxl_driver.c | 80 +++--------------------------------------------- 3 files changed, 88 insertions(+), 76 deletions(-) diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c index b83d1fa..109a4e2 100644 --- a/src/libxl/libxl_domain.c +++ b/src/libxl/libxl_domain.c @@ -23,6 +23,8 @@ #include <config.h> +#include <fcntl.h> + #include "libxl_domain.h" #include "viralloc.h" @@ -555,3 +557,77 @@ libxlDomainManagedSavePath(libxlDriverPrivatePtr driver, virDomainObjPtr vm) { virObjectUnref(cfg); return ret; } + +/* + * Open a saved image file and initialize domain definition from the header. + * + * Returns the opened fd on success, -1 on failure. + */ +int +libxlDomainSaveImageOpen(libxlDriverPrivatePtr driver, + libxlDriverConfigPtr cfg, + const char *from, + virDomainDefPtr *ret_def, + libxlSavefileHeaderPtr ret_hdr) +{ + int fd; + virDomainDefPtr def = NULL; + libxlSavefileHeader hdr; + char *xml = NULL; + + if ((fd = virFileOpenAs(from, O_RDONLY, 0, -1, -1, 0)) < 0) { + virReportSystemError(-fd, + _("Failed to open domain image file '%s'"), from); + goto error; + } + + if (saferead(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) { + virReportError(VIR_ERR_OPERATION_FAILED, + "%s", _("failed to read libxl header")); + goto error; + } + + if (memcmp(hdr.magic, LIBXL_SAVE_MAGIC, sizeof(hdr.magic))) { + virReportError(VIR_ERR_INVALID_ARG, "%s", _("image magic is incorrect")); + goto error; + } + + if (hdr.version > LIBXL_SAVE_VERSION) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("image version is not supported (%d > %d)"), + hdr.version, LIBXL_SAVE_VERSION); + goto error; + } + + if (hdr.xmlLen <= 0) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("invalid XML length: %d"), hdr.xmlLen); + goto error; + } + + if (VIR_ALLOC_N(xml, hdr.xmlLen) < 0) + goto error; + + if (saferead(fd, xml, hdr.xmlLen) != hdr.xmlLen) { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("failed to read XML")); + goto error; + } + + if (!(def = virDomainDefParseString(xml, cfg->caps, driver->xmlopt, + 1 << VIR_DOMAIN_VIRT_XEN, + VIR_DOMAIN_XML_INACTIVE))) + goto error; + + VIR_FREE(xml); + + *ret_def = def; + *ret_hdr = hdr; + + return fd; + +error: + VIR_FREE(xml); + virDomainDefFree(def); + VIR_FORCE_CLOSE(fd); + return -1; +} diff --git a/src/libxl/libxl_domain.h b/src/libxl/libxl_domain.h index 5558009..3c1f5c0 100644 --- a/src/libxl/libxl_domain.h +++ b/src/libxl/libxl_domain.h @@ -99,4 +99,12 @@ char * libxlDomainManagedSavePath(libxlDriverPrivatePtr driver, virDomainObjPtr vm); +int +libxlDomainSaveImageOpen(libxlDriverPrivatePtr driver, + libxlDriverConfigPtr cfg, + const char *from, + virDomainDefPtr *ret_def, + libxlSavefileHeaderPtr ret_hdr) + ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5); + #endif /* LIBXL_DOMAIN_H */ diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index ef623d5..a2e982c 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -161,78 +161,6 @@ cleanup: return ret; } -/* - * This internal function expects the driver lock to already be held on - * entry. - */ -static int ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5) -libxlSaveImageOpen(libxlDriverPrivatePtr driver, - libxlDriverConfigPtr cfg, - const char *from, - virDomainDefPtr *ret_def, - libxlSavefileHeaderPtr ret_hdr) -{ - int fd; - virDomainDefPtr def = NULL; - libxlSavefileHeader hdr; - char *xml = NULL; - - if ((fd = virFileOpenAs(from, O_RDONLY, 0, -1, -1, 0)) < 0) { - virReportSystemError(-fd, - _("Failed to open domain image file '%s'"), from); - goto error; - } - - if (saferead(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) { - virReportError(VIR_ERR_OPERATION_FAILED, - "%s", _("failed to read libxl header")); - goto error; - } - - if (memcmp(hdr.magic, LIBXL_SAVE_MAGIC, sizeof(hdr.magic))) { - virReportError(VIR_ERR_INVALID_ARG, "%s", _("image magic is incorrect")); - goto error; - } - - if (hdr.version > LIBXL_SAVE_VERSION) { - virReportError(VIR_ERR_OPERATION_FAILED, - _("image version is not supported (%d > %d)"), - hdr.version, LIBXL_SAVE_VERSION); - goto error; - } - - if (hdr.xmlLen <= 0) { - virReportError(VIR_ERR_OPERATION_FAILED, - _("invalid XML length: %d"), hdr.xmlLen); - goto error; - } - - if (VIR_ALLOC_N(xml, hdr.xmlLen) < 0) - goto error; - - if (saferead(fd, xml, hdr.xmlLen) != hdr.xmlLen) { - virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("failed to read XML")); - goto error; - } - - if (!(def = virDomainDefParseString(xml, cfg->caps, driver->xmlopt, - 1 << VIR_DOMAIN_VIRT_XEN, - VIR_DOMAIN_XML_INACTIVE))) - goto error; - - VIR_FREE(xml); - - *ret_def = def; - *ret_hdr = hdr; - - return fd; - -error: - VIR_FREE(xml); - virDomainDefFree(def); - VIR_FORCE_CLOSE(fd); - return -1; -} /* * Core dump domain to default dump path. @@ -700,9 +628,9 @@ libxlVmStart(libxlDriverPrivatePtr driver, virDomainObjPtr vm, if (virFileExists(managed_save_path)) { - managed_save_fd = libxlSaveImageOpen(driver, cfg, - managed_save_path, - &def, &hdr); + managed_save_fd = libxlDomainSaveImageOpen(driver, cfg, + managed_save_path, + &def, &hdr); if (managed_save_fd < 0) goto endjob; @@ -2100,7 +2028,7 @@ libxlDomainRestoreFlags(virConnectPtr conn, const char *from, return -1; } - fd = libxlSaveImageOpen(driver, cfg, from, &def, &hdr); + fd = libxlDomainSaveImageOpen(driver, cfg, from, &def, &hdr); if (fd < 0) goto cleanup_unlock; -- 1.8.1.4

Move libxlVmCleanup and libxlVmCleanupJob from libxl_driver to libxl_domain for use by other libxl modules. For consistency, rename to libxlDomainCleanup and libxlDomainCleanupJob. Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- src/libxl/libxl_domain.c | 87 ++++++++++++++++++++++++++++++++++++++++++ src/libxl/libxl_domain.h | 10 +++++ src/libxl/libxl_driver.c | 98 +++--------------------------------------------- 3 files changed, 103 insertions(+), 92 deletions(-) diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c index 109a4e2..f123b89 100644 --- a/src/libxl/libxl_domain.c +++ b/src/libxl/libxl_domain.c @@ -28,6 +28,7 @@ #include "libxl_domain.h" #include "viralloc.h" +#include "viratomic.h" #include "virfile.h" #include "virerror.h" #include "virlog.h" @@ -631,3 +632,89 @@ error: VIR_FORCE_CLOSE(fd); return -1; } + +/* + * Cleanup function for domain that has reached shutoff state. + * + * virDomainObjPtr should be locked on invocation + */ +void +libxlDomainCleanup(libxlDriverPrivatePtr driver, + virDomainObjPtr vm, + virDomainShutoffReason reason) +{ + libxlDomainObjPrivatePtr priv = vm->privateData; + libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver); + int vnc_port; + char *file; + size_t i; + + vm->def->id = -1; + + if (priv->deathW) { + libxl_evdisable_domain_death(priv->ctx, priv->deathW); + priv->deathW = NULL; + } + + if (vm->persistent) + virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, reason); + + if (virAtomicIntDecAndTest(&driver->nactive) && driver->inhibitCallback) + driver->inhibitCallback(false, driver->inhibitOpaque); + + if ((vm->def->ngraphics == 1) && + vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC && + vm->def->graphics[0]->data.vnc.autoport) { + vnc_port = vm->def->graphics[0]->data.vnc.port; + if (vnc_port >= LIBXL_VNC_PORT_MIN) { + if (virPortAllocatorRelease(driver->reservedVNCPorts, + vnc_port) < 0) + VIR_DEBUG("Could not mark port %d as unused", vnc_port); + } + } + + /* Remove any cputune settings */ + if (vm->def->cputune.nvcpupin) { + for (i = 0; i < vm->def->cputune.nvcpupin; ++i) { + virBitmapFree(vm->def->cputune.vcpupin[i]->cpumask); + VIR_FREE(vm->def->cputune.vcpupin[i]); + } + VIR_FREE(vm->def->cputune.vcpupin); + vm->def->cputune.nvcpupin = 0; + } + + if (virAsprintf(&file, "%s/%s.xml", cfg->stateDir, vm->def->name) > 0) { + if (unlink(file) < 0 && errno != ENOENT && errno != ENOTDIR) + VIR_DEBUG("Failed to remove domain XML for %s", vm->def->name); + VIR_FREE(file); + } + + if (vm->newDef) { + virDomainDefFree(vm->def); + vm->def = vm->newDef; + vm->def->id = -1; + vm->newDef = NULL; + } + + virObjectUnref(cfg); +} + +/* + * Cleanup function for domain that has reached shutoff state. + * Executed in the context of a job. + * + * virDomainObjPtr should be locked on invocation + * Returns true if references remain on virDomainObjPtr, false otherwise. + */ +bool +libxlDomainCleanupJob(libxlDriverPrivatePtr driver, + virDomainObjPtr vm, + virDomainShutoffReason reason) +{ + if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_DESTROY) < 0) + return true; + + libxlDomainCleanup(driver, vm, reason); + + return libxlDomainObjEndJob(driver, vm); +} diff --git a/src/libxl/libxl_domain.h b/src/libxl/libxl_domain.h index 3c1f5c0..949e1c2 100644 --- a/src/libxl/libxl_domain.h +++ b/src/libxl/libxl_domain.h @@ -107,4 +107,14 @@ libxlDomainSaveImageOpen(libxlDriverPrivatePtr driver, libxlSavefileHeaderPtr ret_hdr) ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5); +void +libxlDomainCleanup(libxlDriverPrivatePtr driver, + virDomainObjPtr vm, + virDomainShutoffReason reason); + +bool +libxlDomainCleanupJob(libxlDriverPrivatePtr driver, + virDomainObjPtr vm, + virDomainShutoffReason reason); + #endif /* LIBXL_DOMAIN_H */ diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index a2e982c..dc91958 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -207,92 +207,6 @@ cleanup: } /* - * Cleanup function for domain that has reached shutoff state. - * - * virDomainObjPtr should be locked on invocation - */ -static void -libxlVmCleanup(libxlDriverPrivatePtr driver, - virDomainObjPtr vm, - virDomainShutoffReason reason) -{ - libxlDomainObjPrivatePtr priv = vm->privateData; - libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver); - int vnc_port; - char *file; - size_t i; - - vm->def->id = -1; - - if (priv->deathW) { - libxl_evdisable_domain_death(priv->ctx, priv->deathW); - priv->deathW = NULL; - } - - if (vm->persistent) - virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, reason); - - if (virAtomicIntDecAndTest(&driver->nactive) && driver->inhibitCallback) - driver->inhibitCallback(false, driver->inhibitOpaque); - - if ((vm->def->ngraphics == 1) && - vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC && - vm->def->graphics[0]->data.vnc.autoport) { - vnc_port = vm->def->graphics[0]->data.vnc.port; - if (vnc_port >= LIBXL_VNC_PORT_MIN) { - if (virPortAllocatorRelease(driver->reservedVNCPorts, - vnc_port) < 0) - VIR_DEBUG("Could not mark port %d as unused", vnc_port); - } - } - - /* Remove any cputune settings */ - if (vm->def->cputune.nvcpupin) { - for (i = 0; i < vm->def->cputune.nvcpupin; ++i) { - virBitmapFree(vm->def->cputune.vcpupin[i]->cpumask); - VIR_FREE(vm->def->cputune.vcpupin[i]); - } - VIR_FREE(vm->def->cputune.vcpupin); - vm->def->cputune.nvcpupin = 0; - } - - if (virAsprintf(&file, "%s/%s.xml", cfg->stateDir, vm->def->name) > 0) { - if (unlink(file) < 0 && errno != ENOENT && errno != ENOTDIR) - VIR_DEBUG("Failed to remove domain XML for %s", vm->def->name); - VIR_FREE(file); - } - - if (vm->newDef) { - virDomainDefFree(vm->def); - vm->def = vm->newDef; - vm->def->id = -1; - vm->newDef = NULL; - } - - virObjectUnref(cfg); -} - -/* - * Cleanup function for domain that has reached shutoff state. - * Executed in the context of a job. - * - * virDomainObjPtr should be locked on invocation - * Returns true if references remain on virDomainObjPtr, false otherwise. - */ -static bool -libxlVmCleanupJob(libxlDriverPrivatePtr driver, - virDomainObjPtr vm, - virDomainShutoffReason reason) -{ - if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_DESTROY) < 0) - return true; - - libxlVmCleanup(driver, vm, reason); - - return libxlDomainObjEndJob(driver, vm); -} - -/* * Handle previously registered event notification from libxenlight. * * Note: Xen 4.3 removed the const from the event handler signature. @@ -390,7 +304,7 @@ destroy: dom_event = NULL; } libxl_domain_destroy(ctx, vm->def->id, NULL); - if (libxlVmCleanupJob(driver, vm, reason)) { + if (libxlDomainCleanupJob(driver, vm, reason)) { if (!vm->persistent) { virDomainObjListRemove(driver->domains, vm); vm = NULL; @@ -404,7 +318,7 @@ restart: dom_event = NULL; } libxl_domain_destroy(ctx, vm->def->id, NULL); - libxlVmCleanupJob(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN); + libxlDomainCleanupJob(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN); libxlVmStart(driver, vm, 0, -1); cleanup: @@ -813,7 +727,7 @@ libxlReconnectDomain(virDomainObjPtr vm, return 0; out: - libxlVmCleanup(driver, vm, VIR_DOMAIN_SHUTOFF_UNKNOWN); + libxlDomainCleanup(driver, vm, VIR_DOMAIN_SHUTOFF_UNKNOWN); if (!vm->persistent) virDomainObjListRemoveLocked(driver->domains, vm); else @@ -1596,7 +1510,7 @@ libxlDomainDestroyFlags(virDomainPtr dom, goto cleanup; } - if (libxlVmCleanupJob(driver, vm, VIR_DOMAIN_SHUTOFF_DESTROYED)) { + if (libxlDomainCleanupJob(driver, vm, VIR_DOMAIN_SHUTOFF_DESTROYED)) { if (!vm->persistent) { virDomainObjListRemove(driver->domains, vm); vm = NULL; @@ -1938,7 +1852,7 @@ libxlDoDomainSave(libxlDriverPrivatePtr driver, virDomainObjPtr vm, goto cleanup; } - libxlVmCleanup(driver, vm, VIR_DOMAIN_SHUTOFF_SAVED); + libxlDomainCleanup(driver, vm, VIR_DOMAIN_SHUTOFF_SAVED); vm->hasManagedSave = true; ret = 0; @@ -2131,7 +2045,7 @@ libxlDomainCoreDump(virDomainPtr dom, const char *to, unsigned int flags) goto unpause; } - libxlVmCleanup(driver, vm, VIR_DOMAIN_SHUTOFF_CRASHED); + libxlDomainCleanup(driver, vm, VIR_DOMAIN_SHUTOFF_CRASHED); event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED, VIR_DOMAIN_EVENT_STOPPED_CRASHED); if (!vm->persistent) -- 1.8.1.4

Move libxlDomEventsRegister from libxl_driver to libxl_domain for use by other libxl modules. For consistency, rename to libxlDomainEventsRegister. Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- src/libxl/libxl_domain.c | 24 ++++++++++++++++++++++++ src/libxl/libxl_domain.h | 4 +++- src/libxl/libxl_driver.c | 30 +++--------------------------- 3 files changed, 30 insertions(+), 28 deletions(-) diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c index f123b89..5ffa9dd 100644 --- a/src/libxl/libxl_domain.c +++ b/src/libxl/libxl_domain.c @@ -718,3 +718,27 @@ libxlDomainCleanupJob(libxlDriverPrivatePtr driver, return libxlDomainObjEndJob(driver, vm); } + +/* + * Register for domain events emitted by libxl. + */ +int +libxlDomainEventsRegister(virDomainObjPtr vm) +{ + libxlDomainObjPrivatePtr priv = vm->privateData; + + libxl_event_register_callbacks(priv->ctx, &ev_hooks, vm); + + /* Always enable domain death events */ + if (libxl_evenable_domain_death(priv->ctx, vm->def->id, 0, &priv->deathW)) + goto error; + + return 0; + +error: + if (priv->deathW) { + libxl_evdisable_domain_death(priv->ctx, priv->deathW); + priv->deathW = NULL; + } + return -1; +} diff --git a/src/libxl/libxl_domain.h b/src/libxl/libxl_domain.h index 949e1c2..1ac9174 100644 --- a/src/libxl/libxl_domain.h +++ b/src/libxl/libxl_domain.h @@ -75,7 +75,7 @@ struct _libxlDomainObjPrivate { extern virDomainXMLPrivateDataCallbacks libxlDomainXMLPrivateDataCallbacks; extern virDomainDefParserConfig libxlDomainDefParserConfig; - +extern const struct libxl_event_hooks ev_hooks; int libxlDomainObjPrivateInitCtx(virDomainObjPtr vm); @@ -116,5 +116,7 @@ bool libxlDomainCleanupJob(libxlDriverPrivatePtr driver, virDomainObjPtr vm, virDomainShutoffReason reason); +int +libxlDomainEventsRegister(virDomainObjPtr vm); #endif /* LIBXL_DOMAIN_H */ diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index dc91958..7451726 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -379,36 +379,12 @@ error: libxl_event_free(priv->ctx, (libxl_event *)event); } -static const struct libxl_event_hooks ev_hooks = { +const struct libxl_event_hooks ev_hooks = { .event_occurs_mask = LIBXL_EVENTMASK_ALL, .event_occurs = libxlEventHandler, .disaster = NULL, }; -/* - * Register for domain events emitted by libxl. - */ -static int -libxlDomEventsRegister(virDomainObjPtr vm) -{ - libxlDomainObjPrivatePtr priv = vm->privateData; - - libxl_event_register_callbacks(priv->ctx, &ev_hooks, vm); - - /* Always enable domain death events */ - if (libxl_evenable_domain_death(priv->ctx, vm->def->id, 0, &priv->deathW)) - goto error; - - return 0; - -error: - if (priv->deathW) { - libxl_evdisable_domain_death(priv->ctx, priv->deathW); - priv->deathW = NULL; - } - return -1; -} - static int libxlDomainSetVcpuAffinities(libxlDriverPrivatePtr driver, virDomainObjPtr vm) { @@ -621,7 +597,7 @@ libxlVmStart(libxlDriverPrivatePtr driver, virDomainObjPtr vm, * be cleaned up if there are any subsequent failures. */ vm->def->id = domid; - if (libxlDomEventsRegister(vm) < 0) + if (libxlDomainEventsRegister(vm) < 0) goto cleanup_dom; if ((dom_xml = virDomainDefFormat(vm->def, 0)) == NULL) @@ -722,7 +698,7 @@ libxlReconnectDomain(virDomainObjPtr vm, driver->inhibitCallback(true, driver->inhibitOpaque); /* Re-register domain death et. al. events */ - libxlDomEventsRegister(vm); + libxlDomainEventsRegister(vm); virObjectUnlock(vm); return 0; -- 1.8.1.4

Move libxlDomainAutoCoreDump from libxl_driver to libxl_domain for use by other libxl modules. Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- src/libxl/libxl_domain.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ src/libxl/libxl_domain.h | 4 ++++ src/libxl/libxl_driver.c | 44 -------------------------------------------- 3 files changed, 48 insertions(+), 44 deletions(-) diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c index 5ffa9dd..6816a96 100644 --- a/src/libxl/libxl_domain.c +++ b/src/libxl/libxl_domain.c @@ -742,3 +742,47 @@ error: } return -1; } + +/* + * Core dump domain to default dump path. + * + * virDomainObjPtr must be locked on invocation + */ +int +libxlDomainAutoCoreDump(libxlDriverPrivatePtr driver, + virDomainObjPtr vm) +{ + libxlDomainObjPrivatePtr priv = vm->privateData; + libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver); + time_t curtime = time(NULL); + char timestr[100]; + struct tm time_info; + char *dumpfile = NULL; + int ret = -1; + + localtime_r(&curtime, &time_info); + strftime(timestr, sizeof(timestr), "%Y-%m-%d-%H:%M:%S", &time_info); + + if (virAsprintf(&dumpfile, "%s/%s-%s", + cfg->autoDumpDir, + vm->def->name, + timestr) < 0) + goto cleanup; + + if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0) + goto cleanup; + + /* Unlock virDomainObj while dumping core */ + virObjectUnlock(vm); + libxl_domain_core_dump(priv->ctx, vm->def->id, dumpfile, NULL); + virObjectLock(vm); + + ignore_value(libxlDomainObjEndJob(driver, vm)); + ret = 0; + +cleanup: + VIR_FREE(dumpfile); + virObjectUnref(cfg); + + return ret; +} diff --git a/src/libxl/libxl_domain.h b/src/libxl/libxl_domain.h index 1ac9174..a50efd3 100644 --- a/src/libxl/libxl_domain.h +++ b/src/libxl/libxl_domain.h @@ -119,4 +119,8 @@ libxlDomainCleanupJob(libxlDriverPrivatePtr driver, int libxlDomainEventsRegister(virDomainObjPtr vm); +int +libxlDomainAutoCoreDump(libxlDriverPrivatePtr driver, + virDomainObjPtr vm); + #endif /* LIBXL_DOMAIN_H */ diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 7451726..663577f 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -163,50 +163,6 @@ cleanup: /* - * Core dump domain to default dump path. - * - * virDomainObjPtr must be locked on invocation - */ -static int -libxlDomainAutoCoreDump(libxlDriverPrivatePtr driver, - virDomainObjPtr vm) -{ - libxlDomainObjPrivatePtr priv = vm->privateData; - libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver); - time_t curtime = time(NULL); - char timestr[100]; - struct tm time_info; - char *dumpfile = NULL; - int ret = -1; - - localtime_r(&curtime, &time_info); - strftime(timestr, sizeof(timestr), "%Y-%m-%d-%H:%M:%S", &time_info); - - if (virAsprintf(&dumpfile, "%s/%s-%s", - cfg->autoDumpDir, - vm->def->name, - timestr) < 0) - goto cleanup; - - if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0) - goto cleanup; - - /* Unlock virDomainObj while dumping core */ - virObjectUnlock(vm); - libxl_domain_core_dump(priv->ctx, vm->def->id, dumpfile, NULL); - virObjectLock(vm); - - ignore_value(libxlDomainObjEndJob(driver, vm)); - ret = 0; - -cleanup: - VIR_FREE(dumpfile); - virObjectUnref(cfg); - - return ret; -} - -/* * Handle previously registered event notification from libxenlight. * * Note: Xen 4.3 removed the const from the event handler signature. -- 1.8.1.4

Move libxlDoNodeGetInfo from libxl_driver to libxl_conf for use by other libxl modules. For consistency, rename to libxlDriverNodeGetInfo. Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- src/libxl/libxl_conf.c | 36 ++++++++++++++++++++++++++++++++++++ src/libxl/libxl_conf.h | 4 ++++ src/libxl/libxl_driver.c | 41 ++--------------------------------------- 3 files changed, 42 insertions(+), 39 deletions(-) diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index 13eddd1..199e3e9 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -1144,6 +1144,42 @@ libxlDriverConfigGet(libxlDriverPrivatePtr driver) return cfg; } +int +libxlDriverNodeGetInfo(libxlDriverPrivatePtr driver, virNodeInfoPtr info) +{ + libxl_physinfo phy_info; + virArch hostarch = virArchFromHost(); + libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver); + int ret = -1; + + if (libxl_get_physinfo(cfg->ctx, &phy_info)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("libxl_get_physinfo_info failed")); + goto cleanup; + } + + if (virStrcpyStatic(info->model, virArchToString(hostarch)) == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("machine type %s too big for destination"), + virArchToString(hostarch)); + goto cleanup; + } + + info->memory = phy_info.total_pages * (cfg->verInfo->pagesize / 1024); + info->cpus = phy_info.nr_cpus; + info->nodes = phy_info.nr_nodes; + info->cores = phy_info.cores_per_socket; + info->threads = phy_info.threads_per_core; + info->sockets = 1; + info->mhz = phy_info.cpu_khz / 1000; + + ret = 0; + +cleanup: + virObjectUnref(cfg); + return ret; +} + virCapsPtr libxlMakeCapabilities(libxl_ctx *ctx) { diff --git a/src/libxl/libxl_conf.h b/src/libxl/libxl_conf.h index f089a92..6584933 100644 --- a/src/libxl/libxl_conf.h +++ b/src/libxl/libxl_conf.h @@ -136,6 +136,10 @@ libxlDriverConfigNew(void); libxlDriverConfigPtr libxlDriverConfigGet(libxlDriverPrivatePtr driver); +int +libxlDriverNodeGetInfo(libxlDriverPrivatePtr driver, + virNodeInfoPtr info); + virCapsPtr libxlMakeCapabilities(libxl_ctx *ctx); diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 663577f..665c740 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -125,43 +125,6 @@ cleanup: return ret; } -static int -libxlDoNodeGetInfo(libxlDriverPrivatePtr driver, virNodeInfoPtr info) -{ - libxl_physinfo phy_info; - virArch hostarch = virArchFromHost(); - libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver); - int ret = -1; - - if (libxl_get_physinfo(cfg->ctx, &phy_info)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("libxl_get_physinfo_info failed")); - goto cleanup; - } - - if (virStrcpyStatic(info->model, virArchToString(hostarch)) == NULL) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("machine type %s too big for destination"), - virArchToString(hostarch)); - goto cleanup; - } - - info->memory = phy_info.total_pages * (cfg->verInfo->pagesize / 1024); - info->cpus = phy_info.nr_cpus; - info->nodes = phy_info.nr_nodes; - info->cores = phy_info.cores_per_socket; - info->threads = phy_info.threads_per_core; - info->sockets = 1; - info->mhz = phy_info.cpu_khz / 1000; - - ret = 0; - -cleanup: - virObjectUnref(cfg); - return ret; -} - - /* * Handle previously registered event notification from libxenlight. * @@ -355,7 +318,7 @@ libxlDomainSetVcpuAffinities(libxlDriverPrivatePtr driver, virDomainObjPtr vm) size_t i; int ret = -1; - if (libxlDoNodeGetInfo(driver, &nodeinfo) < 0) + if (libxlDriverNodeGetInfo(driver, &nodeinfo) < 0) goto cleanup; cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo)); @@ -1032,7 +995,7 @@ libxlNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info) if (virNodeGetInfoEnsureACL(conn) < 0) return -1; - return libxlDoNodeGetInfo(conn->privateData, info); + return libxlDriverNodeGetInfo(conn->privateData, info); } static char * -- 1.8.1.4

Move libxlDomainSetVcpuAffinities from libxl_driver to libxl_domain for use by other libxl modules. Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- src/libxl/libxl_domain.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++ src/libxl/libxl_domain.h | 4 ++++ src/libxl/libxl_driver.c | 54 ------------------------------------------------ 3 files changed, 58 insertions(+), 54 deletions(-) diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c index 6816a96..ef85790 100644 --- a/src/libxl/libxl_domain.c +++ b/src/libxl/libxl_domain.c @@ -786,3 +786,57 @@ cleanup: return ret; } + +int +libxlDomainSetVcpuAffinities(libxlDriverPrivatePtr driver, virDomainObjPtr vm) +{ + libxlDomainObjPrivatePtr priv = vm->privateData; + virDomainDefPtr def = vm->def; + libxl_bitmap map; + virBitmapPtr cpumask = NULL; + uint8_t *cpumap = NULL; + virNodeInfo nodeinfo; + size_t cpumaplen; + int vcpu; + size_t i; + int ret = -1; + + if (libxlDriverNodeGetInfo(driver, &nodeinfo) < 0) + goto cleanup; + + cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo)); + + for (vcpu = 0; vcpu < def->cputune.nvcpupin; ++vcpu) { + if (vcpu != def->cputune.vcpupin[vcpu]->vcpuid) + continue; + + if (VIR_ALLOC_N(cpumap, cpumaplen) < 0) + goto cleanup; + + cpumask = def->cputune.vcpupin[vcpu]->cpumask; + + for (i = 0; i < virBitmapSize(cpumask); ++i) { + bool bit; + ignore_value(virBitmapGetBit(cpumask, i, &bit)); + if (bit) + VIR_USE_CPU(cpumap, i); + } + + map.size = cpumaplen; + map.map = cpumap; + + if (libxl_set_vcpuaffinity(priv->ctx, def->id, vcpu, &map) != 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Failed to pin vcpu '%d' with libxenlight"), vcpu); + goto cleanup; + } + + VIR_FREE(cpumap); + } + + ret = 0; + +cleanup: + VIR_FREE(cpumap); + return ret; +} diff --git a/src/libxl/libxl_domain.h b/src/libxl/libxl_domain.h index a50efd3..775a91c 100644 --- a/src/libxl/libxl_domain.h +++ b/src/libxl/libxl_domain.h @@ -123,4 +123,8 @@ int libxlDomainAutoCoreDump(libxlDriverPrivatePtr driver, virDomainObjPtr vm); +int +libxlDomainSetVcpuAffinities(libxlDriverPrivatePtr driver, + virDomainObjPtr vm); + #endif /* LIBXL_DOMAIN_H */ diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 665c740..b511383 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -305,60 +305,6 @@ const struct libxl_event_hooks ev_hooks = { }; static int -libxlDomainSetVcpuAffinities(libxlDriverPrivatePtr driver, virDomainObjPtr vm) -{ - libxlDomainObjPrivatePtr priv = vm->privateData; - virDomainDefPtr def = vm->def; - libxl_bitmap map; - virBitmapPtr cpumask = NULL; - uint8_t *cpumap = NULL; - virNodeInfo nodeinfo; - size_t cpumaplen; - int vcpu; - size_t i; - int ret = -1; - - if (libxlDriverNodeGetInfo(driver, &nodeinfo) < 0) - goto cleanup; - - cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo)); - - for (vcpu = 0; vcpu < def->cputune.nvcpupin; ++vcpu) { - if (vcpu != def->cputune.vcpupin[vcpu]->vcpuid) - continue; - - if (VIR_ALLOC_N(cpumap, cpumaplen) < 0) - goto cleanup; - - cpumask = def->cputune.vcpupin[vcpu]->cpumask; - - for (i = 0; i < virBitmapSize(cpumask); ++i) { - bool bit; - ignore_value(virBitmapGetBit(cpumask, i, &bit)); - if (bit) - VIR_USE_CPU(cpumap, i); - } - - map.size = cpumaplen; - map.map = cpumap; - - if (libxl_set_vcpuaffinity(priv->ctx, def->id, vcpu, &map) != 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Failed to pin vcpu '%d' with libxenlight"), vcpu); - goto cleanup; - } - - VIR_FREE(cpumap); - } - - ret = 0; - -cleanup: - VIR_FREE(cpumap); - return ret; -} - -static int libxlFreeMem(libxlDomainObjPrivatePtr priv, libxl_domain_config *d_config) { uint32_t needed_mem; -- 1.8.1.4

Move libxlFreeMem from libxl_driver to libxl_domain for use by other libxl modules. For consistency, rename to libxlDomainFreeMem. Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- src/libxl/libxl_domain.c | 39 +++++++++++++++++++++++++++++++++++++++ src/libxl/libxl_domain.h | 4 ++++ src/libxl/libxl_driver.c | 41 +---------------------------------------- 3 files changed, 44 insertions(+), 40 deletions(-) diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c index ef85790..6f7924c 100644 --- a/src/libxl/libxl_domain.c +++ b/src/libxl/libxl_domain.c @@ -840,3 +840,42 @@ cleanup: VIR_FREE(cpumap); return ret; } + +int +libxlDomainFreeMem(libxlDomainObjPrivatePtr priv, libxl_domain_config *d_config) +{ + uint32_t needed_mem; + uint32_t free_mem; + size_t i; + int ret = -1; + int tries = 3; + int wait_secs = 10; + + if ((ret = libxl_domain_need_memory(priv->ctx, &d_config->b_info, + &needed_mem)) >= 0) { + for (i = 0; i < tries; ++i) { + if ((ret = libxl_get_free_memory(priv->ctx, &free_mem)) < 0) + break; + + if (free_mem >= needed_mem) { + ret = 0; + break; + } + + if ((ret = libxl_set_memory_target(priv->ctx, 0, + free_mem - needed_mem, + /* relative */ 1, 0)) < 0) + break; + + ret = libxl_wait_for_free_memory(priv->ctx, 0, needed_mem, + wait_secs); + if (ret == 0 || ret != ERROR_NOMEM) + break; + + if ((ret = libxl_wait_for_memory_target(priv->ctx, 0, 1)) < 0) + break; + } + } + + return ret; +} diff --git a/src/libxl/libxl_domain.h b/src/libxl/libxl_domain.h index 775a91c..7dacb36 100644 --- a/src/libxl/libxl_domain.h +++ b/src/libxl/libxl_domain.h @@ -127,4 +127,8 @@ int libxlDomainSetVcpuAffinities(libxlDriverPrivatePtr driver, virDomainObjPtr vm); +int +libxlDomainFreeMem(libxlDomainObjPrivatePtr priv, + libxl_domain_config *d_config); + #endif /* LIBXL_DOMAIN_H */ diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index b511383..ffe9c13 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -304,45 +304,6 @@ const struct libxl_event_hooks ev_hooks = { .disaster = NULL, }; -static int -libxlFreeMem(libxlDomainObjPrivatePtr priv, libxl_domain_config *d_config) -{ - uint32_t needed_mem; - uint32_t free_mem; - size_t i; - int ret = -1; - int tries = 3; - int wait_secs = 10; - - if ((ret = libxl_domain_need_memory(priv->ctx, &d_config->b_info, - &needed_mem)) >= 0) { - for (i = 0; i < tries; ++i) { - if ((ret = libxl_get_free_memory(priv->ctx, &free_mem)) < 0) - break; - - if (free_mem >= needed_mem) { - ret = 0; - break; - } - - if ((ret = libxl_set_memory_target(priv->ctx, 0, - free_mem - needed_mem, - /* relative */ 1, 0)) < 0) - break; - - ret = libxl_wait_for_free_memory(priv->ctx, 0, needed_mem, - wait_secs); - if (ret == 0 || ret != ERROR_NOMEM) - break; - - if ((ret = libxl_wait_for_memory_target(priv->ctx, 0, 1)) < 0) - break; - } - } - - return ret; -} - /* * Start a domain through libxenlight. * @@ -421,7 +382,7 @@ libxlVmStart(libxlDriverPrivatePtr driver, virDomainObjPtr vm, if (libxlBuildDomainConfig(driver, vm, &d_config) < 0) goto endjob; - if (cfg->autoballoon && libxlFreeMem(priv, &d_config) < 0) { + if (cfg->autoballoon && libxlDomainFreeMem(priv, &d_config) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("libxenlight failed to get free memory for domain '%s'"), d_config.c_info.name); -- 1.8.1.4

Move libxlVmStart from libxl_driver to libxl_domain for use by other libxl modules. For consistency, rename to libxlDomainStart. Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- src/libxl/libxl_domain.c | 176 +++++++++++++++++++++++++++++++++++++++++++ src/libxl/libxl_domain.h | 6 ++ src/libxl/libxl_driver.c | 191 ++--------------------------------------------- 3 files changed, 187 insertions(+), 186 deletions(-) diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c index 6f7924c..c1936aa 100644 --- a/src/libxl/libxl_domain.c +++ b/src/libxl/libxl_domain.c @@ -879,3 +879,179 @@ libxlDomainFreeMem(libxlDomainObjPrivatePtr priv, libxl_domain_config *d_config) return ret; } + +/* + * Start a domain through libxenlight. + * + * virDomainObjPtr should be locked on invocation + */ +int +libxlDomainStart(libxlDriverPrivatePtr driver, virDomainObjPtr vm, + bool start_paused, int restore_fd) +{ + libxl_domain_config d_config; + virDomainDefPtr def = NULL; + virObjectEventPtr event = NULL; + libxlSavefileHeader hdr; + int ret = -1; + uint32_t domid = 0; + char *dom_xml = NULL; + char *managed_save_path = NULL; + int managed_save_fd = -1; + libxlDomainObjPrivatePtr priv = vm->privateData; + libxlDriverConfigPtr cfg; +#ifdef LIBXL_HAVE_DOMAIN_CREATE_RESTORE_PARAMS + libxl_domain_restore_params params; +#endif + + if (libxlDomainObjPrivateInitCtx(vm) < 0) + return ret; + + if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0) + return ret; + + cfg = libxlDriverConfigGet(driver); + /* If there is a managed saved state restore it instead of starting + * from scratch. The old state is removed once the restoring succeeded. */ + if (restore_fd < 0) { + managed_save_path = libxlDomainManagedSavePath(driver, vm); + if (managed_save_path == NULL) + goto endjob; + + if (virFileExists(managed_save_path)) { + + managed_save_fd = libxlDomainSaveImageOpen(driver, cfg, + managed_save_path, + &def, &hdr); + if (managed_save_fd < 0) + goto endjob; + + restore_fd = managed_save_fd; + + if (STRNEQ(vm->def->name, def->name) || + memcmp(vm->def->uuid, def->uuid, VIR_UUID_BUFLEN)) { + char vm_uuidstr[VIR_UUID_STRING_BUFLEN]; + char def_uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(vm->def->uuid, vm_uuidstr); + virUUIDFormat(def->uuid, def_uuidstr); + virReportError(VIR_ERR_OPERATION_FAILED, + _("cannot restore domain '%s' uuid %s from a file" + " which belongs to domain '%s' uuid %s"), + vm->def->name, vm_uuidstr, def->name, def_uuidstr); + goto endjob; + } + + virDomainObjAssignDef(vm, def, true, NULL); + def = NULL; + + if (unlink(managed_save_path) < 0) + VIR_WARN("Failed to remove the managed state %s", + managed_save_path); + + vm->hasManagedSave = false; + } + VIR_FREE(managed_save_path); + } + + libxl_domain_config_init(&d_config); + + if (libxlBuildDomainConfig(driver, vm, &d_config) < 0) + goto endjob; + + if (cfg->autoballoon && libxlDomainFreeMem(priv, &d_config) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("libxenlight failed to get free memory for domain '%s'"), + d_config.c_info.name); + goto endjob; + } + + /* Unlock virDomainObj while creating the domain */ + virObjectUnlock(vm); + if (restore_fd < 0) { + ret = libxl_domain_create_new(priv->ctx, &d_config, + &domid, NULL, NULL); + } else { +#ifdef LIBXL_HAVE_DOMAIN_CREATE_RESTORE_PARAMS + params.checkpointed_stream = 0; + ret = libxl_domain_create_restore(priv->ctx, &d_config, &domid, + restore_fd, ¶ms, NULL, NULL); +#else + ret = libxl_domain_create_restore(priv->ctx, &d_config, &domid, + restore_fd, NULL, NULL); +#endif + } + virObjectLock(vm); + + if (ret) { + if (restore_fd < 0) + virReportError(VIR_ERR_INTERNAL_ERROR, + _("libxenlight failed to create new domain '%s'"), + d_config.c_info.name); + else + virReportError(VIR_ERR_INTERNAL_ERROR, + _("libxenlight failed to restore domain '%s'"), + d_config.c_info.name); + goto endjob; + } + + /* + * The domain has been successfully created with libxl, so it should + * be cleaned up if there are any subsequent failures. + */ + vm->def->id = domid; + if (libxlDomainEventsRegister(vm) < 0) + goto cleanup_dom; + + if ((dom_xml = virDomainDefFormat(vm->def, 0)) == NULL) + goto cleanup_dom; + + if (libxl_userdata_store(priv->ctx, domid, "libvirt-xml", + (uint8_t *)dom_xml, strlen(dom_xml) + 1)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("libxenlight failed to store userdata")); + goto cleanup_dom; + } + + if (libxlDomainSetVcpuAffinities(driver, vm) < 0) + goto cleanup_dom; + + if (!start_paused) { + libxl_domain_unpause(priv->ctx, domid); + virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_BOOTED); + } else { + virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER); + } + + if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0) + goto cleanup_dom; + + if (virAtomicIntInc(&driver->nactive) == 1 && driver->inhibitCallback) + driver->inhibitCallback(true, driver->inhibitOpaque); + + event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STARTED, + restore_fd < 0 ? + VIR_DOMAIN_EVENT_STARTED_BOOTED : + VIR_DOMAIN_EVENT_STARTED_RESTORED); + if (event) + libxlDomainEventQueue(driver, event); + + ret = 0; + goto endjob; + +cleanup_dom: + libxl_domain_destroy(priv->ctx, domid, NULL); + vm->def->id = -1; + virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, VIR_DOMAIN_SHUTOFF_FAILED); + +endjob: + if (!libxlDomainObjEndJob(driver, vm)) + vm = NULL; + + libxl_domain_config_dispose(&d_config); + VIR_FREE(dom_xml); + VIR_FREE(managed_save_path); + virDomainDefFree(def); + VIR_FORCE_CLOSE(managed_save_fd); + virObjectUnref(cfg); + return ret; +} diff --git a/src/libxl/libxl_domain.h b/src/libxl/libxl_domain.h index 7dacb36..4b5767a 100644 --- a/src/libxl/libxl_domain.h +++ b/src/libxl/libxl_domain.h @@ -131,4 +131,10 @@ int libxlDomainFreeMem(libxlDomainObjPrivatePtr priv, libxl_domain_config *d_config); +int +libxlDomainStart(libxlDriverPrivatePtr driver, + virDomainObjPtr vm, + bool start_paused, + int restore_fd); + #endif /* LIBXL_DOMAIN_H */ diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index ffe9c13..adf5c5d 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -74,10 +74,6 @@ static int libxlDomainManagedSaveLoad(virDomainObjPtr vm, void *opaque); -static int -libxlVmStart(libxlDriverPrivatePtr driver, virDomainObjPtr vm, - bool start_paused, int restore_fd); - /* Function definitions */ static virDomainObjPtr @@ -111,7 +107,7 @@ libxlAutostartDomain(virDomainObjPtr vm, virResetLastError(); if (vm->autostart && !virDomainObjIsActive(vm) && - libxlVmStart(driver, vm, false, -1) < 0) { + libxlDomainStart(driver, vm, false, -1) < 0) { err = virGetLastError(); VIR_ERROR(_("Failed to autostart VM '%s': %s"), vm->def->name, @@ -238,7 +234,7 @@ restart: } libxl_domain_destroy(ctx, vm->def->id, NULL); libxlDomainCleanupJob(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN); - libxlVmStart(driver, vm, 0, -1); + libxlDomainStart(driver, vm, 0, -1); cleanup: if (vm) @@ -305,183 +301,6 @@ const struct libxl_event_hooks ev_hooks = { }; /* - * Start a domain through libxenlight. - * - * virDomainObjPtr should be locked on invocation - */ -static int -libxlVmStart(libxlDriverPrivatePtr driver, virDomainObjPtr vm, - bool start_paused, int restore_fd) -{ - libxl_domain_config d_config; - virDomainDefPtr def = NULL; - virObjectEventPtr event = NULL; - libxlSavefileHeader hdr; - int ret = -1; - uint32_t domid = 0; - char *dom_xml = NULL; - char *managed_save_path = NULL; - int managed_save_fd = -1; - libxlDomainObjPrivatePtr priv = vm->privateData; - libxlDriverConfigPtr cfg; -#ifdef LIBXL_HAVE_DOMAIN_CREATE_RESTORE_PARAMS - libxl_domain_restore_params params; -#endif - - if (libxlDomainObjPrivateInitCtx(vm) < 0) - return ret; - - if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0) - return ret; - - cfg = libxlDriverConfigGet(driver); - /* If there is a managed saved state restore it instead of starting - * from scratch. The old state is removed once the restoring succeeded. */ - if (restore_fd < 0) { - managed_save_path = libxlDomainManagedSavePath(driver, vm); - if (managed_save_path == NULL) - goto endjob; - - if (virFileExists(managed_save_path)) { - - managed_save_fd = libxlDomainSaveImageOpen(driver, cfg, - managed_save_path, - &def, &hdr); - if (managed_save_fd < 0) - goto endjob; - - restore_fd = managed_save_fd; - - if (STRNEQ(vm->def->name, def->name) || - memcmp(vm->def->uuid, def->uuid, VIR_UUID_BUFLEN)) { - char vm_uuidstr[VIR_UUID_STRING_BUFLEN]; - char def_uuidstr[VIR_UUID_STRING_BUFLEN]; - virUUIDFormat(vm->def->uuid, vm_uuidstr); - virUUIDFormat(def->uuid, def_uuidstr); - virReportError(VIR_ERR_OPERATION_FAILED, - _("cannot restore domain '%s' uuid %s from a file" - " which belongs to domain '%s' uuid %s"), - vm->def->name, vm_uuidstr, def->name, def_uuidstr); - goto endjob; - } - - virDomainObjAssignDef(vm, def, true, NULL); - def = NULL; - - if (unlink(managed_save_path) < 0) - VIR_WARN("Failed to remove the managed state %s", - managed_save_path); - - vm->hasManagedSave = false; - } - VIR_FREE(managed_save_path); - } - - libxl_domain_config_init(&d_config); - - if (libxlBuildDomainConfig(driver, vm, &d_config) < 0) - goto endjob; - - if (cfg->autoballoon && libxlDomainFreeMem(priv, &d_config) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("libxenlight failed to get free memory for domain '%s'"), - d_config.c_info.name); - goto endjob; - } - - /* Unlock virDomainObj while creating the domain */ - virObjectUnlock(vm); - if (restore_fd < 0) { - ret = libxl_domain_create_new(priv->ctx, &d_config, - &domid, NULL, NULL); - } else { -#ifdef LIBXL_HAVE_DOMAIN_CREATE_RESTORE_PARAMS - params.checkpointed_stream = 0; - ret = libxl_domain_create_restore(priv->ctx, &d_config, &domid, - restore_fd, ¶ms, NULL, NULL); -#else - ret = libxl_domain_create_restore(priv->ctx, &d_config, &domid, - restore_fd, NULL, NULL); -#endif - } - virObjectLock(vm); - - if (ret) { - if (restore_fd < 0) - virReportError(VIR_ERR_INTERNAL_ERROR, - _("libxenlight failed to create new domain '%s'"), - d_config.c_info.name); - else - virReportError(VIR_ERR_INTERNAL_ERROR, - _("libxenlight failed to restore domain '%s'"), - d_config.c_info.name); - goto endjob; - } - - /* - * The domain has been successfully created with libxl, so it should - * be cleaned up if there are any subsequent failures. - */ - vm->def->id = domid; - if (libxlDomainEventsRegister(vm) < 0) - goto cleanup_dom; - - if ((dom_xml = virDomainDefFormat(vm->def, 0)) == NULL) - goto cleanup_dom; - - if (libxl_userdata_store(priv->ctx, domid, "libvirt-xml", - (uint8_t *)dom_xml, strlen(dom_xml) + 1)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("libxenlight failed to store userdata")); - goto cleanup_dom; - } - - if (libxlDomainSetVcpuAffinities(driver, vm) < 0) - goto cleanup_dom; - - if (!start_paused) { - libxl_domain_unpause(priv->ctx, domid); - virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_BOOTED); - } else { - virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER); - } - - if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0) - goto cleanup_dom; - - if (virAtomicIntInc(&driver->nactive) == 1 && driver->inhibitCallback) - driver->inhibitCallback(true, driver->inhibitOpaque); - - event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STARTED, - restore_fd < 0 ? - VIR_DOMAIN_EVENT_STARTED_BOOTED : - VIR_DOMAIN_EVENT_STARTED_RESTORED); - if (event) - libxlDomainEventQueue(driver, event); - - ret = 0; - goto endjob; - -cleanup_dom: - libxl_domain_destroy(priv->ctx, domid, NULL); - vm->def->id = -1; - virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, VIR_DOMAIN_SHUTOFF_FAILED); - -endjob: - if (!libxlDomainObjEndJob(driver, vm)) - vm = NULL; - - libxl_domain_config_dispose(&d_config); - VIR_FREE(dom_xml); - VIR_FREE(managed_save_path); - virDomainDefFree(def); - VIR_FORCE_CLOSE(managed_save_fd); - virObjectUnref(cfg); - return ret; -} - - -/* * Reconnect to running domains that were previously started/created * with libxenlight driver. */ @@ -980,7 +799,7 @@ libxlDomainCreateXML(virConnectPtr conn, const char *xml, goto cleanup; def = NULL; - if (libxlVmStart(driver, vm, (flags & VIR_DOMAIN_START_PAUSED) != 0, + if (libxlDomainStart(driver, vm, (flags & VIR_DOMAIN_START_PAUSED) != 0, -1) < 0) { virDomainObjListRemove(driver->domains, vm); vm = NULL; @@ -1760,7 +1579,7 @@ libxlDomainRestoreFlags(virConnectPtr conn, const char *from, def = NULL; - ret = libxlVmStart(driver, vm, (flags & VIR_DOMAIN_SAVE_PAUSED) != 0, fd); + ret = libxlDomainStart(driver, vm, (flags & VIR_DOMAIN_SAVE_PAUSED) != 0, fd); if (ret < 0 && !vm->persistent) { virDomainObjListRemove(driver->domains, vm); vm = NULL; @@ -2636,7 +2455,7 @@ libxlDomainCreateWithFlags(virDomainPtr dom, goto cleanup; } - ret = libxlVmStart(driver, vm, (flags & VIR_DOMAIN_START_PAUSED) != 0, -1); + ret = libxlDomainStart(driver, vm, (flags & VIR_DOMAIN_START_PAUSED) != 0, -1); cleanup: if (vm) -- 1.8.1.4

Include a pointer to the libxl driver in libxlDomainObjPrivate object so it can be used in the domain event handler and shutdown thread. Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- src/libxl/libxl_domain.c | 5 +++-- src/libxl/libxl_domain.h | 4 +++- src/libxl/libxl_driver.c | 4 ++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c index c1936aa..71cfb3d 100644 --- a/src/libxl/libxl_domain.c +++ b/src/libxl/libxl_domain.c @@ -723,10 +723,11 @@ libxlDomainCleanupJob(libxlDriverPrivatePtr driver, * Register for domain events emitted by libxl. */ int -libxlDomainEventsRegister(virDomainObjPtr vm) +libxlDomainEventsRegister(libxlDriverPrivatePtr driver, virDomainObjPtr vm) { libxlDomainObjPrivatePtr priv = vm->privateData; + priv->driver = driver; libxl_event_register_callbacks(priv->ctx, &ev_hooks, vm); /* Always enable domain death events */ @@ -999,7 +1000,7 @@ libxlDomainStart(libxlDriverPrivatePtr driver, virDomainObjPtr vm, * be cleaned up if there are any subsequent failures. */ vm->def->id = domid; - if (libxlDomainEventsRegister(vm) < 0) + if (libxlDomainEventsRegister(driver, vm) < 0) goto cleanup_dom; if ((dom_xml = virDomainDefFormat(vm->def, 0)) == NULL) diff --git a/src/libxl/libxl_domain.h b/src/libxl/libxl_domain.h index 4b5767a..979ce2a 100644 --- a/src/libxl/libxl_domain.h +++ b/src/libxl/libxl_domain.h @@ -68,6 +68,7 @@ struct _libxlDomainObjPrivate { /* console */ virChrdevsPtr devs; libxl_evgen_domain_death *deathW; + libxlDriverPrivatePtr driver; struct libxlDomainJobObj job; }; @@ -117,7 +118,8 @@ libxlDomainCleanupJob(libxlDriverPrivatePtr driver, virDomainObjPtr vm, virDomainShutoffReason reason); int -libxlDomainEventsRegister(virDomainObjPtr vm); +libxlDomainEventsRegister(libxlDriverPrivatePtr driver, + virDomainObjPtr vm); int libxlDomainAutoCoreDump(libxlDriverPrivatePtr driver, diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index adf5c5d..ec6c73a 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -145,11 +145,11 @@ struct libxlShutdownThreadInfo static void libxlDomainShutdownThread(void *opaque) { - libxlDriverPrivatePtr driver = libxl_driver; struct libxlShutdownThreadInfo *shutdown_info = opaque; virDomainObjPtr vm = shutdown_info->vm; libxlDomainObjPrivatePtr priv = vm->privateData; libxl_event *ev = shutdown_info->event; + libxlDriverPrivatePtr driver = priv->driver; libxl_ctx *ctx = priv->ctx; virObjectEventPtr dom_event = NULL; libxl_shutdown_reason xl_reason = ev->u.domain_shutdown.shutdown_reason; @@ -343,7 +343,7 @@ libxlReconnectDomain(virDomainObjPtr vm, driver->inhibitCallback(true, driver->inhibitOpaque); /* Re-register domain death et. al. events */ - libxlDomainEventsRegister(vm); + libxlDomainEventsRegister(driver, vm); virObjectUnlock(vm); return 0; -- 1.8.1.4

Move the domain event handler and shutdown thread out of the main driver module and into libxl_domain module Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- src/libxl/libxl_domain.c | 179 +++++++++++++++++++++++++++++++++++++++++++++++ src/libxl/libxl_driver.c | 179 ----------------------------------------------- 2 files changed, 179 insertions(+), 179 deletions(-) diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c index 71cfb3d..e3f705f 100644 --- a/src/libxl/libxl_domain.c +++ b/src/libxl/libxl_domain.c @@ -489,6 +489,185 @@ virDomainDefParserConfig libxlDomainDefParserConfig = { .devicesPostParseCallback = libxlDomainDeviceDefPostParse, }; + +struct libxlShutdownThreadInfo +{ + virDomainObjPtr vm; + libxl_event *event; +}; + + +static void +libxlDomainShutdownThread(void *opaque) +{ + struct libxlShutdownThreadInfo *shutdown_info = opaque; + virDomainObjPtr vm = shutdown_info->vm; + libxlDomainObjPrivatePtr priv = vm->privateData; + libxl_event *ev = shutdown_info->event; + libxlDriverPrivatePtr driver = priv->driver; + libxl_ctx *ctx = priv->ctx; + virObjectEventPtr dom_event = NULL; + libxl_shutdown_reason xl_reason = ev->u.domain_shutdown.shutdown_reason; + virDomainShutoffReason reason = VIR_DOMAIN_SHUTOFF_SHUTDOWN; + + virObjectLock(vm); + + if (xl_reason == LIBXL_SHUTDOWN_REASON_POWEROFF) { + dom_event = virDomainEventLifecycleNewFromObj(vm, + VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN); + switch ((enum virDomainLifecycleAction) vm->def->onPoweroff) { + case VIR_DOMAIN_LIFECYCLE_DESTROY: + reason = VIR_DOMAIN_SHUTOFF_SHUTDOWN; + goto destroy; + case VIR_DOMAIN_LIFECYCLE_RESTART: + case VIR_DOMAIN_LIFECYCLE_RESTART_RENAME: + goto restart; + case VIR_DOMAIN_LIFECYCLE_PRESERVE: + case VIR_DOMAIN_LIFECYCLE_LAST: + goto cleanup; + } + } else if (xl_reason == LIBXL_SHUTDOWN_REASON_CRASH) { + dom_event = virDomainEventLifecycleNewFromObj(vm, + VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_CRASHED); + switch ((enum virDomainLifecycleCrashAction) vm->def->onCrash) { + case VIR_DOMAIN_LIFECYCLE_CRASH_DESTROY: + reason = VIR_DOMAIN_SHUTOFF_CRASHED; + goto destroy; + case VIR_DOMAIN_LIFECYCLE_CRASH_RESTART: + case VIR_DOMAIN_LIFECYCLE_CRASH_RESTART_RENAME: + goto restart; + case VIR_DOMAIN_LIFECYCLE_CRASH_PRESERVE: + case VIR_DOMAIN_LIFECYCLE_CRASH_LAST: + goto cleanup; + case VIR_DOMAIN_LIFECYCLE_CRASH_COREDUMP_DESTROY: + libxlDomainAutoCoreDump(driver, vm); + goto destroy; + case VIR_DOMAIN_LIFECYCLE_CRASH_COREDUMP_RESTART: + libxlDomainAutoCoreDump(driver, vm); + goto restart; + } + } else if (xl_reason == LIBXL_SHUTDOWN_REASON_REBOOT) { + dom_event = virDomainEventLifecycleNewFromObj(vm, + VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN); + switch ((enum virDomainLifecycleAction) vm->def->onReboot) { + case VIR_DOMAIN_LIFECYCLE_DESTROY: + reason = VIR_DOMAIN_SHUTOFF_SHUTDOWN; + goto destroy; + case VIR_DOMAIN_LIFECYCLE_RESTART: + case VIR_DOMAIN_LIFECYCLE_RESTART_RENAME: + goto restart; + case VIR_DOMAIN_LIFECYCLE_PRESERVE: + case VIR_DOMAIN_LIFECYCLE_LAST: + goto cleanup; + } + } else { + VIR_INFO("Unhandled shutdown_reason %d", xl_reason); + goto cleanup; + } + +destroy: + if (dom_event) { + libxlDomainEventQueue(driver, dom_event); + dom_event = NULL; + } + libxl_domain_destroy(ctx, vm->def->id, NULL); + if (libxlDomainCleanupJob(driver, vm, reason)) { + if (!vm->persistent) { + virDomainObjListRemove(driver->domains, vm); + vm = NULL; + } + } + goto cleanup; + +restart: + if (dom_event) { + libxlDomainEventQueue(driver, dom_event); + dom_event = NULL; + } + libxl_domain_destroy(ctx, vm->def->id, NULL); + libxlDomainCleanupJob(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN); + libxlDomainStart(driver, vm, 0, -1); + +cleanup: + if (vm) + virObjectUnlock(vm); + if (dom_event) + libxlDomainEventQueue(driver, dom_event); + libxl_event_free(ctx, ev); + VIR_FREE(shutdown_info); +} + +/* + * Handle previously registered domain event notification from libxenlight. + * + * Note: Xen 4.3 removed the const from the event handler signature. + * Detect which signature to use based on + * LIBXL_HAVE_NONCONST_EVENT_OCCURS_EVENT_ARG. + */ +#ifdef LIBXL_HAVE_NONCONST_EVENT_OCCURS_EVENT_ARG +# define VIR_LIBXL_EVENT_CONST /* empty */ +#else +# define VIR_LIBXL_EVENT_CONST const +#endif + +static void +libxlEventHandler(void *data, VIR_LIBXL_EVENT_CONST libxl_event *event) +{ + virDomainObjPtr vm = data; + libxlDomainObjPrivatePtr priv = vm->privateData; + libxl_shutdown_reason xl_reason = event->u.domain_shutdown.shutdown_reason; + struct libxlShutdownThreadInfo *shutdown_info; + virThread thread; + + if (event->type != LIBXL_EVENT_TYPE_DOMAIN_SHUTDOWN) { + VIR_INFO("Unhandled event type %d", event->type); + goto error; + } + + /* + * Similar to the xl implementation, ignore SUSPEND. Any actions needed + * after calling libxl_domain_suspend() are handled by it's callers. + */ + if (xl_reason == LIBXL_SHUTDOWN_REASON_SUSPEND) + goto error; + + /* + * Start a thread to handle shutdown. We don't want to be tying up + * libxl's event machinery by doing a potentially lengthy shutdown. + */ + if (VIR_ALLOC(shutdown_info) < 0) + goto error; + + shutdown_info->vm = data; + shutdown_info->event = (libxl_event *)event; + if (virThreadCreate(&thread, false, libxlDomainShutdownThread, + shutdown_info) < 0) { + /* + * Not much we can do on error here except log it. + */ + VIR_ERROR(_("Failed to create thread to handle domain shutdown")); + goto error; + } + + /* + * libxl_event freed in shutdown thread + */ + return; + +error: + /* Cast away any const */ + libxl_event_free(priv->ctx, (libxl_event *)event); +} + +const struct libxl_event_hooks ev_hooks = { + .event_occurs_mask = LIBXL_EVENTMASK_ALL, + .event_occurs = libxlEventHandler, + .disaster = NULL, +}; + static const libxl_childproc_hooks libxl_child_hooks = { #ifdef LIBXL_HAVE_SIGCHLD_OWNER_SELECTIVE_REAP .chldowner = libxl_sigchld_owner_libxl_always_selective_reap, diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index ec6c73a..c6722d9 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -122,185 +122,6 @@ cleanup: } /* - * Handle previously registered event notification from libxenlight. - * - * Note: Xen 4.3 removed the const from the event handler signature. - * Detect which signature to use based on - * LIBXL_HAVE_NONCONST_EVENT_OCCURS_EVENT_ARG. - */ - -#ifdef LIBXL_HAVE_NONCONST_EVENT_OCCURS_EVENT_ARG -# define VIR_LIBXL_EVENT_CONST /* empty */ -#else -# define VIR_LIBXL_EVENT_CONST const -#endif - -struct libxlShutdownThreadInfo -{ - virDomainObjPtr vm; - libxl_event *event; -}; - - -static void -libxlDomainShutdownThread(void *opaque) -{ - struct libxlShutdownThreadInfo *shutdown_info = opaque; - virDomainObjPtr vm = shutdown_info->vm; - libxlDomainObjPrivatePtr priv = vm->privateData; - libxl_event *ev = shutdown_info->event; - libxlDriverPrivatePtr driver = priv->driver; - libxl_ctx *ctx = priv->ctx; - virObjectEventPtr dom_event = NULL; - libxl_shutdown_reason xl_reason = ev->u.domain_shutdown.shutdown_reason; - virDomainShutoffReason reason = VIR_DOMAIN_SHUTOFF_SHUTDOWN; - - virObjectLock(vm); - - if (xl_reason == LIBXL_SHUTDOWN_REASON_POWEROFF) { - dom_event = virDomainEventLifecycleNewFromObj(vm, - VIR_DOMAIN_EVENT_STOPPED, - VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN); - switch ((enum virDomainLifecycleAction) vm->def->onPoweroff) { - case VIR_DOMAIN_LIFECYCLE_DESTROY: - reason = VIR_DOMAIN_SHUTOFF_SHUTDOWN; - goto destroy; - case VIR_DOMAIN_LIFECYCLE_RESTART: - case VIR_DOMAIN_LIFECYCLE_RESTART_RENAME: - goto restart; - case VIR_DOMAIN_LIFECYCLE_PRESERVE: - case VIR_DOMAIN_LIFECYCLE_LAST: - goto cleanup; - } - } else if (xl_reason == LIBXL_SHUTDOWN_REASON_CRASH) { - dom_event = virDomainEventLifecycleNewFromObj(vm, - VIR_DOMAIN_EVENT_STOPPED, - VIR_DOMAIN_EVENT_STOPPED_CRASHED); - switch ((enum virDomainLifecycleCrashAction) vm->def->onCrash) { - case VIR_DOMAIN_LIFECYCLE_CRASH_DESTROY: - reason = VIR_DOMAIN_SHUTOFF_CRASHED; - goto destroy; - case VIR_DOMAIN_LIFECYCLE_CRASH_RESTART: - case VIR_DOMAIN_LIFECYCLE_CRASH_RESTART_RENAME: - goto restart; - case VIR_DOMAIN_LIFECYCLE_CRASH_PRESERVE: - case VIR_DOMAIN_LIFECYCLE_CRASH_LAST: - goto cleanup; - case VIR_DOMAIN_LIFECYCLE_CRASH_COREDUMP_DESTROY: - libxlDomainAutoCoreDump(driver, vm); - goto destroy; - case VIR_DOMAIN_LIFECYCLE_CRASH_COREDUMP_RESTART: - libxlDomainAutoCoreDump(driver, vm); - goto restart; - } - } else if (xl_reason == LIBXL_SHUTDOWN_REASON_REBOOT) { - dom_event = virDomainEventLifecycleNewFromObj(vm, - VIR_DOMAIN_EVENT_STOPPED, - VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN); - switch ((enum virDomainLifecycleAction) vm->def->onReboot) { - case VIR_DOMAIN_LIFECYCLE_DESTROY: - reason = VIR_DOMAIN_SHUTOFF_SHUTDOWN; - goto destroy; - case VIR_DOMAIN_LIFECYCLE_RESTART: - case VIR_DOMAIN_LIFECYCLE_RESTART_RENAME: - goto restart; - case VIR_DOMAIN_LIFECYCLE_PRESERVE: - case VIR_DOMAIN_LIFECYCLE_LAST: - goto cleanup; - } - } else { - VIR_INFO("Unhandled shutdown_reason %d", xl_reason); - goto cleanup; - } - -destroy: - if (dom_event) { - libxlDomainEventQueue(driver, dom_event); - dom_event = NULL; - } - libxl_domain_destroy(ctx, vm->def->id, NULL); - if (libxlDomainCleanupJob(driver, vm, reason)) { - if (!vm->persistent) { - virDomainObjListRemove(driver->domains, vm); - vm = NULL; - } - } - goto cleanup; - -restart: - if (dom_event) { - libxlDomainEventQueue(driver, dom_event); - dom_event = NULL; - } - libxl_domain_destroy(ctx, vm->def->id, NULL); - libxlDomainCleanupJob(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN); - libxlDomainStart(driver, vm, 0, -1); - -cleanup: - if (vm) - virObjectUnlock(vm); - if (dom_event) - libxlDomainEventQueue(driver, dom_event); - libxl_event_free(ctx, ev); - VIR_FREE(shutdown_info); -} - -static void -libxlEventHandler(void *data, VIR_LIBXL_EVENT_CONST libxl_event *event) -{ - virDomainObjPtr vm = data; - libxlDomainObjPrivatePtr priv = vm->privateData; - libxl_shutdown_reason xl_reason = event->u.domain_shutdown.shutdown_reason; - struct libxlShutdownThreadInfo *shutdown_info; - virThread thread; - - if (event->type != LIBXL_EVENT_TYPE_DOMAIN_SHUTDOWN) { - VIR_INFO("Unhandled event type %d", event->type); - goto error; - } - - /* - * Similar to the xl implementation, ignore SUSPEND. Any actions needed - * after calling libxl_domain_suspend() are handled by it's callers. - */ - if (xl_reason == LIBXL_SHUTDOWN_REASON_SUSPEND) - goto error; - - /* - * Start a thread to handle shutdown. We don't want to be tying up - * libxl's event machinery by doing a potentially lengthy shutdown. - */ - if (VIR_ALLOC(shutdown_info) < 0) - goto error; - - shutdown_info->vm = data; - shutdown_info->event = (libxl_event *)event; - if (virThreadCreate(&thread, false, libxlDomainShutdownThread, - shutdown_info) < 0) { - /* - * Not much we can do on error here except log it. - */ - VIR_ERROR(_("Failed to create thread to handle domain shutdown")); - goto error; - } - - /* - * libxl_event freed in shutdown thread - */ - return; - -error: - /* Cast away any const */ - libxl_event_free(priv->ctx, (libxl_event *)event); -} - -const struct libxl_event_hooks ev_hooks = { - .event_occurs_mask = LIBXL_EVENTMASK_ALL, - .event_occurs = libxlEventHandler, - .disaster = NULL, -}; - -/* * Reconnect to running domains that were previously started/created * with libxenlight driver. */ -- 1.8.1.4

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@suse.com> --- 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 | 218 +++++++++++++++++ src/libxl/libxl_migration.c | 579 ++++++++++++++++++++++++++++++++++++++++++++ src/libxl/libxl_migration.h | 78 ++++++ 7 files changed, 885 insertions(+), 1 deletion(-) diff --git a/po/POTFILES.in b/po/POTFILES.in index c565771..36ac669 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -74,6 +74,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 6ef32ee..929b304 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -698,7 +698,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 6584933..0ad444d 100644 --- a/src/libxl/libxl_conf.h +++ b/src/libxl/libxl_conf.h @@ -42,6 +42,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" @@ -113,6 +116,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 c6722d9..418437b 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 "virtypedparam.h" #include "viruri.h" @@ -194,6 +195,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); @@ -266,6 +268,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; @@ -3852,12 +3861,216 @@ 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; } } +static char * +libxlDomainMigrateBegin3Params(virDomainPtr domain, + virTypedParameterPtr params, + int nparams, + char **cookieout ATTRIBUTE_UNUSED, + int *cookieoutlen ATTRIBUTE_UNUSED, + unsigned int flags) +{ + const char *xmlin = NULL; + const char *dname = 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 || + virTypedParamsGetString(params, nparams, + VIR_MIGRATE_PARAM_DEST_NAME, + &dname) < 0) + return NULL; + + if (!(vm = libxlDomObjFromDomain(domain))) + return NULL; + + if (virDomainMigrateBegin3ParamsEnsureACL(domain->conn, vm->def) < 0) { + 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, @@ -3944,6 +4157,11 @@ static virDriver libxlDriver = { .connectDomainEventDeregisterAny = libxlConnectDomainEventDeregisterAny, /* 0.9.0 */ .connectIsAlive = libxlConnectIsAlive, /* 0.9.8 */ .connectSupportsFeature = libxlConnectSupportsFeature, /* 1.1.1 */ + .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..46f91d3 --- /dev/null +++ b/src/libxl/libxl_migration.c @@ -0,0 +1,579 @@ +/* + * 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@suse.com> + * Chunyan Liu <cyliu@suse.com> + */ + +#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 + +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"; + + +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 void +libxlDoMigrateReceive(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 = libxlDomainStart(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 +libxlDoMigrateSend(libxlDriverPrivatePtr driver, + virDomainObjPtr vm, + unsigned long flags, + int sockfd) +{ + libxlDomainObjPrivatePtr priv; + libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver); + virObjectEventPtr 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 = 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; +} + +char * +libxlDomainMigrationBegin(virConnectPtr conn, + virDomainObjPtr vm, + const char *xmlin) +{ + libxlDriverPrivatePtr driver = conn->privateData; + libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver); + virDomainDefPtr def = NULL; + char *xml = NULL; + + if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0) + goto cleanup; + + if (xmlin) { + if (!(def = virDomainDefParseString(xmlin, cfg->caps, + driver->xmlopt, + 1 << VIR_DOMAIN_VIRT_XEN, + VIR_DOMAIN_XML_INACTIVE))) + goto endjob; + + xml = virDomainDefFormat(def, VIR_DOMAIN_XML_SECURE); + } else { + xml = virDomainDefFormat(vm->def, VIR_DOMAIN_XML_SECURE); + } + +cleanup: + if (vm) + virObjectUnlock(vm); + + virDomainDefFree(def); + 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: + if (nsocks) { + 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@suse.com> + */ + +#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 */ -- 1.8.1.4

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@suse.com> --- A few small fixes found while reviewing/testing the patch. V2: - Change name of local variable in libxlDoMigrateSend from 'live' to 'xl_flags'. - Fail early in libxlDomainMigrateBegin3Params if domain is inactive 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 | 225 +++++++++++++++++ src/libxl/libxl_migration.c | 579 ++++++++++++++++++++++++++++++++++++++++++++ src/libxl/libxl_migration.h | 78 ++++++ 7 files changed, 892 insertions(+), 1 deletion(-) diff --git a/po/POTFILES.in b/po/POTFILES.in index c565771..36ac669 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -74,6 +74,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 6ef32ee..929b304 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -698,7 +698,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 6584933..0ad444d 100644 --- a/src/libxl/libxl_conf.h +++ b/src/libxl/libxl_conf.h @@ -42,6 +42,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" @@ -113,6 +116,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 c6722d9..eb4dbec 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 "virtypedparam.h" #include "viruri.h" @@ -194,6 +195,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); @@ -266,6 +268,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; @@ -3852,12 +3861,223 @@ 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; } } +static char * +libxlDomainMigrateBegin3Params(virDomainPtr domain, + virTypedParameterPtr params, + int nparams, + char **cookieout ATTRIBUTE_UNUSED, + int *cookieoutlen ATTRIBUTE_UNUSED, + unsigned int flags) +{ + const char *xmlin = NULL; + const char *dname = 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 || + virTypedParamsGetString(params, nparams, + VIR_MIGRATE_PARAM_DEST_NAME, + &dname) < 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, @@ -3944,6 +4164,11 @@ static virDriver libxlDriver = { .connectDomainEventDeregisterAny = libxlConnectDomainEventDeregisterAny, /* 0.9.0 */ .connectIsAlive = libxlConnectIsAlive, /* 0.9.8 */ .connectSupportsFeature = libxlConnectSupportsFeature, /* 1.1.1 */ + .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..4366c94 --- /dev/null +++ b/src/libxl/libxl_migration.c @@ -0,0 +1,579 @@ +/* + * 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@suse.com> + * Chunyan Liu <cyliu@suse.com> + */ + +#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 + +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"; + + +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 void +libxlDoMigrateReceive(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 = libxlDomainStart(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 +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; + + /* 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, xl_flags, 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 = 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; +} + +char * +libxlDomainMigrationBegin(virConnectPtr conn, + virDomainObjPtr vm, + const char *xmlin) +{ + libxlDriverPrivatePtr driver = conn->privateData; + libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver); + virDomainDefPtr def = NULL; + char *xml = NULL; + + if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0) + goto cleanup; + + if (xmlin) { + if (!(def = virDomainDefParseString(xmlin, cfg->caps, + driver->xmlopt, + 1 << VIR_DOMAIN_VIRT_XEN, + VIR_DOMAIN_XML_INACTIVE))) + goto endjob; + + xml = virDomainDefFormat(def, VIR_DOMAIN_XML_SECURE); + } else { + xml = virDomainDefFormat(vm->def, VIR_DOMAIN_XML_SECURE); + } + +cleanup: + if (vm) + virObjectUnlock(vm); + + virDomainDefFree(def); + 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: + if (nsocks) { + 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@suse.com> + */ + +#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 */ -- 1.8.1.4
participants (1)
-
Jim Fehlig