]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
tests: qemublock: Add testing of bitmap merging for incremental backups
authorPeter Krempa <pkrempa@redhat.com>
Thu, 12 Dec 2019 15:01:22 +0000 (16:01 +0100)
committerPeter Krempa <pkrempa@redhat.com>
Fri, 13 Dec 2019 12:22:55 +0000 (13:22 +0100)
Add test code which will crawl a fake internal list of checkpoints and
generate the list of bitmaps for merging to gather the final bitmap for
the backup.

The initial tests cover the basic case of all bitmaps being present in
the top layer of the backing chain.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
tests/qemublocktest.c
tests/qemublocktestdata/backupmerge/basic-deep-out.json [new file with mode: 0644]
tests/qemublocktestdata/backupmerge/basic-flat-out.json [new file with mode: 0644]
tests/qemublocktestdata/backupmerge/basic-intermediate-out.json [new file with mode: 0644]

index 55268197d8b0b661b8c7ae494c942dcbf4f4ec69..1c8977637c0744a2aab1b70d9556fdb43e124543 100644 (file)
@@ -28,6 +28,7 @@
 # include "qemu/qemu_block.h"
 # include "qemu/qemu_qapi.h"
 # include "qemu/qemu_monitor_json.h"
+# include "qemu/qemu_backup.h"
 
 # include "qemu/qemu_command.h"
 
@@ -558,6 +559,145 @@ testQemuDetectBitmaps(const void *opaque)
 }
 
 
+static virStorageSourcePtr
+testQemuBackupIncrementalBitmapCalculateGetFakeImage(size_t idx)
+{
+   virStorageSourcePtr ret;
+
+   if (!(ret = virStorageSourceNew()))
+       abort();
+
+   ret->type = VIR_STORAGE_TYPE_FILE;
+   ret->format = VIR_STORAGE_FILE_QCOW2;
+   ret->path = g_strdup_printf("/image%zu", idx);
+   ret->nodestorage = g_strdup_printf("libvirt-%zu-storage", idx);
+   ret->nodeformat = g_strdup_printf("libvirt-%zu-format", idx);
+
+   return ret;
+}
+
+
+static virStorageSourcePtr
+testQemuBackupIncrementalBitmapCalculateGetFakeChain(void)
+{
+    virStorageSourcePtr ret;
+    virStorageSourcePtr n;
+    size_t i;
+
+    n = ret = testQemuBackupIncrementalBitmapCalculateGetFakeImage(1);
+
+    for (i = 2; i < 10; i++) {
+        n->backingStore = testQemuBackupIncrementalBitmapCalculateGetFakeImage(i);
+        n = n->backingStore;
+    }
+
+    return ret;
+}
+
+
+typedef virDomainMomentDefPtr testMomentList;
+
+static void
+testMomentListFree(testMomentList *list)
+{
+    testMomentList *tmp = list;
+
+    if (!list)
+        return;
+
+    while (*tmp) {
+        virObjectUnref(*tmp);
+        tmp++;
+    }
+
+    g_free(list);
+}
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(testMomentList, testMomentListFree);
+
+static virDomainMomentDefPtr
+testQemuBackupGetIncrementalMoment(const char *name)
+{
+    virDomainCheckpointDefPtr checkpoint = NULL;
+
+    if (!(checkpoint = virDomainCheckpointDefNew()))
+        abort();
+
+    checkpoint->parent.name = g_strdup(name);
+
+    return (virDomainMomentDefPtr) checkpoint;
+}
+
+
+static virDomainMomentDefPtr *
+testQemuBackupGetIncremental(const char *incFrom)
+{
+    const char *checkpoints[] = {"current", "d", "c", "b", "a"};
+    virDomainMomentDefPtr *incr;
+    size_t i;
+
+    incr = g_new0(virDomainMomentDefPtr, G_N_ELEMENTS(checkpoints) + 1);
+
+    for (i = 0; i < G_N_ELEMENTS(checkpoints); i++) {
+        incr[i] = testQemuBackupGetIncrementalMoment(checkpoints[i]);
+
+        if (STREQ(incFrom, checkpoints[i]))
+            break;
+    }
+
+    return incr;
+}
+
+static const char *backupDataPrefix = "qemublocktestdata/backupmerge/";
+
+struct testQemuBackupIncrementalBitmapCalculateData {
+    const char *name;
+    virStorageSourcePtr chain;
+    const char *incremental;
+    const char *nodedatafile;
+};
+
+
+static int
+testQemuBackupIncrementalBitmapCalculate(const void *opaque)
+{
+    const struct testQemuBackupIncrementalBitmapCalculateData *data = opaque;
+    g_autoptr(virJSONValue) nodedatajson = NULL;
+    g_autoptr(virHashTable) nodedata = NULL;
+    g_autoptr(virJSONValue) mergebitmaps = NULL;
+    g_autofree char *actual = NULL;
+    g_autofree char *expectpath = NULL;
+    g_autoptr(testMomentList) incremental = NULL;
+
+    expectpath = g_strdup_printf("%s/%s%s-out.json", abs_srcdir,
+                                 backupDataPrefix, data->name);
+
+    if (!(nodedatajson = virTestLoadFileJSON(bitmapDetectPrefix, data->nodedatafile,
+                                             ".json", NULL)))
+        return -1;
+
+    if (!(nodedata = qemuMonitorJSONBlockGetNamedNodeDataJSON(nodedatajson))) {
+        VIR_TEST_VERBOSE("failed to load nodedata JSON\n");
+        return -1;
+    }
+
+    incremental = testQemuBackupGetIncremental(data->incremental);
+
+    if (!(mergebitmaps = qemuBackupDiskPrepareOneBitmapsChain(incremental,
+                                                              data->chain,
+                                                              nodedata,
+                                                              "testdisk"))) {
+        VIR_TEST_VERBOSE("failed to calculate merged bitmaps");
+        return -1;
+    }
+
+    if (!(actual = virJSONValueToString(mergebitmaps, true)))
+        return -1;
+
+    return virTestCompareToFile(actual, expectpath);
+}
+
+
 static int
 mymain(void)
 {
@@ -566,12 +706,16 @@ mymain(void)
     struct testBackingXMLjsonXMLdata xmljsonxmldata;
     struct testQemuDiskXMLToJSONData diskxmljsondata;
     struct testQemuImageCreateData imagecreatedata;
+    struct testQemuBackupIncrementalBitmapCalculateData backupbitmapcalcdata;
     char *capslatest_x86_64 = NULL;
     virQEMUCapsPtr caps_x86_64 = NULL;
+    g_autoptr(virStorageSource) bitmapSourceChain = NULL;
 
     if (qemuTestDriverInit(&driver) < 0)
         return EXIT_FAILURE;
 
+    bitmapSourceChain = testQemuBackupIncrementalBitmapCalculateGetFakeChain();
+
     diskxmljsondata.driver = &driver;
     imagecreatedata.driver = &driver;
 
@@ -779,6 +923,22 @@ mymain(void)
     TEST_BITMAP_DETECT("synthetic");
     TEST_BITMAP_DETECT("snapshots");
 
+# define TEST_BACKUP_BITMAP_CALCULATE(testname, source, incrbackup, named) \
+    do { \
+        backupbitmapcalcdata.name = testname; \
+        backupbitmapcalcdata.chain = source; \
+        backupbitmapcalcdata.incremental = incrbackup; \
+        backupbitmapcalcdata.nodedatafile = named; \
+        if (virTestRun("incremental backup bitmap " testname, \
+                       testQemuBackupIncrementalBitmapCalculate, \
+                       &backupbitmapcalcdata) < 0) \
+            ret = -1; \
+    } while (0)
+
+    TEST_BACKUP_BITMAP_CALCULATE("basic-flat", bitmapSourceChain, "current", "basic");
+    TEST_BACKUP_BITMAP_CALCULATE("basic-intermediate", bitmapSourceChain, "d", "basic");
+    TEST_BACKUP_BITMAP_CALCULATE("basic-deep", bitmapSourceChain, "a", "basic");
+
  cleanup:
     virHashFree(diskxmljsondata.schema);
     qemuTestDriverFree(&driver);
diff --git a/tests/qemublocktestdata/backupmerge/basic-deep-out.json b/tests/qemublocktestdata/backupmerge/basic-deep-out.json
new file mode 100644 (file)
index 0000000..28c3d16
--- /dev/null
@@ -0,0 +1,22 @@
+[
+  {
+    "node": "libvirt-1-format",
+    "name": "current"
+  },
+  {
+    "node": "libvirt-1-format",
+    "name": "d"
+  },
+  {
+    "node": "libvirt-1-format",
+    "name": "c"
+  },
+  {
+    "node": "libvirt-1-format",
+    "name": "b"
+  },
+  {
+    "node": "libvirt-1-format",
+    "name": "a"
+  }
+]
diff --git a/tests/qemublocktestdata/backupmerge/basic-flat-out.json b/tests/qemublocktestdata/backupmerge/basic-flat-out.json
new file mode 100644 (file)
index 0000000..b89252e
--- /dev/null
@@ -0,0 +1,6 @@
+[
+  {
+    "node": "libvirt-1-format",
+    "name": "current"
+  }
+]
diff --git a/tests/qemublocktestdata/backupmerge/basic-intermediate-out.json b/tests/qemublocktestdata/backupmerge/basic-intermediate-out.json
new file mode 100644 (file)
index 0000000..0dffcaf
--- /dev/null
@@ -0,0 +1,10 @@
+[
+  {
+    "node": "libvirt-1-format",
+    "name": "current"
+  },
+  {
+    "node": "libvirt-1-format",
+    "name": "d"
+  }
+]