From da373f13dc9763df0ec0703d24c847967df380c6 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Mar 30 2021 15:31:33 +0000 Subject: import libguestfs-1.40.2-27.module+el8.4.0+9282+0bdec052 --- 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 deleted file mode 100644 index 3edbb8d..0000000 --- a/SOURCES/0001-common-mlpcre-add-offset-flag-for-PCRE.matches.patch +++ /dev/null @@ -1,126 +0,0 @@ -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/0001-daemon-lib-Replace-deprecated-security_context_t-wit.patch b/SOURCES/0001-daemon-lib-Replace-deprecated-security_context_t-wit.patch new file mode 100644 index 0000000..dacbba7 --- /dev/null +++ b/SOURCES/0001-daemon-lib-Replace-deprecated-security_context_t-wit.patch @@ -0,0 +1,56 @@ +From a5e8afb4ed8576a1b3398add2ede49a1f90ad01a Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 30 Jul 2020 13:57:45 +0100 +Subject: [PATCH] daemon, lib: Replace deprecated security_context_t with char + *. + +This gives deprecation warnings. It always was simply a char *, and +the recommendation upstream is to replace uses with char *: + +https://github.com/SELinuxProject/selinux/commit/9eb9c9327563014ad6a807814e7975424642d5b9 +(cherry picked from commit eb78e990ac5277a4282293f8787af871a1420b61) +--- + daemon/selinux.c | 3 +-- + lib/launch-libvirt.c | 5 ++--- + 2 files changed, 3 insertions(+), 5 deletions(-) + +diff --git a/daemon/selinux.c b/daemon/selinux.c +index 1c1446d30..f4d839c19 100644 +--- a/daemon/selinux.c ++++ b/daemon/selinux.c +@@ -63,8 +63,7 @@ char * + do_getcon (void) + { + #if defined(HAVE_GETCON) +- security_context_t context; +- char *r; ++ char *context, *r; + + if (getcon (&context) == -1) { + reply_with_perror ("getcon"); +diff --git a/lib/launch-libvirt.c b/lib/launch-libvirt.c +index bc5978cc4..4a47bbb29 100644 +--- a/lib/launch-libvirt.c ++++ b/lib/launch-libvirt.c +@@ -288,8 +288,7 @@ create_cow_overlay_libvirt (guestfs_h *g, void *datav, struct drive *drv) + if (data->selinux_imagelabel) { + debug (g, "setting SELinux label on %s to %s", + overlay, data->selinux_imagelabel); +- if (setfilecon (overlay, +- (security_context_t) data->selinux_imagelabel) == -1) ++ if (setfilecon (overlay, data->selinux_imagelabel) == -1) + selinux_warning (g, __func__, "setfilecon", overlay); + } + #endif +@@ -840,7 +839,7 @@ is_custom_hv (guestfs_h *g) + static void + set_socket_create_context (guestfs_h *g) + { +- security_context_t scon; /* this is actually a 'char *' */ ++ char *scon; + context_t con; + + if (getcon (&scon) == -1) { +-- +2.18.4 + diff --git a/SOURCES/0002-caml_named_value-returns-const-value-pointer-in-OCam.patch b/SOURCES/0002-caml_named_value-returns-const-value-pointer-in-OCam.patch new file mode 100644 index 0000000..ce3a12a --- /dev/null +++ b/SOURCES/0002-caml_named_value-returns-const-value-pointer-in-OCam.patch @@ -0,0 +1,36 @@ +From 524b0c748a3a2d47b4c76e3aa546b9d4af144e6c Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Sat, 7 Dec 2019 11:08:54 +0000 +Subject: [PATCH] caml_named_value returns const value pointer in OCaml 4.09+ + +(cherry picked from ocaml-augeas +commit 1cf5aef99b26a46529ca797547c0b49627fffe78) +--- + common/mlaugeas/augeas-c.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/common/mlaugeas/augeas-c.c b/common/mlaugeas/augeas-c.c +index 3e0ba67ba..3b1dc2551 100644 +--- a/common/mlaugeas/augeas-c.c ++++ b/common/mlaugeas/augeas-c.c +@@ -77,7 +77,7 @@ static const int error_map_len = sizeof error_map / sizeof error_map[0]; + static void + raise_error (augeas_t t, const char *msg) + { +- value *exn = caml_named_value ("Augeas.Error"); ++ const value *exn = caml_named_value ("Augeas.Error"); + value args[4]; + const int code = aug_error (t); + const char *aug_err_minor; +@@ -113,7 +113,7 @@ raise_error (augeas_t t, const char *msg) + static void + raise_init_error (const char *msg) + { +- value *exn = caml_named_value ("Augeas.Error"); ++ const value *exn = caml_named_value ("Augeas.Error"); + value args[4]; + + args[0] = caml_alloc (1, 0); +-- +2.18.4 + diff --git a/SOURCES/0002-v2v-add-Var_expander.patch b/SOURCES/0002-v2v-add-Var_expander.patch deleted file mode 100644 index 219a332..0000000 --- a/SOURCES/0002-v2v-add-Var_expander.patch +++ /dev/null @@ -1,415 +0,0 @@ -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-ocaml-Change-calls-to-caml_named_value-to-cope-with-.patch b/SOURCES/0003-ocaml-Change-calls-to-caml_named_value-to-cope-with-.patch new file mode 100644 index 0000000..09efa19 --- /dev/null +++ b/SOURCES/0003-ocaml-Change-calls-to-caml_named_value-to-cope-with-.patch @@ -0,0 +1,78 @@ +From 3860ab78d9fe5c34785aabc2227ebc8687b1171b Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 5 Sep 2019 09:00:14 +0100 +Subject: [PATCH] ocaml: Change calls to caml_named_value() to cope with const + value* return. + +In OCaml >= 4.09 the return value pointer of caml_named_value is +declared const. + +Based on Pino Toscano's original patch to ocaml-augeas. + +(cherry picked from commit 9788fa50601ad4f1eab56d0b763591268026e536) +--- + common/mlpcre/pcre-c.c | 3 +-- + common/mltools/uri-c.c | 6 ++---- + common/mlvisit/visit-c.c | 4 +--- + 3 files changed, 4 insertions(+), 9 deletions(-) + +diff --git a/common/mlpcre/pcre-c.c b/common/mlpcre/pcre-c.c +index 0762a8341..07f99b8d6 100644 +--- a/common/mlpcre/pcre-c.c ++++ b/common/mlpcre/pcre-c.c +@@ -73,12 +73,11 @@ init (void) + static void + raise_pcre_error (const char *msg, int errcode) + { +- value *exn = caml_named_value ("PCRE.Error"); + value args[2]; + + args[0] = caml_copy_string (msg); + args[1] = Val_int (errcode); +- caml_raise_with_args (*exn, 2, args); ++ caml_raise_with_args (*caml_named_value ("PCRE.Error"), 2, args); + } + + /* Wrap and unwrap pcre regular expression handles, with a finalizer. */ +diff --git a/common/mltools/uri-c.c b/common/mltools/uri-c.c +index 2a8837cd9..e03647c7b 100644 +--- a/common/mltools/uri-c.c ++++ b/common/mltools/uri-c.c +@@ -46,10 +46,8 @@ guestfs_int_mllib_parse_uri (value argv /* arg value, not an array! */) + int r; + + r = parse_uri (String_val (argv), &uri); +- if (r == -1) { +- value *exn = caml_named_value ("URI.Parse_failed"); +- caml_raise (*exn); +- } ++ if (r == -1) ++ caml_raise (*caml_named_value ("URI.Parse_failed")); + + /* Convert the struct into an OCaml tuple. */ + rv = caml_alloc_tuple (5); +diff --git a/common/mlvisit/visit-c.c b/common/mlvisit/visit-c.c +index 7137c4998..201f6d762 100644 +--- a/common/mlvisit/visit-c.c ++++ b/common/mlvisit/visit-c.c +@@ -53,7 +53,6 @@ value + guestfs_int_mllib_visit (value gv, value dirv, value fv) + { + CAMLparam3 (gv, dirv, fv); +- value *visit_failure_exn; + guestfs_h *g = (guestfs_h *) (intptr_t) Int64_val (gv); + struct visitor_function_wrapper_args args; + /* The dir string could move around when we call the +@@ -84,8 +83,7 @@ guestfs_int_mllib_visit (value gv, value dirv, value fv) + * already printed the error to stderr (XXX - fix), so we raise a + * generic exception. + */ +- visit_failure_exn = caml_named_value ("Visit.Failure"); +- caml_raise (*visit_failure_exn); ++ caml_raise (*caml_named_value ("Visit.Failure")); + } + free (dir); + +-- +2.18.4 + diff --git a/SOURCES/0003-v2v-add-o-json-output-mode.patch b/SOURCES/0003-v2v-add-o-json-output-mode.patch deleted file mode 100644 index 21e3c52..0000000 --- a/SOURCES/0003-v2v-add-o-json-output-mode.patch +++ /dev/null @@ -1,785 +0,0 @@ -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/0004-inspect-fix-icon-of-RHEL.patch b/SOURCES/0004-inspect-fix-icon-of-RHEL.patch deleted file mode 100644 index 181d99e..0000000 --- a/SOURCES/0004-inspect-fix-icon-of-RHEL.patch +++ /dev/null @@ -1,32 +0,0 @@ -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-ocaml-Use-caml_alloc_initialized_string-instead-of-m.patch b/SOURCES/0004-ocaml-Use-caml_alloc_initialized_string-instead-of-m.patch new file mode 100644 index 0000000..6b6c1c4 --- /dev/null +++ b/SOURCES/0004-ocaml-Use-caml_alloc_initialized_string-instead-of-m.patch @@ -0,0 +1,121 @@ +From 5c5cc8b7bc2588c04dd0d0472b466f978f8ac55c Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 6 Feb 2020 10:17:35 +0000 +Subject: [PATCH] ocaml: Use caml_alloc_initialized_string instead of memcpy. + +See this commit in libguestfs-common: +https://github.com/libguestfs/libguestfs-common/commit/398dc56a6cb5d6d01506338fa94ef580e668d5e9 + +(cherry picked from commit 9f3148c791a970b7d6adf249e949a1b7e0b4b0c1) +--- + generator/OCaml.ml | 10 ++++------ + m4/guestfs-ocaml.m4 | 18 ++++++++++++++++++ + ocaml/guestfs-c.c | 3 +-- + ocaml/guestfs-c.h | 18 ++++++++++++++++++ + 4 files changed, 41 insertions(+), 8 deletions(-) + +diff --git a/generator/OCaml.ml b/generator/OCaml.ml +index bd4f73b85..1b6970f6d 100644 +--- a/generator/OCaml.ml ++++ b/generator/OCaml.ml +@@ -504,12 +504,11 @@ copy_table (char * const * argv) + | name, FString -> + pr " v = caml_copy_string (%s->%s);\n" typ name + | name, FBuffer -> +- pr " v = caml_alloc_string (%s->%s_len);\n" typ name; +- pr " memcpy (String_val (v), %s->%s, %s->%s_len);\n" ++ pr " v = caml_alloc_initialized_string (%s->%s_len, %s->%s);\n" + typ name typ name + | name, FUUID -> +- pr " v = caml_alloc_string (32);\n"; +- pr " memcpy (String_val (v), %s->%s, 32);\n" typ name ++ pr " v = caml_alloc_initialized_string (32, %s->%s);\n" ++ typ name + | name, (FBytes|FInt64|FUInt64) -> + pr " v = caml_copy_int64 (%s->%s);\n" typ name + | name, (FInt32|FUInt32) -> +@@ -757,8 +756,7 @@ copy_table (char * const * argv) + pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n"; + pr " free (r);\n"; + | RBufferOut _ -> +- pr " rv = caml_alloc_string (size);\n"; +- pr " memcpy (String_val (rv), r, size);\n"; ++ pr " rv = caml_alloc_initialized_string (size, r);\n"; + pr " free (r);\n" + ); + +diff --git a/m4/guestfs-ocaml.m4 b/m4/guestfs-ocaml.m4 +index 3c504ce7e..90658e8c5 100644 +--- a/m4/guestfs-ocaml.m4 ++++ b/m4/guestfs-ocaml.m4 +@@ -221,6 +221,24 @@ AS_IF([test "x$have_Hivex_OPEN_UNSAFE" = "xno"],[ + ]) + AC_SUBST([HIVEX_OPEN_UNSAFE_FLAG]) + ++dnl Check if OCaml has caml_alloc_initialized_string (added 2017). ++AS_IF([test "x$OCAMLC" != "xno" && test "x$OCAMLFIND" != "xno" && \ ++ test "x$enable_ocaml" = "xyes"],[ ++ AC_MSG_CHECKING([for caml_alloc_initialized_string]) ++ cat >conftest.c <<'EOF' ++#include ++int main () { char *p = (void *) caml_alloc_initialized_string; return 0; } ++EOF ++ AS_IF([$OCAMLC conftest.c >&AS_MESSAGE_LOG_FD 2>&1],[ ++ AC_MSG_RESULT([yes]) ++ AC_DEFINE([HAVE_CAML_ALLOC_INITIALIZED_STRING],[1], ++ [caml_alloc_initialized_string found at compile time.]) ++ ],[ ++ AC_MSG_RESULT([no]) ++ ]) ++ rm -f conftest.c conftest.o ++]) ++ + dnl Flags we want to pass to every OCaml compiler call. + OCAML_WARN_ERROR="-warn-error CDEFLMPSUVYZX+52-3" + AC_SUBST([OCAML_WARN_ERROR]) +diff --git a/ocaml/guestfs-c.c b/ocaml/guestfs-c.c +index 3b5fb198f..18d7dd978 100644 +--- a/ocaml/guestfs-c.c ++++ b/ocaml/guestfs-c.c +@@ -360,8 +360,7 @@ event_callback_wrapper_locked (guestfs_h *g, + + ehv = Val_int (event_handle); + +- bufv = caml_alloc_string (buf_len); +- memcpy (String_val (bufv), buf, buf_len); ++ bufv = caml_alloc_initialized_string (buf_len, buf); + + arrayv = caml_alloc (array_len, 0); + for (i = 0; i < array_len; ++i) { +diff --git a/ocaml/guestfs-c.h b/ocaml/guestfs-c.h +index f05dbd8e7..93ad3e2bf 100644 +--- a/ocaml/guestfs-c.h ++++ b/ocaml/guestfs-c.h +@@ -19,6 +19,24 @@ + #ifndef GUESTFS_OCAML_C_H + #define GUESTFS_OCAML_C_H + ++#include "config.h" ++ ++#include ++#include ++ ++/* Replacement if caml_alloc_initialized_string is missing, added ++ * to OCaml runtime in 2017. ++ */ ++#ifndef HAVE_CAML_ALLOC_INITIALIZED_STRING ++static inline value ++caml_alloc_initialized_string (mlsize_t len, const char *p) ++{ ++ value sv = caml_alloc_string (len); ++ memcpy ((char *) String_val (sv), p, len); ++ return sv; ++} ++#endif ++ + #define Guestfs_val(v) (*((guestfs_h **)Data_custom_val(v))) + extern void guestfs_int_ocaml_raise_error (guestfs_h *g, const char *func) + Noreturn; +-- +2.18.4 + diff --git a/SOURCES/0005-ocaml-Use-caml_alloc_initialized_string-instead-of-m.patch b/SOURCES/0005-ocaml-Use-caml_alloc_initialized_string-instead-of-m.patch new file mode 100644 index 0000000..d80926d --- /dev/null +++ b/SOURCES/0005-ocaml-Use-caml_alloc_initialized_string-instead-of-m.patch @@ -0,0 +1,125 @@ +From 3b4082b239ec0976b366293067e42f91d56cfcd5 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 6 Feb 2020 10:15:29 +0000 +Subject: [PATCH] ocaml: Use caml_alloc_initialized_string instead of memcpy. + +Since about 2017 OCaml has had a function for creating an initialized +string. This uses the function instead of caml_alloc_string + memcpy +(which doesn't work for OCaml 4.10) and defines a replacement if the +function is missing. + +Note this requires configure.ac in libguestfs.git and virt-v2v.git to +define HAVE_CAML_ALLOC_INITIALIZED_STRING. + +(cherry picked from commit 398dc56a6cb5d6d01506338fa94ef580e668d5e9) +--- + common/mlpcre/pcre-c.c | 16 ++++++++++++++-- + common/mlvisit/visit-c.c | 16 ++++++++++++++-- + common/mlxml/xml-c.c | 16 ++++++++++++++-- + 3 files changed, 42 insertions(+), 6 deletions(-) + +diff --git a/common/mlpcre/pcre-c.c b/common/mlpcre/pcre-c.c +index 07f99b8d6..7dbba5857 100644 +--- a/common/mlpcre/pcre-c.c ++++ b/common/mlpcre/pcre-c.c +@@ -39,6 +39,19 @@ + + #pragma GCC diagnostic ignored "-Wmissing-prototypes" + ++/* Replacement if caml_alloc_initialized_string is missing, added ++ * to OCaml runtime in 2017. ++ */ ++#ifndef HAVE_CAML_ALLOC_INITIALIZED_STRING ++static inline value ++caml_alloc_initialized_string (mlsize_t len, const char *p) ++{ ++ value sv = caml_alloc_string (len); ++ memcpy ((char *) String_val (sv), p, len); ++ return sv; ++} ++#endif ++ + /* Data on the most recent match is stored in this thread-local + * variable. It is freed either by the next call to PCRE.matches or + * by (clean) thread exit. +@@ -257,8 +270,7 @@ guestfs_int_pcre_sub (value nv) + if (len < 0) + raise_pcre_error ("pcre_get_substring", len); + +- strv = caml_alloc_string (len); +- memcpy (String_val (strv), str, len); ++ strv = caml_alloc_initialized_string (len, str); + CAMLreturn (strv); + } + +diff --git a/common/mlvisit/visit-c.c b/common/mlvisit/visit-c.c +index 201f6d762..d5585ca94 100644 +--- a/common/mlvisit/visit-c.c ++++ b/common/mlvisit/visit-c.c +@@ -35,6 +35,19 @@ + + #pragma GCC diagnostic ignored "-Wmissing-prototypes" + ++/* Replacement if caml_alloc_initialized_string is missing, added ++ * to OCaml runtime in 2017. ++ */ ++#ifndef HAVE_CAML_ALLOC_INITIALIZED_STRING ++static inline value ++caml_alloc_initialized_string (mlsize_t len, const char *p) ++{ ++ value sv = caml_alloc_string (len); ++ memcpy ((char *) String_val (sv), p, len); ++ return sv; ++} ++#endif ++ + struct visitor_function_wrapper_args { + /* In both case we are pointing to local roots, hence why these are + * value* not value. +@@ -198,8 +211,7 @@ copy_xattr (const struct guestfs_xattr *xattr) + rv = caml_alloc (2, 0); + v = caml_copy_string (xattr->attrname); + Store_field (rv, 0, v); +- v = caml_alloc_string (xattr->attrval_len); +- memcpy (String_val (v), xattr->attrval, xattr->attrval_len); ++ v = caml_alloc_initialized_string (xattr->attrval_len, xattr->attrval); + Store_field (rv, 1, v); + CAMLreturn (rv); + } +diff --git a/common/mlxml/xml-c.c b/common/mlxml/xml-c.c +index d3db7e227..a0fa0fc3d 100644 +--- a/common/mlxml/xml-c.c ++++ b/common/mlxml/xml-c.c +@@ -40,6 +40,19 @@ + + #pragma GCC diagnostic ignored "-Wmissing-prototypes" + ++/* Replacement if caml_alloc_initialized_string is missing, added ++ * to OCaml runtime in 2017. ++ */ ++#ifndef HAVE_CAML_ALLOC_INITIALIZED_STRING ++static inline value ++caml_alloc_initialized_string (mlsize_t len, const char *p) ++{ ++ value sv = caml_alloc_string (len); ++ memcpy ((char *) String_val (sv), p, len); ++ return sv; ++} ++#endif ++ + /* xmlDocPtr type */ + #define docptr_val(v) (*((xmlDocPtr *)Data_custom_val(v))) + +@@ -183,8 +196,7 @@ mllib_xml_to_string (value docv, value formatv) + doc = docptr_val (docv); + xmlDocDumpFormatMemory (doc, &mem, &size, Bool_val (formatv)); + +- strv = caml_alloc_string (size); +- memcpy (String_val (strv), mem, size); ++ strv = caml_alloc_initialized_string (size, mem); + free (mem); + + CAMLreturn (strv); +-- +2.18.4 + 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 deleted file mode 100644 index 0f115f4..0000000 --- a/SOURCES/0005-v2v-warn-when-the-guest-has-direct-network-interface.patch +++ /dev/null @@ -1,48 +0,0 @@ -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-ocaml-Change-calls-to-caml_named_value-to-cope-with-.patch b/SOURCES/0006-ocaml-Change-calls-to-caml_named_value-to-cope-with-.patch new file mode 100644 index 0000000..76e8119 --- /dev/null +++ b/SOURCES/0006-ocaml-Change-calls-to-caml_named_value-to-cope-with-.patch @@ -0,0 +1,32 @@ +From 96462b30d5ca6e45601512609cedfc874739137d Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 5 Sep 2019 09:00:14 +0100 +Subject: [PATCH] ocaml: Change calls to caml_named_value() to cope with const + value* return. + +In OCaml >= 4.09 the return value pointer of caml_named_value is +declared const. + +Based on Pino Toscano's original patch to ocaml-augeas. + +(cherry picked from commit 74ce7332dbb9bab2a69737257f0d07c93eb9bab4) +--- + generator/daemon.ml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/generator/daemon.ml b/generator/daemon.ml +index a4e136aaa..b67c4d20b 100644 +--- a/generator/daemon.ml ++++ b/generator/daemon.ml +@@ -746,7 +746,7 @@ let generate_daemon_caml_stubs () = + let nr_args = List.length args_do_function in + + pr "{\n"; +- pr " static value *cb = NULL;\n"; ++ pr " static const value *cb = NULL;\n"; + pr " CAMLparam0 ();\n"; + pr " CAMLlocal2 (v, retv);\n"; + pr " CAMLlocalN (args, %d);\n" +-- +2.18.4 + diff --git a/SOURCES/0006-v2v-update-documentation-on-nbdkit-RHBZ-1605242.patch b/SOURCES/0006-v2v-update-documentation-on-nbdkit-RHBZ-1605242.patch deleted file mode 100644 index c3ef027..0000000 --- a/SOURCES/0006-v2v-update-documentation-on-nbdkit-RHBZ-1605242.patch +++ /dev/null @@ -1,55 +0,0 @@ -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-cat-Fix-GCC-10-warning.patch b/SOURCES/0007-cat-Fix-GCC-10-warning.patch new file mode 100644 index 0000000..4cc5aba --- /dev/null +++ b/SOURCES/0007-cat-Fix-GCC-10-warning.patch @@ -0,0 +1,34 @@ +From 93422725a0a8248d97b67cdbc20e065f5164e089 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 6 Feb 2020 10:27:48 +0000 +Subject: [PATCH] cat: Fix GCC 10 warning. + +I believe this warning is bogus, but simply initializing the local +variable is enough to avoid it. + +log.c: In function 'do_log': +log.c:390:7: error: 'comm_len' may be used uninitialized in this function [-Werror=maybe-uninitialized] + 390 | printf (" %.*s", (int) comm_len, comm); + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +(cherry picked from commit 4e199494c41d3240aa5c0708887b7a7513c6b6f2) +--- + cat/log.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/cat/log.c b/cat/log.c +index 25107e25f..f8a5c85f2 100644 +--- a/cat/log.c ++++ b/cat/log.c +@@ -337,7 +337,7 @@ do_log_journal (void) + while ((r = guestfs_journal_next (g)) > 0) { + CLEANUP_FREE_XATTR_LIST struct guestfs_xattr_list *xattrs = NULL; + const char *priority_str, *identifier, *comm, *pid, *message; +- size_t priority_len, identifier_len, comm_len, pid_len, message_len; ++ size_t priority_len, identifier_len, comm_len = 0, pid_len, message_len; + int priority = LOG_INFO; + int64_t ts; + +-- +2.18.4 + 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 deleted file mode 100644 index f7ec87f..0000000 --- a/SOURCES/0007-v2v-linux-do-not-uninstall-open-vm-tools-w-ubuntu-se.patch +++ /dev/null @@ -1,57 +0,0 @@ -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-builder-Fix-const-correctness-for-OCaml-4.10.patch b/SOURCES/0008-builder-Fix-const-correctness-for-OCaml-4.10.patch new file mode 100644 index 0000000..654dcd9 --- /dev/null +++ b/SOURCES/0008-builder-Fix-const-correctness-for-OCaml-4.10.patch @@ -0,0 +1,29 @@ +From 17df30b82007073a40deb37ff7f840d56a1b5bf1 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 6 Feb 2020 10:33:39 +0000 +Subject: [PATCH] builder: Fix const correctness for OCaml 4.10. + +String_val now returns a const char *. + +(cherry picked from commit d6fcf519f2d860fe3167629f042f5ff6a4ccc40d) +--- + builder/setlocale-c.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/builder/setlocale-c.c b/builder/setlocale-c.c +index f2ad85352..6d877e7ac 100644 +--- a/builder/setlocale-c.c ++++ b/builder/setlocale-c.c +@@ -44,7 +44,8 @@ virt_builder_setlocale (value val_category, value val_name) + { + CAMLparam2 (val_category, val_name); + CAMLlocal2 (rv, rv2); +- char *ret, *locstring; ++ const char *locstring; ++ char *ret; + int category; + + category = lc_string_table[Int_val (val_category)]; +-- +2.18.4 + 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 deleted file mode 100644 index 6691d7a..0000000 --- a/SOURCES/0008-v2v-linux-canonicalize-module-path-for-arch-detectio.patch +++ /dev/null @@ -1,36 +0,0 @@ -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-mlxml-Fix-pointed-target-signedness.patch b/SOURCES/0009-mlxml-Fix-pointed-target-signedness.patch new file mode 100644 index 0000000..d1bce94 --- /dev/null +++ b/SOURCES/0009-mlxml-Fix-pointed-target-signedness.patch @@ -0,0 +1,33 @@ +From 8eb9f06b156c6362a17712cfed9c629dec297a2c Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 6 Feb 2020 10:22:42 +0000 +Subject: [PATCH] mlxml: Fix pointed target signedness. + +xml-c.c: In function 'mllib_xml_to_string': +xml-c.c:199:47: error: pointer targets in passing argument 2 of 'caml_alloc_initialized_string' differ in signedness [-Werror=pointer-sign] + 199 | strv = caml_alloc_initialized_string (size, mem); + | ^~~ + | | + | xmlChar * {aka unsigned char *} + +(cherry picked from commit ea10827b4cfb3cfe5f782421c01d2902e5f73f90) +--- + common/mlxml/xml-c.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/common/mlxml/xml-c.c b/common/mlxml/xml-c.c +index a0fa0fc3d..715c3bb24 100644 +--- a/common/mlxml/xml-c.c ++++ b/common/mlxml/xml-c.c +@@ -196,7 +196,7 @@ mllib_xml_to_string (value docv, value formatv) + doc = docptr_val (docv); + xmlDocDumpFormatMemory (doc, &mem, &size, Bool_val (formatv)); + +- strv = caml_alloc_initialized_string (size, mem); ++ strv = caml_alloc_initialized_string (size, (const char *) mem); + free (mem); + + CAMLreturn (strv); +-- +2.18.4 + 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 deleted file mode 100644 index ce35612..0000000 --- a/SOURCES/0009-v2v-linux-improve-arch-detection-from-modules-RHBZ-1.patch +++ /dev/null @@ -1,61 +0,0 @@ -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 deleted file mode 100644 index 6b66ed9..0000000 --- a/SOURCES/0010-Use-proper-label-for-nbdkit-sockets.patch +++ /dev/null @@ -1,63 +0,0 @@ -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-common-mlpcre-add-offset-flag-for-PCRE.matches.patch b/SOURCES/0010-common-mlpcre-add-offset-flag-for-PCRE.matches.patch new file mode 100644 index 0000000..16d1443 --- /dev/null +++ b/SOURCES/0010-common-mlpcre-add-offset-flag-for-PCRE.matches.patch @@ -0,0 +1,126 @@ +From 83c76b6c610df17e0b9bfd9cd11deb43ebc40411 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 7dbba5857..ec3a6f00d 100644 +--- a/common/mlpcre/pcre-c.c ++++ b/common/mlpcre/pcre-c.c +@@ -133,6 +133,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, +@@ -177,9 +186,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); +@@ -217,7 +226,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.18.4 + diff --git a/SOURCES/0011-v2v-add-Var_expander.patch b/SOURCES/0011-v2v-add-Var_expander.patch new file mode 100644 index 0000000..e9f77a5 --- /dev/null +++ b/SOURCES/0011-v2v-add-Var_expander.patch @@ -0,0 +1,415 @@ +From 8b7c559f6c619bab8a708358db15b2959623c833 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.18.4 + 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 deleted file mode 100644 index 7c688b1..0000000 --- a/SOURCES/0011-v2v-start-reading-the-new-libvirt-firmware-autoselec.patch +++ /dev/null @@ -1,45 +0,0 @@ -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 deleted file mode 100644 index ac06365..0000000 --- a/SOURCES/0012-common-mltools-move-the-code-for-machine-readable-up.patch +++ /dev/null @@ -1,96 +0,0 @@ -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-json-output-mode.patch b/SOURCES/0012-v2v-add-o-json-output-mode.patch new file mode 100644 index 0000000..0b11b25 --- /dev/null +++ b/SOURCES/0012-v2v-add-o-json-output-mode.patch @@ -0,0 +1,785 @@ +From 87df9bcb99bdb60d5cedf52e155361826e700816 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.18.4 + 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 deleted file mode 100644 index febcfd1..0000000 --- a/SOURCES/0013-common-mltools-make-sure-machine-readable-output-is-.patch +++ /dev/null @@ -1,34 +0,0 @@ -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-inspect-fix-icon-of-RHEL.patch b/SOURCES/0013-inspect-fix-icon-of-RHEL.patch new file mode 100644 index 0000000..27b0ce1 --- /dev/null +++ b/SOURCES/0013-inspect-fix-icon-of-RHEL.patch @@ -0,0 +1,32 @@ +From 9ff9ddf3c372acee3a31a9d9435b1f32e0932943 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.18.4 + 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 deleted file mode 100644 index 8f9a207..0000000 --- a/SOURCES/0014-common-mltools-allow-fd-for-machine-readable-output.patch +++ /dev/null @@ -1,87 +0,0 @@ -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-warn-when-the-guest-has-direct-network-interface.patch b/SOURCES/0014-v2v-warn-when-the-guest-has-direct-network-interface.patch new file mode 100644 index 0000000..14b277c --- /dev/null +++ b/SOURCES/0014-v2v-warn-when-the-guest-has-direct-network-interface.patch @@ -0,0 +1,48 @@ +From 573f551ff8ced48f4ea21ec7bbbad235092f36f2 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.18.4 + 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 deleted file mode 100644 index 7fa6ab5..0000000 --- a/SOURCES/0015-OCaml-tools-output-messages-into-JSON-for-machine-re.patch +++ /dev/null @@ -1,514 +0,0 @@ -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-update-documentation-on-nbdkit-RHBZ-1605242.patch b/SOURCES/0015-v2v-update-documentation-on-nbdkit-RHBZ-1605242.patch new file mode 100644 index 0000000..2becf46 --- /dev/null +++ b/SOURCES/0015-v2v-update-documentation-on-nbdkit-RHBZ-1605242.patch @@ -0,0 +1,55 @@ +From 31ffb01b14ef809d4c5836e9244eb114e971c36e 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.18.4 + diff --git a/SOURCES/0016-OCaml-tools-fix-3999-3339-typo.patch b/SOURCES/0016-OCaml-tools-fix-3999-3339-typo.patch deleted file mode 100644 index e4e9f0f..0000000 --- a/SOURCES/0016-OCaml-tools-fix-3999-3339-typo.patch +++ /dev/null @@ -1,77 +0,0 @@ -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-linux-do-not-uninstall-open-vm-tools-w-ubuntu-se.patch b/SOURCES/0016-v2v-linux-do-not-uninstall-open-vm-tools-w-ubuntu-se.patch new file mode 100644 index 0000000..94b6803 --- /dev/null +++ b/SOURCES/0016-v2v-linux-do-not-uninstall-open-vm-tools-w-ubuntu-se.patch @@ -0,0 +1,57 @@ +From 9857aa4f951dd289b54e5693946b3f7adbe5c98b 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.18.4 + diff --git a/SOURCES/0017-v2v-linux-canonicalize-module-path-for-arch-detectio.patch b/SOURCES/0017-v2v-linux-canonicalize-module-path-for-arch-detectio.patch new file mode 100644 index 0000000..c856771 --- /dev/null +++ b/SOURCES/0017-v2v-linux-canonicalize-module-path-for-arch-detectio.patch @@ -0,0 +1,36 @@ +From 999180eca864baf0a82267448de120d2ed0e4787 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.18.4 + 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 deleted file mode 100644 index d05b5b2..0000000 --- a/SOURCES/0017-v2v-remove-extra-nbdkit-bit-from-documentation-RHBZ-.patch +++ /dev/null @@ -1,31 +0,0 @@ -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-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 deleted file mode 100644 index 8c3611a..0000000 --- a/SOURCES/0018-v2v-i-vmx-Use-scp-T-option-if-available-to-unbreak-s.patch +++ /dev/null @@ -1,49 +0,0 @@ -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/0018-v2v-linux-improve-arch-detection-from-modules-RHBZ-1.patch b/SOURCES/0018-v2v-linux-improve-arch-detection-from-modules-RHBZ-1.patch new file mode 100644 index 0000000..e1e1c66 --- /dev/null +++ b/SOURCES/0018-v2v-linux-improve-arch-detection-from-modules-RHBZ-1.patch @@ -0,0 +1,61 @@ +From de9ebcaf0784c464a3ca3b2686935ce2bddcc281 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.18.4 + diff --git a/SOURCES/0019-Use-proper-label-for-nbdkit-sockets.patch b/SOURCES/0019-Use-proper-label-for-nbdkit-sockets.patch new file mode 100644 index 0000000..9ba82b9 --- /dev/null +++ b/SOURCES/0019-Use-proper-label-for-nbdkit-sockets.patch @@ -0,0 +1,63 @@ +From 19c52dffc48af65eb07e6e1f8a85fc093ede9eb2 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.18.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 deleted file mode 100644 index 6c92927..0000000 --- a/SOURCES/0019-v2v-Allow-Windows-virtio-ISO-to-be-a-block-device-as.patch +++ /dev/null @@ -1,28 +0,0 @@ -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/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 deleted file mode 100644 index 7f81ba9..0000000 --- a/SOURCES/0020-v2v-Set-DISKTYPE-2-in-RHV-and-VDSM-meta-files-RHBZ-1.patch +++ /dev/null @@ -1,46 +0,0 @@ -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-start-reading-the-new-libvirt-firmware-autoselec.patch b/SOURCES/0020-v2v-start-reading-the-new-libvirt-firmware-autoselec.patch new file mode 100644 index 0000000..76ba3cf --- /dev/null +++ b/SOURCES/0020-v2v-start-reading-the-new-libvirt-firmware-autoselec.patch @@ -0,0 +1,45 @@ +From 3fe15743f316f1576115e30ebd0a512b3667e2f1 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.18.4 + diff --git a/SOURCES/0021-common-mltools-move-the-code-for-machine-readable-up.patch b/SOURCES/0021-common-mltools-move-the-code-for-machine-readable-up.patch new file mode 100644 index 0000000..5a539bd --- /dev/null +++ b/SOURCES/0021-common-mltools-move-the-code-for-machine-readable-up.patch @@ -0,0 +1,96 @@ +From 7ac3289d64b37348f29de9db4d71c3286836066b 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.18.4 + 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 deleted file mode 100644 index 6f063b4..0000000 --- a/SOURCES/0021-v2v-rhv-upload-plugin-improve-wait-logic-after-final.patch +++ /dev/null @@ -1,55 +0,0 @@ -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-common-mltools-make-sure-machine-readable-output-is-.patch b/SOURCES/0022-common-mltools-make-sure-machine-readable-output-is-.patch new file mode 100644 index 0000000..afbc879 --- /dev/null +++ b/SOURCES/0022-common-mltools-make-sure-machine-readable-output-is-.patch @@ -0,0 +1,34 @@ +From d60ef2eca9c0e51944a9c17806d6936af45907f5 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.18.4 + 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 deleted file mode 100644 index b01b226..0000000 --- a/SOURCES/0022-v2v-o-rhv-upload-check-whether-the-cluster-exists.patch +++ /dev/null @@ -1,61 +0,0 @@ -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-common-mltools-allow-fd-for-machine-readable-output.patch b/SOURCES/0023-common-mltools-allow-fd-for-machine-readable-output.patch new file mode 100644 index 0000000..52e1b86 --- /dev/null +++ b/SOURCES/0023-common-mltools-allow-fd-for-machine-readable-output.patch @@ -0,0 +1,87 @@ +From f7acb14822f1a962a211c0d11488ffceadde2b68 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.18.4 + 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 deleted file mode 100644 index 0f2c916..0000000 --- a/SOURCES/0023-v2v-o-rhv-upload-split-vmcheck-out-of-precheck.patch +++ /dev/null @@ -1,264 +0,0 @@ -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-OCaml-tools-output-messages-into-JSON-for-machine-re.patch b/SOURCES/0024-OCaml-tools-output-messages-into-JSON-for-machine-re.patch new file mode 100644 index 0000000..0b00a0d --- /dev/null +++ b/SOURCES/0024-OCaml-tools-output-messages-into-JSON-for-machine-re.patch @@ -0,0 +1,514 @@ +From e34b3a6aca9e7e51888416c57f768522597a2df1 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.18.4 + 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 deleted file mode 100644 index 60862e1..0000000 --- a/SOURCES/0024-v2v-o-rhv-upload-change-precheck-script-to-return-a-.patch +++ /dev/null @@ -1,53 +0,0 @@ -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-OCaml-tools-fix-3999-3339-typo.patch b/SOURCES/0025-OCaml-tools-fix-3999-3339-typo.patch new file mode 100644 index 0000000..796867d --- /dev/null +++ b/SOURCES/0025-OCaml-tools-fix-3999-3339-typo.patch @@ -0,0 +1,77 @@ +From 1d6f775d8826915f9547c7dcac0fd10e702c3d80 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.18.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 deleted file mode 100644 index 0560c10..0000000 --- a/SOURCES/0025-v2v-o-rhv-upload-improve-lookup-of-specified-resourc.patch +++ /dev/null @@ -1,169 +0,0 @@ -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/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 deleted file mode 100644 index b2235af..0000000 --- a/SOURCES/0026-v2v-o-rhv-upload-tell-whether-a-SD-actually-exists.patch +++ /dev/null @@ -1,36 +0,0 @@ -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-remove-extra-nbdkit-bit-from-documentation-RHBZ-.patch b/SOURCES/0026-v2v-remove-extra-nbdkit-bit-from-documentation-RHBZ-.patch new file mode 100644 index 0000000..e3e707a --- /dev/null +++ b/SOURCES/0026-v2v-remove-extra-nbdkit-bit-from-documentation-RHBZ-.patch @@ -0,0 +1,31 @@ +From ee414298417aa570df4f1c77a5d47672c2871629 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.18.4 + diff --git a/SOURCES/0027-v2v-add-output-disk_copied-hook.patch b/SOURCES/0027-v2v-add-output-disk_copied-hook.patch deleted file mode 100644 index ed609b4..0000000 --- a/SOURCES/0027-v2v-add-output-disk_copied-hook.patch +++ /dev/null @@ -1,76 +0,0 @@ -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-i-vmx-Use-scp-T-option-if-available-to-unbreak-s.patch b/SOURCES/0027-v2v-i-vmx-Use-scp-T-option-if-available-to-unbreak-s.patch new file mode 100644 index 0000000..a45bf92 --- /dev/null +++ b/SOURCES/0027-v2v-i-vmx-Use-scp-T-option-if-available-to-unbreak-s.patch @@ -0,0 +1,49 @@ +From f36bb1b9c44cda46afa1a34522202a5319fd0a5a 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.18.4 + diff --git a/SOURCES/0028-v2v-Allow-Windows-virtio-ISO-to-be-a-block-device-as.patch b/SOURCES/0028-v2v-Allow-Windows-virtio-ISO-to-be-a-block-device-as.patch new file mode 100644 index 0000000..82e592c --- /dev/null +++ b/SOURCES/0028-v2v-Allow-Windows-virtio-ISO-to-be-a-block-device-as.patch @@ -0,0 +1,28 @@ +From 9a9270b0156cf30d98c26eaffb8b12c98d0d9bf4 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.18.4 + 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 deleted file mode 100644 index 1040341..0000000 --- a/SOURCES/0028-v2v-o-rhv-upload-collect-disks-UUIDs-right-after-cop.patch +++ /dev/null @@ -1,84 +0,0 @@ -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-Set-DISKTYPE-2-in-RHV-and-VDSM-meta-files-RHBZ-1.patch b/SOURCES/0029-v2v-Set-DISKTYPE-2-in-RHV-and-VDSM-meta-files-RHBZ-1.patch new file mode 100644 index 0000000..76aa6a3 --- /dev/null +++ b/SOURCES/0029-v2v-Set-DISKTYPE-2-in-RHV-and-VDSM-meta-files-RHBZ-1.patch @@ -0,0 +1,46 @@ +From c49492cf218f4e6c1e90979c8d50ce3557642c42 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.18.4 + 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 deleted file mode 100644 index fc7c385..0000000 --- a/SOURCES/0029-v2v-o-rhv-upload-add-oo-rhv-disk-uuid-option.patch +++ /dev/null @@ -1,201 +0,0 @@ -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-o-rhv-upload-make-oo-rhv-cafile-optional.patch b/SOURCES/0030-v2v-o-rhv-upload-make-oo-rhv-cafile-optional.patch deleted file mode 100644 index 38d803d..0000000 --- a/SOURCES/0030-v2v-o-rhv-upload-make-oo-rhv-cafile-optional.patch +++ /dev/null @@ -1,87 +0,0 @@ -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/0030-v2v-rhv-upload-plugin-improve-wait-logic-after-final.patch b/SOURCES/0030-v2v-rhv-upload-plugin-improve-wait-logic-after-final.patch new file mode 100644 index 0000000..11e4ed6 --- /dev/null +++ b/SOURCES/0030-v2v-rhv-upload-plugin-improve-wait-logic-after-final.patch @@ -0,0 +1,55 @@ +From 1a601b248f347b2237ff458376a010eeb46d005d 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.18.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 deleted file mode 100644 index 47694b3..0000000 --- a/SOURCES/0031-v2v-Fix-default-graphics-driver-for-SUSE-guests.patch +++ /dev/null @@ -1,40 +0,0 @@ -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-o-rhv-upload-check-whether-the-cluster-exists.patch b/SOURCES/0031-v2v-o-rhv-upload-check-whether-the-cluster-exists.patch new file mode 100644 index 0000000..9079b85 --- /dev/null +++ b/SOURCES/0031-v2v-o-rhv-upload-check-whether-the-cluster-exists.patch @@ -0,0 +1,61 @@ +From fed5b4195b1b220e43964aa61d01634b307f09a4 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.18.4 + diff --git a/SOURCES/0032-v2v-o-rhv-upload-split-vmcheck-out-of-precheck.patch b/SOURCES/0032-v2v-o-rhv-upload-split-vmcheck-out-of-precheck.patch new file mode 100644 index 0000000..1bc6c82 --- /dev/null +++ b/SOURCES/0032-v2v-o-rhv-upload-split-vmcheck-out-of-precheck.patch @@ -0,0 +1,264 @@ +From fb5e3592a94b535abe686b65e51577ad0e36fcd0 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.18.4 + 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 deleted file mode 100644 index da0c9aa..0000000 --- a/SOURCES/0032-v2v-windows-Add-a-helper-function-for-installing-Pow.patch +++ /dev/null @@ -1,73 +0,0 @@ -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 deleted file mode 100644 index 62740d1..0000000 --- a/SOURCES/0033-v2v-Copy-static-IP-address-information-over-for-Wind.patch +++ /dev/null @@ -1,423 +0,0 @@ -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-o-rhv-upload-change-precheck-script-to-return-a-.patch b/SOURCES/0033-v2v-o-rhv-upload-change-precheck-script-to-return-a-.patch new file mode 100644 index 0000000..72a82f9 --- /dev/null +++ b/SOURCES/0033-v2v-o-rhv-upload-change-precheck-script-to-return-a-.patch @@ -0,0 +1,53 @@ +From bb04eba9683c4143f9b5880238f006af3b13c05c 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.18.4 + diff --git a/SOURCES/0034-New-API-luks_uuid.patch b/SOURCES/0034-New-API-luks_uuid.patch deleted file mode 100644 index 37368da..0000000 --- a/SOURCES/0034-New-API-luks_uuid.patch +++ /dev/null @@ -1,87 +0,0 @@ -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-o-rhv-upload-improve-lookup-of-specified-resourc.patch b/SOURCES/0034-v2v-o-rhv-upload-improve-lookup-of-specified-resourc.patch new file mode 100644 index 0000000..cde9b5b --- /dev/null +++ b/SOURCES/0034-v2v-o-rhv-upload-improve-lookup-of-specified-resourc.patch @@ -0,0 +1,169 @@ +From 07348a7d9a7533b11513706a91d8eb8b91ce8518 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.18.4 + 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 deleted file mode 100644 index ed0daf9..0000000 --- a/SOURCES/0035-options-Fix-segfault-when-multiple-key-parameters-gi.patch +++ /dev/null @@ -1,47 +0,0 @@ -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-o-rhv-upload-tell-whether-a-SD-actually-exists.patch b/SOURCES/0035-v2v-o-rhv-upload-tell-whether-a-SD-actually-exists.patch new file mode 100644 index 0000000..4cfbbb8 --- /dev/null +++ b/SOURCES/0035-v2v-o-rhv-upload-tell-whether-a-SD-actually-exists.patch @@ -0,0 +1,36 @@ +From e7b94193f29d7a2715a860deb6db0708eef8c107 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.18.4 + diff --git a/SOURCES/0036-options-Simplify-selector-parsing-for-key-options.patch b/SOURCES/0036-options-Simplify-selector-parsing-for-key-options.patch deleted file mode 100644 index a157bbf..0000000 --- a/SOURCES/0036-options-Simplify-selector-parsing-for-key-options.patch +++ /dev/null @@ -1,85 +0,0 @@ -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-add-output-disk_copied-hook.patch b/SOURCES/0036-v2v-add-output-disk_copied-hook.patch new file mode 100644 index 0000000..5f37ed2 --- /dev/null +++ b/SOURCES/0036-v2v-add-output-disk_copied-hook.patch @@ -0,0 +1,76 @@ +From fbb0daf1ee29cda6d9117be2430c7d5d66463eca 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.18.4 + diff --git a/SOURCES/0037-options-Allow-multiple-key-parameters.patch b/SOURCES/0037-options-Allow-multiple-key-parameters.patch deleted file mode 100644 index 080c6c4..0000000 --- a/SOURCES/0037-options-Allow-multiple-key-parameters.patch +++ /dev/null @@ -1,181 +0,0 @@ -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-o-rhv-upload-collect-disks-UUIDs-right-after-cop.patch b/SOURCES/0037-v2v-o-rhv-upload-collect-disks-UUIDs-right-after-cop.patch new file mode 100644 index 0000000..3891ef7 --- /dev/null +++ b/SOURCES/0037-v2v-o-rhv-upload-collect-disks-UUIDs-right-after-cop.patch @@ -0,0 +1,84 @@ +From 8f8fbe96bfcb6f284590ddd17b960247ec87bde9 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.18.4 + diff --git a/SOURCES/0038-options-rename-key.device-as-key.id.patch b/SOURCES/0038-options-rename-key.device-as-key.id.patch deleted file mode 100644 index 667cdf5..0000000 --- a/SOURCES/0038-options-rename-key.device-as-key.id.patch +++ /dev/null @@ -1,437 +0,0 @@ -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-o-rhv-upload-add-oo-rhv-disk-uuid-option.patch b/SOURCES/0038-v2v-o-rhv-upload-add-oo-rhv-disk-uuid-option.patch new file mode 100644 index 0000000..d2483bd --- /dev/null +++ b/SOURCES/0038-v2v-o-rhv-upload-add-oo-rhv-disk-uuid-option.patch @@ -0,0 +1,201 @@ +From 9d7b3e53fd4346bbb2abfb046df224de03f5b92f 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.18.4 + 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 deleted file mode 100644 index 9b3fc9c..0000000 --- a/SOURCES/0039-options-allow-a-UUID-as-identifier-for-key.patch +++ /dev/null @@ -1,313 +0,0 @@ -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-v2v-o-rhv-upload-make-oo-rhv-cafile-optional.patch b/SOURCES/0039-v2v-o-rhv-upload-make-oo-rhv-cafile-optional.patch new file mode 100644 index 0000000..e58ab1a --- /dev/null +++ b/SOURCES/0039-v2v-o-rhv-upload-make-oo-rhv-cafile-optional.patch @@ -0,0 +1,87 @@ +From 971f3c3239a9d6433fa351ceb983db9cce2ab4ac 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.18.4 + 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 deleted file mode 100644 index e94bcd6..0000000 --- a/SOURCES/0040-docs-remove-paragraph-about-VMware-tools-on-Windows-.patch +++ /dev/null @@ -1,82 +0,0 @@ -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-Fix-default-graphics-driver-for-SUSE-guests.patch b/SOURCES/0040-v2v-Fix-default-graphics-driver-for-SUSE-guests.patch new file mode 100644 index 0000000..9abbfc0 --- /dev/null +++ b/SOURCES/0040-v2v-Fix-default-graphics-driver-for-SUSE-guests.patch @@ -0,0 +1,40 @@ +From 14f47e2084688af0d67807f2a5cfbd90759d8e7f 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.18.4 + diff --git a/SOURCES/0041-mlcustomize-Trim-whitespaces-from-commands-read-from.patch b/SOURCES/0041-mlcustomize-Trim-whitespaces-from-commands-read-from.patch deleted file mode 100644 index 2d9be80..0000000 --- a/SOURCES/0041-mlcustomize-Trim-whitespaces-from-commands-read-from.patch +++ /dev/null @@ -1,29 +0,0 @@ -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-windows-Add-a-helper-function-for-installing-Pow.patch b/SOURCES/0041-v2v-windows-Add-a-helper-function-for-installing-Pow.patch new file mode 100644 index 0000000..07ca8ee --- /dev/null +++ b/SOURCES/0041-v2v-windows-Add-a-helper-function-for-installing-Pow.patch @@ -0,0 +1,73 @@ +From d875df20c30868db210396b64f6dcec2cb6d57b4 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.18.4 + 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 deleted file mode 100644 index 651d86d..0000000 --- a/SOURCES/0042-openstack-Increase-Cinder-volume-attach-timeout-to-5.patch +++ /dev/null @@ -1,43 +0,0 @@ -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-Copy-static-IP-address-information-over-for-Wind.patch b/SOURCES/0042-v2v-Copy-static-IP-address-information-over-for-Wind.patch new file mode 100644 index 0000000..c72d967 --- /dev/null +++ b/SOURCES/0042-v2v-Copy-static-IP-address-information-over-for-Wind.patch @@ -0,0 +1,423 @@ +From 77606e831f8891b65350effb6502d233d74f8cfc 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.18.4 + diff --git a/SOURCES/0043-New-API-luks_uuid.patch b/SOURCES/0043-New-API-luks_uuid.patch new file mode 100644 index 0000000..1d2b80d --- /dev/null +++ b/SOURCES/0043-New-API-luks_uuid.patch @@ -0,0 +1,87 @@ +From c31eaba4d6b36d90cfd835a4750e50f6a5256b73 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.18.4 + 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 deleted file mode 100644 index 397077e..0000000 --- a/SOURCES/0043-v2v-o-rhv-upload-check-for-a-valid-image-transfer-ri.patch +++ /dev/null @@ -1,35 +0,0 @@ -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-options-Fix-segfault-when-multiple-key-parameters-gi.patch b/SOURCES/0044-options-Fix-segfault-when-multiple-key-parameters-gi.patch new file mode 100644 index 0000000..1d44585 --- /dev/null +++ b/SOURCES/0044-options-Fix-segfault-when-multiple-key-parameters-gi.patch @@ -0,0 +1,47 @@ +From a7fe83c678520aca2289eab2af6d8aebdf225bb7 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.18.4 + diff --git a/SOURCES/0044-rhv-upload-Check-status-more-frequently.patch b/SOURCES/0044-rhv-upload-Check-status-more-frequently.patch deleted file mode 100644 index 350f32b..0000000 --- a/SOURCES/0044-rhv-upload-Check-status-more-frequently.patch +++ /dev/null @@ -1,49 +0,0 @@ -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/0045-options-Simplify-selector-parsing-for-key-options.patch b/SOURCES/0045-options-Simplify-selector-parsing-for-key-options.patch new file mode 100644 index 0000000..d449c1a --- /dev/null +++ b/SOURCES/0045-options-Simplify-selector-parsing-for-key-options.patch @@ -0,0 +1,85 @@ +From c74aa1326061723bd87e599699096d1085472772 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.18.4 + 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 deleted file mode 100644 index 68b32cb..0000000 --- a/SOURCES/0045-rhv-upload-Show-transfer-id-in-error-message.patch +++ /dev/null @@ -1,31 +0,0 @@ -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/0046-options-Allow-multiple-key-parameters.patch b/SOURCES/0046-options-Allow-multiple-key-parameters.patch new file mode 100644 index 0000000..78900c7 --- /dev/null +++ b/SOURCES/0046-options-Allow-multiple-key-parameters.patch @@ -0,0 +1,180 @@ +From 0267ad921c3be8a780342b052264666cef2cc1b1 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 | 35 ++++++++++++++++++++++++------- + common/options/keys.c | 45 +++++++++++++++++++++++++++++++--------- + common/options/options.h | 6 ++++-- + 3 files changed, 66 insertions(+), 20 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.18.4 + diff --git a/SOURCES/0046-rhv-upload-Fix-waiting-for-transfer.patch b/SOURCES/0046-rhv-upload-Fix-waiting-for-transfer.patch deleted file mode 100644 index cc6fd5b..0000000 --- a/SOURCES/0046-rhv-upload-Fix-waiting-for-transfer.patch +++ /dev/null @@ -1,89 +0,0 @@ -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-options-rename-key.device-as-key.id.patch b/SOURCES/0047-options-rename-key.device-as-key.id.patch new file mode 100644 index 0000000..e67cbf2 --- /dev/null +++ b/SOURCES/0047-options-rename-key.device-as-key.id.patch @@ -0,0 +1,437 @@ +From dd28c27df30c5a41bec97181a297d4df95aad0ab 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.18.4 + 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 deleted file mode 100644 index e09d484..0000000 --- a/SOURCES/0047-v2v-Optimize-convert-for-images-with-small-holes.patch +++ /dev/null @@ -1,84 +0,0 @@ -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-options-allow-a-UUID-as-identifier-for-key.patch b/SOURCES/0048-options-allow-a-UUID-as-identifier-for-key.patch new file mode 100644 index 0000000..80402a2 --- /dev/null +++ b/SOURCES/0048-options-allow-a-UUID-as-identifier-for-key.patch @@ -0,0 +1,313 @@ +From 88c4dc1e5b9f9e545c89e8b8ee6878f57df3139c 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.18.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 deleted file mode 100644 index c18d6c9..0000000 --- a/SOURCES/0048-v2v-o-rhv-upload-Make-oo-rhv-cafile-optional-in-all-.patch +++ /dev/null @@ -1,49 +0,0 @@ -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/0049-docs-Fix-update-crypto-policies-command-RHBZ-1791257.patch b/SOURCES/0049-docs-Fix-update-crypto-policies-command-RHBZ-1791257.patch deleted file mode 100644 index 378986c..0000000 --- a/SOURCES/0049-docs-Fix-update-crypto-policies-command-RHBZ-1791257.patch +++ /dev/null @@ -1,33 +0,0 @@ -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-docs-remove-paragraph-about-VMware-tools-on-Windows-.patch b/SOURCES/0049-docs-remove-paragraph-about-VMware-tools-on-Windows-.patch new file mode 100644 index 0000000..4301fbb --- /dev/null +++ b/SOURCES/0049-docs-remove-paragraph-about-VMware-tools-on-Windows-.patch @@ -0,0 +1,82 @@ +From 14c456c0f5d9caad9aedc5abb7b6a025ac09e7bd 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.18.4 + 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 deleted file mode 100644 index e06ddaf..0000000 --- a/SOURCES/0050-add-versioned-directory-for-guest-agent-on-EL8.patch +++ /dev/null @@ -1,35 +0,0 @@ -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-mlcustomize-Trim-whitespaces-from-commands-read-from.patch b/SOURCES/0050-mlcustomize-Trim-whitespaces-from-commands-read-from.patch new file mode 100644 index 0000000..6a41357 --- /dev/null +++ b/SOURCES/0050-mlcustomize-Trim-whitespaces-from-commands-read-from.patch @@ -0,0 +1,29 @@ +From 931846b8f08e5e763141cadfc5e9b194b69303e3 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.18.4 + diff --git a/SOURCES/0051-openstack-Increase-Cinder-volume-attach-timeout-to-5.patch b/SOURCES/0051-openstack-Increase-Cinder-volume-attach-timeout-to-5.patch new file mode 100644 index 0000000..b0b2d88 --- /dev/null +++ b/SOURCES/0051-openstack-Increase-Cinder-volume-attach-timeout-to-5.patch @@ -0,0 +1,43 @@ +From 7cfbc1e0fac86b1139c59945f74eab8906ec18bc 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.18.4 + 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 deleted file mode 100644 index 7210464..0000000 --- a/SOURCES/0051-v2v-fix-path-to-source-when-copying-files-from-guest.patch +++ /dev/null @@ -1,41 +0,0 @@ -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/0052-v2v-o-rhv-upload-check-for-a-valid-image-transfer-ri.patch b/SOURCES/0052-v2v-o-rhv-upload-check-for-a-valid-image-transfer-ri.patch new file mode 100644 index 0000000..039d151 --- /dev/null +++ b/SOURCES/0052-v2v-o-rhv-upload-check-for-a-valid-image-transfer-ri.patch @@ -0,0 +1,35 @@ +From 303ecfdf662a2fd80b115a1e2f20560e6f97d953 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.18.4 + diff --git a/SOURCES/0052-v2v-windows-install-QEMU-Guest-Agent-MSI.patch b/SOURCES/0052-v2v-windows-install-QEMU-Guest-Agent-MSI.patch deleted file mode 100644 index 2f0b7ae..0000000 --- a/SOURCES/0052-v2v-windows-install-QEMU-Guest-Agent-MSI.patch +++ /dev/null @@ -1,119 +0,0 @@ -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-rhv-upload-Check-status-more-frequently.patch b/SOURCES/0053-rhv-upload-Check-status-more-frequently.patch new file mode 100644 index 0000000..4e69981 --- /dev/null +++ b/SOURCES/0053-rhv-upload-Check-status-more-frequently.patch @@ -0,0 +1,49 @@ +From 7a4b425471223234fde5a65ca5fe5abc87fb0276 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.18.4 + 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 deleted file mode 100644 index 70aec69..0000000 --- a/SOURCES/0053-windows-small-tweaks-of-qemu-ga-firstboot-script.patch +++ /dev/null @@ -1,42 +0,0 @@ -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-rhv-upload-Show-transfer-id-in-error-message.patch b/SOURCES/0054-rhv-upload-Show-transfer-id-in-error-message.patch new file mode 100644 index 0000000..477d6c2 --- /dev/null +++ b/SOURCES/0054-rhv-upload-Show-transfer-id-in-error-message.patch @@ -0,0 +1,31 @@ +From 8659766f3559177edf60f7ed6e1ed834f5d4d4a0 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.18.4 + 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 deleted file mode 100644 index 3f307ef..0000000 --- a/SOURCES/0054-windows-fix-detection-of-qemu-ga-installer-on-RHV.patch +++ /dev/null @@ -1,43 +0,0 @@ -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-rhv-upload-Fix-waiting-for-transfer.patch b/SOURCES/0055-rhv-upload-Fix-waiting-for-transfer.patch new file mode 100644 index 0000000..cb4b91d --- /dev/null +++ b/SOURCES/0055-rhv-upload-Fix-waiting-for-transfer.patch @@ -0,0 +1,89 @@ +From 79a7e239ca55bffb2af059e1cfe07206d37cb858 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() ++ 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 transfer.phase != types.ImageTransferPhase.INITIALIZING: +- break +- if time.time() > endt: ++ 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.18.4 + diff --git a/SOURCES/0055-windows-delay-installation-of-qemu-ga-MSI.patch b/SOURCES/0055-windows-delay-installation-of-qemu-ga-MSI.patch deleted file mode 100644 index 41d1548..0000000 --- a/SOURCES/0055-windows-delay-installation-of-qemu-ga-MSI.patch +++ /dev/null @@ -1,67 +0,0 @@ -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 deleted file mode 100644 index a998da3..0000000 --- a/SOURCES/0056-daemon-xattr-Refactor-code-which-splits-attr-names-f.patch +++ /dev/null @@ -1,283 +0,0 @@ -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-Optimize-convert-for-images-with-small-holes.patch b/SOURCES/0056-v2v-Optimize-convert-for-images-with-small-holes.patch new file mode 100644 index 0000000..c7ce346 --- /dev/null +++ b/SOURCES/0056-v2v-Optimize-convert-for-images-with-small-holes.patch @@ -0,0 +1,84 @@ +From 48718639cc7fc5f93260b00553397ccb3faa7bbc 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.18.4 + diff --git a/SOURCES/0057-daemon-Add-filter_list-utility-function.patch b/SOURCES/0057-daemon-Add-filter_list-utility-function.patch deleted file mode 100644 index db1e1d8..0000000 --- a/SOURCES/0057-daemon-Add-filter_list-utility-function.patch +++ /dev/null @@ -1,84 +0,0 @@ -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-v2v-o-rhv-upload-Make-oo-rhv-cafile-optional-in-all-.patch b/SOURCES/0057-v2v-o-rhv-upload-Make-oo-rhv-cafile-optional-in-all-.patch new file mode 100644 index 0000000..e839d50 --- /dev/null +++ b/SOURCES/0057-v2v-o-rhv-upload-Make-oo-rhv-cafile-optional-in-all-.patch @@ -0,0 +1,49 @@ +From fdf461e88c464de697c14adea2e8e61644811844 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.18.4 + diff --git a/SOURCES/0058-daemon-xattr-Filter-out-user.WofCompressedData-from-.patch b/SOURCES/0058-daemon-xattr-Filter-out-user.WofCompressedData-from-.patch deleted file mode 100644 index ab6cbeb..0000000 --- a/SOURCES/0058-daemon-xattr-Filter-out-user.WofCompressedData-from-.patch +++ /dev/null @@ -1,120 +0,0 @@ -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-docs-Fix-update-crypto-policies-command-RHBZ-1791257.patch b/SOURCES/0058-docs-Fix-update-crypto-policies-command-RHBZ-1791257.patch new file mode 100644 index 0000000..d13f36c --- /dev/null +++ b/SOURCES/0058-docs-Fix-update-crypto-policies-command-RHBZ-1791257.patch @@ -0,0 +1,33 @@ +From 99de55c364d95ae50a6d6cd6865e52a6737738c5 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.18.4 + diff --git a/SOURCES/0059-add-versioned-directory-for-guest-agent-on-EL8.patch b/SOURCES/0059-add-versioned-directory-for-guest-agent-on-EL8.patch new file mode 100644 index 0000000..3481439 --- /dev/null +++ b/SOURCES/0059-add-versioned-directory-for-guest-agent-on-EL8.patch @@ -0,0 +1,35 @@ +From 2a08f0f71b92a2489b873c7cef5aae2b2cec88d2 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.18.4 + diff --git a/SOURCES/0059-mltools-add-run_in_guest_command-helper.patch b/SOURCES/0059-mltools-add-run_in_guest_command-helper.patch deleted file mode 100644 index 506b6c4..0000000 --- a/SOURCES/0059-mltools-add-run_in_guest_command-helper.patch +++ /dev/null @@ -1,95 +0,0 @@ -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 deleted file mode 100644 index d9162af..0000000 --- a/SOURCES/0060-customize-port-do_run-to-run_in_guest_command.patch +++ /dev/null @@ -1,83 +0,0 @@ -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-v2v-fix-path-to-source-when-copying-files-from-guest.patch b/SOURCES/0060-v2v-fix-path-to-source-when-copying-files-from-guest.patch new file mode 100644 index 0000000..316ddb3 --- /dev/null +++ b/SOURCES/0060-v2v-fix-path-to-source-when-copying-files-from-guest.patch @@ -0,0 +1,41 @@ +From 66cd34e84e41d3f70e95fa745637ba6eb4779aec 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 ( ++ debug "windows: copy_from_virtio_win: guest tools source directory %s" ++ virtio_win; ++ + let dir = virtio_win // srcdir in +- debug "windows: copy_from_virtio_win: guest tools source directory %s" dir; +- +- if not (is_directory srcdir) then missing () ++ 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.18.4 + 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 deleted file mode 100644 index 7b66f71..0000000 --- a/SOURCES/0061-sysprep-add-a-update_system_ca_store-side-effect.patch +++ /dev/null @@ -1,138 +0,0 @@ -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/0061-v2v-windows-install-QEMU-Guest-Agent-MSI.patch b/SOURCES/0061-v2v-windows-install-QEMU-Guest-Agent-MSI.patch new file mode 100644 index 0000000..f37b2e5 --- /dev/null +++ b/SOURCES/0061-v2v-windows-install-QEMU-Guest-Agent-MSI.patch @@ -0,0 +1,119 @@ +From cf06f1d264a8832aa31265da5b2a28547b0faf49 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.18.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 deleted file mode 100644 index 6505f87..0000000 --- a/SOURCES/0062-sysprep-ca-certificates-request-system-CA-store-upda.patch +++ /dev/null @@ -1,42 +0,0 @@ -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-windows-small-tweaks-of-qemu-ga-firstboot-script.patch b/SOURCES/0062-windows-small-tweaks-of-qemu-ga-firstboot-script.patch new file mode 100644 index 0000000..178545b --- /dev/null +++ b/SOURCES/0062-windows-small-tweaks-of-qemu-ga-firstboot-script.patch @@ -0,0 +1,42 @@ +From ab6076b6fe33cfe9a7b5d29bea5b8c24553894cc 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.18.4 + diff --git a/SOURCES/0063-sysprep-add-IPA-offline-unenrollment-RHBZ-1789592.patch b/SOURCES/0063-sysprep-add-IPA-offline-unenrollment-RHBZ-1789592.patch deleted file mode 100644 index e3d6243..0000000 --- a/SOURCES/0063-sysprep-add-IPA-offline-unenrollment-RHBZ-1789592.patch +++ /dev/null @@ -1,107 +0,0 @@ -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/0063-windows-fix-detection-of-qemu-ga-installer-on-RHV.patch b/SOURCES/0063-windows-fix-detection-of-qemu-ga-installer-on-RHV.patch new file mode 100644 index 0000000..fe2934c --- /dev/null +++ b/SOURCES/0063-windows-fix-detection-of-qemu-ga-installer-on-RHV.patch @@ -0,0 +1,43 @@ +From 52a4f93f1d8bb150167885c94df890af0d00d76d 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.18.4 + diff --git a/SOURCES/0064-sysprep-add-Kerberos-keytab-file-removal.patch b/SOURCES/0064-sysprep-add-Kerberos-keytab-file-removal.patch deleted file mode 100644 index 96ecb64..0000000 --- a/SOURCES/0064-sysprep-add-Kerberos-keytab-file-removal.patch +++ /dev/null @@ -1,81 +0,0 @@ -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-windows-delay-installation-of-qemu-ga-MSI.patch b/SOURCES/0064-windows-delay-installation-of-qemu-ga-MSI.patch new file mode 100644 index 0000000..bbca2bc --- /dev/null +++ b/SOURCES/0064-windows-delay-installation-of-qemu-ga-MSI.patch @@ -0,0 +1,67 @@ +From 898b0654a0c4ef55af147a5ca081d2399ce05855 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.18.4 + diff --git a/SOURCES/0065-RHEL-8-Remove-libguestfs-live-RHBZ-798980.patch b/SOURCES/0065-RHEL-8-Remove-libguestfs-live-RHBZ-798980.patch deleted file mode 100644 index 131014d..0000000 --- a/SOURCES/0065-RHEL-8-Remove-libguestfs-live-RHBZ-798980.patch +++ /dev/null @@ -1,38 +0,0 @@ -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). - -This isn't supported in RHEL 8. ---- - lib/launch-unix.c | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/lib/launch-unix.c b/lib/launch-unix.c -index 4794a7b13..993b83601 100644 ---- a/lib/launch-unix.c -+++ b/lib/launch-unix.c -@@ -37,6 +37,12 @@ - static int - launch_unix (guestfs_h *g, void *datav, const char *sockpath) - { -+ error (g, -+ "launch: In RHEL, only the 'libvirt' or 'direct' method is supported.\n" -+ "In particular, \"libguestfs live\" is not supported."); -+ return -1; -+ -+#if 0 - int r, daemon_sock = -1; - struct sockaddr_un addr; - uint32_t size; -@@ -106,6 +112,7 @@ launch_unix (guestfs_h *g, void *datav, const char *sockpath) - g->conn = NULL; - } - return -1; -+#endif - } - - static int --- -2.25.4 - diff --git a/SOURCES/0065-daemon-xattr-Refactor-code-which-splits-attr-names-f.patch b/SOURCES/0065-daemon-xattr-Refactor-code-which-splits-attr-names-f.patch new file mode 100644 index 0000000..1aab555 --- /dev/null +++ b/SOURCES/0065-daemon-xattr-Refactor-code-which-splits-attr-names-f.patch @@ -0,0 +1,283 @@ +From a13f9b06370a6fef6f671f5aa7c23df0f0fd542e 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.18.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 deleted file mode 100644 index a2d0e91..0000000 --- a/SOURCES/0066-RHEL-8-Remove-9p-APIs-from-RHEL-RHBZ-921710.patch +++ /dev/null @@ -1,372 +0,0 @@ -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). - ---- - Makefile.am | 2 +- - daemon/9p.c | 224 -------------------------------------- - daemon/Makefile.am | 1 - - docs/C_SOURCE_FILES | 1 - - generator/actions_core.ml | 21 ---- - generator/proc_nr.ml | 2 - - gobject/Makefile.inc | 2 - - po/POTFILES | 2 - - 8 files changed, 1 insertion(+), 254 deletions(-) - delete mode 100644 daemon/9p.c - -diff --git a/Makefile.am b/Makefile.am -index 0067d7b7b..e9351eadc 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -78,7 +78,7 @@ SUBDIRS += tests/xfs - SUBDIRS += tests/charsets - SUBDIRS += tests/xml - SUBDIRS += tests/mount-local --SUBDIRS += tests/9p -+#SUBDIRS += tests/9p - SUBDIRS += tests/rsync - SUBDIRS += tests/bigdirs - SUBDIRS += tests/disk-labels -diff --git a/daemon/9p.c b/daemon/9p.c -deleted file mode 100644 -index 55644249d..000000000 ---- a/daemon/9p.c -+++ /dev/null -@@ -1,224 +0,0 @@ --/* libguestfs - the guestfsd daemon -- * Copyright (C) 2011 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. -- */ -- --#include -- --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#include "daemon.h" --#include "actions.h" -- --#define BUS_PATH "/sys/bus/virtio/drivers/9pnet_virtio" -- --static char *read_whole_file (const char *filename); -- --/* https://bugzilla.redhat.com/show_bug.cgi?id=714981#c1 */ --char ** --do_list_9p (void) --{ -- CLEANUP_FREE_STRINGSBUF DECLARE_STRINGSBUF (r); -- -- DIR *dir; -- -- dir = opendir (BUS_PATH); -- if (!dir) { -- perror ("opendir: " BUS_PATH); -- if (errno != ENOENT) { -- reply_with_perror ("opendir: " BUS_PATH); -- return NULL; -- } -- -- /* If this directory doesn't exist, it probably means that -- * the virtio driver isn't loaded. Don't return an error -- * in this case, but return an empty list. -- */ -- if (end_stringsbuf (&r) == -1) -- return NULL; -- -- return take_stringsbuf (&r); -- } -- -- while (1) { -- struct dirent *d; -- -- errno = 0; -- d = readdir (dir); -- if (d == NULL) break; -- -- if (STRPREFIX (d->d_name, "virtio")) { -- CLEANUP_FREE char *mount_tag_path = NULL; -- if (asprintf (&mount_tag_path, BUS_PATH "/%s/mount_tag", -- d->d_name) == -1) { -- reply_with_perror ("asprintf"); -- closedir (dir); -- return NULL; -- } -- -- /* A bit unclear, but it looks like the virtio transport allows -- * the mount tag length to be unlimited (or up to 65536 bytes). -- * See: linux/include/linux/virtio_9p.h -- */ -- CLEANUP_FREE char *mount_tag = read_whole_file (mount_tag_path); -- if (mount_tag == 0) -- continue; -- -- if (add_string (&r, mount_tag) == -1) { -- closedir (dir); -- return NULL; -- } -- } -- } -- -- /* Check readdir didn't fail */ -- if (errno != 0) { -- reply_with_perror ("readdir: /sys/block"); -- closedir (dir); -- return NULL; -- } -- -- /* Close the directory handle */ -- if (closedir (dir) == -1) { -- reply_with_perror ("closedir: /sys/block"); -- return NULL; -- } -- -- /* Sort the tags. */ -- if (r.size > 0) -- sort_strings (r.argv, r.size); -- -- /* NULL terminate the list */ -- if (end_stringsbuf (&r) == -1) -- return NULL; -- -- return take_stringsbuf (&r); --} -- --/* Read whole file into dynamically allocated array. If there is an -- * error, DON'T call reply_with_perror, just return NULL. Returns a -- * \0-terminated string. -- */ --static char * --read_whole_file (const char *filename) --{ -- char *r = NULL; -- size_t alloc = 0, size = 0; -- int fd; -- -- fd = open (filename, O_RDONLY|O_CLOEXEC); -- if (fd == -1) { -- perror (filename); -- return NULL; -- } -- -- while (1) { -- alloc += 256; -- char *r2 = realloc (r, alloc); -- if (r2 == NULL) { -- perror ("realloc"); -- free (r); -- close (fd); -- return NULL; -- } -- r = r2; -- -- /* The '- 1' in the size calculation ensures there is space below -- * to add \0 to the end of the input. -- */ -- ssize_t n = read (fd, r + size, alloc - size - 1); -- if (n == -1) { -- fprintf (stderr, "read: %s: %m\n", filename); -- free (r); -- close (fd); -- return NULL; -- } -- if (n == 0) -- break; -- size += n; -- } -- -- if (close (fd) == -1) { -- fprintf (stderr, "close: %s: %m\n", filename); -- free (r); -- return NULL; -- } -- -- r[size] = '\0'; -- -- return r; --} -- --/* Takes optional arguments, consult optargs_bitmask. */ --int --do_mount_9p (const char *mount_tag, const char *mountpoint, const char *options) --{ -- CLEANUP_FREE char *mp = NULL, *opts = NULL, *err = NULL; -- struct stat statbuf; -- int r; -- -- ABS_PATH (mountpoint, 0, return -1); -- -- mp = sysroot_path (mountpoint); -- if (!mp) { -- reply_with_perror ("malloc"); -- return -1; -- } -- -- /* Check the mountpoint exists and is a directory. */ -- if (stat (mp, &statbuf) == -1) { -- reply_with_perror ("%s", mountpoint); -- return -1; -- } -- if (!S_ISDIR (statbuf.st_mode)) { -- reply_with_perror ("%s: mount point is not a directory", mountpoint); -- return -1; -- } -- -- /* Add trans=virtio to the options. */ -- if ((optargs_bitmask & GUESTFS_MOUNT_9P_OPTIONS_BITMASK) && -- STRNEQ (options, "")) { -- if (asprintf (&opts, "trans=virtio,%s", options) == -1) { -- reply_with_perror ("asprintf"); -- return -1; -- } -- } -- else { -- opts = strdup ("trans=virtio"); -- if (opts == NULL) { -- reply_with_perror ("strdup"); -- return -1; -- } -- } -- -- r = command (NULL, &err, -- "mount", "-o", opts, "-t", "9p", mount_tag, mp, NULL); -- if (r == -1) { -- reply_with_error ("%s on %s: %s", mount_tag, mountpoint, err); -- return -1; -- } -- -- return 0; --} -diff --git a/daemon/Makefile.am b/daemon/Makefile.am -index 5d1c222db..a9b40be25 100644 ---- a/daemon/Makefile.am -+++ b/daemon/Makefile.am -@@ -76,7 +76,6 @@ guestfsd_SOURCES = \ - ../common/protocol/guestfs_protocol.h \ - ../common/utils/cleanups.h \ - ../common/utils/guestfs-utils.h \ -- 9p.c \ - acl.c \ - actions.h \ - available.c \ -diff --git a/docs/C_SOURCE_FILES b/docs/C_SOURCE_FILES -index 7f1c60b30..f45e7124d 100644 ---- a/docs/C_SOURCE_FILES -+++ b/docs/C_SOURCE_FILES -@@ -71,7 +71,6 @@ common/windows/windows.h - customize/crypt-c.c - customize/dummy.c - customize/perl_edit-c.c --daemon/9p.c - daemon/acl.c - daemon/actions.h - daemon/augeas.c -diff --git a/generator/actions_core.ml b/generator/actions_core.ml -index deda483a9..f466600df 100644 ---- a/generator/actions_core.ml -+++ b/generator/actions_core.ml -@@ -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." }; - -- { defaults with -- name = "list_9p"; added = (1, 11, 12); -- style = RStringList (RPlainString, "mounttags"), [], []; -- shortdesc = "list 9p filesystems"; -- longdesc = "\ --List all 9p filesystems attached to the guest. A list of --mount tags is returned." }; -- -- { defaults with -- name = "mount_9p"; added = (1, 11, 12); -- style = RErr, [String (PlainString, "mounttag"); String (PlainString, "mountpoint")], [OString "options"]; -- camel_name = "Mount9P"; -- shortdesc = "mount 9p filesystem"; -- longdesc = "\ --Mount the virtio-9p filesystem with the tag C on the --directory C. -- --If required, C will be automatically added to the options. --Any other options required can be passed in the optional C --parameter." }; -- - { defaults with - 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 11a557076..1ef5ba0b7 100644 ---- a/generator/proc_nr.ml -+++ b/generator/proc_nr.ml -@@ -295,8 +295,6 @@ let proc_nr = [ - 282, "internal_autosync"; - 283, "is_zero"; - 284, "is_zero_device"; --285, "list_9p"; --286, "mount_9p"; - 287, "list_dm_devices"; - 288, "ntfsresize"; - 289, "btrfs_filesystem_resize"; -diff --git a/gobject/Makefile.inc b/gobject/Makefile.inc -index 067f861a9..7afe83c59 100644 ---- a/gobject/Makefile.inc -+++ b/gobject/Makefile.inc -@@ -93,7 +93,6 @@ guestfs_gobject_headers= \ - include/guestfs-gobject/optargs-mksquashfs.h \ - include/guestfs-gobject/optargs-mkswap.h \ - include/guestfs-gobject/optargs-mktemp.h \ -- include/guestfs-gobject/optargs-mount_9p.h \ - include/guestfs-gobject/optargs-mount_local.h \ - include/guestfs-gobject/optargs-ntfsclone_out.h \ - include/guestfs-gobject/optargs-ntfsfix.h \ -@@ -186,7 +185,6 @@ guestfs_gobject_sources= \ - src/optargs-mksquashfs.c \ - src/optargs-mkswap.c \ - src/optargs-mktemp.c \ -- src/optargs-mount_9p.c \ - src/optargs-mount_local.c \ - src/optargs-ntfsclone_out.c \ - src/optargs-ntfsfix.c \ -diff --git a/po/POTFILES b/po/POTFILES -index 79f4b8c56..b99333d0d 100644 ---- a/po/POTFILES -+++ b/po/POTFILES -@@ -58,7 +58,6 @@ customize/crypt-c.c - customize/dummy.c - customize/perl_edit-c.c - customize/test-password.pl --daemon/9p.c - daemon/acl.c - daemon/augeas.c - daemon/available.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 --gobject/src/optargs-mount_9p.c - gobject/src/optargs-mount_local.c - gobject/src/optargs-ntfsclone_out.c - gobject/src/optargs-ntfsfix.c --- -2.25.4 - diff --git a/SOURCES/0066-daemon-Add-filter_list-utility-function.patch b/SOURCES/0066-daemon-Add-filter_list-utility-function.patch new file mode 100644 index 0000000..11cdb18 --- /dev/null +++ b/SOURCES/0066-daemon-Add-filter_list-utility-function.patch @@ -0,0 +1,84 @@ +From 2e5a8775941b5767abcfcf93f9f84c9560e0f378 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.18.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 deleted file mode 100644 index 6037ba5..0000000 --- a/SOURCES/0067-RHEL-8-Disable-unsupported-remote-drive-protocols-RH.patch +++ /dev/null @@ -1,609 +0,0 @@ -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 - (RHBZ#962113). - -This disables support for unsupported remote drive protocols: - - * ftp - * ftps - * http - * https - * tftp - * gluster - * iscsi - * sheepdog - * ssh - -Note 'nbd' is not disabled, and of course 'file' works. - -We hope to gradually add some of these back over the lifetime of RHEL 8. ---- - docs/guestfs-testing.pod | 20 ----- - fish/guestfish.pod | 66 ++-------------- - fish/test-add-uri.sh | 32 -------- - generator/actions_core.ml | 50 +------------ - lib/drives.c | 8 ++ - lib/guestfs.pod | 100 ------------------------- - tests/disks/test-qemu-drive-libvirt.sh | 28 ------- - tests/disks/test-qemu-drive.sh | 60 --------------- - 8 files changed, 16 insertions(+), 348 deletions(-) - -diff --git a/docs/guestfs-testing.pod b/docs/guestfs-testing.pod -index f558964bf..8f264ed17 100644 ---- a/docs/guestfs-testing.pod -+++ b/docs/guestfs-testing.pod -@@ -109,26 +109,6 @@ image. To exit, type C. - If you get an error, try enabling debugging (add C<-v> to the command - line). Also make sure that L succeeds. - --=head2 Try to open a remote guest image with guestfish. -- --You may also have to disable libvirt by setting this: -- -- export LIBGUESTFS_BACKEND=direct -- --If you have a disk image available over HTTP/FTP, try to open it. -- -- guestfish --ro -i --format=raw -a http://www.example.com/disk.img -- --For SSH you will need to make sure that ssh-agent is set up so you --don't need a password to log in to the remote machine. Then a command --similar to this should work: -- -- guestfish --ro -i --format=raw \ -- -a ssh://remote.example.com/path/to/disk.img -- --If you get an error, try enabling debugging (add C<-v> to the command --line). Also make sure that L succeeds. -- - =head2 Run virt-alignment-scan on all your guests. - - Run L on guests or disk images: -diff --git a/fish/guestfish.pod b/fish/guestfish.pod -index f1fdf094d..bacb60e0b 100644 ---- a/fish/guestfish.pod -+++ b/fish/guestfish.pod -@@ -131,9 +131,9 @@ To list what is available do: - - =head2 Remote drives - --Access a remote disk using ssh: -+Access a remote disk using NBD: - -- guestfish -a ssh://example.com/path/to/disk.img -+ guestfish -a nbd://example.com - - =head2 Remote control - -@@ -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: - -- guestfish -a ssh://root@example.com/disk.img -+ guestfish -a nbd://example.com - - URIs I be used with the L command. The equivalent - command using the API directly is: - -- > add /disk.img protocol:ssh server:tcp:example.com username:root -+ > add /disk.img protocol:nbd server:tcp:example.com - - 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. - --=head2 B<-a ftp://[user@]example.com[:port]/disk.img> -- --=head2 B<-a ftps://[user@]example.com[:port]/disk.img> -- --=head2 B<-a http://[user@]example.com[:port]/disk.img> -- --=head2 B<-a https://[user@]example.com[:port]/disk.img> -- --=head2 B<-a tftp://[user@]example.com[:port]/disk.img> -- --Add a disk located on a remote FTP, HTTP or TFTP server. -- --The equivalent API command would be: -- -- > add /disk.img protocol:(ftp|...) server:tcp:example.com -- --=head2 B<-a gluster://example.com[:port]/volname/image> -- --Add a disk image located on GlusterFS storage. -- --The server is the one running C, and may be C. -- --The equivalent API command would be: -- -- > add volname/image protocol:gluster server:tcp:example.com -- --=head2 B<-a iscsi://example.com[:port]/target-iqn-name[/lun]> -- --Add a disk located on an iSCSI server. -- --The equivalent API command would be: -- -- > add target-iqn-name/lun protocol:iscsi server:tcp:example.com -- - =head2 B<-a nbd://example.com[:port]> - - =head2 B<-a nbd://example.com[:port]/exportname> -@@ -1228,35 +1194,13 @@ The equivalent API command would be: - - > add pool/disk protocol:rbd server:tcp:example.com:port - --=head2 B<-a sheepdog://[example.com[:port]]/volume/image> -- --Add a disk image located on a Sheepdog volume. -- --The server name is optional. Although libguestfs and Sheepdog --supports multiple servers, only at most one server can be specified --when using this URI syntax. -- --The equivalent API command would be: -- -- > add volume protocol:sheepdog [server:tcp:example.com] -- --=head2 B<-a ssh://[user@]example.com[:port]/disk.img> -- --Add a disk image located on a remote server, accessed using the Secure --Shell (ssh) SFTP protocol. SFTP is supported out of the box by all --major SSH servers. -- --The equivalent API command would be: -- -- > add /disk protocol:ssh server:tcp:example.com [username:user] -- - Note that the URIs follow the syntax of - L: in particular, there - are restrictions on the allowed characters for the various components - of the URI. Characters such as C<:>, C<@>, and C B be - percent-encoded: - -- $ guestfish -a ssh://user:pass%40word@example.com/disk.img -+ $ guestfish -a rbd://user:pass%40word@example.com[:port]/pool/disk - - In this case, the password is C. - -diff --git a/fish/test-add-uri.sh b/fish/test-add-uri.sh -index 756df997b..8f84fd31b 100755 ---- a/fish/test-add-uri.sh -+++ b/fish/test-add-uri.sh -@@ -40,14 +40,6 @@ function fail () - $VG guestfish -x -a file://$abs_builddir/test-add-uri.img test-add-uri.out 2>&1 - grep -sq 'add_drive ".*/test-add-uri.img"' test-add-uri.out || fail - --# curl --$VG guestfish -x -a ftp://user@example.com/disk.img test-add-uri.out 2>&1 --grep -sq 'add_drive "/disk.img" "protocol:ftp" "server:tcp:example.com" "username:user"' test-add-uri.out || fail -- --# gluster --$VG guestfish -x -a gluster://example.com/disk test-add-uri.out 2>&1 --grep -sq 'add_drive "disk" "protocol:gluster" "server:tcp:example.com"' test-add-uri.out || fail -- - # NBD - $VG guestfish -x -a nbd://example.com test-add-uri.out 2>&1 - grep -sq 'add_drive "" "protocol:nbd" "server:tcp:example.com"' test-add-uri.out || fail -@@ -67,29 +59,5 @@ grep -sq 'add_drive "pool/disk" "protocol:rbd" "server:tcp:example.com:6789"' te - $VG guestfish -x -a rbd:///pool/disk test-add-uri.out 2>&1 - grep -sq 'add_drive "pool/disk" "protocol:rbd"' test-add-uri.out || fail - --# sheepdog --$VG guestfish -x -a sheepdog:///volume/image test-add-uri.out 2>&1 --grep -sq 'add_drive "volume/image" "protocol:sheepdog"' test-add-uri.out || fail -- --$VG guestfish -x -a sheepdog://example.com:3000/volume/image test-add-uri.out 2>&1 --grep -sq 'add_drive "volume/image" "protocol:sheepdog" "server:tcp:example.com:3000"' test-add-uri.out || fail -- --# ssh --$VG guestfish -x -a ssh://example.com/disk.img test-add-uri.out 2>&1 --grep -sq 'add_drive "/disk.img" "protocol:ssh" "server:tcp:example.com"' test-add-uri.out || fail -- --$VG guestfish -x -a ssh://user@example.com/disk.img test-add-uri.out 2>&1 --grep -sq 'add_drive "/disk.img" "protocol:ssh" "server:tcp:example.com" "username:user"' test-add-uri.out || fail -- --$VG guestfish -x -a ssh://user@example.com:2000/disk.img test-add-uri.out 2>&1 --grep -sq 'add_drive "/disk.img" "protocol:ssh" "server:tcp:example.com:2000" "username:user"' test-add-uri.out || fail -- --# iSCSI --$VG guestfish -x -a iscsi://example.com/iqn.2015-12.com.libguestfs:test1/0 test-add-uri.out 2>&1 --grep -sq 'add_drive "iqn.2015-12.com.libguestfs:test1/0" "protocol:iscsi" "server:tcp:example.com"' test-add-uri.out || fail -- --$VG guestfish -x -a iscsi://user:password@example.com/iqn.2015-12.com.libguestfs:test2/0 test-add-uri.out 2>&1 --grep -sq 'add_drive "iqn.2015-12.com.libguestfs:test2/0" "protocol:iscsi" "server:tcp:example.com" "username:user" "secret:password"' test-add-uri.out || fail -- - rm test-add-uri.out - rm test-add-uri.img -diff --git a/generator/actions_core.ml b/generator/actions_core.ml -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. - This is the default if the optional protocol parameter - is omitted. - --=item C -- --Connect to a remote FTP, HTTP or TFTP server. --The C parameter must also be supplied - see below. -- --See also: L -- --=item C -- --Connect to the GlusterFS server. --The C parameter must also be supplied - see below. -- --See also: L -- --=item C -- --Connect to the iSCSI server. --The C parameter must also be supplied - see below. --The C parameter may be supplied. See below. --The C parameter may be supplied. See below. -- --See also: L. -- - =item C - - Connect to the Network Block Device server. -@@ -336,22 +313,6 @@ The C parameter may be supplied. See below. - - See also: L. - --=item C -- --Connect to the Sheepdog server. --The C parameter may also be supplied - see below. -- --See also: L. -- --=item C -- --Connect to the Secure Shell (ssh) server. -- --The C parameter must be supplied. --The C parameter may be supplied. See below. -- --See also: L. -- - =back - - =item C -@@ -362,13 +323,8 @@ is a list of server(s). - Protocol Number of servers required - -------- -------------------------- - file List must be empty or param not used at all -- ftp|ftps|http|https|tftp Exactly one -- gluster Exactly one -- iscsi Exactly one - nbd Exactly one - rbd Zero or more -- sheepdog Zero or more -- ssh Exactly one - - Each list element is a string specifying a server. The string must be - in one of the following formats: -@@ -384,10 +340,10 @@ for the protocol is used (see F). - - =item C - --For the C, C, C, C, C, C, C --and C protocols, this specifies the remote username. -+For the C -+protocol, this specifies the remote username. - --If not given, then the local username is used for C, and no authentication -+If not given, then no authentication - is attempted for ceph. But note this sometimes may give unexpected results, for - example if using the libvirt backend and if the libvirt backend is configured to - start the qemu appliance as a special user such as C. If in doubt, -diff --git a/lib/drives.c b/lib/drives.c -index 82ef30093..3d712c6e4 100644 ---- a/lib/drives.c -+++ b/lib/drives.c -@@ -165,6 +165,7 @@ create_drive_non_file (guestfs_h *g, - return drv; - } - -+#if 0 /* DISABLED IN RHEL 8 */ - static struct drive * - create_drive_curl (guestfs_h *g, - const struct drive_create_data *data) -@@ -223,6 +224,7 @@ create_drive_gluster (guestfs_h *g, - - return create_drive_non_file (g, data); - } -+#endif /* DISABLED IN RHEL 8 */ - - static int - nbd_port (void) -@@ -291,6 +293,7 @@ create_drive_rbd (guestfs_h *g, - return create_drive_non_file (g, data); - } - -+#if 0 /* DISABLED IN RHEL 8 */ - static struct drive * - create_drive_sheepdog (guestfs_h *g, - const struct drive_create_data *data) -@@ -391,6 +394,7 @@ create_drive_iscsi (guestfs_h *g, - - return create_drive_non_file (g, data); - } -+#endif /* DISABLED IN RHEL 8 */ - - /** - * Create the special F drive. -@@ -826,6 +830,7 @@ guestfs_impl_add_drive_opts (guestfs_h *g, const char *filename, - drv = create_drive_file (g, &data); - } - } -+#if 0 /* DISABLED IN RHEL 8 */ - else if (STREQ (protocol, "ftp")) { - data.protocol = drive_protocol_ftp; - drv = create_drive_curl (g, &data); -@@ -850,6 +855,7 @@ guestfs_impl_add_drive_opts (guestfs_h *g, const char *filename, - data.protocol = drive_protocol_iscsi; - drv = create_drive_iscsi (g, &data); - } -+#endif /* DISABLED IN RHEL 8 */ - else if (STREQ (protocol, "nbd")) { - data.protocol = drive_protocol_nbd; - drv = create_drive_nbd (g, &data); -@@ -858,6 +864,7 @@ guestfs_impl_add_drive_opts (guestfs_h *g, const char *filename, - data.protocol = drive_protocol_rbd; - drv = create_drive_rbd (g, &data); - } -+#if 0 /* DISABLED IN RHEL 8 */ - else if (STREQ (protocol, "sheepdog")) { - data.protocol = drive_protocol_sheepdog; - drv = create_drive_sheepdog (g, &data); -@@ -870,6 +877,7 @@ guestfs_impl_add_drive_opts (guestfs_h *g, const char *filename, - data.protocol = drive_protocol_tftp; - drv = create_drive_curl (g, &data); - } -+#endif /* DISABLED IN RHEL 8 */ - else { - error (g, _("unknown protocol ‘%s’"), protocol); - drv = NULL; /*FALLTHROUGH*/ -diff --git a/lib/guestfs.pod b/lib/guestfs.pod -index af944ddb7..58559a6b4 100644 ---- a/lib/guestfs.pod -+++ b/lib/guestfs.pod -@@ -714,70 +714,6 @@ servers. The server string is documented in - L. The C and C parameters are - also optional, and if not given, then no authentication will be used. - --=head3 FTP, HTTP AND TFTP -- --Libguestfs can access remote disks over FTP, FTPS, HTTP, HTTPS --or TFTP protocols. -- --To do this, set the optional C and C parameters of --L like this: -- -- char **servers = { "www.example.org", NULL }; -- guestfs_add_drive_opts (g, "/disk.img", -- GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw", -- GUESTFS_ADD_DRIVE_OPTS_PROTOCOL, "http", -- GUESTFS_ADD_DRIVE_OPTS_SERVER, servers, -- -1); -- --The C can be one of C<"ftp">, C<"ftps">, C<"http">, --C<"https"> or C<"tftp">. -- --C (the C parameter) is a list which must have a --single element. The single element is a string defining the web, --FTP or TFTP server. The format of this string is documented in --L. -- --=head3 GLUSTER -- --Libguestfs can access Gluster disks. -- --To do this, set the optional C and C parameters of --L like this: -- -- char **servers = { "gluster.example.org:24007", NULL }; -- guestfs_add_drive_opts (g, "volname/image", -- GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw", -- GUESTFS_ADD_DRIVE_OPTS_PROTOCOL, "gluster", -- GUESTFS_ADD_DRIVE_OPTS_SERVER, servers, -- -1); -- --C (the C parameter) is a list which must have a --single element. The single element is a string defining the Gluster --server. The format of this string is documented in --L. -- --Note that gluster usually requires the client process (ie. libguestfs) --to run as B and will give unfathomable errors if it is not --(eg. "No data available"). -- --=head3 ISCSI -- --Libguestfs can access iSCSI disks remotely. -- --To do this, set the optional C and C parameters like --this: -- -- char **server = { "iscsi.example.org:3000", NULL }; -- guestfs_add_drive_opts (g, "target-iqn-name/lun", -- GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw", -- GUESTFS_ADD_DRIVE_OPTS_PROTOCOL, "iscsi", -- GUESTFS_ADD_DRIVE_OPTS_SERVER, server, -- -1); -- --The C parameter is a list which must have a single element. --The single element is a string defining the iSCSI server. The format --of this string is documented in L. -- - =head3 NETWORK BLOCK DEVICE - - Libguestfs can access Network Block Device (NBD) disks remotely. -@@ -840,42 +776,6 @@ L - - =back - --=head3 SHEEPDOG -- --Libguestfs can access Sheepdog disks. -- --To do this, set the optional C and C parameters of --L like this: -- -- char **servers = { /* optional servers ... */ NULL }; -- guestfs_add_drive_opts (g, "volume", -- GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw", -- GUESTFS_ADD_DRIVE_OPTS_PROTOCOL, "sheepdog", -- GUESTFS_ADD_DRIVE_OPTS_SERVER, servers, -- -1); -- --The optional list of C may be zero or more server addresses --(C<"hostname:port">). The format of the server strings is documented --in L. -- --=head3 SSH -- --Libguestfs can access disks over a Secure Shell (SSH) connection. -- --To do this, set the C and C and (optionally) --C parameters of L like this: -- -- char **server = { "remote.example.com", NULL }; -- guestfs_add_drive_opts (g, "/path/to/disk.img", -- GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw", -- GUESTFS_ADD_DRIVE_OPTS_PROTOCOL, "ssh", -- GUESTFS_ADD_DRIVE_OPTS_SERVER, server, -- GUESTFS_ADD_DRIVE_OPTS_USERNAME, "remoteuser", -- -1); -- --The format of the server string is documented in --L. -- - =head2 INSPECTION - - 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 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 - grep -sq -- '-drive file=rbd:abc-def/ghi-jkl:auth_supported=none,' "$DEBUG_QEMU_FILE" || fail ceph2 - rm "$DEBUG_QEMU_FILE" - --# Gluster. -- --$guestfish -d gluster run ||: --check_output --grep -sq -- '-drive file=gluster://1.2.3.4:1234/volname/image,' "$DEBUG_QEMU_FILE" || fail gluster --rm "$DEBUG_QEMU_FILE" -- --# iSCSI. -- --$guestfish -d iscsi run ||: --check_output --grep -sq -- '-drive file=iscsi://1.2.3.4:1234/iqn.2003-01.org.linux-iscsi.fedora' "$DEBUG_QEMU_FILE" || fail iscsi --rm "$DEBUG_QEMU_FILE" -- --# NBD. -- --$guestfish -d nbd run ||: --check_output --grep -sq -- '-drive file=nbd:1.2.3.4:1234,' "$DEBUG_QEMU_FILE" || fail nbd --rm "$DEBUG_QEMU_FILE" -- --# Sheepdog. -- --$guestfish -d sheepdog run ||: --check_output --grep -sq -- '-drive file=sheepdog:volume,' "$DEBUG_QEMU_FILE" || fail sheepdog --rm "$DEBUG_QEMU_FILE" -- - # Local, stored in a pool. - - $guestfish -d pool1 run ||: -diff --git a/tests/disks/test-qemu-drive.sh b/tests/disks/test-qemu-drive.sh -index 19dd60a2f..583e031bd 100755 ---- a/tests/disks/test-qemu-drive.sh -+++ b/tests/disks/test-qemu-drive.sh -@@ -62,45 +62,6 @@ check_output - grep -sq -- '-drive file=rbd:abc-def/ghi-jkl:auth_supported=none,' "$DEBUG_QEMU_FILE" || fail - rm "$DEBUG_QEMU_FILE" - --# HTTP. -- --guestfish < +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.18.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 deleted file mode 100644 index 28fbee6..0000000 --- a/SOURCES/0068-RHEL-8-Remove-User-Mode-Linux-RHBZ-1144197.patch +++ /dev/null @@ -1,72 +0,0 @@ -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). - -This isn't supported in RHEL 8. ---- - lib/launch-uml.c | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - -diff --git a/lib/launch-uml.c b/lib/launch-uml.c -index da20c17d9..a5e0e8179 100644 ---- a/lib/launch-uml.c -+++ b/lib/launch-uml.c -@@ -44,7 +44,9 @@ struct backend_uml_data { - char umid[UML_UMID_LEN+1]; /* umid=<...> unique ID. */ - }; - -+#if 0 - static void print_vmlinux_command_line (guestfs_h *g, char **argv); -+#endif - - /* Run uml_mkcow to create a COW overlay. */ - static char * -@@ -81,6 +83,7 @@ create_cow_overlay_uml (guestfs_h *g, void *datav, struct drive *drv) - return make_cow_overlay (g, drv->src.u.path); - } - -+#if 0 - /* Test for features which are not supported by the UML backend. - * Possibly some of these should just be warnings, not errors. - */ -@@ -128,10 +131,17 @@ uml_supported (guestfs_h *g) - - return true; - } -+#endif - - static int - launch_uml (guestfs_h *g, void *datav, const char *arg) - { -+ error (g, -+ "launch: In RHEL, only the 'libvirt' or 'direct' method is supported.\n" -+ "In particular, User-Mode Linux (UML) is not supported."); -+ return -1; -+ -+#if 0 - struct backend_uml_data *data = datav; - CLEANUP_FREE_STRINGSBUF DECLARE_STRINGSBUF (cmdline); - int console_sock = -1, daemon_sock = -1; -@@ -491,8 +501,10 @@ launch_uml (guestfs_h *g, void *datav, const char *arg) - } - g->state = CONFIG; - return -1; -+#endif - } - -+#if 0 - /* This is called from the forked subprocess just before vmlinux runs, - * so it can just print the message straight to stderr, where it will - * be picked up and funnelled through the usual appliance event API. -@@ -522,6 +534,7 @@ print_vmlinux_command_line (guestfs_h *g, char **argv) - - fputc ('\n', stderr); - } -+#endif - - static int - shutdown_uml (guestfs_h *g, void *datav, int check_for_errors) --- -2.25.4 - diff --git a/SOURCES/0068-mltools-add-run_in_guest_command-helper.patch b/SOURCES/0068-mltools-add-run_in_guest_command-helper.patch new file mode 100644 index 0000000..655db0b --- /dev/null +++ b/SOURCES/0068-mltools-add-run_in_guest_command-helper.patch @@ -0,0 +1,95 @@ +From 9a8246e91ac0fa38d96691dc6025cb8b117f9cb2 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.18.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 deleted file mode 100644 index 567b1cc..0000000 --- a/SOURCES/0069-RHEL-8-v2v-Select-correct-qemu-binary-for-o-qemu-mod.patch +++ /dev/null @@ -1,33 +0,0 @@ -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 - (RHBZ#1147313). - -RHEL 8 does not have qemu-system-x86_64 (etc), and in addition the -qemu binary is located in /usr/libexec. Encode the path to this -binary directly in the script. - -Note that we don't support people running qemu directly like this. -It's just for quick testing of converted VMs, and to help us with -support cases. ---- - v2v/output_qemu.ml | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/v2v/output_qemu.ml b/v2v/output_qemu.ml -index 1f6798aaf..8665d7b5c 100644 ---- a/v2v/output_qemu.ml -+++ b/v2v/output_qemu.ml -@@ -81,7 +81,7 @@ object - * module deals with shell and qemu comma quoting. - *) - let cmd = Qemuopts.create () in -- Qemuopts.set_binary_by_arch cmd (Some guestcaps.gcaps_arch); -+ Qemuopts.set_binary cmd "/usr/libexec/qemu-kvm"; - - let flag = Qemuopts.flag cmd - and arg = Qemuopts.arg cmd --- -2.25.4 - diff --git a/SOURCES/0069-customize-port-do_run-to-run_in_guest_command.patch b/SOURCES/0069-customize-port-do_run-to-run_in_guest_command.patch new file mode 100644 index 0000000..1ec70cc --- /dev/null +++ b/SOURCES/0069-customize-port-do_run-to-run_in_guest_command.patch @@ -0,0 +1,82 @@ +From 02f8969558ecadc13726068ccb732595c5d29565 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 | 46 +++++--------------------------------- + 1 file changed, 6 insertions(+), 40 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; ++ Guestfs_config.host_cpu guest_arch ++ in + +- (* 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) ++ try ++ run_in_guest_command g root ~logfile ~incompatible_fn cmd + with + G.Error msg -> + debug_logfile (); +-- +2.18.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 deleted file mode 100644 index 038b7f2..0000000 --- a/SOURCES/0070-RHEL-8-v2v-Disable-the-qemu-boot-option-RHBZ-1147313.patch +++ /dev/null @@ -1,105 +0,0 @@ -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). - -This cannot work because there is no Gtk or SDL output mode -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-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 686631271..e3578ddcb 100644 ---- a/v2v/cmdline.ml -+++ b/v2v/cmdline.ml -@@ -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"), -@@ -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 -+ if qemu_boot then -+ error (f_"-o qemu: the --qemu-boot option cannot be used in RHEL"); - 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 25041d0ec..bd606592b 100644 ---- a/v2v/virt-v2v.pod -+++ b/v2v/virt-v2v.pod -@@ -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. - --To convert a local disk image and immediately boot it in local --qemu, do: -- -- virt-v2v -i disk disk.img -o qemu -os /var/tmp --qemu-boot -- - =head1 OPTIONS - - =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>. - --When using this output mode, you can also specify the I<--qemu-boot> --option which boots the guest under qemu immediately. -- - =item B<-o> B - - This is the same as I<-o rhv>. -@@ -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. - --=item B<--qemu-boot> -- --When using I<-o qemu> only, this boots the guest immediately after --virt-v2v finishes. -- - =item B<-q> - - =item B<--quiet> --- -2.25.4 - diff --git a/SOURCES/0070-sysprep-add-a-update_system_ca_store-side-effect.patch b/SOURCES/0070-sysprep-add-a-update_system_ca_store-side-effect.patch new file mode 100644 index 0000000..e8ad4ff --- /dev/null +++ b/SOURCES/0070-sysprep-add-a-update_system_ca_store-side-effect.patch @@ -0,0 +1,138 @@ +From f4613f408e4584741d08aa39c950de304f5e18db 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.18.4 + diff --git a/SOURCES/0071-RHEL-8-Disable-alternate-Augeas-lenses.patch b/SOURCES/0071-RHEL-8-Disable-alternate-Augeas-lenses.patch deleted file mode 100644 index caafc5b..0000000 --- a/SOURCES/0071-RHEL-8-Disable-alternate-Augeas-lenses.patch +++ /dev/null @@ -1,60 +0,0 @@ -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. - -These are included in the RHEL augeas package, and therefore not -required. - -See: -https://www.redhat.com/archives/libguestfs/2014-October/msg00220.html ---- - appliance/Makefile.am | 1 - - daemon/augeas.c | 5 ++++- - 2 files changed, 4 insertions(+), 2 deletions(-) - -diff --git a/appliance/Makefile.am b/appliance/Makefile.am -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 - rm -rf tmp-d - mkdir -p tmp-d$(DAEMON_SUPERMIN_DIR) tmp-d/etc tmp-d/usr/share/guestfs - ln ../daemon/guestfsd tmp-d$(DAEMON_SUPERMIN_DIR)/guestfsd -- ln $(srcdir)/guestfs_shadow.aug tmp-d/usr/share/guestfs/guestfs_shadow.aug - ( cd tmp-d && tar zcf - * ) > $@-t - rm -r tmp-d - mv $@-t $@ -diff --git a/daemon/augeas.c b/daemon/augeas.c -index 453251337..5bbfffa2d 100644 ---- a/daemon/augeas.c -+++ b/daemon/augeas.c -@@ -134,7 +134,7 @@ do_aug_init (const char *root, int flags) - } - - /* Pass AUG_NO_ERR_CLOSE so we can display detailed errors. */ -- aug = aug_init (buf, "/usr/share/guestfs/", flags | AUG_NO_ERR_CLOSE); -+ aug = aug_init (buf, NULL, flags | AUG_NO_ERR_CLOSE); - - if (!aug) { - reply_with_error ("augeas initialization failed"); -@@ -148,6 +148,8 @@ do_aug_init (const char *root, int flags) - return -1; - } - -+ /* We already have the needed lenses in RHEL 8 */ -+#if 0 - if (!augeas_is_version (1, 2, 1)) { - int r = aug_transform (aug, "guestfs_shadow", "/etc/shadow", - 0 /* = included */); -@@ -166,6 +168,7 @@ do_aug_init (const char *root, int flags) - } - } - } -+#endif - - return 0; - } --- -2.25.4 - diff --git a/SOURCES/0071-sysprep-ca-certificates-request-system-CA-store-upda.patch b/SOURCES/0071-sysprep-ca-certificates-request-system-CA-store-upda.patch new file mode 100644 index 0000000..128bd01 --- /dev/null +++ b/SOURCES/0071-sysprep-ca-certificates-request-system-CA-store-upda.patch @@ -0,0 +1,42 @@ +From 315bf96d182d5626e5935aaf57b0787fedffc62b 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.18.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 deleted file mode 100644 index d1094d3..0000000 --- a/SOURCES/0072-RHEL-8-Fix-list-of-supported-sound-cards-to-match-RH.patch +++ /dev/null @@ -1,34 +0,0 @@ -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 - (RHBZ#1176493). - ---- - v2v/utils.ml | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/v2v/utils.ml b/v2v/utils.ml -index 74b501f81..21e9c9c15 100644 ---- a/v2v/utils.ml -+++ b/v2v/utils.ml -@@ -51,13 +51,14 @@ let kvm_arch = function - (* Does qemu support the given sound card? *) - let qemu_supports_sound_card = function - | Types.AC97 -- | Types.ES1370 - | Types.ICH6 - | Types.ICH9 - | Types.PCSpeaker -+ -> true -+ | Types.ES1370 - | Types.SB16 - | Types.USBAudio -- -> true -+ -> false - - (* Find the UEFI firmware. *) - let find_uefi_firmware guest_arch = --- -2.25.4 - diff --git a/SOURCES/0072-sysprep-add-IPA-offline-unenrollment-RHBZ-1789592.patch b/SOURCES/0072-sysprep-add-IPA-offline-unenrollment-RHBZ-1789592.patch new file mode 100644 index 0000000..13105f7 --- /dev/null +++ b/SOURCES/0072-sysprep-add-IPA-offline-unenrollment-RHBZ-1789592.patch @@ -0,0 +1,107 @@ +From 90bb3cd1793275da50d509570d07d279989e2c45 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.18.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 deleted file mode 100644 index 6105bed..0000000 --- a/SOURCES/0073-RHEL-8-Reject-use-of-libguestfs-winsupport-features-.patch +++ /dev/null @@ -1,40 +0,0 @@ -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 - for virt-* tools (RHBZ#1240276). - ---- - generator/c.ml | 16 ++++++++++++++++ - 1 file changed, 16 insertions(+) - -diff --git a/generator/c.ml b/generator/c.ml -index 86f7d89a3..b5bb99f53 100644 ---- a/generator/c.ml -+++ b/generator/c.ml -@@ -1832,6 +1832,22 @@ and generate_client_actions actions () = - check_args_validity c_name style; - trace_call name c_name style; - -+ (* RHEL 8 *) -+ if name = "mount" || name = "mount_ro" || name = "mount_options" || -+ name = "mount_vfs" then ( -+ pr " if (g->program && !STRPREFIX (g->program, \"virt-\")) {\n"; -+ pr " CLEANUP_FREE char *vfs_type = guestfs_vfs_type (g, mountable);\n"; -+ pr " if (vfs_type && STREQ (vfs_type, \"ntfs\")) {\n"; -+ pr " error (g, \"mount: unsupported filesystem type\");\n"; -+ pr " if (trace_flag)\n"; -+ pr " guestfs_int_trace (g, \"%%s = %%s (error)\",\n"; -+ pr " \"%s\", \"-1\");\n" name; -+ pr " return %s;\n" (string_of_errcode errcode); -+ pr " }\n"; -+ pr " }\n"; -+ pr "\n"; -+ ); -+ - (* Calculate the total size of all FileIn arguments to pass - * as a progress bar hint. - *) --- -2.25.4 - diff --git a/SOURCES/0073-sysprep-add-Kerberos-keytab-file-removal.patch b/SOURCES/0073-sysprep-add-Kerberos-keytab-file-removal.patch new file mode 100644 index 0000000..844fef8 --- /dev/null +++ b/SOURCES/0073-sysprep-add-Kerberos-keytab-file-removal.patch @@ -0,0 +1,81 @@ +From c8dc0b229b3cbcb72ca90ddf025087586a7d2e38 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.18.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 deleted file mode 100644 index 0b21bba..0000000 --- a/SOURCES/0074-RHEL-8-Fix-tests-for-libguestfs-winsupport.patch +++ /dev/null @@ -1,93 +0,0 @@ -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. - -It doesn't let us use guestfish for arbitrary Windows edits. ---- - test-data/phony-guests/make-windows-img.sh | 1 + - tests/charsets/test-charset-fidelity.c | 2 ++ - v2v/test-v2v-virtio-win-iso.sh | 8 +++++++- - v2v/test-v2v-windows-conversion.sh | 8 +++++++- - 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 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 - - # Create a disk image. - guestfish < "$script" - :> "$expected" - -+cat >> "$script" < "$response" -+guestfish --ro -a "$d/windows-sda" < "$script" > "$response" - diff -u "$expected" "$response" - - rm -r $d -diff --git a/v2v/test-v2v-windows-conversion.sh b/v2v/test-v2v-windows-conversion.sh -index f1da222a9..ff94fe39b 100755 ---- a/v2v/test-v2v-windows-conversion.sh -+++ b/v2v/test-v2v-windows-conversion.sh -@@ -73,6 +73,12 @@ mktest () - :> "$script" - :> "$expected" - -+cat >> "$script" < "$response" -+guestfish --ro -a "$d/windows-sda" < "$script" > "$response" - diff -u "$expected" "$response" - - # We also update the Registry several times, for firstboot, and (ONLY --- -2.25.4 - diff --git a/SOURCES/0074-vCenter-fix-parsing-of-HTTP-status-string-RHBZ-18373.patch b/SOURCES/0074-vCenter-fix-parsing-of-HTTP-status-string-RHBZ-18373.patch new file mode 100644 index 0000000..3387816 --- /dev/null +++ b/SOURCES/0074-vCenter-fix-parsing-of-HTTP-status-string-RHBZ-18373.patch @@ -0,0 +1,35 @@ +From 318aa975b212c9b8778606ce440c95682f99c700 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Tue, 19 May 2020 12:14:18 +0200 +Subject: [PATCH] vCenter: fix parsing of HTTP status string (RHBZ#1837328) + +vCenter 7 answers with an HTTP/2 status string, so we cannot extract +the status code from it by using fixed positions in that string. +Hence, pick the status code by reading what's after the whitespace. + +Tested with vCenter 6.5 and 7. + +(cherry picked from commit d2aa82317964d62fcc8dc7b6737773003d04b998 +in virt-v2v) +--- + v2v/vCenter.ml | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/v2v/vCenter.ml b/v2v/vCenter.ml +index b1b9f9b15..b15e2f7d0 100644 +--- a/v2v/vCenter.ml ++++ b/v2v/vCenter.ml +@@ -213,7 +213,9 @@ and fetch_headers_from_url password_file uri sslverify https_url = + | [] -> + dump_response stderr; + error (f_"vcenter: no status code in output of ‘curl’ command. Is ‘curl’ installed?") +- | ss -> String.sub (List.hd (List.rev ss)) 9 3 in ++ | ss -> ++ let s = List.hd (List.rev ss) in ++ String.sub s (String.index s ' ' + 1) 3 in + + let headers = + List.map ( +-- +2.18.4 + diff --git a/SOURCES/0075-RHEL-8-Remove-libguestfs-live-RHBZ-798980.patch b/SOURCES/0075-RHEL-8-Remove-libguestfs-live-RHBZ-798980.patch new file mode 100644 index 0000000..707bf1c --- /dev/null +++ b/SOURCES/0075-RHEL-8-Remove-libguestfs-live-RHBZ-798980.patch @@ -0,0 +1,38 @@ +From a7fefab912d97962fb77f0f57799b7b70634376c 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). + +This isn't supported in RHEL 8. +--- + lib/launch-unix.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/lib/launch-unix.c b/lib/launch-unix.c +index 4794a7b13..993b83601 100644 +--- a/lib/launch-unix.c ++++ b/lib/launch-unix.c +@@ -37,6 +37,12 @@ + static int + launch_unix (guestfs_h *g, void *datav, const char *sockpath) + { ++ error (g, ++ "launch: In RHEL, only the 'libvirt' or 'direct' method is supported.\n" ++ "In particular, \"libguestfs live\" is not supported."); ++ return -1; ++ ++#if 0 + int r, daemon_sock = -1; + struct sockaddr_un addr; + uint32_t size; +@@ -106,6 +112,7 @@ launch_unix (guestfs_h *g, void *datav, const char *sockpath) + g->conn = NULL; + } + return -1; ++#endif + } + + static int +-- +2.18.4 + 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 deleted file mode 100644 index 71a4655..0000000 --- a/SOURCES/0075-RHEL-8-tests-Disable-daemon-tests-that-require-the-u.patch +++ /dev/null @@ -1,28 +0,0 @@ -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-Remove-9p-APIs-from-RHEL-RHBZ-921710.patch b/SOURCES/0076-RHEL-8-Remove-9p-APIs-from-RHEL-RHBZ-921710.patch new file mode 100644 index 0000000..c854812 --- /dev/null +++ b/SOURCES/0076-RHEL-8-Remove-9p-APIs-from-RHEL-RHBZ-921710.patch @@ -0,0 +1,372 @@ +From 683153015b95a7b6d4979d48736c80e366986c72 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). + +--- + Makefile.am | 2 +- + daemon/9p.c | 224 -------------------------------------- + daemon/Makefile.am | 1 - + docs/C_SOURCE_FILES | 1 - + generator/actions_core.ml | 21 ---- + generator/proc_nr.ml | 2 - + gobject/Makefile.inc | 2 - + po/POTFILES | 2 - + 8 files changed, 1 insertion(+), 254 deletions(-) + delete mode 100644 daemon/9p.c + +diff --git a/Makefile.am b/Makefile.am +index 0067d7b7b..e9351eadc 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -78,7 +78,7 @@ SUBDIRS += tests/xfs + SUBDIRS += tests/charsets + SUBDIRS += tests/xml + SUBDIRS += tests/mount-local +-SUBDIRS += tests/9p ++#SUBDIRS += tests/9p + SUBDIRS += tests/rsync + SUBDIRS += tests/bigdirs + SUBDIRS += tests/disk-labels +diff --git a/daemon/9p.c b/daemon/9p.c +deleted file mode 100644 +index 55644249d..000000000 +--- a/daemon/9p.c ++++ /dev/null +@@ -1,224 +0,0 @@ +-/* libguestfs - the guestfsd daemon +- * Copyright (C) 2011 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. +- */ +- +-#include +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include "daemon.h" +-#include "actions.h" +- +-#define BUS_PATH "/sys/bus/virtio/drivers/9pnet_virtio" +- +-static char *read_whole_file (const char *filename); +- +-/* https://bugzilla.redhat.com/show_bug.cgi?id=714981#c1 */ +-char ** +-do_list_9p (void) +-{ +- CLEANUP_FREE_STRINGSBUF DECLARE_STRINGSBUF (r); +- +- DIR *dir; +- +- dir = opendir (BUS_PATH); +- if (!dir) { +- perror ("opendir: " BUS_PATH); +- if (errno != ENOENT) { +- reply_with_perror ("opendir: " BUS_PATH); +- return NULL; +- } +- +- /* If this directory doesn't exist, it probably means that +- * the virtio driver isn't loaded. Don't return an error +- * in this case, but return an empty list. +- */ +- if (end_stringsbuf (&r) == -1) +- return NULL; +- +- return take_stringsbuf (&r); +- } +- +- while (1) { +- struct dirent *d; +- +- errno = 0; +- d = readdir (dir); +- if (d == NULL) break; +- +- if (STRPREFIX (d->d_name, "virtio")) { +- CLEANUP_FREE char *mount_tag_path = NULL; +- if (asprintf (&mount_tag_path, BUS_PATH "/%s/mount_tag", +- d->d_name) == -1) { +- reply_with_perror ("asprintf"); +- closedir (dir); +- return NULL; +- } +- +- /* A bit unclear, but it looks like the virtio transport allows +- * the mount tag length to be unlimited (or up to 65536 bytes). +- * See: linux/include/linux/virtio_9p.h +- */ +- CLEANUP_FREE char *mount_tag = read_whole_file (mount_tag_path); +- if (mount_tag == 0) +- continue; +- +- if (add_string (&r, mount_tag) == -1) { +- closedir (dir); +- return NULL; +- } +- } +- } +- +- /* Check readdir didn't fail */ +- if (errno != 0) { +- reply_with_perror ("readdir: /sys/block"); +- closedir (dir); +- return NULL; +- } +- +- /* Close the directory handle */ +- if (closedir (dir) == -1) { +- reply_with_perror ("closedir: /sys/block"); +- return NULL; +- } +- +- /* Sort the tags. */ +- if (r.size > 0) +- sort_strings (r.argv, r.size); +- +- /* NULL terminate the list */ +- if (end_stringsbuf (&r) == -1) +- return NULL; +- +- return take_stringsbuf (&r); +-} +- +-/* Read whole file into dynamically allocated array. If there is an +- * error, DON'T call reply_with_perror, just return NULL. Returns a +- * \0-terminated string. +- */ +-static char * +-read_whole_file (const char *filename) +-{ +- char *r = NULL; +- size_t alloc = 0, size = 0; +- int fd; +- +- fd = open (filename, O_RDONLY|O_CLOEXEC); +- if (fd == -1) { +- perror (filename); +- return NULL; +- } +- +- while (1) { +- alloc += 256; +- char *r2 = realloc (r, alloc); +- if (r2 == NULL) { +- perror ("realloc"); +- free (r); +- close (fd); +- return NULL; +- } +- r = r2; +- +- /* The '- 1' in the size calculation ensures there is space below +- * to add \0 to the end of the input. +- */ +- ssize_t n = read (fd, r + size, alloc - size - 1); +- if (n == -1) { +- fprintf (stderr, "read: %s: %m\n", filename); +- free (r); +- close (fd); +- return NULL; +- } +- if (n == 0) +- break; +- size += n; +- } +- +- if (close (fd) == -1) { +- fprintf (stderr, "close: %s: %m\n", filename); +- free (r); +- return NULL; +- } +- +- r[size] = '\0'; +- +- return r; +-} +- +-/* Takes optional arguments, consult optargs_bitmask. */ +-int +-do_mount_9p (const char *mount_tag, const char *mountpoint, const char *options) +-{ +- CLEANUP_FREE char *mp = NULL, *opts = NULL, *err = NULL; +- struct stat statbuf; +- int r; +- +- ABS_PATH (mountpoint, 0, return -1); +- +- mp = sysroot_path (mountpoint); +- if (!mp) { +- reply_with_perror ("malloc"); +- return -1; +- } +- +- /* Check the mountpoint exists and is a directory. */ +- if (stat (mp, &statbuf) == -1) { +- reply_with_perror ("%s", mountpoint); +- return -1; +- } +- if (!S_ISDIR (statbuf.st_mode)) { +- reply_with_perror ("%s: mount point is not a directory", mountpoint); +- return -1; +- } +- +- /* Add trans=virtio to the options. */ +- if ((optargs_bitmask & GUESTFS_MOUNT_9P_OPTIONS_BITMASK) && +- STRNEQ (options, "")) { +- if (asprintf (&opts, "trans=virtio,%s", options) == -1) { +- reply_with_perror ("asprintf"); +- return -1; +- } +- } +- else { +- opts = strdup ("trans=virtio"); +- if (opts == NULL) { +- reply_with_perror ("strdup"); +- return -1; +- } +- } +- +- r = command (NULL, &err, +- "mount", "-o", opts, "-t", "9p", mount_tag, mp, NULL); +- if (r == -1) { +- reply_with_error ("%s on %s: %s", mount_tag, mountpoint, err); +- return -1; +- } +- +- return 0; +-} +diff --git a/daemon/Makefile.am b/daemon/Makefile.am +index 5d1c222db..a9b40be25 100644 +--- a/daemon/Makefile.am ++++ b/daemon/Makefile.am +@@ -76,7 +76,6 @@ guestfsd_SOURCES = \ + ../common/protocol/guestfs_protocol.h \ + ../common/utils/cleanups.h \ + ../common/utils/guestfs-utils.h \ +- 9p.c \ + acl.c \ + actions.h \ + available.c \ +diff --git a/docs/C_SOURCE_FILES b/docs/C_SOURCE_FILES +index 7f1c60b30..f45e7124d 100644 +--- a/docs/C_SOURCE_FILES ++++ b/docs/C_SOURCE_FILES +@@ -71,7 +71,6 @@ common/windows/windows.h + customize/crypt-c.c + customize/dummy.c + customize/perl_edit-c.c +-daemon/9p.c + daemon/acl.c + daemon/actions.h + daemon/augeas.c +diff --git a/generator/actions_core.ml b/generator/actions_core.ml +index deda483a9..f466600df 100644 +--- a/generator/actions_core.ml ++++ b/generator/actions_core.ml +@@ -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." }; + +- { defaults with +- name = "list_9p"; added = (1, 11, 12); +- style = RStringList (RPlainString, "mounttags"), [], []; +- shortdesc = "list 9p filesystems"; +- longdesc = "\ +-List all 9p filesystems attached to the guest. A list of +-mount tags is returned." }; +- +- { defaults with +- name = "mount_9p"; added = (1, 11, 12); +- style = RErr, [String (PlainString, "mounttag"); String (PlainString, "mountpoint")], [OString "options"]; +- camel_name = "Mount9P"; +- shortdesc = "mount 9p filesystem"; +- longdesc = "\ +-Mount the virtio-9p filesystem with the tag C on the +-directory C. +- +-If required, C will be automatically added to the options. +-Any other options required can be passed in the optional C +-parameter." }; +- + { defaults with + 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 11a557076..1ef5ba0b7 100644 +--- a/generator/proc_nr.ml ++++ b/generator/proc_nr.ml +@@ -295,8 +295,6 @@ let proc_nr = [ + 282, "internal_autosync"; + 283, "is_zero"; + 284, "is_zero_device"; +-285, "list_9p"; +-286, "mount_9p"; + 287, "list_dm_devices"; + 288, "ntfsresize"; + 289, "btrfs_filesystem_resize"; +diff --git a/gobject/Makefile.inc b/gobject/Makefile.inc +index 067f861a9..7afe83c59 100644 +--- a/gobject/Makefile.inc ++++ b/gobject/Makefile.inc +@@ -93,7 +93,6 @@ guestfs_gobject_headers= \ + include/guestfs-gobject/optargs-mksquashfs.h \ + include/guestfs-gobject/optargs-mkswap.h \ + include/guestfs-gobject/optargs-mktemp.h \ +- include/guestfs-gobject/optargs-mount_9p.h \ + include/guestfs-gobject/optargs-mount_local.h \ + include/guestfs-gobject/optargs-ntfsclone_out.h \ + include/guestfs-gobject/optargs-ntfsfix.h \ +@@ -186,7 +185,6 @@ guestfs_gobject_sources= \ + src/optargs-mksquashfs.c \ + src/optargs-mkswap.c \ + src/optargs-mktemp.c \ +- src/optargs-mount_9p.c \ + src/optargs-mount_local.c \ + src/optargs-ntfsclone_out.c \ + src/optargs-ntfsfix.c \ +diff --git a/po/POTFILES b/po/POTFILES +index 79f4b8c56..b99333d0d 100644 +--- a/po/POTFILES ++++ b/po/POTFILES +@@ -58,7 +58,6 @@ customize/crypt-c.c + customize/dummy.c + customize/perl_edit-c.c + customize/test-password.pl +-daemon/9p.c + daemon/acl.c + daemon/augeas.c + daemon/available.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 +-gobject/src/optargs-mount_9p.c + gobject/src/optargs-mount_local.c + gobject/src/optargs-ntfsclone_out.c + gobject/src/optargs-ntfsfix.c +-- +2.18.4 + 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 deleted file mode 100644 index c261226..0000000 --- a/SOURCES/0076-RHEL-8-v2v-Disable-the-virt-v2v-in-place-option.patch +++ /dev/null @@ -1,286 +0,0 @@ -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-Disable-unsupported-remote-drive-protocols-RH.patch b/SOURCES/0077-RHEL-8-Disable-unsupported-remote-drive-protocols-RH.patch new file mode 100644 index 0000000..187be93 --- /dev/null +++ b/SOURCES/0077-RHEL-8-Disable-unsupported-remote-drive-protocols-RH.patch @@ -0,0 +1,609 @@ +From 336961659225584add638442cc0cf933803e008e 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 + (RHBZ#962113). + +This disables support for unsupported remote drive protocols: + + * ftp + * ftps + * http + * https + * tftp + * gluster + * iscsi + * sheepdog + * ssh + +Note 'nbd' is not disabled, and of course 'file' works. + +We hope to gradually add some of these back over the lifetime of RHEL 8. +--- + docs/guestfs-testing.pod | 20 ----- + fish/guestfish.pod | 66 ++-------------- + fish/test-add-uri.sh | 32 -------- + generator/actions_core.ml | 50 +------------ + lib/drives.c | 8 ++ + lib/guestfs.pod | 100 ------------------------- + tests/disks/test-qemu-drive-libvirt.sh | 28 ------- + tests/disks/test-qemu-drive.sh | 60 --------------- + 8 files changed, 16 insertions(+), 348 deletions(-) + +diff --git a/docs/guestfs-testing.pod b/docs/guestfs-testing.pod +index f558964bf..8f264ed17 100644 +--- a/docs/guestfs-testing.pod ++++ b/docs/guestfs-testing.pod +@@ -109,26 +109,6 @@ image. To exit, type C. + If you get an error, try enabling debugging (add C<-v> to the command + line). Also make sure that L succeeds. + +-=head2 Try to open a remote guest image with guestfish. +- +-You may also have to disable libvirt by setting this: +- +- export LIBGUESTFS_BACKEND=direct +- +-If you have a disk image available over HTTP/FTP, try to open it. +- +- guestfish --ro -i --format=raw -a http://www.example.com/disk.img +- +-For SSH you will need to make sure that ssh-agent is set up so you +-don't need a password to log in to the remote machine. Then a command +-similar to this should work: +- +- guestfish --ro -i --format=raw \ +- -a ssh://remote.example.com/path/to/disk.img +- +-If you get an error, try enabling debugging (add C<-v> to the command +-line). Also make sure that L succeeds. +- + =head2 Run virt-alignment-scan on all your guests. + + Run L on guests or disk images: +diff --git a/fish/guestfish.pod b/fish/guestfish.pod +index f1fdf094d..bacb60e0b 100644 +--- a/fish/guestfish.pod ++++ b/fish/guestfish.pod +@@ -131,9 +131,9 @@ To list what is available do: + + =head2 Remote drives + +-Access a remote disk using ssh: ++Access a remote disk using NBD: + +- guestfish -a ssh://example.com/path/to/disk.img ++ guestfish -a nbd://example.com + + =head2 Remote control + +@@ -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: + +- guestfish -a ssh://root@example.com/disk.img ++ guestfish -a nbd://example.com + + URIs I be used with the L command. The equivalent + command using the API directly is: + +- > add /disk.img protocol:ssh server:tcp:example.com username:root ++ > add /disk.img protocol:nbd server:tcp:example.com + + 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. + +-=head2 B<-a ftp://[user@]example.com[:port]/disk.img> +- +-=head2 B<-a ftps://[user@]example.com[:port]/disk.img> +- +-=head2 B<-a http://[user@]example.com[:port]/disk.img> +- +-=head2 B<-a https://[user@]example.com[:port]/disk.img> +- +-=head2 B<-a tftp://[user@]example.com[:port]/disk.img> +- +-Add a disk located on a remote FTP, HTTP or TFTP server. +- +-The equivalent API command would be: +- +- > add /disk.img protocol:(ftp|...) server:tcp:example.com +- +-=head2 B<-a gluster://example.com[:port]/volname/image> +- +-Add a disk image located on GlusterFS storage. +- +-The server is the one running C, and may be C. +- +-The equivalent API command would be: +- +- > add volname/image protocol:gluster server:tcp:example.com +- +-=head2 B<-a iscsi://example.com[:port]/target-iqn-name[/lun]> +- +-Add a disk located on an iSCSI server. +- +-The equivalent API command would be: +- +- > add target-iqn-name/lun protocol:iscsi server:tcp:example.com +- + =head2 B<-a nbd://example.com[:port]> + + =head2 B<-a nbd://example.com[:port]/exportname> +@@ -1228,35 +1194,13 @@ The equivalent API command would be: + + > add pool/disk protocol:rbd server:tcp:example.com:port + +-=head2 B<-a sheepdog://[example.com[:port]]/volume/image> +- +-Add a disk image located on a Sheepdog volume. +- +-The server name is optional. Although libguestfs and Sheepdog +-supports multiple servers, only at most one server can be specified +-when using this URI syntax. +- +-The equivalent API command would be: +- +- > add volume protocol:sheepdog [server:tcp:example.com] +- +-=head2 B<-a ssh://[user@]example.com[:port]/disk.img> +- +-Add a disk image located on a remote server, accessed using the Secure +-Shell (ssh) SFTP protocol. SFTP is supported out of the box by all +-major SSH servers. +- +-The equivalent API command would be: +- +- > add /disk protocol:ssh server:tcp:example.com [username:user] +- + Note that the URIs follow the syntax of + L: in particular, there + are restrictions on the allowed characters for the various components + of the URI. Characters such as C<:>, C<@>, and C B be + percent-encoded: + +- $ guestfish -a ssh://user:pass%40word@example.com/disk.img ++ $ guestfish -a rbd://user:pass%40word@example.com[:port]/pool/disk + + In this case, the password is C. + +diff --git a/fish/test-add-uri.sh b/fish/test-add-uri.sh +index 756df997b..8f84fd31b 100755 +--- a/fish/test-add-uri.sh ++++ b/fish/test-add-uri.sh +@@ -40,14 +40,6 @@ function fail () + $VG guestfish -x -a file://$abs_builddir/test-add-uri.img test-add-uri.out 2>&1 + grep -sq 'add_drive ".*/test-add-uri.img"' test-add-uri.out || fail + +-# curl +-$VG guestfish -x -a ftp://user@example.com/disk.img test-add-uri.out 2>&1 +-grep -sq 'add_drive "/disk.img" "protocol:ftp" "server:tcp:example.com" "username:user"' test-add-uri.out || fail +- +-# gluster +-$VG guestfish -x -a gluster://example.com/disk test-add-uri.out 2>&1 +-grep -sq 'add_drive "disk" "protocol:gluster" "server:tcp:example.com"' test-add-uri.out || fail +- + # NBD + $VG guestfish -x -a nbd://example.com test-add-uri.out 2>&1 + grep -sq 'add_drive "" "protocol:nbd" "server:tcp:example.com"' test-add-uri.out || fail +@@ -67,29 +59,5 @@ grep -sq 'add_drive "pool/disk" "protocol:rbd" "server:tcp:example.com:6789"' te + $VG guestfish -x -a rbd:///pool/disk test-add-uri.out 2>&1 + grep -sq 'add_drive "pool/disk" "protocol:rbd"' test-add-uri.out || fail + +-# sheepdog +-$VG guestfish -x -a sheepdog:///volume/image test-add-uri.out 2>&1 +-grep -sq 'add_drive "volume/image" "protocol:sheepdog"' test-add-uri.out || fail +- +-$VG guestfish -x -a sheepdog://example.com:3000/volume/image test-add-uri.out 2>&1 +-grep -sq 'add_drive "volume/image" "protocol:sheepdog" "server:tcp:example.com:3000"' test-add-uri.out || fail +- +-# ssh +-$VG guestfish -x -a ssh://example.com/disk.img test-add-uri.out 2>&1 +-grep -sq 'add_drive "/disk.img" "protocol:ssh" "server:tcp:example.com"' test-add-uri.out || fail +- +-$VG guestfish -x -a ssh://user@example.com/disk.img test-add-uri.out 2>&1 +-grep -sq 'add_drive "/disk.img" "protocol:ssh" "server:tcp:example.com" "username:user"' test-add-uri.out || fail +- +-$VG guestfish -x -a ssh://user@example.com:2000/disk.img test-add-uri.out 2>&1 +-grep -sq 'add_drive "/disk.img" "protocol:ssh" "server:tcp:example.com:2000" "username:user"' test-add-uri.out || fail +- +-# iSCSI +-$VG guestfish -x -a iscsi://example.com/iqn.2015-12.com.libguestfs:test1/0 test-add-uri.out 2>&1 +-grep -sq 'add_drive "iqn.2015-12.com.libguestfs:test1/0" "protocol:iscsi" "server:tcp:example.com"' test-add-uri.out || fail +- +-$VG guestfish -x -a iscsi://user:password@example.com/iqn.2015-12.com.libguestfs:test2/0 test-add-uri.out 2>&1 +-grep -sq 'add_drive "iqn.2015-12.com.libguestfs:test2/0" "protocol:iscsi" "server:tcp:example.com" "username:user" "secret:password"' test-add-uri.out || fail +- + rm test-add-uri.out + rm test-add-uri.img +diff --git a/generator/actions_core.ml b/generator/actions_core.ml +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. + This is the default if the optional protocol parameter + is omitted. + +-=item C +- +-Connect to a remote FTP, HTTP or TFTP server. +-The C parameter must also be supplied - see below. +- +-See also: L +- +-=item C +- +-Connect to the GlusterFS server. +-The C parameter must also be supplied - see below. +- +-See also: L +- +-=item C +- +-Connect to the iSCSI server. +-The C parameter must also be supplied - see below. +-The C parameter may be supplied. See below. +-The C parameter may be supplied. See below. +- +-See also: L. +- + =item C + + Connect to the Network Block Device server. +@@ -336,22 +313,6 @@ The C parameter may be supplied. See below. + + See also: L. + +-=item C +- +-Connect to the Sheepdog server. +-The C parameter may also be supplied - see below. +- +-See also: L. +- +-=item C +- +-Connect to the Secure Shell (ssh) server. +- +-The C parameter must be supplied. +-The C parameter may be supplied. See below. +- +-See also: L. +- + =back + + =item C +@@ -362,13 +323,8 @@ is a list of server(s). + Protocol Number of servers required + -------- -------------------------- + file List must be empty or param not used at all +- ftp|ftps|http|https|tftp Exactly one +- gluster Exactly one +- iscsi Exactly one + nbd Exactly one + rbd Zero or more +- sheepdog Zero or more +- ssh Exactly one + + Each list element is a string specifying a server. The string must be + in one of the following formats: +@@ -384,10 +340,10 @@ for the protocol is used (see F). + + =item C + +-For the C, C, C, C, C, C, C +-and C protocols, this specifies the remote username. ++For the C ++protocol, this specifies the remote username. + +-If not given, then the local username is used for C, and no authentication ++If not given, then no authentication + is attempted for ceph. But note this sometimes may give unexpected results, for + example if using the libvirt backend and if the libvirt backend is configured to + start the qemu appliance as a special user such as C. If in doubt, +diff --git a/lib/drives.c b/lib/drives.c +index 82ef30093..3d712c6e4 100644 +--- a/lib/drives.c ++++ b/lib/drives.c +@@ -165,6 +165,7 @@ create_drive_non_file (guestfs_h *g, + return drv; + } + ++#if 0 /* DISABLED IN RHEL 8 */ + static struct drive * + create_drive_curl (guestfs_h *g, + const struct drive_create_data *data) +@@ -223,6 +224,7 @@ create_drive_gluster (guestfs_h *g, + + return create_drive_non_file (g, data); + } ++#endif /* DISABLED IN RHEL 8 */ + + static int + nbd_port (void) +@@ -291,6 +293,7 @@ create_drive_rbd (guestfs_h *g, + return create_drive_non_file (g, data); + } + ++#if 0 /* DISABLED IN RHEL 8 */ + static struct drive * + create_drive_sheepdog (guestfs_h *g, + const struct drive_create_data *data) +@@ -391,6 +394,7 @@ create_drive_iscsi (guestfs_h *g, + + return create_drive_non_file (g, data); + } ++#endif /* DISABLED IN RHEL 8 */ + + /** + * Create the special F drive. +@@ -826,6 +830,7 @@ guestfs_impl_add_drive_opts (guestfs_h *g, const char *filename, + drv = create_drive_file (g, &data); + } + } ++#if 0 /* DISABLED IN RHEL 8 */ + else if (STREQ (protocol, "ftp")) { + data.protocol = drive_protocol_ftp; + drv = create_drive_curl (g, &data); +@@ -850,6 +855,7 @@ guestfs_impl_add_drive_opts (guestfs_h *g, const char *filename, + data.protocol = drive_protocol_iscsi; + drv = create_drive_iscsi (g, &data); + } ++#endif /* DISABLED IN RHEL 8 */ + else if (STREQ (protocol, "nbd")) { + data.protocol = drive_protocol_nbd; + drv = create_drive_nbd (g, &data); +@@ -858,6 +864,7 @@ guestfs_impl_add_drive_opts (guestfs_h *g, const char *filename, + data.protocol = drive_protocol_rbd; + drv = create_drive_rbd (g, &data); + } ++#if 0 /* DISABLED IN RHEL 8 */ + else if (STREQ (protocol, "sheepdog")) { + data.protocol = drive_protocol_sheepdog; + drv = create_drive_sheepdog (g, &data); +@@ -870,6 +877,7 @@ guestfs_impl_add_drive_opts (guestfs_h *g, const char *filename, + data.protocol = drive_protocol_tftp; + drv = create_drive_curl (g, &data); + } ++#endif /* DISABLED IN RHEL 8 */ + else { + error (g, _("unknown protocol ‘%s’"), protocol); + drv = NULL; /*FALLTHROUGH*/ +diff --git a/lib/guestfs.pod b/lib/guestfs.pod +index af944ddb7..58559a6b4 100644 +--- a/lib/guestfs.pod ++++ b/lib/guestfs.pod +@@ -714,70 +714,6 @@ servers. The server string is documented in + L. The C and C parameters are + also optional, and if not given, then no authentication will be used. + +-=head3 FTP, HTTP AND TFTP +- +-Libguestfs can access remote disks over FTP, FTPS, HTTP, HTTPS +-or TFTP protocols. +- +-To do this, set the optional C and C parameters of +-L like this: +- +- char **servers = { "www.example.org", NULL }; +- guestfs_add_drive_opts (g, "/disk.img", +- GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw", +- GUESTFS_ADD_DRIVE_OPTS_PROTOCOL, "http", +- GUESTFS_ADD_DRIVE_OPTS_SERVER, servers, +- -1); +- +-The C can be one of C<"ftp">, C<"ftps">, C<"http">, +-C<"https"> or C<"tftp">. +- +-C (the C parameter) is a list which must have a +-single element. The single element is a string defining the web, +-FTP or TFTP server. The format of this string is documented in +-L. +- +-=head3 GLUSTER +- +-Libguestfs can access Gluster disks. +- +-To do this, set the optional C and C parameters of +-L like this: +- +- char **servers = { "gluster.example.org:24007", NULL }; +- guestfs_add_drive_opts (g, "volname/image", +- GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw", +- GUESTFS_ADD_DRIVE_OPTS_PROTOCOL, "gluster", +- GUESTFS_ADD_DRIVE_OPTS_SERVER, servers, +- -1); +- +-C (the C parameter) is a list which must have a +-single element. The single element is a string defining the Gluster +-server. The format of this string is documented in +-L. +- +-Note that gluster usually requires the client process (ie. libguestfs) +-to run as B and will give unfathomable errors if it is not +-(eg. "No data available"). +- +-=head3 ISCSI +- +-Libguestfs can access iSCSI disks remotely. +- +-To do this, set the optional C and C parameters like +-this: +- +- char **server = { "iscsi.example.org:3000", NULL }; +- guestfs_add_drive_opts (g, "target-iqn-name/lun", +- GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw", +- GUESTFS_ADD_DRIVE_OPTS_PROTOCOL, "iscsi", +- GUESTFS_ADD_DRIVE_OPTS_SERVER, server, +- -1); +- +-The C parameter is a list which must have a single element. +-The single element is a string defining the iSCSI server. The format +-of this string is documented in L. +- + =head3 NETWORK BLOCK DEVICE + + Libguestfs can access Network Block Device (NBD) disks remotely. +@@ -840,42 +776,6 @@ L + + =back + +-=head3 SHEEPDOG +- +-Libguestfs can access Sheepdog disks. +- +-To do this, set the optional C and C parameters of +-L like this: +- +- char **servers = { /* optional servers ... */ NULL }; +- guestfs_add_drive_opts (g, "volume", +- GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw", +- GUESTFS_ADD_DRIVE_OPTS_PROTOCOL, "sheepdog", +- GUESTFS_ADD_DRIVE_OPTS_SERVER, servers, +- -1); +- +-The optional list of C may be zero or more server addresses +-(C<"hostname:port">). The format of the server strings is documented +-in L. +- +-=head3 SSH +- +-Libguestfs can access disks over a Secure Shell (SSH) connection. +- +-To do this, set the C and C and (optionally) +-C parameters of L like this: +- +- char **server = { "remote.example.com", NULL }; +- guestfs_add_drive_opts (g, "/path/to/disk.img", +- GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw", +- GUESTFS_ADD_DRIVE_OPTS_PROTOCOL, "ssh", +- GUESTFS_ADD_DRIVE_OPTS_SERVER, server, +- GUESTFS_ADD_DRIVE_OPTS_USERNAME, "remoteuser", +- -1); +- +-The format of the server string is documented in +-L. +- + =head2 INSPECTION + + 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 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 + grep -sq -- '-drive file=rbd:abc-def/ghi-jkl:auth_supported=none,' "$DEBUG_QEMU_FILE" || fail ceph2 + rm "$DEBUG_QEMU_FILE" + +-# Gluster. +- +-$guestfish -d gluster run ||: +-check_output +-grep -sq -- '-drive file=gluster://1.2.3.4:1234/volname/image,' "$DEBUG_QEMU_FILE" || fail gluster +-rm "$DEBUG_QEMU_FILE" +- +-# iSCSI. +- +-$guestfish -d iscsi run ||: +-check_output +-grep -sq -- '-drive file=iscsi://1.2.3.4:1234/iqn.2003-01.org.linux-iscsi.fedora' "$DEBUG_QEMU_FILE" || fail iscsi +-rm "$DEBUG_QEMU_FILE" +- +-# NBD. +- +-$guestfish -d nbd run ||: +-check_output +-grep -sq -- '-drive file=nbd:1.2.3.4:1234,' "$DEBUG_QEMU_FILE" || fail nbd +-rm "$DEBUG_QEMU_FILE" +- +-# Sheepdog. +- +-$guestfish -d sheepdog run ||: +-check_output +-grep -sq -- '-drive file=sheepdog:volume,' "$DEBUG_QEMU_FILE" || fail sheepdog +-rm "$DEBUG_QEMU_FILE" +- + # Local, stored in a pool. + + $guestfish -d pool1 run ||: +diff --git a/tests/disks/test-qemu-drive.sh b/tests/disks/test-qemu-drive.sh +index 19dd60a2f..583e031bd 100755 +--- a/tests/disks/test-qemu-drive.sh ++++ b/tests/disks/test-qemu-drive.sh +@@ -62,45 +62,6 @@ check_output + grep -sq -- '-drive file=rbd:abc-def/ghi-jkl:auth_supported=none,' "$DEBUG_QEMU_FILE" || fail + rm "$DEBUG_QEMU_FILE" + +-# HTTP. +- +-guestfish < -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-Remove-User-Mode-Linux-RHBZ-1144197.patch b/SOURCES/0078-RHEL-8-Remove-User-Mode-Linux-RHBZ-1144197.patch new file mode 100644 index 0000000..fb4d77a --- /dev/null +++ b/SOURCES/0078-RHEL-8-Remove-User-Mode-Linux-RHBZ-1144197.patch @@ -0,0 +1,72 @@ +From cbb6a42b9074ed78c74ddefee4ec7571132a4d24 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). + +This isn't supported in RHEL 8. +--- + lib/launch-uml.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/lib/launch-uml.c b/lib/launch-uml.c +index da20c17d9..a5e0e8179 100644 +--- a/lib/launch-uml.c ++++ b/lib/launch-uml.c +@@ -44,7 +44,9 @@ struct backend_uml_data { + char umid[UML_UMID_LEN+1]; /* umid=<...> unique ID. */ + }; + ++#if 0 + static void print_vmlinux_command_line (guestfs_h *g, char **argv); ++#endif + + /* Run uml_mkcow to create a COW overlay. */ + static char * +@@ -81,6 +83,7 @@ create_cow_overlay_uml (guestfs_h *g, void *datav, struct drive *drv) + return make_cow_overlay (g, drv->src.u.path); + } + ++#if 0 + /* Test for features which are not supported by the UML backend. + * Possibly some of these should just be warnings, not errors. + */ +@@ -128,10 +131,17 @@ uml_supported (guestfs_h *g) + + return true; + } ++#endif + + static int + launch_uml (guestfs_h *g, void *datav, const char *arg) + { ++ error (g, ++ "launch: In RHEL, only the 'libvirt' or 'direct' method is supported.\n" ++ "In particular, User-Mode Linux (UML) is not supported."); ++ return -1; ++ ++#if 0 + struct backend_uml_data *data = datav; + CLEANUP_FREE_STRINGSBUF DECLARE_STRINGSBUF (cmdline); + int console_sock = -1, daemon_sock = -1; +@@ -491,8 +501,10 @@ launch_uml (guestfs_h *g, void *datav, const char *arg) + } + g->state = CONFIG; + return -1; ++#endif + } + ++#if 0 + /* This is called from the forked subprocess just before vmlinux runs, + * so it can just print the message straight to stderr, where it will + * be picked up and funnelled through the usual appliance event API. +@@ -522,6 +534,7 @@ print_vmlinux_command_line (guestfs_h *g, char **argv) + + fputc ('\n', stderr); + } ++#endif + + static int + shutdown_uml (guestfs_h *g, void *datav, int check_for_errors) +-- +2.18.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 deleted file mode 100644 index 5c61493..0000000 --- a/SOURCES/0078-RHEL-8-v2v-do-not-mention-SUSE-Xen-hosts-RHBZ-143020.patch +++ /dev/null @@ -1,26 +0,0 @@ -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/0079-RHEL-8-v2v-Select-correct-qemu-binary-for-o-qemu-mod.patch b/SOURCES/0079-RHEL-8-v2v-Select-correct-qemu-binary-for-o-qemu-mod.patch new file mode 100644 index 0000000..e538c96 --- /dev/null +++ b/SOURCES/0079-RHEL-8-v2v-Select-correct-qemu-binary-for-o-qemu-mod.patch @@ -0,0 +1,33 @@ +From a2c0ccac7b1bcb451987b6c1b85e3a5ee48b8949 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 + (RHBZ#1147313). + +RHEL 8 does not have qemu-system-x86_64 (etc), and in addition the +qemu binary is located in /usr/libexec. Encode the path to this +binary directly in the script. + +Note that we don't support people running qemu directly like this. +It's just for quick testing of converted VMs, and to help us with +support cases. +--- + v2v/output_qemu.ml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/v2v/output_qemu.ml b/v2v/output_qemu.ml +index 1f6798aaf..8665d7b5c 100644 +--- a/v2v/output_qemu.ml ++++ b/v2v/output_qemu.ml +@@ -81,7 +81,7 @@ object + * module deals with shell and qemu comma quoting. + *) + let cmd = Qemuopts.create () in +- Qemuopts.set_binary_by_arch cmd (Some guestcaps.gcaps_arch); ++ Qemuopts.set_binary cmd "/usr/libexec/qemu-kvm"; + + let flag = Qemuopts.flag cmd + and arg = Qemuopts.arg cmd +-- +2.18.4 + 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 deleted file mode 100644 index 4c38c1d..0000000 --- a/SOURCES/0079-RHEL-8-v2v-rhv-upload-Remove-restriction-on-oa-spars.patch +++ /dev/null @@ -1,91 +0,0 @@ -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 deleted file mode 100644 index d2d7118..0000000 --- a/SOURCES/0080-RHEL-8-use-platform-python.patch +++ /dev/null @@ -1,27 +0,0 @@ -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-the-qemu-boot-option-RHBZ-1147313.patch b/SOURCES/0080-RHEL-8-v2v-Disable-the-qemu-boot-option-RHBZ-1147313.patch new file mode 100644 index 0000000..68db0b0 --- /dev/null +++ b/SOURCES/0080-RHEL-8-v2v-Disable-the-qemu-boot-option-RHBZ-1147313.patch @@ -0,0 +1,105 @@ +From 4190aec225ec3bf4d1e39fbde89131d4c8a6a9a7 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). + +This cannot work because there is no Gtk or SDL output mode +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-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 686631271..e3578ddcb 100644 +--- a/v2v/cmdline.ml ++++ b/v2v/cmdline.ml +@@ -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"), +@@ -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 ++ if qemu_boot then ++ error (f_"-o qemu: the --qemu-boot option cannot be used in RHEL"); + 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 25041d0ec..bd606592b 100644 +--- a/v2v/virt-v2v.pod ++++ b/v2v/virt-v2v.pod +@@ -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. + +-To convert a local disk image and immediately boot it in local +-qemu, do: +- +- virt-v2v -i disk disk.img -o qemu -os /var/tmp --qemu-boot +- + =head1 OPTIONS + + =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>. + +-When using this output mode, you can also specify the I<--qemu-boot> +-option which boots the guest under qemu immediately. +- + =item B<-o> B + + This is the same as I<-o rhv>. +@@ -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. + +-=item B<--qemu-boot> +- +-When using I<-o qemu> only, this boots the guest immediately after +-virt-v2v finishes. +- + =item B<-q> + + =item B<--quiet> +-- +2.18.4 + diff --git a/SOURCES/0081-RHEL-8-Disable-alternate-Augeas-lenses.patch b/SOURCES/0081-RHEL-8-Disable-alternate-Augeas-lenses.patch new file mode 100644 index 0000000..28b3ee1 --- /dev/null +++ b/SOURCES/0081-RHEL-8-Disable-alternate-Augeas-lenses.patch @@ -0,0 +1,60 @@ +From 1b819b67c2cc39e4728c4299749f1dd439937743 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. + +These are included in the RHEL augeas package, and therefore not +required. + +See: +https://www.redhat.com/archives/libguestfs/2014-October/msg00220.html +--- + appliance/Makefile.am | 1 - + daemon/augeas.c | 5 ++++- + 2 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/appliance/Makefile.am b/appliance/Makefile.am +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 + rm -rf tmp-d + mkdir -p tmp-d$(DAEMON_SUPERMIN_DIR) tmp-d/etc tmp-d/usr/share/guestfs + ln ../daemon/guestfsd tmp-d$(DAEMON_SUPERMIN_DIR)/guestfsd +- ln $(srcdir)/guestfs_shadow.aug tmp-d/usr/share/guestfs/guestfs_shadow.aug + ( cd tmp-d && tar zcf - * ) > $@-t + rm -r tmp-d + mv $@-t $@ +diff --git a/daemon/augeas.c b/daemon/augeas.c +index 453251337..5bbfffa2d 100644 +--- a/daemon/augeas.c ++++ b/daemon/augeas.c +@@ -134,7 +134,7 @@ do_aug_init (const char *root, int flags) + } + + /* Pass AUG_NO_ERR_CLOSE so we can display detailed errors. */ +- aug = aug_init (buf, "/usr/share/guestfs/", flags | AUG_NO_ERR_CLOSE); ++ aug = aug_init (buf, NULL, flags | AUG_NO_ERR_CLOSE); + + if (!aug) { + reply_with_error ("augeas initialization failed"); +@@ -148,6 +148,8 @@ do_aug_init (const char *root, int flags) + return -1; + } + ++ /* We already have the needed lenses in RHEL 8 */ ++#if 0 + if (!augeas_is_version (1, 2, 1)) { + int r = aug_transform (aug, "guestfs_shadow", "/etc/shadow", + 0 /* = included */); +@@ -166,6 +168,7 @@ do_aug_init (const char *root, int flags) + } + } + } ++#endif + + return 0; + } +-- +2.18.4 + 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 deleted file mode 100644 index ecca5c4..0000000 --- a/SOURCES/0081-RHEL-8-point-to-KB-for-supported-v2v-hypervisors-gue.patch +++ /dev/null @@ -1,125 +0,0 @@ -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/0082-RHEL-8-Fix-list-of-supported-sound-cards-to-match-RH.patch b/SOURCES/0082-RHEL-8-Fix-list-of-supported-sound-cards-to-match-RH.patch new file mode 100644 index 0000000..d487184 --- /dev/null +++ b/SOURCES/0082-RHEL-8-Fix-list-of-supported-sound-cards-to-match-RH.patch @@ -0,0 +1,34 @@ +From 74d6c774c52ad7d6dd1746a4d11eb7668e826374 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 + (RHBZ#1176493). + +--- + v2v/utils.ml | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/v2v/utils.ml b/v2v/utils.ml +index 74b501f81..21e9c9c15 100644 +--- a/v2v/utils.ml ++++ b/v2v/utils.ml +@@ -51,13 +51,14 @@ let kvm_arch = function + (* Does qemu support the given sound card? *) + let qemu_supports_sound_card = function + | Types.AC97 +- | Types.ES1370 + | Types.ICH6 + | Types.ICH9 + | Types.PCSpeaker ++ -> true ++ | Types.ES1370 + | Types.SB16 + | Types.USBAudio +- -> true ++ -> false + + (* Find the UEFI firmware. *) + let find_uefi_firmware guest_arch = +-- +2.18.4 + diff --git a/SOURCES/0083-RHEL-8-Reject-use-of-libguestfs-winsupport-features-.patch b/SOURCES/0083-RHEL-8-Reject-use-of-libguestfs-winsupport-features-.patch new file mode 100644 index 0000000..7d7967b --- /dev/null +++ b/SOURCES/0083-RHEL-8-Reject-use-of-libguestfs-winsupport-features-.patch @@ -0,0 +1,40 @@ +From 434dd6ac0634211a48dd8d46c6efa68ef1270ae5 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 + for virt-* tools (RHBZ#1240276). + +--- + generator/c.ml | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/generator/c.ml b/generator/c.ml +index 86f7d89a3..b5bb99f53 100644 +--- a/generator/c.ml ++++ b/generator/c.ml +@@ -1832,6 +1832,22 @@ and generate_client_actions actions () = + check_args_validity c_name style; + trace_call name c_name style; + ++ (* RHEL 8 *) ++ if name = "mount" || name = "mount_ro" || name = "mount_options" || ++ name = "mount_vfs" then ( ++ pr " if (g->program && !STRPREFIX (g->program, \"virt-\")) {\n"; ++ pr " CLEANUP_FREE char *vfs_type = guestfs_vfs_type (g, mountable);\n"; ++ pr " if (vfs_type && STREQ (vfs_type, \"ntfs\")) {\n"; ++ pr " error (g, \"mount: unsupported filesystem type\");\n"; ++ pr " if (trace_flag)\n"; ++ pr " guestfs_int_trace (g, \"%%s = %%s (error)\",\n"; ++ pr " \"%s\", \"-1\");\n" name; ++ pr " return %s;\n" (string_of_errcode errcode); ++ pr " }\n"; ++ pr " }\n"; ++ pr "\n"; ++ ); ++ + (* Calculate the total size of all FileIn arguments to pass + * as a progress bar hint. + *) +-- +2.18.4 + diff --git a/SOURCES/0084-RHEL-8-Fix-tests-for-libguestfs-winsupport.patch b/SOURCES/0084-RHEL-8-Fix-tests-for-libguestfs-winsupport.patch new file mode 100644 index 0000000..cb324e4 --- /dev/null +++ b/SOURCES/0084-RHEL-8-Fix-tests-for-libguestfs-winsupport.patch @@ -0,0 +1,93 @@ +From dbbd9c3d94eeb1ad700bc0745a245da1fb71e1b7 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. + +It doesn't let us use guestfish for arbitrary Windows edits. +--- + test-data/phony-guests/make-windows-img.sh | 1 + + tests/charsets/test-charset-fidelity.c | 2 ++ + v2v/test-v2v-virtio-win-iso.sh | 8 +++++++- + v2v/test-v2v-windows-conversion.sh | 8 +++++++- + 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 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 + + # Create a disk image. + guestfish < "$script" + :> "$expected" + ++cat >> "$script" < "$response" ++guestfish --ro -a "$d/windows-sda" < "$script" > "$response" + diff -u "$expected" "$response" + + rm -r $d +diff --git a/v2v/test-v2v-windows-conversion.sh b/v2v/test-v2v-windows-conversion.sh +index f1da222a9..ff94fe39b 100755 +--- a/v2v/test-v2v-windows-conversion.sh ++++ b/v2v/test-v2v-windows-conversion.sh +@@ -73,6 +73,12 @@ mktest () + :> "$script" + :> "$expected" + ++cat >> "$script" < "$response" ++guestfish --ro -a "$d/windows-sda" < "$script" > "$response" + diff -u "$expected" "$response" + + # We also update the Registry several times, for firstboot, and (ONLY +-- +2.18.4 + diff --git a/SOURCES/0085-RHEL-8-tests-Disable-daemon-tests-that-require-the-u.patch b/SOURCES/0085-RHEL-8-tests-Disable-daemon-tests-that-require-the-u.patch new file mode 100644 index 0000000..7cd91cb --- /dev/null +++ b/SOURCES/0085-RHEL-8-tests-Disable-daemon-tests-that-require-the-u.patch @@ -0,0 +1,28 @@ +From e6a6af387981b849349c72e7d5c367b944dbd317 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.18.4 + diff --git a/SOURCES/0086-RHEL-8-v2v-Disable-the-virt-v2v-in-place-option.patch b/SOURCES/0086-RHEL-8-v2v-Disable-the-virt-v2v-in-place-option.patch new file mode 100644 index 0000000..47d311f --- /dev/null +++ b/SOURCES/0086-RHEL-8-v2v-Disable-the-virt-v2v-in-place-option.patch @@ -0,0 +1,286 @@ +From 153dc4ea922875c582490bc4e0ccad227aa62558 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.18.4 + diff --git a/SOURCES/0087-RHEL-8-v2v-i-disk-force-VNC-as-display-RHBZ-1372671.patch b/SOURCES/0087-RHEL-8-v2v-i-disk-force-VNC-as-display-RHBZ-1372671.patch new file mode 100644 index 0000000..fc18897 --- /dev/null +++ b/SOURCES/0087-RHEL-8-v2v-i-disk-force-VNC-as-display-RHBZ-1372671.patch @@ -0,0 +1,26 @@ +From 68d6b9b268ccc6fd12c94acc7e0d3aa130eaee95 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.18.4 + diff --git a/SOURCES/0088-RHEL-8-v2v-do-not-mention-SUSE-Xen-hosts-RHBZ-143020.patch b/SOURCES/0088-RHEL-8-v2v-do-not-mention-SUSE-Xen-hosts-RHBZ-143020.patch new file mode 100644 index 0000000..8fba832 --- /dev/null +++ b/SOURCES/0088-RHEL-8-v2v-do-not-mention-SUSE-Xen-hosts-RHBZ-143020.patch @@ -0,0 +1,26 @@ +From 9c3434985b67dd6387f7d358753b289ae43e54fe 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.18.4 + diff --git a/SOURCES/0089-RHEL-8-v2v-rhv-upload-Remove-restriction-on-oa-spars.patch b/SOURCES/0089-RHEL-8-v2v-rhv-upload-Remove-restriction-on-oa-spars.patch new file mode 100644 index 0000000..462763e --- /dev/null +++ b/SOURCES/0089-RHEL-8-v2v-rhv-upload-Remove-restriction-on-oa-spars.patch @@ -0,0 +1,91 @@ +From 24c75d5ae2ca66fc683e98d32f7949a35caf6260 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.18.4 + diff --git a/SOURCES/0090-RHEL-8-use-platform-python.patch b/SOURCES/0090-RHEL-8-use-platform-python.patch new file mode 100644 index 0000000..0b73995 --- /dev/null +++ b/SOURCES/0090-RHEL-8-use-platform-python.patch @@ -0,0 +1,27 @@ +From cb6f386f75f210bdc97133a026e2fdb29a2fe28d 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.18.4 + diff --git a/SOURCES/0091-RHEL-8-point-to-KB-for-supported-v2v-hypervisors-gue.patch b/SOURCES/0091-RHEL-8-point-to-KB-for-supported-v2v-hypervisors-gue.patch new file mode 100644 index 0000000..5302c62 --- /dev/null +++ b/SOURCES/0091-RHEL-8-point-to-KB-for-supported-v2v-hypervisors-gue.patch @@ -0,0 +1,125 @@ +From ada9209ada5511a7876ca9c0e1183bde217adbae 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.18.4 + diff --git a/SOURCES/0092-lib-Increase-default-memsize-to-1280-RHBZ-1837765.patch b/SOURCES/0092-lib-Increase-default-memsize-to-1280-RHBZ-1837765.patch new file mode 100644 index 0000000..00edfd0 --- /dev/null +++ b/SOURCES/0092-lib-Increase-default-memsize-to-1280-RHBZ-1837765.patch @@ -0,0 +1,66 @@ +From ee88832841e82a407c9df44a82b87270ec0d492b Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Tue, 30 Jun 2020 17:34:47 +0100 +Subject: [PATCH] lib: Increase default memsize to 1280 (RHBZ#1837765). + +Argon2 is the default LUKS Password-Based Key Derivation Function +(PBKDF) for some new guests such as RHEL 8.2 and Fedora. It is +designed to be "memory hard", meaning that by design it requires large +amounts of memory, making it expensive to brute-force. Unfortunately +the default for guests which had more than a few GB of RAM at install +time is to require about 1 GB of RAM to decrypt the block device, +which is considerably larger than the default available in the +libguestfs appliance. + +To make it possible to open these encrypted disks we need to make the +appliance larger. This could be done as a one-off, and the current +workaround is simply to set LIBGUESTFS_MEMSIZE=2048 or a similar +amount. However since we don't know in advance whether we could be +dealing with an encrypted disk, partition, etc. or what PBKDF it uses, +the only way to deal with this in all circumstances is to increase the +default memsize. This commit increases it quite a lot (768 -> 1280) +which is unfortunate. + +Note as there is some confusion on this point: Since libguestfs does +not attempt to decrypt disks in parallel, you only need ~ 1GB in +total, not per encrypted disk. + +For a reproducer, see: +https://bugzilla.redhat.com/show_bug.cgi?id=1837765#c14 + +(cherry picked from commit 224f373043302845122bf701ffc6e3416e0168fa) +--- + lib/guestfs-internal.h | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/lib/guestfs-internal.h b/lib/guestfs-internal.h +index 75b8a5c8e..30553d7c0 100644 +--- a/lib/guestfs-internal.h ++++ b/lib/guestfs-internal.h +@@ -94,7 +94,7 @@ + * creating device nodes. + */ + #ifdef __powerpc__ +-# define DEFAULT_MEMSIZE 1024 ++# define DEFAULT_MEMSIZE 1280 + #endif + + /* Kernel 3.19 is unable to uncompress the initramfs on aarch64 unless +@@ -103,12 +103,12 @@ + * common on aarch64, treat this like the ppc case above. + */ + #ifdef __aarch64__ +-# define DEFAULT_MEMSIZE 1024 ++# define DEFAULT_MEMSIZE 1280 + #endif + + /* The default and minimum memory size for most users. */ + #ifndef DEFAULT_MEMSIZE +-# define DEFAULT_MEMSIZE 768 ++# define DEFAULT_MEMSIZE 1280 + #endif + #ifndef MIN_MEMSIZE + # define MIN_MEMSIZE 256 +-- +2.18.4 + diff --git a/SOURCES/0093-tar-in-Add-workaround-because-tar-doesn-t-restore-ca.patch b/SOURCES/0093-tar-in-Add-workaround-because-tar-doesn-t-restore-ca.patch new file mode 100644 index 0000000..fe7ecd5 --- /dev/null +++ b/SOURCES/0093-tar-in-Add-workaround-because-tar-doesn-t-restore-ca.patch @@ -0,0 +1,41 @@ +From 38ecae6c0298943b4bc74d6d3d5c888ca0853dec Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 13 Oct 2016 12:47:43 +0100 +Subject: [PATCH] tar-in: Add workaround because tar doesn't restore + capabilities (RHBZ#1384241). + +Current GNU tar does not restore all extended attributes. In +particular only user.* capabilities are restored (although all +are saved in the tarball). + +To restore capabilities, SELinux security attributes, and other things +we need to use --xattrs-include=* + +For further information on the tar bug, see: +https://bugzilla.redhat.com/show_bug.cgi?id=771927 + +(cherry picked from commit 6d0ab14b56743679638ead0829ff3131749ac59b) +--- + daemon/tar.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/daemon/tar.c b/daemon/tar.c +index 300e99448..9464d7105 100644 +--- a/daemon/tar.c ++++ b/daemon/tar.c +@@ -188,7 +188,11 @@ do_tar_in (const char *dir, const char *compress, int xattrs, int selinux, int a + "tar", + dir, filter, + chown_supported ? "" : "--no-same-owner ", +- xattrs ? "--xattrs " : "", ++ /* --xattrs-include=* is a workaround for a bug ++ * in tar, and hopefully won't be required ++ * forever. See RHBZ#771927. ++ */ ++ xattrs ? "--xattrs --xattrs-include='*' " : "", + selinux ? "--selinux " : "", + acls ? "--acls " : "", + error_file) == -1) { +-- +2.18.4 + diff --git a/SOURCES/0094-mlcustomize-Refactor-SELinux_relabel-code.patch b/SOURCES/0094-mlcustomize-Refactor-SELinux_relabel-code.patch new file mode 100644 index 0000000..4f641ae --- /dev/null +++ b/SOURCES/0094-mlcustomize-Refactor-SELinux_relabel-code.patch @@ -0,0 +1,155 @@ +From 3bceb391d14aeebb21dd9742108fa98945a32c5c Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Tue, 5 May 2020 16:44:14 +0100 +Subject: [PATCH] mlcustomize: Refactor SELinux_relabel code. + +This shouldn't change the effect of this code. + +Cherry picked from libguestfs-common +commit 3493d9fcaab6de1c09528e55a01bc24f0fb6c03c and backported +to libguestfs 1.40 branch (which predates the common submodule). +--- + customize/SELinux_relabel.ml | 127 +++++++++++++++++++---------------- + 1 file changed, 68 insertions(+), 59 deletions(-) + +diff --git a/customize/SELinux_relabel.ml b/customize/SELinux_relabel.ml +index 44995df6b..5df1f0895 100644 +--- a/customize/SELinux_relabel.ml ++++ b/customize/SELinux_relabel.ml +@@ -28,65 +28,74 @@ module G = Guestfs + let array_find a l = + List.mem a (Array.to_list l) + +-let relabel (g : G.guestfs) = +- (* Is the guest using SELinux? *) +- if g#is_file ~followsymlinks:true "/usr/sbin/load_policy" && +- g#is_file ~followsymlinks:true "/etc/selinux/config" then ( +- (* Is setfiles / SELinux relabelling functionality available? *) +- if g#feature_available [| "selinuxrelabel" |] then ( +- (* Use Augeas to parse /etc/selinux/config. *) +- g#aug_init "/" (16+32) (* AUG_SAVE_NOOP | AUG_NO_LOAD *); +- (* See: https://bugzilla.redhat.com/show_bug.cgi?id=975412#c0 *) +- ignore (g#aug_rm "/augeas/load/*[\"/etc/selinux/config/\" !~ regexp('^') + glob(incl) + regexp('/.*')]"); +- g#aug_load (); +- debug_augeas_errors g; +- +- (* Get the SELinux policy name, eg. "targeted", "minimum". +- * Use "targeted" if not specified, just like libselinux does. +- *) +- let policy = +- let config_path = "/files/etc/selinux/config" in +- let selinuxtype_path = config_path ^ "/SELINUXTYPE" in +- let keys = g#aug_ls config_path in +- if array_find selinuxtype_path keys then +- g#aug_get selinuxtype_path +- else +- "targeted" in +- +- g#aug_close (); +- +- (* Get the spec file name. *) +- let specfile = +- sprintf "/etc/selinux/%s/contexts/files/file_contexts" policy in +- +- (* RHEL 6.2 - 6.5 had a malformed specfile that contained the +- * invalid regular expression "/var/run/spice-vdagentd.\pid" +- * (instead of "\.p"). This stops setfiles from working on +- * the guest. +- * +- * Because an SELinux relabel writes all over the filesystem, +- * it seems reasonable to fix this problem in the specfile +- * at the same time. (RHBZ#1374232) +- *) +- if g#grep ~fixed:true "vdagentd.\\pid" specfile <> [||] then ( +- debug "fixing invalid regular expression in %s" specfile; +- let old_specfile = specfile ^ "~" in +- g#mv specfile old_specfile; +- let content = g#read_file old_specfile in +- let content = +- String.replace content "vdagentd.\\pid" "vdagentd\\.pid" in +- g#write specfile content; +- g#copy_attributes ~all:true old_specfile specfile +- ); +- +- (* Relabel everything. *) +- g#selinux_relabel ~force:true specfile "/"; +- +- (* If that worked, we don't need to autorelabel. *) ++let rec relabel (g : G.guestfs) = ++ (* Is the guest using SELinux? (Otherwise this is a no-op). *) ++ if is_selinux_guest g then ( ++ try ++ use_setfiles g; ++ (* That worked, so we don't need to autorelabel. *) + g#rm_f "/.autorelabel" +- ) +- else ( +- (* SELinux guest, but not SELinux host. Fallback to this. *) ++ with Failure _ -> ++ (* This is the fallback in case something in the setfiles ++ * method didn't work. That includes the case where a non-SELinux ++ * host is processing an SELinux guest, and other things. ++ *) + g#touch "/.autorelabel" +- ) + ) ++ ++and is_selinux_guest g = ++ g#is_file ~followsymlinks:true "/usr/sbin/load_policy" && ++ g#is_file ~followsymlinks:true "/etc/selinux/config" ++ ++and use_setfiles g = ++ (* Is setfiles / SELinux relabelling functionality available? *) ++ if not (g#feature_available [| "selinuxrelabel" |]) then ++ failwith "no selinux relabel feature"; ++ ++ (* Use Augeas to parse /etc/selinux/config. *) ++ g#aug_init "/" (16+32) (* AUG_SAVE_NOOP | AUG_NO_LOAD *); ++ (* See: https://bugzilla.redhat.com/show_bug.cgi?id=975412#c0 *) ++ ignore (g#aug_rm "/augeas/load/*[\"/etc/selinux/config/\" !~ regexp('^') + glob(incl) + regexp('/.*')]"); ++ g#aug_load (); ++ debug_augeas_errors g; ++ ++ (* Get the SELinux policy name, eg. "targeted", "minimum". ++ * Use "targeted" if not specified, just like libselinux does. ++ *) ++ let policy = ++ let config_path = "/files/etc/selinux/config" in ++ let selinuxtype_path = config_path ^ "/SELINUXTYPE" in ++ let keys = g#aug_ls config_path in ++ if array_find selinuxtype_path keys then ++ g#aug_get selinuxtype_path ++ else ++ "targeted" in ++ ++ g#aug_close (); ++ ++ (* Get the spec file name. *) ++ let specfile = ++ sprintf "/etc/selinux/%s/contexts/files/file_contexts" policy in ++ ++ (* RHEL 6.2 - 6.5 had a malformed specfile that contained the ++ * invalid regular expression "/var/run/spice-vdagentd.\pid" ++ * (instead of "\.p"). This stops setfiles from working on ++ * the guest. ++ * ++ * Because an SELinux relabel writes all over the filesystem, ++ * it seems reasonable to fix this problem in the specfile ++ * at the same time. (RHBZ#1374232) ++ *) ++ if g#grep ~fixed:true "vdagentd.\\pid" specfile <> [||] then ( ++ debug "fixing invalid regular expression in %s" specfile; ++ let old_specfile = specfile ^ "~" in ++ g#mv specfile old_specfile; ++ let content = g#read_file old_specfile in ++ let content = ++ String.replace content "vdagentd.\\pid" "vdagentd\\.pid" in ++ g#write specfile content; ++ g#copy_attributes ~all:true old_specfile specfile ++ ); ++ ++ (* Relabel everything. *) ++ g#selinux_relabel ~force:true specfile "/" +-- +2.18.4 + diff --git a/SOURCES/0095-mlcustomize-Fall-back-to-autorelabel-if-specfile-doe.patch b/SOURCES/0095-mlcustomize-Fall-back-to-autorelabel-if-specfile-doe.patch new file mode 100644 index 0000000..b2be0f3 --- /dev/null +++ b/SOURCES/0095-mlcustomize-Fall-back-to-autorelabel-if-specfile-doe.patch @@ -0,0 +1,41 @@ +From a5e6e764c8753c254e801b32059530fbc2e86e8d Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Tue, 5 May 2020 16:44:15 +0100 +Subject: [PATCH] mlcustomize: Fall back to autorelabel if specfile does not + exist (RHBZ#1828952). + +https://bugzilla.redhat.com/show_bug.cgi?id=1828952#c2 + +Cherry picked from libguestfs-common +commit 101dac2eac8c61f0081c343b5d69cfa4efbc2a98 and backported +to libguestfs 1.40 branch (which predates the common submodule). + +If SELINUXTYPE is set to some value other than targeted then we look +for a directory /etc/selinux/ which does not exist. +However this should not cause a fatal error. Using setfiles to do the +relabelling immediately is a nice-to-have, but we can fallback to +using autorelabel if we're unable to achieve it. +--- + customize/SELinux_relabel.ml | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/customize/SELinux_relabel.ml b/customize/SELinux_relabel.ml +index 5df1f0895..5ecf7bd7e 100644 +--- a/customize/SELinux_relabel.ml ++++ b/customize/SELinux_relabel.ml +@@ -77,6 +77,12 @@ and use_setfiles g = + let specfile = + sprintf "/etc/selinux/%s/contexts/files/file_contexts" policy in + ++ (* If the spec file doesn't exist then fall back to using ++ * autorelabel (RHBZ#1828952). ++ *) ++ if not (g#is_file ~followsymlinks:true specfile) then ++ failwith "no spec file"; ++ + (* RHEL 6.2 - 6.5 had a malformed specfile that contained the + * invalid regular expression "/var/run/spice-vdagentd.\pid" + * (instead of "\.p"). This stops setfiles from working on +-- +2.18.4 + diff --git a/SOURCES/copy-patches.sh b/SOURCES/copy-patches.sh index a073f9d..0f2ab70 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.3.0 +rhel_version=8.4.0 # Check we're in the right directory. if [ ! -f libguestfs.spec ]; then diff --git a/SPECS/libguestfs.spec b/SPECS/libguestfs.spec index f70763f..91f50af 100644 --- a/SPECS/libguestfs.spec +++ b/SPECS/libguestfs.spec @@ -36,7 +36,7 @@ Summary: Access and modify virtual machine disk images Name: libguestfs Epoch: 1 Version: 1.40.2 -Release: 24%{?dist} +Release: 27%{?dist} License: LGPLv2+ # Source and patches. @@ -54,87 +54,101 @@ ExclusiveArch: x86_64 %{power64} aarch64 s390x # to the current directory. # Patches. -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 -Patch0068: 0068-RHEL-8-Remove-User-Mode-Linux-RHBZ-1144197.patch -Patch0069: 0069-RHEL-8-v2v-Select-correct-qemu-binary-for-o-qemu-mod.patch -Patch0070: 0070-RHEL-8-v2v-Disable-the-qemu-boot-option-RHBZ-1147313.patch -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-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 +Patch0001: 0001-daemon-lib-Replace-deprecated-security_context_t-wit.patch +Patch0002: 0002-caml_named_value-returns-const-value-pointer-in-OCam.patch +Patch0003: 0003-ocaml-Change-calls-to-caml_named_value-to-cope-with-.patch +Patch0004: 0004-ocaml-Use-caml_alloc_initialized_string-instead-of-m.patch +Patch0005: 0005-ocaml-Use-caml_alloc_initialized_string-instead-of-m.patch +Patch0006: 0006-ocaml-Change-calls-to-caml_named_value-to-cope-with-.patch +Patch0007: 0007-cat-Fix-GCC-10-warning.patch +Patch0008: 0008-builder-Fix-const-correctness-for-OCaml-4.10.patch +Patch0009: 0009-mlxml-Fix-pointed-target-signedness.patch +Patch0010: 0010-common-mlpcre-add-offset-flag-for-PCRE.matches.patch +Patch0011: 0011-v2v-add-Var_expander.patch +Patch0012: 0012-v2v-add-o-json-output-mode.patch +Patch0013: 0013-inspect-fix-icon-of-RHEL.patch +Patch0014: 0014-v2v-warn-when-the-guest-has-direct-network-interface.patch +Patch0015: 0015-v2v-update-documentation-on-nbdkit-RHBZ-1605242.patch +Patch0016: 0016-v2v-linux-do-not-uninstall-open-vm-tools-w-ubuntu-se.patch +Patch0017: 0017-v2v-linux-canonicalize-module-path-for-arch-detectio.patch +Patch0018: 0018-v2v-linux-improve-arch-detection-from-modules-RHBZ-1.patch +Patch0019: 0019-Use-proper-label-for-nbdkit-sockets.patch +Patch0020: 0020-v2v-start-reading-the-new-libvirt-firmware-autoselec.patch +Patch0021: 0021-common-mltools-move-the-code-for-machine-readable-up.patch +Patch0022: 0022-common-mltools-make-sure-machine-readable-output-is-.patch +Patch0023: 0023-common-mltools-allow-fd-for-machine-readable-output.patch +Patch0024: 0024-OCaml-tools-output-messages-into-JSON-for-machine-re.patch +Patch0025: 0025-OCaml-tools-fix-3999-3339-typo.patch +Patch0026: 0026-v2v-remove-extra-nbdkit-bit-from-documentation-RHBZ-.patch +Patch0027: 0027-v2v-i-vmx-Use-scp-T-option-if-available-to-unbreak-s.patch +Patch0028: 0028-v2v-Allow-Windows-virtio-ISO-to-be-a-block-device-as.patch +Patch0029: 0029-v2v-Set-DISKTYPE-2-in-RHV-and-VDSM-meta-files-RHBZ-1.patch +Patch0030: 0030-v2v-rhv-upload-plugin-improve-wait-logic-after-final.patch +Patch0031: 0031-v2v-o-rhv-upload-check-whether-the-cluster-exists.patch +Patch0032: 0032-v2v-o-rhv-upload-split-vmcheck-out-of-precheck.patch +Patch0033: 0033-v2v-o-rhv-upload-change-precheck-script-to-return-a-.patch +Patch0034: 0034-v2v-o-rhv-upload-improve-lookup-of-specified-resourc.patch +Patch0035: 0035-v2v-o-rhv-upload-tell-whether-a-SD-actually-exists.patch +Patch0036: 0036-v2v-add-output-disk_copied-hook.patch +Patch0037: 0037-v2v-o-rhv-upload-collect-disks-UUIDs-right-after-cop.patch +Patch0038: 0038-v2v-o-rhv-upload-add-oo-rhv-disk-uuid-option.patch +Patch0039: 0039-v2v-o-rhv-upload-make-oo-rhv-cafile-optional.patch +Patch0040: 0040-v2v-Fix-default-graphics-driver-for-SUSE-guests.patch +Patch0041: 0041-v2v-windows-Add-a-helper-function-for-installing-Pow.patch +Patch0042: 0042-v2v-Copy-static-IP-address-information-over-for-Wind.patch +Patch0043: 0043-New-API-luks_uuid.patch +Patch0044: 0044-options-Fix-segfault-when-multiple-key-parameters-gi.patch +Patch0045: 0045-options-Simplify-selector-parsing-for-key-options.patch +Patch0046: 0046-options-Allow-multiple-key-parameters.patch +Patch0047: 0047-options-rename-key.device-as-key.id.patch +Patch0048: 0048-options-allow-a-UUID-as-identifier-for-key.patch +Patch0049: 0049-docs-remove-paragraph-about-VMware-tools-on-Windows-.patch +Patch0050: 0050-mlcustomize-Trim-whitespaces-from-commands-read-from.patch +Patch0051: 0051-openstack-Increase-Cinder-volume-attach-timeout-to-5.patch +Patch0052: 0052-v2v-o-rhv-upload-check-for-a-valid-image-transfer-ri.patch +Patch0053: 0053-rhv-upload-Check-status-more-frequently.patch +Patch0054: 0054-rhv-upload-Show-transfer-id-in-error-message.patch +Patch0055: 0055-rhv-upload-Fix-waiting-for-transfer.patch +Patch0056: 0056-v2v-Optimize-convert-for-images-with-small-holes.patch +Patch0057: 0057-v2v-o-rhv-upload-Make-oo-rhv-cafile-optional-in-all-.patch +Patch0058: 0058-docs-Fix-update-crypto-policies-command-RHBZ-1791257.patch +Patch0059: 0059-add-versioned-directory-for-guest-agent-on-EL8.patch +Patch0060: 0060-v2v-fix-path-to-source-when-copying-files-from-guest.patch +Patch0061: 0061-v2v-windows-install-QEMU-Guest-Agent-MSI.patch +Patch0062: 0062-windows-small-tweaks-of-qemu-ga-firstboot-script.patch +Patch0063: 0063-windows-fix-detection-of-qemu-ga-installer-on-RHV.patch +Patch0064: 0064-windows-delay-installation-of-qemu-ga-MSI.patch +Patch0065: 0065-daemon-xattr-Refactor-code-which-splits-attr-names-f.patch +Patch0066: 0066-daemon-Add-filter_list-utility-function.patch +Patch0067: 0067-daemon-xattr-Filter-out-user.WofCompressedData-from-.patch +Patch0068: 0068-mltools-add-run_in_guest_command-helper.patch +Patch0069: 0069-customize-port-do_run-to-run_in_guest_command.patch +Patch0070: 0070-sysprep-add-a-update_system_ca_store-side-effect.patch +Patch0071: 0071-sysprep-ca-certificates-request-system-CA-store-upda.patch +Patch0072: 0072-sysprep-add-IPA-offline-unenrollment-RHBZ-1789592.patch +Patch0073: 0073-sysprep-add-Kerberos-keytab-file-removal.patch +Patch0074: 0074-vCenter-fix-parsing-of-HTTP-status-string-RHBZ-18373.patch +Patch0075: 0075-RHEL-8-Remove-libguestfs-live-RHBZ-798980.patch +Patch0076: 0076-RHEL-8-Remove-9p-APIs-from-RHEL-RHBZ-921710.patch +Patch0077: 0077-RHEL-8-Disable-unsupported-remote-drive-protocols-RH.patch +Patch0078: 0078-RHEL-8-Remove-User-Mode-Linux-RHBZ-1144197.patch +Patch0079: 0079-RHEL-8-v2v-Select-correct-qemu-binary-for-o-qemu-mod.patch +Patch0080: 0080-RHEL-8-v2v-Disable-the-qemu-boot-option-RHBZ-1147313.patch +Patch0081: 0081-RHEL-8-Disable-alternate-Augeas-lenses.patch +Patch0082: 0082-RHEL-8-Fix-list-of-supported-sound-cards-to-match-RH.patch +Patch0083: 0083-RHEL-8-Reject-use-of-libguestfs-winsupport-features-.patch +Patch0084: 0084-RHEL-8-Fix-tests-for-libguestfs-winsupport.patch +Patch0085: 0085-RHEL-8-tests-Disable-daemon-tests-that-require-the-u.patch +Patch0086: 0086-RHEL-8-v2v-Disable-the-virt-v2v-in-place-option.patch +Patch0087: 0087-RHEL-8-v2v-i-disk-force-VNC-as-display-RHBZ-1372671.patch +Patch0088: 0088-RHEL-8-v2v-do-not-mention-SUSE-Xen-hosts-RHBZ-143020.patch +Patch0089: 0089-RHEL-8-v2v-rhv-upload-Remove-restriction-on-oa-spars.patch +Patch0090: 0090-RHEL-8-use-platform-python.patch +Patch0091: 0091-RHEL-8-point-to-KB-for-supported-v2v-hypervisors-gue.patch +Patch0092: 0092-lib-Increase-default-memsize-to-1280-RHBZ-1837765.patch +Patch0093: 0093-tar-in-Add-workaround-because-tar-doesn-t-restore-ca.patch +Patch0094: 0094-mlcustomize-Refactor-SELinux_relabel-code.patch +Patch0095: 0095-mlcustomize-Fall-back-to-autorelabel-if-specfile-doe.patch # Use git for patch management. BuildRequires: git @@ -1265,6 +1279,19 @@ install -m 0644 utils/boot-benchmark/boot-benchmark.1 $RPM_BUILD_ROOT%{_mandir}/ %changelog +* Tue Jan 05 2021 Richard W.M. Jones - 1:1.40.2-27 +- selinux-relabel does not work if SELINUXTYPE != targeted +- tar-in command does not allow restoring file capabilities + resolves: rhbz#1384241 rhbz#1828952 + +* Mon Jan 04 2021 Richard W.M. Jones - 1:1.40.2-26 +- insufficient default memsize to open anaconda default RHEL 8.2 luks device + resolves: rhbz#1837765 + +* Mon Jul 20 2020 Pino Toscano - 1:1.40.2-25 +- v2v: handle HTTP/2 replies from vCenter + resolves: rhbz#1854380 + * Wed Jun 24 2020 Pino Toscano - 1:1.40.2-24 - v2v: ship a newer version of rhev-apt.exe resolves: rhbz#1849997