From e36b31db16a6d8dc33bb0b4041a93c79e1e349bc Mon Sep 17 00:00:00 2001 From: Pino Toscano Date: Wed, 20 Dec 2017 15:42:13 +0100 Subject: [PATCH 1/2] Add a per-OS get_osinfo method w/ factory Create a new get_osinfo method in the module of every OS, with a global factory method in GuestFactory: it makes it possible to associate a short ID of libosinfo OSes to each of the supported OSes in oz. Signed-off-by: Pino Toscano --- oz/Debian.py | 6 ++++++ oz/Fedora.py | 6 ++++++ oz/FedoraCore.py | 6 ++++++ oz/FreeBSD.py | 6 ++++++ oz/GuestFactory.py | 18 ++++++++++++++++++ oz/Mageia.py | 6 ++++++ oz/Mandrake.py | 6 ++++++ oz/Mandriva.py | 6 ++++++ oz/OpenSUSE.py | 6 ++++++ oz/RHEL_2_1.py | 10 ++++++++++ oz/RHEL_3.py | 11 +++++++++++ oz/RHEL_4.py | 11 +++++++++++ oz/RHEL_5.py | 11 +++++++++++ oz/RHEL_6.py | 14 ++++++++++++++ oz/RHEL_7.py | 14 ++++++++++++++ oz/RHL.py | 10 ++++++++++ oz/Ubuntu.py | 6 ++++++ oz/Windows.py | 18 ++++++++++++++++++ 18 files changed, 171 insertions(+) diff --git a/oz/Debian.py b/oz/Debian.py index 4172aab5..f739d58a 100644 --- a/oz/Debian.py +++ b/oz/Debian.py @@ -676,3 +676,9 @@ def get_supported_string(): Return supported versions as a string. """ return "Debian: " + ", ".join(sorted(version_to_config.keys())) + +def get_osinfo(distro, update): + """ + Return the libosinfo short ID. + """ + return "debian%s" % update diff --git a/oz/Fedora.py b/oz/Fedora.py index 1f9411d1..bbb5062a 100644 --- a/oz/Fedora.py +++ b/oz/Fedora.py @@ -279,3 +279,9 @@ def get_supported_string(): Return supported versions as a string. """ return "Fedora: " + ", ".join(sorted(version_to_config.keys(), key=int)) + +def get_osinfo(distro, update): + """ + Return the libosinfo short ID. + """ + return "fedora%s" % update diff --git a/oz/FedoraCore.py b/oz/FedoraCore.py index 335d0213..e57f91e3 100644 --- a/oz/FedoraCore.py +++ b/oz/FedoraCore.py @@ -90,3 +90,9 @@ def get_supported_string(): Return supported versions as a string. """ return "Fedora Core: " + ", ".join(sorted(version_to_config.keys())) + +def get_osinfo(distro, update): + """ + Return the libosinfo short ID. + """ + return "fedora%s" % update diff --git a/oz/FreeBSD.py b/oz/FreeBSD.py index 8fbd640e..48b7564c 100644 --- a/oz/FreeBSD.py +++ b/oz/FreeBSD.py @@ -126,3 +126,9 @@ def get_supported_string(): Return supported versions as a string. """ return "FreeBSD: " + ", ".join(sorted(version_to_config.keys())) + +def get_osinfo(distro, update): + """ + Return the libosinfo short ID. + """ + return "freebsd%s" % update diff --git a/oz/GuestFactory.py b/oz/GuestFactory.py index 6aececa7..7930769e 100644 --- a/oz/GuestFactory.py +++ b/oz/GuestFactory.py @@ -120,3 +120,21 @@ def distrolist(): strings.sort() print('\n'.join(strings)) + +def get_osinfo(distro, update): + """ + Function to return the appropriate libosinfo short ID for the specified + distribution, if possible (hence None can be returned as well). + The arguments are: + + distro - The distribution name. + update - The version of the specified distribution. + """ + + importname = os_dict.get(distro, None) + if importname: + # we found the matching module; import and call the get_osinfo method + module = __import__('oz.' + importname) + return getattr(module, importname).get_osinfo(distro, update) + + return None diff --git a/oz/Mageia.py b/oz/Mageia.py index 5aa47927..fa4a0105 100644 --- a/oz/Mageia.py +++ b/oz/Mageia.py @@ -569,3 +569,9 @@ def get_supported_string(): Return supported versions as a string. """ return "Mageia: " + ", ".join(sorted(version_to_config.keys())) + +def get_osinfo(distro, update): + """ + Return the libosinfo short ID. + """ + return "mageia%s" % update diff --git a/oz/Mandrake.py b/oz/Mandrake.py index c85573c7..4890430d 100644 --- a/oz/Mandrake.py +++ b/oz/Mandrake.py @@ -161,3 +161,9 @@ def get_supported_string(): Return supported versions as a string. """ return "Mandrake: " + ", ".join(sorted(version_to_config.keys(), key=float)) + +def get_osinfo(distro, update): + """ + Return the libosinfo short ID. + """ + return "mandrake%s" % update diff --git a/oz/Mandriva.py b/oz/Mandriva.py index 56239507..fed84a47 100644 --- a/oz/Mandriva.py +++ b/oz/Mandriva.py @@ -136,3 +136,9 @@ def get_supported_string(): Return supported versions as a string. """ return "Mandriva: " + ", ".join(sorted(version_to_config.keys())) + +def get_osinfo(distro, update): + """ + Return the libosinfo short ID. + """ + return "mandriva%s" % update diff --git a/oz/OpenSUSE.py b/oz/OpenSUSE.py index ae4c3fad..2479a4cd 100644 --- a/oz/OpenSUSE.py +++ b/oz/OpenSUSE.py @@ -525,3 +525,9 @@ def get_supported_string(): Return supported versions as a string. """ return "OpenSUSE: " + ", ".join(sorted(version_to_config.keys())) + +def get_osinfo(distro, update): + """ + Return the libosinfo short ID. + """ + return "opensuse%s" % update diff --git a/oz/RHEL_2_1.py b/oz/RHEL_2_1.py index 08613513..15eac1c1 100644 --- a/oz/RHEL_2_1.py +++ b/oz/RHEL_2_1.py @@ -55,3 +55,13 @@ def get_supported_string(): Return supported versions as a string. """ return "RHEL 2.1: " + ", ".join(versions) + +def get_osinfo(distro, update): + """ + Return the libosinfo short ID. + """ + if update == 'GOLD': + return "rhel2.1" + if update[0] == 'U': + return "rhel2.1.%s" % update[1:] + return None diff --git a/oz/RHEL_3.py b/oz/RHEL_3.py index eff22a92..61a14dbb 100644 --- a/oz/RHEL_3.py +++ b/oz/RHEL_3.py @@ -111,3 +111,14 @@ def get_supported_string(): Return supported versions as a string. """ return "RHEL/CentOS 3: " + ", ".join(versions) + +def get_osinfo(distro, update): + """ + Return the libosinfo short ID. + """ + if distro == "RHEL-3": + if update == 'GOLD': + return "rhel3" + if update[0] == 'U': + return "rhel3.%s" % update[1:] + return None diff --git a/oz/RHEL_4.py b/oz/RHEL_4.py index 309bed77..f79859f9 100644 --- a/oz/RHEL_4.py +++ b/oz/RHEL_4.py @@ -137,3 +137,14 @@ def get_supported_string(): Return supported versions as a string. """ return "RHEL/CentOS/Scientific Linux 4: " + ", ".join(sorted(version_to_config.keys())) + +def get_osinfo(distro, update): + """ + Return the libosinfo short ID. + """ + if distro == "RHEL-4": + if update == 'GOLD': + return "rhel4.0" + if update[0] == 'U': + return "rhel4.%s" % update[1:] + return None diff --git a/oz/RHEL_5.py b/oz/RHEL_5.py index 9002b96c..fefe1d63 100644 --- a/oz/RHEL_5.py +++ b/oz/RHEL_5.py @@ -148,3 +148,14 @@ def get_supported_string(): Return supported versions as a string. """ return "RHEL/OL/CentOS/Scientific Linux{,CERN} 5: " + ", ".join(sorted(version_to_config.keys())) + +def get_osinfo(distro, update): + """ + Return the libosinfo short ID. + """ + if distro == "RHEL-5": + if update == 'GOLD': + return "rhel5.0" + if update[0] == 'U': + return "rhel5.%s" % update[1:] + return None diff --git a/oz/RHEL_6.py b/oz/RHEL_6.py index aa254458..276a231e 100644 --- a/oz/RHEL_6.py +++ b/oz/RHEL_6.py @@ -73,3 +73,17 @@ def get_supported_string(): Return supported versions as a string. """ return "RHEL/OL/CentOS/Scientific Linux{,CERN} 6" + +def get_osinfo(distro, update): + """ + Return the libosinfo short ID. + """ + if update.isdigit(): + verstring = "6.%s" % update + else: + verstring = "6.0" + if distro == "RHEL-6": + return "rhel%s" % verstring + if distro == "CentOS-6": + return "centos%s" % verstring + return None diff --git a/oz/RHEL_7.py b/oz/RHEL_7.py index 70623221..ee5cb914 100644 --- a/oz/RHEL_7.py +++ b/oz/RHEL_7.py @@ -77,3 +77,17 @@ def get_supported_string(): Return supported versions as a string. """ return "RHEL 7" + +def get_osinfo(distro, update): + """ + Return the libosinfo short ID. + """ + if distro == "RHEL-7": + if update.isdigit(): + verstring = "7.%s" % update + else: + verstring = "7.0" + return "rhel%s" % verstring + if distro == "CentOS-7": + return "centos7.0" + return None diff --git a/oz/RHL.py b/oz/RHL.py index 4bd65193..f6034ed8 100644 --- a/oz/RHL.py +++ b/oz/RHL.py @@ -114,3 +114,13 @@ def get_supported_string(): Return supported versions as a string. """ return "RHL: 7.0, 7.1, 7.2, 7.3, 8, 9" + +def get_osinfo(distro, update): + """ + Return the libosinfo short ID. + """ + if update == "8": + return "rhl8.0" + if update == "7.0": + return "rhl7" + return "rhl%s" % update diff --git a/oz/Ubuntu.py b/oz/Ubuntu.py index 202048b3..5c2cb2e8 100644 --- a/oz/Ubuntu.py +++ b/oz/Ubuntu.py @@ -1231,3 +1231,9 @@ def get_supported_string(): Return supported versions as a string. """ return "Ubuntu: " + ", ".join(reversed(version_to_config.keys())) + +def get_osinfo(distro, update): + """ + Return the libosinfo short ID. + """ + return "ubuntu%s" % '.'.join(update.split('.')[:2]) diff --git a/oz/Windows.py b/oz/Windows.py index 78464ed9..4c69bfac 100644 --- a/oz/Windows.py +++ b/oz/Windows.py @@ -335,3 +335,21 @@ def get_supported_string(): Return supported versions as a string. """ return "Windows: 2000, XP, 2003, 7, 2008, 2012, 8, 8.1, 2016, 10" + +def get_osinfo(distro, update): + """ + Return the libosinfo short ID. + """ + winids = { + "2000": "win2k", + "XP": "winxp", + "2003": "win2k3", + "2008": "win2k8", + "7": "win7", + "2012": "win2k12", + "8": "win8", + "8.1": "win8.1", + "2016": "win2k16", + "10": "win10", + } + return winids.get(update) From 4a51fe6637f4f8e8791f3173d6c344d24a17b078 Mon Sep 17 00:00:00 2001 From: Pino Toscano Date: Wed, 20 Dec 2017 16:21:42 +0100 Subject: [PATCH 2/2] Optionally use libosinfo for OSes URLs Try to use libosinfo (if available) to get the URLs of install trees and ISOs of the supported OSes, using a libosinfo short ID provided by all the OS classes. Add and child tags of to override (or set) the short ID, and its libosinfo variant. This makes the and child tags of optional, as they can be determined automatically from libosinfo, at least from the majority of cases. Signed-off-by: Pino Toscano --- oz/TDL.py | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- oz/tdl.rng | 26 +++++++++++++---- 2 files changed, 102 insertions(+), 8 deletions(-) diff --git a/oz/TDL.py b/oz/TDL.py index f18c6988..7ec4326a 100644 --- a/oz/TDL.py +++ b/oz/TDL.py @@ -31,6 +31,13 @@ import StringIO except ImportError: from io import StringIO +try: + import gi + gi.require_version('Libosinfo', '1.0') + from gi.repository import Libosinfo as libosinfo + libosinfo_available = True +except ImportError: + libosinfo_available = False import lxml.etree @@ -96,6 +103,27 @@ def data_from_type(name, contenttype, content): return out +def _osinfo_os_from_short_id(short_id): + """ + Function to get the libosinfo OS from the short ID specified as argument. + The list of available libosinfo OSes is cached. + """ + if not _osinfo_os_from_short_id.oses: + loader = libosinfo.Loader() + loader.process_default_path() + db = loader.get_db() + _osinfo_os_from_short_id.oses = db.get_os_list() + f = libosinfo.Filter() + f.add_constraint("short-id", short_id) + elems = _osinfo_os_from_short_id.oses.new_filtered(f).get_elements() + num_elems = len(elems) + if num_elems == 0: + raise oz.OzException.OzException("osinfo OS for short ID '%s' not found" % (short_id)) + elif num_elems > 1: + raise oz.OzException.OzException("More than 1 osinfo OS for short ID '%s' found (%d found)" % (short_id, num_elems)) + return elems[0] +_osinfo_os_from_short_id.oses = None + class Repository(object): """ Class that represents a single repository to be used for installing @@ -213,6 +241,14 @@ def __init__(self, xmlstring, rootpw_required=False): optional=True) # key is not required, so it is not fatal if it is None + self.osinfo_id = _xml_get_value(self.doc, '/template/os/osinfo', + 'osinfo-db short ID', optional=True) + self.osinfo_variant = _xml_get_value(self.doc, '/template/os/variant', + 'osinfo-db variant', optional=True) + if not self.osinfo_id: + self.osinfo_id = oz.GuestFactory.get_osinfo(self.distro, self.update) + # osinfo and variant are not required, so it is not fatal if they are None + self.description = _xml_get_value(self.doc, '/template/description', 'description', optional=True) # description is not required, so it is not fatal if it is None @@ -235,10 +271,33 @@ def __init__(self, xmlstring, rootpw_required=False): if self.installtype == "url": self.url = _xml_get_value(self.doc, '/template/os/install/url', - 'OS install URL') + 'OS install URL', + optional=libosinfo_available) + # if self.url is none, it means libosinfo is available + if not self.url: + if not self.osinfo_id: + raise oz.OzException.OzException("Missing ") + osos = _osinfo_os_from_short_id(self.osinfo_id) + osfilter = libosinfo.Filter() + osfilter.add_constraint('architecture', self.arch) + if self.osinfo_variant: + osfilter.add_constraint('variant', self.osinfo_variant) + tree_list = osos.get_tree_list() + trees = tree_list.new_filtered(osfilter).get_elements() + num_trees = len(trees) + if num_trees == 0: + raise oz.OzException.OzException("osinfo OS '%s' has no install tree" % (self.osinfo_id)) + elif num_trees > 1: + raise oz.OzException.OzException("More than 1 install tree for osinfo OS '%s' found (%d found)" % (self.osinfo_id, num_trees)) + tree = trees[0] + url = tree.get_url() + if not url: + raise oz.OzException.OzException("osinfo OS '%s' has no URL for the install tree" % (self.osinfo_id)) + self.url = url elif self.installtype == "iso": self.iso = _xml_get_value(self.doc, '/template/os/install/iso', - 'OS install ISO') + 'OS install ISO', + optional=libosinfo_available) self.iso_md5_url = _xml_get_value(self.doc, '/template/os/install/md5sum', 'OS install ISO MD5SUM', @@ -255,6 +314,27 @@ def __init__(self, xmlstring, rootpw_required=False): # if multiple are if (self.iso_md5_url and self.iso_sha1_url) or (self.iso_md5_url and self.iso_sha256_url) or (self.iso_sha1_url and self.iso_sha256_url): raise oz.OzException.OzException("Only one of , , and can be specified") + # if self.iso is none, it means libosinfo is available + if not self.iso: + if not self.osinfo_id: + raise oz.OzException.OzException("Missing ") + osos = _osinfo_os_from_short_id(self.osinfo_id) + osfilter = libosinfo.Filter() + osfilter.add_constraint('architecture', self.arch) + if self.osinfo_variant: + osfilter.add_constraint('variant', self.osinfo_variant) + media_list = osos.get_media_list() + media = media_list.new_filtered(osfilter).get_elements() + num_media = len(media) + if num_media == 0: + raise oz.OzException.OzException("osinfo OS '%s' has no install media" % (self.osinfo_id)) + elif num_media > 1: + raise oz.OzException.OzException("More than 1 install media for osinfo OS '%s' found (%d found)" % (self.osinfo_id, num_media)) + medium = media[0] + url = medium.get_url() + if not url: + raise oz.OzException.OzException("osinfo OS '%s' has no URL for the install media" % (self.osinfo_id)) + self.iso = url else: raise oz.OzException.OzException("Unknown install type " + self.installtype + " in TDL") diff --git a/oz/tdl.rng b/oz/tdl.rng index dc29c9ac..7487e9e9 100644 --- a/oz/tdl.rng +++ b/oz/tdl.rng @@ -89,6 +89,16 @@ + + + + + + + + + + @@ -228,9 +238,11 @@ url - - - + + + + + @@ -238,9 +250,11 @@ iso - - - + + + + +