From 0da4208c47162f7e48d98888b2256be378c86030 Mon Sep 17 00:00:00 2001 From: Sol Jerome Date: Tue, 4 Nov 2014 11:32:19 -0600 Subject: Yum.py: Fix traceback when arch missing Sometimes repositories may not contain packages for a specific architecture group. This handles that case gracefully instead of causing a traceback and failing to bind all Package entries. Signed-off-by: Sol Jerome --- src/lib/Bcfg2/Server/Plugins/Packages/Yum.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'src/lib/Bcfg2/Server/Plugins/Packages') diff --git a/src/lib/Bcfg2/Server/Plugins/Packages/Yum.py b/src/lib/Bcfg2/Server/Plugins/Packages/Yum.py index 6139a28b5..4ee9cce52 100644 --- a/src/lib/Bcfg2/Server/Plugins/Packages/Yum.py +++ b/src/lib/Bcfg2/Server/Plugins/Packages/Yum.py @@ -1287,10 +1287,13 @@ class YumSource(Source): arch = [a for a in self.arches if a in metadata.groups] if not arch: return False - return ((package in self.packages['global'] or - package in self.packages[arch[0]]) and - package not in self.blacklist and - (len(self.whitelist) == 0 or package in self.whitelist)) + try: + return ((package in self.packages['global'] or + package in self.packages[arch[0]]) and + package not in self.blacklist and + (len(self.whitelist) == 0 or package in self.whitelist)) + except KeyError: + return False is_package.__doc__ = Source.is_package.__doc__ def get_vpkgs(self, metadata): -- cgit v1.2.3-1-g7c22 From 7d6032e82ea26baf82c64435925d6991d812e768 Mon Sep 17 00:00:00 2001 From: Alexander Sulfrian Date: Wed, 14 Jan 2015 23:35:22 +0100 Subject: Plugins/Packages: fix initialization of YumSource During __init__ of the parent class get_repo_name is called. That needs fields (pump_id) that are defined later in the __init__ of YumSource. We introduce the new function _init_attributes to parse all attributes out of the tag before calling any other functions. --- src/lib/Bcfg2/Server/Plugins/Packages/Source.py | 134 ++++++++++++++---------- src/lib/Bcfg2/Server/Plugins/Packages/Yum.py | 7 +- 2 files changed, 81 insertions(+), 60 deletions(-) (limited to 'src/lib/Bcfg2/Server/Plugins/Packages') diff --git a/src/lib/Bcfg2/Server/Plugins/Packages/Source.py b/src/lib/Bcfg2/Server/Plugins/Packages/Source.py index 30cdd543f..c09a9988b 100644 --- a/src/lib/Bcfg2/Server/Plugins/Packages/Source.py +++ b/src/lib/Bcfg2/Server/Plugins/Packages/Source.py @@ -143,6 +143,83 @@ class Source(Bcfg2.Server.Plugin.Debuggable): # pylint: disable=R0902 #: source self.essentialpkgs = set() + self._init_attributes(basepath, xsource, setup) + + #: A set of all package names in this source. This will not + #: necessarily be populated, particularly by backends that + #: reimplement large portions of + #: :class:`Bcfg2.Server.Plugins.Packages.Collection.Collection` + self.pkgnames = set() + + #: A dict of ```` -> ````. + #: This will not necessarily be populated, particularly by + #: backends that reimplement large portions of + #: :class:`Bcfg2.Server.Plugins.Packages.Collection.Collection` + self.deps = dict() + + #: A dict of ```` -> ````. This will not necessarily be populated, + #: particularly by backends that reimplement large portions of + #: :class:`Bcfg2.Server.Plugins.Packages.Collection.Collection` + self.provides = dict() + + #: The file (or directory) used for this source's cache data + self.cachefile = os.path.join(self.basepath, + "cache-%s" % self.cachekey) + if not self.rawurl: + baseurl = self.url + "%(version)s/%(component)s/%(arch)s/" + else: + baseurl = self.rawurl + + #: A list of dicts, each of which describes the URL to one + #: repository contained in this source. Each dict contains + #: the following keys: + #: + #: * ``version``: The version of the repo (``None`` for + #: ``rawurl`` repos) + #: * ``component``: The component use to form this URL + #: (``None`` for ``rawurl`` repos) + #: * ``arch``: The architecture of this repo + #: * ``baseurl``: Either the ``rawurl`` attribute, or the + #: format string built from the ``url`` attribute + #: * ``url``: The actual URL to the repository + self.url_map = [] + for arch in self.arches: + if self.url: + usettings = [dict(version=self.version, component=comp, + arch=arch, debsrc=self.debsrc) + for comp in self.components] + else: # rawurl given + usettings = [dict(version=self.version, component=None, + arch=arch, debsrc=self.debsrc)] + + for setting in usettings: + if not self.rawurl: + setting['baseurl'] = self.url + else: + setting['baseurl'] = self.rawurl + setting['url'] = baseurl % setting + setting['name'] = self.get_repo_name(setting) + self.url_map.extend(usettings) + + def _init_attributes(self, basepath, xsource, setup): + """ + This functions evaluates the Source tag and parses all + attributes. Override this function in a sub class to + parse specific attributes. Do not use ``__init__`` because + ``Source.__init__`` may call other functions that already + need this specific fields. This functions is called before + any other function. + + :param basepath: The base filesystem path under which cache + data for this source should be stored + :type basepath: string + :param xsource: The XML tag that describes this source + :type source: lxml.etree._Element + :param setup: A Bcfg2 options dict + :type setup: dict + """ + #: A list of the text of all 'Component' attributes of this #: source from XML self.components = [item.text for item in xsource.findall('Component')] @@ -241,63 +318,6 @@ class Source(Bcfg2.Server.Plugin.Debuggable): # pylint: disable=R0902 self.conditions.append(lambda m, el=el: el.get("name") == m.hostname) - #: A set of all package names in this source. This will not - #: necessarily be populated, particularly by backends that - #: reimplement large portions of - #: :class:`Bcfg2.Server.Plugins.Packages.Collection.Collection` - self.pkgnames = set() - - #: A dict of ```` -> ````. - #: This will not necessarily be populated, particularly by - #: backends that reimplement large portions of - #: :class:`Bcfg2.Server.Plugins.Packages.Collection.Collection` - self.deps = dict() - - #: A dict of ```` -> ````. This will not necessarily be populated, - #: particularly by backends that reimplement large portions of - #: :class:`Bcfg2.Server.Plugins.Packages.Collection.Collection` - self.provides = dict() - - #: The file (or directory) used for this source's cache data - self.cachefile = os.path.join(self.basepath, - "cache-%s" % self.cachekey) - if not self.rawurl: - baseurl = self.url + "%(version)s/%(component)s/%(arch)s/" - else: - baseurl = self.rawurl - - #: A list of dicts, each of which describes the URL to one - #: repository contained in this source. Each dict contains - #: the following keys: - #: - #: * ``version``: The version of the repo (``None`` for - #: ``rawurl`` repos) - #: * ``component``: The component use to form this URL - #: (``None`` for ``rawurl`` repos) - #: * ``arch``: The architecture of this repo - #: * ``baseurl``: Either the ``rawurl`` attribute, or the - #: format string built from the ``url`` attribute - #: * ``url``: The actual URL to the repository - self.url_map = [] - for arch in self.arches: - if self.url: - usettings = [dict(version=self.version, component=comp, - arch=arch, debsrc=self.debsrc) - for comp in self.components] - else: # rawurl given - usettings = [dict(version=self.version, component=None, - arch=arch, debsrc=self.debsrc)] - - for setting in usettings: - if not self.rawurl: - setting['baseurl'] = self.url - else: - setting['baseurl'] = self.rawurl - setting['url'] = baseurl % setting - setting['name'] = self.get_repo_name(setting) - self.url_map.extend(usettings) - @property def cachekey(self): """ A unique key for this source that will be used to generate diff --git a/src/lib/Bcfg2/Server/Plugins/Packages/Yum.py b/src/lib/Bcfg2/Server/Plugins/Packages/Yum.py index 6139a28b5..ae8ac5d6f 100644 --- a/src/lib/Bcfg2/Server/Plugins/Packages/Yum.py +++ b/src/lib/Bcfg2/Server/Plugins/Packages/Yum.py @@ -1028,8 +1028,9 @@ class YumSource(Source): #: YumSource sets the ``type`` on Package entries to "yum" ptype = 'yum' - def __init__(self, basepath, xsource, setup): - Source.__init__(self, basepath, xsource, setup) + def _init_attributes(self, basepath, xsource, setup): + Source._init_attributes(self, basepath, xsource, setup) + self.pulp_id = None if HAS_PULP and xsource.get("pulp_id"): self.pulp_id = xsource.get("pulp_id") @@ -1071,7 +1072,7 @@ class YumSource(Source): self.needed_paths = set() self.file_to_arch = dict() self.yumgroups = dict() - __init__.__doc__ = Source.__init__.__doc__ + _init_attributes.__doc__ = Source._init_attributes.__doc__ @property def use_yum(self): -- cgit v1.2.3-1-g7c22 From d2a52e47c867f8f5864781f200bed4d0adf373b3 Mon Sep 17 00:00:00 2001 From: Alexander Sulfrian Date: Fri, 23 Jan 2015 17:44:20 +0100 Subject: Plugins/Packages: all attributes should be defined in __init__ --- src/lib/Bcfg2/Server/Plugins/Packages/Source.py | 117 ++++++++++++++---------- src/lib/Bcfg2/Server/Plugins/Packages/Yum.py | 17 +++- 2 files changed, 81 insertions(+), 53 deletions(-) (limited to 'src/lib/Bcfg2/Server/Plugins/Packages') diff --git a/src/lib/Bcfg2/Server/Plugins/Packages/Source.py b/src/lib/Bcfg2/Server/Plugins/Packages/Source.py index c09a9988b..cf26c982f 100644 --- a/src/lib/Bcfg2/Server/Plugins/Packages/Source.py +++ b/src/lib/Bcfg2/Server/Plugins/Packages/Source.py @@ -143,6 +143,75 @@ class Source(Bcfg2.Server.Plugin.Debuggable): # pylint: disable=R0902 #: source self.essentialpkgs = set() + #: A list of the text of all 'Component' attributes of this + #: source from XML + self.components = [] + + #: A list of the arches supported by this source + self.arches = [] + + #: A list of the the names of packages that are blacklisted + #: from this source + self.blacklist = [] + + #: A list of the the names of packages that are whitelisted in + #: this source + self.whitelist = [] + + #: Whether or not to include deb-src lines in the generated APT + #: configuration + self.debsrc = False + + #: A dict of repository options that will be included in the + #: configuration generated on the server side (if such is + #: applicable; most backends do not generate any sort of + #: repository configuration on the Bcfg2 server) + self.server_options = dict() + + #: A dict of repository options that will be included in the + #: configuration generated for the client (if that is + #: supported by the backend) + self.client_options = dict() + + #: A list of URLs to GPG keys that apply to this source + self.gpgkeys = [] + + #: Whether or not to include essential packages from this source + self.essential = True + + #: Whether or not to include recommended packages from this source + self.recommended = False + + #: The "rawurl" attribute from :attr:`xsource`, if applicable. + #: A trailing slash is automatically appended to this if there + #: wasn't one already present. + self.rawurl = None + + #: The "url" attribute from :attr:`xsource`, if applicable. A + #: trailing slash is automatically appended to this if there + #: wasn't one already present. + self.url = None + + #: The "version" attribute from :attr:`xsource` + self.version = None + + #: The "name" attribute from :attr:`xsource` + self.name = None + + #: A list of predicates that are used to determine if this + #: source applies to a given + #: :class:`Bcfg2.Server.Plugins.Metadata.ClientMetadata` + #: object. + self.conditions = [] + + #: Formerly, :ref:`server-plugins-generators-packages` only + #: supported applying package sources to groups; that is, they + #: could not be assigned by more complicated logic like + #: per-client repositories and group or client negation. This + #: attribute attempts to provide for some limited backwards + #: compat with older code that relies on this. + self.groups = [] + self._init_attributes(basepath, xsource, setup) #: A set of all package names in this source. This will not @@ -220,35 +289,12 @@ class Source(Bcfg2.Server.Plugin.Debuggable): # pylint: disable=R0902 :type setup: dict """ - #: A list of the text of all 'Component' attributes of this - #: source from XML self.components = [item.text for item in xsource.findall('Component')] - - #: A list of the arches supported by this source self.arches = [item.text for item in xsource.findall('Arch')] - - #: A list of the the names of packages that are blacklisted - #: from this source self.blacklist = [item.text for item in xsource.findall('Blacklist')] - - #: A list of the the names of packages that are whitelisted in - #: this source self.whitelist = [item.text for item in xsource.findall('Whitelist')] - - #: Whether or not to include deb-src lines in the generated APT - #: configuration self.debsrc = xsource.get('debsrc', 'false') == 'true' - #: A dict of repository options that will be included in the - #: configuration generated on the server side (if such is - #: applicable; most backends do not generate any sort of - #: repository configuration on the Bcfg2 server) - self.server_options = dict() - - #: A dict of repository options that will be included in the - #: configuration generated for the client (if that is - #: supported by the backend) - self.client_options = dict() opts = xsource.findall("Options") for el in opts: repoopts = dict([(k, v) @@ -259,48 +305,23 @@ class Source(Bcfg2.Server.Plugin.Debuggable): # pylint: disable=R0902 if el.get("serveronly", "false").lower() == "false": self.client_options.update(repoopts) - #: A list of URLs to GPG keys that apply to this source self.gpgkeys = [el.text for el in xsource.findall("GPGKey")] - #: Whether or not to include essential packages from this source self.essential = xsource.get('essential', 'true').lower() == 'true' - - #: Whether or not to include recommended packages from this source self.recommended = xsource.get('recommended', 'false').lower() == 'true' - #: The "rawurl" attribute from :attr:`xsource`, if applicable. - #: A trailing slash is automatically appended to this if there - #: wasn't one already present. self.rawurl = xsource.get('rawurl', '') if self.rawurl and not self.rawurl.endswith("/"): self.rawurl += "/" - #: The "url" attribute from :attr:`xsource`, if applicable. A - #: trailing slash is automatically appended to this if there - #: wasn't one already present. self.url = xsource.get('url', '') if self.url and not self.url.endswith("/"): self.url += "/" - #: The "version" attribute from :attr:`xsource` self.version = xsource.get('version', '') - - #: The "name" attribute from :attr:`xsource` self.name = xsource.get('name', None) - #: A list of predicates that are used to determine if this - #: source applies to a given - #: :class:`Bcfg2.Server.Plugins.Metadata.ClientMetadata` - #: object. - self.conditions = [] - #: Formerly, :ref:`server-plugins-generators-packages` only - #: supported applying package sources to groups; that is, they - #: could not be assigned by more complicated logic like - #: per-client repositories and group or client negation. This - #: attribute attempts to provide for some limited backwards - #: compat with older code that relies on this. - self.groups = [] for el in xsource.iterancestors(): if el.tag == "Group": if el.get("negate", "false").lower() == "true": diff --git a/src/lib/Bcfg2/Server/Plugins/Packages/Yum.py b/src/lib/Bcfg2/Server/Plugins/Packages/Yum.py index ae8ac5d6f..6669d3066 100644 --- a/src/lib/Bcfg2/Server/Plugins/Packages/Yum.py +++ b/src/lib/Bcfg2/Server/Plugins/Packages/Yum.py @@ -1028,10 +1028,21 @@ class YumSource(Source): #: YumSource sets the ``type`` on Package entries to "yum" ptype = 'yum' + def __init__(self, basepath, xsource, setup): + self.filemap = dict() + self.file_to_arch = dict() + self.needed_paths = set() + self.packages = dict() + self.yumgroups = dict() + self.pulp_id = None + self.repo = None + + Source.__init__(self, basepath, xsource, setup) + __init__.__doc__ = Source.__init__.__doc__ + def _init_attributes(self, basepath, xsource, setup): Source._init_attributes(self, basepath, xsource, setup) - self.pulp_id = None if HAS_PULP and xsource.get("pulp_id"): self.pulp_id = xsource.get("pulp_id") @@ -1064,14 +1075,10 @@ class YumSource(Source): self.repo['relative_path']) self.arches = [self.repo['arch']] - self.packages = dict() self.deps = dict([('global', dict())]) self.provides = dict([('global', dict())]) self.filemap = dict([(x, dict()) for x in ['global'] + self.arches]) - self.needed_paths = set() - self.file_to_arch = dict() - self.yumgroups = dict() _init_attributes.__doc__ = Source._init_attributes.__doc__ @property -- cgit v1.2.3-1-g7c22 From eafcb0ad931c5ae2d34e564c811a8c4cc0ee6278 Mon Sep 17 00:00:00 2001 From: Alexander Sulfrian Date: Fri, 23 Jan 2015 17:57:16 +0100 Subject: Plugins/Packages/Source: Remove unused arguments of _init_attributes --- src/lib/Bcfg2/Server/Plugins/Packages/Source.py | 9 ++------- src/lib/Bcfg2/Server/Plugins/Packages/Yum.py | 4 ++-- 2 files changed, 4 insertions(+), 9 deletions(-) (limited to 'src/lib/Bcfg2/Server/Plugins/Packages') diff --git a/src/lib/Bcfg2/Server/Plugins/Packages/Source.py b/src/lib/Bcfg2/Server/Plugins/Packages/Source.py index cf26c982f..6c5b61742 100644 --- a/src/lib/Bcfg2/Server/Plugins/Packages/Source.py +++ b/src/lib/Bcfg2/Server/Plugins/Packages/Source.py @@ -212,7 +212,7 @@ class Source(Bcfg2.Server.Plugin.Debuggable): # pylint: disable=R0902 #: compat with older code that relies on this. self.groups = [] - self._init_attributes(basepath, xsource, setup) + self._init_attributes(xsource) #: A set of all package names in this source. This will not #: necessarily be populated, particularly by backends that @@ -271,7 +271,7 @@ class Source(Bcfg2.Server.Plugin.Debuggable): # pylint: disable=R0902 setting['name'] = self.get_repo_name(setting) self.url_map.extend(usettings) - def _init_attributes(self, basepath, xsource, setup): + def _init_attributes(self, xsource): """ This functions evaluates the Source tag and parses all attributes. Override this function in a sub class to @@ -280,13 +280,8 @@ class Source(Bcfg2.Server.Plugin.Debuggable): # pylint: disable=R0902 need this specific fields. This functions is called before any other function. - :param basepath: The base filesystem path under which cache - data for this source should be stored - :type basepath: string :param xsource: The XML tag that describes this source :type source: lxml.etree._Element - :param setup: A Bcfg2 options dict - :type setup: dict """ self.components = [item.text for item in xsource.findall('Component')] diff --git a/src/lib/Bcfg2/Server/Plugins/Packages/Yum.py b/src/lib/Bcfg2/Server/Plugins/Packages/Yum.py index 6669d3066..20b0e103d 100644 --- a/src/lib/Bcfg2/Server/Plugins/Packages/Yum.py +++ b/src/lib/Bcfg2/Server/Plugins/Packages/Yum.py @@ -1040,8 +1040,8 @@ class YumSource(Source): Source.__init__(self, basepath, xsource, setup) __init__.__doc__ = Source.__init__.__doc__ - def _init_attributes(self, basepath, xsource, setup): - Source._init_attributes(self, basepath, xsource, setup) + def _init_attributes(self, xsource): + Source._init_attributes(self, xsource) if HAS_PULP and xsource.get("pulp_id"): self.pulp_id = xsource.get("pulp_id") -- cgit v1.2.3-1-g7c22 From 3829eda6e46a291875d989ecb0afa6a28ed0e3b8 Mon Sep 17 00:00:00 2001 From: Alexander Sulfrian Date: Wed, 25 Mar 2015 20:23:18 +0100 Subject: Server/Plugins/Packages: Fix _init_attributes position. _init_attributes should be called after all properties of the Source class are initialized (so that _init_attributes could overwrite some of it). The Yum class initializes self.deps with a different default entry, that should not be reset by __init__ of Source afterwards. --- src/lib/Bcfg2/Server/Plugins/Packages/Source.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/lib/Bcfg2/Server/Plugins/Packages') diff --git a/src/lib/Bcfg2/Server/Plugins/Packages/Source.py b/src/lib/Bcfg2/Server/Plugins/Packages/Source.py index 6c5b61742..7aa688f12 100644 --- a/src/lib/Bcfg2/Server/Plugins/Packages/Source.py +++ b/src/lib/Bcfg2/Server/Plugins/Packages/Source.py @@ -212,8 +212,6 @@ class Source(Bcfg2.Server.Plugin.Debuggable): # pylint: disable=R0902 #: compat with older code that relies on this. self.groups = [] - self._init_attributes(xsource) - #: A set of all package names in this source. This will not #: necessarily be populated, particularly by backends that #: reimplement large portions of @@ -232,6 +230,8 @@ class Source(Bcfg2.Server.Plugin.Debuggable): # pylint: disable=R0902 #: :class:`Bcfg2.Server.Plugins.Packages.Collection.Collection` self.provides = dict() + self._init_attributes(xsource) + #: The file (or directory) used for this source's cache data self.cachefile = os.path.join(self.basepath, "cache-%s" % self.cachekey) -- cgit v1.2.3-1-g7c22 From 82b8b12f6bba17201376775fe90490bdcc8642df Mon Sep 17 00:00:00 2001 From: Sol Jerome Date: Mon, 30 Mar 2015 15:03:21 -0500 Subject: Packages/Yum.py: Fix dependency resolution logic This commit helps the internal YUM resolver to choose the latest version of a package to generate dependencies. Previously, we were simply iterating through the file so that the last instance listed always won (even if that instance was an older version with differing dependencies). Signed-off-by: Sol Jerome --- src/lib/Bcfg2/Server/Plugins/Packages/Yum.py | 103 ++++++++++++++++++++++++++- 1 file changed, 101 insertions(+), 2 deletions(-) (limited to 'src/lib/Bcfg2/Server/Plugins/Packages') diff --git a/src/lib/Bcfg2/Server/Plugins/Packages/Yum.py b/src/lib/Bcfg2/Server/Plugins/Packages/Yum.py index 20b0e103d..789df79d5 100644 --- a/src/lib/Bcfg2/Server/Plugins/Packages/Yum.py +++ b/src/lib/Bcfg2/Server/Plugins/Packages/Yum.py @@ -1169,6 +1169,94 @@ class YumSource(Source): self.file_to_arch[self.escape_url(fullurl)] = arch return urls + # pylint: disable=R0911,R0912 + # disabling the pylint errors above because we are interesting in + # replicating the flow of the RPM code. + def _compare_rpm_versions(self, str1, str2): + """ Compare RPM versions. + + This is an attempt to reimplement RPM's rpmvercmp method in python. + + :param str1: package 1 version string + :param str2: package 2 version string + :return: 1 - str1 is newer than str2 + 0 - str1 and str2 are the same version + -1 - str2 is newer than str1""" + if str1 == str2: + return 0 + + front_strip_re = re.compile('^[^A-Za-z0-9~]+') + risdigit = re.compile('(^[0-9]+)') + risalpha = re.compile('(^[A-Za-z])') + lzeroes = re.compile('^0+') + + while len(str1) > 0 or len(str2) > 0: + str1 = front_strip_re.sub('', str1) + str2 = front_strip_re.sub('', str2) + + if len(str1) == 0 or len(str2) == 0: + break + + # handle the tilde separator + if str1[0] == '~' and str2[0] == '~': + str1 = str1[1:] + str2 = str2[1:] + elif str1[0] == '~': + return -1 + elif str2[0] == '~': + return 1 + + # grab continuous segments from each string + isnum = False + if risdigit.match(str1): + segment1 = risdigit.split(str1)[1] + str1 = risdigit.split(str1)[2] + if risdigit.match(str2): + segment2 = risdigit.split(str2)[1] + str2 = risdigit.split(str2)[2] + else: + segment2 = '' + isnum = True + else: + segment1 = risalpha.split(str1)[1] + str1 = risalpha.split(str1)[2] + if risalpha.match(str2): + segment2 = risalpha.split(str2)[1] + str2 = risalpha.split(str2)[2] + else: + segment2 = '' + + # numeric segments are always newer than alpha segments + if len(segment2) == 0: + if isnum: + return 1 + return -1 + + if isnum: + # discard leading zeroes + segment1 = lzeroes.sub('', segment1) + segment2 = lzeroes.sub('', segment2) + # higher number has more digits + if len(segment1) > len(segment2): + return 1 + elif len(segment2) > len(segment1): + return -1 + # do a simple string comparison + if segment1 > segment2: + return 1 + elif segment2 > segment1: + return -1 + + # if one of the strings is empty, the version of the longer + # string is higher + if len(str1) > len(str2): + return 1 + elif len(str2) > len(str1): + return -1 + else: + return 0 + # pylint: enable=R0911,R0912 + @Bcfg2.Server.Plugin.track_statistics() def read_files(self): """ When using the builtin yum parser, read and parse locally @@ -1237,13 +1325,24 @@ class YumSource(Source): if arch not in self.packages: self.packages[arch] = set() if arch not in self.deps: - self.deps[arch] = dict() + self.deps[arch] = {} if arch not in self.provides: - self.provides[arch] = dict() + self.provides[arch] = {} + versionmap = {} for pkg in data.getchildren(): if not pkg.tag.endswith('package'): continue pkgname = pkg.find(XP + 'name').text + vtag = pkg.find(XP + 'version') + version = "%s%s-%s" % (vtag.get('epoch'), vtag.get('ver'), + vtag.get('rel')) + if pkgname in self.packages[arch]: + # skip if version older than a previous version + if self._compare_rpm_versions(version, + versionmap[pkgname]) < 0: + continue + + versionmap[pkgname] = version self.packages[arch].add(pkgname) pdata = pkg.find(XP + 'format') -- cgit v1.2.3-1-g7c22 From f3e9378c975d401c061da14e8e60fb031182f289 Mon Sep 17 00:00:00 2001 From: Sol Jerome Date: Tue, 31 Mar 2015 09:01:51 -0500 Subject: Yum.py: Compare epoch/version/release separately Signed-off-by: Sol Jerome --- src/lib/Bcfg2/Server/Plugins/Packages/Yum.py | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'src/lib/Bcfg2/Server/Plugins/Packages') diff --git a/src/lib/Bcfg2/Server/Plugins/Packages/Yum.py b/src/lib/Bcfg2/Server/Plugins/Packages/Yum.py index 789df79d5..20103820c 100644 --- a/src/lib/Bcfg2/Server/Plugins/Packages/Yum.py +++ b/src/lib/Bcfg2/Server/Plugins/Packages/Yum.py @@ -1334,15 +1334,24 @@ class YumSource(Source): continue pkgname = pkg.find(XP + 'name').text vtag = pkg.find(XP + 'version') - version = "%s%s-%s" % (vtag.get('epoch'), vtag.get('ver'), - vtag.get('rel')) + epoch = vtag.get('epoch') + version = vtag.get('ver') + release = vtag.get('rel') if pkgname in self.packages[arch]: # skip if version older than a previous version - if self._compare_rpm_versions(version, - versionmap[pkgname]) < 0: + if (self._compare_rpm_versions( + epoch, versionmap[pkgname]['epoch']) < 0): continue - - versionmap[pkgname] = version + elif (self._compare_rpm_versions( + version, versionmap[pkgname]['version']) < 0): + continue + elif (self._compare_rpm_versions( + release, versionmap[pkgname]['release']) < 0): + continue + versionmap[pkgname] = {} + versionmap[pkgname]['epoch'] = epoch + versionmap[pkgname]['version'] = version + versionmap[pkgname]['release'] = release self.packages[arch].add(pkgname) pdata = pkg.find(XP + 'format') -- cgit v1.2.3-1-g7c22 From 45a63e8cf0bfc5de075ee68d54b492b30f59bc77 Mon Sep 17 00:00:00 2001 From: Sol Jerome Date: Tue, 28 Apr 2015 08:59:23 -0500 Subject: Yum.py: Add debug log message Log a message to debug if the package is missing from the host's primary architecture package list (as per Chris's request). Signed-off-by: Sol Jerome --- src/lib/Bcfg2/Server/Plugins/Packages/Yum.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/lib/Bcfg2/Server/Plugins/Packages') diff --git a/src/lib/Bcfg2/Server/Plugins/Packages/Yum.py b/src/lib/Bcfg2/Server/Plugins/Packages/Yum.py index 4ee9cce52..0e4f93246 100644 --- a/src/lib/Bcfg2/Server/Plugins/Packages/Yum.py +++ b/src/lib/Bcfg2/Server/Plugins/Packages/Yum.py @@ -1293,6 +1293,8 @@ class YumSource(Source): package not in self.blacklist and (len(self.whitelist) == 0 or package in self.whitelist)) except KeyError: + self.logger.debug("Packages: Unable to find %s for arch %s" % + (package, arch[0])) return False is_package.__doc__ = Source.is_package.__doc__ -- cgit v1.2.3-1-g7c22