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

Richard W.M. Jones
Fri, 23 Nov 2018 11:53:05 -0000

On Fri, Nov 23, 2018 at 12:39:44PM +0100, Martin Kletzander
wrote:
> 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

It's a shame I missed this thread because I'd probably have asked why
we're inventing yet another scheme for naming guests.  Particularly in
the libosinfo project which has already got the canonical naming
scheme!

Anyway that's water under the bridge now so ...

> 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)

SLES is duplicated?

> +  | { 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

Looks fine to me apart from the possible duplication.

Rich.

--
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
virt-df lists disk usage of guests without needing to install any
software inside the virtual machine.  Supports Linux and Windows.