From 286cb463a01696250ede820971b34f9ad8717517 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Thu, 5 Dec 2024 13:36:29 +0000 Subject: [PATCH] in-place: Add new -O option to write inspector XML When using virt-v2v-in-place there is no easy way to get the post-conversion metadata, such as the operating system and firmware that virt-v2v detected inside the guest. This commit adds new, optional '-O output.xml' to write this information out to a file. The format is identical to virt-v2v-inspector (and roughly a superset of virt-inspector). Fixes: https://issues.redhat.com/browse/RHEL-58032 Thanks: Martin Necas (cherry picked from commit 2f0958e5ac5c3442c2771518c5b73d6ebcd5bd4a) (cherry picked from commit 3dc5eb5c76fd6be2108c5b3907d9d31bbacd00a5) --- docs/virt-v2v-in-place.pod | 18 +++++++++ in-place/Makefile.am | 2 + in-place/in_place.ml | 39 +++++++++++++----- tests/Makefile.am | 2 + tests/test-in-place-xml.sh | 81 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 132 insertions(+), 10 deletions(-) create mode 100755 tests/test-in-place-xml.sh diff --git a/docs/virt-v2v-in-place.pod b/docs/virt-v2v-in-place.pod index 4057dae5..34e99cf0 100644 --- a/docs/virt-v2v-in-place.pod +++ b/docs/virt-v2v-in-place.pod @@ -7,10 +7,12 @@ virt-v2v-in-place - Convert a guest to use KVM in-place virt-v2v-in-place -i disk [other -i* options] [virt-customize options] filename + [-O output.xml] virt-v2v-in-place -i libvirt|libvirtxml [other -i* options] [virt-customize options] guest + [-O output.xml] =head1 DESCRIPTION @@ -35,6 +37,14 @@ If the guest has been copied to local libvirt then: virt-v2v-in-place -i libvirt guest +=head2 Output XML + +Optionally use the I<-O> option to write post-conversion metadata +about the guest to an XML file. This is in the same format as +L. This can be used, for example, to find out +what operating system and firmware was found inside the guest during +conversion. + =head2 Exit code If virt-v2v-in-place fails it will return a non-zero (error) exit @@ -205,6 +215,14 @@ are mapped to C. See L. +=item B<-O> output.xml + +=item B<-O -> + +If this option is present, write post-conversion metadata about the +guest to the named XML file, or to stdout if I<-O -> is used. This is +in the same format as L. + =item B<--print-source> Print information about the source guest and stop. This option is diff --git a/in-place/Makefile.am b/in-place/Makefile.am index 2fecb3a7..89e3f5f3 100644 --- a/in-place/Makefile.am +++ b/in-place/Makefile.am @@ -57,6 +57,7 @@ OCAMLPACKAGES = \ -I $(top_builddir)/lib \ -I $(top_builddir)/input \ -I $(top_builddir)/convert \ + -I $(top_builddir)/inspector \ -I $(top_builddir)/common/mlstdutils \ -I $(top_builddir)/common/mlutils \ -I $(top_builddir)/common/mlgettext \ @@ -103,6 +104,7 @@ OCAMLLINKFLAGS = \ mlv2vlib.$(MLARCHIVE) \ mlconvert.$(MLARCHIVE) \ mlinput.$(MLARCHIVE) \ + create_inspector_xml.$(MLOBJECT) \ $(LINK_CUSTOM_OCAMLC_ONLY) virt_v2v_in_place_DEPENDENCIES = \ diff --git a/in-place/in_place.ml b/in-place/in_place.ml index 42075139..c77533e7 100644 --- a/in-place/in_place.ml +++ b/in-place/in_place.ml @@ -28,6 +28,12 @@ open Getopt.OptionName open Types open Utils +open Create_inspector_xml + +type output_xml_option = + | No_output_xml | Output_xml_to_stdout + | Output_xml_to_file of string + (* Matches --mac command line parameters. *) let mac_re = PCRE.compile "^([[:xdigit:]]{2}:[[:xdigit:]]{2}:[[:xdigit:]]{2}:[[:xdigit:]]{2}:[[:xdigit:]]{2}:[[:xdigit:]]{2}):(network|bridge|ip):(.*)$" let mac_ip_re = PCRE.compile "^([[:xdigit:]]|:|\\.)+$" @@ -61,6 +67,13 @@ let rec main () = in let network_map = Networks.create () in + + let output_xml = ref No_output_xml in + let set_output_xml_option filename = + if filename = "-" then output_xml := Output_xml_to_stdout + else output_xml := Output_xml_to_file filename + in + let static_ips = ref [] in let rec add_network str = match String.split ":" str with @@ -172,6 +185,8 @@ let rec main () = 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’"; + [ S 'O' ], Getopt.String ("output.xml", set_output_xml_option), + s_"Set the output filename"; [ L"print-source" ], Getopt.Set print_source, s_"Print source and stop"; [ L"root" ], Getopt.String ("ask|... ", set_root_choice), @@ -228,6 +243,7 @@ read the man page virt-v2v-in-place(1). let customize_ops = get_customize_ops () in let input_conn = !input_conn in let input_mode = !input_mode in + let output_xml = !output_xml in let print_source = !print_source in let root_choice = !root_choice in let static_ips = !static_ips in @@ -246,6 +262,7 @@ read the man page virt-v2v-in-place(1). pr "mac-option\n"; pr "mac-ip-option\n"; pr "customize-ops\n"; + pr "output-xml-option\n"; pr "input:disk\n"; pr "input:libvirt\n"; pr "input:libvirtxml\n"; @@ -348,16 +365,18 @@ read the man page virt-v2v-in-place(1). ignore (Sys.command cmd) ); - (* XXX Should we create target metadata and if so where? - * - * If the input mode is libvirt, there is an argument for - * updating the libvirt XML of the guest. If the input - * mode is disk, maybe we should write .xml. - * - * For the moment we just ignore the output from the - * conversion step. - *) - ignore (inspect, target_meta); + (* Write the post-conversion metadata, if asked. *) + let chan = + match output_xml with + | No_output_xml -> None + | Output_xml_to_stdout -> Some Stdlib.stdout + | Output_xml_to_file filename -> Some (open_out filename) in + Option.iter ( + fun chan -> + let doc = create_inspector_xml v2vdir inspect target_meta in + DOM.doc_to_chan chan doc; + Stdlib.flush chan + ) chan; message (f_"Finishing off"); (* As the last thing, write a file indicating success before diff --git a/tests/Makefile.am b/tests/Makefile.am index fac18bbe..209034b8 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -82,6 +82,7 @@ TESTS = \ test-i-ova.sh \ test-i-vmx.sh \ test-in-place.sh \ + test-in-place-xml.sh \ test-inspector.sh \ test-it-vddk-io-query.sh \ test-mac.sh \ @@ -240,6 +241,7 @@ EXTRA_DIST += \ test-i-vmx-7.vmx \ test-i-vmx.sh \ test-in-place.sh \ + test-in-place-xml.sh \ test-inspector.sh \ test-it-vddk-io-query.sh \ test-mac-expected.xml \ diff --git a/tests/test-in-place-xml.sh b/tests/test-in-place-xml.sh new file mode 100755 index 00000000..e9580006 --- /dev/null +++ b/tests/test-in-place-xml.sh @@ -0,0 +1,81 @@ +#!/bin/bash - +# libguestfs virt-v2v test script +# Copyright (C) 2014-2024 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 virt-v2v-in-place -O option. + +unset CDPATH +export LANG=C +set -e + +source ./functions.sh +set -e +set -x + +skip_if_skipped +requires test -f ../test-data/phony-guests/windows.img + +img_base="$abs_top_builddir/test-data/phony-guests/windows.img" + +export VIRT_TOOLS_DATA_DIR="$srcdir/../test-data/fake-virt-tools" +export VIRTIO_WIN="$srcdir/../test-data/fake-virtio-win" + +d=$PWD/test-v2v-in-place-xml.d +rm -rf $d +cleanup_fn rm -r $d +mkdir $d + +img="$d/test.qcow2" +qemu-img convert -f raw $img_base -O qcow2 $img + +out="$d/out.xml" + +libvirt_xml="$d/test.xml" +rm -f $libvirt_xml +n=windows +cat > $libvirt_xml < + + $n + 1048576 + + hvm + + + + + + + + + + + +EOF + +$VG virt-v2v-in-place --debug-gc -i libvirt -ic "test://$libvirt_xml" \ + $n -O $out +cat $out + +# Expect certain elements to be present. +grep '^virt-v2v-inspector' $out +grep '' $out +grep "" $out +grep 'windows' $out +grep 'win2k22' $out