[Pkg-libvirt-commits] [libguestfs] 29/266: v2v: Add support for converting Windows guests.

Hilko Bengen bengen at moszumanska.debian.org
Fri Oct 3 14:41:35 UTC 2014


This is an automated email from the git hooks/post-receive script.

bengen pushed a commit to annotated tag debian/1%1.27.35-1
in repository libguestfs.

commit bcdbe6405c10ecb7374ae47eee6385be17dbd49e
Author: Richard W.M. Jones <rjones at redhat.com>
Date:   Tue Jul 8 16:33:45 2014 +0100

    v2v: Add support for converting Windows guests.
    
    This completes commit f296d34f3b30c82309b22b54bf5a2c133992bd93.
---
 run.in                 |   6 -
 v2v/Makefile.am        |  16 ++-
 v2v/convert_windows.ml | 289 +++++++++++++++++++++++++++++++++++--------------
 v2v/link.sh.in         |   2 +-
 4 files changed, 220 insertions(+), 93 deletions(-)

diff --git a/run.in b/run.in
index 1fcd795..f09b8fd 100755
--- a/run.in
+++ b/run.in
@@ -92,12 +92,6 @@ if [ -z "$XDG_CONFIG_DIRS" ]; then
     export XDG_CONFIG_DIRS
 fi
 
-# Data directory used by virt-v2v.
-if [ -z "$VIRT_TOOLS_DATA_DIR" ]; then
-    VIRT_TOOLS_DATA_DIR="$s/v2v"
-    export VIRT_TOOLS_DATA_DIR
-fi
-
 # For Perl.
 if [ -z "$PERL5LIB" ]; then
     PERL5LIB="$b/perl/blib/lib:$b/perl/blib/arch"
diff --git a/v2v/Makefile.am b/v2v/Makefile.am
index a62e191..69875fd 100644
--- a/v2v/Makefile.am
+++ b/v2v/Makefile.am
@@ -68,9 +68,20 @@ virt_v2v_CFLAGS = \
 BOBJECTS = \
 	$(top_builddir)/mllib/common_gettext.cmo \
 	$(top_builddir)/mllib/common_utils.cmo \
+	$(top_builddir)/mllib/regedit.cmo \
 	$(top_builddir)/mllib/tTY.cmo \
 	$(top_builddir)/mllib/progress.cmo \
 	$(top_builddir)/mllib/config.cmo \
+	$(top_builddir)/customize/urandom.cmx \
+	$(top_builddir)/customize/random_seed.cmx \
+	$(top_builddir)/customize/hostname.cmx \
+	$(top_builddir)/customize/timezone.cmx \
+	$(top_builddir)/customize/firstboot.cmx \
+	$(top_builddir)/customize/perl_edit.cmx \
+	$(top_builddir)/customize/crypt-c.o \
+	$(top_builddir)/customize/crypt.cmx \
+	$(top_builddir)/customize/password.cmx \
+	$(top_builddir)/customize/customize_run.cmo \
 	$(SOURCES_ML:.ml=.cmo)
 XOBJECTS = $(BOBJECTS:.cmo=.cmx)
 
@@ -82,7 +93,8 @@ OCAMLPACKAGES = \
 	-I $(top_builddir)/src/.libs \
 	-I ../gnulib/lib/.libs \
 	-I $(top_builddir)/ocaml \
-	-I $(top_builddir)/mllib
+	-I $(top_builddir)/mllib \
+	-I $(top_builddir)/customize
 if HAVE_OCAML_PKG_GETTEXT
 OCAMLPACKAGES += -package gettext-stub
 endif
@@ -150,7 +162,7 @@ depend: .depend
 
 .depend: $(wildcard $(abs_srcdir)/*.mli) $(wildcard $(abs_srcdir)/*.ml)
 	rm -f $@ $@-t
-	$(OCAMLFIND) ocamldep -I ../ocaml -I $(abs_srcdir) -I $(abs_top_builddir)/mllib $^ | \
+	$(OCAMLFIND) ocamldep -I ../ocaml -I $(abs_srcdir) -I $(abs_top_builddir)/mllib -I $(abs_top_builddir)/customize $^ | \
 	  $(SED) 's/ *$$//' | \
 	  $(SED) -e :a -e '/ *\\$$/N; s/ *\\\n */ /; ta' | \
 	  $(SED) -e 's,$(abs_srcdir)/,$(builddir)/,g' | \
diff --git a/v2v/convert_windows.ml b/v2v/convert_windows.ml
index d8df3c8..3b0f673 100644
--- a/v2v/convert_windows.ml
+++ b/v2v/convert_windows.ml
@@ -21,6 +21,8 @@ open Printf
 open Common_gettext.Gettext
 open Common_utils
 
+open Regedit
+
 open Utils
 open Types
 
@@ -44,22 +46,26 @@ let convert verbose (g : G.guestfs) inspect source =
   let virt_tools_data_dir =
     try Sys.getenv "VIRT_TOOLS_DATA_DIR"
     with Not_found -> Config.datadir // "virt-tools" in
+
   let virtio_win_dir = "/usr/share/virtio-win" in
 
-  (* Since this is a Windows guest, RHSrvAny must exist.  (Check also
-   * that it's not a dangling symlink but a real file).
-   *)
-  let rhsrvany_exe = virt_tools_data_dir // "rhsrvany.exe" in
-  (try
-    let chan = open_in rhsrvany_exe in
-    close_in chan
-   with
-     Sys_error msg ->
-       error (f_"'%s' is missing.  This file is required in order to do Windows conversions.  You can get it by building rhsrvany (https://github.com/rwmjones/rhsrvany).  Original error: %s")
-         rhsrvany_exe msg
-  );
-
-  let systemroot = g#inspect_get_windows_systemroot inspect.i_root 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 =
+    try
+      let chan = open_in rhev_apt_exe in
+      close_in chan;
+      Some rhev_apt_exe
+    with
+      Sys_error msg ->
+        warning ~prog (f_"'%s' is missing.  Unable to install RHEV-APT (RHEV guest agent).  Original error: %s")
+          rhev_apt_exe msg;
+        None in
+
+  let systemroot = g#inspect_get_windows_systemroot inspect.i_root
+  and major_version = g#inspect_get_major_version inspect.i_root
+  and minor_version = g#inspect_get_minor_version inspect.i_root
+  and arch = g#inspect_get_arch inspect.i_root in
 
   (* This is a wrapper that handles opening and closing the hive
    * properly around a function [f].  If [~write] is [true] then the
@@ -90,32 +96,6 @@ let convert verbose (g : G.guestfs) inspect source =
       let node = g#hivex_node_get_child node x in
       if node = 0L then raise Not_found;
       get_node node xs
-
-  (* Take a 7 bit ASCII string and encode it as UTF16LE. *)
-  and encode_utf16le str =
-    let len = String.length str in
-    let copy = String.make (len*2) '\000' in
-    for i = 0 to len-1 do
-      String.unsafe_set copy (i*2) (String.unsafe_get str i)
-    done;
-    copy
-
-  (* Take a UTF16LE string and decode it to UTF-8.  Actually this
-   * fails if the string is not 7 bit ASCII.  XXX Use iconv here.
-   *)
-  and decode_utf16le str =
-    let len = String.length str in
-    if len mod 2 <> 0 then
-      error (f_"decode_utf16le: Windows string does not appear to be in UTF16-LE encoding.  This could be a bug in virt-v2v.");
-    let copy = String.create (len/2) in
-    for i = 0 to (len/2)-1 do
-      let cl = String.unsafe_get str (i*2) in
-      let ch = String.unsafe_get str ((i*2)+1) in
-      if ch != '\000' || Char.code cl >= 127 then
-        error (f_"decode_utf16le: Windows UTF16-LE string contains non-7-bit characters.  This is a bug in virt-v2v, please report it.");
-      String.unsafe_set copy i cl
-    done;
-    copy
   in
 
   (*----------------------------------------------------------------------*)
@@ -135,7 +115,7 @@ let convert verbose (g : G.guestfs) inspect source =
         raise Not_found
       );
       let data = g#hivex_value_value valueh in
-      let data = decode_utf16le data in
+      let data = decode_utf16le ~prog data in
 
       (* The uninstall program will be uninst.exe.  This is a wrapper
        * around _uninst.exe which prompts the user.  As we don't want
@@ -162,6 +142,44 @@ let convert verbose (g : G.guestfs) inspect source =
   (*----------------------------------------------------------------------*)
   (* Perform the conversion of the Windows guest. *)
 
+  let rec configure_firstboot () =
+    let fb = Buffer.create 1024 in
+    bprintf fb "@echo off\n";
+
+    configure_rhev_apt fb;
+    unconfigure_xenpv fb;
+
+    (* Write the completed script to the guest. *)
+    let firstboot_script = Buffer.contents fb in
+    Firstboot.add_firstboot_script ~prog g inspect.i_root 1 firstboot_script
+
+  and configure_rhev_apt fb =
+    (* Configure RHEV-APT (the RHEV guest agent).  However if it doesn't
+     * exist just warn about it and continue.
+     *)
+    match rhev_apt_exe with
+    | None -> ()
+    | Some rhev_apt_exe ->
+      g#upload rhev_apt_exe "/rhev-apt.exe"; (* XXX *)
+
+      bprintf fb "\
+echo installing rhev-apt
+\"\\rhev-apt.exe\" /S /v /qn
+
+echo starting rhev-apt
+net start rhev-apt
+"
+
+  and unconfigure_xenpv fb =
+    match xenpv_uninst with
+    | None -> () (* nothing to be uninstalled *)
+    | Some uninst ->
+      bprintf fb "\
+echo uninstalling Xen PV driver
+\"%s\"
+" uninst
+  in
+
   let rec update_system_hive root =
     (* Update the SYSTEM hive.  When this function is called the hive has
      * already been opened as a hivex handle inside guestfs.
@@ -175,58 +193,158 @@ let convert verbose (g : G.guestfs) inspect source =
 
     if verbose then printf "current ControlSet is %s\n%!" current_cs;
 
-    let firstboot = configure_firstboot root current_cs in
-    configure_rhev_apt root firstboot;
-    (match xenpv_uninst with
-    | None -> () (* nothing to be uninstalled *)
-    | Some uninst -> unconfigure_xenpv root firstboot uninst
-    );
-    close_firstboot root firstboot;
     disable_services root current_cs;
-    let block_net_drivers = install_virtio_drivers root current_cs in
-
-    block_net_drivers
-
-  and configure_firstboot root current_cs =
-    ignore virt_tools_data_dir;
-    ()
-
-
-
-
-  and configure_rhev_apt root firstboot =
-    ()
-
-
-
-  and unconfigure_xenpv root firstboot uninst_exe =
-    ()
-
-
-
-
-
-  and close_firstboot root firstboot =
-    ()
-
-
-
-
+    install_virtio_drivers root current_cs
 
   and disable_services root current_cs =
-    ()
-
-
-
+    (* Disable miscellaneous services. *)
+    let services = get_node root [current_cs; "Services"] in
 
+    (* Disable the Processor and Intelppm services
+     * http://blogs.msdn.com/b/virtual_pc_guy/archive/2005/10/24/484461.aspx
+     *
+     * Disable the rhelscsi service (RHBZ#809273).
+     *)
+    let disable = [ "Processor"; "Intelppm"; "rhelscsi" ] in
+    List.iter (
+      fun name ->
+        let node = g#hivex_node_get_child services name in
+        if node <> 0L then (
+          (* Delete the node instead of trying to disable it.  RHBZ#737600. *)
+          g#hivex_node_delete_child node
+        )
+    ) disable
 
   and install_virtio_drivers root current_cs =
-    ignore virtio_win_dir;
-    ("XXX", "XXX")
-
+    (* Copy the virtio drivers to the guest. *)
+    let driverdir = sprintf "%s/Drivers/VirtIO" systemroot in
+    let driverdir = g#case_sensitive_path driverdir in
+    g#mkdir_p driverdir;
+
+    (* See if the drivers for this guest are available in virtio_win_dir. *)
+    let path =
+      match major_version, minor_version, arch with
+      | 5, 1, "i386" ->
+        Some (virtio_win_dir // "drivers/i386/WinXP")
+      | 5, 2, "i386" ->
+        Some (virtio_win_dir // "drivers/i386/Win2003")
+      | 5, 2, "x86_64" ->
+        Some (virtio_win_dir // "drivers/amd64/Win2003")
+      | 6, 0, "i386" ->
+        Some (virtio_win_dir // "drivers/i386/Win2008")
+      | 6, 0, "x86_64" ->
+        Some (virtio_win_dir // "drivers/amd64/Win2008")
+      | 6, 1, "i386" ->
+        Some (virtio_win_dir // "drivers/i386/Win2008R2")
+      | 6, 1, "x86_64" ->
+        Some (virtio_win_dir // "drivers/amd64/Win2008R2")
+      | 6, 3, "i386" ->
+        Some (virtio_win_dir // "drivers/i386/Win2012R2")
+      | 6, 3, "x86_64" ->
+        Some (virtio_win_dir // "drivers/amd64/Win2012R2")
+      | _, _, _ ->
+        None in
+
+    let path =
+      match path with
+      | None -> None
+      | Some path ->
+        if is_directory path then Some path else None in
+
+    match path with
+    | None ->
+      warning ~prog (f_"there are no virtio drivers available for this version of Windows (%d.%d %s).  virt-v2v looks for drivers in %s\n\nThe guest will be configured to use slower emulated devices.")
+        major_version minor_version arch virtio_win_dir;
+      ( "ide", "rtl8139" )
+
+    | Some path ->
+      (* Can we install the block driver? *)
+      let block =
+        let block_path = path // "viostor.sys" in
+        if not (Sys.file_exists block_path) then (
+          warning ~prog (f_"there is no viostor (virtio block device) driver for this version of Windows (%d.%d %s).  virt-v2v looks for this driver here: %s\n\nThe guest will be configured to use a slower emulated device.")
+            major_version minor_version arch block_path;
+          "ide"
+        )
+        else (
+          let target = sprintf "%s/system32/drivers/viostor.sys" systemroot in
+          let target = g#case_sensitive_path target in
+          g#cp block_path target;
+          add_viostor_to_critical_device_database root current_cs;
+          "virtio"
+        ) in
+
+      (* Can we install the virtio-net driver? *)
+      let net =
+        let net_path = path // "netkvm.inf" in
+        if not (Sys.file_exists net_path) then (
+          warning ~prog (f_"there is no virtio network driver for this version of Windows (%d.%d %s).  virt-v2v looks for this driver here: %s\n\nThe guest will be configured to use a slower emulated device.")
+            major_version minor_version arch net_path;
+          "rtl8139"
+        )
+        else
+          (* It will be installed at firstboot. *)
+          "virtio" in
 
+      (* Copy the drivers to the driverdir.  They will be installed at
+       * firstboot.
+       *)
+      let files = Sys.readdir path in
+      let files = Array.to_list files in
+      let files = List.map ((//) path) files in
+      List.iter (fun file -> g#upload file driverdir) files;
 
+      (block, net)
 
+  and add_viostor_to_critical_device_database root current_cs =
+    (* 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 regedits = [
+      [ current_cs; "Control"; "CriticalDeviceDatabase"; "pci#ven_1af4&dev_1001&subsys_00000000" ],
+      [ "Service", REG_SZ "viostor";
+        "ClassGUID", REG_SZ "{4D36E97B-E325-11CE-BFC1-08002BE10318}" ];
+
+      [ current_cs; "Control"; "CriticalDeviceDatabase"; "pci#ven_1af4&dev_1001&subsys_00020000" ],
+      [ "Service", REG_SZ "viostor";
+        "ClassGUID", REG_SZ "{4D36E97B-E325-11CE-BFC1-08002BE10318}" ];
+
+      [ current_cs; "Control"; "CriticalDeviceDatabase"; "pci#ven_1af4&dev_1001&subsys_00021af4" ],
+      [ "Service", REG_SZ "viostor";
+        "ClassGUID", REG_SZ "{4D36E97B-E325-11CE-BFC1-08002BE10318}" ];
+
+      [ current_cs; "Services"; "viostor" ],
+      [ "Type", REG_DWORD 0x1_l;
+        "Start", REG_DWORD 0x0_l;
+        "Group", REG_SZ "SCSI miniport";
+        "ErrorControl", REG_DWORD 0x1_l;
+        "ImagePath", REG_SZ "system32\\\\drivers\\\\viostor.sys";
+        "Tag", REG_DWORD 0x21_l ];
+
+      [ current_cs; "Services"; "viostor"; "Parameters" ],
+      [ "BusType", REG_DWORD 0x1_l ];
+
+      [ current_cs; "Services"; "viostor"; "Parameters"; "MaxTransferSize" ],
+      [ "ParamDesc", REG_SZ "Maximum Transfer Size";
+        "type", REG_SZ "enum";
+        "default", REG_SZ "0" ];
+
+      [ current_cs; "Services"; "viostor"; "Parameters"; "MaxTransferSize"; "enum" ],
+      [ "0", REG_SZ "64  KB";
+        "1", REG_SZ "128 KB";
+        "2", REG_SZ "256 KB" ];
+
+      [ current_cs; "Services"; "viostor"; "Parameters"; "PnpInterface" ],
+      [ "5", REG_DWORD 0x1_l ];
+
+      [ current_cs; "Services"; "viostor"; "Enum" ],
+      [ "0", REG_SZ "PCI\\VEN_1AF4&DEV_1001&SUBSYS_00021AF4&REV_00\\3&13c0b0c5&0&20";
+        "Count", REG_DWORD 0x1_l;
+        "NextInstance", REG_DWORD 0x1_l ];
+    ] in
+
+    reg_import g root regedits
 
   and update_software_hive root =
     (* Update the SOFTWARE hive.  When this function is called the
@@ -336,6 +454,9 @@ let convert verbose (g : G.guestfs) inspect source =
     )
   in
 
+  (* Firstboot configuration. *)
+  configure_firstboot ();
+
   (* Open the system hive and update it. *)
   let block_driver, net_driver =
     with_hive "system" ~write:true update_system_hive in
diff --git a/v2v/link.sh.in b/v2v/link.sh.in
index 9e5684b..f909015 100644
--- a/v2v/link.sh.in
+++ b/v2v/link.sh.in
@@ -19,4 +19,4 @@
 # Hack automake to link binary properly.  There is no other way to add
 # the -cclib parameter to the end of the command line.
 
-exec "$@" -linkpkg -cclib '-lutils -lncurses @LIBXML2_LIBS@ -lgnu'
+exec "$@" -linkpkg -cclib '-lutils -lncurses -lcrypt @LIBXML2_LIBS@ -lgnu'

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-libvirt/libguestfs.git



More information about the Pkg-libvirt-commits mailing list