Martin Kletzander
2018-Nov-23 11:39 UTC
[Libguestfs] [PATCH] v2v: Add support for libosinfo metadata
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
Richard W.M. Jones
2018-Nov-23 11:53 UTC
Re: [Libguestfs] [PATCH] v2v: Add support for libosinfo metadata
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.htmlIt'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" inLooks 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. http://people.redhat.com/~rjones/virt-df/
Martin Kletzander
2018-Nov-23 13:10 UTC
Re: [Libguestfs] [PATCH] v2v: Add support for libosinfo metadata
On Fri, Nov 23, 2018 at 11:53:05AM +0000, Richard W.M. Jones wrote:>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 ... >But it is using the osinfo naming scheme. I mean the ID. Also I forgot to format the patch with notes, so attaching them now, just for completeness: This is basically just another occurrence of the osinfo "guessing" that already exists in the inspector code. If suggested, I can move it there and join those together. I tried this on few disks from virt-builder, but not on any Windows one. All worked nicely except openSuSE tumbleweed which met an error earlier than the XML creation phase. The matching code could be made shorter, but since this is my "tryout patch" for libguestfs, I'm just glad it works. I'd appreciate literally *any* comment to any part of this. I haven't find any unit tests for these kind of functions, so no tests are added. If there is a place where tests would fit nicely, feel free to let me know.>> 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? >Oh, I removed the comment i had there. osinfo does not use 0 in the version, it's just SLES 10, SLES 10.1 (for SP1), 10.2 (for SP2) and so on. But I just noticed I forgot to differentiate SLED from SLES. It should be possible based on i_product_name. I think it would make sense for libosinfo and it doesn't look like they are separate in libguestfs (on purpose). Would it also make sense to separate them here? Is it even possible? I'm not sure what the compatibility promises are. Martin