[libvirt] [PATCH 4/4] Add domainSave/Restore to libxl driver

Jim Fehlig jfehlig at novell.com
Thu Apr 7 21:02:21 UTC 2011


Markus Groß wrote:
> ---
>  src/libxl/libxl_conf.h   |   10 +++
>  src/libxl/libxl_driver.c |  184 +++++++++++++++++++++++++++++++++++++++++++++-
>  2 files changed, 191 insertions(+), 3 deletions(-)
>
> diff --git a/src/libxl/libxl_conf.h b/src/libxl/libxl_conf.h
> index f2f0d8a..e28615b 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 at novell.com>
> + *     Markus Groß <gross at univention.de>
>   */
>  /*---------------------------------------------------------------------------*/
>  
> @@ -85,6 +87,14 @@ struct _libxlDomainObjPrivate {
>      int eventHdl;
>  };
>  
> +static const char libxlSavefileMagic[16]= "libvirt-xml\n \0 \r";
> +typedef struct _libxlSavefileHeader libxlSavefileHeader;
> +typedef libxlSavefileHeader *libxlSavefileHeaderPtr;
> +struct _libxlSavefileHeader {
> +    char magic[16]; /* magic id */
> +    uint32_t xmlLen; /* length of saved xml */
> +};
>   

I think we should pad the header, similar to qemu driver, and provide a
version field.

> +
>  
>  # define libxlError(code, ...)                                     \
>      virReportErrorHelper(NULL, VIR_FROM_LIBXL, code, __FILE__,     \
> diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
> index 1539385..b02d4b7 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,7 +61,6 @@
>  
>  static libxlDriverPrivatePtr libxl_driver = NULL;
>  
> -
>  /* Function declarations */
>  static int
>  libxlVmStart(libxlDriverPrivatePtr driver,
> @@ -1555,6 +1555,184 @@ libxlDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info)
>  }
>  
>  static int
> +libxlDomainSave(virDomainPtr dom, const char * to)
> +{
> +    libxlDriverPrivatePtr driver = dom->conn->privateData;
> +    virDomainObjPtr vm;
> +    libxlDomainObjPrivatePtr priv;
> +    virDomainEventPtr event = NULL;
> +    libxlSavefileHeader hdr;
> +    libxl_domain_suspend_info s_info;
> +    char * xml;
> +    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 (vm->state != VIR_DOMAIN_PAUSED) {
> +        memset(&s_info, 0, sizeof(s_info));
> +
> +        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, libxlSavefileMagic, sizeof(hdr.magic));
> +        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, &s_info, 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) != 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;
> +    virDomainEventPtr event = 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, libxlSavefileMagic, sizeof(hdr.magic))) {
> +        libxlError(VIR_ERR_INVALID_ARG, "%s", _("image magic is incorrect"));
> +        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, 0)))
> +        goto cleanup;
> +
> +    if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0)
> +        goto cleanup;
> +
> +    if (!(vm = virDomainAssignDef(driver->caps, &driver->domains, def, false)))
> +        goto cleanup;
> +
> +    def = NULL;
> +
> +    ret = libxlVmStart(driver, vm, false);
>   

This starts a new domain.  To restore a domain, you need to use
libxl_domain_create_restore().

Regards,
Jim

> +
> +    if (ret == 0) {
> +        event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STARTED,
> +                                       VIR_DOMAIN_EVENT_STARTED_RESTORED);
> +    } else if (ret < 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);
> +    if (event)
> +        libxlDomainEventQueue(driver, event);
> +    libxlDriverUnlock(driver);
> +    return ret;
> +}
> +
> +static int
>  libxlDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
>                           unsigned int flags)
>  {
> @@ -2658,8 +2836,8 @@ static virDriver libxlDriver = {
>      NULL,                       /* domainSetBlkioParameters */
>      NULL,                       /* domainGetBlkioParameters */
>      libxlDomainGetInfo,         /* domainGetInfo */
> -    NULL,                       /* domainSave */
> -    NULL,                       /* domainRestore */
> +    libxlDomainSave,            /* domainSave */
> +    libxlDomainRestore,         /* domainRestore */
>      NULL,                       /* domainCoreDump */
>      libxlDomainSetVcpus,        /* domainSetVcpus */
>      libxlDomainSetVcpusFlags,   /* domainSetVcpusFlags */
>   




More information about the libvir-list mailing list