render / rpms / libvirt

Forked from rpms/libvirt 9 months ago
Clone
6d3351
From b7638da5f8a4ad19fc45f530063044d0b5020422 Mon Sep 17 00:00:00 2001
6d3351
Message-Id: <b7638da5f8a4ad19fc45f530063044d0b5020422@dist-git>
6d3351
From: Jiri Denemark <jdenemar@redhat.com>
6d3351
Date: Thu, 25 May 2017 10:20:57 +0200
6d3351
Subject: [PATCH] qemu: Store save cookie in save images and snapshots
6d3351
6d3351
The following patches will add an actual content in the cookie and use
6d3351
the data when restoring a domain.
6d3351
6d3351
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
6d3351
Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
6d3351
(cherry picked from commit 5c2f01abcb43810e7617f9a6544ce0d0b6caed34)
6d3351
6d3351
https://bugzilla.redhat.com/show_bug.cgi?id=1441662
6d3351
6d3351
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
6d3351
---
6d3351
 docs/formatsnapshot.html.in     |  6 +++
6d3351
 docs/schemas/domainsnapshot.rng |  7 +++
6d3351
 src/qemu/qemu_driver.c          | 96 ++++++++++++++++++++++++++++++++++++-----
6d3351
 3 files changed, 99 insertions(+), 10 deletions(-)
6d3351
6d3351
diff --git a/docs/formatsnapshot.html.in b/docs/formatsnapshot.html.in
6d3351
index c3ab516fa4..5e8e21c8a7 100644
6d3351
--- a/docs/formatsnapshot.html.in
6d3351
+++ b/docs/formatsnapshot.html.in
6d3351
@@ -235,6 +235,12 @@
6d3351
         at the time of the snapshot (since
6d3351
         0.9.5).  Readonly.
6d3351
       
6d3351
+      
cookie
6d3351
+      
Save image cookie containing additional data libvirt may need to
6d3351
+        properly restore a domain from an active snapshot when such data
6d3351
+        cannot be stored directly in the domain to maintain
6d3351
+        compatibility with older libvirt or hypervisor. Readonly.
6d3351
+      
6d3351
     
6d3351
 
6d3351
     

Examples

6d3351
diff --git a/docs/schemas/domainsnapshot.rng b/docs/schemas/domainsnapshot.rng
6d3351
index 4ab1b828f2..2680887095 100644
6d3351
--- a/docs/schemas/domainsnapshot.rng
6d3351
+++ b/docs/schemas/domainsnapshot.rng
6d3351
@@ -90,6 +90,13 @@
6d3351
             </element>
6d3351
           </element>
6d3351
         </optional>
6d3351
+        <optional>
6d3351
+          <element name='cookie'>
6d3351
+            <zeroOrMore>
6d3351
+              <ref name='customElement'/>
6d3351
+            </zeroOrMore>
6d3351
+          </element>
6d3351
+        </optional>
6d3351
       </interleave>
6d3351
     </element>
6d3351
   </define>
6d3351
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
6d3351
index 7ce0f01f70..dbb1ea9475 100644
6d3351
--- a/src/qemu/qemu_driver.c
6d3351
+++ b/src/qemu/qemu_driver.c
6d3351
@@ -2813,7 +2813,8 @@ struct _virQEMUSaveHeader {
6d3351
     uint32_t data_len;
6d3351
     uint32_t was_running;
6d3351
     uint32_t compressed;
6d3351
-    uint32_t unused[15];
6d3351
+    uint32_t cookieOffset;
6d3351
+    uint32_t unused[14];
6d3351
 };
6d3351
 
6d3351
 typedef struct _virQEMUSaveData virQEMUSaveData;
6d3351
@@ -2821,6 +2822,7 @@ typedef virQEMUSaveData *virQEMUSaveDataPtr;
6d3351
 struct _virQEMUSaveData {
6d3351
     virQEMUSaveHeader header;
6d3351
     char *xml;
6d3351
+    char *cookie;
6d3351
 };
6d3351
 
6d3351
 
6d3351
@@ -2831,6 +2833,7 @@ bswap_header(virQEMUSaveHeaderPtr hdr)
6d3351
     hdr->data_len = bswap_32(hdr->data_len);
6d3351
     hdr->was_running = bswap_32(hdr->was_running);
6d3351
     hdr->compressed = bswap_32(hdr->compressed);
6d3351
+    hdr->cookieOffset = bswap_32(hdr->cookieOffset);
6d3351
 }
6d3351
 
6d3351
 
6d3351
@@ -2841,6 +2844,7 @@ virQEMUSaveDataFree(virQEMUSaveDataPtr data)
6d3351
         return;
6d3351
 
6d3351
     VIR_FREE(data->xml);
6d3351
+    VIR_FREE(data->cookie);
6d3351
     VIR_FREE(data);
6d3351
 }
6d3351
 
6d3351
@@ -2850,8 +2854,10 @@ virQEMUSaveDataFree(virQEMUSaveDataPtr data)
6d3351
  */
6d3351
 static virQEMUSaveDataPtr
6d3351
 virQEMUSaveDataNew(char *domXML,
6d3351
+                   qemuDomainSaveCookiePtr cookieObj,
6d3351
                    bool running,
6d3351
-                   int compressed)
6d3351
+                   int compressed,
6d3351
+                   virDomainXMLOptionPtr xmlopt)
6d3351
 {
6d3351
     virQEMUSaveDataPtr data = NULL;
6d3351
     virQEMUSaveHeaderPtr header;
6d3351
@@ -2861,6 +2867,11 @@ virQEMUSaveDataNew(char *domXML,
6d3351
 
6d3351
     VIR_STEAL_PTR(data->xml, domXML);
6d3351
 
6d3351
+    if (cookieObj &&
6d3351
+        !(data->cookie = virSaveCookieFormat((virObjectPtr) cookieObj,
6d3351
+                                             virDomainXMLOptionGetSaveCookie(xmlopt))))
6d3351
+        goto error;
6d3351
+
6d3351
     header = &data->header;
6d3351
     memcpy(header->magic, QEMU_SAVE_PARTIAL, sizeof(header->magic));
6d3351
     header->version = QEMU_SAVE_VERSION;
6d3351
@@ -2868,6 +2879,10 @@ virQEMUSaveDataNew(char *domXML,
6d3351
     header->compressed = compressed;
6d3351
 
6d3351
     return data;
6d3351
+
6d3351
+ error:
6d3351
+    virQEMUSaveDataFree(data);
6d3351
+    return NULL;
6d3351
 }
6d3351
 
6d3351
 
6d3351
@@ -2887,11 +2902,17 @@ virQEMUSaveDataWrite(virQEMUSaveDataPtr data,
6d3351
 {
6d3351
     virQEMUSaveHeaderPtr header = &data->header;
6d3351
     size_t len;
6d3351
+    size_t xml_len;
6d3351
+    size_t cookie_len = 0;
6d3351
     int ret = -1;
6d3351
     size_t zerosLen = 0;
6d3351
     char *zeros = NULL;
6d3351
 
6d3351
-    len = strlen(data->xml) + 1;
6d3351
+    xml_len = strlen(data->xml) + 1;
6d3351
+    if (data->cookie)
6d3351
+        cookie_len = strlen(data->cookie) + 1;
6d3351
+
6d3351
+    len = xml_len + cookie_len;
6d3351
 
6d3351
     if (header->data_len > 0) {
6d3351
         if (len > header->data_len) {
6d3351
@@ -2907,6 +2928,9 @@ virQEMUSaveDataWrite(virQEMUSaveDataPtr data,
6d3351
         header->data_len = len;
6d3351
     }
6d3351
 
6d3351
+    if (data->cookie)
6d3351
+        header->cookieOffset = xml_len;
6d3351
+
6d3351
     if (safewrite(fd, header, sizeof(*header)) != sizeof(*header)) {
6d3351
         virReportSystemError(errno,
6d3351
                              _("failed to write header to domain save file '%s'"),
6d3351
@@ -2914,14 +2938,28 @@ virQEMUSaveDataWrite(virQEMUSaveDataPtr data,
6d3351
         goto cleanup;
6d3351
     }
6d3351
 
6d3351
-    if (safewrite(fd, data->xml, header->data_len) != header->data_len ||
6d3351
-        safewrite(fd, zeros, zerosLen) != zerosLen) {
6d3351
+    if (safewrite(fd, data->xml, xml_len) != xml_len) {
6d3351
         virReportSystemError(errno,
6d3351
                              _("failed to write domain xml to '%s'"),
6d3351
                              path);
6d3351
         goto cleanup;
6d3351
     }
6d3351
 
6d3351
+    if (data->cookie &&
6d3351
+        safewrite(fd, data->cookie, cookie_len) != cookie_len) {
6d3351
+        virReportSystemError(errno,
6d3351
+                             _("failed to write cookie to '%s'"),
6d3351
+                             path);
6d3351
+        goto cleanup;
6d3351
+    }
6d3351
+
6d3351
+    if (safewrite(fd, zeros, zerosLen) != zerosLen) {
6d3351
+        virReportSystemError(errno,
6d3351
+                             _("failed to write padding to '%s'"),
6d3351
+                             path);
6d3351
+        goto cleanup;
6d3351
+    }
6d3351
+
6d3351
     ret = 0;
6d3351
 
6d3351
  cleanup:
6d3351
@@ -3236,6 +3274,7 @@ qemuDomainSaveInternal(virQEMUDriverPtr driver, virDomainPtr dom,
6d3351
     qemuDomainObjPrivatePtr priv = vm->privateData;
6d3351
     virCapsPtr caps;
6d3351
     virQEMUSaveDataPtr data = NULL;
6d3351
+    qemuDomainSaveCookiePtr cookie = NULL;
6d3351
 
6d3351
     if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
6d3351
         goto cleanup;
6d3351
@@ -3301,7 +3340,11 @@ qemuDomainSaveInternal(virQEMUDriverPtr driver, virDomainPtr dom,
6d3351
         goto endjob;
6d3351
     }
6d3351
 
6d3351
-    if (!(data = virQEMUSaveDataNew(xml, was_running, compressed)))
6d3351
+    if (!(cookie = qemuDomainSaveCookieNew(vm)))
6d3351
+        goto endjob;
6d3351
+
6d3351
+    if (!(data = virQEMUSaveDataNew(xml, cookie, was_running, compressed,
6d3351
+                                    driver->xmlopt)))
6d3351
         goto endjob;
6d3351
     xml = NULL;
6d3351
 
6d3351
@@ -3338,6 +3381,7 @@ qemuDomainSaveInternal(virQEMUDriverPtr driver, virDomainPtr dom,
6d3351
         qemuDomainRemoveInactive(driver, vm);
6d3351
 
6d3351
  cleanup:
6d3351
+    virObjectUnref(cookie);
6d3351
     VIR_FREE(xml);
6d3351
     virQEMUSaveDataFree(data);
6d3351
     qemuDomainEventQueue(driver, event);
6d3351
@@ -6282,6 +6326,8 @@ qemuDomainSaveImageOpen(virQEMUDriverPtr driver,
6d3351
     virDomainDefPtr def = NULL;
6d3351
     int oflags = open_write ? O_RDWR : O_RDONLY;
6d3351
     virCapsPtr caps = NULL;
6d3351
+    size_t xml_len;
6d3351
+    size_t cookie_len;
6d3351
 
6d3351
     if (bypass_cache) {
6d3351
         int directFlag = virFileDirectFdFlag();
6d3351
@@ -6362,15 +6408,33 @@ qemuDomainSaveImageOpen(virQEMUDriverPtr driver,
6d3351
         goto error;
6d3351
     }
6d3351
 
6d3351
-    if (VIR_ALLOC_N(data->xml, header->data_len) < 0)
6d3351
+    if (header->cookieOffset)
6d3351
+        xml_len = header->cookieOffset;
6d3351
+    else
6d3351
+        xml_len = header->data_len;
6d3351
+
6d3351
+    cookie_len = header->data_len - xml_len;
6d3351
+
6d3351
+    if (VIR_ALLOC_N(data->xml, xml_len) < 0)
6d3351
         goto error;
6d3351
 
6d3351
-    if (saferead(fd, data->xml, header->data_len) != header->data_len) {
6d3351
+    if (saferead(fd, data->xml, xml_len) != xml_len) {
6d3351
         virReportError(VIR_ERR_OPERATION_FAILED,
6d3351
                        "%s", _("failed to read domain XML"));
6d3351
         goto error;
6d3351
     }
6d3351
 
6d3351
+    if (cookie_len > 0) {
6d3351
+        if (VIR_ALLOC_N(data->cookie, cookie_len) < 0)
6d3351
+            goto error;
6d3351
+
6d3351
+        if (saferead(fd, data->cookie, cookie_len) != cookie_len) {
6d3351
+            virReportError(VIR_ERR_OPERATION_FAILED, "%s",
6d3351
+                           _("failed to read cookie"));
6d3351
+            goto error;
6d3351
+        }
6d3351
+    }
6d3351
+
6d3351
     /* Create a domain from this XML */
6d3351
     if (!(def = virDomainDefParseString(data->xml, caps, driver->xmlopt, NULL,
6d3351
                                         VIR_DOMAIN_DEF_PARSE_INACTIVE |
6d3351
@@ -6411,6 +6475,11 @@ qemuDomainSaveImageStartVM(virConnectPtr conn,
6d3351
     char *errbuf = NULL;
6d3351
     virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
6d3351
     virQEMUSaveHeaderPtr header = &data->header;
6d3351
+    qemuDomainSaveCookiePtr cookie = NULL;
6d3351
+
6d3351
+    if (virSaveCookieParseString(data->cookie, (virObjectPtr *) &cookie,
6d3351
+                                 virDomainXMLOptionGetSaveCookie(driver->xmlopt)) < 0)
6d3351
+        goto cleanup;
6d3351
 
6d3351
     if ((header->version == 2) &&
6d3351
         (header->compressed != QEMU_SAVE_FORMAT_RAW)) {
6d3351
@@ -6501,6 +6570,7 @@ qemuDomainSaveImageStartVM(virConnectPtr conn,
6d3351
     ret = 0;
6d3351
 
6d3351
  cleanup:
6d3351
+    virObjectUnref(cookie);
6d3351
     virCommandFree(cmd);
6d3351
     VIR_FREE(errbuf);
6d3351
     if (qemuSecurityRestoreSavedStateLabel(driver->securityManager,
6d3351
@@ -13561,6 +13631,9 @@ qemuDomainSnapshotCreateActiveInternal(virConnectPtr conn,
6d3351
     if (ret < 0)
6d3351
         goto cleanup;
6d3351
 
6d3351
+    if (!(snap->def->cookie = (virObjectPtr) qemuDomainSaveCookieNew(vm)))
6d3351
+        goto cleanup;
6d3351
+
6d3351
     if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_HALT) {
6d3351
         event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
6d3351
                                          VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
6d3351
@@ -14439,10 +14512,13 @@ qemuDomainSnapshotCreateActiveExternal(virConnectPtr conn,
6d3351
                                                     "snapshot", false)) < 0)
6d3351
             goto cleanup;
6d3351
 
6d3351
-        if (!(xml = qemuDomainDefFormatLive(driver, vm->def, true, true)))
6d3351
+        if (!(xml = qemuDomainDefFormatLive(driver, vm->def, true, true)) ||
6d3351
+            !(snap->def->cookie = (virObjectPtr) qemuDomainSaveCookieNew(vm)))
6d3351
             goto cleanup;
6d3351
 
6d3351
-        if (!(data = virQEMUSaveDataNew(xml, resume, compressed)))
6d3351
+        if (!(data = virQEMUSaveDataNew(xml,
6d3351
+                                        (qemuDomainSaveCookiePtr) snap->def->cookie,
6d3351
+                                        resume, compressed, driver->xmlopt)))
6d3351
             goto cleanup;
6d3351
         xml = NULL;
6d3351
 
6d3351
-- 
6d3351
2.13.1
6d3351