[libvirt] [PATCH v7 09/23] backup: Parse and output checkpoint XML
Ján Tomko
jtomko at redhat.com
Wed Mar 27 14:01:03 UTC 2019
On Wed, Mar 27, 2019 at 05:10:40AM -0500, Eric Blake wrote:
>Add a new file checkpoint_conf.c that performs the translation to and
>from new XML describing a checkpoint. The code shares a common base
>class with snapshots, since a checkpoint similarly represents the
>domain state at a moment in time. Add some basic testing of round trip
>XML handling through the new code.
>
>Signed-off-by: Eric Blake <eblake at redhat.com>
>---
> src/conf/checkpoint_conf.h | 96 +++++
> src/conf/virconftypes.h | 3 +
> po/POTFILES | 1 +
> src/conf/Makefile.inc.am | 2 +
> src/conf/checkpoint_conf.c | 553 ++++++++++++++++++++++++++++
> src/libvirt_private.syms | 8 +
> tests/Makefile.am | 9 +-
> tests/domaincheckpointxml2xmltest.c | 212 +++++++++++
> 8 files changed, 882 insertions(+), 2 deletions(-)
> create mode 100644 src/conf/checkpoint_conf.h
> create mode 100644 src/conf/checkpoint_conf.c
> create mode 100644 tests/domaincheckpointxml2xmltest.c
>
>diff --git a/src/conf/checkpoint_conf.h b/src/conf/checkpoint_conf.h
>new file mode 100644
>index 0000000000..6647d0cd7c
>--- /dev/null
>+++ b/src/conf/checkpoint_conf.h
>@@ -0,0 +1,96 @@
>+/*
>+ * checkpoint_conf.h: domain checkpoint XML processing
>+ * (based on snapshot_conf.h)
>+ *
>+ * Copyright (C) 2006-2019 Red Hat, Inc.
>+ * Copyright (C) 2006-2008 Daniel P. Berrange
>+ *
>+ * This library is free software; you can redistribute it and/or
>+ * modify it under the terms of the GNU Lesser General Public
>+ * License as published by the Free Software Foundation; either
>+ * version 2.1 of the License, or (at your option) any later version.
>+ *
>+ * This library is distributed in the hope that it will be useful,
>+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
>+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
>+ * Lesser General Public License for more details.
>+ *
>+ * You should have received a copy of the GNU Lesser General Public
>+ * License along with this library. If not, see
>+ * <http://www.gnu.org/licenses/>.
>+ */
>+
>+#ifndef LIBVIRT_CHECKPOINT_CONF_H
>+# define LIBVIRT_CHECKPOINT_CONF_H
>+
>+# include "internal.h"
>+# include "domain_conf.h"
>+# include "moment_conf.h"
>+
>+/* Items related to checkpoint state */
>+
>+typedef enum {
>+ VIR_DOMAIN_CHECKPOINT_TYPE_DEFAULT = 0,
>+ VIR_DOMAIN_CHECKPOINT_TYPE_NONE,
>+ VIR_DOMAIN_CHECKPOINT_TYPE_BITMAP,
>+
>+ VIR_DOMAIN_CHECKPOINT_TYPE_LAST
>+} virDomainCheckpointType;
>+
>+/* Stores disk-checkpoint information */
>+typedef struct _virDomainCheckpointDiskDef virDomainCheckpointDiskDef;
>+typedef virDomainCheckpointDiskDef *virDomainCheckpointDiskDefPtr;
>+struct _virDomainCheckpointDiskDef {
>+ char *name; /* name matching the <target dev='...' of the domain */
>+ int idx; /* index within checkpoint->dom->disks that matches name */
>+ int type; /* virDomainCheckpointType */
>+ char *bitmap; /* bitmap name, if type is bitmap */
>+ unsigned long long size; /* current checkpoint size in bytes */
>+};
>+
>+/* Stores the complete checkpoint metadata */
>+struct _virDomainCheckpointDef {
>+ virDomainMomentDef common;
>+
>+ /* Additional Public XML. */
>+ size_t ndisks; /* should not exceed dom->ndisks */
>+ virDomainCheckpointDiskDef *disks;
>+};
>+
>+
>+typedef enum {
>+ VIR_DOMAIN_CHECKPOINT_PARSE_REDEFINE = 1 << 0,
>+ VIR_DOMAIN_CHECKPOINT_PARSE_INTERNAL = 1 << 1,
>+} virDomainCheckpointParseFlags;
>+
>+typedef enum {
>+ VIR_DOMAIN_CHECKPOINT_FORMAT_SECURE = 1 << 0,
>+ VIR_DOMAIN_CHECKPOINT_FORMAT_NO_DOMAIN = 1 << 1,
>+ VIR_DOMAIN_CHECKPOINT_FORMAT_SIZE = 1 << 2,
>+ VIR_DOMAIN_CHECKPOINT_FORMAT_INTERNAL = 1 << 3,
>+ VIR_DOMAIN_CHECKPOINT_FORMAT_CURRENT = 1 << 4,
>+} virDomainCheckpointFormatFlags;
>+
>+unsigned int virDomainCheckpointFormatConvertXMLFlags(unsigned int flags);
>+
>+virDomainCheckpointDefPtr virDomainCheckpointDefParseString(const char *xmlStr,
>+ virCapsPtr caps,
>+ virDomainXMLOptionPtr xmlopt,
>+ bool *current,
>+ unsigned int flags);
>+virDomainCheckpointDefPtr virDomainCheckpointDefParseNode(xmlDocPtr xml,
>+ xmlNodePtr root,
>+ virCapsPtr caps,
>+ virDomainXMLOptionPtr xmlopt,
>+ bool *current,
>+ unsigned int flags);
>+void virDomainCheckpointDefFree(virDomainCheckpointDefPtr def);
>+char *virDomainCheckpointDefFormat(virDomainCheckpointDefPtr def,
>+ virCapsPtr caps,
>+ virDomainXMLOptionPtr xmlopt,
>+ unsigned int flags);
>+int virDomainCheckpointAlignDisks(virDomainCheckpointDefPtr checkpoint);
>+
>+VIR_ENUM_DECL(virDomainCheckpoint);
>+
>+#endif /* LIBVIRT_CHECKPOINT_CONF_H */
>diff --git a/src/conf/virconftypes.h b/src/conf/virconftypes.h
>index 6a8267c422..f01721c6d5 100644
>--- a/src/conf/virconftypes.h
>+++ b/src/conf/virconftypes.h
>@@ -103,6 +103,9 @@ typedef virDomainBlkiotune *virDomainBlkiotunePtr;
> typedef struct _virDomainBlockIoTuneInfo virDomainBlockIoTuneInfo;
> typedef virDomainBlockIoTuneInfo *virDomainBlockIoTuneInfoPtr;
>
>+typedef struct _virDomainCheckpointDef virDomainCheckpointDef;
>+typedef virDomainCheckpointDef *virDomainCheckpointDefPtr;
>+
> typedef struct _virDomainChrDef virDomainChrDef;
> typedef virDomainChrDef *virDomainChrDefPtr;
>
>diff --git a/po/POTFILES b/po/POTFILES
>index 88af551664..57c55fb35f 100644
>--- a/po/POTFILES
>+++ b/po/POTFILES
>@@ -15,6 +15,7 @@ src/bhyve/bhyve_monitor.c
> src/bhyve/bhyve_parse_command.c
> src/bhyve/bhyve_process.c
> src/conf/capabilities.c
>+src/conf/checkpoint_conf.c
> src/conf/cpu_conf.c
> src/conf/device_conf.c
> src/conf/domain_addr.c
>diff --git a/src/conf/Makefile.inc.am b/src/conf/Makefile.inc.am
>index 6eb64db9de..913e21e2d1 100644
>--- a/src/conf/Makefile.inc.am
>+++ b/src/conf/Makefile.inc.am
>@@ -10,6 +10,8 @@ NETDEV_CONF_SOURCES = \
> DOMAIN_CONF_SOURCES = \
> conf/capabilities.c \
> conf/capabilities.h \
>+ conf/checkpoint_conf.c \
>+ conf/checkpoint_conf.h \
> conf/domain_addr.c \
> conf/domain_addr.h \
> conf/domain_capabilities.c \
>diff --git a/src/conf/checkpoint_conf.c b/src/conf/checkpoint_conf.c
>new file mode 100644
>index 0000000000..bdcf763a48
>--- /dev/null
>+++ b/src/conf/checkpoint_conf.c
>@@ -0,0 +1,553 @@
>+/*
>+ * checkpoint_conf.c: domain checkpoint XML processing
>+ *
>+ * Copyright (C) 2006-2019 Red Hat, Inc.
>+ * Copyright (C) 2006-2008 Daniel P. Berrange
>+ *
>+ * This library is free software; you can redistribute it and/or
>+ * modify it under the terms of the GNU Lesser General Public
>+ * License as published by the Free Software Foundation; either
>+ * version 2.1 of the License, or (at your option) any later version.
>+ *
>+ * This library is distributed in the hope that it will be useful,
>+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
>+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
>+ * Lesser General Public License for more details.
>+ *
>+ * You should have received a copy of the GNU Lesser General Public
>+ * License along with this library. If not, see
>+ * <http://www.gnu.org/licenses/>.
>+ */
>+
>+#include <config.h>
>+
>+#include <sys/time.h>
>+
>+#include "internal.h"
>+#include "virbitmap.h"
>+#include "virbuffer.h"
>+#include "datatypes.h"
>+#include "domain_conf.h"
>+#include "virlog.h"
>+#include "viralloc.h"
>+#include "checkpoint_conf.h"
>+#include "virstoragefile.h"
>+#include "viruuid.h"
>+#include "virfile.h"
>+#include "virerror.h"
>+#include "virxml.h"
>+#include "virstring.h"
>+
>+#define VIR_FROM_THIS VIR_FROM_DOMAIN_CHECKPOINT
>+
>+VIR_LOG_INIT("conf.checkpoint_conf");
>+
>+VIR_ENUM_IMPL(virDomainCheckpoint, VIR_DOMAIN_CHECKPOINT_TYPE_LAST,
>+ "default", "no", "bitmap");
>+
>+
>+/* Checkpoint Def functions */
>+static void
>+virDomainCheckpointDiskDefClear(virDomainCheckpointDiskDefPtr disk)
>+{
>+ VIR_FREE(disk->name);
>+ VIR_FREE(disk->bitmap);
>+}
>+
>+void virDomainCheckpointDefFree(virDomainCheckpointDefPtr def)
>+{
>+ size_t i;
>+
>+ if (!def)
>+ return;
>+
>+ virDomainMomentDefClear(&def->common);
>+ for (i = 0; i < def->ndisks; i++)
>+ virDomainCheckpointDiskDefClear(&def->disks[i]);
>+ VIR_FREE(def->disks);
>+ VIR_FREE(def);
>+}
>+
>+static int
>+virDomainCheckpointDiskDefParseXML(xmlNodePtr node,
>+ xmlXPathContextPtr ctxt,
>+ virDomainCheckpointDiskDefPtr def)
>+{
>+ int ret = -1;
>+ char *checkpoint = NULL;
>+ char *bitmap = NULL;
>+ xmlNodePtr saved = ctxt->node;
>+
>+ ctxt->node = node;
>+
>+ def->name = virXMLPropString(node, "name");
>+ if (!def->name) {
>+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
>+ _("missing name from disk checkpoint element"));
>+ goto cleanup;
>+ }
>+
>+ checkpoint = virXMLPropString(node, "checkpoint");
>+ if (checkpoint) {
>+ def->type = virDomainCheckpointTypeFromString(checkpoint);
>+ if (def->type <= 0) {
>+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
>+ _("unknown disk checkpoint setting '%s'"),
>+ checkpoint);
>+ goto cleanup;
>+ }
>+ } else {
>+ def->type = VIR_DOMAIN_CHECKPOINT_TYPE_BITMAP;
>+ }
>+
>+ bitmap = virXMLPropString(node, "bitmap");
>+ if (bitmap) {
>+ if (def->type != VIR_DOMAIN_CHECKPOINT_TYPE_BITMAP) {
>+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
>+ _("disk checkpoint bitmap '%s' requires "
>+ "type='bitmap'"),
>+ bitmap);
>+ goto cleanup;
>+ }
>+ VIR_STEAL_PTR(def->bitmap, bitmap);
>+ }
>+
>+ ret = 0;
>+ cleanup:
>+ ctxt->node = saved;
>+
>+ VIR_FREE(checkpoint);
>+ VIR_FREE(bitmap);
>+ if (ret < 0)
>+ virDomainCheckpointDiskDefClear(def);
>+ return ret;
>+}
>+
>+/* flags is bitwise-or of virDomainCheckpointParseFlags. If flags
>+ * does not include VIR_DOMAIN_CHECKPOINT_PARSE_REDEFINE, then caps
>+ * are ignored. If flags does not include
>+ * VIR_DOMAIN_CHECKPOINT_PARSE_INTERNAL, then current is ignored.
>+ */
>+static virDomainCheckpointDefPtr
>+virDomainCheckpointDefParse(xmlXPathContextPtr ctxt,
>+ virCapsPtr caps,
>+ virDomainXMLOptionPtr xmlopt,
>+ bool *current,
>+ unsigned int flags)
>+{
>+ virDomainCheckpointDefPtr def = NULL;
>+ virDomainCheckpointDefPtr ret = NULL;
>+ xmlNodePtr *nodes = NULL;
>+ size_t i;
>+ int n;
>+ char *creation = NULL;
>+ struct timeval tv;
>+ int active;
>+ char *tmp;
>+
>+ if (VIR_ALLOC(def) < 0)
>+ goto cleanup;
>+
>+ gettimeofday(&tv, NULL);
>+
Eww. I'd expect an XML parsing function to behave the same regardless of
the time of day.
For domains, we'd put this kind of stuff into a post-parse function.
>+ def->common.name = virXPathString("string(./name)", ctxt);
>+ if (def->common.name == NULL) {
>+ if (flags & VIR_DOMAIN_CHECKPOINT_PARSE_REDEFINE) {
>+ virReportError(VIR_ERR_XML_ERROR, "%s",
>+ _("a redefined checkpoint must have a name"));
>+ goto cleanup;
>+ }
>+ if (virAsprintf(&def->common.name, "%lld", (long long)tv.tv_sec) < 0)
>+ goto cleanup;
>+ }
>+
>+ def->common.description = virXPathString("string(./description)", ctxt);
>+
>+ if (flags & VIR_DOMAIN_CHECKPOINT_PARSE_REDEFINE) {
>+ if (virXPathLongLong("string(./creationTime)", ctxt,
>+ &def->common.creationTime) < 0) {
>+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
>+ _("missing creationTime from existing checkpoint"));
>+ goto cleanup;
>+ }
>+
>+ def->common.parent = virXPathString("string(./parent/name)", ctxt);
>+
>+ if ((tmp = virXPathString("string(./domain/@type)", ctxt))) {
tmp is freed right away and the error reported on else is duplicate with the
one a few lines below.
>+ int domainflags = VIR_DOMAIN_DEF_PARSE_INACTIVE |
>+ VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE;
>+ xmlNodePtr domainNode = virXPathNode("./domain", ctxt);
>+
>+ VIR_FREE(tmp);
>+ if (!domainNode) {
>+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
>+ _("missing domain in checkpoint"));
>+ goto cleanup;
>+ }
>+ def->common.dom = virDomainDefParseNode(ctxt->node->doc, domainNode,
>+ caps, xmlopt, NULL,
>+ domainflags);
>+ if (!def->common.dom)
>+ goto cleanup;
>+ } else {
>+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
>+ _("missing domain in checkpoint redefine"));
>+ goto cleanup;
>+ }
>+ } else {
>+ def->common.creationTime = tv.tv_sec;
>+ }
>+
Jano
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20190327/02c68d9e/attachment-0001.sig>
More information about the libvir-list
mailing list