yum cleanup (#28818)

This commit is contained in:
Martin Krizek 2017-09-12 12:59:15 +02:00 committed by ansibot
parent 5b1c91bf19
commit d52316fcc2

View file

@ -264,7 +264,7 @@ try:
from yum.misc import find_unfinished_transactions, find_ts_remaining from yum.misc import find_unfinished_transactions, find_ts_remaining
from rpmUtils.miscutils import splitFilename, compareEVR from rpmUtils.miscutils import splitFilename, compareEVR
transaction_helpers = True transaction_helpers = True
except: except ImportError:
transaction_helpers = False transaction_helpers = False
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
@ -279,7 +279,6 @@ rpmbin = None
def yum_base(conf_file=None, installroot='/'): def yum_base(conf_file=None, installroot='/'):
my = yum.YumBase() my = yum.YumBase()
my.preconf.debuglevel = 0 my.preconf.debuglevel = 0
my.preconf.errorlevel = 0 my.preconf.errorlevel = 0
@ -303,18 +302,19 @@ def yum_base(conf_file=None, installroot='/'):
return my return my
def ensure_yum_utils(module):
def ensure_yum_utils(module):
repoquerybin = module.get_bin_path('repoquery', required=False) repoquerybin = module.get_bin_path('repoquery', required=False)
if module.params['install_repoquery'] and not repoquerybin and not module.check_mode: if module.params['install_repoquery'] and not repoquerybin and not module.check_mode:
yum_path = module.get_bin_path('yum') yum_path = module.get_bin_path('yum')
if yum_path: if yum_path:
rc, so, se = module.run_command('%s -y install yum-utils' % yum_path) module.run_command('%s -y install yum-utils' % yum_path)
repoquerybin = module.get_bin_path('repoquery', required=False) repoquerybin = module.get_bin_path('repoquery', required=False)
return repoquerybin return repoquerybin
def fetch_rpm_from_url(spec, module=None): def fetch_rpm_from_url(spec, module=None):
# download package so that we can query it # download package so that we can query it
package_name, _ = os.path.splitext(str(spec.rsplit('/', 1)[1])) package_name, _ = os.path.splitext(str(spec.rsplit('/', 1)[1]))
@ -337,11 +337,12 @@ def fetch_rpm_from_url(spec, module=None):
return package_file.name return package_file.name
def po_to_envra(po): def po_to_envra(po):
if hasattr(po, 'ui_envra'): if hasattr(po, 'ui_envra'):
return po.ui_envra return po.ui_envra
else:
return '%s:%s-%s-%s.%s' % (po.epoch, po.name, po.version, po.release, po.arch) return '%s:%s-%s-%s.%s' % (po.epoch, po.name, po.version, po.release, po.arch)
def is_group_installed(name): def is_group_installed(name):
@ -370,7 +371,7 @@ def is_installed(module, repoq, pkgspec, conf_file, qf=def_qf, en_repos=None, di
for rid in en_repos: for rid in en_repos:
my.repos.enableRepo(rid) my.repos.enableRepo(rid)
e, m, u = my.rpmdb.matchPackageNames([pkgspec]) e, m, _ = my.rpmdb.matchPackageNames([pkgspec])
pkgs = e + m pkgs = e + m
if not pkgs and not is_pkg: if not pkgs and not is_pkg:
pkgs.extend(my.returnInstalledPackagesByDep(pkgspec)) pkgs.extend(my.returnInstalledPackagesByDep(pkgspec))
@ -414,6 +415,7 @@ def is_installed(module, repoq, pkgspec, conf_file, qf=def_qf, en_repos=None, di
return [] return []
def is_available(module, repoq, pkgspec, conf_file, qf=def_qf, en_repos=None, dis_repos=None, installroot='/'): def is_available(module, repoq, pkgspec, conf_file, qf=def_qf, en_repos=None, dis_repos=None, installroot='/'):
if en_repos is None: if en_repos is None:
en_repos = [] en_repos = []
@ -430,7 +432,7 @@ def is_available(module, repoq, pkgspec, conf_file, qf=def_qf, en_repos=None, di
for rid in en_repos: for rid in en_repos:
my.repos.enableRepo(rid) my.repos.enableRepo(rid)
e, m, u = my.pkgSack.matchPackageNames([pkgspec]) e, m, _ = my.pkgSack.matchPackageNames([pkgspec])
pkgs = e + m pkgs = e + m
if not pkgs: if not pkgs:
pkgs.extend(my.returnPackagesByDep(pkgspec)) pkgs.extend(my.returnPackagesByDep(pkgspec))
@ -457,6 +459,7 @@ def is_available(module, repoq, pkgspec, conf_file, qf=def_qf, en_repos=None, di
return [] return []
def is_update(module, repoq, pkgspec, conf_file, qf=def_qf, en_repos=None, dis_repos=None, installroot='/'): def is_update(module, repoq, pkgspec, conf_file, qf=def_qf, en_repos=None, dis_repos=None, installroot='/'):
if en_repos is None: if en_repos is None:
en_repos = [] en_repos = []
@ -478,7 +481,7 @@ def is_update(module, repoq, pkgspec, conf_file, qf=def_qf, en_repos=None, dis_r
pkgs = my.returnPackagesByDep(pkgspec) + my.returnInstalledPackagesByDep(pkgspec) pkgs = my.returnPackagesByDep(pkgspec) + my.returnInstalledPackagesByDep(pkgspec)
if not pkgs: if not pkgs:
e, m, u = my.pkgSack.matchPackageNames([pkgspec]) e, m, _ = my.pkgSack.matchPackageNames([pkgspec])
pkgs = e + m pkgs = e + m
updates = my.doPackageLists(pkgnarrow='updates').updates updates = my.doPackageLists(pkgnarrow='updates').updates
except Exception as e: except Exception as e:
@ -508,6 +511,7 @@ def is_update(module, repoq, pkgspec, conf_file, qf=def_qf, en_repos=None, dis_r
return set() return set()
def what_provides(module, repoq, req_spec, conf_file, qf=def_qf, en_repos=None, dis_repos=None, installroot='/'): def what_provides(module, repoq, req_spec, conf_file, qf=def_qf, en_repos=None, dis_repos=None, installroot='/'):
if en_repos is None: if en_repos is None:
en_repos = [] en_repos = []
@ -526,10 +530,10 @@ def what_provides(module, repoq, req_spec, conf_file, qf=def_qf, en_repos=None,
pkgs = my.returnPackagesByDep(req_spec) + my.returnInstalledPackagesByDep(req_spec) pkgs = my.returnPackagesByDep(req_spec) + my.returnInstalledPackagesByDep(req_spec)
if not pkgs: if not pkgs:
e, m, u = my.pkgSack.matchPackageNames([req_spec]) e, m, _ = my.pkgSack.matchPackageNames([req_spec])
pkgs.extend(e) pkgs.extend(e)
pkgs.extend(m) pkgs.extend(m)
e, m, u = my.rpmdb.matchPackageNames([req_spec]) e, m, _ = my.rpmdb.matchPackageNames([req_spec])
pkgs.extend(e) pkgs.extend(e)
pkgs.extend(m) pkgs.extend(m)
except Exception as e: except Exception as e:
@ -560,6 +564,7 @@ def what_provides(module, repoq, req_spec, conf_file, qf=def_qf, en_repos=None,
return set() return set()
def transaction_exists(pkglist): def transaction_exists(pkglist):
""" """
checks the package list to see if any packages are checks the package list to see if any packages are
@ -599,7 +604,8 @@ def transaction_exists(pkglist):
break break
return conflicts return conflicts
def local_envra(module, path):
def local_envra(path):
"""return envra of a local rpm passed in""" """return envra of a local rpm passed in"""
ts = rpm.TransactionSet() ts = rpm.TransactionSet()
@ -616,20 +622,20 @@ def local_envra(module, path):
header[rpm.RPMTAG_RELEASE], header[rpm.RPMTAG_RELEASE],
header[rpm.RPMTAG_ARCH]) header[rpm.RPMTAG_ARCH])
def pkg_to_dict(pkgstr):
def pkg_to_dict(pkgstr):
if pkgstr.strip(): if pkgstr.strip():
n, e, v, r, a, repo = pkgstr.split('|') n, e, v, r, a, repo = pkgstr.split('|')
else: else:
return {'error_parsing': pkgstr} return {'error_parsing': pkgstr}
d = { d = {
'name':n, 'name': n,
'arch':a, 'arch': a,
'epoch':e, 'epoch': e,
'release':r, 'release': r,
'version':v, 'version': v,
'repo':repo, 'repo': repo,
'envra': '%s:%s-%s-%s.%s' % (e, n, v, r, a) 'envra': '%s:%s-%s-%s.%s' % (e, n, v, r, a)
} }
@ -640,15 +646,16 @@ def pkg_to_dict(pkgstr):
return d return d
def repolist(module, repoq, qf="%{repoid}"):
def repolist(module, repoq, qf="%{repoid}"):
cmd = repoq + ["--qf", qf, "-a"] cmd = repoq + ["--qf", qf, "-a"]
rc, out, err = module.run_command(cmd) rc, out, _ = module.run_command(cmd)
ret = [] ret = []
if rc == 0: if rc == 0:
ret = set([p for p in out.split('\n') if p.strip()]) ret = set([p for p in out.split('\n') if p.strip()])
return ret return ret
def list_stuff(module, repoquerybin, conf_file, stuff, installroot='/', disablerepo='', enablerepo=''): def list_stuff(module, repoquerybin, conf_file, stuff, installroot='/', disablerepo='', enablerepo=''):
qf = "%{name}|%{epoch}|%{version}|%{release}|%{arch}|%{repoid}" qf = "%{name}|%{epoch}|%{version}|%{release}|%{arch}|%{repoid}"
@ -686,12 +693,12 @@ def exec_install(module, items, action, pkgs, res, yum_basecmd):
lang_env = dict(LANG='C', LC_ALL='C', LC_MESSAGES='C') lang_env = dict(LANG='C', LC_ALL='C', LC_MESSAGES='C')
rc, out, err = module.run_command(cmd, environ_update=lang_env) rc, out, err = module.run_command(cmd, environ_update=lang_env)
if (rc == 1): if rc == 1:
for spec in items: for spec in items:
# Fail on invalid urls: # Fail on invalid urls:
if ('://' in spec and ('No package %s available.' % spec in out or 'Cannot open: %s. Skipping.' % spec in err)): if ('://' in spec and ('No package %s available.' % spec in out or 'Cannot open: %s. Skipping.' % spec in err)):
err = 'Package at %s could not be installed' % spec err = 'Package at %s could not be installed' % spec
module.fail_json(changed=False,msg=err,rc=1) module.fail_json(changed=False, msg=err, rc=rc)
res['rc'] = rc res['rc'] = rc
res['results'].append(out) res['results'].append(out)
@ -733,10 +740,10 @@ def install(module, items, repoq, yum_basecmd, conf_file, en_repos, dis_repos, i
if not os.path.exists(spec): if not os.path.exists(spec):
res['msg'] += "No RPM file matching '%s' found on system" % spec res['msg'] += "No RPM file matching '%s' found on system" % spec
res['results'].append("No RPM file matching '%s' found on system" % spec) res['results'].append("No RPM file matching '%s' found on system" % spec)
res['rc'] = 127 # Ensure the task fails in with-loop res['rc'] = 127 # Ensure the task fails in with-loop
module.fail_json(**res) module.fail_json(**res)
envra = local_envra(module, spec) envra = local_envra(spec)
# look for them in the rpmdb # look for them in the rpmdb
if is_installed(module, repoq, envra, conf_file, en_repos=en_repos, dis_repos=dis_repos, installroot=installroot): if is_installed(module, repoq, envra, conf_file, en_repos=en_repos, dis_repos=dis_repos, installroot=installroot):
@ -777,15 +784,15 @@ def install(module, items, repoq, yum_basecmd, conf_file, en_repos, dis_repos, i
if not pkglist: if not pkglist:
res['msg'] += "No package matching '%s' found available, installed or updated" % spec res['msg'] += "No package matching '%s' found available, installed or updated" % spec
res['results'].append("No package matching '%s' found available, installed or updated" % spec) res['results'].append("No package matching '%s' found available, installed or updated" % spec)
res['rc'] = 126 # Ensure the task fails in with-loop res['rc'] = 126 # Ensure the task fails in with-loop
module.fail_json(**res) module.fail_json(**res)
# if any of the packages are involved in a transaction, fail now # if any of the packages are involved in a transaction, fail now
# so that we don't hang on the yum operation later # so that we don't hang on the yum operation later
conflicts = transaction_exists(pkglist) conflicts = transaction_exists(pkglist)
if len(conflicts) > 0: if conflicts:
res['msg'] += "The following packages have pending transactions: %s" % ", ".join(conflicts) res['msg'] += "The following packages have pending transactions: %s" % ", ".join(conflicts)
res['rc'] = 125 # Ensure the task fails in with-loop res['rc'] = 125 # Ensure the task fails in with-loop
module.fail_json(**res) module.fail_json(**res)
# if any of them are installed # if any of them are installed
@ -1003,11 +1010,11 @@ def latest(module, items, repoq, yum_basecmd, conf_file, en_repos, dis_repos, in
if not os.path.exists(spec): if not os.path.exists(spec):
res['msg'] += "No RPM file matching '%s' found on system" % spec res['msg'] += "No RPM file matching '%s' found on system" % spec
res['results'].append("No RPM file matching '%s' found on system" % spec) res['results'].append("No RPM file matching '%s' found on system" % spec)
res['rc'] = 127 # Ensure the task fails in with-loop res['rc'] = 127 # Ensure the task fails in with-loop
module.fail_json(**res) module.fail_json(**res)
# get the pkg e:name-v-r.arch # get the pkg e:name-v-r.arch
envra = local_envra(module, spec) envra = local_envra(spec)
# local rpm files can't be updated # local rpm files can't be updated
if not is_installed(module, repoq, envra, conf_file, en_repos=en_repos, dis_repos=dis_repos, installroot=installroot): if not is_installed(module, repoq, envra, conf_file, en_repos=en_repos, dis_repos=dis_repos, installroot=installroot):
@ -1018,7 +1025,7 @@ def latest(module, items, repoq, yum_basecmd, conf_file, en_repos, dis_repos, in
elif '://' in spec: elif '://' in spec:
# download package so that we can check if it's already installed # download package so that we can check if it's already installed
package = fetch_rpm_from_url(spec, module=module) package = fetch_rpm_from_url(spec, module=module)
envra = local_envra(module, package) envra = local_envra(package)
# local rpm files can't be updated # local rpm files can't be updated
if not is_installed(module, repoq, envra, conf_file, en_repos=en_repos, dis_repos=dis_repos, installroot=installroot): if not is_installed(module, repoq, envra, conf_file, en_repos=en_repos, dis_repos=dis_repos, installroot=installroot):
@ -1036,7 +1043,7 @@ def latest(module, items, repoq, yum_basecmd, conf_file, en_repos, dis_repos, in
if not pkglist: if not pkglist:
res['msg'] += "No package matching '%s' found available, installed or updated" % spec res['msg'] += "No package matching '%s' found available, installed or updated" % spec
res['results'].append("No package matching '%s' found available, installed or updated" % spec) res['results'].append("No package matching '%s' found available, installed or updated" % spec)
res['rc'] = 126 # Ensure the task fails in with-loop res['rc'] = 126 # Ensure the task fails in with-loop
module.fail_json(**res) module.fail_json(**res)
nothing_to_do = True nothing_to_do = True
@ -1045,7 +1052,6 @@ def latest(module, items, repoq, yum_basecmd, conf_file, en_repos, dis_repos, in
nothing_to_do = False nothing_to_do = False
break break
# this contains the full NVR and spec could contain wildcards # this contains the full NVR and spec could contain wildcards
# or virtual provides (like "python-*" or "smtp-daemon") while # or virtual provides (like "python-*" or "smtp-daemon") while
# updates contains name only. # updates contains name only.
@ -1067,10 +1073,10 @@ def latest(module, items, repoq, yum_basecmd, conf_file, en_repos, dis_repos, in
# if any of the packages are involved in a transaction, fail now # if any of the packages are involved in a transaction, fail now
# so that we don't hang on the yum operation later # so that we don't hang on the yum operation later
conflicts = transaction_exists(pkglist) conflicts = transaction_exists(pkglist)
if len(conflicts) > 0: if conflicts:
res['msg'] += "The following packages have pending transactions: %s" % ", ".join(conflicts) res['msg'] += "The following packages have pending transactions: %s" % ", ".join(conflicts)
res['results'].append("The following packages have pending transactions: %s" % ", ".join(conflicts)) res['results'].append("The following packages have pending transactions: %s" % ", ".join(conflicts))
res['rc'] = 128 # Ensure the task fails in with-loop res['rc'] = 128 # Ensure the task fails in with-loop
module.fail_json(**res) module.fail_json(**res)
# check_mode output # check_mode output
@ -1090,7 +1096,7 @@ def latest(module, items, repoq, yum_basecmd, conf_file, en_repos, dis_repos, in
res['changes'] = dict(installed=pkgs['install'], updated=to_update) res['changes'] = dict(installed=pkgs['install'], updated=to_update)
if len(will_update) > 0 or len(pkgs['install']) > 0: if will_update or pkgs['install']:
res['changed'] = True res['changed'] = True
return res return res
@ -1099,7 +1105,7 @@ def latest(module, items, repoq, yum_basecmd, conf_file, en_repos, dis_repos, in
if cmd: # update all if cmd: # update all
rc, out, err = module.run_command(cmd) rc, out, err = module.run_command(cmd)
res['changed'] = True res['changed'] = True
elif len(pkgs['install']) or len(will_update): elif pkgs['install'] or will_update:
cmd = yum_basecmd + ['install'] + pkgs['install'] + pkgs['update'] cmd = yum_basecmd + ['install'] + pkgs['install'] + pkgs['update']
rc, out, err = module.run_command(cmd) rc, out, err = module.run_command(cmd)
out_lower = out.strip().lower() out_lower = out.strip().lower()
@ -1118,6 +1124,7 @@ def latest(module, items, repoq, yum_basecmd, conf_file, en_repos, dis_repos, in
return res return res
def ensure(module, state, pkgs, conf_file, enablerepo, disablerepo, def ensure(module, state, pkgs, conf_file, enablerepo, disablerepo,
disable_gpg_check, exclude, repoq, skip_broken, security, disable_gpg_check, exclude, repoq, skip_broken, security,
installroot='/', allow_downgrade=False): installroot='/', allow_downgrade=False):
@ -1203,9 +1210,9 @@ def ensure(module, state, pkgs, conf_file, enablerepo, disablerepo,
my.repos.enableRepo(enablerepo) my.repos.enableRepo(enablerepo)
new_repos = my.repos.repos.keys() new_repos = my.repos.repos.keys()
for i in new_repos: for i in new_repos:
if not i in current_repos: if i not in current_repos:
rid = my.repos.getRepo(i) rid = my.repos.getRepo(i)
a = rid.repoXML.repoid # nopep8 - https://github.com/ansible/ansible/pull/21475#pullrequestreview-22404868 a = rid.repoXML.repoid # nopep8 - https://github.com/ansible/ansible/pull/21475#pullrequestreview-22404868
current_repos = new_repos current_repos = new_repos
except yum.Errors.YumBaseError as e: except yum.Errors.YumBaseError as e:
module.fail_json(msg="Error setting/accessing repos: %s" % to_native(e)) module.fail_json(msg="Error setting/accessing repos: %s" % to_native(e))
@ -1231,7 +1238,6 @@ def ensure(module, state, pkgs, conf_file, enablerepo, disablerepo,
def main(): def main():
# state=installed name=pkgspec # state=installed name=pkgspec
# state=removed name=pkgspec # state=removed name=pkgspec
# state=latest name=pkgspec # state=latest name=pkgspec
@ -1248,9 +1254,7 @@ def main():
name=dict(aliases=['pkg'], type="list"), name=dict(aliases=['pkg'], type="list"),
exclude=dict(required=False, default=None), exclude=dict(required=False, default=None),
# removed==absent, installed==present, these are accepted as aliases # removed==absent, installed==present, these are accepted as aliases
state=dict(default='installed', choices=['absent', 'present', state=dict(default='installed', choices=['absent', 'present', 'installed', 'removed', 'latest']),
'installed', 'removed',
'latest']),
enablerepo=dict(), enablerepo=dict(),
disablerepo=dict(), disablerepo=dict(),
list=dict(), list=dict(),
@ -1288,7 +1292,6 @@ def main():
results = {'results': list_stuff(module, repoquerybin, params['conf_file'], results = {'results': list_stuff(module, repoquerybin, params['conf_file'],
params['list'], params['installroot'], params['list'], params['installroot'],
params['disablerepo'], params['enablerepo'])} params['disablerepo'], params['enablerepo'])}
else: else:
# If rhn-plugin is installed and no rhn-certificate is available on # If rhn-plugin is installed and no rhn-certificate is available on
# the system then users will see an error message using the yum API. # the system then users will see an error message using the yum API.
@ -1325,7 +1328,7 @@ def main():
skip_broken, security, params['installroot'], allow_downgrade) skip_broken, security, params['installroot'], allow_downgrade)
if repoquery: if repoquery:
results['msg'] = '%s %s' % (results.get('msg', ''), 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.') 'Warning: Due to potential bad behaviour with rhnplugin and certificates, used slower repoquery calls instead of Yum API.')
module.exit_json(**results) module.exit_json(**results)