Sometime recently yum-security in "list updates mode"[1] has started causing backtraces and taking a huge amount of time.
For those that don't know the way plugins exclude items frfom "list
updates" is to use the exclude_hook and call conduit.getPackages and the
conduit.delPackage for any that they don't want.
The speed problem seems to be that conduit.delPackage() now takes about
a quarter of a second or so, combined with having to remove most/all of
the pacakges on the system.
The traceback is due to the fact that yum-security just did:
for pkg in conduit.getPackages():
...and this recurses into the function that calls the exclude plugins,
YumBase._getSacks(), and is protected from that being a problem by
doing:
if self._pkgSack and thisrepo is None:
...but if you remove _all_ of the packages the above fails. This can be
fixed by just moving the getPackages to a variable before the for loop
like:
pkgs = conduit.getPackages()
for pkg in pkgs:
...however I fixed that and the speed problem by instead doing:
upds = conduit._base.doPackageLists(pkgnarrow='updates')
pkgs = upds.updates
...this feels a little hacky, but it takes the runtime on my machine
from about an hour to 5 seconds (so I feel a little justified :).
Another way to go is if we could test if the package is an
update/installed etc, like:
pkgs = conduit.getPackages()
for pkg in pkgs:
if <pkg isn't installed already>:
# Do our normal work, incl. likely delPackage()
...but I don't think that's available at this point.
Full patch against yum-utils is attached.
[1] Ie. yum list updates --security
--
James Antill <[EMAIL PROTECTED]>
Red Hat
diff --git a/plugins/security/security.py b/plugins/security/security.py
index 9d97a3b..f8f1cf8 100755
--- a/plugins/security/security.py
+++ b/plugins/security/security.py
@@ -338,10 +338,27 @@ def exclude_hook(conduit):
conduit.delPackage(pkg)
used_map = ysp_gen_used_map(opts)
- for pkg in conduit.getPackages():
- if not ysp_should_keep_pkg(opts, pkg, md_info, used_map):
+ # The official API is:
+ #
+ # pkgs = conduit.getPackages()
+ #
+ # ...however that is _extremely_ slow, deleting all packages. So we ask
+ # for the list of update packages, which is all we care about.
+ upds = conduit._base.doPackageLists(pkgnarrow='updates')
+ pkgs = upds.updates
+ tot = 0
+ cnt = 0
+ for pkg in pkgs:
+ tot += 1
+ if ysp_should_keep_pkg(opts, pkg, md_info, used_map):
+ cnt += 1
+ else:
ysp_del_pkg(pkg)
ysp_chk_used_map(used_map, lambda x: conduit.error(2, x))
+ if cnt:
+ conduit.info(2, 'Needed %d of %d packages, for security' % (cnt, tot))
+ else:
+ conduit.info(2, 'No packages needed, for security, %d available' % tot)
def preresolve_hook(conduit):
'''
@@ -366,11 +383,13 @@ def preresolve_hook(conduit):
(tspkg.po,tspkg.po.repoid))
tsinfo.remove(tspkg.pkgtup)
+ tot = 0
cnt = 0
used_map = ysp_gen_used_map(opts)
tsinfo = conduit.getTsInfo()
tspkgs = tsinfo.getMembers()
for tspkg in tspkgs:
+ tot += 1
if not ysp_should_keep_pkg(opts, tspkg.po, md_info, used_map):
ysp_del_pkg(tspkg)
else:
@@ -378,9 +397,9 @@ def preresolve_hook(conduit):
ysp_chk_used_map(used_map, lambda x: conduit.error(2, x))
if cnt:
- conduit.info(2, 'Needed %d packages, for security' % (cnt))
+ conduit.info(2, 'Needed %d of %d packages, for security' % (cnt, tot))
else:
- conduit.info(2, 'No packages needed, for security')
+ conduit.info(2, 'No packages needed, for security, %d available' % tot)
if __name__ == '__main__':
print "This is a plugin that is supposed to run from inside YUM"
signature.asc
Description: This is a digitally signed message part
_______________________________________________ Yum-devel mailing list [email protected] https://lists.dulug.duke.edu/mailman/listinfo/yum-devel
