import libguestfs-1.38.4-11.1.module+el8.0.0+4084+cceb9f44

This commit is contained in:
CentOS Sources 2019-09-10 06:48:05 -04:00 committed by Andrew Lukoshko
commit 7d6753cdd1
89 changed files with 15115 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
SOURCES/RHEV-Application-Provisioning-Tool.exe_4.42
SOURCES/libguestfs-1.38.4.tar.gz
SOURCES/libguestfs.keyring
SOURCES/rhsrvany.exe

4
.libguestfs.metadata Normal file
View File

@ -0,0 +1,4 @@
c44dcbd8c9b390e151c16821ff093e4dc408be66 SOURCES/RHEV-Application-Provisioning-Tool.exe_4.42
15c8f487ee163374cb7be9436fb1bb697cef7d9e SOURCES/libguestfs-1.38.4.tar.gz
1bbc40f501a7fef9eef2a39b701a71aee2fea7c4 SOURCES/libguestfs.keyring
2bd96e478fc004cd323b5bd754c856641877dac6 SOURCES/rhsrvany.exe

View File

@ -0,0 +1,973 @@
From 21f0a22072f0543c416c440665bcf75ae09e6233 Mon Sep 17 00:00:00 2001
From: Pino Toscano <ptoscano@redhat.com>
Date: Mon, 12 Feb 2018 11:24:06 +0100
Subject: [PATCH] Switch from YAJL to Jansson
While YAJL mostly works fine, it did not see any active development in
the last 3 years. OTOH, Jansson is another JSON C implementation, with
a very liberal license, and a much nicer API.
Hence, switch all of libguestfs from YAJL to Jansson:
- configure checks, and buildsystem in general
- packages pulled in the appliance
- actual implementations
- contrib scripts
- documentation
This also makes use of the better APIs available (e.g. json_object_get,
json_array_foreach, and json_object_foreach). This does not change the
API of our OCaml Yajl module.
(cherry picked from commit bd1c5c9f4dcf38458099db8a0bf4659a07ef055d)
---
appliance/packagelist.in | 13 ++--
builder/Makefile.am | 4 +-
builder/yajl-c.c | 66 ++++++++--------
contrib/p2v/aux-scripts/do-build.sh | 8 +-
contrib/p2v/build-p2v-iso.sh | 3 +-
daemon/Makefile.am | 4 +-
daemon/ldm.c | 113 ++++++++++++----------------
docs/guestfs-building.pod | 2 +-
lib/Makefile.am | 4 +-
lib/info.c | 113 +++++++++++-----------------
lib/qemu.c | 64 ++++++----------
m4/guestfs-libraries.m4 | 4 +-
12 files changed, 168 insertions(+), 230 deletions(-)
diff --git a/appliance/packagelist.in b/appliance/packagelist.in
index 8ded2588a..f92a6ce95 100644
--- a/appliance/packagelist.in
+++ b/appliance/packagelist.in
@@ -35,6 +35,7 @@ ifelse(REDHAT,1,
hivex
iproute
iputils
+ jansson
kernel
libcap
libldm
@@ -51,7 +52,6 @@ ifelse(REDHAT,1,
systemd dnl for /sbin/reboot and udevd
vim-minimal
xz
- yajl
yara
zfs-fuse
)
@@ -82,12 +82,12 @@ dnl iproute has been renamed to iproute2
libc-bin
libcap2
libhivex0
+ libjansson4
libpcre3
libsystemd0
libsystemd-id128-0
libsystemd-journal0
libtirpc1
- libyajl2
libyara3
linux-image
dnl syslinux 'suggests' mtools, but in reality it's a hard dependency:
@@ -116,6 +116,7 @@ ifelse(ARCHLINUX,1,
hivex
iproute2
iputils
+ jansson
libcap
libtirpc
linux
@@ -131,7 +132,6 @@ ifelse(ARCHLINUX,1,
systemd
vim
xz
- yajl
yara
)
@@ -153,9 +153,9 @@ ifelse(SUSE,1,
iputils
libcap2
libhivex0
+ libjansson4
libselinux1
libtirpc3
- libyajl2
libyara3
mkisofs
ntfsprogs
@@ -177,6 +177,7 @@ ifelse(FRUGALWARE,1,
hfsplus
iproute2
iputils
+ jansson
kernel
libcap
libtirpc
@@ -188,7 +189,6 @@ ifelse(FRUGALWARE,1,
systemd
vim
xz
- yajl
xfsprogs-acl
xfsprogs-attr
gptfdisk
@@ -209,9 +209,9 @@ ifelse(MAGEIA,1,
iproute2
iputils
libcap
+ libjansson4
libldm
libtirpc
- libyajl
dnl syslinux uses mtools without depending on it
mtools
nilfs-utils
@@ -224,7 +224,6 @@ ifelse(MAGEIA,1,
systemd /* for /sbin/reboot and udevd */
vim-minimal
xz
- yajl
)
acl
diff --git a/builder/Makefile.am b/builder/Makefile.am
index e5872bdd9..c7b50778a 100644
--- a/builder/Makefile.am
+++ b/builder/Makefile.am
@@ -157,7 +157,7 @@ virt_builder_CFLAGS = \
$(LIBLZMA_CFLAGS) \
$(LIBTINFO_CFLAGS) \
$(LIBXML2_CFLAGS) \
- $(YAJL_CFLAGS)
+ $(JANSSON_CFLAGS)
BOBJECTS = $(SOURCES_ML:.ml=.cmo)
XOBJECTS = $(BOBJECTS:.cmo=.cmx)
@@ -211,7 +211,7 @@ OCAMLCLIBS = \
$(LIBCRYPT_LIBS) \
$(LIBLZMA_LIBS) \
$(LIBXML2_LIBS) \
- $(YAJL_LIBS) \
+ $(JANSSON_LIBS) \
$(LIBINTL) \
-lgnu
diff --git a/builder/yajl-c.c b/builder/yajl-c.c
index 3c2402e42..e53755f55 100644
--- a/builder/yajl-c.c
+++ b/builder/yajl-c.c
@@ -23,24 +23,17 @@
#include <caml/memory.h>
#include <caml/mlvalues.h>
-#include <yajl/yajl_tree.h>
+#include <jansson.h>
#include <stdio.h>
#include <string.h>
-/* GCC can't work out that the YAJL_IS_<foo> test is sufficient to
- * ensure that YAJL_GET_<foo> later doesn't return NULL.
- */
-#if defined(__GNUC__) && __GNUC__ >= 6 /* gcc >= 6 */
-#pragma GCC diagnostic ignored "-Wnull-dereference"
-#endif
-
#define Val_none (Val_int (0))
value virt_builder_yajl_tree_parse (value stringv);
static value
-convert_yajl_value (yajl_val val, int level)
+convert_json_t (json_t *val, int level)
{
CAMLparam0 ();
CAMLlocal4 (rv, lv, v, sv);
@@ -48,46 +41,51 @@ convert_yajl_value (yajl_val val, int level)
if (level > 20)
caml_invalid_argument ("too many levels of object/array nesting");
- if (YAJL_IS_OBJECT (val)) {
- const size_t len = YAJL_GET_OBJECT(val)->len;
+ if (json_is_object (val)) {
+ const size_t len = json_object_size (val);
size_t i;
+ const char *key;
+ json_t *jvalue;
rv = caml_alloc (1, 3);
lv = caml_alloc_tuple (len);
- for (i = 0; i < len; ++i) {
+ i = 0;
+ json_object_foreach (val, key, jvalue) {
v = caml_alloc_tuple (2);
- sv = caml_copy_string (YAJL_GET_OBJECT(val)->keys[i]);
+ sv = caml_copy_string (key);
Store_field (v, 0, sv);
- sv = convert_yajl_value (YAJL_GET_OBJECT(val)->values[i], level + 1);
+ sv = convert_json_t (jvalue, level + 1);
Store_field (v, 1, sv);
Store_field (lv, i, v);
+ ++i;
}
Store_field (rv, 0, lv);
- } else if (YAJL_IS_ARRAY (val)) {
- const size_t len = YAJL_GET_ARRAY(val)->len;
+ } else if (json_is_array (val)) {
+ const size_t len = json_array_size (val);
size_t i;
+ json_t *jvalue;
rv = caml_alloc (1, 4);
lv = caml_alloc_tuple (len);
- for (i = 0; i < len; ++i) {
- v = convert_yajl_value (YAJL_GET_ARRAY(val)->values[i], level + 1);
+ json_array_foreach (val, i, jvalue) {
+ v = convert_json_t (jvalue, level + 1);
Store_field (lv, i, v);
}
Store_field (rv, 0, lv);
- } else if (YAJL_IS_STRING (val)) {
+ } else if (json_is_string (val)) {
rv = caml_alloc (1, 0);
- v = caml_copy_string (YAJL_GET_STRING(val));
+ v = caml_copy_string (json_string_value (val));
Store_field (rv, 0, v);
- } else if (YAJL_IS_DOUBLE (val)) {
+ } else if (json_is_real (val)) {
rv = caml_alloc (1, 2);
- v = caml_copy_double (YAJL_GET_DOUBLE(val));
+ v = caml_copy_double (json_real_value (val));
Store_field (rv, 0, v);
- } else if (YAJL_IS_INTEGER (val)) {
+ } else if (json_is_integer (val)) {
rv = caml_alloc (1, 1);
- v = caml_copy_int64 (YAJL_GET_INTEGER(val));
+ v = caml_copy_int64 (json_integer_value (val));
Store_field (rv, 0, v);
- } else if (YAJL_IS_TRUE (val)) {
+ } else if (json_is_true (val)) {
rv = caml_alloc (1, 5);
Store_field (rv, 0, Val_true);
- } else if (YAJL_IS_FALSE (val)) {
+ } else if (json_is_false (val)) {
rv = caml_alloc (1, 5);
Store_field (rv, 0, Val_false);
} else
@@ -101,21 +99,21 @@ virt_builder_yajl_tree_parse (value stringv)
{
CAMLparam1 (stringv);
CAMLlocal1 (rv);
- yajl_val tree;
- char error_buf[256];
+ json_t *tree;
+ json_error_t err;
- tree = yajl_tree_parse (String_val (stringv), error_buf, sizeof error_buf);
+ tree = json_loads (String_val (stringv), JSON_DECODE_ANY, &err);
if (tree == NULL) {
- char buf[256 + sizeof error_buf];
- if (strlen (error_buf) > 0)
- snprintf (buf, sizeof buf, "JSON parse error: %s", error_buf);
+ char buf[256 + JSON_ERROR_TEXT_LENGTH];
+ if (strlen (err.text) > 0)
+ snprintf (buf, sizeof buf, "JSON parse error: %s", err.text);
else
snprintf (buf, sizeof buf, "unknown JSON parse error");
caml_invalid_argument (buf);
}
- rv = convert_yajl_value (tree, 1);
- yajl_tree_free (tree);
+ rv = convert_json_t (tree, 1);
+ json_decref (tree);
CAMLreturn (rv);
}
diff --git a/contrib/p2v/aux-scripts/do-build.sh b/contrib/p2v/aux-scripts/do-build.sh
index 5edb53d0e..dd6424bb4 100644
--- a/contrib/p2v/aux-scripts/do-build.sh
+++ b/contrib/p2v/aux-scripts/do-build.sh
@@ -53,8 +53,8 @@ case $osversion in
# This just forces configure to ignore these missing dependencies.
export LIBTINFO_CFLAGS=-D_GNU_SOURCE
export LIBTINFO_LIBS=-lncurses
- export YAJL_CFLAGS=-D_GNU_SOURCE
- export YAJL_LIBS=-lyajl
+ export JANSSON_CFLAGS=-D_GNU_SOURCE
+ export JANSSON_LIBS=-ljansson
# Remove some unsupported flags that the configure script hard codes.
sed -i -e 's/-fno-strict-overflow//' configure
sed -i -e 's/-Wno-strict-overflow//' configure
@@ -66,8 +66,8 @@ case $osversion in
# This just forces configure to ignore these missing dependencies.
export LIBTINFO_CFLAGS=-D_GNU_SOURCE
export LIBTINFO_LIBS=-lncurses
- export YAJL_CFLAGS=-D_GNU_SOURCE
- export YAJL_LIBS=-lyajl
+ export JANSSON_CFLAGS=-D_GNU_SOURCE
+ export JANSSON_LIBS=-ljansson
;;
esac
diff --git a/contrib/p2v/build-p2v-iso.sh b/contrib/p2v/build-p2v-iso.sh
index c80a1b134..ae25cebc8 100755
--- a/contrib/p2v/build-p2v-iso.sh
+++ b/contrib/p2v/build-p2v-iso.sh
@@ -86,7 +86,6 @@ done
# Various hacks for different versions of RHEL.
if=virtio
netdev=virtio-net-pci
-pkgs="$pkgs,yajl-devel"
declare -a epel
case $osversion in
rhel-5.*|centos-5.*)
@@ -105,10 +104,12 @@ case $osversion in
rhel-6.*|centos-6.*)
epel[0]="--run-command"
epel[1]="yum install -y --nogpgcheck https://dl.fedoraproject.org/pub/epel/epel-release-latest-6.noarch.rpm"
+ pkgs="$pkgs,jansson-devel"
;;
rhel-7.*|centos-7.*)
epel[0]="--run-command"
epel[1]="yum install -y --nogpgcheck https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm"
+ pkgs="$pkgs,jansson-devel"
;;
esac
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 6240f517d..d9ed5625e 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -218,7 +218,7 @@ guestfsd_LDADD = \
camldaemon.o \
$(ACL_LIBS) \
$(CAP_LIBS) \
- $(YAJL_LIBS) \
+ $(JANSSON_LIBS) \
$(SELINUX_LIBS) \
$(AUGEAS_LIBS) \
$(HIVEX_LIBS) \
@@ -256,7 +256,7 @@ guestfsd_CFLAGS = \
$(AUGEAS_CFLAGS) \
$(HIVEX_CFLAGS) \
$(SD_JOURNAL_CFLAGS) \
- $(YAJL_CFLAGS) \
+ $(JANSSON_CFLAGS) \
$(PCRE_CFLAGS)
# Parts of the daemon are written in OCaml. These are linked into a
diff --git a/daemon/ldm.c b/daemon/ldm.c
index 2f4d2aef3..be4fb9701 100644
--- a/daemon/ldm.c
+++ b/daemon/ldm.c
@@ -25,19 +25,12 @@
#include <sys/stat.h>
#include <string.h>
-#include <yajl/yajl_tree.h>
+#include <jansson.h>
#include "daemon.h"
#include "actions.h"
#include "optgroups.h"
-/* GCC can't work out that the YAJL_IS_<foo> test is sufficient to
- * ensure that YAJL_GET_<foo> later doesn't return NULL.
- */
-#if defined(__GNUC__) && GUESTFS_GCC_VERSION >= 60000 /* gcc >= 6 */
-#pragma GCC diagnostic ignored "-Wnull-dereference"
-#endif
-
int
optgroup_ldm_available (void)
{
@@ -72,44 +65,42 @@ do_ldmtool_remove_all (void)
return 0;
}
-static yajl_val
+static json_t *
parse_json (const char *json, const char *func)
{
- yajl_val tree;
- char parse_error[1024];
+ json_t *tree;
+ json_error_t err;
if (verbose)
fprintf (stderr, "%s: parsing json: %s\n", func, json);
- tree = yajl_tree_parse (json, parse_error, sizeof parse_error);
+ tree = json_loads (json, 0, &err);
if (tree == NULL) {
reply_with_error ("parse error: %s",
- strlen (parse_error) ? parse_error : "unknown error");
+ strlen (err.text) ? err.text : "unknown error");
return NULL;
}
- /* Caller should free this by doing 'yajl_tree_free (tree);'. */
+ /* Caller should free this by doing 'json_decref (tree);'. */
return tree;
}
#define TYPE_ERROR ((char **) -1)
static char **
-json_value_to_string_list (yajl_val node)
+json_value_to_string_list (json_t *node)
{
CLEANUP_FREE_STRINGSBUF DECLARE_STRINGSBUF (strs);
- yajl_val n;
- size_t i, len;
+ json_t *n;
+ size_t i;
- if (! YAJL_IS_ARRAY (node))
+ if (!json_is_array (node))
return TYPE_ERROR;
- len = YAJL_GET_ARRAY (node)->len;
- for (i = 0; i < len; ++i) {
- n = YAJL_GET_ARRAY (node)->values[i];
- if (! YAJL_IS_STRING (n))
+ json_array_foreach (node, i, n) {
+ if (!json_is_string (n))
return TYPE_ERROR;
- if (add_string (&strs, YAJL_GET_STRING (n)) == -1)
+ if (add_string (&strs, json_string_value (n)) == -1)
return NULL;
}
if (end_stringsbuf (&strs) == -1)
@@ -123,14 +114,14 @@ parse_json_get_string_list (const char *json,
const char *func, const char *cmd)
{
char **ret;
- yajl_val tree = NULL;
+ json_t *tree = NULL;
tree = parse_json (json, func);
if (tree == NULL)
return NULL;
ret = json_value_to_string_list (tree);
- yajl_tree_free (tree);
+ json_decref (tree);
if (ret == TYPE_ERROR) {
reply_with_error ("output of '%s' was not a JSON array of strings", cmd);
return NULL;
@@ -144,43 +135,40 @@ static char *
parse_json_get_object_string (const char *json, const char *key, int flags,
const char *func, const char *cmd)
{
- char *str, *ret;
- yajl_val tree = NULL, node;
- size_t i, len;
+ const char *str;
+ char *ret;
+ json_t *tree = NULL, *node;
tree = parse_json (json, func);
if (tree == NULL)
return NULL;
- if (! YAJL_IS_OBJECT (tree))
+ if (!json_is_object (tree))
goto bad_type;
- len = YAJL_GET_OBJECT (tree)->len;
- for (i = 0; i < len; ++i) {
- if (STREQ (YAJL_GET_OBJECT (tree)->keys[i], key)) {
- node = YAJL_GET_OBJECT (tree)->values[i];
-
- if ((flags & GET_STRING_NULL_TO_EMPTY) && YAJL_IS_NULL (node))
- ret = strdup ("");
- else {
- str = YAJL_GET_STRING (node);
- if (str == NULL)
- goto bad_type;
- ret = strdup (str);
- }
- if (ret == NULL)
- reply_with_perror ("strdup");
-
- yajl_tree_free (tree);
+ node = json_object_get (tree, key);
+ if (node == NULL)
+ goto bad_type;
- return ret;
- }
+ if ((flags & GET_STRING_NULL_TO_EMPTY) && json_is_null (node))
+ ret = strdup ("");
+ else {
+ str = json_string_value (node);
+ if (str == NULL)
+ goto bad_type;
+ ret = strndup (str, json_string_length (node));
}
+ if (ret == NULL)
+ reply_with_perror ("strdup");
+
+ json_decref (tree);
+
+ return ret;
bad_type:
reply_with_error ("output of '%s' was not a JSON object "
"containing a key '%s' of type string", cmd, key);
- yajl_tree_free (tree);
+ json_decref (tree);
return NULL;
}
@@ -189,33 +177,30 @@ parse_json_get_object_string_list (const char *json, const char *key,
const char *func, const char *cmd)
{
char **ret;
- yajl_val tree, node;
- size_t i, len;
+ json_t *tree, *node;
tree = parse_json (json, func);
if (tree == NULL)
return NULL;
- if (! YAJL_IS_OBJECT (tree))
+ if (!json_is_object (tree))
goto bad_type;
- len = YAJL_GET_OBJECT (tree)->len;
- for (i = 0; i < len; ++i) {
- if (STREQ (YAJL_GET_OBJECT (tree)->keys[i], key)) {
- node = YAJL_GET_OBJECT (tree)->values[i];
- ret = json_value_to_string_list (node);
- if (ret == TYPE_ERROR)
- goto bad_type;
- yajl_tree_free (tree);
- return ret;
- }
- }
+ node = json_object_get (tree, key);
+ if (node == NULL)
+ goto bad_type;
+
+ ret = json_value_to_string_list (node);
+ if (ret == TYPE_ERROR)
+ goto bad_type;
+ json_decref (tree);
+ return ret;
bad_type:
reply_with_error ("output of '%s' was not a JSON object "
"containing a key '%s' of type array of strings",
cmd, key);
- yajl_tree_free (tree);
+ json_decref (tree);
return NULL;
}
diff --git a/docs/guestfs-building.pod b/docs/guestfs-building.pod
index d350b1d73..2029429fd 100644
--- a/docs/guestfs-building.pod
+++ b/docs/guestfs-building.pod
@@ -172,7 +172,7 @@ I<Required>.
I<Required>.
-=item yajl E<ge> 2.0.4
+=item Jansson
I<Required>.
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 91c4e0a2e..d075174d9 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -141,7 +141,7 @@ libguestfs_la_CFLAGS = \
$(PCRE_CFLAGS) \
$(LIBVIRT_CFLAGS) \
$(LIBXML2_CFLAGS) \
- $(YAJL_CFLAGS)
+ $(JANSSON_CFLAGS)
libguestfs_la_LIBADD = \
../common/errnostring/liberrnostring.la \
@@ -152,7 +152,7 @@ libguestfs_la_LIBADD = \
$(PCRE_LIBS) \
$(LIBVIRT_LIBS) $(LIBXML2_LIBS) \
$(SELINUX_LIBS) \
- $(YAJL_LIBS) \
+ $(JANSSON_LIBS) \
../gnulib/lib/libgnu.la \
$(GETADDRINFO_LIB) \
$(HOSTENT_LIB) \
diff --git a/lib/info.c b/lib/info.c
index 93fadcd39..2eadc1c11 100644
--- a/lib/info.c
+++ b/lib/info.c
@@ -37,53 +37,46 @@
#include <sys/resource.h>
#endif
-#include <yajl/yajl_tree.h>
+#include <jansson.h>
#include "guestfs.h"
#include "guestfs-internal.h"
#include "guestfs-internal-actions.h"
#ifdef HAVE_ATTRIBUTE_CLEANUP
-#define CLEANUP_YAJL_TREE_FREE __attribute__((cleanup(cleanup_yajl_tree_free)))
+#define CLEANUP_JSON_T_DECREF __attribute__((cleanup(cleanup_json_t_decref)))
static void
-cleanup_yajl_tree_free (void *ptr)
+cleanup_json_t_decref (void *ptr)
{
- yajl_tree_free (* (yajl_val *) ptr);
+ json_decref (* (json_t **) ptr);
}
#else
-#define CLEANUP_YAJL_TREE_FREE
+#define CLEANUP_JSON_T_DECREF
#endif
-static yajl_val get_json_output (guestfs_h *g, const char *filename);
+static json_t *get_json_output (guestfs_h *g, const char *filename);
static void set_child_rlimits (struct command *);
char *
guestfs_impl_disk_format (guestfs_h *g, const char *filename)
{
- size_t i, len;
- CLEANUP_YAJL_TREE_FREE yajl_val tree = get_json_output (g, filename);
+ CLEANUP_JSON_T_DECREF json_t *tree = get_json_output (g, filename);
+ json_t *node;
if (tree == NULL)
return NULL;
- if (! YAJL_IS_OBJECT (tree))
+ if (!json_is_object (tree))
goto bad_type;
- len = YAJL_GET_OBJECT(tree)->len;
- for (i = 0; i < len; ++i) {
- if (STREQ (YAJL_GET_OBJECT(tree)->keys[i], "format")) {
- const char *str;
- yajl_val node = YAJL_GET_OBJECT(tree)->values[i];
- if (YAJL_IS_NULL (node))
- goto bad_type;
- str = YAJL_GET_STRING (node);
- if (str == NULL)
- goto bad_type;
- return safe_strdup (g, str); /* caller frees */
- }
- }
+ node = json_object_get (tree, "format");
+ if (!json_is_string (node))
+ goto bad_type;
+
+ return safe_strndup (g, json_string_value (node),
+ json_string_length (node)); /* caller frees */
bad_type:
error (g, _("qemu-img info: JSON output did not contain format key"));
@@ -93,30 +86,20 @@ guestfs_impl_disk_format (guestfs_h *g, const char *filename)
int64_t
guestfs_impl_disk_virtual_size (guestfs_h *g, const char *filename)
{
- size_t i, len;
- CLEANUP_YAJL_TREE_FREE yajl_val tree = get_json_output (g, filename);
+ CLEANUP_JSON_T_DECREF json_t *tree = get_json_output (g, filename);
+ json_t *node;
if (tree == NULL)
return -1;
- if (! YAJL_IS_OBJECT (tree))
+ if (!json_is_object (tree))
goto bad_type;
- len = YAJL_GET_OBJECT(tree)->len;
- for (i = 0; i < len; ++i) {
- if (STREQ (YAJL_GET_OBJECT(tree)->keys[i], "virtual-size")) {
- yajl_val node = YAJL_GET_OBJECT(tree)->values[i];
- if (YAJL_IS_NULL (node))
- goto bad_type;
- if (! YAJL_IS_NUMBER (node))
- goto bad_type;
- if (! YAJL_IS_INTEGER (node)) {
- error (g, _("qemu-img info: virtual-size is not representable as a 64 bit integer"));
- return -1;
- }
- return YAJL_GET_INTEGER (node);
- }
- }
+ node = json_object_get (tree, "virtual-size");
+ if (!json_is_integer (node))
+ goto bad_type;
+
+ return json_integer_value (node);
bad_type:
error (g, _("qemu-img info: JSON output did not contain virtual-size key"));
@@ -126,29 +109,25 @@ guestfs_impl_disk_virtual_size (guestfs_h *g, const char *filename)
int
guestfs_impl_disk_has_backing_file (guestfs_h *g, const char *filename)
{
- size_t i, len;
- CLEANUP_YAJL_TREE_FREE yajl_val tree = get_json_output (g, filename);
+ CLEANUP_JSON_T_DECREF json_t *tree = get_json_output (g, filename);
+ json_t *node;
if (tree == NULL)
return -1;
- if (! YAJL_IS_OBJECT (tree))
+ if (!json_is_object (tree))
goto bad_type;
- len = YAJL_GET_OBJECT(tree)->len;
- for (i = 0; i < len; ++i) {
- if (STREQ (YAJL_GET_OBJECT(tree)->keys[i], "backing-filename")) {
- yajl_val node = YAJL_GET_OBJECT(tree)->values[i];
- /* Work on the assumption that if this field is null, it means
- * no backing file, rather than being an error.
- */
- if (YAJL_IS_NULL (node))
- return 0;
- return 1;
- }
- }
+ node = json_object_get (tree, "backing-filename");
+ if (node == NULL)
+ return 0; /* no backing-filename key means no backing file */
- return 0; /* no backing-filename key means no backing file */
+ /* Work on the assumption that if this field is null, it means
+ * no backing file, rather than being an error.
+ */
+ if (json_is_null (node))
+ return 0;
+ return 1;
bad_type:
error (g, _("qemu-img info: JSON output was not an object"));
@@ -161,12 +140,12 @@ guestfs_impl_disk_has_backing_file (guestfs_h *g, const char *filename)
static void parse_json (guestfs_h *g, void *treevp, const char *input, size_t len);
#define PARSE_JSON_NO_OUTPUT ((void *) -1)
-static yajl_val
+static json_t *
get_json_output (guestfs_h *g, const char *filename)
{
CLEANUP_CMD_CLOSE struct command *cmd = guestfs_int_new_command (g);
int r;
- yajl_val tree = NULL;
+ json_t *tree = NULL;
guestfs_int_cmd_add_arg (cmd, "qemu-img");
guestfs_int_cmd_add_arg (cmd, "info");
@@ -196,16 +175,15 @@ get_json_output (guestfs_h *g, const char *filename)
return NULL;
}
- return tree; /* caller must call yajl_tree_free (tree) */
+ return tree; /* caller must call json_decref (tree) */
}
/* Parse the JSON document printed by qemu-img info --output json. */
static void
parse_json (guestfs_h *g, void *treevp, const char *input, size_t len)
{
- yajl_val *tree_ret = treevp;
- CLEANUP_FREE char *input_copy = NULL;
- char parse_error[256];
+ json_t **tree_ret = treevp;
+ json_error_t err;
assert (*tree_ret == NULL);
@@ -218,15 +196,12 @@ parse_json (guestfs_h *g, void *treevp, const char *input, size_t len)
return;
}
- /* 'input' is not \0-terminated; we have to make it so. */
- input_copy = safe_strndup (g, input, len);
+ debug (g, "%s: qemu-img info JSON output:\n%.*s\n", __func__, (int) len, input);
- debug (g, "%s: qemu-img info JSON output:\n%s\n", __func__, input_copy);
-
- *tree_ret = yajl_tree_parse (input_copy, parse_error, sizeof parse_error);
+ *tree_ret = json_loadb (input, len, 0, &err);
if (*tree_ret == NULL) {
- if (strlen (parse_error) > 0)
- error (g, _("qemu-img info: JSON parse error: %s"), parse_error);
+ if (strlen (err.text) > 0)
+ error (g, _("qemu-img info: JSON parse error: %s"), err.text);
else
error (g, _("qemu-img info: unknown JSON parse error"));
}
diff --git a/lib/qemu.c b/lib/qemu.c
index 6159b5a52..a50eca988 100644
--- a/lib/qemu.c
+++ b/lib/qemu.c
@@ -37,7 +37,7 @@
#include <libxml/uri.h>
-#include <yajl/yajl_tree.h>
+#include <jansson.h>
#include "full-write.h"
#include "ignore-value.h"
@@ -57,7 +57,7 @@ struct qemu_data {
/* The following fields are derived from the fields above. */
struct version qemu_version; /* Parsed qemu version number. */
- yajl_val qmp_schema_tree; /* qmp_schema parsed into a JSON tree */
+ json_t *qmp_schema_tree; /* qmp_schema parsed into a JSON tree */
};
static char *cache_filename (guestfs_h *g, const char *cachedir, const struct stat *, const char *suffix);
@@ -73,7 +73,7 @@ static int write_cache_qmp_schema (guestfs_h *g, const struct qemu_data *data, c
static int read_cache_qemu_stat (guestfs_h *g, struct qemu_data *data, const char *filename);
static int write_cache_qemu_stat (guestfs_h *g, const struct qemu_data *data, const char *filename);
static void parse_qemu_version (guestfs_h *g, const char *, struct version *qemu_version);
-static void parse_json (guestfs_h *g, const char *, yajl_val *);
+static void parse_json (guestfs_h *g, const char *, json_t **);
static void read_all (guestfs_h *g, void *retv, const char *buf, size_t len);
static int generic_read_cache (guestfs_h *g, const char *filename, char **strp);
static int generic_write_cache (guestfs_h *g, const char *filename, const char *str);
@@ -405,17 +405,17 @@ parse_qemu_version (guestfs_h *g, const char *qemu_help,
* is not possible.
*/
static void
-parse_json (guestfs_h *g, const char *json, yajl_val *treep)
+parse_json (guestfs_h *g, const char *json, json_t **treep)
{
- char parse_error[256] = "";
+ json_error_t err;
if (!json)
return;
- *treep = yajl_tree_parse (json, parse_error, sizeof parse_error);
+ *treep = json_loads (json, 0, &err);
if (*treep == NULL) {
- if (strlen (parse_error) > 0)
- debug (g, "QMP parse error: %s (ignored)", parse_error);
+ if (strlen (err.text) > 0)
+ debug (g, "QMP parse error: %s (ignored)", err.text);
else
debug (g, "QMP unknown parse error (ignored)");
}
@@ -580,17 +580,6 @@ guestfs_int_qemu_supports_device (guestfs_h *g,
return strstr (data->qemu_devices, device_name) != NULL;
}
-/* GCC can't work out that the YAJL_IS_<foo> test is sufficient to
- * ensure that YAJL_GET_<foo> later doesn't return NULL.
- */
-#pragma GCC diagnostic push
-#if defined(__GNUC__) && __GNUC__ >= 6 /* gcc >= 6 */
-#pragma GCC diagnostic ignored "-Wnull-dereference"
-#endif
-#if defined(__GNUC__) && GUESTFS_GCC_VERSION >= 40800 /* gcc >= 4.8.0 */
-#pragma GCC diagnostic ignored "-Wnonnull"
-#endif
-
/**
* Test if the qemu binary uses mandatory file locking, added in
* QEMU >= 2.10 (but sometimes disabled).
@@ -599,11 +588,7 @@ int
guestfs_int_qemu_mandatory_locking (guestfs_h *g,
const struct qemu_data *data)
{
- const char *return_path[] = { "return", NULL };
- const char *meta_type_path[] = { "meta-type", NULL };
- const char *members_path[] = { "members", NULL };
- const char *name_path[] = { "name", NULL };
- yajl_val schema, v, meta_type, members, m, name;
+ json_t *schema, *v, *meta_type, *members, *m, *name;
size_t i, j;
/* If there's no QMP schema, fall back to checking the version. */
@@ -616,27 +601,24 @@ guestfs_int_qemu_mandatory_locking (guestfs_h *g,
* Extract the schema from the wrapper. Note the returned schema
* will be an array.
*/
- schema = yajl_tree_get (data->qmp_schema_tree, return_path, yajl_t_array);
- if (schema == NULL)
+ schema = json_object_get (data->qmp_schema_tree, "return");
+ if (!json_is_array (schema))
goto fallback;
- assert (YAJL_IS_ARRAY(schema));
/* Now look for any member of the array which has:
* { "meta-type": "object",
* "members": [ ... { "name": "locking", ... } ... ] ... }
*/
- for (i = 0; i < YAJL_GET_ARRAY(schema)->len; ++i) {
- v = YAJL_GET_ARRAY(schema)->values[i];
- meta_type = yajl_tree_get (v, meta_type_path, yajl_t_string);
- if (meta_type && YAJL_IS_STRING (meta_type) &&
- STREQ (YAJL_GET_STRING (meta_type), "object")) {
- members = yajl_tree_get (v, members_path, yajl_t_array);
- if (members) {
- for (j = 0; j < YAJL_GET_ARRAY(members)->len; ++j) {
- m = YAJL_GET_ARRAY(members)->values[j];
- name = yajl_tree_get (m, name_path, yajl_t_string);
- if (name && YAJL_IS_STRING (name) &&
- STREQ (YAJL_GET_STRING (name), "locking"))
+ json_array_foreach (schema, i, v) {
+ meta_type = json_object_get (v, "meta-type");
+ if (json_is_string (meta_type) &&
+ STREQ (json_string_value (meta_type), "object")) {
+ members = json_object_get (v, "members");
+ if (json_is_array (members)) {
+ json_array_foreach (members, j, m) {
+ name = json_object_get (v, "name");
+ if (json_is_string (name) &&
+ STREQ (json_string_value (name), "locking"))
return 1;
}
}
@@ -646,8 +628,6 @@ guestfs_int_qemu_mandatory_locking (guestfs_h *g,
return 0;
}
-#pragma GCC diagnostic pop
-
/**
* Escape a qemu parameter.
*
@@ -996,7 +976,7 @@ guestfs_int_free_qemu_data (struct qemu_data *data)
free (data->qemu_help);
free (data->qemu_devices);
free (data->qmp_schema);
- yajl_tree_free (data->qmp_schema_tree);
+ json_decref (data->qmp_schema_tree);
free (data);
}
}
diff --git a/m4/guestfs-libraries.m4 b/m4/guestfs-libraries.m4
index 78a9e792f..2fdbd9669 100644
--- a/m4/guestfs-libraries.m4
+++ b/m4/guestfs-libraries.m4
@@ -299,8 +299,8 @@ LIBS="$LIBS $LIBXML2_LIBS"
AC_CHECK_FUNCS([xmlBufferDetach])
LIBS="$old_LIBS"
-dnl Check for yajl JSON library (required).
-PKG_CHECK_MODULES([YAJL], [yajl >= 2.0.4])
+dnl Check for Jansson JSON library (required).
+PKG_CHECK_MODULES([JANSSON], [jansson])
dnl Check for C++ (optional, we just use this to test the header works).
AC_PROG_CXX
--
2.21.0

View File

@ -0,0 +1,31 @@
From 898e6c1e39deb130566220a11a2eaf2dcb2cb733 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Thu, 29 Mar 2018 20:18:34 +0100
Subject: [PATCH] qemu: Fix transcription error in conversion of yajl to
jansson.
This broke qemu mandatory locking detection.
Fixes commit bd1c5c9f4dcf38458099db8a0bf4659a07ef055d.
(cherry picked from commit e79286f71738d9385157d9e87211be02645722c3)
---
lib/qemu.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/qemu.c b/lib/qemu.c
index a50eca988..3e7f15946 100644
--- a/lib/qemu.c
+++ b/lib/qemu.c
@@ -616,7 +616,7 @@ guestfs_int_qemu_mandatory_locking (guestfs_h *g,
members = json_object_get (v, "members");
if (json_is_array (members)) {
json_array_foreach (members, j, m) {
- name = json_object_get (v, "name");
+ name = json_object_get (m, "name");
if (json_is_string (name) &&
STREQ (json_string_value (name), "locking"))
return 1;
--
2.21.0

View File

@ -0,0 +1,342 @@
From d330b210b7d62ccd9f73909215251f4ce68cd6c9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Golembiovsk=C3=BD?= <tgolembi@redhat.com>
Date: Thu, 22 Feb 2018 11:41:07 +0100
Subject: [PATCH] v2v: ovf: Create OVF more aligned with the standard
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
For historical reasons the OVF used in RHV export domain contains some
deviations from the OVF standard. The format used in -o rhv has to
remain fixed but for -o vdsm and we could produce much nicer OVF. This
patch serves as a preparatory step to this.
The main reason for creating different OVF is that it can be used to
create VM by oVirt REST API. The RHV export domain flavor cannot be used
that way.
For now the virt-v2v behavior is unchanged. The modified output will be
enabled in some later patch.
Signed-off-by: Tomáš Golembiovský <tgolembi@redhat.com>
(cherry picked from commit a52ed4b4454396eb13d2cdf5762292bff3104f66)
---
v2v/create_ovf.ml | 152 ++++++++++++++++++++++++++++++++-------------
v2v/create_ovf.mli | 12 +++-
v2v/output_rhv.ml | 3 +-
v2v/output_vdsm.ml | 3 +-
4 files changed, 121 insertions(+), 49 deletions(-)
diff --git a/v2v/create_ovf.ml b/v2v/create_ovf.ml
index e9d569dc1..0ec0a088c 100644
--- a/v2v/create_ovf.ml
+++ b/v2v/create_ovf.ml
@@ -29,6 +29,10 @@ open Types
open Utils
open DOM
+type ovf_flavour =
+ | OVirt
+ | RHVExportStorageDomain
+
(* We set the creation time to be the same for all dates in
* all metadata files. All dates in OVF are UTC.
*)
@@ -295,7 +299,7 @@ let create_meta_files output_alloc sd_uuid image_uuids targets =
(* Create the OVF file. *)
let rec create_ovf source targets guestcaps inspect
- output_alloc sd_uuid image_uuids vol_uuids vm_uuid =
+ output_alloc sd_uuid image_uuids vol_uuids vm_uuid ovf_flavour =
assert (List.length targets = List.length vol_uuids);
let memsize_mb = source.s_memory /^ 1024L /^ 1024L in
@@ -314,12 +318,26 @@ let rec create_ovf source targets guestcaps inspect
] [
Comment generated_by;
e "References" [] [];
- e "Section" ["xsi:type", "ovf:NetworkSection_Type"] [
- e "Info" [] [PCData "List of networks"]
- ];
- e "Section" ["xsi:type", "ovf:DiskSection_Type"] [
- e "Info" [] [PCData "List of Virtual Disks"]
- ];
+ (match ovf_flavour with
+ | OVirt ->
+ e "NetworkSection" [] [
+ e "Info" [] [PCData "List of networks"]
+ ]
+ | RHVExportStorageDomain ->
+ e "Section" ["xsi:type", "ovf:NetworkSection_Type"] [
+ e "Info" [] [PCData "List of networks"]
+ ]
+ );
+ (match ovf_flavour with
+ | OVirt ->
+ e "DiskSection" [] [
+ e "Info" [] [PCData "List of Virtual Disks"]
+ ]
+ | RHVExportStorageDomain ->
+ e "Section" ["xsi:type", "ovf:DiskSection_Type"] [
+ e "Info" [] [PCData "List of Virtual Disks"]
+ ]
+ );
let content_subnodes = ref [
e "Name" [] [PCData source.s_name];
@@ -352,11 +370,20 @@ let rec create_ovf source targets guestcaps inspect
);
List.push_back content_subnodes (
- e "Section" ["ovf:id", vm_uuid; "ovf:required", "false";
- "xsi:type", "ovf:OperatingSystemSection_Type"] [
+ let osinfo_subnodes = [
e "Info" [] [PCData inspect.i_product_name];
e "Description" [] [PCData ostype];
- ]
+ ] in
+ (match ovf_flavour with
+ | OVirt ->
+ e "OperatingSystemSection" ["ovf:id", vm_uuid;
+ "ovf:required", "false"]
+ osinfo_subnodes
+ | RHVExportStorageDomain ->
+ e "Section" ["ovf:id", vm_uuid; "ovf:required", "false";
+ "xsi:type", "ovf:OperatingSystemSection_Type"]
+ osinfo_subnodes
+ )
);
let virtual_hardware_section_items = ref [
@@ -444,24 +471,34 @@ let rec create_ovf source targets guestcaps inspect
);
List.push_back content_subnodes (
- e "Section" ["xsi:type", "ovf:VirtualHardwareSection_Type"]
- !virtual_hardware_section_items
+ match ovf_flavour with
+ | OVirt ->
+ e "VirtualHardwareSection" [] !virtual_hardware_section_items
+ | RHVExportStorageDomain ->
+ e "Section" ["xsi:type", "ovf:VirtualHardwareSection_Type"]
+ !virtual_hardware_section_items
);
- e "Content" ["ovf:id", "out"; "xsi:type", "ovf:VirtualSystem_Type"]
- !content_subnodes
+ (match ovf_flavour with
+ | OVirt ->
+ e "VirtualSystem" ["ovf:id", "out"] !content_subnodes
+ | RHVExportStorageDomain ->
+ e "Content" ["ovf:id", "out"; "xsi:type", "ovf:VirtualSystem_Type"]
+ !content_subnodes
+ )
] in
(* Add disks to the OVF XML. *)
- add_disks targets guestcaps output_alloc sd_uuid image_uuids vol_uuids ovf;
+ add_disks targets guestcaps output_alloc sd_uuid image_uuids vol_uuids
+ ovf_flavour ovf;
(* Old virt-v2v ignored removable media. XXX *)
(* Add networks to the OVF XML. *)
- add_networks source.s_nics guestcaps ovf;
+ add_networks source.s_nics guestcaps ovf_flavour ovf;
(* Add sound card to the OVF XML. *)
- add_sound_card source.s_sound ovf;
+ add_sound_card source.s_sound ovf_flavour ovf;
(* Old virt-v2v didn't really look at the video and display
* metadata, instead just adding a single standard display (see
@@ -481,21 +518,42 @@ let rec create_ovf source targets guestcaps inspect
(* Return the OVF document. *)
ovf
+(* Find appropriate section depending on the OVF flavour being generated.
+ *
+ * For example normal disk section is in node <DiskSection> whereas in case of
+ * RHV export storage domain it is <Section xsi:type="ovf:DiskSection_Type">.
+ *)
+and get_flavoured_section ovf ovf_flavour ovirt_path rhv_path rhv_path_attr =
+ let nodes =
+ match ovf_flavour with
+ | OVirt ->
+ let nodes = path_to_nodes ovf ovirt_path in
+ (match nodes with
+ | [node] -> node
+ | [] | _::_::_ -> assert false)
+ | RHVExportStorageDomain ->
+ let nodes = path_to_nodes ovf rhv_path in
+ try find_node_by_attr nodes rhv_path_attr
+ with Not_found -> assert false
+ in
+ nodes
+
(* This modifies the OVF DOM, adding a section for each disk. *)
-and add_disks targets guestcaps output_alloc sd_uuid image_uuids vol_uuids ovf =
+and add_disks targets guestcaps output_alloc sd_uuid image_uuids vol_uuids
+ ovf_flavour ovf =
let references =
let nodes = path_to_nodes ovf ["ovf:Envelope"; "References"] in
match nodes with
| [] | _::_::_ -> assert false
| [node] -> node in
- let disk_section =
- let sections = path_to_nodes ovf ["ovf:Envelope"; "Section"] in
- try find_node_by_attr sections ("xsi:type", "ovf:DiskSection_Type")
- with Not_found -> assert false in
- let virtualhardware_section =
- let sections = path_to_nodes ovf ["ovf:Envelope"; "Content"; "Section"] in
- try find_node_by_attr sections ("xsi:type", "ovf:VirtualHardwareSection_Type")
- with Not_found -> assert false in
+ let disk_section = get_flavoured_section ovf ovf_flavour
+ ["ovf:Envelope"; "DiskSection"]
+ ["ovf:Envelope"; "Section"]
+ ("xsi:type", "ovf:DiskSection_Type") in
+ let virtualhardware_section = get_flavoured_section ovf ovf_flavour
+ ["ovf:Envelope"; "VirtualSystem"; "VirtualHardwareSection"]
+ ["ovf:Envelope"; "Content"; "Section"]
+ ("xsi:type", "ovf:VirtualHardwareSection_Type") in
(* Iterate over the disks, adding them to the OVF document. *)
List.iteri (
@@ -509,7 +567,12 @@ and add_disks targets guestcaps output_alloc sd_uuid image_uuids vol_uuids ovf =
let is_bootable_drive = i == 0 in
let boot_order = i+1 in
- let fileref = sprintf "%s/%s" image_uuid vol_uuid in
+ let fileref =
+ match ovf_flavour with
+ | OVirt ->
+ vol_uuid
+ | RHVExportStorageDomain ->
+ sprintf "%s/%s" image_uuid vol_uuid in
(* ovf:size and ovf:actual_size fields are integer GBs. If you
* use floating point numbers then RHV will fail to parse them.
@@ -560,7 +623,10 @@ and add_disks targets guestcaps output_alloc sd_uuid image_uuids vol_uuids ovf =
(* Add disk to DiskSection. *)
let disk =
let attrs = ref [
- "ovf:diskId", vol_uuid;
+ "ovf:diskId",
+ (match ovf_flavour with
+ | OVirt -> image_uuid
+ | RHVExportStorageDomain -> vol_uuid);
"ovf:size", Int64.to_string size_gb;
"ovf:capacity", Int64.to_string ov.ov_virtual_size;
"ovf:fileRef", fileref;
@@ -619,15 +685,15 @@ and add_disks targets guestcaps output_alloc sd_uuid image_uuids vol_uuids ovf =
) (List.combine3 targets image_uuids vol_uuids)
(* This modifies the OVF DOM, adding a section for each NIC. *)
-and add_networks nics guestcaps ovf =
- let network_section =
- let sections = path_to_nodes ovf ["ovf:Envelope"; "Section"] in
- try find_node_by_attr sections ("xsi:type", "ovf:NetworkSection_Type")
- with Not_found -> assert false in
- let virtualhardware_section =
- let sections = path_to_nodes ovf ["ovf:Envelope"; "Content"; "Section"] in
- try find_node_by_attr sections ("xsi:type", "ovf:VirtualHardwareSection_Type")
- with Not_found -> assert false in
+and add_networks nics guestcaps ovf_flavour ovf =
+ let network_section = get_flavoured_section ovf ovf_flavour
+ ["ovf:Envelope"; "NetworkSection"]
+ ["ovf:Envelope"; "Section"]
+ ("xsi:type", "ovf:NetworkSection_Type") in
+ let virtualhardware_section = get_flavoured_section ovf ovf_flavour
+ ["ovf:Envelope"; "VirtualSystem"; "VirtualHardwareSection"]
+ ["ovf:Envelope"; "Content"; "Section"]
+ ("xsi:type", "ovf:VirtualHardwareSection_Type") in
(* Iterate over the NICs, adding them to the OVF document. *)
List.iteri (
@@ -675,7 +741,7 @@ and add_networks nics guestcaps ovf =
) nics
(* This modifies the OVF DOM, adding a sound card, if oVirt can emulate it. *)
-and add_sound_card sound ovf =
+and add_sound_card sound ovf_flavour ovf =
let device =
match sound with
| None -> None
@@ -688,12 +754,10 @@ and add_sound_card sound ovf =
match device with
| Some device ->
- let virtualhardware_section =
- let sections =
- path_to_nodes ovf ["ovf:Envelope"; "Content"; "Section"] in
- try find_node_by_attr sections
- ("xsi:type", "ovf:VirtualHardwareSection_Type")
- with Not_found -> assert false in
+ let virtualhardware_section = get_flavoured_section ovf ovf_flavour
+ ["ovf:Envelope"; "VirtualSystem"; "VirtualHardwareSection"]
+ ["ovf:Envelope"; "Content"; "Section"]
+ ("xsi:type", "ovf:VirtualHardwareSection_Type") in
let item =
e "Item" [] [
diff --git a/v2v/create_ovf.mli b/v2v/create_ovf.mli
index 07e8af6a0..8a8c7dd12 100644
--- a/v2v/create_ovf.mli
+++ b/v2v/create_ovf.mli
@@ -16,16 +16,22 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*)
+type ovf_flavour =
+ | OVirt
+ | RHVExportStorageDomain
+
(** Create OVF and related files for RHV.
- The format is described in
- http://www.ovirt.org/images/8/86/Ovirt_ovf_format.odt
+ The format for RHV export storage domain is described in:
+ http://resources.ovirt.org/old-site-files/Ovirt_ovf_format.odt
+
+ The format understood by oVirt has no known documentation.
OVF isn't a real standard, so it's likely that if we ever had to
create OVF for another target management system then we would need
to heavily modify or even duplicate this code. *)
-val create_ovf : Types.source -> Types.target list -> Types.guestcaps -> Types.inspect -> Types.output_allocation -> string -> string list -> string list -> string -> DOM.doc
+val create_ovf : Types.source -> Types.target list -> Types.guestcaps -> Types.inspect -> Types.output_allocation -> string -> string list -> string list -> string -> ovf_flavour -> DOM.doc
(** Create the OVF file.
Actually a {!DOM} document is created, not a file. It can be written
diff --git a/v2v/output_rhv.ml b/v2v/output_rhv.ml
index 0b732e4cf..5260ab030 100644
--- a/v2v/output_rhv.ml
+++ b/v2v/output_rhv.ml
@@ -275,7 +275,8 @@ object
(* Create the metadata. *)
let ovf = Create_ovf.create_ovf source targets guestcaps inspect
- output_alloc esd_uuid image_uuids vol_uuids vm_uuid in
+ output_alloc esd_uuid image_uuids vol_uuids vm_uuid
+ Create_ovf.RHVExportStorageDomain in
(* Write it to the metadata file. *)
let dir = esd_mp // esd_uuid // "master" // "vms" // vm_uuid in
diff --git a/v2v/output_vdsm.ml b/v2v/output_vdsm.ml
index c5e904ba1..ce286d327 100644
--- a/v2v/output_vdsm.ml
+++ b/v2v/output_vdsm.ml
@@ -175,7 +175,8 @@ object
output_alloc dd_uuid
vdsm_options.image_uuids
vdsm_options.vol_uuids
- vdsm_options.vm_uuid in
+ vdsm_options.vm_uuid
+ Create_ovf.RHVExportStorageDomain in
(* Write it to the metadata file. *)
let file = vdsm_options.ovf_output // vdsm_options.vm_uuid ^ ".ovf" in
--
2.21.0

View File

@ -0,0 +1,213 @@
From 14cfe80643a7df4ddf412aebdf39543344c1cf6e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Golembiovsk=C3=BD?= <tgolembi@redhat.com>
Date: Thu, 22 Feb 2018 11:41:08 +0100
Subject: [PATCH] v2v: vdsm: add --vdsm-fixed-ovf option
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Add option for -o vdsm that enables output of the modified OVF. oVirt
engine should already be able to consume the OVF, but let's not take any
chances and enable it only by command line argument. It can be made
default later when it receives proper testing.
Signed-off-by: Tomáš Golembiovský <tgolembi@redhat.com>
(cherry picked from commit 285014b290507865fd2020e44ea453af0262b624)
---
v2v/cmdline.ml | 10 ++++++++++
v2v/create_ovf.ml | 7 +++++++
v2v/create_ovf.mli | 9 +++++++++
v2v/output_vdsm.ml | 9 +++++++--
v2v/output_vdsm.mli | 1 +
v2v/test-v2v-o-vdsm-options.sh | 3 ++-
v2v/virt-v2v.pod | 20 ++++++++++++++++++++
7 files changed, 56 insertions(+), 3 deletions(-)
diff --git a/v2v/cmdline.ml b/v2v/cmdline.ml
index d88d0a579..75909ee77 100644
--- a/v2v/cmdline.ml
+++ b/v2v/cmdline.ml
@@ -79,6 +79,11 @@ let parse_cmdline () =
let vdsm_compat = ref "0.10" in
let set_vdsm_compat s = vdsm_compat := s in
+ let vdsm_ovf_flavour = ref Create_ovf.RHVExportStorageDomain in
+ let ovf_flavours_str = String.concat "|" Create_ovf.ovf_flavours in
+ let set_vdsm_ovf_flavour arg =
+ vdsm_ovf_flavour := Create_ovf.ovf_flavour_of_string arg in
+
let set_string_option_once optname optref arg =
match !optref with
| Some _ ->
@@ -251,6 +256,8 @@ let parse_cmdline () =
s_"Output VM UUID";
[ L"vdsm-ovf-output" ], Getopt.String ("-", set_string_option_once "--vdsm-ovf-output" vdsm_ovf_output),
s_"Output OVF file";
+ [ L"vdsm-ovf-flavour" ], Getopt.Symbol (ovf_flavours_str, Create_ovf.ovf_flavours, set_vdsm_ovf_flavour),
+ s_"Set the type of generated OVF (default rhvexp)";
[ L"vmtype" ], Getopt.String ("-", vmtype_warning),
s_"Ignored for backwards compatibility";
] in
@@ -327,6 +334,7 @@ read the man page virt-v2v(1).
let vdsm_vol_uuids = List.rev !vdsm_vol_uuids in
let vdsm_vm_uuid = !vdsm_vm_uuid in
let vdsm_ovf_output = Option.default "." !vdsm_ovf_output in
+ let vdsm_ovf_flavour = !vdsm_ovf_flavour in
(* No arguments and machine-readable mode? Print out some facts
* about what this binary supports.
@@ -343,6 +351,7 @@ read the man page virt-v2v(1).
List.iter (printf "input:%s\n") (Modules_list.input_modules ());
List.iter (printf "output:%s\n") (Modules_list.output_modules ());
List.iter (printf "convert:%s\n") (Modules_list.convert_modules ());
+ List.iter (printf "ovf:%s\n") Create_ovf.ovf_flavours;
exit 0
);
@@ -542,6 +551,7 @@ read the man page virt-v2v(1).
vm_uuid = vdsm_vm_uuid;
ovf_output = vdsm_ovf_output;
compat = vdsm_compat;
+ ovf_flavour = vdsm_ovf_flavour;
} in
Output_vdsm.output_vdsm os vdsm_options output_alloc,
output_format, output_alloc in
diff --git a/v2v/create_ovf.ml b/v2v/create_ovf.ml
index 0ec0a088c..d0735afce 100644
--- a/v2v/create_ovf.ml
+++ b/v2v/create_ovf.ml
@@ -33,6 +33,13 @@ type ovf_flavour =
| OVirt
| RHVExportStorageDomain
+let ovf_flavours = ["ovirt"; "rhvexp"]
+
+let ovf_flavour_of_string = function
+ | "ovirt" -> OVirt
+ | "rhvexp" -> RHVExportStorageDomain
+ | flav -> invalid_arg flav
+
(* We set the creation time to be the same for all dates in
* all metadata files. All dates in OVF are UTC.
*)
diff --git a/v2v/create_ovf.mli b/v2v/create_ovf.mli
index 8a8c7dd12..2d80660e3 100644
--- a/v2v/create_ovf.mli
+++ b/v2v/create_ovf.mli
@@ -20,6 +20,15 @@ type ovf_flavour =
| OVirt
| RHVExportStorageDomain
+(** The string representation of available OVF flavours. *)
+val ovf_flavours : string list
+
+(** Convert from a string to the corresponding OVF flavour.
+
+ Throw [Invalid_argument] if the string does not match any
+ valid flavour. *)
+val ovf_flavour_of_string : string -> ovf_flavour
+
(** Create OVF and related files for RHV.
The format for RHV export storage domain is described in:
diff --git a/v2v/output_vdsm.ml b/v2v/output_vdsm.ml
index ce286d327..b76a2e930 100644
--- a/v2v/output_vdsm.ml
+++ b/v2v/output_vdsm.ml
@@ -32,6 +32,7 @@ type vdsm_options = {
vm_uuid : string;
ovf_output : string;
compat : string;
+ ovf_flavour : Create_ovf.ovf_flavour;
}
class output_vdsm os vdsm_options output_alloc =
@@ -39,7 +40,7 @@ object
inherit output
method as_options =
- sprintf "-o vdsm -os %s%s%s --vdsm-vm-uuid %s --vdsm-ovf-output %s%s" os
+ sprintf "-o vdsm -os %s%s%s --vdsm-vm-uuid %s --vdsm-ovf-output %s%s%s" os
(String.concat ""
(List.map (sprintf " --vdsm-image-uuid %s") vdsm_options.image_uuids))
(String.concat ""
@@ -49,6 +50,10 @@ object
(match vdsm_options.compat with
| "0.10" -> "" (* currently this is the default, so don't print it *)
| s -> sprintf " --vdsm-compat=%s" s)
+ (match vdsm_options.ovf_flavour with
+ | Create_ovf.OVirt -> "--vdsm-ovf-flavour=ovf"
+ (* currently this is the default, so don't print it *)
+ | Create_ovf.RHVExportStorageDomain -> "")
method supported_firmware = [ TargetBIOS ]
@@ -176,7 +181,7 @@ object
vdsm_options.image_uuids
vdsm_options.vol_uuids
vdsm_options.vm_uuid
- Create_ovf.RHVExportStorageDomain in
+ vdsm_options.ovf_flavour in
(* Write it to the metadata file. *)
let file = vdsm_options.ovf_output // vdsm_options.vm_uuid ^ ".ovf" in
diff --git a/v2v/output_vdsm.mli b/v2v/output_vdsm.mli
index 401a71ec4..6ed684638 100644
--- a/v2v/output_vdsm.mli
+++ b/v2v/output_vdsm.mli
@@ -24,6 +24,7 @@ type vdsm_options = {
vm_uuid : string; (* --vdsm-vm-uuid *)
ovf_output : string; (* --vdsm-ovf-output *)
compat : string; (* --vdsm-compat=0.10|1.1 *)
+ ovf_flavour : Create_ovf.ovf_flavour;
}
(** Miscellaneous extra command line parameters used by VDSM. *)
diff --git a/v2v/test-v2v-o-vdsm-options.sh b/v2v/test-v2v-o-vdsm-options.sh
index 753efc4e7..4ad5d4aad 100755
--- a/v2v/test-v2v-o-vdsm-options.sh
+++ b/v2v/test-v2v-o-vdsm-options.sh
@@ -55,7 +55,8 @@ $VG virt-v2v --debug-gc \
--vdsm-vol-uuid VOL \
--vdsm-vm-uuid VM \
--vdsm-ovf-output $d/12345678-1234-1234-1234-123456789abc/master/vms/VM \
- --vdsm-compat=1.1
+ --vdsm-compat=1.1 \
+ --vdsm-ovf-flavour=ovirt
# Test the OVF metadata was created.
test -f $d/12345678-1234-1234-1234-123456789abc/master/vms/VM/VM.ovf
diff --git a/v2v/virt-v2v.pod b/v2v/virt-v2v.pod
index cced114f3..0ea5fa97f 100644
--- a/v2v/virt-v2v.pod
+++ b/v2v/virt-v2v.pod
@@ -759,6 +759,26 @@ hex digit can be C<0-9> or C<a-f>), conforming to S<OSF DCE 1.1>.
These options can only be used with I<-o vdsm>.
+=item B<--vdsm-ovf-flavour> flavour
+
+This option controls the format of the OVF generated at the end of conversion.
+Currently there are two possible flavours:
+
+=over 4
+
+=item rhevexp
+
+The OVF format used in RHV export storage domain.
+
+=item ovirt
+
+The OVF format understood by oVirt REST API.
+
+=back
+
+For backward compatibility the default is I<rhevexp>, but this may change in
+the future.
+
=item B<-v>
=item B<--verbose>
--
2.21.0

View File

@ -0,0 +1,124 @@
From 00ed208050cdb2178ac58878cb126504ebc7b311 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Thu, 22 Feb 2018 14:22:12 +0000
Subject: [PATCH] v2v: OVF: Code formatting.
Updates commit a52ed4b4454396eb13d2cdf5762292bff3104f66
("v2v: ovf: Create OVF more aligned with the standard") with some
small code refactoring and formatting.
(cherry picked from commit 9e83f3a2ccef4e91b0b3275b712df8b16e233cff)
---
v2v/create_ovf.ml | 73 ++++++++++++++++++++++++++---------------------
1 file changed, 41 insertions(+), 32 deletions(-)
diff --git a/v2v/create_ovf.ml b/v2v/create_ovf.ml
index d0735afce..0e07afea8 100644
--- a/v2v/create_ovf.ml
+++ b/v2v/create_ovf.ml
@@ -530,20 +530,16 @@ let rec create_ovf source targets guestcaps inspect
* For example normal disk section is in node <DiskSection> whereas in case of
* RHV export storage domain it is <Section xsi:type="ovf:DiskSection_Type">.
*)
-and get_flavoured_section ovf ovf_flavour ovirt_path rhv_path rhv_path_attr =
- let nodes =
- match ovf_flavour with
- | OVirt ->
- let nodes = path_to_nodes ovf ovirt_path in
- (match nodes with
+and get_flavoured_section ovf ovirt_path rhv_path rhv_path_attr = function
+ | OVirt ->
+ let nodes = path_to_nodes ovf ovirt_path in
+ (match nodes with
| [node] -> node
| [] | _::_::_ -> assert false)
- | RHVExportStorageDomain ->
- let nodes = path_to_nodes ovf rhv_path in
- try find_node_by_attr nodes rhv_path_attr
- with Not_found -> assert false
- in
- nodes
+ | RHVExportStorageDomain ->
+ let nodes = path_to_nodes ovf rhv_path in
+ try find_node_by_attr nodes rhv_path_attr
+ with Not_found -> assert false
(* This modifies the OVF DOM, adding a section for each disk. *)
and add_disks targets guestcaps output_alloc sd_uuid image_uuids vol_uuids
@@ -553,14 +549,19 @@ and add_disks targets guestcaps output_alloc sd_uuid image_uuids vol_uuids
match nodes with
| [] | _::_::_ -> assert false
| [node] -> node in
- let disk_section = get_flavoured_section ovf ovf_flavour
- ["ovf:Envelope"; "DiskSection"]
- ["ovf:Envelope"; "Section"]
- ("xsi:type", "ovf:DiskSection_Type") in
- let virtualhardware_section = get_flavoured_section ovf ovf_flavour
- ["ovf:Envelope"; "VirtualSystem"; "VirtualHardwareSection"]
- ["ovf:Envelope"; "Content"; "Section"]
- ("xsi:type", "ovf:VirtualHardwareSection_Type") in
+ let disk_section =
+ get_flavoured_section ovf
+ ["ovf:Envelope"; "DiskSection"]
+ ["ovf:Envelope"; "Section"]
+ ("xsi:type", "ovf:DiskSection_Type")
+ ovf_flavour in
+ let virtualhardware_section =
+ get_flavoured_section ovf
+ ["ovf:Envelope"; "VirtualSystem";
+ "VirtualHardwareSection"]
+ ["ovf:Envelope"; "Content"; "Section"]
+ ("xsi:type", "ovf:VirtualHardwareSection_Type")
+ ovf_flavour in
(* Iterate over the disks, adding them to the OVF document. *)
List.iteri (
@@ -693,14 +694,19 @@ and add_disks targets guestcaps output_alloc sd_uuid image_uuids vol_uuids
(* This modifies the OVF DOM, adding a section for each NIC. *)
and add_networks nics guestcaps ovf_flavour ovf =
- let network_section = get_flavoured_section ovf ovf_flavour
- ["ovf:Envelope"; "NetworkSection"]
- ["ovf:Envelope"; "Section"]
- ("xsi:type", "ovf:NetworkSection_Type") in
- let virtualhardware_section = get_flavoured_section ovf ovf_flavour
- ["ovf:Envelope"; "VirtualSystem"; "VirtualHardwareSection"]
- ["ovf:Envelope"; "Content"; "Section"]
- ("xsi:type", "ovf:VirtualHardwareSection_Type") in
+ let network_section =
+ get_flavoured_section ovf
+ ["ovf:Envelope"; "NetworkSection"]
+ ["ovf:Envelope"; "Section"]
+ ("xsi:type", "ovf:NetworkSection_Type")
+ ovf_flavour in
+ let virtualhardware_section =
+ get_flavoured_section ovf
+ ["ovf:Envelope"; "VirtualSystem";
+ "VirtualHardwareSection"]
+ ["ovf:Envelope"; "Content"; "Section"]
+ ("xsi:type", "ovf:VirtualHardwareSection_Type")
+ ovf_flavour in
(* Iterate over the NICs, adding them to the OVF document. *)
List.iteri (
@@ -761,10 +767,13 @@ and add_sound_card sound ovf_flavour ovf =
match device with
| Some device ->
- let virtualhardware_section = get_flavoured_section ovf ovf_flavour
- ["ovf:Envelope"; "VirtualSystem"; "VirtualHardwareSection"]
- ["ovf:Envelope"; "Content"; "Section"]
- ("xsi:type", "ovf:VirtualHardwareSection_Type") in
+ let virtualhardware_section =
+ get_flavoured_section ovf
+ ["ovf:Envelope"; "VirtualSystem";
+ "VirtualHardwareSection"]
+ ["ovf:Envelope"; "Content"; "Section"]
+ ("xsi:type", "ovf:VirtualHardwareSection_Type")
+ ovf_flavour in
let item =
e "Item" [] [
--
2.21.0

View File

@ -0,0 +1,127 @@
From 83b5f589231da2ab6d04680f42c37dc6058cbe6e Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 20 Feb 2018 15:21:48 +0000
Subject: [PATCH] v2v: DOM: Add doc_to_string function.
Convert a document to an in-memory string.
(cherry picked from commit 802c8635cc2537a7d4b7af8981c670e2fdbb2675)
---
v2v/DOM.ml | 61 +++++++++++++++++++++++++++++++++--------------------
v2v/DOM.mli | 3 +++
2 files changed, 41 insertions(+), 23 deletions(-)
diff --git a/v2v/DOM.ml b/v2v/DOM.ml
index 7f66e0920..8b106224b 100644
--- a/v2v/DOM.ml
+++ b/v2v/DOM.ml
@@ -46,43 +46,48 @@ let e name attrs children =
* we will be writing, ie. libvirt XML and OVF metadata, where
* whitespace is generally not significant, but readability is useful.
*)
-let rec node_to_chan ?(indent = 0) chan = function
- | PCData str -> output_string chan (xml_quote_pcdata str)
+let rec node_to_buf ?(indent = 0) buf = function
+ | PCData str ->
+ Buffer.add_string buf (xml_quote_pcdata str)
| Comment str ->
- output_spaces chan indent;
- fprintf chan "<!-- %s -->" (xml_quote_pcdata str)
- | Element e -> element_to_chan ~indent chan e
-and element_to_chan ?(indent = 0) chan
+ buffer_add_spaces buf indent;
+ bprintf buf "<!-- %s -->" (xml_quote_pcdata str)
+ | Element e ->
+ element_to_buf ~indent buf e
+and element_to_buf ?(indent = 0) buf
{ e_name = name; e_attrs = attrs; e_children = children } =
- output_spaces chan indent;
- fprintf chan "<%s" name;
- List.iter (fun (n, v) -> fprintf chan " %s='%s'" n (xml_quote_attr v)) attrs;
+ buffer_add_spaces buf indent;
+ bprintf buf "<%s" name;
+ List.iter (fun (n, v) -> bprintf buf " %s='%s'" n (xml_quote_attr v)) attrs;
if children <> [] then (
- output_string chan ">";
+ Buffer.add_string buf ">";
let last_child_was_element = ref false in
List.iter (
function
| Element _ as child ->
last_child_was_element := true;
- output_char chan '\n';
- node_to_chan ~indent:(indent+2) chan child;
+ Buffer.add_char buf '\n';
+ node_to_buf ~indent:(indent+2) buf child;
| PCData _ as child ->