The following patches will add an actual content in the cookie and use
the data when restoring a domain.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
---
docs/formatsnapshot.html.in | 6 +++
docs/schemas/domainsnapshot.rng | 7 ++++
src/qemu/qemu_driver.c | 90 ++++++++++++++++++++++++++++++++++++-----
3 files changed, 93 insertions(+), 10 deletions(-)
diff --git a/docs/formatsnapshot.html.in b/docs/formatsnapshot.html.in
index c3ab516fa..5e8e21c8a 100644
--- a/docs/formatsnapshot.html.in
+++ b/docs/formatsnapshot.html.in
@@ -235,6 +235,12 @@
at the time of the snapshot (<span class="since">since
0.9.5</span>). Readonly.
</dd>
+ <dt><code>cookie</code></dt>
+ <dd>Save image cookie containing additional data libvirt may need to
+ properly restore a domain from an active snapshot when such data
+ cannot be stored directly in the <code>domain</code> to maintain
+ compatibility with older libvirt or hypervisor. Readonly.
+ </dd>
</dl>
<h2><a name="example">Examples</a></h2>
diff --git a/docs/schemas/domainsnapshot.rng b/docs/schemas/domainsnapshot.rng
index 4ab1b828f..268088709 100644
--- a/docs/schemas/domainsnapshot.rng
+++ b/docs/schemas/domainsnapshot.rng
@@ -90,6 +90,13 @@
</element>
</element>
</optional>
+ <optional>
+ <element name='cookie'>
+ <zeroOrMore>
+ <ref name='customElement'/>
+ </zeroOrMore>
+ </element>
+ </optional>
</interleave>
</element>
</define>
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 96077df78..10df56e61 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -2808,7 +2808,8 @@ struct _virQEMUSaveHeader {
uint32_t data_len;
uint32_t was_running;
uint32_t compressed;
- uint32_t unused[15];
+ uint32_t cookie;
+ uint32_t unused[14];
};
typedef struct _virQEMUSaveData virQEMUSaveData;
@@ -2816,6 +2817,7 @@ typedef virQEMUSaveData *virQEMUSaveDataPtr;
struct _virQEMUSaveData {
virQEMUSaveHeader header;
char *xml;
+ char *cookie;
};
@@ -2826,6 +2828,7 @@ bswap_header(virQEMUSaveHeaderPtr hdr)
hdr->data_len = bswap_32(hdr->data_len);
hdr->was_running = bswap_32(hdr->was_running);
hdr->compressed = bswap_32(hdr->compressed);
+ hdr->cookie = bswap_32(hdr->cookie);
}
@@ -2836,6 +2839,7 @@ virQEMUSaveDataFree(virQEMUSaveDataPtr data)
return;
VIR_FREE(data->xml);
+ VIR_FREE(data->cookie);
VIR_FREE(data);
}
@@ -2845,8 +2849,10 @@ virQEMUSaveDataFree(virQEMUSaveDataPtr data)
*/
static virQEMUSaveDataPtr
virQEMUSaveDataNew(char *domXML,
+ qemuDomainSaveCookiePtr cookie,
bool running,
- int compressed)
+ int compressed,
+ virDomainXMLOptionPtr xmlopt)
{
virQEMUSaveDataPtr data = NULL;
virQEMUSaveHeaderPtr header;
@@ -2856,6 +2862,11 @@ virQEMUSaveDataNew(char *domXML,
VIR_STEAL_PTR(data->xml, domXML);
+ if (cookie &&
+ !(data->cookie = virSaveCookieFormat((virObjectPtr) cookie,
+ virDomainXMLOptionGetSaveCookie(xmlopt))))
+ goto error;
+
header = &data->header;
memcpy(header->magic, QEMU_SAVE_PARTIAL, sizeof(header->magic));
header->version = QEMU_SAVE_VERSION;
@@ -2863,6 +2874,10 @@ virQEMUSaveDataNew(char *domXML,
header->compressed = compressed;
return data;
+
+ error:
+ virQEMUSaveDataFree(data);
+ return NULL;
}
@@ -2882,9 +2897,15 @@ virQEMUSaveDataWrite(virQEMUSaveDataPtr data,
{
virQEMUSaveHeaderPtr header = &data->header;
size_t len;
+ size_t xml_len;
+ size_t cookie_len = 0;
int ret = -1;
- len = strlen(data->xml) + 1;
+ xml_len = strlen(data->xml) + 1;
+ if (data->cookie)
+ cookie_len = strlen(data->cookie) + 1;
+
+ len = xml_len + cookie_len;
if (header->data_len > 0) {
if (len > header->data_len) {
@@ -2893,12 +2914,15 @@ virQEMUSaveDataWrite(virQEMUSaveDataPtr data,
goto cleanup;
}
- if (VIR_EXPAND_N(data->xml, len, header->data_len - len) < 0)
+ if (VIR_EXPAND_N(data->xml, xml_len, header->data_len - len) < 0)
goto cleanup;
} else {
header->data_len = len;
}
+ if (data->cookie)
+ header->cookie = xml_len;
+
if (safewrite(fd, header, sizeof(*header)) != sizeof(*header)) {
virReportSystemError(errno,
_("failed to write header to domain save file '%s'"),
@@ -2906,13 +2930,21 @@ virQEMUSaveDataWrite(virQEMUSaveDataPtr data,
goto cleanup;
}
- if (safewrite(fd, data->xml, header->data_len) != header->data_len) {
+ if (safewrite(fd, data->xml, xml_len) != xml_len) {
virReportSystemError(errno,
_("failed to write domain xml to '%s'"),
path);
goto cleanup;
}
+ if (data->cookie &&
+ safewrite(fd, data->cookie, cookie_len) != cookie_len) {
+ virReportSystemError(errno,
+ _("failed to write cookie to '%s'"),
+ path);
+ goto cleanup;
+ }
+
ret = 0;
cleanup:
@@ -3245,6 +3277,7 @@ qemuDomainSaveInternal(virQEMUDriverPtr driver, virDomainPtr dom,
qemuDomainObjPrivatePtr priv = vm->privateData;
virCapsPtr caps;
virQEMUSaveDataPtr data = NULL;
+ qemuDomainSaveCookiePtr cookie = NULL;
if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
goto cleanup;
@@ -3310,7 +3343,11 @@ qemuDomainSaveInternal(virQEMUDriverPtr driver, virDomainPtr dom,
goto endjob;
}
- if (!(data = virQEMUSaveDataNew(xml, was_running, compressed)))
+ if (!(cookie = qemuDomainSaveCookieNew(vm)))
+ goto endjob;
+
+ if (!(data = virQEMUSaveDataNew(xml, cookie, was_running, compressed,
+ driver->xmlopt)))
goto endjob;
xml = NULL;
@@ -3347,6 +3384,7 @@ qemuDomainSaveInternal(virQEMUDriverPtr driver, virDomainPtr dom,
qemuDomainRemoveInactive(driver, vm);
cleanup:
+ virObjectUnref(cookie);
VIR_FREE(xml);
virQEMUSaveDataFree(data);
qemuDomainEventQueue(driver, event);
@@ -6283,6 +6321,8 @@ qemuDomainSaveImageOpen(virQEMUDriverPtr driver,
virDomainDefPtr def = NULL;
int oflags = open_write ? O_RDWR : O_RDONLY;
virCapsPtr caps = NULL;
+ size_t xml_len;
+ size_t cookie_len;
if (bypass_cache) {
int directFlag = virFileDirectFdFlag();
@@ -6363,15 +6403,33 @@ qemuDomainSaveImageOpen(virQEMUDriverPtr driver,
goto error;
}
- if (VIR_ALLOC_N(data->xml, header->data_len) < 0)
+ if (header->cookie)
+ xml_len = header->cookie;
+ else
+ xml_len = header->data_len;
+
+ cookie_len = header->data_len - xml_len;
+
+ if (VIR_ALLOC_N(data->xml, xml_len) < 0)
goto error;
- if (saferead(fd, data->xml, header->data_len) != header->data_len) {
+ if (saferead(fd, data->xml, xml_len) != xml_len) {
virReportError(VIR_ERR_OPERATION_FAILED,
"%s", _("failed to read domain XML"));
goto error;
}
+ if (cookie_len > 0) {
+ if (VIR_ALLOC_N(data->cookie, cookie_len) < 0)
+ goto error;
+
+ if (saferead(fd, data->cookie, cookie_len) != cookie_len) {
+ virReportError(VIR_ERR_OPERATION_FAILED, "%s",
+ _("failed to read cookie"));
+ goto error;
+ }
+ }
+
/* Create a domain from this XML */
if (!(def = virDomainDefParseString(data->xml, caps, driver->xmlopt, NULL,
VIR_DOMAIN_DEF_PARSE_INACTIVE |
@@ -6412,6 +6470,11 @@ qemuDomainSaveImageStartVM(virConnectPtr conn,
char *errbuf = NULL;
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
virQEMUSaveHeaderPtr header = &data->header;
+ qemuDomainSaveCookiePtr cookie = NULL;
+
+ if (virSaveCookieParseString(data->cookie, (virObjectPtr *) &cookie,
+ virDomainXMLOptionGetSaveCookie(driver->xmlopt)) < 0)
+ goto cleanup;
if ((header->version == 2) &&
(header->compressed != QEMU_SAVE_FORMAT_RAW)) {
@@ -6502,6 +6565,7 @@ qemuDomainSaveImageStartVM(virConnectPtr conn,
ret = 0;
cleanup:
+ virObjectUnref(cookie);
virCommandFree(cmd);
VIR_FREE(errbuf);
if (qemuSecurityRestoreSavedStateLabel(driver->securityManager,
@@ -13554,6 +13618,9 @@ qemuDomainSnapshotCreateActiveInternal(virConnectPtr conn,
if (ret < 0)
goto cleanup;
+ if (!(snap->def->cookie = (virObjectPtr) qemuDomainSaveCookieNew(vm)))
+ goto cleanup;
+
if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_HALT) {
event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
@@ -14433,10 +14500,13 @@ qemuDomainSnapshotCreateActiveExternal(virConnectPtr conn,
"snapshot", false)) < 0)
goto cleanup;
- if (!(xml = qemuDomainDefFormatLive(driver, vm->def, true, true)))
+ if (!(xml = qemuDomainDefFormatLive(driver, vm->def, true, true)) ||
+ !(snap->def->cookie = (virObjectPtr) qemuDomainSaveCookieNew(vm)))
goto cleanup;
- if (!(data = virQEMUSaveDataNew(xml, resume, compressed)))
+ if (!(data = virQEMUSaveDataNew(xml,
+ (qemuDomainSaveCookiePtr) snap->def->cookie,
+ resume, compressed, driver->xmlopt)))
goto cleanup;
xml = NULL;
--
2.13.0
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
On Mon, Jun 05, 2017 at 11:26:58AM +0200, Jiri Denemark wrote: > The following patches will add an actual content in the cookie and use > the data when restoring a domain. > > Signed-off-by: Jiri Denemark <jdenemar@redhat.com> > --- > docs/formatsnapshot.html.in | 6 +++ > docs/schemas/domainsnapshot.rng | 7 ++++ > src/qemu/qemu_driver.c | 90 ++++++++++++++++++++++++++++++++++++----- > 3 files changed, 93 insertions(+), 10 deletions(-) > > diff --git a/docs/formatsnapshot.html.in b/docs/formatsnapshot.html.in > index c3ab516fa..5e8e21c8a 100644 > --- a/docs/formatsnapshot.html.in > +++ b/docs/formatsnapshot.html.in > @@ -235,6 +235,12 @@ > at the time of the snapshot (<span class="since">since > 0.9.5</span>). Readonly. > </dd> > + <dt><code>cookie</code></dt> > + <dd>Save image cookie containing additional data libvirt may need to > + properly restore a domain from an active snapshot when such data > + cannot be stored directly in the <code>domain</code> to maintain > + compatibility with older libvirt or hypervisor. Readonly. > + </dd> > </dl> > > <h2><a name="example">Examples</a></h2> > diff --git a/docs/schemas/domainsnapshot.rng b/docs/schemas/domainsnapshot.rng > index 4ab1b828f..268088709 100644 > --- a/docs/schemas/domainsnapshot.rng > +++ b/docs/schemas/domainsnapshot.rng > @@ -90,6 +90,13 @@ > </element> > </element> > </optional> > + <optional> > + <element name='cookie'> > + <zeroOrMore> > + <ref name='customElement'/> > + </zeroOrMore> > + </element> > + </optional> > </interleave> > </element> > </define> > diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c > index 96077df78..10df56e61 100644 > --- a/src/qemu/qemu_driver.c > +++ b/src/qemu/qemu_driver.c > @@ -2808,7 +2808,8 @@ struct _virQEMUSaveHeader { > uint32_t data_len; > uint32_t was_running; > uint32_t compressed; > - uint32_t unused[15]; > + uint32_t cookie; I would suggest cookieOffset. > + uint32_t unused[14]; > }; > > typedef struct _virQEMUSaveData virQEMUSaveData; > @@ -2816,6 +2817,7 @@ typedef virQEMUSaveData *virQEMUSaveDataPtr; > struct _virQEMUSaveData { > virQEMUSaveHeader header; > char *xml; > + char *cookie; > }; > > > @@ -2826,6 +2828,7 @@ bswap_header(virQEMUSaveHeaderPtr hdr) > hdr->data_len = bswap_32(hdr->data_len); > hdr->was_running = bswap_32(hdr->was_running); > hdr->compressed = bswap_32(hdr->compressed); > + hdr->cookie = bswap_32(hdr->cookie); > } > > > @@ -2836,6 +2839,7 @@ virQEMUSaveDataFree(virQEMUSaveDataPtr data) > return; > > VIR_FREE(data->xml); > + VIR_FREE(data->cookie); > VIR_FREE(data); > } > > @@ -2845,8 +2849,10 @@ virQEMUSaveDataFree(virQEMUSaveDataPtr data) > */ > static virQEMUSaveDataPtr > virQEMUSaveDataNew(char *domXML, > + qemuDomainSaveCookiePtr cookie, I would suggest cookieObj. > bool running, > - int compressed) > + int compressed, > + virDomainXMLOptionPtr xmlopt) > { > virQEMUSaveDataPtr data = NULL; > virQEMUSaveHeaderPtr header; > @@ -2856,6 +2862,11 @@ virQEMUSaveDataNew(char *domXML, > > VIR_STEAL_PTR(data->xml, domXML); > > + if (cookie && > + !(data->cookie = virSaveCookieFormat((virObjectPtr) cookie, > + virDomainXMLOptionGetSaveCookie(xmlopt)))) Here it's kind of confusing, > + goto error; > + > header = &data->header; > memcpy(header->magic, QEMU_SAVE_PARTIAL, sizeof(header->magic)); > header->version = QEMU_SAVE_VERSION; > @@ -2863,6 +2874,10 @@ virQEMUSaveDataNew(char *domXML, > header->compressed = compressed; > > return data; > + > + error: > + virQEMUSaveDataFree(data); > + return NULL; > } > > > @@ -2882,9 +2897,15 @@ virQEMUSaveDataWrite(virQEMUSaveDataPtr data, > { > virQEMUSaveHeaderPtr header = &data->header; > size_t len; > + size_t xml_len; > + size_t cookie_len = 0; > int ret = -1; > > - len = strlen(data->xml) + 1; > + xml_len = strlen(data->xml) + 1; > + if (data->cookie) > + cookie_len = strlen(data->cookie) + 1; > + > + len = xml_len + cookie_len; > > if (header->data_len > 0) { > if (len > header->data_len) { > @@ -2893,12 +2914,15 @@ virQEMUSaveDataWrite(virQEMUSaveDataPtr data, > goto cleanup; > } > > - if (VIR_EXPAND_N(data->xml, len, header->data_len - len) < 0) > + if (VIR_EXPAND_N(data->xml, xml_len, header->data_len - len) < 0) I think that we should drop the expanding and just write 0 to the remaining data part of save image ... [1] > goto cleanup; > } else { > header->data_len = len; > } > > + if (data->cookie) > + header->cookie = xml_len; and this is also kind of confusing. > + > if (safewrite(fd, header, sizeof(*header)) != sizeof(*header)) { > virReportSystemError(errno, > _("failed to write header to domain save file '%s'"), > @@ -2906,13 +2930,21 @@ virQEMUSaveDataWrite(virQEMUSaveDataPtr data, > goto cleanup; > } > > - if (safewrite(fd, data->xml, header->data_len) != header->data_len) { > + if (safewrite(fd, data->xml, xml_len) != xml_len) { > virReportSystemError(errno, > _("failed to write domain xml to '%s'"), > path); > goto cleanup; [1] ... there you write the expanded XML to the save image which will stop at the end of the our internal data part ... [2] > } > > + if (data->cookie && > + safewrite(fd, data->cookie, cookie_len) != cookie_len) { > + virReportSystemError(errno, > + _("failed to write cookie to '%s'"), > + path); > + goto cleanup; > + } > + [2] ... and here you continue writing the cookie data out of the internal data part. Pavel -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
© 2016 - 2025 Red Hat, Inc.