import libguestfs-1.38.4-11.1.module+el8.0.0+4084+cceb9f44
This commit is contained in:
commit
7d6753cdd1
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal 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
4
.libguestfs.metadata
Normal 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
|
973
SOURCES/0001-Switch-from-YAJL-to-Jansson.patch
Normal file
973
SOURCES/0001-Switch-from-YAJL-to-Jansson.patch
Normal 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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
213
SOURCES/0004-v2v-vdsm-add-vdsm-fixed-ovf-option.patch
Normal file
213
SOURCES/0004-v2v-vdsm-add-vdsm-fixed-ovf-option.patch
Normal 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
|
||||
|
124
SOURCES/0005-v2v-OVF-Code-formatting.patch
Normal file
124
SOURCES/0005-v2v-OVF-Code-formatting.patch
Normal 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
|
||||
|
127
SOURCES/0006-v2v-DOM-Add-doc_to_string-function.patch
Normal file
127
SOURCES/0006-v2v-DOM-Add-doc_to_string-function.patch
Normal 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 ->
|
||||