From 96e4e9a036cfbf069b6383916687c3dac804f55a 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 18310179..3da17d53: 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/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 982dff17..36d5d624 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-port=PORT VDDK port @@ -69,6 +70,7 @@ information on these settings. let vddk_option_keys = [ "config"; "cookie"; + "file"; "libdir"; "nfchostport"; "port"; @@ -88,11 +90,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 \ @@ -135,6 +132,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. @@ -183,9 +181,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; @@ -193,7 +209,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 @@ -209,7 +228,7 @@ information on these settings. file in let _, pid = Nbdkit.run_unix socket nbdkit in On_exit.kill pid - ) disks; + ); source end