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

Markus Gross gross at univention.de
Fri Apr 8 07:40:19 UTC 2011


Thanks Jim for the review of patch 3 and 4.
I will rework them and post a v2 as soon as I am back from vacation.

Cheers,
Markus

Quoting Jim Fehlig <jfehlig at novell.com>:

> 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