customize, v2v: Use %systemroot% and CurrentControlSet from inspection.

For reasons unknown virt-v2v recomputed the CurrentControlSet from
first principles, and passed %systemroot% around to all functions.
However that data is available from the libguestfs inspection APIs.
This commit is contained in:
Richard W.M. Jones
2017-02-17 21:53:01 +00:00
parent 441db174f5
commit 5b48a8d59d
8 changed files with 69 additions and 56 deletions

View File

@@ -318,12 +318,7 @@ echo uninstalling firstboot service
let filename = g#case_sensitive_path filename in
Registry.with_hive_write g filename
(fun root_node ->
(* Find the 'Current' ControlSet. *)
let current_cs =
let select = g#hivex_node_get_child root_node "Select" in
let valueh = g#hivex_node_get_value select "Current" in
let value = int_of_le32 (g#hivex_value_value valueh) in
sprintf "ControlSet%03Ld" value in
let current_cs = g#inspect_get_windows_current_control_set root in
(* Add a new rhsrvany service to the system registry to execute
* firstboot. NB: All these edits are in the HKLM\SYSTEM hive.

View File

@@ -68,17 +68,16 @@ let convert ~keep_serial_console (g : G.guestfs) inspect source rcaps =
None
) in
(* Get the Windows %systemroot%. *)
let systemroot = g#inspect_get_windows_systemroot inspect.i_root in
(* Get the software and system hive files. *)
let software_hive_filename =
let filename = sprintf "%s/system32/config/software" systemroot in
let filename = sprintf "%s/system32/config/software"
inspect.i_windows_systemroot in
let filename = g#case_sensitive_path filename in
filename in
let system_hive_filename =
let filename = sprintf "%s/system32/config/system" systemroot in
let filename = sprintf "%s/system32/config/system"
inspect.i_windows_systemroot in
let filename = g#case_sensitive_path filename in
filename in
@@ -223,13 +222,6 @@ let convert ~keep_serial_console (g : G.guestfs) inspect source rcaps =
(*----------------------------------------------------------------------*)
(* Perform the conversion of the Windows guest. *)
(* Find the 'Current' ControlSet. *)
let get_current_cs root =
let select = g#hivex_node_get_child root "Select" in
let valueh = g#hivex_node_get_value select "Current" in
let value = int_of_le32 (g#hivex_value_value valueh) in
sprintf "ControlSet%03Ld" value in
let rec configure_firstboot () =
wait_pnp ();
(match installer with
@@ -298,8 +290,8 @@ reg delete \"%s\" /v %s /f" strkey name
let name = "SuppressUI" in
let value = Registry.with_hive_write g system_hive_filename (
fun root ->
let current_cs = get_current_cs root in
set_reg_val_dword_1 root (current_cs :: key_path) name
set_reg_val_dword_1 root (inspect.i_windows_current_control_set
:: key_path) name
) in
reg_restore ("HKLM\\SYSTEM\\CurrentControlSet" :: key_path) name
value
@@ -402,18 +394,16 @@ if errorlevel 3010 exit /b 0
(* Update the SYSTEM hive. When this function is called the hive has
* already been opened as a hivex handle inside guestfs.
*)
let current_cs = get_current_cs root in
debug "current ControlSet is %s" current_cs;
disable_xenpv_win_drivers root;
disable_prl_drivers root;
disable_autoreboot root;
Windows_virtio.install_drivers g inspect root rcaps
disable_xenpv_win_drivers root current_cs;
disable_prl_drivers root current_cs;
disable_autoreboot root current_cs;
Windows_virtio.install_drivers g inspect systemroot
root current_cs rcaps
and disable_xenpv_win_drivers root current_cs =
and disable_xenpv_win_drivers root =
(* Disable xenpv-win service (RHBZ#809273). *)
let services = Registry.get_node g root [current_cs; "Services"] in
let services =
Registry.get_node g root
[inspect.i_windows_current_control_set; "Services"] in
match services with
| None -> ()
@@ -422,9 +412,11 @@ if errorlevel 3010 exit /b 0
if node <> 0L then
g#hivex_node_set_value node "Start" 4_L (le32_of_int 4_L)
and disable_prl_drivers root current_cs =
and disable_prl_drivers root =
(* Prevent Parallels drivers from loading at boot. *)
let services = Registry.get_node g root [current_cs; "Services"] in
let services =
Registry.get_node g root
[inspect.i_windows_current_control_set; "Services"] in
let prl_svcs = [ "prl_boot"; "prl_dd"; "prl_eth5"; "prl_fs"; "prl_memdev";
"prl_mouf"; "prl_pv32"; "prl_pv64"; "prl_scsi";
"prl_sound"; "prl_strg"; "prl_tg"; "prl_time";
@@ -447,7 +439,8 @@ if errorlevel 3010 exit /b 0
* HKLM, System\CurrentControlSet\Control\Class\{4d36e967-e325-11ce-bfc1-08002be10318}, LowerFilters, 0x00018002, prl_strg
*)
let strg_cls = Registry.get_node g root
[current_cs; "Control"; "Class";
[inspect.i_windows_current_control_set;
"Control"; "Class";
"{4d36e967-e325-11ce-bfc1-08002be10318}"] in
match strg_cls with
| None -> ()
@@ -467,12 +460,13 @@ if errorlevel 3010 exit /b 0
g#hivex_node_set_value strg_cls lfkey 7_L data
)
and disable_autoreboot root current_cs =
and disable_autoreboot root =
(* If the guest reboots after a crash, it's hard to see the original
* error (eg. the infamous 0x0000007B). Turn off autoreboot.
*)
let crash_control =
Registry.get_node g root [current_cs; "Control"; "CrashControl"] in
Registry.get_node g root [inspect.i_windows_current_control_set;
"Control"; "CrashControl"] in
match crash_control with
| None -> ()
| Some crash_control ->

View File

@@ -32,6 +32,8 @@ let rec inspect_source root_choice g =
reject_if_not_installed_image g root;
let typ = g#inspect_get_type root in
(* Mount up the filesystems. *)
let mps = g#inspect_get_mountpoints root in
let cmp (a,_) (b,_) = compare (String.length a) (String.length b) in
@@ -65,9 +67,20 @@ let rec inspect_source root_choice g =
StringMap.add name (app :: vs) map
) StringMap.empty apps in
(* If the guest is Windows, get some Windows-specific inspection
* data, else (for simplicity when accessing) use empty strings.
*)
let systemroot, current_cs =
match typ with
| "windows" ->
g#inspect_get_windows_systemroot root,
g#inspect_get_windows_current_control_set root
| _ ->
"", "" in
let inspect = {
i_root = root;
i_type = g#inspect_get_type root;
i_type = typ;
i_distro = g#inspect_get_distro root;
i_arch = g#inspect_get_arch root;
i_major_version = g#inspect_get_major_version root;
@@ -80,6 +93,8 @@ let rec inspect_source root_choice g =
i_apps = apps;
i_apps_map = apps_map;
i_firmware = get_firmware_bootable_device g;
i_windows_systemroot = systemroot;
i_windows_current_control_set = current_cs;
} in
debug "%s" (string_of_inspect inspect);

View File

@@ -324,6 +324,8 @@ type inspect = {
i_apps : Guestfs.application2 list;
i_apps_map : Guestfs.application2 list StringMap.t;
i_firmware : i_firmware;
i_windows_systemroot : string;
i_windows_current_control_set : string;
}
let string_of_inspect inspect =
@@ -339,6 +341,8 @@ i_package_management = %s
i_product_name = %s
i_product_variant = %s
i_firmware = %s
i_windows_systemroot = %s
i_windows_current_control_set = %s
" inspect.i_root
inspect.i_type
inspect.i_distro
@@ -352,6 +356,8 @@ i_firmware = %s
(match inspect.i_firmware with
| I_BIOS -> "BIOS"
| I_UEFI devices -> sprintf "UEFI [%s]" (String.concat ", " devices))
inspect.i_windows_systemroot
inspect.i_windows_current_control_set
type mpstat = {
mp_dev : string;

View File

@@ -230,6 +230,8 @@ type inspect = {
i_firmware : i_firmware;
(** The list of EFI system partitions for the guest with UEFI,
otherwise the BIOS identifier. *)
i_windows_systemroot : string;
i_windows_current_control_set : string;
}
(** Inspection information. *)

View File

@@ -30,7 +30,8 @@ let inspect_defaults = {
i_major_version = 0; i_minor_version = 0;
i_root = ""; i_package_format = ""; i_package_management = "";
i_product_name = ""; i_product_variant = ""; i_mountpoints = [];
i_apps = []; i_apps_map = StringMap.empty; i_firmware = I_BIOS
i_apps = []; i_apps_map = StringMap.empty; i_firmware = I_BIOS;
i_windows_systemroot = ""; i_windows_current_control_set = "";
}
let test_get_ostype ctx =

View File

@@ -37,9 +37,9 @@ let scsi_class_guid = "{4D36E97B-E325-11CE-BFC1-08002BE10318}"
let viostor_pciid = "VEN_1AF4&DEV_1001&SUBSYS_00021AF4&REV_00"
let vioscsi_pciid = "VEN_1AF4&DEV_1004&SUBSYS_00081AF4&REV_00"
let rec install_drivers g inspect systemroot root current_cs rcaps =
let rec install_drivers g inspect root rcaps =
(* Copy the virtio drivers to the guest. *)
let driverdir = sprintf "%s/Drivers/VirtIO" systemroot in
let driverdir = sprintf "%s/Drivers/VirtIO" inspect.i_windows_systemroot in
g#mkdir_p driverdir;
if not (copy_drivers g inspect driverdir) then (
@@ -98,22 +98,22 @@ let rec install_drivers g inspect systemroot root current_cs rcaps =
(* Block driver needs tweaks to allow booting; the rest is set up by PnP
* manager *)
let source = driverdir // (driver_name ^ ".sys") in
let target = sprintf "%s/system32/drivers/%s.sys" systemroot driver_name in
let target = sprintf "%s/system32/drivers/%s.sys"
inspect.i_windows_systemroot driver_name in
let target = g#case_sensitive_path target in
g#cp source target;
add_guestor_to_registry g root current_cs driver_name
viostor_pciid;
add_guestor_to_registry g inspect root driver_name viostor_pciid;
Virtio_blk
| Some Virtio_SCSI, _, true ->
(* Block driver needs tweaks to allow booting; the rest is set up by PnP
* manager *)
let source = driverdir // "vioscsi.sys" in
let target = sprintf "%s/system32/drivers/vioscsi.sys" systemroot in
let target = sprintf "%s/system32/drivers/vioscsi.sys"
inspect.i_windows_systemroot in
let target = g#case_sensitive_path target in
g#cp source target;
add_guestor_to_registry g root current_cs "vioscsi"
vioscsi_pciid;
add_guestor_to_registry g inspect root "vioscsi" vioscsi_pciid;
Virtio_SCSI
| Some IDE, _, _ ->
@@ -168,18 +168,18 @@ let rec install_drivers g inspect systemroot root current_cs rcaps =
(block, net, video)
)
and add_guestor_to_registry g root current_cs drv_name drv_pciid =
and add_guestor_to_registry g inspect root drv_name drv_pciid =
let ddb_node = g#hivex_node_get_child root "DriverDatabase" in
let regedits =
if ddb_node = 0L then
cdb_regedits current_cs drv_name drv_pciid
cdb_regedits inspect drv_name drv_pciid
else
ddb_regedits current_cs drv_name drv_pciid in
ddb_regedits inspect drv_name drv_pciid in
let drv_sys_path = sprintf "system32\\drivers\\%s.sys" drv_name in
let common_regedits = [
[ current_cs; "Services"; drv_name ],
[ inspect.i_windows_current_control_set; "Services"; drv_name ],
[ "Type", REG_DWORD 0x1_l;
"Start", REG_DWORD 0x0_l;
"Group", REG_SZ "SCSI miniport";
@@ -189,19 +189,20 @@ and add_guestor_to_registry g root current_cs drv_name drv_pciid =
reg_import g root (regedits @ common_regedits)
and cdb_regedits current_cs drv_name drv_pciid =
and cdb_regedits inspect drv_name drv_pciid =
(* See http://rwmj.wordpress.com/2010/04/30/tip-install-a-device-driver-in-a-windows-vm/
* NB: All these edits are in the HKLM\SYSTEM hive. No other
* hive may be modified here.
*)
[
[ current_cs; "Control"; "CriticalDeviceDatabase";
[ inspect.i_windows_current_control_set;
"Control"; "CriticalDeviceDatabase";
"PCI#" ^ drv_pciid ],
[ "Service", REG_SZ drv_name;
"ClassGUID", REG_SZ scsi_class_guid ];
]
and ddb_regedits current_cs drv_name drv_pciid =
and ddb_regedits inspect drv_name drv_pciid =
(* Windows >= 8 doesn't use the CriticalDeviceDatabase. Instead
* one must add keys into the DriverDatabase.
*)

View File

@@ -19,17 +19,16 @@
(** Functions for installing Windows virtio drivers. *)
val install_drivers
: Guestfs.guestfs -> Types.inspect -> string -> Registry.node -> string ->
: Guestfs.guestfs -> Types.inspect -> Registry.node ->
Types.requested_guestcaps ->
Types.guestcaps_block_type * Types.guestcaps_net_type * Types.guestcaps_video_type
(** [install_drivers g inspect systemroot root current_cs rcaps]
(** [install_drivers g inspect root rcaps]
installs virtio drivers from the driver directory or driver
ISO into the guest driver directory and updates the registry
so that the [viostor.sys] driver gets loaded by Windows at boot.
[root] is the root node of the system hive (which is open for writes
when this function is called). [current_cs] is the name of the
[CurrentControlSet] (eg. ["ControlSet001"]).
when this function is called).
[rcaps] is the set of guest "capabilities" requested by the caller. This
may include the type of the block driver, network driver, and video driver.