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

Markus Groß gross at univention.de
Wed Apr 6 08:58:42 UTC 2011


---
 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 */
+};
+
 
 # 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);
+
+    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 */
-- 
1.7.4.3




More information about the libvir-list mailing list