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

Richard W.M. Jones rjones at redhat.com
Tue Apr 5 12:21:19 UTC 2016


On Tue, Apr 05, 2016 at 01:47:33PM +0200, Cédric Bosdonnat wrote:
> 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.

I didn't check this in detail, but it seems reasonable.

Rich.

>  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
> 
> _______________________________________________
> Libguestfs mailing list
> Libguestfs at redhat.com
> https://www.redhat.com/mailman/listinfo/libguestfs

-- 
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
Fedora Windows cross-compiler. Compile Windows programs, test, and
build Windows installers. Over 100 libraries supported.
http://fedoraproject.org/wiki/MinGW




More information about the Libguestfs mailing list