diff options
Diffstat (limited to 'src/software/lmi/software/yumdb/repository.py')
-rw-r--r-- | src/software/lmi/software/yumdb/repository.py | 202 |
1 files changed, 202 insertions, 0 deletions
diff --git a/src/software/lmi/software/yumdb/repository.py b/src/software/lmi/software/yumdb/repository.py new file mode 100644 index 0000000..758ae21 --- /dev/null +++ b/src/software/lmi/software/yumdb/repository.py @@ -0,0 +1,202 @@ +# -*- encoding: utf-8 -*- +# Software Management Providers +# +# Copyright (C) 2012-2013 Red Hat, Inc. All rights reserved. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +# +# Authors: Michal Minar <miminar@redhat.com> +# +""" +Module holding an abstraction for YUM repository. +""" + +from datetime import datetime +import logging +import yum +import yum.Errors + +# maps names of Repository properties to their corresponding property +# names in YumRepository object +PROPERTY_NAME_MAP = { + "repoid" : "id", + "base_urls" : "baseurl", + "config_file" : "repofile", + "cost" : "cost", + "enabled" : "enabled", + "gpg_check" : "gpgcheck", + "last_edit" : "repo_config_age", + "mirror_list" : "mirrorlist", + "mirror_urls" : "mirrorurls", + "name" : "name", + "pkg_dir" : "pkgdir", + "ready" : "ready", + "repo_gpg_check" : "repo_gpgcheck", + "timeout" : "timeout" +} + +def get_prop_from_yum_repo(repo, prop_name): + """ + @param prop_name is one Repository properties + @return value of property from object of YumRepository + """ + if not isinstance(repo, yum.yumRepo.YumRepository): + raise TypeError("repo must be in instance of yum.yumRepo.YumRepository") + if prop_name in PROPERTY_NAME_MAP: + val = getattr(repo, PROPERTY_NAME_MAP[prop_name]) + if prop_name == "last_edit": + val = datetime.fromtimestamp(val) + elif prop_name == "mirror_urls" and not repo.mirrorlist: + val = None + elif prop_name == "ready": + val = val() + elif prop_name in {"arch", "basearch", "releasever"}: + val = repo.yumvar[prop_name] + elif prop_name in {"revision", "last_update"}: + if repo.enabled and repo.repoXML: + md = repo.repoXML + if prop_name == "last_update": + val = datetime.fromtimestamp(md.timestamp) + elif prop_name == "revision": + val = long(md.revision) + else: + val = getattr(repo.repoXML, prop_name) + else: + val = None + elif prop_name == "pkg_count": + # this needs populated sack: ydb.repos.populateSack(repo.id) + val = len(repo.sack) + else: + raise ValueError('Unknown repository property: "%s"' % prop_name) + return val + +class Repository(object): + """ + Container for repository metadata. It represents yum repository. + It's supposed to be passed from YumWorker to YumDB client and + vice-versa. + """ + __slots__ = ( + "objid", # [int] id of python object on server process + "repoid", # [string] repository id name + # (name of config file) + + "arch", # [string] architecture of packages + "basearch", # [string] base system architecture + "base_urls", # [list] base urls as strings + #"cache", + #"cache_dir", + "name", # [string] repository descriptive name + "config_file", # [string] file path to corresponding + # config file + "cost", # [int] cost of repository + "enabled", # [boolean] whether repo is enabled + "gpg_check", # [boolean] whether to check gpg signature + #"metadata_expire", # how long are metadata considered valid + "last_edit", # datetime of last config modification + "last_update", # datetime of last change of repository + # on server + "mirror_list", # url of mirrorlist, or None + "mirror_urls", # list of urls obtained from mirrorlist or None + #"persist_dir", # + #"pkg_count", # number of packages in directory + "pkg_dir", # directory with packages + #"proxy", # boolean saying whether this is a proxy + "ready", # boolean saying, whether it's ready for use + "releasever", # version of targeted distribution + "repo_gpg_check", # [boolean] whether to check gpg + # signarues of data + "revision", + "timeout", # timeout for requests + ) + + def __init__(self, objid, repoid, arch, basearch, base_urls, + config_file, cost, enabled, gpg_check, last_edit, last_update, + name, pkg_dir, ready, releasever, repo_gpg_check, revision, + timeout, mirror_list=None, mirror_urls=None): + for arg in ('last_edit', 'last_update'): + if ( locals()[arg] is not None + and not isinstance(locals()[arg], datetime)): + raise TypeError("%s must be an instance of datetime" % arg) + if not isinstance(timeout, float): + raise TypeError("timeout must be a float") + for arg in ('cost', 'revision'): + if ( locals()[arg] is not None + and not isinstance(locals()[arg], (int, long))): + raise TypeError("%s must be an integer" % arg) + self.objid = objid + self.repoid = repoid + self.arch = arch + self.basearch = basearch + self.base_urls = list(base_urls) + self.config_file = config_file + self.cost = cost + self.enabled = bool(enabled) + self.gpg_check = bool(gpg_check) + self.last_edit = last_edit + self.last_update = last_update + self.mirror_list = "" if not mirror_list else mirror_list + self.mirror_urls = [] if not mirror_urls else list(mirror_urls) + self.name = name + #self.pkg_count = pkg_count + self.pkg_dir = pkg_dir + self.ready = bool(ready) + self.releasever = releasever + self.repo_gpg_check = bool(repo_gpg_check) + self.revision = revision + self.timeout = timeout + + def __str__(self): + return self.repoid + + def __getstate__(self): + """ + Used for serialization with pickle. + @return container content that will be serialized + """ + return dict((k, getattr(self, k)) for k in self.__slots__) + + def __setstate__(self, state): + """ + Used for deserialization with pickle. + Restores the object from serialized form. + @param state is an object created by __setstate__() method + """ + for k, value in state.items(): + setattr(self, k, value) + +def make_repository_from_db(repo): + """ + Create instance of Repository from instance of yum.yumRepo.YumRepository + @return instance of Repository + """ + if not isinstance(repo, yum.yumRepo.YumRepository): + raise TypeError("repo must be in instance of yum.yumRepo.YumRepository") + metadata = {} + for prop_name in Repository.__slots__[1:]: + try: + metadata[prop_name] = get_prop_from_yum_repo(repo, prop_name) + except yum.Errors.RepoError as exc: + # some properties can cause error (like requesting ready) + logging.getLogger(__name__).warn( + 'failed to get property "%s" of repo "%s": %s' % ( + prop_name, repo.name, exc)) + if prop_name == "ready": + metadata[prop_name] = False + continue + + res = Repository(id(repo), **metadata) + return res + |