[Libguestfs] [PATCH] v2v: Add support for libosinfo metadata

Martin Kletzander
Fri, 23 Nov 2018 11:39:44 -0000

There's a standardized libosinfo namespace for libvirt domain metadata.  For
now
it supports the id of the OS only.  However that is still a very helpful feature
that is already supported in gnome-boxes and virt-manager (at least).

The discussion happened here:

  https://www.redhat.com/archives/libosinfo/2018-September/msg00003.html

So let's add the support to local and libvirt outputs.

Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
---
 v2v/create_libvirt_xml.ml  | 109 ++++++++++++++++++++++++++++++++++++-
 v2v/create_libvirt_xml.mli |   1 +
 v2v/output_libvirt.ml      |   4 +-
 v2v/output_local.ml        |   4 +-
 4 files changed, 113 insertions(+), 5 deletions(-)

diff --git a/v2v/create_libvirt_xml.ml b/v2v/create_libvirt_xml.ml
index 55e83e8bc1b9..180f3768792b 100644
--- a/v2v/create_libvirt_xml.ml
+++ b/v2v/create_libvirt_xml.ml
@@ -34,8 +34,102 @@ let find_target_disk targets { s_disk_id = id }    try
List.find (fun t -> t.target_overlay.ov_source.s_disk_id = id) targets
   with Not_found -> assert false

+let get_osinfo_id = function
+  | { i_type = "linux"; i_distro = "rhel";
+      i_major_version = major; i_minor_version = minor } ->
+    Some (sprintf "http://redhat.com/rhel/%d.%d" major minor)
+
+  | { i_type = "linux"; i_distro = "centos";
+      i_major_version = major; i_minor_version = minor } when major < 7
->
+    Some (sprintf "http://centos.org/centos/%d.%d" major minor)
+
+  | { i_type = "linux"; i_distro = "centos";
i_major_version = major } ->
+    Some (sprintf "http://centos.org/centos/%d.0" major)
+
+  | { i_type = "linux"; i_distro = "sles";
+      i_major_version = major; i_minor_version = 0 } ->
+    Some (sprintf "http://suse.com/sles/%d" major)
+
+  | { i_type = "linux"; i_distro = "sles";
+      i_major_version = major; i_minor_version = minor } ->
+    Some (sprintf "http://suse.com/sles/%d.%d" major minor)
+
+  | { i_type = "linux"; i_distro = "opensuse";
+      i_major_version = major; i_minor_version = minor } ->
+    Some (sprintf "http://opensuse.org/opensuse/%d.%d" major minor)
+
+  | { i_type = "linux"; i_distro = "debian";
i_major_version = major } ->
+    Some (sprintf "http://debian.org/debian/%d" major)
+
+  | { i_type = "linux"; i_distro = "ubuntu";
+      i_major_version = major; i_minor_version = minor } ->
+    Some (sprintf "http://ubuntu.com/ubuntu/%d.%02d" major minor)
+
+  | { i_type = "linux"; i_distro = "fedora";
i_major_version = major } ->
+    Some (sprintf "http://fedoraproject.org/fedora/%d" major)
+
+  | { i_type = "windows"; i_major_version = major; i_minor_version =
minor }
+    when major < 4 ->
+    Some (sprintf "http://microsoft.com/win/%d.%d" major minor)
+
+  | { i_type = "windows"; i_major_version = 5; i_minor_version = 1 }
->
+    Some "http://microsoft.com/win/xp"
+
+  | { i_type = "windows"; i_major_version = 5; i_minor_version = 2;
+      i_product_name = product } when String.find product "XP" >=
0 ->
+    Some "http://microsoft.com/win/xp"
+
+  | { i_type = "windows"; i_major_version = 5; i_minor_version = 2;
+      i_product_name = product } when String.find product "R2" >=
0 ->
+    Some "http://microsoft.com/win/2k3r2"
+
+  | { i_type = "windows"; i_major_version = 5; i_minor_version = 2 }
->
+    Some "http://microsoft.com/win/2k3"
+
+  | { i_type = "windows"; i_major_version = 6; i_minor_version = 0;
+      i_product_variant = "Server" } ->
+    Some "http://microsoft.com/win/2k8"
+
+  | { i_type = "windows"; i_major_version = 6; i_minor_version = 0 }
->
+    Some "http://microsoft.com/win/vista"
+
+  | { i_type = "windows"; i_major_version = 6; i_minor_version = 1;
+      i_product_variant = "Server" } ->
+    Some "http://microsoft.com/win/2k8r2"
+
+  | { i_type = "windows"; i_major_version = 6; i_minor_version = 1 }
->
+    Some "http://microsoft.com/win/7"
+
+  | { i_type = "windows"; i_major_version = 6; i_minor_version = 2;
+      i_product_variant = "Server" } ->
+    Some "http://microsoft.com/win/2k12"
+
+  | { i_type = "windows"; i_major_version = 6; i_minor_version = 2 }
->
+    Some "http://microsoft.com/win/8"
+
+  | { i_type = "windows"; i_major_version = 6; i_minor_version = 3;
+      i_product_variant = "Server" } ->
+    Some "http://microsoft.com/win/2k12r2"
+
+  | { i_type = "windows"; i_major_version = 6; i_minor_version = 3 }
->
+    Some "http://microsoft.com/win/8.1"
+
+  | { i_type = "windows"; i_major_version = 10; i_minor_version = 0;
+      i_product_variant = "Server" } ->
+    Some "http://microsoft.com/win/2k16"
+
+  | { i_type = "windows"; i_major_version = 10; i_minor_version = 0 }
->
+    Some "http://microsoft.com/win/10"
+
+  | { i_type = typ; i_distro = distro;
+      i_major_version = major; i_minor_version = minor; i_arch = arch;
+      i_product_name = product } ->
+    warning (f_"unknown guest operating system: %s %s %d.%d %s (%s)")
+      typ distro major minor arch product;
+    None
+
 let create_libvirt_xml ?pool source targets target_buses guestcaps
-                       target_features target_firmware +
target_features target_firmware inspect    (* The main body of the libvirt XML
document. *)
   let body = ref [] in

@@ -49,6 +143,19 @@ let create_libvirt_xml ?pool source targets target_buses
guestcaps
    | Some genid -> List.push_back body (e "genid" [] [PCData
genid])
   );

+
+  (match get_osinfo_id inspect with
+   | None -> ()
+   | Some osinfo_id ->
+     List.push_back_list body [
+       e "metadata" [] [
+         e "libosinfo:libosinfo" ["xmlns:libosinfo",
"http://libosinfo.org/xmlns/libvirt/domain/1.0"] [
+           e "libosinfo:os" ["id", osinfo_id] [];
+         ];
+       ];
+     ];
+  );
+
   let memory_k = source.s_memory /^ 1024L in
   List.push_back_list body [
     e "memory" ["unit", "KiB"] [PCData
(Int64.to_string memory_k)];
diff --git a/v2v/create_libvirt_xml.mli b/v2v/create_libvirt_xml.mli
index 3f883c625c8a..9a596208481a 100644
--- a/v2v/create_libvirt_xml.mli
+++ b/v2v/create_libvirt_xml.mli
@@ -22,6 +22,7 @@ val create_libvirt_xml : ?pool:string -> Types.source ->
Types.target list ->
                          Types.target_buses ->
                          Types.guestcaps -> string list ->
                          Types.target_firmware ->
+                         Types.inspect ->
                          DOM.doc
 (** [create_libvirt_xml ?pool source targets target_buses guestcaps
     target_features target_firmware] creates the final libvirt XML
diff --git a/v2v/output_libvirt.ml b/v2v/output_libvirt.ml
index 1271bdc2f5e3..9008b05079cd 100644
--- a/v2v/output_libvirt.ml
+++ b/v2v/output_libvirt.ml
@@ -143,7 +143,7 @@ class output_libvirt oc output_pool = object
        error_unless_uefi_firmware guestcaps.gcaps_arch

   method create_metadata source targets
-                         target_buses guestcaps _ target_firmware +
target_buses guestcaps inspect target_firmware      (* We copied directly into
the final pool directory.  However we
      * have to tell libvirt.
      *)
@@ -172,7 +172,7 @@ class output_libvirt oc output_pool = object
     (* Create the metadata. *)
     let doc        create_libvirt_xml ~pool:pool_name source targets
target_buses
-                         guestcaps target_features target_firmware in
+                         guestcaps target_features target_firmware inspect in

     let tmpfile, chan = Filename.open_temp_file "v2vlibvirt"
".xml" in
     DOM.doc_to_chan chan doc;
diff --git a/v2v/output_local.ml b/v2v/output_local.ml
index 2f4b4e6c9cfd..3a00ed58a72d 100644
--- a/v2v/output_local.ml
+++ b/v2v/output_local.ml
@@ -49,7 +49,7 @@ class output_local dir = object
        error_unless_uefi_firmware guestcaps.gcaps_arch

   method create_metadata source targets
-                         target_buses guestcaps _ target_firmware +
target_buses guestcaps inspect target_firmware      (* We don't know what
target features the hypervisor supports, but
      * assume a common set that libvirt supports.
      *)
@@ -61,7 +61,7 @@ class output_local dir = object

     let doc        create_libvirt_xml source targets target_buses
-                         guestcaps target_features target_firmware in
+                         guestcaps target_features target_firmware inspect in

     let name = source.s_name in
     let file = dir // name ^ ".xml" in
--
2.19.2