[Libguestfs] [v2v PATCH v2 3/3] v2v: try to get windows driver files from libosinfo

Pino Toscano ptoscano at redhat.com
Tue Jan 28 15:25:38 UTC 2020


Query libosinfo to get the list of files for drivers of Windows guests,
copying them if they are local files only. In case it is not possible
(e.g. no driver files are listed, or their location is a non-local URL,
or they do not exists), the manual filtering of the virtio-win content
is done as before.
---
 v2v/windows_virtio.ml | 78 ++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 74 insertions(+), 4 deletions(-)

diff --git a/v2v/windows_virtio.ml b/v2v/windows_virtio.ml
index 5ec7664b..1468d207 100644
--- a/v2v/windows_virtio.ml
+++ b/v2v/windows_virtio.ml
@@ -297,10 +297,11 @@ and ddb_regedits inspect drv_name drv_pciid =
  * been copied.
  *)
 and copy_drivers g inspect driverdir =
-  [] <> copy_from_virtio_win g inspect "/" driverdir
-    virtio_iso_path_matches_guest_os
-    (fun () ->
-      error (f_"root directory ‘/’ is missing from the virtio-win directory or ISO.\n\nThis should not happen and may indicate that virtio-win or virt-v2v is broken in some way.  Please report this as a bug with a full debug log."))
+  [] <> copy_from_libosinfo g inspect driverdir ||
+    [] <> copy_from_virtio_win g inspect "/" driverdir
+      virtio_iso_path_matches_guest_os
+      (fun () ->
+        error (f_"root directory ‘/’ is missing from the virtio-win directory or ISO.\n\nThis should not happen and may indicate that virtio-win or virt-v2v is broken in some way.  Please report this as a bug with a full debug log."))
 
 and copy_qemu_ga g inspect =
   copy_from_virtio_win g inspect "/" "/"
@@ -460,6 +461,75 @@ and virtio_iso_path_matches_qemu_ga path inspect =
   | ("x86_64", "RHEV-QGA64.msi") -> true
   | _ -> false
 
+(* Look up in libosinfo for the OS, and copy all the locally
+ * available files specified as drivers for that OS to the [destdir].
+ *
+ * This function does nothing in case either:
+ * - the osinfo short ID is not found in the libosinfo DB
+ * - the OS does not have any driver for the same architecture
+ * - the location of the drivers is a local directory
+ *
+ * Files that do not exist are silently skipped.
+ *
+ * Returns list of copied files.
+ *)
+and copy_from_libosinfo g inspect destdir =
+  let { i_osinfo = osinfo; i_arch = arch } = inspect in
+  try
+    let os = Libosinfo_utils.get_os_by_short_id osinfo in
+    let drivers = os#get_device_drivers () in
+    (*
+     * Filter out drivers that we cannot use:
+     * - for a different architecture
+     * - non-pre-installable ones
+     * - location is an invalid URL, or a non-local one
+     *)
+    let drivers =
+      List.filter (
+        fun { Libosinfo.architecture; location; pre_installable } ->
+          if architecture <> arch || not pre_installable then
+            false
+          else
+            try
+              (match Xml.parse_uri location with
+              | { Xml.uri_scheme = Some scheme;
+                  Xml.uri_path = Some _ } when scheme = "file" -> true
+              | _ -> false
+              )
+            with Invalid_argument _ -> false
+      ) drivers in
+    (* Sort the drivers by priority, like libosinfo does. *)
+    let drivers =
+      List.sort (
+        fun { Libosinfo.priority = prioA } { Libosinfo.priority = prioB } ->
+          compare prioB prioA
+      ) drivers in
+    (* Any driver available? *)
+    if drivers = [] then
+      raise Not_found;
+    let driver = List.hd drivers in
+    let uri = Xml.parse_uri driver.Libosinfo.location in
+    let basedir =
+      match uri.Xml.uri_path with
+      | Some p -> p
+      | None -> assert false in
+    List.filter_map (
+      fun f ->
+        let source = basedir // f in
+        if not (Sys.file_exists source) then
+          None
+        else (
+          let target_name = String.lowercase_ascii (Filename.basename f) in
+          let target = destdir ^ "/" ^ target_name in
+          debug "windows: copying guest tools bits (via libosinfo): 'host:%s' -> '%s'"
+                source target;
+
+          g#write target (read_whole_file source);
+          Some target_name
+        )
+    ) driver.Libosinfo.files
+  with Not_found -> []
+
 (* The following function is only exported for unit tests. *)
 module UNIT_TESTS = struct
   let virtio_iso_path_matches_guest_os = virtio_iso_path_matches_guest_os
-- 
2.24.1




More information about the Libguestfs mailing list