diff options
author | Toshio Kuratomi <toshio@fedoraproject.org> | 2015-12-13 09:16:28 -0800 |
---|---|---|
committer | Charles Paul <cpaul@ansible.com> | 2015-12-15 10:42:40 -0600 |
commit | 6284107a33c905feb65f7e0edd9341431ca3154f (patch) | |
tree | 0ba0b7e5c41d4b14910368b5ff180043707401e4 | |
parent | 76e29e7407823415007c70284e61c198a3bd363d (diff) | |
download | ansible-modules-core-6284107a33c905feb65f7e0edd9341431ca3154f.tar.gz |
Use rpm instead of repoquery for is_installed()
* This keeps us from hitting bugs in repoquery/yum plugins in certain
instances (#2559).
* The previous is also a small performance boost
* Also in is_installed(), when using the yum API, return if we detect
a package name has been installed. We don't need to also check
virtual provides in that case. This is another small performance
boost.
* Sort the list of packages returned by the list parameter.
-rw-r--r-- | packaging/os/yum.py | 55 |
1 files changed, 34 insertions, 21 deletions
diff --git a/packaging/os/yum.py b/packaging/os/yum.py index fec9d8b5..5464bbe8 100644 --- a/packaging/os/yum.py +++ b/packaging/os/yum.py @@ -21,8 +21,6 @@ # along with Ansible. If not, see <http://www.gnu.org/licenses/>. # - -import traceback import os import yum import rpm @@ -179,6 +177,7 @@ EXAMPLES = ''' BUFSIZE = 65536 def_qf = "%{name}-%{version}-%{release}.%{arch}" +rpmbin = None def yum_base(conf_file=None): @@ -222,8 +221,8 @@ def is_installed(module, repoq, pkgspec, conf_file, qf=def_qf, en_repos=None, di en_repos = [] if dis_repos is None: dis_repos = [] - if not repoq: + if not repoq: pkgs = [] try: my = yum_base(conf_file) @@ -231,10 +230,10 @@ def is_installed(module, repoq, pkgspec, conf_file, qf=def_qf, en_repos=None, di my.repos.disableRepo(rid) for rid in en_repos: my.repos.enableRepo(rid) - + e, m, u = my.rpmdb.matchPackageNames([pkgspec]) pkgs = e + m - if not pkgs: + if not pkgs and not is_pkg: pkgs.extend(my.returnInstalledPackagesByDep(pkgspec)) except Exception, e: module.fail_json(msg="Failure talking to yum: %s" % e) @@ -242,21 +241,31 @@ def is_installed(module, repoq, pkgspec, conf_file, qf=def_qf, en_repos=None, di return [ po_to_nevra(p) for p in pkgs ] else: + global rpmbin + if not rpmbin: + rpmbin = module.get_bin_path('rpm', required=True) - cmd = repoq + ["--disablerepo=*", "--pkgnarrow=installed", "--qf", qf, pkgspec] + cmd = [rpmbin, '-q', '--qf', qf, pkgspec] rc, out, err = module.run_command(cmd) - if not is_pkg: - cmd = repoq + ["--disablerepo=*", "--pkgnarrow=installed", "--qf", qf, "--whatprovides", pkgspec] + if rc != 0 and 'is not installed' not in out: + module.fail_json(msg='Error from rpm: %s: %s' % (cmd, err)) + if 'is not installed' in out: + out = '' + + pkgs = [p for p in out.replace('(none)', '0').split('\n') if p.strip()] + if not pkgs and not is_pkg: + cmd = [rpmbin, '-q', '--qf', qf, '--whatprovides', pkgspec] rc2, out2, err2 = module.run_command(cmd) else: rc2, out2, err2 = (0, '', '') - - if rc == 0 and rc2 == 0: - out += out2 - return [p for p in out.split('\n') if p.strip()] - else: - module.fail_json(msg='Error from repoquery: %s: %s' % (cmd, err + err2)) - + + if rc2 != 0 and 'no package provides' not in out2: + module.fail_json(msg='Error from rpm: %s: %s' % (cmd, err + err2)) + if 'no package provides' in out2: + out2 = '' + pkgs += [p for p in out2.replace('(none)', '0').split('\n') if p.strip()] + return pkgs + return [] def is_available(module, repoq, pkgspec, conf_file, qf=def_qf, en_repos=None, dis_repos=None): @@ -496,20 +505,22 @@ def repolist(module, repoq, qf="%{repoid}"): def list_stuff(module, repoquerybin, conf_file, stuff): qf = "%{name}|%{epoch}|%{version}|%{release}|%{arch}|%{repoid}" + # is_installed goes through rpm instead of repoquery so it needs a slightly different format + is_installed_qf = "%{name}|%{epoch}|%{version}|%{release}|%{arch}|installed\n" repoq = [repoquerybin, '--show-duplicates', '--plugins', '--quiet'] if conf_file and os.path.exists(conf_file): repoq += ['-c', conf_file] if stuff == 'installed': - return [ pkg_to_dict(p) for p in is_installed(module, repoq, '-a', conf_file, qf=qf) if p.strip() ] + return [ pkg_to_dict(p) for p in sorted(is_installed(module, repoq, '-a', conf_file, qf=is_installed_qf)) if p.strip() ] elif stuff == 'updates': - return [ pkg_to_dict(p) for p in is_update(module, repoq, '-a', conf_file, qf=qf) if p.strip() ] + return [ pkg_to_dict(p) for p in sorted(is_update(module, repoq, '-a', conf_file, qf=qf)) if p.strip() ] elif stuff == 'available': - return [ pkg_to_dict(p) for p in is_available(module, repoq, '-a', conf_file, qf=qf) if p.strip() ] + return [ pkg_to_dict(p) for p in sorted(is_available(module, repoq, '-a', conf_file, qf=qf)) if p.strip() ] elif stuff == 'repos': - return [ dict(repoid=name, state='enabled') for name in repolist(module, repoq) if name.strip() ] + return [ dict(repoid=name, state='enabled') for name in sorted(repolist(module, repoq)) if name.strip() ] else: - return [ pkg_to_dict(p) for p in is_installed(module, repoq, stuff, conf_file, qf=qf) + is_available(module, repoq, stuff, conf_file, qf=qf) if p.strip() ] + return [ pkg_to_dict(p) for p in sorted(is_installed(module, repoq, stuff, conf_file, qf=is_installed_qf) + is_available(module, repoq, stuff, conf_file, qf=qf)) if p.strip() ] def install(module, items, repoq, yum_basecmd, conf_file, en_repos, dis_repos): @@ -941,6 +952,7 @@ def ensure(module, state, pkgs, conf_file, enablerepo, disablerepo, return res + def main(): # state=installed name=pkgspec @@ -1011,7 +1023,8 @@ def main(): results = ensure(module, state, pkg, params['conf_file'], enablerepo, disablerepo, disable_gpg_check, exclude, repoquery) if repoquery: - results['msg'] = '%s %s' % (results.get('msg',''), 'Warning: Due to potential bad behaviour with rhnplugin and certificates, used slower repoquery calls instead of Yum API.') + results['msg'] = '%s %s' % (results.get('msg',''), + 'Warning: Due to potential bad behaviour with rhnplugin and certificates, used slower repoquery calls instead of Yum API.') module.exit_json(**results) |