summaryrefslogtreecommitdiffstats
path: root/src/software/openlmi/software/yumdb/process.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/software/openlmi/software/yumdb/process.py')
-rw-r--r--src/software/openlmi/software/yumdb/process.py178
1 files changed, 118 insertions, 60 deletions
diff --git a/src/software/openlmi/software/yumdb/process.py b/src/software/openlmi/software/yumdb/process.py
index faa0711..96c471e 100644
--- a/src/software/openlmi/software/yumdb/process.py
+++ b/src/software/openlmi/software/yumdb/process.py
@@ -75,44 +75,96 @@ def _get_package_filter_function(filters):
filters = dict((k, value) for k, value in filters.items()
if value is not None)
+ match = None
if "nevra" in filters:
- def _cmp_nevra(pkg):
- """@return True if pkg matches nevra filter"""
- value = '%s-%s:%s-%s.%s' % (
- pkg.name,
- "0" if not pkg.epoch or pkg.epoch == "(none)"
- else pkg.epoch,
- pkg.version, pkg.release, pkg.arch)
- return value == filters["nevra"]
- return _cmp_nevra
-
+ match = util.RE_NEVRA.match(filters["nevra"])
elif "envra" in filters:
- def _cmp_envra(pkg):
- """@return True if pkg matches envra filter"""
- value = '%s:%s-%s-%s.%s' % (
- "0" if not pkg.epoch or pkg.epoch == "(none)"
- else pkg.epoch,
- pkg.name,
- pkg.version, pkg.release, pkg.arch)
- return value == filters["envra"]
- return _cmp_envra
-
- else:
- if "evra" in filters:
- for prop_name in ("epoch", "version", "release", "epoch"):
- filters.pop(prop_name, None)
- filter_list = []
- # properties are sorted by their filtering ability
- # (the most unprobable property, that can match, comes first)
- for prop_name in ("evra", "name", "version", "epoch",
- "release", "arch"):
- if not prop_name in filters:
- continue
- filter_list.append((prop_name, filters.pop(prop_name)))
- def _cmp_props(pkg):
- """@return True if pkg matches properies filter"""
- return all(getattr(pkg, p) == v for p, v in filter_list)
- return _cmp_props
+ match = util.RE_ENVRA.match(filters["envra"])
+ if match is not None:
+ for attr in ("name", "epoch", "version", "release", "arch"):
+ match_attr = attr
+ if attr in {'version', 'release'}:
+ match_attr = attr[:3]
+ filters[attr] = match.group(match_attr)
+ filters.pop('nevra', None)
+ filters.pop('envra', None)
+ elif "evra" in filters:
+ for prop_name in ("epoch", "version", "release", "epoch"):
+ filters.pop(prop_name, None)
+ filter_list = []
+ # properties are sorted by their filtering ability
+ # (the most unprobable property, that can match, comes first)
+ for prop_name in ("evra", "name", "version", "epoch",
+ "release", "repoid", "arch"):
+ if not prop_name in filters:
+ continue
+ filter_list.append((prop_name, filters.pop(prop_name)))
+ def _cmp_props(pkg):
+ """@return True if pkg matches properies filter"""
+ return all(getattr(pkg, p) == v for p, v in filter_list)
+ return _cmp_props
+
+class RepoFilterSetter(object):
+ """
+ A context manager, that will set a repository filter lasting
+ as long as the object itself.
+ """
+ def __init__(self, yum_base, include_repos=None, exclude_repos=None):
+ if not isinstance(yum_base, yum.YumBase):
+ raise TypeError("yum_base must be a YumBase instance")
+ self._yum_base = yum_base
+ self._include = include_repos
+ self._exclude = exclude_repos
+ # after __enter__ this will be dictionary containing (
+ # repoid, enabled) pairs
+ self._prev_states = None
+
+ def __enter__(self):
+ self._prev_states = { r.id: r.enabled
+ for r in self._yum_base.repos.repos.values()}
+ if isinstance(self._exclude, (list, tuple, set)):
+ exclude = ",".join(self._exclude)
+ else:
+ exclude = self._exclude
+ # set of repositories, that were affected
+ repos = set()
+ if exclude:
+ repos.update(self._yum_base.repos.disableRepo(exclude))
+ _logger().info('disabling repositories: [%s]', ", ".join(repos))
+ if isinstance(self._include, (list, tuple, set)):
+ include = ",".join(self._include)
+ else:
+ include = self._include
+ if include:
+ affected = self._yum_base.repos.enableRepo(include)
+ _logger().info('enabling repositories: [%s]', ", ".join(affected))
+ repos.update(affected)
+ for repoid, prev_enabled in self._prev_states.items():
+ if ( repoid not in repos
+ or ( bool(prev_enabled)
+ is bool(self._yum_base.repos.getRepo(repoid).enabled))):
+ # keep only manipulated repositories
+ del self._prev_states[repoid]
+ if len(self._prev_states):
+ for repoid in (r for r, v in self._prev_states.items() if v):
+ self._yum_base.pkgSack.sacks.pop(repoid, None)
+ self._yum_base.repos.populateSack()
+ return self
+
+ def __exit__(self, exc_type, exc_value, exc_tb):
+ # restore previous repository states
+ if len(self._prev_states):
+ _logger().info('restoring repositories: [%s]',
+ ", ".join(self._prev_states.keys()))
+ for repoid, enabled in self._prev_states.items():
+ repo = self._yum_base.repos.getRepo(repoid)
+ if enabled:
+ repo.enable()
+ else:
+ repo.disable()
+ for repoid in (r for r, v in self._prev_states.items() if not v):
+ self._yum_base.pkgSack.sacks.pop(repoid, None)
+ self._yum_base.repos.populateSack()
# *****************************************************************************
# Decorators
@@ -204,7 +256,7 @@ class YumWorker(Process):
yum_args=None,
yum_kwargs=None,
logging_config=None):
- Process.__init__(self)
+ Process.__init__(self, name="YumWorker")
self._queue_in = queue_in
self._queue_out = queue_out
self._session_level = 0
@@ -304,7 +356,7 @@ class YumWorker(Process):
for orig in packages:
pkg = packageinfo.make_package_from_db(orig)
if cache_packages is True:
- self._pkg_cache[pkg.pkgid] = orig
+ self._pkg_cache[pkg.objid] = orig
res.append(pkg)
return res
@@ -336,15 +388,15 @@ class YumWorker(Process):
if not isinstance(pkg, packageinfo.PackageInfo):
raise TypeError("pkg must be instance of PackageInfo")
_logger().debug("looking up yum package %s with id=%d",
- pkg, pkg.pkgid)
+ pkg, pkg.objid)
try:
- result = self._pkg_cache[pkg.pkgid]
+ result = self._pkg_cache[pkg.objid]
_logger().debug("lookup successful")
except KeyError:
_logger().warn("lookup of package %s with id=%d failed, trying"
- " to query database", pkg, pkg.pkgid)
+ " to query database", pkg, pkg.objid)
result = self._handle_filter_packages(
- 'installed' if pkg.installed else 'avail_reinst',
+ 'installed' if pkg.installed else 'available',
allow_duplicates=False,
sort=False,
transform=False,
@@ -363,8 +415,10 @@ class YumWorker(Process):
last modification times.
"""
if self._yum_base is not None:
- self._yum_base.repos.close()
+ for repoid in self._yum_base.repos.repos.keys():
+ self._yum_base.repos.delete(repoid)
del self._yum_base.repos
+ del self._yum_base.pkgSack
self._repodir_mtimes.clear()
@_trace_function
@@ -388,16 +442,17 @@ class YumWorker(Process):
for repo in self._yum_base.repos.repos.values():
filename = repo.repofile
if ( not os.path.exists(filename)
- or os.stat(filename).st_mtime > repo.repo_config_age):
- _logger().info('config file of repository "%s"'
- ' changed', repo.id)
+ or ( int(os.stat(filename).st_mtime)
+ > repo.repo_config_age)):
+ _logger().info('config file of repository "%s" changed',
+ repo.id)
dirty = True
break
if dirty is True:
_logger().info("repository cache is dirty, cleaning up ...")
self._clear_repository_cache()
- if dirty is True or not self._repodir_mtimes:
self._yum_base.getReposFromConfig()
+ if dirty is True or not self._repodir_mtimes:
self._update_repodir_mtimes()
@_trace_function
@@ -478,14 +533,14 @@ class YumWorker(Process):
Handler for session end job.
"""
_logger().info("ending session level %d", self._session_level)
- self._session_level -= 1
+ self._session_level = max(self._session_level - 1, 0)
if self._session_level == 0:
self._unlock_database()
self._session_ended = True
@_needs_database
def _handle_get_package_list(self, kind, allow_duplicates, sort,
- transform=True):
+ include_repos=None, exclude_repos=None, transform=True):
"""
Handler for listing packages job.
@param transform says, whether to return just a package abstractions
@@ -500,10 +555,11 @@ class YumWorker(Process):
what = 'all'
else:
what = kind
- _logger().debug("calling YumBase.doPackageLists(%s, showdups=%s)",
- what, allow_duplicates)
- pkglist = self._yum_base.doPackageLists(what, showdups=allow_duplicates)
- _logger().debug("YumBase.doPackageLists() finished")
+ with RepoFilterSetter(self._yum_base, include_repos, exclude_repos):
+ _logger().debug("calling YumBase.doPackageLists(%s, showdups=%s)",
+ what, allow_duplicates)
+ pkglist = self._yum_base.doPackageLists(what,
+ showdups=allow_duplicates)
if kind == 'all':
result = pkglist.available + pkglist.installed
elif kind == 'available':
@@ -519,12 +575,14 @@ class YumWorker(Process):
@_needs_database
def _handle_filter_packages(self, kind, allow_duplicates, sort,
+ include_repos=None, exclude_repos=None,
transform=True, **filters):
"""
Handler for filtering packages job.
@return [pkg1, pkg2, ...]
"""
pkglist = self._handle_get_package_list(kind, allow_duplicates, False,
+ include_repos=include_repos, exclude_repos=exclude_repos,
transform=False)
matches = _get_package_filter_function(filters)
result = [p for p in pkglist if matches(p)]
@@ -644,24 +702,24 @@ class YumWorker(Process):
@return list of yumdb.Repository instances -- filtered
"""
filters = dict((k, v) for k, v in filters.items() if v is not None)
- if 'name' in filters:
+ if 'repoid' in filters:
self._check_repository_configs()
try:
repo = repository.make_repository_from_db(
- self._yum_base.repos.getRepo(filters["name"]))
+ self._yum_base.repos.getRepo(filters["repoid"]))
if ( (kind == "enabled" and not repo.enabled)
or (kind == "disabled" and repo.enabled)):
_logger().warn(
'no such repository with id="%s"matching filters',
- filters['name'])
+ filters['repoid'])
return []
_logger().debug(
"exactly one repository matching filters found")
return [repo]
except (KeyError, yum.Errors.RepoError):
_logger().warn('repository with id="%s" could not be found',
- filters['name'])
- raise errors.RepositoryNotFound(filters['name'])
+ filters['repoid'])
+ raise errors.RepositoryNotFound(filters['repoid'])
repos = self._handle_get_repository_list(kind, transform=False)
result = []
for repo in repos:
@@ -681,9 +739,9 @@ class YumWorker(Process):
@return previous enabled state
"""
try:
- repo = self._yum_base.repos.getRepo(repo.name)
+ repo = self._yum_base.repos.getRepo(repo.repoid)
except (KeyError, yum.Errors.RepoError):
- raise errors.RepositoryNotFound(repo.name)
+ raise errors.RepositoryNotFound(repo.repoid)
res = repo.enabled
try:
if enable ^ res: