Note that this is not finished yet, but allows to test the image
detection patches:
Prepare few images:
qemu-img create -f qcow2 /tmp/base.qcow2 10M
qemu-img create -f qcow2 -b /tmp/base.qcow2 /tmp/overlay1-noformat.qcow2
qemu-img create -f qcow2 -F qcow2 -b /tmp/base.qcow2 /tmp/overlay1-format.qcow2
qemu-img create -f qcow2 -F qcow2 -b /tmp/overlay1-format.qcow2
/tmp/overlay2-format.qcow2
qemu-img create -f qcow2 -b /tmp/overlay1-noformat.qcow2
/tmp/overlay2-noformat.qcow2
qemu-img creage -f qcow2 -b nbd://example/asdf /tmp/nbd-noformat.qcow2 10M
(Note that the last one prints error, but that's expected)
Probe images:
$ ./tests/qemublockprobe -f qcow2 -p /tmp/overlay1-noformat.qcow2
type: file (1)
path: /tmp/overlay1-noformat.qcow2
format: qcow2 (14)
protocol: none' (0)
backing store raw: /tmp/base.qcow2
type: file (1)
path: /tmp/base.qcow2
format: qcow2 (14)
protocol: none' (0)
type: none (0)
path: (null)
format: none (0)
protocol: none' (0)
$ ./tests/qemublockprobe -f qcow2 -p /tmp/overlay2-format.qcow2
type: file (1)
path: /tmp/overlay2-format.qcow2
format: qcow2 (14)
protocol: none' (0)
backing store raw: /tmp/overlay1-format.qcow2
type: file (1)
path: /tmp/overlay1-format.qcow2
format: qcow2 (14)
protocol: none' (0)
backing store raw: /tmp/base.qcow2
type: file (1)
path: /tmp/base.qcow2
format: qcow2 (14)
protocol: none' (0)
type: none (0)
path: (null)
format: none (0)
protocol: none' (0)
$ ./tests/qemublockprobe -f qcow2 -p /tmp/overlay2-noformat.qcow2
/home/pipo/build/libvirt/gcc/tests/.libs/lt-qemublockprobe: libvirt error: Requested
operation is not valid: format of backing image '/tmp/overlay1-noformat.qcow2' of
image '/tmp/overlay2-noformat.qcow2' was not specified in the image metadata (See
https://libvirt.org/kbase/backing_chains.html for troubleshooting)
$ ./tests/qemublockprobe -f qcow2 -p /tmp/nbd-noformat.qcow2
/home/pipo/build/libvirt/gcc/tests/.libs/lt-qemublockprobe: libvirt error: Requested
operation is not valid: format of backing image 'nbd://example/asdf' of image
'/tmp/nbd-noformat.qcow2' was not specified in the image metadata (See
https://libvirt.org/kbase/backing_chains.html for troubleshooting)
---
tests/Makefile.am | 13 ++++-
tests/qemublockprobe.c | 130 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 142 insertions(+), 1 deletion(-)
create mode 100644 tests/qemublockprobe.c
diff --git a/tests/Makefile.am b/tests/Makefile.am
index ed5255b62d..a47c7eda22 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -291,7 +291,9 @@ test_programs += qemuxml2argvtest qemuxml2xmltest \
qemufirmwaretest \
qemuvhostusertest \
$(NULL)
-test_helpers += qemucapsprobe
+test_helpers += qemucapsprobe \
+ qemublockprobe \
+ $(NULL)
test_libraries += libqemumonitortestutils.la \
libqemutestdriver.la \
libqemuxml2argvmock.la \
@@ -652,6 +654,14 @@ qemublocktest_LDADD = \
$(qemu_LDADDS) \
$(NULL)
+qemublockprobe_SOURCES = \
+ qemublockprobe.c \
+ $(NULL)
+qemublockprobe_LDADD = \
+ ../src/libvirt.la \
+ $(qemu_LDADDS) \
+ $(NULL)
+
qemudomaincheckpointxml2xmltest_SOURCES = \
qemudomaincheckpointxml2xmltest.c testutilsqemu.c testutilsqemu.h \
testutils.c testutils.h
@@ -707,6 +717,7 @@ EXTRA_DIST += qemuxml2argvtest.c qemuxml2xmltest.c \
qemucaps2xmltest.c qemucommandutiltest.c \
qemumemlocktest.c qemucpumock.c testutilshostcpus.h \
qemublocktest.c \
+ qemublockprobe.c \
qemumigparamstest.c \
qemusecuritytest.c qemusecuritytest.h \
qemusecuritymock.c \
diff --git a/tests/qemublockprobe.c b/tests/qemublockprobe.c
new file mode 100644
index 0000000000..0dbc31028c
--- /dev/null
+++ b/tests/qemublockprobe.c
@@ -0,0 +1,130 @@
+/*
+ * qemublockprobe.c: image backing chain prober
+ *
+ * Copyright (C) 2019 Red Hat, Inc.
+ *
+ * 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 <stdio.h>
+#include <stdbool.h>
+
+#include "util/virfile.h"
+#include "util/virlog.h"
+#include "util/virstoragefile.h"
+
+#include "virgettext.h"
+
+#define VIR_FROM_THIS VIR_FROM_QEMU
+
+
+static void
+print_source(virStorageSourcePtr src)
+{
+ size_t i;
+
+ g_print("type: %s (%d)\n", virStorageTypeToString(src->type),
src->type);
+ g_print("path: %s\n", src->path);
+ g_print("format: %s (%d)\n",
virStorageFileFormatTypeToString(src->format), src->format);
+ g_print("protocol: %s' (%d)\n",
virStorageNetProtocolTypeToString(src->protocol), src->protocol);
+ for (i = 0; i < src->nhosts; i++) {
+ virStorageNetHostDefPtr h = src->hosts + i;
+
+ g_print("host %zu: name: '%s', port: '%u', transport:
'%s'(%d), socket: '%s'\n",
+ i, h->name, h->port,
virStorageNetHostTransportTypeToString(h->transport),
+ h->transport, h->socket);
+ }
+ if (src->sliceStorage)
+ g_print("slice type: storage, offset: %llu, size: %llu\n",
+ src->sliceStorage->offset, src->sliceStorage->size);
+ if (src->backingStoreRaw)
+ g_print("backing store raw: %s\n", src->backingStoreRaw);
+ if (src->externalDataStoreRaw)
+ g_print("external store raw: %s\n", src->externalDataStoreRaw);
+ if (src->relPath)
+ g_print("relative path: %s\n", src->relPath);
+
+ g_print("\n");
+}
+
+
+int main(int argc, char **argv)
+{
+ g_autofree char *path = NULL;
+ g_autofree char *format = NULL;
+ g_autoptr(GError) error = NULL;
+ bool verbose = false;
+ g_autoptr(virStorageSource) src = NULL;
+ GOptionContext *ctx;
+ virStorageSourcePtr n;
+ int ret = 1;
+
+ GOptionEntry entries[] = {
+ { "path", 'p', 0, G_OPTION_ARG_STRING, &path, "path to
image", "DIR" },
+ { "format", 'f', 0, G_OPTION_ARG_STRING, &format,
"format of image", "DIR" },
+ { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
"Verbose output", NULL },
+ { 0 }
+ };
+
+
+ ctx = g_option_context_new("- inspect an image");
+ g_option_context_add_main_entries(ctx, entries, PACKAGE);
+ if (!g_option_context_parse(ctx, &argc, &argv, &error)) {
+ g_printerr("%s: option parsing failed: %s\n",
+ argv[0], error->message);
+ return 1;
+ }
+
+ if (!path) {
+ g_printerr("%s: missing path\n", argv[0]);
+ return 1;
+ }
+
+ if (virErrorInitialize() < 0) {
+ g_printerr("%s: failed to initialize error handling\n", argv[0]);
+ return 1;
+ }
+
+ virLogSetFromEnv();
+ virFileActivateDirOverrideForProg(argv[0]);
+
+ if (!(src = virStorageSourceNew()))
+ goto cleanup;
+
+ src->path = g_steal_pointer(&path);
+ src->type = VIR_STORAGE_TYPE_FILE;
+
+ if (format &&
+ (src->format = virStorageFileFormatTypeFromString(format)) < 0) {
+ g_printerr("%s: unknown format '%s'\n", argv[0], format);
+ goto cleanup;
+ }
+
+ if (virStorageFileGetMetadata(src, -1, -1, true) < 0)
+ goto cleanup;
+
+ for (n = src; n; n = n->backingStore)
+ print_source(n);
+
+ ret = 0;
+
+ cleanup:
+ if (virGetLastErrorCode() != VIR_ERR_OK)
+ g_printerr("%s: libvirt error: %s\n", argv[0],
virGetLastErrorMessage());
+
+ return ret;
+}
--
2.24.1