Backup xml description is like this:
<domainbackup>
<name>backup name</name>
<disk type="file" name="sda">
<target file="/path/to/backup/file.qcow2" format="qcow2"/>
</disk>
</domainbackup>
- <name> element is optional.
- disk @type attribute is optional, default to 'file'. Valid
values are 'file', 'block', 'dir', 'network',
'volume' just
as usual for specifing domain disk sources. It specifies
backup <target> type.
- <target> element has same attributes and its values as
<source> element in domain disk description.
- target @format attribute is optional. If it is not specified
then hypervisor will choose format by its default rule
(for qemu it same format as disk to be backed up).
Elements that are not explicitly mentioned as optional are
mandatory. Current description does not support implicitly
specified disks to be backed up like snapshot xml description
for example.
---
po/POTFILES.in | 1 +
src/Makefile.am | 1 +
src/conf/backup_conf.c | 267 +++++++++++++++++++++++++++++++++++++++++++++++
src/conf/backup_conf.h | 65 ++++++++++++
src/libvirt_private.syms | 6 ++
src/qemu/qemu_conf.h | 1 +
6 files changed, 341 insertions(+)
create mode 100644 src/conf/backup_conf.c
create mode 100644 src/conf/backup_conf.h
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 5077857..cb9831e 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -20,6 +20,7 @@ src/bhyve/bhyve_driver.c
src/bhyve/bhyve_monitor.c
src/bhyve/bhyve_parse_command.c
src/bhyve/bhyve_process.c
+src/conf/backup_conf.c
src/conf/capabilities.c
src/conf/cpu_conf.c
src/conf/device_conf.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 615ad60..5b14826 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -404,6 +404,7 @@ DOMAIN_CONF_SOURCES = \
conf/domain_audit.c conf/domain_audit.h \
conf/domain_nwfilter.c conf/domain_nwfilter.h \
conf/snapshot_conf.c conf/snapshot_conf.h \
+ conf/backup_conf.c conf/backup_conf.h \
conf/numa_conf.c conf/numa_conf.h \
conf/virdomainobjlist.c conf/virdomainobjlist.h
diff --git a/src/conf/backup_conf.c b/src/conf/backup_conf.c
new file mode 100644
index 0000000..a5bd995
--- /dev/null
+++ b/src/conf/backup_conf.c
@@ -0,0 +1,267 @@
+/*
+ * backup_conf.c: domain backup XML processing
+ *
+ * Copyright (C) 2017 Parallels International GmbH
+ *
+ * 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 <fcntl.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+#include "internal.h"
+#include "virbitmap.h"
+#include "virbuffer.h"
+#include "count-one-bits.h"
+#include "datatypes.h"
+#include "domain_conf.h"
+#include "virlog.h"
+#include "viralloc.h"
+#include "netdev_bandwidth_conf.h"
+#include "netdev_vport_profile_conf.h"
+#include "nwfilter_conf.h"
+#include "secret_conf.h"
+#include "backup_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_BACKUP
+
+VIR_LOG_INIT("conf.backup_conf");
+
+
+/* Backup Def functions */
+static void
+virDomainBackupDiskDefClear(virDomainBackupDiskDefPtr disk)
+{
+ VIR_FREE(disk->name);
+ virStorageSourceFree(disk->target);
+ disk->target = NULL;
+}
+
+
+static int
+virDomainBackupDiskDefParseXML(xmlNodePtr node,
+ xmlXPathContextPtr ctxt,
+ virDomainBackupDiskDefPtr def)
+{
+ int ret = -1;
+ char *type = NULL;
+ char *format = NULL;
+ xmlNodePtr cur;
+ xmlNodePtr saved = ctxt->node;
+ virStorageSourcePtr target;
+
+ ctxt->node = node;
+
+ if (!(def->name = virXMLPropString(node, "name"))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("missing name from disk backup element"));
+ goto cleanup;
+ }
+
+ if (!(cur = virXPathNode("./target", ctxt))) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("missing target for disk '%s'"), def->name);
+ goto cleanup;
+ }
+
+ if (VIR_ALLOC(def->target) < 0)
+ goto cleanup;
+ target = def->target;
+
+ if ((type = virXMLPropString(node, "type"))) {
+ if ((target->type = virStorageTypeFromString(type)) <= 0) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("unknown disk '%s' backup type
'%s'"),
+ def->name, type);
+ goto cleanup;
+ }
+ } else {
+ target->type = VIR_STORAGE_TYPE_FILE;
+ }
+
+ if (virDomainDiskSourceParse(cur, ctxt, target) < 0)
+ goto cleanup;
+
+ if ((format = virXPathString("string(./target/@format)", ctxt)) &&
+ (target->format = virStorageFileFormatTypeFromString(format)) <= 0) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("unknown disk '%s' backup format
'%s'"),
+ def->name, format);
+ goto cleanup;
+ }
+
+ if (virStorageSourceIsLocalStorage(def->target)) {
+ if (!target->path) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("disk '%s' backup path is not
specified"),
+ def->name);
+ goto cleanup;
+ }
+ if (target->path[0] != '/') {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("disk '%s' backup path '%s' must be
absolute"),
+ def->name, target->path);
+ goto cleanup;
+ }
+ }
+
+ ret = 0;
+ cleanup:
+ ctxt->node = saved;
+
+ VIR_FREE(format);
+ VIR_FREE(type);
+ if (ret < 0)
+ virDomainBackupDiskDefClear(def);
+
+ return ret;
+}
+
+
+static virDomainBackupDefPtr
+virDomainBackupDefParse(xmlXPathContextPtr ctxt,
+ virCapsPtr caps ATTRIBUTE_UNUSED,
+ virDomainXMLOptionPtr xmlopt ATTRIBUTE_UNUSED,
+ unsigned int fflags ATTRIBUTE_UNUSED)
+{
+ virDomainBackupDefPtr def;
+ virDomainBackupDefPtr ret = NULL;
+ xmlNodePtr *nodes = NULL;
+ size_t i;
+ int n;
+ struct timeval tv;
+
+ if (VIR_ALLOC(def) < 0)
+ return NULL;
+
+ gettimeofday(&tv, NULL);
+
+ if (!(def->name = virXPathString("string(./name)", ctxt)) &&
+ virAsprintf(&def->name, "%lld", (long long)tv.tv_sec) < 0)
+ goto cleanup;
+
+ def->description = virXPathString("string(./description)", ctxt);
+ def->creationTime = tv.tv_sec;
+
+ if ((n = virXPathNodeSet("./disk", ctxt, &nodes)) < 0)
+ goto cleanup;
+
+ if (n == 0) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("no disk is specified to be backed up"));
+ goto cleanup;
+ }
+
+ if (VIR_ALLOC_N(def->disks, n) < 0)
+ goto cleanup;
+ def->ndisks = n;
+
+ for (i = 0; i < def->ndisks; i++) {
+ if (virDomainBackupDiskDefParseXML(nodes[i], ctxt, &def->disks[i]) <
0)
+ goto cleanup;
+ }
+
+ ret = def;
+ def = NULL;
+
+ cleanup:
+ VIR_FREE(nodes);
+ virDomainBackupDefFree(def);
+
+ return ret;
+}
+
+
+virDomainBackupDefPtr
+virDomainBackupDefParseNode(xmlDocPtr xml,
+ xmlNodePtr root,
+ virCapsPtr caps,
+ virDomainXMLOptionPtr xmlopt,
+ unsigned int flags)
+{
+ xmlXPathContextPtr ctxt = NULL;
+ virDomainBackupDefPtr def = NULL;
+
+ if (!xmlStrEqual(root->name, BAD_CAST "domainbackup")) {
+ virReportError(VIR_ERR_XML_ERROR, "%s", _("domainbackup"));
+ goto cleanup;
+ }
+
+ ctxt = xmlXPathNewContext(xml);
+ if (ctxt == NULL) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ ctxt->node = root;
+ def = virDomainBackupDefParse(ctxt, caps, xmlopt, flags);
+
+ cleanup:
+ xmlXPathFreeContext(ctxt);
+
+ return def;
+}
+
+
+virDomainBackupDefPtr
+virDomainBackupDefParseString(const char *xmlStr,
+ virCapsPtr caps,
+ virDomainXMLOptionPtr xmlopt,
+ unsigned int flags)
+{
+ virDomainBackupDefPtr ret = NULL;
+ xmlDocPtr xml;
+ int keepBlanksDefault = xmlKeepBlanksDefault(0);
+
+ if ((xml = virXMLParse(NULL, xmlStr, _("(domain_backup)")))) {
+ xmlKeepBlanksDefault(keepBlanksDefault);
+ ret = virDomainBackupDefParseNode(xml, xmlDocGetRootElement(xml),
+ caps, xmlopt, flags);
+ xmlFreeDoc(xml);
+ }
+ xmlKeepBlanksDefault(keepBlanksDefault);
+
+ return ret;
+}
+
+
+void
+virDomainBackupDefFree(virDomainBackupDefPtr def)
+{
+ size_t i;
+
+ if (!def)
+ return;
+
+ VIR_FREE(def->name);
+ VIR_FREE(def->description);
+
+ for (i = 0; i < def->ndisks; i++)
+ virDomainBackupDiskDefClear(&def->disks[i]);
+ VIR_FREE(def->disks);
+
+ VIR_FREE(def);
+}
diff --git a/src/conf/backup_conf.h b/src/conf/backup_conf.h
new file mode 100644
index 0000000..6f689e3
--- /dev/null
+++ b/src/conf/backup_conf.h
@@ -0,0 +1,65 @@
+/*
+ * backup_conf.h: domain backup XML processing
+ *
+ * Copyright (C) 2017 Parallels International GmbH
+ *
+ * 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 __BACKUP_CONF_H
+# define __BACKUP_CONF_H
+
+# include "internal.h"
+# include "domain_conf.h"
+
+/* Items related to backup state */
+
+/* Stores disk-backup information */
+typedef struct _virDomainBackupDiskDef virDomainBackupDiskDef;
+typedef virDomainBackupDiskDef *virDomainBackupDiskDefPtr;
+struct _virDomainBackupDiskDef {
+ char *name; /* name matching the <target dev='...' of the domain */
+ virStorageSourcePtr target;
+};
+
+/* Stores the complete backup metadata */
+typedef struct _virDomainBackupDef virDomainBackupDef;
+typedef virDomainBackupDef *virDomainBackupDefPtr;
+struct _virDomainBackupDef {
+ /* Public XML. */
+ char *name;
+ char *description;
+ long long creationTime; /* in seconds */
+
+ size_t ndisks; /* should not exceed dom->ndisks */
+ virDomainBackupDiskDef *disks;
+};
+
+virDomainBackupDefPtr
+virDomainBackupDefParseString(const char *xmlStr,
+ virCapsPtr caps,
+ virDomainXMLOptionPtr xmlopt,
+ unsigned int flags);
+virDomainBackupDefPtr
+virDomainBackupDefParseNode(xmlDocPtr xml,
+ xmlNodePtr root,
+ virCapsPtr caps,
+ virDomainXMLOptionPtr xmlopt,
+ unsigned int flags);
+void
+virDomainBackupDefFree(virDomainBackupDefPtr def);
+
+#endif /* __BACKUP_CONF_H */
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index fdb0106..e2ffc91 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -42,6 +42,12 @@ virAccessPermStorageVolTypeFromString;
virAccessPermStorageVolTypeToString;
+# conf/backup_conf.h
+virDomainBackupDefFree;
+virDomainBackupDefParseNode;
+virDomainBackupDefParseString;
+
+
# conf/capabilities.h
virCapabilitiesAddGuest;
virCapabilitiesAddGuestDomain;
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index 1407eef..0626729 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -32,6 +32,7 @@
# include "network_conf.h"
# include "domain_conf.h"
# include "snapshot_conf.h"
+# include "backup_conf.h"
# include "domain_event.h"
# include "virthread.h"
# include "security/security_manager.h"
--
1.8.3.1