[Libguestfs] [PATCH 7/7] v2v: add support for SUSE VMDP drivers

Cédric Bosdonnat cbosdonnat at suse.com
Tue Apr 5 11:47:33 UTC 2016


To add this support, the existing code searches for either the viostor
or the VMDP (Virtual Machine Driver Pack) files and updates the registry
accordingly.

Note that VMDP's block driver pvvxblk depends on the ballooning driver
pvvxbn.
---
 v2v/convert_windows.ml |  59 ++++++++++++++++++++------
 v2v/windows_virtio.ml  | 113 +++++++++++++++++++++++++++++++++++++++++--------
 2 files changed, 141 insertions(+), 31 deletions(-)

diff --git a/v2v/convert_windows.ml b/v2v/convert_windows.ml
index 5daae6c..cb936ec 100644
--- a/v2v/convert_windows.ml
+++ b/v2v/convert_windows.ml
@@ -43,18 +43,25 @@ let convert ~keep_serial_console (g : G.guestfs) inspect source rcaps =
     try Sys.getenv "VIRT_TOOLS_DATA_DIR"
     with Not_found -> Guestfs_config.datadir // "virt-tools" in
 
-  (* Check if RHEV-APT exists.  This is optional. *)
-  let rhev_apt_exe = virt_tools_data_dir // "rhev-apt.exe" in
-  let rhev_apt_exe =
+  (* Check if either RHEV-APT or VMDP exists.  This is optional. *)
+  let tools = ["rhev-apt.exe"; "vmdp.exe"] in
+  let installer =
     try
-      let chan = open_in rhev_apt_exe in
-      close_in chan;
-      Some rhev_apt_exe
-    with
-      Sys_error msg ->
-        warning (f_"'%s' is missing.  Unable to install RHEV-APT (RHEV guest agent).  Original error: %s")
-          rhev_apt_exe msg;
-        None in
+      let tool = List.find (
+        fun item ->
+          try (
+            let exe_path = virt_tools_data_dir // item in
+            let chan = open_in exe_path in
+            close_in chan;
+            true
+          ) with _ ->
+            false
+      ) tools in
+      Some (virt_tools_data_dir // tool)
+    with Not_found -> (
+      warning (f_"Neither rhev-apt.exe nor vmdp.exe can be found.  Unable to install one of them.");
+      None
+    ) in
 
   (* Get the Windows %systemroot%. *)
   let systemroot = g#inspect_get_windows_systemroot inspect.i_root in
@@ -211,7 +218,14 @@ let convert ~keep_serial_console (g : G.guestfs) inspect source rcaps =
   (* Perform the conversion of the Windows guest. *)
 
   let rec configure_firstboot () =
-    configure_rhev_apt ();
+    match installer with
+    | None -> info (f_"No firstboot installer to configure")
+    | Some installer_path ->
+       let installer_name = Filename.basename installer_path in
+       match installer_name with
+        | "rhev-apt.exe" -> configure_rhev_apt ()
+        | "vmdp.exe" -> configure_vmdp ()
+        | _ -> info (f_"No setup function for installer '%s'") installer_path;
     unconfigure_xenpv ();
     unconfigure_prltools ()
 
@@ -219,7 +233,7 @@ let convert ~keep_serial_console (g : G.guestfs) inspect source rcaps =
     (* Configure RHEV-APT (the RHEV guest agent).  However if it doesn't
      * exist just warn about it and continue.
      *)
-    match rhev_apt_exe with
+    match installer with
     | None -> ()
     | Some rhev_apt_exe ->
       g#upload rhev_apt_exe "/rhev-apt.exe"; (* XXX *)
@@ -236,6 +250,25 @@ net start rhev-apt
       Firstboot.add_firstboot_script g inspect.i_root
         "configure rhev-apt" fb_script
 
+  and configure_vmdp () =
+    (* Configure VMDP if possible *)
+    match installer with
+    | None -> ()
+    | Some vmdp_exe ->
+      g#upload vmdp_exe "/vmdp.exe";
+
+      let fb_script = "\
+echo V2V first boot script started
+echo Decompressing VMDP installer
+\"\\vmdp.exe\"
+cd \"VMDP-WIN*\"
+echo Installing VMDP
+setup.exe /eula_accepted /auto_reboot
+cd ..
+" in
+      Firstboot.add_firstboot_script g inspect.i_root
+        "configure vmdp" fb_script
+
   and unconfigure_xenpv () =
     match xenpv_uninst with
     | None -> () (* nothing to be uninstalled *)
diff --git a/v2v/windows_virtio.ml b/v2v/windows_virtio.ml
index 22e3e31..87e39e6 100644
--- a/v2v/windows_virtio.ml
+++ b/v2v/windows_virtio.ml
@@ -62,15 +62,23 @@ let rec install_drivers g inspect systemroot root current_cs rcaps =
   else (
     (* Can we install the block driver? *)
     let block : guestcaps_block_type =
-      let has_viostor = g#exists (driverdir // "viostor.inf") in
+      let filenames = ["pvvxblk.sys"; "virtio_blk.sys"; "vrtioblk.sys"; "viostor.sys"] in
+      let driver_name = try (
+        List.find (
+          fun driver_file ->
+            let source = driverdir // driver_file in
+            g#exists source
+        ) filenames
+      ) with Not_found -> "" in
+      let has_viostor = not (driver_name = "") in
       match rcaps.rcaps_block_bus, has_viostor with
       | Some Virtio_blk, false ->
-        error (f_"there is no viostor (virtio block device) driver for this version of Windows (%d.%d %s).  virt-v2v looks for this driver in %s\n\nThe guest will be configured to use a slower emulated device.")
+        error (f_"there is no virtio block device driver for this version of Windows (%d.%d %s).  virt-v2v looks for this driver in %s\n\nThe guest will be configured to use a slower emulated device.")
               inspect.i_major_version inspect.i_minor_version
               inspect.i_arch virtio_win
 
       | None, false ->
-        warning (f_"there is no viostor (virtio block device) driver for this version of Windows (%d.%d %s).  virt-v2v looks for this driver in %s\n\nThe guest will be configured to use a slower emulated device.")
+        warning (f_"there is no virtio block device driver for this version of Windows (%d.%d %s).  virt-v2v looks for this driver in %s\n\nThe guest will be configured to use a slower emulated device.")
                 inspect.i_major_version inspect.i_minor_version
                 inspect.i_arch virtio_win;
         IDE
@@ -78,11 +86,17 @@ let rec install_drivers g inspect systemroot root current_cs rcaps =
       | (Some Virtio_blk | None), true ->
         (* Block driver needs tweaks to allow booting; the rest is set up by PnP
          * manager *)
-        let source = driverdir // "viostor.sys" in
-        let target = sprintf "%s/system32/drivers/viostor.sys" systemroot in
+        let source = driverdir // driver_name in
+        let targetdir = systemroot ^ "/system32/drivers/" in
+        let target = targetdir // driver_name in
         let target = g#case_sensitive_path target in
         g#cp source target;
-        add_viostor_to_registry g inspect root current_cs driverdir;
+        if (driver_name = "pvvxblk.sys") then (
+          let target = targetdir // "pvvxbn.sys" in
+          let target = g#case_sensitive_path target in
+          g#cp (driverdir // "pvvxbn.sys") target
+        );
+        add_viostor_to_registry g inspect root current_cs driverdir driver_name;
         Virtio_blk
 
       | Some IDE, _ ->
@@ -90,7 +104,8 @@ let rec install_drivers g inspect systemroot root current_cs rcaps =
 
     (* Can we install the virtio-net driver? *)
     let net : guestcaps_net_type =
-      let has_netkvm = g#exists (driverdir // "netkvm.inf") in
+      let filenames = ["pvvxnet.inf"; "virtio_net.inf"; "netkvm.inf"] in
+      let has_netkvm = List.exists (fun driver_file -> g#exists (driverdir // driver_file)) filenames in
       match rcaps.rcaps_net_bus, has_netkvm with
       | Some Virtio_net, false ->
         error (f_"there is no virtio network driver for this version of Windows (%d.%d %s).  virt-v2v looks for this driver in %s")
@@ -133,20 +148,19 @@ let rec install_drivers g inspect systemroot root current_cs rcaps =
     (block, net, video)
   )
 
-and add_viostor_to_registry g inspect root current_cs driverdir =
+and add_viostor_to_registry g inspect root current_cs driverdir driver_name =
   let { i_major_version = major; i_minor_version = minor;
         i_arch = arch } = inspect in
   if (major == 6 && minor >= 2) || major >= 7 then (* Windows >= 8 *)
-    add_viostor_to_driver_database g root arch current_cs driverdir
+    add_viostor_to_driver_database g root arch current_cs driverdir driver_name
   else                          (* Windows <= 7 *)
-    add_viostor_to_critical_device_database g root current_cs major
+    add_viostor_to_critical_device_database g root current_cs major driver_name
 
-and add_viostor_to_critical_device_database g root current_cs major =
+and add_viostor_to_critical_device_database g root current_cs major driver =
   (* 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.
    *)
-  let driver = "viostor.sys" in
   let driver_name = Filename.chop_extension driver in
   (* Windows 2k3 uses '&0&', windows 2k8 '&2&' *)
   let subkey =
@@ -208,11 +222,10 @@ and add_viostor_to_critical_device_database g root current_cs major =
 
   reg_import g root regedits
 
-and add_viostor_to_driver_database g root arch current_cs driverdir =
+and add_viostor_to_driver_database g root arch current_cs driverdir driver =
   (* Windows >= 8 doesn't use the CriticalDeviceDatabase.  Instead
    * one must add keys into the DriverDatabase.
    *)
-  let driver = "viostor.sys" in
   let driver_name = Filename.chop_extension driver in
 
   let inf_full =
@@ -229,8 +242,12 @@ and add_viostor_to_driver_database g root arch current_cs driverdir =
 
   let scsi_adapter_guid = "{4d36e97b-e325-11ce-bfc1-08002be10318}" in
 
-  let driverdesc = "Red Hat VirtIO SCSI controller" in
-  let provider = "Red Hat, Inc." in
+  let driverdesc = if (driver_name = "pvvxblk")
+    then "SUSE Block Driver for Windows"
+    else "Red Hat VirtIO SCSI controller" in
+
+  let provider = if (driver_name = "pvvxblk") then "SUSE" else "Red Hat, Inc." in
+  let msi_supported = if (driver_name = "pvvxblk") then 0x0_l else 0x1_l in
 
   let driver_inst = (sprintf "%s_inst" driver_name) in
 
@@ -256,11 +273,14 @@ and add_viostor_to_driver_database g root arch current_cs driverdir =
       [ "DevicePolicy", REG_DWORD 0x00000005_l ];
 
       [ "DriverDatabase"; "DriverPackages"; inf_full; "Configurations"; driver_inst; "Device"; "Interrupt Management"; "MessageSignaledInterruptProperties" ],
-      [ "MSISupported", REG_DWORD 0x00000001_l;
+      [ "MSISupported", REG_DWORD msi_supported;
         "MessageNumberLimit", REG_DWORD 0x00000002_l ];
     ] in
 
-  reg_import g root regedits;
+  (reg_import g root regedits;
+   if (driver_name = "pvvxblk") then
+     add_pvvxbn_to_driver_database g root arch current_cs driverdir
+  );
 
 (*
        A few more keys which we don't add above.  Note that "oem1.inf" ==
@@ -454,6 +474,63 @@ and get_common_regedits g root current_cs adapter_guid driverdir driver driverde
       driverdesc_key, REG_SZ driverdesc ];
   ]
 
+and add_pvvxbn_to_driver_database g root arch current_cs driverdir =
+
+  let driver_name = "pvvxbn" in
+
+  let inf_full =
+    let arch =
+      match arch with
+      | "x86_64" -> "amd64"
+      | "i386" | "i486" | "i585" | "i686" -> "x86"
+      | _ ->
+         error (f_"when adding pvvxbn to the DriverDatabase, unknown architecture: %s") arch in
+    sprintf "%s.inf_%s_%s" driver_name arch "9b414b949945d17b" in
+
+  let driverdesc = "SUSE Bus/Balloon Driver for Windows" in
+  let driver_inst = "pvvxbn_inst" in
+  let provider = "SUSE" in
+
+  let device_id = "VEN_1AF4&DEV_1002&SUBSYS_00051AF4&REV_00" in
+  let device_subkey = "3&13c0b0c5&0&20" in
+  let device_alt = "CC_00FF00" in
+
+  let balloon_bus_guid = "{4d36e97d-e325-11ce-bfc1-08002be10318}" in
+
+  let class_guid = "{9fae43c0-44bf-465e-90c9-3da1c30ed68b}" in
+
+  let service_group = "Boot Bus Extender" in
+  (* NB: balloon_bus_guid appears inside this string. *)
+  let driver_version = "\x00\xff\x09\x00\x00\x00\x00\x00\x7d\xe9\x36\x4d\x25\xe3\xce\x11\xbf\xc1\x08\x00\x2b\xe1\x03\x18\x00\x40\x7f\x1d\xdc\xfb\xd0\x01\x13\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00"  in
+  let device_addr = "(0,4,0)" in
+
+  let common_regedits = get_common_regedits g root current_cs balloon_bus_guid driverdir "pvvxbn.sys" driverdesc driver_version service_group inf_full device_id device_subkey device_alt device_addr provider in
+
+  let regedits = common_regedits @ [
+      [ current_cs; "Control"; "DeviceClasses"; class_guid ],
+      [];
+
+      [ current_cs; "Control"; "DeviceClasses"; class_guid;
+        sprintf "##?#PCI#%s#%s#%s" device_id device_subkey class_guid ],
+      [ "DeviceInstance", REG_SZ (sprintf "PCI\\%s\\%s" device_id device_subkey) ];
+
+      [ current_cs; "Control"; "DeviceClasses"; class_guid;
+        sprintf "##?#PCI#%s#%s#%s" device_id device_subkey class_guid; "#" ],
+      [];
+
+      [ current_cs; "Services"; driver_name; "Parameters"; "Device" ],
+      [ "grant_frames", REG_DWORD 0xA_l;
+        "pvctrl_flags", REG_DWORD 0x5_l;
+        "shutdown_notification", REG_DWORD 0x1_l;
+        "use_pv_drivers", REG_DWORD 0x1c0003_l ];
+
+      [ "DriverDatabase"; "DriverPackages"; inf_full; "Configurations"; driver_inst; "Services"; driver_name; "Parameters"; "Device" ],
+      [ "dbg_print_mask", REG_DWORD 0x7_l ];
+
+  ] in
+
+  reg_import g root regedits;
+
 (* Copy the matching drivers to the driverdir; return true if any have
  * been copied.
  *)
-- 
2.6.2




More information about the Libguestfs mailing list