1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
|
(* virt-v2v
* Copyright (C) 2020 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*)
open Std_utils
open Tools_utils
open Common_gettext.Gettext
(* Singleton DB, created on the first access. *)
let db = lazy (new Libosinfo.osinfo_db ())
(*
* Helper function to get the DB -- use it as sole way to get the DB.
*)
let get_db () =
Lazy.force db
let get_os_by_short_id os =
let os = (get_db ())#find_os_by_short_id os in
debug "libosinfo: loaded OS: %s" (os#get_id ());
os
let string_of_osinfo_device_list dev_list =
(* Turn the fields of an "osinfo_device" record into a list. *)
let listify { Libosinfo.id; vendor; vendor_id; product; product_id; name;
class_; bus_type; subsystem } =
[ id; vendor; vendor_id; product; product_id; name;
class_; bus_type; subsystem ]
(* Given a list of strings, and a list of previously known maximum widths,
* "increase" each width, if necessary, to the length of the corresponding
* string.
*)
and grow_widths = List.map2 (fun s -> max (String.length s))
in
(* Compute the maximum width for each field in "dev_list". *)
let max_widths =
List.fold_right grow_widths (List.map listify dev_list)
[ 0; 0; 0; 0; 0; 0; 0; 0; 0 ]
(* Given a list of strings and a list of field widths, format "string1 |
* string2 | ... | stringN" such that each field is right-padded to the
* corresponding width.
*)
and columnate strings widths =
String.concat " | " (List.map2 (Printf.sprintf "%-*s") widths strings)
in
(* Format "dev_list" as a table by (a) printing one "osinfo_device" record
* per line, and (b) right-padding each field of each "osinfo_device" record
* to the maximum width of that field.
*)
String.concat "\n"
(List.map (fun dev -> columnate (listify dev) max_widths) dev_list)
let string_of_osinfo_device_driver { Libosinfo.architecture; location;
pre_installable; signed; priority;
files; devices } =
Printf.sprintf "%s: [%s, %s, %s, priority %Ld]\nFiles:\n%s\nDevices:\n%s"
location architecture
(if pre_installable then "pre-installable" else "not pre-installable")
(if signed then "signed" else "unsigned")
priority
(String.concat "\n" files)
(string_of_osinfo_device_list devices)
let best_driver drivers arch =
let debug_drivers =
List.iter (fun d -> debug "Driver: %s" (string_of_osinfo_device_driver d))
(* The architecture that "inspect.i_arch" from libguestfs
* ("daemon/filearch.ml") calls "i386", the osinfo-db schema
* ("data/schema/osinfo.rng.in") calls "i686".
*)
and arch = if arch = "i386" then "i686" else arch in
debug "libosinfo drivers before filtering:";
debug_drivers drivers;
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
debug "libosinfo drivers after filtering:";
debug_drivers drivers;
let drivers =
List.sort (
fun { Libosinfo.priority = prioA } { Libosinfo.priority = prioB } ->
compare prioB prioA
) drivers in
if drivers = [] then
raise Not_found;
List.hd drivers
type os_support = {
q35 : bool;
vio10 : bool;
}
let os_support_of_osinfo_device_list =
let rec next accu left =
match accu, left with
| { q35 = true; vio10 = true }, _
| _ , [] ->
accu
| { q35; vio10 }, { Libosinfo.id } :: tail ->
let q35 = q35 || id = "http://qemu.org/chipset/x86/q35"
and vio10 = vio10 || id = "http://pcisig.com/pci/1af4/1041" in
next { q35; vio10 } tail
in
next { q35 = false; vio10 = false }
|