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