From c91befda5c420a5bfad30fe9568a8afdb3d03ad5 Mon Sep 17 00:00:00 2001 From: Seth Vidal Date: Thu, 2 Aug 2012 01:47:48 -0400 Subject: [PATCH] redo of yum module - uses more system calls but should handle random plugin vomit better. also should handle multiple withitems in a single execution, now. --- library/yum | 475 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 289 insertions(+), 186 deletions(-) diff --git a/library/yum b/library/yum index 03f45d960d0..2e2fbf48982 100755 --- a/library/yum +++ b/library/yum @@ -18,82 +18,109 @@ # along with Ansible. If not, see . # -import yum -import datetime + import traceback +import os -def yum_base(conf_file=None, cachedir=False): - my = yum.YumBase() - my.preconf.debuglevel=0 - if conf_file and os.path.exists(conf_file): - my.preconf.fn = conf_file - if cachedir: - if hasattr(my, 'setCacheDir'): - my.setCacheDir() - else: - cachedir = yum.misc.getCacheDir() - my.repos.setCacheDir(cachedir) - my.conf.cache = 0 +def_qf = "%{name}-%{version}-%{release}.%{arch}" + +def is_installed(repoq, pkgspec, qf=def_qf): + cmd = repoq + "--disablerepo=\* --pkgnarrow=installed --qf '%s' %s " % (qf, pkgspec) + rc,out,err = run(cmd) + if rc == 0: + return [ p for p in out.split('\n') if p.strip() ] - return my + return [] -def pkg_to_dict(po): +def is_available(repoq, pkgspec, qf=def_qf): + cmd = repoq + "--qf '%s' %s " % (qf, pkgspec) + rc,out,err = run(cmd) + if rc == 0: + return [ p for p in out.split('\n') if p.strip() ] + + return [] + + +def is_update(repoq, pkgspec, qf=def_qf): + cmd = repoq + "--pkgnarrow=updates --qf '%s' %s " % (qf, pkgspec) + rc,out,err = run(cmd) + if rc == 0: + return set([ p for p in out.split('\n') if p.strip() ]) + + return [] + + +def what_provides(repoq, req_spec, qf=def_qf): + cmd = repoq + "--qf '%s' --whatprovides %s" % (qf, req_spec) + rc,out,err = run(cmd) + ret = [] + if rc == 0: + ret = set([ p for p in out.split('\n') if p.strip() ]) + + return ret + +def local_nvra(path): + """return nvra of a local rpm passed in""" + + cmd = "/bin/rpm -qp --qf='%%{name}-%%{version}-%%{release}.%%{arch}\n' %s'" % path + rc, out, err = run(cmd) + if rc != 0: + return None + nvra = out.split('\n')[0] + return nvra + + +def pkg_to_dict(pkgstr): + if pkgstr.strip(): + n,e,v,r,a,repo = pkgstr.split('|') + else: + return {'error_parsing': pkgstr} + d = { - 'name':po.name, - 'arch':po.arch, - 'epoch':po.epoch, - 'release':po.release, - 'version':po.version, + 'name':n, + 'arch':a, + 'epoch':e, + 'release':r, + 'version':v, + 'repo':repo, + 'nevra': '%s:%s-%s-%s.%s' % (e,n,v,r,a) } - if type(po) == yum.rpmsack.RPMInstalledPackage: + if repo == 'installed': d['yumstate'] = 'installed' - d['repo'] = 'installed' else: d['yumstate'] = 'available' - d['repo'] = po.repoid - - if hasattr(po, 'ui_from_repo'): - d['repo'] = po.ui_from_repo - - if hasattr(po, 'ui_nevra'): - d['_nevra'] = po.ui_nevra - else: - d['_nevra'] = '%s-%s-%s.%s' % (po.name, po.version, po.release, po.arch) - - return d - -def list_stuff(my, stuff): - # FIXME - there are potential tracebacks that could occur here - # need some more catching for them so we can see what happened - if stuff == 'installed': - return [ pkg_to_dict(po) for po in my.rpmdb ] - elif stuff == 'updates': - return [ pkg_to_dict(po) for - po in my.doPackageLists(pkgnarrow='updates').updates ] - elif stuff == 'available': - return [ pkg_to_dict(po) for po in my.pkgSack ] - elif stuff == 'repos': - r = [] - for repo in my.repos.repos.values(): - t = {} - s = 'disabled' - if repo.enabled: - s = 'enabled' - t[repo.id] = s - r.append(t) - - return r - else: - e,m,u = my.rpmdb.matchPackageNames([stuff]) - p = e + m - e,m,u = my.pkgSack.matchPackageNames([stuff]) - p = p + e + m - return [ pkg_to_dict(po) for po in p ] -def run_yum(command): +def repolist(repoq, qf="%{repoid}"): + cmd = repoq + "--qf '%s' -a" % (qf) + rc,out,err = run(cmd) + ret = [] + if rc == 0: + ret = set([ p for p in out.split('\n') if p.strip() ]) + + return ret + +def list_stuff(conf_file, stuff): + qf = "%{name}|%{epoch}|%{version}|%{release}|%{arch}|%{repoid}" + repoq = '/usr/bin/repoquery --plugins --quiet -q ' + if conf_file and os.path.exists(conf_file): + repoq = '/usr/bin/repoquery -c %s --plugins --quiet -q ' % conf_file + + + if stuff == 'installed': + return [ pkg_to_dict(p) for p in is_installed(repoq, '-a', qf=qf) if p.strip() ] + elif stuff == 'updates': + return [ pkg_to_dict(p) for p in is_update(repoq, '-a', qf=qf) if p.strip() ] + elif stuff == 'available': + return [ pkg_to_dict(p) for p in is_available(repoq, '-a', qf=qf) if p.strip() ] + elif stuff == 'repos': + return [ dict(repoid=name, state='enabled') for name in repolist(repoq) if name.strip() ] + else: + return [ pkg_to_dict(p) for p in is_installed(repoq, stuff, qf=qf) + is_available(repoq, stuff, qf=qf) if p.strip() ] + +def run(command): try: cmd = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) @@ -106,7 +133,7 @@ def run_yum(command): rc = 1 err = traceback.format_exc() out = '' - + if out is None: out = '' if err is None: @@ -116,119 +143,176 @@ def run_yum(command): return rc, out, err -def ensure(my, state, pkgspec): - yumconf = my.conf.config_file_path + +def install(module, items, repoq, yum_basecmd): res = {} - if state in [ 'installed', 'present' ]: - # check if pkgspec is installed - if re.search('[>>