[libvirt] [PATCHv3 0/4] Various additions to libxl driver

This series adds additional functionality to the libxl driver. The detailed changes are noted in each individual patch. The second patch adds core dumping and requires at least Xen 4.1.1, because of this patch for xen: http://lists.xensource.com/archives/html/xen-devel/2011-05/msg01469.html The save/restore functionality requires Xen 4.2 since these patches are needed: http://lists.xensource.com/archives/html/xen-devel/2011-05/msg01314.html http://lists.xensource.com/archives/html/xen-devel/2011-05/msg01528.html To set the maximum memory of a domain this patch from Xen 4.2 is required: http://lists.xensource.com/archives/html/xen-devel/2011-05/msg01717.html Markus Groß (4): Populate domid field of devices for libxenlight Add domainCoreDump to libxl driver Add domainSave/Restore to libxl driver Support maximum and current memory flags in libxl driver src/libxl/libxl_conf.c | 20 ++- src/libxl/libxl_conf.h | 24 ++- src/libxl/libxl_driver.c | 431 +++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 418 insertions(+), 57 deletions(-) -- 1.7.5.2

This patch fixes the population of the libxenlight data structures. Now the devices should be removed correctly from the xenstore if they are detached. --- src/libxl/libxl_conf.c | 20 +++++++++++++------- src/libxl/libxl_conf.h | 10 ++++++---- src/libxl/libxl_driver.c | 6 +++--- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index b58678a..0f6035e 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -479,7 +479,8 @@ error: } int -libxlMakeDisk(virDomainDiskDefPtr l_disk, libxl_device_disk *x_disk) +libxlMakeDisk(virDomainDefPtr def, virDomainDiskDefPtr l_disk, + libxl_device_disk *x_disk) { if (l_disk->src && (x_disk->pdev_path = strdup(l_disk->src)) == NULL) { virReportOOMError(); @@ -537,6 +538,8 @@ libxlMakeDisk(virDomainDiskDefPtr l_disk, libxl_device_disk *x_disk) x_disk->readwrite = !l_disk->readonly; x_disk->is_cdrom = l_disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM ? 1 : 0; + x_disk->domid = def->id; + return 0; } @@ -554,7 +557,7 @@ libxlMakeDiskList(virDomainDefPtr def, libxl_domain_config *d_config) } for (i = 0; i < ndisks; i++) { - if (libxlMakeDisk(l_disks[i], &x_disks[i]) < 0) + if (libxlMakeDisk(def, l_disks[i], &x_disks[i]) < 0) goto error; } @@ -571,11 +574,13 @@ error: } int -libxlMakeNic(virDomainNetDefPtr l_nic, libxl_device_nic *x_nic) +libxlMakeNic(virDomainDefPtr def, virDomainNetDefPtr l_nic, + libxl_device_nic *x_nic) { // TODO: Where is mtu stored? //x_nics[i].mtu = 1492; + x_nic->domid = def->id; memcpy(x_nic->mac, l_nic->mac, sizeof(libxl_mac)); if (l_nic->model && !STREQ(l_nic->model, "netfront")) { @@ -625,7 +630,7 @@ libxlMakeNicList(virDomainDefPtr def, libxl_domain_config *d_config) for (i = 0; i < nnics; i++) { x_nics[i].devid = i; - if (libxlMakeNic(l_nics[i], &x_nics[i])) + if (libxlMakeNic(def, l_nics[i], &x_nics[i])) goto error; } @@ -642,8 +647,8 @@ error: } int -libxlMakeVfb(libxlDriverPrivatePtr driver, virDomainGraphicsDefPtr l_vfb, - libxl_device_vfb *x_vfb) +libxlMakeVfb(libxlDriverPrivatePtr driver, virDomainDefPtr def, + virDomainGraphicsDefPtr l_vfb, libxl_device_vfb *x_vfb) { int port; @@ -694,6 +699,7 @@ libxlMakeVfb(libxlDriverPrivatePtr driver, virDomainGraphicsDefPtr l_vfb, } break; } + x_vfb->domid = def->id; return 0; } @@ -724,7 +730,7 @@ libxlMakeVfbList(libxlDriverPrivatePtr driver, libxl_device_vfb_init(&x_vfbs[i], i); libxl_device_vkb_init(&x_vkbs[i], i); - if (libxlMakeVfb(driver, l_vfbs[i], &x_vfbs[i]) < 0) + if (libxlMakeVfb(driver, def, l_vfbs[i], &x_vfbs[i]) < 0) goto error; } diff --git a/src/libxl/libxl_conf.h b/src/libxl/libxl_conf.h index 5707b4e..bf5a50d 100644 --- a/src/libxl/libxl_conf.h +++ b/src/libxl/libxl_conf.h @@ -90,12 +90,14 @@ virCapsPtr libxlMakeCapabilities(libxl_ctx *ctx); int -libxlMakeDisk(virDomainDiskDefPtr l_dev, libxl_device_disk *x_dev); +libxlMakeDisk(virDomainDefPtr def, virDomainDiskDefPtr l_dev, + libxl_device_disk *x_dev); int -libxlMakeNic(virDomainNetDefPtr l_nic, libxl_device_nic *x_nic); +libxlMakeNic(virDomainDefPtr def, virDomainNetDefPtr l_nic, + libxl_device_nic *x_nic); int -libxlMakeVfb(libxlDriverPrivatePtr driver, virDomainGraphicsDefPtr l_vfb, - libxl_device_vfb *x_vfb); +libxlMakeVfb(libxlDriverPrivatePtr driver, virDomainDefPtr def, + virDomainGraphicsDefPtr l_vfb, libxl_device_vfb *x_vfb); int libxlBuildDomainConfig(libxlDriverPrivatePtr driver, diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 312d414..5463b90 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -2252,7 +2252,7 @@ libxlDomainChangeEjectableMedia(libxlDomainObjPrivatePtr priv, return -1; } - if (libxlMakeDisk(disk, &x_disk) < 0) + if (libxlMakeDisk(vm->def, disk, &x_disk) < 0) goto cleanup; if ((ret = libxl_cdrom_insert(&priv->ctx, vm->def->id, &x_disk)) < 0) { @@ -2307,7 +2307,7 @@ libxlDomainAttachDeviceDiskLive(libxlDomainObjPrivatePtr priv, goto cleanup; } - if (libxlMakeDisk(l_disk, &x_disk) < 0) + if (libxlMakeDisk(vm->def, l_disk, &x_disk) < 0) goto cleanup; if ((ret = libxl_device_disk_add(&priv->ctx, vm->def->id, @@ -2360,7 +2360,7 @@ libxlDomainDetachDeviceDiskLive(libxlDomainObjPrivatePtr priv, l_disk = vm->def->disks[i]; - if (libxlMakeDisk(l_disk, &x_disk) < 0) + if (libxlMakeDisk(vm->def, l_disk, &x_disk) < 0) goto cleanup; if ((ret = libxl_device_disk_del(&priv->ctx, &x_disk, -- 1.7.5.2

Markus Groß wrote:
This patch fixes the population of the libxenlight data structures. Now the devices should be removed correctly from the xenstore if they are detached.
ACK. I've pushed this patch since it is a bug fix to the new disk attach/detach support in the libxenlight driver. Thanks Markus, Jim
--- src/libxl/libxl_conf.c | 20 +++++++++++++------- src/libxl/libxl_conf.h | 10 ++++++---- src/libxl/libxl_driver.c | 6 +++--- 3 files changed, 22 insertions(+), 14 deletions(-)
diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index b58678a..0f6035e 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -479,7 +479,8 @@ error: }
int -libxlMakeDisk(virDomainDiskDefPtr l_disk, libxl_device_disk *x_disk) +libxlMakeDisk(virDomainDefPtr def, virDomainDiskDefPtr l_disk, + libxl_device_disk *x_disk) { if (l_disk->src && (x_disk->pdev_path = strdup(l_disk->src)) == NULL) { virReportOOMError(); @@ -537,6 +538,8 @@ libxlMakeDisk(virDomainDiskDefPtr l_disk, libxl_device_disk *x_disk) x_disk->readwrite = !l_disk->readonly; x_disk->is_cdrom = l_disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM ? 1 : 0;
+ x_disk->domid = def->id; + return 0; }
@@ -554,7 +557,7 @@ libxlMakeDiskList(virDomainDefPtr def, libxl_domain_config *d_config) }
for (i = 0; i < ndisks; i++) { - if (libxlMakeDisk(l_disks[i], &x_disks[i]) < 0) + if (libxlMakeDisk(def, l_disks[i], &x_disks[i]) < 0) goto error; }
@@ -571,11 +574,13 @@ error: }
int -libxlMakeNic(virDomainNetDefPtr l_nic, libxl_device_nic *x_nic) +libxlMakeNic(virDomainDefPtr def, virDomainNetDefPtr l_nic, + libxl_device_nic *x_nic) { // TODO: Where is mtu stored? //x_nics[i].mtu = 1492;
+ x_nic->domid = def->id; memcpy(x_nic->mac, l_nic->mac, sizeof(libxl_mac));
if (l_nic->model && !STREQ(l_nic->model, "netfront")) { @@ -625,7 +630,7 @@ libxlMakeNicList(virDomainDefPtr def, libxl_domain_config *d_config) for (i = 0; i < nnics; i++) { x_nics[i].devid = i;
- if (libxlMakeNic(l_nics[i], &x_nics[i])) + if (libxlMakeNic(def, l_nics[i], &x_nics[i])) goto error; }
@@ -642,8 +647,8 @@ error: }
int -libxlMakeVfb(libxlDriverPrivatePtr driver, virDomainGraphicsDefPtr l_vfb, - libxl_device_vfb *x_vfb) +libxlMakeVfb(libxlDriverPrivatePtr driver, virDomainDefPtr def, + virDomainGraphicsDefPtr l_vfb, libxl_device_vfb *x_vfb) { int port;
@@ -694,6 +699,7 @@ libxlMakeVfb(libxlDriverPrivatePtr driver, virDomainGraphicsDefPtr l_vfb, } break; } + x_vfb->domid = def->id; return 0; }
@@ -724,7 +730,7 @@ libxlMakeVfbList(libxlDriverPrivatePtr driver, libxl_device_vfb_init(&x_vfbs[i], i); libxl_device_vkb_init(&x_vkbs[i], i);
- if (libxlMakeVfb(driver, l_vfbs[i], &x_vfbs[i]) < 0) + if (libxlMakeVfb(driver, def, l_vfbs[i], &x_vfbs[i]) < 0) goto error; }
diff --git a/src/libxl/libxl_conf.h b/src/libxl/libxl_conf.h index 5707b4e..bf5a50d 100644 --- a/src/libxl/libxl_conf.h +++ b/src/libxl/libxl_conf.h @@ -90,12 +90,14 @@ virCapsPtr libxlMakeCapabilities(libxl_ctx *ctx);
int -libxlMakeDisk(virDomainDiskDefPtr l_dev, libxl_device_disk *x_dev); +libxlMakeDisk(virDomainDefPtr def, virDomainDiskDefPtr l_dev, + libxl_device_disk *x_dev); int -libxlMakeNic(virDomainNetDefPtr l_nic, libxl_device_nic *x_nic); +libxlMakeNic(virDomainDefPtr def, virDomainNetDefPtr l_nic, + libxl_device_nic *x_nic); int -libxlMakeVfb(libxlDriverPrivatePtr driver, virDomainGraphicsDefPtr l_vfb, - libxl_device_vfb *x_vfb); +libxlMakeVfb(libxlDriverPrivatePtr driver, virDomainDefPtr def, + virDomainGraphicsDefPtr l_vfb, libxl_device_vfb *x_vfb);
int libxlBuildDomainConfig(libxlDriverPrivatePtr driver, diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 312d414..5463b90 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -2252,7 +2252,7 @@ libxlDomainChangeEjectableMedia(libxlDomainObjPrivatePtr priv, return -1; }
- if (libxlMakeDisk(disk, &x_disk) < 0) + if (libxlMakeDisk(vm->def, disk, &x_disk) < 0) goto cleanup;
if ((ret = libxl_cdrom_insert(&priv->ctx, vm->def->id, &x_disk)) < 0) { @@ -2307,7 +2307,7 @@ libxlDomainAttachDeviceDiskLive(libxlDomainObjPrivatePtr priv, goto cleanup; }
- if (libxlMakeDisk(l_disk, &x_disk) < 0) + if (libxlMakeDisk(vm->def, l_disk, &x_disk) < 0) goto cleanup;
if ((ret = libxl_device_disk_add(&priv->ctx, vm->def->id, @@ -2360,7 +2360,7 @@ libxlDomainDetachDeviceDiskLive(libxlDomainObjPrivatePtr priv,
l_disk = vm->def->disks[i];
- if (libxlMakeDisk(l_disk, &x_disk) < 0) + if (libxlMakeDisk(vm->def, l_disk, &x_disk) < 0) goto cleanup;
if ((ret = libxl_device_disk_del(&priv->ctx, &x_disk,

v2: * incorporated Jim Fehlig's review --- src/libxl/libxl_driver.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 95 insertions(+), 0 deletions(-) diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 5463b90..86b01b2 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -1634,6 +1634,100 @@ libxlDomainGetState(virDomainPtr dom, } static int +libxlDomainCoreDump(virDomainPtr dom, const char *to, int flags) +{ + libxlDriverPrivatePtr driver = dom->conn->privateData; + libxlDomainObjPrivatePtr priv; + virDomainObjPtr vm; + virDomainEventPtr event = NULL; + bool paused = false; + int ret = -1; + + virCheckFlags(VIR_DUMP_LIVE | VIR_DUMP_CRASH, -1); + + libxlDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + libxlDriverUnlock(driver); + + if (!vm) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(dom->uuid, uuidstr); + libxlError(VIR_ERR_NO_DOMAIN, + _("No domain with matching uuid '%s'"), uuidstr); + goto cleanup; + } + + if (!virDomainObjIsActive(vm)) { + libxlError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running")); + goto cleanup; + } + + priv = vm->privateData; + + if (!(flags & VIR_DUMP_LIVE) && + virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) { + if (libxl_domain_pause(&priv->ctx, dom->id) != 0) { + libxlError(VIR_ERR_INTERNAL_ERROR, + _("Before dumping core, failed to suspend domain '%d'" + " with libxenlight"), + dom->id); + goto cleanup; + } + virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_DUMP); + paused = true; + } + + if (libxl_domain_core_dump(&priv->ctx, dom->id, to) != 0) { + libxlError(VIR_ERR_INTERNAL_ERROR, + _("Failed to dump core of domain '%d' with libxenlight"), + dom->id); + goto cleanup_unpause; + } + + libxlDriverLock(driver); + if (flags & VIR_DUMP_CRASH) { + if (libxlVmReap(driver, vm, 1, VIR_DOMAIN_SHUTOFF_CRASHED) != 0) { + libxlError(VIR_ERR_INTERNAL_ERROR, + _("Failed to destroy domain '%d'"), dom->id); + goto cleanup_unlock; + } + + event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_CRASHED); + } + + if ((flags & VIR_DUMP_CRASH) && !vm->persistent) { + virDomainRemoveInactive(&driver->domains, vm); + vm = NULL; + } + + ret = 0; + +cleanup_unlock: + libxlDriverUnlock(driver); +cleanup_unpause: + if (virDomainObjIsActive(vm) && paused) { + if (libxl_domain_unpause(&priv->ctx, dom->id) != 0) { + libxlError(VIR_ERR_INTERNAL_ERROR, + _("After dumping core, failed to resume domain '%d' with" + " libxenlight"), dom->id); + } else { + virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, + VIR_DOMAIN_RUNNING_UNPAUSED); + } + } +cleanup: + if (vm) + virDomainObjUnlock(vm); + if (event) { + libxlDriverLock(driver); + libxlDomainEventQueue(driver, event); + libxlDriverUnlock(driver); + } + return ret; +} + +static int libxlDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, unsigned int flags) { @@ -3265,6 +3359,7 @@ static virDriver libxlDriver = { .domainSetMemoryFlags = libxlDomainSetMemoryFlags, /* 0.9.0 */ .domainGetInfo = libxlDomainGetInfo, /* 0.9.0 */ .domainGetState = libxlDomainGetState, /* 0.9.2 */ + .domainCoreDump = libxlDomainCoreDump, /* 0.9.2 */ .domainSetVcpus = libxlDomainSetVcpus, /* 0.9.0 */ .domainSetVcpusFlags = libxlDomainSetVcpusFlags, /* 0.9.0 */ .domainGetVcpusFlags = libxlDomainGetVcpusFlags, /* 0.9.0 */ -- 1.7.5.2

Markus Groß wrote:
v2: * incorporated Jim Fehlig's review
--- src/libxl/libxl_driver.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 95 insertions(+), 0 deletions(-)
ACK, but I suspect we'll have to wait until 0.9.2 is released before pushing [...]
@@ -3265,6 +3359,7 @@ static virDriver libxlDriver = { .domainSetMemoryFlags = libxlDomainSetMemoryFlags, /* 0.9.0 */ .domainGetInfo = libxlDomainGetInfo, /* 0.9.0 */ .domainGetState = libxlDomainGetState, /* 0.9.2 */ + .domainCoreDump = libxlDomainCoreDump, /* 0.9.2 */
And remember to change this to 0.9.3 before doing so. Regards, Jim

On Mon, May 30, 2011 at 10:57:46PM -0600, Jim Fehlig wrote:
Markus Groß wrote:
v2: * incorporated Jim Fehlig's review
--- src/libxl/libxl_driver.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 95 insertions(+), 0 deletions(-)
ACK, but I suspect we'll have to wait until 0.9.2 is released before pushing
[...]
@@ -3265,6 +3359,7 @@ static virDriver libxlDriver = { .domainSetMemoryFlags = libxlDomainSetMemoryFlags, /* 0.9.0 */ .domainGetInfo = libxlDomainGetInfo, /* 0.9.0 */ .domainGetState = libxlDomainGetState, /* 0.9.2 */ + .domainCoreDump = libxlDomainCoreDump, /* 0.9.2 */
And remember to change this to 0.9.3 before doing so.
Actually it's a pure addition, I fine to push if we push it today, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

Daniel Veillard wrote:
On Mon, May 30, 2011 at 10:57:46PM -0600, Jim Fehlig wrote:
Markus Groß wrote:
v2: * incorporated Jim Fehlig's review
--- src/libxl/libxl_driver.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 95 insertions(+), 0 deletions(-)
ACK, but I suspect we'll have to wait until 0.9.2 is released before pushing
[...]
@@ -3265,6 +3359,7 @@ static virDriver libxlDriver = { .domainSetMemoryFlags = libxlDomainSetMemoryFlags, /* 0.9.0 */ .domainGetInfo = libxlDomainGetInfo, /* 0.9.0 */ .domainGetState = libxlDomainGetState, /* 0.9.2 */ + .domainCoreDump = libxlDomainCoreDump, /* 0.9.2 */
And remember to change this to 0.9.3 before doing so.
Actually it's a pure addition, I fine to push if we push it today,
OK, great. I've pushed the rest of the series. Thanks! Regards, Jim

v3: * initialize xml pointer to avoid segfault * throw error message if domain is paused as libxenlight itself will pause it v2: * header is now padded and has a version field * the correct restore function from libxl is used * only create the restore event once in libxlVmStart --- src/libxl/libxl_conf.h | 14 +++ src/libxl/libxl_driver.c | 229 +++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 228 insertions(+), 15 deletions(-) diff --git a/src/libxl/libxl_conf.h b/src/libxl/libxl_conf.h index bf5a50d..2820afb 100644 --- a/src/libxl/libxl_conf.h +++ b/src/libxl/libxl_conf.h @@ -1,5 +1,6 @@ /*---------------------------------------------------------------------------*/ /* Copyright (c) 2011 SUSE LINUX Products GmbH, Nuernberg, Germany. + * Copyright (C) 2011 Univention GmbH. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -17,6 +18,7 @@ * * Authors: * Jim Fehlig <jfehlig@novell.com> + * Markus Groß <gross@univention.de> */ /*---------------------------------------------------------------------------*/ @@ -81,6 +83,18 @@ struct _libxlDomainObjPrivate { int eventHdl; }; +# define LIBXL_SAVE_MAGIC "libvirt-xml\n \0 \r" +# define LIBXL_SAVE_VERSION 1 + +typedef struct _libxlSavefileHeader libxlSavefileHeader; +typedef libxlSavefileHeader *libxlSavefileHeaderPtr; +struct _libxlSavefileHeader { + char magic[sizeof(LIBXL_SAVE_MAGIC)-1]; + uint32_t version; + uint32_t xmlLen; + /* 24 bytes used, pad up to 64 bytes */ + uint32_t unused[10]; +}; # define libxlError(code, ...) \ virReportErrorHelper(VIR_FROM_LIBXL, code, __FILE__, \ diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 86b01b2..0a2401a 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -29,6 +29,7 @@ #include <sys/utsname.h> #include <math.h> #include <libxl.h> +#include <fcntl.h> #include "internal.h" #include "logging.h" @@ -60,11 +61,10 @@ static libxlDriverPrivatePtr libxl_driver = NULL; - /* Function declarations */ static int -libxlVmStart(libxlDriverPrivatePtr driver, - virDomainObjPtr vm, bool start_paused); +libxlVmStart(libxlDriverPrivatePtr driver, virDomainObjPtr vm, + bool start_paused, int restore_fd); /* Function definitions */ @@ -168,7 +168,7 @@ libxlAutostartDomain(void *payload, const void *name ATTRIBUTE_UNUSED, virResetLastError(); if (vm->autostart && !virDomainObjIsActive(vm) && - libxlVmStart(driver, vm, false) < 0) { + libxlVmStart(driver, vm, false, -1) < 0) { err = virGetLastError(); VIR_ERROR(_("Failed to autostart VM '%s': %s"), vm->def->name, @@ -376,7 +376,7 @@ static void libxlEventHandler(int watch, break; case SHUTDOWN_reboot: libxlVmReap(driver, vm, 0, VIR_DOMAIN_SHUTOFF_SHUTDOWN); - libxlVmStart(driver, vm, 0); + libxlVmStart(driver, vm, 0, -1); break; default: VIR_INFO("Unhandled shutdown_reason %d", info.shutdown_reason); @@ -542,8 +542,8 @@ libxlFreeMem(libxlDomainObjPrivatePtr priv, libxl_domain_config *d_config) * virDomainObjPtr should be locked on invocation */ static int -libxlVmStart(libxlDriverPrivatePtr driver, - virDomainObjPtr vm, bool start_paused) +libxlVmStart(libxlDriverPrivatePtr driver, virDomainObjPtr vm, + bool start_paused, int restore_fd) { libxl_domain_config d_config; virDomainDefPtr def = vm->def; @@ -566,12 +566,23 @@ libxlVmStart(libxlDriverPrivatePtr driver, goto error; } - ret = libxl_domain_create_new(&priv->ctx, &d_config, - NULL, &child_console_pid, &domid); + if (restore_fd < 0) + ret = libxl_domain_create_new(&priv->ctx, &d_config, + NULL, &child_console_pid, &domid); + else + ret = libxl_domain_create_restore(&priv->ctx, &d_config, NULL, + &child_console_pid, &domid, + restore_fd); + if (ret) { - libxlError(VIR_ERR_INTERNAL_ERROR, - _("libxenlight failed to create new domain '%s'"), - d_config.c_info.name); + if (restore_fd < 0) + libxlError(VIR_ERR_INTERNAL_ERROR, + _("libxenlight failed to create new domain '%s'"), + d_config.c_info.name); + else + libxlError(VIR_ERR_INTERNAL_ERROR, + _("libxenlight failed to restore domain '%s'"), + d_config.c_info.name); goto error; } @@ -604,7 +615,9 @@ libxlVmStart(libxlDriverPrivatePtr driver, goto error; event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STARTED, - VIR_DOMAIN_EVENT_STARTED_BOOTED); + restore_fd < 0 ? + VIR_DOMAIN_EVENT_STARTED_BOOTED : + VIR_DOMAIN_EVENT_STARTED_RESTORED); libxlDomainEventQueue(driver, event); libxl_domain_config_destroy(&d_config); @@ -1082,7 +1095,8 @@ libxlDomainCreateXML(virConnectPtr conn, const char *xml, goto cleanup; def = NULL; - if (libxlVmStart(driver, vm, (flags & VIR_DOMAIN_START_PAUSED) != 0) < 0) { + if (libxlVmStart(driver, vm, (flags & VIR_DOMAIN_START_PAUSED) != 0, + -1) < 0) { virDomainRemoveInactive(&driver->domains, vm); vm = NULL; goto cleanup; @@ -1634,6 +1648,189 @@ libxlDomainGetState(virDomainPtr dom, } static int +libxlDomainSave(virDomainPtr dom, const char *to) +{ + libxlDriverPrivatePtr driver = dom->conn->privateData; + virDomainObjPtr vm; + libxlDomainObjPrivatePtr priv; + libxlSavefileHeader hdr; + virDomainEventPtr event = NULL; + char *xml = NULL; + uint32_t xml_len; + int fd; + int ret = -1; + + libxlDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + + if (!vm) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(dom->uuid, uuidstr); + libxlError(VIR_ERR_NO_DOMAIN, + _("No domain with matching uuid '%s'"), uuidstr); + goto cleanup; + } + + if (!virDomainObjIsActive(vm)) { + libxlError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running")); + goto cleanup; + } + + priv = vm->privateData; + + if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) { + libxlError(VIR_ERR_OPERATION_INVALID, + _("Domain '%d' has to be running because libxenlight will" + " suspend it"), dom->id); + goto cleanup; + } + + if ((fd = virFileOpenAs(to, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR, + getuid(), getgid(), 0)) < 0) { + virReportSystemError(-fd, + _("Failed to create domain save file '%s'"), to); + goto cleanup; + } + + if ((xml = virDomainDefFormat(vm->def, 0)) == NULL) + goto cleanup; + xml_len = strlen(xml) + 1; + + memset(&hdr, 0, sizeof(hdr)); + memcpy(hdr.magic, LIBXL_SAVE_MAGIC, sizeof(hdr.magic)); + hdr.version = LIBXL_SAVE_VERSION; + hdr.xmlLen = xml_len; + + if (safewrite(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) { + libxlError(VIR_ERR_OPERATION_FAILED, + _("Failed to write save file header")); + goto cleanup; + } + + if (safewrite(fd, xml, xml_len) != xml_len) { + libxlError(VIR_ERR_OPERATION_FAILED, + _("Failed to write xml description")); + goto cleanup; + } + + if (libxl_domain_suspend(&priv->ctx, NULL, dom->id, fd) != 0) { + libxlError(VIR_ERR_INTERNAL_ERROR, + _("Failed to save domain '%d' with libxenlight"), + dom->id); + goto cleanup; + } + + event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_SAVED); + + if (libxlVmReap(driver, vm, 1, VIR_DOMAIN_SHUTOFF_SAVED) != 0) { + libxlError(VIR_ERR_INTERNAL_ERROR, + _("Failed to destroy domain '%d'"), dom->id); + goto cleanup; + } + + if (!vm->persistent) { + virDomainRemoveInactive(&driver->domains, vm); + vm = NULL; + } + + ret = 0; + +cleanup: + VIR_FREE(xml); + if (VIR_CLOSE(fd) < 0) + virReportSystemError(errno, "%s", _("cannot close file")); + if (vm) + virDomainObjUnlock(vm); + if (event) + libxlDomainEventQueue(driver, event); + libxlDriverUnlock(driver); + return ret; +} + +static int +libxlDomainRestore(virConnectPtr conn, const char *from) +{ + libxlDriverPrivatePtr driver = conn->privateData; + virDomainDefPtr def = NULL; + virDomainObjPtr vm = NULL; + libxlSavefileHeader hdr; + char *xml = NULL; + int fd; + int ret = -1; + + libxlDriverLock(driver); + + if ((fd = virFileOpenAs(from, O_RDONLY, 0, getuid(), getgid(), 0)) < 0) { + libxlError(VIR_ERR_OPERATION_FAILED, + "%s", _("cannot read domain image")); + goto cleanup; + } + + if (saferead(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) { + libxlError(VIR_ERR_OPERATION_FAILED, + "%s", _("failed to read libxl header")); + goto cleanup; + } + + if (memcmp(hdr.magic, LIBXL_SAVE_MAGIC, sizeof(hdr.magic))) { + libxlError(VIR_ERR_INVALID_ARG, "%s", _("image magic is incorrect")); + goto cleanup; + } + + if (hdr.version > LIBXL_SAVE_VERSION) { + libxlError(VIR_ERR_OPERATION_FAILED, + _("image version is not supported (%d > %d)"), + hdr.version, LIBXL_SAVE_VERSION); + goto cleanup; + } + + if (hdr.xmlLen <= 0) { + libxlError(VIR_ERR_OPERATION_FAILED, + _("invalid XML length: %d"), hdr.xmlLen); + goto cleanup; + } + + if (VIR_ALLOC_N(xml, hdr.xmlLen) < 0) { + virReportOOMError(); + goto cleanup; + } + + if (saferead(fd, xml, hdr.xmlLen) != hdr.xmlLen) { + libxlError(VIR_ERR_OPERATION_FAILED, "%s", _("failed to read XML")); + goto cleanup; + } + + if (!(def = virDomainDefParseString(driver->caps, xml, + VIR_DOMAIN_XML_INACTIVE))) + goto cleanup; + + if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0) + goto cleanup; + + if (!(vm = virDomainAssignDef(driver->caps, &driver->domains, def, true))) + goto cleanup; + + def = NULL; + + if ((ret = libxlVmStart(driver, vm, false, fd)) < 0 && + !vm->persistent) { + virDomainRemoveInactive(&driver->domains, vm); + vm = NULL; + } + +cleanup: + VIR_FREE(xml); + virDomainDefFree(def); + if (VIR_CLOSE(fd) < 0) + virReportSystemError(errno, "%s", _("cannot close file")); + if (vm) + virDomainObjUnlock(vm); + libxlDriverUnlock(driver); + return ret; +} + +static int libxlDomainCoreDump(virDomainPtr dom, const char *to, int flags) { libxlDriverPrivatePtr driver = dom->conn->privateData; @@ -2197,7 +2394,7 @@ libxlDomainCreateWithFlags(virDomainPtr dom, goto cleanup; } - ret = libxlVmStart(driver, vm, (flags & VIR_DOMAIN_START_PAUSED) != 0); + ret = libxlVmStart(driver, vm, (flags & VIR_DOMAIN_START_PAUSED) != 0, -1); cleanup: if (vm) @@ -3359,6 +3556,8 @@ static virDriver libxlDriver = { .domainSetMemoryFlags = libxlDomainSetMemoryFlags, /* 0.9.0 */ .domainGetInfo = libxlDomainGetInfo, /* 0.9.0 */ .domainGetState = libxlDomainGetState, /* 0.9.2 */ + .domainSave = libxlDomainSave, /* 0.9.2 */ + .domainRestore = libxlDomainRestore, /* 0.9.2 */ .domainCoreDump = libxlDomainCoreDump, /* 0.9.2 */ .domainSetVcpus = libxlDomainSetVcpus, /* 0.9.0 */ .domainSetVcpusFlags = libxlDomainSetVcpusFlags, /* 0.9.0 */ -- 1.7.5.2

On Mon, May 30, 2011 at 11:53:02AM +0200, Markus Groß wrote:
v3: * initialize xml pointer to avoid segfault * throw error message if domain is paused as libxenlight itself will pause it
v2: * header is now padded and has a version field * the correct restore function from libxl is used * only create the restore event once in libxlVmStart
--- src/libxl/libxl_conf.h | 14 +++ src/libxl/libxl_driver.c | 229 +++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 228 insertions(+), 15 deletions(-)
diff --git a/src/libxl/libxl_conf.h b/src/libxl/libxl_conf.h index bf5a50d..2820afb 100644 --- a/src/libxl/libxl_conf.h +++ b/src/libxl/libxl_conf.h @@ -1,5 +1,6 @@ /*---------------------------------------------------------------------------*/ /* Copyright (c) 2011 SUSE LINUX Products GmbH, Nuernberg, Germany. + * Copyright (C) 2011 Univention GmbH. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -17,6 +18,7 @@ * * Authors: * Jim Fehlig <jfehlig@novell.com> + * Markus Groß <gross@univention.de> */ /*---------------------------------------------------------------------------*/
@@ -81,6 +83,18 @@ struct _libxlDomainObjPrivate { int eventHdl; };
+# define LIBXL_SAVE_MAGIC "libvirt-xml\n \0 \r" +# define LIBXL_SAVE_VERSION 1 + +typedef struct _libxlSavefileHeader libxlSavefileHeader; +typedef libxlSavefileHeader *libxlSavefileHeaderPtr; +struct _libxlSavefileHeader { + char magic[sizeof(LIBXL_SAVE_MAGIC)-1]; + uint32_t version; + uint32_t xmlLen; + /* 24 bytes used, pad up to 64 bytes */ + uint32_t unused[10]; +};
# define libxlError(code, ...) \ virReportErrorHelper(VIR_FROM_LIBXL, code, __FILE__, \ diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 86b01b2..0a2401a 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -29,6 +29,7 @@ #include <sys/utsname.h> #include <math.h> #include <libxl.h> +#include <fcntl.h>
#include "internal.h" #include "logging.h" @@ -60,11 +61,10 @@
static libxlDriverPrivatePtr libxl_driver = NULL;
- /* Function declarations */ static int -libxlVmStart(libxlDriverPrivatePtr driver, - virDomainObjPtr vm, bool start_paused); +libxlVmStart(libxlDriverPrivatePtr driver, virDomainObjPtr vm, + bool start_paused, int restore_fd);
/* Function definitions */ @@ -168,7 +168,7 @@ libxlAutostartDomain(void *payload, const void *name ATTRIBUTE_UNUSED, virResetLastError();
if (vm->autostart && !virDomainObjIsActive(vm) && - libxlVmStart(driver, vm, false) < 0) { + libxlVmStart(driver, vm, false, -1) < 0) { err = virGetLastError(); VIR_ERROR(_("Failed to autostart VM '%s': %s"), vm->def->name, @@ -376,7 +376,7 @@ static void libxlEventHandler(int watch, break; case SHUTDOWN_reboot: libxlVmReap(driver, vm, 0, VIR_DOMAIN_SHUTOFF_SHUTDOWN); - libxlVmStart(driver, vm, 0); + libxlVmStart(driver, vm, 0, -1); break; default: VIR_INFO("Unhandled shutdown_reason %d", info.shutdown_reason); @@ -542,8 +542,8 @@ libxlFreeMem(libxlDomainObjPrivatePtr priv, libxl_domain_config *d_config) * virDomainObjPtr should be locked on invocation */ static int -libxlVmStart(libxlDriverPrivatePtr driver, - virDomainObjPtr vm, bool start_paused) +libxlVmStart(libxlDriverPrivatePtr driver, virDomainObjPtr vm, + bool start_paused, int restore_fd) { libxl_domain_config d_config; virDomainDefPtr def = vm->def; @@ -566,12 +566,23 @@ libxlVmStart(libxlDriverPrivatePtr driver, goto error; }
- ret = libxl_domain_create_new(&priv->ctx, &d_config, - NULL, &child_console_pid, &domid); + if (restore_fd < 0) + ret = libxl_domain_create_new(&priv->ctx, &d_config, + NULL, &child_console_pid, &domid); + else + ret = libxl_domain_create_restore(&priv->ctx, &d_config, NULL, + &child_console_pid, &domid, + restore_fd); + if (ret) { - libxlError(VIR_ERR_INTERNAL_ERROR, - _("libxenlight failed to create new domain '%s'"), - d_config.c_info.name); + if (restore_fd < 0) + libxlError(VIR_ERR_INTERNAL_ERROR, + _("libxenlight failed to create new domain '%s'"), + d_config.c_info.name); + else + libxlError(VIR_ERR_INTERNAL_ERROR, + _("libxenlight failed to restore domain '%s'"), + d_config.c_info.name); goto error; }
@@ -604,7 +615,9 @@ libxlVmStart(libxlDriverPrivatePtr driver, goto error;
event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STARTED, - VIR_DOMAIN_EVENT_STARTED_BOOTED); + restore_fd < 0 ? + VIR_DOMAIN_EVENT_STARTED_BOOTED : + VIR_DOMAIN_EVENT_STARTED_RESTORED); libxlDomainEventQueue(driver, event);
libxl_domain_config_destroy(&d_config); @@ -1082,7 +1095,8 @@ libxlDomainCreateXML(virConnectPtr conn, const char *xml, goto cleanup; def = NULL;
- if (libxlVmStart(driver, vm, (flags & VIR_DOMAIN_START_PAUSED) != 0) < 0) { + if (libxlVmStart(driver, vm, (flags & VIR_DOMAIN_START_PAUSED) != 0, + -1) < 0) { virDomainRemoveInactive(&driver->domains, vm); vm = NULL; goto cleanup; @@ -1634,6 +1648,189 @@ libxlDomainGetState(virDomainPtr dom, }
static int +libxlDomainSave(virDomainPtr dom, const char *to) +{ + libxlDriverPrivatePtr driver = dom->conn->privateData; + virDomainObjPtr vm; + libxlDomainObjPrivatePtr priv; + libxlSavefileHeader hdr; + virDomainEventPtr event = NULL; + char *xml = NULL; + uint32_t xml_len; + int fd; + int ret = -1; + + libxlDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + + if (!vm) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(dom->uuid, uuidstr); + libxlError(VIR_ERR_NO_DOMAIN, + _("No domain with matching uuid '%s'"), uuidstr); + goto cleanup; + } + + if (!virDomainObjIsActive(vm)) { + libxlError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running")); + goto cleanup; + } + + priv = vm->privateData; + + if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) { + libxlError(VIR_ERR_OPERATION_INVALID, + _("Domain '%d' has to be running because libxenlight will" + " suspend it"), dom->id); + goto cleanup; + } + + if ((fd = virFileOpenAs(to, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR, + getuid(), getgid(), 0)) < 0) { + virReportSystemError(-fd, + _("Failed to create domain save file '%s'"), to); + goto cleanup; + } + + if ((xml = virDomainDefFormat(vm->def, 0)) == NULL) + goto cleanup; + xml_len = strlen(xml) + 1; + + memset(&hdr, 0, sizeof(hdr)); + memcpy(hdr.magic, LIBXL_SAVE_MAGIC, sizeof(hdr.magic)); + hdr.version = LIBXL_SAVE_VERSION; + hdr.xmlLen = xml_len; + + if (safewrite(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) { + libxlError(VIR_ERR_OPERATION_FAILED, + _("Failed to write save file header")); + goto cleanup; + } + + if (safewrite(fd, xml, xml_len) != xml_len) { + libxlError(VIR_ERR_OPERATION_FAILED, + _("Failed to write xml description")); + goto cleanup; + } + + if (libxl_domain_suspend(&priv->ctx, NULL, dom->id, fd) != 0) { + libxlError(VIR_ERR_INTERNAL_ERROR, + _("Failed to save domain '%d' with libxenlight"), + dom->id); + goto cleanup; + } + + event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_SAVED); + + if (libxlVmReap(driver, vm, 1, VIR_DOMAIN_SHUTOFF_SAVED) != 0) { + libxlError(VIR_ERR_INTERNAL_ERROR, + _("Failed to destroy domain '%d'"), dom->id); + goto cleanup; + } + + if (!vm->persistent) { + virDomainRemoveInactive(&driver->domains, vm); + vm = NULL; + } + + ret = 0; + +cleanup: + VIR_FREE(xml); + if (VIR_CLOSE(fd) < 0) + virReportSystemError(errno, "%s", _("cannot close file")); + if (vm) + virDomainObjUnlock(vm); + if (event) + libxlDomainEventQueue(driver, event); + libxlDriverUnlock(driver); + return ret; +} + +static int +libxlDomainRestore(virConnectPtr conn, const char *from) +{ + libxlDriverPrivatePtr driver = conn->privateData; + virDomainDefPtr def = NULL; + virDomainObjPtr vm = NULL; + libxlSavefileHeader hdr; + char *xml = NULL; + int fd; + int ret = -1; + + libxlDriverLock(driver); + + if ((fd = virFileOpenAs(from, O_RDONLY, 0, getuid(), getgid(), 0)) < 0) { + libxlError(VIR_ERR_OPERATION_FAILED, + "%s", _("cannot read domain image")); + goto cleanup; + } + + if (saferead(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) { + libxlError(VIR_ERR_OPERATION_FAILED, + "%s", _("failed to read libxl header")); + goto cleanup; + } + + if (memcmp(hdr.magic, LIBXL_SAVE_MAGIC, sizeof(hdr.magic))) { + libxlError(VIR_ERR_INVALID_ARG, "%s", _("image magic is incorrect")); + goto cleanup; + } + + if (hdr.version > LIBXL_SAVE_VERSION) { + libxlError(VIR_ERR_OPERATION_FAILED, + _("image version is not supported (%d > %d)"), + hdr.version, LIBXL_SAVE_VERSION); + goto cleanup; + } + + if (hdr.xmlLen <= 0) { + libxlError(VIR_ERR_OPERATION_FAILED, + _("invalid XML length: %d"), hdr.xmlLen); + goto cleanup; + } + + if (VIR_ALLOC_N(xml, hdr.xmlLen) < 0) { + virReportOOMError(); + goto cleanup; + } + + if (saferead(fd, xml, hdr.xmlLen) != hdr.xmlLen) { + libxlError(VIR_ERR_OPERATION_FAILED, "%s", _("failed to read XML")); + goto cleanup; + } + + if (!(def = virDomainDefParseString(driver->caps, xml, + VIR_DOMAIN_XML_INACTIVE))) + goto cleanup; + + if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0) + goto cleanup; + + if (!(vm = virDomainAssignDef(driver->caps, &driver->domains, def, true))) + goto cleanup; + + def = NULL; + + if ((ret = libxlVmStart(driver, vm, false, fd)) < 0 && + !vm->persistent) { + virDomainRemoveInactive(&driver->domains, vm); + vm = NULL; + } + +cleanup: + VIR_FREE(xml); + virDomainDefFree(def); + if (VIR_CLOSE(fd) < 0) + virReportSystemError(errno, "%s", _("cannot close file")); + if (vm) + virDomainObjUnlock(vm); + libxlDriverUnlock(driver); + return ret; +} + +static int libxlDomainCoreDump(virDomainPtr dom, const char *to, int flags) { libxlDriverPrivatePtr driver = dom->conn->privateData; @@ -2197,7 +2394,7 @@ libxlDomainCreateWithFlags(virDomainPtr dom, goto cleanup; }
- ret = libxlVmStart(driver, vm, (flags & VIR_DOMAIN_START_PAUSED) != 0); + ret = libxlVmStart(driver, vm, (flags & VIR_DOMAIN_START_PAUSED) != 0, -1);
cleanup: if (vm) @@ -3359,6 +3556,8 @@ static virDriver libxlDriver = { .domainSetMemoryFlags = libxlDomainSetMemoryFlags, /* 0.9.0 */ .domainGetInfo = libxlDomainGetInfo, /* 0.9.0 */ .domainGetState = libxlDomainGetState, /* 0.9.2 */ + .domainSave = libxlDomainSave, /* 0.9.2 */ + .domainRestore = libxlDomainRestore, /* 0.9.2 */ .domainCoreDump = libxlDomainCoreDump, /* 0.9.2 */ .domainSetVcpus = libxlDomainSetVcpus, /* 0.9.0 */ .domainSetVcpusFlags = libxlDomainSetVcpusFlags, /* 0.9.0 */ -- 1.7.5.2
ACK, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

Add support to set the maximum memory of the domain. Also add support to change the memory of the current state of the domain, which translates to a running domain or the config of the domain. Based on the code from the qemu driver. --- src/libxl/libxl_driver.c | 101 +++++++++++++++++++++++++++++++++------------- 1 files changed, 73 insertions(+), 28 deletions(-) diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 0a2401a..3491f40 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -1493,22 +1493,19 @@ cleanup: } static int -libxlDomainSetMemoryFlags(virDomainPtr dom, unsigned long memory, +libxlDomainSetMemoryFlags(virDomainPtr dom, unsigned long newmem, unsigned int flags) { libxlDriverPrivatePtr driver = dom->conn->privateData; libxlDomainObjPrivatePtr priv; virDomainObjPtr vm; - virDomainDefPtr def = NULL; + virDomainDefPtr persistentDef = NULL; + bool isActive; int ret = -1; virCheckFlags(VIR_DOMAIN_MEM_LIVE | - VIR_DOMAIN_MEM_CONFIG, -1); - - if ((flags & (VIR_DOMAIN_MEM_LIVE | VIR_DOMAIN_MEM_CONFIG)) == 0) { - libxlError(VIR_ERR_INVALID_ARG, - _("invalid flag combination: (0x%x)"), flags); - } + VIR_DOMAIN_MEM_CONFIG | + VIR_DOMAIN_MEM_MAXIMUM, -1); libxlDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); @@ -1519,13 +1516,22 @@ libxlDomainSetMemoryFlags(virDomainPtr dom, unsigned long memory, goto cleanup; } - if (memory > vm->def->mem.max_balloon) { - libxlError(VIR_ERR_INVALID_ARG, "%s", - _("cannot set memory higher than max memory")); - goto cleanup; + isActive = virDomainObjIsActive(vm); + + if (flags == VIR_DOMAIN_MEM_CURRENT) { + if (isActive) + flags = VIR_DOMAIN_MEM_LIVE; + else + flags = VIR_DOMAIN_MEM_CONFIG; + } + if (flags == VIR_DOMAIN_MEM_MAXIMUM) { + if (isActive) + flags = VIR_DOMAIN_MEM_LIVE | VIR_DOMAIN_MEM_MAXIMUM; + else + flags = VIR_DOMAIN_MEM_CONFIG | VIR_DOMAIN_MEM_MAXIMUM; } - if (!virDomainObjIsActive(vm) && (flags & VIR_DOMAIN_MEM_LIVE)) { + if (!isActive && (flags & VIR_DOMAIN_MEM_LIVE)) { libxlError(VIR_ERR_OPERATION_INVALID, "%s", _("cannot set memory on an inactive domain")); goto cleanup; @@ -1537,31 +1543,63 @@ libxlDomainSetMemoryFlags(virDomainPtr dom, unsigned long memory, _("cannot change persistent config of a transient domain")); goto cleanup; } - if (!(def = virDomainObjGetPersistentDef(driver->caps, vm))) + if (!(persistentDef = virDomainObjGetPersistentDef(driver->caps, vm))) goto cleanup; } - if (flags & VIR_DOMAIN_MEM_LIVE) { - priv = vm->privateData; + if (flags & VIR_DOMAIN_MEM_MAXIMUM) { + /* resize the maximum memory */ - if (libxl_set_memory_target(&priv->ctx, dom->id, memory, 0, - /* force */ 1) < 0) { - libxlError(VIR_ERR_INTERNAL_ERROR, - _("Failed to set memory for domain '%d'" - " with libxenlight"), dom->id); + if (flags & VIR_DOMAIN_MEM_LIVE) { + priv = vm->privateData; + if (libxl_domain_setmaxmem(&priv->ctx, dom->id, newmem) < 0) { + libxlError(VIR_ERR_INTERNAL_ERROR, + _("Failed to set maximum memory for domain '%d'" + " with libxenlight"), dom->id); + goto cleanup; + } + } + + if (flags & VIR_DOMAIN_MEM_CONFIG) { + /* Help clang 2.8 decipher the logic flow. */ + sa_assert(persistentDef); + persistentDef->mem.max_balloon = newmem; + if (persistentDef->mem.cur_balloon > newmem) + persistentDef->mem.cur_balloon = newmem; + ret = virDomainSaveConfig(driver->configDir, persistentDef); goto cleanup; } - } - ret = 0; + } else { + /* resize the current memory */ - if (flags & VIR_DOMAIN_MEM_CONFIG) { - /* clang 2.9 needs an extra hint. */ - sa_assert(def); - def->mem.cur_balloon = memory; - ret = virDomainSaveConfig(driver->configDir, def); + if (newmem > vm->def->mem.max_balloon) { + libxlError(VIR_ERR_INVALID_ARG, "%s", + _("cannot set memory higher than max memory")); + goto cleanup; + } + + if (flags & VIR_DOMAIN_MEM_LIVE) { + priv = vm->privateData; + if (libxl_set_memory_target(&priv->ctx, dom->id, newmem, 0, + /* force */ 1) < 0) { + libxlError(VIR_ERR_INTERNAL_ERROR, + _("Failed to set memory for domain '%d'" + " with libxenlight"), dom->id); + goto cleanup; + } + } + + if (flags & VIR_DOMAIN_MEM_CONFIG) { + sa_assert(persistentDef); + persistentDef->mem.cur_balloon = newmem; + ret = virDomainSaveConfig(driver->configDir, persistentDef); + goto cleanup; + } } + ret = 0; + cleanup: if (vm) virDomainObjUnlock(vm); @@ -1575,6 +1613,12 @@ libxlDomainSetMemory(virDomainPtr dom, unsigned long memory) } static int +libxlDomainSetMaxMemory(virDomainPtr dom, unsigned long memory) +{ + return libxlDomainSetMemoryFlags(dom, memory, VIR_DOMAIN_MEM_MAXIMUM); +} + +static int libxlDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info) { libxlDriverPrivatePtr driver = dom->conn->privateData; @@ -3552,6 +3596,7 @@ static virDriver libxlDriver = { .domainDestroy = libxlDomainDestroy, /* 0.9.0 */ .domainGetOSType = libxlDomainGetOSType, /* 0.9.0 */ .domainGetMaxMemory = libxlDomainGetMaxMemory, /* 0.9.0 */ + .domainSetMaxMemory = libxlDomainSetMaxMemory, /* 0.9.2 */ .domainSetMemory = libxlDomainSetMemory, /* 0.9.0 */ .domainSetMemoryFlags = libxlDomainSetMemoryFlags, /* 0.9.0 */ .domainGetInfo = libxlDomainGetInfo, /* 0.9.0 */ -- 1.7.5.2

On Mon, May 30, 2011 at 11:53:03AM +0200, Markus Groß wrote:
Add support to set the maximum memory of the domain. Also add support to change the memory of the current state of the domain, which translates to a running domain or the config of the domain.
Based on the code from the qemu driver.
--- src/libxl/libxl_driver.c | 101 +++++++++++++++++++++++++++++++++------------- 1 files changed, 73 insertions(+), 28 deletions(-)
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 0a2401a..3491f40 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -1493,22 +1493,19 @@ cleanup: }
static int -libxlDomainSetMemoryFlags(virDomainPtr dom, unsigned long memory, +libxlDomainSetMemoryFlags(virDomainPtr dom, unsigned long newmem, unsigned int flags) { libxlDriverPrivatePtr driver = dom->conn->privateData; libxlDomainObjPrivatePtr priv; virDomainObjPtr vm; - virDomainDefPtr def = NULL; + virDomainDefPtr persistentDef = NULL; + bool isActive; int ret = -1;
virCheckFlags(VIR_DOMAIN_MEM_LIVE | - VIR_DOMAIN_MEM_CONFIG, -1); - - if ((flags & (VIR_DOMAIN_MEM_LIVE | VIR_DOMAIN_MEM_CONFIG)) == 0) { - libxlError(VIR_ERR_INVALID_ARG, - _("invalid flag combination: (0x%x)"), flags); - } + VIR_DOMAIN_MEM_CONFIG | + VIR_DOMAIN_MEM_MAXIMUM, -1);
libxlDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); @@ -1519,13 +1516,22 @@ libxlDomainSetMemoryFlags(virDomainPtr dom, unsigned long memory, goto cleanup; }
- if (memory > vm->def->mem.max_balloon) { - libxlError(VIR_ERR_INVALID_ARG, "%s", - _("cannot set memory higher than max memory")); - goto cleanup; + isActive = virDomainObjIsActive(vm); + + if (flags == VIR_DOMAIN_MEM_CURRENT) { + if (isActive) + flags = VIR_DOMAIN_MEM_LIVE; + else + flags = VIR_DOMAIN_MEM_CONFIG; + } + if (flags == VIR_DOMAIN_MEM_MAXIMUM) { + if (isActive) + flags = VIR_DOMAIN_MEM_LIVE | VIR_DOMAIN_MEM_MAXIMUM; + else + flags = VIR_DOMAIN_MEM_CONFIG | VIR_DOMAIN_MEM_MAXIMUM; }
- if (!virDomainObjIsActive(vm) && (flags & VIR_DOMAIN_MEM_LIVE)) { + if (!isActive && (flags & VIR_DOMAIN_MEM_LIVE)) { libxlError(VIR_ERR_OPERATION_INVALID, "%s", _("cannot set memory on an inactive domain")); goto cleanup; @@ -1537,31 +1543,63 @@ libxlDomainSetMemoryFlags(virDomainPtr dom, unsigned long memory, _("cannot change persistent config of a transient domain")); goto cleanup; } - if (!(def = virDomainObjGetPersistentDef(driver->caps, vm))) + if (!(persistentDef = virDomainObjGetPersistentDef(driver->caps, vm))) goto cleanup; }
- if (flags & VIR_DOMAIN_MEM_LIVE) { - priv = vm->privateData; + if (flags & VIR_DOMAIN_MEM_MAXIMUM) { + /* resize the maximum memory */
- if (libxl_set_memory_target(&priv->ctx, dom->id, memory, 0, - /* force */ 1) < 0) { - libxlError(VIR_ERR_INTERNAL_ERROR, - _("Failed to set memory for domain '%d'" - " with libxenlight"), dom->id); + if (flags & VIR_DOMAIN_MEM_LIVE) { + priv = vm->privateData; + if (libxl_domain_setmaxmem(&priv->ctx, dom->id, newmem) < 0) { + libxlError(VIR_ERR_INTERNAL_ERROR, + _("Failed to set maximum memory for domain '%d'" + " with libxenlight"), dom->id); + goto cleanup; + } + } + + if (flags & VIR_DOMAIN_MEM_CONFIG) { + /* Help clang 2.8 decipher the logic flow. */ + sa_assert(persistentDef); + persistentDef->mem.max_balloon = newmem; + if (persistentDef->mem.cur_balloon > newmem) + persistentDef->mem.cur_balloon = newmem; + ret = virDomainSaveConfig(driver->configDir, persistentDef); goto cleanup; } - }
- ret = 0; + } else { + /* resize the current memory */
- if (flags & VIR_DOMAIN_MEM_CONFIG) { - /* clang 2.9 needs an extra hint. */ - sa_assert(def); - def->mem.cur_balloon = memory; - ret = virDomainSaveConfig(driver->configDir, def); + if (newmem > vm->def->mem.max_balloon) { + libxlError(VIR_ERR_INVALID_ARG, "%s", + _("cannot set memory higher than max memory")); + goto cleanup; + } + + if (flags & VIR_DOMAIN_MEM_LIVE) { + priv = vm->privateData; + if (libxl_set_memory_target(&priv->ctx, dom->id, newmem, 0, + /* force */ 1) < 0) { + libxlError(VIR_ERR_INTERNAL_ERROR, + _("Failed to set memory for domain '%d'" + " with libxenlight"), dom->id); + goto cleanup; + } + } + + if (flags & VIR_DOMAIN_MEM_CONFIG) { + sa_assert(persistentDef); + persistentDef->mem.cur_balloon = newmem; + ret = virDomainSaveConfig(driver->configDir, persistentDef); + goto cleanup; + } }
+ ret = 0; + cleanup: if (vm) virDomainObjUnlock(vm); @@ -1575,6 +1613,12 @@ libxlDomainSetMemory(virDomainPtr dom, unsigned long memory) }
static int +libxlDomainSetMaxMemory(virDomainPtr dom, unsigned long memory) +{ + return libxlDomainSetMemoryFlags(dom, memory, VIR_DOMAIN_MEM_MAXIMUM); +} + +static int libxlDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info) { libxlDriverPrivatePtr driver = dom->conn->privateData; @@ -3552,6 +3596,7 @@ static virDriver libxlDriver = { .domainDestroy = libxlDomainDestroy, /* 0.9.0 */ .domainGetOSType = libxlDomainGetOSType, /* 0.9.0 */ .domainGetMaxMemory = libxlDomainGetMaxMemory, /* 0.9.0 */ + .domainSetMaxMemory = libxlDomainSetMaxMemory, /* 0.9.2 */ .domainSetMemory = libxlDomainSetMemory, /* 0.9.0 */ .domainSetMemoryFlags = libxlDomainSetMemoryFlags, /* 0.9.0 */ .domainGetInfo = libxlDomainGetInfo, /* 0.9.0 */
ACK, it's god to align the xen driver with qemu one here, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/
participants (3)
-
Daniel Veillard
-
Jim Fehlig
-
Markus Groß