[Libguestfs] [PATCH 3/8] customize, v2v: Use %systemroot% and CurrentControlSet from inspection.

Richard W.M. Jones rjones at redhat.com
Sat Feb 18 08:05:30 UTC 2017


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.
---
 customize/firstboot.ml |  7 +------
 v2v/convert_windows.ml | 52 ++++++++++++++++++++++----------------------------
 v2v/inspect_source.ml  | 17 ++++++++++++++++-
 v2v/types.ml           |  6 ++++++
 v2v/types.mli          |  2 ++
 v2v/v2v_unit_tests.ml  |  3 ++-
 v2v/windows_virtio.ml  | 31 +++++++++++++++---------------
 v2v/windows_virtio.mli |  7 +++----
 8 files changed, 69 insertions(+), 56 deletions(-)

diff --git a/customize/firstboot.ml b/customize/firstboot.ml
index 5396ded..3a5c10a 100644
--- a/customize/firstboot.ml
+++ b/customize/firstboot.ml
@@ -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.
diff --git a/v2v/convert_windows.ml b/v2v/convert_windows.ml
index a231219..eabbd56 100644
--- a/v2v/convert_windows.ml
+++ b/v2v/convert_windows.ml
@@ -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 ->
diff --git a/v2v/inspect_source.ml b/v2v/inspect_source.ml
index 3936e72..3b16c42 100644
--- a/v2v/inspect_source.ml
+++ b/v2v/inspect_source.ml
@@ -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);
 
diff --git a/v2v/types.ml b/v2v/types.ml
index afeb178..7fd6327 100644
--- a/v2v/types.ml
+++ b/v2v/types.ml
@@ -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;
diff --git a/v2v/types.mli b/v2v/types.mli
index 96ab36a..df50b1b 100644
--- a/v2v/types.mli
+++ b/v2v/types.mli
@@ -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. *)
 
diff --git a/v2v/v2v_unit_tests.ml b/v2v/v2v_unit_tests.ml
index 1133d92..af86afa 100644
--- a/v2v/v2v_unit_tests.ml
+++ b/v2v/v2v_unit_tests.ml
@@ -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 =
diff --git a/v2v/windows_virtio.ml b/v2v/windows_virtio.ml
index a63ab44..2c28524 100644
--- a/v2v/windows_virtio.ml
+++ b/v2v/windows_virtio.ml
@@ -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.
    *)
diff --git a/v2v/windows_virtio.mli b/v2v/windows_virtio.mli
index 1d25260..4ceeebe 100644
--- a/v2v/windows_virtio.mli
+++ b/v2v/windows_virtio.mli
@@ -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.
-- 
2.10.2




More information about the Libguestfs mailing list