In future commits, we will optionally use nbdkit to serve some remote
disk sources. This patch queries to see whether nbdkit is installed on
the host and queries it for capabilities. The data will be used in later
commits.
Signed-off-by: Jonathon Jongsma <jjongsma(a)redhat.com>
Reviewed-by: Peter Krempa <pkrempa(a)redhat.com>
---
src/qemu/meson.build | 1 +
src/qemu/qemu_conf.h | 1 +
src/qemu/qemu_nbdkit.c | 200 +++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_nbdkit.h | 50 +++++++++++
4 files changed, 252 insertions(+)
create mode 100644 src/qemu/qemu_nbdkit.c
create mode 100644 src/qemu/qemu_nbdkit.h
diff --git a/src/qemu/meson.build b/src/qemu/meson.build
index c8806bbc36..9be6996195 100644
--- a/src/qemu/meson.build
+++ b/src/qemu/meson.build
@@ -28,6 +28,7 @@ qemu_driver_sources = [
'qemu_monitor_json.c',
'qemu_monitor_text.c',
'qemu_namespace.c',
+ 'qemu_nbdkit.c',
'qemu_passt.c',
'qemu_process.c',
'qemu_qapi.c',
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index 11c740d28f..4f610d86a1 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -36,6 +36,7 @@
#include "virthreadpool.h"
#include "locking/lock_manager.h"
#include "qemu_capabilities.h"
+#include "qemu_nbdkit.h"
#include "virclosecallbacks.h"
#include "virhostdev.h"
#include "virfile.h"
diff --git a/src/qemu/qemu_nbdkit.c b/src/qemu/qemu_nbdkit.c
new file mode 100644
index 0000000000..e4e8fd568e
--- /dev/null
+++ b/src/qemu/qemu_nbdkit.c
@@ -0,0 +1,200 @@
+/*
+ * qemu_nbdkit.c: helpers for using nbdkit
+ *
+ * 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 <glib.h>
+
+#include "vircommand.h"
+#include "virerror.h"
+#include "virlog.h"
+#include "virpidfile.h"
+#include "virutil.h"
+#include "qemu_block.h"
+#include "qemu_conf.h"
+#include "qemu_domain.h"
+#include "qemu_extdevice.h"
+#include "qemu_nbdkit.h"
+#include "qemu_security.h"
+
+#include <fcntl.h>
+
+#define VIR_FROM_THIS VIR_FROM_QEMU
+
+VIR_LOG_INIT("qemu.nbdkit");
+
+VIR_ENUM_IMPL(qemuNbdkitCaps,
+ QEMU_NBDKIT_CAPS_LAST,
+ /* 0 */
+ "plugin-curl", /* QEMU_NBDKIT_CAPS_PLUGIN_CURL */
+ "plugin-ssh", /* QEMU_NBDKIT_CAPS_PLUGIN_SSH */
+ "filter-readahead", /* QEMU_NBDKIT_CAPS_FILTER_READAHEAD */
+);
+
+struct _qemuNbdkitCaps {
+ GObject parent;
+
+ char *path;
+ char *version;
+
+ virBitmap *flags;
+};
+G_DEFINE_TYPE(qemuNbdkitCaps, qemu_nbdkit_caps, G_TYPE_OBJECT);
+
+
+static void
+qemuNbdkitCheckCommandCap(qemuNbdkitCaps *nbdkit,
+ virCommand *cmd,
+ qemuNbdkitCapsFlags cap)
+{
+ if (virCommandRun(cmd, NULL) != 0)
+ return;
+
+ VIR_DEBUG("Setting nbdkit capability %i", cap);
+ ignore_value(virBitmapSetBit(nbdkit->flags, cap));
+}
+
+
+static void
+qemuNbdkitQueryFilter(qemuNbdkitCaps *nbdkit,
+ const char *filter,
+ qemuNbdkitCapsFlags cap)
+{
+ g_autoptr(virCommand) cmd = virCommandNewArgList(nbdkit->path,
+ "--version",
+ NULL);
+
+ virCommandAddArgPair(cmd, "--filter", filter);
+
+ /* use null plugin to check for filter */
+ virCommandAddArg(cmd, "null");
+
+ qemuNbdkitCheckCommandCap(nbdkit, cmd, cap);
+}
+
+
+static void
+qemuNbdkitQueryPlugin(qemuNbdkitCaps *nbdkit,
+ const char *plugin,
+ qemuNbdkitCapsFlags cap)
+{
+ g_autoptr(virCommand) cmd = virCommandNewArgList(nbdkit->path,
+ plugin,
+ "--version",
+ NULL);
+
+ qemuNbdkitCheckCommandCap(nbdkit, cmd, cap);
+}
+
+
+static void
+qemuNbdkitCapsQueryPlugins(qemuNbdkitCaps *nbdkit)
+{
+ qemuNbdkitQueryPlugin(nbdkit, "curl", QEMU_NBDKIT_CAPS_PLUGIN_CURL);
+ qemuNbdkitQueryPlugin(nbdkit, "ssh", QEMU_NBDKIT_CAPS_PLUGIN_SSH);
+}
+
+
+static void
+qemuNbdkitCapsQueryFilters(qemuNbdkitCaps *nbdkit)
+{
+ qemuNbdkitQueryFilter(nbdkit, "readahead",
+ QEMU_NBDKIT_CAPS_FILTER_READAHEAD);
+}
+
+
+static int
+qemuNbdkitCapsQueryVersion(qemuNbdkitCaps *nbdkit)
+{
+ g_autoptr(virCommand) cmd = virCommandNewArgList(nbdkit->path,
+ "--version",
+ NULL);
+
+ virCommandSetOutputBuffer(cmd, &nbdkit->version);
+
+ if (virCommandRun(cmd, NULL) != 0)
+ return -1;
+
+ VIR_DEBUG("Got nbdkit version %s", nbdkit->version);
+ return 0;
+}
+
+
+static void
+qemuNbdkitCapsFinalize(GObject *object)
+{
+ qemuNbdkitCaps *nbdkit = QEMU_NBDKIT_CAPS(object);
+
+ g_clear_pointer(&nbdkit->path, g_free);
+ g_clear_pointer(&nbdkit->version, g_free);
+ g_clear_pointer(&nbdkit->flags, virBitmapFree);
+
+ G_OBJECT_CLASS(qemu_nbdkit_caps_parent_class)->finalize(object);
+}
+
+
+void
+qemu_nbdkit_caps_init(qemuNbdkitCaps *caps)
+{
+ caps->flags = virBitmapNew(QEMU_NBDKIT_CAPS_LAST);
+ caps->version = NULL;
+}
+
+
+static void
+qemu_nbdkit_caps_class_init(qemuNbdkitCapsClass *klass)
+{
+ GObjectClass *obj = G_OBJECT_CLASS(klass);
+
+ obj->finalize = qemuNbdkitCapsFinalize;
+}
+
+
+qemuNbdkitCaps *
+qemuNbdkitCapsNew(const char *path)
+{
+ qemuNbdkitCaps *caps = g_object_new(QEMU_TYPE_NBDKIT_CAPS, NULL);
+ caps->path = g_strdup(path);
+
+ return caps;
+}
+
+
+G_GNUC_UNUSED static void
+qemuNbdkitCapsQuery(qemuNbdkitCaps *caps)
+{
+ qemuNbdkitCapsQueryPlugins(caps);
+ qemuNbdkitCapsQueryFilters(caps);
+ qemuNbdkitCapsQueryVersion(caps);
+}
+
+
+bool
+qemuNbdkitCapsGet(qemuNbdkitCaps *nbdkitCaps,
+ qemuNbdkitCapsFlags flag)
+{
+ return virBitmapIsBitSet(nbdkitCaps->flags, flag);
+}
+
+
+void
+qemuNbdkitCapsSet(qemuNbdkitCaps *nbdkitCaps,
+ qemuNbdkitCapsFlags flag)
+{
+ ignore_value(virBitmapSetBit(nbdkitCaps->flags, flag));
+}
diff --git a/src/qemu/qemu_nbdkit.h b/src/qemu/qemu_nbdkit.h
new file mode 100644
index 0000000000..e191e1fdb4
--- /dev/null
+++ b/src/qemu/qemu_nbdkit.h
@@ -0,0 +1,50 @@
+/*
+ * qemu_nbdkit.h: helpers for using nbdkit
+ *
+ * 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/>.
+ *
+ */
+
+#pragma once
+
+#include "internal.h"
+#include "virenum.h"
+
+typedef struct _qemuNbdkitCaps qemuNbdkitCaps;
+
+typedef enum {
+ /* 0 */
+ QEMU_NBDKIT_CAPS_PLUGIN_CURL,
+ QEMU_NBDKIT_CAPS_PLUGIN_SSH,
+ QEMU_NBDKIT_CAPS_FILTER_READAHEAD,
+
+ QEMU_NBDKIT_CAPS_LAST,
+} qemuNbdkitCapsFlags;
+
+VIR_ENUM_DECL(qemuNbdkitCaps);
+
+qemuNbdkitCaps *
+qemuNbdkitCapsNew(const char *path);
+
+bool
+qemuNbdkitCapsGet(qemuNbdkitCaps *nbdkitCaps,
+ qemuNbdkitCapsFlags flag);
+
+void
+qemuNbdkitCapsSet(qemuNbdkitCaps *nbdkitCaps,
+ qemuNbdkitCapsFlags flag);
+
+#define QEMU_TYPE_NBDKIT_CAPS qemu_nbdkit_caps_get_type()
+G_DECLARE_FINAL_TYPE(qemuNbdkitCaps, qemu_nbdkit_caps, QEMU, NBDKIT_CAPS, GObject);
--
2.41.0