commit 9812f4a82060c9578798c7182f757f8259bef760 Author: MSVSphere Packaging Team Date: Tue Nov 26 19:37:57 2024 +0300 import virt-v2v-2.5.6-1.el10 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c0cbdfa --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +SOURCES/libguestfs.keyring +SOURCES/virt-v2v-2.5.6.tar.gz diff --git a/.virt-v2v.metadata b/.virt-v2v.metadata new file mode 100644 index 0000000..4a8116e --- /dev/null +++ b/.virt-v2v.metadata @@ -0,0 +1,2 @@ +1bbc40f501a7fef9eef2a39b701a71aee2fea7c4 SOURCES/libguestfs.keyring +7c49844a2ffb54d6fcb58eca1dbf57b110d5d47e SOURCES/virt-v2v-2.5.6.tar.gz diff --git a/SOURCES/0001-docs-Note-that-mac-len-field-is-now-optional.patch b/SOURCES/0001-docs-Note-that-mac-len-field-is-now-optional.patch new file mode 100644 index 0000000..4c74f1d --- /dev/null +++ b/SOURCES/0001-docs-Note-that-mac-len-field-is-now-optional.patch @@ -0,0 +1,28 @@ +From 7800049c5612e6ffb30be7f8862d147d82976ae8 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Wed, 31 Jul 2024 10:09:50 +0100 +Subject: [PATCH] docs: Note that --mac len field is now optional + +Reported-by: Ming Xie +Updates: commit 159fda411d2f75b087106e7293d273ae142c9fbe +--- + docs/virt-v2v.pod | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/docs/virt-v2v.pod b/docs/virt-v2v.pod +index b53face6..dfe92d77 100644 +--- a/docs/virt-v2v.pod ++++ b/docs/virt-v2v.pod +@@ -394,9 +394,9 @@ 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. ++is the optional gateway IP address. C is the optional subnet ++mask length (an integer). The final parameters are zero or more ++nameserver IP addresses. + + This option can be supplied zero or more times. + diff --git a/SOURCES/0002-convert-More-robust-qemu-ga-installation-change-path.patch b/SOURCES/0002-convert-More-robust-qemu-ga-installation-change-path.patch new file mode 100644 index 0000000..1bf5676 --- /dev/null +++ b/SOURCES/0002-convert-More-robust-qemu-ga-installation-change-path.patch @@ -0,0 +1,207 @@ +From c57ec4fd5d4942d2320aec4a6b01977dabb87f83 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 1 Aug 2024 09:01:47 +0100 +Subject: [PATCH] convert: More robust qemu-ga installation, change paths + +Add a commit from the common submodule to attempt to make qemu-ga +installation more robust on Windows. + +Rename network configuration Powershell script from "v2vnetcf" to +"network-configuration". I also dropped the ".ps1" extension as the +modified Firstboot.add_firstboot_powershell function now adds this. + +Update the common submodule to get these changes: + +Richard W.M. Jones (3): + mlcustomize: Use Start-Process -Wait to run qemu-ga installer + mlcustomize: Add Firstboot.firstboot_dir function + mlcustomize: Place powershell scripts into \Temp +--- + common | 2 +- + convert/convert_windows.ml | 4 ++-- + 2 files changed, 3 insertions(+), 3 deletions(-) + +Submodule common ae639ba3..d489469f: +diff --git a/common/mlcustomize/firstboot.ml b/common/mlcustomize/firstboot.ml +index 4b9b910b..3bbba714 100644 +--- a/common/mlcustomize/firstboot.ml ++++ b/common/mlcustomize/firstboot.ml +@@ -239,7 +239,22 @@ WantedBy=%s + end + + module Windows = struct +- let rec install_service (g : Guestfs.guestfs) root = ++ (* Create and return the firstboot directory. *) ++ let create_firstboot_dir (g : Guestfs.guestfs) = ++ let rec loop firstboot_dir firstboot_dir_win = function ++ | [] -> firstboot_dir, firstboot_dir_win ++ | dir :: path -> ++ let firstboot_dir = ++ if firstboot_dir = "" then "/" ^ dir else firstboot_dir // dir in ++ let firstboot_dir_win = firstboot_dir_win ^ "\\" ^ dir in ++ let firstboot_dir = g#case_sensitive_path firstboot_dir in ++ g#mkdir_p firstboot_dir; ++ loop firstboot_dir firstboot_dir_win path ++ in ++ loop "" "C:" ["Program Files"; "Guestfs"; "Firstboot"] ++ ++ let rec install_service (g : Guestfs.guestfs) root ++ firstboot_dir firstboot_dir_win = + (* Either rhsrvany.exe or pvvxsvc.exe must exist. + * + * (Check also that it's not a dangling symlink but a real file). +@@ -254,20 +269,7 @@ module Windows = struct + error (f_"One of rhsrvany.exe or pvvxsvc.exe is missing in %s. One of them is required in order to install Windows firstboot scripts. You can get one by building rhsrvany (https://github.com/rwmjones/rhsrvany)") + (virt_tools_data_dir ()) in + +- (* Create a directory for firstboot files in the guest. *) +- let firstboot_dir, firstboot_dir_win = +- let rec loop firstboot_dir firstboot_dir_win = function +- | [] -> firstboot_dir, firstboot_dir_win +- | dir :: path -> +- let firstboot_dir = +- if firstboot_dir = "" then "/" ^ dir else firstboot_dir // dir in +- let firstboot_dir_win = firstboot_dir_win ^ "\\" ^ dir in +- let firstboot_dir = g#case_sensitive_path firstboot_dir in +- g#mkdir_p firstboot_dir; +- loop firstboot_dir firstboot_dir_win path +- in +- loop "" "C:" ["Program Files"; "Guestfs"; "Firstboot"] in +- ++ (* Create a directory for firstboot scripts in the guest. *) + g#mkdir_p (firstboot_dir // "scripts"); + + (* Copy pvvxsvc or rhsrvany to the guest. *) +@@ -339,11 +341,25 @@ echo uninstalling firstboot service + "PWD", REG_SZ firstboot_dir_win ]; + ] in + reg_import reg regedits +- ); +- +- firstboot_dir ++ ) + end + ++let firstboot_dir (g : Guestfs.guestfs) root = ++ let typ = g#inspect_get_type root in ++ ++ match typ with ++ | "linux" -> ++ let dir = Linux.firstboot_dir in ++ g#mkdir_p dir; ++ dir, None ++ ++ | "windows" -> ++ let dir, dir_win = Windows.create_firstboot_dir g in ++ dir, Some dir_win ++ ++ | _ -> ++ error (f_"guest type %s is not supported") typ ++ + let script_count = ref 0 + + let add_firstboot_script (g : Guestfs.guestfs) root ?(prio = 5000) name +@@ -363,7 +379,8 @@ let add_firstboot_script (g : Guestfs.guestfs) root ?(prio = 5000) name + g#chmod 0o755 filename + + | "windows", _ -> +- let firstboot_dir = Windows.install_service g root in ++ let firstboot_dir, firstboot_dir_win = Windows.create_firstboot_dir g in ++ Windows.install_service g root firstboot_dir firstboot_dir_win; + let filename = firstboot_dir // "scripts" // filename ^ ".bat" in + g#write filename (String.unix2dos content) + +@@ -382,15 +399,18 @@ let add_firstboot_powershell g root ?prio name code = + *) + assert (g#inspect_get_type root = "windows"); + +- let windows_systemroot = g#inspect_get_windows_systemroot root in +- +- (* Create the temporary directory to put the Powershell file. *) +- let tempdir = sprintf "%s/Temp" windows_systemroot in ++ (* Place the Powershell script into firstboot_dir/Temp *) ++ let firstboot_dir, firstboot_dir_win = Windows.create_firstboot_dir g in ++ let tempdir = sprintf "%s/Temp" firstboot_dir in + g#mkdir_p tempdir; +- let ps_path = sprintf "%s/%s" tempdir name in ++ ++ let ps_path = sprintf "%s/%s.ps1" tempdir name in ++ let ps_path_win = sprintf "%s\\Temp\\%s.ps1" firstboot_dir_win name in + let code = String.concat "\r\n" code ^ "\r\n" in + g#write ps_path code; + +- let fb = sprintf "powershell.exe -ExecutionPolicy ByPass -NoProfile -file %s" +- ps_path in ++ (* Create a regular firstboot bat that just invokes powershell *) ++ let fb = ++ sprintf "powershell.exe -ExecutionPolicy ByPass -NoProfile -file \"%s\"" ++ ps_path_win in + add_firstboot_script g root ?prio name fb +diff --git a/common/mlcustomize/firstboot.mli b/common/mlcustomize/firstboot.mli +index 8231af65..34ff0690 100644 +--- a/common/mlcustomize/firstboot.mli ++++ b/common/mlcustomize/firstboot.mli +@@ -16,6 +16,23 @@ + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *) + ++val firstboot_dir : Guestfs.guestfs -> string -> string * string option ++(** [firstboot_dir g root] ++ returns the path of the firstboot directory, creating it in ++ the guest if necessary. ++ ++ This returns the name of the directory as a guestfs path, and ++ optionally the name as a Windows path (only for Windows guests). ++ ++ For Linux this could be [/usr/lib/virt-sysprep, None] ++ ++ For Windows this could be ["/Program Files/Guestfs/Firstboot", ++ Some "C:\Program Files\Guestfs\Firstboot"] ++ ++ Additional files that are used during firstboot can be placed ++ in this directory, but be careful not to conflict with files ++ and scripts added by the firstboot process itself. *) ++ + val add_firstboot_script : Guestfs.guestfs -> string -> ?prio:int -> string -> + string -> unit + (** [add_firstboot_script g root prio name content] adds a firstboot +diff --git a/common/mlcustomize/inject_virtio_win.ml b/common/mlcustomize/inject_virtio_win.ml +index eee93669..b04a3b38 100644 +--- a/common/mlcustomize/inject_virtio_win.ml ++++ b/common/mlcustomize/inject_virtio_win.ml +@@ -592,11 +592,11 @@ and configure_qemu_ga t files = + add "# Run qemu-ga installers"; + List.iter ( + fun msi_path -> +- add (sprintf "C:\\%s /norestart /qn /l+*vx C:\\%s.log" ++ add (sprintf "Start-Process -Wait -FilePath \"C:\\%s\" -ArgumentList \"/norestart\",\"/qn\",\"/l+*vx\",\"C:\\%s.log\"" + msi_path msi_path) + ) files; + +- Firstboot.add_firstboot_powershell t.g t.root "install-qemu-ga.ps1" !script ++ Firstboot.add_firstboot_powershell t.g t.root "install-qemu-ga" !script + + and configure_blnsvr t blnsvr = + let cmd = sprintf "\ +diff --git a/convert/convert_windows.ml b/convert/convert_windows.ml +index 2d6e2059..52ca5bbe 100644 +--- a/convert/convert_windows.ml ++++ b/convert/convert_windows.ml +@@ -397,7 +397,7 @@ let convert (g : G.guestfs) _ inspect i_firmware block_driver _ static_ips = + %systemroot%\\Sysnative\\PnPutil -i -a \ + %systemroot%\\Drivers\\Virtio\\*.inf" in + +- (* Set priority higher than that of "v2vnetcf.ps1" firstboot script. *) ++ (* Set priority higher than that of "network-configure" firstboot script. *) + Firstboot.add_firstboot_script g inspect.i_root ~prio:2000 + "pnputil install drivers" fb_script; + +@@ -674,7 +674,7 @@ let convert (g : G.guestfs) _ inspect i_firmware block_driver _ static_ips = + * Powershell script which runs at boot. + *) + if static_ips <> [] then ( +- let psh_filename = "v2vnetcf.ps1" in ++ let psh_filename = "network-configure" in + let psh = ref [] in + let add = List.push_back psh in + diff --git a/SOURCES/0003-common-mlcustomize-Inject-qemu-ga-blnsvr-into-firstb.patch b/SOURCES/0003-common-mlcustomize-Inject-qemu-ga-blnsvr-into-firstb.patch new file mode 100644 index 0000000..ce13d10 --- /dev/null +++ b/SOURCES/0003-common-mlcustomize-Inject-qemu-ga-blnsvr-into-firstb.patch @@ -0,0 +1,116 @@ +From 168eacf977ca49e96bc63ddc4109c27515ac0277 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 1 Aug 2024 10:36:52 +0100 +Subject: [PATCH] common: mlcustomize: Inject qemu-ga & blnsvr into + /Temp + +Update common submodule to pick up this further change which should +mean that for all Windows conversions, everything is confined to +C:\Program Files\Guestfs\Firstboot (except the virtio drivers +themselves). + +Richard W.M. Jones (1): + mlcustomize: Inject qemu-ga & blnsvr into /Temp +--- + common | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Submodule common d489469f..04116678: +diff --git a/common/mlcustomize/inject_virtio_win.ml b/common/mlcustomize/inject_virtio_win.ml +index b04a3b38..2981bff5 100644 +--- a/common/mlcustomize/inject_virtio_win.ml ++++ b/common/mlcustomize/inject_virtio_win.ml +@@ -263,14 +263,28 @@ let rec inject_virtio_win_drivers ({ g } as t) reg = + } + ) + +-and inject_qemu_ga t = +- let msi_files = copy_qemu_ga t in ++and inject_qemu_ga ({ g; root } as t) = ++ (* Copy the qemu-ga MSI(s) to the guest. *) ++ let dir, dir_win = Firstboot.firstboot_dir g root in ++ let dir_win = Option.value dir_win ~default:dir in ++ let tempdir = sprintf "%s/Temp" dir in ++ let tempdir_win = sprintf "%s\\Temp" dir_win in ++ g#mkdir_p tempdir; ++ ++ let msi_files = copy_qemu_ga t tempdir in + if msi_files <> [] then +- configure_qemu_ga t msi_files; ++ configure_qemu_ga t tempdir_win msi_files; + msi_files <> [] (* return true if we found some qemu-ga MSI files *) + +-and inject_blnsvr t = +- let files = copy_blnsvr t in ++and inject_blnsvr ({ g; root } as t) = ++ (* Copy the files to the guest. *) ++ let dir, dir_win = Firstboot.firstboot_dir g root in ++ let dir_win = Option.value dir_win ~default:dir in ++ let tempdir = sprintf "%s/Temp" dir in ++ let tempdir_win = sprintf "%s\\Temp" dir_win in ++ g#mkdir_p tempdir; ++ ++ let files = copy_blnsvr t tempdir in + match files with + | [] -> false (* Didn't find or install anything. *) + +@@ -278,7 +292,7 @@ and inject_blnsvr t = + * drivers/by-driver). Pick the first. + *) + | blnsvr :: _ -> +- configure_blnsvr t blnsvr; ++ configure_blnsvr t tempdir_win blnsvr; + true + + and add_guestor_to_registry t ((g, root) as reg) drv_name drv_pciid = +@@ -360,13 +374,13 @@ and copy_drivers t 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 t = +- copy_from_virtio_win t "/" "/" (virtio_iso_path_matches_qemu_ga t) ++and copy_qemu_ga t tempdir = ++ copy_from_virtio_win t "/" tempdir (virtio_iso_path_matches_qemu_ga t) + (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_blnsvr t = +- copy_from_virtio_win t "/" "/" (virtio_iso_path_matches_blnsvr t) ++and copy_blnsvr t tempdir = ++ copy_from_virtio_win t "/" tempdir (virtio_iso_path_matches_blnsvr t) + (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.")) + +@@ -578,7 +592,7 @@ and copy_from_libosinfo { g; i_osinfo; i_arch } destdir = + (* Install qemu-ga. [files] is the non-empty list of possible qemu-ga + * installers we detected. + *) +-and configure_qemu_ga t files = ++and configure_qemu_ga t tempdir_win files = + let script = ref [] in + let add = List.push_back script in + +@@ -591,16 +605,17 @@ and configure_qemu_ga t files = + add ""; + add "# Run qemu-ga installers"; + List.iter ( +- fun msi_path -> +- add (sprintf "Start-Process -Wait -FilePath \"C:\\%s\" -ArgumentList \"/norestart\",\"/qn\",\"/l+*vx\",\"C:\\%s.log\"" +- msi_path msi_path) ++ fun msi -> ++ (* [`] is an escape char for quotes *) ++ add (sprintf "Start-Process -Wait -FilePath \"%s\\%s\" -ArgumentList \"/norestart\",\"/qn\",\"/l+*vx\",\"`\"%s\\%s.log`\"\"" ++ tempdir_win msi tempdir_win msi) + ) files; + + Firstboot.add_firstboot_powershell t.g t.root "install-qemu-ga" !script + +-and configure_blnsvr t blnsvr = ++and configure_blnsvr t tempdir_win blnsvr = + let cmd = sprintf "\ + @echo off\n\ + echo Installing %s\n\ +- c:\\%s -i\n" blnsvr blnsvr in +- Firstboot.add_firstboot_script t.g t.root (sprintf "install-%s" blnsvr) cmd ++ \"%s\\%s\" -i\n" blnsvr tempdir_win blnsvr in ++ Firstboot.add_firstboot_script t.g t.root "install-blnsvr" cmd diff --git a/SOURCES/0004-docs-Add-a-note-about-removal-of-VMware-Tools-on-Win.patch b/SOURCES/0004-docs-Add-a-note-about-removal-of-VMware-Tools-on-Win.patch new file mode 100644 index 0000000..65d461a --- /dev/null +++ b/SOURCES/0004-docs-Add-a-note-about-removal-of-VMware-Tools-on-Win.patch @@ -0,0 +1,45 @@ +From c952f310c902e438a8b0b5240a4b486b698bede8 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Mon, 5 Aug 2024 10:08:34 +0100 +Subject: [PATCH] docs: Add a note about removal of VMware Tools on Windows + +We use VMware's recommended method for removal, but we know from +experience that this rarely works. The alternate method being +proposed involves making very invasive changes to the Registry and +filesystem, which are inappropriate for virt-v2v to do and highly +risky. Therefore simply document this, with notes for the virt-v2v +user if they want to try the risky method. + +Fixes: https://issues.redhat.com/browse/RHEL-51169 +Thanks: Yan Vugenfirer +Reported-by: Ming Xie +--- + docs/virt-v2v.pod | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/docs/virt-v2v.pod b/docs/virt-v2v.pod +index dfe92d77..92941026 100644 +--- a/docs/virt-v2v.pod ++++ b/docs/virt-v2v.pod +@@ -1299,6 +1299,21 @@ B Take care not to interrupt the automatic driver installation + process when logging in to the guest for the first time, as this may + prevent the guest from subsequently booting correctly. + ++=head3 Removing VMware Tools from Windows guests ++ ++Virt-v2v attempts to remove VMware Tools. For Windows guests this is ++supposed to happen during the first boot after conversion. ++ ++We use VMware's recommended uninstallation method as that is the ++safest choice. However our experience has shown that this method ++usually fails. If so, VMware Tools must be removed by some other ++method. ++ ++One possible method is described here: ++L ++You should carefully check this script since it makes very invasive ++changes to the Windows Registry and filesystem. ++ + =head2 Free space for conversion + + =head3 Free space in the guest diff --git a/SOURCES/0005-Update-common-submodule.patch b/SOURCES/0005-Update-common-submodule.patch new file mode 100644 index 0000000..c2b6872 --- /dev/null +++ b/SOURCES/0005-Update-common-submodule.patch @@ -0,0 +1,25 @@ +From 7bc9b115baba6df2969451cd6907e2d7543ef22d Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Mon, 5 Aug 2024 10:18:31 +0100 +Subject: [PATCH] Update common submodule + +Richard W.M. Jones (1): + mlcustomize: Write qemu-ga log file name to log.txt +--- + common | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Submodule common 04116678..7b84a370: +diff --git a/common/mlcustomize/inject_virtio_win.ml b/common/mlcustomize/inject_virtio_win.ml +index 2981bff5..afec1e45 100644 +--- a/common/mlcustomize/inject_virtio_win.ml ++++ b/common/mlcustomize/inject_virtio_win.ml +@@ -606,6 +606,8 @@ and configure_qemu_ga t tempdir_win files = + add "# Run qemu-ga installers"; + List.iter ( + fun msi -> ++ add (sprintf "Write-Host \"Writing log to %s\\%s.log\"" ++ tempdir_win msi); + (* [`] is an escape char for quotes *) + add (sprintf "Start-Process -Wait -FilePath \"%s\\%s\" -ArgumentList \"/norestart\",\"/qn\",\"/l+*vx\",\"`\"%s\\%s.log`\"\"" + tempdir_win msi tempdir_win msi) diff --git a/SOURCES/0006-Pull-in-a-fix-to-make-Windows-firstboot-more-reliabl.patch b/SOURCES/0006-Pull-in-a-fix-to-make-Windows-firstboot-more-reliabl.patch new file mode 100644 index 0000000..1c96f71 --- /dev/null +++ b/SOURCES/0006-Pull-in-a-fix-to-make-Windows-firstboot-more-reliabl.patch @@ -0,0 +1,78 @@ +From 50f005f8b7034916588855c15b10a0195bf54b23 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 8 Aug 2024 10:40:24 +0100 +Subject: [PATCH] Pull in a fix to make Windows firstboot more reliable. + +Update the common submodule to get: + +Richard W.M. Jones (2): + mlcustomize: Add some comments to firstboot batch file + mlcustomize: Reboot Windows between each firstboot script + +Document that Windows may now reboot several times after conversion. +--- + common | 2 +- + docs/virt-v2v.pod | 9 ++++++--- + 2 files changed, 7 insertions(+), 4 deletions(-) + +Submodule common 7b84a370..a7883967: +diff --git a/common/mlcustomize/firstboot.ml b/common/mlcustomize/firstboot.ml +index 3bbba714..52e76401 100644 +--- a/common/mlcustomize/firstboot.ml ++++ b/common/mlcustomize/firstboot.ml +@@ -278,6 +278,9 @@ module Windows = struct + (* Write a firstboot.bat control script which just runs the other + * scripts in the directory. Note we need to use CRLF line endings + * in this script. ++ * ++ * XXX It would be better to use powershell here. For some ideas see ++ * https://github.com/HCK-CI/HLK-Setup-Scripts/ + *) + let firstboot_script = sprintf "\ + @echo off +@@ -299,6 +302,7 @@ if not exist \"%%scripts_done%%\" ( + mkdir \"%%scripts_done%%\" + ) + ++:: Pick the next script to run. + for %%%%f in (\"%%scripts%%\"\\*.bat) do ( + echo running \"%%%%f\" + move \"%%%%f\" \"%%scripts_done%%\" +@@ -307,8 +311,17 @@ for %%%%f in (\"%%scripts%%\"\\*.bat) do ( + set elvl=!errorlevel! + echo .... exit code !elvl! + popd ++ ++ :: Reboot the computer. This is necessary to free any locked ++ :: files which may prevent later scripts from running. ++ shutdown /r /t 0 /y ++ ++ :: Exit the script (in case shutdown returns before rebooting). ++ :: On next boot, the whole firstboot service will be called again. ++ exit /b + ) + ++:: Fallthrough here if there are no scripts. + echo uninstalling firstboot service + \"%%firstboot%%\\%s\" -s firstboot uninstall + " firstboot_dir_win srvany in +diff --git a/docs/virt-v2v.pod b/docs/virt-v2v.pod +index 92941026..587b4604 100644 +--- a/docs/virt-v2v.pod ++++ b/docs/virt-v2v.pod +@@ -1295,9 +1295,12 @@ The guest will be bootable after the offline conversion stage, but + will not yet have all necessary drivers installed to work correctly. + These will be installed automatically the first time the guest boots. + +-B Take care not to interrupt the automatic driver installation +-process when logging in to the guest for the first time, as this may +-prevent the guest from subsequently booting correctly. ++B Windows may reboot 4 or more times the first time after ++conversion. This is required to install the required drivers, guest ++agents, remove VMware Tools, and configure the network. Take care not ++to interrupt the automatic driver installation process when logging in ++to the guest for the first time, as this may prevent the guest from ++subsequently booting correctly. + + =head3 Removing VMware Tools from Windows guests + diff --git a/SOURCES/0007-docs-Restate-position-on-removal-of-VMware-Tools.patch b/SOURCES/0007-docs-Restate-position-on-removal-of-VMware-Tools.patch new file mode 100644 index 0000000..1b25ee4 --- /dev/null +++ b/SOURCES/0007-docs-Restate-position-on-removal-of-VMware-Tools.patch @@ -0,0 +1,30 @@ +From e9c0d63b22bcb4c31cfaac00fc1271713c8bd3b3 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 8 Aug 2024 10:56:16 +0100 +Subject: [PATCH] docs: Restate position on removal of VMware Tools + +With the "reboot after every step" change made in the previous commit, +it seems removal of VMware Tools is now more reliable. Update the +notes about this. + +Updates: commit c952f310c902e438a8b0b5240a4b486b698bede8 +--- + docs/virt-v2v.pod | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/docs/virt-v2v.pod b/docs/virt-v2v.pod +index 587b4604..346be606 100644 +--- a/docs/virt-v2v.pod ++++ b/docs/virt-v2v.pod +@@ -1308,9 +1308,8 @@ Virt-v2v attempts to remove VMware Tools. For Windows guests this is + supposed to happen during the first boot after conversion. + + We use VMware's recommended uninstallation method as that is the +-safest choice. However our experience has shown that this method +-usually fails. If so, VMware Tools must be removed by some other +-method. ++safest choice. If this fails, VMware Tools must be manually removed ++by some other method. + + One possible method is described here: + L diff --git a/SOURCES/0008-RHEL-v2v-Select-correct-qemu-binary-for-o-qemu-mode-.patch b/SOURCES/0008-RHEL-v2v-Select-correct-qemu-binary-for-o-qemu-mode-.patch new file mode 100644 index 0000000..9cf3aa6 --- /dev/null +++ b/SOURCES/0008-RHEL-v2v-Select-correct-qemu-binary-for-o-qemu-mode-.patch @@ -0,0 +1,30 @@ +From 73faaa69c32f09436ea8358c507102f2a0a0868e Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Sun, 28 Sep 2014 19:14:43 +0100 +Subject: [PATCH] RHEL: v2v: Select correct qemu binary for -o qemu mode + (RHBZ#1147313). + +RHEL 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. +--- + output/output_qemu.ml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/output/output_qemu.ml b/output/output_qemu.ml +index 26c1ba48..07dae8c2 100644 +--- a/output/output_qemu.ml ++++ b/output/output_qemu.ml +@@ -131,7 +131,7 @@ module QEMU = struct + * 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 diff --git a/SOURCES/0009-RHEL-v2v-Disable-the-qemu-boot-oo-qemu-boot-option-R.patch b/SOURCES/0009-RHEL-v2v-Disable-the-qemu-boot-oo-qemu-boot-option-R.patch new file mode 100644 index 0000000..7fca063 --- /dev/null +++ b/SOURCES/0009-RHEL-v2v-Disable-the-qemu-boot-oo-qemu-boot-option-R.patch @@ -0,0 +1,121 @@ +From b3860f7f91c5c239d06de4a260b8c312f9b49387 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Tue, 30 Sep 2014 10:50:27 +0100 +Subject: [PATCH] RHEL: v2v: Disable the --qemu-boot / -oo qemu-boot option + (RHBZ#1147313). + +This cannot work because there is no Gtk or SDL output mode +in RHEL's qemu-kvm. + +In addition you will have to edit the -display option in the +qemu script. +--- + docs/virt-v2v-output-local.pod | 6 ++---- + docs/virt-v2v.pod | 17 ----------------- + output/output_qemu.ml | 3 +++ + v2v/v2v.ml | 2 -- + 4 files changed, 5 insertions(+), 23 deletions(-) + +diff --git a/docs/virt-v2v-output-local.pod b/docs/virt-v2v-output-local.pod +index d2a1c270..0be37f5e 100644 +--- a/docs/virt-v2v-output-local.pod ++++ b/docs/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 null + +@@ -47,12 +47,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 null> + +diff --git a/docs/virt-v2v.pod b/docs/virt-v2v.pod +index 346be606..81a4b45a 100644 +--- a/docs/virt-v2v.pod ++++ b/docs/virt-v2v.pod +@@ -146,11 +146,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 -oo qemu-boot +- + =head1 OPTIONS + + =over 4 +@@ -522,9 +517,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<-oo qemu-boot> +-option which boots the guest under qemu immediately. +- + =item B<-o> B + + This is the same as I<-o rhv>. +@@ -607,11 +599,6 @@ For I<-o openstack> (L) only, set a guest ID + which is saved on each Cinder volume in the C + volume property. + +-=item B<-oo qemu-boot> +- +-When using I<-o qemu> only, this boots the guest immediately after +-virt-v2v finishes. +- + =item B<-oo verify-server-certificate> + + =item B<-oo verify-server-certificate=>C +@@ -782,10 +769,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> +- +-This is the same as I<-oo qemu-boot>. +- + =item B<-q> + + =item B<--quiet> +diff --git a/output/output_qemu.ml b/output/output_qemu.ml +index 07dae8c2..b6f24565 100644 +--- a/output/output_qemu.ml ++++ b/output/output_qemu.ml +@@ -65,6 +65,9 @@ module QEMU = struct + let compressed = !compressed + and qemu_boot = !qemu_boot in + ++ if qemu_boot then ++ error (f_"-o qemu: the -oo qemu-boot option cannot be used in RHEL"); ++ + (* -os must be set to a directory. *) + let output_storage = + match options.output_storage with +diff --git a/v2v/v2v.ml b/v2v/v2v.ml +index 48c8cfba..fca5f6e9 100644 +--- a/v2v/v2v.ml ++++ b/v2v/v2v.ml +@@ -277,8 +277,6 @@ let rec main () = + s_"Same as ‘-ip filename’"; + [ L"print-source" ], Getopt.Set print_source, + s_"Print source and stop"; +- [ L"qemu-boot" ], Getopt.Unit (fun () -> set_output_option_compat "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"), diff --git a/SOURCES/0010-RHEL-Fix-list-of-supported-sound-cards-to-match-RHEL.patch b/SOURCES/0010-RHEL-Fix-list-of-supported-sound-cards-to-match-RHEL.patch new file mode 100644 index 0000000..b91cdf8 --- /dev/null +++ b/SOURCES/0010-RHEL-Fix-list-of-supported-sound-cards-to-match-RHEL.patch @@ -0,0 +1,31 @@ +From 9b602a74f1cb359a281a80d944921d6d09a38bc8 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Fri, 24 Apr 2015 09:45:41 -0400 +Subject: [PATCH] RHEL: Fix list of supported sound cards to match RHEL qemu + (RHBZ#1176493). + +--- + lib/utils.ml | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/lib/utils.ml b/lib/utils.ml +index bf010a0a..4c9b7415 100644 +--- a/lib/utils.ml ++++ b/lib/utils.ml +@@ -60,13 +60,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 = diff --git a/SOURCES/0011-RHEL-Fixes-for-libguestfs-winsupport.patch b/SOURCES/0011-RHEL-Fixes-for-libguestfs-winsupport.patch new file mode 100644 index 0000000..a0179bd --- /dev/null +++ b/SOURCES/0011-RHEL-Fixes-for-libguestfs-winsupport.patch @@ -0,0 +1,136 @@ +From 024513d941b74936c1cf13bcb7375117004f6ba5 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Sun, 30 Aug 2015 03:21:57 -0400 +Subject: [PATCH] RHEL: Fixes for libguestfs-winsupport. + +In tests we cannot use guestfish for arbitrary Windows edits. +In virt-v2v helpers we must set the program name to virt-v2v. + +For RHEL 9.3 and above, see this comment: +https://bugzilla.redhat.com/show_bug.cgi?id=2187961#c1 +--- + convert/convert.ml | 1 + + test-data/phony-guests/make-windows-img.sh | 1 + + tests/test-v2v-block-driver.sh | 6 +++++- + tests/test-v2v-in-place.sh | 8 +++++++- + tests/test-v2v-virtio-win-iso.sh | 8 +++++++- + tests/test-v2v-windows-conversion.sh | 8 +++++++- + 6 files changed, 28 insertions(+), 4 deletions(-) + +diff --git a/convert/convert.ml b/convert/convert.ml +index 344c5858..ecc48ad4 100644 +--- a/convert/convert.ml ++++ b/convert/convert.ml +@@ -52,6 +52,7 @@ let rec convert dir options source = + + message (f_"Opening the source"); + let g = open_guestfs ~identifier:"v2v" () in ++ g#set_program "virt-v2v"; + g#set_memsize (g#get_memsize () * 2); + (* Setting the number of vCPUs allows parallel mkinitrd, but make + * sure this is not too large because each vCPU consumes guest RAM. +diff --git a/test-data/phony-guests/make-windows-img.sh b/test-data/phony-guests/make-windows-img.sh +index 30908a91..73cf5144 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 <$response <<-EOM ++ guestfish >$response <<-EOM ++ add-ro $img ++ set-program virt-testing ++ run ++ mount-ro /dev/sda2 / + is-dir $virtio_dir + is-file $virtio_dir/$drv.cat + is-file $virtio_dir/$drv.inf +diff --git a/tests/test-v2v-in-place.sh b/tests/test-v2v-in-place.sh +index 4373f140..2b31b0bb 100755 +--- a/tests/test-v2v-in-place.sh ++++ b/tests/test-v2v-in-place.sh +@@ -89,6 +89,12 @@ mktest () + :> "$script" + :> "$expected" + ++cat >> "$script" < "$response" ++guestfish --ro -a "$img" < "$script" > "$response" + diff -u "$expected" "$response" + + # Test the base image remained untouched +diff --git a/tests/test-v2v-virtio-win-iso.sh b/tests/test-v2v-virtio-win-iso.sh +index 69f6f414..b9b806fb 100755 +--- a/tests/test-v2v-virtio-win-iso.sh ++++ b/tests/test-v2v-virtio-win-iso.sh +@@ -82,6 +82,12 @@ mktest () + :> "$script" + :> "$expected" + ++cat >> "$script" < "$response" ++guestfish --ro -a "$d/windows-sda" < "$script" > "$response" + diff -u "$expected" "$response" +diff --git a/tests/test-v2v-windows-conversion.sh b/tests/test-v2v-windows-conversion.sh +index a4cf191d..1ff41f6a 100755 +--- a/tests/test-v2v-windows-conversion.sh ++++ b/tests/test-v2v-windows-conversion.sh +@@ -76,6 +76,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 diff --git a/SOURCES/0012-RHEL-v2v-i-disk-force-VNC-as-display-RHBZ-1372671.patch b/SOURCES/0012-RHEL-v2v-i-disk-force-VNC-as-display-RHBZ-1372671.patch new file mode 100644 index 0000000..3de3678 --- /dev/null +++ b/SOURCES/0012-RHEL-v2v-i-disk-force-VNC-as-display-RHBZ-1372671.patch @@ -0,0 +1,23 @@ +From a3b4f52cd0e74486b13cbb4d0de007c047afe2cd Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 2 Mar 2017 14:21:37 +0100 +Subject: [PATCH] RHEL: v2v: -i disk: force VNC as display (RHBZ#1372671) + +The SDL output mode is not supported in RHEL's qemu-kvm. +--- + input/input_disk.ml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/input/input_disk.ml b/input/input_disk.ml +index cf1f811b..27fc80de 100644 +--- a/input/input_disk.ml ++++ b/input/input_disk.ml +@@ -77,7 +77,7 @@ module Disk = struct + 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_sound = None; + s_disks = s_disks; diff --git a/SOURCES/0013-RHEL-point-to-KB-for-supported-v2v-hypervisors-guest.patch b/SOURCES/0013-RHEL-point-to-KB-for-supported-v2v-hypervisors-guest.patch new file mode 100644 index 0000000..a58efcb --- /dev/null +++ b/SOURCES/0013-RHEL-point-to-KB-for-supported-v2v-hypervisors-guest.patch @@ -0,0 +1,124 @@ +From 3435557683f568e03656adde0af20e5f3d63d5f1 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Tue, 26 Mar 2019 09:42:25 +0100 +Subject: [PATCH] RHEL: point to KB for supported v2v hypervisors/guests + +--- + docs/virt-v2v-support.pod | 104 ++------------------------------------ + 1 file changed, 4 insertions(+), 100 deletions(-) + +diff --git a/docs/virt-v2v-support.pod b/docs/virt-v2v-support.pod +index 8b64a5ea..1ffc0f9d 100644 +--- a/docs/virt-v2v-support.pod ++++ b/docs/virt-v2v-support.pod +@@ -8,106 +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 4, 5, 6, 7 +- +-=item CentOS 4, 5, 6, 7 +- +-=item Scientific Linux 4, 5, 6, 7 +- +-=item Oracle Linux +- +-=item Fedora +- +-=item SLES 10 and up +- +-=item OpenSUSE 10 and up +- +-=item ALT Linux 9 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 + diff --git a/SOURCES/0014-RHEL-Remove-input-from-Xen.patch b/SOURCES/0014-RHEL-Remove-input-from-Xen.patch new file mode 100644 index 0000000..4476199 --- /dev/null +++ b/SOURCES/0014-RHEL-Remove-input-from-Xen.patch @@ -0,0 +1,554 @@ +From a1dcb4c0bc5670eb739115909bbe08eeefea416a Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Mon, 8 Jul 2024 09:35:54 +0100 +Subject: [PATCH] RHEL: Remove input from Xen + +Originally this bug was to remove input from RHEL 5 Xen only. This +change actually removes all conversions from Xen as in RHEL 9 we only +supported RHEL 5 Xen. + +Fixes: https://issues.redhat.com/browse/RHEL-37687 +--- + docs/Makefile.am | 14 ---- + docs/virt-v2v-input-xen.pod | 154 ------------------------------------ + docs/virt-v2v.pod | 52 ++---------- + input/Makefile.am | 4 +- + input/input_xen_ssh.ml | 132 ------------------------------- + input/input_xen_ssh.mli | 21 ----- + inspector/inspector.ml | 4 - + v2v/v2v.ml | 5 -- + 8 files changed, 6 insertions(+), 380 deletions(-) + delete mode 100644 docs/virt-v2v-input-xen.pod + delete mode 100644 input/input_xen_ssh.ml + delete mode 100644 input/input_xen_ssh.mli + +diff --git a/docs/Makefile.am b/docs/Makefile.am +index 156dc18c..214cfc24 100644 +--- a/docs/Makefile.am ++++ b/docs/Makefile.am +@@ -23,7 +23,6 @@ EXTRA_DIST = \ + virt-v2v-hacking.pod \ + virt-v2v-in-place.pod \ + virt-v2v-input-vmware.pod \ +- virt-v2v-input-xen.pod \ + virt-v2v-inspector.pod \ + virt-v2v-output-local.pod \ + virt-v2v-output-openstack.pod \ +@@ -42,7 +41,6 @@ man_MANS = \ + virt-v2v-hacking.1 \ + virt-v2v-in-place.1 \ + virt-v2v-input-vmware.1 \ +- virt-v2v-input-xen.1 \ + virt-v2v-inspector.1 \ + virt-v2v-output-local.1 \ + virt-v2v-output-openstack.1 \ +@@ -58,7 +56,6 @@ noinst_DATA = \ + $(top_builddir)/website/virt-v2v-hacking.1.html \ + $(top_builddir)/website/virt-v2v-in-place.1.html \ + $(top_builddir)/website/virt-v2v-input-vmware.1.html \ +- $(top_builddir)/website/virt-v2v-input-xen.1.html \ + $(top_builddir)/website/virt-v2v-inspector.1.html \ + $(top_builddir)/website/virt-v2v-output-local.1.html \ + $(top_builddir)/website/virt-v2v-output-openstack.1.html \ +@@ -115,17 +112,6 @@ stamp-virt-v2v-input-vmware.pod: virt-v2v-input-vmware.pod + $< + touch $@ + +-virt-v2v-input-xen.1 $(top_builddir)/website/virt-v2v-input-xen.1.html: stamp-virt-v2v-input-xen.pod +- +-stamp-virt-v2v-input-xen.pod: virt-v2v-input-xen.pod +- $(PODWRAPPER) \ +- --man virt-v2v-input-xen.1 \ +- --html $(top_builddir)/website/virt-v2v-input-xen.1.html \ +- --license GPLv2+ \ +- --warning safe \ +- $< +- touch $@ +- + virt-v2v-inspector.1 $(top_builddir)/website/virt-v2v-inspector.1.html: stamp-virt-v2v-inspector.pod + + stamp-virt-v2v-inspector.pod: virt-v2v-inspector.pod +diff --git a/docs/virt-v2v-input-xen.pod b/docs/virt-v2v-input-xen.pod +deleted file mode 100644 +index 4a0544f8..00000000 +--- a/docs/virt-v2v-input-xen.pod ++++ /dev/null +@@ -1,154 +0,0 @@ +-=head1 NAME +- +-virt-v2v-input-xen - Using virt-v2v to convert guests from Xen +- +-=head1 SYNOPSIS +- +- virt-v2v -ic 'xen+ssh://root@xen.example.com' +- -ip passwordfile +- GUEST_NAME [-o* options] +- +-=head1 DESCRIPTION +- +-This page documents how to use L to convert guests from +-RHEL 5 Xen, or SLES and OpenSUSE Xen hosts. +- +-=head1 INPUT FROM XEN +- +-=head2 SSH authentication +- +-You can use SSH password authentication, by supplying the name of a +-file containing the password to the I<-ip> option (note this option +-does I take the password directly). You may need to adjust +-F on the Xen server to set +-C. +- +-If you are not using password authentication, an alternative is to use +-ssh-agent, and add your ssh public key to +-F (on the Xen host). After doing this, +-you should check that passwordless access works from the virt-v2v +-server to the Xen host. For example: +- +- $ ssh root@xen.example.com +- [ logs straight into the shell, no password is requested ] +- +-Note that support for non-interactive authentication via the I<-ip> +-option is incomplete. Some operations remain that still require the +-user to enter the password manually. Therefore ssh-agent is recommended +-over the I<-ip> option. See L. +- +-With some modern ssh implementations, legacy crypto algorithms required +-to interoperate with RHEL 5 sshd are disabled. To enable them, you may +-need to add the following C stanza to your F<~/.ssh/config>: +- +- Host xen.example.com +- KexAlgorithms +diffie-hellman-group14-sha1 +- MACs +hmac-sha1 +- HostKeyAlgorithms +ssh-rsa +- PubkeyAcceptedKeyTypes +ssh-rsa +- PubkeyAcceptedAlgorithms +ssh-rsa +- +-(C and C have +-identical meaning; the former is the old option name, the latter is the +-new one. Virt-v2v uses both C and C when converting a guest +-from Xen, and on some operating systems, C and C may not +-both accept the same option variant.) +- +-When connecting to RHEL 5 sshd from RHEL 9, the SHA1 algorithm's use in +-signatures has to be re-enabled at the OpenSSL level, in addition to the +-above SSH configuration. Create a file called F<$HOME/openssl-sha1.cnf> +-with the following contents: +- +- .include /etc/ssl/openssl.cnf +- [openssl_init] +- alg_section = evp_properties +- [evp_properties] +- rh-allow-sha1-signatures = yes +- +-and export the following variable into the environment of the +-C process: +- +- OPENSSL_CONF=$HOME/openssl-sha1.cnf +- +-Note that the C environment variable will only take effect +-if the libvirt client library used by virt-v2v is at least version +-8.6.0. +- +-=head2 Test libvirt connection to remote Xen host +- +-Use the L command to list the guests on the remote Xen host: +- +- $ virsh -c xen+ssh://root@xen.example.com list --all +- Id Name State +- ---------------------------------------------------- +- 0 Domain-0 running +- - rhel49-x86_64-pv shut off +- +-You should also try dumping the metadata from any guest on your +-server, like this: +- +- $ virsh -c xen+ssh://root@xen.example.com dumpxml rhel49-x86_64-pv +- +- rhel49-x86_64-pv +- [...] +- +- +-B. Fix your libvirt configuration or the remote server +-before continuing. +- +-B, then the +-conversion will fail. See L +-below for a workaround. +- +-=head2 Importing a guest +- +-To import a particular guest from a Xen server, do: +- +- $ virt-v2v -ic 'xen+ssh://root@xen.example.com' \ +- rhel49-x86_64-pv \ +- -o local -os /var/tmp +- +-where C is the name of the guest (which must be shut +-down). +- +-In this case the output flags are set to write the converted guest to +-a temporary directory as this is just an example, but you can also +-write to libvirt or any other supported target. +- +-=head2 Xen or ssh conversions from block devices +- +-Currently virt-v2v cannot directly access a Xen guest (or any guest +-located remotely over ssh) if that guest’s disks are located on host +-block devices. +- +-To tell if a Xen guest uses host block devices, look at the guest XML. +-You will see: +- +- +- ... +- +- +-where C, C and C are all +-indications that the disk is located on a host block device. +- +-This happens because the qemu ssh block driver that we use to access +-remote disks uses the ssh sftp protocol, and this protocol cannot +-correctly detect the size of host block devices. +- +-The workaround is to copy the block device from the remote Xen +-server to a regular local file, copy the libvirt guest XML, +-adjust the C element to point to the local file, and use +-C<-i libvirtxml> mode instead. +- +-=head1 SEE ALSO +- +-L. +- +-=head1 AUTHOR +- +-Richard W.M. Jones +- +-=head1 COPYRIGHT +- +-Copyright (C) 2009-2020 Red Hat Inc. +diff --git a/docs/virt-v2v.pod b/docs/virt-v2v.pod +index 81a4b45a..9c8dd834 100644 +--- a/docs/virt-v2v.pod ++++ b/docs/virt-v2v.pod +@@ -11,7 +11,7 @@ virt-v2v - Convert a guest to use KVM + =head1 DESCRIPTION + + Virt-v2v converts a single guest from a foreign hypervisor to run on +-KVM. It can read Linux and Windows guests running on VMware, Xen, ++KVM. It can read Linux and Windows guests running on VMware, + Hyper-V and some other hypervisors, and convert them to KVM managed by + libvirt, OpenStack, oVirt, Red Hat Virtualisation (RHV) or several + other targets. It can modify the guest to make it bootable on KVM and +@@ -50,8 +50,6 @@ management systems, guests. + + L — Input from VMware. + +-L — Input from Xen. +- + L — Output to local files or local libvirt. + + L — Output to oVirt or RHV. +@@ -175,10 +173,6 @@ This is only supported for: + + =item * + +-L +- +-=item * +- + L + when using the SSH transport method + +@@ -294,12 +288,10 @@ hypervisor. See L. + Specify a libvirt connection URI to use when reading the guest. This + is only used when S>. + +-Only local libvirt connections, VMware vCenter connections, or RHEL 5 +-Xen remote connections can be used. Other remote libvirt connections +-will not work in general. ++Only local libvirt connections or VMware vCenter connections. ++Other remote libvirt connections will not work in general. + +-See also L, +-L. ++See also L. + + =item B<-if> format + +@@ -844,40 +836,6 @@ Enable tracing of libguestfs API calls. + + =head1 NOTES + +-=head2 Xen paravirtualized guests +- +-Older versions of virt-v2v could turn a Xen paravirtualized (PV) guest +-into a KVM guest by installing a new kernel. This version of virt-v2v +-does I attempt to install any new kernels. Instead it will give +-you an error if there are I Xen PV kernels available. +- +-Therefore before conversion you should check that a regular kernel is +-installed. For some older Linux distributions, this means installing +-a kernel from the table below: +- +- RHEL 3 (Does not apply, as there was no Xen PV kernel) +- +- RHEL 4 i686 with > 10GB of RAM: install 'kernel-hugemem' +- i686 SMP: install 'kernel-smp' +- other i686: install 'kernel' +- x86-64 SMP with > 8 CPUs: install 'kernel-largesmp' +- x86-64 SMP: install 'kernel-smp' +- other x86-64: install 'kernel' +- +- RHEL 5 i686: install 'kernel-PAE' +- x86-64: install 'kernel' +- +- SLES 10 i586 with > 10GB of RAM: install 'kernel-bigsmp' +- i586 SMP: install 'kernel-smp' +- other i586: install 'kernel-default' +- x86-64 SMP: install 'kernel-smp' +- other x86-64: install 'kernel-default' +- +- SLES 11+ i586: install 'kernel-pae' +- x86-64: install 'kernel-default' +- +- Windows (Does not apply, as there is no Xen PV Windows kernel) +- + =head2 Enabling virtio + + "Virtio" is the name for a set of drivers which make disk (block +@@ -1169,7 +1127,7 @@ bandwidth. Virt-v2v should be able to copy guest data at gigabit + ethernet speeds or greater. + + Ensure that the network connections between servers (conversion +-server, NFS server, vCenter, Xen) are as fast and as low latency as ++server, NFS server, vCenter) are as fast and as low latency as + possible. + + =head3 Disk space +diff --git a/input/Makefile.am b/input/Makefile.am +index 4153f878..2f4ceb0c 100644 +--- a/input/Makefile.am ++++ b/input/Makefile.am +@@ -29,7 +29,6 @@ SOURCES_MLI = \ + input_vcenter_https.mli \ + input_vddk.mli \ + input_vmx.mli \ +- input_xen_ssh.mli \ + name_from_disk.mli \ + nbdkit_curl.mli \ + nbdkit_ssh.mli \ +@@ -60,8 +59,7 @@ SOURCES_ML = \ + input_ova.ml \ + input_vcenter_https.ml \ + input_vddk.ml \ +- input_vmx.ml \ +- input_xen_ssh.ml ++ input_vmx.ml + + # We pretend that we're building a C library. automake handles the + # compilation of the C sources for us. At the end we take the C +diff --git a/input/input_xen_ssh.ml b/input/input_xen_ssh.ml +deleted file mode 100644 +index c4235a4b..00000000 +--- a/input/input_xen_ssh.ml ++++ /dev/null +@@ -1,132 +0,0 @@ +-(* helper-v2v-input +- * Copyright (C) 2009-2021 Red Hat Inc. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License along +- * with this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +- *) +- +-open Printf +-open Unix +- +-open Std_utils +-open Tools_utils +-open Common_gettext.Gettext +- +-open Types +-open Utils +- +-open Parse_libvirt_xml +-open Input +- +-module XenSSH = struct +- let to_string options args = +- let xs = args in +- let xs = +- match options.input_conn with +- | Some ic -> ("-ic " ^ ic) :: xs +- | None -> xs in +- let xs = "-i libvirt" :: xs in +- String.concat " " xs +- +- let query_input_options () = +- printf (f_"No input options can be used in this mode.\n") +- +- let setup dir options args = +- if options.input_options <> [] then +- error (f_"no -io (input options) are allowed here"); +- +- if not options.read_only then +- error (f_"in-place mode does not work with Xen over SSH source"); +- +- (* Get the guest name. *) +- let guest = +- match args with +- | [arg] -> arg +- | _ -> +- error (f_"-i libvirt: expecting a libvirt guest name \ +- on the command line") in +- +- (* -ic must be set. *) +- let input_conn = +- match options.input_conn with +- | Some ic -> ic +- | None -> +- error (f_"-i libvirt: expecting -ic parameter for \ +- Xen over SSH connection") in +- +- let uri = +- try Xml.parse_uri input_conn +- with Invalid_argument msg -> +- error (f_"could not parse '-ic %s'. Original error message was: %s") +- input_conn msg in +- +- (* Connect to the hypervisor. *) +- let conn = +- let auth = Libvirt_utils.auth_for_password_file +- ?password_file:options.input_password () in +- Libvirt.Connect.connect_auth ~name:input_conn auth in +- +- (* Parse the libvirt XML. *) +- let source, disks, _ = parse_libvirt_domain conn guest in +- +- let server = +- match uri.Xml.uri_server with +- | Some server -> server +- | None -> +- error (f_"‘-ic %s’ URL does not contain a host name field") +- input_conn in +- +- let port = +- match uri.uri_port with +- | 0 | 22 -> None +- | i -> Some (string_of_int i) in +- +- let user = uri.uri_user in +- +- let password = +- match options.input_password with +- | None -> None +- | Some ip -> Some (Nbdkit_ssh.PasswordFile ip) in +- +- (* Create an nbdkit instance for each disk. *) +- List.iteri ( +- fun i { d_format = format; d_type } -> +- let socket = sprintf "%s/in%d" dir i in +- On_exit.unlink socket; +- +- match d_type with +- | NBD _ | HTTP _ -> (* These should never happen? *) +- assert false +- +- | BlockDev _ -> +- (* Conversion from a remote block device over SSH isn't +- * supported because OpenSSH sftp server doesn't know how +- * to get the size of a block device. Therefore we disallow +- * this and refer users to the manual. +- *) +- error (f_"input from xen over ssh does not support disks stored on \ +- remote block devices. See virt-v2v-input-xen(1) \ +- section \"Xen or ssh conversions from block devices\".") +- +- | LocalFile path -> +- let cor = dir // "convert" in +- let bandwidth = options.bandwidth in +- let nbdkit = Nbdkit_ssh.create_ssh ?bandwidth ~cor ?password +- ?port ~server ?user path in +- let _, pid = Nbdkit.run_unix socket nbdkit in +- On_exit.kill pid +- ) disks; +- +- source +-end +diff --git a/input/input_xen_ssh.mli b/input/input_xen_ssh.mli +deleted file mode 100644 +index fa048231..00000000 +--- a/input/input_xen_ssh.mli ++++ /dev/null +@@ -1,21 +0,0 @@ +-(* virt-v2v +- * Copyright (C) 2009-2021 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. +- *) +- +-(** Input from Xen over SSH *) +- +-module XenSSH : Input.INPUT +diff --git a/inspector/inspector.ml b/inspector/inspector.ml +index 5dde6e8d..7b2211e4 100644 +--- a/inspector/inspector.ml ++++ b/inspector/inspector.ml +@@ -285,10 +285,6 @@ read the man page virt-v2v-inspector(1). + | Some server, Some ("esx"|"gsx"|"vpx"), Some `VDDK -> + (module Input_vddk.VDDK) + +- (* Xen over SSH *) +- | Some server, Some "xen+ssh", _ -> +- (module Input_xen_ssh.XenSSH) +- + (* Old virt-v2v also supported qemu+ssh://. However I am + * deliberately not supporting this in new virt-v2v. Don't + * use virt-v2v if a guest already runs on KVM. +diff --git a/v2v/v2v.ml b/v2v/v2v.ml +index fca5f6e9..6d44d987 100644 +--- a/v2v/v2v.ml ++++ b/v2v/v2v.ml +@@ -388,7 +388,6 @@ read the man page virt-v2v(1). + pr "virt-v2v-2.0\n"; + pr "libguestfs-rewrite\n"; + pr "vcenter-https\n"; +- pr "xen-ssh\n"; + pr "vddk\n"; + pr "colours-option\n"; + pr "vdsm-compat-option\n"; +@@ -452,10 +451,6 @@ read the man page virt-v2v(1). + | Some server, Some ("esx"|"gsx"|"vpx"), Some `VDDK -> + (module Input_vddk.VDDK) + +- (* Xen over SSH *) +- | Some server, Some "xen+ssh", _ -> +- (module Input_xen_ssh.XenSSH) +- + (* Old virt-v2v also supported qemu+ssh://. However I am + * deliberately not supporting this in new virt-v2v. Don't + * use virt-v2v if a guest already runs on KVM. diff --git a/SOURCES/0015-RHEL-Remove-o-glance.patch b/SOURCES/0015-RHEL-Remove-o-glance.patch new file mode 100644 index 0000000..da401ae --- /dev/null +++ b/SOURCES/0015-RHEL-Remove-o-glance.patch @@ -0,0 +1,214 @@ +From 194e3386a00560e02dc09cbf77f6a30b0c897ada Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Wed, 30 Jun 2021 11:15:52 +0100 +Subject: [PATCH] RHEL: Remove -o glance + +Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1977539 +--- + docs/virt-v2v-output-openstack.pod | 54 ++---------------------------- + docs/virt-v2v.pod | 20 ----------- + output/output_glance.mli | 2 +- + tests/test-v2v-o-glance.sh | 3 ++ + v2v/v2v.ml | 7 +--- + 5 files changed, 7 insertions(+), 79 deletions(-) + +diff --git a/docs/virt-v2v-output-openstack.pod b/docs/virt-v2v-output-openstack.pod +index cd4862b1..54cd276e 100644 +--- a/docs/virt-v2v-output-openstack.pod ++++ b/docs/virt-v2v-output-openstack.pod +@@ -10,13 +10,10 @@ virt-v2v-output-openstack - Using virt-v2v to convert guests to OpenStack + [-oo verify-server-certificate=false] + [-oo os-username=admin] [-oo os-*=*] + +- virt-v2v [-i* options] -o glance +- + =head1 DESCRIPTION + + This page documents how to use L to convert guests to run +-on OpenStack. There are two output modes you can select, but only +-I<-o openstack> should be used normally. ++on OpenStack. + + =over 4 + +@@ -27,15 +24,6 @@ Full description: L + This is the modern method for uploading to OpenStack via the REST API. + Guests can be directly converted into Cinder volumes. + +-=item B<-o glance> +- +-Full description: L +- +-This is the old method for uploading to Glance. Unfortunately Glance +-is not well suited to storing converted guests (since virt-v2v deals +-with "pets" not templated "cattle"), so this method is not recommended +-unless you really know what you are doing. +- + =back + + =head1 OUTPUT TO OPENSTACK +@@ -176,48 +164,10 @@ no Cinder volume type is used. + The following options are B supported with OpenStack: I<-oa>, + I<-of>. + +-=head1 OUTPUT TO GLANCE +- +-Note this is a legacy option. In most cases you should use +-L instead. +- +-To output to OpenStack Glance, use the I<-o glance> option. +- +-This runs the L CLI program which must be installed on the +-virt-v2v conversion host. For authentication to work, you will need +-to set C environment variables. See +-L above. +- +-Virt-v2v adds metadata for the guest to Glance, describing such things +-as the guest operating system and what drivers it requires. The +-command C will display the metadata as "Property" +-fields such as C and C. +- +-=head2 Glance and sparseness +- +-Glance image upload doesn't appear to correctly handle sparseness. +-For this reason, using qcow2 will be faster and use less space on the +-Glance server. Use the virt-v2v S> option. +- +-=head2 Glance and multiple disks +- +-If the guest has a single disk, then the name of the disk in Glance +-will be the name of the guest. You can control this using the I<-on> +-option. +- +-Glance doesn't have a concept of associating multiple disks with a +-single guest, and Nova doesn't allow you to boot a guest from multiple +-Glance disks either. If the guest has multiple disks, then the first +-(assumed to be the system disk) will have the name of the guest, and +-the second and subsequent data disks will be called +-C-disk2>, C-disk3> etc. It may be best to +-leave the system disk in Glance, and import the data disks to Cinder. +- + =head1 SEE ALSO + + L, +-L, +-L. ++L. + + =head1 AUTHOR + +diff --git a/docs/virt-v2v.pod b/docs/virt-v2v.pod +index 9c8dd834..50424bc3 100644 +--- a/docs/virt-v2v.pod ++++ b/docs/virt-v2v.pod +@@ -427,14 +427,6 @@ See L below. + + This is the same as I<-o local>. + +-=item B<-o> B +- +-This is a legacy option. You should probably use I<-o openstack> +-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. B (or F). + +-=item I<-o glance> +- +-This temporarily places a full copy of the output disks in +-C<$VIRT_V2V_TMPDIR> (or F). +- + =item I<-o local> + + =item I<-o qemu> +@@ -1356,13 +1343,6 @@ See also L. + Because of how Cinder volumes are presented as F block devices, + using I<-o openstack> normally requires that virt-v2v is run as root. + +-=item Writing to Glance +- +-This does I need root (in fact it probably won’t work), but may +-require either a special user and/or for you to source a script that +-sets authentication environment variables. Consult the Glance +-documentation. +- + =item Writing to block devices + + This normally requires root. See the next section. +diff --git a/output/output_glance.mli b/output/output_glance.mli +index 972320a2..9befc461 100644 +--- a/output/output_glance.mli ++++ b/output/output_glance.mli +@@ -18,4 +18,4 @@ + + (** [-o glance] output mode. *) + +-module Glance : Output.OUTPUT ++(*module Glance : Output.OUTPUT*) +diff --git a/tests/test-v2v-o-glance.sh b/tests/test-v2v-o-glance.sh +index c0db9115..074b5e16 100755 +--- a/tests/test-v2v-o-glance.sh ++++ b/tests/test-v2v-o-glance.sh +@@ -20,6 +20,9 @@ + + set -e + ++# Feature is disabled in RHEL 9. ++exit 77 ++ + source ./functions.sh + set -e + set -x +diff --git a/v2v/v2v.ml b/v2v/v2v.ml +index 6d44d987..f51b55d9 100644 +--- a/v2v/v2v.ml ++++ b/v2v/v2v.ml +@@ -197,7 +197,6 @@ let rec main () = + if !output_mode <> `Not_set then + error (f_"%s option used more than once on the command line") "-o"; + match mode with +- | "glance" -> output_mode := `Glance + | "kubevirt" -> output_mode := `Kubevirt + | "libvirt" -> output_mode := `Libvirt + | "disk" | "local" -> output_mode := `Disk +@@ -257,7 +256,7 @@ let rec main () = + s_"Map network ‘in’ to ‘out’"; + [ L"no-trim" ], Getopt.String ("-", no_trim_warning), + s_"Ignored for backwards compatibility"; +- [ S 'o' ], Getopt.String ("glance|kubevirt|libvirt|local|null|openstack|qemu|rhv|rhv-upload|vdsm", set_output_mode), ++ [ S 'o' ], Getopt.String ("kubevirt|libvirt|local|null|openstack|qemu|rhv|rhv-upload|vdsm", set_output_mode), + s_"Set output mode (default: libvirt)"; + [ M"oa" ], Getopt.String ("sparse|preallocated", set_output_alloc), + s_"Set output allocation mode"; +@@ -325,8 +324,6 @@ virt-v2v -i libvirtxml guest-domain.xml -o local -os /var/tmp + + virt-v2v -i disk disk.img -o local -os /var/tmp + +-virt-v2v -i disk disk.img -o glance +- + There is a companion front-end called \"virt-p2v\" which comes as an + ISO or CD image that can be booted on physical machines. + +@@ -400,7 +397,6 @@ read the man page virt-v2v(1). + pr "input:libvirtxml\n"; + pr "input:ova\n"; + pr "input:vmx\n"; +- pr "output:glance\n"; + pr "output:kubevirt\n"; + pr "output:libvirt\n"; + pr "output:local\n"; +@@ -493,7 +489,6 @@ read the man page virt-v2v(1). + | `Disk -> (module Output_disk.Disk) + | `Null -> (module Output_null.Null) + | `QEmu -> (module Output_qemu.QEMU) +- | `Glance -> (module Output_glance.Glance) + | `Kubevirt -> (module Output_kubevirt.Kubevirt) + | `Openstack -> (module Output_openstack.Openstack) + | `RHV_Upload -> (module Output_rhv_upload.RHVUpload) diff --git a/SOURCES/0016-RHEL-Remove-the-in-place-option.patch b/SOURCES/0016-RHEL-Remove-the-in-place-option.patch new file mode 100644 index 0000000..7115d31 --- /dev/null +++ b/SOURCES/0016-RHEL-Remove-the-in-place-option.patch @@ -0,0 +1,84 @@ +From e2898730dd01704c60ad3896afd03507feb59e27 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 2 Dec 2021 11:56:05 +0000 +Subject: [PATCH] RHEL: Remove the --in-place option + +This disables the virt-v2v --in-place option which we do not +wish to support in RHEL. +--- + docs/virt-v2v.pod | 8 -------- + tests/Makefile.am | 1 - + v2v/v2v.ml | 8 -------- + 3 files changed, 17 deletions(-) + +diff --git a/docs/virt-v2v.pod b/docs/virt-v2v.pod +index 50424bc3..e22dc95f 100644 +--- a/docs/virt-v2v.pod ++++ b/docs/virt-v2v.pod +@@ -24,9 +24,6 @@ virtualize those machines (physical to virtual, or p2v). + To estimate the disk space needed before conversion, see + L. + +-For in-place conversion, there is a separate tool called +-L. +- + =head2 Input and Output + + You normally run virt-v2v with several I<-i*> options controlling the +@@ -39,10 +36,6 @@ The input and output sides of virt-v2v are separate and unrelated. + Virt-v2v can read from any input and write to any output. Therefore + 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 conversions may be done using L. +- + =head2 Other virt-v2v topics + + L — Supported hypervisors, virtualization +@@ -1624,7 +1617,6 @@ L, + L, +-L, + L, + L, + L, +diff --git a/tests/Makefile.am b/tests/Makefile.am +index 723a6506..4bfa1c7a 100644 +--- a/tests/Makefile.am ++++ b/tests/Makefile.am +@@ -77,7 +77,6 @@ TESTS = \ + test-v2v-floppy.sh \ + test-v2v-i-disk.sh \ + test-v2v-i-ova.sh \ +- test-v2v-in-place.sh \ + test-v2v-block-driver.sh \ + test-v2v-inspector.sh \ + test-v2v-mac.sh \ +diff --git a/v2v/v2v.ml b/v2v/v2v.ml +index f51b55d9..a61b055e 100644 +--- a/v2v/v2v.ml ++++ b/v2v/v2v.ml +@@ -219,12 +219,6 @@ let rec main () = + warning (f_"the --vmtype option has been removed and now does nothing") + in + +- (* Options that are errors. *) +- let in_place_error _ = +- error (f_"The --in-place option has been replaced by the \ +- ‘virt-v2v-in-place’ program") +- in +- + let argspec = [ + [ L"bandwidth" ], Getopt.String ("bps", set_string_option_once "--bandwidth" bandwidth), + s_"Set bandwidth to bits per sec"; +@@ -248,8 +242,6 @@ let rec main () = + 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.Unit in_place_error, +- s_"Use virt-v2v-in-place instead"; + [ 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), diff --git a/SOURCES/0017-RHEL-tests-Remove-btrfs-test.patch b/SOURCES/0017-RHEL-tests-Remove-btrfs-test.patch new file mode 100644 index 0000000..7e7e352 --- /dev/null +++ b/SOURCES/0017-RHEL-tests-Remove-btrfs-test.patch @@ -0,0 +1,22 @@ +From 5491bd28a055ff7248dd922c75aa3b9653ec488a Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Tue, 5 Jul 2022 11:58:09 +0100 +Subject: [PATCH] RHEL: tests: Remove btrfs test + +RHEL does not have btrfs so this test always fails. +--- + tests/Makefile.am | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/tests/Makefile.am b/tests/Makefile.am +index 4bfa1c7a..a380a9bf 100644 +--- a/tests/Makefile.am ++++ b/tests/Makefile.am +@@ -101,7 +101,6 @@ TESTS = \ + test-v2v-sound.sh \ + test-v2v-virtio-win-iso.sh \ + test-v2v-fedora-conversion.sh \ +- test-v2v-fedora-btrfs-conversion.sh \ + test-v2v-fedora-luks-on-lvm-conversion.sh \ + test-v2v-fedora-lvm-on-luks-conversion.sh \ + test-v2v-fedora-md-conversion.sh \ diff --git a/SOURCES/0018-RHEL-Remove-block-driver-option.patch b/SOURCES/0018-RHEL-Remove-block-driver-option.patch new file mode 100644 index 0000000..cbee5a7 --- /dev/null +++ b/SOURCES/0018-RHEL-Remove-block-driver-option.patch @@ -0,0 +1,157 @@ +From e75a874958d57ef19d3bbd1215c073267a9cc406 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Fri, 28 Apr 2023 12:28:19 +0100 +Subject: [PATCH] RHEL: Remove --block-driver option + +Go back to the old default of always installing virtio-blk drivers in +Windows guests. + +Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=2190387 +--- + docs/virt-v2v-in-place.pod | 10 ---------- + docs/virt-v2v.pod | 10 ---------- + in-place/in_place.ml | 11 +---------- + tests/Makefile.am | 1 - + v2v/v2v.ml | 11 +---------- + 5 files changed, 2 insertions(+), 41 deletions(-) + +diff --git a/docs/virt-v2v-in-place.pod b/docs/virt-v2v-in-place.pod +index ce57e229..6e1c5363 100644 +--- a/docs/virt-v2v-in-place.pod ++++ b/docs/virt-v2v-in-place.pod +@@ -47,16 +47,6 @@ Display help. + + See I<--network> below. + +-=item B<--block-driver> B +- +-=item B<--block-driver> B +- +-When choosing a block driver for Windows guests, prefer C or +-C. The default is C. +- +-Note this has no effect for Linux guests at the moment. That may be +-added in future. +- + =item B<--colors> + + =item B<--colours> +diff --git a/docs/virt-v2v.pod b/docs/virt-v2v.pod +index e22dc95f..b94fc8b5 100644 +--- a/docs/virt-v2v.pod ++++ b/docs/virt-v2v.pod +@@ -191,16 +191,6 @@ The options are silently ignored for other input methods. + + See I<--network> below. + +-=item B<--block-driver> B +- +-=item B<--block-driver> B +- +-When choosing a block driver for Windows guests, prefer C or +-C. The default is C. +- +-Note this has no effect for Linux guests at the moment. That may be +-added in future. +- + =item B<--colors> + + =item B<--colours> +diff --git a/in-place/in_place.ml b/in-place/in_place.ml +index 1fbd29d3..1c690a54 100644 +--- a/in-place/in_place.ml ++++ b/in-place/in_place.ml +@@ -43,7 +43,6 @@ let rec main () = + + let bandwidth = ref None in + let bandwidth_file = ref None in +- let block_driver = ref None in + let input_conn = ref None in + let input_format = ref None in + let input_password = ref None in +@@ -159,8 +158,6 @@ let rec main () = + let argspec = [ + [ S 'b'; L"bridge" ], Getopt.String ("in:out", add_bridge), + s_"Map bridge ‘in’ to ‘out’"; +- [ L"block-driver" ], Getopt.String ("driver", set_string_option_once "--block-driver" block_driver), +- s_"Prefer 'virtio-blk' or 'virtio-scsi'"; + [ S 'i' ], Getopt.String ("disk|libvirt|libvirtxml|ova|vmx", set_input_mode), + s_"Set input mode (default: libvirt)"; + [ M"ic" ], Getopt.String ("uri", set_string_option_once "-ic" input_conn), +@@ -216,12 +213,6 @@ read the man page virt-v2v-in-place(1). + + (* Dereference the arguments. *) + let args = List.rev !args in +- let block_driver = +- match !block_driver with +- | None | Some "virtio-blk" -> Virtio_blk +- | Some "virtio-scsi" -> Virtio_SCSI +- | Some driver -> +- error (f_"unknown block driver ‘--block-driver %s’") driver in + let input_conn = !input_conn in + let input_mode = !input_mode in + let print_source = !print_source in +@@ -305,7 +296,7 @@ read the man page virt-v2v-in-place(1). + + (* Get the conversion options. *) + let conv_options = { +- Convert.block_driver = block_driver; ++ Convert.block_driver = Virtio_blk; + keep_serial_console = true; + ks = opthandle.ks; + network_map; +diff --git a/tests/Makefile.am b/tests/Makefile.am +index a380a9bf..1ec1a702 100644 +--- a/tests/Makefile.am ++++ b/tests/Makefile.am +@@ -77,7 +77,6 @@ TESTS = \ + test-v2v-floppy.sh \ + test-v2v-i-disk.sh \ + test-v2v-i-ova.sh \ +- test-v2v-block-driver.sh \ + test-v2v-inspector.sh \ + test-v2v-mac.sh \ + test-v2v-machine-readable.sh \ +diff --git a/v2v/v2v.ml b/v2v/v2v.ml +index a61b055e..64a0147c 100644 +--- a/v2v/v2v.ml ++++ b/v2v/v2v.ml +@@ -48,7 +48,6 @@ let rec main () = + + let bandwidth = ref None in + let bandwidth_file = ref None in +- let block_driver = ref None in + let input_conn = ref None in + let input_format = ref None in + let input_password = ref None in +@@ -226,8 +225,6 @@ let rec main () = + s_"Set bandwidth dynamically from file"; + [ S 'b'; L"bridge" ], Getopt.String ("in:out", add_bridge), + s_"Map bridge ‘in’ to ‘out’"; +- [ L"block-driver" ], Getopt.String ("driver", set_string_option_once "--block-driver" block_driver), +- s_"Prefer 'virtio-blk' or 'virtio-scsi'"; + [ L"compressed" ], Getopt.Unit (fun () -> set_output_option_compat "compressed" ""), + s_"Compress output file (-of qcow2 only)"; + [ S 'i' ], Getopt.String ("disk|libvirt|libvirtxml|ova|vmx", set_input_mode), +@@ -343,12 +340,6 @@ read the man page virt-v2v(1). + + (* Dereference the arguments. *) + let args = List.rev !args in +- let block_driver = +- match !block_driver with +- | None | Some "virtio-blk" -> Virtio_blk +- | Some "virtio-scsi" -> Virtio_SCSI +- | Some driver -> +- error (f_"unknown block driver ‘--block-driver %s’") driver in + let input_conn = !input_conn in + let input_mode = !input_mode in + let input_transport = +@@ -515,7 +506,7 @@ read the man page virt-v2v(1). + + (* Get the conversion options. *) + let conv_options = { +- Convert.block_driver = block_driver; ++ Convert.block_driver = Virtio_blk; + keep_serial_console = not remove_serial_console; + ks = opthandle.ks; + network_map; diff --git a/SOURCES/0019-RHEL-Remove-o-rhv-o-rhv-upload-and-o-vdsm-modes.patch b/SOURCES/0019-RHEL-Remove-o-rhv-o-rhv-upload-and-o-vdsm-modes.patch new file mode 100644 index 0000000..87b1548 --- /dev/null +++ b/SOURCES/0019-RHEL-Remove-o-rhv-o-rhv-upload-and-o-vdsm-modes.patch @@ -0,0 +1,4728 @@ +From c0f7a321feb08727609a160ac0c0f2c0adea68f2 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Mon, 8 Jul 2024 09:56:54 +0100 +Subject: [PATCH] RHEL: Remove -o rhv, -o rhv-upload and -o vdsm modes + +Fixes: https://issues.redhat.com/browse/RHEL-36712 +--- + docs/Makefile.am | 14 - + docs/virt-v2v-output-rhv.pod | 232 -------- + docs/virt-v2v.pod | 208 +------ + output/Makefile.am | 54 +- + output/output_rhv.ml | 317 ----------- + output/output_rhv.mli | 21 - + output/output_rhv_upload.ml | 520 ----------------- + output/output_rhv_upload.mli | 21 - + output/output_rhv_upload_cancel_source.mli | 19 - + output/output_rhv_upload_createvm_source.mli | 19 - + output/output_rhv_upload_finalize_source.mli | 19 - + output/output_rhv_upload_plugin_source.mli | 19 - + output/output_rhv_upload_precheck_source.mli | 19 - + output/output_rhv_upload_transfer_source.mli | 19 - + output/output_rhv_upload_vmcheck_source.mli | 19 - + output/output_vdsm.ml | 237 -------- + output/output_vdsm.mli | 21 - + output/rhv-upload-cancel.py | 96 ---- + output/rhv-upload-createvm.py | 137 ----- + output/rhv-upload-finalize.py | 174 ------ + output/rhv-upload-plugin.py | 525 ------------------ + output/rhv-upload-precheck.py | 135 ----- + output/rhv-upload-transfer.py | 298 ---------- + output/rhv-upload-vmcheck.py | 72 --- + tests/Makefile.am | 15 - + tests/test-v2v-o-rhv-upload-module/imageio.py | 71 --- + .../ovirtsdk4/__init__.py | 150 ----- + .../ovirtsdk4/types.py | 184 ------ + tests/test-v2v-o-rhv-upload-oo-query.sh | 41 -- + tests/test-v2v-o-rhv-upload.sh | 74 --- + tests/test-v2v-o-rhv.ovf.expected | 113 ---- + tests/test-v2v-o-rhv.sh | 87 --- + tests/test-v2v-o-vdsm-oo-query.sh | 41 -- + tests/test-v2v-o-vdsm-options.ovf.expected | 113 ---- + tests/test-v2v-o-vdsm-options.sh | 96 ---- + v2v/v2v.ml | 31 +- + 36 files changed, 5 insertions(+), 4226 deletions(-) + delete mode 100644 docs/virt-v2v-output-rhv.pod + delete mode 100644 output/output_rhv.ml + delete mode 100644 output/output_rhv.mli + delete mode 100644 output/output_rhv_upload.ml + delete mode 100644 output/output_rhv_upload.mli + delete mode 100644 output/output_rhv_upload_cancel_source.mli + delete mode 100644 output/output_rhv_upload_createvm_source.mli + delete mode 100644 output/output_rhv_upload_finalize_source.mli + delete mode 100644 output/output_rhv_upload_plugin_source.mli + delete mode 100644 output/output_rhv_upload_precheck_source.mli + delete mode 100644 output/output_rhv_upload_transfer_source.mli + delete mode 100644 output/output_rhv_upload_vmcheck_source.mli + delete mode 100644 output/output_vdsm.ml + delete mode 100644 output/output_vdsm.mli + delete mode 100644 output/rhv-upload-cancel.py + delete mode 100644 output/rhv-upload-createvm.py + delete mode 100644 output/rhv-upload-finalize.py + delete mode 100644 output/rhv-upload-plugin.py + delete mode 100644 output/rhv-upload-precheck.py + delete mode 100644 output/rhv-upload-transfer.py + delete mode 100644 output/rhv-upload-vmcheck.py + delete mode 100755 tests/test-v2v-o-rhv-upload-module/imageio.py + delete mode 100644 tests/test-v2v-o-rhv-upload-module/ovirtsdk4/__init__.py + delete mode 100644 tests/test-v2v-o-rhv-upload-module/ovirtsdk4/types.py + delete mode 100755 tests/test-v2v-o-rhv-upload-oo-query.sh + delete mode 100755 tests/test-v2v-o-rhv-upload.sh + delete mode 100644 tests/test-v2v-o-rhv.ovf.expected + delete mode 100755 tests/test-v2v-o-rhv.sh + delete mode 100755 tests/test-v2v-o-vdsm-oo-query.sh + delete mode 100644 tests/test-v2v-o-vdsm-options.ovf.expected + delete mode 100755 tests/test-v2v-o-vdsm-options.sh + +diff --git a/docs/Makefile.am b/docs/Makefile.am +index 214cfc24..2cbe9397 100644 +--- a/docs/Makefile.am ++++ b/docs/Makefile.am +@@ -26,7 +26,6 @@ EXTRA_DIST = \ + virt-v2v-inspector.pod \ + virt-v2v-output-local.pod \ + virt-v2v-output-openstack.pod \ +- virt-v2v-output-rhv.pod \ + virt-v2v-release-notes-1.42.pod \ + virt-v2v-release-notes-2.0.pod \ + virt-v2v-release-notes-2.2.pod \ +@@ -44,7 +43,6 @@ man_MANS = \ + virt-v2v-inspector.1 \ + virt-v2v-output-local.1 \ + virt-v2v-output-openstack.1 \ +- virt-v2v-output-rhv.1 \ + virt-v2v-release-notes-1.42.1 \ + virt-v2v-release-notes-2.0.1 \ + virt-v2v-release-notes-2.2.1 \ +@@ -59,7 +57,6 @@ noinst_DATA = \ + $(top_builddir)/website/virt-v2v-inspector.1.html \ + $(top_builddir)/website/virt-v2v-output-local.1.html \ + $(top_builddir)/website/virt-v2v-output-openstack.1.html \ +- $(top_builddir)/website/virt-v2v-output-rhv.1.html \ + $(top_builddir)/website/virt-v2v-release-notes-1.42.1.html \ + $(top_builddir)/website/virt-v2v-release-notes-2.0.1.html \ + $(top_builddir)/website/virt-v2v-release-notes-2.2.1.html \ +@@ -146,17 +143,6 @@ stamp-virt-v2v-output-openstack.pod: virt-v2v-output-openstack.pod + $< + touch $@ + +-virt-v2v-output-rhv.1 $(top_builddir)/website/virt-v2v-output-rhv.1.html: stamp-virt-v2v-output-rhv.pod +- +-stamp-virt-v2v-output-rhv.pod: virt-v2v-output-rhv.pod +- $(PODWRAPPER) \ +- --man virt-v2v-output-rhv.1 \ +- --html $(top_builddir)/website/virt-v2v-output-rhv.1.html \ +- --license GPLv2+ \ +- --warning safe \ +- $< +- touch $@ +- + virt-v2v-release-notes-1.42.1 $(top_builddir)/website/virt-v2v-release-notes-1.42.1.html: stamp-virt-v2v-release-notes-1.42.pod + + stamp-virt-v2v-release-notes-1.42.pod: virt-v2v-release-notes-1.42.pod +diff --git a/docs/virt-v2v-output-rhv.pod b/docs/virt-v2v-output-rhv.pod +deleted file mode 100644 +index 2ce697f4..00000000 +--- a/docs/virt-v2v-output-rhv.pod ++++ /dev/null +@@ -1,232 +0,0 @@ +-=head1 NAME +- +-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] +- [-oo rhv-cafile=FILE] +- [-oo rhv-cluster=CLUSTER] +- [-oo rhv-proxy] +- [-oo rhv-disk-uuid=UUID ...] +- [-oo rhv-verifypeer] +- +- virt-v2v [-i* options] -o rhv -os [esd:/path|/path] +- +- virt-v2v [-i* options] -o vdsm +- [-oo vdsm-image-uuid=UUID] +- [-oo vdsm-vol-uuid=UUID] +- [-oo vdsm-vm-uuid=UUID] +- [-oo vdsm-ovf-output=DIR] +- +-=head1 DESCRIPTION +- +-This page documents how to use L to convert guests to an +-oVirt or RHV management instance. There are three output modes that +-you can select, but only I<-o rhv-upload> should be used normally, the +-other two are deprecated: +- +-=over 4 +- +-=item B<-o rhv-upload> B<-os> STORAGE +- +-Full description: L +- +-This is the modern method for uploading to oVirt/RHV via the REST API. +-It requires oVirt/RHV E 4.2. +- +-=item B<-o rhv> B<-os> esd:/path +- +-=item B<-o rhv> B<-os> /path +- +-Full description: L +- +-This is the old method for uploading to oVirt/RHV via the +-Export Storage Domain (ESD). The ESD can either be accessed +-over NFS (using the I<-os esd:/path> form) or if you have +-already NFS-mounted it somewhere specify the path to the mountpoint +-as I<-os /path>. +- +-The Export Storage Domain was deprecated in oVirt 4, and so we expect +-that this method will stop working at some point in the future. +- +-=item B<-o vdsm> +- +-This is the old method used internally by the RHV-M user interface. +-It is never intended to be used directly by end users. +- +-=back +- +-=head1 OUTPUT TO RHV +- +-This new method to upload guests to oVirt or RHV directly via the REST +-API requires oVirt/RHV E 4.2. +- +-You need to specify I<-o rhv-upload> as well as the following extra +-parameters: +- +-=over 4 +- +-=item I<-oc> C +- +-The URL of the REST API which is usually the server name with +-C appended, but might be different if you installed +-oVirt Engine on a different path. +- +-You can optionally add a username and port number to the URL. If the +-username is not specified then virt-v2v defaults to using +-C which is the typical superuser account for oVirt +-instances. +- +-=item I<-of raw> +- +-Currently you must use I<-of raw> and you cannot use I<-oa preallocated>. +- +-These restrictions will be loosened in a future version. +- +-=item I<-op> F +- +-A file containing a password to be used when connecting to the oVirt +-engine. Note the file should contain the whole password, B, and for security the file should have mode +-C<0600> so that others cannot read it. +- +-=item I<-os> C +- +-The storage domain. +- +-=item I<-oo rhv-cafile=>F +- +-The F file (Certificate Authority), copied from +-F on the oVirt engine. +- +-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 +- +-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 must not conflict with the UUIDs of existing disks +- +-=back +- +-=item I<-oo rhv-proxy> +- +-Proxy the upload through oVirt Engine. This is slower than uploading +-directly to the oVirt node but may be necessary if you do not have +-direct network access to the nodes. +- +-=item I<-oo rhv-verifypeer> +- +-Verify the oVirt/RHV server’s identity by checking the server‘s +-certificate against the Certificate Authority. +- +-=back +- +-=head1 OUTPUT TO EXPORT STORAGE DOMAIN +- +-This section only applies to the I<-o rhv> output mode. If you use +-virt-v2v from the RHV-M user interface, then behind the scenes the +-import is managed by VDSM using the I<-o vdsm> output mode (which end +-users should not try to use directly). +- +-You have to specify I<-o rhv> and an I<-os> option that points to the +-RHV-M Export Storage Domain. You can either specify the NFS server +-and mountpoint, eg. S>, or you can +-mount that first and point to the directory where it is mounted, +-eg. S>. Be careful not to point to the Data Storage +-Domain by accident as that will not work. +- +-On successful completion virt-v2v will have written the new guest to +-the Export Storage Domain, but it will not yet be ready to run. It +-must be imported into RHV using the UI before it can be used. +- +-In RHV E 2.2 this is done from the Storage tab. Select the +-export domain the guest was written to. A pane will appear underneath +-the storage domain list displaying several tabs, one of which is "VM +-Import". The converted guest will be listed here. Select the +-appropriate guest an click "Import". See the RHV documentation for +-additional details. +- +-If you export several guests, then you can import them all at the same +-time through the UI. +- +-=head2 Testing RHV conversions +- +-If you do not have an oVirt or RHV instance to test against, then you +-can test conversions by creating a directory structure which looks +-enough like a RHV-M Export Storage Domain to trick virt-v2v: +- +- uuid=`uuidgen` +- mkdir /tmp/rhv +- mkdir /tmp/rhv/$uuid +- mkdir /tmp/rhv/$uuid/images +- mkdir /tmp/rhv/$uuid/master +- mkdir /tmp/rhv/$uuid/master/vms +- touch /tmp/rhv/$uuid/dom_md +- virt-v2v [...] -o rhv -os /tmp/rhv +- +-=head2 Debugging RHV-M import failures +- +-When you export to the RHV-M Export Storage Domain, and then import +-that guest through the RHV-M UI, you may encounter an import failure. +-Diagnosing these failures is infuriatingly difficult as the UI +-generally hides the true reason for the failure. +- +-There are several log files of interest: +- +-=over 4 +- +-=item F +- +-In oVirt E 4.1.0, VDSM preserves the virt-v2v log file for +-30 days in this directory. +- +-This directory is found on the host which performed the conversion. +-The host can be selected in the import dialog, or can be found under +-the C tab in oVirt administration. +- +-=item F +- +-As above, this file is present on the host which performed the +-conversion. It contains detailed error messages from low-level +-operations executed by VDSM, and is useful if the error was not caused +-by virt-v2v, but by VDSM. +- +-=item F +- +-This log file is stored on the RHV-M server. It contains more detail +-for any errors caused by the oVirt GUI. +- +-=back +- +-=head1 SEE ALSO +- +-L. +- +-=head1 AUTHOR +- +-Richard W.M. Jones +- +-=head1 COPYRIGHT +- +-Copyright (C) 2009-2020 Red Hat Inc. +diff --git a/docs/virt-v2v.pod b/docs/virt-v2v.pod +index b94fc8b5..f96fd69f 100644 +--- a/docs/virt-v2v.pod ++++ b/docs/virt-v2v.pod +@@ -13,7 +13,7 @@ virt-v2v - Convert a guest to use KVM + Virt-v2v converts a single guest from a foreign hypervisor to run on + KVM. It can read Linux and Windows guests running on VMware, + Hyper-V and some other hypervisors, and convert them to KVM managed by +-libvirt, OpenStack, oVirt, Red Hat Virtualisation (RHV) or several ++libvirt, OpenStack or several + other targets. It can modify the guest to make it bootable on KVM and + install virtio drivers so it will run quickly. + +@@ -45,8 +45,6 @@ L — Input from VMware. + + L — Output to local files or local libvirt. + +-L — Output to oVirt or RHV. +- + L — Output to OpenStack. + + L — Release notes for 1.42 release. +@@ -74,21 +72,6 @@ disks to F. + + For more information see L. + +-=head2 Convert from VMware to RHV/oVirt +- +-This is the same as the previous example, except you want to send the +-guest to a RHV Data Domain using the RHV REST API. Guest network +-interface(s) are connected to the target network called C. +- +- virt-v2v -ic vpx://vcenter.example.com/Datacenter/esxi vmware_guest \ +- -o rhv-upload -oc https://ovirt-engine.example.com/ovirt-engine/api \ +- -os ovirt-data -op /tmp/ovirt-admin-password -of raw \ +- -oo rhv-cafile=/tmp/ca.pem --bridge ovirtmgmt +- +-In this case the host running virt-v2v acts as a B. +- +-For more information see L. +- + =head2 Convert from ESXi hypervisor over SSH to local libvirt + + You have an ESXi hypervisor called C with SSH access +@@ -468,14 +451,6 @@ no metadata is written. + + Set the output method to OpenStack. See L. + +-=item B<-o> B +- +-This is the same as I<-o rhv>. +- +-=item B<-o> B +- +-This is the same as I<-o rhv-upload>. +- + =item B<-o> B + + Set the output method to I. +@@ -484,40 +459,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>. + +-=item B<-o> B +- +-This is the same as I<-o rhv>. +- +-=item B<-o> B +- +-Set the output method to I. +- +-The converted guest is written to a RHV Export Storage Domain. The +-I<-os> parameter must also be used to specify the location of the +-Export Storage Domain. Note this does not actually import the guest +-into RHV. You have to do that manually later using the UI. +- +-See L. +- +-=item B<-o> B +- +-Set the output method to I. +- +-The converted guest is written directly to a RHV Data Domain. +-This is a faster method than I<-o rhv>, but requires oVirt +-or RHV E 4.2. +- +-See L. +- +-=item B<-o> B +- +-Set the output method to I. +- +-This mode is similar to I<-o rhv>, but the full path to the +-data domain must be given: +-Fdata-center-uuidE/Edata-domain-uuidE>. +-This mode is only used when virt-v2v runs under VDSM control. +- + =item B<-oa> B + + =item B<-oa> B +@@ -580,117 +521,11 @@ For I<-o openstack> (L) only, set optional + OpenStack authentication. For example I<-oo os-username=>NAME is + equivalent to C. + +-=item B<-oo rhv-cafile=>F +- +-For I<-o rhv-upload> (L) only, the F file +-(Certificate Authority), copied from F +-on the oVirt engine. +- +-=item B<-oo rhv-cluster=>C +- +-For I<-o rhv-upload> (L) only, set the RHV Cluster +-Name. If not given it uses C. +- +-=item B<-oo rhv-proxy> +- +-For I<-o rhv-upload> (L) only, proxy the +-upload through oVirt Engine. This is slower than uploading directly +-to the oVirt node but may be necessary if you do not have direct +-network access to the nodes. +- +-=item B<-oo rhv-verifypeer> +- +-For I<-o rhv-upload> (L) only, verify the oVirt/RHV +-server’s identity by checking the server‘s certificate against the +-Certificate Authority. +- + =item B<-oo server-id=>C + + For I<-o openstack> (L) only, set the name + of the conversion appliance where virt-v2v is running. + +-=item B<-oo vdsm-compat=0.10> +- +-=item B<-oo vdsm-compat=1.1> +- +-If I<-o vdsm> and the output format is qcow2, then we add the qcow2 +-I option to the output file for compatibility with RHEL 6 +-(see L). +- +-If I<-oo vdsm-compat=1.1> is used then modern qcow2 (I) +-files are generated instead. +- +-Currently I<-oo vdsm-compat=0.10> is the default, but this will change +-to I<-oo vdsm-compat=1.1> in a future version of virt-v2v (when we can +-assume that everyone is using a modern version of qemu). +- +-B output>. All other output +-modes (including I<-o rhv>) generate modern qcow2 I +-files, always. +- +-If this option is available, then C will appear in +-the I<--machine-readable> output. +- +-=item B<-oo vdsm-image-uuid=>UUID +- +-=item B<-oo vdsm-vol-uuid=>UUID +- +-=item B<-oo vdsm-vm-uuid=>UUID +- +-=item B<-oo vdsm-ovf-output=>DIR +- +-Normally the RHV output mode chooses random UUIDs for the target +-guest. However VDSM needs to control the UUIDs and passes these +-parameters when virt-v2v runs under VDSM control. The parameters +-control: +- +-=over 4 +- +-=item * +- +-the image directory of each guest disk (I<-oo vdsm-image-uuid>) (this +-option is passed once for each guest disk) +- +-=item * +- +-UUIDs for each guest disk (I<-oo vdsm-vol-uuid>) (this option +-is passed once for each guest disk) +- +-=item * +- +-the OVF file name (I<-oo vdsm-vm-uuid>). +- +-=item * +- +-the OVF output directory (default current directory) (I<-oo vdsm-ovf-output>). +- +-=back +- +-The format of UUIDs is: C<12345678-1234-1234-1234-123456789abc> (each +-hex digit can be C<0-9> or C), conforming to S. +- +-These options can only be used with I<-o vdsm>. +- +-=item B<-oo vdsm-ovf-flavour=>flavour +- +-This option controls the format of the OVF generated at the end of conversion. +-Currently there are two possible flavours: +- +-=over 4 +- +-=item rhvexp +- +-The OVF format used in RHV export storage domain. +- +-=item ovirt +- +-The OVF format understood by oVirt REST API. +- +-=back +- +-For backward compatibility the default is I, but this may change in +-the future. +- + =item B<-op> file + + Supply a file containing a password to be used when connecting to the +@@ -708,28 +543,8 @@ For I<-o libvirt>, this is a libvirt directory pool + For I<-o local> and I<-o qemu>, this is a directory name. + The directory must exist. + +-For I<-o rhv-upload>, this is the name of the destination Storage +-Domain. +- + For I<-o openstack>, this is the optional Cinder volume type. + +-For I<-o rhv>, this can be an NFS path of the Export Storage Domain +-of the form ChostE:EpathE>, eg: +- +- rhv-storage.example.com:/rhv/export +- +-The NFS export must be mountable and writable by the user and host +-running virt-v2v, since the virt-v2v program has to actually mount it +-when it runs. So you probably have to run virt-v2v as C. +- +-B You can mount the Export Storage Domain yourself, and point +-I<-os> to the mountpoint. Note that virt-v2v will still need to write +-to this remote directory, so virt-v2v will still need to run as +-C. +- +-You will get an error if virt-v2v is unable to mount/write to the +-Export Storage Domain. +- + =item B<--print-source> + + Print information about the source guest and stop. This option is +@@ -1287,26 +1102,6 @@ require either root or a special user: + + =over 4 + +-=item Mounting the Export Storage Domain +- +-When using I<-o rhv -os server:/esd> virt-v2v has to have sufficient +-privileges to NFS mount the Export Storage Domain from C. +- +-You can avoid needing root here by mounting it yourself before running +-virt-v2v, and passing I<-os /mountpoint> instead, but first of all +-read the next S
+- +-=item Writing to the Export Storage Domain as 36:36 +- +-RHV-M cannot read files and directories from the Export Storage +-Domain unless they have UID:GID 36:36. You will see VM import +-problems if the UID:GID is not correct. +- +-When you run virt-v2v I<-o rhv> as root, virt-v2v attempts to create +-files and directories with the correct ownership. If you run virt-v2v +-as non-root, it will probably still work, but you will need to +-manually change ownership after virt-v2v has finished. +- + =item Writing to libvirt + + When using I<-o libvirt>, you may need to run virt-v2v as root so that +@@ -1413,7 +1208,6 @@ virt-v2v binary. Typical output looks like this: + virt-v2v + libguestfs-rewrite + colours-option +- vdsm-compat-option + input:disk + [...] + output:local +diff --git a/output/Makefile.am b/output/Makefile.am +index 9663acb1..d53a2280 100644 +--- a/output/Makefile.am ++++ b/output/Makefile.am +@@ -17,14 +17,7 @@ + + include $(top_srcdir)/subdir-rules.mk + +-BUILT_SOURCES = \ +- output_rhv_upload_cancel_source.ml \ +- output_rhv_upload_createvm_source.ml \ +- output_rhv_upload_finalize_source.ml \ +- output_rhv_upload_plugin_source.ml \ +- output_rhv_upload_precheck_source.ml \ +- output_rhv_upload_transfer_source.ml \ +- output_rhv_upload_vmcheck_source.ml ++BUILT_SOURCES = + + EXTRA_DIST = \ + $(SOURCES_MLI) \ +@@ -32,13 +25,6 @@ EXTRA_DIST = \ + $(SOURCES_C) \ + $(BUILT_SOURCES) \ + embed.sh \ +- rhv-upload-cancel.py \ +- rhv-upload-createvm.py \ +- rhv-upload-finalize.py \ +- rhv-upload-plugin.py \ +- rhv-upload-precheck.py \ +- rhv-upload-transfer.py \ +- rhv-upload-vmcheck.py \ + test-v2v-python-syntax.sh + + SOURCES_MLI = \ +@@ -54,16 +40,6 @@ SOURCES_MLI = \ + output_null.mli \ + output_openstack.mli \ + output_qemu.mli \ +- output_rhv.mli \ +- output_rhv_upload.mli \ +- output_vdsm.mli \ +- output_rhv_upload_cancel_source.mli \ +- output_rhv_upload_createvm_source.mli \ +- output_rhv_upload_finalize_source.mli \ +- output_rhv_upload_plugin_source.mli \ +- output_rhv_upload_precheck_source.mli \ +- output_rhv_upload_transfer_source.mli \ +- output_rhv_upload_vmcheck_source.mli \ + python_script.mli \ + qemuopts.mli + +@@ -74,13 +50,6 @@ SOURCES_ML = \ + create_kubevirt_yaml.ml \ + qemuopts.ml \ + openstack_image_properties.ml \ +- output_rhv_upload_cancel_source.ml \ +- output_rhv_upload_createvm_source.ml \ +- output_rhv_upload_finalize_source.ml \ +- output_rhv_upload_plugin_source.ml \ +- output_rhv_upload_precheck_source.ml \ +- output_rhv_upload_transfer_source.ml \ +- output_rhv_upload_vmcheck_source.ml \ + output.ml \ + output_disk.ml \ + output_glance.ml \ +@@ -88,30 +57,11 @@ SOURCES_ML = \ + output_libvirt.ml \ + output_null.ml \ + output_openstack.ml \ +- output_qemu.ml \ +- output_rhv.ml \ +- output_rhv_upload.ml \ +- output_vdsm.ml ++ output_qemu.ml + + SOURCES_C = \ + qemuopts-c.c + +-# These files are generated and contain *.py embedded as an OCaml string. +-output_rhv_upload_cancel_source.ml: $(srcdir)/rhv-upload-cancel.py +- $(srcdir)/embed.sh code $^ $@ +-output_rhv_upload_createvm_source.ml: $(srcdir)/rhv-upload-createvm.py +- $(srcdir)/embed.sh code $^ $@ +-output_rhv_upload_finalize_source.ml: $(srcdir)/rhv-upload-finalize.py +- $(srcdir)/embed.sh code $^ $@ +-output_rhv_upload_plugin_source.ml: $(srcdir)/rhv-upload-plugin.py +- $(srcdir)/embed.sh code $^ $@ +-output_rhv_upload_precheck_source.ml: $(srcdir)/rhv-upload-precheck.py +- $(srcdir)/embed.sh code $^ $@ +-output_rhv_upload_transfer_source.ml: $(srcdir)/rhv-upload-transfer.py +- $(srcdir)/embed.sh code $^ $@ +-output_rhv_upload_vmcheck_source.ml: $(srcdir)/rhv-upload-vmcheck.py +- $(srcdir)/embed.sh code $^ $@ +- + # We pretend that we're building a C library. automake handles the + # compilation of the C sources for us. At the end we take the C + # objects and OCaml objects and link them into the OCaml library. +diff --git a/output/output_rhv.ml b/output/output_rhv.ml +deleted file mode 100644 +index 13c2d8dc..00000000 +--- a/output/output_rhv.ml ++++ /dev/null +@@ -1,317 +0,0 @@ +-(* virt-v2v +- * Copyright (C) 2009-2021 Red Hat Inc. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License along +- * with this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +- *) +- +-open Printf +-open Unix +- +-open Std_utils +-open Tools_utils +-open Unix_utils +-open Common_gettext.Gettext +- +-open Types +-open Utils +- +-open Output +- +-module RHV = struct +- type poptions = Types.output_allocation * string * string * string +- +- type t = string * string * string * string list * string list * int64 list +- +- let to_string options = "-o rhv" +- +- let query_output_options () = +- printf (f_"No output options can be used in this mode.\n") +- +- let parse_options options source = +- if options.output_options <> [] then +- error (f_"no -oo (output options) are allowed here"); +- if options.output_password <> None then +- error_option_cannot_be_used_in_output_mode "rhv" "-op"; +- +- (* -os must be set, but at this point we cannot check it. *) +- let output_storage = +- match options.output_storage with +- | None -> error (f_"-o rhv: -os option was not specified") +- | Some d -> d in +- +- let output_name = Option.value ~default:source.s_name options.output_name in +- +- (options.output_alloc, options.output_format, output_name, output_storage) +- +- let rec setup dir options source = +- error_if_disk_count_gt dir 23; +- let disks = get_disks dir in +- let output_alloc, output_format, output_name, output_storage = options in +- +- (* UID:GID required for files and directories when writing to ESD. *) +- let uid = 36 and gid = 36 in +- +- (* Create a UID-switching handle. If we're not root, create a dummy +- * one because we cannot switch UIDs. +- *) +- let running_as_root = geteuid () = 0 in +- let changeuid_t = +- if running_as_root then +- Changeuid.create ~uid ~gid () +- else +- Changeuid.create () in +- +- let esd_mp, esd_uuid = +- mount_and_check_storage_domain (s_"Export Storage Domain") +- output_storage in +- debug "RHV: ESD mountpoint: %s\nRHV: ESD UUID: %s" esd_mp esd_uuid; +- +- (* See if we can write files as UID:GID 36:36. *) +- let () = +- let testfile = esd_mp // esd_uuid // String.random8 () in +- Changeuid.make_file changeuid_t testfile ""; +- let stat = stat testfile in +- Changeuid.unlink changeuid_t testfile; +- let actual_uid = stat.st_uid and actual_gid = stat.st_gid in +- debug "RHV: actual UID:GID of new files is %d:%d" actual_uid actual_gid; +- if uid <> actual_uid || gid <> actual_gid then ( +- if running_as_root then +- warning (f_"cannot write files to the NFS server as %d:%d, \ +- even though we appear to be running as root. This \ +- probably means the NFS client or idmapd is not \ +- configured properly.\n\nYou will have to chown \ +- the files that virt-v2v creates after the run, \ +- otherwise RHV-M will not be able to import the VM.") +- uid gid +- else +- warning (f_"cannot write files to the NFS server as %d:%d. \ +- You might want to stop virt-v2v (^C) and rerun it \ +- as root.") uid gid +- ) in +- +- (* Create unique UUIDs for everything *) +- let vm_uuid = uuidgen () in +- (* Generate random image and volume UUIDs for each target disk. *) +- let image_uuids = List.map (fun _ -> uuidgen ()) disks in +- let vol_uuids = List.map (fun _ -> uuidgen ()) disks in +- +- (* We need to create the target image director(ies) so there's a place +- * for the main program to copy the images to. However if image +- * conversion fails for any reason then we delete this directory. +- *) +- let images_dir = esd_mp // esd_uuid // "images" in +- List.iter ( +- fun image_uuid -> +- let d = images_dir // image_uuid in +- Changeuid.mkdir changeuid_t d 0o755 +- ) image_uuids; +- On_exit.f ( +- fun () -> +- (* virt-v2v writes v2vdir/done on success only. *) +- let success = Sys.file_exists (dir // "done") in +- if not success then ( +- List.iter ( +- fun image_uuid -> +- let d = images_dir // image_uuid in +- let cmd = sprintf "rm -rf %s" (quote d) in +- Changeuid.command changeuid_t cmd +- ) image_uuids +- ) +- ); +- +- (* The final directory structure should look like this: +- * ///images/ +- * / # first disk +- * /.meta # first disk +- * / # second disk +- * /.meta # second disk +- * / # etc +- * /.meta # +- *) +- +- (* Generate the randomly named target files (just the names). +- * The main code is what generates the files themselves. +- *) +- let filenames = +- List.map ( +- fun (image_uuid, vol_uuid) -> +- let filename = images_dir // image_uuid // vol_uuid in +- debug "RHV: disk: %s" filename; +- filename +- ) (List.combine image_uuids vol_uuids) in +- +- (* Generate the .meta file associated with each volume. *) +- let sizes = List.map snd disks in +- let metas = +- Create_ovf.create_meta_files output_alloc output_format +- esd_uuid image_uuids sizes in +- List.iter ( +- fun (filename, meta) -> +- let meta_filename = filename ^ ".meta" in +- Changeuid.make_file changeuid_t meta_filename meta +- ) (List.combine filenames metas); +- +- (* Set up the NBD servers. *) +- List.iter ( +- fun ((i, size), filename) -> +- let socket = sprintf "%s/out%d" dir i in +- On_exit.unlink socket; +- +- (* Create the actual output disk. *) +- let changeuid f = +- Changeuid.func changeuid_t ( +- fun () -> +- (* Run the command to create the file. *) +- f (); +- (* Make the file sufficiently writable so that possibly root, or +- * root squashed nbdkit will definitely be able to open it. +- * An example of how root squashing nonsense makes everyone +- * less secure. +- *) +- chmod filename 0o666 +- ) +- in +- +- (* We have to wait for the NBD server to exit rather than just +- * killing it, otherwise it races with unmounting. See: +- * https://bugzilla.redhat.com/show_bug.cgi?id=1953286#c26 +- *) +- let on_exit_kill = Output.KillAndWait in +- +- output_to_local_file ~changeuid ~on_exit_kill +- output_alloc output_format filename size socket +- ) (List.combine disks filenames); +- +- (* Save parameters since we need them during finalization. *) +- let t = esd_mp, esd_uuid, vm_uuid, image_uuids, vol_uuids, sizes in +- t +- +- and mount_and_check_storage_domain domain_class os = +- (* The user can either specify -os nfs:/export, or a local directory +- * which is assumed to be the already-mounted NFS export. +- *) +- match String.split ":/" os with +- | mp, "" -> (* Already mounted directory. *) +- check_storage_domain domain_class os mp +- | server, export -> +- let export = "/" ^ export in +- +- (* Create a mountpoint. Default mode is too restrictive for us +- * when we need to write into the directory as 36:36. +- *) +- let mp = Mkdtemp.temp_dir "v2v." in +- chmod mp 0o755; +- +- (* Try mounting it. *) +- let cmd = [ "mount"; sprintf "%s:%s" server export; mp ] in +- if run_command cmd <> 0 then +- error (f_"mount command failed, see earlier errors.\n\nThis probably \ +- means you didn't specify the right %s path [-os %s], or \ +- else you need to rerun virt-v2v as root.") domain_class os; +- +- (* Make sure it is unmounted at exit, as late as possible (prio=9999) *) +- On_exit.f ~prio:9999 ( +- fun () -> +- let cmd = [ "umount"; mp ] in +- ignore (run_command cmd); +- try rmdir mp with _ -> () +- ); +- +- check_storage_domain domain_class os mp +- +- and check_storage_domain domain_class os mp = +- (* Typical SD mountpoint looks like this: +- * $ ls /tmp/mnt +- * 39b6af0e-1d64-40c2-97e4-4f094f1919c7 __DIRECT_IO_TEST__ lost+found +- * $ ls /tmp/mnt/39b6af0e-1d64-40c2-97e4-4f094f1919c7 +- * dom_md images master +- * We expect exactly one of those magic UUIDs. +- *) +- let entries = +- try Sys.readdir mp +- with Sys_error msg -> +- error (f_"could not read the %s specified by the '-os %s' \ +- parameter on the command line. Is it really an \ +- OVirt or RHV-M %s? The original error is: %s") +- domain_class os domain_class msg in +- let entries = Array.to_list entries in +- let uuids = List.filter ( +- fun entry -> +- String.length entry = 36 && +- entry.[8] = '-' && entry.[13] = '-' && entry.[18] = '-' && +- entry.[23] = '-' +- ) entries in +- let uuid = +- match uuids with +- | [uuid] -> uuid +- | [] -> +- error (f_"there are no UUIDs in the %s (%s). Is it really an \ +- OVirt or RHV-M %s?") domain_class os domain_class +- | _::_ -> +- error (f_"there are multiple UUIDs in the %s (%s). This is \ +- unexpected, and may be a bug in virt-v2v or OVirt.") +- domain_class os in +- +- (* Check that the domain has been attached to a Data Center by +- * checking that the master/vms directory exists. +- *) +- let () = +- let master_vms_dir = mp // uuid // "master" // "vms" in +- if not (is_directory master_vms_dir) then +- error (f_"%s does not exist or is not a directory.\n\nMost likely \ +- cause: Either the %s (%s) has not been attached to any \ +- Data Center, or the path %s is not an %s at all.\n\n\ +- You have to attach the %s to a Data Center using the \ +- RHV-M / OVirt user interface first.\n\nIf you don’t \ +- know what the %s mount point should be then you can \ +- also find this out through the RHV-M user interface.") +- master_vms_dir domain_class os os +- domain_class domain_class domain_class in +- +- (* Looks good, so return the SD mountpoint and UUID. *) +- (mp, uuid) +- +- let finalize dir options t source inspect target_meta = +- let output_alloc, output_format, output_name, output_storage = options in +- let esd_mp, esd_uuid, vm_uuid, image_uuids, vol_uuids, sizes = t in +- +- (* UID:GID required for files and directories when writing to ESD. *) +- let uid = 36 and gid = 36 in +- +- (* Create a UID-switching handle. If we're not root, create a dummy +- * one because we cannot switch UIDs. +- *) +- let running_as_root = geteuid () = 0 in +- let changeuid_t = +- if running_as_root then +- Changeuid.create ~uid ~gid () +- else +- Changeuid.create () in +- +- (* Create the metadata. *) +- let ovf = +- Create_ovf.create_ovf source inspect target_meta sizes +- output_alloc output_format output_name esd_uuid image_uuids vol_uuids +- ~need_actual_sizes:true dir vm_uuid +- Create_ovf.RHVExportStorageDomain in +- +- (* Write it to the metadata file. *) +- let dir = esd_mp // esd_uuid // "master" // "vms" // vm_uuid in +- Changeuid.mkdir changeuid_t dir 0o755; +- let file = dir // vm_uuid ^ ".ovf" in +- Changeuid.output changeuid_t file (fun chan -> DOM.doc_to_chan chan ovf) +- +- let request_size = None +-end +diff --git a/output/output_rhv.mli b/output/output_rhv.mli +deleted file mode 100644 +index 08f3f2d0..00000000 +--- a/output/output_rhv.mli ++++ /dev/null +@@ -1,21 +0,0 @@ +-(* virt-v2v +- * Copyright (C) 2009-2021 Red Hat Inc. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License along +- * with this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +- *) +- +-(** [-o rhv] output mode. *) +- +-module RHV : Output.OUTPUT +diff --git a/output/output_rhv_upload.ml b/output/output_rhv_upload.ml +deleted file mode 100644 +index 63624860..00000000 +--- a/output/output_rhv_upload.ml ++++ /dev/null +@@ -1,520 +0,0 @@ +-(* virt-v2v +- * Copyright (C) 2009-2021 Red Hat Inc. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License along +- * with this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +- *) +- +-open Printf +-open Unix +- +-open Std_utils +-open Tools_utils +-open Common_gettext.Gettext +- +-open Types +-open Utils +- +-open Output +- +-module RHVUpload = struct +- type poptions = string * string * string * string * string * +- string option * string option * bool * bool * +- string list option +- +- type t = int64 list * string list * string list * +- Python_script.script * Python_script.script * +- JSON.field list * string option * string option * +- string option * string * int list ref +- +- let to_string options = +- "-o rhv-upload" ^ +- (match options.output_conn with +- | Some oc -> " -oc " ^ oc +- | None -> "") ^ +- (match options.output_storage with +- | Some os -> " -os " ^ os +- | None -> "") +- +- let query_output_options () = +- printf (f_"Output options (-oo) which can be used with -o rhv-upload: +- +- -oo rhv-cafile=CA.PEM Set ‘ca.pem’ certificate bundle filename. +- -oo rhv-cluster=CLUSTERNAME Set RHV cluster name. +- -oo rhv-proxy Connect via oVirt Engine proxy (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 rec parse_options options source = +- let output_conn = +- match options.output_conn with +- | None -> +- error (f_"-o rhv-upload: use ‘-oc’ to point to the oVirt \ +- or RHV server REST API URL, which is usually \ +- https://servername/ovirt-engine/api") +- | Some oc -> oc in +- (* In theory we could make the password optional in future. *) +- let output_password = +- match options.output_password with +- | None -> +- error (f_"-o rhv-upload: output password file was not specified, \ +- use ‘-op’ to point to a file which contains the password \ +- used to connect to the oVirt or RHV server") +- | Some op -> op in +- let output_storage = +- match options.output_storage with +- | None -> +- error (f_"-o rhv-upload: output storage was not specified, use ‘-os’"); +- | Some os -> os in +- +- let rhv_cafile = ref None in +- let rhv_cluster = ref None in +- let rhv_direct = ref true in +- let rhv_verifypeer = ref false in +- let rhv_disk_uuids = ref None in +- +- List.iter ( +- function +- | "rhv-cafile", v -> +- if !rhv_cafile <> None then +- error (f_"-o rhv-upload: -oo rhv-cafile set more than once"); +- rhv_cafile := Some v +- | "rhv-cluster", v -> +- if !rhv_cluster <> None then +- error (f_"-o rhv-upload: -oo rhv-cluster set more than once"); +- rhv_cluster := Some v +- | "rhv-direct", "" -> rhv_direct := true +- | "rhv-direct", v -> rhv_direct := bool_of_string v +- | "rhv-proxy", "" -> rhv_direct := false +- | "rhv-proxy", v -> rhv_direct := not (bool_of_string v) +- | "rhv-verifypeer", "" -> rhv_verifypeer := true +- | "rhv-verifypeer", v -> rhv_verifypeer := bool_of_string v +- | "rhv-disk-uuid", v -> +- if not (is_nonnil_uuid v) then +- error (f_"-o rhv-upload: invalid UUID for -oo rhv-disk-uuid"); +- rhv_disk_uuids := Some (v :: (Option.value ~default:[] !rhv_disk_uuids)) +- | k, _ -> +- error (f_"-o rhv-upload: unknown output option ‘-oo %s’") k +- ) options.output_options; +- +- 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 +- +- let output_name = Option.value ~default:source.s_name options.output_name in +- +- (output_conn, options.output_format, +- output_password, output_name, output_storage, +- rhv_cafile, rhv_cluster, rhv_direct, +- rhv_verifypeer, rhv_disk_uuids) +- +- and is_nonnil_uuid uuid = +- let nil_uuid = "00000000-0000-0000-0000-000000000000" in +- let rex_uuid = lazy ( +- let hex = "[a-fA-F0-9]" in +- let str = sprintf "^%s{8}-%s{4}-%s{4}-%s{4}-%s{12}$" +- hex hex hex hex hex in +- PCRE.compile str +- ) in +- if uuid = nil_uuid then false +- else PCRE.matches (Lazy.force rex_uuid) uuid +- +- let rec setup dir options source = +- error_if_disk_count_gt dir 23; +- let disks = get_disks dir in +- let output_conn, output_format, +- output_password, output_name, output_storage, +- rhv_cafile, rhv_cluster, rhv_direct, +- rhv_verifypeer, rhv_disk_uuids = options in +- +- (* We need nbdkit >= 1.22 for API_VERSION 2 and parallel threading model +- * in the python plugin. +- *) +- let nbdkit_min_version = (1, 22, 0) in +- let nbdkit_min_version_string = "1.22.0" in +- +- (* Check that the 'ovirtsdk4' Python module is available. *) +- let error_unless_ovirtsdk4_module_available () = +- let res = run_command [ Python_script.python; "-c"; +- "import ovirtsdk4" ] in +- if res <> 0 then +- error (f_"the Python module ‘ovirtsdk4’ could not be loaded, \ +- is it installed? See previous messages for problems.") +- in +- +- (* Check that nbdkit is available and new enough. *) +- let error_unless_nbdkit_working () = +- if not (Nbdkit.is_installed ()) then +- error (f_"nbdkit is not installed or not working. It is required \ +- to use ‘-o rhv-upload’. See the virt-v2v-output-rhv(1) \ +- manual.") +- in +- +- let error_unless_nbdkit_min_version () = +- let version = Nbdkit.version () in +- if version < nbdkit_min_version then +- error (f_"nbdkit is not new enough, you need to upgrade to nbdkit ≥ %s") +- nbdkit_min_version_string +- in +- +- (* Check that the python3 plugin is installed and working +- * and can load the plugin script. +- *) +- let error_unless_nbdkit_python_plugin_working plugin_script = +- let cmd = sprintf "nbdkit python %s --dump-plugin >/dev/null" +- (quote (Python_script.path plugin_script)) in +- debug "%s" cmd; +- if Sys.command cmd <> 0 then +- error (f_"nbdkit python plugin is not installed or not working. \ +- It is required if you want to use ‘-o rhv-upload’. +- +-See also the virt-v2v-output-rhv(1) manual."); +- in +- +- (* Check that nbdkit was compiled with SELinux support (for the +- * --selinux-label option). +- *) +- let error_unless_nbdkit_compiled_with_selinux () = +- if have_selinux then ( +- let config = Nbdkit.config () in +- let selinux = try List.assoc "selinux" config with Not_found -> "no" in +- if selinux = "no" then +- error (f_"nbdkit was compiled without SELinux support. You will \ +- have to recompile nbdkit with libselinux-devel installed, \ +- or else set SELinux to Permissive mode while doing the \ +- conversion.") +- ) +- in +- +- Python_script.error_unless_python_interpreter_found (); +- error_unless_ovirtsdk4_module_available (); +- error_unless_nbdkit_working (); +- error_unless_nbdkit_min_version (); +- error_unless_nbdkit_compiled_with_selinux (); +- +- (* Python code. *) +- 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 +- let transfer_script = +- Python_script.create ~name:"rhv-upload-transfer.py" +- Output_rhv_upload_transfer_source.code in +- let finalize_script = +- Python_script.create ~name:"rhv-upload-finalize.py" +- Output_rhv_upload_finalize_source.code in +- let cancel_script = +- Python_script.create ~name:"rhv-upload-cancel.py" +- Output_rhv_upload_cancel_source.code in +- let createvm_script = +- Python_script.create ~name:"rhv-upload-createvm.py" +- Output_rhv_upload_createvm_source.code in +- +- error_unless_nbdkit_python_plugin_working plugin_script; +- +- (* JSON parameters which are invariant between disks. *) +- let json_params = [ +- "verbose", JSON.Bool (verbose ()); +- +- "output_conn", JSON.String output_conn; +- "output_password", JSON.String output_password; +- "output_storage", JSON.String output_storage; +- "rhv_cafile", json_optstring rhv_cafile; +- "rhv_cluster", JSON.String (Option.value ~default:"Default" rhv_cluster); +- "rhv_direct", JSON.Bool rhv_direct; +- +- (* The 'Insecure' flag seems to be a number with various possible +- * meanings, however we just set it to True/False. +- * +- * https://github.com/oVirt/ovirt-engine-sdk/blob/19aa7070b80e60a4cfd910448287aecf9083acbe/sdk/lib/ovirtsdk4/__init__.py#L395 +- *) +- "insecure", JSON.Bool (not rhv_verifypeer); +- ] in +- +- (* nbdkit command line which is invariant between disks. *) +- let cmd = Nbdkit.create "python" in +- Nbdkit.add_arg cmd "script" (Python_script.path plugin_script); +- +- (* Match number of parallel coroutines in qemu-img *) +- Nbdkit.set_threads cmd 8; +- +- (* Python code prechecks. *) +- let json_params = match rhv_disk_uuids with +- | None -> json_params +- | Some uuids -> +- let ids = List.map (fun uuid -> JSON.String uuid) uuids in +- ("rhv_disk_uuids", JSON.List ids) :: json_params +- in +- let precheck_json = dir // "v2vprecheck.json" in +- let fd = Unix.openfile precheck_json [O_WRONLY; O_CREAT; O_TRUNC] 0o600 in +- if Python_script.run_command ~stdout_fd:fd +- precheck_script json_params [] <> 0 then +- error (f_"failed server prechecks, see earlier errors"); +- if verbose () then +- debug "precheck output before parsing: %s" +- (read_whole_file precheck_json); +- let json = JSON_parser.json_parser_tree_parse_file precheck_json in +- debug "precheck output parsed as: %s" +- (JSON.string_of_doc ~fmt:JSON.Indented ["", json]); +- let rhv_storagedomain_uuid = +- Some (JSON_parser.object_get_string "rhv_storagedomain_uuid" json) in +- let rhv_cluster_uuid = +- Some (JSON_parser.object_get_string "rhv_cluster_uuid" json) in +- let rhv_cluster_cpu_architecture = +- Some (JSON_parser.object_get_string "rhv_cluster_cpu_architecture" json) in +- +- (* If the disk UUIDs were not provided, then generate them. +- * This is simpler than letting RHV generate them and trying +- * to read them back from RHV. +- *) +- let disk_uuids = +- match rhv_disk_uuids with +- | Some uuids -> +- let nr_disks = List.length disks in +- if List.length uuids <> nr_disks 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)") nr_disks; +- uuids +- | None -> List.map (fun _ -> uuidgen ()) disks in +- +- (* This will accumulate the list of transfer IDs from the transfer +- * script. +- *) +- let transfer_ids = ref [] in +- +- let rhv_cluster_name = +- match List.assoc "rhv_cluster" json_params with +- | JSON.String s -> s +- | _ -> assert false in +- +- let json_params = +- ("output_name", JSON.String output_name) :: json_params in +- +- (* 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 vmcheck_script json_params [] <> 0 then +- error (f_"failed vmchecks, see earlier errors"); +- +- (* Cancel the transfer and delete disks. +- * +- * This ignores errors since the only time we are doing this is on +- * the failure path. +- *) +- let cancel transfer_ids disk_uuids = +- let ids = List.map (fun id -> JSON.String id) transfer_ids in +- let json_params = ("transfer_ids", JSON.List ids) :: json_params in +- let ids = List.map (fun uuid -> JSON.String uuid) disk_uuids in +- let json_params = ("disk_uuids", JSON.List ids) :: json_params in +- ignore (Python_script.run_command cancel_script json_params []) +- in +- +- (* Set up an at-exit handler to perform some cleanups. +- * - Kill nbdkit PIDs (only before finalization). +- * - Delete the orphan disks (only on conversion failure). +- *) +- let nbdkit_pids = ref [] in +- On_exit.f ( +- fun () -> +- (* Kill the nbdkit PIDs. *) +- List.iter ( +- fun pid -> +- try kill pid Sys.sigterm +- with exn -> debug "%s" (Printexc.to_string exn) +- ) !nbdkit_pids; +- nbdkit_pids := []; +- +- (* virt-v2v writes v2vdir/done on success only. *) +- let success = Sys.file_exists (dir // "done") in +- if not success then ( +- if disk_uuids <> [] then +- cancel !transfer_ids disk_uuids +- ) +- ); +- +- (* Create an nbdkit instance for each disk and set the +- * target URI to point to the NBD socket. +- *) +- List.iter ( +- fun ((i, size), uuid) -> +- let socket = sprintf "%s/out%d" dir i in +- On_exit.unlink socket; +- +- let disk_name = sprintf "%s-%03d" output_name i in +- let json_params = +- ("disk_name", JSON.String disk_name) :: json_params in +- +- let disk_format = +- match output_format with +- | "raw" as fmt -> fmt +- | "qcow2" as fmt -> fmt +- | _ -> +- error (f_"rhv-upload: -of %s: Only output format ‘raw’ or ‘qcow2’ \ +- is supported. If the input is in a different format \ +- then force one of these output formats by adding \ +- either ‘-of raw’ or ‘-of qcow2’ on the command line.") +- output_format in +- let json_params = +- ("disk_format", JSON.String disk_format) :: json_params in +- +- let json_params = +- ("disk_size", JSON.Int size) :: json_params in +- +- let json_params = +- ("disk_uuid", JSON.String uuid) :: json_params in +- +- (* Write the JSON parameters to a file. *) +- let json_param_file = dir // sprintf "out.params%d.json" i in +- with_open_out +- json_param_file +- (fun chan -> output_string chan (JSON.string_of_doc json_params)); +- +- (* Start the transfer. *) +- let transfer_json = dir // sprintf "v2vtransfer%d.json" i in +- let fd = +- Unix.openfile transfer_json [O_WRONLY; O_CREAT; O_TRUNC] 0o600 in +- if Python_script.run_command ~stdout_fd:fd +- transfer_script json_params [] <> 0 then +- error (f_"failed to start transfer, see earlier errors"); +- if verbose () then +- debug "transfer output before parsing: %s" +- (read_whole_file transfer_json); +- let json = JSON_parser.json_parser_tree_parse_file transfer_json in +- debug "transfer output parsed as: %s" +- (JSON.string_of_doc ~fmt:JSON.Indented ["", json]); +- let destination_url = +- JSON_parser.object_get_string "destination_url" json in +- let transfer_id = +- JSON_parser.object_get_string "transfer_id" json in +- List.push_back transfer_ids transfer_id; +- let is_ovirt_host = +- JSON_parser.object_get_bool "is_ovirt_host" json in +- +- (* Create the nbdkit instance. *) +- Nbdkit.add_arg cmd "size" (Int64.to_string size); +- Nbdkit.add_arg cmd "url" destination_url; +- Option.iter (Nbdkit.add_arg cmd "cafile") rhv_cafile; +- if not rhv_verifypeer then +- Nbdkit.add_arg cmd "insecure" "true"; +- if is_ovirt_host then +- Nbdkit.add_arg cmd "is_ovirt_host" "true"; +- let _, pid = Nbdkit.run_unix socket cmd in +- List.push_front pid nbdkit_pids +- ) (List.combine disks disk_uuids); +- +- (* Stash some data we will need during finalization. *) +- let disk_sizes = List.map snd disks in +- let t = (disk_sizes : int64 list), disk_uuids, !transfer_ids, +- finalize_script, createvm_script, json_params, +- rhv_storagedomain_uuid, rhv_cluster_uuid, +- rhv_cluster_cpu_architecture, rhv_cluster_name, nbdkit_pids in +- t +- +- and json_optstring = function +- | Some s -> JSON.String s +- | None -> JSON.Null +- +- let finalize dir options t source inspect target_meta = +- let output_conn, output_format, +- output_password, output_name, output_storage, +- rhv_cafile, rhv_cluster, rhv_direct, +- rhv_verifypeer, rhv_disk_uuids = options in +- let disk_sizes, disk_uuids, transfer_ids, +- finalize_script, createvm_script, json_params, +- rhv_storagedomain_uuid, rhv_cluster_uuid, +- rhv_cluster_cpu_architecture, rhv_cluster_name, +- nbdkit_pids = t in +- +- (* Check the cluster CPU arch matches what we derived about the +- * guest during conversion. +- *) +- (match rhv_cluster_cpu_architecture with +- | None -> assert false +- | Some arch -> +- if arch <> target_meta.guestcaps.gcaps_arch then +- error (f_"the cluster ‘%s’ does not support the architecture %s \ +- but %s") +- rhv_cluster_name target_meta.guestcaps.gcaps_arch arch +- ); +- +- (* We must kill all our nbdkit instances before finalizing the +- * transfer. See: +- * https://listman.redhat.com/archives/libguestfs/2022-February/msg00111.html +- * +- * We want to fail here if the kill fails because nbdkit +- * died already, as that would be unexpected. +- *) +- let () = +- let pids = !nbdkit_pids in +- List.iter (fun pid -> kill pid Sys.sigterm) pids; +- List.iter (fun pid -> ignore (waitpid [] pid)) pids; +- nbdkit_pids := [] (* Don't kill them again in the On_exit handler. *) in +- +- (* Finalize all the transfers. *) +- let json_params = +- let ids = List.map (fun id -> JSON.String id) transfer_ids in +- let json_params = ("transfer_ids", JSON.List ids) :: json_params in +- let ids = List.map (fun uuid -> JSON.String uuid) disk_uuids in +- let json_params = ("disk_uuids", JSON.List ids) :: json_params in +- json_params in +- if Python_script.run_command finalize_script json_params [] <> 0 then +- error (f_"failed to finalize the transfers, see earlier errors"); +- +- (* 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 ()) disk_sizes +- and vm_uuid = uuidgen () in +- +- (* Create the metadata. *) +- let ovf = +- Create_ovf.create_ovf source inspect target_meta disk_sizes +- Sparse output_format output_name +- sd_uuid disk_uuids vol_uuids dir vm_uuid 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 = dir // "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 +- then +- error (f_"failed to create virtual machine, see earlier errors") +- +- (* The imageio server has high overhead per request. Using 4 MiB +- * request size is 1.8x times faster compared with nbdcopy default +- * request size (256k). +- *) +- let request_size = Some (4*1024*1024) +-end +diff --git a/output/output_rhv_upload.mli b/output/output_rhv_upload.mli +deleted file mode 100644 +index 35457596..00000000 +--- a/output/output_rhv_upload.mli ++++ /dev/null +@@ -1,21 +0,0 @@ +-(* virt-v2v +- * Copyright (C) 2009-2021 Red Hat Inc. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License along +- * with this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +- *) +- +-(** [-o rhv-upload] output mode. *) +- +-module RHVUpload : Output.OUTPUT +diff --git a/output/output_rhv_upload_cancel_source.mli b/output/output_rhv_upload_cancel_source.mli +deleted file mode 100644 +index aa33bc54..00000000 +--- a/output/output_rhv_upload_cancel_source.mli ++++ /dev/null +@@ -1,19 +0,0 @@ +-(* 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. +- *) +- +-val code : string +diff --git a/output/output_rhv_upload_createvm_source.mli b/output/output_rhv_upload_createvm_source.mli +deleted file mode 100644 +index c1bafa15..00000000 +--- a/output/output_rhv_upload_createvm_source.mli ++++ /dev/null +@@ -1,19 +0,0 @@ +-(* 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/output/output_rhv_upload_finalize_source.mli b/output/output_rhv_upload_finalize_source.mli +deleted file mode 100644 +index aa33bc54..00000000 +--- a/output/output_rhv_upload_finalize_source.mli ++++ /dev/null +@@ -1,19 +0,0 @@ +-(* 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. +- *) +- +-val code : string +diff --git a/output/output_rhv_upload_plugin_source.mli b/output/output_rhv_upload_plugin_source.mli +deleted file mode 100644 +index c1bafa15..00000000 +--- a/output/output_rhv_upload_plugin_source.mli ++++ /dev/null +@@ -1,19 +0,0 @@ +-(* 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/output/output_rhv_upload_precheck_source.mli b/output/output_rhv_upload_precheck_source.mli +deleted file mode 100644 +index aa33bc54..00000000 +--- a/output/output_rhv_upload_precheck_source.mli ++++ /dev/null +@@ -1,19 +0,0 @@ +-(* 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. +- *) +- +-val code : string +diff --git a/output/output_rhv_upload_transfer_source.mli b/output/output_rhv_upload_transfer_source.mli +deleted file mode 100644 +index aa33bc54..00000000 +--- a/output/output_rhv_upload_transfer_source.mli ++++ /dev/null +@@ -1,19 +0,0 @@ +-(* 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. +- *) +- +-val code : string +diff --git a/output/output_rhv_upload_vmcheck_source.mli b/output/output_rhv_upload_vmcheck_source.mli +deleted file mode 100644 +index c1bafa15..00000000 +--- a/output/output_rhv_upload_vmcheck_source.mli ++++ /dev/null +@@ -1,19 +0,0 @@ +-(* 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/output/output_vdsm.ml b/output/output_vdsm.ml +deleted file mode 100644 +index 3052fb9c..00000000 +--- a/output/output_vdsm.ml ++++ /dev/null +@@ -1,237 +0,0 @@ +-(* virt-v2v +- * Copyright (C) 2009-2021 Red Hat Inc. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License along +- * with this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +- *) +- +-open Printf +-open Unix +- +-open Std_utils +-open Tools_utils +-open Common_gettext.Gettext +- +-open Types +-open Utils +- +-open Output +- +-module VDSM = struct +- type poptions = Types.output_allocation * string * string * string * +- string list * string list * string * string * +- string * Create_ovf.ovf_flavour +- +- type t = string * string * int64 list +- +- let to_string options = "-o vdsm" +- +- let query_output_options () = +- let ovf_flavours_str = String.concat "|" Create_ovf.ovf_flavours in +- +- printf (f_"Output options (-oo) which can be used with -o vdsm: +- +- -oo vdsm-compat=0.10|1.1 Write qcow2 with compat=0.10|1.1 +- (default: 0.10) +- -oo vdsm-vm-uuid=UUID VM UUID (required) +- -oo vdsm-ovf-output=DIR OVF metadata directory (required) +- -oo vdsm-ovf-flavour=%s +- Set the type of generated OVF (default: rhvexp) +- +-For each disk you must supply one of each of these options: +- +- -oo vdsm-image-uuid=UUID Image directory UUID +- -oo vdsm-vol-uuid=UUID Disk volume UUID +-") ovf_flavours_str +- +- let parse_options options source = +- if options.output_password <> None then +- error_option_cannot_be_used_in_output_mode "vdsm" "-op"; +- +- let vm_uuid = ref None in +- let ovf_output = ref None in (* default "." *) +- let compat = ref "0.10" in +- let ovf_flavour = ref Create_ovf.RHVExportStorageDomain in +- let image_uuids = ref [] in +- let vol_uuids = ref [] in +- +- List.iter ( +- function +- | "vdsm-compat", "0.10" -> compat := "0.10" +- | "vdsm-compat", "1.1" -> compat := "1.1" +- | "vdsm-compat", v -> +- error (f_"-o vdsm: unknown vdsm-compat level ‘%s’") v +- | "vdsm-vm-uuid", v -> +- if !vm_uuid <> None then +- error (f_"-o vdsm: -oo vdsm-vm-uuid set more than once"); +- vm_uuid := Some v; +- | "vdsm-ovf-output", v -> +- if !ovf_output <> None then +- error (f_"-o vdsm: -oo vdsm-ovf-output set more than once"); +- ovf_output := Some v; +- | "vdsm-ovf-flavour", v -> +- ovf_flavour := Create_ovf.ovf_flavour_of_string v +- | "vdsm-image-uuid", v -> +- List.push_front v image_uuids +- | "vdsm-vol-uuid", v -> +- List.push_front v vol_uuids +- | k, _ -> +- error (f_"-o vdsm: unknown output option ‘-oo %s’") k +- ) options.output_options; +- +- let compat = !compat in +- let image_uuids = List.rev !image_uuids in +- let vol_uuids = List.rev !vol_uuids in +- if image_uuids = [] || vol_uuids = [] then +- error (f_"-o vdsm: either -oo vdsm-vol-uuid or \ +- -oo vdsm-vm-uuid was not specified"); +- let vm_uuid = +- match !vm_uuid with +- | None -> +- error (f_"-o vdsm: -oo vdsm-image-uuid was not specified") +- | Some uuid -> uuid in +- let ovf_output = Option.value ~default:"." !ovf_output in +- let ovf_flavour = !ovf_flavour in +- +- (* -os must be set, but at this point we cannot check it. *) +- let output_storage = +- match options.output_storage with +- | None -> error (f_"-o vdsm: -os option was not specified") +- | 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 +- +- let output_name = Option.value ~default:source.s_name options.output_name in +- +- (options.output_alloc, options.output_format, +- output_name, output_storage, +- image_uuids, vol_uuids, vm_uuid, ovf_output, +- compat, ovf_flavour) +- +- let setup dir options source = +- error_if_disk_count_gt dir 23; +- let disks = get_disks dir in +- let output_alloc, output_format, +- output_name, output_storage, +- image_uuids, vol_uuids, vm_uuid, ovf_output, +- compat, ovf_flavour = options in +- +- if List.length image_uuids <> List.length disks || +- List.length vol_uuids <> List.length disks then +- error (f_"the number of ‘-oo vdsm-image-uuid’ and ‘-oo vdsm-vol-uuid’ \ +- parameters passed on the command line has to match the \ +- number of guest disk images (for this guest: %d)") +- (List.length disks); +- +- let dd_mp, dd_uuid = +- let fields = +- String.nsplit "/" output_storage in (* ... "data-center" "UUID" *) +- let fields = List.rev fields in (* "UUID" "data-center" ... *) +- let fields = List.dropwhile ((=) "") fields in +- match fields with +- | uuid :: rest when String.length uuid = 36 -> +- let mp = String.concat "/" (List.rev rest) in +- mp, uuid +- | _ -> +- error (f_"vdsm: invalid -os parameter \ +- does not contain a valid UUID: %s") +- output_storage in +- +- debug "VDSM: DD mountpoint: %s\nVDSM: DD UUID: %s" dd_mp dd_uuid; +- +- (* Note that VDSM has to create all these directories. *) +- let images_dir = dd_mp // dd_uuid // "images" in +- List.iter ( +- fun image_uuid -> +- let d = images_dir // image_uuid in +- if not (is_directory d) then +- error (f_"image directory (%s) does not exist or is not a directory") +- d +- ) image_uuids; +- +- (* Note that VDSM has to create this directory too. *) +- if not (is_directory ovf_output) then +- error (f_"OVF (metadata) directory (%s) does not exist or \ +- is not a directory") +- ovf_output; +- +- debug "VDSM: OVF (metadata) directory: %s" ovf_output; +- +- (* The final directory structure should look like this: +- * ///images/ +- * / # first disk +- * /.meta # first disk +- * / # second disk +- * /.meta # second disk +- * / # etc +- * /.meta # +- *) +- +- (* Create the target filenames. *) +- let filenames = +- List.map ( +- fun (image_uuid, vol_uuid) -> +- let filename = images_dir // image_uuid // vol_uuid in +- debug "VDSM: disk: %s" filename; +- filename +- ) (List.combine image_uuids vol_uuids) in +- +- (* Generate the .meta files associated with each volume. *) +- let sizes = List.map snd disks in +- let metas = +- Create_ovf.create_meta_files output_alloc output_format +- dd_uuid image_uuids sizes in +- List.iter ( +- fun (filename, meta) -> +- let meta_filename = filename ^ ".meta" in +- with_open_out meta_filename (fun chan -> output_string chan meta) +- ) (List.combine filenames metas); +- +- (* Set up the NBD servers. *) +- List.iter ( +- fun ((i, size), filename) -> +- let socket = sprintf "%s/out%d" dir i in +- On_exit.unlink socket; +- +- (* Create the actual output disk. *) +- output_to_local_file output_alloc output_format filename size socket +- ) (List.combine disks filenames); +- +- (* Save parameters since we need them during finalization. *) +- let t = dd_mp, dd_uuid, sizes in +- t +- +- let finalize dir options t source inspect target_meta = +- let output_alloc, output_format, +- output_name, output_storage, +- image_uuids, vol_uuids, vm_uuid, ovf_output, +- compat, ovf_flavour = options in +- let dd_mp, dd_uuid, sizes = t in +- +- (* Create the metadata. *) +- let ovf = Create_ovf.create_ovf source inspect target_meta sizes +- output_alloc output_format output_name dd_uuid +- image_uuids +- vol_uuids +- dir +- vm_uuid +- ovf_flavour in +- +- (* Write it to the metadata file. *) +- let file = ovf_output // vm_uuid ^ ".ovf" in +- with_open_out file (fun chan -> DOM.doc_to_chan chan ovf) +- +- let request_size = None +-end +diff --git a/output/output_vdsm.mli b/output/output_vdsm.mli +deleted file mode 100644 +index 2260d7e6..00000000 +--- a/output/output_vdsm.mli ++++ /dev/null +@@ -1,21 +0,0 @@ +-(* virt-v2v +- * Copyright (C) 2009-2021 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 vdsm] output mode. *) +- +-module VDSM : Output.OUTPUT +diff --git a/output/rhv-upload-cancel.py b/output/rhv-upload-cancel.py +deleted file mode 100644 +index b36e1904..00000000 +--- a/output/rhv-upload-cancel.py ++++ /dev/null +@@ -1,96 +0,0 @@ +-# -*- python -*- +-# oVirt or RHV upload cancel used by ‘virt-v2v -o rhv-upload’ +-# Copyright (C) 2019-2021 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 +-from contextlib import closing +-from urllib.parse import urlparse, urlunparse +- +-import ovirtsdk4 as sdk +-import ovirtsdk4.types as types +- +- +-def debug(s): +- if params['verbose']: +- print(s, file=sys.stderr) +- sys.stderr.flush() +- +- +-# 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" +-netloc = f"{parsed.hostname:parsed.port}" if parsed.port else parsed.hostname +- +-# Connect to the server. +-connection = sdk.Connection( +- url=urlunparse(parsed._replace(netloc=netloc)), +- username=username, +- password=output_password, +- ca_file=params['rhv_cafile'], +- log=logging.getLogger(), +- insecure=params['insecure'], +-) +- +-with closing(connection): +- system_service = connection.system_service() +- image_transfers_service = system_service.image_transfers_service() +- +- # Try to cancel the transfers. This should delete the associated disk. +- for id in params['transfer_ids']: +- try: +- transfer_service = \ +- image_transfers_service.image_transfer_service(id) +- transfer_service.cancel() +- except sdk.NotFoundError: +- debug("unexpected error: transfer id %s not found" % id) +- except Exception: +- if params['verbose']: +- traceback.print_exc() +- +- disks_service = system_service.disks_service() +- +- # In case we didn't associate a disk with a transfer and as a last +- # resort, delete the disk too. +- for uuid in params['disk_uuids']: +- try: +- disk_service = disks_service.disk_service(uuid) +- disk_service.remove() +- except (sdk.NotFoundError, sdk.Error): +- # We expect these exceptions so ignore them. +- pass +- except Exception: +- if params['verbose']: +- traceback.print_exc() +diff --git a/output/rhv-upload-createvm.py b/output/rhv-upload-createvm.py +deleted file mode 100644 +index 9af2c167..00000000 +--- a/output/rhv-upload-createvm.py ++++ /dev/null +@@ -1,137 +0,0 @@ +-# -*- python -*- +-# oVirt or RHV upload create VM used by ‘virt-v2v -o rhv-upload’ +-# Copyright (C) 2018 Red Hat Inc. +-# +-# This program is free software; you can redistribute it and/or modify +-# it under the terms of the GNU General Public License as published by +-# the Free Software Foundation; either version 2 of the License, or +-# (at your option) any later version. +-# +-# This program is distributed in the hope that it will be useful, +-# but WITHOUT ANY WARRANTY; without even the implied warranty of +-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-# GNU General Public License for more details. +-# +-# You should have received a copy of the GNU General Public License along +-# with this program; if not, write to the Free Software Foundation, Inc., +-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +- +-import json +-import logging +-import sys +-import time +-import uuid +- +-from urllib.parse import urlparse, urlunparse +- +-import ovirtsdk4 as sdk +-import ovirtsdk4.types as types +- +- +-def debug(s): +- if params['verbose']: +- print(s, file=sys.stderr) +- sys.stderr.flush() +- +- +-def jobs_completed(system_service, correlation_id): +- jobs_service = system_service.jobs_service() +- +- try: +- jobs = jobs_service.list( +- search="correlation_id=%s" % correlation_id) +- except sdk.Error as e: +- debug( +- "Error searching for jobs with correlation id %s: %s" % +- (correlation_id, e)) +- # We don't know, assume that jobs did not complete yet. +- return False +- +- # STARTED is the only "in progress" status, anything else means the job +- # has already terminated. +- if all(job.status != types.JobStatus.STARTED for job in jobs): +- failed_jobs = [(job.description, str(job.status)) +- for job in jobs +- if job.status != types.JobStatus.FINISHED] +- if failed_jobs: +- raise RuntimeError( +- "Failed to create a VM! Failed jobs: %r" % failed_jobs) +- return True +- else: +- running_jobs = [(job.description, str(job.status)) for job in jobs] +- debug("Some jobs with correlation id %s are running: %s" % +- (correlation_id, running_jobs)) +- return False +- +- +-# Seconds to wait for the VM import job to complete in oVirt. +-timeout = 3 * 60 +- +-# Parameters are passed in via a JSON doc from the OCaml code. +-# Because this Python code ships embedded inside virt-v2v there +-# is no formal API here. +-params = None +-ovf = None # OVF file +- +-if len(sys.argv) != 3: +- raise RuntimeError("incorrect number of parameters") +- +-# Parameters are passed in via a JSON document. +-with open(sys.argv[1], 'r') as fp: +- params = json.load(fp) +- +-# What is passed in is a password file, read the actual password. +-with open(params['output_password'], 'r') as fp: +- output_password = fp.read() +-output_password = output_password.rstrip() +- +-# Read the OVF document. +-with open(sys.argv[2], 'r') as fp: +- ovf = fp.read() +- +-# Parse out the username from the output_conn URL. +-parsed = urlparse(params['output_conn']) +-username = parsed.username or "admin@internal" +-netloc = f"{parsed.hostname:parsed.port}" if parsed.port else parsed.hostname +- +-# Connect to the server. +-connection = sdk.Connection( +- url=urlunparse(parsed._replace(netloc=netloc)), +- username=username, +- password=output_password, +- ca_file=params['rhv_cafile'], +- log=logging.getLogger(), +- insecure=params['insecure'], +-) +- +-system_service = connection.system_service() +- +-# Get the cluster. +-cluster = system_service.clusters_service().cluster_service(params['rhv_cluster_uuid']) +-cluster = cluster.get() +- +-correlation_id = str(uuid.uuid4()) +-vms_service = system_service.vms_service() +-vm = vms_service.add( +- types.Vm( +- cluster=cluster, +- initialization=types.Initialization( +- configuration=types.Configuration( +- type=types.ConfigurationType.OVA, +- data=ovf, +- ) +- ) +- ), +- query={'correlation_id': correlation_id}, +-) +- +-# Wait for the import job to finish. +-endt = time.monotonic() + timeout +-while True: +- time.sleep(10) +- if jobs_completed(system_service, correlation_id): +- break +- if time.monotonic() > endt: +- raise RuntimeError( +- "Timed out waiting for VM creation!" +- " Jobs still running for correlation id %s" % correlation_id) +diff --git a/output/rhv-upload-finalize.py b/output/rhv-upload-finalize.py +deleted file mode 100644 +index 12fd39ec..00000000 +--- a/output/rhv-upload-finalize.py ++++ /dev/null +@@ -1,174 +0,0 @@ +-# -*- python -*- +-# oVirt or RHV upload finalize used by ‘virt-v2v -o rhv-upload’ +-# Copyright (C) 2018-2021 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 urllib.parse import urlparse, urlunparse +- +-import ovirtsdk4 as sdk +-import ovirtsdk4.types as types +- +-# Timeout to wait for oVirt disks to change status, or the transfer +-# object to finish initializing [seconds]. +-timeout = 5 * 60 +- +- +-def debug(s): +- if params['verbose']: +- print(s, file=sys.stderr) +- sys.stderr.flush() +- +- +-def finalize_transfer(connection, transfer_id, disk_id): +- """ +- Finalize a transfer, making the transfer disk available. +- +- If finalizing succeeds, the transfer's disk status will change to OK +- and transfer's phase will change to FINISHED_SUCCESS. Unfortunately, +- the disk status is modified before the transfer finishes, and oVirt +- may still hold a lock on the disk at this point. +- +- The only way to make sure that the disk is unlocked, is to wait +- until the transfer phase switches FINISHED_SUCCESS. Unfortunately +- oVirt makes this hard to use because the transfer is removed shortly +- after switching the phase to the final phase. However if the +- transfer was removed, we can be sure that the disk is not locked, +- since oVirt releases the locks before removing the transfer. +- +- On errors, the transfer's phase will change to FINISHED_FAILURE and +- the disk status will change to ILLEGAL and it will be removed. Again +- the transfer will be removed shortly after that. +- +- If oVirt fails to finalize the transfer, transfer's phase will +- change to PAUSED_SYSTEM. In this case the disk's status will change +- to ILLEGAL and it will not be removed. +- +- oVirt 4.4.7 made waiting for transfer easier by keeping transfers +- after they complete, but we must support older versions so we have +- generic code that work with any version. +- +- For more info see: +- - http://ovirt.github.io/ovirt-engine-api-model/4.4/#services/image_transfer +- - http://ovirt.github.io/ovirt-engine-sdk/master/types.m.html#ovirtsdk4.types.ImageTransfer +- """ +- debug("finalizing transfer %s" % transfer_id) +- transfer_service = (connection.system_service() +- .image_transfers_service() +- .image_transfer_service(transfer_id)) +- +- start = time.monotonic() +- +- transfer_service.finalize() +- +- while True: +- time.sleep(1) +- try: +- transfer = transfer_service.get() +- except sdk.NotFoundError: +- # Transfer was removed (ovirt < 4.4.7). We need to check the +- # disk status to understand if the transfer was successful. +- # Due to the way oVirt does locking, we know that the disk +- # is unlocked at this point so we can check only once. +- +- debug("transfer %s was removed, checking disk %s status" +- % (transfer_id, disk_id)) +- +- disk_service = (connection.system_service() +- .disks_service() +- .disk_service(disk_id)) +- +- try: +- disk = disk_service.get() +- except sdk.NotFoundError: +- raise RuntimeError( +- "transfer %s failed: disk %s was removed" +- % (transfer_id, disk_id)) +- +- debug("disk %s is %s" % (disk.id, disk.status)) +- +- if disk.status == types.DiskStatus.OK: +- break +- +- raise RuntimeError( +- "transfer %s failed: disk is %s" % (transfer_id, disk.status)) +- else: +- # Transfer exists, check if it reached one of the final +- # phases, or we timed out. +- +- debug("transfer %s is %s" % (transfer.id, transfer.phase)) +- +- if transfer.phase == types.ImageTransferPhase.FINISHED_SUCCESS: +- break +- +- if transfer.phase == types.ImageTransferPhase.FINISHED_FAILURE: +- raise RuntimeError( +- "transfer %s has failed" % (transfer_id,)) +- +- if transfer.phase == types.ImageTransferPhase.PAUSED_SYSTEM: +- raise RuntimeError( +- "transfer %s was paused by system" % (transfer.id,)) +- +- if time.monotonic() > start + timeout: +- raise RuntimeError( +- "timed out waiting for transfer %s to finalize, " +- "transfer is %s" +- % (transfer.id, transfer.phase)) +- +- debug("transfer %s finalized in %.3f seconds" +- % (transfer_id, time.monotonic() - start)) +- +- +-# 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" +-netloc = f"{parsed.hostname:parsed.port}" if parsed.port else parsed.hostname +- +-# Connect to the server. +-connection = sdk.Connection( +- url=urlunparse(parsed._replace(netloc=netloc)), +- username=username, +- password=output_password, +- ca_file=params['rhv_cafile'], +- log=logging.getLogger(), +- insecure=params['insecure'], +-) +- +-# Finalize all the transfers. +-for (transfer_id, disk_id) in zip(params['transfer_ids'], params['disk_uuids']): +- finalize_transfer(connection, transfer_id, disk_id) +- +-connection.close() +diff --git a/output/rhv-upload-plugin.py b/output/rhv-upload-plugin.py +deleted file mode 100644 +index 8bc79a4a..00000000 +--- a/output/rhv-upload-plugin.py ++++ /dev/null +@@ -1,525 +0,0 @@ +-# -*- python -*- +-# oVirt or RHV upload nbdkit plugin used by ‘virt-v2v -o rhv-upload’ +-# Copyright (C) 2018-2021 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 queue +-import socket +-import ssl +-import threading +-import time +- +-from contextlib import contextmanager +-from http.client import HTTPSConnection, HTTPConnection +-from urllib.parse import urlparse +- +-import nbdkit +- +-# Using version 2 supporting the buffer protocol for better performance. +-API_VERSION = 2 +- +-# Maximum number of connection to imageio server. Based on testing with imageio +-# client, this give best performance. +-MAX_CONNECTIONS = 4 +- +-# Maximum idle time allowed for imageio connections. +-IDLE_TIMEOUT = 30 +- +-# Required parameters. +-size = None +-url = None +- +-# Optional parameters. +-cafile = None +-insecure = False +-is_ovirt_host = False +- +-# List of options read from imageio server. +-options = None +- +-# Pool of HTTP connections. +-pool = None +- +-# Set when plugin is cleaning up. +-done = threading.Event() +- +-# Set when periodic flush request fails. +-pool_error = None +- +- +-# Parse parameters. +-def config(key, value): +- global cafile, url, is_ovirt_host, insecure, size +- +- if key == "cafile": +- cafile = value +- elif key == "insecure": +- insecure = value.lower() in ['true', '1'] +- elif key == "is_ovirt_host": +- is_ovirt_host = value.lower() in ['true', '1'] +- elif key == "size": +- size = int(value) +- elif key == "url": +- url = urlparse(value) +- else: +- raise RuntimeError("unknown configuration key '%s'" % key) +- +- +-def config_complete(): +- # These parameters are required. +- if url is None: +- raise RuntimeError("url parameter was not set") +- if size is None: +- raise RuntimeError("size parameter was not set") +- +- +-def after_fork(): +- global options, pool +- +- http = create_http(url) +- options = get_options(http, url) +- http.close() +- +- nbdkit.debug("imageio features: flush=%(can_flush)r " +- "zero=%(can_zero)r unix_socket=%(unix_socket)r " +- "max_readers=%(max_readers)r max_writers=%(max_writers)r" +- % options) +- +- pool = create_http_pool(url, options) +- +- t = threading.Thread(target=pool_keeper, name="poolkeeper") +- t.daemon = True +- t.start() +- +- +-# This function is not actually defined before nbdkit 1.28, but it +-# doesn't particularly matter if we don't close the pool because +-# clients should call flush(). +-def cleanup(): +- nbdkit.debug("cleaning up") +- done.set() +- close_http_pool(pool) +- +- +-def thread_model(): +- """ +- Using parallel model to speed up transfer with multiple connections to +- imageio server. +- """ +- return nbdkit.THREAD_MODEL_PARALLEL +- +- +-def open(readonly): +- return 1 +- +- +-def can_trim(h): +- return False +- +- +-def can_flush(h): +- return options['can_flush'] +- +- +-def can_fua(h): +- # imageio flush feature is is compatible with NBD_CMD_FLAG_FUA. +- return options['can_flush'] +- +- +-def can_multi_conn(h): +- # We can always handle multiple connections, and the number of NBD +- # connections is independent of the number of HTTP clients in the +- # pool. +- return True +- +- +-def get_size(h): +- return size +- +- +-# Any unexpected HTTP response status from the server will end up calling this +-# function which logs the full error, and raises a RuntimeError exception. +-def request_failed(r, msg): +- status = r.status +- reason = r.reason +- try: +- body = r.read() +- except EnvironmentError as e: +- body = "(Unable to read response body: %s)" % e +- +- # Log the full error if we're verbose. +- nbdkit.debug("unexpected response from imageio server:") +- nbdkit.debug(msg) +- nbdkit.debug("%d: %s" % (status, reason)) +- nbdkit.debug(body) +- +- # Only a short error is included in the exception. +- raise RuntimeError("%s: %d %s: %r" % (msg, status, reason, body[:200])) +- +- +-# For documentation see: +-# https://github.com/oVirt/ovirt-imageio/blob/master/docs/random-io.md +-# For examples of working code to read/write from the server, see: +-# https://github.com/oVirt/ovirt-imageio/blob/master/daemon/test/server_test.py +-def pread(h, buf, offset, flags): +- count = len(buf) +- headers = {"Range": "bytes=%d-%d" % (offset, offset + count - 1)} +- +- with http_context(pool) as http: +- http.request("GET", url.path, headers=headers) +- +- r = http.getresponse() +- # 206 = HTTP Partial Content. +- if r.status != 206: +- request_failed(r, +- "could not read sector offset %d size %d" % +- (offset, count)) +- +- content_length = int(r.getheader("content-length")) +- if content_length != count: +- # Should never happen. +- request_failed(r, +- "unexpected Content-Length offset %d size %d got %d" % +- (offset, count, content_length)) +- +- with memoryview(buf) as view: +- got = 0 +- while got < count: +- n = r.readinto(view[got:]) +- if n == 0: +- request_failed(r, +- "short read offset %d size %d got %d" % +- (offset, count, got)) +- got += n +- +- +-def pwrite(h, buf, offset, flags): +- count = len(buf) +- +- flush = "y" if (options['can_flush'] and (flags & nbdkit.FLAG_FUA)) else "n" +- +- with http_context(pool) as http: +- http.putrequest("PUT", url.path + "?flush=" + flush) +- # The oVirt server only uses the first part of the range, and the +- # content-length. +- http.putheader("Content-Range", "bytes %d-%d/*" % +- (offset, offset + count - 1)) +- http.putheader("Content-Length", str(count)) +- http.endheaders() +- +- try: +- http.send(buf) +- except BrokenPipeError: +- pass +- +- r = http.getresponse() +- if r.status != 200: +- request_failed(r, +- "could not write sector offset %d size %d" % +- (offset, count)) +- +- r.read() +- +- +-def zero(h, count, offset, flags): +- # Unlike the trim and flush calls, there is no 'can_zero' method +- # so nbdkit could call this even if the server doesn't support +- # zeroing. If this is the case we must emulate. +- if not options['can_zero']: +- emulate_zero(h, count, offset, flags) +- return +- +- flush = bool(options['can_flush'] and (flags & nbdkit.FLAG_FUA)) +- +- # Construct the JSON request for zeroing. +- buf = json.dumps({'op': "zero", +- 'offset': offset, +- 'size': count, +- 'flush': flush}).encode() +- +- headers = {"Content-Type": "application/json", +- "Content-Length": str(len(buf))} +- +- with http_context(pool) as http: +- http.request("PATCH", url.path, body=buf, headers=headers) +- +- r = http.getresponse() +- if r.status != 200: +- request_failed(r, +- "could not zero sector offset %d size %d" % +- (offset, count)) +- +- r.read() +- +- +-def emulate_zero(h, count, offset, flags): +- flush = "y" if (options['can_flush'] and (flags & nbdkit.FLAG_FUA)) else "n" +- +- with http_context(pool) as http: +- http.putrequest("PUT", url.path + "?flush=" + flush) +- http.putheader("Content-Range", +- "bytes %d-%d/*" % (offset, offset + count - 1)) +- http.putheader("Content-Length", str(count)) +- http.endheaders() +- +- try: +- buf = bytearray(128 * 1024) +- while count > len(buf): +- http.send(buf) +- count -= len(buf) +- http.send(memoryview(buf)[:count]) +- except BrokenPipeError: +- pass +- +- r = http.getresponse() +- if r.status != 200: +- request_failed(r, +- "could not write zeroes offset %d size %d" % +- (offset, count)) +- +- r.read() +- +- +-def flush(h, flags): +- if pool_error: +- raise pool_error +- +- # Wait until all inflight requests are completed, and send a flush +- # request for all imageio connections. +- locked = [] +- +- # Lock the pool by taking all connections out. +- while len(locked) < pool.maxsize: +- locked.append(pool.get()) +- +- try: +- for item in locked: +- send_flush(item.http) +- item.last_used = time.monotonic() +- finally: +- # Unlock the pool by puting the connection back. +- for item in locked: +- pool.put(item) +- +- +-def send_flush(http): +- # Construct the JSON request for flushing. +- buf = json.dumps({'op': "flush"}).encode() +- +- headers = {"Content-Type": "application/json", +- "Content-Length": str(len(buf))} +- +- http.request("PATCH", url.path, body=buf, headers=headers) +- +- r = http.getresponse() +- if r.status != 200: +- request_failed(r, "could not flush") +- +- r.read() +- +- +-# Modify http.client.HTTPConnection to work over a Unix domain socket. +-# Derived from uhttplib written by Erik van Zijst under an MIT license. +-# (https://pypi.org/project/uhttplib/) +-# Ported to Python 3 by Irit Goihman. +-class UnixHTTPConnection(HTTPConnection): +- def __init__(self, path, timeout=socket._GLOBAL_DEFAULT_TIMEOUT): +- self.path = path +- HTTPConnection.__init__(self, "localhost", timeout=timeout) +- +- def connect(self): +- self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) +- if self.timeout is not socket._GLOBAL_DEFAULT_TIMEOUT: +- self.sock.settimeout(timeout) +- self.sock.connect(self.path) +- +- +-class PoolItem: +- +- def __init__(self, http): +- self.http = http +- self.last_used = None +- +- +-# Connection pool. +-def create_http_pool(url, options): +- count = min(options["max_readers"], +- options["max_writers"], +- MAX_CONNECTIONS) +- +- nbdkit.debug("creating http pool connections=%d" % count) +- +- unix_socket = options["unix_socket"] if is_ovirt_host else None +- +- pool = queue.Queue(count) +- +- for i in range(count): +- http = create_http(url, unix_socket=unix_socket) +- pool.put(PoolItem(http)) +- +- return pool +- +- +-def pool_keeper(): +- """ +- Thread flushing idle connections, keeping them alive. +- +- If a connection does not send any request for 60 seconds, imageio +- server closes the connection. Recovering from closed connection is +- hard and unsafe, so this thread ensure that connections never +- becomes idle by sending a flush request if the connection is idle +- for too much time. +- +- In normal conditions, all connections are busy most of the time, so +- the keeper will find no idle connections. If there short delays in +- nbdcopy, the keeper will find some idle connections, but will +- quickly return them back to the pool. In the pathological case when +- nbdcopy is blocked for 3 minutes on vddk input, the keeper will send +- a flush request on all connections every ~30 seconds, until nbdcopy +- starts communicating again. +- """ +- global pool_error +- +- nbdkit.debug("poolkeeper: started") +- +- while not done.wait(IDLE_TIMEOUT / 2): +- idle = [] +- +- while True: +- try: +- idle.append(pool.get_nowait()) +- except queue.Empty: +- break +- +- if idle: +- now = time.monotonic() +- for item in idle: +- if item.last_used and now - item.last_used > IDLE_TIMEOUT: +- nbdkit.debug("poolkeeper: flushing idle connection") +- try: +- send_flush(item.http) +- item.last_used = now +- except Exception as e: +- # We will report this error on the next request. +- pool_error = e +- item.last_used = None +- +- pool.put(item) +- +- nbdkit.debug("poolkeeper: stopped") +- +- +-@contextmanager +-def http_context(pool): +- """ +- Context manager yielding an imageio http connection from the pool. Blocks +- until a connection is available. +- """ +- if pool_error: +- raise pool_error +- +- item = pool.get() +- try: +- yield item.http +- finally: +- item.last_used = time.monotonic() +- pool.put(item) +- +- +-def close_http_pool(pool): +- """ +- Wait until all inflight requests are done, close all connections and remove +- them from the pool. +- +- No request can be served by the pool after this call. +- """ +- nbdkit.debug("closing http pool") +- +- locked = [] +- +- while len(locked) < pool.maxsize: +- locked.append(pool.get()) +- +- for item in locked: +- item.http.close() +- +- +-def create_http(url, unix_socket=None): +- """ +- Create http connection for transfer url. +- +- Returns HTTPConnection. +- """ +- if unix_socket: +- nbdkit.debug("creating unix http connection socket=%r" % unix_socket) +- try: +- return UnixHTTPConnection(unix_socket) +- except Exception as e: +- # Very unlikely, but we can recover by using https. +- nbdkit.debug("cannot create unix socket connection: %s" % e) +- +- if url.scheme == "https": +- context = \ +- ssl.create_default_context(purpose=ssl.Purpose.SERVER_AUTH, +- cafile=cafile) +- if insecure: +- context.check_hostname = False +- context.verify_mode = ssl.CERT_NONE +- +- nbdkit.debug("creating https connection host=%s port=%s" % +- (url.hostname, url.port)) +- return HTTPSConnection(url.hostname, url.port, context=context) +- elif url.scheme == "http": +- nbdkit.debug("creating http connection host=%s port=%s" % +- (url.hostname, url.port)) +- return HTTPConnection(url.hostname, url.port) +- else: +- raise RuntimeError("unknown URL scheme (%s)" % url.scheme) +- +- +-def get_options(http, url): +- """ +- Send OPTIONS request to imageio server and return options dict. +- """ +- http.request("OPTIONS", url.path) +- r = http.getresponse() +- data = r.read() +- +- if r.status == 200: +- j = json.loads(data) +- features = j["features"] +- return { +- "can_flush": "flush" in features, +- "can_zero": "zero" in features, +- "unix_socket": j.get('unix_socket'), +- "max_readers": j.get("max_readers", 1), +- "max_writers": j.get("max_writers", 1), +- } +- +- elif r.status == 405 or r.status == 204: +- # Old imageio servers returned either 405 Method Not Allowed or +- # 204 No Content (with an empty body). +- return { +- "can_flush": False, +- "can_zero": False, +- "unix_socket": None, +- "max_readers": 1, +- "max_writers": 1, +- } +- else: +- raise RuntimeError("could not use OPTIONS request: %d: %s" % +- (r.status, r.reason)) +diff --git a/output/rhv-upload-precheck.py b/output/rhv-upload-precheck.py +deleted file mode 100644 +index 0bbb738d..00000000 +--- a/output/rhv-upload-precheck.py ++++ /dev/null +@@ -1,135 +0,0 @@ +-# -*- python -*- +-# oVirt or RHV pre-upload checks used by ‘virt-v2v -o rhv-upload’ +-# Copyright (C) 2018-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. +- +-import json +-import logging +-import re +-import sys +- +-from urllib.parse import urlparse, urlunparse +- +-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" +-netloc = f"{parsed.hostname:parsed.port}" if parsed.port else parsed.hostname +- +-# Check the storage domain name is valid +-# (https://bugzilla.redhat.com/show_bug.cgi?id=1986386#c1) +-# Also this means it cannot contain spaces or glob symbols, so +-# the search below is valid. +-output_storage = params['output_storage'] +-if not re.match('^[-a-zA-Z0-9_]+$', output_storage): +- raise RuntimeError("The storage domain (-os) parameter ‘%s’ is not valid" % +- output_storage) +- +-# Connect to the server. +-connection = sdk.Connection( +- url=urlunparse(parsed._replace(netloc=netloc)), +- username=username, +- password=output_password, +- ca_file=params['rhv_cafile'], +- log=logging.getLogger(), +- insecure=params['insecure'], +-) +- +-system_service = connection.system_service() +- +-# Check whether there is a datacenter for the specified storage. +-data_centers = system_service.data_centers_service().list( +- search='storage.name=%s' % output_storage, +- case_sensitive=True, +-) +-if len(data_centers) == 0: +- storage_domains = system_service.storage_domains_service().list( +- search='name=%s' % 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" % +- 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" % +- output_storage) +-datacenter = data_centers[0] +- +-# Get the storage domain. +-storage_domains = connection.follow_link(datacenter.storage_domains) +-try: +- storage_domain = [sd for sd in storage_domains +- if sd.name == output_storage][0] +-except IndexError: +- raise RuntimeError("The storage domain ‘%s’ does not exist" % +- output_storage) +- +-# 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’ is not part of the DC ‘%s’, " +- "where the storage domain ‘%s’ is" % +- (params['rhv_cluster'], datacenter.name, +- output_storage)) +-cluster = clusters[0] +-cpu = cluster.cpu +-if cpu.architecture == types.Architecture.UNDEFINED: +- raise RuntimeError("The cluster ‘%s’ has an unknown architecture" % +- (params['rhv_cluster'])) +- +-# Find if any disk already exists with specified UUID. +-# Only used with -oo rhv-disk-uuid. It is assumed that the +-# random UUIDs that we generate are unlikely to conflict. +-disks_service = system_service.disks_service() +- +-for uuid in params.get('rhv_disk_uuids', []): +- try: +- disk_service = disks_service.disk_service(uuid).get() +- raise RuntimeError("Disk with the UUID '%s' already exists" % uuid) +- except sdk.NotFoundError: +- pass +- +-# Otherwise everything is OK, print a JSON with the results. +-results = { +- "rhv_storagedomain_uuid": storage_domain.id, +- "rhv_cluster_uuid": cluster.id, +- "rhv_cluster_cpu_architecture": cpu.architecture.value, +-} +- +-json.dump(results, sys.stdout) +diff --git a/output/rhv-upload-transfer.py b/output/rhv-upload-transfer.py +deleted file mode 100644 +index ed96153b..00000000 +--- a/output/rhv-upload-transfer.py ++++ /dev/null +@@ -1,298 +0,0 @@ +-# -*- python -*- +-# oVirt or RHV upload start transfer used by ‘virt-v2v -o rhv-upload’ +-# Copyright (C) 2018-2021 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 inspect +-import json +-import logging +-import sys +-import time +-from contextlib import closing +-from urllib.parse import urlparse, urlunparse +- +-import ovirtsdk4 as sdk +-import ovirtsdk4.types as types +- +-# Timeout to wait for oVirt disks to change status, or the transfer +-# object to finish initializing [seconds]. +-timeout = 5 * 60 +- +- +-def debug(s): +- if params['verbose']: +- print(s, file=sys.stderr) +- sys.stderr.flush() +- +- +-def find_host(connection): +- """Return the current host object or None.""" +- try: +- with open("/etc/vdsm/vdsm.id") as f: +- vdsm_id = f.readline().strip() +- except FileNotFoundError: +- # Expected condition when running on non-oVirt host. +- debug("not an oVirt host, using non-oVirt host") +- return None +- except Exception as e: +- # Unexpected but we can degrade to remote transfer. +- debug(f"warning: cannot read host id, using non-oVirt host: {e}") +- return None +- +- debug("hw_id = %r" % vdsm_id) +- +- system_service = connection.system_service() +- storage_name = params['output_storage'] +- data_centers = system_service.data_centers_service().list( +- search='storage.name=%s' % storage_name, +- 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). +- debug("storange domain (%s) is not attached to a DC" % storage_name) +- return None +- +- datacenter = data_centers[0] +- debug("datacenter = %s" % datacenter.name) +- +- hosts_service = system_service.hosts_service() +- hosts = hosts_service.list( +- search="hw_id=%s and datacenter=%s and status=Up" +- % (vdsm_id, datacenter.name), +- case_sensitive=True, +- ) +- if len(hosts) == 0: +- # Couldn't find a host that's fulfilling the following criteria: +- # - 'hw_id' equals to 'vdsm_id' +- # - Its status is 'Up' +- # - Belongs to the storage domain's datacenter +- debug("cannot find a running host with hw_id=%r, " +- "that belongs to datacenter '%s', " +- "using any host" % (vdsm_id, datacenter.name)) +- return None +- +- host = hosts[0] +- debug("host.id = %r" % host.id) +- +- return types.Host(id=host.id) +- +- +-def create_disk(connection): +- """ +- Create a new disk for the transfer and wait until the disk is ready. +- +- Returns disk object. +- """ +- system_service = connection.system_service() +- disks_service = system_service.disks_service() +- +- if params['disk_format'] == "raw": +- disk_format = types.DiskFormat.RAW +- else: +- disk_format = types.DiskFormat.COW +- +- disk = disks_service.add( +- disk=types.Disk( +- id=params['disk_uuid'], +- name=params['disk_name'], +- description="Uploaded by virt-v2v", +- format=disk_format, +- # XXX For qcow2 disk on block storage, we should use the estimated +- # size, based on qemu-img measure of the overlay. +- initial_size=params['disk_size'], +- provisioned_size=params['disk_size'], +- # Handling this properly will be complex, see: +- # https://www.redhat.com/archives/libguestfs/2018-March/msg00177.html +- sparse=True, +- storage_domains=[ +- types.StorageDomain( +- name=params['output_storage'], +- ) +- ], +- ) +- ) +- +- debug("disk.id = %r" % disk.id) +- +- # Wait till the disk moved from LOCKED state to OK state, as the transfer +- # can't start if the disk is locked. +- +- disk_service = disks_service.disk_service(disk.id) +- endt = time.monotonic() + timeout +- while True: +- time.sleep(1) +- disk = disk_service.get() +- if disk.status == types.DiskStatus.OK: +- break +- if time.monotonic() > endt: +- raise RuntimeError( +- "timed out waiting for disk %s to become unlocked" % disk.id) +- +- return disk +- +- +-def create_transfer(connection, disk, host): +- """ +- Create image transfer and wait until the transfer is ready. +- +- Returns a transfer object. +- """ +- system_service = connection.system_service() +- transfers_service = system_service.image_transfers_service() +- +- extra = {} +- if transfer_supports_format(): +- extra["format"] = types.DiskFormat.RAW +- +- transfer = transfers_service.add( +- types.ImageTransfer( +- disk=types.Disk(id=disk.id), +- host=host, +- inactivity_timeout=3600, +- **extra, +- ) +- ) +- +- # At this point the transfer owns the disk and will delete the disk if the +- # transfer is canceled, or if finalizing the transfer fails. +- +- debug("transfer.id = %r" % transfer.id) +- +- # Get a reference to the created transfer service. +- transfer_service = transfers_service.image_transfer_service(transfer.id) +- +- # 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.monotonic() + timeout +- while True: +- 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: +- transfer_service.cancel() +- raise RuntimeError( +- "unexpected transfer %s phase %s" +- % (transfer.id, transfer.phase)) +- +- if time.monotonic() > endt: +- transfer_service.cancel() +- raise RuntimeError( +- "timed out waiting for transfer %s" % transfer.id) +- +- return transfer +- +- +-def transfer_supports_format(): +- """ +- Return True if transfer supports the "format" argument, enabing the NBD +- bakend on imageio side, which allows uploading to qcow2 images. +- +- This feature was added in ovirt 4.3. We assume that the SDK version matches +- engine version. +- """ +- sig = inspect.signature(types.ImageTransfer) +- return "format" in sig.parameters +- +- +-def get_transfer_url(transfer): +- """ +- Returns the transfer url, preferring direct transfer if possible. +- """ +- if params['rhv_direct']: +- if transfer.transfer_url is None: +- raise RuntimeError("direct upload to host not supported, " +- "requires ovirt-engine >= 4.2 and only works " +- "when virt-v2v is run within the oVirt/RHV " +- "environment, eg. on an oVirt node.") +- return transfer.transfer_url +- else: +- return transfer.proxy_url +- +- +-# 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: +- data = fp.read() +- +-try: +- params = json.loads(data) +-except ValueError as e: +- raise RuntimeError(f"Cannot parse params {data!r}: {e}").with_traceback( +- e.__traceback__ +- ) from None +- +-# 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" +-netloc = f"{parsed.hostname:parsed.port}" if parsed.port else parsed.hostname +- +-connection = sdk.Connection( +- url=urlunparse(parsed._replace(netloc=netloc)), +- username=username, +- password=output_password, +- ca_file=params['rhv_cafile'], +- log=logging.getLogger(), +- insecure=params['insecure'], +-) +- +-with closing(connection): +- # Use the local host if possible. +- host = find_host(connection) if params['rhv_direct'] else None +- disk = create_disk(connection) +- +- transfer = create_transfer(connection, disk, host) +- destination_url = get_transfer_url(transfer) +- +-# Send the destination URL, transfer ID, and host flag back to OCaml code. +-results = { +- "transfer_id": transfer.id, +- "destination_url": destination_url, +- "is_ovirt_host": host is not None, +-} +-json.dump(results, sys.stdout) +diff --git a/output/rhv-upload-vmcheck.py b/output/rhv-upload-vmcheck.py +deleted file mode 100644 +index cd500574..00000000 +--- a/output/rhv-upload-vmcheck.py ++++ /dev/null +@@ -1,72 +0,0 @@ +-# -*- python -*- +-# oVirt or RHV VM existence check used by ‘virt-v2v -o rhv-upload’ +-# Copyright (C) 2018-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. +- +-import json +-import logging +-import sys +- +-from urllib.parse import urlparse, urlunparse +- +-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" +-netloc = f"{parsed.hostname:parsed.port}" if parsed.port else parsed.hostname +- +-# Connect to the server. +-connection = sdk.Connection( +- url=urlunparse(parsed._replace(netloc=netloc)), +- username=username, +- password=output_password, +- ca_file=params['rhv_cafile'], +- log=logging.getLogger(), +- insecure=params['insecure'], +-) +- +-system_service = connection.system_service() +- +-# Find if a virtual machine already exists with that name. +-vms_service = system_service.vms_service() +-vms = vms_service.list( +- search=("name=%s" % params['output_name']), +-) +-if len(vms) > 0: +- vm = vms[0] +- raise RuntimeError("VM already exists with name ‘%s’, id ‘%s’" % +- (params['output_name'], vm.id)) +- +-# Otherwise everything is OK, exit with no error. +diff --git a/tests/Makefile.am b/tests/Makefile.am +index 1ec1a702..955d08a0 100644 +--- a/tests/Makefile.am ++++ b/tests/Makefile.am +@@ -70,8 +70,6 @@ TESTS = \ + test-v2v-i-ova-two-disks.sh \ + test-v2v-i-vmx.sh \ + test-v2v-it-vddk-io-query.sh \ +- test-v2v-o-rhv-upload-oo-query.sh \ +- test-v2v-o-vdsm-oo-query.sh \ + test-v2v-bad-networks-and-bridges.sh \ + test-v2v-cdrom.sh \ + test-v2v-floppy.sh \ +@@ -89,9 +87,6 @@ TESTS = \ + test-v2v-o-null.sh \ + test-v2v-o-openstack.sh \ + test-v2v-o-qemu.sh \ +- test-v2v-o-rhv.sh \ +- test-v2v-o-rhv-upload.sh \ +- test-v2v-o-vdsm-options.sh \ + test-v2v-oa-option-qcow2.sh \ + test-v2v-oa-option-raw.sh \ + test-v2v-of-option.sh \ +@@ -256,16 +251,6 @@ EXTRA_DIST += \ + test-v2v-o-null.sh \ + test-v2v-o-openstack.sh \ + test-v2v-o-qemu.sh \ +- test-v2v-o-rhv.ovf.expected \ +- test-v2v-o-rhv.sh \ +- test-v2v-o-rhv-upload.sh \ +- test-v2v-o-rhv-upload-module/imageio.py \ +- test-v2v-o-rhv-upload-module/ovirtsdk4/__init__.py \ +- test-v2v-o-rhv-upload-module/ovirtsdk4/types.py \ +- test-v2v-o-rhv-upload-oo-query.sh \ +- test-v2v-o-vdsm-oo-query.sh \ +- test-v2v-o-vdsm-options.ovf.expected \ +- test-v2v-o-vdsm-options.sh \ + test-v2v-oa-option-qcow2.sh \ + test-v2v-oa-option-raw.sh \ + test-v2v-of-option.sh \ +diff --git a/tests/test-v2v-o-rhv-upload-module/imageio.py b/tests/test-v2v-o-rhv-upload-module/imageio.py +deleted file mode 100755 +index b9a491d7..00000000 +--- a/tests/test-v2v-o-rhv-upload-module/imageio.py ++++ /dev/null +@@ -1,71 +0,0 @@ +-#!/usr/bin/env python3 +-# -*- python -*- +-# Copyright (C) 2018-2021 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. +- +-# Fake imageio web server used as a test harness. +-# See v2v/test-v2v-o-rhv-upload.sh +- +-import sys +-import threading +-from http.server import HTTPServer, BaseHTTPRequestHandler +- +-class RequestHandler(BaseHTTPRequestHandler): +- protocol_version = 'HTTP/1.1' +- +- def do_OPTIONS(self): +- self.discard_request() +- +- # Advertize only flush and zero support. +- content = b'''{ "features": [ "flush", "zero" ] }''' +- length = len(content) +- +- self.send_response(200) +- self.send_header("Content-type", "application/json; charset=UTF-8") +- self.send_header("Content-Length", length) +- self.end_headers() +- self.wfile.write(content) +- +- # eg. zero request. Just ignore it. +- def do_PATCH(self): +- self.discard_request() +- self.send_response(200) +- self.send_header("Content-Length", "0") +- self.end_headers() +- +- # Flush request. Ignore it. +- def do_PUT(self): +- self.discard_request() +- self.send_response(200) +- self.send_header("Content-Length", "0") +- self.end_headers() +- +- def discard_request(self): +- length = self.headers.get('Content-Length') +- if length: +- length = int(length) +- content = self.rfile.read(length) +- +-server_address = ("", 0) +-# XXX This should test HTTPS, not HTTP, because we are testing a +-# different path through the main code. +-httpd = HTTPServer(server_address, RequestHandler) +-imageio_port = httpd.server_address[1] +- +-print("port: %d" % imageio_port) +-sys.stdout.flush() +- +-httpd.serve_forever() +diff --git a/tests/test-v2v-o-rhv-upload-module/ovirtsdk4/__init__.py b/tests/test-v2v-o-rhv-upload-module/ovirtsdk4/__init__.py +deleted file mode 100644 +index e33d0714..00000000 +--- a/tests/test-v2v-o-rhv-upload-module/ovirtsdk4/__init__.py ++++ /dev/null +@@ -1,150 +0,0 @@ +-# -*- python -*- +-# 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. +- +-# Fake ovirtsdk4 module used as a test harness. +-# See v2v/test-v2v-o-rhv-upload.sh +- +-class Error(Exception): +- pass +- +- +-class NotFoundError(Error): +- pass +- +- +-class Connection(object): +- def __init__( +- self, +- url=None, +- username=None, +- password=None, +- ca_file=None, +- log=None, +- insecure=False, +- debug=True, +- ): +- pass +- +- def close(self): +- pass +- +- def follow_link(self, objs): +- return objs +- +- def system_service(self): +- return SystemService() +- +- +-class SystemService(object): +- def clusters_service(self): +- return ClustersService() +- +- def data_centers_service(self): +- return DataCentersService() +- +- def disks_service(self): +- return DisksService() +- +- def jobs_service(self): +- return JobsService() +- +- def image_transfers_service(self): +- return ImageTransfersService() +- +- def storage_domains_service(self): +- return StorageDomainsService() +- +- def vms_service(self): +- return VmsService() +- +- +-class ClusterService(object): +- def get(self): +- return types.Cluster() +- +- +-class ClustersService(object): +- def cluster_service(self, id): +- return ClusterService() +- +- +-class DataCentersService(object): +- def list(self, search=None, case_sensitive=False): +- return [types.DataCenter()] +- +- +-class DiskService(object): +- def __init__(self, disk_id): +- self._disk_id = disk_id +- +- def get(self): +- return types.Disk(id=self._disk_id) +- +- def remove(self): +- pass +- +- +-class DisksService(object): +- def add(self, disk=None): +- disk.id = "756d81b0-d5c0-41bc-9bbe-b343c3fa3490" +- return disk +- +- def disk_service(self, disk_id): +- return DiskService(disk_id) +- +- +-class JobsService(object): +- def list(self, search=None): +- return [types.Job()] +- +- +-class ImageTransferService(object): +- def __init__(self): +- self._finalized = False +- +- def cancel(self): +- pass +- +- def get(self): +- if self._finalized: +- raise NotFoundError +- else: +- return types.ImageTransfer() +- +- def finalize(self): +- self._finalized = True +- +- +-class ImageTransfersService(object): +- def add(self, transfer): +- return transfer +- +- def image_transfer_service(self, id): +- return ImageTransferService() +- +- +-class StorageDomainsService(object): +- def list(self, search=None, case_sensitive=False): +- return [StorageDomain()] +- +- +-class VmsService(object): +- def add(self, vm, query=None): +- return vm +- +- def list(self, search=None): +- return [] +diff --git a/tests/test-v2v-o-rhv-upload-module/ovirtsdk4/types.py b/tests/test-v2v-o-rhv-upload-module/ovirtsdk4/types.py +deleted file mode 100644 +index 38d89573..00000000 +--- a/tests/test-v2v-o-rhv-upload-module/ovirtsdk4/types.py ++++ /dev/null +@@ -1,184 +0,0 @@ +-# -*- python -*- +-# 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. +- +-# Fake ovirtsdk4 module used as a test harness. +-# See v2v/test-v2v-o-rhv-upload.sh +- +-import os +-from enum import Enum +- +-imageio_port = os.getenv("IMAGEIO_PORT") +-assert imageio_port is not None +- +- +-class Architecture(Enum): +- UNDEFINED = "undefined" +- X86_64 = "x86_64" +- +- def __init__(self, arch): +- self._arch = arch +- +- def __str__(self): +- return self._arch +- +- +-class Cpu(object): +- architecture = Architecture.X86_64 +- +- +-class Cluster(object): +- id = "2e97537b-a783-4706-af9e-75cb2e032dcd" +- name = "Default" +- cpu = Cpu() +- +- +-class Configuration(object): +- def __init__(self, type=None, data=None): +- pass +- +- +-class ConfigurationType(Enum): +- OVA = 'ova' +- OVF = 'ovf' +- +- def __init__(self, image): +- self._image = image +- +- def __str__(self): +- return self._image +- +- +-class DiskFormat(Enum): +- COW = "cow" +- RAW = "raw" +- +- def __init__(self, image): +- self._image = image +- +- def __str__(self): +- return self._image +- +- +-class DiskStatus(Enum): +- ILLEGAL = "illegal" +- LOCKED = "locked" +- OK = "ok" +- +- def __init__(self, image): +- self._image = image +- +- def __str__(self): +- return self._image +- +- +-class Disk(object): +- def __init__( +- self, +- id=None, +- name=None, +- description=None, +- format=None, +- initial_size=None, +- provisioned_size=None, +- sparse=False, +- storage_domains=None +- ): +- self.id = id +- +- status = DiskStatus.OK +- +- +-class ImageTransferPhase(Enum): +- CANCELLED = 'cancelled' +- FINALIZING_FAILURE = 'finalizing_failure' +- FINALIZING_SUCCESS = 'finalizing_success' +- FINISHED_FAILURE = 'finished_failure' +- FINISHED_SUCCESS = 'finished_success' +- INITIALIZING = 'initializing' +- PAUSED_SYSTEM = 'paused_system' +- PAUSED_USER = 'paused_user' +- RESUMING = 'resuming' +- TRANSFERRING = 'transferring' +- UNKNOWN = 'unknown' +- +- def __init__(self, image): +- self._image = image +- +- def __str__(self): +- return self._image +- +- +-class ImageTransfer(object): +- def __init__( +- self, +- disk=None, +- host=None, +- inactivity_timeout=None, +- ): +- pass +- +- id = "e26ac8ab-7090-4d5e-95ad-e707b511a359" +- phase = ImageTransferPhase.TRANSFERRING +- transfer_url = "http://localhost:" + imageio_port + "/" +- +- +-class Initialization(object): +- def __init__(self, configuration): +- pass +- +- +-class JobStatus(Enum): +- ABORTED = "aborted" +- FAILED = "failed" +- FINISHED = "finished" +- STARTED = "started" +- UNKNOWN = "unknown" +- +- def __init__(self, image): +- self._image = image +- +- def __str__(self): +- return self._image +- +- +-class Job(object): +- description = "Fake job" +- status = JobStatus.FINISHED +- +- +-class StorageDomain(object): +- def __init__(self, name=None): +- pass +- +- id = "ba87af68-b630-4211-a73a-694c1a689405" +- name = "Storage" +- +- +-class Vm(object): +- def __init__( +- self, +- cluster=None, +- initialization=None +- ): +- pass +- +- +-class DataCenter(object): +- id = "31d8c73b-554b-4958-bb04-9ce97f0849e1" +- name = "DC" +- storage_domains = [StorageDomain()] +- clusters = [Cluster()] +diff --git a/tests/test-v2v-o-rhv-upload-oo-query.sh b/tests/test-v2v-o-rhv-upload-oo-query.sh +deleted file mode 100755 +index 5ef56b90..00000000 +--- a/tests/test-v2v-o-rhv-upload-oo-query.sh ++++ /dev/null +@@ -1,41 +0,0 @@ +-#!/bin/bash - +-# libguestfs virt-v2v test script +-# Copyright (C) 2018 Red Hat Inc. +-# +-# This program is free software; you can redistribute it and/or modify +-# it under the terms of the GNU General Public License as published by +-# the Free Software Foundation; either version 2 of the License, or +-# (at your option) any later version. +-# +-# This program is distributed in the hope that it will be useful, +-# but WITHOUT ANY WARRANTY; without even the implied warranty of +-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-# GNU General Public License for more details. +-# +-# You should have received a copy of the GNU General Public License +-# along with this program; if not, write to the Free Software +-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +- +-# Test -oo "?" option. +- +-set -e +- +-source ./functions.sh +-set -e +-set -x +- +-skip_if_skipped +- +-export VIRT_TOOLS_DATA_DIR="$srcdir/../test-data/fake-virt-tools" +-export VIRTIO_WIN="$srcdir/../test-data/fake-virtio-win" +- +-f=test-v2v-o-rhv-upload-oo-query.actual +-rm -f $f +- +-$VG virt-v2v --debug-gc \ +- -o rhv-upload -oo "?" > $f +- +-grep -- "-oo rhv-cafile" $f +-grep -- "-oo rhv-verifypeer" $f +- +-rm $f +diff --git a/tests/test-v2v-o-rhv-upload.sh b/tests/test-v2v-o-rhv-upload.sh +deleted file mode 100755 +index 15d5d028..00000000 +--- a/tests/test-v2v-o-rhv-upload.sh ++++ /dev/null +@@ -1,74 +0,0 @@ +-#!/bin/bash - +-# libguestfs virt-v2v test script +-# Copyright (C) 2018 Red Hat Inc. +-# +-# This program is free software; you can redistribute it and/or modify +-# it under the terms of the GNU General Public License as published by +-# the Free Software Foundation; either version 2 of the License, or +-# (at your option) any later version. +-# +-# This program is distributed in the hope that it will be useful, +-# but WITHOUT ANY WARRANTY; without even the implied warranty of +-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-# GNU General Public License for more details. +-# +-# You should have received a copy of the GNU General Public License +-# along with this program; if not, write to the Free Software +-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +- +-# Test -o rhv-upload. +-# +-# These uses a test harness (see +-# tests/test-v2v-o-rhv-upload-module/ovirtsdk4) to fake responses from +-# oVirt. +- +-set -e +-set -x +- +-source ./functions.sh +-set -e +-set -x +- +-skip_if_skipped +-requires python3 --version +-requires nbdkit $VIRT_V2V_NBDKIT_PYTHON_PLUGIN --version +-requires test -f ../test-data/phony-guests/windows.img +- +-libvirt_uri="test://$abs_top_builddir/test-data/phony-guests/guests.xml" +-f=../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" +-export PYTHONPATH=$srcdir/test-v2v-o-rhv-upload-module:$PYTHONPATH +- +-# Run the imageio process and get the port number. +-log=test-v2v-o-rhv-upload.webserver.log +-rm -f $log +-cleanup_fn rm -f $log +-$srcdir/test-v2v-o-rhv-upload-module/imageio.py >$log 2>&1 & +-pid=$! +-cleanup_fn kill $pid +-export IMAGEIO_PORT= +-for i in {1..5}; do +- IMAGEIO_PORT=$( grep "^port:" $log | awk '{print $2}' ) +- if [ -n "$IMAGEIO_PORT" ]; then break; fi +- sleep 3 +-done +-if [ ! -n "$IMAGEIO_PORT" ]; then +- echo "$0: imageio process did not start up" +- cat $log +- exit 1 +-fi +-echo IMAGEIO_PORT=$IMAGEIO_PORT +- +-# Run virt-v2v -o rhv-upload. +-# +-# The fake ovirtsdk4 module doesn't care about most of the options +-# like -oc, -oo rhv-cafile, -op etc. Any values may be used. +-$VG virt-v2v --debug-gc -v -x \ +- -i libvirt -ic "$libvirt_uri" windows \ +- -o rhv-upload \ +- -oc https://example.com/ovirt-engine/api \ +- -oo rhv-cafile=/dev/null \ +- -op /dev/null \ +- -os Storage +diff --git a/tests/test-v2v-o-rhv.ovf.expected b/tests/test-v2v-o-rhv.ovf.expected +deleted file mode 100644 +index 25e492fd..00000000 +--- a/tests/test-v2v-o-rhv.ovf.expected ++++ /dev/null +@@ -1,113 +0,0 @@ +- +- +- +- +- +- +-
+- List of networks +- +-
+-
+- List of Virtual Disks +- +-
+- +- windows +- 00000000-0000-0000-0000-000000000000 +- Blank +- generated by virt-v2v +- +- #DATE# +- True +- False +- +- False +- 0 +- 2 +- 1 +-
+- Microsoft Windows 7 Phony Edition +- Windows7 +-
+-
+- 1 CPU, 1024 Memory +- +- 1 virtual cpu +- Number of virtual CPU +- 1 +- 3 +- 1 +- 1 +- +- +- 1024 MB of memory +- Memory Size +- 2 +- 4 +- MegaBytes +- 1024 +- +- +- USB Controller +- 3 +- 23 +- Disabled +- +- +- Graphical Controller +- #UUID# +- 20 +- video +- 1 +- vga +- +- +- RNG Device +- #UUID# +- 0 +- rng +- virtio +- +- urandom +- +- +- +- Memory Ballooning Device +- #UUID# +- 0 +- balloon +- memballoon +- +- virtio +- +- +- +- Drive 1 +- #VOL_ID# +- 17 +- disk +- #DISK_ID#/#VOL_ID# +- 00000000-0000-0000-0000-000000000000 +- 00000000-0000-0000-0000-000000000000 +- +- 12345678-1234-1234-1234-123456789abc +- 00000000-0000-0000-0000-000000000000 +- #DATE# +- #DATE# +- #DATE# +- 1 +- +- +- #UUID# +- Ethernet adapter on default +- 10 +- 3 +- interface +- default +- eth0 +- 00:11:22:33:44:55 +- +-
+-
+-
+diff --git a/tests/test-v2v-o-rhv.sh b/tests/test-v2v-o-rhv.sh +deleted file mode 100755 +index e6ec7c61..00000000 +--- a/tests/test-v2v-o-rhv.sh ++++ /dev/null +@@ -1,87 +0,0 @@ +-#!/bin/bash - +-# libguestfs virt-v2v test script +-# Copyright (C) 2014 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 -o rhv. +- +-set -e +- +-source ./functions.sh +-set -e +-set -x +- +-skip_if_skipped +-requires test -f ../test-data/phony-guests/windows.img +- +-libvirt_uri="test://$abs_top_builddir/test-data/phony-guests/guests.xml" +-f=../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=test-v2v-o-rhv.d +-rm -rf $d +-cleanup_fn rm -r $d +-mkdir $d +- +-# Create a dummy Export Storage Domain. +-mkdir $d/12345678-1234-1234-1234-123456789abc +-mkdir $d/12345678-1234-1234-1234-123456789abc/images +-mkdir $d/12345678-1234-1234-1234-123456789abc/master +-mkdir $d/12345678-1234-1234-1234-123456789abc/master/vms +- +-# $VG - XXX Disabled because the forking used to write files in -o rhv +-# mode confuses valgrind. +-virt-v2v --debug-gc -v -x \ +- -i libvirt -ic "$libvirt_uri" windows \ +- -o rhv -os $d +- +-# Test the OVF metadata was created. +-test -f $d/12345678-1234-1234-1234-123456789abc/master/vms/*/*.ovf +- +-pushd $d/12345678-1234-1234-1234-123456789abc/images/* +- +-# Test the disk .meta was created. +-test -f *.meta +- +-# Test the disk file was created. +-vol=`basename *.meta .meta` +-test -f $vol +- +-popd +- +-# Compare resulting OVF +-VM_ID=$(basename $(ls -1d $d/12345678-1234-1234-1234-123456789abc/master/vms/*)) +-DISK_ID=$(basename $(ls -1d $d/12345678-1234-1234-1234-123456789abc/images/*)) +-VOL_ID=$(basename $(ls -1d $d/12345678-1234-1234-1234-123456789abc/images/$DISK_ID/*.meta) .meta) +-OVF=$(ls -1d $d/12345678-1234-1234-1234-123456789abc/master/vms/$VM_ID/$VM_ID.ovf) +- +-RE_UUID='\<[0-9a-fA-F]\{8\}-[0-9a-fA-F]\{4\}-[0-9a-fA-F]\{4\}-[0-9a-fA-F]\{4\}-[0-9a-fA-F]\{12\}\>' +- +-# Filter variable strings +-sed -i \ +- -e "s/$DISK_ID/#DISK_ID#/g" \ +- -e "s/$VM_ID/#VM_ID#/g" \ +- -e "s/$VOL_ID/#VOL_ID#/g" \ +- -e "s/\('"$RE_UUID"'#UUID#[^<]*#DATE# $f +- +-grep -- "-oo vdsm-compat" $f +-grep -- "-oo vdsm-image-uuid" $f +- +-rm $f +diff --git a/tests/test-v2v-o-vdsm-options.ovf.expected b/tests/test-v2v-o-vdsm-options.ovf.expected +deleted file mode 100644 +index 23ca180f..00000000 +--- a/tests/test-v2v-o-vdsm-options.ovf.expected ++++ /dev/null +@@ -1,113 +0,0 @@ +- +- +- +- +- +- +- +- List of networks +- +- +- +- List of Virtual Disks +- +- +- +- windows +- 00000000-0000-0000-0000-000000000000 +- Blank +- generated by virt-v2v +- +- #DATE# +- True +- False +- +- False +- 0 +- 2 +- 1 +- +- Microsoft Windows 7 Phony Edition +- Windows7 +- +- +- 1 CPU, 1024 Memory +- +- 1 virtual cpu +- Number of virtual CPU +- 1 +- 3 +- 1 +- 1 +- +- +- 1024 MB of memory +- Memory Size +- 2 +- 4 +- MegaBytes +- 1024 +- +- +- USB Controller +- 3 +- 23 +- Disabled +- +- +- Graphical Controller +- #UUID# +- 32768 +- video +- 1 +- vga +- +- +- RNG Device +- #UUID# +- 0 +- rng +- virtio +- +- urandom +- +- +- +- Memory Ballooning Device +- #UUID# +- 0 +- balloon +- memballoon +- +- virtio +- +- +- +- Drive 1 +- VOL +- 17 +- disk +- VOL +- 00000000-0000-0000-0000-000000000000 +- 00000000-0000-0000-0000-000000000000 +- +- 12345678-1234-1234-1234-123456789abc +- 00000000-0000-0000-0000-000000000000 +- #DATE# +- #DATE# +- #DATE# +- 1 +- +- +- #UUID# +- Ethernet adapter on default +- 10 +- 3 +- interface +- default +- eth0 +- 00:11:22:33:44:55 +- +- +- +- +diff --git a/tests/test-v2v-o-vdsm-options.sh b/tests/test-v2v-o-vdsm-options.sh +deleted file mode 100755 +index e8f8c538..00000000 +--- a/tests/test-v2v-o-vdsm-options.sh ++++ /dev/null +@@ -1,96 +0,0 @@ +-#!/bin/bash - +-# libguestfs virt-v2v test script +-# Copyright (C) 2014-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. +- +-# Test -o vdsm options -oo vdsm-*-uuid +- +-set -e +-set -x +- +-source ./functions.sh +-set -e +-set -x +- +-skip_if_skipped +-requires test -f ../test-data/phony-guests/windows.img +- +-libvirt_uri="test://$abs_top_builddir/test-data/phony-guests/guests.xml" +-f=../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=test-v2v-o-vdsm-options.d +-rm -rf $d +-cleanup_fn rm -r $d +-mkdir $d +- +-# Create a dummy Export Storage Domain. +-mkdir $d/12345678-1234-1234-1234-123456789abc +-mkdir $d/12345678-1234-1234-1234-123456789abc/images +-mkdir $d/12345678-1234-1234-1234-123456789abc/images/IMAGE +-mkdir $d/12345678-1234-1234-1234-123456789abc/master +-mkdir $d/12345678-1234-1234-1234-123456789abc/master/vms +-mkdir $d/12345678-1234-1234-1234-123456789abc/master/vms/VM +- +-# The -oo vdsm-*-uuid options don't actually check that the +-# parameter is a UUID, which is useful here. +- +-$VG virt-v2v --debug-gc \ +- -i libvirt -ic "$libvirt_uri" windows \ +- -o vdsm -os $d/12345678-1234-1234-1234-123456789abc \ +- -of qcow2 \ +- -oo vdsm-image-uuid=IMAGE \ +- -oo vdsm-vol-uuid=VOL \ +- -oo vdsm-vm-uuid=VM \ +- -oo vdsm-ovf-output=$d/12345678-1234-1234-1234-123456789abc/master/vms/VM \ +- -oo vdsm-compat=1.1 \ +- -oo vdsm-ovf-flavour=ovirt +- +-# Test the OVF metadata was created. +-test -f $d/12345678-1234-1234-1234-123456789abc/master/vms/VM/VM.ovf +- +-pushd $d/12345678-1234-1234-1234-123456789abc/images/IMAGE +- +-# Test the disk .meta was created. +-test -f VOL.meta +- +-# Test the disk file was created. +-test -f VOL +- +-# Test that a qcow2 file with compat=1.1 was generated. +-test "$(guestfish disk-format VOL)" = "qcow2" +-qemu-img info VOL | grep 'compat: 1.1' +- +-popd +- +-# Compare resulting OVF +-OVF="$d/12345678-1234-1234-1234-123456789abc/master/vms/VM/VM.ovf" +- +-RE_UUID='\<[0-9a-fA-F]\{8\}-[0-9a-fA-F]\{4\}-[0-9a-fA-F]\{4\}-[0-9a-fA-F]\{4\}-[0-9a-fA-F]\{12\}\>' +- +-# Filter variable strings +-sed -i \ +- -e "s/\('"$RE_UUID"'#UUID#[^<]*#DATE# output_mode := `Disk + | "null" -> output_mode := `Null + | "openstack" | "osp" | "rhosp" -> output_mode := `Openstack +- | "ovirt" | "rhv" | "rhev" -> output_mode := `RHV +- | "ovirt-upload" | "ovirt_upload" | "rhv-upload" | "rhv_upload" -> +- output_mode := `RHV_Upload + | "qemu" -> output_mode := `QEmu +- | "vdsm" -> output_mode := `VDSM + | s -> + error (f_"unknown -o option: %s") s + in +@@ -245,7 +241,7 @@ let rec main () = + s_"Map network ‘in’ to ‘out’"; + [ L"no-trim" ], Getopt.String ("-", no_trim_warning), + s_"Ignored for backwards compatibility"; +- [ S 'o' ], Getopt.String ("kubevirt|libvirt|local|null|openstack|qemu|rhv|rhv-upload|vdsm", set_output_mode), ++ [ S 'o' ], Getopt.String ("kubevirt|libvirt|local|null|openstack|qemu", set_output_mode), + s_"Set output mode (default: libvirt)"; + [ M"oa" ], Getopt.String ("sparse|preallocated", set_output_alloc), + s_"Set output allocation mode"; +@@ -283,18 +279,6 @@ let rec main () = + s_"Same as ‘-io vddk-thumbprint=thumbprint’"; + [ L"vddk-transports" ], Getopt.String ("transports", set_input_option_compat "vddk-transports"), + s_"Same as ‘-io vddk-transports=transports’"; +- [ L"vdsm-compat" ], Getopt.String ("0.10|1.1", set_output_option_compat "vdsm-compat"), +- s_"Same as ‘-oo vdsm-compat=0.10|1.1’"; +- [ L"vdsm-image-uuid" ], Getopt.String ("uuid", set_output_option_compat "vdsm-image-uuid"), +- s_"Same as ‘-oo vdsm-image-uuid=uuid’"; +- [ L"vdsm-vol-uuid" ], Getopt.String ("uuid", set_output_option_compat "vdsm-vol-uuid"), +- s_"Same as ‘-oo vdsm-vol-uuid=uuid’"; +- [ L"vdsm-vm-uuid" ], Getopt.String ("uuid", set_output_option_compat "vdsm-vm-uuid"), +- s_"Same as ‘-oo vdsm-vm-uuid=uuid’"; +- [ L"vdsm-ovf-output" ], Getopt.String ("dir", set_output_option_compat "vdsm-ovf-output"), +- s_"Same as ‘-oo vdsm-ovf-output=dir’"; +- [ L"vdsm-ovf-flavour" ], Getopt.String ("ovirt|rhvexp", set_output_option_compat "vdsm-ovf-flavour"), +- s_"Same as ‘-oo vdsm-ovf-flavour=flavour’"; + [ L"vmtype" ], Getopt.String ("-", vmtype_warning), + s_"Ignored for backwards compatibility"; + ] in +@@ -306,9 +290,6 @@ let rec main () = + + virt-v2v -ic vpx://vcenter.example.com/Datacenter/esxi -os imported esx_guest + +-virt-v2v -ic vpx://vcenter.example.com/Datacenter/esxi esx_guest \ +- -o rhv -os rhv.nfs:/export_domain --network ovirtmgmt +- + virt-v2v -i libvirtxml guest-domain.xml -o local -os /var/tmp + + virt-v2v -i disk disk.img -o local -os /var/tmp +@@ -370,7 +351,6 @@ read the man page virt-v2v(1). + pr "vcenter-https\n"; + pr "vddk\n"; + pr "colours-option\n"; +- pr "vdsm-compat-option\n"; + pr "io/oo\n"; + pr "mac-option\n"; + pr "bandwidth-option\n"; +@@ -386,9 +366,6 @@ read the man page virt-v2v(1). + pr "output:null\n"; + pr "output:openstack\n"; + pr "output:qemu\n"; +- pr "output:rhv\n"; +- pr "output:rhv-upload\n"; +- pr "output:vdsm\n"; + pr "convert:linux\n"; + pr "convert:windows\n"; + List.iter (pr "ovf:%s\n") Create_ovf.ovf_flavours; +@@ -473,10 +450,7 @@ read the man page virt-v2v(1). + | `Null -> (module Output_null.Null) + | `QEmu -> (module Output_qemu.QEMU) + | `Kubevirt -> (module Output_kubevirt.Kubevirt) +- | `Openstack -> (module Output_openstack.Openstack) +- | `RHV_Upload -> (module Output_rhv_upload.RHVUpload) +- | `RHV -> (module Output_rhv.RHV) +- | `VDSM -> (module Output_vdsm.VDSM) in ++ | `Openstack -> (module Output_openstack.Openstack) in + + let output_options = { + Output.output_alloc = output_alloc; +@@ -501,7 +475,6 @@ read the man page virt-v2v(1). + *) + let remove_serial_console = + match output_mode with +- | `RHV | `VDSM -> true + | _ -> false in + + (* Get the conversion options. *) diff --git a/SOURCES/0020-RHEL-Add-warning-about-virt-v2v-in-place-not-being-s.patch b/SOURCES/0020-RHEL-Add-warning-about-virt-v2v-in-place-not-being-s.patch new file mode 100644 index 0000000..30ad2b4 --- /dev/null +++ b/SOURCES/0020-RHEL-Add-warning-about-virt-v2v-in-place-not-being-s.patch @@ -0,0 +1,24 @@ +From 2a8788ae6bdb392ee12e0e66a7b0c9faef20eb44 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Tue, 9 Jul 2024 11:30:09 +0100 +Subject: [PATCH] RHEL: Add warning about virt-v2v-in-place not being supported + +Fixes: https://issues.redhat.com/browse/RHEL-40903 +--- + in-place/in_place.ml | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/in-place/in_place.ml b/in-place/in_place.ml +index 1c690a54..a70e812b 100644 +--- a/in-place/in_place.ml ++++ b/in-place/in_place.ml +@@ -197,6 +197,9 @@ read the man page virt-v2v-in-place(1). + let opthandle = create_standard_options argspec ~anon_fun ~key_opts:true ~machine_readable:true usage_msg in + Getopt.parse opthandle.getopt; + ++ warning "virt-v2v-in-place is NOT SUPPORTED for command line use. \ ++ It is almost always better to use virt-v2v instead of this tool."; ++ + (* Print the version, easier than asking users to tell us. *) + debug "info: %s: %s %s (%s)" + prog Config.package_name Config.package_version_full diff --git a/SOURCES/copy-patches.sh b/SOURCES/copy-patches.sh new file mode 100755 index 0000000..b811085 --- /dev/null +++ b/SOURCES/copy-patches.sh @@ -0,0 +1,65 @@ +#!/bin/bash - + +set -e + +# Maintainer script to copy patches from the git repo to the current +# directory. Use it like this: +# ./copy-patches.sh + +project=virt-v2v +rhel_version=10.0 + +# Check we're in the right directory. +if [ ! -f $project.spec ]; then + echo "$0: run this from the directory containing '$project.spec'" + exit 1 +fi + +case `id -un` in + rjones) git_checkout=$HOME/d/$project-rhel-$rhel_version ;; + lacos) git_checkout=$HOME/src/v2v/$project ;; + *) git_checkout=$HOME/d/$project-rhel-$rhel_version ;; +esac +if [ ! -d $git_checkout ]; then + echo "$0: $git_checkout does not exist" + echo "This script is only for use by the maintainer when preparing a" + echo "$project release on RHEL." + exit 1 +fi + +# Get the base version of the project. +version=`grep '^Version:' $project.spec | awk '{print $2}'` +tag="v$version" + +# Remove any existing patches. +git rm -f [0-9]*.patch ||: +rm -f [0-9]*.patch + +# Get the patches. +( + cd $git_checkout + rm -f [0-9]*.patch + git -c core.abbrev=8 format-patch -O/dev/null --subject-prefix=PATCH -N \ + --submodule=diff --no-signature --patience $tag +) +mv $git_checkout/[0-9]*.patch . + +# Remove any not to be applied. +rm -f *NOT-FOR-RPM*.patch + +# Add the patches. +git add [0-9]*.patch + +# Print out the patch lines. +echo +echo "--- Copy the following text into $project.spec file" +echo + +echo "# Patches." +for f in [0-9]*.patch; do + n=`echo $f | awk -F- '{print $1}'` + echo "Patch$n: $f" +done + +echo +echo "--- End of text" diff --git a/SOURCES/virt-v2v-2.5.6.tar.gz.sig b/SOURCES/virt-v2v-2.5.6.tar.gz.sig new file mode 100644 index 0000000..17a588b --- /dev/null +++ b/SOURCES/virt-v2v-2.5.6.tar.gz.sig @@ -0,0 +1,17 @@ +-----BEGIN PGP SIGNATURE----- + +iQJFBAABCAAvFiEE93dPsa0HSn6Mh2fqkXOPc+G3aKAFAmapDYsRHHJpY2hAYW5u +ZXhpYS5vcmcACgkQkXOPc+G3aKATow//dAt+/eD4WANTgt82gOK5VLuhlp/il6/L +IsErVntOsmAlr1Ukag6lAFmrQrxDHbRo1g9w+P3dabEbedqeAy0vlyE7feifbzfn +8dAGAYJBPqyhG5w5Y1YKU/ZfJF5OjxuD9kjn5YTBNmNNva2wqrb4vQqLfmfhpMlx +hf3xMlqJ3plXvaqPFk69BzSgA1hKP9Z/f522RQs9lRq+aSP00zatLX9DK5oXynas +6DbInkrfUjbMaENoYcuUzC1w45DUcTcq6Or36+h86G78yIkQpfwlS82G0/f4wVnv +QlD5pC6dCmowuCrr5/xMoYt5ah7L+qcEUIRJ4uB0xQgQtQV32eLIFjpcHsN973ot +ji2ievMtoM5Ncu2Hq1R02Hvx5PUvVZamEpEWf+HzqJl2VATw2F63CMALLjxR6mw4 +WORi90ZLQWtbt7lJgZEI29WOabuBWGG/cn+01gWLh8swqQpAgkGsbJhCxNXLiUfy +0PE7K+zoWVZzSiuOVeIh1Gn2p75gSTRQXfY+l+IfPPfOUBOuNN+w1J5HRUaT7ZAk +zBbPGFA2Y6x2zR9TD5n87QftXF6LPhf715qh5URI4Wl0pE+C9gxhQk+nf1aMKJ5J +/fOAtU8N+PtZPUm95NTaQxpkraspwHmhLRygWzA7wUGANmVUiX0fE3qgxW9NE2bI +paYjGigt040= +=FGlR +-----END PGP SIGNATURE----- diff --git a/SPECS/virt-v2v.spec b/SPECS/virt-v2v.spec new file mode 100644 index 0000000..2a06dcc --- /dev/null +++ b/SPECS/virt-v2v.spec @@ -0,0 +1,684 @@ +# If we should verify tarball signature with GPGv2. +%global verify_tarball_signature 1 + +# The source directory. +%global source_directory 2.5-development + +Name: virt-v2v +Epoch: 1 +Version: 2.5.6 +Release: 1%{?dist} +Summary: Convert a virtual machine to run on KVM + +License: GPL-2.0-or-later AND LGPL-2.0-or-later +URL: https://github.com/libguestfs/virt-v2v + +Source0: http://download.libguestfs.org/virt-v2v/%{source_directory}/%{name}-%{version}.tar.gz +%if 0%{verify_tarball_signature} +Source1: http://download.libguestfs.org/virt-v2v/%{source_directory}/%{name}-%{version}.tar.gz.sig +# Keyring used to verify tarball signature. +Source2: libguestfs.keyring +%endif + +# Maintainer script which helps with handling patches. +Source3: copy-patches.sh + +# Patches are maintained in the following repository: +# https://github.com/libguestfs/virt-v2v/commits/rhel-10.0 + +# Patches. +Patch0001: 0001-docs-Note-that-mac-len-field-is-now-optional.patch +Patch0002: 0002-convert-More-robust-qemu-ga-installation-change-path.patch +Patch0003: 0003-common-mlcustomize-Inject-qemu-ga-blnsvr-into-firstb.patch +Patch0004: 0004-docs-Add-a-note-about-removal-of-VMware-Tools-on-Win.patch +Patch0005: 0005-Update-common-submodule.patch +Patch0006: 0006-Pull-in-a-fix-to-make-Windows-firstboot-more-reliabl.patch +Patch0007: 0007-docs-Restate-position-on-removal-of-VMware-Tools.patch +Patch0008: 0008-RHEL-v2v-Select-correct-qemu-binary-for-o-qemu-mode-.patch +Patch0009: 0009-RHEL-v2v-Disable-the-qemu-boot-oo-qemu-boot-option-R.patch +Patch0010: 0010-RHEL-Fix-list-of-supported-sound-cards-to-match-RHEL.patch +Patch0011: 0011-RHEL-Fixes-for-libguestfs-winsupport.patch +Patch0012: 0012-RHEL-v2v-i-disk-force-VNC-as-display-RHBZ-1372671.patch +Patch0013: 0013-RHEL-point-to-KB-for-supported-v2v-hypervisors-guest.patch +Patch0014: 0014-RHEL-Remove-input-from-Xen.patch +Patch0015: 0015-RHEL-Remove-o-glance.patch +Patch0016: 0016-RHEL-Remove-the-in-place-option.patch +Patch0017: 0017-RHEL-tests-Remove-btrfs-test.patch +Patch0018: 0018-RHEL-Remove-block-driver-option.patch +Patch0019: 0019-RHEL-Remove-o-rhv-o-rhv-upload-and-o-vdsm-modes.patch +Patch0020: 0020-RHEL-Add-warning-about-virt-v2v-in-place-not-being-s.patch + +%if !0%{?rhel} +# libguestfs hasn't been built on i686 for a while since there is no +# kernel built for this architecture any longer and libguestfs rather +# fundamentally depends on the kernel. Therefore we must exclude this +# arch. Note there is no bug filed for this because we do not ever +# expect that libguestfs or virt-v2v will be available on i686 so +# there is nothing that needs fixing. +ExcludeArch: %{ix86} +%else +# Architectures where virt-v2v is shipped on RHEL: +# +# not on aarch64 because it is not useful there +# not on %%{power64} because of RHBZ#1287826 +# not on s390x because it is not useful there +ExclusiveArch: x86_64 +%endif + +BuildRequires: autoconf, automake, libtool +BuildRequires: make +BuildRequires: /usr/bin/pod2man +BuildRequires: gcc +BuildRequires: ocaml >= 4.04 + +BuildRequires: libguestfs-devel >= 1:1.49.8-1 +BuildRequires: augeas-devel +BuildRequires: bash-completion +BuildRequires: file-devel +BuildRequires: gettext-devel +BuildRequires: jansson-devel +BuildRequires: libnbd-devel +BuildRequires: libosinfo-devel +BuildRequires: libvirt-daemon-kvm +BuildRequires: libvirt-devel +BuildRequires: libxml2-devel +BuildRequires: pcre2-devel +BuildRequires: perl(Sys::Guestfs) +BuildRequires: po4a +BuildRequires: /usr/bin/virsh +BuildRequires: xorriso + +BuildRequires: ocaml-findlib-devel +BuildRequires: ocaml-libguestfs-devel +BuildRequires: ocaml-libvirt-devel +BuildRequires: ocaml-libnbd-devel +BuildRequires: ocaml-fileutils-devel +BuildRequires: ocaml-gettext-devel +%if !0%{?rhel} +BuildRequires: ocaml-ounit-devel +%endif + +# These are for running our limited test. +BuildRequires: glibc-utils +BuildRequires: %{_bindir}/qemu-nbd +BuildRequires: %{_bindir}/nbdcopy +BuildRequires: %{_bindir}/nbdinfo +BuildRequires: nbdkit-file-plugin +BuildRequires: nbdkit-null-plugin +%if !0%{?rhel} +BuildRequires: nbdkit-python-plugin +%endif +BuildRequires: nbdkit-cow-filter >= 1.28.3-1.el9 +BuildRequires: mingw-srvany-redistributable >= 1.1-6 +%ifarch x86_64 +BuildRequires: glibc-static +%endif + +%if 0%{verify_tarball_signature} +BuildRequires: gnupg2 +%endif + +Requires: libguestfs%{?_isa} >= 1:1.49.8-1 +Requires: guestfs-tools >= 1.49.7-1 + +# XFS is the default filesystem in Fedora and RHEL. +Requires: libguestfs-xfs + +%if 0%{?rhel} && ! 0%{?eln} +# For Windows conversions on RHEL. +Requires: libguestfs-winsupport >= 7.2 +%endif + +Requires: gawk +Requires: gzip +Requires: unzip +Requires: curl +Requires: openssh-clients >= 8.8p1 +Requires: %{_bindir}/virsh + +# Ensure the UEFI firmware is available, to properly convert +# EFI guests (RHBZ#1429643). +%ifarch x86_64 +Requires: edk2-ovmf +%endif +%ifarch aarch64 +Requires: edk2-aarch64 +%endif + +%if !0%{?rhel} +Requires: python3 +%elif %{?rhel} == 9 +Requires: platform-python +# Python is not needed by RHEL 10. +%endif +Requires: libnbd >= 1.10 +Requires: %{_bindir}/qemu-nbd +Requires: %{_bindir}/nbdcopy +Requires: %{_bindir}/nbdinfo +Requires: nbdkit-server >= 1.28.3-1.el9 +Requires: nbdkit-curl-plugin +Requires: nbdkit-file-plugin +Requires: nbdkit-nbd-plugin +Requires: nbdkit-null-plugin +%if !0%{?rhel} +Requires: nbdkit-python-plugin +%endif +Requires: nbdkit-ssh-plugin +%ifarch x86_64 +Requires: nbdkit-vddk-plugin +%endif +Requires: nbdkit-blocksize-filter +Requires: nbdkit-cacheextents-filter +Requires: nbdkit-cow-filter >= 1.28.3-1.el9 +Requires: nbdkit-multi-conn-filter +Requires: nbdkit-rate-filter +Requires: nbdkit-retry-filter + +# For rhsrvany.exe, used to install firstboot scripts in Windows guests. +Requires: mingw-srvany-redistributable >= 1.1-6 + +# On RHEL, virtio-win should be used to install virtio drivers +# and qemu-ga in converted guests. (RHBZ#1972644) +%if 0%{?rhel} +Recommends: virtio-win +%endif + + +%description +Virt-v2v converts a single guest from a foreign hypervisor to run on +KVM. It can read Linux and Windows guests running on VMware, Xen, +Hyper-V and some other hypervisors, and convert them to KVM managed by +libvirt, OpenStack, oVirt, Red Hat Virtualisation (RHV) or several +other targets. It can modify the guest to make it bootable on KVM and +install virtio drivers so it will run quickly. + + +%package bash-completion +Summary: Bash tab-completion for %{name} +BuildArch: noarch +Requires: bash-completion >= 2.0 +Requires: %{name} = %{epoch}:%{version}-%{release} + + +%description bash-completion +Install this package if you want intelligent bash tab-completion +for %{name}. + + +%package man-pages-ja +Summary: Japanese (ja) man pages for %{name} +BuildArch: noarch +Requires: %{name} = %{epoch}:%{version}-%{release} + +%description man-pages-ja +%{name}-man-pages-ja contains Japanese (ja) man pages +for %{name}. + + +%package man-pages-uk +Summary: Ukrainian (uk) man pages for %{name} +BuildArch: noarch +Requires: %{name} = %{epoch}:%{version}-%{release} + +%description man-pages-uk +%{name}-man-pages-uk contains Ukrainian (uk) man pages +for %{name}. + + +%prep +%if 0%{verify_tarball_signature} +%{gpgverify} --keyring='%{SOURCE2}' --signature='%{SOURCE1}' --data='%{SOURCE0}' +%endif +%autosetup -p1 + +autoreconf -fiv + + +%build +%configure \ +%if !0%{?rhel} + --with-extra="fedora=%{fedora},release=%{release}" \ +%else + --with-extra="rhel=%{rhel},release=%{release}" \ +%endif + +make V=1 %{?_smp_mflags} + + +%install +%make_install + +# Delete libtool crap. +find $RPM_BUILD_ROOT -name '*.la' -delete + +%if 0%{?rhel} +# On RHEL move virt-v2v-in-place to libexec since it is not supported, +# and remove the documentation. +mkdir -p $RPM_BUILD_ROOT%{_libexecdir} +mv $RPM_BUILD_ROOT%{_bindir}/virt-v2v-in-place $RPM_BUILD_ROOT%{_libexecdir}/ +rm $RPM_BUILD_ROOT%{_mandir}/man1/virt-v2v-in-place.1* +%endif + +# Find locale files. +%find_lang %{name} + + +%check +%ifarch x86_64 +# Only run the tests with non-debug (ie. non-Rawhide) kernels. +# XXX This tests for any debug kernel installed. +if grep CONFIG_DEBUG_MUTEXES=y /lib/modules/*/config ; then + echo "Skipping tests because debug kernel is installed" + exit 0 +fi + +# Make sure we can see the debug messages (RHBZ#1230160). +export LIBGUESTFS_DEBUG=1 +export LIBGUESTFS_TRACE=1 + +# The built in tests take a very long time to run under TCG (in Koji), +# so just perform a very simple conversion to check things are +# working. +for f in windows.img fedora.img; do + make -C test-data/phony-guests $f + if test -s test-data/phony-guests/$f; then + ./run virt-v2v -v -x -i disk test-data/phony-guests/$f -o null + fi +done +%endif + + +%files -f %{name}.lang +%license COPYING +%doc README +%{_bindir}/virt-v2v +%if !0%{?rhel} +%{_bindir}/virt-v2v-in-place +%else +%{_libexecdir}/virt-v2v-in-place +%endif +%{_bindir}/virt-v2v-inspector +%{_mandir}/man1/virt-v2v.1* +%{_mandir}/man1/virt-v2v-hacking.1* +%{_mandir}/man1/virt-v2v-input-vmware.1* +%if !0%{?rhel} +%{_mandir}/man1/virt-v2v-input-xen.1* +%{_mandir}/man1/virt-v2v-in-place.1* +%endif +%{_mandir}/man1/virt-v2v-inspector.1* +%{_mandir}/man1/virt-v2v-output-local.1* +%{_mandir}/man1/virt-v2v-output-openstack.1* +%if !0%{?rhel} +%{_mandir}/man1/virt-v2v-output-rhv.1* +%endif +%{_mandir}/man1/virt-v2v-release-notes-1.42.1* +%{_mandir}/man1/virt-v2v-release-notes-2.0.1* +%{_mandir}/man1/virt-v2v-release-notes-2.2.1* +%{_mandir}/man1/virt-v2v-release-notes-2.4.1* +%{_mandir}/man1/virt-v2v-support.1* + + +%files bash-completion +%license COPYING +%{bash_completions_dir}/virt-v2v + + +%files man-pages-ja +%license COPYING +%lang(ja) %{_mandir}/ja/man1/*.1* + + +%files man-pages-uk +%license COPYING +%lang(uk) %{_mandir}/uk/man1/*.1* + + +%changelog +* Mon Aug 12 2024 Richard W.M. Jones - 1:2.5.6-1 +- Further fixes for QEMU Guest Agent install & VMware Tools removal + resolves: RHEL-50563 + +* Thu Jul 25 2024 Richard W.M. Jones - 1:2.5.5-2 +- Fix installation of QEMU Guest Agent + resolves: RHEL-50563 + +* Thu Jul 11 2024 Richard W.M. Jones - 1:2.5.5-1 +- New upstream development version 2.5.5 + resolves: RHEL-46869 + +* Mon Jul 08 2024 Richard W.M. Jones - 1:2.5.4-5 +- RHEL patches: + * Select correct qemu binary for -o qemu mode + * Disable the --qemu-boot / -oo qemu-boot option + * Fix list of supported sound cards to match RHEL qemu + * Fixes for libguestfs-winsupport + * -i disk: force VNC as display + * point to KB for supported v2v hypervisors/guests + * Remove -o glance + * Remove the --in-place option + * tests: Remove btrfs test + * Remove --block-driver option +- Remove input from Xen + resolves: RHEL-37687 +- Remove -o rhv, -o rhv-upload and -o vdsm modes + resolves: RHEL-36712 + +* Tue Jun 25 2024 Troy Dawson - 1:2.5.4-4 +- Bump release for June 2024 mass rebuild + +* Wed Jun 19 2024 Richard W.M. Jones - 1:2.5.4-3 +- OCaml 5.2.0 ppc64le fix + +* Wed May 29 2024 Richard W.M. Jones - 1:2.5.4-2 +- OCaml 5.2.0 for Fedora 41 + +* Thu Apr 25 2024 Richard W.M. Jones - 1:2.5.4-1 +- New upstream development version 2.5.4 + +* Fri Apr 12 2024 Richard W.M. Jones - 1:2.5.3-2 +- Fix bytecode compilation (RHBZ#2274708) + +* Thu Apr 11 2024 Richard W.M. Jones - 1:2.5.3-1 +- New development branch version 2.5.3 +- Unconditionally run autoreconf. + +* Mon Mar 25 2024 Richard W.M. Jones - 1:2.5.2-2 +- Use %%{bash_completions_dir} macro + +* Tue Mar 12 2024 Richard W.M. Jones - 1:2.5.2-1 +- New development branch version 2.5.2 + +* Sat Jan 27 2024 Fedora Release Engineering - 1:2.5.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild + +* Thu Jan 18 2024 Richard W.M. Jones - 1:2.5.1-1 +- New development branch version 2.5.1 + +* Thu Jan 4 2024 Richard W.M. Jones - 1:2.4.0-1 +- New stable branch version 2.4.0 + +* Tue Dec 19 2023 Richard W.M. Jones - 1:2.3.8-1 +- New development branch version 2.3.8 + +* Mon Dec 18 2023 Richard W.M. Jones - 1:2.3.7-4 +- OCaml 5.1.1 + s390x code gen fix for Fedora 40 + +* Tue Dec 12 2023 Richard W.M. Jones - 1:2.3.7-3 +- OCaml 5.1.1 rebuild for Fedora 40 + +* Sat Dec 09 2023 Richard W.M. Jones - 1:2.3.7-2 +- New development branch version 2.3.7 + +* Mon Nov 27 2023 Richard W.M. Jones - 1:2.3.6-2 +- Fix build for libxml2 2.12.1 + +* Thu Nov 02 2023 Richard W.M. Jones - 1:2.3.6-1 +- New development branch version 2.3.6 + +* Fri Oct 20 2023 Yaakov Selkowitz - 1:2.3.5-4 +- Use mingw-srvany-redistributable + +* Thu Oct 05 2023 Richard W.M. Jones - 1:2.3.5-3 +- OCaml 5.1 rebuild for Fedora 40 + +* Sat Jul 22 2023 Fedora Release Engineering - 1:2.3.5-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild + +* Fri Jul 14 2023 Richard W.M. Jones - 1:2.3.5-1 +- New development branch version 2.3.5 + +* Wed Jul 12 2023 Richard W.M. Jones - 1:2.3.4-4 +- OCaml 5.0 rebuild for Fedora 39 + +* Mon Jul 10 2023 Jerry James - 1:2.3.4-3 +- OCaml 5.0.0 rebuild + +* Mon Jun 05 2023 Richard W.M. Jones - 1:2.3.4-2 +- Migrated to SPDX license +- Fix installation on newer RHEL + +* Wed Apr 19 2023 Richard W.M. Jones - 1:2.3.4-1 +- New development branch version 2.3.4 + +* Mon Feb 06 2023 Richard W.M. Jones - 1:2.3.3-1 +- New development branch version 2.3.3 + +* Tue Jan 24 2023 Richard W.M. Jones - 1:2.3.2-2 +- Rebuild OCaml packages for F38 + +* Thu Jan 19 2023 Richard W.M. Jones - 1:2.3.2-1 +- New development branch version 2.3.2 + +* Tue Jan 17 2023 Richard W.M. Jones - 1:2.3.1-1 +- New development branch version 2.3.1 + +* Tue Jan 10 2023 Richard W.M. Jones - 1:2.2.0-1 +- New stable branch version 2.2.0 + +* Fri Jan 06 2023 Richard W.M. Jones - 1:2.1.12-1 +- New upstream development version 2.1.12 +- Add release notes for future virt-v2v 2.2 + +* Sat Dec 10 2022 Richard W.M. Jones - 1:2.1.11-2 +- New upstream development version 2.1.11 + +* Sat Nov 26 2022 Richard W.M. Jones - 1:2.1.10-1 +- New upstream development version 2.1.10 +- New tool: virt-v2v-inspector + +* Tue Oct 11 2022 Richard W.M. Jones - 1:2.1.9-1 +- New upstream development version 2.1.9 + +* Tue Aug 23 2022 Richard W.M. Jones - 1:2.1.8-2 +- Add BR glibc-static for tests on x86_64. + +* Mon Aug 01 2022 Richard W.M. Jones - 1:2.1.8-1 +- New upstream development version 2.1.8 + +* Sat Jul 23 2022 Fedora Release Engineering - 1:2.1.7-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild + +* Tue Jul 05 2022 Richard W.M. Jones - 1:2.1.7-1 +- New upstream development version 2.1.7 + +* Sun Jun 19 2022 Richard W.M. Jones - 1:2.1.6-2 +- OCaml 4.14.0 rebuild + +* Fri Jun 17 2022 Richard W.M. Jones - 1:2.1.6-1 +- New upstream development version 2.1.6 + +* Sat Jun 11 2022 Richard W.M. Jones - 1:2.1.5-1 +- New upstream development version 2.1.5 +- Add Requires python3 / platform-python (RHBZ#2094779) +- Remove nbdkit-readahead-filter as it is no longer used +- Enable the tests + +* Thu May 26 2022 Richard W.M. Jones - 1:2.1.4-1 +- New upstream development version 2.1.4 + +* Thu May 12 2022 Richard W.M. Jones - 1:2.1.3-1 +- New upstream development version 2.1.3 + +* Tue Apr 26 2022 Richard W.M. Jones - 1:2.1.2-1 +- New upstream development version 2.1.2 + +* Tue Apr 12 2022 Richard W.M. Jones - 1:2.1.1-1 +- New upstream development version 2.1.1 + +* Mon Apr 04 2022 Richard W.M. Jones - 1:2.0.2-1 +- New upstream stable branch version 2.0.2 + +* Wed Mar 23 2022 Richard W.M. Jones - 1:2.0.1-1 +- New upstream stable branch version 2.0.1 +- Fixes security issue when running virt-v2v as root (RHBZ#2066773). + +* Mon Mar 14 2022 Richard W.M. Jones - 1:2.0.0-1 +- New upstream stable branch version 2.0.0 +- New virt-v2v-in-place and release notes man pages. +- Remove the RHEL (downstream) patches which are out of date. +- Don't use absolute symlinks. + +* Tue Feb 15 2022 Richard W.M. Jones - 1:1.45.99-1 +- New upstream development version 1.45.99 (preview of 2.0) +- Requires nbdkit-blocksize-filter. + +* Thu Feb 10 2022 Richard W.M. Jones - 1:1.45.98-1 +- New upstream development version 1.45.98 (preview of 2.0) + +* Fri Feb 04 2022 Richard W.M. Jones - 1:1.45.97-3 +- OCaml 4.13.1 rebuild to remove package notes + +* Sat Jan 22 2022 Fedora Release Engineering - 1:1.45.97-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild + +* Mon Jan 17 2022 Richard W.M. Jones - 1:1.45.97-1 +- New upstream development version 1.45.97 (preview of 2.0) + +* Thu Jan 06 2022 Richard W.M. Jones - 1:1.45.96-1 +- New upstream development version 1.45.96 (preview of 2.0) + +* Sat Dec 18 2021 Richard W.M. Jones - 1:1.45.95-1 +- New upstream development version 1.45.95 (preview of 2.0) + +* Tue Dec 07 2021 Richard W.M. Jones - 1:1.45.94-1 +- New upstream development version 1.45.94 (preview of 2.0) + +* Fri Dec 03 2021 Richard W.M. Jones - 1:1.45.93-1 +- New upstream development version 1.45.93 (preview of 2.0) + +* Thu Dec 02 2021 Richard W.M. Jones - 1:1.45.92-1 +- New upstream development version 1.45.92 (preview of 2.0) + +* Thu Nov 25 2021 Richard W.M. Jones - 1:1.45.91-2 +- Bump release and rebuild + +* Tue Nov 23 2021 Richard W.M. Jones - 1:1.45.91-1 +- New upstream development version 1.45.91 (preview of 2.0) + +* Tue Oct 05 2021 Richard W.M. Jones - 1:1.45.90-2 +- OCaml 4.13.1 build + +* Tue Sep 21 2021 Richard W.M. Jones - 1:1.45.90-1 +- New upstream development version 1.45.90 (preview of 2.0) + +* Fri Aug 06 2021 Richard W.M. Jones - 1:1.45.3-1 +- New upstream development version 1.45.3. +- Rebase RHEL patches. + +* Fri Jul 23 2021 Fedora Release Engineering - 1:1.45.2-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild + +* Wed Jun 30 2021 Richard W.M. Jones - 1:1.45.2-1 +- New upstream development version 1.45.2. +- Remove --debug-overlays and --print-estimate options. +- Remove -o glance option on RHEL 9 (RHBZ#1977539). +- Remove support for RHEV-APT (RHBZ#1945549). + +* Wed Jun 16 2021 Richard W.M. Jones - 1:1.45.1-1 +- New upstream development version 1.45.1. +- Require virtio-win on RHEL (RHBZ#1972644). +- v2v-test-harness, virt-v2v-copy-to-local have been removed upstream. + +* Thu Jun 10 2021 Richard W.M. Jones - 1:1.44.0-2 +- nbdkit-vddk-plugin dep only exists on x86-64. + +* Fri Apr 30 2021 Richard W.M. Jones - 1:1.44.0-1 +- New upstream stable branch version 1.44.0. + +* Wed Apr 14 2021 Richard W.M. Jones - 1:1.43.5-1 +- New upstream version 1.43.5. + +* Thu Apr 01 2021 Richard W.M. Jones - 1:1.43.4-5 +- Add upstream patch to depend on xorriso. +- Change libguestfs-tools-c -> guestfs-tools. + +* Tue Mar 30 2021 Richard W.M. Jones - 1:1.43.4-3 +- Add downstream (RHEL-only) patches (RHBZ#1931724). + +* Mon Mar 8 2021 Richard W.M. Jones - 1:1.43.4-2 +- Bump and rebuild for ocaml-gettext update. + +* Wed Mar 3 2021 Richard W.M. Jones - 1:1.43.4-1 +- New upstream version 1.43.4. + +* Tue Mar 2 2021 Richard W.M. Jones - 1:1.43.3-4 +- OCaml 4.12.0 build + +* Tue Mar 2 2021 Richard W.M. Jones - 1:1.43.3-3 +- Add fix for OCaml 4.12. + +* Wed Jan 27 2021 Fedora Release Engineering - 1:1.43.3-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild + +* Tue Jan 05 2021 Richard W.M. Jones - 1:1.43.3-1 +- New upstream version 1.43.3. + +* Thu Dec 03 2020 Richard W.M. Jones - 1:1.43.2-3 +- Drop obsolete virt-v2v-copy-to-local tool for Fedora 34 and RHEL 9. + +* Wed Dec 02 2020 Richard W.M. Jones - 1:1.43.2-2 +- Unify Fedora and RHEL spec files. + +* Tue Dec 01 2020 Richard W.M. Jones - 1:1.43.2-1 +- New upstream version 1.43.2. + +* Tue Sep 01 2020 Richard W.M. Jones - 1:1.43.1-5 +- OCaml 4.11.1 rebuild + +* Fri Aug 21 2020 Richard W.M. Jones - 1:1.43.1-4 +- OCaml 4.11.0 rebuild + +* Sat Aug 01 2020 Fedora Release Engineering - 1:1.43.1-3 +- Second attempt - Rebuilt for + https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Wed Jul 29 2020 Fedora Release Engineering - 1:1.43.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Mon Jul 06 2020 Richard W.M. Jones - 1.43.1-1 +- New development branch 1.43. + +* Wed May 06 2020 Richard W.M. Jones - 1.42.0-4 +- Re-add Epoch. Forgotten when we split this package from libguestfs. + +* Tue May 05 2020 Richard W.M. Jones - 1.42.0-2 +- OCaml 4.11.0+dev2-2020-04-22 rebuild + +* Thu Apr 16 2020 Richard W.M. Jones - 1.42.0-1 +- New upstream stable version 1.42.0. + +* Sat Apr 04 2020 Richard W.M. Jones - 1.41.8-11 +- Update all OCaml dependencies for RPM 4.16. + +* Thu Feb 27 2020 Richard W.M. Jones - 1.41.8-10 +- OCaml 4.10.0 final. + +* Fri Jan 31 2020 Fedora Release Engineering - 1.41.8-9 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild + +* Sun Jan 19 2020 Richard W.M. Jones - 1.41.8-8 +- Bump release and rebuild. + +* Sun Jan 19 2020 Richard W.M. Jones - 1.41.8-7 +- Bump release and rebuild. + +* Sun Jan 19 2020 Richard W.M. Jones - 1.41.8-6 +- Bump release and rebuild. + +* Sun Jan 19 2020 Richard W.M. Jones - 1.41.8-5 +- OCaml 4.10.0+beta1 rebuild. +- Use nbdkit-python-plugin (now all Python 3 in Rawhide). + +* Wed Nov 27 2019 Richard W.M. Jones - 1.41.8-4 +- Use license instead of doc for COPYING file. +- Include license in all subpackages. +- Use gpgverify macro. +- Don't own bash-completion directory because we Require the + bash-completion package which owns it already. + +* Tue Nov 26 2019 Richard W.M. Jones - 1.41.8-2 +- Fix permissions on .sig file. +- Disable -oa preallocated test since it fails in reviewers mock environment. + +* Fri Nov 15 2019 Richard W.M. Jones - 1.41.8-1 +- Initial release of separate virt-v2v program, was part of libguestfs.