[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