From fb8a4d851946677d5c79afb575267f17a8b649a5 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Tue, 29 Apr 2025 13:44:07 +0100 Subject: [PATCH] input: Add -io vddk-file=... option This option allows the file parameter of nbdkit-vddk-plugin to be overridden. Useful for performing conversions of snapshots, since the filename returned by libvirt may not be the correct snapshot filename. This also updates the common submodule, pulling in: Richard W.M. Jones (2): mlstdutils: Implement String.implode mlstdutils: Add List.make function Suggested-by: Martin Necas Fixes: https://issues.redhat.com/browse/RHEL-88543 (cherry picked from commit 5328142e6a9faae1db99c646991d27badc6efe91) --- common | 2 +- docs/virt-v2v-input-vmware.pod | 9 +++++---- input/input_vddk.ml | 35 ++++++++++++++++++++++++++-------- 3 files changed, 33 insertions(+), 13 deletions(-) Submodule common 57c2b3f0..3873d593: diff --git a/common/mlstdutils/std_utils.ml b/common/mlstdutils/std_utils.ml index 212a1513..6880fce5 100644 --- a/common/mlstdutils/std_utils.ml +++ b/common/mlstdutils/std_utils.ml @@ -409,6 +409,14 @@ module List = struct let push_back_list xsp xs = xsp := !xsp @ xs let push_front_list xs xsp = xsp := xs @ !xsp + + let make n x = + let rec loop acc = function + | 0 -> acc + | i when i > 0 -> loop (x :: acc) (i-1) + | _ -> invalid_arg "make" + in + loop [] n end let (//) = Filename.concat diff --git a/common/mlstdutils/std_utils.mli b/common/mlstdutils/std_utils.mli index 72a2d44c..ae6004b2 100644 --- a/common/mlstdutils/std_utils.mli +++ b/common/mlstdutils/std_utils.mli @@ -291,6 +291,9 @@ module List : sig [push_front_list] is like {!push_front} above, except it prepends a list to the list reference. *) + + val make : int -> 'a -> 'a list + (** [make n x] returns a list with [x] repeated [n] times. *) end (** Override the List module from stdlib. *) diff --git a/common/mlstdutils/std_utils_tests.ml b/common/mlstdutils/std_utils_tests.ml index 4e368152..5f8c1440 100644 --- a/common/mlstdutils/std_utils_tests.ml +++ b/common/mlstdutils/std_utils_tests.ml @@ -179,6 +179,12 @@ let test_which ctx = end; () +(* Test List.make. *) +let test_list_make ctx = + assert_equal_stringlist [] (List.make 0 "1"); + assert_equal_stringlist ["1"; "1"; "1"] (List.make 3 "1"); + assert_raises (Invalid_argument "make") (fun () -> List.make (-1) "1") + (* Suites declaration. *) let suite = "mllib Std_utils" >::: @@ -195,6 +201,7 @@ let suite = "strings.span" >:: test_string_span; "strings.chomp" >:: test_string_chomp; "which" >:: test_which; + "list.make" >:: test_list_make; ] let () = diff --git a/docs/virt-v2v-input-vmware.pod b/docs/virt-v2v-input-vmware.pod index b28268c2..80ca560a 100644 --- a/docs/virt-v2v-input-vmware.pod +++ b/docs/virt-v2v-input-vmware.pod @@ -342,10 +342,11 @@ SSL thumbprint: -o local -os /var/tmp Other options that you might need to add in rare circumstances include -I<-io vddk-config>, I<-io vddk-cookie>, I<-io vddk-nfchostport>, -I<-io vddk-port>, I<-io vddk-snapshot>, and I<-io vddk-transports>, -which are all explained in the L documentation. -Do not use these options unless you know what you are doing. +I<-io vddk-config>, I<-io vddk-cookie>, I<-io vddk-file>, +I<-io vddk-nfchostport>, I<-io vddk-port>, I<-io vddk-snapshot>, and +I<-io vddk-transports>, which are all explained in the +L documentation. Do not use these options +unless you know what you are doing. =head2 VDDK: Debugging VDDK failures diff --git a/input/input_vddk.ml b/input/input_vddk.ml index 659ff08f..316fe5f8 100644 --- a/input/input_vddk.ml +++ b/input/input_vddk.ml @@ -50,6 +50,7 @@ All other settings are optional: -io vddk-config=FILE VDDK configuration file -io vddk-cookie=COOKIE VDDK cookie + -io vddk-file=FILE Override nbdkit-vddk-plugin file= parameter -io vddk-libdir=LIBDIR VDDK library parent directory -io vddk-nfchostport=PORT VDDK nfchostport -io vddk-noextents=true Avoid slow VDDK QueryAllocatedBlocks API @@ -70,6 +71,7 @@ information on these settings. let vddk_option_keys = [ "config"; "cookie"; + "file"; "libdir"; "nfchostport"; "noextents"; @@ -90,11 +92,6 @@ information on these settings. (key, value) ) options.input_options in - (* Check no option appears more than once. *) - let keys = List.map fst io_options in - if List.length keys <> List.length (List.sort_uniq compare keys) then - error (f_"-it vddk: duplicate -io options on the command line"); - (* thumbprint is mandatory. *) if not (List.mem_assoc "thumbprint" io_options) then error (f_"You must pass the ‘-io vddk-thumbprint’ option with the \ @@ -137,6 +134,7 @@ information on these settings. (* Parse the libvirt XML. *) let source, disks, xml = parse_libvirt_domain conn guest in + let nr_disks = List.length disks in (* Find the element from the XML. This was added * in libvirt >= 3.7 and is required. @@ -188,9 +186,27 @@ information on these settings. let transports = try Some (List.assoc "transports" io_options) with Not_found -> None in + (* If -io vddk-file was given, there must be exactly one per guest + * disk. Get the list of file overrides. + *) + let file_overrides = + if List.mem_assoc "file" io_options then ( + let fos = + List.filter_map (function ("file",b) -> Some (Some b) | _ -> None) + io_options in + if List.length fos <> nr_disks then + error (f_"‘-io vddk-file=’ must be used exactly %d times") nr_disks; + fos + ) + else ( + (* List of no overrides. *) + List.make nr_disks None + ) in + (* Create an nbdkit instance for each disk. *) + List.combine disks file_overrides |> List.iteri ( - fun i { d_format = format; d_type } -> + fun i ({ d_format = format; d_type }, file_override) -> let socket = sprintf "%s/in%d" dir i in On_exit.unlink socket; @@ -198,7 +214,10 @@ information on these settings. | BlockDev _ | NBD _ | HTTP _ -> (* These should never happen? *) assert false - | LocalFile file -> + | LocalFile orig_file -> + (* If -io vddk-file, override it here. *) + let file = Option.value file_override ~default:orig_file in + (* The attribute returned by the libvirt * VMX driver looks like "[datastore] path". We can use it * directly as the nbdkit file= parameter, and it is passed @@ -215,7 +234,7 @@ information on these settings. file in let _, pid = Nbdkit.run_unix socket nbdkit in On_exit.kill pid - ) disks; + ); source end