osdict: Add toplevel OSDB as API entry point

Makes code more readable, and lazy loading simpler.
This commit is contained in:
Cole Robinson 2015-04-04 12:04:11 -04:00
parent f644b0997d
commit bd9ab2d5b5
7 changed files with 187 additions and 176 deletions

View File

@ -124,13 +124,13 @@ class TestMisc(unittest.TestCase):
"\n".join([("%s version=%s" % tup) for tup in failures])) "\n".join([("%s version=%s" % tup) for tup in failures]))
def test_libosinfo_aliases_ro(self): def test_libosinfo_aliases_ro(self):
from virtinst import osdict from virtinst import OSDB
aliases = getattr(osdict, "_aliases") aliases = getattr(OSDB, "_aliases")
if len(aliases) != 40: if len(aliases) != 40:
raise AssertionError(_("osdict._aliases changed size. It " raise AssertionError(_("OSDB._aliases changed size. It "
"should never be extended, since it is only for back " "should never be extended, since it is only for back "
"compat with pre-libosinfo osdict.")) "compat with pre-libosinfo osdict.py"))
class TestURI(unittest.TestCase): class TestURI(unittest.TestCase):

View File

@ -813,7 +813,7 @@ class vmmCreate(vmmGObjectUI):
STABLE_OS_SUPPORT or STABLE_OS_SUPPORT or
None) None)
types = virtinst.osdict.list_os(list_types=True) types = virtinst.OSDB.list_os(list_types=True)
if not filtervars: if not filtervars:
# Kind of a hack, just show linux + windows by default since # Kind of a hack, just show linux + windows by default since
# that's all 98% of people care about # that's all 98% of people care about
@ -821,7 +821,7 @@ class vmmCreate(vmmGObjectUI):
else: else:
supportl = [] supportl = []
for t in types: for t in types:
l = virtinst.osdict.list_os(typename=t.name, l = virtinst.OSDB.list_os(typename=t.name,
only_supported=True, only_supported=True,
filtervars=filtervars) filtervars=filtervars)
if l: if l:
@ -852,9 +852,9 @@ class vmmCreate(vmmGObjectUI):
None) None)
preferred = self.config.preferred_distros preferred = self.config.preferred_distros
variants = virtinst.osdict.list_os(typename=_type, variants = virtinst.OSDB.list_os(typename=_type,
sortpref=preferred) sortpref=preferred)
supportl = virtinst.osdict.list_os(typename=_type, supportl = virtinst.OSDB.list_os(typename=_type,
sortpref=preferred, sortpref=preferred,
only_supported=True, only_supported=True,
filtervars=filtervars) filtervars=filtervars)
@ -1653,7 +1653,10 @@ class vmmCreate(vmmGObjectUI):
self.addstorage.check_path_search( self.addstorage.check_path_search(
self, self.conn, path) self, self.conn, path)
res = virtinst.osdict.get_recommended_resources(variant, self.guest) res = None
osobj = virtinst.OSDB.lookup_os(variant)
if osobj:
res = osobj.get_recommended_resources(self.guest)
# Change the default values suggested to the user. # Change the default values suggested to the user.
ram_size = DEFAULT_MEM ram_size = DEFAULT_MEM
@ -2014,7 +2017,7 @@ class vmmCreate(vmmGObjectUI):
distro_type = None distro_type = None
distro_var = None distro_var = None
if variant: if variant:
osclass = virtinst.osdict.lookup_os(variant) osclass = virtinst.OSDB.lookup_os(variant)
distro_type = osclass.typename distro_type = osclass.typename
distro_var = osclass.name distro_var = osclass.name

View File

@ -37,6 +37,7 @@ stable_defaults = _cliconfig.stable_defaults
from . import util from . import util
from virtinst import support from virtinst import support
from virtinst.uri import URISplit from virtinst.uri import URISplit
from virtinst.osdict import OSDB
from virtinst.osxml import OSXML from virtinst.osxml import OSXML
from virtinst.domainfeatures import DomainFeatures from virtinst.domainfeatures import DomainFeatures

View File

@ -25,11 +25,11 @@ import tempfile
import urlgrabber import urlgrabber
from . import osdict
from . import urlfetcher from . import urlfetcher
from . import util from . import util
from .devicedisk import VirtualDisk from .devicedisk import VirtualDisk
from .installer import Installer from .installer import Installer
from .osdict import OSDB
from .storage import StoragePool, StorageVolume from .storage import StoragePool, StorageVolume
@ -502,7 +502,7 @@ class DistroInstaller(Installer):
logging.debug("Can't detect distro for media on " logging.debug("Can't detect distro for media on "
"remote connection.") "remote connection.")
else: else:
distro = osdict.lookup_os_by_media(self.location) distro = OSDB.lookup_os_by_media(self.location)
except: except:
logging.debug("Error attempting to detect distro.", exc_info=True) logging.debug("Error attempting to detect distro.", exc_info=True)

View File

@ -26,9 +26,9 @@ import libvirt
from virtcli import cliconfig from virtcli import cliconfig
from . import osdict
from . import util from . import util
from . import support from . import support
from .osdict import OSDB
from .clock import Clock from .clock import Clock
from .cpu import CPU from .cpu import CPU
from .device import VirtualDevice from .device import VirtualDevice
@ -211,9 +211,9 @@ class Guest(XMLBuilder):
############################### ###############################
def _set_os_object(self, variant): def _set_os_object(self, variant):
obj = osdict.lookup_os(variant) obj = OSDB.lookup_os(variant)
if not obj: if not obj:
obj = osdict.lookup_os("generic") obj = OSDB.lookup_os("generic")
self.__os_object = obj self.__os_object = obj
def _get_os_object(self): def _get_os_object(self):
if not self.__os_object: if not self.__os_object:
@ -226,7 +226,7 @@ class Guest(XMLBuilder):
def _set_os_variant(self, val): def _set_os_variant(self, val):
if val: if val:
val = val.lower() val = val.lower()
if osdict.lookup_os(val) is None: if OSDB.lookup_os(val) is None:
raise ValueError( raise ValueError(
_("Distro '%s' does not exist in our dictionary") % val) _("Distro '%s' does not exist in our dictionary") % val)

View File

@ -25,53 +25,9 @@ import re
from gi.repository import Libosinfo as libosinfo from gi.repository import Libosinfo as libosinfo
# This is only for back compatibility with pre-libosinfo support. ###################
# This should never change. # Sorting helpers #
_aliases = { ###################
"altlinux" : "altlinux1.0",
"debianetch" : "debian4",
"debianlenny" : "debian5",
"debiansqueeze" : "debian6",
"debianwheezy" : "debian7",
"freebsd10" : "freebsd10.0",
"freebsd6" : "freebsd6.0",
"freebsd7" : "freebsd7.0",
"freebsd8" : "freebsd8.0",
"freebsd9" : "freebsd9.0",
"mandriva2009" : "mandriva2009.0",
"mandriva2010" : "mandriva2010.0",
"mbs1" : "mbs1.0",
"msdos" : "msdos6.22",
"openbsd4" : "openbsd4.2",
"opensolaris" : "opensolaris2009.06",
"opensuse11" : "opensuse11.4",
"opensuse12" : "opensuse12.3",
"rhel4" : "rhel4.0",
"rhel5" : "rhel5.0",
"rhel6" : "rhel6.0",
"rhel7" : "rhel7.0",
"ubuntuhardy" : "ubuntu8.04",
"ubuntuintrepid" : "ubuntu8.10",
"ubuntujaunty" : "ubuntu9.04",
"ubuntukarmic" : "ubuntu9.10",
"ubuntulucid" : "ubuntu10.04",
"ubuntumaverick" : "ubuntu10.10",
"ubuntunatty" : "ubuntu11.04",
"ubuntuoneiric" : "ubuntu11.10",
"ubuntuprecise" : "ubuntu12.04",
"ubuntuquantal" : "ubuntu12.10",
"ubunturaring" : "ubuntu13.04",
"ubuntusaucy" : "ubuntu13.10",
"vista" : "winvista",
"winxp64" : "winxp",
"linux" : "generic",
"windows" : "winxp",
"solaris" : "solaris10",
"virtio26": "fedora10",
}
_allvariants = {}
def _remove_older_point_releases(distro_list): def _remove_older_point_releases(distro_list):
ret = distro_list[:] ret = distro_list[:]
@ -161,18 +117,154 @@ def _sort(tosort, sortpref=None, limit_point_releases=False):
return retlist return retlist
class _OsVariantType(object): class _OSDB(object):
"""
Entry point for the public API
"""
def __init__(self):
self.__os_loader = None
self.__all_variants = None
def __init__(self, name, label, urldistro, sortby): # This is only for back compatibility with pre-libosinfo support.
self.name = name # This should never change.
self.label = label _aliases = {
self.urldistro = urldistro "altlinux" : "altlinux1.0",
self.sortby = sortby "debianetch" : "debian4",
"debianlenny" : "debian5",
"debiansqueeze" : "debian6",
"debianwheezy" : "debian7",
"freebsd10" : "freebsd10.0",
"freebsd6" : "freebsd6.0",
"freebsd7" : "freebsd7.0",
"freebsd8" : "freebsd8.0",
"freebsd9" : "freebsd9.0",
"mandriva2009" : "mandriva2009.0",
"mandriva2010" : "mandriva2010.0",
"mbs1" : "mbs1.0",
"msdos" : "msdos6.22",
"openbsd4" : "openbsd4.2",
"opensolaris" : "opensolaris2009.06",
"opensuse11" : "opensuse11.4",
"opensuse12" : "opensuse12.3",
"rhel4" : "rhel4.0",
"rhel5" : "rhel5.0",
"rhel6" : "rhel6.0",
"rhel7" : "rhel7.0",
"ubuntuhardy" : "ubuntu8.04",
"ubuntuintrepid" : "ubuntu8.10",
"ubuntujaunty" : "ubuntu9.04",
"ubuntukarmic" : "ubuntu9.10",
"ubuntulucid" : "ubuntu10.04",
"ubuntumaverick" : "ubuntu10.10",
"ubuntunatty" : "ubuntu11.04",
"ubuntuoneiric" : "ubuntu11.10",
"ubuntuprecise" : "ubuntu12.04",
"ubuntuquantal" : "ubuntu12.10",
"ubunturaring" : "ubuntu13.04",
"ubuntusaucy" : "ubuntu13.10",
"vista" : "winvista",
"winxp64" : "winxp",
def is_type(self): "linux" : "generic",
return self.__class__ == _OsVariantType "windows" : "winxp",
"solaris" : "solaris10",
"virtio26": "fedora10",
}
#################
# Internal APIs #
#################
def _make_default_variants(self):
ret = {}
# Back compat 'types'
for name, label in [
("linux", "Linux"),
("windows", "Windows"),
("solaris", "Solaris"),
("unix", "UNIX"),
("other", "Other")]:
ret[name] = _OsVariantType(name, label, None, None)
# Generic variant
v = _OsVariant(None)
ret[v.name] = v
return ret
@property
def _os_loader(self):
if not self.__os_loader:
loader = libosinfo.Loader()
loader.process_default_path()
self.__os_loader = loader
return self.__os_loader
@property
def _all_variants(self):
if not self.__all_variants:
loader = self._os_loader
allvariants = self._make_default_variants()
db = loader.get_db()
oslist = db.get_os_list()
for os in range(oslist.get_length()):
osi = _OsVariant(oslist.get_nth(os))
allvariants[osi.name] = osi
self.__all_variants = allvariants
return self.__all_variants
###############
# Public APIs #
###############
def lookup_os(self, key):
key = self._aliases.get(key) or key
ret = self._all_variants.get(key)
if ret is None or ret.is_type():
return None
return ret
def lookup_os_by_media(self, location):
media = libosinfo.Media.create_from_location(location, None)
ret = self._os_loader.get_db().guess_os_from_media(media)
if ret and len(ret) > 0 and ret[0]:
return ret[0].get_short_id()
return None
def list_os(self, list_types=False, typename=None,
filtervars=None, only_supported=False,
**kwargs):
sortmap = {}
filtervars = filtervars or []
for key, osinfo in self._all_variants.items():
is_type = osinfo.is_type()
if list_types and not is_type:
continue
if not list_types and is_type:
continue
if typename and typename != osinfo.typename:
continue
if filtervars:
filtervars = [self.lookup_os(x).name for x in filtervars]
if osinfo.name not in filtervars:
continue
if only_supported and not osinfo.supported:
continue
sortmap[key] = osinfo
kwargs["limit_point_releases"] = only_supported
return _sort(sortmap, **kwargs)
#####################
# OsVariant classes #
#####################
def _is_os_related_to(o, related_os_list): def _is_os_related_to(o, related_os_list):
if o.get_short_id() in related_os_list: if o.get_short_id() in related_os_list:
return True return True
@ -186,6 +278,17 @@ def _is_os_related_to(o, related_os_list):
return False return False
class _OsVariantType(object):
def __init__(self, name, label, urldistro, sortby):
self.name = name
self.label = label
self.urldistro = urldistro
self.sortby = sortby
def is_type(self):
return self.__class__ == _OsVariantType
class _OsVariant(_OsVariantType): class _OsVariant(_OsVariantType):
def __init__(self, o): def __init__(self, o):
self._os = o self._os = o
@ -486,100 +589,4 @@ class _OsVariant(_OsVariantType):
return ret return ret
OSDB = _OSDB()
def _add_type(name, label, urldistro=None, sortby=None):
t = _OsVariantType(name, label, urldistro, sortby)
_allvariants[name] = t
def _add_generic_variant():
v = _OsVariant(None)
_allvariants[v.name] = v
_add_type("linux", "Linux")
_add_type("windows", "Windows")
_add_type("solaris", "Solaris")
_add_type("unix", "UNIX")
_add_type("other", "Other")
_add_generic_variant()
_os_data_loaded = False
_os_loader = None
def _get_os_loader():
global _os_loader
if _os_loader:
return _os_loader
_os_loader = libosinfo.Loader()
_os_loader.process_default_path()
return _os_loader
def _load_os_data():
global _os_data_loaded
if _os_data_loaded:
return
loader = _get_os_loader()
db = loader.get_db()
oslist = db.get_os_list()
for os in range(oslist.get_length()):
osi = _OsVariant(oslist.get_nth(os))
_allvariants[osi.name] = osi
_os_data_loaded = True
def lookup_os(key):
_load_os_data()
key = _aliases.get(key) or key
ret = _allvariants.get(key)
if ret is None or ret.is_type():
return None
return ret
def list_os(list_types=False, typename=None,
filtervars=None, only_supported=False,
**kwargs):
_load_os_data()
sortmap = {}
filtervars = filtervars or []
for key, osinfo in _allvariants.items():
is_type = osinfo.is_type()
if list_types and not is_type:
continue
if not list_types and is_type:
continue
if typename and typename != osinfo.typename:
continue
if filtervars:
filtervars = [lookup_os(x).name for x in filtervars]
if osinfo.name not in filtervars:
continue
if only_supported and not osinfo.supported:
continue
sortmap[key] = osinfo
kwargs["limit_point_releases"] = only_supported
return _sort(sortmap, **kwargs)
def get_recommended_resources(variant, guest):
_load_os_data()
v = _allvariants.get(variant)
if v is None:
return None
return v.get_recommended_resources(guest)
def lookup_os_by_media(location):
loader = _get_os_loader()
media = libosinfo.Media.create_from_location(location, None)
ret = loader.get_db().guess_os_from_media(media)
if ret and len(ret) > 0 and ret[0]:
return ret[0].get_short_id()
return None

View File

@ -32,7 +32,7 @@ import urlparse
import urlgrabber.grabber as grabber import urlgrabber.grabber as grabber
from . import osdict from .osdict import OSDB
######################################################################### #########################################################################
@ -326,7 +326,7 @@ def getDistroStore(guest, fetcher):
urldistro = None urldistro = None
if guest.os_variant: if guest.os_variant:
urldistro = osdict.lookup_os(guest.os_variant).urldistro urldistro = OSDB.lookup_os(guest.os_variant).urldistro
dist = _distroFromTreeinfo(fetcher, arch, _type) dist = _distroFromTreeinfo(fetcher, arch, _type)
if dist: if dist:
@ -447,7 +447,7 @@ class Distro(object):
self.name)) self.name))
def _check_osvariant_valid(self, os_variant): def _check_osvariant_valid(self, os_variant):
return osdict.lookup_os(os_variant) is not None return OSDB.lookup_os(os_variant) is not None
def get_osdict_info(self): def get_osdict_info(self):
""" """
@ -667,7 +667,7 @@ class FedoraDistro(RedHatDistro):
Search osdict list, find newest fedora version listed Search osdict list, find newest fedora version listed
""" """
ret = None ret = None
for osinfo in osdict.list_os(typename="linux"): for osinfo in OSDB.list_os(typename="linux"):
if osinfo.name.startswith("fedora") and "unknown" not in osinfo.name: if osinfo.name.startswith("fedora") and "unknown" not in osinfo.name:
# First fedora* occurrence should be the newest # First fedora* occurrence should be the newest
ret = osinfo.name ret = osinfo.name
@ -866,7 +866,7 @@ class SuseDistro(Distro):
def _detect_osdict_from_url(self): def _detect_osdict_from_url(self):
root = "opensuse" root = "opensuse"
oses = [n for n in osdict.list_os() if n.name.startswith(root)] oses = [n for n in OSDB.list_os() if n.name.startswith(root)]
for osobj in oses: for osobj in oses:
codename = osobj.name[len(root):] codename = osobj.name[len(root):]
@ -941,7 +941,7 @@ class DebianDistro(Distro):
def _detect_osdict_from_url(self): def _detect_osdict_from_url(self):
root = self.name.lower() root = self.name.lower()
oses = [n for n in osdict.list_os() if n.name.startswith(root)] oses = [n for n in OSDB.list_os() if n.name.startswith(root)]
if self._url_prefix == "daily": if self._url_prefix == "daily":
return oses[0].name return oses[0].name