diff --git a/.gitignore b/.gitignore index 2a668bd..10fd57f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -SOURCES/RHEV-Application-Provisioning-Tool.exe_4.43-3 -SOURCES/libguestfs-1.38.4.tar.gz +SOURCES/RHEV-Application-Provisioning-Tool.exe_4.43-5 +SOURCES/libguestfs-1.40.2.tar.gz SOURCES/libguestfs.keyring SOURCES/rhsrvany.exe diff --git a/.libguestfs.metadata b/.libguestfs.metadata index 2cd3223..355ef3d 100644 --- a/.libguestfs.metadata +++ b/.libguestfs.metadata @@ -1,4 +1,4 @@ -ac8722917cc31c36836e241bd7a4beb5f8a8b0c8 SOURCES/RHEV-Application-Provisioning-Tool.exe_4.43-3 -15c8f487ee163374cb7be9436fb1bb697cef7d9e SOURCES/libguestfs-1.38.4.tar.gz +130adbc011dc0af736465b813c2b22a600c128c1 SOURCES/RHEV-Application-Provisioning-Tool.exe_4.43-5 +45755f0f73b503790974484053ff482f32665b13 SOURCES/libguestfs-1.40.2.tar.gz 1bbc40f501a7fef9eef2a39b701a71aee2fea7c4 SOURCES/libguestfs.keyring 2bd96e478fc004cd323b5bd754c856641877dac6 SOURCES/rhsrvany.exe diff --git a/SOURCES/0001-Switch-from-YAJL-to-Jansson.patch b/SOURCES/0001-Switch-from-YAJL-to-Jansson.patch deleted file mode 100644 index e773fea..0000000 --- a/SOURCES/0001-Switch-from-YAJL-to-Jansson.patch +++ /dev/null @@ -1,974 +0,0 @@ -From 21f0a22072f0543c416c440665bcf75ae09e6233 Mon Sep 17 00:00:00 2001 -From: Pino Toscano -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 | 115 ++++++++++++---------------- - 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, 169 insertions(+), 231 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 - #include - --#include -+#include - - #include - #include - --/* GCC can't work out that the YAJL_IS_ test is sufficient to -- * ensure that YAJL_GET_ 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 - #include - --#include -+#include - - #include "daemon.h" - #include "actions.h" - #include "optgroups.h" - --/* GCC can't work out that the YAJL_IS_ test is sufficient to -- * ensure that YAJL_GET_ 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; -+ -+ node = json_object_get (tree, key); -+ if (node == NULL) - 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); -- -- 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. - - I. - --=item yajl E 2.0.4 -+=item Jansson - - I. - -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 - #endif - --#include -+#include - - #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__, input_copy); -+ debug (g, "%s: qemu-img info JSON output:\n%.*s\n", __func__, (int) len, input); - -- *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 - --#include -+#include - - #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_ test is sufficient to -- * ensure that YAJL_GET_ 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 - diff --git a/SOURCES/0001-common-mlpcre-add-offset-flag-for-PCRE.matches.patch b/SOURCES/0001-common-mlpcre-add-offset-flag-for-PCRE.matches.patch new file mode 100644 index 0000000..3edbb8d --- /dev/null +++ b/SOURCES/0001-common-mlpcre-add-offset-flag-for-PCRE.matches.patch @@ -0,0 +1,126 @@ +From 6e0dbefde3ddb0711e2b0961ee913084dc5e6a41 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Tue, 19 Feb 2019 10:50:01 +0100 +Subject: [PATCH] common/mlpcre: add offset flag for PCRE.matches + +This way it is possible to change where the matching start, instead of +always assuming it is the beginning. + +(cherry picked from commit 0ed2e5c14a302d15fd3b75ee2c1cb808a06cb746) +--- + common/mlpcre/PCRE.ml | 2 +- + common/mlpcre/PCRE.mli | 5 ++++- + common/mlpcre/pcre-c.c | 16 +++++++++++++--- + common/mlpcre/pcre_tests.ml | 11 ++++++++--- + 4 files changed, 26 insertions(+), 8 deletions(-) + +diff --git a/common/mlpcre/PCRE.ml b/common/mlpcre/PCRE.ml +index b054928f9..33074af1c 100644 +--- a/common/mlpcre/PCRE.ml ++++ b/common/mlpcre/PCRE.ml +@@ -23,7 +23,7 @@ exception Error of string * int + type regexp + + external compile : ?anchored:bool -> ?caseless:bool -> ?dotall:bool -> ?extended:bool -> ?multiline:bool -> string -> regexp = "guestfs_int_pcre_compile_byte" "guestfs_int_pcre_compile" +-external matches : regexp -> string -> bool = "guestfs_int_pcre_matches" ++external matches : ?offset:int -> regexp -> string -> bool = "guestfs_int_pcre_matches" + external sub : int -> string = "guestfs_int_pcre_sub" + external subi : int -> int * int = "guestfs_int_pcre_subi" + +diff --git a/common/mlpcre/PCRE.mli b/common/mlpcre/PCRE.mli +index eacb6fd90..e10d512fc 100644 +--- a/common/mlpcre/PCRE.mli ++++ b/common/mlpcre/PCRE.mli +@@ -62,7 +62,7 @@ val compile : ?anchored:bool -> ?caseless:bool -> ?dotall:bool -> ?extended:bool + See pcreapi(3) for details of what they do. + All flags default to false. *) + +-val matches : regexp -> string -> bool ++val matches : ?offset:int -> regexp -> string -> bool + (** Test whether the regular expression matches the string. This + returns true if the regexp matches or false otherwise. + +@@ -71,6 +71,9 @@ val matches : regexp -> string -> bool + or the thread/program exits. You can call {!sub} to return + these substrings. + ++ The [?offset] flag is used to change the start of the search, ++ which by default is at the beginning of the string (position 0). ++ + This can raise {!Error} if PCRE returns an error. *) + + val sub : int -> string +diff --git a/common/mlpcre/pcre-c.c b/common/mlpcre/pcre-c.c +index 0762a8341..be054a004 100644 +--- a/common/mlpcre/pcre-c.c ++++ b/common/mlpcre/pcre-c.c +@@ -121,6 +121,15 @@ is_Some_true (value v) + Bool_val (Field (v, 0)) /* Some true */; + } + ++static int ++Optint_val (value intv, int defval) ++{ ++ if (intv == Val_int (0)) /* None */ ++ return defval; ++ else /* Some int */ ++ return Int_val (Field (intv, 0)); ++} ++ + value + guestfs_int_pcre_compile (value anchoredv, value caselessv, value dotallv, + value extendedv, value multilinev, +@@ -165,9 +174,9 @@ guestfs_int_pcre_compile_byte (value *argv, int argn) + } + + value +-guestfs_int_pcre_matches (value rev, value strv) ++guestfs_int_pcre_matches (value offsetv, value rev, value strv) + { +- CAMLparam2 (rev, strv); ++ CAMLparam3 (offsetv, rev, strv); + pcre *re = Regexp_val (rev); + struct last_match *m, *oldm; + size_t len = caml_string_length (strv); +@@ -205,7 +214,8 @@ guestfs_int_pcre_matches (value rev, value strv) + caml_raise_out_of_memory (); + } + +- m->r = pcre_exec (re, NULL, m->subject, len, 0, 0, m->vec, veclen); ++ m->r = pcre_exec (re, NULL, m->subject, len, Optint_val (offsetv, 0), 0, ++ m->vec, veclen); + if (m->r < 0 && m->r != PCRE_ERROR_NOMATCH) { + int ret = m->r; + free_last_match (m); +diff --git a/common/mlpcre/pcre_tests.ml b/common/mlpcre/pcre_tests.ml +index 346019c40..3e5981107 100644 +--- a/common/mlpcre/pcre_tests.ml ++++ b/common/mlpcre/pcre_tests.ml +@@ -30,9 +30,9 @@ let compile ?(anchored = false) ?(caseless = false) + patt; + PCRE.compile ~anchored ~caseless ~dotall ~extended ~multiline patt + +-let matches re str = +- eprintf "PCRE.matches %s ->%!" str; +- let r = PCRE.matches re str in ++let matches ?(offset = 0) re str = ++ eprintf "PCRE.matches %s, %d ->%!" str offset; ++ let r = PCRE.matches ~offset re str in + eprintf " %b\n%!" r; + r + +@@ -103,6 +103,11 @@ let () = + assert (subi 1 = (2, 3)); + assert (subi 2 = (3, 3)); + ++ assert (matches ~offset:5 re0 "aaabcabc" = true); ++ assert (sub 0 = "ab"); ++ ++ assert (matches ~offset:5 re0 "aaabcbaac" = false); ++ + assert (replace re0 "dd" "abcabcaabccca" = "ddcabcaabccca"); + assert (replace ~global:true re0 "dd" "abcabcaabccca" = "ddcddcddccca"); + +-- +2.25.4 + diff --git a/SOURCES/0002-qemu-Fix-transcription-error-in-conversion-of-yajl-t.patch b/SOURCES/0002-qemu-Fix-transcription-error-in-conversion-of-yajl-t.patch deleted file mode 100644 index e079e1a..0000000 --- a/SOURCES/0002-qemu-Fix-transcription-error-in-conversion-of-yajl-t.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 898e6c1e39deb130566220a11a2eaf2dcb2cb733 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -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 - diff --git a/SOURCES/0002-v2v-add-Var_expander.patch b/SOURCES/0002-v2v-add-Var_expander.patch new file mode 100644 index 0000000..219a332 --- /dev/null +++ b/SOURCES/0002-v2v-add-Var_expander.patch @@ -0,0 +1,415 @@ +From a98136d6ee36df15a226f853d47bd803a7a25329 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Tue, 19 Feb 2019 14:54:31 +0100 +Subject: [PATCH] v2v: add Var_expander + +This helper module provides a facility to replace %{FOO}-like variables +in text strings with user-provided content. + +(cherry picked from commit a27748d7000f417c16045967497208d275a09ce8) +--- + .gitignore | 1 + + v2v/Makefile.am | 32 ++++++++++- + v2v/dummy.c | 2 + + v2v/var_expander.ml | 72 ++++++++++++++++++++++++ + v2v/var_expander.mli | 82 +++++++++++++++++++++++++++ + v2v/var_expander_tests.ml | 113 ++++++++++++++++++++++++++++++++++++++ + 6 files changed, 300 insertions(+), 2 deletions(-) + create mode 100644 v2v/dummy.c + create mode 100644 v2v/var_expander.ml + create mode 100644 v2v/var_expander.mli + create mode 100644 v2v/var_expander_tests.ml + +diff --git a/.gitignore b/.gitignore +index 637bf7765..f2efcdde2 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -693,6 +693,7 @@ Makefile.in + /v2v/uefi.ml + /v2v/uefi.mli + /v2v/v2v_unit_tests ++/v2v/var_expander_tests + /v2v/virt-v2v + /v2v/virt-v2v.1 + /v2v/virt-v2v-copy-to-local +diff --git a/v2v/Makefile.am b/v2v/Makefile.am +index 2312812fb..f196be81d 100644 +--- a/v2v/Makefile.am ++++ b/v2v/Makefile.am +@@ -98,6 +98,7 @@ SOURCES_MLI = \ + utils.mli \ + v2v.mli \ + vCenter.mli \ ++ var_expander.mli \ + windows.mli \ + windows_virtio.mli + +@@ -106,6 +107,7 @@ SOURCES_ML = \ + types.ml \ + uefi.ml \ + utils.ml \ ++ var_expander.ml \ + python_script.ml \ + name_from_disk.ml \ + vCenter.ml \ +@@ -442,7 +444,7 @@ TESTS += \ + endif + + if HAVE_OCAML_PKG_OUNIT +-TESTS += v2v_unit_tests ++TESTS += v2v_unit_tests var_expander_tests + endif + + if ENABLE_APPLIANCE +@@ -651,7 +653,7 @@ EXTRA_DIST += \ + # Unit tests. + check_PROGRAMS = + if HAVE_OCAML_PKG_OUNIT +-check_PROGRAMS += v2v_unit_tests ++check_PROGRAMS += v2v_unit_tests var_expander_tests + endif + + v2v_unit_tests_BOBJECTS = \ +@@ -671,13 +673,28 @@ v2v_unit_tests_SOURCES = $(virt_v2v_SOURCES) + v2v_unit_tests_CPPFLAGS = $(virt_v2v_CPPFLAGS) + v2v_unit_tests_CFLAGS = $(virt_v2v_CFLAGS) + ++var_expander_tests_BOBJECTS = \ ++ var_expander.cmo \ ++ var_expander_tests.cmo ++var_expander_tests_XOBJECTS = $(var_expander_tests_BOBJECTS:.cmo=.cmx) ++ ++var_expander_tests_SOURCES = dummy.c ++var_expander_tests_CPPFLAGS = $(virt_v2v_CPPFLAGS) ++var_expander_tests_CFLAGS = $(virt_v2v_CFLAGS) ++ + if !HAVE_OCAMLOPT + # Can't call this v2v_unit_tests_OBJECTS because automake gets confused. + v2v_unit_tests_THEOBJECTS = $(v2v_unit_tests_BOBJECTS) + v2v_unit_tests.cmo: OCAMLPACKAGES += -package oUnit ++ ++var_expander_tests_THEOBJECTS = $(var_expander_tests_BOBJECTS) ++var_expander_tests.cmo: OCAMLPACKAGES += -package oUnit + else + v2v_unit_tests_THEOBJECTS = $(v2v_unit_tests_XOBJECTS) + v2v_unit_tests.cmx: OCAMLPACKAGES += -package oUnit ++ ++var_expander_tests_THEOBJECTS = $(var_expander_tests_XOBJECTS) ++var_expander_tests.cmx: OCAMLPACKAGES += -package oUnit + endif + + v2v_unit_tests_DEPENDENCIES = \ +@@ -696,6 +713,17 @@ v2v_unit_tests_LINK = \ + $(OCAMLLINKFLAGS) \ + $(v2v_unit_tests_THEOBJECTS) -o $@ + ++var_expander_tests_DEPENDENCIES = \ ++ $(var_expander_tests_THEOBJECTS) \ ++ ../common/mlpcre/mlpcre.$(MLARCHIVE) \ ++ $(top_srcdir)/ocaml-link.sh ++var_expander_tests_LINK = \ ++ $(top_srcdir)/ocaml-link.sh -cclib '$(OCAMLCLIBS)' -- \ ++ $(OCAMLFIND) $(BEST) $(OCAMLFLAGS) \ ++ $(OCAMLPACKAGES) -package oUnit \ ++ $(OCAMLLINKFLAGS) \ ++ $(var_expander_tests_THEOBJECTS) -o $@ ++ + # Dependencies. + .depend: \ + $(srcdir)/*.mli \ +diff --git a/v2v/dummy.c b/v2v/dummy.c +new file mode 100644 +index 000000000..ebab6198c +--- /dev/null ++++ b/v2v/dummy.c +@@ -0,0 +1,2 @@ ++/* Dummy source, to be used for OCaml-based tools with no C sources. */ ++enum { foo = 1 }; +diff --git a/v2v/var_expander.ml b/v2v/var_expander.ml +new file mode 100644 +index 000000000..24b9bafe3 +--- /dev/null ++++ b/v2v/var_expander.ml +@@ -0,0 +1,72 @@ ++(* virt-v2v ++ * Copyright (C) 2019 Red Hat Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ *) ++ ++open Std_utils ++ ++exception Invalid_variable of string ++ ++let var_re = PCRE.compile "(^|[^%])%{([^}]+)}" ++ ++let check_variable var = ++ String.iter ( ++ function ++ | '0'..'9' ++ | 'a'..'z' ++ | 'A'..'Z' ++ | '_' ++ | '-' -> () ++ | _ -> raise (Invalid_variable var) ++ ) var ++ ++let scan_variables str = ++ let res = ref [] in ++ let offset = ref 0 in ++ while PCRE.matches ~offset:!offset var_re str; do ++ let var = PCRE.sub 2 in ++ check_variable var; ++ let _, end_ = PCRE.subi 0 in ++ List.push_back res var; ++ offset := end_ ++ done; ++ List.remove_duplicates !res ++ ++let replace_fn str fn = ++ let res = ref str in ++ let offset = ref 0 in ++ while PCRE.matches ~offset:!offset var_re !res; do ++ let var = PCRE.sub 2 in ++ check_variable var; ++ let start_, end_ = PCRE.subi 0 in ++ match fn var with ++ | None -> ++ offset := end_ ++ | Some text -> ++ let prefix_len = ++ let prefix_start, prefix_end = PCRE.subi 1 in ++ prefix_end - prefix_start in ++ res := (String.sub !res 0 (start_ + prefix_len)) ^ text ^ (String.sub !res end_ (String.length !res - end_)); ++ offset := start_ + prefix_len + String.length text ++ done; ++ !res ++ ++let replace_list str lst = ++ let fn var = ++ try Some (List.assoc var lst) ++ with Not_found -> None ++ in ++ replace_fn str fn +diff --git a/v2v/var_expander.mli b/v2v/var_expander.mli +new file mode 100644 +index 000000000..80aa33c2c +--- /dev/null ++++ b/v2v/var_expander.mli +@@ -0,0 +1,82 @@ ++(* virt-v2v ++ * Copyright (C) 2019 Red Hat Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ *) ++ ++(** Simple variable expander. ++ ++ This module provides the support to expand variables in strings, ++ specified in the form of [%{name}]. ++ ++ For example: ++ ++{v ++let str = "variable-%{INDEX} in %{INDEX} replaced %{INDEX} times" ++let index = ref 0 ++let fn = function ++ | "INDEX" -> ++ incr index; ++ Some (string_of_int !index) ++ | _ -> None ++in ++let str = Var_expander.replace_fn str fn ++(* now str is "variable-1 in 2 replaced 3 times" *) ++v} ++ ++ The names of variables can contain only ASCII letters (uppercase, ++ and lowercase), digits, underscores, and dashes. ++ ++ The replacement is done in a single pass: this means that if a ++ variable is replaced with the text of a variable, that new text ++ is kept as is in the final output. In practice: ++ ++{v ++let str = "%{VAR}" ++let str = Var_expander.replace_list str [("VAR", "%{VAR}")] ++(* now str is "%{VAR}" *) ++v} ++*) ++ ++exception Invalid_variable of string ++(** Invalid variable name error. ++ ++ In case a variable contains characters not allowed, then this ++ exception with the actual unacceptable variable. *) ++ ++val scan_variables : string -> string list ++(** Scan the pattern string for all the variables available. ++ ++ This can raise {!Invalid_variable} in case there are invalid ++ variable names. *) ++ ++val replace_fn : string -> (string -> string option) -> string ++(** Replaces a string expanding all the variables. ++ ++ The replacement function specify how a variable is replaced; ++ if [None] is returned, then that variable is not replaced. ++ ++ This can raise {!Invalid_variable} in case there are invalid ++ variable names. *) ++ ++val replace_list : string -> (string * string) list -> string ++(** Replaces a string expanding all the variables. ++ ++ The replacement list specify how a variable is replaced; ++ if it is not specified in the list, then that variable is not ++ replaced. ++ ++ This can raise {!Invalid_variable} in case there are invalid ++ variable names. *) +diff --git a/v2v/var_expander_tests.ml b/v2v/var_expander_tests.ml +new file mode 100644 +index 000000000..35b628369 +--- /dev/null ++++ b/v2v/var_expander_tests.ml +@@ -0,0 +1,113 @@ ++(* virt-v2v ++ * Copyright (C) 2019 Red Hat Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ *) ++ ++open Printf ++open OUnit ++ ++open Std_utils ++ ++let assert_equal_string = assert_equal ~printer:identity ++let assert_equal_stringlist = assert_equal ~printer:(fun x -> "(" ^ (String.escaped (String.concat "," x)) ^ ")") ++ ++let replace_none_fn _ = None ++let replace_empty_fn _ = Some "" ++ ++let test_no_replacement () = ++ assert_equal_string "" (Var_expander.replace_fn "" replace_none_fn); ++ assert_equal_string "x" (Var_expander.replace_fn "x" replace_none_fn); ++ assert_equal_string "%{}" (Var_expander.replace_fn "%{}" replace_none_fn); ++ assert_equal_string "%{EMPTY}" (Var_expander.replace_fn "%{EMPTY}" replace_none_fn); ++ assert_equal_string "%{EMPTY} %{no}" (Var_expander.replace_fn "%{EMPTY} %{no}" replace_none_fn); ++ assert_equal_string "a %{EMPTY} b" (Var_expander.replace_fn "a %{EMPTY} b" replace_none_fn); ++ () ++ ++let test_replacements () = ++ assert_equal_string "" (Var_expander.replace_fn "%{EMPTY}" replace_empty_fn); ++ assert_equal_string "x " (Var_expander.replace_fn "x %{EMPTY}" replace_empty_fn); ++ assert_equal_string "xy" (Var_expander.replace_fn "x%{EMPTY}y" replace_empty_fn); ++ assert_equal_string "x<->y" (Var_expander.replace_fn "x%{FOO}y" (function | "FOO" -> Some "<->" | _ -> None)); ++ assert_equal_string "a x b" (Var_expander.replace_fn "a %{FOO} b" (function | "FOO" -> Some "x" | _ -> None)); ++ assert_equal_string "%{FOO} x" (Var_expander.replace_fn "%{FOO} %{BAR}" (function | "BAR" -> Some "x" | _ -> None)); ++ assert_equal_string "%{FOO}" (Var_expander.replace_fn "%{BAR}" (function | "BAR" -> Some "%{FOO}" | _ -> None)); ++ assert_equal_string "%{FOO} x" (Var_expander.replace_fn "%{BAR} %{FOO}" (function | "BAR" -> Some "%{FOO}" | "FOO" -> Some "x" | _ -> None)); ++ begin ++ let str = "%{INDEX}, %{INDEX}, %{INDEX}" in ++ let index = ref 0 in ++ let fn = function ++ | "INDEX" -> ++ incr index; ++ Some (string_of_int !index) ++ | _ -> None ++ in ++ assert_equal_string "1, 2, 3" (Var_expander.replace_fn str fn) ++ end; ++ () ++ ++let test_escape () = ++ assert_equal_string "%%{FOO}" (Var_expander.replace_fn "%%{FOO}" replace_empty_fn); ++ assert_equal_string "x %%{FOO} x" (Var_expander.replace_fn "%{FOO} %%{FOO} %{FOO}" (function | "FOO" -> Some "x" | _ -> None)); ++ () ++ ++let test_list () = ++ assert_equal_string "x %{NONE}" (Var_expander.replace_list "%{FOO} %{NONE}" [("FOO", "x")]); ++ () ++ ++let test_scan_variables () = ++ let assert_invalid_variable var = ++ let str = "%{" ^ var ^ "}" in ++ assert_raises (Var_expander.Invalid_variable var) ++ (fun () -> Var_expander.scan_variables str) ++ in ++ assert_equal_stringlist [] (Var_expander.scan_variables ""); ++ assert_equal_stringlist [] (Var_expander.scan_variables "foo"); ++ assert_equal_stringlist ["FOO"] (Var_expander.scan_variables "%{FOO}"); ++ assert_equal_stringlist ["FOO"; "BAR"] (Var_expander.scan_variables "%{FOO} %{BAR}"); ++ assert_equal_stringlist ["FOO"; "BAR"] (Var_expander.scan_variables "%{FOO} %{BAR} %{FOO}"); ++ assert_equal_stringlist ["FOO"; "BAR"] (Var_expander.scan_variables "%{FOO} %%{ESCAPED} %{BAR}"); ++ assert_invalid_variable "FOO/BAR"; ++ () ++ ++let test_errors () = ++ let assert_invalid_variable var = ++ let str = "%{" ^ var ^ "}" in ++ assert_raises (Var_expander.Invalid_variable var) ++ (fun () -> Var_expander.replace_fn str replace_none_fn) ++ in ++ assert_invalid_variable "FOO/BAR"; ++ assert_invalid_variable "FOO:BAR"; ++ assert_invalid_variable "FOO(BAR"; ++ assert_invalid_variable "FOO)BAR"; ++ assert_invalid_variable "FOO@BAR"; ++ () ++ ++(* Suites declaration. *) ++let suite = ++ TestList ([ ++ "basic" >::: [ ++ "no_replacement" >:: test_no_replacement; ++ "replacements" >:: test_replacements; ++ "escape" >:: test_escape; ++ "list" >:: test_list; ++ "scan_variables" >:: test_scan_variables; ++ "errors" >:: test_errors; ++ ]; ++ ]) ++ ++let () = ++ ignore (run_test_tt_main suite); ++ Printf.fprintf stderr "\n" +-- +2.25.4 + diff --git a/SOURCES/0003-v2v-add-o-json-output-mode.patch b/SOURCES/0003-v2v-add-o-json-output-mode.patch new file mode 100644 index 0000000..21e3c52 --- /dev/null +++ b/SOURCES/0003-v2v-add-o-json-output-mode.patch @@ -0,0 +1,785 @@ +From 480c7169c341fc2f86609a13100c42e10f599b83 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Mon, 25 Feb 2019 13:14:43 +0100 +Subject: [PATCH] v2v: add -o json output mode + +Add a new output mode to virt-v2v: similar to -o local, the written +metadata is a JSON file with the majority of the data that virt-v2v +knowns about (or collects) during the conversion. + +This is meant to be used only when no existing output mode is usable, +and a guest needs to be converted to run on KVM anyway. The user of +this mode is supposed to use all the data in the JSON, as they contain +important details on how even run the guest (e.g. w.r.t. firmware, +drivers of disks/NICs, etc). + +(cherry picked from commit f190e08d85556dac293ef15bfeee38e54471570f) +--- + v2v/Makefile.am | 4 + + v2v/cmdline.ml | 29 +++ + v2v/create_json.ml | 348 ++++++++++++++++++++++++++++++++++ + v2v/create_json.mli | 29 +++ + v2v/output_json.ml | 116 ++++++++++++ + v2v/output_json.mli | 31 +++ + v2v/virt-v2v-output-local.pod | 55 ++++++ + v2v/virt-v2v.pod | 15 +- + 8 files changed, 625 insertions(+), 2 deletions(-) + create mode 100644 v2v/create_json.ml + create mode 100644 v2v/create_json.mli + create mode 100644 v2v/output_json.ml + create mode 100644 v2v/output_json.mli + +diff --git a/v2v/Makefile.am b/v2v/Makefile.am +index f196be81d..53c137fc6 100644 +--- a/v2v/Makefile.am ++++ b/v2v/Makefile.am +@@ -52,6 +52,7 @@ SOURCES_MLI = \ + config.mli \ + convert_linux.mli \ + convert_windows.mli \ ++ create_json.mli \ + create_libvirt_xml.mli \ + create_ovf.mli \ + DOM.mli \ +@@ -75,6 +76,7 @@ SOURCES_MLI = \ + networks.mli \ + openstack_image_properties.mli \ + output_glance.mli \ ++ output_json.mli \ + output_libvirt.mli \ + output_local.mli \ + output_null.mli \ +@@ -117,6 +119,7 @@ SOURCES_ML = \ + parse_ovf_from_ova.ml \ + parse_ova.ml \ + create_ovf.ml \ ++ create_json.ml \ + linux.ml \ + windows.ml \ + windows_virtio.ml \ +@@ -141,6 +144,7 @@ SOURCES_ML = \ + convert_windows.ml \ + output_null.ml \ + output_glance.ml \ ++ output_json.ml \ + output_libvirt.ml \ + output_local.ml \ + output_qemu.ml \ +diff --git a/v2v/cmdline.ml b/v2v/cmdline.ml +index 46f6910d0..4d390f249 100644 +--- a/v2v/cmdline.ml ++++ b/v2v/cmdline.ml +@@ -138,6 +138,7 @@ let parse_cmdline () = + | "glance" -> output_mode := `Glance + | "libvirt" -> output_mode := `Libvirt + | "disk" | "local" -> output_mode := `Local ++ | "json" -> output_mode := `JSON + | "null" -> output_mode := `Null + | "openstack" | "osp" | "rhosp" -> output_mode := `Openstack + | "ovirt" | "rhv" | "rhev" -> output_mode := `RHV +@@ -413,6 +414,17 @@ read the man page virt-v2v(1). + | `RHV -> no_options (); `RHV + | `QEmu -> no_options (); `QEmu + ++ | `JSON -> ++ if is_query then ( ++ Output_json.print_output_options (); ++ exit 0 ++ ) ++ else ( ++ let json_options = ++ Output_json.parse_output_options output_options in ++ `JSON json_options ++ ) ++ + | `Openstack -> + if is_query then ( + Output_openstack.print_output_options (); +@@ -546,6 +558,23 @@ read the man page virt-v2v(1). + Output_libvirt.output_libvirt output_conn output_storage, + output_format, output_alloc + ++ | `JSON json_options -> ++ if output_password <> None then ++ error_option_cannot_be_used_in_output_mode "json" "-op"; ++ if output_conn <> None then ++ error_option_cannot_be_used_in_output_mode "json" "-oc"; ++ let os = ++ match output_storage with ++ | None -> ++ error (f_"-o json: output directory was not specified, use '-os /dir'") ++ | Some d when not (is_directory d) -> ++ error (f_"-os %s: output directory does not exist or is not a directory") d ++ | Some d -> d in ++ if qemu_boot then ++ error_option_cannot_be_used_in_output_mode "json" "--qemu-boot"; ++ Output_json.output_json os json_options, ++ output_format, output_alloc ++ + | `Local -> + if output_password <> None then + error_option_cannot_be_used_in_output_mode "local" "-op"; +diff --git a/v2v/create_json.ml b/v2v/create_json.ml +new file mode 100644 +index 000000000..fdf7b12f5 +--- /dev/null ++++ b/v2v/create_json.ml +@@ -0,0 +1,348 @@ ++(* virt-v2v ++ * Copyright (C) 2019 Red Hat Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ *) ++ ++open Std_utils ++open C_utils ++open Tools_utils ++ ++open Types ++open Utils ++ ++module G = Guestfs ++ ++let json_list_of_string_list = ++ List.map (fun x -> JSON.String x) ++ ++let json_list_of_string_string_list = ++ List.map (fun (x, y) -> x, JSON.String y) ++ ++let push_optional_string lst name = function ++ | None -> () ++ | Some v -> List.push_back lst (name, JSON.String v) ++ ++let push_optional_int lst name = function ++ | None -> () ++ | Some v -> List.push_back lst (name, JSON.Int (Int64.of_int v)) ++ ++let json_unknown_string = function ++ | "unknown" -> JSON.Null ++ | v -> JSON.String v ++ ++let find_target_disk targets { s_disk_id = id } = ++ try List.find (fun t -> t.target_overlay.ov_source.s_disk_id = id) targets ++ with Not_found -> assert false ++ ++let create_json_metadata source targets target_buses ++ guestcaps inspect target_firmware = ++ let doc = ref [ ++ "version", JSON.Int 1L; ++ "name", JSON.String source.s_name; ++ "memory", JSON.Int source.s_memory; ++ "vcpu", JSON.Int (Int64.of_int source.s_vcpu); ++ ] in ++ ++ (match source.s_genid with ++ | None -> () ++ | Some genid -> List.push_back doc ("genid", JSON.String genid) ++ ); ++ ++ if source.s_cpu_vendor <> None || source.s_cpu_model <> None || ++ source.s_cpu_topology <> None then ( ++ let cpu = ref [] in ++ ++ push_optional_string cpu "vendor" source.s_cpu_vendor; ++ push_optional_string cpu "model" source.s_cpu_model; ++ (match source.s_cpu_topology with ++ | None -> () ++ | Some { s_cpu_sockets; s_cpu_cores; s_cpu_threads } -> ++ let attrs = [ ++ "sockets", JSON.Int (Int64.of_int s_cpu_sockets); ++ "cores", JSON.Int (Int64.of_int s_cpu_cores); ++ "threads", JSON.Int (Int64.of_int s_cpu_threads); ++ ] in ++ List.push_back cpu ("topology", JSON.Dict attrs) ++ ); ++ ++ List.push_back doc ("cpu", JSON.Dict !cpu); ++ ); ++ ++ let firmware = ++ let firmware_type = ++ match target_firmware with ++ | TargetBIOS -> "bios" ++ | TargetUEFI -> "uefi" in ++ ++ let fw = ref [ ++ "type", JSON.String firmware_type; ++ ] in ++ ++ (match target_firmware with ++ | TargetBIOS -> () ++ | TargetUEFI -> ++ let uefi_firmware = find_uefi_firmware guestcaps.gcaps_arch in ++ let flags = ++ List.map ( ++ function ++ | Uefi.UEFI_FLAG_SECURE_BOOT_REQUIRED -> "secure_boot_required" ++ ) uefi_firmware.Uefi.flags in ++ ++ let uefi = ref [ ++ "code", JSON.String uefi_firmware.Uefi.code; ++ "vars", JSON.String uefi_firmware.Uefi.vars; ++ "flags", JSON.List (json_list_of_string_list flags); ++ ] in ++ ++ push_optional_string uefi "code-debug" uefi_firmware.Uefi.code_debug; ++ ++ List.push_back fw ("uefi", JSON.Dict !uefi) ++ ); ++ ++ !fw in ++ List.push_back doc ("firmware", JSON.Dict firmware); ++ ++ List.push_back doc ("features", ++ JSON.List (json_list_of_string_list source.s_features)); ++ ++ let machine = ++ match guestcaps.gcaps_machine with ++ | I440FX -> "pc" ++ | Q35 -> "q35" ++ | Virt -> "virt" in ++ List.push_back doc ("machine", JSON.String machine); ++ ++ let disks, removables = ++ let disks = ref [] ++ and removables = ref [] in ++ ++ let iter_bus bus_name drive_prefix i = function ++ | BusSlotEmpty -> () ++ | BusSlotDisk d -> ++ (* Find the corresponding target disk. *) ++ let t = find_target_disk targets d in ++ ++ let target_file = ++ match t.target_file with ++ | TargetFile s -> s ++ | TargetURI _ -> assert false in ++ ++ let disk = [ ++ "dev", JSON.String (drive_prefix ^ drive_name i); ++ "bus", JSON.String bus_name; ++ "format", JSON.String t.target_format; ++ "file", JSON.String (absolute_path target_file); ++ ] in ++ ++ List.push_back disks (JSON.Dict disk) ++ ++ | BusSlotRemovable { s_removable_type = CDROM } -> ++ let cdrom = [ ++ "type", JSON.String "cdrom"; ++ "dev", JSON.String (drive_prefix ^ drive_name i); ++ "bus", JSON.String bus_name; ++ ] in ++ ++ List.push_back removables (JSON.Dict cdrom) ++ ++ | BusSlotRemovable { s_removable_type = Floppy } -> ++ let floppy = [ ++ "type", JSON.String "floppy"; ++ "dev", JSON.String (drive_prefix ^ drive_name i); ++ ] in ++ ++ List.push_back removables (JSON.Dict floppy) ++ in ++ ++ Array.iteri (iter_bus "virtio" "vd") target_buses.target_virtio_blk_bus; ++ Array.iteri (iter_bus "ide" "hd") target_buses.target_ide_bus; ++ Array.iteri (iter_bus "scsi" "sd") target_buses.target_scsi_bus; ++ Array.iteri (iter_bus "floppy" "fd") target_buses.target_floppy_bus; ++ ++ !disks, !removables in ++ List.push_back doc ("disks", JSON.List disks); ++ List.push_back doc ("removables", JSON.List removables); ++ ++ let nics = ++ List.map ( ++ fun { s_mac = mac; s_vnet_type = vnet_type; s_nic_model = nic_model; ++ s_vnet = vnet; } -> ++ let vnet_type_str = ++ match vnet_type with ++ | Bridge -> "bridge" ++ | Network -> "network" in ++ ++ let nic = ref [ ++ "vnet", JSON.String vnet; ++ "vnet-type", JSON.String vnet_type_str; ++ ] in ++ ++ let nic_model_str = Option.map string_of_nic_model nic_model in ++ push_optional_string nic "model" nic_model_str; ++ ++ push_optional_string nic "mac" mac; ++ ++ JSON.Dict !nic ++ ) source.s_nics in ++ List.push_back doc ("nics", JSON.List nics); ++ ++ let guestcaps_dict = ++ let block_bus = ++ match guestcaps.gcaps_block_bus with ++ | Virtio_blk -> "virtio-blk" ++ | Virtio_SCSI -> "virtio-scsi" ++ | IDE -> "ide" in ++ let net_bus = ++ match guestcaps.gcaps_net_bus with ++ | Virtio_net -> "virtio-net" ++ | E1000 -> "e1000" ++ | RTL8139 -> "rtl8139" in ++ let video = ++ match guestcaps.gcaps_video with ++ | QXL -> "qxl" ++ | Cirrus -> "cirrus" in ++ let machine = ++ match guestcaps.gcaps_machine with ++ | I440FX -> "i440fx" ++ | Q35 -> "q35" ++ | Virt -> "virt" in ++ ++ [ ++ "block-bus", JSON.String block_bus; ++ "net-bus", JSON.String net_bus; ++ "video", JSON.String video; ++ "machine", JSON.String machine; ++ "arch", JSON.String guestcaps.gcaps_arch; ++ "virtio-rng", JSON.Bool guestcaps.gcaps_virtio_rng; ++ "virtio-balloon", JSON.Bool guestcaps.gcaps_virtio_balloon; ++ "isa-pvpanic", JSON.Bool guestcaps.gcaps_isa_pvpanic; ++ "acpi", JSON.Bool guestcaps.gcaps_acpi; ++ ] in ++ List.push_back doc ("guestcaps", JSON.Dict guestcaps_dict); ++ ++ (match source.s_sound with ++ | None -> () ++ | Some { s_sound_model = model } -> ++ let sound = [ ++ "model", JSON.String (string_of_source_sound_model model); ++ ] in ++ List.push_back doc ("sound", JSON.Dict sound) ++ ); ++ ++ (match source.s_display with ++ | None -> () ++ | Some d -> ++ let display_type = ++ match d.s_display_type with ++ | Window -> "window" ++ | VNC -> "vnc" ++ | Spice -> "spice" in ++ ++ let display = ref [ ++ "type", JSON.String display_type; ++ ] in ++ ++ push_optional_string display "keymap" d.s_keymap; ++ push_optional_string display "password" d.s_password; ++ ++ let listen = ++ match d.s_listen with ++ | LNoListen -> None ++ | LAddress address -> ++ Some [ ++ "type", JSON.String "address"; ++ "address", JSON.String address; ++ ] ++ | LNetwork network -> ++ Some [ ++ "type", JSON.String "network"; ++ "network", JSON.String network; ++ ] ++ | LSocket None -> ++ Some [ ++ "type", JSON.String "socket"; ++ "socket", JSON.Null; ++ ] ++ | LSocket (Some socket) -> ++ Some [ ++ "type", JSON.String "socket"; ++ "socket", JSON.String socket; ++ ] ++ | LNone -> ++ Some [ ++ "type", JSON.String "none"; ++ ] in ++ (match listen with ++ | None -> () ++ | Some l -> List.push_back display ("listen", JSON.Dict l) ++ ); ++ ++ push_optional_int display "port" d.s_port; ++ ++ List.push_back doc ("display", JSON.Dict !display) ++ ); ++ ++ let inspect_dict = ++ let apps = ++ List.map ( ++ fun { G.app2_name = name; app2_display_name = display_name; ++ app2_epoch = epoch; app2_version = version; ++ app2_release = release; app2_arch = arch; } -> ++ JSON.Dict [ ++ "name", JSON.String name; ++ "display-name", JSON.String display_name; ++ "epoch", JSON.Int (Int64.of_int32 epoch); ++ "version", JSON.String version; ++ "release", JSON.String release; ++ "arch", JSON.String arch; ++ ] ++ ) inspect.i_apps in ++ ++ let firmware_dict = ++ match inspect.i_firmware with ++ | I_BIOS -> ++ [ ++ "type", JSON.String "bios"; ++ ] ++ | I_UEFI devices -> ++ [ ++ "type", JSON.String "uefi"; ++ "devices", JSON.List (json_list_of_string_list devices); ++ ] in ++ ++ [ ++ "root", JSON.String inspect.i_root; ++ "type", JSON.String inspect.i_type; ++ "distro", json_unknown_string inspect.i_distro; ++ "osinfo", json_unknown_string inspect.i_osinfo; ++ "arch", JSON.String inspect.i_arch; ++ "major-version", JSON.Int (Int64.of_int inspect.i_major_version); ++ "minor-version", JSON.Int (Int64.of_int inspect.i_minor_version); ++ "package-format", json_unknown_string inspect.i_package_format; ++ "package-management", json_unknown_string inspect.i_package_management; ++ "product-name", json_unknown_string inspect.i_product_name; ++ "product-variant", json_unknown_string inspect.i_product_variant; ++ "mountpoints", JSON.Dict (json_list_of_string_string_list inspect.i_mountpoints); ++ "applications", JSON.List apps; ++ "windows-systemroot", JSON.String inspect.i_windows_systemroot; ++ "windows-software-hive", JSON.String inspect.i_windows_software_hive; ++ "windows-system-hive", JSON.String inspect.i_windows_system_hive; ++ "windows-current-control-set", JSON.String inspect.i_windows_current_control_set; ++ "firmware", JSON.Dict firmware_dict; ++ ] in ++ List.push_back doc ("inspect", JSON.Dict inspect_dict); ++ ++ !doc +diff --git a/v2v/create_json.mli b/v2v/create_json.mli +new file mode 100644 +index 000000000..6dbb6e48b +--- /dev/null ++++ b/v2v/create_json.mli +@@ -0,0 +1,29 @@ ++(* virt-v2v ++ * Copyright (C) 2019 Red Hat Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ *) ++ ++(** Create JSON metadata for [-o json]. *) ++ ++val create_json_metadata : Types.source -> Types.target list -> ++ Types.target_buses -> ++ Types.guestcaps -> ++ Types.inspect -> ++ Types.target_firmware -> ++ JSON.doc ++(** [create_json_metadata source targets target_buses guestcaps ++ inspect target_firmware] creates the JSON with the majority ++ of the data that virt-v2v used for the conversion. *) +diff --git a/v2v/output_json.ml b/v2v/output_json.ml +new file mode 100644 +index 000000000..ca0bda978 +--- /dev/null ++++ b/v2v/output_json.ml +@@ -0,0 +1,116 @@ ++(* virt-v2v ++ * Copyright (C) 2019 Red Hat Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ *) ++ ++open Printf ++ ++open Std_utils ++open Tools_utils ++open Common_gettext.Gettext ++ ++open Types ++open Utils ++ ++type json_options = { ++ json_disks_pattern : string; ++} ++ ++let print_output_options () = ++ printf (f_"Output options (-oo) which can be used with -o json: ++ ++ -oo json-disks-pattern=PATTERN Pattern for the disks. ++") ++ ++let known_pattern_variables = ["DiskNo"; "DiskDeviceName"; "GuestName"] ++ ++let parse_output_options options = ++ let json_disks_pattern = ref None in ++ ++ List.iter ( ++ function ++ | "json-disks-pattern", v -> ++ if !json_disks_pattern <> None then ++ error (f_"-o json: -oo json-disks-pattern set more than once"); ++ let vars = ++ try Var_expander.scan_variables v ++ with Var_expander.Invalid_variable var -> ++ error (f_"-o json: -oo json-disks-pattern: invalid variable %%{%s}") ++ var in ++ List.iter ( ++ fun var -> ++ if not (List.mem var known_pattern_variables) then ++ error (f_"-o json: -oo json-disks-pattern: unhandled variable %%{%s}") ++ var ++ ) vars; ++ json_disks_pattern := Some v ++ | k, _ -> ++ error (f_"-o json: unknown output option ‘-oo %s’") k ++ ) options; ++ ++ let json_disks_pattern = ++ Option.default "%{GuestName}-%{DiskDeviceName}" !json_disks_pattern in ++ ++ { json_disks_pattern } ++ ++class output_json dir json_options = object ++ inherit output ++ ++ method as_options = sprintf "-o json -os %s" dir ++ ++ method prepare_targets source overlays _ _ _ _ = ++ List.mapi ( ++ fun i (_, ov) -> ++ let outname = ++ let vars_fn = function ++ | "DiskNo" -> Some (string_of_int (i+1)) ++ | "DiskDeviceName" -> Some ov.ov_sd ++ | "GuestName" -> Some source.s_name ++ | _ -> assert false ++ in ++ Var_expander.replace_fn json_options.json_disks_pattern vars_fn in ++ let destname = dir // outname in ++ mkdir_p (Filename.dirname destname) 0o755; ++ TargetFile destname ++ ) overlays ++ ++ method supported_firmware = [ TargetBIOS; TargetUEFI ] ++ ++ method create_metadata source targets ++ target_buses guestcaps inspect target_firmware = ++ let doc = ++ Create_json.create_json_metadata source targets target_buses ++ guestcaps inspect target_firmware in ++ let doc_string = JSON.string_of_doc ~fmt:JSON.Indented doc in ++ ++ if verbose () then ( ++ eprintf "resulting JSON:\n"; ++ output_string stderr doc_string; ++ eprintf "\n\n%!"; ++ ); ++ ++ let name = source.s_name in ++ let file = dir // name ^ ".json" in ++ ++ with_open_out file ( ++ fun chan -> ++ output_string chan doc_string; ++ output_char chan '\n' ++ ) ++end ++ ++let output_json = new output_json ++let () = Modules_list.register_output_module "json" +diff --git a/v2v/output_json.mli b/v2v/output_json.mli +new file mode 100644 +index 000000000..52f58f2d1 +--- /dev/null ++++ b/v2v/output_json.mli +@@ -0,0 +1,31 @@ ++(* virt-v2v ++ * Copyright (C) 2019 Red Hat Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ *) ++ ++(** [-o json] target. *) ++ ++type json_options ++(** Miscellaneous extra command line parameters used by json. *) ++ ++val print_output_options : unit -> unit ++val parse_output_options : (string * string) list -> json_options ++(** Print and parse json -oo options. *) ++ ++val output_json : string -> json_options -> Types.output ++(** [output_json directory json_options] creates and returns a new ++ {!Types.output} object specialized for writing output to local ++ files with JSON metadata. *) +diff --git a/v2v/virt-v2v-output-local.pod b/v2v/virt-v2v-output-local.pod +index 7427b1ed7..7c397c0a4 100644 +--- a/v2v/virt-v2v-output-local.pod ++++ b/v2v/virt-v2v-output-local.pod +@@ -11,6 +11,9 @@ or libvirt + + virt-v2v [-i* options] -o qemu -os DIRECTORY [--qemu-boot] + ++ virt-v2v [-i* options] -o json -os DIRECTORY ++ [-oo json-disks-pattern=PATTERN] ++ + virt-v2v [-i* options] -o null + + =head1 DESCRIPTION +@@ -54,6 +57,13 @@ above, a shell script is created which contains the raw qemu command + you would need to boot the guest. However the shell script is not + run, I you also add the I<--qemu-boot> option. + ++=item B<-o json -os> C ++ ++This converts the guest to files in C. The metadata ++produced is a JSON file containing the majority of the data virt-v2v ++gathers during the conversion. ++See L below. ++ + =item B<-o null> + + The guest is converted, but the final result is thrown away and no +@@ -140,6 +150,51 @@ Define the final guest in libvirt: + + =back + ++=head1 OUTPUT TO JSON ++ ++The I<-o json> option produces the following files by default: ++ ++ NAME.json JSON metadata. ++ NAME-sda, NAME-sdb, etc. Guest disk(s). ++ ++where C is the guest name. ++ ++It is possible to change the pattern of the disks using the ++I<-oo json-disks-pattern=...> option: it allows parameters in form of ++C<%{...}> variables, for example: ++ ++ -oo json-disks-pattern=disk%{DiskNo}.img ++ ++Recognized variables are: ++ ++=over 4 ++ ++=item C<%{DiskNo}> ++ ++The index of the disk, starting from 1. ++ ++=item C<%{DiskDeviceName}> ++ ++The destination device of the disk, e.g. C, C, etc. ++ ++=item C<%{GuestName}> ++ ++The name of the guest. ++ ++=back ++ ++Using a pattern it is possible use subdirectories for the disks, ++even with names depending on variables; for example: ++ ++ -oo json-disks-pattern=%{GuestName}-%{DiskNo}/disk.img ++ ++The default pattern is C<%{GuestName}-%{DiskDeviceName}>. ++ ++If the literal C<%{...}> text is needed, it is possible to avoid the ++escape it with a leading C<%>; for example, ++C<%%{GuestName}-%{DiskNo}.img> will create file names for the ++disks like C<%%{GuestName}-1.img>, C<%%{GuestName}-2.img>, etc. ++ + =head1 SEE ALSO + + L. +diff --git a/v2v/virt-v2v.pod b/v2v/virt-v2v.pod +index cf9464834..9a555c3be 100644 +--- a/v2v/virt-v2v.pod ++++ b/v2v/virt-v2v.pod +@@ -425,6 +425,17 @@ instead. + Set the output method to OpenStack Glance. In this mode the converted + guest is uploaded to Glance. See L. + ++=item B<-o> B ++ ++Set the output method to I. ++ ++In this mode, the converted guest is written to a local directory ++specified by I<-os /dir> (the directory must exist), with a JSON file ++containing the majority of the metadata that virt-v2v gathered during ++the conversion. ++ ++See L. ++ + =item B<-o> B + + Set the output method to I. This is the default. +@@ -696,8 +707,8 @@ The location of the storage for the converted guest. + For I<-o libvirt>, this is a libvirt directory pool + (see S>) or pool UUID. + +-For I<-o local> and I<-o qemu>, this is a directory name. The +-directory must exist. ++For I<-o json>, I<-o local> and I<-o qemu>, this is a directory name. ++The directory must exist. + + For I<-o rhv-upload>, this is the name of the destination Storage + Domain. +-- +2.25.4 + diff --git a/SOURCES/0003-v2v-ovf-Create-OVF-more-aligned-with-the-standard.patch b/SOURCES/0003-v2v-ovf-Create-OVF-more-aligned-with-the-standard.patch deleted file mode 100644 index 3c95c8a..0000000 --- a/SOURCES/0003-v2v-ovf-Create-OVF-more-aligned-with-the-standard.patch +++ /dev/null @@ -1,342 +0,0 @@ -From d330b210b7d62ccd9f73909215251f4ce68cd6c9 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Golembiovsk=C3=BD?= -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ý -(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 whereas in case of -+ * RHV export storage domain it is
. -+ *) -+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 - diff --git a/SOURCES/0004-inspect-fix-icon-of-RHEL.patch b/SOURCES/0004-inspect-fix-icon-of-RHEL.patch new file mode 100644 index 0000000..181d99e --- /dev/null +++ b/SOURCES/0004-inspect-fix-icon-of-RHEL.patch @@ -0,0 +1,32 @@ +From e7ff090884f5e32585e9683d35b72bca01e0a836 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Mon, 11 Feb 2019 19:28:00 +0100 +Subject: [PATCH] inspect: fix icon of RHEL + +Use a better icon for RHEL guests, still provided by redhat-logos (or +equivalent in downstream distributions), and which fits a better +definition of logo for the distribution. + +Thanks to Ray Strode for the hints. + +(cherry picked from commit c648052690a4a07a59c741308e0e8497d6f18057) +--- + lib/inspect-icon.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/inspect-icon.c b/lib/inspect-icon.c +index 623591aa6..19f3f87af 100644 +--- a/lib/inspect-icon.c ++++ b/lib/inspect-icon.c +@@ -317,7 +317,7 @@ icon_rhel (guestfs_h *g, int major, size_t *size_r) + if (major < 7) + shadowman = "/usr/share/pixmaps/redhat/shadowman-transparent.png"; + else +- shadowman = "/usr/share/pixmaps/fedora-logo-sprite.png"; ++ shadowman = "/usr/share/icons/hicolor/96x96/apps/system-logo-icon.png"; + + return get_png (g, shadowman, size_r, 102400); + } +-- +2.25.4 + diff --git a/SOURCES/0004-v2v-vdsm-add-vdsm-fixed-ovf-option.patch b/SOURCES/0004-v2v-vdsm-add-vdsm-fixed-ovf-option.patch deleted file mode 100644 index 238e64b..0000000 --- a/SOURCES/0004-v2v-vdsm-add-vdsm-fixed-ovf-option.patch +++ /dev/null @@ -1,213 +0,0 @@ -From 14cfe80643a7df4ddf412aebdf39543344c1cf6e Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Golembiovsk=C3=BD?= -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ý -(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), conforming to S. - - 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, but this may change in -+the future. -+ - =item B<-v> - - =item B<--verbose> --- -2.21.0 - diff --git a/SOURCES/0005-v2v-OVF-Code-formatting.patch b/SOURCES/0005-v2v-OVF-Code-formatting.patch deleted file mode 100644 index 39de8ca..0000000 --- a/SOURCES/0005-v2v-OVF-Code-formatting.patch +++ /dev/null @@ -1,124 +0,0 @@ -From 00ed208050cdb2178ac58878cb126504ebc7b311 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -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 whereas in case of - * RHV export storage domain it is
. - *) --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 - diff --git a/SOURCES/0005-v2v-warn-when-the-guest-has-direct-network-interface.patch b/SOURCES/0005-v2v-warn-when-the-guest-has-direct-network-interface.patch new file mode 100644 index 0000000..0f115f4 --- /dev/null +++ b/SOURCES/0005-v2v-warn-when-the-guest-has-direct-network-interface.patch @@ -0,0 +1,48 @@ +From df8794643644c742b7cfced948eee4519b38a643 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Fri, 12 Apr 2019 17:28:12 +0200 +Subject: [PATCH] v2v: warn when the guest has direct network interfaces + (RHBZ#1518539) + +virt-v2v obviously cannot convert this kind of devices, since they are +specific to the host of the hypervisor. Thus, emit a warning about the +presence of direct network interfaces, so at least this can be noticed +when converting a guest. + +(cherry picked from commit 1629ec6a5639cf5e226e80bcee749ae8851b1fae) +--- + v2v/parse_libvirt_xml.ml | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/v2v/parse_libvirt_xml.ml b/v2v/parse_libvirt_xml.ml +index d5d78d367..b9970cee8 100644 +--- a/v2v/parse_libvirt_xml.ml ++++ b/v2v/parse_libvirt_xml.ml +@@ -492,6 +492,24 @@ let parse_libvirt_xml ?conn xml = + ) + in + ++ (* Check for direct attachments to physical network interfaces. ++ * (RHBZ#1518539) ++ *) ++ let () = ++ let obj = Xml.xpath_eval_expression xpathctx "/domain/devices/interface[@type='direct']" in ++ let nr_nodes = Xml.xpathobj_nr_nodes obj in ++ if nr_nodes > 0 then ( ++ (* Sadly fn_ in ocaml-gettext seems broken, and always returns the ++ * singular string no matter what. Work around this by using a simple ++ * string with sn_ (which works), and outputting it as a whole. ++ *) ++ let msg = sn_ "this guest has a direct network interface which will be ignored" ++ "this guest has direct network interfaces which will be ignored" ++ nr_nodes in ++ warning "%s" msg ++ ) ++ in ++ + ({ + s_hypervisor = hypervisor; + s_name = name; s_orig_name = name; +-- +2.25.4 + diff --git a/SOURCES/0006-v2v-DOM-Add-doc_to_string-function.patch b/SOURCES/0006-v2v-DOM-Add-doc_to_string-function.patch deleted file mode 100644 index b5f9f45..0000000 --- a/SOURCES/0006-v2v-DOM-Add-doc_to_string-function.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 83b5f589231da2ab6d04680f42c37dc6058cbe6e Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -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 "" (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 "" (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 -> - last_child_was_element := false; -- node_to_chan ~indent:(indent+2) chan child; -+ node_to_buf ~indent:(indent+2) buf child; - | Comment _ 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; - ) children; - if !last_child_was_element then ( -- output_char chan '\n'; -- output_spaces chan indent -+ Buffer.add_char buf '\n'; -+ buffer_add_spaces buf indent - ); -- fprintf chan "" name -+ bprintf buf "" name - ) else ( -- output_string chan "/>" -+ Buffer.add_string buf "/>" - ) - -+and buffer_add_spaces buf n = -+ Buffer.add_string buf (String.spaces n) -+ - (* Quote XML content. Note you must use single - * quotes around the attribute. - *) -@@ -99,10 +104,20 @@ and xml_quote_pcdata str = - let str = String.replace str ">" ">" in - str - --let doc_to_chan chan (Doc doc) = -- fprintf chan "\n"; -- element_to_chan chan doc; -- fprintf chan "\n" -+let doc_to_buf buf (Doc doc) = -+ bprintf buf "\n"; -+ element_to_buf buf doc; -+ bprintf buf "\n" -+ -+let doc_to_string doc = -+ let buf = Buffer.create 4096 in -+ doc_to_buf buf doc; -+ Buffer.contents buf -+ -+let doc_to_chan chan doc = -+ let buf = Buffer.create 4096 in -+ doc_to_buf buf doc; -+ Buffer.output_buffer chan buf - - let path_to_nodes (Doc doc) path = - match path with -diff --git a/v2v/DOM.mli b/v2v/DOM.mli -index 1aa89b7e7..99223c389 100644 ---- a/v2v/DOM.mli -+++ b/v2v/DOM.mli -@@ -60,6 +60,9 @@ v} - v} - *) - -+val doc_to_string : doc -> string -+(** Convert a document to a string representation. *) -+ - val doc_to_chan : out_channel -> doc -> unit - (** Write the XML document to an output channel. *) - --- -2.21.0 - diff --git a/SOURCES/0006-v2v-update-documentation-on-nbdkit-RHBZ-1605242.patch b/SOURCES/0006-v2v-update-documentation-on-nbdkit-RHBZ-1605242.patch new file mode 100644 index 0000000..c3ef027 --- /dev/null +++ b/SOURCES/0006-v2v-update-documentation-on-nbdkit-RHBZ-1605242.patch @@ -0,0 +1,55 @@ +From de267e07b9b26d2f89470d4305d7259edb24663b Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Fri, 12 Apr 2019 16:19:43 +0200 +Subject: [PATCH] v2v: update documentation on nbdkit (RHBZ#1605242) + +nbdkit >= 1.6 ships a VDDK plugin always built, so recommend that +version instead of recommending to build nbdkit from sources. + +(cherry picked from commit 0704d8eb0bcc8139886eb4291f75a3ca49a91e58) +--- + v2v/virt-v2v-input-vmware.pod | 28 ++-------------------------- + 1 file changed, 2 insertions(+), 26 deletions(-) + +diff --git a/v2v/virt-v2v-input-vmware.pod b/v2v/virt-v2v-input-vmware.pod +index 2b6dbaeec..b3ebda182 100644 +--- a/v2v/virt-v2v-input-vmware.pod ++++ b/v2v/virt-v2v-input-vmware.pod +@@ -197,32 +197,8 @@ library is permitted by the license. + + =item 2. + +-You must also compile nbdkit, enabling the VDDK plugin. nbdkit E +-1.1.25 is recommended, but it is usually best to compile from the git +-tree. +- +-=over 4 +- +-=item * +- +-L +- +-=item * +- +-L +- +-=back +- +-Compile nbdkit as described in the sources (see link above). +- +-You do B need to run C because you can run nbdkit +-from its source directory. The source directory has a shell script +-called F which runs the locally built copy of nbdkit and its +-plugins. So set C<$PATH> to point to the nbdkit top build directory +-(that is, the directory containing the shell script called F), +-eg: +- +- export PATH=/path/to/nbdkit-1.1.x:$PATH ++nbdkit E 1.6 is recommended, as it ships with the VDDK plugin ++enabled unconditionally. + + =item 3. + +-- +2.25.4 + diff --git a/SOURCES/0007-v2v-Add-op-output-password-file-option.patch b/SOURCES/0007-v2v-Add-op-output-password-file-option.patch deleted file mode 100644 index 79afa1e..0000000 --- a/SOURCES/0007-v2v-Add-op-output-password-file-option.patch +++ /dev/null @@ -1,138 +0,0 @@ -From ae2d0a507af53563d0b70d28654c9c60a857fd10 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Thu, 22 Feb 2018 11:43:33 +0000 -Subject: [PATCH] v2v: Add -op (output password file) option. - -Currently unused, in a future commit this will allow you to pass in a -password to be used when connecting to the target hypervisor. - -(cherry picked from commit a4e181137a38f5767dd1bf05dc482959cb7283be) ---- - v2v/cmdline.ml | 18 ++++++++++++++++++ - v2v/test-v2v-docs.sh | 2 +- - v2v/virt-v2v.pod | 7 +++++++ - 3 files changed, 26 insertions(+), 1 deletion(-) - -diff --git a/v2v/cmdline.ml b/v2v/cmdline.ml -index 75909ee77..2a067741e 100644 ---- a/v2v/cmdline.ml -+++ b/v2v/cmdline.ml -@@ -62,6 +62,7 @@ let parse_cmdline () = - let output_conn = ref None in - let output_format = ref None in - let output_name = ref None in -+ let output_password = ref None in - let output_storage = ref None in - let password_file = ref None in - let vddk_config = ref None in -@@ -219,6 +220,8 @@ let parse_cmdline () = - s_"Set output format"; - [ M"on" ], Getopt.String ("name", set_string_option_once "-on" output_name), - s_"Rename guest when converting"; -+ [ M"op" ], Getopt.String ("filename", set_string_option_once "-op" output_password), -+ s_"Use password from file to connect to output hypervisor"; - [ M"os" ], Getopt.String ("storage", set_string_option_once "-os" output_storage), - s_"Set output storage location"; - [ L"password-file" ], Getopt.String ("file", set_string_option_once "--password-file" password_file), -@@ -314,6 +317,7 @@ read the man page virt-v2v(1). - let output_format = !output_format in - let output_mode = !output_mode in - let output_name = !output_name in -+ let output_password = !output_password in - let output_storage = !output_storage in - let password_file = !password_file in - let print_source = !print_source in -@@ -461,6 +465,8 @@ read the man page virt-v2v(1). - | `Glance -> - if output_conn <> None then - error_option_cannot_be_used_in_output_mode "glance" "-oc"; -+ if output_password <> None then -+ error_option_cannot_be_used_in_output_mode "glance" "-op"; - if output_storage <> None then - error_option_cannot_be_used_in_output_mode "glance" "-os"; - if qemu_boot then -@@ -472,6 +478,8 @@ read the man page virt-v2v(1). - - | `Not_set - | `Libvirt -> -+ if output_password <> None then -+ error_option_cannot_be_used_in_output_mode "libvirt" "-op"; - let output_storage = Option.default "default" output_storage in - if qemu_boot then - error_option_cannot_be_used_in_output_mode "libvirt" "--qemu-boot"; -@@ -481,6 +489,8 @@ read the man page virt-v2v(1). - output_format, output_alloc - - | `Local -> -+ if output_password <> None then -+ error_option_cannot_be_used_in_output_mode "local" "-op"; - let os = - match output_storage with - | None -> -@@ -500,6 +510,8 @@ read the man page virt-v2v(1). - error_option_cannot_be_used_in_output_mode "null" "-oc"; - if output_format <> None then - error_option_cannot_be_used_in_output_mode "null" "-of"; -+ if output_password <> None then -+ error_option_cannot_be_used_in_output_mode "null" "-op"; - if output_storage <> None then - error_option_cannot_be_used_in_output_mode "null" "-os"; - if qemu_boot then -@@ -509,6 +521,8 @@ read the man page virt-v2v(1). - Some "raw", Sparse - - | `QEmu -> -+ if output_password <> None then -+ error_option_cannot_be_used_in_output_mode "qemu" "-op"; - let os = - match output_storage with - | None -> -@@ -520,6 +534,8 @@ read the man page virt-v2v(1). - output_format, output_alloc - - | `RHV -> -+ if output_password <> None then -+ error_option_cannot_be_used_in_output_mode "rhv" "-op"; - let os = - match output_storage with - | None -> -@@ -531,6 +547,8 @@ read the man page virt-v2v(1). - output_format, output_alloc - - | `VDSM -> -+ if output_password <> None then -+ error_option_cannot_be_used_in_output_mode "vdsm" "-op"; - let os = - match output_storage with - | None -> -diff --git a/v2v/test-v2v-docs.sh b/v2v/test-v2v-docs.sh -index 5d034c465..0e3bd916a 100755 ---- a/v2v/test-v2v-docs.sh -+++ b/v2v/test-v2v-docs.sh -@@ -22,4 +22,4 @@ $TEST_FUNCTIONS - skip_if_skipped - - $top_srcdir/podcheck.pl virt-v2v.pod virt-v2v \ -- --ignore=--debug-overlay,--ic,--if,--it,--no-trim,--oa,--oc,--of,--on,--os,--vmtype -+ --ignore=--debug-overlay,--ic,--if,--it,--no-trim,--oa,--oc,--of,--on,--op,--os,--vmtype -diff --git a/v2v/virt-v2v.pod b/v2v/virt-v2v.pod -index 0ea5fa97f..00ba45555 100644 ---- a/v2v/virt-v2v.pod -+++ b/v2v/virt-v2v.pod -@@ -569,6 +569,13 @@ If not specified, then the input format is used. - Rename the guest when converting it. If this option is not used then - the output name is the same as the input name. - -+=item B<-op> file -+ -+Supply a file containing a password to be used when connecting to the -+target hypervisor. Note the file should contain the whole password, -+B, and for security the file should have -+mode C<0600> so that others cannot read it. -+ - =item B<-os> storage - - The location of the storage for the converted guest. --- -2.21.0 - diff --git a/SOURCES/0007-v2v-linux-do-not-uninstall-open-vm-tools-w-ubuntu-se.patch b/SOURCES/0007-v2v-linux-do-not-uninstall-open-vm-tools-w-ubuntu-se.patch new file mode 100644 index 0000000..f7ec87f --- /dev/null +++ b/SOURCES/0007-v2v-linux-do-not-uninstall-open-vm-tools-w-ubuntu-se.patch @@ -0,0 +1,57 @@ +From 51367a1f2d4a5c54564a6bcaf8c193de643d3ee4 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Wed, 27 Feb 2019 17:51:59 +0100 +Subject: [PATCH] v2v: linux: do not uninstall open-vm-tools w/ ubuntu-server + +ubuntu-server depends on open-vm-tools on Ubuntu, so if v2v tries to +uninstall open-vm-tools then dpkg will (rightfully) fail with a +dependency issue. + +Since open-vm-tools is harmless after the conversion anyway (it will +not even run), then do not attempt to uninstall it if ubuntu-server is +installed too. + +Followup of commit 2bebacf8bf611f0f80a66915f78653ce30b38129. + +Thanks to: Ming Xie. + +(cherry picked from commit 1a4fd822ef057764f809cddce642b3223756629e) +--- + v2v/convert_linux.ml | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +diff --git a/v2v/convert_linux.ml b/v2v/convert_linux.ml +index 3d61400b5..b4b2f24c4 100644 +--- a/v2v/convert_linux.ml ++++ b/v2v/convert_linux.ml +@@ -289,6 +289,18 @@ let convert (g : G.guestfs) inspect source output rcaps = + + (* Uninstall VMware Tools. *) + let remove = ref [] and libraries = ref [] in ++ (* On Ubuntu, the ubuntu-server metapackage depends on ++ * open-vm-tools, and thus any attempt to remove it will cause ++ * dependency issues. Hence, special case this situation, and ++ * leave open-vm-tools installed in this case. ++ *) ++ let has_ubuntu_server = ++ if family = `Debian_family then ++ List.exists ( ++ fun { G.app2_name = name } -> ++ name = "ubuntu-server" ++ ) inspect.i_apps ++ else false in + List.iter ( + fun { G.app2_name = name } -> + if String.is_prefix name "vmware-tools-libraries-" then +@@ -301,7 +313,7 @@ let convert (g : G.guestfs) inspect source output rcaps = + List.push_front name remove + else if String.is_prefix name "open-vm-tools-" then + List.push_front name remove +- else if name = "open-vm-tools" then ++ else if name = "open-vm-tools" && not has_ubuntu_server then + List.push_front name remove + ) inspect.i_apps; + let libraries = !libraries in +-- +2.25.4 + diff --git a/SOURCES/0008-v2v-cmdline-Move-definition-to-before-its-only-use.patch b/SOURCES/0008-v2v-cmdline-Move-definition-to-before-its-only-use.patch deleted file mode 100644 index e5adf73..0000000 --- a/SOURCES/0008-v2v-cmdline-Move-definition-to-before-its-only-use.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 311d8dff12b8079b7eb9d6d2d917a9c6883928a4 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Thu, 22 Mar 2018 10:28:36 +0000 -Subject: [PATCH] v2v: cmdline: Move definition to before its only use. - -(cherry picked from commit 3167ce1f91667de4c4fe1885bb33c06ee6fa38c5) ---- - v2v/cmdline.ml | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/v2v/cmdline.ml b/v2v/cmdline.ml -index 2a067741e..a83fcbae0 100644 ---- a/v2v/cmdline.ml -+++ b/v2v/cmdline.ml -@@ -81,7 +81,6 @@ let parse_cmdline () = - 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 - -@@ -183,7 +182,8 @@ let parse_cmdline () = - let i_options = - String.concat "|" (Modules_list.input_modules ()) - and o_options = -- String.concat "|" (Modules_list.output_modules ()) in -+ String.concat "|" (Modules_list.output_modules ()) -+ and ovf_flavours_str = String.concat "|" Create_ovf.ovf_flavours in - - let argspec = [ - [ S 'b'; L"bridge" ], Getopt.String ("in:out", add_bridge), --- -2.21.0 - diff --git a/SOURCES/0008-v2v-linux-canonicalize-module-path-for-arch-detectio.patch b/SOURCES/0008-v2v-linux-canonicalize-module-path-for-arch-detectio.patch new file mode 100644 index 0000000..6691d7a --- /dev/null +++ b/SOURCES/0008-v2v-linux-canonicalize-module-path-for-arch-detectio.patch @@ -0,0 +1,36 @@ +From 6239ce21ea4d47914aa149cee724e998c287d26c Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Wed, 20 Mar 2019 16:55:05 +0100 +Subject: [PATCH] v2v: linux: canonicalize module path for arch detection + (RHBZ#1690574) + +Kernel modules can be also symlinks to files available outside the +"canonical" module directory; the "file" API, used by the +"file-architecture" API, return the actual type of a file (so symlinks, +block devices, etc), and thus "file-architecture" fails on symlinks. + +To prevent this situation, canonicalize the path of the module picked +for architecture detection: this way, "file-architecture" will act on a +real file. + +(cherry picked from commit 0a093035d485b3c2e66d56541ebe159f1b632ba6) +--- + v2v/linux_kernels.ml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/v2v/linux_kernels.ml b/v2v/linux_kernels.ml +index 3313aabc7..889ec2f2a 100644 +--- a/v2v/linux_kernels.ml ++++ b/v2v/linux_kernels.ml +@@ -189,7 +189,7 @@ let detect_kernels (g : G.guestfs) inspect family bootloader = + *) + let arch = + let any_module = modpath ^ List.hd modules in +- g#file_architecture any_module in ++ g#file_architecture (g#realpath any_module) in + + (* Just return the module names, without path or extension. *) + let modules = List.filter_map ( +-- +2.25.4 + diff --git a/SOURCES/0009-v2v-Add-general-mechanism-for-input-and-output-optio.patch b/SOURCES/0009-v2v-Add-general-mechanism-for-input-and-output-optio.patch deleted file mode 100644 index 0963e7b..0000000 --- a/SOURCES/0009-v2v-Add-general-mechanism-for-input-and-output-optio.patch +++ /dev/null @@ -1,1268 +0,0 @@ -From 5198d704e964fa896773d250624858e865c30082 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Thu, 22 Mar 2018 10:29:23 +0000 -Subject: [PATCH] v2v: Add general mechanism for input and output options - (-io/-oo). - -Currently we have a bunch of ad hoc options like --vddk* and --vdsm* -(and proposed to add --rhv*) to handle extra parameters for input and -output modes/transports. This complicates the command line parsing -and also the clarity of the command line (becauseit's not very obvious -which options apply to which side of the conversion). - -Replace these with a general mechanism for handling input and output -options. - -Thus (for example): - - --vddk-thumbprint=... becomes -io vddk-thumbprint=... - --vdsm-compat=0.10 -oo vdsm-compat=0.10 - -The responsibility for parsing input and output options moves into the -input and output drivers. - -This improves error checking so it's harder now for wrong flags to be -included on the command line when they don't apply to the current mode. - -The old option names are preserved for compatibility. - -(cherry picked from commit 6327e716cdd2f161bc639733f216a3a29d26ad3c) ---- - v2v/Makefile.am | 4 + - v2v/cmdline.ml | 229 ++++++++++++++------------- - v2v/input_libvirt.ml | 4 +- - v2v/input_libvirt.mli | 4 +- - v2v/input_libvirt_vddk.ml | 112 +++++++++----- - v2v/input_libvirt_vddk.mli | 16 +- - v2v/output_vdsm.ml | 79 +++++++++- - v2v/output_vdsm.mli | 13 +- - v2v/test-v2v-docs.sh | 31 +++- - v2v/test-v2v-it-vddk-io-query.sh | 38 +++++ - v2v/test-v2v-o-vdsm-oo-query.sh | 38 +++++ - v2v/test-v2v-o-vdsm-options.sh | 16 +- - v2v/virt-v2v.pod | 258 ++++++++++++++++--------------- - 13 files changed, 530 insertions(+), 312 deletions(-) - create mode 100755 v2v/test-v2v-it-vddk-io-query.sh - create mode 100755 v2v/test-v2v-o-vdsm-oo-query.sh - -diff --git a/v2v/Makefile.am b/v2v/Makefile.am -index 0c3224b24..482ba58e5 100644 ---- a/v2v/Makefile.am -+++ b/v2v/Makefile.am -@@ -307,6 +307,8 @@ TESTS = \ - test-v2v-i-ova-tar.sh \ - test-v2v-i-ova-two-disks.sh \ - test-v2v-i-vmx.sh \ -+ test-v2v-it-vddk-io-query.sh \ -+ test-v2v-o-vdsm-oo-query.sh \ - test-v2v-bad-networks-and-bridges.sh - - if HAVE_LIBVIRT -@@ -470,6 +472,7 @@ EXTRA_DIST += \ - test-v2v-i-vmx-4.vmx \ - test-v2v-i-vmx-5.vmx \ - test-v2v-in-place.sh \ -+ test-v2v-it-vddk-io-query.sh \ - test-v2v-machine-readable.sh \ - test-v2v-networks-and-bridges-expected.xml \ - test-v2v-networks-and-bridges.sh \ -@@ -480,6 +483,7 @@ EXTRA_DIST += \ - test-v2v-o-null.sh \ - test-v2v-o-qemu.sh \ - test-v2v-o-rhv.sh \ -+ test-v2v-o-vdsm-oo-query.sh \ - test-v2v-o-vdsm-options.sh \ - test-v2v-oa-option.sh \ - test-v2v-of-option.sh \ -diff --git a/v2v/cmdline.ml b/v2v/cmdline.ml -index a83fcbae0..5b8f686a8 100644 ---- a/v2v/cmdline.ml -+++ b/v2v/cmdline.ml -@@ -65,24 +65,6 @@ let parse_cmdline () = - let output_password = ref None in - let output_storage = ref None in - let password_file = ref None in -- let vddk_config = ref None in -- let vddk_cookie = ref None in -- let vddk_libdir = ref None in -- let vddk_nfchostport = ref None in -- let vddk_port = ref None in -- let vddk_snapshot = ref None in -- let vddk_thumbprint = ref None in -- let vddk_transports = ref None in -- let vddk_vimapiver = ref None in -- let vdsm_vm_uuid = ref None in -- let vdsm_ovf_output = ref None in (* default "." *) -- -- 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 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 -@@ -106,6 +88,15 @@ let parse_cmdline () = - error (f_"unknown -i option: %s") s - in - -+ let input_options = ref [] in -+ let set_input_option_compat k v = -+ input_options := (k, v) :: !input_options -+ in -+ let set_input_option option = -+ let k, v = String.split "=" option in -+ set_input_option_compat k v -+ in -+ - let network_map = ref NetworkMap.empty in - let add_network, add_bridge = - let add flag name t str = -@@ -159,6 +150,15 @@ let parse_cmdline () = - error (f_"unknown -oa option: %s") s - in - -+ let output_options = ref [] in -+ let set_output_option_compat k v = -+ output_options := (k, v) :: !output_options -+ in -+ let set_output_option option = -+ let k, v = String.split "=" option in -+ set_output_option_compat k v -+ in -+ - let root_choice = ref AskRoot in - let set_root_choice = function - | "ask" -> root_choice := AskRoot -@@ -169,12 +169,6 @@ let parse_cmdline () = - error (f_"unknown --root option: %s") s - in - -- let vdsm_image_uuids = ref [] in -- let add_vdsm_image_uuid s = List.push_front s vdsm_image_uuids in -- -- let vdsm_vol_uuids = ref [] in -- let add_vdsm_vol_uuid s = List.push_front s vdsm_vol_uuids in -- - let vmtype_warning _ = - warning (f_"the --vmtype option has been removed and now does nothing") - in -@@ -198,6 +192,8 @@ let parse_cmdline () = - s_"Libvirt URI"; - [ M"if" ], Getopt.String ("format", set_string_option_once "-if" input_format), - s_"Input format (for -i disk)"; -+ [ M"io" ], Getopt.String ("option[=value]", set_input_option), -+ s_"Set option for input mode"; - [ M"it" ], Getopt.String ("transport", set_string_option_once "-it" input_transport), - s_"Input transport"; - [ L"in-place" ], Getopt.Set in_place, -@@ -220,6 +216,8 @@ let parse_cmdline () = - s_"Set output format"; - [ M"on" ], Getopt.String ("name", set_string_option_once "-on" output_name), - s_"Rename guest when converting"; -+ [ M"oo" ], Getopt.String ("option[=value]", set_output_option), -+ s_"Set option for output mode"; - [ M"op" ], Getopt.String ("filename", set_string_option_once "-op" output_password), - s_"Use password from file to connect to output hypervisor"; - [ M"os" ], Getopt.String ("storage", set_string_option_once "-os" output_storage), -@@ -231,36 +229,36 @@ let parse_cmdline () = - [ L"qemu-boot" ], Getopt.Set qemu_boot, s_"Boot in qemu (-o qemu only)"; - [ L"root" ], Getopt.String ("ask|... ", set_root_choice), - s_"How to choose root filesystem"; -- [ L"vddk-config" ], Getopt.String ("filename", set_string_option_once "--vddk-config" vddk_config), -- s_"Set VDDK config file"; -- [ L"vddk-cookie" ], Getopt.String ("cookie", set_string_option_once "--vddk-cookie" vddk_cookie), -- s_"Set VDDK cookie"; -- [ L"vddk-libdir" ], Getopt.String ("libdir", set_string_option_once "--vddk-libdir" vddk_libdir), -- s_"Set VDDK library parent directory"; -- [ L"vddk-nfchostport" ], Getopt.String ("nfchostport", set_string_option_once "--vddk-nfchostport" vddk_nfchostport), -- s_"Set VDDK nfchostport"; -- [ L"vddk-port" ], Getopt.String ("port", set_string_option_once "--vddk-port" vddk_port), -- s_"Set VDDK port"; -- [ L"vddk-snapshot" ], Getopt.String ("snapshot-moref", set_string_option_once "--vddk-snapshot" vddk_snapshot), -- s_"Set VDDK snapshot"; -- [ L"vddk-thumbprint" ], Getopt.String ("thumbprint", set_string_option_once "--vddk-thumbprint" vddk_thumbprint), -- s_"Set VDDK thumbprint"; -- [ L"vddk-transports" ], Getopt.String ("transports", set_string_option_once "--vddk-transports" vddk_transports), -- s_"Set VDDK transports"; -- [ L"vddk-vimapiver" ], Getopt.String ("apiver", set_string_option_once "--vddk-vimapiver" vddk_vimapiver), -- s_"Set VDDK vimapiver"; -- [ L"vdsm-compat" ], Getopt.Symbol ("0.10|1.1", ["0.10"; "1.1"], set_vdsm_compat), -- s_"Write qcow2 with compat=0.10|1.1"; -- [ L"vdsm-image-uuid" ], Getopt.String ("uuid", add_vdsm_image_uuid), -- s_"Output image UUID(s)"; -- [ L"vdsm-vol-uuid" ], Getopt.String ("uuid", add_vdsm_vol_uuid), -- s_"Output vol UUID(s)"; -- [ L"vdsm-vm-uuid" ], Getopt.String ("uuid", set_string_option_once "--vdsm-vm-uuid" vdsm_vm_uuid), -- 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"vddk-config" ], Getopt.String ("filename", set_input_option_compat "vddk-config"), -+ s_"Same as ‘-io vddk-config=filename’"; -+ [ L"vddk-cookie" ], Getopt.String ("cookie", set_input_option_compat "vddk-cookie"), -+ s_"Same as ‘-io vddk-cookie=filename’"; -+ [ L"vddk-libdir" ], Getopt.String ("libdir", set_input_option_compat "vddk-libdir"), -+ s_"Same as ‘-io vddk-libdir=libdir’"; -+ [ L"vddk-nfchostport" ], Getopt.String ("nfchostport", set_input_option_compat "vddk-nfchostport"), -+ s_"Same as ‘-io vddk-nfchostport=nfchostport’"; -+ [ L"vddk-port" ], Getopt.String ("port", set_input_option_compat "vddk-port"), -+ s_"Same as ‘-io vddk-port=port’"; -+ [ L"vddk-snapshot" ], Getopt.String ("snapshot-moref", set_input_option_compat "vddk-snapshot"), -+ s_"Same as ‘-io vddk-snapshot=snapshot-moref’"; -+ [ L"vddk-thumbprint" ], Getopt.String ("thumbprint", set_input_option_compat "vddk-thumbprint"), -+ s_"Same as ‘-io vddk-thumbprint=thumbprint’"; -+ [ L"vddk-transports" ], Getopt.String ("transports", set_input_option_compat "vddk-transports"), -+ s_"Same as ‘-io vddk-transports=transports’"; -+ [ L"vddk-vimapiver" ], Getopt.String ("apiver", set_input_option_compat "vddk-vimapiver"), -+ s_"Same as ‘-io vddk-vimapiver=apiver’"; -+ [ L"vdsm-compat" ], Getopt.String ("0.10|1.1", set_output_option_compat "vdsm-compat"), -+ s_"Same as ‘-oo vdsm-compat=0.10|1.1’"; -+ [ L"vdsm-image-uuid" ], Getopt.String ("uuid", set_output_option_compat "vdsm-image-uuid"), -+ s_"Same as ‘-oo vdsm-image-uuid=uuid’"; -+ [ L"vdsm-vol-uuid" ], Getopt.String ("uuid", set_output_option_compat "vdsm-vol-uuid"), -+ s_"Same as ‘-oo vdsm-vol-uuid=uuid’"; -+ [ L"vdsm-vm-uuid" ], Getopt.String ("uuid", set_output_option_compat "vdsm-vm-uuid"), -+ s_"Same as ‘-oo vdsm-vm-uuid=uuid’"; -+ [ L"vdsm-ovf-output" ], Getopt.String ("dir", set_output_option_compat "vdsm-ovf-output"), -+ s_"Same as ‘-oo vdsm-ovf-output=dir’"; -+ [ L"vdsm-ovf-flavour" ], Getopt.String (ovf_flavours_str, set_output_option_compat "vdsm-ovf-flavour"), -+ s_"Same as ‘-oo vdsm-ovf-flavour=flavour’"; - [ L"vmtype" ], Getopt.String ("-", vmtype_warning), - s_"Ignored for backwards compatibility"; - ] in -@@ -299,6 +297,7 @@ read the man page virt-v2v(1). - let input_conn = !input_conn in - let input_format = !input_format in - let input_mode = !input_mode in -+ let input_options = List.rev !input_options in - let input_transport = - match !input_transport with - | None -> None -@@ -317,28 +316,13 @@ read the man page virt-v2v(1). - let output_format = !output_format in - let output_mode = !output_mode in - let output_name = !output_name in -+ let output_options = List.rev !output_options in - let output_password = !output_password in - let output_storage = !output_storage in - let password_file = !password_file in - let print_source = !print_source in - let qemu_boot = !qemu_boot in - let root_choice = !root_choice in -- let vddk_options = -- { Input_libvirt_vddk.vddk_config = !vddk_config; -- vddk_cookie = !vddk_cookie; -- vddk_libdir = !vddk_libdir; -- vddk_nfchostport = !vddk_nfchostport; -- vddk_port = !vddk_port; -- vddk_snapshot = !vddk_snapshot; -- vddk_thumbprint = !vddk_thumbprint; -- vddk_transports = !vddk_transports; -- vddk_vimapiver = !vddk_vimapiver } in -- let vdsm_compat = !vdsm_compat in -- let vdsm_image_uuids = List.rev !vdsm_image_uuids in -- 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. -@@ -352,6 +336,7 @@ read the man page virt-v2v(1). - printf "colours-option\n"; - printf "vdsm-compat-option\n"; - printf "in-place\n"; -+ printf "io/oo\n"; - 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 ()); -@@ -359,6 +344,65 @@ read the man page virt-v2v(1). - exit 0 - ); - -+ (* Input transport affects whether some input options should or -+ * should not be used. -+ *) -+ let input_transport = -+ let is_query = input_options = ["?", ""] in -+ let no_options () = -+ if is_query then ( -+ printf (f_"No -io (input options) are supported with this input transport.\n"); -+ exit 0 -+ ) -+ else if input_options <> [] then -+ error (f_"no -io (input options) are allowed here"); -+ in -+ match input_transport with -+ | None -> no_options (); None -+ | Some `SSH -> no_options (); Some `SSH -+ | Some `VDDK -> -+ if is_query then ( -+ Input_libvirt_vddk.print_input_options (); -+ exit 0 -+ ) -+ else ( -+ let vddk_options = -+ Input_libvirt_vddk.parse_input_options input_options in -+ Some (`VDDK vddk_options) -+ ) in -+ -+ (* Output mode affects whether some output options should or -+ * should not be used. -+ *) -+ let output_mode = -+ let is_query = output_options = ["?", ""] in -+ let no_options () = -+ if is_query then ( -+ printf (f_"No -oo (output options) are supported in this output mode.\n"); -+ exit 0 -+ ) -+ else if output_options <> [] then -+ error (f_"no -oo (output options) are allowed here"); -+ in -+ match output_mode with -+ | `Not_set -> no_options (); `Not_set -+ | `Glance -> no_options (); `Glance -+ | `Libvirt -> no_options (); `Libvirt -+ | `Local -> no_options (); `Local -+ | `Null -> no_options (); `Null -+ | `RHV -> no_options (); `RHV -+ | `QEmu -> no_options (); `QEmu -+ | `VDSM -> -+ if is_query then ( -+ Output_vdsm.print_output_options (); -+ exit 0 -+ ) -+ else ( -+ let vdsm_options = -+ Output_vdsm.parse_output_options output_options in -+ `VDSM vdsm_options -+ ) in -+ - (* Parse out the password from the password file. *) - let password = - match password_file with -@@ -367,27 +411,6 @@ read the man page virt-v2v(1). - let password = read_first_line_from_file filename in - Some password in - -- (* Input transport affects whether some parameters should or -- * should not be used. -- *) -- (match input_transport with -- | None -- | Some `SSH -> -- if !vddk_config <> None || -- !vddk_cookie <> None || -- !vddk_libdir <> None || -- !vddk_nfchostport <> None || -- !vddk_port <> None || -- !vddk_snapshot <> None || -- !vddk_thumbprint <> None || -- !vddk_transports <> None || -- !vddk_vimapiver <> None then -- error (f_"‘--vddk-*’ options should only be used when conversion via the nbdkit VDDK plugin has been enabled, ie. using ‘-it vddk’.") -- | Some `VDDK -> -- if !vddk_thumbprint = None then -- error (f_"‘--vddk-thumbprint’ is required when using ‘-it vddk’.") -- ); -- - (* Parsing of the argument(s) depends on the input mode. *) - let input = - match input_mode with -@@ -413,11 +436,10 @@ read the man page virt-v2v(1). - let input_transport = - match input_transport with - | None -> None -- | Some `VDDK -> Some `VDDK -+ | (Some (`VDDK _) as vddk) -> vddk - | Some `SSH -> - error (f_"only ‘-it vddk’ can be used here") in -- Input_libvirt.input_libvirt vddk_options password -- input_conn input_transport guest -+ Input_libvirt.input_libvirt password input_conn input_transport guest - - | `LibvirtXML -> - (* -i libvirtxml: Expecting a filename (XML file). *) -@@ -448,7 +470,7 @@ read the man page virt-v2v(1). - match input_transport with - | None -> None - | Some `SSH -> Some `SSH -- | Some `VDDK -> -+ | Some (`VDDK _) -> - error (f_"only ‘-it ssh’ can be used here") in - Input_vmx.input_vmx input_transport arg in - -@@ -546,7 +568,7 @@ read the man page virt-v2v(1). - Output_rhv.output_rhv os output_alloc, - output_format, output_alloc - -- | `VDSM -> -+ | `VDSM vdsm_options -> - if output_password <> None then - error_option_cannot_be_used_in_output_mode "vdsm" "-op"; - let os = -@@ -556,21 +578,6 @@ read the man page virt-v2v(1). - | Some d -> d in - if qemu_boot then - error_option_cannot_be_used_in_output_mode "vdsm" "--qemu-boot"; -- let vdsm_vm_uuid = -- match vdsm_vm_uuid with -- | None -> -- error (f_"-o vdsm: --vdsm-image-uuid was not specified") -- | Some s -> s in -- if vdsm_image_uuids = [] || vdsm_vol_uuids = [] then -- error (f_"-o vdsm: either --vdsm-vol-uuid or --vdsm-vm-uuid was not specified"); -- let vdsm_options = { -- Output_vdsm.image_uuids = vdsm_image_uuids; -- vol_uuids = vdsm_vol_uuids; -- 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/input_libvirt.ml b/v2v/input_libvirt.ml -index 25c81b924..377257dc2 100644 ---- a/v2v/input_libvirt.ml -+++ b/v2v/input_libvirt.ml -@@ -27,7 +27,7 @@ open Types - open Utils - - (* Choose the right subclass based on the URI. *) --let input_libvirt vddk_options password libvirt_uri input_transport guest = -+let input_libvirt password libvirt_uri input_transport guest = - match libvirt_uri with - | None -> - Input_libvirt_other.input_libvirt_other password libvirt_uri guest -@@ -53,7 +53,7 @@ let input_libvirt vddk_options password libvirt_uri input_transport guest = - password libvirt_uri parsed_uri server guest - - (* vCenter or ESXi using nbdkit vddk plugin *) -- | Some server, Some ("esx"|"gsx"|"vpx"), Some `VDDK -> -+ | Some server, Some ("esx"|"gsx"|"vpx"), Some (`VDDK vddk_options) -> - Input_libvirt_vddk.input_libvirt_vddk vddk_options password - libvirt_uri parsed_uri guest - -diff --git a/v2v/input_libvirt.mli b/v2v/input_libvirt.mli -index 6f9162482..08824bb67 100644 ---- a/v2v/input_libvirt.mli -+++ b/v2v/input_libvirt.mli -@@ -18,7 +18,7 @@ - - (** [-i libvirt] source. *) - --val input_libvirt : Input_libvirt_vddk.vddk_options -> string option -> string option -> [`VDDK] option -> string -> Types.input --(** [input_libvirt vddk_options password libvirt_uri input_transport guest] -+val input_libvirt : string option -> string option -> [`VDDK of Input_libvirt_vddk.vddk_options] option -> string -> Types.input -+(** [input_libvirt password libvirt_uri input_transport guest] - creates and returns a new {!Types.input} object specialized for reading - input from libvirt sources. *) -diff --git a/v2v/input_libvirt_vddk.ml b/v2v/input_libvirt_vddk.ml -index a53f3e71d..0b3ed7af9 100644 ---- a/v2v/input_libvirt_vddk.ml -+++ b/v2v/input_libvirt_vddk.ml -@@ -33,22 +33,73 @@ open Xpath_helpers - - open Printf - --type vddk_options = { -- vddk_config : string option; -- vddk_cookie : string option; -- vddk_libdir : string option; -- vddk_nfchostport : string option; -- vddk_port : string option; -- vddk_snapshot : string option; -- vddk_thumbprint : string option; -- vddk_transports : string option; -- vddk_vimapiver : string option; --} -+type vddk_options = (string * string) list -+ -+(* List of vddk-* input options. *) -+let vddk_option_keys = -+ [ "config"; -+ "cookie"; -+ "libdir"; -+ "nfchostport"; -+ "port"; -+ "snapshot"; -+ "thumbprint"; -+ "transports"; -+ "vimapiver" ] -+ -+let print_input_options () = -+ printf (f_"Input options (-io) which can be used with -it vddk: -+ -+ -io vddk-thumbprint=xx:xx:xx:... -+ VDDK server thumbprint (required) -+ -+All other settings are optional: -+ -+ -io vddk-config=FILE VDDK configuration file -+ -io vddk-cookie=COOKIE VDDK cookie -+ -io vddk-libdir=LIBDIR VDDK library parent directory -+ -io vddk-nfchostport=PORT VDDK nfchostport -+ -io vddk-port=PORT VDDK port -+ -io vddk-snapshot=SNAPSHOT-MOREF -+ VDDK snapshot moref -+ -io vddk-transports=MODE:MODE:.. -+ VDDK transports -+ -io vddk-vimapiver=APIVER VDDK vimapiver -+ -+Refer to nbdkit-vddk-plugin(1) and the VDDK documentation for further -+information on these settings. -+") -+ -+let parse_input_options options = -+ (* Check there are no options we don't understand. Also removes -+ * the "vddk-" prefix from the internal list. -+ *) -+ let options = -+ List.map ( -+ fun (key, value) -> -+ let error_invalid_key () = -+ error (f_"-it vddk: ‘-io %s’ is not a valid input option") key -+ in -+ if not (String.is_prefix key "vddk-") then error_invalid_key (); -+ let key = String.sub key 5 (String.length key-5) in -+ if not (List.mem key vddk_option_keys) then error_invalid_key (); -+ -+ (key, value) -+ ) options in -+ -+ (* Check no option appears twice. *) -+ let keys = List.map fst options in -+ if List.length keys <> List.length (List.sort_uniq keys) then -+ error (f_"-it vddk: duplicate -io options on the command line"); -+ -+ options - - (* Subclass specialized for handling VMware via nbdkit vddk plugin. *) - class input_libvirt_vddk vddk_options password libvirt_uri parsed_uri guest = - (* The VDDK path. *) -- let libdir = vddk_options.vddk_libdir in -+ let libdir = -+ try Some (List.assoc "libdir" vddk_options) -+ with Not_found -> None in - - (* VDDK libraries are located under lib32/ or lib64/ relative to the - * libdir. Note this is unrelated to Linux multilib or multiarch. -@@ -68,7 +119,7 @@ class input_libvirt_vddk vddk_options password libvirt_uri parsed_uri guest = - | None -> () - | Some libdir -> - if not (is_directory libdir) then -- error (f_"‘--vddk-libdir %s’ does not point to a directory. See \"INPUT FROM VDDK\" in the virt-v2v(1) manual.") libdir -+ error (f_"‘-io vddk-libdir=%s’ does not point to a directory. See \"INPUT FROM VDDK\" in the virt-v2v(1) manual.") libdir - ); - - (match library_path with -@@ -122,15 +173,15 @@ See also \"INPUT FROM VDDK\" in the virt-v2v(1) manual.") - else - error (f_"nbdkit VDDK plugin is not installed or not working. It is required if you want to use VDDK. - --It looks like you did not set the right path in the ‘--vddk-libdir’ option, or your copy of the VDDK directory is incomplete. There should be a library called ’/%s/libvixDiskLib.so.?’. -+It looks like you did not set the right path in the ‘-io vddk-libdir’ option, or your copy of the VDDK directory is incomplete. There should be a library called ’/%s/libvixDiskLib.so.?’. - - See also \"INPUT FROM VDDK\" in the virt-v2v(1) manual.") libNN - ) - in - - let error_unless_thumbprint () = -- if vddk_options.vddk_thumbprint = None then -- error (f_"You must pass the ‘--vddk-thumbprint’ option with the SSL thumbprint of the VMware server. To find the thumbprint, see the nbdkit-vddk-plugin(1) manual. See also \"INPUT FROM VDDK\" in the virt-v2v(1) manual.") -+ if not (List.mem_assoc "thumbprint" vddk_options) then -+ error (f_"You must pass the ‘-io vddk-thumbprint’ option with the SSL thumbprint of the VMware server. To find the thumbprint, see the nbdkit-vddk-plugin(1) manual. See also \"INPUT FROM VDDK\" in the virt-v2v(1) manual.") - in - - (* Check that nbdkit was compiled with SELinux support (for the -@@ -147,18 +198,6 @@ See also \"INPUT FROM VDDK\" in the virt-v2v(1) manual.") libNN - error (f_"nbdkit was compiled without SELinux support. You will have to recompile nbdkit with libselinux-devel installed, or else set SELinux to Permissive mode while doing the conversion.") - in - -- (* List of passthrough parameters. *) -- let vddk_passthrus = -- [ "config", (fun { vddk_config } -> vddk_config); -- "cookie", (fun { vddk_cookie } -> vddk_cookie); -- "libdir", (fun { vddk_libdir } -> vddk_libdir); -- "nfchostport", (fun { vddk_nfchostport } -> vddk_nfchostport); -- "port", (fun { vddk_port } -> vddk_port); -- "snapshot", (fun { vddk_snapshot } -> vddk_snapshot); -- "thumbprint", (fun { vddk_thumbprint } -> vddk_thumbprint); -- "transports", (fun { vddk_transports } -> vddk_transports); -- "vimapiver", (fun { vddk_vimapiver } -> vddk_vimapiver) ] in -- - object - inherit input_libvirt password libvirt_uri guest as super - -@@ -172,14 +211,9 @@ object - - method as_options = - let pt_options = -- String.concat "" ( -- List.map ( -- fun (name, get_field) -> -- match get_field vddk_options with -- | None -> "" -- | Some field -> sprintf " --vddk-%s %s" name field -- ) vddk_passthrus -- ) in -+ String.concat "" -+ (List.map (fun (k, v) -> -+ sprintf " -io vddk-%s=%s" k v) vddk_options) in - sprintf "%s -it vddk %s" - super#as_options (* superclass prints "-i libvirt etc" *) - pt_options -@@ -284,11 +318,7 @@ object - add_arg (sprintf "vm=moref=%s" moref); - - (* The passthrough parameters. *) -- List.iter ( -- fun (name, get_field) -> -- Option.may (fun field -> add_arg (sprintf "%s=%s" name field)) -- (get_field vddk_options) -- ) vddk_passthrus; -+ List.iter (fun (k, v) -> add_arg (sprintf "%s=%s" k v)) vddk_options; - - get_args () in - -diff --git a/v2v/input_libvirt_vddk.mli b/v2v/input_libvirt_vddk.mli -index c8606c72a..1cebba506 100644 ---- a/v2v/input_libvirt_vddk.mli -+++ b/v2v/input_libvirt_vddk.mli -@@ -18,19 +18,13 @@ - - (** [-i libvirt] when the source is VMware via nbdkit vddk plugin *) - --type vddk_options = { -- vddk_config : string option; -- vddk_cookie : string option; -- vddk_libdir : string option; -- vddk_nfchostport : string option; -- vddk_port : string option; -- vddk_snapshot : string option; -- vddk_thumbprint : string option; -- vddk_transports : string option; -- vddk_vimapiver : string option; --} -+type vddk_options - (** Various options passed through to the nbdkit vddk plugin unmodified. *) - -+val print_input_options : unit -> unit -+val parse_input_options : (string * string) list -> vddk_options -+(** Print and parse vddk -io options. *) -+ - val input_libvirt_vddk : vddk_options -> string option -> string option -> Xml.uri -> string -> Types.input - (** [input_libvirt_vddk vddk_options password libvirt_uri parsed_uri guest] - creates and returns a {!Types.input} object specialized for reading -diff --git a/v2v/output_vdsm.ml b/v2v/output_vdsm.ml -index b76a2e930..92b3fd122 100644 ---- a/v2v/output_vdsm.ml -+++ b/v2v/output_vdsm.ml -@@ -35,23 +35,90 @@ type vdsm_options = { - ovf_flavour : Create_ovf.ovf_flavour; - } - -+let ovf_flavours_str = String.concat "|" Create_ovf.ovf_flavours -+ -+let print_output_options () = -+ printf (f_"Output options (-oo) which can be used with -o vdsm: -+ -+ -oo vdsm-compat=0.10|1.1 Write qcow2 with compat=0.10|1.1 -+ (default: 0.10) -+ -oo vdsm-vm-uuid=UUID VM UUID (required) -+ -oo vdsm-ovf-output=DIR OVF metadata directory (required) -+ -oo vdsm-ovf-flavour=%s -+ Set the type of generated OVF (default: rhvexp) -+ -+For each disk you must supply one of each of these options: -+ -+ -oo vdsm-image-uuid=UUID Image directory UUID -+ -oo vdsm-vol-uuid=UUID Disk volume UUID -+") ovf_flavours_str -+ -+let parse_output_options options = -+ let vm_uuid = ref None in -+ let ovf_output = ref None in (* default "." *) -+ let compat = ref "0.10" in -+ let ovf_flavour = ref Create_ovf.RHVExportStorageDomain in -+ let image_uuids = ref [] in -+ let vol_uuids = ref [] in -+ -+ List.iter ( -+ function -+ | "vdsm-compat", "0.10" -> compat := "0.10" -+ | "vdsm-compat", "1.1" -> compat := "1.1" -+ | "vdsm-compat", v -> -+ error (f_"-o vdsm: unknown vdsm-compat level ‘%s’") v -+ | "vdsm-vm-uuid", v -> -+ if !vm_uuid <> None then -+ error (f_"-o vdsm: -oo vdsm-vm-uuid set twice"); -+ vm_uuid := Some v; -+ | "vdsm-ovf-output", v -> -+ if !ovf_output <> None then -+ error (f_"-o vdsm: -oo vdsm-ovf-output set twice"); -+ ovf_output := Some v; -+ | "vdsm-ovf-flavour", v -> -+ ovf_flavour := Create_ovf.ovf_flavour_of_string v -+ | "vdsm-image-uuid", v -> -+ List.push_front v image_uuids -+ | "vdsm-vol-uuid", v -> -+ List.push_front v vol_uuids -+ | k, _ -> -+ error (f_"-o vdsm: unknown output option ‘-oo %s’") k -+ ) options; -+ -+ let compat = !compat in -+ let image_uuids = List.rev !image_uuids in -+ let vol_uuids = List.rev !vol_uuids in -+ if image_uuids = [] || vol_uuids = [] then -+ error (f_"-o vdsm: either -oo vdsm-vol-uuid or -oo vdsm-vm-uuid was not specified"); -+ let vm_uuid = -+ match !vm_uuid with -+ | None -> -+ error (f_"-o vdsm: -oo vdsm-image-uuid was not specified") -+ | Some uuid -> uuid in -+ let ovf_output = Option.default "." !ovf_output in -+ let ovf_flavour = !ovf_flavour in -+ -+ { image_uuids; vol_uuids; vm_uuid; ovf_output; compat; ovf_flavour } -+ - class output_vdsm os vdsm_options output_alloc = - object - inherit output - - method as_options = -- sprintf "-o vdsm -os %s%s%s --vdsm-vm-uuid %s --vdsm-ovf-output %s%s%s" os -+ sprintf "-o vdsm -os %s%s%s -oo vdsm-vm-uuid=%s -oo vdsm-ovf-output=%s%s%s" os - (String.concat "" -- (List.map (sprintf " --vdsm-image-uuid %s") vdsm_options.image_uuids)) -+ (List.map (sprintf " -oo vdsm-image-uuid=%s") -+ vdsm_options.image_uuids)) - (String.concat "" -- (List.map (sprintf " --vdsm-vol-uuid %s") vdsm_options.vol_uuids)) -+ (List.map (sprintf " -oo vdsm-vol-uuid=%s") -+ vdsm_options.vol_uuids)) - vdsm_options.vm_uuid - vdsm_options.ovf_output - (match vdsm_options.compat with - | "0.10" -> "" (* currently this is the default, so don't print it *) -- | s -> sprintf " --vdsm-compat=%s" s) -+ | s -> sprintf " -oo vdsm-compat=%s" s) - (match vdsm_options.ovf_flavour with -- | Create_ovf.OVirt -> "--vdsm-ovf-flavour=ovf" -+ | Create_ovf.OVirt -> "-oo vdsm-ovf-flavour=ovf" - (* currently this is the default, so don't print it *) - | Create_ovf.RHVExportStorageDomain -> "") - -@@ -84,7 +151,7 @@ object - method prepare_targets _ targets = - if List.length vdsm_options.image_uuids <> List.length targets || - List.length vdsm_options.vol_uuids <> List.length targets then -- error (f_"the number of ‘--vdsm-image-uuid’ and ‘--vdsm-vol-uuid’ parameters passed on the command line has to match the number of guest disk images (for this guest: %d)") -+ error (f_"the number of ‘-oo vdsm-image-uuid’ and ‘-oo vdsm-vol-uuid’ parameters passed on the command line has to match the number of guest disk images (for this guest: %d)") - (List.length targets); - - let mp, uuid = -diff --git a/v2v/output_vdsm.mli b/v2v/output_vdsm.mli -index 6ed684638..36f327900 100644 ---- a/v2v/output_vdsm.mli -+++ b/v2v/output_vdsm.mli -@@ -18,16 +18,13 @@ - - (** [-o vdsm] target. *) - --type vdsm_options = { -- image_uuids : string list; (* --vdsm-image-uuid (multiple) *) -- vol_uuids : string list; (* --vdsm-vol-uuid (multiple) *) -- 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; --} -+type vdsm_options - (** Miscellaneous extra command line parameters used by VDSM. *) - -+val print_output_options : unit -> unit -+val parse_output_options : (string * string) list -> vdsm_options -+(** Print and parse vdsm -oo options. *) -+ - val output_vdsm : string -> vdsm_options -> Types.output_allocation -> Types.output - (** [output_vdsm os vdsm_options output_alloc] creates and - returns a new {!Types.output} object specialized for writing -diff --git a/v2v/test-v2v-docs.sh b/v2v/test-v2v-docs.sh -index 0e3bd916a..e1e22b599 100755 ---- a/v2v/test-v2v-docs.sh -+++ b/v2v/test-v2v-docs.sh -@@ -22,4 +22,33 @@ $TEST_FUNCTIONS - skip_if_skipped - - $top_srcdir/podcheck.pl virt-v2v.pod virt-v2v \ -- --ignore=--debug-overlay,--ic,--if,--it,--no-trim,--oa,--oc,--of,--on,--op,--os,--vmtype -+ --ignore=\ -+--debug-overlay,\ -+--ic,\ -+--if,\ -+--io,\ -+--it,\ -+--no-trim,\ -+--oa,\ -+--oc,\ -+--of,\ -+--on,\ -+--oo,\ -+--op,\ -+--os,\ -+--vddk-config,\ -+--vddk-cookie,\ -+--vddk-libdir,\ -+--vddk-nfchostport,\ -+--vddk-port,\ -+--vddk-snapshot,\ -+--vddk-thumbprint,\ -+--vddk-transports,\ -+--vddk-vimapiver,\ -+--vdsm-compat,\ -+--vdsm-image-uuid,\ -+--vdsm-ovf-flavour,\ -+--vdsm-ovf-output,\ -+--vdsm-vm-uuid,\ -+--vdsm-vol-uuid,\ -+--vmtype -diff --git a/v2v/test-v2v-it-vddk-io-query.sh b/v2v/test-v2v-it-vddk-io-query.sh -new file mode 100755 -index 000000000..014e30207 ---- /dev/null -+++ b/v2v/test-v2v-it-vddk-io-query.sh -@@ -0,0 +1,38 @@ -+#!/bin/bash - -+# libguestfs virt-v2v test script -+# Copyright (C) 2018 Red Hat Inc. -+# -+# This program is free software; you can redistribute it and/or modify -+# it under the terms of the GNU General Public License as published by -+# the Free Software Foundation; either version 2 of the License, or -+# (at your option) any later version. -+# -+# This program is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+# GNU General Public License for more details. -+# -+# You should have received a copy of the GNU General Public License -+# along with this program; if not, write to the Free Software -+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ -+# Test -io "?" option. -+ -+set -e -+ -+$TEST_FUNCTIONS -+skip_if_skipped -+ -+export VIRT_TOOLS_DATA_DIR="$top_srcdir/test-data/fake-virt-tools" -+export VIRTIO_WIN="$top_srcdir/test-data/fake-virtio-win" -+ -+f=test-v2v-it-vddk-io-query.actual -+rm -f $f -+ -+$VG virt-v2v --debug-gc \ -+ -it vddk -io "?" > $f -+ -+grep -- "-io vddk-config" $f -+grep -- "-io vddk-thumbprint" $f -+ -+rm $f -diff --git a/v2v/test-v2v-o-vdsm-oo-query.sh b/v2v/test-v2v-o-vdsm-oo-query.sh -new file mode 100755 -index 000000000..5691446ea ---- /dev/null -+++ b/v2v/test-v2v-o-vdsm-oo-query.sh -@@ -0,0 +1,38 @@ -+#!/bin/bash - -+# libguestfs virt-v2v test script -+# Copyright (C) 2018 Red Hat Inc. -+# -+# This program is free software; you can redistribute it and/or modify -+# it under the terms of the GNU General Public License as published by -+# the Free Software Foundation; either version 2 of the License, or -+# (at your option) any later version. -+# -+# This program is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+# GNU General Public License for more details. -+# -+# You should have received a copy of the GNU General Public License -+# along with this program; if not, write to the Free Software -+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ -+# Test -oo "?" option. -+ -+set -e -+ -+$TEST_FUNCTIONS -+skip_if_skipped -+ -+export VIRT_TOOLS_DATA_DIR="$top_srcdir/test-data/fake-virt-tools" -+export VIRTIO_WIN="$top_srcdir/test-data/fake-virtio-win" -+ -+f=test-v2v-o-vdsm-oo-query.actual -+rm -f $f -+ -+$VG virt-v2v --debug-gc \ -+ -o vdsm -oo "?" > $f -+ -+grep -- "-oo vdsm-compat" $f -+grep -- "-oo vdsm-image-uuid" $f -+ -+rm $f -diff --git a/v2v/test-v2v-o-vdsm-options.sh b/v2v/test-v2v-o-vdsm-options.sh -index 4ad5d4aad..65ce1234e 100755 ---- a/v2v/test-v2v-o-vdsm-options.sh -+++ b/v2v/test-v2v-o-vdsm-options.sh -@@ -16,7 +16,7 @@ - # along with this program; if not, write to the Free Software - # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - --# Test -o vdsm options --vdsm-*-uuid -+# Test -o vdsm options -oo vdsm-*-uuid - - set -e - set -x -@@ -44,19 +44,19 @@ mkdir $d/12345678-1234-1234-1234-123456789abc/master - mkdir $d/12345678-1234-1234-1234-123456789abc/master/vms - mkdir $d/12345678-1234-1234-1234-123456789abc/master/vms/VM - --# The --vdsm-*-uuid options don't actually check that the -+# The -oo vdsm-*-uuid options don't actually check that the - # parameter is a UUID, which is useful here. - - $VG virt-v2v --debug-gc \ - -i libvirt -ic "$libvirt_uri" windows \ - -o vdsm -os $d/12345678-1234-1234-1234-123456789abc \ - -of qcow2 \ -- --vdsm-image-uuid IMAGE \ -- --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-ovf-flavour=ovirt -+ -oo vdsm-image-uuid=IMAGE \ -+ -oo vdsm-vol-uuid=VOL \ -+ -oo vdsm-vm-uuid=VM \ -+ -oo vdsm-ovf-output=$d/12345678-1234-1234-1234-123456789abc/master/vms/VM \ -+ -oo vdsm-compat=1.1 \ -+ -oo 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 00ba45555..69ca23dfd 100644 ---- a/v2v/virt-v2v.pod -+++ b/v2v/virt-v2v.pod -@@ -397,6 +397,47 @@ See L below. - - Conflicts with all I<-o *> options. - -+=item B<-io> OPTION=VALUE -+ -+Set input option(s) related to the current input mode or transport. -+To display short help on what options are available you can use: -+ -+ virt-v2v -it vddk -io "?" -+ -+=item B<-io vddk-libdir=>LIBDIR -+ -+Set the VDDK library directory. This directory should I -+subdirectories called F, F etc., but do not include -+F actually in the parameter. -+ -+In most cases this parameter is required when using the I<-it vddk> -+(VDDK) transport. See L below for details. -+ -+=item B<-io vddk-thumbprint=>xx:xx:xx:... -+ -+Set the thumbprint of the remote VMware server. -+ -+This parameter is required when using the I<-it vddk> (VDDK) transport. -+See L below for details. -+ -+=item B<-io vddk-config=>FILENAME -+ -+=item B<-io vddk-cookie=>COOKIE -+ -+=item B<-io vddk-nfchostport=>PORT -+ -+=item B<-io vddk-port=>PORT -+ -+=item B<-io vddk-snapshot=>SNAPSHOT-MOREF -+ -+=item B<-io vddk-transports=>MODE:MODE:... -+ -+=item B<-io vddk-vimapiver=>APIVER -+ -+When using VDDK mode, these options are passed unmodified to the -+L VDDK plugin. Please refer to L. -+These are all optional. -+ - =item B<-it> B - - When using I<-i vmx>, this enables the ssh transport. -@@ -406,7 +447,7 @@ See L below. - - Use VMware VDDK as a transport to copy the input disks. See - L below. If you use this parameter then you may --need to use other I<--vddk*> options to specify how to connect through -+need to use other I<-io vddk*> options to specify how to connect through - VDDK. - - =item B<--keys-from-stdin> -@@ -569,6 +610,95 @@ If not specified, then the input format is used. - Rename the guest when converting it. If this option is not used then - the output name is the same as the input name. - -+=item B<-oo> OPTION=VALUE -+ -+Set output option(s) related to the current output mode. -+To display short help on what options are available you can use: -+ -+ virt-v2v -o vdsm -oo "?" -+ -+=item B<-oo vdsm-compat=0.10> -+ -+=item B<-oo vdsm-compat=1.1> -+ -+If I<-o vdsm> and the output format is qcow2, then we add the qcow2 -+I option to the output file for compatibility with RHEL 6 -+(see L). -+ -+If I<-oo vdsm-compat=1.1> is used then modern qcow2 (I) -+files are generated instead. -+ -+Currently I<-oo vdsm-compat=0.10> is the default, but this will change -+to I<-oo vdsm-compat=1.1> in a future version of virt-v2v (when we can -+assume that everyone is using a modern version of qemu). -+ -+B output>. All other output -+modes (including I<-o rhv>) generate modern qcow2 I -+files, always. -+ -+If this option is available, then C will appear in -+the I<--machine-readable> output. -+ -+=item B<-oo vdsm-image-uuid=>UUID -+ -+=item B<-oo vdsm-vol-uuid=>UUID -+ -+=item B<-oo vdsm-vm-uuid=>UUID -+ -+=item B<-oo vdsm-ovf-output=>DIR -+ -+Normally the RHV output mode chooses random UUIDs for the target -+guest. However VDSM needs to control the UUIDs and passes these -+parameters when virt-v2v runs under VDSM control. The parameters -+control: -+ -+=over 4 -+ -+=item * -+ -+the image directory of each guest disk (I<-oo vdsm-image-uuid>) (this -+option is passed once for each guest disk) -+ -+=item * -+ -+UUIDs for each guest disk (I<-oo vdsm-vol-uuid>) (this option -+is passed once for each guest disk) -+ -+=item * -+ -+the OVF file name (I<-oo vdsm-vm-uuid>). -+ -+=item * -+ -+the OVF output directory (default current directory) (I<-oo vdsm-ovf-output>). -+ -+=back -+ -+The format of UUIDs is: C<12345678-1234-1234-1234-123456789abc> (each -+hex digit can be C<0-9> or C), conforming to S. -+ -+These options can only be used with I<-o vdsm>. -+ -+=item B<-oo 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, but this may change in -+the future. -+ - =item B<-op> file - - Supply a file containing a password to be used when connecting to the -@@ -670,122 +800,6 @@ boot an operating system from the first virtio disk. Specifically, - F must be on the first virtio disk, and it cannot chainload an - OS which is not in the first virtio disk. - --=item B<--vddk-libdir> LIBDIR -- --Set the VDDK library directory. This directory should I --subdirectories called F, F etc., but do not include --F actually in the parameter. -- --In most cases this parameter is required when using the I<-it vddk> --(VDDK) transport. See L below for details. -- --=item B<--vddk-thumbprint> xx:xx:xx:... -- --Set the thumbprint of the remote VMware server. -- --This parameter is required when using the I<-it vddk> (VDDK) transport. --See L below for details. -- --=item B<--vddk-config> FILENAME -- --=item B<--vddk-cookie> COOKIE -- --=item B<--vddk-nfchostport> PORT -- --=item B<--vddk-port> PORT -- --=item B<--vddk-snapshot> SNAPSHOT-MOREF -- --=item B<--vddk-transports> MODE:MODE:... -- --=item B<--vddk-vimapiver> APIVER -- --When using VDDK mode, these options are passed unmodified to the --L VDDK plugin. Please refer to L. --These are all optional. -- --=item B<--vdsm-compat=0.10> -- --=item B<--vdsm-compat=1.1> -- --If I<-o vdsm> and the output format is qcow2, then we add the qcow2 --I option to the output file for compatibility with RHEL 6 --(see L). -- --If I<--vdsm-compat=1.1> is used then modern qcow2 (I) --files are generated instead. -- --Currently I<--vdsm-compat=0.10> is the default, but this will change --to I<--vdsm-compat=1.1> in a future version of virt-v2v (when we can --assume that everyone is using a modern version of qemu). -- --B output>. All other output --modes (including I<-o rhv>) generate modern qcow2 I --files, always. -- --If this option is available, then C will appear in --the I<--machine-readable> output. -- --=item B<--vdsm-image-uuid> UUID -- --=item B<--vdsm-vol-uuid> UUID -- --=item B<--vdsm-vm-uuid> UUID -- --=item B<--vdsm-ovf-output> -- --Normally the RHV output mode chooses random UUIDs for the target --guest. However VDSM needs to control the UUIDs and passes these --parameters when virt-v2v runs under VDSM control. The parameters --control: -- --=over 4 -- --=item * -- --the image directory of each guest disk (I<--vdsm-image-uuid>) (this --option is passed once for each guest disk) -- --=item * -- --UUIDs for each guest disk (I<--vdsm-vol-uuid>) (this option --is passed once for each guest disk) -- --=item * -- --the OVF file name (I<--vdsm-vm-uuid>). -- --=item * -- --the OVF output directory (default current directory) (I<--vdsm-ovf-output>). -- --=back -- --The format of UUIDs is: C<12345678-1234-1234-1234-123456789abc> (each --hex digit can be C<0-9> or C), conforming to S. -- --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, but this may change in --the future. -- - =item B<-v> - - =item B<--verbose> -@@ -1679,15 +1693,15 @@ SSL thumbprint: - $ virt-v2v \ - -ic 'vpx://root@vcenter.example.com/Datacenter/esxi?no_verify=1' \ - -it vddk \ -- --vddk-libdir /path/to/vmware-vix-disklib-distrib \ -- --vddk-thumbprint xx:xx:xx:... \ -+ -io vddk-libdir=/path/to/vmware-vix-disklib-distrib \ -+ -io vddk-thumbprint=xx:xx:xx:... \ - "Windows 2003" \ - -o local -os /var/tmp - - Other options that you might need to add in rare circumstances include --I<--vddk-config>, I<--vddk-cookie>, I<--vddk-nfchostport>, --I<--vddk-port>, I<--vddk-snapshot>, I<--vddk-transports> and --I<--vddk-vimapiver>, which are all explained in the -+I<-io vddk-config>, I<-io vddk-cookie>, I<-io vddk-nfchostport>, -+I<-io vddk-port>, I<-io vddk-snapshot>, I<-io vddk-transports> and -+I<-io vddk-vimapiver>, which are all explained in the - L documentation. - - =head2 VDDK: DEBUGGING VDDK FAILURES --- -2.21.0 - diff --git a/SOURCES/0009-v2v-linux-improve-arch-detection-from-modules-RHBZ-1.patch b/SOURCES/0009-v2v-linux-improve-arch-detection-from-modules-RHBZ-1.patch new file mode 100644 index 0000000..ce35612 --- /dev/null +++ b/SOURCES/0009-v2v-linux-improve-arch-detection-from-modules-RHBZ-1.patch @@ -0,0 +1,61 @@ +From 10afd834b5e1787cb2b22fce96de30baf37b5b2b Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Wed, 20 Mar 2019 12:32:02 +0100 +Subject: [PATCH] v2v: linux: improve arch detection from modules + (RHBZ#1690574) + +Try to look for a well known kernel module (so far only virtio, or kvm) +to use for detecting the architecture of a kernel. This way, we can +avoid picking 3rd party modules that cause troubles. + +(cherry picked from commit 363b5e0b4ecebe861a9aafe8bce5a8390b54571c) +--- + v2v/linux_kernels.ml | 30 +++++++++++++++++++++++++++--- + 1 file changed, 27 insertions(+), 3 deletions(-) + +diff --git a/v2v/linux_kernels.ml b/v2v/linux_kernels.ml +index 889ec2f2a..30160f0da 100644 +--- a/v2v/linux_kernels.ml ++++ b/v2v/linux_kernels.ml +@@ -185,11 +185,35 @@ let detect_kernels (g : G.guestfs) inspect family bootloader = + assert (List.length modules > 0); + + (* Determine the kernel architecture by looking at the +- * architecture of an arbitrary kernel module. ++ * architecture of a kernel module. ++ * ++ * To avoid architecture detection issues with 3rd party ++ * modules (RHBZ#1690574), try to pick one of the well ++ * known modules, if available. Otherwise, an arbitrary ++ * module is used. + *) + let arch = +- let any_module = modpath ^ List.hd modules in +- g#file_architecture (g#realpath any_module) in ++ (* Well known kernel modules. *) ++ let candidates = [ "virtio"; "kvm" ] in ++ let all_candidates = List.flatten ( ++ List.map ( ++ fun f -> ++ [ "/" ^ f ^ ".o"; "/" ^ f ^ ".ko"; "/" ^ f ^ ".ko.xz" ] ++ ) candidates ++ ) in ++ let candidate = ++ try ++ List.find ( ++ fun m -> ++ List.exists (String.is_suffix m) all_candidates ++ ) modules ++ with Not_found -> ++ (* No known module found, pick an arbitrary one ++ * (the first). ++ *) ++ List.hd modules in ++ let candidate = modpath ^ candidate in ++ g#file_architecture (g#realpath candidate) in + + (* Just return the module names, without path or extension. *) + let modules = List.filter_map ( +-- +2.25.4 + diff --git a/SOURCES/0010-Use-proper-label-for-nbdkit-sockets.patch b/SOURCES/0010-Use-proper-label-for-nbdkit-sockets.patch new file mode 100644 index 0000000..6b66ed9 --- /dev/null +++ b/SOURCES/0010-Use-proper-label-for-nbdkit-sockets.patch @@ -0,0 +1,63 @@ +From 54b63460b7602ac5c68d6e58ab60e7f85877cefc Mon Sep 17 00:00:00 2001 +From: Martin Kletzander +Date: Mon, 27 May 2019 13:30:05 +0200 +Subject: [PATCH] Use proper label for nbdkit sockets + +While svirt_t can be used for sockets it does not always guarantee that it will +be accessible from a virtual machine. The VM might be running under svirt_tcg_t +context which will need a svirt_tcg_t label on the socket in order to access it. + +There is, however, another label, svirt_socket_t, which is accessible from +virt_domain: + + # sesearch -A -s svirt_t -c unix_stream_socket -p connectto + ... + allow virt_domain svirt_socket_t:unix_stream_socket { ... connectto ... }; + ... + +And virt_domain is a type attribute of both svirt_t and svirt_tcg_t: + + # seinfo -x -a virt_domain + Type Attributes: 1 + attribute virt_domain; + svirt_t + svirt_tcg_t + +Resolves: https://bugzilla.redhat.com/1698437 + +Signed-off-by: Martin Kletzander +(cherry picked from commit c2918b8b74506523a723b804d452816a059c5e50) +--- + v2v/input_libvirt_vddk.ml | 2 +- + v2v/output_rhv_upload.ml | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/v2v/input_libvirt_vddk.ml b/v2v/input_libvirt_vddk.ml +index 97c7cb532..567233d58 100644 +--- a/v2v/input_libvirt_vddk.ml ++++ b/v2v/input_libvirt_vddk.ml +@@ -290,7 +290,7 @@ object + add_arg "--newstyle"; (* use newstyle NBD protocol *) + add_arg "--exportname"; add_arg "/"; + if have_selinux then ( (* label the socket so qemu can open it *) +- add_arg "--selinux-label"; add_arg "system_u:object_r:svirt_t:s0" ++ add_arg "--selinux-label"; add_arg "system_u:object_r:svirt_socket_t:s0" + ); + + (* Name of the plugin. Everything following is a plugin parameter. *) +diff --git a/v2v/output_rhv_upload.ml b/v2v/output_rhv_upload.ml +index 77c39107e..c2a5c72c7 100644 +--- a/v2v/output_rhv_upload.ml ++++ b/v2v/output_rhv_upload.ml +@@ -217,7 +217,7 @@ See also the virt-v2v-output-rhv(1) manual.") + let args = + (* label the socket so qemu can open it *) + if have_selinux then +- args @ ["--selinux-label"; "system_u:object_r:svirt_t:s0"] ++ args @ ["--selinux-label"; "system_u:object_r:svirt_socket_t:s0"] + else args in + args in + +-- +2.25.4 + diff --git a/SOURCES/0010-v2v-OVF-write-ovirt-id-attribute-for-the-OS-in-OVirt.patch b/SOURCES/0010-v2v-OVF-write-ovirt-id-attribute-for-the-OS-in-OVirt.patch deleted file mode 100644 index 6ec645b..0000000 --- a/SOURCES/0010-v2v-OVF-write-ovirt-id-attribute-for-the-OS-in-OVirt.patch +++ /dev/null @@ -1,247 +0,0 @@ -From 1b4c00a3ec7c0618e8557e1e71d5782527a94828 Mon Sep 17 00:00:00 2001 -From: Pino Toscano -Date: Wed, 4 Apr 2018 18:18:32 +0200 -Subject: [PATCH] v2v: OVF: write ovirt:id attribute for the OS in OVirt - flavour - -When writing the OVF in OVirt flavour, add a ovirt:id attribute to the -OperatingSystemSection tag: this attribute represents the numeric value -of the ostype ID, which is ignored by oVirt when parsing OVFs in API -mode. - -(cherry picked from commit 593a19cc86cfa8f24c66518c8ba21222550b066a) ---- - v2v/create_ovf.ml | 202 +++++++++++++++++++++++++++++++++++++++++++++- - 1 file changed, 201 insertions(+), 1 deletion(-) - -diff --git a/v2v/create_ovf.ml b/v2v/create_ovf.ml -index 0e07afea8..730ab64b4 100644 ---- a/v2v/create_ovf.ml -+++ b/v2v/create_ovf.ml -@@ -242,6 +242,203 @@ and get_ostype = function - typ distro major minor arch product; - "Unassigned" - -+(* Determine the ovirt:id attribute from libguestfs inspection. -+ * See ovirt-engine sources, file: -+ * packaging/conf/osinfo-defaults.properties -+ * and also: -+ * https://bugzilla.redhat.com/show_bug.cgi?id=1219857#c9 -+ *) -+and get_ovirt_osid = function -+ | { i_type = "linux"; i_distro = ("rhel"|"centos"); i_major_version = 3; -+ i_arch = "i386" } -> -+ 9 -+ -+ | { i_type = "linux"; i_distro = ("rhel"|"centos"); i_major_version = 3; -+ i_arch = "x86_64" } -> -+ 15 -+ -+ | { i_type = "linux"; i_distro = ("rhel"|"centos"); i_major_version = 4; -+ i_arch = "i386" } -> -+ 8 -+ -+ | { i_type = "linux"; i_distro = ("rhel"|"centos"); i_major_version = 4; -+ i_arch = "x86_64" } -> -+ 14 -+ -+ | { i_type = "linux"; i_distro = ("rhel"|"centos"); i_major_version = 5; -+ i_arch = "i386" } -> -+ 7 -+ -+ | { i_type = "linux"; i_distro = ("rhel"|"centos"); i_major_version = 5; -+ i_arch = "x86_64" } -> -+ 13 -+ -+ | { i_type = "linux"; i_distro = ("rhel"|"centos"); i_major_version = 6; -+ i_arch = "i386" } -> -+ 18 -+ -+ | { i_type = "linux"; i_distro = ("rhel"|"centos"); i_major_version = 6; -+ i_arch = "x86_64" } -> -+ 19 -+ -+ | { i_type = "linux"; i_distro = ("rhel"|"centos"); i_major_version = 6; -+ i_minor_version = min; i_arch = ("ppc64"|"ppc64le") } when min >= 9 -> -+ 1007 -+ -+ | { i_type = "linux"; i_distro = ("rhel"|"centos"); i_major_version = 6; -+ i_arch = ("ppc64"|"ppc64le") } -> -+ 1003 -+ -+ | { i_type = "linux"; i_distro = ("rhel"|"centos"); i_major_version = 7; -+ i_arch = "x86_64" } -> -+ 24 -+ -+ | { i_type = "linux"; i_distro = ("rhel"|"centos"); i_major_version = 7; -+ i_arch = ("ppc64"|"ppc64le") } -> -+ 1006 -+ -+ | { i_type = "linux"; i_distro = ("rhel"|"centos"); i_major_version = 7; -+ i_arch = "s390x" } -> -+ 2003 -+ -+ | { i_type = "linux"; i_distro = "sles"; i_major_version = maj; -+ i_arch = "x86_64" } when maj >= 11 -> -+ 1193 -+ -+ | { i_type = "linux"; i_distro = "sles"; i_major_version = maj; -+ i_arch = ("ppc64"|"ppc64le") } when maj >= 11 -> -+ 1004 -+ -+ | { i_type = "linux"; i_distro = "sles"; i_major_version = maj; -+ i_arch = "s390x" } when maj >= 12 -> -+ 2004 -+ -+ (* Only Debian 7 is available, so use it for any 7+ version. *) -+ | { i_type = "linux"; i_distro = "debian"; i_major_version = v } -+ when v >= 7 -> -+ 1300 -+ -+ (* Only Ubuntu 12.04 to 14.04 are available, so use them starting -+ * from 12.04, and 14.04 for anything after it. -+ *) -+ | { i_type = "linux"; i_distro = "ubuntu"; i_major_version = v; -+ i_arch = ("ppc64"|"ppc64le") } when v >= 14 -> -+ 1005 -+ -+ | { i_type = "linux"; i_distro = "ubuntu"; i_major_version = v; -+ i_arch = "s390x" } when v >= 16 -> -+ 2005 -+ -+ | { i_type = "linux"; i_distro = "ubuntu"; i_major_version = v } -+ when v >= 14 -> -+ 1256 -+ -+ | { i_type = "linux"; i_distro = "ubuntu"; i_major_version = 12; -+ i_minor_version = 4 } -> -+ 1252 -+ -+ | { i_type = "linux"; i_distro = "ubuntu"; i_major_version = 12; -+ i_minor_version = 10 } -> -+ 1253 -+ -+ | { i_type = "linux"; i_distro = "ubuntu"; i_major_version = 13; -+ i_minor_version = 4 } -> -+ 1254 -+ -+ | { i_type = "linux"; i_distro = "ubuntu"; i_major_version = 13; -+ i_minor_version = 10 } -> -+ 1255 -+ -+ | { i_type = "linux"; i_arch = ("ppc64"|"ppc64le") } -> -+ 1002 -+ -+ | { i_type = "linux"; i_arch = "s390x" } -> -+ 2002 -+ -+ | { i_type = "linux" } -> -+ 5 -+ -+ | { i_type = "windows"; i_major_version = 5; i_minor_version = 1 } -> -+ 1 (* no architecture differentiation of XP on RHV *) -+ -+ | { i_type = "windows"; i_major_version = 5; i_minor_version = 2; -+ i_product_name = product } when String.find product "XP" >= 0 -> -+ 1 (* no architecture differentiation of XP on RHV *) -+ -+ | { i_type = "windows"; i_major_version = 5; i_minor_version = 2; -+ i_arch = "i386" } -> -+ 3 -+ -+ | { i_type = "windows"; i_major_version = 5; i_minor_version = 2; -+ i_arch = "x86_64" } -> -+ 10 -+ -+ | { i_type = "windows"; i_major_version = 6; i_minor_version = 0; -+ i_arch = "i386" } -> -+ 4 -+ -+ | { i_type = "windows"; i_major_version = 6; i_minor_version = 0; -+ i_arch = "x86_64" } -> -+ 16 -+ -+ | { i_type = "windows"; i_major_version = 6; i_minor_version = 1; -+ i_arch = "i386" } -> -+ 11 -+ -+ | { i_type = "windows"; i_major_version = 6; i_minor_version = 1; -+ i_arch = "x86_64"; i_product_variant = "Client" } -> -+ 12 -+ -+ | { i_type = "windows"; i_major_version = 6; i_minor_version = 1; -+ i_arch = "x86_64" } -> -+ 17 -+ -+ | { i_type = "windows"; i_major_version = 6; i_minor_version = 2; -+ i_arch = "i386" } -> -+ 20 -+ -+ | { i_type = "windows"; i_major_version = 6; i_minor_version = 2; -+ i_arch = "x86_64"; i_product_variant = "Client" } -> -+ 21 -+ -+ | { i_type = "windows"; i_major_version = 6; i_minor_version = 2; -+ i_arch = "x86_64" } -> -+ 23 -+ -+ (* Treat Windows 8.1 client like Windows 8. See: -+ * https://bugzilla.redhat.com/show_bug.cgi?id=1309580#c4 -+ *) -+ | { i_type = "windows"; i_major_version = 6; i_minor_version = 3; -+ i_arch = "i386"; i_product_variant = "Client" } -> -+ 20 -+ -+ | { i_type = "windows"; i_major_version = 6; i_minor_version = 3; -+ i_arch = "x86_64"; i_product_variant = "Client" } -> -+ 21 -+ -+ | { i_type = "windows"; i_major_version = 6; i_minor_version = 3; -+ i_arch = "x86_64" } -> -+ 23 -+ -+ | { i_type = "windows"; i_major_version = 10; i_minor_version = 0; -+ i_arch = "i386" } -> -+ 26 -+ -+ | { i_type = "windows"; i_major_version = 10; i_minor_version = 0; -+ i_arch = "x86_64"; i_product_variant = "Client" } -> -+ 27 -+ -+ | { i_type = "windows"; i_major_version = 10; i_minor_version = 0; -+ i_arch = "x86_64" } -> -+ 29 -+ -+ | { i_type = typ; i_distro = distro; -+ i_major_version = major; i_minor_version = minor; i_arch = arch; -+ i_product_name = product } -> -+ warning (f_"unknown guest operating system: %s %s %d.%d %s (%s)") -+ typ distro major minor arch product; -+ 0 -+ - (* Set the element based on the source hypervisor. - * https://bugzilla.redhat.com/show_bug.cgi?id=1342398#c6 - * https://gerrit.ovirt.org/#/c/59147/ -@@ -321,6 +518,7 @@ let rec create_ovf source targets guestcaps inspect - "xmlns:vssd", "http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData"; - "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"; - "xmlns:ovf", "http://schemas.dmtf.org/ovf/envelope/1/"; -+ "xmlns:ovirt", "http://www.ovirt.org/ovf"; - "ovf:version", "0.9" - ] [ - Comment generated_by; -@@ -383,8 +581,10 @@ let rec create_ovf source targets guestcaps inspect - ] in - (match ovf_flavour with - | OVirt -> -+ let ovirt_osid = get_ovirt_osid inspect in - e "OperatingSystemSection" ["ovf:id", vm_uuid; -- "ovf:required", "false"] -+ "ovf:required", "false"; -+ "ovirt:id", string_of_int ovirt_osid] - osinfo_subnodes - | RHVExportStorageDomain -> - e "Section" ["ovf:id", vm_uuid; "ovf:required", "false"; --- -2.21.0 - diff --git a/SOURCES/0011-v2v-OVF-fix-ovf-id-for-VirtualSystem-in-OVirt-flavou.patch b/SOURCES/0011-v2v-OVF-fix-ovf-id-for-VirtualSystem-in-OVirt-flavou.patch deleted file mode 100644 index f1a7c0b..0000000 --- a/SOURCES/0011-v2v-OVF-fix-ovf-id-for-VirtualSystem-in-OVirt-flavou.patch +++ /dev/null @@ -1,32 +0,0 @@ -From b96a2119b20f204661fa2165aea3c6c2b84e23de Mon Sep 17 00:00:00 2001 -From: Pino Toscano -Date: Thu, 5 Apr 2018 10:28:17 +0200 -Subject: [PATCH] v2v: OVF: fix ovf:id for VirtualSystem in OVirt flavour - -When writing the OVF in OVirt flavour, write the actual UUID of the -VM as ovf:id attribute for , instead of a dummy value. - -Suggested by Arik Hadas in -https://www.redhat.com/archives/libguestfs/2018-April/msg00005.html - -(cherry picked from commit 9dce43931a19510be1b6d21ce67d14a4136ce241) ---- - v2v/create_ovf.ml | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/v2v/create_ovf.ml b/v2v/create_ovf.ml -index 730ab64b4..b1ab8df3f 100644 ---- a/v2v/create_ovf.ml -+++ b/v2v/create_ovf.ml -@@ -688,7 +688,7 @@ let rec create_ovf source targets guestcaps inspect - - (match ovf_flavour with - | OVirt -> -- e "VirtualSystem" ["ovf:id", "out"] !content_subnodes -+ e "VirtualSystem" ["ovf:id", vm_uuid] !content_subnodes - | RHVExportStorageDomain -> - e "Content" ["ovf:id", "out"; "xsi:type", "ovf:VirtualSystem_Type"] - !content_subnodes --- -2.21.0 - diff --git a/SOURCES/0011-v2v-start-reading-the-new-libvirt-firmware-autoselec.patch b/SOURCES/0011-v2v-start-reading-the-new-libvirt-firmware-autoselec.patch new file mode 100644 index 0000000..7c688b1 --- /dev/null +++ b/SOURCES/0011-v2v-start-reading-the-new-libvirt-firmware-autoselec.patch @@ -0,0 +1,45 @@ +From 042554182bcc782527dc74e035e2efaf6eb38aa4 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Mon, 8 Apr 2019 18:23:27 +0200 +Subject: [PATCH] v2v: start reading the new libvirt firmware autoselect + +Starting with 5.2.0, libvirt has a way to select automatically the +firmware for a guest using an attribute of the tag. Hence, use +this information (when available, of course) to flag the firmware used +by the guest. + +(cherry picked from commit fb7983f999004c1f8100776819ea65b21990956d) +--- + v2v/parse_libvirt_xml.ml | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/v2v/parse_libvirt_xml.ml b/v2v/parse_libvirt_xml.ml +index b9970cee8..14cd82afd 100644 +--- a/v2v/parse_libvirt_xml.ml ++++ b/v2v/parse_libvirt_xml.ml +@@ -476,6 +476,13 @@ let parse_libvirt_xml ?conn xml = + done; + List.rev !nics in + ++ (* Firmware. *) ++ let firmware = ++ match xpath_string "/domain/os/@firmware" with ++ | Some "bios" -> BIOS ++ | Some "efi" -> UEFI ++ | None | Some _ -> UnknownFirmware in ++ + (* Check for hostdev devices. (RHBZ#1472719) *) + let () = + let obj = Xml.xpath_eval_expression xpathctx "/domain/devices/hostdev" in +@@ -520,7 +527,7 @@ let parse_libvirt_xml ?conn xml = + s_cpu_model = cpu_model; + s_cpu_topology = cpu_topology; + s_features = features; +- s_firmware = UnknownFirmware; (* XXX until RHBZ#1217444 is fixed *) ++ s_firmware = firmware; + s_display = display; + s_video = video; + s_sound = sound; +-- +2.25.4 + diff --git a/SOURCES/0012-common-mltools-move-the-code-for-machine-readable-up.patch b/SOURCES/0012-common-mltools-move-the-code-for-machine-readable-up.patch new file mode 100644 index 0000000..ac06365 --- /dev/null +++ b/SOURCES/0012-common-mltools-move-the-code-for-machine-readable-up.patch @@ -0,0 +1,96 @@ +From 692a752cf3e552790ada8cc07f937036adaa8bf0 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Thu, 21 Mar 2019 17:16:37 +0100 +Subject: [PATCH] common/mltools: move the code for machine readable up + +Move the code for handling machine readable up in the file, so it can be +used by other functions. + +Only code motion, no behaviour changes. + +(cherry picked from commit 8b06ea0ebc9534e4fda9cc9a33c98f939401af79) +--- + common/mltools/tools_utils.ml | 60 +++++++++++++++++------------------ + 1 file changed, 30 insertions(+), 30 deletions(-) + +diff --git a/common/mltools/tools_utils.ml b/common/mltools/tools_utils.ml +index 24641369e..5a35708cd 100644 +--- a/common/mltools/tools_utils.ml ++++ b/common/mltools/tools_utils.ml +@@ -33,6 +33,36 @@ external c_inspect_decrypt : Guestfs.t -> int64 -> (string * key_store_key) list + external c_set_echo_keys : unit -> unit = "guestfs_int_mllib_set_echo_keys" "noalloc" + external c_set_keys_from_stdin : unit -> unit = "guestfs_int_mllib_set_keys_from_stdin" "noalloc" + ++type machine_readable_fn = { ++ pr : 'a. ('a, unit, string, unit) format4 -> 'a; ++} (* [@@unboxed] *) ++ ++type machine_readable_output_type = ++ | NoOutput ++ | Channel of out_channel ++ | File of string ++let machine_readable_output = ref NoOutput ++let machine_readable_channel = ref None ++let machine_readable () = ++ let chan = ++ if !machine_readable_channel = None then ( ++ let chan = ++ match !machine_readable_output with ++ | NoOutput -> None ++ | Channel chan -> Some chan ++ | File f -> Some (open_out f) in ++ machine_readable_channel := chan ++ ); ++ !machine_readable_channel ++ in ++ match chan with ++ | None -> None ++ | Some chan -> ++ let pr fs = ++ ksprintf (output_string chan) fs ++ in ++ Some { pr } ++ + (* ANSI terminal colours. *) + let istty chan = + Unix.isatty (Unix.descr_of_out_channel chan) +@@ -236,36 +266,6 @@ let human_size i = + ) + ) + +-type machine_readable_fn = { +- pr : 'a. ('a, unit, string, unit) format4 -> 'a; +-} (* [@@unboxed] *) +- +-type machine_readable_output_type = +- | NoOutput +- | Channel of out_channel +- | File of string +-let machine_readable_output = ref NoOutput +-let machine_readable_channel = ref None +-let machine_readable () = +- let chan = +- if !machine_readable_channel = None then ( +- let chan = +- match !machine_readable_output with +- | NoOutput -> None +- | Channel chan -> Some chan +- | File f -> Some (open_out f) in +- machine_readable_channel := chan +- ); +- !machine_readable_channel +- in +- match chan with +- | None -> None +- | Some chan -> +- let pr fs = +- ksprintf (output_string chan) fs +- in +- Some { pr } +- + type cmdline_options = { + getopt : Getopt.t; + ks : key_store; +-- +2.25.4 + diff --git a/SOURCES/0012-v2v-Add-o-rhv-upload-output-mode-RHBZ-1557273.patch b/SOURCES/0012-v2v-Add-o-rhv-upload-output-mode-RHBZ-1557273.patch deleted file mode 100644 index 046488b..0000000 --- a/SOURCES/0012-v2v-Add-o-rhv-upload-output-mode-RHBZ-1557273.patch +++ /dev/null @@ -1,1764 +0,0 @@ -From 79aa92b800800592551f1389db0a059b3f111f33 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Mon, 12 Feb 2018 16:45:02 +0000 -Subject: [PATCH] v2v: Add -o rhv-upload output mode (RHBZ#1557273). -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This adds a new output mode to virt-v2v. virt-v2v -o rhv-upload -streams images directly to an oVirt or RHV >= 4 Data Domain using the -oVirt SDK v4. It is more efficient than -o rhv because it does not -need to go via the Export Storage Domain, and is possible for humans -to use unlike -o vdsm. - -The implementation uses the Python SDK (‘ovirtsdk4’ module). An -nbdkit Python 3 plugin translates NBD calls from qemu into HTTPS -requests to oVirt via the SDK. - -(cherry picked from commit cc04573927cca97de60d544d37467e67c25867a7) ---- - .gitignore | 3 + - TODO | 27 ++ - v2v/Makefile.am | 30 +- - v2v/cmdline.ml | 41 ++ - v2v/embed.sh | 48 +++ - v2v/output_rhv_upload.ml | 401 +++++++++++++++++++ - v2v/output_rhv_upload.mli | 33 ++ - v2v/output_rhv_upload_createvm_source.mli | 19 + - v2v/output_rhv_upload_plugin_source.mli | 19 + - v2v/output_rhv_upload_precheck_source.mli | 19 + - v2v/rhv-upload-createvm.py | 86 +++++ - v2v/rhv-upload-plugin.py | 445 ++++++++++++++++++++++ - v2v/rhv-upload-precheck.py | 73 ++++ - v2v/test-v2v-o-rhv-upload-oo-query.sh | 38 ++ - v2v/test-v2v-python-syntax.sh | 45 +++ - v2v/virt-v2v.pod | 138 ++++++- - 16 files changed, 1447 insertions(+), 18 deletions(-) - create mode 100755 v2v/embed.sh - create mode 100644 v2v/output_rhv_upload.ml - create mode 100644 v2v/output_rhv_upload.mli - create mode 100644 v2v/output_rhv_upload_createvm_source.mli - create mode 100644 v2v/output_rhv_upload_plugin_source.mli - create mode 100644 v2v/output_rhv_upload_precheck_source.mli - create mode 100644 v2v/rhv-upload-createvm.py - create mode 100644 v2v/rhv-upload-plugin.py - create mode 100644 v2v/rhv-upload-precheck.py - create mode 100755 v2v/test-v2v-o-rhv-upload-oo-query.sh - create mode 100755 v2v/test-v2v-python-syntax.sh - -diff --git a/.gitignore b/.gitignore -index 8101a2d9b..af80e36d1 100644 ---- a/.gitignore -+++ b/.gitignore -@@ -672,6 +672,9 @@ Makefile.in - /utils/qemu-speed-test/qemu-speed-test - /v2v/.depend - /v2v/oUnit-* -+/v2v/output_rhv_upload_createvm_source.ml -+/v2v/output_rhv_upload_plugin_source.ml -+/v2v/output_rhv_upload_precheck_source.ml - /v2v/real-*.d/ - /v2v/real-*.img - /v2v/real-*.xml -diff --git a/TODO b/TODO -index 2e37ce67c..d196a3f6b 100644 ---- a/TODO -+++ b/TODO -@@ -570,3 +570,30 @@ Subsecond handling in virt-diff, virt-ls - - Handle nanoseconds properly. You should be able to specify them on - the command line and display them. -+ -+virt-v2v -o rhv-upload -+---------------------- -+ -+* Set or disable the ticket timeout. The default is going to be -+ increased (from current 60 seconds), so maybe we won't have to -+ set it. See also: -+ https://bugzilla.redhat.com/show_bug.cgi?id=1563278 -+ -+* qcow2 cannot be supported yet because there is not yet any -+ concept in imageio of read+write handles. -+ https://bugzilla.redhat.com/show_bug.cgi?id=1563299 -+ -+* preallocated cannot be supported yet because imageio doesn't -+ know how to zero the image efficiently, instead it runs an -+ fallocate process which writes to every block and that takes -+ many minutes. -+ -+* Really check what insecure/rhv_cafile do and implement it correctly. -+ -+* Measure and resolve performance problems. -+ -+* Allocated image size is unknown for v2v uploads, but imageio needs -+ to know it. We pass initial_size == provisioned_size == virtual size. -+ That can't be fixed from the v2v side. -+ -+* There are unresolved issues about how to clean up disks on failure. -diff --git a/v2v/Makefile.am b/v2v/Makefile.am -index 482ba58e5..694a64573 100644 ---- a/v2v/Makefile.am -+++ b/v2v/Makefile.am -@@ -22,12 +22,19 @@ generator_built = \ - uefi.mli - - BUILT_SOURCES = \ -- $(generator_built) -+ $(generator_built) \ -+ output_rhv_upload_createvm_source.ml \ -+ output_rhv_upload_plugin_source.ml \ -+ output_rhv_upload_precheck_source.ml - - EXTRA_DIST = \ - $(SOURCES_MLI) $(SOURCES_ML) $(SOURCES_C) \ - copy_to_local.ml \ - copy_to_local.mli \ -+ embed-code.sh \ -+ rhv-upload-createvm.py \ -+ rhv-upload-plugin.py \ -+ rhv-upload-precheck.py \ - v2v_unit_tests.ml \ - virt-v2v.pod \ - virt-v2v-copy-to-local.pod -@@ -62,6 +69,10 @@ SOURCES_MLI = \ - output_null.mli \ - output_qemu.mli \ - output_rhv.mli \ -+ output_rhv_upload.mli \ -+ output_rhv_upload_createvm_source.mli \ -+ output_rhv_upload_plugin_source.mli \ -+ output_rhv_upload_precheck_source.mli \ - output_vdsm.mli \ - parse_ova.mli \ - parse_ovf_from_ova.mli \ -@@ -116,6 +127,10 @@ SOURCES_ML = \ - output_local.ml \ - output_qemu.ml \ - output_rhv.ml \ -+ output_rhv_upload_createvm_source.ml \ -+ output_rhv_upload_plugin_source.ml \ -+ output_rhv_upload_precheck_source.ml \ -+ output_rhv_upload.ml \ - output_vdsm.ml \ - inspect_source.ml \ - target_bus_assignment.ml \ -@@ -126,6 +141,15 @@ SOURCES_C = \ - libvirt_utils-c.c \ - qemuopts-c.c - -+# These files are generated and contain rhv-upload-*.py embedded as an -+# OCaml string. -+output_rhv_upload_createvm_source.ml: rhv-upload-createvm.py -+ ./embed.sh code $^ $@ -+output_rhv_upload_plugin_source.ml: rhv-upload-plugin.py -+ ./embed.sh code $^ $@ -+output_rhv_upload_precheck_source.ml: rhv-upload-precheck.py -+ ./embed.sh code $^ $@ -+ - if HAVE_OCAML - - bin_PROGRAMS = virt-v2v virt-v2v-copy-to-local -@@ -295,6 +319,7 @@ TESTS_ENVIRONMENT = $(top_builddir)/run --test - - TESTS = \ - test-v2v-docs.sh \ -+ test-v2v-python-syntax.sh \ - test-v2v-i-ova-bad-sha1.sh \ - test-v2v-i-ova-bad-sha256.sh \ - test-v2v-i-ova-formats.sh \ -@@ -308,6 +333,7 @@ TESTS = \ - test-v2v-i-ova-two-disks.sh \ - test-v2v-i-vmx.sh \ - test-v2v-it-vddk-io-query.sh \ -+ test-v2v-o-rhv-upload-oo-query.sh \ - test-v2v-o-vdsm-oo-query.sh \ - test-v2v-bad-networks-and-bridges.sh - -@@ -483,6 +509,7 @@ EXTRA_DIST += \ - test-v2v-o-null.sh \ - test-v2v-o-qemu.sh \ - test-v2v-o-rhv.sh \ -+ test-v2v-o-rhv-upload-oo-query.sh \ - test-v2v-o-vdsm-oo-query.sh \ - test-v2v-o-vdsm-options.sh \ - test-v2v-oa-option.sh \ -@@ -491,6 +518,7 @@ EXTRA_DIST += \ - test-v2v-print-source.expected \ - test-v2v-print-source.sh \ - test-v2v-print-source.xml \ -+ test-v2v-python-syntax.sh \ - test-v2v-conversion-of.sh \ - test-v2v-sound.sh \ - test-v2v-sound.xml \ -diff --git a/v2v/cmdline.ml b/v2v/cmdline.ml -index 5b8f686a8..9b1348c37 100644 ---- a/v2v/cmdline.ml -+++ b/v2v/cmdline.ml -@@ -133,6 +133,8 @@ let parse_cmdline () = - | "disk" | "local" -> output_mode := `Local - | "null" -> output_mode := `Null - | "ovirt" | "rhv" | "rhev" -> output_mode := `RHV -+ | "ovirt-upload" | "ovirt_upload" | "rhv-upload" | "rhv_upload" -> -+ output_mode := `RHV_Upload - | "qemu" -> output_mode := `QEmu - | "vdsm" -> output_mode := `VDSM - | s -> -@@ -392,6 +394,16 @@ read the man page virt-v2v(1). - | `Null -> no_options (); `Null - | `RHV -> no_options (); `RHV - | `QEmu -> no_options (); `QEmu -+ | `RHV_Upload -> -+ if is_query then ( -+ Output_rhv_upload.print_output_options (); -+ exit 0 -+ ) -+ else ( -+ let rhv_options = -+ Output_rhv_upload.parse_output_options output_options in -+ `RHV_Upload rhv_options -+ ) - | `VDSM -> - if is_query then ( - Output_vdsm.print_output_options (); -@@ -568,6 +580,35 @@ read the man page virt-v2v(1). - Output_rhv.output_rhv os output_alloc, - output_format, output_alloc - -+ | `RHV_Upload rhv_options -> -+ let output_conn = -+ match output_conn with -+ | None -> -+ error (f_"-o rhv-upload: use ‘-oc’ to point to the oVirt or RHV server REST API URL, which is usually https://servername/ovirt-engine/api") -+ | Some oc -> oc in -+ (* Output format / sparse must currently be raw+sparse. We can -+ * change this in future. See TODO file for details. XXX -+ *) -+ if output_alloc <> Sparse || output_format <> Some "raw" then -+ error (f_"-o rhv-upload: currently you must use ‘-of raw’ and you cannot use ‘-oa preallocated’ with this output mode. These restrictions will be loosened in a future version."); -+ (* In theory we could make the password optional in future. *) -+ let output_password = -+ match output_password with -+ | None -> -+ error (f_"-o rhv-upload: output password file was not specified, use ‘-op’ to point to a file which contains the password used to connect to the oVirt or RHV server") -+ | Some op -> op in -+ let os = -+ match output_storage with -+ | None -> -+ error (f_"-o rhv-upload: output storage was not specified, use ‘-os’"); -+ | Some os -> os in -+ if qemu_boot then -+ error_option_cannot_be_used_in_output_mode "rhv-upload" "--qemu-boot"; -+ Output_rhv_upload.output_rhv_upload output_alloc output_conn -+ output_password os -+ rhv_options, -+ output_format, output_alloc -+ - | `VDSM vdsm_options -> - if output_password <> None then - error_option_cannot_be_used_in_output_mode "vdsm" "-op"; -diff --git a/v2v/embed.sh b/v2v/embed.sh -new file mode 100755 -index 000000000..363d7e2b0 ---- /dev/null -+++ b/v2v/embed.sh -@@ -0,0 +1,48 @@ -+#!/bin/bash - -+# Embed code or other content into an OCaml file. -+# Copyright (C) 2018 Red Hat Inc. -+# -+# This program is free software; you can redistribute it and/or modify -+# it under the terms of the GNU General Public License as published by -+# the Free Software Foundation; either version 2 of the License, or -+# (at your option) any later version. -+# -+# This program is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+# GNU General Public License for more details. -+# -+# You should have received a copy of the GNU General Public License -+# along with this program; if not, write to the Free Software -+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ -+# Embed code or other content into an OCaml file. -+# -+# It is embedded into a string. As OCaml string literals have virtually -+# no restrictions on length or content we only have to escape double -+# quotes for backslash characters. -+ -+if [ $# -ne 3 ]; then -+ echo "embed.sh identifier input output" -+ exit 1 -+fi -+ -+set -e -+set -u -+ -+ident="$1" -+input="$2" -+output="$3" -+ -+rm -f "$output" "$output"-t -+ -+exec >"$output"-t -+ -+echo "(* Generated by embed.sh from $input *)" -+echo -+echo let "$ident" = '"' -+sed -e 's/\(["\]\)/\\\1/g' < "$input" -+echo '"' -+ -+chmod -w "$output"-t -+mv "$output"-t "$output" -diff --git a/v2v/output_rhv_upload.ml b/v2v/output_rhv_upload.ml -new file mode 100644 -index 000000000..129461242 ---- /dev/null -+++ b/v2v/output_rhv_upload.ml -@@ -0,0 +1,401 @@ -+(* virt-v2v -+ * Copyright (C) 2009-2018 Red Hat Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ *) -+ -+open Printf -+open Unix -+ -+open Std_utils -+open Tools_utils -+open Unix_utils -+open Common_gettext.Gettext -+ -+open Types -+open Utils -+ -+type rhv_options = { -+ rhv_cafile : string; -+ rhv_cluster : string option; -+ rhv_direct : bool; -+ rhv_verifypeer : bool; -+} -+ -+let print_output_options () = -+ printf (f_"Output options (-oo) which can be used with -o rhv-upload: -+ -+ -oo rhv-cafile=CA.PEM Set ‘ca.pem’ certificate bundle filename. -+ -oo rhv-cluster=CLUSTERNAME Set RHV cluster name. -+ -oo rhv-direct[=true|false] Use direct transfer mode (default: false). -+ -oo rhv-verifypeer[=true|false] Verify server identity (default: false). -+") -+ -+let parse_output_options options = -+ let rhv_cafile = ref None in -+ let rhv_cluster = ref None in -+ let rhv_direct = ref false in -+ let rhv_verifypeer = ref false in -+ -+ List.iter ( -+ function -+ | "rhv-cafile", v -> -+ if !rhv_cafile <> None then -+ error (f_"-o rhv-upload: -oo rhv-cafile set twice"); -+ rhv_cafile := Some v -+ | "rhv-cluster", v -> -+ if !rhv_cluster <> None then -+ error (f_"-o rhv-upload: -oo rhv-cluster set twice"); -+ rhv_cluster := Some v -+ | "rhv-direct", "" -> rhv_direct := true -+ | "rhv-direct", v -> rhv_direct := bool_of_string v -+ | "rhv-verifypeer", "" -> rhv_verifypeer := true -+ | "rhv-verifypeer", v -> rhv_verifypeer := bool_of_string v -+ | k, _ -> -+ error (f_"-o rhv-upload: unknown output option ‘-oo %s’") k -+ ) options; -+ -+ let rhv_cafile = -+ match !rhv_cafile with -+ | Some s -> s -+ | None -> -+ error (f_"-o rhv-upload: must use ‘-oo rhv-cafile’ to supply the path to the oVirt or RHV user’s ‘ca.pem’ file") in -+ let rhv_cluster = !rhv_cluster in -+ let rhv_direct = !rhv_direct in -+ let rhv_verifypeer = !rhv_verifypeer in -+ -+ { rhv_cafile; rhv_cluster; rhv_direct; rhv_verifypeer } -+ -+let python3 = "python3" (* Defined by PEP 394 *) -+let pidfile_timeout = 30 -+let finalization_timeout = 5*60 -+ -+class output_rhv_upload output_alloc output_conn -+ output_password output_storage -+ rhv_options = -+ (* Create a temporary directory which will be deleted on exit. *) -+ let tmpdir = -+ let base_dir = (open_guestfs ())#get_cachedir () in -+ let t = Mkdtemp.temp_dir ~base_dir "rhvupload." in -+ rmdir_on_exit t; -+ t in -+ -+ let diskid_file_of_id id = tmpdir // sprintf "diskid.%d" id in -+ -+ (* Write the Python precheck, plugin and create VM to a temporary file. *) -+ let precheck = -+ let precheck = tmpdir // "rhv-upload-precheck.py" in -+ with_open_out -+ precheck -+ (fun chan -> output_string chan Output_rhv_upload_precheck_source.code); -+ precheck in -+ let plugin = -+ let plugin = tmpdir // "rhv-upload-plugin.py" in -+ with_open_out -+ plugin -+ (fun chan -> output_string chan Output_rhv_upload_plugin_source.code); -+ plugin in -+ let createvm = -+ let createvm = tmpdir // "rhv-upload-createvm.py" in -+ with_open_out -+ createvm -+ (fun chan -> output_string chan Output_rhv_upload_createvm_source.code); -+ createvm in -+ -+ (* Is SELinux enabled and enforcing on the host? *) -+ let have_selinux = -+ 0 = Sys.command "getenforce 2>/dev/null | grep -isq Enforcing" in -+ -+ (* Check that the Python binary is available. *) -+ let error_unless_python_binary_on_path () = -+ try ignore (which python3) -+ with Executable_not_found _ -> -+ error (f_"no python binary called ‘%s’ can be found on the $PATH") -+ python3 -+ in -+ -+ (* Check that nbdkit is available and new enough. *) -+ let error_unless_nbdkit_working () = -+ if 0 <> Sys.command "nbdkit --version >/dev/null" then -+ error (f_"nbdkit is not installed or not working. It is required to use ‘-o rhv-upload’. See \"OUTPUT TO RHV\" in the virt-v2v(1) manual."); -+ -+ (* Check it's a new enough version. The latest features we -+ * require are ‘--exit-with-parent’ and ‘--selinux-label’, both -+ * added in 1.1.14. (We use 1.1.16 as the minimum here because -+ * it also adds the selinux=yes|no flag in --dump-config). -+ *) -+ let lines = external_command "nbdkit --help" in -+ let lines = String.concat " " lines in -+ if String.find lines "exit-with-parent" == -1 || -+ String.find lines "selinux-label" == -1 then -+ error (f_"nbdkit is not new enough, you need to upgrade to nbdkit ≥ 1.1.16") -+ in -+ -+ (* Check that the python3 plugin is installed and working -+ * and can load the plugin script. -+ *) -+ let error_unless_nbdkit_python3_working () = -+ let cmd = sprintf "nbdkit %s %s --dump-plugin >/dev/null" -+ python3 (quote plugin) in -+ if Sys.command cmd <> 0 then -+ error (f_"nbdkit Python 3 plugin is not installed or not working. It is required if you want to use ‘-o rhv-upload’. -+ -+See also \"OUTPUT TO RHV\" in the virt-v2v(1) manual.") -+ in -+ -+ (* Check that nbdkit was compiled with SELinux support (for the -+ * --selinux-label option). -+ *) -+ let error_unless_nbdkit_compiled_with_selinux () = -+ let lines = external_command "nbdkit --dump-config" in -+ (* In nbdkit <= 1.1.15 the selinux attribute was not present -+ * at all in --dump-config output so there was no way to tell. -+ * Ignore this case because there will be an error later when -+ * we try to use the --selinux-label parameter. -+ *) -+ if List.mem "selinux=no" (List.map String.trim lines) then -+ error (f_"nbdkit was compiled without SELinux support. You will have to recompile nbdkit with libselinux-devel installed, or else set SELinux to Permissive mode while doing the conversion.") -+ in -+ -+ (* JSON parameters which are invariant between disks. *) -+ let json_params = [ -+ "verbose", JSON.Bool (verbose ()); -+ -+ "output_conn", JSON.String output_conn; -+ "output_password", JSON.String output_password; -+ "output_storage", JSON.String output_storage; -+ "output_sparse", JSON.Bool (match output_alloc with -+ | Sparse -> true -+ | Preallocated -> false); -+ "rhv_cafile", JSON.String rhv_options.rhv_cafile; -+ "rhv_cluster", -+ JSON.String (Option.default "Default" rhv_options.rhv_cluster); -+ "rhv_direct", JSON.Bool rhv_options.rhv_direct; -+ -+ (* The 'Insecure' flag seems to be a number with various possible -+ * meanings, however we just set it to True/False. -+ * -+ * https://github.com/oVirt/ovirt-engine-sdk/blob/19aa7070b80e60a4cfd910448287aecf9083acbe/sdk/lib/ovirtsdk4/__init__.py#L395 -+ *) -+ "insecure", JSON.Bool (not rhv_options.rhv_verifypeer); -+ ] in -+ -+ (* nbdkit command line args which are invariant between disks. *) -+ let nbdkit_args = -+ let args = [ -+ "nbdkit"; -+ -+ "--foreground"; (* run in foreground *) -+ "--exit-with-parent"; (* exit when virt-v2v exits *) -+ "--newstyle"; (* use newstyle NBD protocol *) -+ "--exportname"; "/"; -+ -+ "python3"; (* use the nbdkit Python 3 plugin *) -+ plugin; (* Python plugin script *) -+ ] in -+ let args = if verbose () then args @ ["--verbose"] else args in -+ let args = -+ (* label the socket so qemu can open it *) -+ if have_selinux then -+ args @ ["--selinux-label"; "system_u:object_r:svirt_t:s0"] -+ else args in -+ args in -+ -+object -+ inherit output -+ -+ method precheck () = -+ error_unless_python_binary_on_path (); -+ error_unless_nbdkit_working (); -+ error_unless_nbdkit_python3_working (); -+ if have_selinux then -+ error_unless_nbdkit_compiled_with_selinux () -+ -+ method as_options = -+ "-o rhv-upload" ^ -+ (match output_alloc with -+ | Sparse -> "" (* default, don't need to print it *) -+ | Preallocated -> " -oa preallocated") ^ -+ sprintf " -oc %s -op %s -os %s" -+ output_conn output_password output_storage -+ -+ method supported_firmware = [ TargetBIOS ] -+ -+ method prepare_targets source targets = -+ let output_name = source.s_name in -+ let json_params = -+ ("output_name", JSON.String output_name) :: json_params in -+ -+ (* Python code prechecks. These can't run in #precheck because -+ * we need to know the name of the virtual machine. -+ *) -+ let json_param_file = tmpdir // "params.json" in -+ with_open_out -+ json_param_file -+ (fun chan -> output_string chan (JSON.string_of_doc json_params)); -+ if run_command [ python3; precheck; json_param_file ] <> 0 then -+ error (f_"failed server prechecks, see earlier errors"); -+ -+ (* Create an nbdkit instance for each disk and set the -+ * target URI to point to the NBD socket. -+ *) -+ List.map ( -+ fun t -> -+ let id = t.target_overlay.ov_source.s_disk_id in -+ let disk_name = sprintf "%s-%03d" output_name id in -+ let json_params = -+ ("disk_name", JSON.String disk_name) :: json_params in -+ -+ let disk_format = -+ match t.target_format with -+ | ("raw" | "qcow2") as fmt -> fmt -+ | _ -> -+ error (f_"rhv-upload: -of %s: Only output format ‘raw’ or ‘qcow2’ is supported. If the input is in a different format then force one of these output formats by adding either ‘-of raw’ or ‘-of qcow2’ on the command line.") -+ t.target_format in -+ let json_params = -+ ("disk_format", JSON.String disk_format) :: json_params in -+ -+ let disk_size = t.target_overlay.ov_virtual_size in -+ let json_params = -+ ("disk_size", JSON.Int64 disk_size) :: json_params in -+ -+ (* Ask the plugin to write the disk ID to a special file. *) -+ let diskid_file = diskid_file_of_id id in -+ let json_params = -+ ("diskid_file", JSON.String diskid_file) :: json_params in -+ -+ (* Write the JSON parameters to a file. *) -+ let json_param_file = tmpdir // sprintf "params%d.json" id in -+ with_open_out -+ json_param_file -+ (fun chan -> output_string chan (JSON.string_of_doc json_params)); -+ -+ let sock = tmpdir // sprintf "nbdkit%d.sock" id in -+ let pidfile = tmpdir // sprintf "nbdkit%d.pid" id in -+ -+ (* Add common arguments to per-target arguments. *) -+ let args = -+ nbdkit_args @ [ "--pidfile"; pidfile; -+ "--unix"; sock; -+ sprintf "params=%s" json_param_file ] in -+ -+ (* Print the full command we are about to run when debugging. *) -+ if verbose () then ( -+ eprintf "running nbdkit:\n"; -+ List.iter (fun arg -> eprintf " %s" (quote arg)) args; -+ prerr_newline () -+ ); -+ -+ (* Start an nbdkit instance in the background. By using -+ * --exit-with-parent we don't have to worry about clean-up. -+ *) -+ let args = Array.of_list args in -+ let pid = fork () in -+ if pid = 0 then ( -+ (* Child process (nbdkit). *) -+ execvp "nbdkit" args -+ ); -+ -+ (* Wait for the pidfile to appear so we know that nbdkit -+ * is listening for requests. -+ *) -+ if not (wait_for_file pidfile pidfile_timeout) then ( -+ if verbose () then -+ error (f_"nbdkit did not start up. See previous debugging messages for problems.") -+ else -+ error (f_"nbdkit did not start up. There may be errors printed by nbdkit above. -+ -+If the messages above are not sufficient to diagnose the problem then add the ‘virt-v2v -v -x’ options and examine the debugging output carefully.") -+ ); -+ -+ if have_selinux then ( -+ (* Note that Unix domain sockets have both a file label and -+ * a socket/process label. Using --selinux-label above -+ * only set the socket label, but we must also set the file -+ * label. -+ *) -+ ignore ( -+ run_command ["chcon"; "system_u:object_r:svirt_image_t:s0"; -+ sock] -+ ); -+ ); -+ (* ... and the regular Unix permissions, in case qemu is -+ * running as another user. -+ *) -+ chmod sock 0o777; -+ -+ (* Tell ‘qemu-img convert’ to write to the nbd socket which is -+ * connected to nbdkit. -+ *) -+ let json_params = [ -+ "file.driver", JSON.String "nbd"; -+ "file.path", JSON.String sock; -+ "file.export", JSON.String "/"; -+ ] in -+ let target_file = -+ TargetURI ("json:" ^ JSON.string_of_doc json_params) in -+ { t with target_file } -+ ) targets -+ -+ method create_metadata source targets _ guestcaps inspect target_firmware = -+ (* Get the UUIDs of each disk image. These files are written -+ * out by the nbdkit plugins on successful finalization of the -+ * transfer. -+ *) -+ let nr_disks = List.length targets in -+ let image_uuids = -+ List.map ( -+ fun t -> -+ let id = t.target_overlay.ov_source.s_disk_id in -+ let diskid_file = diskid_file_of_id id in -+ if not (wait_for_file diskid_file finalization_timeout) then -+ error (f_"transfer of disk %d/%d failed, see earlier error messages") -+ (id+1) nr_disks; -+ let diskid = read_whole_file diskid_file in -+ diskid -+ ) targets in -+ -+ (* We don't have the storage domain UUID, but instead we write -+ * in a magic value which the Python code (which can get it) -+ * will substitute. -+ *) -+ let sd_uuid = "@SD_UUID@" in -+ -+ (* The volume and VM UUIDs are made up. *) -+ let vol_uuids = List.map (fun _ -> uuidgen ()) targets -+ and vm_uuid = uuidgen () in -+ -+ (* Create the metadata. *) -+ let ovf = -+ Create_ovf.create_ovf source targets guestcaps inspect -+ output_alloc -+ sd_uuid image_uuids vol_uuids vm_uuid -+ OVirt in -+ let ovf = DOM.doc_to_string ovf in -+ -+ let json_param_file = tmpdir // "params.json" in -+ with_open_out -+ json_param_file -+ (fun chan -> output_string chan (JSON.string_of_doc json_params)); -+ -+ let ovf_file = tmpdir // "vm.ovf" in -+ with_open_out ovf_file (fun chan -> output_string chan ovf); -+ if run_command [ python3; createvm; json_param_file; ovf_file ] <> 0 then -+ error (f_"failed to create virtual machine, see earlier errors") -+ -+end -+ -+let output_rhv_upload = new output_rhv_upload -+let () = Modules_list.register_output_module "rhv-upload" -diff --git a/v2v/output_rhv_upload.mli b/v2v/output_rhv_upload.mli -new file mode 100644 -index 000000000..f6cd69a61 ---- /dev/null -+++ b/v2v/output_rhv_upload.mli -@@ -0,0 +1,33 @@ -+(* virt-v2v -+ * Copyright (C) 2009-2018 Red Hat Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ *) -+ -+(** [-o rhv-upload] target. *) -+ -+type rhv_options -+(** Miscellaneous extra command line parameters used by rhv-upload. *) -+ -+val print_output_options : unit -> unit -+val parse_output_options : (string * string) list -> rhv_options -+(** Print and parse rhv-upload -oo options. *) -+ -+val output_rhv_upload : Types.output_allocation -> string -> string -> -+ string -> rhv_options -> Types.output -+(** [output_rhv_upload output_alloc output_conn output_password output_storage -+ rhv_options] -+ creates and returns a new {!Types.output} object specialized for writing -+ output to oVirt or RHV directly via RHV APIs. *) -diff --git a/v2v/output_rhv_upload_createvm_source.mli b/v2v/output_rhv_upload_createvm_source.mli -new file mode 100644 -index 000000000..c1bafa15b ---- /dev/null -+++ b/v2v/output_rhv_upload_createvm_source.mli -@@ -0,0 +1,19 @@ -+(* virt-v2v -+ * Copyright (C) 2018 Red Hat Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ *) -+ -+val code : string -diff --git a/v2v/output_rhv_upload_plugin_source.mli b/v2v/output_rhv_upload_plugin_source.mli -new file mode 100644 -index 000000000..c1bafa15b ---- /dev/null -+++ b/v2v/output_rhv_upload_plugin_source.mli -@@ -0,0 +1,19 @@ -+(* virt-v2v -+ * Copyright (C) 2018 Red Hat Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ *) -+ -+val code : string -diff --git a/v2v/output_rhv_upload_precheck_source.mli b/v2v/output_rhv_upload_precheck_source.mli -new file mode 100644 -index 000000000..c1bafa15b ---- /dev/null -+++ b/v2v/output_rhv_upload_precheck_source.mli -@@ -0,0 +1,19 @@ -+(* virt-v2v -+ * Copyright (C) 2018 Red Hat Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ *) -+ -+val code : string -diff --git a/v2v/rhv-upload-createvm.py b/v2v/rhv-upload-createvm.py -new file mode 100644 -index 000000000..a34627ec8 ---- /dev/null -+++ b/v2v/rhv-upload-createvm.py -@@ -0,0 +1,86 @@ -+# -*- python -*- -+# oVirt or RHV upload create VM used by ‘virt-v2v -o rhv-upload’ -+# Copyright (C) 2018 Red Hat Inc. -+# -+# This program is free software; you can redistribute it and/or modify -+# it under the terms of the GNU General Public License as published by -+# the Free Software Foundation; either version 2 of the License, or -+# (at your option) any later version. -+# -+# This program is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+# GNU General Public License for more details. -+# -+# You should have received a copy of the GNU General Public License along -+# with this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ -+import json -+import logging -+import sys -+import time -+ -+from http.client import HTTPSConnection -+from urllib.parse import urlparse -+ -+import ovirtsdk4 as sdk -+import ovirtsdk4.types as types -+ -+# Parameters are passed in via a JSON doc from the OCaml code. -+# Because this Python code ships embedded inside virt-v2v there -+# is no formal API here. -+params = None -+ovf = None # OVF file -+ -+if len(sys.argv) != 3: -+ raise RuntimeError("incorrect number of parameters") -+ -+# Parameters are passed in via a JSON document. -+with open(sys.argv[1], 'r') as fp: -+ params = json.load(fp) -+ -+# What is passed in is a password file, read the actual password. -+with open(params['output_password'], 'r') as fp: -+ output_password = fp.read() -+output_password = output_password.rstrip() -+ -+# Read the OVF document. -+with open(sys.argv[2], 'r') as fp: -+ ovf = fp.read() -+ -+# Parse out the username from the output_conn URL. -+parsed = urlparse(params['output_conn']) -+username = parsed.username or "admin@internal" -+ -+# Connect to the server. -+connection = sdk.Connection( -+ url = params['output_conn'], -+ username = username, -+ password = output_password, -+ ca_file = params['rhv_cafile'], -+ log = logging.getLogger(), -+ insecure = params['insecure'], -+) -+ -+system_service = connection.system_service() -+ -+# Get the storage domain UUID and substitute it into the OVF doc. -+sds_service = system_service.storage_domains_service() -+sd = sds_service.list(search=("name=%s" % params['output_storage']))[0] -+sd_uuid = sd.id -+ -+ovf.replace("@SD_UUID@", sd_uuid) -+ -+vms_service = system_service.vms_service() -+vm = vms_service.add( -+ types.Vm( -+ cluster=types.Cluster(name = params['rhv_cluster']), -+ initialization=types.Initialization( -+ configuration = types.Configuration( -+ type = types.ConfigurationType.OVA, -+ data = ovf, -+ ) -+ ) -+ ) -+) -diff --git a/v2v/rhv-upload-plugin.py b/v2v/rhv-upload-plugin.py -new file mode 100644 -index 000000000..791c9e7d2 ---- /dev/null -+++ b/v2v/rhv-upload-plugin.py -@@ -0,0 +1,445 @@ -+# -*- python -*- -+# oVirt or RHV upload nbdkit plugin used by ‘virt-v2v -o rhv-upload’ -+# Copyright (C) 2018 Red Hat Inc. -+# -+# This program is free software; you can redistribute it and/or modify -+# it under the terms of the GNU General Public License as published by -+# the Free Software Foundation; either version 2 of the License, or -+# (at your option) any later version. -+# -+# This program is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+# GNU General Public License for more details. -+# -+# You should have received a copy of the GNU General Public License along -+# with this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ -+import builtins -+import json -+import logging -+import ssl -+import sys -+import time -+ -+from http.client import HTTPSConnection -+from urllib.parse import urlparse -+ -+import ovirtsdk4 as sdk -+import ovirtsdk4.types as types -+ -+# Timeout to wait for oVirt disks to change status, or the transfer -+# object to finish initializing [seconds]. -+timeout = 5*60 -+ -+# Parameters are passed in via a JSON doc from the OCaml code. -+# Because this Python code ships embedded inside virt-v2v there -+# is no formal API here. -+params = None -+ -+def config(key, value): -+ global params -+ -+ if key == "params": -+ with builtins.open(value, 'r') as fp: -+ params = json.load(fp) -+ else: -+ raise RuntimeError("unknown configuration key '%s'" % key) -+ -+def config_complete(): -+ if params is None: -+ raise RuntimeError("missing configuration parameters") -+ -+def debug(s): -+ if params['verbose']: -+ print(s, file=sys.stderr) -+ sys.stderr.flush() -+ -+def open(readonly): -+ # Parse out the username from the output_conn URL. -+ parsed = urlparse(params['output_conn']) -+ username = parsed.username or "admin@internal" -+ -+ # Read the password from file. -+ with builtins.open(params['output_password'], 'r') as fp: -+ password = fp.read() -+ password = password.rstrip() -+ -+ # Connect to the server. -+ connection = sdk.Connection( -+ url = params['output_conn'], -+ username = username, -+ password = password, -+ ca_file = params['rhv_cafile'], -+ log = logging.getLogger(), -+ insecure = params['insecure'], -+ ) -+ -+ system_service = connection.system_service() -+ -+ # Create the disk. -+ disks_service = system_service.disks_service() -+ if params['disk_format'] == "raw": -+ disk_format = types.DiskFormat.RAW -+ else: -+ disk_format = types.DiskFormat.COW -+ disk = disks_service.add( -+ disk = types.Disk( -+ name = params['disk_name'], -+ description = "Uploaded by virt-v2v", -+ format = disk_format, -+ initial_size = params['disk_size'], -+ provisioned_size = params['disk_size'], -+ # XXX Ignores params['output_sparse']. -+ # Handling this properly will be complex, see: -+ # https://www.redhat.com/archives/libguestfs/2018-March/msg00177.html -+ sparse = True, -+ storage_domains = [ -+ types.StorageDomain( -+ name = params['output_storage'], -+ ) -+ ], -+ ) -+ ) -+ -+ # Wait till the disk is up, as the transfer can't start if the -+ # disk is locked: -+ disk_service = disks_service.disk_service(disk.id) -+ debug("disk.id = %r" % disk.id) -+ -+ endt = time.time() + timeout -+ while True: -+ time.sleep(5) -+ disk = disk_service.get() -+ if disk.status == types.DiskStatus.OK: -+ break -+ if time.time() > endt: -+ raise RuntimeError("timed out waiting for disk to become unlocked") -+ -+ # Get a reference to the transfer service. -+ transfers_service = system_service.image_transfers_service() -+ -+ # Create a new image transfer. -+ transfer = transfers_service.add( -+ types.ImageTransfer( -+ image = types.Image( -+ id = disk.id -+ ) -+ ) -+ ) -+ debug("transfer.id = %r" % transfer.id) -+ -+ # Get a reference to the created transfer service. -+ transfer_service = transfers_service.image_transfer_service(transfer.id) -+ -+ # After adding a new transfer for the disk, the transfer's status -+ # will be INITIALIZING. Wait until the init phase is over. The -+ # actual transfer can start when its status is "Transferring". -+ endt = time.time() + timeout -+ while True: -+ time.sleep(5) -+ transfer = transfer_service.get() -+ if transfer.phase != types.ImageTransferPhase.INITIALIZING: -+ break -+ if time.time() > endt: -+ raise RuntimeError("timed out waiting for transfer status " + -+ "!= INITIALIZING") -+ -+ # Now we have permission to start the transfer. -+ if params['rhv_direct']: -+ if transfer.transfer_url is None: -+ raise RuntimeError("direct upload to host not supported, " + -+ "requires ovirt-engine >= 4.2 and only works " + -+ "when virt-v2v is run within the oVirt/RHV " + -+ "environment, eg. on an oVirt node.") -+ destination_url = urlparse(transfer.transfer_url) -+ else: -+ destination_url = urlparse(transfer.proxy_url) -+ -+ context = ssl.create_default_context() -+ context.load_verify_locations(cafile = params['rhv_cafile']) -+ -+ http = HTTPSConnection( -+ destination_url.hostname, -+ destination_url.port, -+ context = context -+ ) -+ -+ # Save everything we need to make requests in the handle. -+ return { -+ 'can_flush': False, -+ 'can_trim': False, -+ 'can_zero': False, -+ 'connection': connection, -+ 'disk': disk, -+ 'disk_service': disk_service, -+ 'failed': False, -+ 'got_options': False, -+ 'highestwrite': 0, -+ 'http': http, -+ 'needs_auth': not params['rhv_direct'], -+ 'path': destination_url.path, -+ 'transfer': transfer, -+ 'transfer_service': transfer_service, -+ } -+ -+# Can we issue zero, trim or flush requests? -+def get_options(h): -+ if h['got_options']: -+ return -+ h['got_options'] = True -+ -+ http = h['http'] -+ transfer = h['transfer'] -+ -+ http.putrequest("OPTIONS", h['path']) -+ http.putheader("Authorization", transfer.signed_ticket) -+ http.endheaders() -+ -+ r = http.getresponse() -+ if r.status == 200: -+ # New imageio never needs authentication. -+ h['needs_auth'] = False -+ -+ j = json.loads(r.read()) -+ h['can_zero'] = "zero" in j['features'] -+ h['can_trim'] = "trim" in j['features'] -+ h['can_flush'] = "flush" in j['features'] -+ -+ # Old imageio servers returned either 405 Method Not Allowed or -+ # 204 No Content (with an empty body). If we see that we leave -+ # all the features as False and they will be emulated. -+ elif r.status == 405 or r.status == 204: -+ pass -+ -+ else: -+ raise RuntimeError("could not use OPTIONS request: %d: %s" % -+ (r.status, r.reason)) -+ -+def can_trim(h): -+ get_options(h) -+ return h['can_trim'] -+ -+def can_flush(h): -+ get_options(h) -+ return h['can_flush'] -+ -+def get_size(h): -+ return params['disk_size'] -+ -+# For documentation see: -+# https://github.com/oVirt/ovirt-imageio/blob/master/docs/random-io.md -+# For examples of working code to read/write from the server, see: -+# https://github.com/oVirt/ovirt-imageio/blob/master/daemon/test/server_test.py -+ -+def pread(h, count, offset): -+ http = h['http'] -+ transfer = h['transfer'] -+ transfer_service = h['transfer_service'] -+ -+ http.putrequest("GET", h['path']) -+ # Authorization is only needed for old imageio. -+ if h['needs_auth']: -+ http.putheader("Authorization", transfer.signed_ticket) -+ http.putheader("Range", "bytes=%d-%d" % (offset, offset+count-1)) -+ http.endheaders() -+ -+ r = http.getresponse() -+ # 206 = HTTP Partial Content. -+ if r.status != 206: -+ h['transfer_service'].pause() -+ h['failed'] = True -+ raise RuntimeError("could not read sector (%d, %d): %d: %s" % -+ (offset, count, r.status, r.reason)) -+ return r.read() -+ -+def pwrite(h, buf, offset): -+ http = h['http'] -+ transfer = h['transfer'] -+ transfer_service = h['transfer_service'] -+ -+ count = len(buf) -+ h['highestwrite'] = max(h['highestwrite'], offset+count) -+ -+ http.putrequest("PUT", h['path'] + "?flush=n") -+ # Authorization is only needed for old imageio. -+ if h['needs_auth']: -+ http.putheader("Authorization", transfer.signed_ticket) -+ # The oVirt server only uses the first part of the range, and the -+ # content-length. -+ http.putheader("Content-Range", "bytes %d-%d/*" % (offset, offset+count-1)) -+ http.putheader("Content-Length", str(count)) -+ http.endheaders() -+ http.send(buf) -+ -+ r = http.getresponse() -+ if r.status != 200: -+ transfer_service.pause() -+ h['failed'] = True -+ raise RuntimeError("could not write sector (%d, %d): %d: %s" % -+ (offset, count, r.status, r.reason)) -+ -+def zero(h, count, offset, may_trim): -+ http = h['http'] -+ transfer = h['transfer'] -+ transfer_service = h['transfer_service'] -+ -+ # Unlike the trim and flush calls, there is no 'can_zero' method -+ # so nbdkit could call this even if the server doesn't support -+ # zeroing. If this is the case we must emulate. -+ if not h['can_zero']: -+ emulate_zero(h, count, offset) -+ return -+ -+ # Construct the JSON request for zeroing. -+ buf = json.dumps({'op': "zero", -+ 'offset': offset, -+ 'size': count, -+ 'flush': False}).encode() -+ -+ http.putrequest("PATCH", h['path']) -+ http.putheader("Content-Type", "application/json") -+ http.putheader("Content-Length", len(buf)) -+ http.endheaders() -+ http.send(buf) -+ -+ r = http.getresponse() -+ if r.status != 200: -+ transfer_service.pause() -+ h['failed'] = True -+ raise RuntimeError("could not zero sector (%d, %d): %d: %s" % -+ (offset, count, r.status, r.reason)) -+ -+def emulate_zero(h, count, offset): -+ # qemu-img convert starts by trying to zero/trim the whole device. -+ # Since we've just created a new disk it's safe to ignore these -+ # requests as long as they are smaller than the highest write seen. -+ # After that we must emulate them with writes. -+ if offset+count < h['highestwrite']: -+ http.putrequest("PUT", h['path']) -+ # Authorization is only needed for old imageio. -+ if h['needs_auth']: -+ http.putheader("Authorization", transfer.signed_ticket) -+ http.putheader("Content-Range", -+ "bytes %d-%d/*" % (offset, offset+count-1)) -+ http.putheader("Content-Length", str(count)) -+ http.endheaders() -+ -+ buf = bytearray(128*1024) -+ while count > len(buf): -+ http.send(buf) -+ count -= len(buf) -+ http.send(buffer(buf, 0, count)) -+ -+ r = http.getresponse() -+ if r.status != 200: -+ transfer_service.pause() -+ h['failed'] = True -+ raise RuntimeError("could not write zeroes (%d, %d): %d: %s" % -+ (offset, count, r.status, r.reason)) -+ -+def trim(h, count, offset): -+ http = h['http'] -+ transfer = h['transfer'] -+ transfer_service = h['transfer_service'] -+ -+ # Construct the JSON request for trimming. -+ buf = json.dumps({'op': "trim", -+ 'offset': offset, -+ 'size': count, -+ 'flush': False}).encode() -+ -+ http.putrequest("PATCH", h['path']) -+ http.putheader("Content-Type", "application/json") -+ http.putheader("Content-Length", len(buf)) -+ http.endheaders() -+ http.send(buf) -+ -+ r = http.getresponse() -+ if r.status != 200: -+ transfer_service.pause() -+ h['failed'] = True -+ raise RuntimeError("could not trim sector (%d, %d): %d: %s" % -+ (offset, count, r.status, r.reason)) -+ -+def flush(h): -+ http = h['http'] -+ transfer = h['transfer'] -+ transfer_service = h['transfer_service'] -+ -+ # Construct the JSON request for flushing. -+ buf = json.dumps({'op': "flush"}).encode() -+ -+ http.putrequest("PATCH", h['path']) -+ http.putheader("Content-Type", "application/json") -+ http.putheader("Content-Length", len(buf)) -+ http.endheaders() -+ http.send(buf) -+ -+ r = http.getresponse() -+ if r.status != 200: -+ transfer_service.pause() -+ h['failed'] = True -+ raise RuntimeError("could not flush: %d: %s" % (r.status, r.reason)) -+ -+def delete_disk_on_failure(h): -+ disk_service = h['disk_service'] -+ disk_service.remove() -+ -+def close(h): -+ http = h['http'] -+ connection = h['connection'] -+ -+ # This is sometimes necessary because python doesn't set up -+ # sys.stderr to be line buffered and so debug, errors or -+ # exceptions printed previously might not be emitted before the -+ # plugin exits. -+ sys.stderr.flush() -+ -+ # If the connection failed earlier ensure we clean up the disk. -+ if h['failed']: -+ delete_disk_on_failure(h) -+ connection.close() -+ return -+ -+ try: -+ # Issue a flush request on close so that the data is written to -+ # persistent store before we create the VM. -+ if h['can_flush']: -+ flush(h) -+ -+ http.close() -+ -+ disk = h['disk'] -+ transfer_service = h['transfer_service'] -+ -+ transfer_service.finalize() -+ -+ # Wait until the transfer disk job is completed since -+ # only then we can be sure the disk is unlocked. As this -+ # code is not very clear, what's happening is that we are -+ # waiting for the transfer object to cease to exist, which -+ # falls through to the exception case and then we can -+ # continue. -+ endt = time.time() + timeout -+ try: -+ while True: -+ time.sleep(1) -+ tmp = transfer_service.get() -+ if time.time() > endt: -+ raise RuntimeError("timed out waiting for transfer " + -+ "to finalize") -+ except sdk.NotFoundError: -+ pass -+ -+ # Write the disk ID file. Only do this on successful completion. -+ with builtins.open(params['diskid_file'], 'w') as fp: -+ fp.write(disk.id) -+ -+ except: -+ # Otherwise on any failure we must clean up the disk. -+ delete_disk_on_failure(h) -+ raise -+ -+ connection.close() -diff --git a/v2v/rhv-upload-precheck.py b/v2v/rhv-upload-precheck.py -new file mode 100644 -index 000000000..2798a29dd ---- /dev/null -+++ b/v2v/rhv-upload-precheck.py -@@ -0,0 +1,73 @@ -+# -*- python -*- -+# oVirt or RHV pre-upload checks used by ‘virt-v2v -o rhv-upload’ -+# Copyright (C) 2018 Red Hat Inc. -+# -+# This program is free software; you can redistribute it and/or modify -+# it under the terms of the GNU General Public License as published by -+# the Free Software Foundation; either version 2 of the License, or -+# (at your option) any later version. -+# -+# This program is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+# GNU General Public License for more details. -+# -+# You should have received a copy of the GNU General Public License along -+# with this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ -+import json -+import logging -+import sys -+import time -+ -+from http.client import HTTPSConnection -+from urllib.parse import urlparse -+ -+import ovirtsdk4 as sdk -+import ovirtsdk4.types as types -+ -+# Parameters are passed in via a JSON doc from the OCaml code. -+# Because this Python code ships embedded inside virt-v2v there -+# is no formal API here. -+params = None -+ -+if len(sys.argv) != 2: -+ raise RuntimeError("incorrect number of parameters") -+ -+# Parameters are passed in via a JSON document. -+with open(sys.argv[1], 'r') as fp: -+ params = json.load(fp) -+ -+# What is passed in is a password file, read the actual password. -+with open(params['output_password'], 'r') as fp: -+ output_password = fp.read() -+output_password = output_password.rstrip() -+ -+# Parse out the username from the output_conn URL. -+parsed = urlparse(params['output_conn']) -+username = parsed.username or "admin@internal" -+ -+# Connect to the server. -+connection = sdk.Connection( -+ url = params['output_conn'], -+ username = username, -+ password = output_password, -+ ca_file = params['rhv_cafile'], -+ log = logging.getLogger(), -+ insecure = params['insecure'], -+) -+ -+system_service = connection.system_service() -+ -+# Find if a virtual machine already exists with that name. -+vms_service = system_service.vms_service() -+vms = vms_service.list( -+ search = ("name=%s" % params['output_name']), -+) -+if len(vms) > 0: -+ vm = vms[0] -+ raise RuntimeError("VM already exists with name ‘%s’, id ‘%s’" % -+ (params['output_name'], vm.id)) -+ -+# Otherwise everything is OK, exit with no error. -diff --git a/v2v/test-v2v-o-rhv-upload-oo-query.sh b/v2v/test-v2v-o-rhv-upload-oo-query.sh -new file mode 100755 -index 000000000..29d69e1c1 ---- /dev/null -+++ b/v2v/test-v2v-o-rhv-upload-oo-query.sh -@@ -0,0 +1,38 @@ -+#!/bin/bash - -+# libguestfs virt-v2v test script -+# Copyright (C) 2018 Red Hat Inc. -+# -+# This program is free software; you can redistribute it and/or modify -+# it under the terms of the GNU General Public License as published by -+# the Free Software Foundation; either version 2 of the License, or -+# (at your option) any later version. -+# -+# This program is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+# GNU General Public License for more details. -+# -+# You should have received a copy of the GNU General Public License -+# along with this program; if not, write to the Free Software -+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ -+# Test -oo "?" option. -+ -+set -e -+ -+$TEST_FUNCTIONS -+skip_if_skipped -+ -+export VIRT_TOOLS_DATA_DIR="$top_srcdir/test-data/fake-virt-tools" -+export VIRTIO_WIN="$top_srcdir/test-data/fake-virtio-win" -+ -+f=test-v2v-o-rhv-upload-oo-query.actual -+rm -f $f -+ -+$VG virt-v2v --debug-gc \ -+ -o rhv-upload -oo "?" > $f -+ -+grep -- "-oo rhv-cafile" $f -+grep -- "-oo rhv-verifypeer" $f -+ -+rm $f -diff --git a/v2v/test-v2v-python-syntax.sh b/v2v/test-v2v-python-syntax.sh -new file mode 100755 -index 000000000..b167f4610 ---- /dev/null -+++ b/v2v/test-v2v-python-syntax.sh -@@ -0,0 +1,45 @@ -+#!/bin/bash - -+# libguestfs -+# Copyright (C) 2018 Red Hat Inc. -+# -+# This program is free software; you can redistribute it and/or modify -+# it under the terms of the GNU General Public License as published by -+# the Free Software Foundation; either version 2 of the License, or -+# (at your option) any later version. -+# -+# This program is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+# GNU General Public License for more details. -+# -+# You should have received a copy of the GNU General Public License -+# along with this program; if not, write to the Free Software -+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ -+set -e -+ -+$TEST_FUNCTIONS -+skip_if_skipped -+ -+# Files to check. -+files="rhv-upload-createvm.py rhv-upload-plugin.py rhv-upload-precheck.py" -+ -+# Base version of Python. -+python=python3 -+ -+# Checks the files are syntactically correct, but not very much else. -+for f in $files; do -+ $python -m py_compile $f -+done -+ -+# Checks the files correspond to PEP8 coding style. -+# https://www.python.org/dev/peps/pep-0008/ -+if $python-pep8 --version >/dev/null 2>&1; then -+ for f in $files; do -+ # Ignore: -+ # E226 missing whitespace around arithmetic operator -+ # E251 unexpected spaces around keyword / parameter equals -+ # E302 expected 2 blank lines, found 1 -+ $python-pep8 --ignore=E226,E251,E302 $f -+ done -+fi -diff --git a/v2v/virt-v2v.pod b/v2v/virt-v2v.pod -index 69ca23dfd..2d2f8cfd3 100644 ---- a/v2v/virt-v2v.pod -+++ b/v2v/virt-v2v.pod -@@ -6,15 +6,18 @@ virt-v2v - Convert a guest to use KVM - - virt-v2v -ic vpx://vcenter.example.com/Datacenter/esxi vmware_guest - -- virt-v2v -ic vpx://vcenter.example.com/Datacenter/esxi vmware_guest \ -- -o rhv -os rhv.nfs:/export_domain --bridge ovirtmgmt -- - virt-v2v -i libvirtxml guest-domain.xml -o local -os /var/tmp - - virt-v2v -i disk disk.img -o local -os /var/tmp - - virt-v2v -i disk disk.img -o glance - -+ virt-v2v -ic vpx://vcenter.example.com/Datacenter/esxi vmware_guest \ -+ -o rhv-upload -oc https://ovirt-engine.example.com/ovirt-engine/api \ -+ -os ovirt-data -op /tmp/ovirt-admin-password -of raw \ -+ -oo rhv-cafile=/tmp/ca.pem -oo rhv-direct \ -+ --bridge ovirtmgmt -+ - virt-v2v -ic qemu:///system qemu_guest --in-place - - =head1 DESCRIPTION -@@ -52,20 +55,18 @@ For more information see L below. - =head2 Convert from VMware to RHV/oVirt - - This is the same as the previous example, except you want to send the --guest to a RHV-M Export Storage Domain which is located remotely --(over NFS) at C. If you are unclear about --the location of the Export Storage Domain you should check the --settings on your RHV-M management console. Guest network -+guest to a RHV Data Domain using the RHV REST API. Guest network - interface(s) are connected to the target network called C. - - virt-v2v -ic vpx://vcenter.example.com/Datacenter/esxi vmware_guest \ -- -o rhv -os rhv.nfs:/export_domain --bridge ovirtmgmt -+ -o rhv-upload -oc https://ovirt-engine.example.com/ovirt-engine/api \ -+ -os ovirt-data -op /tmp/ovirt-admin-password -of raw \ -+ -oo rhv-cafile=/tmp/ca.pem -oo rhv-direct \ -+ --bridge ovirtmgmt - - In this case the host running virt-v2v acts as a B. - --Note that after conversion, the guest will appear in the RHV-M Export --Storage Domain, from where you will need to import it using the RHV-M --user interface. (See L). -+For more information see L below. - - =head2 Convert from ESXi hypervisor over SSH to local libvirt - -@@ -129,9 +130,9 @@ qemu, do: - Xen ───▶│ -i libvirt ──▶ │ │ │ (default) │ - ... ───▶│ (default) │ │ │ ──┐ └────────────┘ - └────────────┘ │ │ ─┐└──────▶ -o glance -- -i libvirtxml ─────────▶ │ │ ┐└─────────▶ -o rhv -- -i vmx ────────────────▶ │ │ └──────────▶ -o vdsm -- └────────────┘ -+ -i libvirtxml ─────────▶ │ │ ┐├─────────▶ -o rhv -+ -i vmx ────────────────▶ │ │ │└─────────▶ -o vdsm -+ └────────────┘ └──────────▶ -o rhv-upload - - Virt-v2v has a number of possible input and output modes, selected - using the I<-i> and I<-o> options. Only one input and output mode can -@@ -164,8 +165,9 @@ libvirt configuration file (mainly for testing). - I<-o qemu> writes to a local disk image with a shell script for - booting the guest directly in qemu (mainly for testing). - --I<-o rhv> is used to write to a RHV / oVirt target. I<-o vdsm> --is only used when virt-v2v runs under VDSM control. -+I<-o rhv-upload> is used to write to a RHV / oVirt target. I<-o rhv> -+is a legacy method to write to RHV / oVirt E 4.2. I<-o vdsm> is -+only used when virt-v2v runs under VDSM control. - - I<--in-place> instructs virt-v2v to customize the guest OS in the input - virtual machine, instead of creating a new VM in the target hypervisor. -@@ -550,6 +552,10 @@ written. - - This is the same as I<-o rhv>. - -+=item B<-o> B -+ -+This is the same as I<-o rhv-upload>. -+ - =item B<-o> B - - Set the output method to I. -@@ -574,6 +580,16 @@ I<-os> parameter must also be used to specify the location of the - Export Storage Domain. Note this does not actually import the guest - into RHV. You have to do that manually later using the UI. - -+See L below. -+ -+=item B<-o> B -+ -+Set the output method to I. -+ -+The converted guest is written directly to a RHV Data Domain. -+This is a faster method than I<-o rhv>, but requires oVirt -+or RHV E 4.2. -+ - See L below. - - =item B<-o> B -@@ -615,7 +631,33 @@ the output name is the same as the input name. - Set output option(s) related to the current output mode. - To display short help on what options are available you can use: - -- virt-v2v -o vdsm -oo "?" -+ virt-v2v -o rhv-upload -oo "?" -+ -+=item B<-oo rhv-cafile=>F -+ -+For I<-o rhv-upload> (L) only, the F file -+(Certificate Authority), copied from F -+on the oVirt engine. -+ -+=item B<-oo rhv-cluster=>C -+ -+For I<-o rhv-upload> (L) only, set the RHV Cluster -+Name. If not given it uses C. -+ -+=item B<-oo rhv-direct> -+ -+For I<-o rhv-upload> (L) only, if this option is given -+then virt-v2v will attempt to directly upload the disk to the oVirt -+node, otherwise it will proxy the upload through the oVirt engine. -+Direct upload requires that you have network access to the oVirt -+nodes. Non-direct upload is slightly slower but should work in all -+situations. -+ -+=item B<-oo rhv-verifypeer> -+ -+For I<-o rhv-upload> (L) only, verify the oVirt/RHV -+server’s identity by checking the server‘s certificate against the -+Certificate Authority. - - =item B<-oo vdsm-compat=0.10> - -@@ -1901,6 +1943,68 @@ Define the final guest in libvirt: - - =head1 OUTPUT TO RHV - -+This new method to upload guests to oVirt or RHV directly via the REST -+API requires oVirt/RHV E 4.2. -+ -+You need to specify I<-o rhv-upload> as well as the following extra -+parameters: -+ -+=over 4 -+ -+=item I<-oc> C -+ -+The URL of the REST API which is usually the server name with -+C appended, but might be different if you installed -+oVirt Engine on a different path. -+ -+You can optionally add a username and port number to the URL. If the -+username is not specified then virt-v2v defaults to using -+C which is the typical superuser account for oVirt -+instances. -+ -+=item I<-of raw> -+ -+Currently you must use I<-of raw> and you cannot use I<-oa preallocated>. -+ -+These restrictions will be loosened in a future version. -+ -+=item I<-op> F -+ -+A file containing a password to be used when connecting to the oVirt -+engine. Note the file should contain the whole password, B, and for security the file should have mode -+C<0600> so that others cannot read it. -+ -+=item I<-os> C -+ -+The storage domain. -+ -+=item I<-oo rhv-cafile=>F -+ -+The F file (Certificate Authority), copied from -+F on the oVirt engine. -+ -+=item I<-oo rhv-cluster=>C -+ -+Set the RHV Cluster Name. If not given it uses C. -+ -+=item I<-oo rhv-direct> -+ -+If this option is given then virt-v2v will attempt to directly upload -+the disk to the oVirt node, otherwise it will proxy the upload through -+the oVirt engine. Direct upload requires that you have network access -+to the oVirt nodes. Non-direct upload is slightly slower but should -+work in all situations. -+ -+=item I<-oo rhv-verifypeer> -+ -+Verify the oVirt/RHV server’s identity by checking the server‘s -+certificate against the Certificate Authority. -+ -+=back -+ -+=head1 OUTPUT TO RHV (OLD METHOD) -+ - This section only applies to the I<-o rhv> output mode. If you use - virt-v2v from the RHV-M user interface, then behind the scenes the - import is managed by VDSM using the I<-o vdsm> output mode (which end --- -2.21.0 - diff --git a/SOURCES/0013-common-mltools-make-sure-machine-readable-output-is-.patch b/SOURCES/0013-common-mltools-make-sure-machine-readable-output-is-.patch new file mode 100644 index 0000000..febcfd1 --- /dev/null +++ b/SOURCES/0013-common-mltools-make-sure-machine-readable-output-is-.patch @@ -0,0 +1,34 @@ +From 61e503d193706c38d58147a2d308faf01948550c Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Fri, 22 Mar 2019 11:36:41 +0100 +Subject: [PATCH] common/mltools: make sure machine readable output is flushed + +Enhance the helper printf function for machine readable output to always +flush after each string: this way, readers of the machine readable +stream can get the output as soon as it is outputted. + +(cherry picked from commit abf1607f46ddc3d829a3688b9499a9bcd2319d19) +--- + common/mltools/tools_utils.ml | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/common/mltools/tools_utils.ml b/common/mltools/tools_utils.ml +index 5a35708cd..ade4cb37f 100644 +--- a/common/mltools/tools_utils.ml ++++ b/common/mltools/tools_utils.ml +@@ -59,7 +59,11 @@ let machine_readable () = + | None -> None + | Some chan -> + let pr fs = +- ksprintf (output_string chan) fs ++ let out s = ++ output_string chan s; ++ flush chan ++ in ++ ksprintf out fs + in + Some { pr } + +-- +2.25.4 + diff --git a/SOURCES/0013-v2v-refer-to-the-right-embed-script-in-EXTRA_DIST.patch b/SOURCES/0013-v2v-refer-to-the-right-embed-script-in-EXTRA_DIST.patch deleted file mode 100644 index d51e7ef..0000000 --- a/SOURCES/0013-v2v-refer-to-the-right-embed-script-in-EXTRA_DIST.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 2648e807faaa94c080c33b8a0d70c078339c59f8 Mon Sep 17 00:00:00 2001 -From: Pino Toscano -Date: Fri, 20 Apr 2018 13:00:56 +0200 -Subject: [PATCH] v2v: refer to the right embed script in EXTRA_DIST - -Fixes commit cc04573927cca97de60d544d37467e67c25867a7. - -(cherry picked from commit cf49fe100338aeac281c7cbcdfe743177ceb0606) ---- - v2v/Makefile.am | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/v2v/Makefile.am b/v2v/Makefile.am -index 694a64573..3a0c80f44 100644 ---- a/v2v/Makefile.am -+++ b/v2v/Makefile.am -@@ -31,7 +31,7 @@ EXTRA_DIST = \ - $(SOURCES_MLI) $(SOURCES_ML) $(SOURCES_C) \ - copy_to_local.ml \ - copy_to_local.mli \ -- embed-code.sh \ -+ embed.sh \ - rhv-upload-createvm.py \ - rhv-upload-plugin.py \ - rhv-upload-precheck.py \ --- -2.21.0 - diff --git a/SOURCES/0014-common-mltools-allow-fd-for-machine-readable-output.patch b/SOURCES/0014-common-mltools-allow-fd-for-machine-readable-output.patch new file mode 100644 index 0000000..8f9a207 --- /dev/null +++ b/SOURCES/0014-common-mltools-allow-fd-for-machine-readable-output.patch @@ -0,0 +1,87 @@ +From 0dd5c55c62f4e239c7be75852cf8a667be833cf1 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Fri, 22 Mar 2019 12:59:11 +0100 +Subject: [PATCH] common/mltools: allow fd for machine readable output + +Allow to specify a file descriptor for the machine readable output. + +Use the same assumption as done in v2v, i.e. that Unix.file_descr is +simply the int file descriptor. + +(cherry picked from commit 70514dfaf1e45b5ad34f20f3297af9782099cf80) +--- + common/mltools/test-machine-readable.sh | 7 +++++++ + common/mltools/tools_utils.ml | 11 ++++++++++- + lib/guestfs.pod | 5 +++++ + 3 files changed, 22 insertions(+), 1 deletion(-) + +diff --git a/common/mltools/test-machine-readable.sh b/common/mltools/test-machine-readable.sh +index 1162c58e9..824460e6d 100755 +--- a/common/mltools/test-machine-readable.sh ++++ b/common/mltools/test-machine-readable.sh +@@ -65,3 +65,10 @@ test $($t --machine-readable=stream:stdout |& wc -l) -eq 3 + # Output "stream:stderr". + $t --machine-readable=stream:stderr 2>&1 >/dev/null | grep 'machine-readable' + test $($t --machine-readable=stream:stderr 2>&1 >/dev/null | wc -l) -eq 2 ++ ++# Output "fd:". ++fn="$tmpdir/fdfile" ++exec 4>"$fn" ++$t --machine-readable=fd:4 ++exec 4>&- ++test $(cat "$fn" | wc -l) -eq 1 +diff --git a/common/mltools/tools_utils.ml b/common/mltools/tools_utils.ml +index ade4cb37f..35478f39e 100644 +--- a/common/mltools/tools_utils.ml ++++ b/common/mltools/tools_utils.ml +@@ -41,6 +41,7 @@ type machine_readable_output_type = + | NoOutput + | Channel of out_channel + | File of string ++ | Fd of int + let machine_readable_output = ref NoOutput + let machine_readable_channel = ref None + let machine_readable () = +@@ -50,7 +51,10 @@ let machine_readable () = + match !machine_readable_output with + | NoOutput -> None + | Channel chan -> Some chan +- | File f -> Some (open_out f) in ++ | File f -> Some (open_out f) ++ | Fd fd -> ++ (* Note that Unix.file_descr is really just an int. *) ++ Some (Unix.out_channel_of_descr (Obj.magic fd)) in + machine_readable_channel := chan + ); + !machine_readable_channel +@@ -296,6 +300,11 @@ let create_standard_options argspec ?anon_fun ?(key_opts = false) ?(machine_read + | n -> + error (f_"invalid output stream for --machine-readable: %s") fmt in + machine_readable_output := Channel chan ++ | "fd" -> ++ (try ++ machine_readable_output := Fd (int_of_string outname) ++ with Failure _ -> ++ error (f_"invalid output fd for --machine-readable: %s") fmt) + | n -> + error (f_"invalid output for --machine-readable: %s") fmt + ) +diff --git a/lib/guestfs.pod b/lib/guestfs.pod +index 53cece2da..f11028466 100644 +--- a/lib/guestfs.pod ++++ b/lib/guestfs.pod +@@ -3287,6 +3287,11 @@ The possible values are: + + =over 4 + ++=item BI ++ ++The output goes to the specified I, which is a file descriptor ++already opened for writing. ++ + =item BF + + The output goes to the specified F. +-- +2.25.4 + diff --git a/SOURCES/0014-v2v-o-rhv-upload-Don-t-require-of-raw-parameter.patch b/SOURCES/0014-v2v-o-rhv-upload-Don-t-require-of-raw-parameter.patch deleted file mode 100644 index 83c34e9..0000000 --- a/SOURCES/0014-v2v-o-rhv-upload-Don-t-require-of-raw-parameter.patch +++ /dev/null @@ -1,84 +0,0 @@ -From 2e9cc6b2307668f330d11384bba63b70160d3e42 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Fri, 20 Apr 2018 11:48:47 +0100 -Subject: [PATCH] =?UTF-8?q?v2v:=20-o=20rhv-upload:=20Don't=20require=20?= - =?UTF-8?q?=E2=80=98-of=20raw=E2=80=99=20parameter.?= -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Because we checked the limitation of raw+sparse during command line -processing, it had the effect of forcing you to use ‘-of raw’ even if -the input was already in raw format. Move the checking to the output -mode to avoid this. - -Fixes commit cc04573927cca97de60d544d37467e67c25867a7. - -(cherry picked from commit b3769afaece360b8a2095e3d8a7a934d351c3ade) ---- - v2v/cmdline.ml | 5 ----- - v2v/output_rhv_upload.ml | 18 +++++++++++++++++- - 2 files changed, 17 insertions(+), 6 deletions(-) - -diff --git a/v2v/cmdline.ml b/v2v/cmdline.ml -index 9b1348c37..97d4f4377 100644 ---- a/v2v/cmdline.ml -+++ b/v2v/cmdline.ml -@@ -586,11 +586,6 @@ read the man page virt-v2v(1). - | None -> - error (f_"-o rhv-upload: use ‘-oc’ to point to the oVirt or RHV server REST API URL, which is usually https://servername/ovirt-engine/api") - | Some oc -> oc in -- (* Output format / sparse must currently be raw+sparse. We can -- * change this in future. See TODO file for details. XXX -- *) -- if output_alloc <> Sparse || output_format <> Some "raw" then -- error (f_"-o rhv-upload: currently you must use ‘-of raw’ and you cannot use ‘-oa preallocated’ with this output mode. These restrictions will be loosened in a future version."); - (* In theory we could make the password optional in future. *) - let output_password = - match output_password with -diff --git a/v2v/output_rhv_upload.ml b/v2v/output_rhv_upload.ml -index 129461242..dc0d96d53 100644 ---- a/v2v/output_rhv_upload.ml -+++ b/v2v/output_rhv_upload.ml -@@ -169,6 +169,19 @@ See also \"OUTPUT TO RHV\" in the virt-v2v(1) manual.") - error (f_"nbdkit was compiled without SELinux support. You will have to recompile nbdkit with libselinux-devel installed, or else set SELinux to Permissive mode while doing the conversion.") - in - -+ (* Output format/sparse must be raw/sparse. We may be able to -+ * lift this limitation in future, but it requires changes on the -+ * RHV side. See TODO file for details. XXX -+ *) -+ let error_current_limitation required_param = -+ error (f_"rhv-upload: currently you must use ‘%s’. This restriction will be loosened in a future version.") required_param -+ in -+ -+ let error_unless_output_alloc_sparse () = -+ if output_alloc <> Sparse then -+ error_current_limitation "-oa sparse" -+ in -+ - (* JSON parameters which are invariant between disks. *) - let json_params = [ - "verbose", JSON.Bool (verbose ()); -@@ -220,6 +233,7 @@ object - error_unless_python_binary_on_path (); - error_unless_nbdkit_working (); - error_unless_nbdkit_python3_working (); -+ error_unless_output_alloc_sparse (); - if have_selinux then - error_unless_nbdkit_compiled_with_selinux () - -@@ -260,7 +274,9 @@ object - - let disk_format = - match t.target_format with -- | ("raw" | "qcow2") as fmt -> fmt -+ | "raw" as fmt -> fmt -+ | "qcow2" -> -+ error_current_limitation "-of raw" - | _ -> - error (f_"rhv-upload: -of %s: Only output format ‘raw’ or ‘qcow2’ is supported. If the input is in a different format then force one of these output formats by adding either ‘-of raw’ or ‘-of qcow2’ on the command line.") - t.target_format in --- -2.21.0 - diff --git a/SOURCES/0015-OCaml-tools-output-messages-into-JSON-for-machine-re.patch b/SOURCES/0015-OCaml-tools-output-messages-into-JSON-for-machine-re.patch new file mode 100644 index 0000000..7fa6ab5 --- /dev/null +++ b/SOURCES/0015-OCaml-tools-output-messages-into-JSON-for-machine-re.patch @@ -0,0 +1,514 @@ +From 1b29702cefae8a66c83bc84dd15e7b858af3ab47 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Fri, 22 Mar 2019 16:24:25 +0100 +Subject: [PATCH] OCaml tools: output messages into JSON for machine readable + +When the machine readable mode is enabled, print all the messages +(progress, info, warning, and errors) also as JSON in the machine +readable stream: this way, users can easily parse the status of the +OCaml tool, and report that back. + +The formatting of the current date time into the RFC 3999 format is done +in C, because of the lack of OCaml APIs for this. + +(cherry picked from commit f79129b8dc92470e3a5597daf53c84038bd6859e) +--- + .gitignore | 1 + + common/mltools/Makefile.am | 39 ++++++- + common/mltools/parse_tools_messages_test.py | 118 ++++++++++++++++++++ + common/mltools/test-tools-messages.sh | 28 +++++ + common/mltools/tools_messages_tests.ml | 46 ++++++++ + common/mltools/tools_utils-c.c | 51 +++++++++ + common/mltools/tools_utils.ml | 16 +++ + lib/guestfs.pod | 19 ++++ + 8 files changed, 316 insertions(+), 2 deletions(-) + create mode 100644 common/mltools/parse_tools_messages_test.py + create mode 100755 common/mltools/test-tools-messages.sh + create mode 100644 common/mltools/tools_messages_tests.ml + +diff --git a/.gitignore b/.gitignore +index f2efcdde2..db1dbb7cc 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -147,6 +147,7 @@ Makefile.in + /common/mltools/JSON_tests + /common/mltools/JSON_parser_tests + /common/mltools/machine_readable_tests ++/common/mltools/tools_messages_tests + /common/mltools/tools_utils_tests + /common/mltools/oUnit-* + /common/mlutils/.depend +diff --git a/common/mltools/Makefile.am b/common/mltools/Makefile.am +index 37d10e610..ae78b84b7 100644 +--- a/common/mltools/Makefile.am ++++ b/common/mltools/Makefile.am +@@ -27,6 +27,8 @@ EXTRA_DIST = \ + machine_readable_tests.ml \ + test-getopt.sh \ + test-machine-readable.sh \ ++ test-tools-messages.sh \ ++ tools_messages_tests.ml \ + tools_utils_tests.ml + + SOURCES_MLI = \ +@@ -45,12 +47,12 @@ SOURCES_MLI = \ + + SOURCES_ML = \ + getopt.ml \ ++ JSON.ml \ + tools_utils.ml \ + URI.ml \ + planner.ml \ + registry.ml \ + regedit.ml \ +- JSON.ml \ + JSON_parser.ml \ + curl.ml \ + checksums.ml \ +@@ -196,6 +198,15 @@ machine_readable_tests_CPPFLAGS = \ + machine_readable_tests_BOBJECTS = machine_readable_tests.cmo + machine_readable_tests_XOBJECTS = $(machine_readable_tests_BOBJECTS:.cmo=.cmx) + ++tools_messages_tests_SOURCES = dummy.c ++tools_messages_tests_CPPFLAGS = \ ++ -I. \ ++ -I$(top_builddir) \ ++ -I$(shell $(OCAMLC) -where) \ ++ -I$(top_srcdir)/lib ++tools_messages_tests_BOBJECTS = tools_messages_tests.cmo ++tools_messages_tests_XOBJECTS = $(tools_messages_tests_BOBJECTS:.cmo=.cmx) ++ + # Can't call the following as _OBJECTS because automake gets confused. + if !HAVE_OCAMLOPT + tools_utils_tests_THEOBJECTS = $(tools_utils_tests_BOBJECTS) +@@ -212,6 +223,9 @@ JSON_parser_tests.cmo: OCAMLPACKAGES += $(OCAMLPACKAGES_TESTS) + + machine_readable_tests_THEOBJECTS = $(machine_readable_tests_BOBJECTS) + machine_readable_tests.cmo: OCAMLPACKAGES += $(OCAMLPACKAGES_TESTS) ++ ++tools_messages_tests_THEOBJECTS = $(tools_messages_tests_tests_BOBJECTS) ++tools_messages_tests.cmo: OCAMLPACKAGES += $(OCAMLPACKAGES_TESTS) + else + tools_utils_tests_THEOBJECTS = $(tools_utils_tests_XOBJECTS) + tools_utils_tests.cmx: OCAMLPACKAGES += $(OCAMLPACKAGES_TESTS) +@@ -227,6 +241,9 @@ JSON_parser_tests.cmx: OCAMLPACKAGES += $(OCAMLPACKAGES_TESTS) + + machine_readable_tests_THEOBJECTS = $(machine_readable_tests_XOBJECTS) + machine_readable_tests.cmx: OCAMLPACKAGES += $(OCAMLPACKAGES_TESTS) ++ ++tools_messages_tests_THEOBJECTS = $(tools_messages_tests_XOBJECTS) ++tools_messages_tests.cmx: OCAMLPACKAGES += $(OCAMLPACKAGES_TESTS) + endif + + OCAMLLINKFLAGS = \ +@@ -302,14 +319,32 @@ machine_readable_tests_LINK = \ + $(OCAMLPACKAGES) $(OCAMLPACKAGES_TESTS) \ + $(machine_readable_tests_THEOBJECTS) -o $@ + ++tools_messages_tests_DEPENDENCIES = \ ++ $(tools_messages_tests_THEOBJECTS) \ ++ ../mlstdutils/mlstdutils.$(MLARCHIVE) \ ++ ../mlgettext/mlgettext.$(MLARCHIVE) \ ++ ../mlpcre/mlpcre.$(MLARCHIVE) \ ++ $(MLTOOLS_CMA) \ ++ $(top_srcdir)/ocaml-link.sh ++tools_messages_tests_LINK = \ ++ $(top_srcdir)/ocaml-link.sh -cclib '-lutils -lgnu' -- \ ++ $(OCAMLFIND) $(BEST) $(OCAMLFLAGS) $(OCAMLLINKFLAGS) \ ++ $(OCAMLPACKAGES) $(OCAMLPACKAGES_TESTS) \ ++ $(tools_messages_tests_THEOBJECTS) -o $@ ++ + TESTS_ENVIRONMENT = $(top_builddir)/run --test + + TESTS = \ + test-getopt.sh \ + test-machine-readable.sh ++if HAVE_PYTHON ++TESTS += \ ++ test-tools-messages.sh ++endif + check_PROGRAMS = \ + getopt_tests \ +- machine_readable_tests ++ machine_readable_tests \ ++ tools_messages_tests + + if HAVE_OCAML_PKG_OUNIT + check_PROGRAMS += JSON_tests JSON_parser_tests tools_utils_tests +diff --git a/common/mltools/parse_tools_messages_test.py b/common/mltools/parse_tools_messages_test.py +new file mode 100644 +index 000000000..9dcd6cae6 +--- /dev/null ++++ b/common/mltools/parse_tools_messages_test.py +@@ -0,0 +1,118 @@ ++# Copyright (C) 2019 Red Hat Inc. ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program; if not, write to the Free Software ++# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++import datetime ++import json ++import os ++import sys ++import unittest ++ ++exe = "tools_messages_tests" ++ ++if sys.version_info >= (3, 4): ++ def set_fd_inheritable(fd): ++ os.set_inheritable(fd, True) ++else: ++ def set_fd_inheritable(fd): ++ pass ++ ++ ++if sys.version_info >= (3, 0): ++ def fdopen(fd, mode): ++ return open(fd, mode) ++ ++ def isModuleInstalled(mod): ++ import importlib ++ return bool(importlib.util.find_spec(mod)) ++else: ++ def fdopen(fd, mode): ++ return os.fdopen(fd, mode) ++ ++ def isModuleInstalled(mod): ++ import imp ++ try: ++ imp.find_module(mod) ++ return True ++ except ImportError: ++ return False ++ ++ ++def skipUnlessHasModule(mod): ++ if not isModuleInstalled(mod): ++ return unittest.skip("%s not available" % mod) ++ return lambda func: func ++ ++ ++def iterload(stream): ++ dec = json.JSONDecoder() ++ for line in stream: ++ yield dec.raw_decode(line) ++ ++ ++def loadJsonFromCommand(extraargs): ++ r, w = os.pipe() ++ set_fd_inheritable(r) ++ r = fdopen(r, "r") ++ set_fd_inheritable(w) ++ w = fdopen(w, "w") ++ pid = os.fork() ++ if pid: ++ w.close() ++ l = list(iterload(r)) ++ l = [o[0] for o in l] ++ r.close() ++ return l ++ else: ++ r.close() ++ args = ["tools_messages_tests", ++ "--machine-readable=fd:%d" % w.fileno()] + extraargs ++ os.execvp("./" + exe, args) ++ ++ ++@skipUnlessHasModule('iso8601') ++class TestParseToolsMessages(unittest.TestCase): ++ def check_json(self, json, typ, msg): ++ import iso8601 ++ # Check the type. ++ jsontype = json.pop("type") ++ self.assertEqual(jsontype, typ) ++ # Check the message. ++ jsonmsg = json.pop("message") ++ self.assertEqual(jsonmsg, msg) ++ # Check the timestamp. ++ jsonts = json.pop("timestamp") ++ dt = iso8601.parse_date(jsonts) ++ now = datetime.datetime.now(dt.tzinfo) ++ self.assertGreater(now, dt) ++ # Check there are no more keys left (and thus not previously tested). ++ self.assertEqual(len(json), 0) ++ ++ def test_messages(self): ++ objects = loadJsonFromCommand([]) ++ self.assertEqual(len(objects), 4) ++ self.check_json(objects[0], "message", "Starting") ++ self.check_json(objects[1], "info", "An information message") ++ self.check_json(objects[2], "warning", "Warning: message here") ++ self.check_json(objects[3], "message", "Finishing") ++ ++ def test_error(self): ++ objects = loadJsonFromCommand(["--error"]) ++ self.assertEqual(len(objects), 1) ++ self.check_json(objects[0], "error", "Error!") ++ ++ ++if __name__ == '__main__': ++ unittest.main() +diff --git a/common/mltools/test-tools-messages.sh b/common/mltools/test-tools-messages.sh +new file mode 100755 +index 000000000..0e24d6ce9 +--- /dev/null ++++ b/common/mltools/test-tools-messages.sh +@@ -0,0 +1,28 @@ ++#!/bin/bash - ++# libguestfs ++# Copyright (C) 2019 Red Hat Inc. ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program; if not, write to the Free Software ++# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++# Test the --machine-readable functionality of the module Tools_utils. ++# See also: machine_readable_tests.ml ++ ++set -e ++set -x ++ ++$TEST_FUNCTIONS ++skip_if_skipped ++ ++$PYTHON parse_tools_messages_test.py +diff --git a/common/mltools/tools_messages_tests.ml b/common/mltools/tools_messages_tests.ml +new file mode 100644 +index 000000000..d5f9be89b +--- /dev/null ++++ b/common/mltools/tools_messages_tests.ml +@@ -0,0 +1,46 @@ ++(* ++ * Copyright (C) 2019 Red Hat Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ *) ++ ++(* Test the message output for tools of the module Tools_utils. ++ * The tests are controlled by the test-tools-messages.sh script. ++ *) ++ ++open Printf ++ ++open Std_utils ++open Tools_utils ++open Getopt.OptionName ++ ++let is_error = ref false ++ ++let args = [ ++ [ L "error" ], Getopt.Set is_error, "Only print the error"; ++] ++let usage_msg = sprintf "%s: test the message outputs" prog ++ ++let opthandle = create_standard_options args ~machine_readable:true usage_msg ++let () = ++ Getopt.parse opthandle.getopt; ++ ++ if !is_error then ++ error "Error!"; ++ ++ message "Starting"; ++ info "An information message"; ++ warning "Warning: message here"; ++ message "Finishing" +diff --git a/common/mltools/tools_utils-c.c b/common/mltools/tools_utils-c.c +index c88c95082..b015dcace 100644 +--- a/common/mltools/tools_utils-c.c ++++ b/common/mltools/tools_utils-c.c +@@ -23,6 +23,8 @@ + #include + #include + #include ++#include ++#include + + #include + #include +@@ -37,6 +39,7 @@ + extern value guestfs_int_mllib_inspect_decrypt (value gv, value gpv, value keysv); + extern value guestfs_int_mllib_set_echo_keys (value unitv); + extern value guestfs_int_mllib_set_keys_from_stdin (value unitv); ++extern value guestfs_int_mllib_rfc3999_date_time_string (value unitv); + + /* Interface with the guestfish inspection and decryption code. */ + int echo_keys = 0; +@@ -103,3 +106,51 @@ guestfs_int_mllib_set_keys_from_stdin (value unitv) + keys_from_stdin = 1; + return Val_unit; + } ++ ++value ++guestfs_int_mllib_rfc3999_date_time_string (value unitv) ++{ ++ CAMLparam1 (unitv); ++ char buf[64]; ++ struct timespec ts; ++ struct tm tm; ++ size_t ret; ++ size_t total = 0; ++ ++ if (clock_gettime (CLOCK_REALTIME, &ts) == -1) ++ unix_error (errno, (char *) "clock_gettime", Val_unit); ++ ++ if (localtime_r (&ts.tv_sec, &tm) == NULL) ++ unix_error (errno, (char *) "localtime_r", caml_copy_int64 (ts.tv_sec)); ++ ++ /* Sadly strftime does not support nanoseconds, so what we do is: ++ * - stringify everything before the nanoseconds ++ * - print the nanoseconds ++ * - stringify the rest (i.e. the timezone) ++ * then place ':' between the hours, and the minutes of the ++ * timezone offset. ++ */ ++ ++ ret = strftime (buf, sizeof (buf), "%Y-%m-%dT%H:%M:%S.", &tm); ++ if (ret == 0) ++ unix_error (errno, (char *) "strftime", Val_unit); ++ total += ret; ++ ++ ret = snprintf (buf + total, sizeof (buf) - total, "%09ld", ts.tv_nsec); ++ if (ret == 0) ++ unix_error (errno, (char *) "sprintf", caml_copy_int64 (ts.tv_nsec)); ++ total += ret; ++ ++ ret = strftime (buf + total, sizeof (buf) - total, "%z", &tm); ++ if (ret == 0) ++ unix_error (errno, (char *) "strftime", Val_unit); ++ total += ret; ++ ++ /* Move the timezone minutes one character to the right, moving the ++ * null character too. ++ */ ++ memmove (buf + total - 1, buf + total - 2, 3); ++ buf[total - 2] = ':'; ++ ++ CAMLreturn (caml_copy_string (buf)); ++} +diff --git a/common/mltools/tools_utils.ml b/common/mltools/tools_utils.ml +index 35478f39e..de42df600 100644 +--- a/common/mltools/tools_utils.ml ++++ b/common/mltools/tools_utils.ml +@@ -32,6 +32,7 @@ and key_store_key = + external c_inspect_decrypt : Guestfs.t -> int64 -> (string * key_store_key) list -> unit = "guestfs_int_mllib_inspect_decrypt" + external c_set_echo_keys : unit -> unit = "guestfs_int_mllib_set_echo_keys" "noalloc" + external c_set_keys_from_stdin : unit -> unit = "guestfs_int_mllib_set_keys_from_stdin" "noalloc" ++external c_rfc3999_date_time_string : unit -> string = "guestfs_int_mllib_rfc3999_date_time_string" + + type machine_readable_fn = { + pr : 'a. ('a, unit, string, unit) format4 -> 'a; +@@ -86,12 +87,24 @@ let ansi_magenta ?(chan = stdout) () = + let ansi_restore ?(chan = stdout) () = + if colours () || istty chan then output_string chan "\x1b[0m" + ++let log_as_json msgtype msg = ++ match machine_readable () with ++ | None -> () ++ | Some { pr } -> ++ let json = [ ++ "message", JSON.String msg; ++ "timestamp", JSON.String (c_rfc3999_date_time_string ()); ++ "type", JSON.String msgtype; ++ ] in ++ pr "%s\n" (JSON.string_of_doc ~fmt:JSON.Compact json) ++ + (* Timestamped progress messages, used for ordinary messages when not + * --quiet. + *) + let start_t = Unix.gettimeofday () + let message fs = + let display str = ++ log_as_json "message" str; + if not (quiet ()) then ( + let t = sprintf "%.1f" (Unix.gettimeofday () -. start_t) in + printf "[%6s] " t; +@@ -106,6 +119,7 @@ let message fs = + (* Error messages etc. *) + let error ?(exit_code = 1) fs = + let display str = ++ log_as_json "error" str; + let chan = stderr in + ansi_red ~chan (); + wrap ~chan (sprintf (f_"%s: error: %s") prog str); +@@ -124,6 +138,7 @@ let error ?(exit_code = 1) fs = + + let warning fs = + let display str = ++ log_as_json "warning" str; + let chan = stdout in + ansi_blue ~chan (); + wrap ~chan (sprintf (f_"%s: warning: %s") prog str); +@@ -134,6 +149,7 @@ let warning fs = + + let info fs = + let display str = ++ log_as_json "info" str; + let chan = stdout in + ansi_magenta ~chan (); + wrap ~chan (sprintf (f_"%s: %s") prog str); +diff --git a/lib/guestfs.pod b/lib/guestfs.pod +index f11028466..3c1d635c5 100644 +--- a/lib/guestfs.pod ++++ b/lib/guestfs.pod +@@ -3279,6 +3279,25 @@ Some of the tools support a I<--machine-readable> option, which is + generally used to make the output more machine friendly, for easier + parsing for example. By default, this output goes to stdout. + ++When using the I<--machine-readable> option, the progress, ++information, warning, and error messages are also printed in JSON ++format for easier log tracking. Thus, it is highly recommended to ++redirect the machine-readable output to a different stream. The ++format of these JSON messages is like the following (actually printed ++within a single line, below it is indented for readability): ++ ++ { ++ "message": "Finishing off", ++ "timestamp": "2019-03-22T14:46:49.067294446+01:00", ++ "type": "message" ++ } ++ ++C can be: C for progress messages, C for ++information messages, C for warning messages, and C ++for error message. ++C is the L ++timestamp of the message. ++ + In addition to that, a subset of these tools support an extra string + passed to the I<--machine-readable> option: this string specifies + where the machine-readable output will go. +-- +2.25.4 + diff --git a/SOURCES/0015-v2v-o-rhv-upload-install-RHV-tools-RHBZ-1561828.patch b/SOURCES/0015-v2v-o-rhv-upload-install-RHV-tools-RHBZ-1561828.patch deleted file mode 100644 index a5b0312..0000000 --- a/SOURCES/0015-v2v-o-rhv-upload-install-RHV-tools-RHBZ-1561828.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 1ddbe89dbc3877e6135e13413f97ee30a12c8e72 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Golembiovsk=C3=BD?= -Date: Sun, 22 Apr 2018 22:57:55 +0200 -Subject: [PATCH] v2v: -o rhv-upload: install RHV tools (RHBZ#1561828). -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Tomáš Golembiovský -(cherry picked from commit f3f00d3f9c6464aa31e3091bdee1191ef15512c6) ---- - v2v/output_rhv_upload.ml | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/v2v/output_rhv_upload.ml b/v2v/output_rhv_upload.ml -index dc0d96d53..0152b8d5a 100644 ---- a/v2v/output_rhv_upload.ml -+++ b/v2v/output_rhv_upload.ml -@@ -247,6 +247,9 @@ object - - method supported_firmware = [ TargetBIOS ] - -+ (* rhev-apt.exe will be installed (if available). *) -+ method install_rhev_apt = true -+ - method prepare_targets source targets = - let output_name = source.s_name in - let json_params = --- -2.21.0 - diff --git a/SOURCES/0016-OCaml-tools-fix-3999-3339-typo.patch b/SOURCES/0016-OCaml-tools-fix-3999-3339-typo.patch new file mode 100644 index 0000000..e4e9f0f --- /dev/null +++ b/SOURCES/0016-OCaml-tools-fix-3999-3339-typo.patch @@ -0,0 +1,77 @@ +From 1d4e167ebcf75771957f3ba109354a8217e78004 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Mon, 1 Apr 2019 17:01:44 +0200 +Subject: [PATCH] OCaml tools: fix 3999 -> 3339 typo + +RFC 3339 is the actual RFC for date/time strings. +Typo found by Martin 'eagle eyes' Kletzander. + +Fixes commit f79129b8dc92470e3a5597daf53c84038bd6859e. + +(cherry picked from commit 1086599ad8eeb8be299d5ffbcb2efb1024ff9ab8) +--- + common/mltools/tools_utils-c.c | 4 ++-- + common/mltools/tools_utils.ml | 4 ++-- + lib/guestfs.pod | 2 +- + 3 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/common/mltools/tools_utils-c.c b/common/mltools/tools_utils-c.c +index b015dcace..3b80091c0 100644 +--- a/common/mltools/tools_utils-c.c ++++ b/common/mltools/tools_utils-c.c +@@ -39,7 +39,7 @@ + extern value guestfs_int_mllib_inspect_decrypt (value gv, value gpv, value keysv); + extern value guestfs_int_mllib_set_echo_keys (value unitv); + extern value guestfs_int_mllib_set_keys_from_stdin (value unitv); +-extern value guestfs_int_mllib_rfc3999_date_time_string (value unitv); ++extern value guestfs_int_mllib_rfc3339_date_time_string (value unitv); + + /* Interface with the guestfish inspection and decryption code. */ + int echo_keys = 0; +@@ -108,7 +108,7 @@ guestfs_int_mllib_set_keys_from_stdin (value unitv) + } + + value +-guestfs_int_mllib_rfc3999_date_time_string (value unitv) ++guestfs_int_mllib_rfc3339_date_time_string (value unitv) + { + CAMLparam1 (unitv); + char buf[64]; +diff --git a/common/mltools/tools_utils.ml b/common/mltools/tools_utils.ml +index de42df600..127180225 100644 +--- a/common/mltools/tools_utils.ml ++++ b/common/mltools/tools_utils.ml +@@ -32,7 +32,7 @@ and key_store_key = + external c_inspect_decrypt : Guestfs.t -> int64 -> (string * key_store_key) list -> unit = "guestfs_int_mllib_inspect_decrypt" + external c_set_echo_keys : unit -> unit = "guestfs_int_mllib_set_echo_keys" "noalloc" + external c_set_keys_from_stdin : unit -> unit = "guestfs_int_mllib_set_keys_from_stdin" "noalloc" +-external c_rfc3999_date_time_string : unit -> string = "guestfs_int_mllib_rfc3999_date_time_string" ++external c_rfc3339_date_time_string : unit -> string = "guestfs_int_mllib_rfc3339_date_time_string" + + type machine_readable_fn = { + pr : 'a. ('a, unit, string, unit) format4 -> 'a; +@@ -93,7 +93,7 @@ let log_as_json msgtype msg = + | Some { pr } -> + let json = [ + "message", JSON.String msg; +- "timestamp", JSON.String (c_rfc3999_date_time_string ()); ++ "timestamp", JSON.String (c_rfc3339_date_time_string ()); + "type", JSON.String msgtype; + ] in + pr "%s\n" (JSON.string_of_doc ~fmt:JSON.Compact json) +diff --git a/lib/guestfs.pod b/lib/guestfs.pod +index 3c1d635c5..af944ddb7 100644 +--- a/lib/guestfs.pod ++++ b/lib/guestfs.pod +@@ -3295,7 +3295,7 @@ within a single line, below it is indented for readability): + C can be: C for progress messages, C for + information messages, C for warning messages, and C + for error message. +-C is the L ++C is the L + timestamp of the message. + + In addition to that, a subset of these tools support an extra string +-- +2.25.4 + diff --git a/SOURCES/0016-v2v-Map-Windows-Server-2012-R2-x86-64-to-ovirt-ID-25.patch b/SOURCES/0016-v2v-Map-Windows-Server-2012-R2-x86-64-to-ovirt-ID-25.patch deleted file mode 100644 index 6e149e8..0000000 --- a/SOURCES/0016-v2v-Map-Windows-Server-2012-R2-x86-64-to-ovirt-ID-25.patch +++ /dev/null @@ -1,30 +0,0 @@ -From c2570c81e8c3dffadbcfa5c857a38ae858745f9e Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Tue, 1 May 2018 11:30:11 +0100 -Subject: [PATCH] v2v: Map Windows Server 2012 R2 x86-64 to ovirt ID 25. - -Thanks: Michal Skrivanek - -Fixes commit 593a19cc86cfa8f24c66518c8ba21222550b066a. - -(cherry picked from commit c6e89299299f1f620437ac3d05a1f0f12de0f208) ---- - v2v/create_ovf.ml | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/v2v/create_ovf.ml b/v2v/create_ovf.ml -index b1ab8df3f..b3beb1eba 100644 ---- a/v2v/create_ovf.ml -+++ b/v2v/create_ovf.ml -@@ -418,7 +418,7 @@ and get_ovirt_osid = function - - | { i_type = "windows"; i_major_version = 6; i_minor_version = 3; - i_arch = "x86_64" } -> -- 23 -+ 25 - - | { i_type = "windows"; i_major_version = 10; i_minor_version = 0; - i_arch = "i386" } -> --- -2.21.0 - diff --git a/SOURCES/0017-v2v-fix-build-rules-for-output_rhv_upload_-_source.m.patch b/SOURCES/0017-v2v-fix-build-rules-for-output_rhv_upload_-_source.m.patch deleted file mode 100644 index eba4322..0000000 --- a/SOURCES/0017-v2v-fix-build-rules-for-output_rhv_upload_-_source.m.patch +++ /dev/null @@ -1,54 +0,0 @@ -From b31fcaf9879b9f4fe36a19e439895a867a1fbc72 Mon Sep 17 00:00:00 2001 -From: Pino Toscano -Date: Tue, 22 May 2018 17:24:18 +0200 -Subject: [PATCH] v2v: fix build rules for output_rhv_upload_*_source.ml files - -Use the $(srcdir) variable where needed, to make sure it builds also -with srcdir != builddir. - -Furthermore, make sure that the OCaml dependencies calculation depend on -the generated output_rhv_upload_*_source.ml files, otherwise there will -be incomplete OCaml rules for them in the generated .depend. - -Fixes commit cc04573927cca97de60d544d37467e67c25867a7. - -(cherry picked from commit a4e3b7c0598370d8d068b21909da95b6031eb688) ---- - v2v/Makefile.am | 14 +++++++------- - 1 file changed, 7 insertions(+), 7 deletions(-) - -diff --git a/v2v/Makefile.am b/v2v/Makefile.am -index 3a0c80f44..7de050b06 100644 ---- a/v2v/Makefile.am -+++ b/v2v/Makefile.am -@@ -143,12 +143,12 @@ SOURCES_C = \ - - # These files are generated and contain rhv-upload-*.py embedded as an - # OCaml string. --output_rhv_upload_createvm_source.ml: rhv-upload-createvm.py -- ./embed.sh code $^ $@ --output_rhv_upload_plugin_source.ml: rhv-upload-plugin.py -- ./embed.sh code $^ $@ --output_rhv_upload_precheck_source.ml: rhv-upload-precheck.py -- ./embed.sh code $^ $@ -+output_rhv_upload_createvm_source.ml: $(srcdir)/rhv-upload-createvm.py -+ $(srcdir)/embed.sh code $^ $@ -+output_rhv_upload_plugin_source.ml: $(srcdir)/rhv-upload-plugin.py -+ $(srcdir)/embed.sh code $^ $@ -+output_rhv_upload_precheck_source.ml: $(srcdir)/rhv-upload-precheck.py -+ $(srcdir)/embed.sh code $^ $@ - - if HAVE_OCAML - -@@ -575,7 +575,7 @@ v2v_unit_tests_LINK = \ - $(v2v_unit_tests_THEOBJECTS) -o $@ - - # Dependencies. --.depend: $(srcdir)/*.mli $(srcdir)/*.ml -+.depend: $(srcdir)/*.mli $(srcdir)/*.ml output_rhv_upload_createvm_source.ml output_rhv_upload_plugin_source.ml output_rhv_upload_precheck_source.ml - $(top_builddir)/ocaml-dep.sh $^ - -include .depend - --- -2.21.0 - diff --git a/SOURCES/0017-v2v-remove-extra-nbdkit-bit-from-documentation-RHBZ-.patch b/SOURCES/0017-v2v-remove-extra-nbdkit-bit-from-documentation-RHBZ-.patch new file mode 100644 index 0000000..d05b5b2 --- /dev/null +++ b/SOURCES/0017-v2v-remove-extra-nbdkit-bit-from-documentation-RHBZ-.patch @@ -0,0 +1,31 @@ +From 18007f645332e6a7c039a6bdb690e0a55f9cd1c7 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Thu, 18 Jul 2019 15:38:53 +0200 +Subject: [PATCH] v2v: remove extra nbdkit bit from documentation + (RHBZ#1723305) + +Since there is no more need to build nbdkit from sources, then there is +no need to set $PATH with a custom build of nbdkit. + +Followup of commit 0704d8eb0bcc8139886eb4291f75a3ca49a91e58. + +(cherry picked from commit 6d251e3828ff94deac7589b5892df174430e01f9) +--- + v2v/virt-v2v-input-vmware.pod | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/v2v/virt-v2v-input-vmware.pod b/v2v/virt-v2v-input-vmware.pod +index b3ebda182..3acdd773e 100644 +--- a/v2v/virt-v2v-input-vmware.pod ++++ b/v2v/virt-v2v-input-vmware.pod +@@ -293,7 +293,6 @@ To import a particular guest from vCenter server or ESXi hypervisor, + use a command like the following, substituting the URI, guest name and + SSL thumbprint: + +- $ export PATH=/path/to/nbdkit-1.1.x:$PATH + $ virt-v2v \ + -ic 'vpx://root@vcenter.example.com/Datacenter/esxi?no_verify=1' \ + -it vddk \ +-- +2.25.4 + diff --git a/SOURCES/0018-v2v-fix-rhevexp-typo-in-documentation.patch b/SOURCES/0018-v2v-fix-rhevexp-typo-in-documentation.patch deleted file mode 100644 index 9f4f779..0000000 --- a/SOURCES/0018-v2v-fix-rhevexp-typo-in-documentation.patch +++ /dev/null @@ -1,37 +0,0 @@ -From bd2afb6e11b107aa7f158136ff6d4fb24732b2bf Mon Sep 17 00:00:00 2001 -From: Pino Toscano -Date: Tue, 29 May 2018 06:49:23 +0200 -Subject: [PATCH] v2v: fix "rhevexp" typo in documentation - -Spotted by Ming Xie. - -(cherry picked from commit c021ac5e64053052a392762aaff9c8ed73fc2082) ---- - v2v/virt-v2v.pod | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/v2v/virt-v2v.pod b/v2v/virt-v2v.pod -index 2d2f8cfd3..f012ea533 100644 ---- a/v2v/virt-v2v.pod -+++ b/v2v/virt-v2v.pod -@@ -728,7 +728,7 @@ Currently there are two possible flavours: - - =over 4 - --=item rhevexp -+=item rhvexp - - The OVF format used in RHV export storage domain. - -@@ -738,7 +738,7 @@ The OVF format understood by oVirt REST API. - - =back - --For backward compatibility the default is I, but this may change in -+For backward compatibility the default is I, but this may change in - the future. - - =item B<-op> file --- -2.21.0 - diff --git a/SOURCES/0018-v2v-i-vmx-Use-scp-T-option-if-available-to-unbreak-s.patch b/SOURCES/0018-v2v-i-vmx-Use-scp-T-option-if-available-to-unbreak-s.patch new file mode 100644 index 0000000..8c3611a --- /dev/null +++ b/SOURCES/0018-v2v-i-vmx-Use-scp-T-option-if-available-to-unbreak-s.patch @@ -0,0 +1,49 @@ +From d74842f209b5461692a2d283d622157862bdc230 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 25 Jul 2019 14:52:42 +0100 +Subject: [PATCH] v2v: -i vmx: Use scp -T option if available to unbreak scp + (RHBZ#1733168). + +Tested using: + +cd v2v +LIBGUESTFS_BACKEND=direct ../run virt-v2v -i vmx -it ssh "ssh://localhost/$PWD/test-v2v-i-vmx-1.vmx" -o null -v -x + +and manually examining the debug output. + +Thanks: Ming Xie, Jakub Jelen. +(cherry picked from commit 7692c31494f7b1d37e380eed9eb99c5952940dbf) +--- + v2v/input_vmx.ml | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/v2v/input_vmx.ml b/v2v/input_vmx.ml +index b169b2537..e3469308d 100644 +--- a/v2v/input_vmx.ml ++++ b/v2v/input_vmx.ml +@@ -61,6 +61,11 @@ let server_of_uri { Xml.uri_server } = + let path_of_uri { Xml.uri_path } = + match uri_path with None -> assert false | Some p -> p + ++let scp_supports_T_option = lazy ( ++ let cmd = "LANG=C scp -T |& grep \"unknown option\"" in ++ shell_command cmd <> 0 ++) ++ + (* 'scp' a remote file into a temporary local file, returning the path + * of the temporary local file. + *) +@@ -68,8 +73,9 @@ let scp_from_remote_to_temporary uri tmpdir filename = + let localfile = tmpdir // filename in + + let cmd = +- sprintf "scp%s%s %s%s:%s %s" ++ sprintf "scp%s%s%s %s%s:%s %s" + (if verbose () then "" else " -q") ++ (if Lazy.force scp_supports_T_option then " -T" else "") + (match port_of_uri uri with + | None -> "" + | Some port -> sprintf " -P %d" port) +-- +2.25.4 + diff --git a/SOURCES/0019-v2v-Allow-Windows-virtio-ISO-to-be-a-block-device-as.patch b/SOURCES/0019-v2v-Allow-Windows-virtio-ISO-to-be-a-block-device-as.patch new file mode 100644 index 0000000..6c92927 --- /dev/null +++ b/SOURCES/0019-v2v-Allow-Windows-virtio-ISO-to-be-a-block-device-as.patch @@ -0,0 +1,28 @@ +From 4b94dac532dc17cde462479bf90ab2631006b80b Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 4 Jul 2019 15:51:25 +0100 +Subject: [PATCH] v2v: Allow Windows virtio ISO to be a block device as well as + a regular file. + +Thanks: Steven Rosenberg +(cherry picked from commit c22a8b68fe5729d3a8907b41eef287cd9f3a55c0) +--- + v2v/windows_virtio.ml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/v2v/windows_virtio.ml b/v2v/windows_virtio.ml +index 92bf3ec60..a6dc29f2c 100644 +--- a/v2v/windows_virtio.ml ++++ b/v2v/windows_virtio.ml +@@ -330,7 +330,7 @@ and copy_from_virtio_win g inspect srcdir destdir filter missing = + ) paths + ) + ) +- else if is_regular_file virtio_win then ( ++ else if is_regular_file virtio_win || is_block_device virtio_win then ( + debug "windows: copy_from_virtio_win: guest tools source ISO %s" virtio_win; + + try +-- +2.25.4 + diff --git a/SOURCES/0019-v2v-add-and-use-Create_ovf.ovf_flavour_to_string.patch b/SOURCES/0019-v2v-add-and-use-Create_ovf.ovf_flavour_to_string.patch deleted file mode 100644 index bd23b8b..0000000 --- a/SOURCES/0019-v2v-add-and-use-Create_ovf.ovf_flavour_to_string.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 973810a232b2f2a33425d28287e0ec77c483279a Mon Sep 17 00:00:00 2001 -From: Pino Toscano -Date: Tue, 29 May 2018 07:04:50 +0200 -Subject: [PATCH] v2v: add and use Create_ovf.ovf_flavour_to_string - -Add an helper to convert an OVF flavour to string, and use it in --o vdsm to print the actual value of the vdsm-ovf-flavour option. - -Thanks to Ming Xie. - -(cherry picked from commit c0da02f90d9b52413c24dd9dae61662ad033cc16) ---- - v2v/create_ovf.ml | 4 ++++ - v2v/create_ovf.mli | 3 +++ - v2v/output_vdsm.ml | 5 +++-- - 3 files changed, 10 insertions(+), 2 deletions(-) - -diff --git a/v2v/create_ovf.ml b/v2v/create_ovf.ml -index b3beb1eba..9e0c772fd 100644 ---- a/v2v/create_ovf.ml -+++ b/v2v/create_ovf.ml -@@ -40,6 +40,10 @@ let ovf_flavour_of_string = function - | "rhvexp" -> RHVExportStorageDomain - | flav -> invalid_arg flav - -+let ovf_flavour_to_string = function -+ | OVirt -> "ovirt" -+ | RHVExportStorageDomain -> "rhvexp" -+ - (* 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 2d80660e3..8200b76f9 100644 ---- a/v2v/create_ovf.mli -+++ b/v2v/create_ovf.mli -@@ -29,6 +29,9 @@ val ovf_flavours : string list - valid flavour. *) - val ovf_flavour_of_string : string -> ovf_flavour - -+(** Convert an OVF flavour to its string representation. *) -+val ovf_flavour_to_string : ovf_flavour -> string -+ - (** 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 92b3fd122..9a1b748bc 100644 ---- a/v2v/output_vdsm.ml -+++ b/v2v/output_vdsm.ml -@@ -118,9 +118,10 @@ object - | "0.10" -> "" (* currently this is the default, so don't print it *) - | s -> sprintf " -oo vdsm-compat=%s" s) - (match vdsm_options.ovf_flavour with -- | Create_ovf.OVirt -> "-oo vdsm-ovf-flavour=ovf" - (* currently this is the default, so don't print it *) -- | Create_ovf.RHVExportStorageDomain -> "") -+ | Create_ovf.RHVExportStorageDomain -> "" -+ | flav -> sprintf "-oo vdsm-ovf-flavour=%s" -+ (Create_ovf.ovf_flavour_to_string flav)) - - method supported_firmware = [ TargetBIOS ] - --- -2.21.0 - diff --git a/SOURCES/0020-v2v-Set-DISKTYPE-2-in-RHV-and-VDSM-meta-files-RHBZ-1.patch b/SOURCES/0020-v2v-Set-DISKTYPE-2-in-RHV-and-VDSM-meta-files-RHBZ-1.patch new file mode 100644 index 0000000..7f81ba9 --- /dev/null +++ b/SOURCES/0020-v2v-Set-DISKTYPE-2-in-RHV-and-VDSM-meta-files-RHBZ-1.patch @@ -0,0 +1,46 @@ +From 2eeada3ec57760f57d5da473f32b359c6b55c616 Mon Sep 17 00:00:00 2001 +From: Nir Soffer +Date: Mon, 2 Sep 2019 17:45:13 +0100 +Subject: [PATCH] v2v: Set DISKTYPE=2 in RHV and VDSM meta files + (RHBZ#1746699). + +Added in virt-p2v commit: + + commit e83b6f50af34ce650063ecc520bfabab400e8e73 + Author: Matthew Booth + Date: Fri Mar 26 09:40:20 2010 +0000 + + Add export to RHEV + + Allow guests to be written to a RHEV NFS export storage domain. + + Add 'rhev' output method and -osd command-line option. + Example command line: + + virt-v2v -f virt-v2v.conf -ic 'esx://yellow.rhev.marston/' \ + -o rhev -osd blue:/export/export RHEL3-32 + + This will connect to an ESX server and write the guest 'RHEL3-32' to + blue:/export/export, which is a pre-initialised RHEV export storage domain. + +(cherry picked from commit fcfdbc9420b07e3003df38481afb9ccd22045e1a) +--- + v2v/create_ovf.ml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/v2v/create_ovf.ml b/v2v/create_ovf.ml +index 91ff5198d..9aad5dd15 100644 +--- a/v2v/create_ovf.ml ++++ b/v2v/create_ovf.ml +@@ -501,7 +501,7 @@ let create_meta_files output_alloc sd_uuid image_uuids overlays = + bpf "CTIME=%.0f\n" time; + bpf "MTIME=%.0f\n" time; + bpf "IMAGE=%s\n" image_uuid; +- bpf "DISKTYPE=1\n"; ++ bpf "DISKTYPE=2\n"; + bpf "PUUID=00000000-0000-0000-0000-000000000000\n"; + bpf "LEGALITY=LEGAL\n"; + bpf "POOL_UUID=\n"; +-- +2.25.4 + diff --git a/SOURCES/0020-v2v-o-rhv-upload-Set-inactivity-timeout-RHBZ-1586198.patch b/SOURCES/0020-v2v-o-rhv-upload-Set-inactivity-timeout-RHBZ-1586198.patch deleted file mode 100644 index 1ff5740..0000000 --- a/SOURCES/0020-v2v-o-rhv-upload-Set-inactivity-timeout-RHBZ-1586198.patch +++ /dev/null @@ -1,42 +0,0 @@ -From e61cbd740b84eb78a1ffc52223e4f1cc3202c978 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Tue, 5 Jun 2018 19:09:43 +0100 -Subject: [PATCH] v2v: -o rhv-upload: Set inactivity timeout (RHBZ#1586198). -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This increases the inactivity timeout for transfers from the default -(60 seconds in oVirt < 4.2.3, 600 seconds in >= 4.2.3), up to 1 hour, -so that we should never hit it for ordinary transfers. - -Note this requires oVirt >= 4.2.3. The corresponding oVirt fix was -https://bugzilla.redhat.com/1563278 - -I also replaced the deprecated ‘image’ parameter with ‘disk’. - -Thanks: Nir Soffer, Daniel Erez. -(cherry picked from commit f25404c65f8e078a3ca5bd5a1ab91343edd22506) ---- - v2v/rhv-upload-plugin.py | 5 ++--- - 1 file changed, 2 insertions(+), 3 deletions(-) - -diff --git a/v2v/rhv-upload-plugin.py b/v2v/rhv-upload-plugin.py -index 791c9e7d2..b4557b83c 100644 ---- a/v2v/rhv-upload-plugin.py -+++ b/v2v/rhv-upload-plugin.py -@@ -123,9 +123,8 @@ def open(readonly): - # Create a new image transfer. - transfer = transfers_service.add( - types.ImageTransfer( -- image = types.Image( -- id = disk.id -- ) -+ disk = types.Disk(id = disk.id), -+ inactivity_timeout = 3600, - ) - ) - debug("transfer.id = %r" % transfer.id) --- -2.21.0 - diff --git a/SOURCES/0021-New-API-inspect_get_osinfo.patch b/SOURCES/0021-New-API-inspect_get_osinfo.patch deleted file mode 100644 index ba61da3..0000000 --- a/SOURCES/0021-New-API-inspect_get_osinfo.patch +++ /dev/null @@ -1,136 +0,0 @@ -From 24aef5baa9725e26efd37fa78b83f98629d77eba Mon Sep 17 00:00:00 2001 -From: Pino Toscano -Date: Wed, 21 Feb 2018 17:33:28 +0100 -Subject: [PATCH] New API: inspect_get_osinfo - -Try to guess the possible osinfo-db short ID for the specified OS. - -Related to: https://bugzilla.redhat.com/show_bug.cgi?id=1544842 - -(cherry picked from commit 286b88891c2288fb7f64c9538296599ece04bcb1) ---- - generator/actions_inspection.ml | 14 ++++++ - lib/Makefile.am | 1 + - lib/inspect-osinfo.c | 75 +++++++++++++++++++++++++++++++++ - 3 files changed, 90 insertions(+) - create mode 100644 lib/inspect-osinfo.c - -diff --git a/generator/actions_inspection.ml b/generator/actions_inspection.ml -index 0ac282435..ff5083114 100644 ---- a/generator/actions_inspection.ml -+++ b/generator/actions_inspection.ml -@@ -770,4 +770,18 @@ advice before using trademarks in applications. - - =back" }; - -+ { defaults with -+ name = "inspect_get_osinfo"; added = (1, 39, 1); -+ style = RString (RPlainString, "id"), [String (Mountable, "root")], []; -+ shortdesc = "get a possible osinfo short ID corresponding to this operating system"; -+ longdesc = "\ -+This function returns a possible short ID for libosinfo corresponding -+to the guest. -+ -+I The returned ID is only a guess by libguestfs, and nothing -+ensures that it actually exists in osinfo-db. -+ -+If no ID could not be determined, then the string C is -+returned." }; -+ - ] -diff --git a/lib/Makefile.am b/lib/Makefile.am -index d075174d9..742b182cc 100644 ---- a/lib/Makefile.am -+++ b/lib/Makefile.am -@@ -95,6 +95,7 @@ libguestfs_la_SOURCES = \ - info.c \ - inspect-apps.c \ - inspect-icon.c \ -+ inspect-osinfo.c \ - journal.c \ - launch.c \ - launch-direct.c \ -diff --git a/lib/inspect-osinfo.c b/lib/inspect-osinfo.c -new file mode 100644 -index 000000000..816d317f1 ---- /dev/null -+++ b/lib/inspect-osinfo.c -@@ -0,0 +1,75 @@ -+/* libguestfs -+ * Copyright (C) 2018 Red Hat Inc. -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -+ */ -+ -+#include -+ -+#include "guestfs.h" -+#include "guestfs-internal.h" -+#include "guestfs-internal-actions.h" -+ -+char * -+guestfs_impl_inspect_get_osinfo (guestfs_h *g, const char *root) -+{ -+ CLEANUP_FREE char *type = NULL; -+ CLEANUP_FREE char *distro = NULL; -+ int major, minor; -+ -+ type = guestfs_inspect_get_type (g, root); -+ if (!type) -+ return NULL; -+ distro = guestfs_inspect_get_distro (g, root); -+ if (!distro) -+ return NULL; -+ major = guestfs_inspect_get_major_version (g, root); -+ minor = guestfs_inspect_get_minor_version (g, root); -+ -+ if (STREQ (type, "linux")) { -+ if (STREQ (distro, "centos")) { -+ if (major >= 7) -+ return safe_asprintf (g, "%s%d.0", distro, major); -+ else if (major == 6) -+ return safe_asprintf (g, "%s%d.%d", distro, major, minor); -+ } -+ else if (STREQ (distro, "debian")) { -+ if (major >= 4) -+ return safe_asprintf (g, "%s%d", distro, major); -+ } -+ else if (STREQ (distro, "fedora") || STREQ (distro, "mageia")) -+ return safe_asprintf (g, "%s%d", distro, major); -+ else if (STREQ (distro, "sles")) { -+ if (minor == 0) -+ return safe_asprintf (g, "%s%d", distro, major); -+ else -+ return safe_asprintf (g, "%s%dsp%d", distro, major, minor); -+ } -+ else if (STREQ (distro, "ubuntu")) -+ return safe_asprintf (g, "%s%d.%02d", distro, major, minor); -+ -+ if (major > 0 || minor > 0) -+ return safe_asprintf (g, "%s%d.%d", distro, major, minor); -+ } -+ else if (STREQ (type, "freebsd") || STREQ (type, "netbsd") || STREQ (type, "openbsd")) -+ return safe_asprintf (g, "%s%d.%d", distro, major, minor); -+ else if (STREQ (type, "dos")) { -+ if (STREQ (distro, "msdos")) -+ return safe_strdup (g, "msdos6.22"); -+ } -+ -+ /* No ID could be guessed, return "unknown". */ -+ return safe_strdup (g, "unknown"); -+} --- -2.21.0 - diff --git a/SOURCES/0021-v2v-rhv-upload-plugin-improve-wait-logic-after-final.patch b/SOURCES/0021-v2v-rhv-upload-plugin-improve-wait-logic-after-final.patch new file mode 100644 index 0000000..6f063b4 --- /dev/null +++ b/SOURCES/0021-v2v-rhv-upload-plugin-improve-wait-logic-after-final.patch @@ -0,0 +1,55 @@ +From 41f3e803050b46fd79d8c2e728fc0425da05878c Mon Sep 17 00:00:00 2001 +From: Daniel Erez +Date: Mon, 18 Mar 2019 18:51:26 +0200 +Subject: [PATCH] v2v: rhv-upload-plugin - improve wait logic after finalize + (RHBZ#1680361) + +After invoking transfer_service.finalize, check operation status by +examining DiskStatus. This is done instead of failing after a +predefined timeout regardless the status. + +Bug-Url: https://bugzilla.redhat.com/show_bug.cgi?id=1680361 +Signed-off-by: Richard W.M. Jones +Tested-by: Ilanit Stein +(cherry picked from commit eeabb3fdc7756887b53106f455a7b54309130637) +--- + v2v/rhv-upload-plugin.py | 19 +++++++++++++------ + 1 file changed, 13 insertions(+), 6 deletions(-) + +diff --git a/v2v/rhv-upload-plugin.py b/v2v/rhv-upload-plugin.py +index 2a950c5ed..4d61a089b 100644 +--- a/v2v/rhv-upload-plugin.py ++++ b/v2v/rhv-upload-plugin.py +@@ -523,16 +523,23 @@ def close(h): + # waiting for the transfer object to cease to exist, which + # falls through to the exception case and then we can + # continue. +- endt = time.time() + timeout ++ disk_id = disk.id ++ start = time.time() + try: + while True: + time.sleep(1) +- tmp = transfer_service.get() +- if time.time() > endt: +- raise RuntimeError("timed out waiting for transfer " +- "to finalize") ++ disk_service = h['disk_service'] ++ disk = disk_service.get() ++ if disk.status == types.DiskStatus.LOCKED: ++ if time.time() > start + timeout: ++ raise RuntimeError("timed out waiting for transfer " ++ "to finalize") ++ continue ++ if disk.status == types.DiskStatus.OK: ++ debug("finalized after %s seconds" % (time.time() - start)) ++ break + except sdk.NotFoundError: +- pass ++ raise RuntimeError("transfer failed: disk %s not found" % disk_id) + + # Write the disk ID file. Only do this on successful completion. + with builtins.open(params['diskid_file'], 'w') as fp: +-- +2.25.4 + diff --git a/SOURCES/0022-inspector-show-the-per-OS-osinfo-guess-RHBZ-1544842.patch b/SOURCES/0022-inspector-show-the-per-OS-osinfo-guess-RHBZ-1544842.patch deleted file mode 100644 index dfbf66d..0000000 --- a/SOURCES/0022-inspector-show-the-per-OS-osinfo-guess-RHBZ-1544842.patch +++ /dev/null @@ -1,99 +0,0 @@ -From ee00f39eea1c97c5fcb9948b30586c9c106356d7 Mon Sep 17 00:00:00 2001 -From: Pino Toscano -Date: Wed, 21 Feb 2018 17:37:30 +0100 -Subject: [PATCH] inspector: show the per-OS osinfo guess (RHBZ#1544842) - -Output also the osinfo guess for each OS in the generated XML output; -adapt the RNG schema, and the test data to it. - -(cherry picked from commit 2f8ec91fc1f3e81c8fb81d45849bc7462ee13642) ---- - inspector/expected-coreos.img.xml | 1 + - inspector/expected-debian.img.xml | 1 + - inspector/expected-fedora.img.xml | 1 + - inspector/expected-ubuntu.img.xml | 1 + - inspector/inspector.c | 7 +++++++ - inspector/virt-inspector.rng | 1 + - 6 files changed, 12 insertions(+) - -diff --git a/inspector/expected-coreos.img.xml b/inspector/expected-coreos.img.xml -index e4a5d1134..0cdfba6e6 100644 ---- a/inspector/expected-coreos.img.xml -+++ b/inspector/expected-coreos.img.xml -@@ -8,6 +8,7 @@ - 899 - 13 - coreos.invalid -+ coreos899.13 - - / - /usr -diff --git a/inspector/expected-debian.img.xml b/inspector/expected-debian.img.xml -index 37ecfa049..6583dc262 100644 ---- a/inspector/expected-debian.img.xml -+++ b/inspector/expected-debian.img.xml -@@ -11,6 +11,7 @@ - deb - apt - debian.invalid -+ debian5 - - / - /usr -diff --git a/inspector/expected-fedora.img.xml b/inspector/expected-fedora.img.xml -index 8d40e8cb7..df6060a73 100644 ---- a/inspector/expected-fedora.img.xml -+++ b/inspector/expected-fedora.img.xml -@@ -11,6 +11,7 @@ - rpm - yum - fedora.invalid -+ fedora14 - - / - /boot -diff --git a/inspector/expected-ubuntu.img.xml b/inspector/expected-ubuntu.img.xml -index c19c14cd5..4ebcd76d6 100644 ---- a/inspector/expected-ubuntu.img.xml -+++ b/inspector/expected-ubuntu.img.xml -@@ -11,6 +11,7 @@ - deb - apt - ubuntu.invalid -+ ubuntu10.10 - - / - /boot -diff --git a/inspector/inspector.c b/inspector/inspector.c -index d608b1b63..5075a8f04 100644 ---- a/inspector/inspector.c -+++ b/inspector/inspector.c -@@ -443,6 +443,13 @@ output_root (xmlTextWriterPtr xo, char *root) - BAD_CAST str)); - free (str); - -+ str = guestfs_inspect_get_osinfo (g, root); -+ if (!str) exit (EXIT_FAILURE); -+ if (STRNEQ (str, "unknown")) -+ XMLERROR (-1, -+ xmlTextWriterWriteElement (xo, BAD_CAST "osinfo", BAD_CAST str)); -+ free (str); -+ - output_mountpoints (xo, root); - - output_filesystems (xo, root); -diff --git a/inspector/virt-inspector.rng b/inspector/virt-inspector.rng -index 314785202..1e3a58af8 100644 ---- a/inspector/virt-inspector.rng -+++ b/inspector/virt-inspector.rng -@@ -38,6 +38,7 @@ - - - -+ - - - --- -2.21.0 - diff --git a/SOURCES/0022-v2v-o-rhv-upload-check-whether-the-cluster-exists.patch b/SOURCES/0022-v2v-o-rhv-upload-check-whether-the-cluster-exists.patch new file mode 100644 index 0000000..b01b226 --- /dev/null +++ b/SOURCES/0022-v2v-o-rhv-upload-check-whether-the-cluster-exists.patch @@ -0,0 +1,61 @@ +From b37ca67f769749b7b3b5d51e171b7cccfa3b5fd2 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Mon, 15 Apr 2019 17:24:42 +0200 +Subject: [PATCH] v2v: -o rhv-upload: check whether the cluster exists + +In the precheck script, check that the target cluster actually exists. +This will avoid errors when creating the VM after the data copying. + +(cherry picked from commit 05e559549dab75f17e147f4a4eafbac868a7aa5d) +--- + v2v/rhv-upload-precheck.py | 10 ++++++++++ + v2v/test-v2v-o-rhv-upload-module/ovirtsdk4/__init__.py | 7 +++++++ + 2 files changed, 17 insertions(+) + +diff --git a/v2v/rhv-upload-precheck.py b/v2v/rhv-upload-precheck.py +index 2798a29dd..b79f91b4a 100644 +--- a/v2v/rhv-upload-precheck.py ++++ b/v2v/rhv-upload-precheck.py +@@ -70,4 +70,14 @@ if len(vms) > 0: + raise RuntimeError("VM already exists with name ‘%s’, id ‘%s’" % + (params['output_name'], vm.id)) + ++# Check whether the specified cluster exists. ++clusters_service = system_service.clusters_service() ++clusters = clusters_service.list( ++ search='name=%s' % params['rhv_cluster'], ++ case_sensitive=True, ++) ++if len(clusters) == 0: ++ raise RuntimeError("The cluster ‘%s’ does not exist" % ++ (params['rhv_cluster'])) ++ + # Otherwise everything is OK, exit with no error. +diff --git a/v2v/test-v2v-o-rhv-upload-module/ovirtsdk4/__init__.py b/v2v/test-v2v-o-rhv-upload-module/ovirtsdk4/__init__.py +index 8d1058d67..cc4224ccd 100644 +--- a/v2v/test-v2v-o-rhv-upload-module/ovirtsdk4/__init__.py ++++ b/v2v/test-v2v-o-rhv-upload-module/ovirtsdk4/__init__.py +@@ -39,6 +39,9 @@ class Connection(object): + return SystemService() + + class SystemService(object): ++ def clusters_service(self): ++ return ClustersService() ++ + def data_centers_service(self): + return DataCentersService() + +@@ -54,6 +57,10 @@ class SystemService(object): + def vms_service(self): + return VmsService() + ++class ClustersService(object): ++ def list(self, search=None, case_sensitive=False): ++ return ["Default"] ++ + class DataCentersService(object): + def list(self, search=None, case_sensitive=False): + return [] +-- +2.25.4 + diff --git a/SOURCES/0023-v2v-o-rhv-upload-Optimize-http-request-sending.patch b/SOURCES/0023-v2v-o-rhv-upload-Optimize-http-request-sending.patch deleted file mode 100644 index e30f494..0000000 --- a/SOURCES/0023-v2v-o-rhv-upload-Optimize-http-request-sending.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 5917bdc15f3b2e0c96ba5a9860cd36f968a28ec2 Mon Sep 17 00:00:00 2001 -From: Nir Soffer -Date: Thu, 14 Jun 2018 21:16:01 +0300 -Subject: [PATCH] v2v: -o rhv-upload: Optimize http request sending - -When sending request with small or no payload, it is simpler and -possibly more efficient to use the high level HTTPSConnection.request(), -instead of the lower level APIs. - -The only reason to use the lower level APIs is to avoid copying the -payload, or on python 2, to use a bigger buffer size when streaming a -file-like object. - -(cherry picked from commit 77a412c0a1cd0e303a072fc5088c8f3bfed36583) ---- - v2v/rhv-upload-plugin.py | 35 ++++++++++++++++------------------- - 1 file changed, 16 insertions(+), 19 deletions(-) - -diff --git a/v2v/rhv-upload-plugin.py b/v2v/rhv-upload-plugin.py -index b4557b83c..9ad354b84 100644 ---- a/v2v/rhv-upload-plugin.py -+++ b/v2v/rhv-upload-plugin.py -@@ -237,12 +237,12 @@ def pread(h, count, offset): - transfer = h['transfer'] - transfer_service = h['transfer_service'] - -- http.putrequest("GET", h['path']) -+ headers = {"Range", "bytes=%d-%d" % (offset, offset+count-1)} - # Authorization is only needed for old imageio. - if h['needs_auth']: -- http.putheader("Authorization", transfer.signed_ticket) -- http.putheader("Range", "bytes=%d-%d" % (offset, offset+count-1)) -- http.endheaders() -+ headers["Authorization"] = transfer.signed_ticket -+ -+ http.request("GET", h['path'], headers=headers) - - r = http.getresponse() - # 206 = HTTP Partial Content. -@@ -297,11 +297,10 @@ def zero(h, count, offset, may_trim): - 'size': count, - 'flush': False}).encode() - -- http.putrequest("PATCH", h['path']) -- http.putheader("Content-Type", "application/json") -- http.putheader("Content-Length", len(buf)) -- http.endheaders() -- http.send(buf) -+ headers = {"Content-Type": "application/json", -+ "Content-Length": str(len(buf))} -+ -+ http.request("PATCH", h['path'], body=buf, headers=headers) - - r = http.getresponse() - if r.status != 200: -@@ -349,11 +348,10 @@ def trim(h, count, offset): - 'size': count, - 'flush': False}).encode() - -- http.putrequest("PATCH", h['path']) -- http.putheader("Content-Type", "application/json") -- http.putheader("Content-Length", len(buf)) -- http.endheaders() -- http.send(buf) -+ headers = {"Content-Type": "application/json", -+ "Content-Length": str(len(buf))} -+ -+ http.request("PATCH", h['path'], body=buf, headers=headers) - - r = http.getresponse() - if r.status != 200: -@@ -370,11 +368,10 @@ def flush(h): - # Construct the JSON request for flushing. - buf = json.dumps({'op': "flush"}).encode() - -- http.putrequest("PATCH", h['path']) -- http.putheader("Content-Type", "application/json") -- http.putheader("Content-Length", len(buf)) -- http.endheaders() -- http.send(buf) -+ headers = {"Content-Type": "application/json", -+ "Content-Length": str(len(buf))} -+ -+ http.request("PATCH", h['path'], body=buf, headers=headers) - - r = http.getresponse() - if r.status != 200: --- -2.21.0 - diff --git a/SOURCES/0023-v2v-o-rhv-upload-split-vmcheck-out-of-precheck.patch b/SOURCES/0023-v2v-o-rhv-upload-split-vmcheck-out-of-precheck.patch new file mode 100644 index 0000000..0f2c916 --- /dev/null +++ b/SOURCES/0023-v2v-o-rhv-upload-split-vmcheck-out-of-precheck.patch @@ -0,0 +1,264 @@ +From ae560843517da393492418bb61c3dee43e64af2c Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Thu, 12 Sep 2019 13:19:48 +0200 +Subject: [PATCH] v2v: -o rhv-upload: split vmcheck out of precheck + +Split the VM existance check out of the precheck script to a new vmcheck +script, and invoke that in #prepare_targets. Invoke the precheck script +in #precheck, as now it can be run with only values of command line +options. + +This does not change which checks are performed; however, an invalid +cluster name will make virt-v2v fail way earlier (even before connecting +to the source). + +(cherry picked from commit 6499fdc199790619745eee28fcae3421c32c4735) +--- + v2v/Makefile.am | 8 ++- + v2v/output_rhv_upload.ml | 14 +++-- + v2v/output_rhv_upload_precheck_source.mli | 2 +- + v2v/output_rhv_upload_vmcheck_source.mli | 19 ++++++ + v2v/rhv-upload-precheck.py | 12 +--- + v2v/rhv-upload-vmcheck.py | 73 +++++++++++++++++++++++ + 6 files changed, 111 insertions(+), 17 deletions(-) + create mode 100644 v2v/output_rhv_upload_vmcheck_source.mli + create mode 100644 v2v/rhv-upload-vmcheck.py + +diff --git a/v2v/Makefile.am b/v2v/Makefile.am +index 53c137fc6..30f040d3e 100644 +--- a/v2v/Makefile.am ++++ b/v2v/Makefile.am +@@ -26,7 +26,8 @@ BUILT_SOURCES = \ + config.ml \ + output_rhv_upload_createvm_source.ml \ + output_rhv_upload_plugin_source.ml \ +- output_rhv_upload_precheck_source.ml ++ output_rhv_upload_precheck_source.ml \ ++ output_rhv_upload_vmcheck_source.ml + + EXTRA_DIST = \ + $(SOURCES_MLI) $(SOURCES_ML) $(SOURCES_C) \ +@@ -36,6 +37,7 @@ EXTRA_DIST = \ + rhv-upload-createvm.py \ + rhv-upload-plugin.py \ + rhv-upload-precheck.py \ ++ rhv-upload-vmcheck.py \ + v2v_unit_tests.ml \ + virt-v2v.pod \ + virt-v2v-copy-to-local.pod \ +@@ -87,6 +89,7 @@ SOURCES_MLI = \ + output_rhv_upload_createvm_source.mli \ + output_rhv_upload_plugin_source.mli \ + output_rhv_upload_precheck_source.mli \ ++ output_rhv_upload_vmcheck_source.mli \ + output_vdsm.mli \ + parse_ova.mli \ + parse_ovf_from_ova.mli \ +@@ -152,6 +155,7 @@ SOURCES_ML = \ + output_rhv_upload_createvm_source.ml \ + output_rhv_upload_plugin_source.ml \ + output_rhv_upload_precheck_source.ml \ ++ output_rhv_upload_vmcheck_source.ml \ + output_rhv_upload.ml \ + output_vdsm.ml \ + output_openstack.ml \ +@@ -173,6 +177,8 @@ output_rhv_upload_plugin_source.ml: $(srcdir)/rhv-upload-plugin.py + $(srcdir)/embed.sh code $^ $@ + output_rhv_upload_precheck_source.ml: $(srcdir)/rhv-upload-precheck.py + $(srcdir)/embed.sh code $^ $@ ++output_rhv_upload_vmcheck_source.ml: $(srcdir)/rhv-upload-vmcheck.py ++ $(srcdir)/embed.sh code $^ $@ + + if HAVE_OCAML + +diff --git a/v2v/output_rhv_upload.ml b/v2v/output_rhv_upload.ml +index c2a5c72c7..adcbdf25f 100644 +--- a/v2v/output_rhv_upload.ml ++++ b/v2v/output_rhv_upload.ml +@@ -94,10 +94,13 @@ class output_rhv_upload output_alloc output_conn + + let diskid_file_of_id id = tmpdir // sprintf "diskid.%d" id in + +- (* Create Python scripts for precheck, plugin and create VM. *) ++ (* Create Python scripts for precheck, vmcheck, plugin and create VM. *) + let precheck_script = + Python_script.create ~name:"rhv-upload-precheck.py" + Output_rhv_upload_precheck_source.code in ++ let vmcheck_script = ++ Python_script.create ~name:"rhv-upload-vmcheck.py" ++ Output_rhv_upload_vmcheck_source.code in + let plugin_script = + Python_script.create ~name:"rhv-upload-plugin.py" + Output_rhv_upload_plugin_source.code in +@@ -230,6 +233,9 @@ object + error_unless_nbdkit_working (); + error_unless_nbdkit_python_plugin_working (); + error_unless_output_alloc_sparse (); ++ (* Python code prechecks. *) ++ if Python_script.run_command precheck_script json_params [] <> 0 then ++ error (f_"failed server prechecks, see earlier errors"); + if have_selinux then + error_unless_nbdkit_compiled_with_selinux () + +@@ -251,11 +257,11 @@ object + let json_params = + ("output_name", JSON.String output_name) :: json_params in + +- (* Python code prechecks. These can't run in #precheck because ++ (* Check that the VM does not exist. This can't run in #precheck because + * we need to know the name of the virtual machine. + *) +- if Python_script.run_command precheck_script json_params [] <> 0 then +- error (f_"failed server prechecks, see earlier errors"); ++ if Python_script.run_command vmcheck_script json_params [] <> 0 then ++ error (f_"failed vmchecks, see earlier errors"); + + (* Create an nbdkit instance for each disk and set the + * target URI to point to the NBD socket. +diff --git a/v2v/output_rhv_upload_precheck_source.mli b/v2v/output_rhv_upload_precheck_source.mli +index c1bafa15b..aa33bc548 100644 +--- a/v2v/output_rhv_upload_precheck_source.mli ++++ b/v2v/output_rhv_upload_precheck_source.mli +@@ -1,5 +1,5 @@ + (* virt-v2v +- * Copyright (C) 2018 Red Hat Inc. ++ * Copyright (C) 2019 Red Hat Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by +diff --git a/v2v/output_rhv_upload_vmcheck_source.mli b/v2v/output_rhv_upload_vmcheck_source.mli +new file mode 100644 +index 000000000..c1bafa15b +--- /dev/null ++++ b/v2v/output_rhv_upload_vmcheck_source.mli +@@ -0,0 +1,19 @@ ++(* virt-v2v ++ * Copyright (C) 2018 Red Hat Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ *) ++ ++val code : string +diff --git a/v2v/rhv-upload-precheck.py b/v2v/rhv-upload-precheck.py +index b79f91b4a..d6a58f0fc 100644 +--- a/v2v/rhv-upload-precheck.py ++++ b/v2v/rhv-upload-precheck.py +@@ -1,6 +1,6 @@ + # -*- python -*- + # oVirt or RHV pre-upload checks used by ‘virt-v2v -o rhv-upload’ +-# Copyright (C) 2018 Red Hat Inc. ++# Copyright (C) 2018-2019 Red Hat Inc. + # + # This program is free software; you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by +@@ -60,16 +60,6 @@ connection = sdk.Connection( + + system_service = connection.system_service() + +-# Find if a virtual machine already exists with that name. +-vms_service = system_service.vms_service() +-vms = vms_service.list( +- search = ("name=%s" % params['output_name']), +-) +-if len(vms) > 0: +- vm = vms[0] +- raise RuntimeError("VM already exists with name ‘%s’, id ‘%s’" % +- (params['output_name'], vm.id)) +- + # Check whether the specified cluster exists. + clusters_service = system_service.clusters_service() + clusters = clusters_service.list( +diff --git a/v2v/rhv-upload-vmcheck.py b/v2v/rhv-upload-vmcheck.py +new file mode 100644 +index 000000000..fbb884b94 +--- /dev/null ++++ b/v2v/rhv-upload-vmcheck.py +@@ -0,0 +1,73 @@ ++# -*- python -*- ++# oVirt or RHV VM existance check used by ‘virt-v2v -o rhv-upload’ ++# Copyright (C) 2018-2019 Red Hat Inc. ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License along ++# with this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++import json ++import logging ++import sys ++import time ++ ++from http.client import HTTPSConnection ++from urllib.parse import urlparse ++ ++import ovirtsdk4 as sdk ++import ovirtsdk4.types as types ++ ++# Parameters are passed in via a JSON doc from the OCaml code. ++# Because this Python code ships embedded inside virt-v2v there ++# is no formal API here. ++params = None ++ ++if len(sys.argv) != 2: ++ raise RuntimeError("incorrect number of parameters") ++ ++# Parameters are passed in via a JSON document. ++with open(sys.argv[1], 'r') as fp: ++ params = json.load(fp) ++ ++# What is passed in is a password file, read the actual password. ++with open(params['output_password'], 'r') as fp: ++ output_password = fp.read() ++output_password = output_password.rstrip() ++ ++# Parse out the username from the output_conn URL. ++parsed = urlparse(params['output_conn']) ++username = parsed.username or "admin@internal" ++ ++# Connect to the server. ++connection = sdk.Connection( ++ url = params['output_conn'], ++ username = username, ++ password = output_password, ++ ca_file = params['rhv_cafile'], ++ log = logging.getLogger(), ++ insecure = params['insecure'], ++) ++ ++system_service = connection.system_service() ++ ++# Find if a virtual machine already exists with that name. ++vms_service = system_service.vms_service() ++vms = vms_service.list( ++ search = ("name=%s" % params['output_name']), ++) ++if len(vms) > 0: ++ vm = vms[0] ++ raise RuntimeError("VM already exists with name ‘%s’, id ‘%s’" % ++ (params['output_name'], vm.id)) ++ ++# Otherwise everything is OK, exit with no error. +-- +2.25.4 + diff --git a/SOURCES/0024-v2v-o-rhv-upload-Log-full-imageio-response-on-failur.patch b/SOURCES/0024-v2v-o-rhv-upload-Log-full-imageio-response-on-failur.patch deleted file mode 100644 index 58bbfa4..0000000 --- a/SOURCES/0024-v2v-o-rhv-upload-Log-full-imageio-response-on-failur.patch +++ /dev/null @@ -1,153 +0,0 @@ -From c2ed35e2bc17bcacf333626b21cd6796d4d8d6cf Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Tue, 5 Jun 2018 13:27:43 +0100 -Subject: [PATCH] v2v: -o rhv-upload: Log full imageio response on failure. - -Thanks: Nir Soffer -(cherry picked from commit 831a75cd11c5a87e40fccdadcb62353f6a4d5a72) ---- - v2v/rhv-upload-plugin.py | 69 ++++++++++++++++++++++++---------------- - 1 file changed, 42 insertions(+), 27 deletions(-) - -diff --git a/v2v/rhv-upload-plugin.py b/v2v/rhv-upload-plugin.py -index 9ad354b84..7c5084efd 100644 ---- a/v2v/rhv-upload-plugin.py -+++ b/v2v/rhv-upload-plugin.py -@@ -227,6 +227,32 @@ def can_flush(h): - def get_size(h): - return params['disk_size'] - -+# Any unexpected HTTP response status from the server will end up -+# calling this function which logs the full error, pauses the -+# transfer, sets the failed state, and raises a RuntimeError -+# exception. -+def request_failed(h, r, msg): -+ # Setting the failed flag in the handle causes the disk to be -+ # cleaned up on close. -+ h['failed'] = True -+ h['transfer_service'].pause() -+ -+ status = r.status -+ reason = r.reason -+ try: -+ body = r.read() -+ except EnvironmentError as e: -+ body = "(Unable to read response body: %s)" % e -+ -+ # Log the full error if we're verbose. -+ debug("unexpected response from imageio server:") -+ debug(msg) -+ debug("%d: %s" % (status, reason)) -+ debug(body) -+ -+ # Only a short error is included in the exception. -+ raise RuntimeError("%s: %d %s: %r", msg, status, reason, body[:200]) -+ - # For documentation see: - # https://github.com/oVirt/ovirt-imageio/blob/master/docs/random-io.md - # For examples of working code to read/write from the server, see: -@@ -247,16 +273,14 @@ def pread(h, count, offset): - r = http.getresponse() - # 206 = HTTP Partial Content. - if r.status != 206: -- h['transfer_service'].pause() -- h['failed'] = True -- raise RuntimeError("could not read sector (%d, %d): %d: %s" % -- (offset, count, r.status, r.reason)) -+ request_failed(h, r, -+ "could not read sector offset %d size %d" % -+ (offset, count)) - return r.read() - - def pwrite(h, buf, offset): - http = h['http'] - transfer = h['transfer'] -- transfer_service = h['transfer_service'] - - count = len(buf) - h['highestwrite'] = max(h['highestwrite'], offset+count) -@@ -274,15 +298,13 @@ def pwrite(h, buf, offset): - - r = http.getresponse() - if r.status != 200: -- transfer_service.pause() -- h['failed'] = True -- raise RuntimeError("could not write sector (%d, %d): %d: %s" % -- (offset, count, r.status, r.reason)) -+ request_failed(h, r, -+ "could not write sector offset %d size %d" % -+ (offset, count)) - - def zero(h, count, offset, may_trim): - http = h['http'] - transfer = h['transfer'] -- transfer_service = h['transfer_service'] - - # Unlike the trim and flush calls, there is no 'can_zero' method - # so nbdkit could call this even if the server doesn't support -@@ -304,10 +326,9 @@ def zero(h, count, offset, may_trim): - - r = http.getresponse() - if r.status != 200: -- transfer_service.pause() -- h['failed'] = True -- raise RuntimeError("could not zero sector (%d, %d): %d: %s" % -- (offset, count, r.status, r.reason)) -+ request_failed(h, r, -+ "could not zero sector offset %d size %d" % -+ (offset, count)) - - def emulate_zero(h, count, offset): - # qemu-img convert starts by trying to zero/trim the whole device. -@@ -332,15 +353,13 @@ def emulate_zero(h, count, offset): - - r = http.getresponse() - if r.status != 200: -- transfer_service.pause() -- h['failed'] = True -- raise RuntimeError("could not write zeroes (%d, %d): %d: %s" % -- (offset, count, r.status, r.reason)) -+ request_failed(h, r, -+ "could not write zeroes offset %d size %d" % -+ (offset, count)) - - def trim(h, count, offset): - http = h['http'] - transfer = h['transfer'] -- transfer_service = h['transfer_service'] - - # Construct the JSON request for trimming. - buf = json.dumps({'op': "trim", -@@ -355,15 +374,13 @@ def trim(h, count, offset): - - r = http.getresponse() - if r.status != 200: -- transfer_service.pause() -- h['failed'] = True -- raise RuntimeError("could not trim sector (%d, %d): %d: %s" % -- (offset, count, r.status, r.reason)) -+ request_failed(h, r, -+ "could not trim sector offset %d size %d" % -+ (offset, count)) - - def flush(h): - http = h['http'] - transfer = h['transfer'] -- transfer_service = h['transfer_service'] - - # Construct the JSON request for flushing. - buf = json.dumps({'op': "flush"}).encode() -@@ -375,9 +392,7 @@ def flush(h): - - r = http.getresponse() - if r.status != 200: -- transfer_service.pause() -- h['failed'] = True -- raise RuntimeError("could not flush: %d: %s" % (r.status, r.reason)) -+ request_failed(h, r, "could not flush") - - def delete_disk_on_failure(h): - disk_service = h['disk_service'] --- -2.21.0 - diff --git a/SOURCES/0024-v2v-o-rhv-upload-change-precheck-script-to-return-a-.patch b/SOURCES/0024-v2v-o-rhv-upload-change-precheck-script-to-return-a-.patch new file mode 100644 index 0000000..60862e1 --- /dev/null +++ b/SOURCES/0024-v2v-o-rhv-upload-change-precheck-script-to-return-a-.patch @@ -0,0 +1,53 @@ +From f0f00c5f0ea1a726dd2c8501bcc269211f30e2a8 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Thu, 12 Sep 2019 14:17:36 +0200 +Subject: [PATCH] v2v: -o rhv-upload: change precheck script to return a JSON + +This way it is possible to communicate data from the precheck script +back to virt-v2v. + +For now there are no results, so the resulting JSON is discarded. + +(cherry picked from commit cc6e2a7f9ea53258c2edb758e3ec9beb7baa1fc6) +--- + v2v/output_rhv_upload.ml | 8 +++++++- + v2v/rhv-upload-precheck.py | 6 +++++- + 2 files changed, 12 insertions(+), 2 deletions(-) + +diff --git a/v2v/output_rhv_upload.ml b/v2v/output_rhv_upload.ml +index adcbdf25f..fd6f2e3e6 100644 +--- a/v2v/output_rhv_upload.ml ++++ b/v2v/output_rhv_upload.ml +@@ -234,8 +234,14 @@ object + error_unless_nbdkit_python_plugin_working (); + error_unless_output_alloc_sparse (); + (* Python code prechecks. *) +- if Python_script.run_command precheck_script json_params [] <> 0 then ++ let precheck_fn = tmpdir // "v2vprecheck.json" in ++ let fd = Unix.openfile precheck_fn [O_WRONLY; O_CREAT] 0o600 in ++ if Python_script.run_command ~stdout_fd:fd ++ precheck_script json_params [] <> 0 then + error (f_"failed server prechecks, see earlier errors"); ++ let json = JSON_parser.json_parser_tree_parse_file precheck_fn in ++ debug "precheck output parsed as: %s" ++ (JSON.string_of_doc ~fmt:JSON.Indented ["", json]); + if have_selinux then + error_unless_nbdkit_compiled_with_selinux () + +diff --git a/v2v/rhv-upload-precheck.py b/v2v/rhv-upload-precheck.py +index d6a58f0fc..de8a66c05 100644 +--- a/v2v/rhv-upload-precheck.py ++++ b/v2v/rhv-upload-precheck.py +@@ -70,4 +70,8 @@ if len(clusters) == 0: + raise RuntimeError("The cluster ‘%s’ does not exist" % + (params['rhv_cluster'])) + +-# Otherwise everything is OK, exit with no error. ++# Otherwise everything is OK, print a JSON with the results. ++results = { ++} ++ ++json.dump(results, sys.stdout) +-- +2.25.4 + diff --git a/SOURCES/0025-v2v-o-rhv-upload-improve-lookup-of-specified-resourc.patch b/SOURCES/0025-v2v-o-rhv-upload-improve-lookup-of-specified-resourc.patch new file mode 100644 index 0000000..0560c10 --- /dev/null +++ b/SOURCES/0025-v2v-o-rhv-upload-improve-lookup-of-specified-resourc.patch @@ -0,0 +1,169 @@ +From ccd327919ca1fed3e10fdd3567ede0dc8cd5d0c3 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Thu, 12 Sep 2019 15:21:26 +0200 +Subject: [PATCH] v2v: -o rhv-upload: improve lookup of specified resources + (RHBZ#1612653) + +Improve the way the precheck script checks for the specified resources: +- look directly for a data center with the specified storage domain +- get the storage domain object from the storage domains attached to the + data center found +- similarly, look for the specified cluster among the ones attached to + the data center found +When everything is found, return the UUID of the storage domain, and of +the cluster back to virt-v2v, which will store them. + +Similarly, rework the createvm script to directly get the requested +cluster, instead of looking for it once again. Also, since the UUID of +the storage domain is available in virt-v2v already, use it directly +instead of using a placeholder. + +This should fix a number of issues: +- unexisting/unattached storage domains are rejected outright +- the cluster is rejected if not part of the same data center of the + selected storage domain +- renaming the specified storage domain during the data copying will not + cause the conversion to fail (which will still use the specified + storage domain, no matter the new name) + +Based on the hints by Daniel Erez in RHBZ#1612653. + +(cherry picked from commit c49aa4fe01aac82d4776dd2a3524ce16e6deed06) +--- + v2v/output_rhv_upload.ml | 24 +++++++++++++++++++----- + v2v/rhv-upload-createvm.py | 11 ++++------- + v2v/rhv-upload-precheck.py | 30 ++++++++++++++++++++++++------ + 3 files changed, 47 insertions(+), 18 deletions(-) + +diff --git a/v2v/output_rhv_upload.ml b/v2v/output_rhv_upload.ml +index fd6f2e3e6..19bdfcf05 100644 +--- a/v2v/output_rhv_upload.ml ++++ b/v2v/output_rhv_upload.ml +@@ -227,6 +227,11 @@ See also the virt-v2v-output-rhv(1) manual.") + object + inherit output + ++ (* The storage domain UUID. *) ++ val mutable rhv_storagedomain_uuid = None ++ (* The cluster UUID. *) ++ val mutable rhv_cluster_uuid = None ++ + method precheck () = + Python_script.error_unless_python_interpreter_found (); + error_unless_ovirtsdk4_module_available (); +@@ -242,6 +247,10 @@ object + let json = JSON_parser.json_parser_tree_parse_file precheck_fn in + debug "precheck output parsed as: %s" + (JSON.string_of_doc ~fmt:JSON.Indented ["", json]); ++ rhv_storagedomain_uuid <- ++ Some (JSON_parser.object_get_string "rhv_storagedomain_uuid" json); ++ rhv_cluster_uuid <- ++ Some (JSON_parser.object_get_string "rhv_cluster_uuid" json); + if have_selinux then + error_unless_nbdkit_compiled_with_selinux () + +@@ -388,11 +397,11 @@ If the messages above are not sufficient to diagnose the problem then add the + diskid + ) targets in + +- (* We don't have the storage domain UUID, but instead we write +- * in a magic value which the Python code (which can get it) +- * will substitute. +- *) +- let sd_uuid = "@SD_UUID@" in ++ (* The storage domain UUID. *) ++ let sd_uuid = ++ match rhv_storagedomain_uuid with ++ | None -> assert false ++ | Some uuid -> uuid in + + (* The volume and VM UUIDs are made up. *) + let vol_uuids = List.map (fun _ -> uuidgen ()) targets +@@ -406,6 +415,11 @@ If the messages above are not sufficient to diagnose the problem then add the + OVirt in + let ovf = DOM.doc_to_string ovf in + ++ let json_params = ++ match rhv_cluster_uuid with ++ | None -> assert false ++ | Some uuid -> ("rhv_cluster_uuid", JSON.String uuid) :: json_params in ++ + let ovf_file = tmpdir // "vm.ovf" in + with_open_out ovf_file (fun chan -> output_string chan ovf); + if Python_script.run_command createvm_script json_params [ovf_file] <> 0 +diff --git a/v2v/rhv-upload-createvm.py b/v2v/rhv-upload-createvm.py +index 1d0e8c95d..ed57a9b20 100644 +--- a/v2v/rhv-upload-createvm.py ++++ b/v2v/rhv-upload-createvm.py +@@ -65,17 +65,14 @@ connection = sdk.Connection( + + system_service = connection.system_service() + +-# Get the storage domain UUID and substitute it into the OVF doc. +-sds_service = system_service.storage_domains_service() +-sd = sds_service.list(search=("name=%s" % params['output_storage']))[0] +-sd_uuid = sd.id +- +-ovf = ovf.replace("@SD_UUID@", sd_uuid) ++# Get the cluster. ++cluster = system_service.clusters_service().cluster_service(params['rhv_cluster_uuid']) ++cluster = cluster.get() + + vms_service = system_service.vms_service() + vm = vms_service.add( + types.Vm( +- cluster=types.Cluster(name = params['rhv_cluster']), ++ cluster=cluster, + initialization=types.Initialization( + configuration = types.Configuration( + type = types.ConfigurationType.OVA, +diff --git a/v2v/rhv-upload-precheck.py b/v2v/rhv-upload-precheck.py +index de8a66c05..725a8dc9e 100644 +--- a/v2v/rhv-upload-precheck.py ++++ b/v2v/rhv-upload-precheck.py +@@ -60,18 +60,36 @@ connection = sdk.Connection( + + system_service = connection.system_service() + +-# Check whether the specified cluster exists. +-clusters_service = system_service.clusters_service() +-clusters = clusters_service.list( +- search='name=%s' % params['rhv_cluster'], ++# Check whether there is a datacenter for the specified storage. ++data_centers = system_service.data_centers_service().list( ++ search='storage.name=%s' % params['output_storage'], + case_sensitive=True, + ) ++if len(data_centers) == 0: ++ # The storage domain is not attached to a datacenter ++ # (shouldn't happen, would fail on disk creation). ++ raise RuntimeError("The storage domain ‘%s’ is not attached to a DC" % ++ (params['output_storage'])) ++datacenter = data_centers[0] ++ ++# Get the storage domain. ++storage_domains = connection.follow_link(datacenter.storage_domains) ++storage_domain = [sd for sd in storage_domains if sd.name == params['output_storage']][0] ++ ++# Get the cluster. ++clusters = connection.follow_link(datacenter.clusters) ++clusters = [cluster for cluster in clusters if cluster.name == params['rhv_cluster']] + if len(clusters) == 0: +- raise RuntimeError("The cluster ‘%s’ does not exist" % +- (params['rhv_cluster'])) ++ raise RuntimeError("The cluster ‘%s’ is not part of the DC ‘%s’, " ++ "where the storage domain ‘%s’ is" % ++ (params['rhv_cluster'], datacenter.name, ++ params['output_storage'])) ++cluster = clusters[0] + + # Otherwise everything is OK, print a JSON with the results. + results = { ++ "rhv_storagedomain_uuid": storage_domain.id, ++ "rhv_cluster_uuid": cluster.id, + } + + json.dump(results, sys.stdout) +-- +2.25.4 + diff --git a/SOURCES/0025-v2v-rvh-upload-plugin-Always-read-the-response.patch b/SOURCES/0025-v2v-rvh-upload-plugin-Always-read-the-response.patch deleted file mode 100644 index 04e02ad..0000000 --- a/SOURCES/0025-v2v-rvh-upload-plugin-Always-read-the-response.patch +++ /dev/null @@ -1,112 +0,0 @@ -From 6cd873ff9a6ba6fed0534a253148b4daf48f0190 Mon Sep 17 00:00:00 2001 -From: Nir Soffer -Date: Mon, 25 Jun 2018 19:22:13 +0300 -Subject: [PATCH] v2v: rvh-upload-plugin: Always read the response - -Python manual warns[1]: - - Note that you must have read the whole response before you can send - a new request to the server. - -The reason for this warning is exposed only when the server is using -keep alive connections. When the response is not read, sending a new -request will fail with: - - httplib.ResponseNotReady - -Even if Content-Length was 0 or the request has no content. The failure -looks like this when using --verbose: - -nbdkit: python[1]: debug: zero count=33554432 offset=0 may_trim=1 fua=0 -nbdkit: python[1]: debug: zero count=33554432 offset=33554432 may_trim=1 fua=0 -nbdkit: python[1]: error: /home/nsoffer/src/libguestfs/tmp/rhvupload.Au2B5I/rhv-upload-plugin.py: zero: error: Request-sent -nbdkit: python[1]: debug: sending error reply: Input/output error -qemu-img: error writing zeroes at offset 0: Input/output error - -Change all requests to read the whole response. - -Tested with imageio patch supporting keep alive connections: -https://gerrit.ovirt.org/#/c/92296/ - -[1] https://docs.python.org/3.8/library/http.client.html#http.client.HTTPConnection.getresponse - -(cherry picked from commit f4e0a8342dbeb2c779c76e1807a37b24a0c96feb) ---- - v2v/rhv-upload-plugin.py | 15 ++++++++++++++- - 1 file changed, 14 insertions(+), 1 deletion(-) - -diff --git a/v2v/rhv-upload-plugin.py b/v2v/rhv-upload-plugin.py -index 7c5084efd..2eec375f7 100644 ---- a/v2v/rhv-upload-plugin.py -+++ b/v2v/rhv-upload-plugin.py -@@ -197,11 +197,13 @@ def get_options(h): - http.endheaders() - - r = http.getresponse() -+ data = r.read() -+ - if r.status == 200: - # New imageio never needs authentication. - h['needs_auth'] = False - -- j = json.loads(r.read()) -+ j = json.loads(data) - h['can_zero'] = "zero" in j['features'] - h['can_trim'] = "trim" in j['features'] - h['can_flush'] = "flush" in j['features'] -@@ -276,6 +278,7 @@ def pread(h, count, offset): - request_failed(h, r, - "could not read sector offset %d size %d" % - (offset, count)) -+ - return r.read() - - def pwrite(h, buf, offset): -@@ -302,6 +305,8 @@ def pwrite(h, buf, offset): - "could not write sector offset %d size %d" % - (offset, count)) - -+ r.read() -+ - def zero(h, count, offset, may_trim): - http = h['http'] - transfer = h['transfer'] -@@ -330,6 +335,8 @@ def zero(h, count, offset, may_trim): - "could not zero sector offset %d size %d" % - (offset, count)) - -+ r.read() -+ - def emulate_zero(h, count, offset): - # qemu-img convert starts by trying to zero/trim the whole device. - # Since we've just created a new disk it's safe to ignore these -@@ -357,6 +364,8 @@ def emulate_zero(h, count, offset): - "could not write zeroes offset %d size %d" % - (offset, count)) - -+ r.read() -+ - def trim(h, count, offset): - http = h['http'] - transfer = h['transfer'] -@@ -378,6 +387,8 @@ def trim(h, count, offset): - "could not trim sector offset %d size %d" % - (offset, count)) - -+ r.read() -+ - def flush(h): - http = h['http'] - transfer = h['transfer'] -@@ -394,6 +405,8 @@ def flush(h): - if r.status != 200: - request_failed(h, r, "could not flush") - -+ r.read() -+ - def delete_disk_on_failure(h): - disk_service = h['disk_service'] - disk_service.remove() --- -2.21.0 - diff --git a/SOURCES/0026-v2v-o-rhv-upload-tell-whether-a-SD-actually-exists.patch b/SOURCES/0026-v2v-o-rhv-upload-tell-whether-a-SD-actually-exists.patch new file mode 100644 index 0000000..b2235af --- /dev/null +++ b/SOURCES/0026-v2v-o-rhv-upload-tell-whether-a-SD-actually-exists.patch @@ -0,0 +1,36 @@ +From 5883b1efc1c54742bed7f56f4b1522061321c8f9 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Fri, 13 Sep 2019 12:40:34 +0200 +Subject: [PATCH] v2v: -o rhv-upload: tell whether a SD actually exists + +If there is no DC with the specified storage domain attached to it, it +can mean that the SD does not exist. + +(cherry picked from commit 2b39c27b7f1e72f3a3bf3a616e4576af691beb88) +--- + v2v/rhv-upload-precheck.py | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/v2v/rhv-upload-precheck.py b/v2v/rhv-upload-precheck.py +index 725a8dc9e..1b344ba27 100644 +--- a/v2v/rhv-upload-precheck.py ++++ b/v2v/rhv-upload-precheck.py +@@ -66,6 +66,15 @@ data_centers = system_service.data_centers_service().list( + case_sensitive=True, + ) + if len(data_centers) == 0: ++ storage_domains = system_service.storage_domains_service().list( ++ search='name=%s' % params['output_storage'], ++ case_sensitive=True, ++ ) ++ if len(storage_domains) == 0: ++ # The storage domain does not even exist. ++ raise RuntimeError("The storage domain ‘%s’ does not exist" % ++ (params['output_storage'])) ++ + # The storage domain is not attached to a datacenter + # (shouldn't happen, would fail on disk creation). + raise RuntimeError("The storage domain ‘%s’ is not attached to a DC" % +-- +2.25.4 + diff --git a/SOURCES/0026-v2v-rhv-upload-plugin-Fix-name-error.patch b/SOURCES/0026-v2v-rhv-upload-plugin-Fix-name-error.patch deleted file mode 100644 index 7b1951c..0000000 --- a/SOURCES/0026-v2v-rhv-upload-plugin-Fix-name-error.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 47fd85a883892e2070a2287cc9411896645ab3bf Mon Sep 17 00:00:00 2001 -From: Nir Soffer -Date: Mon, 25 Jun 2018 20:56:52 +0300 -Subject: [PATCH] v2v: rhv-upload-plugin: Fix name error - -"http" and "transfer" variables were missing in emulate_zero, so the -code would fail with NameError. This can happen only when communicating -with old imageio versions not supporting the "zero" feature. - -Testing with qemu-img 2.12 show that we never send emulated zero request -because of the highestwrite mechanism, but it can break with older -qemu-img-rhev used on RHEL. - -(cherry picked from commit 0ae61ce99c351f9cda598016fb55ccc50313df67) ---- - v2v/rhv-upload-plugin.py | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/v2v/rhv-upload-plugin.py b/v2v/rhv-upload-plugin.py -index 2eec375f7..10887c031 100644 ---- a/v2v/rhv-upload-plugin.py -+++ b/v2v/rhv-upload-plugin.py -@@ -338,6 +338,9 @@ def zero(h, count, offset, may_trim): - r.read() - - def emulate_zero(h, count, offset): -+ http = h['http'] -+ transfer = h['transfer'] -+ - # qemu-img convert starts by trying to zero/trim the whole device. - # Since we've just created a new disk it's safe to ignore these - # requests as long as they are smaller than the highest write seen. --- -2.21.0 - diff --git a/SOURCES/0027-v2v-add-output-disk_copied-hook.patch b/SOURCES/0027-v2v-add-output-disk_copied-hook.patch new file mode 100644 index 0000000..ed609b4 --- /dev/null +++ b/SOURCES/0027-v2v-add-output-disk_copied-hook.patch @@ -0,0 +1,76 @@ +From 7baca2397e3e494fa727e63e9a2d34b81b78c298 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Mon, 16 Sep 2019 14:01:14 +0200 +Subject: [PATCH] v2v: add output#disk_copied hook + +Add a simple method in the Output class to do work right after a disk +was successfully copied. + +(cherry picked from commit 74ee936505acf56d01f9b819588e7902a9401e81) +--- + v2v/types.ml | 1 + + v2v/types.mli | 8 ++++++++ + v2v/v2v.ml | 9 ++++++++- + 3 files changed, 17 insertions(+), 1 deletion(-) + +diff --git a/v2v/types.ml b/v2v/types.ml +index 77f879200..714b30014 100644 +--- a/v2v/types.ml ++++ b/v2v/types.ml +@@ -521,6 +521,7 @@ class virtual output = object + method override_output_format (_ : overlay) = (None : string option) + method virtual prepare_targets : source -> (string * overlay) list -> target_buses -> guestcaps -> inspect -> target_firmware -> target_file list + method disk_create = (open_guestfs ())#disk_create ++ method disk_copied (_ : target) (_ : int) (_ : int) = () + method virtual create_metadata : source -> target list -> target_buses -> guestcaps -> inspect -> target_firmware -> unit + method keep_serial_console = true + method install_rhev_apt = false +diff --git a/v2v/types.mli b/v2v/types.mli +index be9406100..f595ab0ef 100644 +--- a/v2v/types.mli ++++ b/v2v/types.mli +@@ -441,6 +441,10 @@ end + │ by running ‘qemu-img convert’. + │ + ▼ ++ output#disk_copied The output mode is notified about the ++ │ successful copy of each disk. ++ │ ++ ▼ + output#create_metadata VM should be created from the metadata + supplied. Also any finalization can + be done here. +@@ -485,6 +489,10 @@ class virtual output : object + (** Called in order to create disks on the target. The method has the + same signature as Guestfs#disk_create. Normally you should {b not} + define this since the default method calls Guestfs#disk_create. *) ++ method disk_copied : target -> int -> int -> unit ++ (** Called after a disk was successfully copied on the target. ++ The second parameter is the index of the copied disk (starting ++ from 0), and the third is the number of disks in total. *) + method virtual create_metadata : source -> target list -> target_buses -> guestcaps -> inspect -> target_firmware -> unit + (** Called after conversion and copying to create metadata and + do any finalization. *) +diff --git a/v2v/v2v.ml b/v2v/v2v.ml +index 277d8f2c7..63e809030 100644 +--- a/v2v/v2v.ml ++++ b/v2v/v2v.ml +@@ -798,7 +798,14 @@ and copy_targets cmdline targets input output = + pc; + if pc < 0. then eprintf " ! ESTIMATE TOO LOW !"; + eprintf "\n%!"; +- ) ++ ); ++ ++ (* Let the output mode know that the disk was copied successfully, ++ * so it can perform any operations without waiting for all the ++ * other disks to be copied (i.e. before the metadata is actually ++ * created). ++ *) ++ output#disk_copied t i nr_disks + ) targets + + (* Update the target_actual_size field in the target structure. *) +-- +2.25.4 + diff --git a/SOURCES/0027-v2v-rhv-upload-plugin-Remove-unused-variables.patch b/SOURCES/0027-v2v-rhv-upload-plugin-Remove-unused-variables.patch deleted file mode 100644 index cba76b5..0000000 --- a/SOURCES/0027-v2v-rhv-upload-plugin-Remove-unused-variables.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 6e683fa651864a04a1c4e2a326d84cfc9330d706 Mon Sep 17 00:00:00 2001 -From: Nir Soffer -Date: Tue, 26 Jun 2018 01:43:01 +0300 -Subject: [PATCH] v2v: rhv-upload-plugin: Remove unused variables - -Remove some instances of "transfer" and "transfer_service" that are not -used in current code. - -(cherry picked from commit 32ab53cecd78ee5c140f17e5792710698627d265) ---- - v2v/rhv-upload-plugin.py | 4 ---- - 1 file changed, 4 deletions(-) - -diff --git a/v2v/rhv-upload-plugin.py b/v2v/rhv-upload-plugin.py -index 10887c031..5c036c46a 100644 ---- a/v2v/rhv-upload-plugin.py -+++ b/v2v/rhv-upload-plugin.py -@@ -263,7 +263,6 @@ def request_failed(h, r, msg): - def pread(h, count, offset): - http = h['http'] - transfer = h['transfer'] -- transfer_service = h['transfer_service'] - - headers = {"Range", "bytes=%d-%d" % (offset, offset+count-1)} - # Authorization is only needed for old imageio. -@@ -309,7 +308,6 @@ def pwrite(h, buf, offset): - - def zero(h, count, offset, may_trim): - http = h['http'] -- transfer = h['transfer'] - - # Unlike the trim and flush calls, there is no 'can_zero' method - # so nbdkit could call this even if the server doesn't support -@@ -371,7 +369,6 @@ def emulate_zero(h, count, offset): - - def trim(h, count, offset): - http = h['http'] -- transfer = h['transfer'] - - # Construct the JSON request for trimming. - buf = json.dumps({'op': "trim", -@@ -394,7 +391,6 @@ def trim(h, count, offset): - - def flush(h): - http = h['http'] -- transfer = h['transfer'] - - # Construct the JSON request for flushing. - buf = json.dumps({'op': "flush"}).encode() --- -2.21.0 - diff --git a/SOURCES/0028-v2v-o-rhv-upload-Always-fetch-server-options-when-op.patch b/SOURCES/0028-v2v-o-rhv-upload-Always-fetch-server-options-when-op.patch deleted file mode 100644 index b1b83a6..0000000 --- a/SOURCES/0028-v2v-o-rhv-upload-Always-fetch-server-options-when-op.patch +++ /dev/null @@ -1,122 +0,0 @@ -From 1d2058c08b9eff607127d199b574273100e9ba55 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Tue, 19 Jun 2018 18:02:21 +0100 -Subject: [PATCH] v2v: -o rhv-upload: Always fetch server options when opening - the connection. -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Previously we lazily requested the server options in the can_* -callbacks. The can_* callbacks are always called by nbdkit straight -after open, so this just adds complexity for no benefit. This change -simply makes the code always fetch the server options during the open -callback. - -This is — functionally at least — mostly just refactoring. However I -also added a useful debug message so we can see what features the -imageio server is offering. - -(cherry picked from commit a1e1f6ec887c2a7973612d2edf7066fd3194ba0b) ---- - v2v/rhv-upload-plugin.py | 63 +++++++++++++++++++--------------------- - 1 file changed, 30 insertions(+), 33 deletions(-) - -diff --git a/v2v/rhv-upload-plugin.py b/v2v/rhv-upload-plugin.py -index 5c036c46a..f215eaecf 100644 ---- a/v2v/rhv-upload-plugin.py -+++ b/v2v/rhv-upload-plugin.py -@@ -165,34 +165,13 @@ def open(readonly): - context = context - ) - -- # Save everything we need to make requests in the handle. -- return { -- 'can_flush': False, -- 'can_trim': False, -- 'can_zero': False, -- 'connection': connection, -- 'disk': disk, -- 'disk_service': disk_service, -- 'failed': False, -- 'got_options': False, -- 'highestwrite': 0, -- 'http': http, -- 'needs_auth': not params['rhv_direct'], -- 'path': destination_url.path, -- 'transfer': transfer, -- 'transfer_service': transfer_service, -- } -+ # The first request is to fetch the features of the server. -+ needs_auth = not params['rhv_direct'] -+ can_flush = False -+ can_trim = False -+ can_zero = False - --# Can we issue zero, trim or flush requests? --def get_options(h): -- if h['got_options']: -- return -- h['got_options'] = True -- -- http = h['http'] -- transfer = h['transfer'] -- -- http.putrequest("OPTIONS", h['path']) -+ http.putrequest("OPTIONS", destination_url.path) - http.putheader("Authorization", transfer.signed_ticket) - http.endheaders() - -@@ -201,12 +180,12 @@ def get_options(h): - - if r.status == 200: - # New imageio never needs authentication. -- h['needs_auth'] = False -+ needs_auth = False - - j = json.loads(data) -- h['can_zero'] = "zero" in j['features'] -- h['can_trim'] = "trim" in j['features'] -- h['can_flush'] = "flush" in j['features'] -+ can_flush = "flush" in j['features'] -+ can_trim = "trim" in j['features'] -+ can_zero = "zero" in j['features'] - - # Old imageio servers returned either 405 Method Not Allowed or - # 204 No Content (with an empty body). If we see that we leave -@@ -218,12 +197,30 @@ def get_options(h): - raise RuntimeError("could not use OPTIONS request: %d: %s" % - (r.status, r.reason)) - -+ debug("imageio features: flush=%r trim=%r zero=%r" % -+ (can_flush, can_trim, can_zero)) -+ -+ # Save everything we need to make requests in the handle. -+ return { -+ 'can_flush': can_flush, -+ 'can_trim': can_trim, -+ 'can_zero': can_zero, -+ 'connection': connection, -+ 'disk': disk, -+ 'disk_service': disk_service, -+ 'failed': False, -+ 'highestwrite': 0, -+ 'http': http, -+ 'needs_auth': needs_auth, -+ 'path': destination_url.path, -+ 'transfer': transfer, -+ 'transfer_service': transfer_service, -+ } -+ - def can_trim(h): -- get_options(h) - return h['can_trim'] - - def can_flush(h): -- get_options(h) - return h['can_flush'] - - def get_size(h): --- -2.21.0 - diff --git a/SOURCES/0028-v2v-o-rhv-upload-collect-disks-UUIDs-right-after-cop.patch b/SOURCES/0028-v2v-o-rhv-upload-collect-disks-UUIDs-right-after-cop.patch new file mode 100644 index 0000000..1040341 --- /dev/null +++ b/SOURCES/0028-v2v-o-rhv-upload-collect-disks-UUIDs-right-after-cop.patch @@ -0,0 +1,84 @@ +From 9ae4cc6feaf66cf34b9cdf0cf2c251ed7ef61259 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Mon, 16 Sep 2019 14:07:22 +0200 +Subject: [PATCH] v2v: -o rhv-upload: collect disks UUIDs right after copy + +Instead of waiting for the completion of the nbdkit transfers to get the +UUIDs of the disks, use the new #disk_copied hook to do that after each +disk is copied. + +This has almost no behaviour on rhv-upload, except for the --no-copy +mode: +- previously it used to hit the 5 minute timeout while waiting for the + finalization of the first disk +- now it asserts on the different number of collected UUIDs vs the + actual targets; at the moment there is nothing else that can be done, + as this assumption is needed e.g. when creating the OVF file + +(cherry picked from commit 7b93ad6a32f09043bf870202b59bea83d47e0c3a) +--- + v2v/output_rhv_upload.ml | 32 ++++++++++++++++---------------- + 1 file changed, 16 insertions(+), 16 deletions(-) + +diff --git a/v2v/output_rhv_upload.ml b/v2v/output_rhv_upload.ml +index 19bdfcf05..382ad0d93 100644 +--- a/v2v/output_rhv_upload.ml ++++ b/v2v/output_rhv_upload.ml +@@ -231,6 +231,8 @@ object + val mutable rhv_storagedomain_uuid = None + (* The cluster UUID. *) + val mutable rhv_cluster_uuid = None ++ (* List of disk UUIDs. *) ++ val mutable disks_uuids = [] + + method precheck () = + Python_script.error_unless_python_interpreter_found (); +@@ -379,23 +381,21 @@ If the messages above are not sufficient to diagnose the problem then add the + TargetURI ("json:" ^ JSON.string_of_doc json_params) + ) overlays + +- method create_metadata source targets _ guestcaps inspect target_firmware = +- (* Get the UUIDs of each disk image. These files are written +- * out by the nbdkit plugins on successful finalization of the ++ method disk_copied t i nr_disks = ++ (* Get the UUID of the disk image. This file is written ++ * out by the nbdkit plugin on successful finalization of the + * transfer. + *) +- let nr_disks = List.length targets in +- let image_uuids = +- List.mapi ( +- fun i t -> +- let id = t.target_overlay.ov_source.s_disk_id in +- let diskid_file = diskid_file_of_id id in +- if not (wait_for_file diskid_file finalization_timeout) then +- error (f_"transfer of disk %d/%d failed, see earlier error messages") +- (i+1) nr_disks; +- let diskid = read_whole_file diskid_file in +- diskid +- ) targets in ++ let id = t.target_overlay.ov_source.s_disk_id in ++ let diskid_file = diskid_file_of_id id in ++ if not (wait_for_file diskid_file finalization_timeout) then ++ error (f_"transfer of disk %d/%d failed, see earlier error messages") ++ (i+1) nr_disks; ++ let diskid = read_whole_file diskid_file in ++ disks_uuids <- disks_uuids @ [diskid]; ++ ++ method create_metadata source targets _ guestcaps inspect target_firmware = ++ assert (List.length disks_uuids = List.length targets); + + (* The storage domain UUID. *) + let sd_uuid = +@@ -411,7 +411,7 @@ If the messages above are not sufficient to diagnose the problem then add the + let ovf = + Create_ovf.create_ovf source targets guestcaps inspect + target_firmware output_alloc +- sd_uuid image_uuids vol_uuids vm_uuid ++ sd_uuid disks_uuids vol_uuids vm_uuid + OVirt in + let ovf = DOM.doc_to_string ovf in + +-- +2.25.4 + diff --git a/SOURCES/0029-v2v-o-rhv-upload-Use-Unix-domain-socket-to-access-im.patch b/SOURCES/0029-v2v-o-rhv-upload-Use-Unix-domain-socket-to-access-im.patch deleted file mode 100644 index 604d06f..0000000 --- a/SOURCES/0029-v2v-o-rhv-upload-Use-Unix-domain-socket-to-access-im.patch +++ /dev/null @@ -1,141 +0,0 @@ -From db7e06935bfd20e02110549371a5174e68a45cf0 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Mon, 18 Jun 2018 15:34:37 +0100 -Subject: [PATCH] v2v: -o rhv-upload: Use Unix domain socket to access imageio - (RHBZ#1588088). - -In the case where virt-v2v runs on the same server as the imageio -daemon that we are talking to, it may be possible to optimize access -using a Unix domain socket. - -This is only an optimization. If it fails or if we're not running on -the same server it will fall back to the usual HTTPS over TCP -connection. - -Thanks: Nir Soffer, Daniel Erez. -(cherry picked from commit b7a2e6270d53200d2df471c36a1fb2b46db8bbac) ---- - v2v/rhv-upload-plugin.py | 61 ++++++++++++++++++++++++++++++++++++++-- - 1 file changed, 58 insertions(+), 3 deletions(-) - -diff --git a/v2v/rhv-upload-plugin.py b/v2v/rhv-upload-plugin.py -index f215eaecf..8805e3552 100644 ---- a/v2v/rhv-upload-plugin.py -+++ b/v2v/rhv-upload-plugin.py -@@ -19,11 +19,12 @@ - import builtins - import json - import logging -+import socket - import ssl - import sys - import time - --from http.client import HTTPSConnection -+from http.client import HTTPSConnection, HTTPConnection - from urllib.parse import urlparse - - import ovirtsdk4 as sdk -@@ -56,6 +57,28 @@ def debug(s): - print(s, file=sys.stderr) - sys.stderr.flush() - -+def find_host(connection): -+ """Return the current host object or None.""" -+ try: -+ with builtins.open("/etc/vdsm/vdsm.id") as f: -+ vdsm_id = f.readline().strip() -+ except Exception as e: -+ return None -+ debug("hw_id = %r" % vdsm_id) -+ -+ hosts_service = connection.system_service().hosts_service() -+ hosts = hosts_service.list( -+ search="hw_id=%s" % vdsm_id, -+ case_sensitive=False, -+ ) -+ if len(hosts) == 0: -+ return None -+ -+ host = hosts[0] -+ debug("host.id = %r" % host.id) -+ -+ return types.Host(id = host.id) -+ - def open(readonly): - # Parse out the username from the output_conn URL. - parsed = urlparse(params['output_conn']) -@@ -121,9 +144,11 @@ def open(readonly): - transfers_service = system_service.image_transfers_service() - - # Create a new image transfer. -+ host = find_host(connection) - transfer = transfers_service.add( - types.ImageTransfer( - disk = types.Disk(id = disk.id), -+ host = host, - inactivity_timeout = 3600, - ) - ) -@@ -170,6 +195,7 @@ def open(readonly): - can_flush = False - can_trim = False - can_zero = False -+ unix_socket = None - - http.putrequest("OPTIONS", destination_url.path) - http.putheader("Authorization", transfer.signed_ticket) -@@ -186,6 +212,7 @@ def open(readonly): - can_flush = "flush" in j['features'] - can_trim = "trim" in j['features'] - can_zero = "zero" in j['features'] -+ unix_socket = j.get('unix_socket') - - # Old imageio servers returned either 405 Method Not Allowed or - # 204 No Content (with an empty body). If we see that we leave -@@ -197,8 +224,17 @@ def open(readonly): - raise RuntimeError("could not use OPTIONS request: %d: %s" % - (r.status, r.reason)) - -- debug("imageio features: flush=%r trim=%r zero=%r" % -- (can_flush, can_trim, can_zero)) -+ debug("imageio features: flush=%r trim=%r zero=%r unix_socket=%r" % -+ (can_flush, can_trim, can_zero, unix_socket)) -+ -+ # If we are connected to imageio on the local host and the -+ # transfer features a unix_socket then we can reconnect to that. -+ if host is not None and unix_socket is not None: -+ try: -+ http = UnixHTTPConnection(unix_socket) -+ debug("optimizing connection using unix socket %r" % unix_socket) -+ except: -+ pass - - # Save everything we need to make requests in the handle. - return { -@@ -463,3 +499,22 @@ def close(h): - raise - - connection.close() -+ -+# Modify http.client.HTTPConnection to work over a Unix domain socket. -+# Derived from uhttplib written by Erik van Zijst under an MIT license. -+# (https://pypi.org/project/uhttplib/) -+# Ported to Python 3 by Irit Goihman. -+ -+class UnsupportedError(Exception): -+ pass -+ -+class UnixHTTPConnection(HTTPConnection): -+ def __init__(self, path, timeout=socket._GLOBAL_DEFAULT_TIMEOUT): -+ self.path = path -+ HTTPConnection.__init__(self, "localhost", timeout=timeout) -+ -+ def connect(self): -+ self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) -+ if self.timeout is not socket._GLOBAL_DEFAULT_TIMEOUT: -+ self.sock.settimeout(timeout) -+ self.sock.connect(self.path) --- -2.21.0 - diff --git a/SOURCES/0029-v2v-o-rhv-upload-add-oo-rhv-disk-uuid-option.patch b/SOURCES/0029-v2v-o-rhv-upload-add-oo-rhv-disk-uuid-option.patch new file mode 100644 index 0000000..fc7c385 --- /dev/null +++ b/SOURCES/0029-v2v-o-rhv-upload-add-oo-rhv-disk-uuid-option.patch @@ -0,0 +1,201 @@ +From 9d7503382f33a7721378ec586ea718c63a0ec3b6 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Thu, 19 Sep 2019 12:19:09 +0200 +Subject: [PATCH] v2v: -o rhv-upload: add -oo rhv-disk-uuid option + +This way it is possible to override the UUIDs of the uploaded disks, +instead of letting RHV generate them. + +This can be useful to force certain UUIDs, and to specify the disks in +--no-copy mode (which now can be used). + +(cherry picked from commit 537ba8357e44ca3aa8878a2ac98e9476a570d3f4) +--- + v2v/output_rhv_upload.ml | 43 ++++++++++++++++++++++++++++++++----- + v2v/rhv-upload-plugin.py | 2 ++ + v2v/virt-v2v-output-rhv.pod | 24 +++++++++++++++++++++ + 3 files changed, 64 insertions(+), 5 deletions(-) + +diff --git a/v2v/output_rhv_upload.ml b/v2v/output_rhv_upload.ml +index 382ad0d93..206657a2b 100644 +--- a/v2v/output_rhv_upload.ml ++++ b/v2v/output_rhv_upload.ml +@@ -32,6 +32,7 @@ type rhv_options = { + rhv_cluster : string option; + rhv_direct : bool; + rhv_verifypeer : bool; ++ rhv_disk_uuids : string list option; + } + + let print_output_options () = +@@ -41,6 +42,11 @@ let print_output_options () = + -oo rhv-cluster=CLUSTERNAME Set RHV cluster name. + -oo rhv-direct[=true|false] Use direct transfer mode (default: false). + -oo rhv-verifypeer[=true|false] Verify server identity (default: false). ++ ++You can override the UUIDs of the disks, instead of using autogenerated UUIDs ++after their uploads (if you do, you must supply one for each disk): ++ ++ -oo rhv-disk-uuid=UUID Disk UUID + ") + + let parse_output_options options = +@@ -48,6 +54,7 @@ let parse_output_options options = + let rhv_cluster = ref None in + let rhv_direct = ref false in + let rhv_verifypeer = ref false in ++ let rhv_disk_uuids = ref None in + + List.iter ( + function +@@ -63,6 +70,8 @@ let parse_output_options options = + | "rhv-direct", v -> rhv_direct := bool_of_string v + | "rhv-verifypeer", "" -> rhv_verifypeer := true + | "rhv-verifypeer", v -> rhv_verifypeer := bool_of_string v ++ | "rhv-disk-uuid", v -> ++ rhv_disk_uuids := Some (v :: (Option.default [] !rhv_disk_uuids)) + | k, _ -> + error (f_"-o rhv-upload: unknown output option ‘-oo %s’") k + ) options; +@@ -75,8 +84,9 @@ let parse_output_options options = + let rhv_cluster = !rhv_cluster in + let rhv_direct = !rhv_direct in + let rhv_verifypeer = !rhv_verifypeer in ++ let rhv_disk_uuids = Option.map List.rev !rhv_disk_uuids in + +- { rhv_cafile; rhv_cluster; rhv_direct; rhv_verifypeer } ++ { rhv_cafile; rhv_cluster; rhv_direct; rhv_verifypeer; rhv_disk_uuids } + + let nbdkit_python_plugin = Config.virt_v2v_nbdkit_python_plugin + let pidfile_timeout = 30 +@@ -270,6 +280,16 @@ object + method install_rhev_apt = true + + method prepare_targets source overlays _ _ _ _ = ++ let uuids = ++ match rhv_options.rhv_disk_uuids with ++ | None -> ++ List.map (fun _ -> None) overlays ++ | Some uuids -> ++ if List.length uuids <> List.length overlays then ++ error (f_"the number of ‘-oo rhv-disk-uuid’ parameters passed on the command line has to match the number of guest disk images (for this guest: %d)") ++ (List.length overlays); ++ List.map (fun uuid -> Some uuid) uuids in ++ + let output_name = source.s_name in + let json_params = + ("output_name", JSON.String output_name) :: json_params in +@@ -284,7 +304,7 @@ object + * target URI to point to the NBD socket. + *) + List.map ( +- fun (target_format, ov) -> ++ fun ((target_format, ov), uuid) -> + let id = ov.ov_source.s_disk_id in + let disk_name = sprintf "%s-%03d" output_name id in + let json_params = +@@ -310,6 +330,12 @@ object + let json_params = + ("diskid_file", JSON.String diskid_file) :: json_params in + ++ let json_params = ++ match uuid with ++ | None -> json_params ++ | Some uuid -> ++ ("rhv_disk_uuid", JSON.String uuid) :: json_params in ++ + (* Write the JSON parameters to a file. *) + let json_param_file = tmpdir // sprintf "params%d.json" id in + with_open_out +@@ -379,7 +405,7 @@ If the messages above are not sufficient to diagnose the problem then add the + "file.export", JSON.String "/"; + ] in + TargetURI ("json:" ^ JSON.string_of_doc json_params) +- ) overlays ++ ) (List.combine overlays uuids) + + method disk_copied t i nr_disks = + (* Get the UUID of the disk image. This file is written +@@ -395,7 +421,14 @@ If the messages above are not sufficient to diagnose the problem then add the + disks_uuids <- disks_uuids @ [diskid]; + + method create_metadata source targets _ guestcaps inspect target_firmware = +- assert (List.length disks_uuids = List.length targets); ++ let image_uuids = ++ match rhv_options.rhv_disk_uuids, disks_uuids with ++ | None, [] -> ++ error (f_"there must be ‘-oo rhv-disk-uuid’ parameters passed on the command line to specify the UUIDs of guest disk images (for this guest: %d)") ++ (List.length targets) ++ | Some uuids, _ -> uuids ++ | None, uuids -> uuids in ++ assert (List.length image_uuids = List.length targets); + + (* The storage domain UUID. *) + let sd_uuid = +@@ -411,7 +444,7 @@ If the messages above are not sufficient to diagnose the problem then add the + let ovf = + Create_ovf.create_ovf source targets guestcaps inspect + target_firmware output_alloc +- sd_uuid disks_uuids vol_uuids vm_uuid ++ sd_uuid image_uuids vol_uuids vm_uuid + OVirt in + let ovf = DOM.doc_to_string ovf in + +diff --git a/v2v/rhv-upload-plugin.py b/v2v/rhv-upload-plugin.py +index 4d61a089b..6ec74a5d4 100644 +--- a/v2v/rhv-upload-plugin.py ++++ b/v2v/rhv-upload-plugin.py +@@ -135,6 +135,8 @@ def open(readonly): + disk_format = types.DiskFormat.COW + disk = disks_service.add( + disk = types.Disk( ++ # The ID is optional. ++ id = params.get('rhv_disk_uuid'), + name = params['disk_name'], + description = "Uploaded by virt-v2v", + format = disk_format, +diff --git a/v2v/virt-v2v-output-rhv.pod b/v2v/virt-v2v-output-rhv.pod +index 651f61dae..e840ca78d 100644 +--- a/v2v/virt-v2v-output-rhv.pod ++++ b/v2v/virt-v2v-output-rhv.pod +@@ -9,6 +9,7 @@ virt-v2v-output-rhv - Using virt-v2v to convert guests to oVirt or RHV + [-oo rhv-cafile=FILE] + [-oo rhv-cluster=CLUSTER] + [-oo rhv-direct] ++ [-oo rhv-disk-uuid=UUID ...] + [-oo rhv-verifypeer] + + virt-v2v [-i* options] -o rhv -os [esd:/path|/path] +@@ -104,6 +105,29 @@ F on the oVirt engine. + + Set the RHV Cluster Name. If not given it uses C. + ++=item I<-oo rhv-disk-uuid=>C ++ ++This option can used to manually specify UUIDs for the disks when ++creating the virtual machine. If not specified, the oVirt engine will ++generate random UUIDs for the disks. Please note that: ++ ++=over 4 ++ ++=item * ++ ++you B pass as many I<-oo rhv-disk-uuid=UUID> options as the ++amount of disks in the guest ++ ++=item * ++ ++the specified UUIDs are used as they are, without checking whether ++they are already used by other disks ++ ++=back ++ ++This option is considered advanced, and to be used mostly in ++combination with I<--no-copy>. ++ + =item I<-oo rhv-direct> + + If this option is given then virt-v2v will attempt to directly upload +-- +2.25.4 + diff --git a/SOURCES/0030-v2v-improve-os-documentation-for-rhv-upload.patch b/SOURCES/0030-v2v-improve-os-documentation-for-rhv-upload.patch deleted file mode 100644 index 7b47c16..0000000 --- a/SOURCES/0030-v2v-improve-os-documentation-for-rhv-upload.patch +++ /dev/null @@ -1,29 +0,0 @@ -From da504873e18fc1414d670f318c10d5fb512e05dd Mon Sep 17 00:00:00 2001 -From: Pino Toscano -Date: Fri, 29 Jun 2018 12:58:33 +0200 -Subject: [PATCH] v2v: improve -os documentation for rhv-upload - -Thanks to: Ming Xie - -(cherry picked from commit 8d33ff8ba415180dee8f1f91f3b4d16d72ec094e) ---- - v2v/virt-v2v.pod | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/v2v/virt-v2v.pod b/v2v/virt-v2v.pod -index f012ea533..893e47fb9 100644 ---- a/v2v/virt-v2v.pod -+++ b/v2v/virt-v2v.pod -@@ -758,6 +758,9 @@ For I<-o libvirt>, this is a libvirt directory pool - For I<-o local> and I<-o qemu>, this is a directory name. The - directory must exist. - -+For I<-o rhv-upload>, this is the name of the destination Storage -+Domain. -+ - For I<-o rhv>, this can be an NFS path of the Export Storage Domain - of the form ChostE:EpathE>, eg: - --- -2.21.0 - diff --git a/SOURCES/0030-v2v-o-rhv-upload-make-oo-rhv-cafile-optional.patch b/SOURCES/0030-v2v-o-rhv-upload-make-oo-rhv-cafile-optional.patch new file mode 100644 index 0000000..38d803d --- /dev/null +++ b/SOURCES/0030-v2v-o-rhv-upload-make-oo-rhv-cafile-optional.patch @@ -0,0 +1,87 @@ +From 5ad1e7c160f5fe0d499d8d25116cb0e1692f1e93 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Fri, 27 Sep 2019 13:56:42 +0200 +Subject: [PATCH] v2v: -o rhv-upload: make -oo rhv-cafile optional + +It makes little sense to require the oVirt certificate, especially when +the verification of the connection (-oo rhv-verifypeer) is disabled by +default. The only work done with the certificate in that case is +checking that it is a valid certificate file. + +Hence, make -oo rhv-cafile optional, requiring it only when +-oo rhv-verifypeer is enabled. + +(cherry picked from commit 0a5eaad7db3c9b9a03fa88102a9e6142c855bfd1) +--- + v2v/output_rhv_upload.ml | 16 +++++++++------- + v2v/virt-v2v-output-rhv.pod | 2 ++ + 2 files changed, 11 insertions(+), 7 deletions(-) + +diff --git a/v2v/output_rhv_upload.ml b/v2v/output_rhv_upload.ml +index 206657a2b..2c8c18732 100644 +--- a/v2v/output_rhv_upload.ml ++++ b/v2v/output_rhv_upload.ml +@@ -28,7 +28,7 @@ open Types + open Utils + + type rhv_options = { +- rhv_cafile : string; ++ rhv_cafile : string option; + rhv_cluster : string option; + rhv_direct : bool; + rhv_verifypeer : bool; +@@ -76,15 +76,13 @@ let parse_output_options options = + error (f_"-o rhv-upload: unknown output option ‘-oo %s’") k + ) options; + +- let rhv_cafile = +- match !rhv_cafile with +- | Some s -> s +- | None -> +- error (f_"-o rhv-upload: must use ‘-oo rhv-cafile’ to supply the path to the oVirt or RHV user’s ‘ca.pem’ file") in ++ let rhv_cafile = !rhv_cafile in + let rhv_cluster = !rhv_cluster in + let rhv_direct = !rhv_direct in + let rhv_verifypeer = !rhv_verifypeer in + let rhv_disk_uuids = Option.map List.rev !rhv_disk_uuids in ++ if rhv_verifypeer && rhv_cafile = None then ++ error (f_"-o rhv-upload: must use ‘-oo rhv-cafile’ to supply the path to the oVirt or RHV user’s ‘ca.pem’ file"); + + { rhv_cafile; rhv_cluster; rhv_direct; rhv_verifypeer; rhv_disk_uuids } + +@@ -92,6 +90,10 @@ let nbdkit_python_plugin = Config.virt_v2v_nbdkit_python_plugin + let pidfile_timeout = 30 + let finalization_timeout = 5*60 + ++let json_optstring = function ++ | Some s -> JSON.String s ++ | None -> JSON.Null ++ + class output_rhv_upload output_alloc output_conn + output_password output_storage + rhv_options = +@@ -200,7 +202,7 @@ See also the virt-v2v-output-rhv(1) manual.") + "output_sparse", JSON.Bool (match output_alloc with + | Sparse -> true + | Preallocated -> false); +- "rhv_cafile", JSON.String rhv_options.rhv_cafile; ++ "rhv_cafile", json_optstring rhv_options.rhv_cafile; + "rhv_cluster", + JSON.String (Option.default "Default" rhv_options.rhv_cluster); + "rhv_direct", JSON.Bool rhv_options.rhv_direct; +diff --git a/v2v/virt-v2v-output-rhv.pod b/v2v/virt-v2v-output-rhv.pod +index e840ca78d..04a894268 100644 +--- a/v2v/virt-v2v-output-rhv.pod ++++ b/v2v/virt-v2v-output-rhv.pod +@@ -101,6 +101,8 @@ The storage domain. + The F file (Certificate Authority), copied from + F on the oVirt engine. + ++This option must be specified if I<-oo rhv-verifypeer> is enabled. ++ + =item I<-oo rhv-cluster=>C + + Set the RHV Cluster Name. If not given it uses C. +-- +2.25.4 + diff --git a/SOURCES/0031-v2v-Fix-default-graphics-driver-for-SUSE-guests.patch b/SOURCES/0031-v2v-Fix-default-graphics-driver-for-SUSE-guests.patch new file mode 100644 index 0000000..47694b3 --- /dev/null +++ b/SOURCES/0031-v2v-Fix-default-graphics-driver-for-SUSE-guests.patch @@ -0,0 +1,40 @@ +From 1b409cee748cfb60cc87f8bfa80370048d8dd014 Mon Sep 17 00:00:00 2001 +From: Mike Latimer +Date: Mon, 25 Mar 2019 14:38:00 +0000 +Subject: [PATCH] v2v: Fix default graphics driver for SUSE guests. + +See discussion in this upstream thread: +https://www.redhat.com/archives/libguestfs/2019-February/thread.html#00047 + +Thanks: Mike Latimer, Pino Toscano. +(cherry picked from commit 612f170e6062f2ff74643b6096b7e0765b52cfbd) +--- + v2v/convert_linux.ml | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/v2v/convert_linux.ml b/v2v/convert_linux.ml +index b4b2f24c4..f9e811c8d 100644 +--- a/v2v/convert_linux.ml ++++ b/v2v/convert_linux.ml +@@ -104,7 +104,7 @@ let convert (g : G.guestfs) inspect source output rcaps = + + let video = + match rcaps.rcaps_video with +- | None -> get_display_driver () ++ | None -> QXL + | Some video -> video in + + let block_type = +@@ -783,9 +783,6 @@ let convert (g : G.guestfs) inspect source output rcaps = + else + true + +- and get_display_driver () = +- if family = `SUSE_family then Cirrus else QXL +- + and configure_display_driver video = + let video_driver = match video with QXL -> "qxl" | Cirrus -> "cirrus" in + +-- +2.25.4 + diff --git a/SOURCES/0031-v2v-rhv-upload-plugin-Remove-unneeded-auth.patch b/SOURCES/0031-v2v-rhv-upload-plugin-Remove-unneeded-auth.patch deleted file mode 100644 index 031cb22..0000000 --- a/SOURCES/0031-v2v-rhv-upload-plugin-Remove-unneeded-auth.patch +++ /dev/null @@ -1,69 +0,0 @@ -From a3e99c84e1aed2fc275be00292f86414c8d4432a Mon Sep 17 00:00:00 2001 -From: Nir Soffer -Date: Fri, 29 Jun 2018 17:41:10 +0300 -Subject: [PATCH] v2v: rhv-upload-plugin: Remove unneeded auth - -Old imageio proxy was using Authorization header for GET and PUT -requests. Remove unneeded authorization when sending OPTIONS request. - -Remove unneeded duplicated comments about authorization for old -imageio, and replace them with a comment when we set needs_auth. - -(cherry picked from commit d5f36bacf9bb6d4d244184551792989906f60896) ---- - v2v/rhv-upload-plugin.py | 12 +++++------- - 1 file changed, 5 insertions(+), 7 deletions(-) - -diff --git a/v2v/rhv-upload-plugin.py b/v2v/rhv-upload-plugin.py -index 8805e3552..f404bd758 100644 ---- a/v2v/rhv-upload-plugin.py -+++ b/v2v/rhv-upload-plugin.py -@@ -191,16 +191,17 @@ def open(readonly): - ) - - # The first request is to fetch the features of the server. -+ -+ # Authentication was needed only for GET and PUT requests when -+ # communicating with old imageio-proxy. - needs_auth = not params['rhv_direct'] -+ - can_flush = False - can_trim = False - can_zero = False - unix_socket = None - -- http.putrequest("OPTIONS", destination_url.path) -- http.putheader("Authorization", transfer.signed_ticket) -- http.endheaders() -- -+ http.request("OPTIONS", destination_url.path) - r = http.getresponse() - data = r.read() - -@@ -298,7 +299,6 @@ def pread(h, count, offset): - transfer = h['transfer'] - - headers = {"Range", "bytes=%d-%d" % (offset, offset+count-1)} -- # Authorization is only needed for old imageio. - if h['needs_auth']: - headers["Authorization"] = transfer.signed_ticket - -@@ -321,7 +321,6 @@ def pwrite(h, buf, offset): - h['highestwrite'] = max(h['highestwrite'], offset+count) - - http.putrequest("PUT", h['path'] + "?flush=n") -- # Authorization is only needed for old imageio. - if h['needs_auth']: - http.putheader("Authorization", transfer.signed_ticket) - # The oVirt server only uses the first part of the range, and the -@@ -378,7 +377,6 @@ def emulate_zero(h, count, offset): - # After that we must emulate them with writes. - if offset+count < h['highestwrite']: - http.putrequest("PUT", h['path']) -- # Authorization is only needed for old imageio. - if h['needs_auth']: - http.putheader("Authorization", transfer.signed_ticket) - http.putheader("Content-Range", --- -2.21.0 - diff --git a/SOURCES/0032-v2v-rhv-upload-plugin-Improve-error-handling.patch b/SOURCES/0032-v2v-rhv-upload-plugin-Improve-error-handling.patch deleted file mode 100644 index 1c2899c..0000000 --- a/SOURCES/0032-v2v-rhv-upload-plugin-Improve-error-handling.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 8aaf7d89ef8b686840d3683fb27c4746624088a5 Mon Sep 17 00:00:00 2001 -From: Nir Soffer -Date: Sat, 30 Jun 2018 01:21:50 +0300 -Subject: [PATCH] v2v: rhv-upload-plugin: Improve error handling - -When optimizing the connection using unix socket, we handle these cases: - -- The local host is not an oVirt host (no /etc/vdsm/vdsm.id). -- The local host is an oVirt host, but is not registered with engine. -- Creating UnixHTTPConnection() fails. Unlikely and probably a bug in - the plugin, but we can recover by using the https connection. - -The current code handle these cases silently, making it harder to -understand why the unix socket optimization did no happen. Add debug -message to make this clear. - -Also comment in the error handler why we take this path instead of -failing the operation. - -(cherry picked from commit f5442d2f044b398efc992fb4d56c8d3096c781e6) ---- - v2v/rhv-upload-plugin.py | 12 ++++++++++-- - 1 file changed, 10 insertions(+), 2 deletions(-) - -diff --git a/v2v/rhv-upload-plugin.py b/v2v/rhv-upload-plugin.py -index f404bd758..8e4052048 100644 ---- a/v2v/rhv-upload-plugin.py -+++ b/v2v/rhv-upload-plugin.py -@@ -63,7 +63,10 @@ def find_host(connection): - with builtins.open("/etc/vdsm/vdsm.id") as f: - vdsm_id = f.readline().strip() - except Exception as e: -+ # This is most likely not an oVirt host. -+ debug("cannot read /etc/vdsm/vdsm.id, using any host: %s" % e) - return None -+ - debug("hw_id = %r" % vdsm_id) - - hosts_service = connection.system_service().hosts_service() -@@ -72,6 +75,8 @@ def find_host(connection): - case_sensitive=False, - ) - if len(hosts) == 0: -+ # This oVirt host is not registered with engine. -+ debug("cannot find host with hw_id=%r, using any host" % vdsm_id) - return None - - host = hosts[0] -@@ -233,9 +238,12 @@ def open(readonly): - if host is not None and unix_socket is not None: - try: - http = UnixHTTPConnection(unix_socket) -+ except Exception as e: -+ # Very unlikely failure, but we can recover by using the https -+ # connection. -+ debug("cannot create unix socket connection, using https: %s" % e) -+ else: - debug("optimizing connection using unix socket %r" % unix_socket) -- except: -- pass - - # Save everything we need to make requests in the handle. - return { --- -2.21.0 - diff --git a/SOURCES/0032-v2v-windows-Add-a-helper-function-for-installing-Pow.patch b/SOURCES/0032-v2v-windows-Add-a-helper-function-for-installing-Pow.patch new file mode 100644 index 0000000..da0c9aa --- /dev/null +++ b/SOURCES/0032-v2v-windows-Add-a-helper-function-for-installing-Pow.patch @@ -0,0 +1,73 @@ +From bb09f8b1ab0fc3bda654e7d564d5010f9f24f660 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Tue, 4 Dec 2018 16:09:42 +0000 +Subject: [PATCH] v2v: windows: Add a helper function for installing Powershell + firstboot scripts. + +(cherry picked from commit e1e9b3845e76a4bb406d16b96283ac38677cd91f) +--- + v2v/Makefile.am | 1 + + v2v/windows.ml | 23 +++++++++++++++++++++++ + v2v/windows.mli | 6 ++++++ + 3 files changed, 30 insertions(+) + +diff --git a/v2v/Makefile.am b/v2v/Makefile.am +index 30f040d3e..6568c9a6b 100644 +--- a/v2v/Makefile.am ++++ b/v2v/Makefile.am +@@ -667,6 +667,7 @@ check_PROGRAMS += v2v_unit_tests var_expander_tests + endif + + v2v_unit_tests_BOBJECTS = \ ++ $(top_builddir)/customize/firstboot.cmo \ + types.cmo \ + uefi.cmo \ + utils.cmo \ +diff --git a/v2v/windows.ml b/v2v/windows.ml +index 23d589b00..d83f77b7f 100644 +--- a/v2v/windows.ml ++++ b/v2v/windows.ml +@@ -45,3 +45,26 @@ and check_app { Guestfs.app2_name = name; + publisher =~ rex_avg_tech + + and (=~) str rex = PCRE.matches rex str ++ ++(* Unfortunately Powershell scripts cannot be directly executed ++ * (unless some system config changes are made which for other ++ * reasons we don't want to do) and so we have to run this via ++ * a regular batch file. ++ *) ++let install_firstboot_powershell g { Types.i_windows_systemroot; i_root } ++ filename code = ++ let tempdir = sprintf "%s/Temp" i_windows_systemroot in ++ g#mkdir_p tempdir; ++ let code = String.concat "\r\n" code ^ "\r\n" in ++ g#write (sprintf "%s/%s" tempdir filename) code; ++ ++ (* Powershell interpreter. Should we check this exists? XXX *) ++ let ps_exe = ++ i_windows_systemroot ^ ++ "\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" in ++ ++ (* Windows path to the Powershell script. *) ++ let ps_path = i_windows_systemroot ^ "\\Temp\\" ^ filename in ++ ++ let fb = sprintf "%s -ExecutionPolicy ByPass -file %s" ps_exe ps_path in ++ Firstboot.add_firstboot_script g i_root filename fb +diff --git a/v2v/windows.mli b/v2v/windows.mli +index 016ef2a78..6db7874b0 100644 +--- a/v2v/windows.mli ++++ b/v2v/windows.mli +@@ -21,3 +21,9 @@ + val detect_antivirus : Types.inspect -> bool + (** Return [true] if anti-virus (AV) software was detected in + this Windows guest. *) ++ ++val install_firstboot_powershell : Guestfs.guestfs -> Types.inspect -> ++ string -> string list -> unit ++(** [install_powershell_firstboot g inspect filename code] installs a ++ Powershell script (the lines of code) as a firstboot script in ++ the Windows VM. *) +-- +2.25.4 + diff --git a/SOURCES/0033-v2v-Copy-static-IP-address-information-over-for-Wind.patch b/SOURCES/0033-v2v-Copy-static-IP-address-information-over-for-Wind.patch new file mode 100644 index 0000000..62740d1 --- /dev/null +++ b/SOURCES/0033-v2v-Copy-static-IP-address-information-over-for-Wind.patch @@ -0,0 +1,423 @@ +From 70e2215cd1f660dbad5a336bb611ad1b9cf1e60d Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Tue, 4 Dec 2018 16:09:42 +0000 +Subject: [PATCH] v2v: Copy static IP address information over for Windows + guests (RHBZ#1626503). + +For Linux the guest itself remembers the IP address associated with +each MAC address. Thus it doesn't matter if the interface type +changes (ie. to virtio-net), because as long as we preserve the MAC +address the guest will use the same IP address or the same DHCP +configuration. + +However on Windows this association is not maintained by MAC address. +In fact the MAC address isn't saved anywhere in the guest registry. +(It seems instead this is likely done through PCI device type and +address which we don't record at the moment and is almost impossible +to preserve.) When a guest which doesn't use DHCP is migrated, the +guest sees the brand new virtio-net devices and doesn't know what to +do with them, and meanwhile the right static IPs are still associated +with the old and now-defunct interfaces in the registry. + +We cannot collect the required information from within the guest. +However we can collect it outside the tool by some other means +(eg. using VMware Tools APIs) and present this information to virt-v2v +which then writes it into the Windows guest at firstboot time. + +This commit adds the --mac ..:ip:.. sub-option which creates a +Powershell script to set network adapters at firstboot. An option +such as: + + --mac 00:0c:29:e6:3d:9d:ip:192.168.0.89,192.168.0.1,24,192.168.0.254 + +approximately turns into this script: + + # Wait for the netkvm (virtio-net) driver to become active. + $adapters = @() + While (-Not $adapters) { + Start-Sleep -Seconds 5 + $adapters = Get-NetAdapter -Physical | + Where DriverFileName -eq "netkvm.sys" + } + $mac_address = '00-0c-29-e6-3d-9d' + $ifindex = (Get-NetAdapter -Physical | + Where MacAddress -eq $mac_address).ifIndex + if ($ifindex) { + New-NetIPAddress -InterfaceIndex $ifindex + -IPAddress '192.168.0.89' + -DefaultGateway '192.168.0.1' + -PrefixLength 24 + Set-DnsClientServerAddress -InterfaceIndex $ifindex + -ServerAddresses ('192.168.0.254') + } + +Thanks: Brett Thurber for diagnosing the problem and suggesting paths +towards a fix. + +(cherry picked from commit dfd9fac7435cf2f9293961b6cc1fe316af4feebc) +--- + v2v/cmdline.ml | 41 ++++++++++++++++++----- + v2v/cmdline.mli | 1 + + v2v/convert_linux.ml | 2 +- + v2v/convert_windows.ml | 76 +++++++++++++++++++++++++++++++++++++++++- + v2v/modules_list.ml | 2 +- + v2v/modules_list.mli | 2 +- + v2v/types.ml | 8 +++++ + v2v/types.mli | 9 +++++ + v2v/v2v.ml | 7 ++-- + v2v/virt-v2v.pod | 18 ++++++++++ + 10 files changed, 150 insertions(+), 16 deletions(-) + +diff --git a/v2v/cmdline.ml b/v2v/cmdline.ml +index 4d390f249..686631271 100644 +--- a/v2v/cmdline.ml ++++ b/v2v/cmdline.ml +@@ -40,11 +40,12 @@ type cmdline = { + print_estimate : bool; + print_source : bool; + root_choice : root_choice; ++ static_ips : static_ip list; + ks : Tools_utils.key_store; + } + + (* Matches --mac command line parameters. *) +-let mac_re = PCRE.compile ~anchored:true "([[:xdigit:]]{2}:[[:xdigit:]]{2}:[[:xdigit:]]{2}:[[:xdigit:]]{2}:[[:xdigit:]]{2}:[[:xdigit:]]{2}):(network|bridge):(.*)" ++let mac_re = PCRE.compile ~anchored:true "([[:xdigit:]]{2}:[[:xdigit:]]{2}:[[:xdigit:]]{2}:[[:xdigit:]]{2}:[[:xdigit:]]{2}:[[:xdigit:]]{2}):(network|bridge|ip):(.*)" + + let parse_cmdline () = + let compressed = ref false in +@@ -97,6 +98,7 @@ let parse_cmdline () = + in + + let network_map = Networks.create () in ++ let static_ips = ref [] in + let add_network str = + match String.split ":" str with + | "", "" -> +@@ -119,11 +121,30 @@ let parse_cmdline () = + if not (PCRE.matches mac_re str) then + error (f_"cannot parse --mac \"%s\" parameter") str; + let mac = PCRE.sub 1 and out = PCRE.sub 3 in +- let vnet_type = +- match PCRE.sub 2 with +- | "network" -> Network | "bridge" -> Bridge +- | _ -> assert false in +- Networks.add_mac network_map mac vnet_type out ++ match PCRE.sub 2 with ++ | "network" -> ++ Networks.add_mac network_map mac Network out ++ | "bridge" -> ++ Networks.add_mac network_map mac Bridge out ++ | "ip" -> ++ let add if_mac_addr if_ip_address if_default_gateway ++ if_prefix_length if_nameservers = ++ List.push_back static_ips ++ { if_mac_addr; if_ip_address; if_default_gateway; ++ if_prefix_length; if_nameservers } ++ in ++ (match String.nsplit "," out with ++ | [] -> ++ error (f_"invalid --mac ip option") ++ | [ip] -> add mac ip None None [] ++ | [ip; gw] -> add mac ip (Some gw) None [] ++ | ip :: gw :: len :: nameservers -> ++ let len = ++ try int_of_string len with ++ | Failure _ -> error (f_"cannot parse --mac ip prefix length field as an integer: %s") len in ++ add mac ip (Some gw) (Some len) nameservers ++ ); ++ | _ -> assert false + in + + let no_trim_warning _ = +@@ -211,8 +232,8 @@ let parse_cmdline () = + s_"Input transport"; + [ L"in-place" ], Getopt.Set in_place, + s_"Only tune the guest in the input VM"; +- [ L"mac" ], Getopt.String ("mac:network|bridge:out", add_mac), +- s_"Map NIC to network or bridge"; ++ [ L"mac" ], Getopt.String ("mac:network|bridge|ip:out", add_mac), ++ s_"Map NIC to network or bridge or assign static IP"; + [ S 'n'; L"network" ], Getopt.String ("in:out", add_network), + s_"Map network ‘in’ to ‘out’"; + [ L"no-copy" ], Getopt.Clear do_copy, +@@ -335,6 +356,7 @@ read the man page virt-v2v(1). + let print_source = !print_source in + let qemu_boot = !qemu_boot in + let root_choice = !root_choice in ++ let static_ips = !static_ips in + + (* No arguments and machine-readable mode? Print out some facts + * about what this binary supports. +@@ -351,6 +373,7 @@ read the man page virt-v2v(1). + pr "in-place\n"; + pr "io/oo\n"; + pr "mac-option\n"; ++ pr "mac-ip-option\n"; + List.iter (pr "input:%s\n") (Modules_list.input_modules ()); + List.iter (pr "output:%s\n") (Modules_list.output_modules ()); + List.iter (pr "convert:%s\n") (Modules_list.convert_modules ()); +@@ -685,7 +708,7 @@ read the man page virt-v2v(1). + { + compressed; debug_overlays; do_copy; in_place; network_map; + output_alloc; output_format; output_name; +- print_estimate; print_source; root_choice; ++ print_estimate; print_source; root_choice; static_ips; + ks = opthandle.ks; + }, + input, output +diff --git a/v2v/cmdline.mli b/v2v/cmdline.mli +index 78601e191..a009e9888 100644 +--- a/v2v/cmdline.mli ++++ b/v2v/cmdline.mli +@@ -30,6 +30,7 @@ type cmdline = { + print_estimate : bool; + print_source : bool; + root_choice : Types.root_choice; ++ static_ips : Types.static_ip list; + ks : Tools_utils.key_store; + } + +diff --git a/v2v/convert_linux.ml b/v2v/convert_linux.ml +index f9e811c8d..1ada36115 100644 +--- a/v2v/convert_linux.ml ++++ b/v2v/convert_linux.ml +@@ -34,7 +34,7 @@ open Linux_kernels + module G = Guestfs + + (* The conversion function. *) +-let convert (g : G.guestfs) inspect source output rcaps = ++let convert (g : G.guestfs) inspect source output rcaps _ = + (*----------------------------------------------------------------------*) + (* Inspect the guest first. We already did some basic inspection in + * the common v2v.ml code, but that has to deal with generic guests +diff --git a/v2v/convert_windows.ml b/v2v/convert_windows.ml +index 1db3c0ea6..75e609d61 100644 +--- a/v2v/convert_windows.ml ++++ b/v2v/convert_windows.ml +@@ -38,7 +38,7 @@ module G = Guestfs + * time the Windows VM is booted on KVM. + *) + +-let convert (g : G.guestfs) inspect source output rcaps = ++let convert (g : G.guestfs) inspect source output rcaps static_ips = + (*----------------------------------------------------------------------*) + (* Inspect the Windows guest. *) + +@@ -228,6 +228,8 @@ let convert (g : G.guestfs) inspect source output rcaps = + Registry.with_hive_write g inspect.i_windows_software_hive + update_software_hive; + ++ configure_network_interfaces net_driver; ++ + fix_ntfs_heads (); + + fix_win_esp (); +@@ -603,6 +605,78 @@ if errorlevel 3010 exit /b 0 + | None -> + warning (f_"could not find registry key HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion") + ++ and configure_network_interfaces net_driver = ++ (* If we were asked to force network interfaces to have particular ++ * static IP addresses then it is done here by installing a ++ * Powershell script which runs at boot. ++ *) ++ if static_ips <> [] then ( ++ let psh_filename = "v2vnetcf.ps1" in ++ let psh = ref [] in ++ let add = List.push_back psh in ++ ++ add "# Uncomment this line for lots of debug output."; ++ add "# Set-PSDebug -Trace 1"; ++ add ""; ++ ++ (* If virtio-net was added to the registry, we must wait for ++ * it to be installed at runtime. ++ *) ++ if net_driver = Virtio_net then ( ++ add "# Wait for the netkvm (virtio-net) driver to become active."; ++ add "$adapters = @()"; ++ add "While (-Not $adapters) {"; ++ add " Start-Sleep -Seconds 5"; ++ add " $adapters = Get-NetAdapter -Physical | Where DriverFileName -eq \"netkvm.sys\""; ++ add " Write-Host \"adapters = '$adapters'\""; ++ add "}"; ++ add "" ++ ); ++ ++ List.iter ( ++ fun { if_mac_addr; if_ip_address; if_default_gateway; ++ if_prefix_length; if_nameservers } -> ++ add (sprintf "$mac_address = '%s'" ++ (String.replace if_mac_addr ":" "-")); ++ add "$ifindex = (Get-NetAdapter -Physical | Where MacAddress -eq $mac_address).ifIndex"; ++ add "if ($ifindex) {"; ++ ++ add " Write-Host \"setting IP address of adapter at $ifindex\""; ++ ++ (* New-NetIPAddress command *) ++ let args = ref [] in ++ List.push_back args "-InterfaceIndex"; ++ List.push_back args "$ifindex"; ++ List.push_back args "-IPAddress"; ++ List.push_back args (sprintf "'%s'" if_ip_address); ++ (match if_default_gateway with ++ | None -> () ++ | Some gw -> ++ List.push_back args "-DefaultGateway"; ++ List.push_back args (sprintf "'%s'" gw) ++ ); ++ (match if_prefix_length with ++ | None -> () ++ | Some len -> ++ List.push_back args "-PrefixLength"; ++ List.push_back args (string_of_int len) ++ ); ++ let cmd1 = "New-NetIPAddress " ^ String.concat " " !args in ++ add (" " ^ cmd1); ++ ++ (* Set-DnsClientServerAddress command *) ++ if if_nameservers <> [] then ( ++ add (sprintf " Set-DnsClientServerAddress -InterfaceIndex $ifindex -ServerAddresses (%s)" ++ (String.concat "," (List.map (sprintf "'%s'") if_nameservers))) ++ ); ++ add "}"; ++ add "" ++ ) static_ips; ++ ++ (* Install the Powershell script to run at firstboot. *) ++ Windows.install_firstboot_powershell g inspect psh_filename !psh ++ ) (* static_ips <> [] *) ++ + and fix_ntfs_heads () = + (* NTFS hardcodes the number of heads on the drive which created + it in the filesystem header. Modern versions of Windows +diff --git a/v2v/modules_list.ml b/v2v/modules_list.ml +index a0a74aaf2..76b3def5d 100644 +--- a/v2v/modules_list.ml ++++ b/v2v/modules_list.ml +@@ -38,7 +38,7 @@ type inspection_fn = Types.inspect -> bool + + type conversion_fn = + Guestfs.guestfs -> Types.inspect -> Types.source -> Types.output_settings -> +- Types.requested_guestcaps -> Types.guestcaps ++ Types.requested_guestcaps -> Types.static_ip list -> Types.guestcaps + + let convert_modules = ref [] + +diff --git a/v2v/modules_list.mli b/v2v/modules_list.mli +index 3e80d3e23..ad2024755 100644 +--- a/v2v/modules_list.mli ++++ b/v2v/modules_list.mli +@@ -34,7 +34,7 @@ type inspection_fn = Types.inspect -> bool + + type conversion_fn = + Guestfs.guestfs -> Types.inspect -> Types.source -> Types.output_settings -> +- Types.requested_guestcaps -> Types.guestcaps ++ Types.requested_guestcaps -> Types.static_ip list -> Types.guestcaps + + val register_convert_module : inspection_fn -> string -> conversion_fn -> unit + (** [register_convert_module inspect_fn name fn] registers a +diff --git a/v2v/types.ml b/v2v/types.ml +index 714b30014..4ba6117fd 100644 +--- a/v2v/types.ml ++++ b/v2v/types.ml +@@ -506,6 +506,14 @@ type root_choice = AskRoot | SingleRoot | FirstRoot | RootDev of string + + type output_allocation = Sparse | Preallocated + ++type static_ip = { ++ if_mac_addr : string; ++ if_ip_address : string; ++ if_default_gateway : string option; ++ if_prefix_length : int option; ++ if_nameservers : string list; ++} ++ + class virtual input = object + method precheck () = () + method virtual as_options : string +diff --git a/v2v/types.mli b/v2v/types.mli +index f595ab0ef..528d77965 100644 +--- a/v2v/types.mli ++++ b/v2v/types.mli +@@ -361,6 +361,15 @@ type root_choice = AskRoot | SingleRoot | FirstRoot | RootDev of string + type output_allocation = Sparse | Preallocated + (** Type of [-oa] (output allocation) option. *) + ++type static_ip = { ++ if_mac_addr : string; ++ if_ip_address : string; ++ if_default_gateway : string option; ++ if_prefix_length : int option; ++ if_nameservers : string list; ++} ++(** [--mac ..:ip:..] option. *) ++ + (** {2 Input object} + + This is subclassed for the various input [-i] options. +diff --git a/v2v/v2v.ml b/v2v/v2v.ml +index 63e809030..d7a868659 100644 +--- a/v2v/v2v.ml ++++ b/v2v/v2v.ml +@@ -133,7 +133,7 @@ let rec main () = + | In_place -> + rcaps_from_source source in + +- do_convert g inspect source output rcaps in ++ do_convert g inspect source output rcaps cmdline.static_ips in + + g#umount_all (); + +@@ -556,7 +556,7 @@ and estimate_target_size mpstats overlays = + ) + + (* Conversion. *) +-and do_convert g inspect source output rcaps = ++and do_convert g inspect source output rcaps interfaces = + (match inspect.i_product_name with + | "unknown" -> + message (f_"Converting the guest to run on KVM") +@@ -572,7 +572,8 @@ and do_convert g inspect source output rcaps = + debug "picked conversion module %s" conversion_name; + debug "requested caps: %s" (string_of_requested_guestcaps rcaps); + let guestcaps = +- convert g inspect source (output :> Types.output_settings) rcaps in ++ convert g inspect source (output :> Types.output_settings) rcaps ++ interfaces in + debug "%s" (string_of_guestcaps guestcaps); + + (* Did we manage to install virtio drivers? *) +diff --git a/v2v/virt-v2v.pod b/v2v/virt-v2v.pod +index 9a555c3be..0642d158f 100644 +--- a/v2v/virt-v2v.pod ++++ b/v2v/virt-v2v.pod +@@ -368,6 +368,24 @@ Map source NIC MAC address to a network or bridge. + + See L below. + ++=item B<--mac> aa:bb:cc:dd:ee:ffB<:ip:>ipaddr[,gw[,len[,ns,ns,...]]] ++ ++Force a particular interface (controlled by its MAC address) to have a ++static IP address after boot. ++ ++The fields in the parameter are: C is the IP address. C ++is the optional gateway IP address. C is the subnet mask length ++(an integer). The final parameters are zero or more nameserver IP ++addresses. ++ ++This option can be supplied zero or more times. ++ ++You only need to use this option for certain broken guests such as ++Windows which are unable to preserve MAC to static IP address mappings ++automatically. You don't need to use it if Windows is using DHCP. It ++is currently ignored for Linux guests since they do not have this ++problem. ++ + =item B<--machine-readable> + + =item B<--machine-readable>=format +-- +2.25.4 + diff --git a/SOURCES/0033-v2v-rhv-upload-plugin-Optimize-only-direct-upload.patch b/SOURCES/0033-v2v-rhv-upload-plugin-Optimize-only-direct-upload.patch deleted file mode 100644 index 755fdc9..0000000 --- a/SOURCES/0033-v2v-rhv-upload-plugin-Optimize-only-direct-upload.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 7b5ec5a6478276cec587c7d6a64b9a1ab26447b2 Mon Sep 17 00:00:00 2001 -From: Nir Soffer -Date: Sat, 30 Jun 2018 01:39:03 +0300 -Subject: [PATCH] v2v: rhv-upload-plugin: Optimize only direct upload - -The optimization to start the transfer on the local host makes sense -only when using the rhv-direct=true option. When using a proxy, let the -engine choose a host. - -(cherry picked from commit 891b5a0ec0f320acec0f06b64159eaf3dfbbfeaf) ---- - v2v/rhv-upload-plugin.py | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/v2v/rhv-upload-plugin.py b/v2v/rhv-upload-plugin.py -index 8e4052048..da309e288 100644 ---- a/v2v/rhv-upload-plugin.py -+++ b/v2v/rhv-upload-plugin.py -@@ -148,8 +148,8 @@ def open(readonly): - # Get a reference to the transfer service. - transfers_service = system_service.image_transfers_service() - -- # Create a new image transfer. -- host = find_host(connection) -+ # Create a new image transfer, using the local host is possible. -+ host = find_host(connection) if params['rhv_direct'] else None - transfer = transfers_service.add( - types.ImageTransfer( - disk = types.Disk(id = disk.id), --- -2.21.0 - diff --git a/SOURCES/0034-New-API-luks_uuid.patch b/SOURCES/0034-New-API-luks_uuid.patch new file mode 100644 index 0000000..37368da --- /dev/null +++ b/SOURCES/0034-New-API-luks_uuid.patch @@ -0,0 +1,87 @@ +From bcd376966fedca02a52ad61405e84de931a89899 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Fri, 29 Nov 2019 11:48:59 +0100 +Subject: [PATCH] New API: luks_uuid + +Return the UUID of a LUKS device. + +(cherry picked from commit 206ce8bbf1bc3332dc019e553d17d6a36f74b725) +--- + daemon/luks.c | 25 +++++++++++++++++++++++++ + generator/actions_core.ml | 8 ++++++++ + generator/proc_nr.ml | 1 + + lib/MAX_PROC_NR | 2 +- + 4 files changed, 35 insertions(+), 1 deletion(-) + +diff --git a/daemon/luks.c b/daemon/luks.c +index 5c48a91eb..d631cb100 100644 +--- a/daemon/luks.c ++++ b/daemon/luks.c +@@ -292,3 +292,28 @@ do_luks_kill_slot (const char *device, const char *key, int keyslot) + + return 0; + } ++ ++char * ++do_luks_uuid (const char *device) ++{ ++ const char *argv[MAX_ARGS]; ++ size_t i = 0; ++ ++ ADD_ARG (argv, i, "cryptsetup"); ++ ADD_ARG (argv, i, "luksUUID"); ++ ADD_ARG (argv, i, device); ++ ADD_ARG (argv, i, NULL); ++ ++ char *out = NULL; ++ CLEANUP_FREE char *err = NULL; ++ int r = commandv (&out, &err, (const char * const *) argv); ++ ++ if (r == -1) { ++ reply_with_error ("%s", err); ++ return NULL; ++ } ++ ++ trim (out); ++ ++ return out; ++} +diff --git a/generator/actions_core.ml b/generator/actions_core.ml +index 7b6568b90..deda483a9 100644 +--- a/generator/actions_core.ml ++++ b/generator/actions_core.ml +@@ -9728,4 +9728,12 @@ it is useful when you have added a new device or deleted an + existing device (such as when the C API + is used)." }; + ++ { defaults with ++ name = "luks_uuid"; added = (1, 41, 9); ++ style = RString (RPlainString, "uuid"), [String (Device, "device")], []; ++ optional = Some "luks"; ++ shortdesc = "get the UUID of a LUKS device"; ++ longdesc = "\ ++This returns the UUID of the LUKS device C." }; ++ + ] +diff --git a/generator/proc_nr.ml b/generator/proc_nr.ml +index efa8c5d21..11a557076 100644 +--- a/generator/proc_nr.ml ++++ b/generator/proc_nr.ml +@@ -514,6 +514,7 @@ let proc_nr = [ + 504, "part_get_gpt_attributes"; + 505, "f2fs_expand"; + 506, "lvm_scan"; ++507, "luks_uuid"; + ] + + (* End of list. If adding a new entry, add it at the end of the list +diff --git a/lib/MAX_PROC_NR b/lib/MAX_PROC_NR +index 80e3e6eab..055b6671a 100644 +--- a/lib/MAX_PROC_NR ++++ b/lib/MAX_PROC_NR +@@ -1 +1 @@ +-506 ++507 +-- +2.25.4 + diff --git a/SOURCES/0034-v2v-rhv-plugin-find-suitable-host-RHBZ-1596810-RHBZ-.patch b/SOURCES/0034-v2v-rhv-plugin-find-suitable-host-RHBZ-1596810-RHBZ-.patch deleted file mode 100644 index 2d0ccf8..0000000 --- a/SOURCES/0034-v2v-rhv-plugin-find-suitable-host-RHBZ-1596810-RHBZ-.patch +++ /dev/null @@ -1,61 +0,0 @@ -From e1401de974b6ac6d3e6e94e774f24a9b74f806f2 Mon Sep 17 00:00:00 2001 -From: Daniel Erez -Date: Thu, 5 Jul 2018 20:23:35 +0300 -Subject: [PATCH] v2v: rhv plugin - find suitable host (RHBZ#1596810) - (RHBZ#1596851) - -For direct upload, a suitable host must be in status 'Up' -and belong to the same datacenter as the created disk. -Added these criteria to the host search query. - -(cherry picked from commit 4ed1bc5a79a77ad3a620b339f9ac2ecc8df6fd03) ---- - v2v/rhv-upload-plugin.py | 28 ++++++++++++++++++++++++---- - 1 file changed, 24 insertions(+), 4 deletions(-) - -diff --git a/v2v/rhv-upload-plugin.py b/v2v/rhv-upload-plugin.py -index da309e288..931fcfaa2 100644 ---- a/v2v/rhv-upload-plugin.py -+++ b/v2v/rhv-upload-plugin.py -@@ -69,14 +69,34 @@ def find_host(connection): - - debug("hw_id = %r" % vdsm_id) - -- hosts_service = connection.system_service().hosts_service() -+ system_service = connection.system_service() -+ storage_name = params['output_storage'] -+ data_centers = system_service.data_centers_service().list( -+ search='storage=%s' % storage_name, -+ case_sensitive=False, -+ ) -+ if len(data_centers) == 0: -+ # The storage domain is not attached to a datacenter -+ # (shouldn't happen, would fail on disk creation). -+ debug("storange domain (%s) is not attached to a DC" % storage_name) -+ return None -+ -+ datacenter = data_centers[0] -+ debug("datacenter = %s" % datacenter.name) -+ -+ hosts_service = system_service.hosts_service() - hosts = hosts_service.list( -- search="hw_id=%s" % vdsm_id, -+ search="hw_id=%s and datacenter=%s and status=Up" % (vdsm_id, datacenter.name), - case_sensitive=False, - ) - if len(hosts) == 0: -- # This oVirt host is not registered with engine. -- debug("cannot find host with hw_id=%r, using any host" % vdsm_id) -+ # Couldn't find a host that's fulfilling the following criteria: -+ # - 'hw_id' equals to 'vdsm_id' -+ # - Its status is 'Up' -+ # - Belongs to the storage domain's datacenter -+ debug("cannot find a running host with hw_id=%r, " \ -+ "that belongs to datacenter '%s', " \ -+ "using any host" % (vdsm_id, datacenter.name)) - return None - - host = hosts[0] --- -2.21.0 - diff --git a/SOURCES/0035-options-Fix-segfault-when-multiple-key-parameters-gi.patch b/SOURCES/0035-options-Fix-segfault-when-multiple-key-parameters-gi.patch new file mode 100644 index 0000000..ed0daf9 --- /dev/null +++ b/SOURCES/0035-options-Fix-segfault-when-multiple-key-parameters-gi.patch @@ -0,0 +1,47 @@ +From 7f12a3ddad2b735dc6d06b7b3ef67aacc57defe2 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Tue, 12 Nov 2019 18:15:44 +0000 +Subject: [PATCH] options: Fix segfault when multiple --key parameters given. + +Easily reproducible using: + + $ guestfish --key dev1:key:key1 --key dev2:key:key2 + +causing this stack trace (or others depending on where the memory +corruption was caught): + + Program received signal SIGABRT, Aborted. + 0x00007ffff7905625 in raise () from /lib64/libc.so.6 + (gdb) bt + #0 0x00007ffff7905625 in raise () from /lib64/libc.so.6 + #1 0x00007ffff78ee8d9 in abort () from /lib64/libc.so.6 + #2 0x00007ffff79494af in __libc_message () from /lib64/libc.so.6 + #3 0x00007ffff7950a6c in malloc_printerr () from /lib64/libc.so.6 + #4 0x00007ffff79528d0 in _int_free () from /lib64/libc.so.6 + #5 0x00005555555bdd6e in free_key_store () + #6 0x0000555555589027 in main () + (gdb) quit + +(cherry picked from commit 8c42f772614b44a8cb974afa904ec9f518431ab2 +in libguestfs-common) +--- + common/options/keys.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/common/options/keys.c b/common/options/keys.c +index 7f689866b..f783066ff 100644 +--- a/common/options/keys.c ++++ b/common/options/keys.c +@@ -216,7 +216,8 @@ key_store_import_key (struct key_store *ks, const struct key_store_key *key) + } + assert (ks != NULL); + +- new_keys = realloc (ks->keys, sizeof (*ks->keys) + 1); ++ new_keys = realloc (ks->keys, ++ (ks->nr_keys + 1) * sizeof (struct key_store_key)); + if (!new_keys) + error (EXIT_FAILURE, errno, "realloc"); + +-- +2.25.4 + diff --git a/SOURCES/0035-v2v-change-QXL-ResourceType-in-OVirt-flavour-RHBZ-15.patch b/SOURCES/0035-v2v-change-QXL-ResourceType-in-OVirt-flavour-RHBZ-15.patch deleted file mode 100644 index e0973ae..0000000 --- a/SOURCES/0035-v2v-change-QXL-ResourceType-in-OVirt-flavour-RHBZ-15.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 77604b91ec01ddd7961e69b70727b8e8c6e4c50b Mon Sep 17 00:00:00 2001 -From: Pino Toscano -Date: Fri, 13 Jul 2018 13:24:07 +0200 -Subject: [PATCH] v2v: change QXL ResourceType in OVirt flavour (RHBZ#1598715) - -Due to a conflict with the IDs of the OVF standard, and the existing -implementation in ovirt-engine, the ID of QXL devices changed to a -different value. - -As a consequence, change the ResourceType of QXL devices, but only in -OVirt flavour to avoid breaking vdsm mode. - -See: https://bugzilla.redhat.com/show_bug.cgi?id=1598715#c5 -(cherry picked from commit aa9e18f6d1fd503822dfd2124b92a2c67704c4c1) ---- - v2v/create_ovf.ml | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/v2v/create_ovf.ml b/v2v/create_ovf.ml -index 9e0c772fd..5db239d66 100644 ---- a/v2v/create_ovf.ml -+++ b/v2v/create_ovf.ml -@@ -643,10 +643,14 @@ let rec create_ovf source targets guestcaps inspect - * See RHBZ#1213701 and RHBZ#1211231 for the reasoning - * behind that. - *) -+ let qxl_resourcetype = -+ match ovf_flavour with -+ | OVirt -> 32768 (* RHBZ#1598715 *) -+ | RHVExportStorageDomain -> 20 in - e "Item" [] [ - e "rasd:Caption" [] [PCData "Graphical Controller"]; - e "rasd:InstanceId" [] [PCData (uuidgen ())]; -- e "rasd:ResourceType" [] [PCData "20"]; -+ e "rasd:ResourceType" [] [PCData (string_of_int qxl_resourcetype)]; - e "Type" [] [PCData "video"]; - e "rasd:VirtualQuantity" [] [PCData "1"]; - e "rasd:Device" [] [PCData "qxl"]; --- -2.21.0 - diff --git a/SOURCES/0036-options-Simplify-selector-parsing-for-key-options.patch b/SOURCES/0036-options-Simplify-selector-parsing-for-key-options.patch new file mode 100644 index 0000000..a157bbf --- /dev/null +++ b/SOURCES/0036-options-Simplify-selector-parsing-for-key-options.patch @@ -0,0 +1,85 @@ +From d2ca3f2f9bd9f26cacef2cf2a38e8ac18484d8e4 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Tue, 26 Nov 2019 12:12:45 +0000 +Subject: [PATCH] options: Simplify selector parsing for --key options. + +Refactor this code to use guestfs_int_split_string function which +slightly simplifies it. This should have no effect. + +(cherry picked from commit 530d0beef74d48617717463a5b585f21e2ed62be +in libguestfs-common) +--- + common/options/keys.c | 35 ++++++++++++++--------------------- + 1 file changed, 14 insertions(+), 21 deletions(-) + +diff --git a/common/options/keys.c b/common/options/keys.c +index f783066ff..74b549731 100644 +--- a/common/options/keys.c ++++ b/common/options/keys.c +@@ -153,49 +153,42 @@ get_key (struct key_store *ks, const char *device) + } + + struct key_store * +-key_store_add_from_selector (struct key_store *ks, const char *selector_orig) ++key_store_add_from_selector (struct key_store *ks, const char *selector) + { +- CLEANUP_FREE char *selector = strdup (selector_orig); +- const char *elem; +- char *saveptr; ++ CLEANUP_FREE_STRING_LIST char **fields = ++ guestfs_int_split_string (':', selector); + struct key_store_key key; + +- if (!selector) +- error (EXIT_FAILURE, errno, "strdup"); ++ if (!fields) ++ error (EXIT_FAILURE, errno, "guestfs_int_split_string"); + +- /* 1: device */ +- elem = strtok_r (selector, ":", &saveptr); +- if (!elem) { ++ if (guestfs_int_count_strings (fields) != 3) { + invalid_selector: +- error (EXIT_FAILURE, 0, "invalid selector for --key: %s", selector_orig); ++ error (EXIT_FAILURE, 0, "invalid selector for --key: %s", selector); + } +- key.device = strdup (elem); ++ ++ /* 1: device */ ++ key.device = strdup (fields[0]); + if (!key.device) + error (EXIT_FAILURE, errno, "strdup"); + + /* 2: key type */ +- elem = strtok_r (NULL, ":", &saveptr); +- if (!elem) +- goto invalid_selector; +- else if (STREQ (elem, "key")) ++ if (STREQ (fields[1], "key")) + key.type = key_string; +- else if (STREQ (elem, "file")) ++ else if (STREQ (fields[1], "file")) + key.type = key_file; + else + goto invalid_selector; + + /* 3: actual key */ +- elem = strtok_r (NULL, ":", &saveptr); +- if (!elem) +- goto invalid_selector; + switch (key.type) { + case key_string: +- key.string.s = strdup (elem); ++ key.string.s = strdup (fields[2]); + if (!key.string.s) + error (EXIT_FAILURE, errno, "strdup"); + break; + case key_file: +- key.file.name = strdup (elem); ++ key.file.name = strdup (fields[2]); + if (!key.file.name) + error (EXIT_FAILURE, errno, "strdup"); + break; +-- +2.25.4 + diff --git a/SOURCES/0036-v2v-o-rhv-upload-check-for-ovirtsdk4-RHBZ-1601943.patch b/SOURCES/0036-v2v-o-rhv-upload-check-for-ovirtsdk4-RHBZ-1601943.patch deleted file mode 100644 index 33d7fbd..0000000 --- a/SOURCES/0036-v2v-o-rhv-upload-check-for-ovirtsdk4-RHBZ-1601943.patch +++ /dev/null @@ -1,40 +0,0 @@ -From bb6b81861e72535f57bdc8e9a3457807f21ad28c Mon Sep 17 00:00:00 2001 -From: Pino Toscano -Date: Tue, 17 Jul 2018 17:12:38 +0200 -Subject: [PATCH] v2v: -o rhv-upload: check for ovirtsdk4 (RHBZ#1601943) - -Check earlier whether the ovirtsdk4 Python can be imported correctly, -to avoid errors later on during the migration. ---- - v2v/output_rhv_upload.ml | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/v2v/output_rhv_upload.ml b/v2v/output_rhv_upload.ml -index 0152b8d5a..63fa2411a 100644 ---- a/v2v/output_rhv_upload.ml -+++ b/v2v/output_rhv_upload.ml -@@ -126,6 +126,13 @@ class output_rhv_upload output_alloc output_conn - python3 - in - -+ (* Check that the 'ovirtsdk4' Python module is available. *) -+ let error_unless_ovirtsdk4_module_available () = -+ let res = run_command [ python3; "-c"; "import ovirtsdk4" ] in -+ if res <> 0 then -+ error (f_"the Python module ‘ovirtsdk4’ could not be loaded, is it installed? See previous messages for problems.") -+ in -+ - (* Check that nbdkit is available and new enough. *) - let error_unless_nbdkit_working () = - if 0 <> Sys.command "nbdkit --version >/dev/null" then -@@ -231,6 +238,7 @@ object - - method precheck () = - error_unless_python_binary_on_path (); -+ error_unless_ovirtsdk4_module_available (); - error_unless_nbdkit_working (); - error_unless_nbdkit_python3_working (); - error_unless_output_alloc_sparse (); --- -2.21.0 - diff --git a/SOURCES/0037-options-Allow-multiple-key-parameters.patch b/SOURCES/0037-options-Allow-multiple-key-parameters.patch new file mode 100644 index 0000000..080c6c4 --- /dev/null +++ b/SOURCES/0037-options-Allow-multiple-key-parameters.patch @@ -0,0 +1,181 @@ +From d3c6f71eed46df3f9ec376359433d9c4b9830860 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Tue, 12 Nov 2019 17:50:17 +0000 +Subject: [PATCH] options: Allow multiple --key parameters. + +This allows multiple --key parameters on the command line to match a +single device. For example: + + tool --key /dev/sda1:key:trykey1 --key /dev/sda1:key:trykey2 + +would try "trykey1" and "trykey2" against /dev/sda1. + +(cherry picked from commit c10c8baedb88e7c2988a01b70fc5f81fa8e4885c +in libguestfs-common) +--- + common/options/decrypt.c | 37 +++++++++++++++++++++++++-------- + common/options/keys.c | 45 +++++++++++++++++++++++++++++++--------- + common/options/options.h | 6 ++++-- + 3 files changed, 67 insertions(+), 21 deletions(-) + +diff --git a/common/options/decrypt.c b/common/options/decrypt.c +index 234163d8c..3511d9fe9 100644 +--- a/common/options/decrypt.c ++++ b/common/options/decrypt.c +@@ -26,6 +26,9 @@ + #include + #include + #include ++#include ++#include ++#include + + #include "c-ctype.h" + +@@ -74,21 +77,37 @@ inspect_do_decrypt (guestfs_h *g, struct key_store *ks) + if (partitions == NULL) + exit (EXIT_FAILURE); + +- int need_rescan = 0; +- size_t i; ++ int need_rescan = 0, r; ++ size_t i, j; ++ + for (i = 0; partitions[i] != NULL; ++i) { + CLEANUP_FREE char *type = guestfs_vfs_type (g, partitions[i]); + if (type && STREQ (type, "crypto_LUKS")) { + char mapname[32]; + make_mapname (partitions[i], mapname, sizeof mapname); + +- CLEANUP_FREE char *key = get_key (ks, partitions[i]); +- /* XXX Should we call guestfs_luks_open_ro if readonly flag +- * is set? This might break 'mount_ro'. +- */ +- if (guestfs_luks_open (g, partitions[i], key, mapname) == -1) +- exit (EXIT_FAILURE); +- ++ CLEANUP_FREE_STRING_LIST char **keys = get_keys (ks, partitions[i]); ++ assert (guestfs_int_count_strings (keys) > 0); ++ ++ /* Try each key in turn. */ ++ for (j = 0; keys[j] != NULL; ++j) { ++ /* XXX Should we call guestfs_luks_open_ro if readonly flag ++ * is set? This might break 'mount_ro'. ++ */ ++ guestfs_push_error_handler (g, NULL, NULL); ++ r = guestfs_luks_open (g, partitions[i], keys[j], mapname); ++ guestfs_pop_error_handler (g); ++ if (r == 0) ++ goto opened; ++ } ++ error (EXIT_FAILURE, 0, ++ _("could not find key to open LUKS encrypted %s.\n\n" ++ "Try using --key on the command line.\n\n" ++ "Original error: %s (%d)"), ++ partitions[i], guestfs_last_error (g), ++ guestfs_last_errno (g)); ++ ++ opened: + need_rescan = 1; + } + } +diff --git a/common/options/keys.c b/common/options/keys.c +index 74b549731..782bdb67f 100644 +--- a/common/options/keys.c ++++ b/common/options/keys.c +@@ -121,15 +121,32 @@ read_first_line_from_file (const char *filename) + return ret; + } + +-char * +-get_key (struct key_store *ks, const char *device) ++/* Return the key(s) matching this particular device from the ++ * keystore. There may be multiple. If none are read from the ++ * keystore, ask the user. ++ */ ++char ** ++get_keys (struct key_store *ks, const char *device) + { +- size_t i; ++ size_t i, j, len; ++ char **r; ++ char *s; ++ ++ /* We know the returned list must have at least one element and not ++ * more than ks->nr_keys. ++ */ ++ len = 1; ++ if (ks) ++ len = MIN (1, ks->nr_keys); ++ r = calloc (len+1, sizeof (char *)); ++ if (r == NULL) ++ error (EXIT_FAILURE, errno, "calloc"); ++ ++ j = 0; + + if (ks) { + for (i = 0; i < ks->nr_keys; ++i) { + struct key_store_key *key = &ks->keys[i]; +- char *s; + + if (STRNEQ (key->device, device)) + continue; +@@ -139,17 +156,25 @@ get_key (struct key_store *ks, const char *device) + s = strdup (key->string.s); + if (!s) + error (EXIT_FAILURE, errno, "strdup"); +- return s; ++ r[j++] = s; ++ break; + case key_file: +- return read_first_line_from_file (key->file.name); ++ s = read_first_line_from_file (key->file.name); ++ r[j++] = s; ++ break; + } +- +- /* Key not found in the key store, ask the user for it. */ +- break; + } + } + +- return read_key (device); ++ if (j == 0) { ++ /* Key not found in the key store, ask the user for it. */ ++ s = read_key (device); ++ if (!s) ++ error (EXIT_FAILURE, 0, _("could not read key from user")); ++ r[0] = s; ++ } ++ ++ return r; + } + + struct key_store * +diff --git a/common/options/options.h b/common/options/options.h +index 6fadf1e76..510e8a8a9 100644 +--- a/common/options/options.h ++++ b/common/options/options.h +@@ -104,7 +104,9 @@ struct mp { + + /* A key in the key store. */ + struct key_store_key { +- /* The device this key refers to. */ ++ /* The device this key refers to. There may be multiple matching ++ * devices in the list. ++ */ + char *device; + + enum { +@@ -146,7 +148,7 @@ extern void print_inspect_prompt (void); + + /* in key.c */ + extern char *read_key (const char *param); +-extern char *get_key (struct key_store *ks, const char *device); ++extern char **get_keys (struct key_store *ks, const char *device); + extern struct key_store *key_store_add_from_selector (struct key_store *ks, const char *selector); + extern struct key_store *key_store_import_key (struct key_store *ks, const struct key_store_key *key); + extern void free_key_store (struct key_store *ks); +-- +2.25.4 + diff --git a/SOURCES/0037-v2v-rhv-plugin-fix-DC-search-string.patch b/SOURCES/0037-v2v-rhv-plugin-fix-DC-search-string.patch deleted file mode 100644 index 2b19997..0000000 --- a/SOURCES/0037-v2v-rhv-plugin-fix-DC-search-string.patch +++ /dev/null @@ -1,29 +0,0 @@ -From c0f9ab66655ec5ca3f065357d6797d0061f04fe0 Mon Sep 17 00:00:00 2001 -From: Daniel Erez -Date: Tue, 24 Jul 2018 19:16:10 +0300 -Subject: [PATCH] v2v: rhv plugin - fix DC search string - -Search for DC by 'storage.name=' to make it explicit. -I.e. "storage=" uses regex, so similar names can be -found in the search query. For example, searching for -a domain named FCSD, will find FCSD1 as well. ---- - v2v/rhv-upload-plugin.py | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/v2v/rhv-upload-plugin.py b/v2v/rhv-upload-plugin.py -index 931fcfaa2..8274f1ee1 100644 ---- a/v2v/rhv-upload-plugin.py -+++ b/v2v/rhv-upload-plugin.py -@@ -72,7 +72,7 @@ def find_host(connection): - system_service = connection.system_service() - storage_name = params['output_storage'] - data_centers = system_service.data_centers_service().list( -- search='storage=%s' % storage_name, -+ search='storage.name=%s' % storage_name, - case_sensitive=False, - ) - if len(data_centers) == 0: --- -2.21.0 - diff --git a/SOURCES/0038-options-rename-key.device-as-key.id.patch b/SOURCES/0038-options-rename-key.device-as-key.id.patch new file mode 100644 index 0000000..667cdf5 --- /dev/null +++ b/SOURCES/0038-options-rename-key.device-as-key.id.patch @@ -0,0 +1,437 @@ +From 3afce3e84c79d7fbca4d6eeb76f237090c5528c9 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Fri, 29 Nov 2019 12:06:20 +0100 +Subject: [PATCH] options: rename key.device as key.id + +In the future it will be also something else other than the device name. + +(cherry picked from commit c863ee5e1df5e1eca7ad6821bd2db3796277a6bd +in libguestfs-common) + +PT: the documentation was amended manually. +--- + cat/virt-cat.pod | 7 ++++--- + cat/virt-log.pod | 7 ++++--- + cat/virt-ls.pod | 7 ++++--- + cat/virt-tail.pod | 7 ++++--- + common/mltools/tools_utils-c.c | 4 ++-- + common/options/keys.c | 8 ++++---- + common/options/options.h | 8 +++++--- + customize/virt-customize.pod | 7 ++++--- + diff/virt-diff.pod | 7 ++++--- + edit/virt-edit.pod | 7 ++++--- + fish/guestfish.pod | 7 ++++--- + fuse/guestmount.pod | 7 ++++--- + get-kernel/virt-get-kernel.pod | 7 ++++--- + inspector/virt-inspector.pod | 7 ++++--- + sparsify/virt-sparsify.pod | 7 ++++--- + sysprep/virt-sysprep.pod | 7 ++++--- + v2v/virt-v2v.pod | 7 ++++--- + 17 files changed, 67 insertions(+), 51 deletions(-) + +diff --git a/cat/virt-cat.pod b/cat/virt-cat.pod +index 745d4a4b6..b0301d636 100644 +--- a/cat/virt-cat.pod ++++ b/cat/virt-cat.pod +@@ -124,15 +124,16 @@ security problem with malicious guests (CVE-2010-3851). + =item B<--key> SELECTOR + + Specify a key for LUKS, to automatically open a LUKS device when using +-the inspection. C can be in one of the following formats: ++the inspection. C must be the libguestfs device name of the LUKS ++device. + + =over 4 + +-=item B<--key> C:key:KEY_STRING ++=item B<--key> C:key:KEY_STRING + + Use the specified C as passphrase. + +-=item B<--key> C:file:FILENAME ++=item B<--key> C:file:FILENAME + + Read the passphrase from F. + +diff --git a/cat/virt-log.pod b/cat/virt-log.pod +index 8de000c5f..0d447b3b5 100644 +--- a/cat/virt-log.pod ++++ b/cat/virt-log.pod +@@ -108,15 +108,16 @@ security problem with malicious guests (CVE-2010-3851). + =item B<--key> SELECTOR + + Specify a key for LUKS, to automatically open a LUKS device when using +-the inspection. C can be in one of the following formats: ++the inspection. C must be the libguestfs device name of the LUKS ++device. + + =over 4 + +-=item B<--key> C:key:KEY_STRING ++=item B<--key> C:key:KEY_STRING + + Use the specified C as passphrase. + +-=item B<--key> C:file:FILENAME ++=item B<--key> C:file:FILENAME + + Read the passphrase from F. + +diff --git a/cat/virt-ls.pod b/cat/virt-ls.pod +index 8d6a9fe37..de02a473d 100644 +--- a/cat/virt-ls.pod ++++ b/cat/virt-ls.pod +@@ -355,15 +355,16 @@ L above. + =item B<--key> SELECTOR + + Specify a key for LUKS, to automatically open a LUKS device when using +-the inspection. C can be in one of the following formats: ++the inspection. C must be the libguestfs device name of the LUKS ++device. + + =over 4 + +-=item B<--key> C:key:KEY_STRING ++=item B<--key> C:key:KEY_STRING + + Use the specified C as passphrase. + +-=item B<--key> C:file:FILENAME ++=item B<--key> C:file:FILENAME + + Read the passphrase from F. + +diff --git a/cat/virt-tail.pod b/cat/virt-tail.pod +index cf8700d1a..f00384f5d 100644 +--- a/cat/virt-tail.pod ++++ b/cat/virt-tail.pod +@@ -126,15 +126,16 @@ security problem with malicious guests (CVE-2010-3851). + =item B<--key> SELECTOR + + Specify a key for LUKS, to automatically open a LUKS device when using +-the inspection. C can be in one of the following formats: ++the inspection. C must be the libguestfs device name of the LUKS ++device. + + =over 4 + +-=item B<--key> C:key:KEY_STRING ++=item B<--key> C:key:KEY_STRING + + Use the specified C as passphrase. + +-=item B<--key> C:file:FILENAME ++=item B<--key> C:file:FILENAME + + Read the passphrase from F. + +diff --git a/common/mltools/tools_utils-c.c b/common/mltools/tools_utils-c.c +index 3b80091c0..6c43b8d74 100644 +--- a/common/mltools/tools_utils-c.c ++++ b/common/mltools/tools_utils-c.c +@@ -57,8 +57,8 @@ guestfs_int_mllib_inspect_decrypt (value gv, value gpv, value keysv) + struct key_store_key key; + + elemv = Field (keysv, 0); +- key.device = strdup (String_val (Field (elemv, 0))); +- if (!key.device) ++ key.id = strdup (String_val (Field (elemv, 0))); ++ if (!key.id) + caml_raise_out_of_memory (); + + v = Field (elemv, 1); +diff --git a/common/options/keys.c b/common/options/keys.c +index 782bdb67f..7c391acde 100644 +--- a/common/options/keys.c ++++ b/common/options/keys.c +@@ -148,7 +148,7 @@ get_keys (struct key_store *ks, const char *device) + for (i = 0; i < ks->nr_keys; ++i) { + struct key_store_key *key = &ks->keys[i]; + +- if (STRNEQ (key->device, device)) ++ if (STRNEQ (key->id, device)) + continue; + + switch (key->type) { +@@ -193,8 +193,8 @@ key_store_add_from_selector (struct key_store *ks, const char *selector) + } + + /* 1: device */ +- key.device = strdup (fields[0]); +- if (!key.device) ++ key.id = strdup (fields[0]); ++ if (!key.id) + error (EXIT_FAILURE, errno, "strdup"); + + /* 2: key type */ +@@ -265,6 +265,6 @@ free_key_store (struct key_store *ks) + free (key->file.name); + break; + } +- free (key->device); ++ free (key->id); + } + } +diff --git a/common/options/options.h b/common/options/options.h +index 510e8a8a9..b83a92b06 100644 +--- a/common/options/options.h ++++ b/common/options/options.h +@@ -104,10 +104,12 @@ struct mp { + + /* A key in the key store. */ + struct key_store_key { +- /* The device this key refers to. There may be multiple matching +- * devices in the list. ++ /* An ID for the device this key refers to. It must be the libguestfs ++ * device name. ++ * ++ * There may be multiple matching devices in the list. + */ +- char *device; ++ char *id; + + enum { + key_string, /* key specified as string */ +diff --git a/customize/virt-customize.pod b/customize/virt-customize.pod +index d1b568040..491606591 100644 +--- a/customize/virt-customize.pod ++++ b/customize/virt-customize.pod +@@ -141,15 +141,16 @@ security problem with malicious guests (CVE-2010-3851). + =item B<--key> SELECTOR + + Specify a key for LUKS, to automatically open a LUKS device when using +-the inspection. C can be in one of the following formats: ++the inspection. C must be the libguestfs device name of the LUKS ++device. + + =over 4 + +-=item B<--key> C:key:KEY_STRING ++=item B<--key> C:key:KEY_STRING + + Use the specified C as passphrase. + +-=item B<--key> C:file:FILENAME ++=item B<--key> C:file:FILENAME + + Read the passphrase from F. + +diff --git a/diff/virt-diff.pod b/diff/virt-diff.pod +index 36ee10ced..22658072d 100644 +--- a/diff/virt-diff.pod ++++ b/diff/virt-diff.pod +@@ -169,15 +169,16 @@ Display file sizes in human-readable format. + =item B<--key> SELECTOR + + Specify a key for LUKS, to automatically open a LUKS device when using +-the inspection. C can be in one of the following formats: ++the inspection. C must be the libguestfs device name of the LUKS ++device. + + =over 4 + +-=item B<--key> C:key:KEY_STRING ++=item B<--key> C:key:KEY_STRING + + Use the specified C as passphrase. + +-=item B<--key> C:file:FILENAME ++=item B<--key> C:file:FILENAME + + Read the passphrase from F. + +diff --git a/edit/virt-edit.pod b/edit/virt-edit.pod +index 3cb3ce6da..5a63cd05f 100644 +--- a/edit/virt-edit.pod ++++ b/edit/virt-edit.pod +@@ -156,15 +156,16 @@ security problem with malicious guests (CVE-2010-3851). + =item B<--key> SELECTOR + + Specify a key for LUKS, to automatically open a LUKS device when using +-the inspection. C can be in one of the following formats: ++the inspection. C must be the libguestfs device name of the LUKS ++device. + + =over 4 + +-=item B<--key> C:key:KEY_STRING ++=item B<--key> C:key:KEY_STRING + + Use the specified C as passphrase. + +-=item B<--key> C:file:FILENAME ++=item B<--key> C:file:FILENAME + + Read the passphrase from F. + +diff --git a/fish/guestfish.pod b/fish/guestfish.pod +index 06644c5b8..ccb57b159 100644 +--- a/fish/guestfish.pod ++++ b/fish/guestfish.pod +@@ -283,15 +283,16 @@ were found. + =item B<--key> SELECTOR + + Specify a key for LUKS, to automatically open a LUKS device when using +-the inspection. C can be in one of the following formats: ++the inspection. C must be the libguestfs device name of the LUKS ++device. + + =over 4 + +-=item B<--key> C:key:KEY_STRING ++=item B<--key> C:key:KEY_STRING + + Use the specified C as passphrase. + +-=item B<--key> C:file:FILENAME ++=item B<--key> C:file:FILENAME + + Read the passphrase from F. + +diff --git a/fuse/guestmount.pod b/fuse/guestmount.pod +index 9319d093c..d9e957b8b 100644 +--- a/fuse/guestmount.pod ++++ b/fuse/guestmount.pod +@@ -249,15 +249,16 @@ mounted on the real virtual machine. + =item B<--key> SELECTOR + + Specify a key for LUKS, to automatically open a LUKS device when using +-the inspection. C can be in one of the following formats: ++the inspection. C must be the libguestfs device name of the LUKS ++device. + + =over 4 + +-=item B<--key> C:key:KEY_STRING ++=item B<--key> C:key:KEY_STRING + + Use the specified C as passphrase. + +-=item B<--key> C:file:FILENAME ++=item B<--key> C:file:FILENAME + + Read the passphrase from F. + +diff --git a/get-kernel/virt-get-kernel.pod b/get-kernel/virt-get-kernel.pod +index 3802412e2..f0ace2d6d 100644 +--- a/get-kernel/virt-get-kernel.pod ++++ b/get-kernel/virt-get-kernel.pod +@@ -92,15 +92,16 @@ security problem with malicious guests (CVE-2010-3851). + =item B<--key> SELECTOR + + Specify a key for LUKS, to automatically open a LUKS device when using +-the inspection. C can be in one of the following formats: ++the inspection. C must be the libguestfs device name of the LUKS ++device. + + =over 4 + +-=item B<--key> C:key:KEY_STRING ++=item B<--key> C:key:KEY_STRING + + Use the specified C as passphrase. + +-=item B<--key> C:file:FILENAME ++=item B<--key> C:file:FILENAME + + Read the passphrase from F. + +diff --git a/inspector/virt-inspector.pod b/inspector/virt-inspector.pod +index 98b278f26..eac9dc3cd 100644 +--- a/inspector/virt-inspector.pod ++++ b/inspector/virt-inspector.pod +@@ -117,15 +117,16 @@ ensure the format is always specified. + =item B<--key> SELECTOR + + Specify a key for LUKS, to automatically open a LUKS device when using +-the inspection. C can be in one of the following formats: ++the inspection. C must be the libguestfs device name of the LUKS ++device. + + =over 4 + +-=item B<--key> C:key:KEY_STRING ++=item B<--key> C:key:KEY_STRING + + Use the specified C as passphrase. + +-=item B<--key> C:file:FILENAME ++=item B<--key> C:file:FILENAME + + Read the passphrase from F. + +diff --git a/sparsify/virt-sparsify.pod b/sparsify/virt-sparsify.pod +index 3f5f9995f..cf7970a5f 100644 +--- a/sparsify/virt-sparsify.pod ++++ b/sparsify/virt-sparsify.pod +@@ -233,15 +233,16 @@ See L below. + =item B<--key> SELECTOR + + Specify a key for LUKS, to automatically open a LUKS device when using +-the inspection. C can be in one of the following formats: ++the inspection. C must be the libguestfs device name of the LUKS ++device. + + =over 4 + +-=item B<--key> C:key:KEY_STRING ++=item B<--key> C:key:KEY_STRING + + Use the specified C as passphrase. + +-=item B<--key> C:file:FILENAME ++=item B<--key> C:file:FILENAME + + Read the passphrase from F. + +diff --git a/sysprep/virt-sysprep.pod b/sysprep/virt-sysprep.pod +index 8d248db94..d7ad7ee33 100644 +--- a/sysprep/virt-sysprep.pod ++++ b/sysprep/virt-sysprep.pod +@@ -189,15 +189,16 @@ security problem with malicious guests (CVE-2010-3851). + =item B<--key> SELECTOR + + Specify a key for LUKS, to automatically open a LUKS device when using +-the inspection. C can be in one of the following formats: ++the inspection. C must be the libguestfs device name of the LUKS ++device. + + =over 4 + +-=item B<--key> C:key:KEY_STRING ++=item B<--key> C:key:KEY_STRING + + Use the specified C as passphrase. + +-=item B<--key> C:file:FILENAME ++=item B<--key> C:file:FILENAME + + Read the passphrase from F. + +diff --git a/v2v/virt-v2v.pod b/v2v/virt-v2v.pod +index 0642d158f..8c2867814 100644 +--- a/v2v/virt-v2v.pod ++++ b/v2v/virt-v2v.pod +@@ -337,15 +337,16 @@ through VDDK. + =item B<--key> SELECTOR + + Specify a key for LUKS, to automatically open a LUKS device when using +-the inspection. C can be in one of the following formats: ++the inspection. C must be the libguestfs device name of the LUKS ++device. + + =over 4 + +-=item B<--key> C:key:KEY_STRING ++=item B<--key> C:key:KEY_STRING + + Use the specified C as passphrase. + +-=item B<--key> C:file:FILENAME ++=item B<--key> C:file:FILENAME + + Read the passphrase from F. + +-- +2.25.4 + diff --git a/SOURCES/0038-v2v-rhv-plugin-case-sensitive-search-queries.patch b/SOURCES/0038-v2v-rhv-plugin-case-sensitive-search-queries.patch deleted file mode 100644 index 0545f34..0000000 --- a/SOURCES/0038-v2v-rhv-plugin-case-sensitive-search-queries.patch +++ /dev/null @@ -1,35 +0,0 @@ -From bc2ba2f47ba8a1f88ea6f3c14addd60e84423adf Mon Sep 17 00:00:00 2001 -From: Daniel Erez -Date: Wed, 25 Jul 2018 11:24:33 +0300 -Subject: [PATCH] v2v: rhv plugin - case-sensitive search queries - -Changed both search queries to case-sensitive (to ensure an exact match). ---- - v2v/rhv-upload-plugin.py | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/v2v/rhv-upload-plugin.py b/v2v/rhv-upload-plugin.py -index 8274f1ee1..4fad27fb8 100644 ---- a/v2v/rhv-upload-plugin.py -+++ b/v2v/rhv-upload-plugin.py -@@ -73,7 +73,7 @@ def find_host(connection): - storage_name = params['output_storage'] - data_centers = system_service.data_centers_service().list( - search='storage.name=%s' % storage_name, -- case_sensitive=False, -+ case_sensitive=True, - ) - if len(data_centers) == 0: - # The storage domain is not attached to a datacenter -@@ -87,7 +87,7 @@ def find_host(connection): - hosts_service = system_service.hosts_service() - hosts = hosts_service.list( - search="hw_id=%s and datacenter=%s and status=Up" % (vdsm_id, datacenter.name), -- case_sensitive=False, -+ case_sensitive=True, - ) - if len(hosts) == 0: - # Couldn't find a host that's fulfilling the following criteria: --- -2.21.0 - diff --git a/SOURCES/0039-options-allow-a-UUID-as-identifier-for-key.patch b/SOURCES/0039-options-allow-a-UUID-as-identifier-for-key.patch new file mode 100644 index 0000000..9b3fc9c --- /dev/null +++ b/SOURCES/0039-options-allow-a-UUID-as-identifier-for-key.patch @@ -0,0 +1,313 @@ +From abb0a1dcc6e15130c334713d0716e223e5fc494d Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Fri, 29 Nov 2019 12:07:13 +0100 +Subject: [PATCH] options: allow a UUID as identifier for --key + +This way it is possible to specify the UUID of the LUKS device instead +of the libguestfs device name to decrypt a device during the inspection. + +Make the usage of the new luks_uuid API conditional, so other projects +using the common submodule do not require a libguestfs version bump. + +(cherry picked from commit bb4a2dc17a78b53437896d4215ae82df8e11b788 +in libguestfs-common) + +PT: the documentation was amended manually. +--- + cat/virt-cat.pod | 4 ++-- + cat/virt-log.pod | 4 ++-- + cat/virt-ls.pod | 4 ++-- + cat/virt-tail.pod | 4 ++-- + common/options/decrypt.c | 8 +++++++- + common/options/keys.c | 4 ++-- + common/options/options.h | 6 +++--- + customize/virt-customize.pod | 4 ++-- + diff/virt-diff.pod | 4 ++-- + edit/virt-edit.pod | 4 ++-- + fish/guestfish.pod | 4 ++-- + fuse/guestmount.pod | 4 ++-- + get-kernel/virt-get-kernel.pod | 4 ++-- + inspector/virt-inspector.pod | 4 ++-- + sparsify/virt-sparsify.pod | 4 ++-- + sysprep/virt-sysprep.pod | 4 ++-- + v2v/virt-v2v.pod | 4 ++-- + 17 files changed, 40 insertions(+), 34 deletions(-) + +diff --git a/cat/virt-cat.pod b/cat/virt-cat.pod +index b0301d636..2cea291ac 100644 +--- a/cat/virt-cat.pod ++++ b/cat/virt-cat.pod +@@ -124,8 +124,8 @@ security problem with malicious guests (CVE-2010-3851). + =item B<--key> SELECTOR + + Specify a key for LUKS, to automatically open a LUKS device when using +-the inspection. C must be the libguestfs device name of the LUKS +-device. ++the inspection. C can be either the libguestfs device name, or ++the UUID of the LUKS device. + + =over 4 + +diff --git a/cat/virt-log.pod b/cat/virt-log.pod +index 0d447b3b5..888108d5f 100644 +--- a/cat/virt-log.pod ++++ b/cat/virt-log.pod +@@ -108,8 +108,8 @@ security problem with malicious guests (CVE-2010-3851). + =item B<--key> SELECTOR + + Specify a key for LUKS, to automatically open a LUKS device when using +-the inspection. C must be the libguestfs device name of the LUKS +-device. ++the inspection. C can be either the libguestfs device name, or ++the UUID of the LUKS device. + + =over 4 + +diff --git a/cat/virt-ls.pod b/cat/virt-ls.pod +index de02a473d..307e79395 100644 +--- a/cat/virt-ls.pod ++++ b/cat/virt-ls.pod +@@ -355,8 +355,8 @@ L above. + =item B<--key> SELECTOR + + Specify a key for LUKS, to automatically open a LUKS device when using +-the inspection. C must be the libguestfs device name of the LUKS +-device. ++the inspection. C can be either the libguestfs device name, or ++the UUID of the LUKS device. + + =over 4 + +diff --git a/cat/virt-tail.pod b/cat/virt-tail.pod +index f00384f5d..a804f4cf3 100644 +--- a/cat/virt-tail.pod ++++ b/cat/virt-tail.pod +@@ -126,8 +126,8 @@ security problem with malicious guests (CVE-2010-3851). + =item B<--key> SELECTOR + + Specify a key for LUKS, to automatically open a LUKS device when using +-the inspection. C must be the libguestfs device name of the LUKS +-device. ++the inspection. C can be either the libguestfs device name, or ++the UUID of the LUKS device. + + =over 4 + +diff --git a/common/options/decrypt.c b/common/options/decrypt.c +index 3511d9fe9..683cf5ed4 100644 +--- a/common/options/decrypt.c ++++ b/common/options/decrypt.c +@@ -86,7 +86,13 @@ inspect_do_decrypt (guestfs_h *g, struct key_store *ks) + char mapname[32]; + make_mapname (partitions[i], mapname, sizeof mapname); + +- CLEANUP_FREE_STRING_LIST char **keys = get_keys (ks, partitions[i]); ++#ifdef GUESTFS_HAVE_LUKS_UUID ++ CLEANUP_FREE char *uuid = guestfs_luks_uuid (g, partitions[i]); ++#else ++ const char *uuid = NULL; ++#endif ++ ++ CLEANUP_FREE_STRING_LIST char **keys = get_keys (ks, partitions[i], uuid); + assert (guestfs_int_count_strings (keys) > 0); + + /* Try each key in turn. */ +diff --git a/common/options/keys.c b/common/options/keys.c +index 7c391acde..798315c2e 100644 +--- a/common/options/keys.c ++++ b/common/options/keys.c +@@ -126,7 +126,7 @@ read_first_line_from_file (const char *filename) + * keystore, ask the user. + */ + char ** +-get_keys (struct key_store *ks, const char *device) ++get_keys (struct key_store *ks, const char *device, const char *uuid) + { + size_t i, j, len; + char **r; +@@ -148,7 +148,7 @@ get_keys (struct key_store *ks, const char *device) + for (i = 0; i < ks->nr_keys; ++i) { + struct key_store_key *key = &ks->keys[i]; + +- if (STRNEQ (key->id, device)) ++ if (STRNEQ (key->id, device) && (uuid && STRNEQ (key->id, uuid))) + continue; + + switch (key->type) { +diff --git a/common/options/options.h b/common/options/options.h +index b83a92b06..9b7830220 100644 +--- a/common/options/options.h ++++ b/common/options/options.h +@@ -104,8 +104,8 @@ struct mp { + + /* A key in the key store. */ + struct key_store_key { +- /* An ID for the device this key refers to. It must be the libguestfs +- * device name. ++ /* An ID for the device this key refers to. It can be either the libguestfs ++ * device name, or the UUID. + * + * There may be multiple matching devices in the list. + */ +@@ -150,7 +150,7 @@ extern void print_inspect_prompt (void); + + /* in key.c */ + extern char *read_key (const char *param); +-extern char **get_keys (struct key_store *ks, const char *device); ++extern char **get_keys (struct key_store *ks, const char *device, const char *uuid); + extern struct key_store *key_store_add_from_selector (struct key_store *ks, const char *selector); + extern struct key_store *key_store_import_key (struct key_store *ks, const struct key_store_key *key); + extern void free_key_store (struct key_store *ks); +diff --git a/customize/virt-customize.pod b/customize/virt-customize.pod +index 491606591..5d92486a2 100644 +--- a/customize/virt-customize.pod ++++ b/customize/virt-customize.pod +@@ -141,8 +141,8 @@ security problem with malicious guests (CVE-2010-3851). + =item B<--key> SELECTOR + + Specify a key for LUKS, to automatically open a LUKS device when using +-the inspection. C must be the libguestfs device name of the LUKS +-device. ++the inspection. C can be either the libguestfs device name, or ++the UUID of the LUKS device. + + =over 4 + +diff --git a/diff/virt-diff.pod b/diff/virt-diff.pod +index 22658072d..e67d09101 100644 +--- a/diff/virt-diff.pod ++++ b/diff/virt-diff.pod +@@ -169,8 +169,8 @@ Display file sizes in human-readable format. + =item B<--key> SELECTOR + + Specify a key for LUKS, to automatically open a LUKS device when using +-the inspection. C must be the libguestfs device name of the LUKS +-device. ++the inspection. C can be either the libguestfs device name, or ++the UUID of the LUKS device. + + =over 4 + +diff --git a/edit/virt-edit.pod b/edit/virt-edit.pod +index 5a63cd05f..918fa66f2 100644 +--- a/edit/virt-edit.pod ++++ b/edit/virt-edit.pod +@@ -156,8 +156,8 @@ security problem with malicious guests (CVE-2010-3851). + =item B<--key> SELECTOR + + Specify a key for LUKS, to automatically open a LUKS device when using +-the inspection. C must be the libguestfs device name of the LUKS +-device. ++the inspection. C can be either the libguestfs device name, or ++the UUID of the LUKS device. + + =over 4 + +diff --git a/fish/guestfish.pod b/fish/guestfish.pod +index ccb57b159..f1fdf094d 100644 +--- a/fish/guestfish.pod ++++ b/fish/guestfish.pod +@@ -283,8 +283,8 @@ were found. + =item B<--key> SELECTOR + + Specify a key for LUKS, to automatically open a LUKS device when using +-the inspection. C must be the libguestfs device name of the LUKS +-device. ++the inspection. C can be either the libguestfs device name, or ++the UUID of the LUKS device. + + =over 4 + +diff --git a/fuse/guestmount.pod b/fuse/guestmount.pod +index d9e957b8b..3a02c087c 100644 +--- a/fuse/guestmount.pod ++++ b/fuse/guestmount.pod +@@ -249,8 +249,8 @@ mounted on the real virtual machine. + =item B<--key> SELECTOR + + Specify a key for LUKS, to automatically open a LUKS device when using +-the inspection. C must be the libguestfs device name of the LUKS +-device. ++the inspection. C can be either the libguestfs device name, or ++the UUID of the LUKS device. + + =over 4 + +diff --git a/get-kernel/virt-get-kernel.pod b/get-kernel/virt-get-kernel.pod +index f0ace2d6d..78fe66df4 100644 +--- a/get-kernel/virt-get-kernel.pod ++++ b/get-kernel/virt-get-kernel.pod +@@ -92,8 +92,8 @@ security problem with malicious guests (CVE-2010-3851). + =item B<--key> SELECTOR + + Specify a key for LUKS, to automatically open a LUKS device when using +-the inspection. C must be the libguestfs device name of the LUKS +-device. ++the inspection. C can be either the libguestfs device name, or ++the UUID of the LUKS device. + + =over 4 + +diff --git a/inspector/virt-inspector.pod b/inspector/virt-inspector.pod +index eac9dc3cd..625da876c 100644 +--- a/inspector/virt-inspector.pod ++++ b/inspector/virt-inspector.pod +@@ -117,8 +117,8 @@ ensure the format is always specified. + =item B<--key> SELECTOR + + Specify a key for LUKS, to automatically open a LUKS device when using +-the inspection. C must be the libguestfs device name of the LUKS +-device. ++the inspection. C can be either the libguestfs device name, or ++the UUID of the LUKS device. + + =over 4 + +diff --git a/sparsify/virt-sparsify.pod b/sparsify/virt-sparsify.pod +index cf7970a5f..0767d07e6 100644 +--- a/sparsify/virt-sparsify.pod ++++ b/sparsify/virt-sparsify.pod +@@ -233,8 +233,8 @@ See L below. + =item B<--key> SELECTOR + + Specify a key for LUKS, to automatically open a LUKS device when using +-the inspection. C must be the libguestfs device name of the LUKS +-device. ++the inspection. C can be either the libguestfs device name, or ++the UUID of the LUKS device. + + =over 4 + +diff --git a/sysprep/virt-sysprep.pod b/sysprep/virt-sysprep.pod +index d7ad7ee33..b38c76c70 100644 +--- a/sysprep/virt-sysprep.pod ++++ b/sysprep/virt-sysprep.pod +@@ -189,8 +189,8 @@ security problem with malicious guests (CVE-2010-3851). + =item B<--key> SELECTOR + + Specify a key for LUKS, to automatically open a LUKS device when using +-the inspection. C must be the libguestfs device name of the LUKS +-device. ++the inspection. C can be either the libguestfs device name, or ++the UUID of the LUKS device. + + =over 4 + +diff --git a/v2v/virt-v2v.pod b/v2v/virt-v2v.pod +index 8c2867814..25041d0ec 100644 +--- a/v2v/virt-v2v.pod ++++ b/v2v/virt-v2v.pod +@@ -337,8 +337,8 @@ through VDDK. + =item B<--key> SELECTOR + + Specify a key for LUKS, to automatically open a LUKS device when using +-the inspection. C must be the libguestfs device name of the LUKS +-device. ++the inspection. C can be either the libguestfs device name, or ++the UUID of the LUKS device. + + =over 4 + +-- +2.25.4 + diff --git a/SOURCES/0039-uefi-remove-last-references-to-kraxel-s-old-edk2-bui.patch b/SOURCES/0039-uefi-remove-last-references-to-kraxel-s-old-edk2-bui.patch deleted file mode 100644 index 89f3431..0000000 --- a/SOURCES/0039-uefi-remove-last-references-to-kraxel-s-old-edk2-bui.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 21cf4aaafb6088168d2f5c679477644c19116f3d Mon Sep 17 00:00:00 2001 -From: Pino Toscano -Date: Fri, 20 Apr 2018 15:27:04 +0200 -Subject: [PATCH] uefi: remove last references to kraxel's old edk2 builds - -Commit 889386f8c6088e57fd68f2bb6bf85f69ecfc6f6c removed most of them -already, so remove the last ones, and the supporting code. ---- - generator/UEFI.ml | 6 ------ - v2v/utils.ml | 1 - - 2 files changed, 7 deletions(-) - -diff --git a/generator/UEFI.ml b/generator/UEFI.ml -index daa78bdc9..bca3fa1ae 100644 ---- a/generator/UEFI.ml -+++ b/generator/UEFI.ml -@@ -30,12 +30,6 @@ open Docstrings - - (* Order is significant *within architectures only*. *) - let firmware = [ -- "i386", -- "/usr/share/edk2.git/ovmf-ia32/OVMF_CODE-pure-efi.fd", -- None, -- "/usr/share/edk2.git/ovmf-ia32/OVMF_VARS-pure-efi.fd", -- []; -- - "x86_64", - "/usr/share/OVMF/OVMF_CODE.fd", - None, -diff --git a/v2v/utils.ml b/v2v/utils.ml -index e880001eb..67e2028f3 100644 ---- a/v2v/utils.ml -+++ b/v2v/utils.ml -@@ -64,7 +64,6 @@ let find_uefi_firmware guest_arch = - let files = - (* The lists of firmware are actually defined in common/utils/uefi.c. *) - match guest_arch with -- | "i386" | "i486" | "i586" | "i686" -> Uefi.uefi_i386_firmware - | "x86_64" -> Uefi.uefi_x86_64_firmware - | "aarch64" -> Uefi.uefi_aarch64_firmware - | arch -> --- -2.21.0 - diff --git a/SOURCES/0040-docs-remove-paragraph-about-VMware-tools-on-Windows-.patch b/SOURCES/0040-docs-remove-paragraph-about-VMware-tools-on-Windows-.patch new file mode 100644 index 0000000..e94bcd6 --- /dev/null +++ b/SOURCES/0040-docs-remove-paragraph-about-VMware-tools-on-Windows-.patch @@ -0,0 +1,82 @@ +From 34b2da989021994389b6392fca06590424b7c975 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Wed, 18 Dec 2019 12:12:26 +0100 +Subject: [PATCH] docs: remove paragraph about VMware tools on Windows + (RHBZ#1785528) + +Starting from libguestfs/virt-v2v 1.39.12, virt-v2v attempts to +uninstall the VMware tools from Windows guests, so there is no need to +remove them manually before the conversion. + +Thanks to: Ming Xie. + +(cherry picked from commit 397b4a90d16f4eb116d55605cbdf3bd844108315 +in virt-v2v) +--- + v2v/virt-v2v-input-vmware.pod | 36 ----------------------------------- + 1 file changed, 36 deletions(-) + +diff --git a/v2v/virt-v2v-input-vmware.pod b/v2v/virt-v2v-input-vmware.pod +index 3acdd773e..16ddb045f 100644 +--- a/v2v/virt-v2v-input-vmware.pod ++++ b/v2v/virt-v2v-input-vmware.pod +@@ -106,18 +106,6 @@ If you find a folder of files called F.vmx>, + F.vmxf>, F.nvram> and one or more F<.vmdk> disk + images, then you can use this method. + +-=head2 VMX: Remove VMware tools from Windows guests +- +-For Windows guests, you should remove VMware tools before conversion. +-Although this is not strictly necessary, and the guest will still be +-able to run, if you don't do this then the converted guest will +-complain on every boot. The tools cannot be removed after conversion +-because the uninstaller checks if it is running on VMware and refuses +-to start (which is also the reason that virt-v2v cannot remove them). +- +-This is not necessary for Linux guests, as virt-v2v is able to remove +-VMware tools. +- + =head2 VMX: Guest must be shut down + + B. If you don't +@@ -319,18 +307,6 @@ Virt-v2v is able to import guests from VMware’s OVA (Open + Virtualization Appliance) files. Only OVAs exported from VMware + vSphere will work. + +-=head2 OVA: Remove VMware tools from Windows guests +- +-For Windows guests, you should remove VMware tools before conversion. +-Although this is not strictly necessary, and the guest will still be +-able to run, if you don't do this then the converted guest will +-complain on every boot. The tools cannot be removed after conversion +-because the uninstaller checks if it is running on VMware and refuses +-to start (which is also the reason that virt-v2v cannot remove them). +- +-This is not necessary for Linux guests, as virt-v2v is able to remove +-VMware tools. +- + =head2 OVA: Create OVA + + To create an OVA in vSphere, use the "Export OVF Template" option +@@ -383,18 +359,6 @@ Virt-v2v uses libvirt for access to vCenter, and therefore the input + mode should be I<-i libvirt>. As this is the default, you don't need + to specify it on the command line. + +-=head2 vCenter: Remove VMware tools from Windows guests +- +-For Windows guests, you should remove VMware tools before conversion. +-Although this is not strictly necessary, and the guest will still be +-able to run, if you don't do this then the converted guest will +-complain on every boot. The tools cannot be removed after conversion +-because the uninstaller checks if it is running on VMware and refuses +-to start (which is also the reason that virt-v2v cannot remove them). +- +-This is not necessary for Linux guests, as virt-v2v is able to remove +-VMware tools. +- + =head2 vCenter: URI + + The libvirt URI of a vCenter server looks something like this: +-- +2.25.4 + diff --git a/SOURCES/0040-v2v-parse_libvirt_xml-handle-srN-CDROM-devices-RHBZ-.patch b/SOURCES/0040-v2v-parse_libvirt_xml-handle-srN-CDROM-devices-RHBZ-.patch deleted file mode 100644 index 5dc70ae..0000000 --- a/SOURCES/0040-v2v-parse_libvirt_xml-handle-srN-CDROM-devices-RHBZ-.patch +++ /dev/null @@ -1,38 +0,0 @@ -From bb804081e9b5fc959b14d2e254d320cf5a658441 Mon Sep 17 00:00:00 2001 -From: Pino Toscano -Date: Thu, 9 Aug 2018 15:01:37 +0200 -Subject: [PATCH] v2v: parse_libvirt_xml: handle srN CDROM devices - (RHBZ#1612785) - -This device naming is mostly written by virt-p2v, so get the slot from -it directly without using the drive_index "decoding" function. - -(cherry picked from commit c9abaa3e96e7209595f0982c1f2f97e37f3369a6) ---- - v2v/parse_libvirt_xml.ml | 10 ++++++++++ - 1 file changed, 10 insertions(+) - -diff --git a/v2v/parse_libvirt_xml.ml b/v2v/parse_libvirt_xml.ml -index 03a201e77..44723014c 100644 ---- a/v2v/parse_libvirt_xml.ml -+++ b/v2v/parse_libvirt_xml.ml -@@ -379,6 +379,16 @@ let parse_libvirt_xml ?conn xml = - let target_dev = xpath_string "target/@dev" in - match target_dev with - | None -> None -+ | Some dev when String.is_prefix dev "sr" -> -+ (* "srN" devices are found mostly in the physical XML written by -+ * virt-p2v. -+ *) -+ let name = String.sub dev 2 (String.length dev - 2) in -+ (try Some (int_of_string name) -+ with Failure _ -> -+ warning (f_"could not parse device name ‘%s’ from the source libvirt XML") dev; -+ None -+ ) - | Some dev -> - let rec loop = function - | [] -> --- -2.21.0 - diff --git a/SOURCES/0041-mlcustomize-Trim-whitespaces-from-commands-read-from.patch b/SOURCES/0041-mlcustomize-Trim-whitespaces-from-commands-read-from.patch new file mode 100644 index 0000000..2d9be80 --- /dev/null +++ b/SOURCES/0041-mlcustomize-Trim-whitespaces-from-commands-read-from.patch @@ -0,0 +1,29 @@ +From 3dc8b808bdc992fb72372ece84b45644bef2c206 Mon Sep 17 00:00:00 2001 +From: Martin Kletzander +Date: Mon, 24 Feb 2020 13:12:03 +0100 +Subject: [PATCH] mlcustomize: Trim whitespaces from commands read from file + (RHBZ#1351000) + +The first split does not care about the whole string, it is just trying to get +the command name in front, so triml is just right. + +Signed-off-by: Martin Kletzander +--- + generator/customize.ml | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/generator/customize.ml b/generator/customize.ml +index c278347c1..0b256e2d2 100644 +--- a/generator/customize.ml ++++ b/generator/customize.ml +@@ -873,6 +873,7 @@ let rec argspec () = + pr " ] in + let lines = read_whole_file filename in + let lines = String.lines_split lines in ++ let lines = List.map String.triml lines in + let lines = List.filter ( + fun line -> + String.length line > 0 && line.[0] <> '#' +-- +2.25.4 + diff --git a/SOURCES/0041-v2v-o-rhv-upload-Fix-error-message-disk-numbering-RH.patch b/SOURCES/0041-v2v-o-rhv-upload-Fix-error-message-disk-numbering-RH.patch deleted file mode 100644 index a70a9f8..0000000 --- a/SOURCES/0041-v2v-o-rhv-upload-Fix-error-message-disk-numbering-RH.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 6f116349a2a02739e64a39ab2aeb23706fac188b Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Tue, 14 Aug 2018 12:50:07 +0100 -Subject: [PATCH] v2v: -o rhv-upload: Fix error message disk numbering - (RHBZ#1615885). - -The output method used the s_disk_id field assuming it was a unique, -monotonically increasing number counting from 0. However this is not -the case, the input method simply has to set s_disk_id to be unique -for each disk. - -Fixes commit cc04573927cca97de60d544d37467e67c25867a7. - -Thanks: Xiaodai Wang -(cherry picked from commit 90c9c12258fbb9a89d16f798725d16fe5bb3504c) ---- - v2v/output_rhv_upload.ml | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/v2v/output_rhv_upload.ml b/v2v/output_rhv_upload.ml -index 63fa2411a..7dbd98a0d 100644 ---- a/v2v/output_rhv_upload.ml -+++ b/v2v/output_rhv_upload.ml -@@ -383,13 +383,13 @@ If the messages above are not sufficient to diagnose the problem then add the - *) - let nr_disks = List.length targets in - let image_uuids = -- List.map ( -- fun t -> -+ List.mapi ( -+ fun i t -> - let id = t.target_overlay.ov_source.s_disk_id in - let diskid_file = diskid_file_of_id id in - if not (wait_for_file diskid_file finalization_timeout) then - error (f_"transfer of disk %d/%d failed, see earlier error messages") -- (id+1) nr_disks; -+ (i+1) nr_disks; - let diskid = read_whole_file diskid_file in - diskid - ) targets in --- -2.21.0 - diff --git a/SOURCES/0042-openstack-Increase-Cinder-volume-attach-timeout-to-5.patch b/SOURCES/0042-openstack-Increase-Cinder-volume-attach-timeout-to-5.patch new file mode 100644 index 0000000..651d86d --- /dev/null +++ b/SOURCES/0042-openstack-Increase-Cinder-volume-attach-timeout-to-5.patch @@ -0,0 +1,43 @@ +From a4433085bf38719bd22a7cfe507c503885c839f2 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Tue, 4 Feb 2020 14:39:39 +0000 +Subject: [PATCH] openstack: Increase Cinder volume attach timeout to 5 minutes + (RHBZ#1685032). + +In some cases we have observed the time taken for a Cinder volume to +attach to the conversion appliance can be longer than the current 60 +seconds. Increase the timeout to 5 minutes. + +Thanks: Ming Xie. + +(cherry picked from commit e2ce290f6e366716f857eeaddc1dc680e5608c80 +in virt-v2v) +--- + v2v/output_openstack.ml | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/v2v/output_openstack.ml b/v2v/output_openstack.ml +index d187f1d5d..bebf9af18 100644 +--- a/v2v/output_openstack.ml ++++ b/v2v/output_openstack.ml +@@ -38,7 +38,7 @@ let openstack_binary = "openstack" + let available_timeout = 300 (* seconds *) + + (* Timeout waiting for Cinder volumes to attach to the appliance. *) +-let attach_timeout = 60 (* seconds *) ++let attach_timeout = 300 (* seconds *) + + (* The -oo options supported by this output method. *) + type os_options = { +@@ -336,7 +336,7 @@ class output_openstack output_conn output_password output_storage + if String.length id > prefix_len then String.sub id 0 prefix_len + else id in + +- with_timeout ++ with_timeout ~sleep:5 + (sprintf (f_"waiting for cinder volume %s to attach to the conversion appliance") id) + attach_timeout + (fun () -> +-- +2.25.4 + diff --git a/SOURCES/0042-v2v-o-rhv-upload-Properly-replace-SD_UUID-in-OVF-RHB.patch b/SOURCES/0042-v2v-o-rhv-upload-Properly-replace-SD_UUID-in-OVF-RHB.patch deleted file mode 100644 index 8346af1..0000000 --- a/SOURCES/0042-v2v-o-rhv-upload-Properly-replace-SD_UUID-in-OVF-RHB.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 739ac1bc0f37c4bceb2e2eeed00f9320605aa641 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Tue, 7 Aug 2018 09:06:46 +0100 -Subject: [PATCH] v2v: -o rhv-upload: Properly replace SD_UUID in OVF - (RHBZ#1612653). - -The @SD_UUID@ pattern was not being replaced correctly. - -Thanks: Daniel Erez. -(cherry picked from commit 389e165519c33b5234db50ea26dcb267321ee152) ---- - v2v/rhv-upload-createvm.py | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/v2v/rhv-upload-createvm.py b/v2v/rhv-upload-createvm.py -index a34627ec8..1d0e8c95d 100644 ---- a/v2v/rhv-upload-createvm.py -+++ b/v2v/rhv-upload-createvm.py -@@ -70,7 +70,7 @@ sds_service = system_service.storage_domains_service() - sd = sds_service.list(search=("name=%s" % params['output_storage']))[0] - sd_uuid = sd.id - --ovf.replace("@SD_UUID@", sd_uuid) -+ovf = ovf.replace("@SD_UUID@", sd_uuid) - - vms_service = system_service.vms_service() - vm = vms_service.add( --- -2.21.0 - diff --git a/SOURCES/0043-ppc64le-Don-t-use-cpu-parameter-under-any-circumstan.patch b/SOURCES/0043-ppc64le-Don-t-use-cpu-parameter-under-any-circumstan.patch deleted file mode 100644 index b22b600..0000000 --- a/SOURCES/0043-ppc64le-Don-t-use-cpu-parameter-under-any-circumstan.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 8be6817e95dbdf826a6065751b4a3a000c78071c Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Tue, 28 Aug 2018 12:59:06 +0100 -Subject: [PATCH] ppc64le: Don't use -cpu parameter under any circumstances - (RHBZ#1605071). - -(cherry picked from commit 56318f0b5ffc287fed71cc7cdd2007dff2b8fb17) ---- - lib/appliance-cpu.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/lib/appliance-cpu.c b/lib/appliance-cpu.c -index a6c1b0faf..fa1bae3f9 100644 ---- a/lib/appliance-cpu.c -+++ b/lib/appliance-cpu.c -@@ -76,6 +76,9 @@ guestfs_int_get_cpu_model (int kvm) - return "host"; - else - return "cortex-a57"; -+#elif defined(__powerpc64__) -+ /* See discussion in https://bugzilla.redhat.com/show_bug.cgi?id=1605071 */ -+ return NULL; - #else - /* On most architectures, it is faster to pass the CPU host model to - * the appliance, allowing maximum speed for things like checksums --- -2.21.0 - diff --git a/SOURCES/0043-v2v-o-rhv-upload-check-for-a-valid-image-transfer-ri.patch b/SOURCES/0043-v2v-o-rhv-upload-check-for-a-valid-image-transfer-ri.patch new file mode 100644 index 0000000..397077e --- /dev/null +++ b/SOURCES/0043-v2v-o-rhv-upload-check-for-a-valid-image-transfer-ri.patch @@ -0,0 +1,35 @@ +From d02694e659ebe1ecad29f8461d87eda6a1f8faa2 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Thu, 19 Sep 2019 09:52:41 +0200 +Subject: [PATCH] v2v: -o rhv-upload: check for a valid image transfer right + away + +Check for the INITIALIZING state of the image transfer right away, +without waiting 5 seconds even before the first time: this way, if the +transfer is already in the right state then there is no need to wait. +--- + v2v/rhv-upload-plugin.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/v2v/rhv-upload-plugin.py b/v2v/rhv-upload-plugin.py +index 6ec74a5d4..7f62b4e3b 100644 +--- a/v2v/rhv-upload-plugin.py ++++ b/v2v/rhv-upload-plugin.py +@@ -190,13 +190,13 @@ def open(readonly): + # actual transfer can start when its status is "Transferring". + endt = time.time() + timeout + while True: +- time.sleep(5) + transfer = transfer_service.get() + if transfer.phase != types.ImageTransferPhase.INITIALIZING: + break + if time.time() > endt: + raise RuntimeError("timed out waiting for transfer status " + "!= INITIALIZING") ++ time.sleep(5) + + # Now we have permission to start the transfer. + if params['rhv_direct']: +-- +2.25.4 + diff --git a/SOURCES/0044-rhv-upload-Check-status-more-frequently.patch b/SOURCES/0044-rhv-upload-Check-status-more-frequently.patch new file mode 100644 index 0000000..350f32b --- /dev/null +++ b/SOURCES/0044-rhv-upload-Check-status-more-frequently.patch @@ -0,0 +1,49 @@ +From 200a365f20d5d8a3ddfe713e9bbe938206e43e9a Mon Sep 17 00:00:00 2001 +From: Nir Soffer +Date: Mon, 18 Nov 2019 01:04:24 +0200 +Subject: [PATCH] rhv-upload: Check status more frequently + +Checking status more frequently save a couple of seconds. Here is +an example flow tested with oVirt upload_disk.py example: + +With 5 seconds wait: + +Created disk in 11.085111 seconds +Created transfer in 1.857502 seconds + +With 1 second wait: + +Created disk in 4.991227 seconds +Created transfer in 1.961243 seconds + +(cherry picked from commit 8816c5db220f518ef70beec7ac543290e3d5c0c7 +in virt-v2v) +--- + v2v/rhv-upload-plugin.py | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/v2v/rhv-upload-plugin.py b/v2v/rhv-upload-plugin.py +index 7f62b4e3b..f13405df1 100644 +--- a/v2v/rhv-upload-plugin.py ++++ b/v2v/rhv-upload-plugin.py +@@ -161,7 +161,7 @@ def open(readonly): + + endt = time.time() + timeout + while True: +- time.sleep(5) ++ time.sleep(1) + disk = disk_service.get() + if disk.status == types.DiskStatus.OK: + break +@@ -196,7 +196,7 @@ def open(readonly): + if time.time() > endt: + raise RuntimeError("timed out waiting for transfer status " + "!= INITIALIZING") +- time.sleep(5) ++ time.sleep(1) + + # Now we have permission to start the transfer. + if params['rhv_direct']: +-- +2.25.4 + diff --git a/SOURCES/0044-tools-Link-OCaml-programs-with-runtime-variant-_pic-.patch b/SOURCES/0044-tools-Link-OCaml-programs-with-runtime-variant-_pic-.patch deleted file mode 100644 index e774ebe..0000000 --- a/SOURCES/0044-tools-Link-OCaml-programs-with-runtime-variant-_pic-.patch +++ /dev/null @@ -1,108 +0,0 @@ -From 81a9e4f428e9a2305a2ea8c576dadde60fa5a381 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Thu, 20 Sep 2018 12:42:59 +0100 -Subject: [PATCH] tools: Link OCaml programs with -runtime-variant _pic if - available. -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -OCaml has a small runtime which is statically linked into the virt -tools (providing things like GC and primitives). Since OCaml 4.03 it -has been possible to select variants of this runtime, one of which is -compiled with -fPIC, using ‘ocamlopt -runtime-variant _pic’. - -This has performance implications on i686, but is relatively free on -other architectures. Since it (in theory) adds to the security of the -final binary this commit enables it whenever it is available. - -(cherry picked from commit 09abb9c990f6e07b3577088522b8ad9fb439a80e) ---- - .gitignore | 1 + - configure.ac | 2 ++ - m4/guestfs-ocaml.m4 | 18 ++++++++++++++++++ - ocaml-link.sh => ocaml-link.sh.in | 8 +++++++- - 4 files changed, 28 insertions(+), 1 deletion(-) - rename ocaml-link.sh => ocaml-link.sh.in (88%) - -diff --git a/.gitignore b/.gitignore -index af80e36d1..89b8baa17 100644 ---- a/.gitignore -+++ b/.gitignore -@@ -410,6 +410,7 @@ Makefile.in - /make-fs/virt-make-fs.1 - /missing - /ocaml-dep.sh -+/ocaml-link.sh - /ocaml/bindtests.bc - /ocaml/bindtests.opt - /ocaml/bindtests.ml -diff --git a/configure.ac b/configure.ac -index 4da3bd021..6c38406bb 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -198,6 +198,8 @@ AC_CONFIG_FILES([installcheck.sh], - [chmod +x,-w installcheck.sh]) - AC_CONFIG_FILES([ocaml-dep.sh], - [chmod +x,-w ocaml-dep.sh]) -+AC_CONFIG_FILES([ocaml-link.sh], -+ [chmod +x,-w ocaml-link.sh]) - AC_CONFIG_FILES([p2v/virt-p2v-make-disk], - [chmod +x,-w p2v/virt-p2v-make-disk]) - AC_CONFIG_FILES([p2v/virt-p2v-make-kickstart], -diff --git a/m4/guestfs-ocaml.m4 b/m4/guestfs-ocaml.m4 -index e08f40a02..fea11a334 100644 ---- a/m4/guestfs-ocaml.m4 -+++ b/m4/guestfs-ocaml.m4 -@@ -59,6 +59,24 @@ AM_CONDITIONAL([HAVE_OCAMLOPT], - AM_CONDITIONAL([HAVE_OCAMLDOC], - [test "x$OCAMLDOC" != "xno"]) - -+dnl Check if ocamlc/ocamlopt -runtime-variant _pic works. It was -+dnl added in OCaml >= 4.03, but in theory might be disabled by -+dnl downstream distros. -+OCAML_RUNTIME_VARIANT_PIC_OPTION="" -+if test "x$OCAMLC" != "xno"; then -+ AC_MSG_CHECKING([if OCaml ‘-runtime-variant _pic’ works]) -+ rm -f conftest.ml contest -+ echo 'print_endline "hello world"' > conftest.ml -+ if $OCAMLC conftest.ml -runtime-variant _pic -o conftest >&5 2>&5 ; then -+ AC_MSG_RESULT([yes]) -+ OCAML_RUNTIME_VARIANT_PIC_OPTION="-runtime-variant _pic" -+ else -+ AC_MSG_RESULT([no]) -+ fi -+ rm -f conftest.ml contest -+fi -+AC_SUBST([OCAML_RUNTIME_VARIANT_PIC_OPTION]) -+ - dnl Check if ocamldep has options -all and -one-line (not present in RHEL 6). - AC_MSG_CHECKING([if ocamldep has the ‘-all’ option]) - if ocamldep -all >&AS_MESSAGE_LOG_FD 2>&1; then -diff --git a/ocaml-link.sh b/ocaml-link.sh.in -similarity index 88% -rename from ocaml-link.sh -rename to ocaml-link.sh.in -index 855637534..fbcc07951 100755 ---- a/ocaml-link.sh -+++ b/ocaml-link.sh.in -@@ -1,4 +1,6 @@ - #!/bin/bash - -+# Script used to link OCaml programs. -+# @configure_input@ - # (C) Copyright 2015-2018 Red Hat Inc. - # - # This program is free software; you can redistribute it and/or modify -@@ -41,4 +43,8 @@ while true ; do - esac - done - --exec "$@" -linkpkg -cclib "${cclib}" -+# NB -cclib must come last. -+exec "$@" \ -+ @OCAML_RUNTIME_VARIANT_PIC_OPTION@ \ -+ -linkpkg \ -+ -cclib "${cclib}" --- -2.21.0 - diff --git a/SOURCES/0045-rhv-upload-Show-transfer-id-in-error-message.patch b/SOURCES/0045-rhv-upload-Show-transfer-id-in-error-message.patch new file mode 100644 index 0000000..68b32cb --- /dev/null +++ b/SOURCES/0045-rhv-upload-Show-transfer-id-in-error-message.patch @@ -0,0 +1,31 @@ +From 7fd1c3be6bb744a93eff6ae1a9cfcdd9280cf247 Mon Sep 17 00:00:00 2001 +From: Nir Soffer +Date: Mon, 18 Nov 2019 23:53:46 +0200 +Subject: [PATCH] rhv-upload: Show transfer id in error message + +(cherry picked from commit d4ca9b6ca42d4ad3c717f5c59402ca6ff5d322bb +in virt-v2v) +--- + v2v/rhv-upload-plugin.py | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/v2v/rhv-upload-plugin.py b/v2v/rhv-upload-plugin.py +index f13405df1..9b83d1cfa 100644 +--- a/v2v/rhv-upload-plugin.py ++++ b/v2v/rhv-upload-plugin.py +@@ -194,8 +194,10 @@ def open(readonly): + if transfer.phase != types.ImageTransferPhase.INITIALIZING: + break + if time.time() > endt: +- raise RuntimeError("timed out waiting for transfer status " +- "!= INITIALIZING") ++ raise RuntimeError( ++ "timed out waiting for transfer %s status != INITIALIZING" ++ % transfer.id) ++ + time.sleep(1) + + # Now we have permission to start the transfer. +-- +2.25.4 + diff --git a/SOURCES/0045-tools-Ensure-CFLAGS-and-LDFLAGS-are-passed-to-all-OC.patch b/SOURCES/0045-tools-Ensure-CFLAGS-and-LDFLAGS-are-passed-to-all-OC.patch deleted file mode 100644 index 443208e..0000000 --- a/SOURCES/0045-tools-Ensure-CFLAGS-and-LDFLAGS-are-passed-to-all-OC.patch +++ /dev/null @@ -1,328 +0,0 @@ -From 7423e43ec2cd27d52650a1caeb7c0576350e0a78 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Thu, 20 Sep 2018 12:59:44 +0100 -Subject: [PATCH] tools: Ensure CFLAGS and LDFLAGS are passed to all OCaml - binaries (RHBZ#1624130). - -After this commit, all annocheck errors are fixed except for: - - Hardened: virt-get-kernel: MAYB: Gaps were detected in the annobin coverage. Run with -v to list. - -After discussion with the annocheck maintainers this gap in coverage -(which corresponds to the OCaml runtime) seems to be caused either by -the runtime not being linked with the right flags, or might be a bug -in annocheck itself. In any case it's not something that can be -resolved within the scope of libguestfs. - -(cherry picked from commit 34c23403c51a4d59d826c8045e06f9aabc2ceb16) ---- - builder/Makefile.am | 2 +- - common/mlaugeas/Makefile.am | 2 +- - common/mlgettext/Makefile.am | 2 +- - common/mlpcre/Makefile.am | 2 +- - common/mlprogress/Makefile.am | 2 +- - common/mlstdutils/Makefile.am | 2 +- - common/mltools/Makefile.am | 2 +- - common/mlutils/Makefile.am | 2 +- - common/mlvisit/Makefile.am | 2 +- - common/mlxml/Makefile.am | 2 +- - customize/Makefile.am | 2 +- - daemon/Makefile.am | 2 +- - dib/Makefile.am | 2 +- - generator/Makefile.am | 2 +- - get-kernel/Makefile.am | 2 +- - ocaml-link.sh.in | 2 +- - ocaml/Makefile.am | 2 +- - resize/Makefile.am | 2 +- - sparsify/Makefile.am | 2 +- - sysprep/Makefile.am | 2 +- - v2v/Makefile.am | 2 +- - v2v/test-harness/Makefile.am | 2 +- - 22 files changed, 22 insertions(+), 22 deletions(-) - -diff --git a/builder/Makefile.am b/builder/Makefile.am -index c7b50778a..a30a229b2 100644 ---- a/builder/Makefile.am -+++ b/builder/Makefile.am -@@ -215,7 +215,7 @@ OCAMLCLIBS = \ - $(LIBINTL) \ - -lgnu - --OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) -+OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) -ccopt '$(CFLAGS)' - - if !HAVE_OCAMLOPT - OBJECTS = $(BOBJECTS) -diff --git a/common/mlaugeas/Makefile.am b/common/mlaugeas/Makefile.am -index 8aa15b80e..2c1a6e0fd 100644 ---- a/common/mlaugeas/Makefile.am -+++ b/common/mlaugeas/Makefile.am -@@ -61,7 +61,7 @@ BOBJECTS = $(SOURCES_ML:.ml=.cmo) - XOBJECTS = $(BOBJECTS:.cmo=.cmx) - - OCAMLPACKAGES = --OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) -+OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) -ccopt '$(CFLAGS)' - - if !HAVE_OCAMLOPT - OBJECTS = $(BOBJECTS) -diff --git a/common/mlgettext/Makefile.am b/common/mlgettext/Makefile.am -index cdcea33ec..b918f90c3 100644 ---- a/common/mlgettext/Makefile.am -+++ b/common/mlgettext/Makefile.am -@@ -60,7 +60,7 @@ if HAVE_OCAML_PKG_GETTEXT - OCAMLPACKAGES += -package gettext-stub - endif - --OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) -+OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) -ccopt '$(CFLAGS)' - - if !HAVE_OCAMLOPT - OBJECTS = $(BOBJECTS) -diff --git a/common/mlpcre/Makefile.am b/common/mlpcre/Makefile.am -index f9699f592..6f04256da 100644 ---- a/common/mlpcre/Makefile.am -+++ b/common/mlpcre/Makefile.am -@@ -70,7 +70,7 @@ OCAMLPACKAGES = \ - -I $(builddir) - OCAMLPACKAGES_TESTS = $(MLPCRE_CMA) - --OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) -+OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) -ccopt '$(CFLAGS)' - - if !HAVE_OCAMLOPT - OBJECTS = $(BOBJECTS) -diff --git a/common/mlprogress/Makefile.am b/common/mlprogress/Makefile.am -index be88ef2de..af006d228 100644 ---- a/common/mlprogress/Makefile.am -+++ b/common/mlprogress/Makefile.am -@@ -76,7 +76,7 @@ OCAMLPACKAGES = \ - -I $(top_builddir)/ocaml \ - -I $(builddir) - --OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) -+OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) -ccopt '$(CFLAGS)' - - if !HAVE_OCAMLOPT - OBJECTS = $(BOBJECTS) -diff --git a/common/mlstdutils/Makefile.am b/common/mlstdutils/Makefile.am -index e38230db8..75252eb46 100644 ---- a/common/mlstdutils/Makefile.am -+++ b/common/mlstdutils/Makefile.am -@@ -79,7 +79,7 @@ if HAVE_OCAML_PKG_OUNIT - OCAMLPACKAGES_TESTS += -package oUnit - endif - --OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) -+OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) -ccopt '$(CFLAGS)' - - if !HAVE_OCAMLOPT - OBJECTS = $(BOBJECTS) -diff --git a/common/mltools/Makefile.am b/common/mltools/Makefile.am -index 66b18f5de..b326cf56a 100644 ---- a/common/mltools/Makefile.am -+++ b/common/mltools/Makefile.am -@@ -131,7 +131,7 @@ OCAMLCLIBS = \ - $(LIBINTL) \ - -lgnu - --OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) -+OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) -ccopt '$(CFLAGS)' - - if !HAVE_OCAMLOPT - OBJECTS = $(BOBJECTS) -diff --git a/common/mlutils/Makefile.am b/common/mlutils/Makefile.am -index 8627e5b10..77feafa56 100644 ---- a/common/mlutils/Makefile.am -+++ b/common/mlutils/Makefile.am -@@ -74,7 +74,7 @@ OCAMLPACKAGES = \ - -I $(top_builddir)/common/mlstdutils \ - -I $(builddir) - --OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) -+OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) -ccopt '$(CFLAGS)' - - if !HAVE_OCAMLOPT - OBJECTS = $(BOBJECTS) -diff --git a/common/mlvisit/Makefile.am b/common/mlvisit/Makefile.am -index add1fe56e..7230415e7 100644 ---- a/common/mlvisit/Makefile.am -+++ b/common/mlvisit/Makefile.am -@@ -80,7 +80,7 @@ OCAMLPACKAGES = \ - -I $(builddir) - OCAMLPACKAGES_TESTS = $(MLVISIT_CMA) - --OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) -+OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) -ccopt '$(CFLAGS)' - - if !HAVE_OCAMLOPT - OBJECTS = $(BOBJECTS) -diff --git a/common/mlxml/Makefile.am b/common/mlxml/Makefile.am -index eab036b82..7f36b743a 100644 ---- a/common/mlxml/Makefile.am -+++ b/common/mlxml/Makefile.am -@@ -72,7 +72,7 @@ OCAMLPACKAGES = \ - -I $(top_builddir)/gnulib/lib/.libs \ - -I $(builddir) - --OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) -+OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) -ccopt '$(CFLAGS)' - - if !HAVE_OCAMLOPT - OBJECTS = $(BOBJECTS) -diff --git a/customize/Makefile.am b/customize/Makefile.am -index efdd27227..69cf6c13f 100644 ---- a/customize/Makefile.am -+++ b/customize/Makefile.am -@@ -173,7 +173,7 @@ OCAMLCLIBS = \ - $(LIBINTL) \ - -lgnu - --OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) -+OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) -ccopt '$(CFLAGS)' - - virt_customize_DEPENDENCIES = \ - $(top_srcdir)/ocaml-link.sh \ -diff --git a/daemon/Makefile.am b/daemon/Makefile.am -index d9ed5625e..dcae1a66c 100644 ---- a/daemon/Makefile.am -+++ b/daemon/Makefile.am -@@ -347,7 +347,7 @@ OCAMLPACKAGES = \ - -I $(top_builddir)/common/mlpcre/.libs \ - -I $(top_builddir)/gnulib/lib/.libs - --OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) -+OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) -ccopt '$(CFLAGS)' - - if !HAVE_OCAMLOPT - OBJECTS = $(BOBJECTS) -diff --git a/dib/Makefile.am b/dib/Makefile.am -index 316f49903..7c2ab09d6 100644 ---- a/dib/Makefile.am -+++ b/dib/Makefile.am -@@ -99,7 +99,7 @@ OCAMLCLIBS = \ - $(LIBINTL) \ - -lgnu - --OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) -+OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) -ccopt '$(CFLAGS)' - - if !HAVE_OCAMLOPT - OBJECTS = $(BOBJECTS) -diff --git a/generator/Makefile.am b/generator/Makefile.am -index c2d10966a..056d01346 100644 ---- a/generator/Makefile.am -+++ b/generator/Makefile.am -@@ -175,7 +175,7 @@ OCAMLPACKAGES = \ - -I . \ - -I $(top_srcdir)/common/mlstdutils \ - -I $(top_builddir)/common/mlstdutils --OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) -+OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) -ccopt '$(CFLAGS)' - - noinst_PROGRAM = generator - -diff --git a/get-kernel/Makefile.am b/get-kernel/Makefile.am -index 81dfb48b4..75379e21f 100644 ---- a/get-kernel/Makefile.am -+++ b/get-kernel/Makefile.am -@@ -82,7 +82,7 @@ OCAMLCLIBS = \ - $(LIBINTL) \ - -lgnu - --OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) -+OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) -ccopt '$(CFLAGS)' - - if !HAVE_OCAMLOPT - OBJECTS = $(BOBJECTS) -diff --git a/ocaml-link.sh.in b/ocaml-link.sh.in -index fbcc07951..6819c641e 100755 ---- a/ocaml-link.sh.in -+++ b/ocaml-link.sh.in -@@ -47,4 +47,4 @@ done - exec "$@" \ - @OCAML_RUNTIME_VARIANT_PIC_OPTION@ \ - -linkpkg \ -- -cclib "${cclib}" -+ -cclib "@LDFLAGS@ $cclib" -diff --git a/ocaml/Makefile.am b/ocaml/Makefile.am -index b0f2900f2..752fc109c 100644 ---- a/ocaml/Makefile.am -+++ b/ocaml/Makefile.am -@@ -37,7 +37,7 @@ CLEANFILES += t/*.annot t/*.cmi t/*.cmo t/*.cmx t/*.o t/*.a t/*.so - - if HAVE_OCAML - --OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) -+OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) -ccopt '$(CFLAGS)' - - noinst_DATA = mlguestfs.cma META - if HAVE_OCAMLOPT -diff --git a/resize/Makefile.am b/resize/Makefile.am -index 847fb313a..7a4367023 100644 ---- a/resize/Makefile.am -+++ b/resize/Makefile.am -@@ -80,7 +80,7 @@ OCAMLCLIBS = \ - $(LIBINTL) \ - -lgnu - --OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) -+OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) -ccopt '$(CFLAGS)' - - if !HAVE_OCAMLOPT - OBJECTS = $(BOBJECTS) -diff --git a/sparsify/Makefile.am b/sparsify/Makefile.am -index 2ab357a68..2dce5e582 100644 ---- a/sparsify/Makefile.am -+++ b/sparsify/Makefile.am -@@ -88,7 +88,7 @@ OCAMLCLIBS = \ - $(LIBINTL) \ - -lgnu - --OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) -+OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) -ccopt '$(CFLAGS)' - - if !HAVE_OCAMLOPT - OBJECTS = $(BOBJECTS) -diff --git a/sysprep/Makefile.am b/sysprep/Makefile.am -index 0cc9da80a..6ed4ac713 100644 ---- a/sysprep/Makefile.am -+++ b/sysprep/Makefile.am -@@ -136,7 +136,7 @@ OCAMLCLIBS = \ - $(LIBINTL) \ - -lgnu - --OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) -+OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) -ccopt '$(CFLAGS)' - - if !HAVE_OCAMLOPT - OBJECTS = $(BOBJECTS) -diff --git a/v2v/Makefile.am b/v2v/Makefile.am -index 7de050b06..7a1ac329e 100644 ---- a/v2v/Makefile.am -+++ b/v2v/Makefile.am -@@ -201,7 +201,7 @@ OCAMLCLIBS = \ - $(LIBINTL) \ - -lgnu - --OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) -+OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) -ccopt '$(CFLAGS)' - - if !HAVE_OCAMLOPT - OBJECTS = $(BOBJECTS) -diff --git a/v2v/test-harness/Makefile.am b/v2v/test-harness/Makefile.am -index d69188969..22c3b8c49 100644 ---- a/v2v/test-harness/Makefile.am -+++ b/v2v/test-harness/Makefile.am -@@ -47,7 +47,7 @@ OCAMLPACKAGES = \ - -I $(top_builddir)/common/mltools \ - -I $(top_builddir)/v2v - --OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) -+OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) -ccopt '$(CFLAGS)' - - BOBJECTS = \ - $(SOURCES_ML:.ml=.cmo) \ --- -2.21.0 - diff --git a/SOURCES/0046-ocaml-make-sure-to-pass-LDFLAGS-to-ocamlmklibs-linke.patch b/SOURCES/0046-ocaml-make-sure-to-pass-LDFLAGS-to-ocamlmklibs-linke.patch deleted file mode 100644 index 283b782..0000000 --- a/SOURCES/0046-ocaml-make-sure-to-pass-LDFLAGS-to-ocamlmklibs-linke.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 57ed1fc4281462e02604b0e740c4ffa31cf93afb Mon Sep 17 00:00:00 2001 -From: Pino Toscano -Date: Thu, 27 Sep 2018 15:51:01 +0200 -Subject: [PATCH] ocaml: make sure to pass LDFLAGS to ocamlmklibs linker - (RHBZ#1624130) - -Pass the LDFLAGS properly as arguments for the C linker when using -ocamlmklibs via the -ldopt option. - -Followup of commit 34c23403c51a4d59d826c8045e06f9aabc2ceb16. - -(cherry picked from commit 4ff573c352973036b722ec0c9bf79be958b83b2c) ---- - ocaml/Makefile.am | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/ocaml/Makefile.am b/ocaml/Makefile.am -index 752fc109c..4d13eed97 100644 ---- a/ocaml/Makefile.am -+++ b/ocaml/Makefile.am -@@ -64,14 +64,14 @@ endif - - stamp-mlguestfs: libguestfsocaml.a $(guestfs_cmm) - $(OCAMLMKLIB) -o mlguestfs \ -+ -ldopt '$(LDFLAGS)' \ - $(libguestfsocaml_a_OBJECTS) guestfs.cmo \ -- $(LDFLAGS) \ - $(LTLIBINTL) \ - -L../lib/.libs -lguestfs - if HAVE_OCAMLOPT - $(OCAMLMKLIB) -o mlguestfs \ -+ -ldopt '$(LDFLAGS)' \ - $(libguestfsocaml_a_OBJECTS) guestfs.cmx \ -- $(LDFLAGS) \ - $(LTLIBINTL) \ - -L../lib/.libs -lguestfs - endif --- -2.21.0 - diff --git a/SOURCES/0046-rhv-upload-Fix-waiting-for-transfer.patch b/SOURCES/0046-rhv-upload-Fix-waiting-for-transfer.patch new file mode 100644 index 0000000..cc6fd5b --- /dev/null +++ b/SOURCES/0046-rhv-upload-Fix-waiting-for-transfer.patch @@ -0,0 +1,89 @@ +From d132157c9e0b6b990cd989662f5499644508de97 Mon Sep 17 00:00:00 2001 +From: Nir Soffer +Date: Thu, 28 Nov 2019 20:36:32 +0200 +Subject: [PATCH] rhv-upload: Fix waiting for transfer + +We were not considering failures while initializing the transfer. In +this case the transfer phase can change to PAUSED_SYSTEM or +FINISHED_FAILURE, and transfer_url will be None, which failed the +upload with a misleading error: + + RuntimeError: direct upload to host not supported, requires + ovirt-engine >= 4.2 and only works when virt-v2v is run within the + oVirt/RHV environment, eg. on an oVirt node + +Change the wait loop to consider all cases: +- Transfer failed and was removed +- Transfer failed and will be removed soon +- Transfer paused by the system (cancel required) +- Unexpected transfer phase (cancel required) +- Timeout waiting for TRANSFERRING state (cancel required) + +Reported-by: Xiaodai Wang + +(cherry picked from commit 40e1844827e4d096b1919a2159f9effc41915a73 +in virt-v2v) +--- + v2v/rhv-upload-plugin.py | 41 +++++++++++++++++++++++++++++++--------- + 1 file changed, 32 insertions(+), 9 deletions(-) + +diff --git a/v2v/rhv-upload-plugin.py b/v2v/rhv-upload-plugin.py +index 9b83d1cfa..14d4e37fb 100644 +--- a/v2v/rhv-upload-plugin.py ++++ b/v2v/rhv-upload-plugin.py +@@ -185,20 +185,43 @@ def open(readonly): + # Get a reference to the created transfer service. + transfer_service = transfers_service.image_transfer_service(transfer.id) + +- # After adding a new transfer for the disk, the transfer's status +- # will be INITIALIZING. Wait until the init phase is over. The +- # actual transfer can start when its status is "Transferring". ++ # Wait until transfer's phase change from INITIALIZING to TRANSFERRING. On ++ # errors transfer's phase can change to PAUSED_SYSTEM or FINISHED_FAILURE. ++ # If the transfer was paused, we need to cancel it to remove the disk, ++ # otherwise the system will remove the disk and transfer shortly after. ++ + endt = time.time() + timeout + while True: +- transfer = transfer_service.get() +- if transfer.phase != types.ImageTransferPhase.INITIALIZING: ++ time.sleep(1) ++ try: ++ transfer = transfer_service.get() ++ except sdk.NotFoundError: ++ # The system has removed the disk and the transfer. ++ raise RuntimeError("transfer %s was removed" % transfer.id) ++ ++ if transfer.phase == types.ImageTransferPhase.FINISHED_FAILURE: ++ # The system will remove the disk and the transfer soon. ++ raise RuntimeError( ++ "transfer %s has failed" % transfer.id) ++ ++ if transfer.phase == types.ImageTransferPhase.PAUSED_SYSTEM: ++ transfer_service.cancel() ++ raise RuntimeError( ++ "transfer %s was paused by system" % transfer.id) ++ ++ if transfer.phase == types.ImageTransferPhase.TRANSFERRING: + break +- if time.time() > endt: ++ ++ if transfer.phase != types.ImageTransferPhase.INITIALIZING: ++ transfer_service.cancel() + raise RuntimeError( +- "timed out waiting for transfer %s status != INITIALIZING" +- % transfer.id) ++ "unexpected transfer %s phase %s" ++ % (transfer.id, transfer.phase)) + +- time.sleep(1) ++ if time.time() > endt: ++ transfer_service.cancel() ++ raise RuntimeError( ++ "timed out waiting for transfer %s" % transfer.id) + + # Now we have permission to start the transfer. + if params['rhv_direct']: +-- +2.25.4 + diff --git a/SOURCES/0047-v2v-Model-machine-type-explicitly.patch b/SOURCES/0047-v2v-Model-machine-type-explicitly.patch deleted file mode 100644 index 24a56c7..0000000 --- a/SOURCES/0047-v2v-Model-machine-type-explicitly.patch +++ /dev/null @@ -1,323 +0,0 @@ -From 81f35e441d06bff2bf60bff6354d53de137847d9 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Tue, 19 Jun 2018 10:44:57 +0100 -Subject: [PATCH] v2v: Model machine type explicitly. - -QEMU for x86 supports two machine types, "pc" (emulating the ancient -Intel i440FX chipset originally used by the Pentium Pro), and "q35" -(https://wiki.qemu.org/Features/Q35). - -Currently virt-v2v does not set any machine type, so libvirt or the -target hypervisor will choose some default, probably i440fx. The -latest advice from the QEMU and libvirt communities is not to rely on -the default machine type but to specify what we need explicitly, but -it may also be that the libvirt configuration file has been changed to -set the default machine type to Q35 (either by the distro or the end -user). - -None of this matters for reasonably new guests since they can boot -with either chipset. However there are some very old guests (notably -Windows XP) which cannot handle Q35. - -This commit changes virt-v2v so it always tries to specify the machine -type explicitly (assuming the target supports that, and not all of -them do). For x86_64 guests this patch always selects i440fx (pc). -In future we hope to get the correct machine type for the guest from -libosinfo but this is not available yet. - -For non-x86 architectures we select the "virt" model which will -probably only work for AArch64. More work is needed for POWER. - -For secure boot we still have to force the machine type to Q35. In a -future version this forcing can be removed since any guest which is -using secure boot will be new enough that it'll be using Q35 anyway -(on x86). - -(cherry picked from commit 55879b2f2c5b205352f48f999e20efd9b455ea43) ---- - v2v/convert_linux.ml | 7 +++++++ - v2v/convert_windows.ml | 7 +++++++ - v2v/create_libvirt_xml.ml | 37 +++++++++++++++++++++++++------------ - v2v/create_ovf.ml | 2 ++ - v2v/output_glance.ml | 5 +++++ - v2v/output_qemu.ml | 30 +++++++++++++++++++----------- - v2v/test-v2v-i-ova.xml | 2 +- - v2v/types.ml | 8 ++++++++ - v2v/types.mli | 6 ++++-- - 9 files changed, 78 insertions(+), 26 deletions(-) - -diff --git a/v2v/convert_linux.ml b/v2v/convert_linux.ml -index 4a7447fe1..fd6b71ba4 100644 ---- a/v2v/convert_linux.ml -+++ b/v2v/convert_linux.ml -@@ -122,6 +122,12 @@ let convert (g : G.guestfs) inspect source output rcaps = - - SELinux_relabel.relabel g; - -+ (* XXX Look up this information in libosinfo in future. *) -+ let machine = -+ match inspect.i_arch with -+ | "i386"|"x86_64" -> I440FX -+ | _ -> Virt in -+ - (* Return guest capabilities from the convert () function. *) - let guestcaps = { - gcaps_block_bus = block_type; -@@ -130,6 +136,7 @@ let convert (g : G.guestfs) inspect source output rcaps = - gcaps_virtio_rng = kernel.ki_supports_virtio_rng; - gcaps_virtio_balloon = kernel.ki_supports_virtio_balloon; - gcaps_isa_pvpanic = kernel.ki_supports_isa_pvpanic; -+ gcaps_machine = machine; - gcaps_arch = Utils.kvm_arch inspect.i_arch; - gcaps_acpi = acpi; - } in -diff --git a/v2v/convert_windows.ml b/v2v/convert_windows.ml -index 163319545..1e058136e 100644 ---- a/v2v/convert_windows.ml -+++ b/v2v/convert_windows.ml -@@ -212,6 +212,12 @@ let convert (g : G.guestfs) inspect source output rcaps = - warning (f_"this guest has Anti-Virus (AV) software and a new virtio block device driver was installed. In some circumstances, AV may prevent new drivers from working (resulting in a 7B boot error). If this happens, try disabling AV before doing the conversion."); - ); - -+ (* XXX Look up this information in libosinfo in future. *) -+ let machine = -+ match inspect.i_arch with -+ | "i386"|"x86_64" -> I440FX -+ | _ -> Virt in -+ - (* Return guest capabilities from the convert () function. *) - let guestcaps = { - gcaps_block_bus = block_driver; -@@ -220,6 +226,7 @@ let convert (g : G.guestfs) inspect source output rcaps = - gcaps_virtio_rng = virtio_rng_supported; - gcaps_virtio_balloon = virtio_ballon_supported; - gcaps_isa_pvpanic = isa_pvpanic_supported; -+ gcaps_machine = machine; - gcaps_arch = Utils.kvm_arch inspect.i_arch; - gcaps_acpi = true; - } in -diff --git a/v2v/create_libvirt_xml.ml b/v2v/create_libvirt_xml.ml -index fbe90eeaa..8a34c94b0 100644 ---- a/v2v/create_libvirt_xml.ml -+++ b/v2v/create_libvirt_xml.ml -@@ -81,15 +81,17 @@ let create_libvirt_xml ?pool source target_buses guestcaps - match target_firmware with - | TargetBIOS -> None - | TargetUEFI -> Some (find_uefi_firmware guestcaps.gcaps_arch) in -- let secure_boot_required = -- match uefi_firmware with -- | Some { Uefi.flags = flags } -- when List.mem Uefi.UEFI_FLAG_SECURE_BOOT_REQUIRED flags -> true -- | _ -> false in -- (* Currently these are required by secure boot, but in theory they -- * might be independent properties. -- *) -- let machine_q35 = secure_boot_required in -+ let machine, secure_boot_required = -+ match guestcaps.gcaps_machine, uefi_firmware with -+ | _, Some { Uefi.flags = flags } -+ when List.mem Uefi.UEFI_FLAG_SECURE_BOOT_REQUIRED flags -> -+ (* Force machine type to Q35 because PC does not support -+ * secure boot. We must remove this when we get the -+ * correct machine type from libosinfo in future. XXX -+ *) -+ Q35, true -+ | machine, _ -> -+ machine, false in - let smm = secure_boot_required in - - (* We have the machine features of the guest when it was on the -@@ -140,7 +142,18 @@ let create_libvirt_xml ?pool source target_buses guestcaps - - (* The section subelements. *) - let os_section = -- let machine = if machine_q35 then [ "machine", "q35" ] else [] in -+ let os = ref [] in -+ -+ let machine = -+ match machine with -+ | I440FX -> "pc" -+ | Q35 -> "q35" -+ | Virt -> "virt" in -+ -+ List.push_back os -+ (e "type" ["arch", guestcaps.gcaps_arch; -+ "machine", machine] -+ [PCData "hvm"]); - - let loader = - match uefi_firmware with -@@ -152,8 +165,8 @@ let create_libvirt_xml ?pool source target_buses guestcaps - [ PCData code ]; - e "nvram" ["template", vars_template] [] ] in - -- (e "type" (["arch", guestcaps.gcaps_arch] @ machine) [PCData "hvm"]) -- :: loader in -+ List.push_back_list os loader; -+ !os in - - List.push_back_list body [ - e "os" [] os_section; -diff --git a/v2v/create_ovf.ml b/v2v/create_ovf.ml -index 5db239d66..01970013e 100644 ---- a/v2v/create_ovf.ml -+++ b/v2v/create_ovf.ml -@@ -602,6 +602,8 @@ let rec create_ovf source targets guestcaps inspect - source.s_vcpu memsize_mb)] - ] in - -+ (* XXX How to set machine type for Q35? *) -+ - List.push_back virtual_hardware_section_items ( - e "Item" [] ([ - e "rasd:Caption" [] [PCData (sprintf "%d virtual cpu" source.s_vcpu)]; -diff --git a/v2v/output_glance.ml b/v2v/output_glance.ml -index c334def42..96c31da59 100644 ---- a/v2v/output_glance.ml -+++ b/v2v/output_glance.ml -@@ -86,6 +86,11 @@ object - (match guestcaps.gcaps_video with - | QXL -> "qxl" - | Cirrus -> "cirrus"); -+ "hw_machine_type", -+ (match guestcaps.gcaps_machine with -+ | I440FX -> "pc" -+ | Q35 -> "q35" -+ | Virt -> "virt"); - "architecture", guestcaps.gcaps_arch; - "hypervisor_type", "kvm"; - "vm_mode", "hvm"; -diff --git a/v2v/output_qemu.ml b/v2v/output_qemu.ml -index 952660de2..e23f22e12 100644 ---- a/v2v/output_qemu.ml -+++ b/v2v/output_qemu.ml -@@ -56,17 +56,25 @@ object - match target_firmware with - | TargetBIOS -> None - | TargetUEFI -> Some (find_uefi_firmware guestcaps.gcaps_arch) in -- let secure_boot_required = -- match uefi_firmware with -- | Some { Uefi.flags } -- when List.mem Uefi.UEFI_FLAG_SECURE_BOOT_REQUIRED flags -> true -- | _ -> false in -- (* Currently these are required by secure boot, but in theory they -- * might be independent properties. -- *) -- let machine_q35 = secure_boot_required in -+ let machine, secure_boot_required = -+ match guestcaps.gcaps_machine, uefi_firmware with -+ | _, Some { Uefi.flags } -+ when List.mem Uefi.UEFI_FLAG_SECURE_BOOT_REQUIRED flags -> -+ (* Force machine type to Q35 because PC does not support -+ * secure boot. We must remove this when we get the -+ * correct machine type from libosinfo in future. XXX -+ *) -+ Q35, true -+ | machine, _ -> -+ machine, false in - let smm = secure_boot_required in - -+ let machine = -+ match machine with -+ | I440FX -> "pc" -+ | Q35 -> "q35" -+ | Virt -> "virt" in -+ - (* Construct the command line. Note that the [Qemuopts] - * module deals with shell and qemu comma quoting. - *) -@@ -80,8 +88,8 @@ object - - flag "-no-user-config"; flag "-nodefaults"; - arg "-name" source.s_name; -- arg_list "-machine" (if machine_q35 then ["q35"] else [] @ -- if smm then ["smm=on"] else [] @ -+ arg_list "-machine" (machine :: -+ (if smm then ["smm=on"] else []) @ - ["accel=kvm:tcg"]); - - (match uefi_firmware with -diff --git a/v2v/test-v2v-i-ova.xml b/v2v/test-v2v-i-ova.xml -index 5a303b80a..b277193a8 100644 ---- a/v2v/test-v2v-i-ova.xml -+++ b/v2v/test-v2v-i-ova.xml -@@ -10,7 +10,7 @@ - - - -- hvm -+ hvm - - destroy - restart -diff --git a/v2v/types.ml b/v2v/types.ml -index bb77e5669..9851386f7 100644 ---- a/v2v/types.ml -+++ b/v2v/types.ml -@@ -401,6 +401,7 @@ type guestcaps = { - gcaps_virtio_rng : bool; - gcaps_virtio_balloon : bool; - gcaps_isa_pvpanic : bool; -+ gcaps_machine : guestcaps_machine; - gcaps_arch : string; - gcaps_acpi : bool; - } -@@ -412,6 +413,7 @@ and requested_guestcaps = { - and guestcaps_block_type = Virtio_blk | Virtio_SCSI | IDE - and guestcaps_net_type = Virtio_net | E1000 | RTL8139 - and guestcaps_video_type = QXL | Cirrus -+and guestcaps_machine = I440FX | Q35 | Virt - - let string_of_block_type = function - | Virtio_blk -> "virtio-blk" -@@ -424,17 +426,23 @@ let string_of_net_type = function - let string_of_video = function - | QXL -> "qxl" - | Cirrus -> "cirrus" -+let string_of_machine = function -+ | I440FX -> "i440fx" -+ | Q35 -> "q35" -+ | Virt -> "virt" - - let string_of_guestcaps gcaps = - sprintf "\ - gcaps_block_bus = %s - gcaps_net_bus = %s - gcaps_video = %s -+gcaps_machine = %s - gcaps_arch = %s - gcaps_acpi = %b - " (string_of_block_type gcaps.gcaps_block_bus) - (string_of_net_type gcaps.gcaps_net_bus) - (string_of_video gcaps.gcaps_video) -+ (string_of_machine gcaps.gcaps_machine) - gcaps.gcaps_arch - gcaps.gcaps_acpi - -diff --git a/v2v/types.mli b/v2v/types.mli -index f60e5c98f..5e33b1de9 100644 ---- a/v2v/types.mli -+++ b/v2v/types.mli -@@ -240,8 +240,9 @@ type guestcaps = { - gcaps_virtio_balloon : bool; (** Guest supports virtio balloon. *) - gcaps_isa_pvpanic : bool; (** Guest supports ISA pvpanic device. *) - -- gcaps_arch : string; (** Architecture that KVM must emulate. *) -- gcaps_acpi : bool; (** True if guest supports acpi. *) -+ gcaps_machine : guestcaps_machine; (** Machine model. *) -+ gcaps_arch : string; (** Architecture that KVM must emulate. *) -+ gcaps_acpi : bool; (** True if guest supports acpi. *) - } - (** Guest capabilities after conversion. eg. Was virtio found or installed? *) - -@@ -257,6 +258,7 @@ and requested_guestcaps = { - and guestcaps_block_type = Virtio_blk | Virtio_SCSI | IDE - and guestcaps_net_type = Virtio_net | E1000 | RTL8139 - and guestcaps_video_type = QXL | Cirrus -+and guestcaps_machine = I440FX | Q35 | Virt - - val string_of_guestcaps : guestcaps -> string - val string_of_requested_guestcaps : requested_guestcaps -> string --- -2.21.0 - diff --git a/SOURCES/0047-v2v-Optimize-convert-for-images-with-small-holes.patch b/SOURCES/0047-v2v-Optimize-convert-for-images-with-small-holes.patch new file mode 100644 index 0000000..e09d484 --- /dev/null +++ b/SOURCES/0047-v2v-Optimize-convert-for-images-with-small-holes.patch @@ -0,0 +1,84 @@ +From 8d39f6bcf21a7c76e29c270b9304c978bbf2e8ba Mon Sep 17 00:00:00 2001 +From: Nir Soffer +Date: Fri, 1 Nov 2019 22:56:18 +0100 +Subject: [PATCH] v2v: Optimize convert for images with small holes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +"qemu-img convert" detects zeroes in allocated areas and punch holes in +the destination image. This may save space on the destination image, but +slows down conversion when using outputs such as rhv-upload, which have +very large overhead per requests. + +Using the -S flag, we can treat small areas filled with zeroes as data, +limiting the number of requests, and speeding the operation. + +Here is an example converting Fedora 30 image: + +$ virt-builder fedora-30 -o src.img +... + +$ qemu-img map -f raw --output json src.img | wc -l +213 + +$ qemu-img convert -f raw -O raw -t none -T none src.img dst.img + +$ qemu-img map -f raw --output json dst.img | wc -l +1443 + +$ ls -lhs *.img +1.2G -rw-r--r--. 1 nsoffer nsoffer 6.0G Nov  1 21:48 dst.img +1.2G -rw-r--r--. 1 nsoffer nsoffer 6.0G Nov  1 21:46 src.img + +Qemu did 1443 writes instead of 213 (5.8X). Lets repeat this conversion +with the -S option: + +$ qemu-img convert -f raw -O raw -t none -T none -S 64k src.img dst.img + +$ qemu-img map -f raw --output json dst.img | wc -l +213 + +$ ls -lhs *.img +1.2G -rw-r--r--. 1 nsoffer nsoffer 6.0G Nov  1 21:48 dst.img +1.2G -rw-r--r--. 1 nsoffer nsoffer 6.0G Nov  1 21:46 src.img + +Picking a good value for -S is not easy. Testing show that 64k is best +value for this test image for limiting the number of requests: + +$ for size in 4k 8k 16k 32k 64k; do \ + printf "%5s: " $size; \ + qemu-img convert -f raw -O raw -t none -T none -S $size src.img dst.img; \ + qemu-img map -f raw --output json dst.img | wc -l; \ +done +   4k: 1443 +   8k: 731 +  16k: 521 +  32k: 387 +  64k: 213 + +We need more testing with oVirt to measure the performance improvement +and pick a good value. This should probably be an option, but lets start +with a minimal change. + +(cherry picked from commit 2aa78ade2d48e926b7b04050338ebd8a0c5e3f05 +in virt-v2v) +--- + v2v/v2v.ml | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/v2v/v2v.ml b/v2v/v2v.ml +index d7a868659..a81a2320a 100644 +--- a/v2v/v2v.ml ++++ b/v2v/v2v.ml +@@ -754,6 +754,7 @@ and copy_targets cmdline targets input output = + (if not (quiet ()) then [ "-p" ] else []) @ + [ "-n"; "-f"; "qcow2"; "-O"; t.target_format ] @ + (if cmdline.compressed then [ "-c" ] else []) @ ++ [ "-S"; "64k" ] @ + [ overlay_file; filename ] in + let start_time = gettimeofday () in + if run_command cmd <> 0 then +-- +2.25.4 + diff --git a/SOURCES/0048-v2v-o-rhv-upload-Make-oo-rhv-cafile-optional-in-all-.patch b/SOURCES/0048-v2v-o-rhv-upload-Make-oo-rhv-cafile-optional-in-all-.patch new file mode 100644 index 0000000..c18d6c9 --- /dev/null +++ b/SOURCES/0048-v2v-o-rhv-upload-Make-oo-rhv-cafile-optional-in-all-.patch @@ -0,0 +1,49 @@ +From 49623c945c93b878d13c0539eddf2d625f5aeb3c Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Wed, 15 Jan 2020 11:12:17 +0000 +Subject: [PATCH] v2v: -o rhv-upload: Make -oo rhv-cafile optional in all cases + (RHBZ#1791240). + +This is actually not required, because ovirtsdk4 will use the system's +global trust store if necessary. Therefore we can make it optional in +all cases. + +(cherry picked from commit 65ee9387d4be0e3c5cd214b967fef7a1a8841233 +in virt-v2v) +--- + v2v/output_rhv_upload.ml | 2 -- + v2v/virt-v2v-output-rhv.pod | 5 ++++- + 2 files changed, 4 insertions(+), 3 deletions(-) + +diff --git a/v2v/output_rhv_upload.ml b/v2v/output_rhv_upload.ml +index 2c8c18732..e1d06867b 100644 +--- a/v2v/output_rhv_upload.ml ++++ b/v2v/output_rhv_upload.ml +@@ -81,8 +81,6 @@ let parse_output_options options = + let rhv_direct = !rhv_direct in + let rhv_verifypeer = !rhv_verifypeer in + let rhv_disk_uuids = Option.map List.rev !rhv_disk_uuids in +- if rhv_verifypeer && rhv_cafile = None then +- error (f_"-o rhv-upload: must use ‘-oo rhv-cafile’ to supply the path to the oVirt or RHV user’s ‘ca.pem’ file"); + + { rhv_cafile; rhv_cluster; rhv_direct; rhv_verifypeer; rhv_disk_uuids } + +diff --git a/v2v/virt-v2v-output-rhv.pod b/v2v/virt-v2v-output-rhv.pod +index 04a894268..4520c9184 100644 +--- a/v2v/virt-v2v-output-rhv.pod ++++ b/v2v/virt-v2v-output-rhv.pod +@@ -101,7 +101,10 @@ The storage domain. + The F file (Certificate Authority), copied from + F on the oVirt engine. + +-This option must be specified if I<-oo rhv-verifypeer> is enabled. ++If I<-oo rhv-verifypeer> is enabled then this option can ++be used to control which CA is used to verify the client’s ++identity. If this option is not used then the system’s ++global trust store is used. + + =item I<-oo rhv-cluster=>C + +-- +2.25.4 + diff --git a/SOURCES/0048-v2v-windows-Fix-rhev-apt-command-line-RHBZ-1624902.patch b/SOURCES/0048-v2v-windows-Fix-rhev-apt-command-line-RHBZ-1624902.patch deleted file mode 100644 index 548cc88..0000000 --- a/SOURCES/0048-v2v-windows-Fix-rhev-apt-command-line-RHBZ-1624902.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 8a4072c4b16e20c6ac55cbf350bfae2d0d1c7a0b Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Mon, 3 Sep 2018 15:24:05 +0100 -Subject: [PATCH] v2v: windows: Fix rhev-apt command line (RHBZ#1624902). - -See: -https://bugzilla.redhat.com/show_bug.cgi?id=1584678#c15 - -Fixes commit bcdbe6405c10ecb7374ae47eee6385be17dbd49e. However this -bug was copied directly from old virt-v2v which did the same thing -(from lib/Sys/VirtConvert/Converter/Windows.pm): - - echo installing rhev-apt >>log.txt - "rhev-apt.exe" /S /v /qn >>log.txt - -Thanks: Lev Veyde -(cherry picked from commit e12c56176abcc2d970a35f83bffc95f7ad1b2aab) ---- - v2v/convert_windows.ml | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/v2v/convert_windows.ml b/v2v/convert_windows.ml -index 1e058136e..0346ba4fe 100644 ---- a/v2v/convert_windows.ml -+++ b/v2v/convert_windows.ml -@@ -347,7 +347,7 @@ echo Wait for PnP to complete - @echo off - - echo installing rhev-apt --\"\\rhev-apt.exe\" /S /v /qn -+\"\\rhev-apt.exe\" /S /v/qn - - echo starting rhev-apt - net start rhev-apt --- -2.21.0 - diff --git a/SOURCES/0049-docs-Fix-update-crypto-policies-command-RHBZ-1791257.patch b/SOURCES/0049-docs-Fix-update-crypto-policies-command-RHBZ-1791257.patch new file mode 100644 index 0000000..378986c --- /dev/null +++ b/SOURCES/0049-docs-Fix-update-crypto-policies-command-RHBZ-1791257.patch @@ -0,0 +1,33 @@ +From 03b67600b98e8af2ea199f8643b2993c1effc60f Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Wed, 15 Jan 2020 10:55:27 +0000 +Subject: [PATCH] docs: Fix update-crypto-policies command (RHBZ#1791257). + +The command as documented was wrong. We need to use the --set option +to change the policy. + +Fixes commit d5cbe7b4bee5dec9e28b1db03e933c97ef6d11e0. +Thanks: Xiaodai Wang + +(cherry picked from commit 0edf419e983fe75daef9eaa7bd0578cbcada2e73 +in virt-v2v) +--- + v2v/virt-v2v-input-xen.pod | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/v2v/virt-v2v-input-xen.pod b/v2v/virt-v2v-input-xen.pod +index 4bb5d2dc2..9fd5065f1 100644 +--- a/v2v/virt-v2v-input-xen.pod ++++ b/v2v/virt-v2v-input-xen.pod +@@ -37,7 +37,7 @@ to interoperate with RHEL 5 sshd are disabled. To enable them you may + need to run this command on the conversion server (ie. ssh client), + but read L first: + +- # update-crypto-policies LEGACY ++ # update-crypto-policies --set LEGACY + + =head2 Test libvirt connection to remote Xen host + +-- +2.25.4 + diff --git a/SOURCES/0049-v2v-docs-Describe-support-for-SHA-2-certs-for-Window.patch b/SOURCES/0049-v2v-docs-Describe-support-for-SHA-2-certs-for-Window.patch deleted file mode 100644 index 5065dfb..0000000 --- a/SOURCES/0049-v2v-docs-Describe-support-for-SHA-2-certs-for-Window.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 4d78c436b15742c25288bcae441a9782ee316fe5 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Mon, 3 Sep 2018 14:30:21 +0100 -Subject: [PATCH] v2v: docs: Describe support for SHA-2 certs for Windows 7 / - 2008 R2 (RHBZ#1624878). - -Thanks: Yan Vugenfirer. -(cherry picked from commit 741ef228cd8d17bd1a8a60a2cfa83c3937120ede) ---- - v2v/virt-v2v.pod | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - -diff --git a/v2v/virt-v2v.pod b/v2v/virt-v2v.pod -index 893e47fb9..dc443b717 100644 ---- a/v2v/virt-v2v.pod -+++ b/v2v/virt-v2v.pod -@@ -1097,6 +1097,20 @@ This can also prevent booting with a 7B error [see previous section] - if the guest has group policy containing - C. - -+=head2 Support for SHA-2 certificates in Windows 7 and Windows Server 2008 R2 -+ -+Later versions of the Windows virtio drivers are signed using SHA-2 -+certificates (instead of SHA-1). The original shipping Windows 7 and -+Windows Server 2008 R2 did not understand SHA-2 certificates and so -+the Windows virtio drivers will not install properly. -+ -+To fix this you must apply SHA-2 Code Signing Support from: -+L -+before converting the guest. -+ -+For further information see: -+L -+ - =head1 UEFI - - VMware allows you to present UEFI firmware to guests (instead of the --- -2.21.0 - diff --git a/SOURCES/0050-add-versioned-directory-for-guest-agent-on-EL8.patch b/SOURCES/0050-add-versioned-directory-for-guest-agent-on-EL8.patch new file mode 100644 index 0000000..e06ddaf --- /dev/null +++ b/SOURCES/0050-add-versioned-directory-for-guest-agent-on-EL8.patch @@ -0,0 +1,35 @@ +From ebc6680ab1030c763a6c4764f6045734c41f0e7f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Golembiovsk=C3=BD?= +Date: Thu, 16 Jan 2020 16:05:10 +0100 +Subject: [PATCH] add versioned directory for guest agent on EL8 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +There was no source directory for EL8 guest agent (only EL6 and EL7). + +RHBZ#1791802 + +Signed-off-by: Tomáš Golembiovský + +(cherry picked from commit 79dd6a6bbb7e95691be18f54d601318d7d713702 +in virt-v2v) +--- + v2v/windows_virtio.ml | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/v2v/windows_virtio.ml b/v2v/windows_virtio.ml +index a6dc29f2c..7be63a316 100644 +--- a/v2v/windows_virtio.ml ++++ b/v2v/windows_virtio.ml +@@ -192,6 +192,7 @@ and install_linux_tools g inspect = + (match inspect.i_major_version with + | 6 -> Some "el6" + | 7 -> Some "el7" ++ | 8 -> Some "el8" + | _ -> None) + | "sles" | "suse-based" | "opensuse" -> Some "lp151" + | _ -> None in +-- +2.25.4 + diff --git a/SOURCES/0050-v2v-docs-Remove-sentence-about-supporting-qemu-kvm-r.patch b/SOURCES/0050-v2v-docs-Remove-sentence-about-supporting-qemu-kvm-r.patch deleted file mode 100644 index 77def1d..0000000 --- a/SOURCES/0050-v2v-docs-Remove-sentence-about-supporting-qemu-kvm-r.patch +++ /dev/null @@ -1,39 +0,0 @@ -From e4ba4ed8bbb033318e85407099a87912124e0040 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Wed, 21 Nov 2018 10:55:45 +0000 -Subject: [PATCH] v2v: docs: Remove sentence about supporting qemu-kvm-rhev in - RHEL (RHBZ#1651977). -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The previous support documentation said that for UEFI guests, when -using RHEL ≥ 7.3 host, you must use qemu-kvm-rhev. For RHEL 8 this is -inaccurate since qemu-kvm-rhev no longer exists. - -To fix this I've dropped the whole sentence. It only applies to the -downstream product (RHEL) and so RHEL can add the right documentation -if it needs to. - -Thanks: Ming Xie, Pino Toscano. -(cherry picked from commit 0e6bbcee7e30f6f1c3b92b77b5214c549d023044) ---- - v2v/virt-v2v.pod | 2 -- - 1 file changed, 2 deletions(-) - -diff --git a/v2v/virt-v2v.pod b/v2v/virt-v2v.pod -index dc443b717..4b53cdc0e 100644 ---- a/v2v/virt-v2v.pod -+++ b/v2v/virt-v2v.pod -@@ -1132,8 +1132,6 @@ automatically, but note that the same version of OVMF must be - installed on the conversion host as is installed on the target - hypervisor, else you will have to adjust paths in the metadata. - --On RHEL E 7.3, only qemu-kvm-rhev (not qemu-kvm) is supported. -- - =item UEFI on OpenStack - - Not supported. --- -2.21.0 - diff --git a/SOURCES/0051-v2v-fix-path-to-source-when-copying-files-from-guest.patch b/SOURCES/0051-v2v-fix-path-to-source-when-copying-files-from-guest.patch new file mode 100644 index 0000000..7210464 --- /dev/null +++ b/SOURCES/0051-v2v-fix-path-to-source-when-copying-files-from-guest.patch @@ -0,0 +1,41 @@ +From 1d0a22aa3f950330b0cf9c5e874642b5a02edf17 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Golembiovsk=C3=BD?= +Date: Fri, 8 Feb 2019 11:44:41 +0100 +Subject: [PATCH] v2v: fix path to source when copying files from guest tools + directory +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The debug message was slightly changed too to better match the similar +message for ISO case. It refers to the root directory instead of the +specific subdirectory inside guest tools. + +Signed-off-by: Tomáš Golembiovský +(cherry picked from commit f4bda5571a36da42bdc800c10f2c85cf20bf5c85) +--- + v2v/windows_virtio.ml | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/v2v/windows_virtio.ml b/v2v/windows_virtio.ml +index 7be63a316..70f0bf09d 100644 +--- a/v2v/windows_virtio.ml ++++ b/v2v/windows_virtio.ml +@@ -309,10 +309,11 @@ and copy_drivers g inspect driverdir = + and copy_from_virtio_win g inspect srcdir destdir filter missing = + let ret = ref [] in + if is_directory virtio_win then ( +- let dir = virtio_win // srcdir in +- debug "windows: copy_from_virtio_win: guest tools source directory %s" dir; ++ debug "windows: copy_from_virtio_win: guest tools source directory %s" ++ virtio_win; + +- if not (is_directory srcdir) then missing () ++ let dir = virtio_win // srcdir in ++ if not (is_directory dir) then missing () + else ( + let cmd = sprintf "cd %s && find -L -type f" (quote dir) in + let paths = external_command cmd in +-- +2.25.4 + diff --git a/SOURCES/0051-v2v-linux-improve-regex-for-resume-entries-RHBZ-1651.patch b/SOURCES/0051-v2v-linux-improve-regex-for-resume-entries-RHBZ-1651.patch deleted file mode 100644 index 11e6a5f..0000000 --- a/SOURCES/0051-v2v-linux-improve-regex-for-resume-entries-RHBZ-1651.patch +++ /dev/null @@ -1,33 +0,0 @@ -From e003f5b8e7fe673aa462199e6190ea58a0cef011 Mon Sep 17 00:00:00 2001 -From: Pino Toscano -Date: Tue, 4 Dec 2018 18:43:59 +0100 -Subject: [PATCH] v2v: linux: improve regex for resume= entries (RHBZ#1651987) - -Add few more characters for the devices of resume= entries in the -command line of grub: this way it is possible to match also /dev/mapper -devices. - -This should require no further processing, since the names of the -/dev/mapper devices do not change after the conversion. - -(cherry picked from commit 50b08fd84bc035ada9e7a3cdda6c36ab7e418e8c) ---- - v2v/convert_linux.ml | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/v2v/convert_linux.ml b/v2v/convert_linux.ml -index fd6b71ba4..da06352a0 100644 ---- a/v2v/convert_linux.ml -+++ b/v2v/convert_linux.ml -@@ -983,7 +983,7 @@ let convert (g : G.guestfs) inspect source output rcaps = - List.flatten (List.map Array.to_list (List.map g#aug_match paths)) in - - (* Map device names for each entry. *) -- let rex_resume = PCRE.compile "^resume=(/dev/[a-z\\d]+)(.*)$" -+ let rex_resume = PCRE.compile "^resume=(/dev/[-a-z\\d/_]+)(.*)$" - and rex_device_cciss = PCRE.compile "^/dev/(cciss/c\\d+d\\d+)(?:p(\\d+))?$" - and rex_device = PCRE.compile "^/dev/([a-z]+)(\\d*)?$" in - --- -2.21.0 - diff --git a/SOURCES/0052-inspection-Parse-os-release-opensuse-leap-as-opensus.patch b/SOURCES/0052-inspection-Parse-os-release-opensuse-leap-as-opensus.patch deleted file mode 100644 index 4be07d6..0000000 --- a/SOURCES/0052-inspection-Parse-os-release-opensuse-leap-as-opensus.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 1e72a13be2bbe054f0a15cdf5cc08c58fe5c43ab Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Mon, 1 Oct 2018 09:51:15 +0100 -Subject: [PATCH] inspection: Parse os-release "opensuse-leap" as opensuse - (RHBZ#1634248). - -(cherry picked from commit 70407cd622dda6f088a0876e1e1ae669e9f8a281) ---- - daemon/inspect_fs_unix.ml | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/daemon/inspect_fs_unix.ml b/daemon/inspect_fs_unix.ml -index f4b2fea14..33b93256f 100644 ---- a/daemon/inspect_fs_unix.ml -+++ b/daemon/inspect_fs_unix.ml -@@ -142,7 +142,7 @@ and distro_of_os_release_id = function - | "frugalware" -> Some DISTRO_FRUGALWARE - | "mageia" -> Some DISTRO_MAGEIA - | "neokylin" -> Some DISTRO_NEOKYLIN -- | "opensuse" -> Some DISTRO_OPENSUSE -+ | "opensuse" | "opensuse-leap" -> Some DISTRO_OPENSUSE - | "pld" -> Some DISTRO_PLD_LINUX - | "rhel" -> Some DISTRO_RHEL - | "sles" | "sled" -> Some DISTRO_SLES --- -2.21.0 - diff --git a/SOURCES/0052-v2v-windows-install-QEMU-Guest-Agent-MSI.patch b/SOURCES/0052-v2v-windows-install-QEMU-Guest-Agent-MSI.patch new file mode 100644 index 0000000..2f0b7ae --- /dev/null +++ b/SOURCES/0052-v2v-windows-install-QEMU-Guest-Agent-MSI.patch @@ -0,0 +1,119 @@ +From c664b50ab691a85d8a827ba51ea767744da548c3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Golembiovsk=C3=BD?= +Date: Tue, 8 Oct 2019 13:16:38 +0200 +Subject: [PATCH] v2v: windows: install QEMU Guest Agent MSI +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Use firstboot script to install MSI with QEMU-GA from virtio-win ISO or +oVirt/RHV guest tools ISO. + +Signed-off-by: Tomáš Golembiovský +(cherry picked from commit 00b4ed312b0ba179e9901b73c099724c3f6606b4) +--- + v2v/convert_windows.ml | 19 +++++++++++++++++++ + v2v/windows_virtio.ml | 27 +++++++++++++++++++++++++++ + v2v/windows_virtio.mli | 4 ++++ + 3 files changed, 50 insertions(+) + +diff --git a/v2v/convert_windows.ml b/v2v/convert_windows.ml +index 75e609d61..bdb0092c3 100644 +--- a/v2v/convert_windows.ml ++++ b/v2v/convert_windows.ml +@@ -293,6 +293,13 @@ let convert (g : G.guestfs) inspect source output rcaps static_ips = + if Sys.file_exists tool_path then + configure_vmdp tool_path; + ++ (* Install QEMU Guest Agent unconditionally and warn if missing *) ++ let qemu_ga_files = Windows_virtio.copy_qemu_ga g inspect in ++ if qemu_ga_files <> [] then ++ configure_qemu_ga qemu_ga_files ++ else ++ warning (f_"QEMU Guest Agent MSI not found on tools ISO/directory. You may want to install the guest agent manually after conversion."); ++ + unconfigure_xenpv (); + unconfigure_prltools (); + unconfigure_vmwaretools () +@@ -418,6 +425,18 @@ popd + Firstboot.add_firstboot_script g inspect.i_root + "finish vmdp setup" fb_recover_script + ++ and configure_qemu_ga files = ++ List.iter ( ++ fun msi_path -> ++ let fb_script = "\ ++echo Installing qemu-ga from " ^ msi_path ^ " ++\"\\" ^ msi_path ^ "\" /qn /forcerestart /l+*vx \"%cd%\\qemu-ga.log\" ++" in ++ Firstboot.add_firstboot_script g inspect.i_root ++ ("install " ^ msi_path) fb_script; ++ ) files ++ ++ + and unconfigure_xenpv () = + match xenpv_uninst with + | None -> () (* nothing to be uninstalled *) +diff --git a/v2v/windows_virtio.ml b/v2v/windows_virtio.ml +index 70f0bf09d..ea7e5c02d 100644 +--- a/v2v/windows_virtio.ml ++++ b/v2v/windows_virtio.ml +@@ -296,6 +296,13 @@ and copy_drivers g inspect driverdir = + (fun () -> + error (f_"root directory ‘/’ is missing from the virtio-win directory or ISO.\n\nThis should not happen and may indicate that virtio-win or virt-v2v is broken in some way. Please report this as a bug with a full debug log.")) + ++and copy_qemu_ga g inspect = ++ copy_from_virtio_win g inspect "/" "/" ++ virtio_iso_path_matches_qemu_ga ++ (fun () -> ++ error (f_"root directory ‘/’ is missing from the virtio-win directory or ISO.\n\nThis should not happen and may indicate that virtio-win or virt-v2v is broken in some way. Please report this as a bug with a full debug log.")) ++ ++ + (* Copy all files from virtio_win directory/ISO located in [srcdir] + * subdirectory and all its subdirectories to the [destdir]. The directory + * hierarchy is not preserved, meaning all files will be directly in [destdir]. +@@ -427,6 +434,26 @@ and virtio_iso_path_matches_guest_os path inspect = + + with Not_found -> false + ++(* Given a path of a file relative to the root of the directory tree ++ * with virtio-win drivers, figure out if it's suitable for the ++ * specific Windows flavor of the current guest. ++ *) ++and virtio_iso_path_matches_qemu_ga path inspect = ++ let { i_arch = arch } = inspect in ++ (* Lowercased path, since the ISO may contain upper or lowercase path ++ * elements. ++ *) ++ let lc_name = String.lowercase_ascii (Filename.basename path) in ++ lc_name = "rhev-qga.msi" || ++ match arch, lc_name with ++ | ("i386", "qemu-ga-x86.msi") ++ | ("i386", "qemu-ga-i386.msi") ++ | ("i386", "RHEV-QGA.msi") ++ | ("x86_64", "qemu-ga-x64.msi") ++ | ("x86_64", "qemu-ga-x86_64.msi") ++ | ("x86_64", "RHEV-QGA64.msi") -> true ++ | _ -> false ++ + (* The following function is only exported for unit tests. *) + module UNIT_TESTS = struct + let virtio_iso_path_matches_guest_os = virtio_iso_path_matches_guest_os +diff --git a/v2v/windows_virtio.mli b/v2v/windows_virtio.mli +index ae3b7e865..731dbd6f0 100644 +--- a/v2v/windows_virtio.mli ++++ b/v2v/windows_virtio.mli +@@ -44,6 +44,10 @@ val install_linux_tools : Guestfs.guestfs -> Types.inspect -> unit + (** installs QEMU Guest Agent on Linux guest OS from the driver directory or + driver ISO. It is not fatal if we fail to install the agent. *) + ++val copy_qemu_ga : Guestfs.guestfs -> Types.inspect -> string list ++(** copy MSIs (idealy just one) with QEMU Guest Agent to Windows guest. The ++ MSIs are not installed by this function. *) ++ + (**/**) + + (* The following function is only exported for unit tests. *) +-- +2.25.4 + diff --git a/SOURCES/0053-inspect-handle-os-release-opensuse-tumbleweed-as-ope.patch b/SOURCES/0053-inspect-handle-os-release-opensuse-tumbleweed-as-ope.patch deleted file mode 100644 index b3aa66b..0000000 --- a/SOURCES/0053-inspect-handle-os-release-opensuse-tumbleweed-as-ope.patch +++ /dev/null @@ -1,30 +0,0 @@ -From c9b55904a06abaea5ee858b590c861caa705ad52 Mon Sep 17 00:00:00 2001 -From: Pino Toscano -Date: Fri, 30 Nov 2018 12:41:03 +0100 -Subject: [PATCH] inspect: handle os-release "opensuse-tumbleweed" as opensuse - -Followup of commit 70407cd622dda6f088a0876e1e1ae669e9f8a281 for openSUSE -Thumbleweed. - -(cherry picked from commit 28bd06227b1633fa08c073fe8dbe65d013d7dc9e) ---- - daemon/inspect_fs_unix.ml | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/daemon/inspect_fs_unix.ml b/daemon/inspect_fs_unix.ml -index 33b93256f..6c3ab6e34 100644 ---- a/daemon/inspect_fs_unix.ml -+++ b/daemon/inspect_fs_unix.ml -@@ -142,7 +142,8 @@ and distro_of_os_release_id = function - | "frugalware" -> Some DISTRO_FRUGALWARE - | "mageia" -> Some DISTRO_MAGEIA - | "neokylin" -> Some DISTRO_NEOKYLIN -- | "opensuse" | "opensuse-leap" -> Some DISTRO_OPENSUSE -+ | "opensuse" -> Some DISTRO_OPENSUSE -+ | s when String.is_prefix s "opensuse-" -> Some DISTRO_OPENSUSE - | "pld" -> Some DISTRO_PLD_LINUX - | "rhel" -> Some DISTRO_RHEL - | "sles" | "sled" -> Some DISTRO_SLES --- -2.21.0 - diff --git a/SOURCES/0053-windows-small-tweaks-of-qemu-ga-firstboot-script.patch b/SOURCES/0053-windows-small-tweaks-of-qemu-ga-firstboot-script.patch new file mode 100644 index 0000000..70aec69 --- /dev/null +++ b/SOURCES/0053-windows-small-tweaks-of-qemu-ga-firstboot-script.patch @@ -0,0 +1,42 @@ +From b5e6c21a8241b3040c772f5ecd93a23a1896dc53 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Golembiovsk=C3=BD?= +Date: Wed, 5 Feb 2020 14:11:36 +0100 +Subject: [PATCH] windows: small tweaks of qemu-ga firstboot script +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +- match log file with script name +- restart manually only after successfull install, this also helps + debugging because we can log the installer return code + +Signed-off-by: Tomáš Golembiovský + +(cherry picked from commit 59f9ff40621240a6eed28c4425d3d69d8b21bc0e +in virt-v2v) +--- + v2v/convert_windows.ml | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/v2v/convert_windows.ml b/v2v/convert_windows.ml +index bdb0092c3..43c1f85de 100644 +--- a/v2v/convert_windows.ml ++++ b/v2v/convert_windows.ml +@@ -430,7 +430,13 @@ popd + fun msi_path -> + let fb_script = "\ + echo Installing qemu-ga from " ^ msi_path ^ " +-\"\\" ^ msi_path ^ "\" /qn /forcerestart /l+*vx \"%cd%\\qemu-ga.log\" ++\"\\" ^ msi_path ^ "\" /norestart /qn /l+*vx \"%~dpn0.log\" ++set elvl=!errorlevel! ++echo Done installing qemu-ga error_level=!elvl! ++if !elvl! == 0 ( ++ echo Restarting Windows... ++ shutdown /r /f /c \"rebooted by firstboot script\" ++) + " in + Firstboot.add_firstboot_script g inspect.i_root + ("install " ^ msi_path) fb_script; +-- +2.25.4 + diff --git a/SOURCES/0054-v2v-update-docs-for-VMware-roles-RHBZ-1530967.patch b/SOURCES/0054-v2v-update-docs-for-VMware-roles-RHBZ-1530967.patch deleted file mode 100644 index 8fb25ea..0000000 --- a/SOURCES/0054-v2v-update-docs-for-VMware-roles-RHBZ-1530967.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 10bff3240c5593c6c2e3c03063b98c53bb1b963e Mon Sep 17 00:00:00 2001 -From: Pino Toscano -Date: Thu, 13 Dec 2018 11:49:48 +0100 -Subject: [PATCH] v2v: update docs for VMware roles (RHBZ#1530967) - -Update the list of permissions needed for VMware vCenter 6.5. - -(cherry picked from commit 37955f14aa628bedbe0c06bddb5f8fa4f508cc62) ---- - v2v/virt-v2v.pod | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - -diff --git a/v2v/virt-v2v.pod b/v2v/virt-v2v.pod -index 4b53cdc0e..d4d8578cb 100644 ---- a/v2v/virt-v2v.pod -+++ b/v2v/virt-v2v.pod -@@ -1331,7 +1331,8 @@ write to libvirt or any other supported target. - - Instead of using the vCenter Administrator role, you can create a - custom non-administrator role to perform the conversion. You will --however need to give it a minimum set of permissions as follows: -+however need to give it a minimum set of permissions as follows -+(using VMware vCenter 6.5): - - =over 4 - -@@ -1351,10 +1352,12 @@ Enable (check) the following objects: - - Validate session - - Virtual Machine: -+ Interaction: -+ - Guest operating system management by VIX API - Provisioning: - - Allow disk access - - Allow read-only disk access -- - Guest Operating system management by VIX API -+ - Allow virtual machine download - - =back - --- -2.21.0 - diff --git a/SOURCES/0054-windows-fix-detection-of-qemu-ga-installer-on-RHV.patch b/SOURCES/0054-windows-fix-detection-of-qemu-ga-installer-on-RHV.patch new file mode 100644 index 0000000..3f307ef --- /dev/null +++ b/SOURCES/0054-windows-fix-detection-of-qemu-ga-installer-on-RHV.patch @@ -0,0 +1,43 @@ +From 34305aa93b6107c0aa9efcb1197efae3675a4ffe Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Golembiovsk=C3=BD?= +Date: Wed, 5 Feb 2020 14:11:35 +0100 +Subject: [PATCH] windows: fix detection of qemu-ga installer on RHV +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The detection was incorrectly matching only 32-bit installer on all +architectures. + +Signed-off-by: Tomáš Golembiovský + +(cherry picked from commit 45acf8d0557bee948c035305a6bafc6c9963a467 +in virt-v2v) +--- + v2v/windows_virtio.ml | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/v2v/windows_virtio.ml b/v2v/windows_virtio.ml +index ea7e5c02d..9a7297344 100644 +--- a/v2v/windows_virtio.ml ++++ b/v2v/windows_virtio.ml +@@ -444,14 +444,13 @@ and virtio_iso_path_matches_qemu_ga path inspect = + * elements. + *) + let lc_name = String.lowercase_ascii (Filename.basename path) in +- lc_name = "rhev-qga.msi" || + match arch, lc_name with + | ("i386", "qemu-ga-x86.msi") + | ("i386", "qemu-ga-i386.msi") +- | ("i386", "RHEV-QGA.msi") ++ | ("i386", "rhev-qga.msi") + | ("x86_64", "qemu-ga-x64.msi") + | ("x86_64", "qemu-ga-x86_64.msi") +- | ("x86_64", "RHEV-QGA64.msi") -> true ++ | ("x86_64", "rhev-qga64.msi") -> true + | _ -> false + + (* The following function is only exported for unit tests. *) +-- +2.25.4 + diff --git a/SOURCES/0055-v2v-o-rhv-upload-decouple-name-of-nbdkit-python-plug.patch b/SOURCES/0055-v2v-o-rhv-upload-decouple-name-of-nbdkit-python-plug.patch deleted file mode 100644 index fcb46c2..0000000 --- a/SOURCES/0055-v2v-o-rhv-upload-decouple-name-of-nbdkit-python-plug.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 6e71dcc1c9c1d8dd37da3f0fd71fc97cc5cbe92f Mon Sep 17 00:00:00 2001 -From: Pino Toscano -Date: Thu, 13 Dec 2018 18:36:20 +0100 -Subject: [PATCH] v2v: -o rhv-upload: decouple name of nbdkit python plugin - -Do not assume that the Python plugin of nbdkit has the same name of the -Python interpreter. - -Use the default upstream name of nbdkit to identify it; downstream -distributions must adjust this variable, in case they rename the Python -plugin of nbdkit. - -(cherry picked from commit 6b80c5fb51f08d3e62393e6722655bbcd940f4e7) ---- - v2v/output_rhv_upload.ml | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/v2v/output_rhv_upload.ml b/v2v/output_rhv_upload.ml -index 7dbd98a0d..79a2fc8fd 100644 ---- a/v2v/output_rhv_upload.ml -+++ b/v2v/output_rhv_upload.ml -@@ -79,6 +79,7 @@ let parse_output_options options = - { rhv_cafile; rhv_cluster; rhv_direct; rhv_verifypeer } - - let python3 = "python3" (* Defined by PEP 394 *) -+let nbdkit_python_plugin = "python" - let pidfile_timeout = 30 - let finalization_timeout = 5*60 - -@@ -155,7 +156,7 @@ class output_rhv_upload output_alloc output_conn - *) - let error_unless_nbdkit_python3_working () = - let cmd = sprintf "nbdkit %s %s --dump-plugin >/dev/null" -- python3 (quote plugin) in -+ nbdkit_python_plugin (quote plugin) in - if Sys.command cmd <> 0 then - error (f_"nbdkit Python 3 plugin is not installed or not working. It is required if you want to use ‘-o rhv-upload’. - -@@ -222,7 +223,7 @@ See also \"OUTPUT TO RHV\" in the virt-v2v(1) manual.") - "--newstyle"; (* use newstyle NBD protocol *) - "--exportname"; "/"; - -- "python3"; (* use the nbdkit Python 3 plugin *) -+ nbdkit_python_plugin; (* use the nbdkit Python plugin *) - plugin; (* Python plugin script *) - ] in - let args = if verbose () then args @ ["--verbose"] else args in --- -2.21.0 - diff --git a/SOURCES/0055-windows-delay-installation-of-qemu-ga-MSI.patch b/SOURCES/0055-windows-delay-installation-of-qemu-ga-MSI.patch new file mode 100644 index 0000000..41d1548 --- /dev/null +++ b/SOURCES/0055-windows-delay-installation-of-qemu-ga-MSI.patch @@ -0,0 +1,67 @@ +From 34a8b1a7115aeb95812ae8ee182055de757f3892 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Golembiovsk=C3=BD?= +Date: Thu, 5 Mar 2020 15:37:13 +0100 +Subject: [PATCH] windows: delay installation of qemu-ga MSI +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Instead of running firstboot script during early boot schedule a task +delayed for 2 minutes. + +During the first boot, after virt-v2v conversion, Windows installs the +drivers injected by virt-v2v. When this installation is finished +Windows enforces some kind of internal reboot. This unfortunately +terminates any running firstboot scripts thus killing the installation +of qemu-ga MSI. + +This is just a best-effort mitigation. It can still happen (e.g. with +slow disk drives) that the drivers are not yet installed when the +delayed installation starts. On the other hand we cannot delay it too +much otherwise we risk that the users logs in and will be doing some +work when the MSI installation starts. After MSI installation finishes +the VM needs to be rebooted which would be annoying if that would happen +under users hands. Although this is not a best fix (that may come later +as it is more complex, e.g. introducing waiting mechanism), the delay as +it is defined works in most cases. And it dramaticaly improves the +situations -- originaly I experienced more than 90% failure rate. + +Signed-off-by: Tomáš Golembiovský + +(cherry picked from commit dc66e78fa37db33e3c7358b7f7c7fa809cf62f9d +in virt-v2v) +--- + v2v/convert_windows.ml | 17 +++++++---------- + 1 file changed, 7 insertions(+), 10 deletions(-) + +diff --git a/v2v/convert_windows.ml b/v2v/convert_windows.ml +index 43c1f85de..088cd33d9 100644 +--- a/v2v/convert_windows.ml ++++ b/v2v/convert_windows.ml +@@ -428,16 +428,13 @@ popd + and configure_qemu_ga files = + List.iter ( + fun msi_path -> +- let fb_script = "\ +-echo Installing qemu-ga from " ^ msi_path ^ " +-\"\\" ^ msi_path ^ "\" /norestart /qn /l+*vx \"%~dpn0.log\" +-set elvl=!errorlevel! +-echo Done installing qemu-ga error_level=!elvl! +-if !elvl! == 0 ( +- echo Restarting Windows... +- shutdown /r /f /c \"rebooted by firstboot script\" +-) +-" in ++ let fb_script = sprintf "\ ++echo Removing any previously scheduled qemu-ga installation ++schtasks.exe /Delete /TN Firstboot-qemu-ga /F ++echo Scheduling delayed installation of qemu-ga from %s ++powershell.exe -command \"$d = (get-date).AddSeconds(120); schtasks.exe /Create /SC ONCE /ST $d.ToString('HH:mm') /SD $d.ToString('MM/dd/yyyy') /RU SYSTEM /TN Firstboot-qemu-ga /TR \\\"C:\\%s /forcerestart /qn /l+*vx C:\\%s.log\\\"\" ++ " ++ msi_path msi_path msi_path in + Firstboot.add_firstboot_script g inspect.i_root + ("install " ^ msi_path) fb_script; + ) files +-- +2.25.4 + diff --git a/SOURCES/0056-daemon-xattr-Refactor-code-which-splits-attr-names-f.patch b/SOURCES/0056-daemon-xattr-Refactor-code-which-splits-attr-names-f.patch new file mode 100644 index 0000000..a998da3 --- /dev/null +++ b/SOURCES/0056-daemon-xattr-Refactor-code-which-splits-attr-names-f.patch @@ -0,0 +1,283 @@ +From 052549a055bbedc402418bc52bcbfa3bfcb97952 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 12 Mar 2020 13:57:06 +0000 +Subject: [PATCH] daemon: xattr: Refactor code which splits attr names from the + kernel. + +The kernel returns xattr names in a slightly peculiar format. We +parsed this format several times in the code. Refactor this parsing +so we only do it in one place. + +(cherry picked from commit 5c175fe73264bbf1d3ef79bb066dfb6aff902ad1) +--- + daemon/xattr.c | 127 ++++++++++++++++++++++++++++++------------------- + 1 file changed, 79 insertions(+), 48 deletions(-) + +diff --git a/daemon/xattr.c b/daemon/xattr.c +index bc5c2df97..3e1144963 100644 +--- a/daemon/xattr.c ++++ b/daemon/xattr.c +@@ -89,6 +89,36 @@ do_lremovexattr (const char *xattr, const char *path) + return _removexattr (xattr, path, lremovexattr); + } + ++/** ++ * L returns the string C<"foo\0bar\0baz"> of length ++ * C. (The last string in the list is \0-terminated but the \0 ++ * is not included in C). ++ * ++ * This function splits it into a regular list of strings. ++ * ++ * B that the returned list contains pointers to the original ++ * strings in C so be careful that you do not double-free them. ++ */ ++static char ** ++split_attr_names (char *buf, size_t len) ++{ ++ size_t i; ++ DECLARE_STRINGSBUF (ret); ++ ++ for (i = 0; i < len; i += strlen (&buf[i]) + 1) { ++ if (add_string_nodup (&ret, &buf[i]) == -1) { ++ free (ret.argv); ++ return NULL; ++ } ++ } ++ if (end_stringsbuf (&ret) == -1) { ++ free (ret.argv); ++ return NULL; ++ } ++ ++ return take_stringsbuf (&ret); ++} ++ + static int + compare_xattrs (const void *vxa1, const void *vxa2) + { +@@ -106,7 +136,8 @@ getxattrs (const char *path, + { + ssize_t len, vlen; + CLEANUP_FREE char *buf = NULL; +- size_t i, j; ++ CLEANUP_FREE /* not string list */ char **names = NULL; ++ size_t i; + guestfs_int_xattr_list *r = NULL; + + buf = _listxattrs (path, listxattr, &len); +@@ -114,18 +145,17 @@ getxattrs (const char *path, + /* _listxattrs issues reply_with_perror already. */ + goto error; + ++ names = split_attr_names (buf, len); ++ if (names == NULL) ++ goto error; ++ + r = calloc (1, sizeof (*r)); + if (r == NULL) { + reply_with_perror ("calloc"); + goto error; + } + +- /* What we get from the kernel is a string "foo\0bar\0baz" of length +- * len. First count the strings. +- */ +- r->guestfs_int_xattr_list_len = 0; +- for (i = 0; i < (size_t) len; i += strlen (&buf[i]) + 1) +- r->guestfs_int_xattr_list_len++; ++ r->guestfs_int_xattr_list_len = guestfs_int_count_strings (names); + + r->guestfs_int_xattr_list_val = + calloc (r->guestfs_int_xattr_list_len, sizeof (guestfs_int_xattr)); +@@ -134,34 +164,34 @@ getxattrs (const char *path, + goto error; + } + +- for (i = 0, j = 0; i < (size_t) len; i += strlen (&buf[i]) + 1, ++j) { ++ for (i = 0; names[i] != NULL; ++i) { + CHROOT_IN; +- vlen = getxattr (path, &buf[i], NULL, 0); ++ vlen = getxattr (path, names[i], NULL, 0); + CHROOT_OUT; + if (vlen == -1) { +- reply_with_perror ("getxattr"); ++ reply_with_perror ("getxattr: %s", names[i]); + goto error; + } + + if (vlen > XATTR_SIZE_MAX) { + /* The next call to getxattr will fail anyway, so ... */ +- reply_with_error ("extended attribute is too large"); ++ reply_with_error ("%s: extended attribute is too large", names[i]); + goto error; + } + +- r->guestfs_int_xattr_list_val[j].attrname = strdup (&buf[i]); +- r->guestfs_int_xattr_list_val[j].attrval.attrval_val = malloc (vlen); +- r->guestfs_int_xattr_list_val[j].attrval.attrval_len = vlen; ++ r->guestfs_int_xattr_list_val[i].attrname = strdup (names[i]); ++ r->guestfs_int_xattr_list_val[i].attrval.attrval_val = malloc (vlen); ++ r->guestfs_int_xattr_list_val[i].attrval.attrval_len = vlen; + +- if (r->guestfs_int_xattr_list_val[j].attrname == NULL || +- r->guestfs_int_xattr_list_val[j].attrval.attrval_val == NULL) { ++ if (r->guestfs_int_xattr_list_val[i].attrname == NULL || ++ r->guestfs_int_xattr_list_val[i].attrval.attrval_val == NULL) { + reply_with_perror ("malloc"); + goto error; + } + + CHROOT_IN; +- vlen = getxattr (path, &buf[i], +- r->guestfs_int_xattr_list_val[j].attrval.attrval_val, ++ vlen = getxattr (path, names[i], ++ r->guestfs_int_xattr_list_val[i].attrval.attrval_val, + vlen); + CHROOT_OUT; + if (vlen == -1) { +@@ -276,7 +306,7 @@ guestfs_int_xattr_list * + do_internal_lxattrlist (const char *path, char *const *names) + { + guestfs_int_xattr_list *ret = NULL; +- size_t i, j; ++ size_t i; + size_t k, m, nr_attrs; + ssize_t len, vlen; + +@@ -293,6 +323,7 @@ do_internal_lxattrlist (const char *path, char *const *names) + void *newptr; + CLEANUP_FREE char *pathname = NULL; + CLEANUP_FREE char *buf = NULL; ++ CLEANUP_FREE /* not string list */ char **attrnames = NULL; + + /* Be careful in this loop about which errors cause the whole call + * to abort, and which errors allow us to continue processing +@@ -350,12 +381,10 @@ do_internal_lxattrlist (const char *path, char *const *names) + if (len == -1) + continue; /* not fatal */ + +- /* What we get from the kernel is a string "foo\0bar\0baz" of length +- * len. First count the strings. +- */ +- nr_attrs = 0; +- for (i = 0; i < (size_t) len; i += strlen (&buf[i]) + 1) +- nr_attrs++; ++ attrnames = split_attr_names (buf, len); ++ if (attrnames == NULL) ++ goto error; ++ nr_attrs = guestfs_int_count_strings (attrnames); + + newptr = + realloc (ret->guestfs_int_xattr_list_val, +@@ -378,36 +407,36 @@ do_internal_lxattrlist (const char *path, char *const *names) + entry[m].attrval.attrval_val = NULL; + } + +- for (i = 0, j = 0; i < (size_t) len; i += strlen (&buf[i]) + 1, ++j) { ++ for (i = 0; attrnames[i] != NULL; ++i) { + CHROOT_IN; +- vlen = lgetxattr (pathname, &buf[i], NULL, 0); ++ vlen = lgetxattr (pathname, attrnames[i], NULL, 0); + CHROOT_OUT; + if (vlen == -1) { +- reply_with_perror ("getxattr"); ++ reply_with_perror ("getxattr: %s", attrnames[i]); + goto error; + } + + if (vlen > XATTR_SIZE_MAX) { +- reply_with_error ("extended attribute is too large"); ++ reply_with_error ("%s: extended attribute is too large", attrnames[i]); + goto error; + } + +- entry[j+1].attrname = strdup (&buf[i]); +- entry[j+1].attrval.attrval_val = malloc (vlen); +- entry[j+1].attrval.attrval_len = vlen; ++ entry[i+1].attrname = strdup (attrnames[i]); ++ entry[i+1].attrval.attrval_val = malloc (vlen); ++ entry[i+1].attrval.attrval_len = vlen; + +- if (entry[j+1].attrname == NULL || +- entry[j+1].attrval.attrval_val == NULL) { ++ if (entry[i+1].attrname == NULL || ++ entry[i+1].attrval.attrval_val == NULL) { + reply_with_perror ("malloc"); + goto error; + } + + CHROOT_IN; +- vlen = lgetxattr (pathname, &buf[i], +- entry[j+1].attrval.attrval_val, vlen); ++ vlen = lgetxattr (pathname, attrnames[i], ++ entry[i+1].attrval.attrval_val, vlen); + CHROOT_OUT; + if (vlen == -1) { +- reply_with_perror ("getxattr"); ++ reply_with_perror ("getxattr: %s", attrnames[i]); + goto error; + } + } +@@ -510,6 +539,7 @@ copy_xattrs (const char *src, const char *dest) + { + ssize_t len, vlen, ret, attrval_len = 0; + CLEANUP_FREE char *buf = NULL, *attrval = NULL; ++ CLEANUP_FREE /* not string list */ char **names = NULL; + size_t i; + + buf = _listxattrs (src, listxattr, &len); +@@ -517,21 +547,22 @@ copy_xattrs (const char *src, const char *dest) + /* _listxattrs issues reply_with_perror already. */ + goto error; + +- /* What we get from the kernel is a string "foo\0bar\0baz" of length +- * len. +- */ +- for (i = 0; i < (size_t) len; i += strlen (&buf[i]) + 1) { ++ names = split_attr_names (buf, len); ++ if (names == NULL) ++ goto error; ++ ++ for (i = 0; names[i] != NULL; ++i) { + CHROOT_IN; +- vlen = getxattr (src, &buf[i], NULL, 0); ++ vlen = getxattr (src, names[i], NULL, 0); + CHROOT_OUT; + if (vlen == -1) { +- reply_with_perror ("getxattr: %s, %s", src, &buf[i]); ++ reply_with_perror ("getxattr: %s, %s", src, names[i]); + goto error; + } + + if (vlen > XATTR_SIZE_MAX) { + /* The next call to getxattr will fail anyway, so ... */ +- reply_with_error ("extended attribute is too large"); ++ reply_with_error ("%s: extended attribute is too large", names[i]); + goto error; + } + +@@ -546,18 +577,18 @@ copy_xattrs (const char *src, const char *dest) + } + + CHROOT_IN; +- vlen = getxattr (src, &buf[i], attrval, vlen); ++ vlen = getxattr (src, names[i], attrval, vlen); + CHROOT_OUT; + if (vlen == -1) { +- reply_with_perror ("getxattr: %s, %s", src, &buf[i]); ++ reply_with_perror ("getxattr: %s, %s", src, names[i]); + goto error; + } + + CHROOT_IN; +- ret = setxattr (dest, &buf[i], attrval, vlen, 0); ++ ret = setxattr (dest, names[i], attrval, vlen, 0); + CHROOT_OUT; + if (ret == -1) { +- reply_with_perror ("setxattr: %s, %s", dest, &buf[i]); ++ reply_with_perror ("setxattr: %s, %s", dest, names[i]); + goto error; + } + } +-- +2.25.4 + diff --git a/SOURCES/0056-v2v-further-doc-update-for-VMware-roles.patch b/SOURCES/0056-v2v-further-doc-update-for-VMware-roles.patch deleted file mode 100644 index fcee497..0000000 --- a/SOURCES/0056-v2v-further-doc-update-for-VMware-roles.patch +++ /dev/null @@ -1,30 +0,0 @@ -From c5460f73b805c754ad736dcacc7d6bf7a5f6cfb7 Mon Sep 17 00:00:00 2001 -From: Pino Toscano -Date: Mon, 7 Jan 2019 12:23:25 +0100 -Subject: [PATCH] v2v: further doc update for VMware roles - -Remove "Allow virtual machine download", added with -commit 37955f14aa628bedbe0c06bddb5f8fa4f508cc62, because it does not -seem to be actually needed. - -Related: RHBZ#1530967 -(cherry picked from commit 5e5896752ef06872696f1da05b414fc9eca94015) ---- - v2v/virt-v2v.pod | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/v2v/virt-v2v.pod b/v2v/virt-v2v.pod -index d4d8578cb..f4d200e3d 100644 ---- a/v2v/virt-v2v.pod -+++ b/v2v/virt-v2v.pod -@@ -1357,7 +1357,6 @@ Enable (check) the following objects: - Provisioning: - - Allow disk access - - Allow read-only disk access -- - Allow virtual machine download - - =back - --- -2.21.0 - diff --git a/SOURCES/0057-daemon-Add-filter_list-utility-function.patch b/SOURCES/0057-daemon-Add-filter_list-utility-function.patch new file mode 100644 index 0000000..db1e1d8 --- /dev/null +++ b/SOURCES/0057-daemon-Add-filter_list-utility-function.patch @@ -0,0 +1,84 @@ +From 1c976cc5d1add98eee09c38ac8e01634c94f3778 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 12 Mar 2020 13:59:05 +0000 +Subject: [PATCH] daemon: Add filter_list utility function. + +For filtering lists of strings based on a predicate. + +(cherry picked from commit af8ed266a282bb20882a9ffb611bd64243d19218) +--- + daemon/daemon.h | 2 ++ + daemon/utils.c | 30 ++++++++++++++++++++++++++++++ + 2 files changed, 32 insertions(+) + +diff --git a/daemon/daemon.h b/daemon/daemon.h +index 66bfdc49e..115591728 100644 +--- a/daemon/daemon.h ++++ b/daemon/daemon.h +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -74,6 +75,7 @@ extern void free_stringsbuf (struct stringsbuf *sb); + extern struct stringsbuf split_lines_sb (char *str); + extern char **split_lines (char *str); + extern char **empty_list (void); ++extern char **filter_list (bool (*p) (const char *), char **strs); + extern int is_power_of_2 (unsigned long v); + extern void trim (char *str); + extern int parse_btrfsvol (const char *desc, mountable_t *mountable); +diff --git a/daemon/utils.c b/daemon/utils.c +index c3f88bcab..e87233d0f 100644 +--- a/daemon/utils.c ++++ b/daemon/utils.c +@@ -24,6 +24,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -482,6 +483,35 @@ empty_list (void) + return ret.argv; + } + ++/** ++ * Filter a list of strings. Returns a newly allocated list of only ++ * the strings where C

. ++ * ++ * B it does not copy the strings, be careful not to double-free ++ * them. ++ */ ++char ** ++filter_list (bool (*p) (const char *str), char **strs) ++{ ++ DECLARE_STRINGSBUF (ret); ++ size_t i; ++ ++ for (i = 0; strs[i] != NULL; ++i) { ++ if (p (strs[i])) { ++ if (add_string_nodup (&ret, strs[i]) == -1) { ++ free (ret.argv); ++ return NULL; ++ } ++ } ++ } ++ if (end_stringsbuf (&ret) == -1) { ++ free (ret.argv); ++ return NULL; ++ } ++ ++ return take_stringsbuf (&ret); ++} ++ + /** + * Skip leading and trailing whitespace, updating the original string + * in-place. +-- +2.25.4 + diff --git a/SOURCES/0057-python-fix-call-of-Python-handlers-of-events.patch b/SOURCES/0057-python-fix-call-of-Python-handlers-of-events.patch deleted file mode 100644 index f2e87bb..0000000 --- a/SOURCES/0057-python-fix-call-of-Python-handlers-of-events.patch +++ /dev/null @@ -1,40 +0,0 @@ -From da45c7c305a8ed03b7b1b11f6524e1321c5ad2b3 Mon Sep 17 00:00:00 2001 -From: Pino Toscano -Date: Tue, 22 Jan 2019 12:43:11 +0100 -Subject: [PATCH] python: fix call of Python handlers of events - -Make sure to reference the arguments, to make sure they are kept alive -during the function call; this is visible when setting an event handler -for the CLOSE event, and testing it with Python 3. - -This does not seem to create a memory leak e.g. with Python 2. - -Also, switch away from the quasi-internal PyEval_CallObject to the -public PyObject_CallObject, which takes care of doing safety checks. - -(cherry picked from commit 85235aec837716f1ddb2926b9a59a02543195500) ---- - python/handle.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/python/handle.c b/python/handle.c -index 1ffa4588a..13a93ad8c 100644 ---- a/python/handle.c -+++ b/python/handle.c -@@ -136,11 +136,12 @@ guestfs_int_py_event_callback_wrapper (guestfs_h *g, - args = Py_BuildValue ("(Kis#O)", - (unsigned PY_LONG_LONG) event, event_handle, - buf, buf_len, py_array); -+ Py_INCREF (args); - - if (PyEval_ThreadsInitialized ()) - py_save = PyGILState_Ensure (); - -- py_r = PyEval_CallObject (py_callback, args); -+ py_r = PyObject_CallObject (py_callback, args); - - if (PyEval_ThreadsInitialized ()) - PyGILState_Release (py_save); --- -2.21.0 - diff --git a/SOURCES/0058-daemon-xattr-Filter-out-user.WofCompressedData-from-.patch b/SOURCES/0058-daemon-xattr-Filter-out-user.WofCompressedData-from-.patch new file mode 100644 index 0000000..ab6cbeb --- /dev/null +++ b/SOURCES/0058-daemon-xattr-Filter-out-user.WofCompressedData-from-.patch @@ -0,0 +1,120 @@ +From fabaf7328a449344028903811674787dc685084b Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 12 Mar 2020 14:40:05 +0000 +Subject: [PATCH] daemon: xattr: Filter out user.WofCompressedData from xattrs + (RHBZ#1811539). + +See comment in code for justification. + +Thanks: Yongkui Guo for finding the bug. +(cherry picked from commit c2c11382bbeb4500f3388a31ffd08cfc18b0de40) +--- + daemon/xattr.c | 43 ++++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 40 insertions(+), 3 deletions(-) + +diff --git a/daemon/xattr.c b/daemon/xattr.c +index 3e1144963..43e49384f 100644 +--- a/daemon/xattr.c ++++ b/daemon/xattr.c +@@ -19,6 +19,8 @@ + #include + + #include ++#include ++#include + #include + #include + +@@ -119,6 +121,29 @@ split_attr_names (char *buf, size_t len) + return take_stringsbuf (&ret); + } + ++/* We hide one extended attribute automatically. This is used by NTFS ++ * to store the compressed contents of a file when using "CompactOS" ++ * (per-file compression). I justify this by: ++ * ++ * (1) The attribute is only used internally by NTFS. The actual file ++ * contents are still available. ++ * ++ * (2) It's probably not valid to copy this attribute when copying the ++ * other attributes of a file. ntfs-3g-system-compression doesn't ++ * support writing compressed files. ++ * ++ * (3) This file isn't readable by the Linux kernel. Reading it will ++ * always return -E2BIG (RHBZ#1811539). So we can't read it even if ++ * we wanted to. ++ * ++ * (4) The Linux kernel itself hides other attributes. ++ */ ++static bool ++not_hidden_xattr (const char *attrname) ++{ ++ return STRNEQ (attrname, "user.WofCompressedData"); ++} ++ + static int + compare_xattrs (const void *vxa1, const void *vxa2) + { +@@ -136,6 +161,7 @@ getxattrs (const char *path, + { + ssize_t len, vlen; + CLEANUP_FREE char *buf = NULL; ++ CLEANUP_FREE /* not string list */ char **names_unfiltered = NULL; + CLEANUP_FREE /* not string list */ char **names = NULL; + size_t i; + guestfs_int_xattr_list *r = NULL; +@@ -145,7 +171,10 @@ getxattrs (const char *path, + /* _listxattrs issues reply_with_perror already. */ + goto error; + +- names = split_attr_names (buf, len); ++ names_unfiltered = split_attr_names (buf, len); ++ if (names_unfiltered == NULL) ++ goto error; ++ names = filter_list (not_hidden_xattr, names_unfiltered); + if (names == NULL) + goto error; + +@@ -323,6 +352,7 @@ do_internal_lxattrlist (const char *path, char *const *names) + void *newptr; + CLEANUP_FREE char *pathname = NULL; + CLEANUP_FREE char *buf = NULL; ++ CLEANUP_FREE /* not string list */ char **attrnames_unfiltered = NULL; + CLEANUP_FREE /* not string list */ char **attrnames = NULL; + + /* Be careful in this loop about which errors cause the whole call +@@ -381,7 +411,10 @@ do_internal_lxattrlist (const char *path, char *const *names) + if (len == -1) + continue; /* not fatal */ + +- attrnames = split_attr_names (buf, len); ++ attrnames_unfiltered = split_attr_names (buf, len); ++ if (attrnames_unfiltered == NULL) ++ goto error; ++ attrnames = filter_list (not_hidden_xattr, attrnames_unfiltered); + if (attrnames == NULL) + goto error; + nr_attrs = guestfs_int_count_strings (attrnames); +@@ -539,6 +572,7 @@ copy_xattrs (const char *src, const char *dest) + { + ssize_t len, vlen, ret, attrval_len = 0; + CLEANUP_FREE char *buf = NULL, *attrval = NULL; ++ CLEANUP_FREE /* not string list */ char **names_unfiltered = NULL; + CLEANUP_FREE /* not string list */ char **names = NULL; + size_t i; + +@@ -547,7 +581,10 @@ copy_xattrs (const char *src, const char *dest) + /* _listxattrs issues reply_with_perror already. */ + goto error; + +- names = split_attr_names (buf, len); ++ names_unfiltered = split_attr_names (buf, len); ++ if (names_unfiltered == NULL) ++ goto error; ++ names = filter_list (not_hidden_xattr, names_unfiltered); + if (names == NULL) + goto error; + +-- +2.25.4 + diff --git a/SOURCES/0058-python-change-types-for-RBufferOut-FBuffer-with-Pyth.patch b/SOURCES/0058-python-change-types-for-RBufferOut-FBuffer-with-Pyth.patch deleted file mode 100644 index b1b2b23..0000000 --- a/SOURCES/0058-python-change-types-for-RBufferOut-FBuffer-with-Pyth.patch +++ /dev/null @@ -1,54 +0,0 @@ -From f4c25f88b1187bfd1ff73c8f824d9a020716ae79 Mon Sep 17 00:00:00 2001 -From: Pino Toscano -Date: Tue, 22 Jan 2019 13:04:59 +0100 -Subject: [PATCH] python: change types for RBufferOut/FBuffer with Python 3 - (RHBZ#1661871) - -So far RBufferOut return values, and FBuffer struct fields are 'str' on -all the versions of Python. Python 3 distinguishes between 'str' -(unicode strings), and 'bytes', with 'str' no more able to hold -arbitrary data. - -For this reason, switch the return value of RBufferOut functions, and -FBuffer struct fields to bytes on Python 3: while this is a potentially -incompatibile change, this is the only way to handle safely sequences -of arbitrary bytes. - -(cherry picked from commit 0ee02e0117527b86a31b2a88a14994ce7f15571f) ---- - generator/python.ml | 9 +++++++++ - 1 file changed, 9 insertions(+) - -diff --git a/generator/python.ml b/generator/python.ml -index 8fa0b17c0..a75b5f375 100644 ---- a/generator/python.ml -+++ b/generator/python.ml -@@ -195,8 +195,13 @@ and generate_python_structs () = - pr " goto err;\n"; - pr " PyDict_SetItemString (dict, \"%s\", value);\n" name; - | name, FBuffer -> -+ pr "#if PY_MAJOR_VERSION >= 3\n"; -+ pr " value = PyBytes_FromStringAndSize (%s->%s, %s->%s_len);\n" -+ typ name typ name; -+ pr "#else\n"; - pr " value = guestfs_int_py_fromstringsize (%s->%s, %s->%s_len);\n" - typ name typ name; -+ pr "#endif\n"; - pr " if (value == NULL)\n"; - pr " goto err;\n"; - pr " PyDict_SetItemString (dict, \"%s\", value);\n" name; -@@ -511,7 +516,11 @@ and generate_python_actions actions () = - pr " guestfs_int_free_string_list (r);\n"; - pr " if (py_r == NULL) goto out;\n"; - | RBufferOut _ -> -+ pr "#if PY_MAJOR_VERSION >= 3\n"; -+ pr " py_r = PyBytes_FromStringAndSize (r, size);\n"; -+ pr "#else\n"; - pr " py_r = guestfs_int_py_fromstringsize (r, size);\n"; -+ pr "#endif\n"; - pr " free (r);\n"; - pr " if (py_r == NULL) goto out;\n"; - ); --- -2.21.0 - diff --git a/SOURCES/0059-Revert-launch-libvirt-Use-qemu-bridge-helper-to-impl.patch b/SOURCES/0059-Revert-launch-libvirt-Use-qemu-bridge-helper-to-impl.patch deleted file mode 100644 index d4b2c90..0000000 --- a/SOURCES/0059-Revert-launch-libvirt-Use-qemu-bridge-helper-to-impl.patch +++ /dev/null @@ -1,238 +0,0 @@ -From 66a40516a2696b7528803d7637c022659fa8c46e Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Thu, 2 Oct 2014 16:44:07 +0100 -Subject: [PATCH] Revert "launch: libvirt: Use qemu-bridge-helper to implement - a full network (RHBZ#1148012)." - -We've been carrying this exact patch in RHEL 7 for several years. It -reverts the change made in 2014 where we switched to using the virbr0 -bridge for libguestfs networking instead of SLIRP. We thought SLIRP -was going to become unsupported in qemu, but recently there have been -more encouraging signs since it looks like SLIRP will be spun off as a -separate project, running as a modular process and properly secured -and supported. - -This reverts commit 224de20b9a8d5ea56f6337f19b4ca237bb88eca0. - -(cherry picked from commit 492a945791b43f80a769a53e60d0899b3d7c60ab) ---- - lib/guestfs-internal.h | 11 +++++ - lib/guestfs.pod | 10 ----- - lib/launch-direct.c | 11 ----- - lib/launch-libvirt.c | 91 ++++++++++-------------------------------- - 4 files changed, 32 insertions(+), 91 deletions(-) - -diff --git a/lib/guestfs-internal.h b/lib/guestfs-internal.h -index adeb9478a..fe3a0e3b9 100644 ---- a/lib/guestfs-internal.h -+++ b/lib/guestfs-internal.h -@@ -147,6 +147,17 @@ - #define MACHINE_TYPE "pseries" - #endif - -+/* Differences in qemu device names on ARMv7 (virtio-mmio), s/390x -+ * (CCW) vs normal hardware with PCI. -+ */ -+#if defined(__arm__) -+#define VIRTIO_DEVICE_NAME(type) type "-device" -+#elif defined(__s390x__) -+#define VIRTIO_DEVICE_NAME(type) type "-ccw" -+#else -+#define VIRTIO_DEVICE_NAME(type) type "-pci" -+#endif -+ - /* Guestfs handle and associated structures. */ - - /* State. */ -diff --git a/lib/guestfs.pod b/lib/guestfs.pod -index 4b24006df..c7fbeef03 100644 ---- a/lib/guestfs.pod -+++ b/lib/guestfs.pod -@@ -1551,16 +1551,6 @@ On Fedora, install C for the C file - (containing symbols). Make sure the symbols precisely match the - kernel being used. - --=head3 network_bridge -- --The libvirt backend supports: -- -- export LIBGUESTFS_BACKEND_SETTINGS=network_bridge=virbrX -- --This allows you to override the bridge that is connected to when the --network is enabled. The default is C. See also --L. -- - =head2 ATTACHING TO RUNNING DAEMONS - - I This is B and has a tendency to eat -diff --git a/lib/launch-direct.c b/lib/launch-direct.c -index 47e8f37de..f6c494d69 100644 ---- a/lib/launch-direct.c -+++ b/lib/launch-direct.c -@@ -49,17 +49,6 @@ - #include "guestfs_protocol.h" - #include "qemuopts.h" - --/* Differences in qemu device names on ARMv7 (virtio-mmio), s/390x -- * (CCW) vs normal hardware with PCI. -- */ --#if defined(__arm__) --#define VIRTIO_DEVICE_NAME(type) type "-device" --#elif defined(__s390x__) --#define VIRTIO_DEVICE_NAME(type) type "-ccw" --#else --#define VIRTIO_DEVICE_NAME(type) type "-pci" --#endif -- - /* Per-handle data. */ - struct backend_direct_data { - pid_t pid; /* Qemu PID. */ -diff --git a/lib/launch-libvirt.c b/lib/launch-libvirt.c -index 7121aee1b..4df26825a 100644 ---- a/lib/launch-libvirt.c -+++ b/lib/launch-libvirt.c -@@ -116,7 +116,6 @@ struct backend_libvirt_data { - char *selinux_label; - char *selinux_imagelabel; - bool selinux_norelabel_disks; -- char *network_bridge; - char name[DOMAIN_NAME_LEN]; /* random name */ - bool is_kvm; /* false = qemu, true = kvm (from capabilities)*/ - struct version libvirt_version; /* libvirt version */ -@@ -157,7 +156,6 @@ static int is_blk (const char *path); - static void ignore_errors (void *ignore, virErrorPtr ignore2); - static void set_socket_create_context (guestfs_h *g); - static void clear_socket_create_context (guestfs_h *g); --static int check_bridge_exists (guestfs_h *g, const char *brname); - - #if HAVE_LIBSELINUX - static void selinux_warning (guestfs_h *g, const char *func, const char *selinux_op, const char *data); -@@ -438,17 +436,8 @@ launch_libvirt (guestfs_h *g, void *datav, const char *libvirt_uri) - guestfs_get_backend_setting (g, "internal_libvirt_imagelabel"); - data->selinux_norelabel_disks = - guestfs_int_get_backend_setting_bool (g, "internal_libvirt_norelabel_disks"); -- if (g->enable_network) { -- data->network_bridge = -- guestfs_get_backend_setting (g, "network_bridge"); -- if (!data->network_bridge) -- data->network_bridge = safe_strdup (g, "virbr0"); -- } - guestfs_pop_error_handler (g); - -- if (g->enable_network && check_bridge_exists (g, data->network_bridge) == -1) -- goto cleanup; -- - /* Locate and/or build the appliance. */ - TRACE0 (launch_build_libvirt_appliance_start); - -@@ -1403,19 +1392,6 @@ construct_libvirt_xml_devices (guestfs_h *g, - } end_element (); - } end_element (); - -- /* Connect to libvirt bridge (see: RHBZ#1148012). */ -- if (g->enable_network) { -- start_element ("interface") { -- attribute ("type", "bridge"); -- start_element ("source") { -- attribute ("bridge", params->data->network_bridge); -- } end_element (); -- start_element ("model") { -- attribute ("type", "virtio"); -- } end_element (); -- } end_element (); -- } -- - /* Libvirt adds some devices by default. Indicate to libvirt - * that we don't want them. - */ -@@ -1823,6 +1799,27 @@ construct_libvirt_xml_qemu_cmdline (guestfs_h *g, - attribute ("value", tmpdir); - } end_element (); - -+ /* Workaround because libvirt user networking cannot specify "net=" -+ * parameter. -+ */ -+ if (g->enable_network) { -+ start_element ("qemu:arg") { -+ attribute ("value", "-netdev"); -+ } end_element (); -+ -+ start_element ("qemu:arg") { -+ attribute ("value", "user,id=usernet,net=169.254.0.0/16"); -+ } end_element (); -+ -+ start_element ("qemu:arg") { -+ attribute ("value", "-device"); -+ } end_element (); -+ -+ start_element ("qemu:arg") { -+ attribute ("value", VIRTIO_DEVICE_NAME ("virtio-net") ",netdev=usernet"); -+ } end_element (); -+ } -+ - /* The qemu command line arguments requested by the caller. */ - for (hp = g->hv_params; hp; hp = hp->next) { - start_element ("qemu:arg") { -@@ -2060,49 +2057,6 @@ is_blk (const char *path) - return S_ISBLK (statbuf.st_mode); - } - --static int --is_dir (const char *path) --{ -- struct stat statbuf; -- -- if (stat (path, &statbuf) == -1) -- return 0; -- return S_ISDIR (statbuf.st_mode); --} -- --/* Used to check the network_bridge exists, or give a useful error -- * message. -- */ --static int --check_bridge_exists (guestfs_h *g, const char *brname) --{ -- CLEANUP_FREE char *path = NULL; -- -- /* If this doesn't look like Linux, give up. */ -- if (!is_dir ("/sys/class/net")) -- return 0; -- -- /* Does the interface exist and is it a bridge? */ -- path = safe_asprintf (g, "/sys/class/net/%s/bridge", brname); -- if (is_dir (path)) -- return 0; -- -- error (g, -- _("bridge ‘%s’ not found. Try running:\n" -- "\n" -- " brctl show\n" -- "\n" -- "to get a list of bridges on the host, and then selecting the\n" -- "bridge you wish the appliance network to connect to using:\n" -- "\n" -- " export LIBGUESTFS_BACKEND_SETTINGS=network_bridge=\n" -- "\n" -- "You may also need to allow the bridge in /etc/qemu/bridge.conf.\n" -- "For further information see guestfs(3)."), -- brname); -- return -1; --} -- - static void - ignore_errors (void *ignore, virErrorPtr ignore2) - { -@@ -2148,9 +2102,6 @@ shutdown_libvirt (guestfs_h *g, void *datav, int check_for_errors) - free (data->selinux_imagelabel); - data->selinux_imagelabel = NULL; - -- free (data->network_bridge); -- data->network_bridge = NULL; -- - for (i = 0; i < data->nr_secrets; ++i) - free (data->secrets[i].secret); - free (data->secrets); --- -2.21.0 - diff --git a/SOURCES/0059-mltools-add-run_in_guest_command-helper.patch b/SOURCES/0059-mltools-add-run_in_guest_command-helper.patch new file mode 100644 index 0000000..506b6c4 --- /dev/null +++ b/SOURCES/0059-mltools-add-run_in_guest_command-helper.patch @@ -0,0 +1,95 @@ +From 1519dfe45d35dbc1f273d468fca3ea77d6cfdfad Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Mon, 4 May 2020 15:14:46 +0200 +Subject: [PATCH] mltools: add run_in_guest_command helper + +Add an helper function to run a command in the guest, checking for the +host/guest compatibility. This is mostly extracted from the internal +do_run helper currently in the Customize_run module of virt-customize. + +(cherry picked from commit e73eca3b73f7d0a54615c5dc55eadd09dc170035 +in libguestfs-common) +--- + common/mltools/tools_utils.ml | 50 ++++++++++++++++++++++++++++++++++ + common/mltools/tools_utils.mli | 10 +++++++ + 2 files changed, 60 insertions(+) + +diff --git a/common/mltools/tools_utils.ml b/common/mltools/tools_utils.ml +index 127180225..d54ec581e 100644 +--- a/common/mltools/tools_utils.ml ++++ b/common/mltools/tools_utils.ml +@@ -679,3 +679,53 @@ let with_timeout op timeout ?(sleep = 2) fn = + loop () + in + loop () ++ ++let run_in_guest_command g root ?logfile ?incompatible_fn cmd = ++ (* Is the host_cpu compatible with the guest arch? ie. Can we ++ * run commands in this guest? ++ *) ++ let guest_arch = g#inspect_get_arch root in ++ let guest_arch_compatible = guest_arch_compatible guest_arch in ++ if not guest_arch_compatible then ( ++ match incompatible_fn with ++ | None -> () ++ | Some fn -> fn () ++ ) ++ else ( ++ (* Add a prologue to the scripts: ++ * - Pass environment variables through from the host. ++ * - Optionally send stdout and stderr to a log file so we capture ++ * all output in error messages. ++ * - Use setarch when running x86_64 host + i686 guest. ++ *) ++ let env_vars = ++ List.filter_map ( ++ fun name -> ++ try Some (sprintf "export %s=%s" name (quote (Sys.getenv name))) ++ with Not_found -> None ++ ) [ "http_proxy"; "https_proxy"; "ftp_proxy"; "no_proxy" ] in ++ let env_vars = String.concat "\n" env_vars ^ "\n" in ++ ++ let cmd = ++ match Guestfs_config.host_cpu, guest_arch with ++ | "x86_64", ("i386"|"i486"|"i586"|"i686") -> ++ sprintf "setarch i686 <<\"__EOCMD\" ++%s ++__EOCMD ++" cmd ++ | _ -> cmd in ++ ++ let logfile_redirect = ++ match logfile with ++ | None -> "" ++ | Some logfile -> sprintf "exec >>%s 2>&1" (quote logfile) in ++ ++ let cmd = sprintf "\ ++%s ++%s ++%s ++" (logfile_redirect) env_vars cmd in ++ ++ debug "running command:\n%s" cmd; ++ ignore (g#sh cmd) ++ ) +diff --git a/common/mltools/tools_utils.mli b/common/mltools/tools_utils.mli +index ab70f583e..102abff4d 100644 +--- a/common/mltools/tools_utils.mli ++++ b/common/mltools/tools_utils.mli +@@ -212,3 +212,13 @@ val with_timeout : string -> int -> ?sleep:int -> (unit -> 'a option) -> 'a + calls {!error} and the program exits. The error message will + contain the diagnostic string [op] to identify the operation + which timed out. *) ++ ++val run_in_guest_command : Guestfs.guestfs -> string -> ?logfile:string -> ?incompatible_fn:(unit -> unit) -> string -> unit ++(** [run_in_guest_command g root ?incompatible_archs_fn cmd] ++ runs a command in the guest, which is already mounted for the ++ specified [root]. The command is run directly in case the ++ architecture of the host and the guest are compatible, optionally ++ calling [?incompatible_fn] in case they are not. ++ ++ [?logfile] is an optional file in the guest to where redirect ++ stdout and stderr of the command. *) +-- +2.25.4 + diff --git a/SOURCES/0060-customize-port-do_run-to-run_in_guest_command.patch b/SOURCES/0060-customize-port-do_run-to-run_in_guest_command.patch new file mode 100644 index 0000000..d9162af --- /dev/null +++ b/SOURCES/0060-customize-port-do_run-to-run_in_guest_command.patch @@ -0,0 +1,83 @@ +From 63d711246f7e86c838c4471bec538a40abffbfb8 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Mon, 4 May 2020 11:55:41 +0200 +Subject: [PATCH] customize: port do_run to run_in_guest_command + +Make use of the new helper function in Tools_utils to run commands in +the guest. + +(cherry picked from commit b25e3495f522378f59d201526d7d2d02c2bf6f3f) +--- + customize/customize_run.ml | 48 ++++++-------------------------------- + 1 file changed, 7 insertions(+), 41 deletions(-) + +diff --git a/customize/customize_run.ml b/customize/customize_run.ml +index 3eacdaca0..f2ee20413 100644 +--- a/customize/customize_run.ml ++++ b/customize/customize_run.ml +@@ -30,12 +30,6 @@ open Append_line + module G = Guestfs + + let run (g : G.guestfs) root (ops : ops) = +- (* Is the host_cpu compatible with the guest arch? ie. Can we +- * run commands in this guest? +- *) +- let guest_arch = g#inspect_get_arch root in +- let guest_arch_compatible = guest_arch_compatible guest_arch in +- + (* Based on the guest type, choose a log file location. *) + let logfile = + match g#inspect_get_type root with +@@ -54,42 +48,14 @@ let run (g : G.guestfs) root (ops : ops) = + + (* Useful wrapper for scripts. *) + let do_run ~display ?(warn_failed_no_network = false) cmd = +- if not guest_arch_compatible then ++ let incompatible_fn () = ++ let guest_arch = g#inspect_get_arch root in + error (f_"host cpu (%s) and guest arch (%s) are not compatible, so you cannot use command line options that involve running commands in the guest. Use --firstboot scripts instead.") +- Guestfs_config.host_cpu guest_arch; +- +- (* Add a prologue to the scripts: +- * - Pass environment variables through from the host. +- * - Send stdout and stderr to a log file so we capture all output +- * in error messages. +- * - Use setarch when running x86_64 host + i686 guest. +- * Also catch errors and dump the log file completely on error. +- *) +- let env_vars = +- List.filter_map ( +- fun name -> +- try Some (sprintf "export %s=%s" name (quote (Sys.getenv name))) +- with Not_found -> None +- ) [ "http_proxy"; "https_proxy"; "ftp_proxy"; "no_proxy" ] in +- let env_vars = String.concat "\n" env_vars ^ "\n" in +- +- let cmd = +- match Guestfs_config.host_cpu, guest_arch with +- | "x86_64", ("i386"|"i486"|"i586"|"i686") -> +- sprintf "setarch i686 <<\"__EOCMD\" +-%s +-__EOCMD +-" cmd +- | _ -> cmd in +- +- let cmd = sprintf "\ +-exec >>%s 2>&1 +-%s +-%s +-" (quote logfile) env_vars cmd in +- +- debug "running command:\n%s" cmd; +- try ignore (g#sh cmd) ++ Guestfs_config.host_cpu guest_arch ++ in ++ ++ try ++ run_in_guest_command g root ~logfile ~incompatible_fn cmd + with + G.Error msg -> + debug_logfile (); +-- +2.25.4 + diff --git a/SOURCES/0060-inspect-fix-icon-of-RHEL.patch b/SOURCES/0060-inspect-fix-icon-of-RHEL.patch deleted file mode 100644 index dec3e9d..0000000 --- a/SOURCES/0060-inspect-fix-icon-of-RHEL.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 31af609ecc65424bb3671c6873005f31fd1b80d4 Mon Sep 17 00:00:00 2001 -From: Pino Toscano -Date: Mon, 11 Feb 2019 19:28:00 +0100 -Subject: [PATCH] inspect: fix icon of RHEL - -Use a better icon for RHEL guests, still provided by redhat-logos (or -equivalent in downstream distributions), and which fits a better -definition of logo for the distribution. - -Thanks to Ray Strode for the hints. - -(cherry picked from commit c648052690a4a07a59c741308e0e8497d6f18057) ---- - lib/inspect-icon.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/lib/inspect-icon.c b/lib/inspect-icon.c -index 0edd3d1b0..443dc6dd3 100644 ---- a/lib/inspect-icon.c -+++ b/lib/inspect-icon.c -@@ -301,7 +301,7 @@ icon_rhel (guestfs_h *g, int major, size_t *size_r) - if (major < 7) - shadowman = "/usr/share/pixmaps/redhat/shadowman-transparent.png"; - else -- shadowman = "/usr/share/pixmaps/fedora-logo-sprite.png"; -+ shadowman = "/usr/share/icons/hicolor/96x96/apps/system-logo-icon.png"; - - return get_png (g, shadowman, size_r, 102400); - } --- -2.21.0 - diff --git a/SOURCES/0061-inspect-fix-inspection-of-partition-less-devices-RHB.patch b/SOURCES/0061-inspect-fix-inspection-of-partition-less-devices-RHB.patch deleted file mode 100644 index 57e7aef..0000000 --- a/SOURCES/0061-inspect-fix-inspection-of-partition-less-devices-RHB.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 751afe91e07286effcc9af81c5d29b19cfa278ec Mon Sep 17 00:00:00 2001 -From: Pino Toscano -Date: Mon, 14 Jan 2019 17:07:45 +0100 -Subject: [PATCH] inspect: fix inspection of partition-less devices - (RHBZ#1661038) - -When parsing "xdev"-kind devices, do not assume that the partition -number can be converted to integer: re_xdev accepts an empty part of the -partition number, so just handle as it is, as string. - -This fixes a regression due to the conversion of the inspection code to -OCaml, as the old C version did not have this issue. - -(cherry picked from commit cf6b527824b2a8dc6e8bc65e38ebdceb227e6db1) ---- - daemon/inspect_fs_unix_fstab.ml | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/daemon/inspect_fs_unix_fstab.ml b/daemon/inspect_fs_unix_fstab.ml -index 170440d2c..3428ad75c 100644 ---- a/daemon/inspect_fs_unix_fstab.ml -+++ b/daemon/inspect_fs_unix_fstab.ml -@@ -347,7 +347,7 @@ and resolve_fstab_device spec md_map os_type = - debug_matching "xdev"; - let typ = PCRE.sub 1 - and disk = PCRE.sub 2 -- and part = int_of_string (PCRE.sub 3) in -+ and part = PCRE.sub 3 in - resolve_xdev typ disk part default - ) - -@@ -464,7 +464,7 @@ and resolve_fstab_device spec md_map os_type = - debug_matching "Hurd"; - let typ = PCRE.sub 1 - and disk = int_of_string (PCRE.sub 2) -- and part = int_of_string (PCRE.sub 3) in -+ and part = PCRE.sub 3 in - - (* Hurd disk devices are like /dev/hdNsM, where hdN is the - * N-th disk and M is the M-th partition on that disk. -@@ -501,7 +501,7 @@ and resolve_xdev typ disk part default = - let i = drive_index disk in - if i >= 0 && i < Array.length devices then ( - let dev = Array.get devices i in -- let dev = dev ^ string_of_int part in -+ let dev = dev ^ part in - if is_partition dev then - Mountable.of_device dev - else --- -2.21.0 - diff --git a/SOURCES/0061-sysprep-add-a-update_system_ca_store-side-effect.patch b/SOURCES/0061-sysprep-add-a-update_system_ca_store-side-effect.patch new file mode 100644 index 0000000..7b66f71 --- /dev/null +++ b/SOURCES/0061-sysprep-add-a-update_system_ca_store-side-effect.patch @@ -0,0 +1,138 @@ +From f3fa23fd9db0723bbeccffc79ce12a707d284643 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Mon, 4 May 2020 12:05:18 +0200 +Subject: [PATCH] sysprep: add a update_system_ca_store side effect + +Add a simple side effect to make operation flag that a regeneration of +the system CA store is needed. In case it is flagged, regenerate the +system CA store directly, or using a firstboot script in case of +incompatible architectures. + +This change is almost a no-op, since no operation requires the +regeneration of the system CA store yet. + +(cherry picked from commit bb7fc6d0a1ed670d16a92d2afd9ff2f876edc595) +--- + sysprep/main.ml | 5 +++++ + sysprep/sysprep_operation.ml | 3 +++ + sysprep/sysprep_operation.mli | 2 ++ + sysprep/utils.ml | 32 ++++++++++++++++++++++++++++++++ + sysprep/utils.mli | 4 ++++ + 5 files changed, 46 insertions(+) + +diff --git a/sysprep/main.ml b/sysprep/main.ml +index 04fd7b23c..4b03d5b48 100644 +--- a/sysprep/main.ml ++++ b/sysprep/main.ml +@@ -25,6 +25,7 @@ open Common_gettext.Gettext + open Getopt.OptionName + + open Sysprep_operation ++open Utils + + module G = Guestfs + +@@ -236,6 +237,10 @@ read the man page virt-sysprep(1). + Sysprep_operation.perform_operations_on_filesystems + ?operations g root side_effects; + ++ (* Do we need to update the system CA store? *) ++ if side_effects#get_update_system_ca_store then ++ update_system_ca_store g root; ++ + (* Unmount everything in this guest. *) + g#umount_all (); + +diff --git a/sysprep/sysprep_operation.ml b/sysprep/sysprep_operation.ml +index 0013ff504..53f042402 100644 +--- a/sysprep/sysprep_operation.ml ++++ b/sysprep/sysprep_operation.ml +@@ -27,10 +27,13 @@ class filesystem_side_effects = + object + val mutable m_created_file = false + val mutable m_changed_file = false ++ val mutable m_update_system_ca_store = false + method created_file () = m_created_file <- true + method get_created_file = m_created_file + method changed_file () = m_changed_file <- true + method get_changed_file = m_changed_file ++ method update_system_ca_store () = m_update_system_ca_store <- true ++ method get_update_system_ca_store = m_update_system_ca_store + end + + class device_side_effects = object end +diff --git a/sysprep/sysprep_operation.mli b/sysprep/sysprep_operation.mli +index 3d9f12550..2a02d5e79 100644 +--- a/sysprep/sysprep_operation.mli ++++ b/sysprep/sysprep_operation.mli +@@ -23,6 +23,8 @@ class filesystem_side_effects : object + method get_created_file : bool + method changed_file : unit -> unit + method get_changed_file : bool ++ method update_system_ca_store : unit -> unit ++ method get_update_system_ca_store : bool + end + (** The callback should indicate if it has side effects by calling + methods in this class. *) +diff --git a/sysprep/utils.ml b/sysprep/utils.ml +index 4c45d42de..29460b3c0 100644 +--- a/sysprep/utils.ml ++++ b/sysprep/utils.ml +@@ -20,6 +20,9 @@ + + open Printf + ++open Tools_utils ++open Common_gettext.Gettext ++ + let rec pod_of_list ?(style = `Dot) xs = + match style with + | `Verbatim -> String.concat "\n" (List.map ((^) " ") xs) +@@ -31,3 +34,32 @@ and _pod_of_list delim xs = + "=over 4\n\n" ^ + String.concat "" (List.map (sprintf "=item %s\n\n%s\n\n" delim) xs) ^ + "=back" ++ ++let rec update_system_ca_store g root = ++ let cmd = update_system_ca_store_command g root in ++ match cmd with ++ | None -> () ++ | Some cmd -> ++ (* Try to run the command directly if possible, adding it as ++ * firstboot script in case of incompatible architectures. ++ *) ++ let cmd = String.concat " " cmd in ++ let incompatible_fn () = ++ Firstboot.add_firstboot_script g root cmd cmd ++ in ++ ++ run_in_guest_command g root ~incompatible_fn cmd ++ ++and update_system_ca_store_command g root = ++ let typ = g#inspect_get_type root in ++ let distro = g#inspect_get_distro root in ++ match typ, distro with ++ | "linux", ("fedora"|"rhel"|"centos"|"scientificlinux"|"oraclelinux"|"redhat-based") -> ++ Some [ "update-ca-trust"; "extract" ] ++ ++ | "linux", ("debian"|"ubuntu"|"kalilinux") -> ++ Some [ "update-ca-certificates" ] ++ ++ | _, _ -> ++ warning (f_"updating the system CA store on this guest %s/%s is not supported") typ distro; ++ None +diff --git a/sysprep/utils.mli b/sysprep/utils.mli +index a57a0d876..82779620e 100644 +--- a/sysprep/utils.mli ++++ b/sysprep/utils.mli +@@ -26,3 +26,7 @@ val pod_of_list : ?style:[`Verbatim|`Star|`Dash|`Dot] -> string list -> string + use a space-indented (verbatim) block. [`Star], [`Dash] or [`Dot] + meaning use a real list with [*], [-] or [·]. The default + style is [·] ([`Dot]). *) ++ ++val update_system_ca_store : Guestfs.guestfs -> string -> unit ++(** Update the system CA store on the guest for the specified root ++ (which is fully mounted). *) +-- +2.25.4 + diff --git a/SOURCES/0062-sysprep-ca-certificates-request-system-CA-store-upda.patch b/SOURCES/0062-sysprep-ca-certificates-request-system-CA-store-upda.patch new file mode 100644 index 0000000..6505f87 --- /dev/null +++ b/SOURCES/0062-sysprep-ca-certificates-request-system-CA-store-upda.patch @@ -0,0 +1,42 @@ +From d78ec54de6b5ba915445d668ebf292bc9ff38a9a Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Mon, 4 May 2020 12:15:43 +0200 +Subject: [PATCH] sysprep: ca-certificates: request system CA store update + +In case any certificate is removed from the guest, regenerate the system +CA store. + +(cherry picked from commit b9065fa7adc93123c53f4827e11dad6b210b7d4b) +--- + sysprep/sysprep_operation_ca_certificates.ml | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/sysprep/sysprep_operation_ca_certificates.ml b/sysprep/sysprep_operation_ca_certificates.ml +index e481cebf8..a2b7986c1 100644 +--- a/sysprep/sysprep_operation_ca_certificates.ml ++++ b/sysprep/sysprep_operation_ca_certificates.ml +@@ -39,7 +39,11 @@ let ca_certificates_perform (g : Guestfs.guestfs) root side_effects = + let set = StringSet.diff set excepts in + StringSet.iter ( + fun filename -> +- try g#rm filename with G.Error _ -> () ++ try ++ g#rm filename; ++ side_effects#update_system_ca_store () ++ with ++ G.Error _ -> () + ) set + ) + +@@ -48,6 +52,8 @@ let op = { + name = "ca-certificates"; + enabled_by_default = false; + heading = s_"Remove CA certificates in the guest"; ++ pod_description = Some (s_"\ ++In case any certificate is removed, the system CA store is updated."); + perform_on_filesystems = Some ca_certificates_perform; + } + +-- +2.25.4 + diff --git a/SOURCES/0062-v2v-update-documentation-on-nbdkit-RHBZ-1605242.patch b/SOURCES/0062-v2v-update-documentation-on-nbdkit-RHBZ-1605242.patch deleted file mode 100644 index 2147188..0000000 --- a/SOURCES/0062-v2v-update-documentation-on-nbdkit-RHBZ-1605242.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 6ea20c9a03cb9ecadd60a1197499a4eaa4593416 Mon Sep 17 00:00:00 2001 -From: Pino Toscano -Date: Fri, 12 Apr 2019 16:19:43 +0200 -Subject: [PATCH] v2v: update documentation on nbdkit (RHBZ#1605242) - -nbdkit >= 1.6 ships a VDDK plugin always built, so recommend that -version instead of recommending to build nbdkit from sources. - -(cherry picked from commit 0704d8eb0bcc8139886eb4291f75a3ca49a91e58) ---- - v2v/virt-v2v.pod | 28 ++-------------------------- - 1 file changed, 2 insertions(+), 26 deletions(-) - -diff --git a/v2v/virt-v2v.pod b/v2v/virt-v2v.pod -index f4d200e3d..74536a2a6 100644 ---- a/v2v/virt-v2v.pod -+++ b/v2v/virt-v2v.pod -@@ -1657,32 +1657,8 @@ library is permitted by the license. - - =item 2. - --You must also compile nbdkit, enabling the VDDK plugin. nbdkit E --1.1.25 is recommended, but it is usually best to compile from the git --tree. -- --=over 4 -- --=item * -- --L -- --=item * -- --L -- --=back -- --Compile nbdkit as described in the sources (see link above). -- --You do B need to run C because you can run nbdkit --from its source directory. The source directory has a shell script --called F which runs the locally built copy of nbdkit and its --plugins. So set C<$PATH> to point to the nbdkit top build directory --(that is, the directory containing the shell script called F), --eg: -- -- export PATH=/path/to/nbdkit-1.1.x:$PATH -+nbdkit E 1.6 is recommended, as it ships with the VDDK plugin -+enabled unconditionally. - - =item 3. - --- -2.21.0 - diff --git a/SOURCES/0063-Use-proper-label-for-nbdkit-sockets.patch b/SOURCES/0063-Use-proper-label-for-nbdkit-sockets.patch deleted file mode 100644 index 7dea3ce..0000000 --- a/SOURCES/0063-Use-proper-label-for-nbdkit-sockets.patch +++ /dev/null @@ -1,63 +0,0 @@ -From c7942097bff8cbbfbee34e1750223c308f32f8a4 Mon Sep 17 00:00:00 2001 -From: Martin Kletzander -Date: Mon, 27 May 2019 13:30:05 +0200 -Subject: [PATCH] Use proper label for nbdkit sockets - -While svirt_t can be used for sockets it does not always guarantee that it will -be accessible from a virtual machine. The VM might be running under svirt_tcg_t -context which will need a svirt_tcg_t label on the socket in order to access it. - -There is, however, another label, svirt_socket_t, which is accessible from -virt_domain: - - # sesearch -A -s svirt_t -c unix_stream_socket -p connectto - ... - allow virt_domain svirt_socket_t:unix_stream_socket { ... connectto ... }; - ... - -And virt_domain is a type attribute of both svirt_t and svirt_tcg_t: - - # seinfo -x -a virt_domain - Type Attributes: 1 - attribute virt_domain; - svirt_t - svirt_tcg_t - -Resolves: https://bugzilla.redhat.com/1698437 - -Signed-off-by: Martin Kletzander -(cherry picked from commit c2918b8b74506523a723b804d452816a059c5e50) ---- - v2v/input_libvirt_vddk.ml | 2 +- - v2v/output_rhv_upload.ml | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/v2v/input_libvirt_vddk.ml b/v2v/input_libvirt_vddk.ml -index 0b3ed7af9..5e8e60bd2 100644 ---- a/v2v/input_libvirt_vddk.ml -+++ b/v2v/input_libvirt_vddk.ml -@@ -292,7 +292,7 @@ object - add_arg "--newstyle"; (* use newstyle NBD protocol *) - add_arg "--exportname"; add_arg "/"; - if have_selinux then ( (* label the socket so qemu can open it *) -- add_arg "--selinux-label"; add_arg "system_u:object_r:svirt_t:s0" -+ add_arg "--selinux-label"; add_arg "system_u:object_r:svirt_socket_t:s0" - ); - - (* Name of the plugin. Everything following is a plugin parameter. *) -diff --git a/v2v/output_rhv_upload.ml b/v2v/output_rhv_upload.ml -index 79a2fc8fd..fc33e5033 100644 ---- a/v2v/output_rhv_upload.ml -+++ b/v2v/output_rhv_upload.ml -@@ -230,7 +230,7 @@ See also \"OUTPUT TO RHV\" in the virt-v2v(1) manual.") - let args = - (* label the socket so qemu can open it *) - if have_selinux then -- args @ ["--selinux-label"; "system_u:object_r:svirt_t:s0"] -+ args @ ["--selinux-label"; "system_u:object_r:svirt_socket_t:s0"] - else args in - args in - --- -2.21.0 - diff --git a/SOURCES/0063-sysprep-add-IPA-offline-unenrollment-RHBZ-1789592.patch b/SOURCES/0063-sysprep-add-IPA-offline-unenrollment-RHBZ-1789592.patch new file mode 100644 index 0000000..e3d6243 --- /dev/null +++ b/SOURCES/0063-sysprep-add-IPA-offline-unenrollment-RHBZ-1789592.patch @@ -0,0 +1,107 @@ +From fa3ff43b763d191ae542594f75987a3686c847b2 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Thu, 7 May 2020 13:53:21 +0200 +Subject: [PATCH] sysprep: add IPA offline unenrollment (RHBZ#1789592) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This new operation unenrolls the guest from a IPA server offline, by +removing the configuration files and certificates. + +Thanks to Christian Heimes and François Cami for the hints. + +(cherry picked from commit 0a53e2c7fc4fe2aa69052134230db0804849b470) +--- + sysprep/Makefile.am | 1 + + sysprep/sysprep_operation_ipa_client.ml | 66 +++++++++++++++++++++++++ + 2 files changed, 67 insertions(+) + create mode 100644 sysprep/sysprep_operation_ipa_client.ml + +diff --git a/sysprep/Makefile.am b/sysprep/Makefile.am +index e6269c3f7..79266314b 100644 +--- a/sysprep/Makefile.am ++++ b/sysprep/Makefile.am +@@ -43,6 +43,7 @@ operations = \ + flag_reconfiguration \ + firewall_rules \ + fs_uuids \ ++ ipa_client \ + kerberos_data \ + lvm_uuids \ + logfiles \ +diff --git a/sysprep/sysprep_operation_ipa_client.ml b/sysprep/sysprep_operation_ipa_client.ml +new file mode 100644 +index 000000000..6e64a754a +--- /dev/null ++++ b/sysprep/sysprep_operation_ipa_client.ml +@@ -0,0 +1,66 @@ ++(* virt-sysprep ++ * Copyright (C) 2020 Red Hat Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ *) ++ ++open Sysprep_operation ++open Common_gettext.Gettext ++ ++module G = Guestfs ++ ++let ipa_client_perform (g : Guestfs.guestfs) root side_effects = ++ let typ = g#inspect_get_type root in ++ if typ = "linux" then ( ++ (* Simple paths with no side effects. *) ++ let paths = [ "/etc/ipa/ca.crt"; ++ "/etc/ipa/default.conf"; ++ "/var/lib/ipa-client/sysrestore/*"; ++ "/var/lib/ipa-client/pki/*" ] in ++ let paths = List.concat (List.map Array.to_list (List.map g#glob_expand paths)) in ++ List.iter ( ++ fun filename -> ++ try g#rm filename with G.Error _ -> () ++ ) paths; ++ ++ (* Certificates in the system CA store. *) ++ let certs = [ "/etc/pki/ca-trust/source/anchors/ipa-ca.crt"; ++ "/usr/local/share/ca-certificates/ipa-ca.crt"; ++ "/etc/pki/ca-trust/source/ipa.p11-kit" ] in ++ List.iter ( ++ fun filename -> ++ try ++ g#rm filename; ++ side_effects#update_system_ca_store () ++ with ++ G.Error _ -> () ++ ) certs ++ ) ++ ++let op = { ++ defaults with ++ name = "ipa-client"; ++ enabled_by_default = true; ++ heading = s_"Remove the IPA files"; ++ pod_description = Some (s_"\ ++Remove all the files related to an IPA (Identity, Policy, Audit) system. ++This effectively unenrolls the guest from an IPA server without interacting ++with it. ++ ++This operation does not run C."); ++ perform_on_filesystems = Some ipa_client_perform; ++} ++ ++let () = register_operation op +-- +2.25.4 + diff --git a/SOURCES/0064-sysprep-add-Kerberos-keytab-file-removal.patch b/SOURCES/0064-sysprep-add-Kerberos-keytab-file-removal.patch new file mode 100644 index 0000000..96ecb64 --- /dev/null +++ b/SOURCES/0064-sysprep-add-Kerberos-keytab-file-removal.patch @@ -0,0 +1,81 @@ +From 7700915a65bfed5f6a9b80d63daf572bff33e154 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Thu, 7 May 2020 14:02:30 +0200 +Subject: [PATCH] sysprep: add Kerberos keytab file removal +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This new operation removes the Kerberos /etc/krb5.keytab file from the +guest. + +Thanks to Christian Heimes and François Cami for the hints. + +Related to RHBZ#1789592. + +(cherry picked from commit faa5d8507f552e05435312f16d9e50f613a13615) +--- + sysprep/Makefile.am | 1 + + .../sysprep_operation_kerberos_hostkeytab.ml | 38 +++++++++++++++++++ + 2 files changed, 39 insertions(+) + create mode 100644 sysprep/sysprep_operation_kerberos_hostkeytab.ml + +diff --git a/sysprep/Makefile.am b/sysprep/Makefile.am +index 79266314b..a99957306 100644 +--- a/sysprep/Makefile.am ++++ b/sysprep/Makefile.am +@@ -45,6 +45,7 @@ operations = \ + fs_uuids \ + ipa_client \ + kerberos_data \ ++ kerberos_hostkeytab \ + lvm_uuids \ + logfiles \ + machine_id \ +diff --git a/sysprep/sysprep_operation_kerberos_hostkeytab.ml b/sysprep/sysprep_operation_kerberos_hostkeytab.ml +new file mode 100644 +index 000000000..cb3023353 +--- /dev/null ++++ b/sysprep/sysprep_operation_kerberos_hostkeytab.ml +@@ -0,0 +1,38 @@ ++(* virt-sysprep ++ * Copyright (C) 2020 Red Hat Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ *) ++ ++open Sysprep_operation ++open Common_gettext.Gettext ++ ++module G = Guestfs ++ ++let kerberos_hostkeytab_perform (g : Guestfs.guestfs) root side_effects = ++ let typ = g#inspect_get_type root in ++ if typ <> "windows" then ( ++ (try g#rm "/etc/krb5.keytab" with G.Error _ -> ()) ++ ) ++ ++let op = { ++ defaults with ++ name = "kerberos-hostkeytab"; ++ enabled_by_default = true; ++ heading = s_"Remove the Kerberos host keytab file in the guest"; ++ perform_on_filesystems = Some kerberos_hostkeytab_perform; ++} ++ ++let () = register_operation op +-- +2.25.4 + diff --git a/SOURCES/0064-v2v-i-vmx-Use-scp-T-option-if-available-to-unbreak-s.patch b/SOURCES/0064-v2v-i-vmx-Use-scp-T-option-if-available-to-unbreak-s.patch deleted file mode 100644 index cc158d0..0000000 --- a/SOURCES/0064-v2v-i-vmx-Use-scp-T-option-if-available-to-unbreak-s.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 06e5cfb90bc63f1d6c56821f0745c6fa8d3f8259 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Thu, 25 Jul 2019 14:52:42 +0100 -Subject: [PATCH] v2v: -i vmx: Use scp -T option if available to unbreak scp - (RHBZ#1733168). - -Tested using: - -cd v2v -LIBGUESTFS_BACKEND=direct ../run virt-v2v -i vmx -it ssh "ssh://localhost/$PWD/test-v2v-i-vmx-1.vmx" -o null -v -x - -and manually examining the debug output. - -Thanks: Ming Xie, Jakub Jelen. -(cherry picked from commit 7692c31494f7b1d37e380eed9eb99c5952940dbf) ---- - v2v/input_vmx.ml | 8 +++++++- - 1 file changed, 7 insertions(+), 1 deletion(-) - -diff --git a/v2v/input_vmx.ml b/v2v/input_vmx.ml -index f79e89139..695266313 100644 ---- a/v2v/input_vmx.ml -+++ b/v2v/input_vmx.ml -@@ -61,6 +61,11 @@ let server_of_uri { Xml.uri_server } = - let path_of_uri { Xml.uri_path } = - match uri_path with None -> assert false | Some p -> p - -+let scp_supports_T_option = lazy ( -+ let cmd = "LANG=C scp -T |& grep \"unknown option\"" in -+ shell_command cmd <> 0 -+) -+ - (* 'scp' a remote file into a temporary local file, returning the path - * of the temporary local file. - *) -@@ -68,8 +73,9 @@ let scp_from_remote_to_temporary uri tmpdir filename = - let localfile = tmpdir // filename in - - let cmd = -- sprintf "scp%s%s %s%s:%s %s" -+ sprintf "scp%s%s%s %s%s:%s %s" - (if verbose () then "" else " -q") -+ (if Lazy.force scp_supports_T_option then " -T" else "") - (match port_of_uri uri with - | None -> "" - | Some port -> sprintf " -P %d" port) --- -2.21.0 - diff --git a/SOURCES/0065-RHEL-8-Remove-libguestfs-live-RHBZ-798980.patch b/SOURCES/0065-RHEL-8-Remove-libguestfs-live-RHBZ-798980.patch index 72e3cfd..131014d 100644 --- a/SOURCES/0065-RHEL-8-Remove-libguestfs-live-RHBZ-798980.patch +++ b/SOURCES/0065-RHEL-8-Remove-libguestfs-live-RHBZ-798980.patch @@ -1,4 +1,4 @@ -From 23dcb04f1c8365df1a8ed7c0dd25081169f41571 Mon Sep 17 00:00:00 2001 +From 0647a3a475c647d363205bdbdaca8a79614460c3 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Fri, 21 Dec 2012 15:50:11 +0000 Subject: [PATCH] RHEL 8: Remove libguestfs live (RHBZ#798980). @@ -9,7 +9,7 @@ This isn't supported in RHEL 8. 1 file changed, 7 insertions(+) diff --git a/lib/launch-unix.c b/lib/launch-unix.c -index 9af481fd9..974336ccd 100644 +index 4794a7b13..993b83601 100644 --- a/lib/launch-unix.c +++ b/lib/launch-unix.c @@ -37,6 +37,12 @@ @@ -34,5 +34,5 @@ index 9af481fd9..974336ccd 100644 static int -- -2.21.0 +2.25.4 diff --git a/SOURCES/0066-RHEL-8-Remove-9p-APIs-from-RHEL-RHBZ-921710.patch b/SOURCES/0066-RHEL-8-Remove-9p-APIs-from-RHEL-RHBZ-921710.patch index 25cdf4b..a2d0e91 100644 --- a/SOURCES/0066-RHEL-8-Remove-9p-APIs-from-RHEL-RHBZ-921710.patch +++ b/SOURCES/0066-RHEL-8-Remove-9p-APIs-from-RHEL-RHBZ-921710.patch @@ -1,4 +1,4 @@ -From 192ac41979f7b7b1f029843a7915cf40b0535e5f Mon Sep 17 00:00:00 2001 +From 3341114876c1a2df330b68d15026ba266d557d6e Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Thu, 18 Jul 2013 18:31:53 +0100 Subject: [PATCH] RHEL 8: Remove 9p APIs from RHEL (RHBZ#921710). @@ -16,7 +16,7 @@ Subject: [PATCH] RHEL 8: Remove 9p APIs from RHEL (RHBZ#921710). delete mode 100644 daemon/9p.c diff --git a/Makefile.am b/Makefile.am -index cc363341f..8fb25a57c 100644 +index 0067d7b7b..e9351eadc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -78,7 +78,7 @@ SUBDIRS += tests/xfs @@ -259,7 +259,7 @@ index 55644249d..000000000 - return 0; -} diff --git a/daemon/Makefile.am b/daemon/Makefile.am -index dcae1a66c..75bef5500 100644 +index 5d1c222db..a9b40be25 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -76,7 +76,6 @@ guestfsd_SOURCES = \ @@ -271,10 +271,10 @@ index dcae1a66c..75bef5500 100644 actions.h \ available.c \ diff --git a/docs/C_SOURCE_FILES b/docs/C_SOURCE_FILES -index f3ee61e0d..e8b1d5283 100644 +index 7f1c60b30..f45e7124d 100644 --- a/docs/C_SOURCE_FILES +++ b/docs/C_SOURCE_FILES -@@ -70,7 +70,6 @@ common/windows/windows.h +@@ -71,7 +71,6 @@ common/windows/windows.h customize/crypt-c.c customize/dummy.c customize/perl_edit-c.c @@ -283,10 +283,10 @@ index f3ee61e0d..e8b1d5283 100644 daemon/actions.h daemon/augeas.c diff --git a/generator/actions_core.ml b/generator/actions_core.ml -index 2ae3ec1d9..237edafce 100644 +index deda483a9..f466600df 100644 --- a/generator/actions_core.ml +++ b/generator/actions_core.ml -@@ -6179,27 +6179,6 @@ This returns true iff the device exists and contains all zero bytes. +@@ -6167,27 +6167,6 @@ This returns true iff the device exists and contains all zero bytes. Note that for large devices this can take a long time to run." }; @@ -315,7 +315,7 @@ index 2ae3ec1d9..237edafce 100644 name = "list_dm_devices"; added = (1, 11, 15); style = RStringList (RDevice, "devices"), [], []; diff --git a/generator/proc_nr.ml b/generator/proc_nr.ml -index 9e16ab14a..e6b018c62 100644 +index 11a557076..1ef5ba0b7 100644 --- a/generator/proc_nr.ml +++ b/generator/proc_nr.ml @@ -295,8 +295,6 @@ let proc_nr = [ @@ -328,7 +328,7 @@ index 9e16ab14a..e6b018c62 100644 288, "ntfsresize"; 289, "btrfs_filesystem_resize"; diff --git a/gobject/Makefile.inc b/gobject/Makefile.inc -index 5aa2dcafe..b8f8e9226 100644 +index 067f861a9..7afe83c59 100644 --- a/gobject/Makefile.inc +++ b/gobject/Makefile.inc @@ -93,7 +93,6 @@ guestfs_gobject_headers= \ @@ -348,7 +348,7 @@ index 5aa2dcafe..b8f8e9226 100644 src/optargs-ntfsclone_out.c \ src/optargs-ntfsfix.c \ diff --git a/po/POTFILES b/po/POTFILES -index a049d66fe..5daec8a89 100644 +index 79f4b8c56..b99333d0d 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -58,7 +58,6 @@ customize/crypt-c.c @@ -359,7 +359,7 @@ index a049d66fe..5daec8a89 100644 daemon/acl.c daemon/augeas.c daemon/available.c -@@ -290,7 +289,6 @@ gobject/src/optargs-mkfs_btrfs.c +@@ -291,7 +290,6 @@ gobject/src/optargs-mkfs_btrfs.c gobject/src/optargs-mksquashfs.c gobject/src/optargs-mkswap.c gobject/src/optargs-mktemp.c @@ -368,5 +368,5 @@ index a049d66fe..5daec8a89 100644 gobject/src/optargs-ntfsclone_out.c gobject/src/optargs-ntfsfix.c -- -2.21.0 +2.25.4 diff --git a/SOURCES/0067-RHEL-8-Disable-unsupported-remote-drive-protocols-RH.patch b/SOURCES/0067-RHEL-8-Disable-unsupported-remote-drive-protocols-RH.patch index ddf1ce3..6037ba5 100644 --- a/SOURCES/0067-RHEL-8-Disable-unsupported-remote-drive-protocols-RH.patch +++ b/SOURCES/0067-RHEL-8-Disable-unsupported-remote-drive-protocols-RH.patch @@ -1,4 +1,4 @@ -From 2555618f32772df00f3ceb4a780d6c13f7b3d93c Mon Sep 17 00:00:00 2001 +From 717d8b6a2d0bb559684a436b4f1bc115ac36d3dd Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Mon, 29 Jul 2013 14:47:56 +0100 Subject: [PATCH] RHEL 8: Disable unsupported remote drive protocols @@ -62,7 +62,7 @@ index f558964bf..8f264ed17 100644 Run L on guests or disk images: diff --git a/fish/guestfish.pod b/fish/guestfish.pod -index bbf43aad5..f4762f929 100644 +index f1fdf094d..bacb60e0b 100644 --- a/fish/guestfish.pod +++ b/fish/guestfish.pod @@ -131,9 +131,9 @@ To list what is available do: @@ -77,7 +77,7 @@ index bbf43aad5..f4762f929 100644 =head2 Remote control -@@ -1127,12 +1127,12 @@ L>. +@@ -1145,12 +1145,12 @@ L>. On the command line, you can use the I<-a> option to add network block devices using a URI-style format, for example: @@ -92,7 +92,7 @@ index bbf43aad5..f4762f929 100644 The possible I<-a URI> formats are described below. -@@ -1142,40 +1142,6 @@ The possible I<-a URI> formats are described below. +@@ -1160,40 +1160,6 @@ The possible I<-a URI> formats are described below. Add the local disk image (or device) called F. @@ -133,7 +133,7 @@ index bbf43aad5..f4762f929 100644 =head2 B<-a nbd://example.com[:port]> =head2 B<-a nbd://example.com[:port]/exportname> -@@ -1210,35 +1176,13 @@ The equivalent API command would be: +@@ -1228,35 +1194,13 @@ The equivalent API command would be: > add pool/disk protocol:rbd server:tcp:example.com:port @@ -220,7 +220,7 @@ index 756df997b..8f84fd31b 100755 rm test-add-uri.out rm test-add-uri.img diff --git a/generator/actions_core.ml b/generator/actions_core.ml -index 237edafce..aca5b1f43 100644 +index f466600df..3893d0e8d 100644 --- a/generator/actions_core.ml +++ b/generator/actions_core.ml @@ -297,29 +297,6 @@ F is interpreted as a local file or device. @@ -373,7 +373,7 @@ index 82ef30093..3d712c6e4 100644 error (g, _("unknown protocol ‘%s’"), protocol); drv = NULL; /*FALLTHROUGH*/ diff --git a/lib/guestfs.pod b/lib/guestfs.pod -index c7fbeef03..18e336a1f 100644 +index af944ddb7..58559a6b4 100644 --- a/lib/guestfs.pod +++ b/lib/guestfs.pod @@ -714,70 +714,6 @@ servers. The server string is documented in @@ -491,7 +491,7 @@ index c7fbeef03..18e336a1f 100644 Libguestfs has APIs for inspecting an unknown disk image to find out diff --git a/tests/disks/test-qemu-drive-libvirt.sh b/tests/disks/test-qemu-drive-libvirt.sh -index ab8052de1..ad22b2fbb 100755 +index e49c69b43..9b1abc4ec 100755 --- a/tests/disks/test-qemu-drive-libvirt.sh +++ b/tests/disks/test-qemu-drive-libvirt.sh @@ -64,34 +64,6 @@ check_output @@ -605,5 +605,5 @@ index 19dd60a2f..583e031bd 100755 -grep -sq -- '-drive file=ssh://rich@example.com/disk.img,' "$DEBUG_QEMU_FILE" || fail -rm "$DEBUG_QEMU_FILE" -- -2.21.0 +2.25.4 diff --git a/SOURCES/0068-RHEL-8-Remove-User-Mode-Linux-RHBZ-1144197.patch b/SOURCES/0068-RHEL-8-Remove-User-Mode-Linux-RHBZ-1144197.patch index 1f202aa..28fbee6 100644 --- a/SOURCES/0068-RHEL-8-Remove-User-Mode-Linux-RHBZ-1144197.patch +++ b/SOURCES/0068-RHEL-8-Remove-User-Mode-Linux-RHBZ-1144197.patch @@ -1,4 +1,4 @@ -From 8d63a3e4116dfe165b7d68086195b5ed2be5cd14 Mon Sep 17 00:00:00 2001 +From 3d30c10f351b61c9c9aae54fd8a250af5cd8a61a Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Fri, 19 Sep 2014 13:38:20 +0100 Subject: [PATCH] RHEL 8: Remove User-Mode Linux (RHBZ#1144197). @@ -9,7 +9,7 @@ This isn't supported in RHEL 8. 1 file changed, 13 insertions(+) diff --git a/lib/launch-uml.c b/lib/launch-uml.c -index b8825cf56..1acf8db27 100644 +index da20c17d9..a5e0e8179 100644 --- a/lib/launch-uml.c +++ b/lib/launch-uml.c @@ -44,7 +44,9 @@ struct backend_uml_data { @@ -68,5 +68,5 @@ index b8825cf56..1acf8db27 100644 static int shutdown_uml (guestfs_h *g, void *datav, int check_for_errors) -- -2.21.0 +2.25.4 diff --git a/SOURCES/0069-RHEL-8-v2v-Select-correct-qemu-binary-for-o-qemu-mod.patch b/SOURCES/0069-RHEL-8-v2v-Select-correct-qemu-binary-for-o-qemu-mod.patch index a565f6d..567b1cc 100644 --- a/SOURCES/0069-RHEL-8-v2v-Select-correct-qemu-binary-for-o-qemu-mod.patch +++ b/SOURCES/0069-RHEL-8-v2v-Select-correct-qemu-binary-for-o-qemu-mod.patch @@ -1,4 +1,4 @@ -From 21ef3ee84af1b42d19659033132b2c22f7c611e4 Mon Sep 17 00:00:00 2001 +From fbc5eea00f9f9cd27a1c53913e58f8a4937fd067 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Sun, 28 Sep 2014 19:14:43 +0100 Subject: [PATCH] RHEL 8: v2v: Select correct qemu binary for -o qemu mode @@ -16,10 +16,10 @@ support cases. 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v2v/output_qemu.ml b/v2v/output_qemu.ml -index e23f22e12..c2f43119a 100644 +index 1f6798aaf..8665d7b5c 100644 --- a/v2v/output_qemu.ml +++ b/v2v/output_qemu.ml -@@ -79,7 +79,7 @@ object +@@ -81,7 +81,7 @@ object * module deals with shell and qemu comma quoting. *) let cmd = Qemuopts.create () in @@ -29,5 +29,5 @@ index e23f22e12..c2f43119a 100644 let flag = Qemuopts.flag cmd and arg = Qemuopts.arg cmd -- -2.21.0 +2.25.4 diff --git a/SOURCES/0070-RHEL-8-v2v-Disable-the-qemu-boot-option-RHBZ-1147313.patch b/SOURCES/0070-RHEL-8-v2v-Disable-the-qemu-boot-option-RHBZ-1147313.patch index 6e23ee1..038b7f2 100644 --- a/SOURCES/0070-RHEL-8-v2v-Disable-the-qemu-boot-option-RHBZ-1147313.patch +++ b/SOURCES/0070-RHEL-8-v2v-Disable-the-qemu-boot-option-RHBZ-1147313.patch @@ -1,4 +1,4 @@ -From 1219acf26ca0805cabe43c1841e4d4a82095f60d Mon Sep 17 00:00:00 2001 +From ec11bac4af65a54400739e476bf90fe815073619 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Tue, 30 Sep 2014 10:50:27 +0100 Subject: [PATCH] RHEL 8: v2v: Disable the --qemu-boot option (RHBZ#1147313). @@ -9,23 +9,24 @@ in RHEL 8's qemu-kvm. In addition you will have to edit the -display option in the qemu script. --- - v2v/cmdline.ml | 3 ++- - v2v/virt-v2v.pod | 13 ------------- - 2 files changed, 2 insertions(+), 14 deletions(-) + v2v/cmdline.ml | 3 ++- + v2v/virt-v2v-output-local.pod | 6 ++---- + v2v/virt-v2v.pod | 13 ------------- + 3 files changed, 4 insertions(+), 18 deletions(-) diff --git a/v2v/cmdline.ml b/v2v/cmdline.ml -index 97d4f4377..6bca12ce3 100644 +index 686631271..e3578ddcb 100644 --- a/v2v/cmdline.ml +++ b/v2v/cmdline.ml -@@ -228,7 +228,6 @@ let parse_cmdline () = - s_"Use password from file"; +@@ -262,7 +262,6 @@ let parse_cmdline () = + s_"Estimate size of source and stop"; [ L"print-source" ], Getopt.Set print_source, s_"Print source and stop"; - [ L"qemu-boot" ], Getopt.Set qemu_boot, s_"Boot in qemu (-o qemu only)"; [ L"root" ], Getopt.String ("ask|... ", set_root_choice), s_"How to choose root filesystem"; [ L"vddk-config" ], Getopt.String ("filename", set_input_option_compat "vddk-config"), -@@ -564,6 +563,8 @@ read the man page virt-v2v(1). +@@ -640,6 +639,8 @@ read the man page virt-v2v(1). | Some d when not (is_directory d) -> error (f_"-os %s: output directory does not exist or is not a directory") d | Some d -> d in @@ -34,11 +35,38 @@ index 97d4f4377..6bca12ce3 100644 Output_qemu.output_qemu os qemu_boot, output_format, output_alloc +diff --git a/v2v/virt-v2v-output-local.pod b/v2v/virt-v2v-output-local.pod +index 7c397c0a4..09a11a7b0 100644 +--- a/v2v/virt-v2v-output-local.pod ++++ b/v2v/virt-v2v-output-local.pod +@@ -9,7 +9,7 @@ or libvirt + + virt-v2v [-i* options] -o local -os DIRECTORY + +- virt-v2v [-i* options] -o qemu -os DIRECTORY [--qemu-boot] ++ virt-v2v [-i* options] -o qemu -os DIRECTORY + + virt-v2v [-i* options] -o json -os DIRECTORY + [-oo json-disks-pattern=PATTERN] +@@ -50,12 +50,10 @@ where C is the guest name. + + =item B<-o qemu -os> C + +-=item B<-o qemu -os> C B<--qemu-boot> +- + This converts the guest to files in C. Unlike I<-o local> + above, a shell script is created which contains the raw qemu command + you would need to boot the guest. However the shell script is not +-run, I you also add the I<--qemu-boot> option. ++run. + + =item B<-o json -os> C + diff --git a/v2v/virt-v2v.pod b/v2v/virt-v2v.pod -index 74536a2a6..30ed059e7 100644 +index 25041d0ec..bd606592b 100644 --- a/v2v/virt-v2v.pod +++ b/v2v/virt-v2v.pod -@@ -115,11 +115,6 @@ Since F contains the path(s) to the guest disk +@@ -142,11 +142,6 @@ Since F contains the path(s) to the guest disk image(s) you do not need to specify the name of the disk image on the command line. @@ -47,10 +75,10 @@ index 74536a2a6..30ed059e7 100644 - - virt-v2v -i disk disk.img -o qemu -os /var/tmp --qemu-boot - - =head1 INPUT AND OUTPUT MODES + =head1 OPTIONS - ┌────────────┐ ┌─────────▶ -o null -@@ -564,9 +559,6 @@ This is similar to I<-o local>, except that a shell script is written + =over 4 +@@ -510,9 +505,6 @@ This is similar to I<-o local>, except that a shell script is written which you can use to boot the guest in qemu. The converted disks and shell script are written to the directory specified by I<-os>. @@ -60,9 +88,9 @@ index 74536a2a6..30ed059e7 100644 =item B<-o> B This is the same as I<-o rhv>. -@@ -791,11 +783,6 @@ Print information about the source guest and stop. This option is +@@ -788,11 +780,6 @@ Print information about the source guest and stop. This option is useful when you are setting up network and bridge maps. - See L. + See L. -=item B<--qemu-boot> - @@ -73,5 +101,5 @@ index 74536a2a6..30ed059e7 100644 =item B<--quiet> -- -2.21.0 +2.25.4 diff --git a/SOURCES/0071-RHEL-8-Disable-alternate-Augeas-lenses.patch b/SOURCES/0071-RHEL-8-Disable-alternate-Augeas-lenses.patch index 42955fb..caafc5b 100644 --- a/SOURCES/0071-RHEL-8-Disable-alternate-Augeas-lenses.patch +++ b/SOURCES/0071-RHEL-8-Disable-alternate-Augeas-lenses.patch @@ -1,4 +1,4 @@ -From 36cf9904d4a5f2662cb5ffcca732fc2b57450aba Mon Sep 17 00:00:00 2001 +From 0abf9c24495d577d20fe0d972212dec4eb2b2e73 Mon Sep 17 00:00:00 2001 From: Pino Toscano Date: Fri, 24 Oct 2014 16:33:50 +0100 Subject: [PATCH] RHEL 8: Disable alternate Augeas lenses. @@ -14,7 +14,7 @@ https://www.redhat.com/archives/libguestfs/2014-October/msg00220.html 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/appliance/Makefile.am b/appliance/Makefile.am -index 6cba8d158..16714b197 100644 +index fc424b1d0..5efc5c036 100644 --- a/appliance/Makefile.am +++ b/appliance/Makefile.am @@ -91,7 +91,6 @@ supermin.d/daemon.tar.gz: ../daemon/guestfsd guestfs_shadow.aug @@ -56,5 +56,5 @@ index 453251337..5bbfffa2d 100644 return 0; } -- -2.21.0 +2.25.4 diff --git a/SOURCES/0072-RHEL-8-Fix-list-of-supported-sound-cards-to-match-RH.patch b/SOURCES/0072-RHEL-8-Fix-list-of-supported-sound-cards-to-match-RH.patch index 32f01aa..d1094d3 100644 --- a/SOURCES/0072-RHEL-8-Fix-list-of-supported-sound-cards-to-match-RH.patch +++ b/SOURCES/0072-RHEL-8-Fix-list-of-supported-sound-cards-to-match-RH.patch @@ -1,4 +1,4 @@ -From 61ef6194eeb687b4fbfa73e6392091aaf2404241 Mon Sep 17 00:00:00 2001 +From c5db36832644bb6330f90670e799d59cef3d6771 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Fri, 24 Apr 2015 09:45:41 -0400 Subject: [PATCH] RHEL 8: Fix list of supported sound cards to match RHEL qemu @@ -9,7 +9,7 @@ Subject: [PATCH] RHEL 8: Fix list of supported sound cards to match RHEL qemu 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/v2v/utils.ml b/v2v/utils.ml -index 67e2028f3..436acb5f1 100644 +index 74b501f81..21e9c9c15 100644 --- a/v2v/utils.ml +++ b/v2v/utils.ml @@ -51,13 +51,14 @@ let kvm_arch = function @@ -30,5 +30,5 @@ index 67e2028f3..436acb5f1 100644 (* Find the UEFI firmware. *) let find_uefi_firmware guest_arch = -- -2.21.0 +2.25.4 diff --git a/SOURCES/0073-RHEL-8-Reject-use-of-libguestfs-winsupport-features-.patch b/SOURCES/0073-RHEL-8-Reject-use-of-libguestfs-winsupport-features-.patch index dbc31fe..6105bed 100644 --- a/SOURCES/0073-RHEL-8-Reject-use-of-libguestfs-winsupport-features-.patch +++ b/SOURCES/0073-RHEL-8-Reject-use-of-libguestfs-winsupport-features-.patch @@ -1,4 +1,4 @@ -From 6ddcb894bc275079d1fb25554d91ca9f4b921406 Mon Sep 17 00:00:00 2001 +From dcd37841d19c43f5874b11a1f81e578df49d58e6 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Tue, 7 Jul 2015 09:28:03 -0400 Subject: [PATCH] RHEL 8: Reject use of libguestfs-winsupport features except @@ -9,7 +9,7 @@ Subject: [PATCH] RHEL 8: Reject use of libguestfs-winsupport features except 1 file changed, 16 insertions(+) diff --git a/generator/c.ml b/generator/c.ml -index 0366866e2..ded9685dc 100644 +index 86f7d89a3..b5bb99f53 100644 --- a/generator/c.ml +++ b/generator/c.ml @@ -1832,6 +1832,22 @@ and generate_client_actions actions () = @@ -36,5 +36,5 @@ index 0366866e2..ded9685dc 100644 * as a progress bar hint. *) -- -2.21.0 +2.25.4 diff --git a/SOURCES/0074-RHEL-8-Fix-tests-for-libguestfs-winsupport.patch b/SOURCES/0074-RHEL-8-Fix-tests-for-libguestfs-winsupport.patch index 6cf822e..0b21bba 100644 --- a/SOURCES/0074-RHEL-8-Fix-tests-for-libguestfs-winsupport.patch +++ b/SOURCES/0074-RHEL-8-Fix-tests-for-libguestfs-winsupport.patch @@ -1,4 +1,4 @@ -From 57bbc9d79d21c23becc9391b46944e8a992bd6ec Mon Sep 17 00:00:00 2001 +From e17bc8207168c45b2e887decc0a19b5689798b0b Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Sun, 30 Aug 2015 03:21:57 -0400 Subject: [PATCH] RHEL 8: Fix tests for libguestfs-winsupport. @@ -12,7 +12,7 @@ It doesn't let us use guestfish for arbitrary Windows edits. 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/test-data/phony-guests/make-windows-img.sh b/test-data/phony-guests/make-windows-img.sh -index d7c3ec9cf..9e556215a 100755 +index 8676b5ac0..1a88d9fc9 100755 --- a/test-data/phony-guests/make-windows-img.sh +++ b/test-data/phony-guests/make-windows-img.sh @@ -37,6 +37,7 @@ fi @@ -89,5 +89,5 @@ index f1da222a9..ff94fe39b 100755 # We also update the Registry several times, for firstboot, and (ONLY -- -2.21.0 +2.25.4 diff --git a/SOURCES/0075-RHEL-8-Revert-v2v-Add-a-support-matrix-to-the-manual.patch b/SOURCES/0075-RHEL-8-Revert-v2v-Add-a-support-matrix-to-the-manual.patch deleted file mode 100644 index f7d74e0..0000000 --- a/SOURCES/0075-RHEL-8-Revert-v2v-Add-a-support-matrix-to-the-manual.patch +++ /dev/null @@ -1,125 +0,0 @@ -From b0399c4e709f9d94e796bbeda90d27e3ed0dc43d Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Mon, 21 Sep 2015 15:49:17 +0100 -Subject: [PATCH] RHEL 8: Revert "v2v: Add a support matrix to the manual - page." - -This reverts commit a03bffa15a5357d5d0244595caf99607be1ec3ab. ---- - v2v/virt-v2v.pod | 100 ----------------------------------------------- - 1 file changed, 100 deletions(-) - -diff --git a/v2v/virt-v2v.pod b/v2v/virt-v2v.pod -index 30ed059e7..276fcea85 100644 ---- a/v2v/virt-v2v.pod -+++ b/v2v/virt-v2v.pod -@@ -167,106 +167,6 @@ only used when virt-v2v runs under VDSM control. - I<--in-place> instructs virt-v2v to customize the guest OS in the input - virtual machine, instead of creating a new VM in the target hypervisor. - --=head1 SUPPORT MATRIX -- --=head2 Hypervisors (Input) -- --=over 4 -- --=item VMware ESXi -- --Must be managed by VMware vCenter E 5.0 unless VDDK is available. -- --=item OVA exported from VMware -- --OVAs from other hypervisors will not work. -- --=item VMX from VMware -- --VMX files generated by other hypervisors will not work. -- --=item RHEL 5 Xen -- --=item SUSE Xen -- --=item Citrix Xen -- --Citrix Xen has not been recently tested. -- --=item Hyper-V -- --Not recently tested. Requires that you export the disk or use --L on Hyper-V. -- --=item Direct from disk images -- --Only disk images exported from supported hypervisors, and using --container formats supported by qemu. -- --=item Physical machines -- --Using the L tool. -- --=back -- --=head2 Hypervisors (Output) -- --QEMU and KVM only. -- --=head2 Virtualization management systems (Output) -- --=over 4 -- --=item OpenStack Glance -- --=item Red Hat Virtualization (RHV) 4.1 and up -- --=item Local libvirt -- --And hence L, L, and similar tools. -- --=item Local disk -- --=back -- --=head2 Guests -- --=over 4 -- --=item Red Hat Enterprise Linux 3, 4, 5, 6, 7 -- --=item CentOS 3, 4, 5, 6, 7 -- --=item Scientific Linux 3, 4, 5, 6, 7 -- --=item Oracle Linux -- --=item Fedora -- --=item SLES 10 and up -- --=item OpenSUSE 10 and up -- --=item Debian 6 and up -- --=item Ubuntu 10.04, 12.04, 14.04, 16.04, and up -- --=item Windows XP to Windows 10 / Windows Server 2016 -- --We use Windows internal version numbers, see --L -- --Currently NT 5.2 to NT 6.3 are supported. -- --See L below for additional notes on converting Windows --guests. -- --=back -- --=head2 Guest firmware -- --BIOS or UEFI for all guest types (but see L below). -- - =head1 OPTIONS - - =over 4 --- -2.21.0 - diff --git a/SOURCES/0075-RHEL-8-tests-Disable-daemon-tests-that-require-the-u.patch b/SOURCES/0075-RHEL-8-tests-Disable-daemon-tests-that-require-the-u.patch new file mode 100644 index 0000000..71a4655 --- /dev/null +++ b/SOURCES/0075-RHEL-8-tests-Disable-daemon-tests-that-require-the-u.patch @@ -0,0 +1,28 @@ +From fbda37c7b2819300b6b09d2b0b84cec547fdd00e Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Mon, 21 Sep 2015 13:12:43 -0400 +Subject: [PATCH] RHEL 8: tests: Disable daemon tests that require the 'unix' + backend. + +--- + tests/daemon/Makefile.am | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/tests/daemon/Makefile.am b/tests/daemon/Makefile.am +index 053cad3e1..0d723fee4 100644 +--- a/tests/daemon/Makefile.am ++++ b/tests/daemon/Makefile.am +@@ -23,9 +23,7 @@ include $(top_srcdir)/subdir-rules.mk + + check_DATA = captive-daemon.pm + +-TESTS = \ +- test-daemon-start.pl \ +- test-btrfs.pl ++TESTS = + + TESTS_ENVIRONMENT = $(top_builddir)/run --test + +-- +2.25.4 + diff --git a/SOURCES/0076-RHEL-8-tests-Disable-daemon-tests-that-require-the-u.patch b/SOURCES/0076-RHEL-8-tests-Disable-daemon-tests-that-require-the-u.patch deleted file mode 100644 index e53fe10..0000000 --- a/SOURCES/0076-RHEL-8-tests-Disable-daemon-tests-that-require-the-u.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 6918c7618f6e1b48704e7aa6f6b05ed8b926d589 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Mon, 21 Sep 2015 13:12:43 -0400 -Subject: [PATCH] RHEL 8: tests: Disable daemon tests that require the 'unix' - backend. - ---- - tests/daemon/Makefile.am | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - -diff --git a/tests/daemon/Makefile.am b/tests/daemon/Makefile.am -index 053cad3e1..0d723fee4 100644 ---- a/tests/daemon/Makefile.am -+++ b/tests/daemon/Makefile.am -@@ -23,9 +23,7 @@ include $(top_srcdir)/subdir-rules.mk - - check_DATA = captive-daemon.pm - --TESTS = \ -- test-daemon-start.pl \ -- test-btrfs.pl -+TESTS = - - TESTS_ENVIRONMENT = $(top_builddir)/run --test - --- -2.21.0 - diff --git a/SOURCES/0076-RHEL-8-v2v-Disable-the-virt-v2v-in-place-option.patch b/SOURCES/0076-RHEL-8-v2v-Disable-the-virt-v2v-in-place-option.patch new file mode 100644 index 0000000..c261226 --- /dev/null +++ b/SOURCES/0076-RHEL-8-v2v-Disable-the-virt-v2v-in-place-option.patch @@ -0,0 +1,286 @@ +From d6e49b3cd141cdf573e1e4f59d248007f3658435 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 14 Jan 2016 11:53:42 -0500 +Subject: [PATCH] RHEL 8: v2v: Disable the virt-v2v --in-place option. + +This disables the virt-v2v --in-place option which we do not +wish to support in RHEL. +(See commit d0069559a939e47e5f29973ed9a69a13f0b58301). +--- + v2v/Makefile.am | 2 - + v2v/cmdline.ml | 8 +-- + v2v/test-v2v-docs.sh | 1 + + v2v/test-v2v-in-place.sh | 108 --------------------------------------- + v2v/virt-v2v.pod | 48 +---------------- + 5 files changed, 7 insertions(+), 160 deletions(-) + delete mode 100755 v2v/test-v2v-in-place.sh + +diff --git a/v2v/Makefile.am b/v2v/Makefile.am +index 6568c9a6b..affa6f7e9 100644 +--- a/v2v/Makefile.am ++++ b/v2v/Makefile.am +@@ -469,7 +469,6 @@ if HAVE_LIBVIRT + TESTS += \ + test-v2v-cdrom.sh \ + test-v2v-floppy.sh \ +- test-v2v-in-place.sh \ + test-v2v-mac.sh \ + test-v2v-networks-and-bridges.sh \ + test-v2v-no-copy.sh \ +@@ -621,7 +620,6 @@ EXTRA_DIST += \ + test-v2v-i-vmx-3.vmx \ + test-v2v-i-vmx-4.vmx \ + test-v2v-i-vmx-5.vmx \ +- test-v2v-in-place.sh \ + test-v2v-it-vddk-io-query.sh \ + test-v2v-machine-readable.sh \ + test-v2v-mac-expected.xml \ +diff --git a/v2v/cmdline.ml b/v2v/cmdline.ml +index e3578ddcb..19c5a269b 100644 +--- a/v2v/cmdline.ml ++++ b/v2v/cmdline.ml +@@ -230,8 +230,7 @@ let parse_cmdline () = + s_"Use password from file to connect to input hypervisor"; + [ M"it" ], Getopt.String ("transport", set_string_option_once "-it" input_transport), + s_"Input transport"; +- [ L"in-place" ], Getopt.Set in_place, +- s_"Only tune the guest in the input VM"; ++ [ L"in-place" ], Getopt.Set in_place, Getopt.hidden_option_description; + [ L"mac" ], Getopt.String ("mac:network|bridge|ip:out", add_mac), + s_"Map NIC to network or bridge or assign static IP"; + [ S 'n'; L"network" ], Getopt.String ("in:out", add_network), +@@ -369,7 +368,6 @@ read the man page virt-v2v(1). + pr "vddk\n"; + pr "colours-option\n"; + pr "vdsm-compat-option\n"; +- pr "in-place\n"; + pr "io/oo\n"; + pr "mac-option\n"; + pr "mac-ip-option\n"; +@@ -544,6 +542,10 @@ read the man page virt-v2v(1). + error (f_"only ‘-it ssh’ can be used here") in + Input_vmx.input_vmx input_transport arg in + ++ (* Prevent use of --in-place option in RHEL. *) ++ if in_place then ++ error (f_"--in-place cannot be used in RHEL"); ++ + (* Common error message. *) + let error_option_cannot_be_used_in_output_mode mode opt = + error (f_"-o %s: %s option cannot be used in this output mode") mode opt +diff --git a/v2v/test-v2v-docs.sh b/v2v/test-v2v-docs.sh +index dfb12bb14..2e45705a3 100755 +--- a/v2v/test-v2v-docs.sh ++++ b/v2v/test-v2v-docs.sh +@@ -26,6 +26,7 @@ $top_srcdir/podcheck.pl virt-v2v.pod virt-v2v \ + --debug-overlay,\ + --ic,\ + --if,\ ++--in-place,\ + --io,\ + --ip,\ + --it,\ +diff --git a/v2v/test-v2v-in-place.sh b/v2v/test-v2v-in-place.sh +deleted file mode 100755 +index 6f7d78f39..000000000 +--- a/v2v/test-v2v-in-place.sh ++++ /dev/null +@@ -1,108 +0,0 @@ +-#!/bin/bash - +-# libguestfs virt-v2v test script +-# Copyright (C) 2014 Red Hat Inc. +-# Copyright (C) 2015 Parallels IP Holdings GmbH. +-# +-# This program is free software; you can redistribute it and/or modify +-# it under the terms of the GNU General Public License as published by +-# the Free Software Foundation; either version 2 of the License, or +-# (at your option) any later version. +-# +-# This program is distributed in the hope that it will be useful, +-# but WITHOUT ANY WARRANTY; without even the implied warranty of +-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-# GNU General Public License for more details. +-# +-# You should have received a copy of the GNU General Public License +-# along with this program; if not, write to the Free Software +-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +- +-# Test --in-place. +- +-unset CDPATH +-export LANG=C +-set -e +- +-$TEST_FUNCTIONS +-skip_if_skipped +-skip_if_backend uml +-skip_unless_phony_guest windows.img +- +-img_base="$abs_top_builddir/test-data/phony-guests/windows.img" +- +-export VIRT_TOOLS_DATA_DIR="$top_srcdir/test-data/fake-virt-tools" +-export VIRTIO_WIN="$top_srcdir/test-data/fake-virtio-win" +- +-d=$PWD/test-v2v-in-place.d +-rm -rf $d +-mkdir $d +- +-img="$d/test.qcow2" +-rm -f $img +-qemu-img create -f qcow2 -b $img_base -o compat=1.1,backing_fmt=raw $img +-md5="$(do_md5 $img_base)" +- +-libvirt_xml="$d/test.xml" +-rm -f $libvirt_xml +-n=windows-overlay +-cat > $libvirt_xml < +- +- $n +- 1048576 +- +- hvm +- +- +- +- +- +- +- +- +- +- +- +-EOF +- +-$VG virt-v2v --debug-gc -i libvirt -ic "test://$libvirt_xml" $n --in-place +- +-# Test that the drivers have been copied over into the guest +-script="$d/test.fish" +-expected="$d/expected" +-response="$d/response" +- +-mktest () +-{ +- local cmd="$1" exp="$2" +- +- echo "echo '$cmd'" >> "$script" +- echo "$cmd" >> "$expected" +- +- echo "$cmd" >> "$script" +- echo "$exp" >> "$expected" +-} +- +-:> "$script" +-:> "$expected" +- +-firstboot_dir="/Program Files/Guestfs/Firstboot" +-mktest "is-dir \"$firstboot_dir\"" true +-mktest "is-file \"$firstboot_dir/firstboot.bat\"" true +-mktest "is-dir \"$firstboot_dir/scripts\"" true +-virtio_dir="/Windows/Drivers/VirtIO" +-mktest "is-dir \"$virtio_dir\"" true +-for drv in netkvm qxl vioscsi viostor; do +- for sfx in cat inf sys; do +- mktest "is-file \"$virtio_dir/$drv.$sfx\"" true +- done +-done +- +-guestfish --ro -a "$img" -i < "$script" > "$response" +-diff -u "$expected" "$response" +- +-# Test the base image remained untouched +-test "$md5" = "$(do_md5 $img_base)" +- +-# Clean up. +-rm -r $d +diff --git a/v2v/virt-v2v.pod b/v2v/virt-v2v.pod +index bd606592b..092d88635 100644 +--- a/v2v/virt-v2v.pod ++++ b/v2v/virt-v2v.pod +@@ -8,10 +8,6 @@ virt-v2v - Convert a guest to use KVM + [-o mode] [other -o* options] + [guest|filename] + +- virt-v2v --in-place +- [-i mode] [other -i* options] +- [guest|filename] +- + =head1 DESCRIPTION + + Virt-v2v converts a single guest from a foreign hypervisor to run on +@@ -39,9 +35,6 @@ these sides of virt-v2v are documented separately in this manual. + + Virt-v2v normally copies from the input to the output, called "copying + mode". In this case the source guest is always left unchanged. +-In-place conversion (I<--in-place>) only uses the I<-i*> options and +-modifies the source guest in-place. (See L +-below.) + + =head2 Other virt-v2v topics + +@@ -255,20 +248,6 @@ For I<-i disk> only, this specifies the format of the input disk + image. For other input methods you should specify the input + format in the metadata. + +-=item B<--in-place> +- +-Do not create an output virtual machine in the target hypervisor. +-Instead, adjust the guest OS in the source VM to run in the input +-hypervisor. +- +-This mode is meant for integration with other toolsets, which take the +-responsibility of converting the VM configuration, providing for +-rollback in case of errors, transforming the storage, etc. +- +-See L below. +- +-Conflicts with all I<-o *> options. +- + =item B<-io> OPTION=VALUE + + Set input option(s) related to the current input mode or transport. +@@ -1300,7 +1279,7 @@ Minimum free space: 10 MB + =head3 Minimum free space check in the host + + You must have sufficient free space in the host directory used to +-store temporary overlays (except in I<--in-place> mode). To find out ++store temporary overlays. To find out + which directory this is, use: + + $ df -h "`guestfish get-cachedir`" +@@ -1403,31 +1382,6 @@ that instead. + + + +-=head2 In-place conversion +- +-It is also possible to use virt-v2v in scenarios where a foreign VM +-has already been imported into a KVM-based hypervisor, but still needs +-adjustments in the guest to make it run in the new virtual hardware. +- +-In that case it is assumed that a third-party tool has created the +-target VM in the supported KVM-based hypervisor based on the source VM +-configuration and contents, but using virtual devices more appropriate +-for KVM (e.g. virtio storage and network, etc.). +- +-Then, to make the guest OS boot and run in the changed environment, +-one can use: +- +- virt-v2v -ic qemu:///system converted_vm --in-place +- +-Virt-v2v will analyze the configuration of C in the +-C libvirt instance, and apply various fixups to the +-guest OS configuration to make it match the VM configuration. This +-may include installing virtio drivers, configuring the bootloader, the +-mountpoints, the network interfaces, and so on. +- +-Should an error occur during the operation, virt-v2v exits with an +-error code leaving the VM in an undefined state. +- + =head2 Machine readable output + + The I<--machine-readable> option can be used to make the output more +-- +2.25.4 + diff --git a/SOURCES/0077-RHEL-8-v2v-Disable-the-virt-v2v-in-place-option.patch b/SOURCES/0077-RHEL-8-v2v-Disable-the-virt-v2v-in-place-option.patch deleted file mode 100644 index 47f9e5e..0000000 --- a/SOURCES/0077-RHEL-8-v2v-Disable-the-virt-v2v-in-place-option.patch +++ /dev/null @@ -1,284 +0,0 @@ -From 690b8d0d2bcd7dc1b5f3c37a3133e89bae97863e Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Thu, 14 Jan 2016 11:53:42 -0500 -Subject: [PATCH] RHEL 8: v2v: Disable the virt-v2v --in-place option. - -This disables the virt-v2v --in-place option which we do not -wish to support in RHEL. -(See commit d0069559a939e47e5f29973ed9a69a13f0b58301). ---- - v2v/Makefile.am | 2 - - v2v/cmdline.ml | 8 +-- - v2v/test-v2v-docs.sh | 1 + - v2v/test-v2v-in-place.sh | 108 --------------------------------------- - v2v/virt-v2v.pod | 46 +---------------- - 5 files changed, 7 insertions(+), 158 deletions(-) - delete mode 100755 v2v/test-v2v-in-place.sh - -diff --git a/v2v/Makefile.am b/v2v/Makefile.am -index 7a1ac329e..156f8ad5b 100644 ---- a/v2v/Makefile.am -+++ b/v2v/Makefile.am -@@ -358,7 +358,6 @@ if HAVE_LIBVIRT - TESTS += \ - test-v2v-cdrom.sh \ - test-v2v-floppy.sh \ -- test-v2v-in-place.sh \ - test-v2v-networks-and-bridges.sh \ - test-v2v-no-copy.sh \ - test-v2v-o-glance.sh \ -@@ -497,7 +496,6 @@ EXTRA_DIST += \ - test-v2v-i-vmx-3.vmx \ - test-v2v-i-vmx-4.vmx \ - test-v2v-i-vmx-5.vmx \ -- test-v2v-in-place.sh \ - test-v2v-it-vddk-io-query.sh \ - test-v2v-machine-readable.sh \ - test-v2v-networks-and-bridges-expected.xml \ -diff --git a/v2v/cmdline.ml b/v2v/cmdline.ml -index 6bca12ce3..0efff4c1d 100644 ---- a/v2v/cmdline.ml -+++ b/v2v/cmdline.ml -@@ -198,8 +198,7 @@ let parse_cmdline () = - s_"Set option for input mode"; - [ M"it" ], Getopt.String ("transport", set_string_option_once "-it" input_transport), - s_"Input transport"; -- [ L"in-place" ], Getopt.Set in_place, -- s_"Only tune the guest in the input VM"; -+ [ L"in-place" ], Getopt.Set in_place, Getopt.hidden_option_description; - [ L"machine-readable" ], Getopt.Set machine_readable, - s_"Make output machine readable"; - [ S 'n'; L"network" ], Getopt.String ("in:out", add_network), -@@ -336,7 +335,6 @@ read the man page virt-v2v(1). - printf "vddk\n"; - printf "colours-option\n"; - printf "vdsm-compat-option\n"; -- printf "in-place\n"; - printf "io/oo\n"; - List.iter (printf "input:%s\n") (Modules_list.input_modules ()); - List.iter (printf "output:%s\n") (Modules_list.output_modules ()); -@@ -485,6 +483,10 @@ read the man page virt-v2v(1). - error (f_"only ‘-it ssh’ can be used here") in - Input_vmx.input_vmx input_transport arg in - -+ (* Prevent use of --in-place option in RHEL. *) -+ if in_place then -+ error (f_"--in-place cannot be used in RHEL"); -+ - (* Common error message. *) - let error_option_cannot_be_used_in_output_mode mode opt = - error (f_"-o %s: %s option cannot be used in this output mode") mode opt -diff --git a/v2v/test-v2v-docs.sh b/v2v/test-v2v-docs.sh -index e1e22b599..da98050ee 100755 ---- a/v2v/test-v2v-docs.sh -+++ b/v2v/test-v2v-docs.sh -@@ -26,6 +26,7 @@ $top_srcdir/podcheck.pl virt-v2v.pod virt-v2v \ - --debug-overlay,\ - --ic,\ - --if,\ -+--in-place,\ - --io,\ - --it,\ - --no-trim,\ -diff --git a/v2v/test-v2v-in-place.sh b/v2v/test-v2v-in-place.sh -deleted file mode 100755 -index 6f7d78f39..000000000 ---- a/v2v/test-v2v-in-place.sh -+++ /dev/null -@@ -1,108 +0,0 @@ --#!/bin/bash - --# libguestfs virt-v2v test script --# Copyright (C) 2014 Red Hat Inc. --# Copyright (C) 2015 Parallels IP Holdings GmbH. --# --# This program is free software; you can redistribute it and/or modify --# it under the terms of the GNU General Public License as published by --# the Free Software Foundation; either version 2 of the License, or --# (at your option) any later version. --# --# This program is distributed in the hope that it will be useful, --# but WITHOUT ANY WARRANTY; without even the implied warranty of --# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --# GNU General Public License for more details. --# --# You should have received a copy of the GNU General Public License --# along with this program; if not, write to the Free Software --# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -- --# Test --in-place. -- --unset CDPATH --export LANG=C --set -e -- --$TEST_FUNCTIONS --skip_if_skipped --skip_if_backend uml --skip_unless_phony_guest windows.img -- --img_base="$abs_top_builddir/test-data/phony-guests/windows.img" -- --export VIRT_TOOLS_DATA_DIR="$top_srcdir/test-data/fake-virt-tools" --export VIRTIO_WIN="$top_srcdir/test-data/fake-virtio-win" -- --d=$PWD/test-v2v-in-place.d --rm -rf $d --mkdir $d -- --img="$d/test.qcow2" --rm -f $img --qemu-img create -f qcow2 -b $img_base -o compat=1.1,backing_fmt=raw $img --md5="$(do_md5 $img_base)" -- --libvirt_xml="$d/test.xml" --rm -f $libvirt_xml --n=windows-overlay --cat > $libvirt_xml < -- -- $n -- 1048576 -- -- hvm -- -- -- -- -- -- -- -- -- -- -- --EOF -- --$VG virt-v2v --debug-gc -i libvirt -ic "test://$libvirt_xml" $n --in-place -- --# Test that the drivers have been copied over into the guest --script="$d/test.fish" --expected="$d/expected" --response="$d/response" -- --mktest () --{ -- local cmd="$1" exp="$2" -- -- echo "echo '$cmd'" >> "$script" -- echo "$cmd" >> "$expected" -- -- echo "$cmd" >> "$script" -- echo "$exp" >> "$expected" --} -- --:> "$script" --:> "$expected" -- --firstboot_dir="/Program Files/Guestfs/Firstboot" --mktest "is-dir \"$firstboot_dir\"" true --mktest "is-file \"$firstboot_dir/firstboot.bat\"" true --mktest "is-dir \"$firstboot_dir/scripts\"" true --virtio_dir="/Windows/Drivers/VirtIO" --mktest "is-dir \"$virtio_dir\"" true --for drv in netkvm qxl vioscsi viostor; do -- for sfx in cat inf sys; do -- mktest "is-file \"$virtio_dir/$drv.$sfx\"" true -- done --done -- --guestfish --ro -a "$img" -i < "$script" > "$response" --diff -u "$expected" "$response" -- --# Test the base image remained untouched --test "$md5" = "$(do_md5 $img_base)" -- --# Clean up. --rm -r $d -diff --git a/v2v/virt-v2v.pod b/v2v/virt-v2v.pod -index 276fcea85..e60011fac 100644 ---- a/v2v/virt-v2v.pod -+++ b/v2v/virt-v2v.pod -@@ -18,8 +18,6 @@ virt-v2v - Convert a guest to use KVM - -oo rhv-cafile=/tmp/ca.pem -oo rhv-direct \ - --bridge ovirtmgmt - -- virt-v2v -ic qemu:///system qemu_guest --in-place -- - =head1 DESCRIPTION - - Virt-v2v converts guests from a foreign hypervisor to run on KVM. It -@@ -164,9 +162,6 @@ I<-o rhv-upload> is used to write to a RHV / oVirt target. I<-o rhv> - is a legacy method to write to RHV / oVirt E 4.2. I<-o vdsm> is - only used when virt-v2v runs under VDSM control. - --I<--in-place> instructs virt-v2v to customize the guest OS in the input --virtual machine, instead of creating a new VM in the target hypervisor. -- - =head1 OPTIONS - - =over 4 -@@ -280,20 +275,6 @@ For I<-i disk> only, this specifies the format of the input disk - image. For other input methods you should specify the input - format in the metadata. - --=item B<--in-place> -- --Do not create an output virtual machine in the target hypervisor. --Instead, adjust the guest OS in the source VM to run in the input --hypervisor. -- --This mode is meant for integration with other toolsets, which take the --responsibility of converting the VM configuration, providing for --rollback in case of errors, transforming the storage, etc. -- --See L below. -- --Conflicts with all I<-o *> options. -- - =item B<-io> OPTION=VALUE - - Set input option(s) related to the current input mode or transport. -@@ -2136,7 +2117,7 @@ Minimum free space: 10 MB - =head2 Minimum free space check in the host - - You must have sufficient free space in the host directory used to --store temporary overlays (except in I<--in-place> mode). To find out -+store temporary overlays. To find out - which directory this is, use: - - $ df -h "`guestfish get-cachedir`" -@@ -2268,31 +2249,6 @@ that instead. - - - --=head1 IN PLACE CONVERSION -- --It is also possible to use virt-v2v in scenarios where a foreign VM --has already been imported into a KVM-based hypervisor, but still needs --adjustments in the guest to make it run in the new virtual hardware. -- --In that case it is assumed that a third-party tool has created the --target VM in the supported KVM-based hypervisor based on the source VM --configuration and contents, but using virtual devices more appropriate --for KVM (e.g. virtio storage and network, etc.). -- --Then, to make the guest OS boot and run in the changed environment, --one can use: -- -- virt-v2v -ic qemu:///system converted_vm --in-place -- --Virt-v2v will analyze the configuration of C in the --C libvirt instance, and apply various fixups to the --guest OS configuration to make it match the VM configuration. This --may include installing virtio drivers, configuring the bootloader, the --mountpoints, the network interfaces, and so on. -- --Should an error occur during the operation, virt-v2v exits with an --error code leaving the VM in an undefined state. -- - =head1 MACHINE READABLE OUTPUT - - The I<--machine-readable> option can be used to make the output more --- -2.21.0 - diff --git a/SOURCES/0077-RHEL-8-v2v-i-disk-force-VNC-as-display-RHBZ-1372671.patch b/SOURCES/0077-RHEL-8-v2v-i-disk-force-VNC-as-display-RHBZ-1372671.patch new file mode 100644 index 0000000..fbab859 --- /dev/null +++ b/SOURCES/0077-RHEL-8-v2v-i-disk-force-VNC-as-display-RHBZ-1372671.patch @@ -0,0 +1,26 @@ +From ce7a5cc371d6f6e0f96c2cd897245a2e83839c20 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 2 Mar 2017 14:21:37 +0100 +Subject: [PATCH] RHEL 8: v2v: -i disk: force VNC as display (RHBZ#1372671) + +The SDL output mode is not supported in RHEL 8's qemu-kvm. +--- + v2v/input_disk.ml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/v2v/input_disk.ml b/v2v/input_disk.ml +index 8321a2a8c..6bd9f43f8 100644 +--- a/v2v/input_disk.ml ++++ b/v2v/input_disk.ml +@@ -89,7 +89,7 @@ class input_disk input_format disk = object + s_features = [ "acpi"; "apic"; "pae" ]; + s_firmware = UnknownFirmware; (* causes virt-v2v to autodetect *) + s_display = +- Some { s_display_type = Window; s_keymap = None; s_password = None; ++ Some { s_display_type = VNC; s_keymap = None; s_password = None; + s_listen = LNoListen; s_port = None }; + s_video = None; + s_sound = None; +-- +2.25.4 + diff --git a/SOURCES/0078-RHEL-8-v2v-do-not-mention-SUSE-Xen-hosts-RHBZ-143020.patch b/SOURCES/0078-RHEL-8-v2v-do-not-mention-SUSE-Xen-hosts-RHBZ-143020.patch new file mode 100644 index 0000000..5c61493 --- /dev/null +++ b/SOURCES/0078-RHEL-8-v2v-do-not-mention-SUSE-Xen-hosts-RHBZ-143020.patch @@ -0,0 +1,26 @@ +From 0cf211cc08f0f0b886021dc10b52a03aa2d22b1f Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Wed, 8 Mar 2017 11:03:40 +0100 +Subject: [PATCH] RHEL 8: v2v: do not mention SUSE Xen hosts (RHBZ#1430203) + +They are not supported in RHEL 8. +--- + v2v/virt-v2v-input-xen.pod | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/v2v/virt-v2v-input-xen.pod b/v2v/virt-v2v-input-xen.pod +index 9fd5065f1..c3c20a6b6 100644 +--- a/v2v/virt-v2v-input-xen.pod ++++ b/v2v/virt-v2v-input-xen.pod +@@ -10,7 +10,7 @@ virt-v2v-input-xen - Using virt-v2v to convert guests from Xen + =head1 DESCRIPTION + + This page documents how to use L to convert guests from +-RHEL 5 Xen, or SLES and OpenSUSE Xen hosts. ++RHEL 5 Xen hosts. + + =head1 INPUT FROM XEN + +-- +2.25.4 + diff --git a/SOURCES/0078-RHEL-8-v2v-i-disk-force-VNC-as-display-RHBZ-1372671.patch b/SOURCES/0078-RHEL-8-v2v-i-disk-force-VNC-as-display-RHBZ-1372671.patch deleted file mode 100644 index 9a5edc2..0000000 --- a/SOURCES/0078-RHEL-8-v2v-i-disk-force-VNC-as-display-RHBZ-1372671.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 86447cac9a58c0a6499fff76d45dd56423979bbe Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Thu, 2 Mar 2017 14:21:37 +0100 -Subject: [PATCH] RHEL 8: v2v: -i disk: force VNC as display (RHBZ#1372671) - -The SDL output mode is not supported in RHEL 8's qemu-kvm. ---- - v2v/input_disk.ml | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/v2v/input_disk.ml b/v2v/input_disk.ml -index 7ecd19fd3..e2b16cf70 100644 ---- a/v2v/input_disk.ml -+++ b/v2v/input_disk.ml -@@ -87,7 +87,7 @@ class input_disk input_format disk = object - s_features = [ "acpi"; "apic"; "pae" ]; - s_firmware = UnknownFirmware; (* causes virt-v2v to autodetect *) - s_display = -- Some { s_display_type = Window; s_keymap = None; s_password = None; -+ Some { s_display_type = VNC; s_keymap = None; s_password = None; - s_listen = LNoListen; s_port = None }; - s_video = None; - s_sound = None; --- -2.21.0 - diff --git a/SOURCES/0079-RHEL-8-v2v-do-not-mention-SUSE-Xen-hosts-RHBZ-143020.patch b/SOURCES/0079-RHEL-8-v2v-do-not-mention-SUSE-Xen-hosts-RHBZ-143020.patch deleted file mode 100644 index 1a56601..0000000 --- a/SOURCES/0079-RHEL-8-v2v-do-not-mention-SUSE-Xen-hosts-RHBZ-143020.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 91c7b5c4042b07fb4e35669dec6d445252c8c9f6 Mon Sep 17 00:00:00 2001 -From: Pino Toscano -Date: Wed, 8 Mar 2017 11:03:40 +0100 -Subject: [PATCH] RHEL 8: v2v: do not mention SUSE Xen hosts (RHBZ#1430203) - -They are not supported in RHEL 8. ---- - v2v/virt-v2v.pod | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - -diff --git a/v2v/virt-v2v.pod b/v2v/virt-v2v.pod -index e60011fac..9f93c00ee 100644 ---- a/v2v/virt-v2v.pod -+++ b/v2v/virt-v2v.pod -@@ -1615,8 +1615,7 @@ verbose messages. - - =head1 INPUT FROM XEN - --Virt-v2v is able to import Xen guests from RHEL 5 Xen or SLES and --openSUSE Xen hosts. -+Virt-v2v is able to import Xen guests from RHEL 5 Xen hosts. - - Virt-v2v uses libvirt for access to the remote Xen host, and therefore - the input mode should be I<-i libvirt>. As this is the default, you --- -2.21.0 - diff --git a/SOURCES/0079-RHEL-8-v2v-rhv-upload-Remove-restriction-on-oa-spars.patch b/SOURCES/0079-RHEL-8-v2v-rhv-upload-Remove-restriction-on-oa-spars.patch new file mode 100644 index 0000000..4c38c1d --- /dev/null +++ b/SOURCES/0079-RHEL-8-v2v-rhv-upload-Remove-restriction-on-oa-spars.patch @@ -0,0 +1,91 @@ +From 2009eb2439c8112789728856f08a9f92c6883ad8 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Mon, 14 May 2018 10:16:58 +0100 +Subject: [PATCH] RHEL 8: v2v: rhv-upload: Remove restriction on -oa sparse. + +See: https://bugzilla.redhat.com/show_bug.cgi?id=1565681 +and the v2v-devel private thread "Do we already support migration using FC?" +--- + v2v/output_rhv_upload.ml | 11 +---------- + v2v/rhv-upload-plugin.py | 4 +--- + v2v/virt-v2v-output-rhv.pod | 8 +------- + 3 files changed, 3 insertions(+), 20 deletions(-) + +diff --git a/v2v/output_rhv_upload.ml b/v2v/output_rhv_upload.ml +index e1d06867b..3f078157a 100644 +--- a/v2v/output_rhv_upload.ml ++++ b/v2v/output_rhv_upload.ml +@@ -177,19 +177,11 @@ See also the virt-v2v-output-rhv(1) manual.") + error (f_"nbdkit was compiled without SELinux support. You will have to recompile nbdkit with libselinux-devel installed, or else set SELinux to Permissive mode while doing the conversion.") + in + +- (* Output format/sparse must be raw/sparse. We may be able to +- * lift this limitation in future, but it requires changes on the +- * RHV side. See TODO file for details. XXX +- *) ++ (* Output format must be raw. *) + let error_current_limitation required_param = + error (f_"rhv-upload: currently you must use ‘%s’. This restriction will be loosened in a future version.") required_param + in + +- let error_unless_output_alloc_sparse () = +- if output_alloc <> Sparse then +- error_current_limitation "-oa sparse" +- in +- + (* JSON parameters which are invariant between disks. *) + let json_params = [ + "verbose", JSON.Bool (verbose ()); +@@ -249,7 +241,6 @@ object + error_unless_ovirtsdk4_module_available (); + error_unless_nbdkit_working (); + error_unless_nbdkit_python_plugin_working (); +- error_unless_output_alloc_sparse (); + (* Python code prechecks. *) + let precheck_fn = tmpdir // "v2vprecheck.json" in + let fd = Unix.openfile precheck_fn [O_WRONLY; O_CREAT] 0o600 in +diff --git a/v2v/rhv-upload-plugin.py b/v2v/rhv-upload-plugin.py +index 14d4e37fb..c7f7a5e8b 100644 +--- a/v2v/rhv-upload-plugin.py ++++ b/v2v/rhv-upload-plugin.py +@@ -142,10 +142,8 @@ def open(readonly): + format = disk_format, + initial_size = params['disk_size'], + provisioned_size = params['disk_size'], +- # XXX Ignores params['output_sparse']. +- # Handling this properly will be complex, see: + # https://www.redhat.com/archives/libguestfs/2018-March/msg00177.html +- sparse = True, ++ sparse = params['output_sparse'], + storage_domains = [ + types.StorageDomain( + name = params['output_storage'], +diff --git a/v2v/virt-v2v-output-rhv.pod b/v2v/virt-v2v-output-rhv.pod +index 4520c9184..f6579a48e 100644 +--- a/v2v/virt-v2v-output-rhv.pod ++++ b/v2v/virt-v2v-output-rhv.pod +@@ -5,7 +5,7 @@ virt-v2v-output-rhv - Using virt-v2v to convert guests to oVirt or RHV + =head1 SYNOPSIS + + virt-v2v [-i* options] -o rhv-upload [-oc ENGINE_URL] -os STORAGE +- [-op PASSWORD] [-of raw] ++ [-op PASSWORD] + [-oo rhv-cafile=FILE] + [-oo rhv-cluster=CLUSTER] + [-oo rhv-direct] +@@ -79,12 +79,6 @@ username is not specified then virt-v2v defaults to using + C which is the typical superuser account for oVirt + instances. + +-=item I<-of raw> +- +-Currently you must use I<-of raw> and you cannot use I<-oa preallocated>. +- +-These restrictions will be loosened in a future version. +- + =item I<-op> F + + A file containing a password to be used when connecting to the oVirt +-- +2.25.4 + diff --git a/SOURCES/0080-RHEL-8-use-platform-python.patch b/SOURCES/0080-RHEL-8-use-platform-python.patch new file mode 100644 index 0000000..d2d7118 --- /dev/null +++ b/SOURCES/0080-RHEL-8-use-platform-python.patch @@ -0,0 +1,27 @@ +From 58a4b8f9a1a8590728dd169f8c481171ab859b7d Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Sun, 16 Dec 2018 16:42:46 +0100 +Subject: [PATCH] RHEL 8: use platform-python + +Use the stable platform-python provided in BaseOS, instead of relying on +some arbitrary version installed by the user. +--- + v2v/python_script.ml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/v2v/python_script.ml b/v2v/python_script.ml +index 3159373a1..f2c00c40f 100644 +--- a/v2v/python_script.ml ++++ b/v2v/python_script.ml +@@ -24,7 +24,7 @@ open Unix_utils + + open Common_gettext.Gettext + +-let python = "python3" (* Defined by PEP 394 *) ++let python = "/usr/libexec/platform-python" + + type script = { + tmpdir : string; (* Temporary directory. *) +-- +2.25.4 + diff --git a/SOURCES/0080-RHEL-8-v2v-disable-unconfig-of-manually-installed-VM.patch b/SOURCES/0080-RHEL-8-v2v-disable-unconfig-of-manually-installed-VM.patch deleted file mode 100644 index b2e5e81..0000000 --- a/SOURCES/0080-RHEL-8-v2v-disable-unconfig-of-manually-installed-VM.patch +++ /dev/null @@ -1,36 +0,0 @@ -From c7c2cc23088861d032a59d4886973eab78958962 Mon Sep 17 00:00:00 2001 -From: Pino Toscano -Date: Mon, 14 Aug 2017 10:02:13 +0200 -Subject: [PATCH] RHEL 8: v2v: disable unconfig of manually installed VMware - tools (RHBZ#1477905) - -It looks like they may require connection to the VMware servers, which -is not always available during conversion. ---- - v2v/convert_linux.ml | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/v2v/convert_linux.ml b/v2v/convert_linux.ml -index da06352a0..c9cf99570 100644 ---- a/v2v/convert_linux.ml -+++ b/v2v/convert_linux.ml -@@ -359,6 +359,7 @@ let convert (g : G.guestfs) inspect source output rcaps = - let remove = !remove in - Linux.remove g inspect remove; - -+(* - (* VMware Tools may have been installed from a tarball, so the - * above code won't remove it. Look for the uninstall tool and run - * if present. -@@ -380,6 +381,8 @@ let convert (g : G.guestfs) inspect source output rcaps = - warning (f_"VMware tools was detected, but uninstallation failed. The error message was: %s (ignored)") - msg - ) -+*) -+ () - - and unconfigure_citrix () = - let pkgs = --- -2.21.0 - diff --git a/SOURCES/0081-RHEL-8-point-to-KB-for-supported-v2v-hypervisors-gue.patch b/SOURCES/0081-RHEL-8-point-to-KB-for-supported-v2v-hypervisors-gue.patch new file mode 100644 index 0000000..ecca5c4 --- /dev/null +++ b/SOURCES/0081-RHEL-8-point-to-KB-for-supported-v2v-hypervisors-gue.patch @@ -0,0 +1,125 @@ +From a53675a2b1142654fa3cacc775e44692419d10e0 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Tue, 26 Mar 2019 09:42:25 +0100 +Subject: [PATCH] RHEL 8: point to KB for supported v2v hypervisors/guests + +--- + v2v/virt-v2v-support.pod | 102 ++------------------------------------- + 1 file changed, 4 insertions(+), 98 deletions(-) + +diff --git a/v2v/virt-v2v-support.pod b/v2v/virt-v2v-support.pod +index a22506068..4ec1a07c1 100644 +--- a/v2v/virt-v2v-support.pod ++++ b/v2v/virt-v2v-support.pod +@@ -8,104 +8,10 @@ systems and guests in virt-v2v + This page documents which foreign hypervisors, virtualization + management systems and guest types that L can support. + +-Note this page applies to upstream virt-v2v from +-L and in downstream distributions of virt-v2v +-sometimes features are intentionally removed, or are present but not +-supported. +- +-=head2 Hypervisors (Input) +- +-=over 4 +- +-=item VMware ESXi +- +-Must be managed by VMware vCenter E 5.0 unless VDDK is available. +- +-=item OVA exported from VMware +- +-OVAs from other hypervisors will not work. +- +-=item VMX from VMware +- +-VMX files generated by other hypervisors will not work. +- +-=item RHEL 5 Xen +- +-=item SUSE Xen +- +-=item Citrix Xen +- +-Citrix Xen has not been recently tested. +- +-=item Hyper-V +- +-Not recently tested. Requires that you export the disk or use +-L on Hyper-V. +- +-=item Direct from disk images +- +-Only disk images exported from supported hypervisors, and using +-container formats supported by qemu. +- +-=item Physical machines +- +-Using the L tool. +- +-=back +- +-=head2 Hypervisors (Output) +- +-QEMU and KVM only. +- +-=head2 Virtualization management systems (Output) +- +-=over 4 +- +-=item OpenStack +- +-=item Red Hat Virtualization (RHV) 4.1 and up +- +-=item Local libvirt +- +-And hence L, L, and similar tools. +- +-=item Local disk +- +-=back +- +-=head2 Guests +- +-=over 4 +- +-=item Red Hat Enterprise Linux 3, 4, 5, 6, 7 +- +-=item CentOS 3, 4, 5, 6, 7 +- +-=item Scientific Linux 3, 4, 5, 6, 7 +- +-=item Oracle Linux +- +-=item Fedora +- +-=item SLES 10 and up +- +-=item OpenSUSE 10 and up +- +-=item Debian 6 and up +- +-=item Ubuntu 10.04, 12.04, 14.04, 16.04, and up +- +-=item Windows XP to Windows 10 / Windows Server 2016 +- +-We use Windows internal version numbers, see +-L +- +-Currently NT 5.2 to NT 6.3 are supported. +- +-See L below for additional notes on converting Windows +-guests. +- +-=back ++For more information on supported hypervisors, and guest types in ++RHEL, please consult the following Knowledgebase article on these ++Red Hat Customer Portal: ++L. + + =head2 Guest firmware + +-- +2.25.4 + diff --git a/SOURCES/0081-RHEL-8-v2v-rhv-upload-Remove-restriction-on-oa-spars.patch b/SOURCES/0081-RHEL-8-v2v-rhv-upload-Remove-restriction-on-oa-spars.patch deleted file mode 100644 index ee1e626..0000000 --- a/SOURCES/0081-RHEL-8-v2v-rhv-upload-Remove-restriction-on-oa-spars.patch +++ /dev/null @@ -1,82 +0,0 @@ -From a609448f0401c82b306c44fb015893a7d4a6be27 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Mon, 14 May 2018 10:16:58 +0100 -Subject: [PATCH] RHEL 8: v2v: rhv-upload: Remove restriction on -oa sparse. - -See: https://bugzilla.redhat.com/show_bug.cgi?id=1565681 -and the v2v-devel private thread "Do we already support migration using FC?" ---- - v2v/output_rhv_upload.ml | 11 +---------- - v2v/rhv-upload-plugin.py | 4 +--- - v2v/virt-v2v.pod | 6 ------ - 3 files changed, 2 insertions(+), 19 deletions(-) - -diff --git a/v2v/output_rhv_upload.ml b/v2v/output_rhv_upload.ml -index fc33e5033..3977c0296 100644 ---- a/v2v/output_rhv_upload.ml -+++ b/v2v/output_rhv_upload.ml -@@ -177,19 +177,11 @@ See also \"OUTPUT TO RHV\" in the virt-v2v(1) manual.") - error (f_"nbdkit was compiled without SELinux support. You will have to recompile nbdkit with libselinux-devel installed, or else set SELinux to Permissive mode while doing the conversion.") - in - -- (* Output format/sparse must be raw/sparse. We may be able to -- * lift this limitation in future, but it requires changes on the -- * RHV side. See TODO file for details. XXX -- *) -+ (* Output format must be raw. *) - let error_current_limitation required_param = - error (f_"rhv-upload: currently you must use ‘%s’. This restriction will be loosened in a future version.") required_param - in - -- let error_unless_output_alloc_sparse () = -- if output_alloc <> Sparse then -- error_current_limitation "-oa sparse" -- in -- - (* JSON parameters which are invariant between disks. *) - let json_params = [ - "verbose", JSON.Bool (verbose ()); -@@ -242,7 +234,6 @@ object - error_unless_ovirtsdk4_module_available (); - error_unless_nbdkit_working (); - error_unless_nbdkit_python3_working (); -- error_unless_output_alloc_sparse (); - if have_selinux then - error_unless_nbdkit_compiled_with_selinux () - -diff --git a/v2v/rhv-upload-plugin.py b/v2v/rhv-upload-plugin.py -index 4fad27fb8..41cb29992 100644 ---- a/v2v/rhv-upload-plugin.py -+++ b/v2v/rhv-upload-plugin.py -@@ -139,10 +139,8 @@ def open(readonly): - format = disk_format, - initial_size = params['disk_size'], - provisioned_size = params['disk_size'], -- # XXX Ignores params['output_sparse']. -- # Handling this properly will be complex, see: - # https://www.redhat.com/archives/libguestfs/2018-March/msg00177.html -- sparse = True, -+ sparse = params['output_sparse'], - storage_domains = [ - types.StorageDomain( - name = params['output_storage'], -diff --git a/v2v/virt-v2v.pod b/v2v/virt-v2v.pod -index 9f93c00ee..2603d38a7 100644 ---- a/v2v/virt-v2v.pod -+++ b/v2v/virt-v2v.pod -@@ -1822,12 +1822,6 @@ username is not specified then virt-v2v defaults to using - C which is the typical superuser account for oVirt - instances. - --=item I<-of raw> -- --Currently you must use I<-of raw> and you cannot use I<-oa preallocated>. -- --These restrictions will be loosened in a future version. -- - =item I<-op> F - - A file containing a password to be used when connecting to the oVirt --- -2.21.0 - diff --git a/SOURCES/0082-RHEL-8-use-python3-as-nbdkit-plugin.patch b/SOURCES/0082-RHEL-8-use-python3-as-nbdkit-plugin.patch deleted file mode 100644 index 3f8a864..0000000 --- a/SOURCES/0082-RHEL-8-use-python3-as-nbdkit-plugin.patch +++ /dev/null @@ -1,26 +0,0 @@ -From ff4f831122bd04c77d4363042eab4b82ad789c6b Mon Sep 17 00:00:00 2001 -From: Pino Toscano -Date: Sun, 16 Dec 2018 16:32:46 +0100 -Subject: [PATCH] RHEL 8: use "python3" as nbdkit plugin - -RHEL uses "python3" as name for the nbdkit Python plugin. ---- - v2v/output_rhv_upload.ml | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/v2v/output_rhv_upload.ml b/v2v/output_rhv_upload.ml -index 3977c0296..13c175f2d 100644 ---- a/v2v/output_rhv_upload.ml -+++ b/v2v/output_rhv_upload.ml -@@ -79,7 +79,7 @@ let parse_output_options options = - { rhv_cafile; rhv_cluster; rhv_direct; rhv_verifypeer } - - let python3 = "python3" (* Defined by PEP 394 *) --let nbdkit_python_plugin = "python" -+let nbdkit_python_plugin = "python3" - let pidfile_timeout = 30 - let finalization_timeout = 5*60 - --- -2.21.0 - diff --git a/SOURCES/0083-RHEL-8-use-platform-python.patch b/SOURCES/0083-RHEL-8-use-platform-python.patch deleted file mode 100644 index 7d9e27d..0000000 --- a/SOURCES/0083-RHEL-8-use-platform-python.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 83e68a8844c9c20fbee98dc784fd82f60e225417 Mon Sep 17 00:00:00 2001 -From: Pino Toscano -Date: Sun, 16 Dec 2018 16:42:46 +0100 -Subject: [PATCH] RHEL 8: use platform-python - -Use the stable platform-python provided in BaseOS, instead of relying on -some arbitrary version installed by the user. ---- - v2v/output_rhv_upload.ml | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/v2v/output_rhv_upload.ml b/v2v/output_rhv_upload.ml -index 13c175f2d..f95ac0d65 100644 ---- a/v2v/output_rhv_upload.ml -+++ b/v2v/output_rhv_upload.ml -@@ -78,7 +78,7 @@ let parse_output_options options = - - { rhv_cafile; rhv_cluster; rhv_direct; rhv_verifypeer } - --let python3 = "python3" (* Defined by PEP 394 *) -+let python3 = "/usr/libexec/platform-python" - let nbdkit_python_plugin = "python3" - let pidfile_timeout = 30 - let finalization_timeout = 5*60 -@@ -121,8 +121,8 @@ class output_rhv_upload output_alloc output_conn - - (* Check that the Python binary is available. *) - let error_unless_python_binary_on_path () = -- try ignore (which python3) -- with Executable_not_found _ -> -+ try ignore (Unix.access python3 [Unix.X_OK]) -+ with Unix_error _ -> - error (f_"no python binary called ‘%s’ can be found on the $PATH") - python3 - in --- -2.21.0 - diff --git a/SOURCES/copy-patches.sh b/SOURCES/copy-patches.sh index 83737da..a073f9d 100755 --- a/SOURCES/copy-patches.sh +++ b/SOURCES/copy-patches.sh @@ -6,7 +6,7 @@ set -e # directory. Use it like this: # ./copy-patches.sh -rhel_version=8.0 +rhel_version=8.3.0 # Check we're in the right directory. if [ ! -f libguestfs.spec ]; then diff --git a/SOURCES/libguestfs-1.38.4.tar.gz.sig b/SOURCES/libguestfs-1.38.4.tar.gz.sig deleted file mode 100644 index f411613..0000000 --- a/SOURCES/libguestfs-1.38.4.tar.gz.sig +++ /dev/null @@ -1,16 +0,0 @@ ------BEGIN PGP SIGNATURE----- - -iQIcBAABAgAGBQJbbdyXAAoJEJFzj3Pht2igrTUP/RMnDgC/8Zi5vKDXC8y6n2rD -wgnvmPNNCNXiMOZa9APk8C8GraHwIGo9GjLThr194Dbk1LteIBSpkj3SkxK4z/vR -3sD9cecT0lgTfhYpcFBrKtETKnr0TEGPC4uanczg4kufYkmXoy6yDMJXVJMCn6rf -jR9HG75SGycqtchr4zwnztBw6TFdGA6Oj/RTGuHuYbhu/qmbUZzZ7tJ6JQ2GbyaJ -8EEkSLtSOAtvbHOj+pjiZrG/wBEhy6owjuAxvjF9ctEq4Hmbr13lJuSBzCC/ysUS -itQog+eVclgDNxVmLfJas3druYgGCJKWVJVEBw7H/8KiM+3leeD/4sFENIiQBg2y -0BTHVtH1RvSteQivFAVFvYee0twuYbJucTFELWbNYfw12Yd51KDJ/+Ncbuu/h1J/ -r5ies67AVohhMju5kIoSK0zgZq+Rsiwj+yMcyqLU+ug7UTy1Otd2O9Xskym5y40G -IKUaBxncaNhOQ6LDcChQCEVideBt4ESXS5ySDwIrEQOgEvcGV/JjsYsAH1WVwsEI -o53HI6ZOrTnBAIc7bJ6HnWXSoV+6NN+Tx7o9GT+oB87PzwTKZh0OzmwuQ4q+pmIz -oddg3IsLm8I1Zg8MgP38QVKS7YKIrwy5adN/3Gjd10ZlA70g3JTGzGyU9xH7GcqJ -rVwKc5uGRjPdwY2wyQIL -=NZ5w ------END PGP SIGNATURE----- diff --git a/SOURCES/libguestfs-1.40.2.tar.gz.sig b/SOURCES/libguestfs-1.40.2.tar.gz.sig new file mode 100644 index 0000000..016e22b --- /dev/null +++ b/SOURCES/libguestfs-1.40.2.tar.gz.sig @@ -0,0 +1,17 @@ +-----BEGIN PGP SIGNATURE----- + +iQJFBAABCAAvFiEE93dPsa0HSn6Mh2fqkXOPc+G3aKAFAlxdivwRHHJpY2hAYW5u +ZXhpYS5vcmcACgkQkXOPc+G3aKC8SRAAotTR3nvV2lUeABLn8uiv5CjmeEEm++C4 +754zGkOb7bRSQzcQ12XC0e4WQwcS/fHHSRhT2ABc1VeLn8ehyEEQ3T3NfDpnpaKR +NYolsI3l8iae4QI0wo85/Wb/k7pXg1uWFZ9t286d1e/NYudMEZ6hiVXsUNlSu0lR +rU5Xr/XGDV01Vlalo1qcVI1p3b3zBFGcNLv5Myc0+Q+RWVYcyrm270VJYmD0OOnh +zzRgb1fBW4rVIbYEhmmhNgbL3758Qaef/jsTxU/tH83LOdJUpxWYvLD7ec3DzsHr +xcNgDCZxCtn4ObdfxJGzVbWO96nmVPxNnVMeDol+PDsrVkQnpSPMPrU/oth5Xh19 ++JeP22SSDahCIbO9YlL3AoA3l1gpLq2f9yTz9JIHm4ytBZmQPD8QU2KBQFsz+/ZE +Gulc0j/3mzlRyoesuVGb79OWBfSDCHittKVFPXqokzNu0jWZVd7GxfJ2DQqUprJd +eK4LDJpInS+Vdohjko8uuC9AfGB68hWbuazjdWLhTNQb3/8EzX5Xu2N88xlWuBQK +HRu8NPp601uI6qdjj38VUXGY5BryDIJdvqf5hoRNe/2scf3OomaMpdck59gLT4LB +/yaNbfPSRenXQ1IM3mU9Opktvm48cpJQ8B80OEmWenhhjXrHrgplVNkXK7inZ7vu +TKia/N90ugY= +=kgC8 +-----END PGP SIGNATURE----- diff --git a/SPECS/libguestfs.spec b/SPECS/libguestfs.spec index 1b82d8a..f70763f 100644 --- a/SPECS/libguestfs.spec +++ b/SPECS/libguestfs.spec @@ -9,9 +9,8 @@ # # Currently the basic sanity check is *broken* on: # -# aarch64: too much output from verbose AAVMF causes libvirtd lockup (RHBZ#1661940) -# s390x: missing TCG support in brew builders (RHBZ#1615402) -%global test_arches %{power64} x86_64 +# (none) +%global test_arches aarch64 %{power64} s390x x86_64 # Architectures where virt-v2v is shipped. # @@ -36,89 +35,89 @@ Summary: Access and modify virtual machine disk images Name: libguestfs Epoch: 1 -Version: 1.38.4 -Release: 15%{?dist} +Version: 1.40.2 +Release: 24%{?dist} License: LGPLv2+ # Source and patches. URL: http://libguestfs.org/ -Source0: http://libguestfs.org/download/1.38-stable/%{name}-%{version}.tar.gz +Source0: http://libguestfs.org/download/1.40-stable/%{name}-%{version}.tar.gz %if 0%{verify_tarball_signature} -Source1: http://libguestfs.org/download/1.38-stable/%{name}-%{version}.tar.gz.sig +Source1: http://libguestfs.org/download/1.40-stable/%{name}-%{version}.tar.gz.sig %endif ExclusiveArch: x86_64 %{power64} aarch64 s390x # RHEL 8 git repository is: -# https://github.com/libguestfs/libguestfs/tree/rhel-8.0 +# https://github.com/libguestfs/libguestfs/tree/rhel-8.3.0 # Use 'copy-patches.sh' to copy the patches from the git repo # to the current directory. # Patches. -Patch0001: 0001-Switch-from-YAJL-to-Jansson.patch -Patch0002: 0002-qemu-Fix-transcription-error-in-conversion-of-yajl-t.patch -Patch0003: 0003-v2v-ovf-Create-OVF-more-aligned-with-the-standard.patch -Patch0004: 0004-v2v-vdsm-add-vdsm-fixed-ovf-option.patch -Patch0005: 0005-v2v-OVF-Code-formatting.patch -Patch0006: 0006-v2v-DOM-Add-doc_to_string-function.patch -Patch0007: 0007-v2v-Add-op-output-password-file-option.patch -Patch0008: 0008-v2v-cmdline-Move-definition-to-before-its-only-use.patch -Patch0009: 0009-v2v-Add-general-mechanism-for-input-and-output-optio.patch -Patch0010: 0010-v2v-OVF-write-ovirt-id-attribute-for-the-OS-in-OVirt.patch -Patch0011: 0011-v2v-OVF-fix-ovf-id-for-VirtualSystem-in-OVirt-flavou.patch -Patch0012: 0012-v2v-Add-o-rhv-upload-output-mode-RHBZ-1557273.patch -Patch0013: 0013-v2v-refer-to-the-right-embed-script-in-EXTRA_DIST.patch -Patch0014: 0014-v2v-o-rhv-upload-Don-t-require-of-raw-parameter.patch -Patch0015: 0015-v2v-o-rhv-upload-install-RHV-tools-RHBZ-1561828.patch -Patch0016: 0016-v2v-Map-Windows-Server-2012-R2-x86-64-to-ovirt-ID-25.patch -Patch0017: 0017-v2v-fix-build-rules-for-output_rhv_upload_-_source.m.patch -Patch0018: 0018-v2v-fix-rhevexp-typo-in-documentation.patch -Patch0019: 0019-v2v-add-and-use-Create_ovf.ovf_flavour_to_string.patch -Patch0020: 0020-v2v-o-rhv-upload-Set-inactivity-timeout-RHBZ-1586198.patch -Patch0021: 0021-New-API-inspect_get_osinfo.patch -Patch0022: 0022-inspector-show-the-per-OS-osinfo-guess-RHBZ-1544842.patch -Patch0023: 0023-v2v-o-rhv-upload-Optimize-http-request-sending.patch -Patch0024: 0024-v2v-o-rhv-upload-Log-full-imageio-response-on-failur.patch -Patch0025: 0025-v2v-rvh-upload-plugin-Always-read-the-response.patch -Patch0026: 0026-v2v-rhv-upload-plugin-Fix-name-error.patch -Patch0027: 0027-v2v-rhv-upload-plugin-Remove-unused-variables.patch -Patch0028: 0028-v2v-o-rhv-upload-Always-fetch-server-options-when-op.patch -Patch0029: 0029-v2v-o-rhv-upload-Use-Unix-domain-socket-to-access-im.patch -Patch0030: 0030-v2v-improve-os-documentation-for-rhv-upload.patch -Patch0031: 0031-v2v-rhv-upload-plugin-Remove-unneeded-auth.patch -Patch0032: 0032-v2v-rhv-upload-plugin-Improve-error-handling.patch -Patch0033: 0033-v2v-rhv-upload-plugin-Optimize-only-direct-upload.patch -Patch0034: 0034-v2v-rhv-plugin-find-suitable-host-RHBZ-1596810-RHBZ-.patch -Patch0035: 0035-v2v-change-QXL-ResourceType-in-OVirt-flavour-RHBZ-15.patch -Patch0036: 0036-v2v-o-rhv-upload-check-for-ovirtsdk4-RHBZ-1601943.patch -Patch0037: 0037-v2v-rhv-plugin-fix-DC-search-string.patch -Patch0038: 0038-v2v-rhv-plugin-case-sensitive-search-queries.patch -Patch0039: 0039-uefi-remove-last-references-to-kraxel-s-old-edk2-bui.patch -Patch0040: 0040-v2v-parse_libvirt_xml-handle-srN-CDROM-devices-RHBZ-.patch -Patch0041: 0041-v2v-o-rhv-upload-Fix-error-message-disk-numbering-RH.patch -Patch0042: 0042-v2v-o-rhv-upload-Properly-replace-SD_UUID-in-OVF-RHB.patch -Patch0043: 0043-ppc64le-Don-t-use-cpu-parameter-under-any-circumstan.patch -Patch0044: 0044-tools-Link-OCaml-programs-with-runtime-variant-_pic-.patch -Patch0045: 0045-tools-Ensure-CFLAGS-and-LDFLAGS-are-passed-to-all-OC.patch -Patch0046: 0046-ocaml-make-sure-to-pass-LDFLAGS-to-ocamlmklibs-linke.patch -Patch0047: 0047-v2v-Model-machine-type-explicitly.patch -Patch0048: 0048-v2v-windows-Fix-rhev-apt-command-line-RHBZ-1624902.patch -Patch0049: 0049-v2v-docs-Describe-support-for-SHA-2-certs-for-Window.patch -Patch0050: 0050-v2v-docs-Remove-sentence-about-supporting-qemu-kvm-r.patch -Patch0051: 0051-v2v-linux-improve-regex-for-resume-entries-RHBZ-1651.patch -Patch0052: 0052-inspection-Parse-os-release-opensuse-leap-as-opensus.patch -Patch0053: 0053-inspect-handle-os-release-opensuse-tumbleweed-as-ope.patch -Patch0054: 0054-v2v-update-docs-for-VMware-roles-RHBZ-1530967.patch -Patch0055: 0055-v2v-o-rhv-upload-decouple-name-of-nbdkit-python-plug.patch -Patch0056: 0056-v2v-further-doc-update-for-VMware-roles.patch -Patch0057: 0057-python-fix-call-of-Python-handlers-of-events.patch -Patch0058: 0058-python-change-types-for-RBufferOut-FBuffer-with-Pyth.patch -Patch0059: 0059-Revert-launch-libvirt-Use-qemu-bridge-helper-to-impl.patch -Patch0060: 0060-inspect-fix-icon-of-RHEL.patch -Patch0061: 0061-inspect-fix-inspection-of-partition-less-devices-RHB.patch -Patch0062: 0062-v2v-update-documentation-on-nbdkit-RHBZ-1605242.patch -Patch0063: 0063-Use-proper-label-for-nbdkit-sockets.patch -Patch0064: 0064-v2v-i-vmx-Use-scp-T-option-if-available-to-unbreak-s.patch +Patch0001: 0001-common-mlpcre-add-offset-flag-for-PCRE.matches.patch +Patch0002: 0002-v2v-add-Var_expander.patch +Patch0003: 0003-v2v-add-o-json-output-mode.patch +Patch0004: 0004-inspect-fix-icon-of-RHEL.patch +Patch0005: 0005-v2v-warn-when-the-guest-has-direct-network-interface.patch +Patch0006: 0006-v2v-update-documentation-on-nbdkit-RHBZ-1605242.patch +Patch0007: 0007-v2v-linux-do-not-uninstall-open-vm-tools-w-ubuntu-se.patch +Patch0008: 0008-v2v-linux-canonicalize-module-path-for-arch-detectio.patch +Patch0009: 0009-v2v-linux-improve-arch-detection-from-modules-RHBZ-1.patch +Patch0010: 0010-Use-proper-label-for-nbdkit-sockets.patch +Patch0011: 0011-v2v-start-reading-the-new-libvirt-firmware-autoselec.patch +Patch0012: 0012-common-mltools-move-the-code-for-machine-readable-up.patch +Patch0013: 0013-common-mltools-make-sure-machine-readable-output-is-.patch +Patch0014: 0014-common-mltools-allow-fd-for-machine-readable-output.patch +Patch0015: 0015-OCaml-tools-output-messages-into-JSON-for-machine-re.patch +Patch0016: 0016-OCaml-tools-fix-3999-3339-typo.patch +Patch0017: 0017-v2v-remove-extra-nbdkit-bit-from-documentation-RHBZ-.patch +Patch0018: 0018-v2v-i-vmx-Use-scp-T-option-if-available-to-unbreak-s.patch +Patch0019: 0019-v2v-Allow-Windows-virtio-ISO-to-be-a-block-device-as.patch +Patch0020: 0020-v2v-Set-DISKTYPE-2-in-RHV-and-VDSM-meta-files-RHBZ-1.patch +Patch0021: 0021-v2v-rhv-upload-plugin-improve-wait-logic-after-final.patch +Patch0022: 0022-v2v-o-rhv-upload-check-whether-the-cluster-exists.patch +Patch0023: 0023-v2v-o-rhv-upload-split-vmcheck-out-of-precheck.patch +Patch0024: 0024-v2v-o-rhv-upload-change-precheck-script-to-return-a-.patch +Patch0025: 0025-v2v-o-rhv-upload-improve-lookup-of-specified-resourc.patch +Patch0026: 0026-v2v-o-rhv-upload-tell-whether-a-SD-actually-exists.patch +Patch0027: 0027-v2v-add-output-disk_copied-hook.patch +Patch0028: 0028-v2v-o-rhv-upload-collect-disks-UUIDs-right-after-cop.patch +Patch0029: 0029-v2v-o-rhv-upload-add-oo-rhv-disk-uuid-option.patch +Patch0030: 0030-v2v-o-rhv-upload-make-oo-rhv-cafile-optional.patch +Patch0031: 0031-v2v-Fix-default-graphics-driver-for-SUSE-guests.patch +Patch0032: 0032-v2v-windows-Add-a-helper-function-for-installing-Pow.patch +Patch0033: 0033-v2v-Copy-static-IP-address-information-over-for-Wind.patch +Patch0034: 0034-New-API-luks_uuid.patch +Patch0035: 0035-options-Fix-segfault-when-multiple-key-parameters-gi.patch +Patch0036: 0036-options-Simplify-selector-parsing-for-key-options.patch +Patch0037: 0037-options-Allow-multiple-key-parameters.patch +Patch0038: 0038-options-rename-key.device-as-key.id.patch +Patch0039: 0039-options-allow-a-UUID-as-identifier-for-key.patch +Patch0040: 0040-docs-remove-paragraph-about-VMware-tools-on-Windows-.patch +Patch0041: 0041-mlcustomize-Trim-whitespaces-from-commands-read-from.patch +Patch0042: 0042-openstack-Increase-Cinder-volume-attach-timeout-to-5.patch +Patch0043: 0043-v2v-o-rhv-upload-check-for-a-valid-image-transfer-ri.patch +Patch0044: 0044-rhv-upload-Check-status-more-frequently.patch +Patch0045: 0045-rhv-upload-Show-transfer-id-in-error-message.patch +Patch0046: 0046-rhv-upload-Fix-waiting-for-transfer.patch +Patch0047: 0047-v2v-Optimize-convert-for-images-with-small-holes.patch +Patch0048: 0048-v2v-o-rhv-upload-Make-oo-rhv-cafile-optional-in-all-.patch +Patch0049: 0049-docs-Fix-update-crypto-policies-command-RHBZ-1791257.patch +Patch0050: 0050-add-versioned-directory-for-guest-agent-on-EL8.patch +Patch0051: 0051-v2v-fix-path-to-source-when-copying-files-from-guest.patch +Patch0052: 0052-v2v-windows-install-QEMU-Guest-Agent-MSI.patch +Patch0053: 0053-windows-small-tweaks-of-qemu-ga-firstboot-script.patch +Patch0054: 0054-windows-fix-detection-of-qemu-ga-installer-on-RHV.patch +Patch0055: 0055-windows-delay-installation-of-qemu-ga-MSI.patch +Patch0056: 0056-daemon-xattr-Refactor-code-which-splits-attr-names-f.patch +Patch0057: 0057-daemon-Add-filter_list-utility-function.patch +Patch0058: 0058-daemon-xattr-Filter-out-user.WofCompressedData-from-.patch +Patch0059: 0059-mltools-add-run_in_guest_command-helper.patch +Patch0060: 0060-customize-port-do_run-to-run_in_guest_command.patch +Patch0061: 0061-sysprep-add-a-update_system_ca_store-side-effect.patch +Patch0062: 0062-sysprep-ca-certificates-request-system-CA-store-upda.patch +Patch0063: 0063-sysprep-add-IPA-offline-unenrollment-RHBZ-1789592.patch +Patch0064: 0064-sysprep-add-Kerberos-keytab-file-removal.patch Patch0065: 0065-RHEL-8-Remove-libguestfs-live-RHBZ-798980.patch Patch0066: 0066-RHEL-8-Remove-9p-APIs-from-RHEL-RHBZ-921710.patch Patch0067: 0067-RHEL-8-Disable-unsupported-remote-drive-protocols-RH.patch @@ -129,15 +128,13 @@ Patch0071: 0071-RHEL-8-Disable-alternate-Augeas-lenses.patch Patch0072: 0072-RHEL-8-Fix-list-of-supported-sound-cards-to-match-RH.patch Patch0073: 0073-RHEL-8-Reject-use-of-libguestfs-winsupport-features-.patch Patch0074: 0074-RHEL-8-Fix-tests-for-libguestfs-winsupport.patch -Patch0075: 0075-RHEL-8-Revert-v2v-Add-a-support-matrix-to-the-manual.patch -Patch0076: 0076-RHEL-8-tests-Disable-daemon-tests-that-require-the-u.patch -Patch0077: 0077-RHEL-8-v2v-Disable-the-virt-v2v-in-place-option.patch -Patch0078: 0078-RHEL-8-v2v-i-disk-force-VNC-as-display-RHBZ-1372671.patch -Patch0079: 0079-RHEL-8-v2v-do-not-mention-SUSE-Xen-hosts-RHBZ-143020.patch -Patch0080: 0080-RHEL-8-v2v-disable-unconfig-of-manually-installed-VM.patch -Patch0081: 0081-RHEL-8-v2v-rhv-upload-Remove-restriction-on-oa-spars.patch -Patch0082: 0082-RHEL-8-use-python3-as-nbdkit-plugin.patch -Patch0083: 0083-RHEL-8-use-platform-python.patch +Patch0075: 0075-RHEL-8-tests-Disable-daemon-tests-that-require-the-u.patch +Patch0076: 0076-RHEL-8-v2v-Disable-the-virt-v2v-in-place-option.patch +Patch0077: 0077-RHEL-8-v2v-i-disk-force-VNC-as-display-RHBZ-1372671.patch +Patch0078: 0078-RHEL-8-v2v-do-not-mention-SUSE-Xen-hosts-RHBZ-143020.patch +Patch0079: 0079-RHEL-8-v2v-rhv-upload-Remove-restriction-on-oa-spars.patch +Patch0080: 0080-RHEL-8-use-platform-python.patch +Patch0081: 0081-RHEL-8-point-to-KB-for-supported-v2v-hypervisors-gue.patch # Use git for patch management. BuildRequires: git @@ -165,7 +162,7 @@ Source7: libguestfs.keyring # RHEV-APT is taken from the RHEV Tools CD # See https://bugzilla.redhat.com/show_bug.cgi?id=1186850 Source96: rhsrvany.exe -Source97: RHEV-Application-Provisioning-Tool.exe_4.43-3 +Source97: RHEV-Application-Provisioning-Tool.exe_4.43-5 Source98: brew-overrides.sh Source99: copy-patches.sh @@ -205,7 +202,8 @@ BuildRequires: unzip BuildRequires: systemd-units BuildRequires: netpbm-progs BuildRequires: icoutils -BuildRequires: libvirt-daemon-kvm +# RHBZ#1710713 (RHBZ#1661940) +BuildRequires: libvirt-daemon-kvm >= 5.3.0 BuildRequires: libacl-devel BuildRequires: libcap-devel BuildRequires: jansson-devel @@ -261,7 +259,7 @@ BuildRequires: gjs # for f in `cat appliance/packagelist`; do echo $f; done | sort -u # However you have to edit the list down to packages which exist in # current RHEL, since supermin ignores non-existent packages. -BuildRequires: acl attr augeas-libs bash binutils bzip2 coreutils cpio cryptsetup curl dhclient diffutils dosfstools e2fsprogs file findutils gawk gdisk genisoimage gfs2-utils grep gzip hivex iproute iputils kernel kmod kpartx less libcap libselinux libxml2 lsof lsscsi lvm2 lzop mdadm openssh-clients parted pciutils pcre policycoreutils procps psmisc qemu-img rsync scrub sed squashfs-tools strace systemd tar udev util-linux vim-minimal which xfsprogs xz yajl +BuildRequires: acl attr augeas-libs bash binutils bzip2 coreutils cpio cryptsetup curl dhclient diffutils dosfstools e2fsprogs file findutils gawk gdisk genisoimage gfs2-utils grep gzip hivex iproute iputils jansson kernel kmod kpartx less libcap libselinux libxml2 lsof lsscsi lvm2 lzop mdadm openssh-clients parted pciutils pcre policycoreutils procps psmisc qemu-img rsync scrub sed squashfs-tools strace systemd tar udev util-linux vim-minimal which xfsprogs xz %ifarch %{ix86} x86_64 BuildRequires: syslinux syslinux-extlinux %endif @@ -298,8 +296,8 @@ Requires: fuse Requires: /usr/bin/qemu-img # For libvirt backend. -# RHBZ#1500870, RHBZ#1501239 -Requires: libvirt-daemon-kvm >= 3.9.0-1 +# RHBZ#1500870, RHBZ#1501239, RHBZ#1508299 +Requires: libvirt-daemon-kvm >= 5.3.0 %ifarch aarch64 Requires: edk2-aarch64 %endif @@ -624,8 +622,8 @@ Requires: edk2-aarch64 # Needed for -it vddk, and -o rhv-upload. Requires: nbdkit -Requires: nbdkit-plugin-python3 -Requires: nbdkit-plugin-vddk +Requires: nbdkit-python-plugin +Requires: nbdkit-vddk-plugin Requires: platform-python @@ -1156,6 +1154,12 @@ install -m 0644 utils/boot-benchmark/boot-benchmark.1 $RPM_BUILD_ROOT%{_mandir}/ %{_bindir}/virt-v2v-copy-to-local %{_mandir}/man1/virt-v2v.1* %{_mandir}/man1/virt-v2v-copy-to-local.1* +%{_mandir}/man1/virt-v2v-input-vmware.1* +%{_mandir}/man1/virt-v2v-input-xen.1* +%{_mandir}/man1/virt-v2v-output-local.1* +%{_mandir}/man1/virt-v2v-output-openstack.1* +%{_mandir}/man1/virt-v2v-output-rhv.1* +%{_mandir}/man1/virt-v2v-support.1* %{_datadir}/virt-tools %endif @@ -1165,6 +1169,7 @@ install -m 0644 utils/boot-benchmark/boot-benchmark.1 $RPM_BUILD_ROOT%{_mandir}/ %{_datadir}/bash-completion/completions/guestfish %{_datadir}/bash-completion/completions/guestmount %{_datadir}/bash-completion/completions/guestunmount +%{_datadir}/bash-completion/completions/libguestfs-test-tool %{_datadir}/bash-completion/completions/virt-* @@ -1260,6 +1265,20 @@ install -m 0644 utils/boot-benchmark/boot-benchmark.1 $RPM_BUILD_ROOT%{_mandir}/ %changelog +* Wed Jun 24 2020 Pino Toscano - 1:1.40.2-24 +- v2v: ship a newer version of rhev-apt.exe + resolves: rhbz#1849997 + +* Tue May 26 2020 Pino Toscano - 1:1.40.2-23 +- Ignore the user.WofCompressedData xattr + resolves: rhbz#1811539 +- sysprep: new ipa-client and kerberos-hostkeytab operations + resolves: rhbz#1789592 + +* Mon Apr 27 2020 Danilo C. L. de Paula - 1.40.2 +- Resolves: bz#1810193 + (Upgrade components in virt:rhel module:stream for RHEL-8.3 release) + * Tue Dec 10 2019 Pino Toscano - 1:1.38.4-15 - Stop building virt-p2v-maker, as it will be built by its own source resolves: rhbz#1777924