2012-03-10 00:33:58 +01:00
#!/usr/bin/python -tt
2012-08-03 03:29:10 +02:00
# -*- coding: utf-8 -*-
2012-03-10 00:33:58 +01:00
# (c) 2012, Red Hat, Inc
# Written by Seth Vidal <skvidal at fedoraproject.org>
2014-02-17 00:06:46 +01:00
# (c) 2014, Epic Games, Inc.
2012-03-10 00:33:58 +01:00
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
#
2012-08-02 07:47:48 +02:00
import os
2012-08-14 00:13:50 +02:00
import yum
2015-01-11 04:27:10 +01:00
import rpm
2015-05-23 05:16:56 +02:00
import platform
import tempfile
import shutil
from distutils . version import LooseVersion
2012-08-14 00:13:50 +02:00
2014-01-22 21:29:50 +01:00
try :
from yum . misc import find_unfinished_transactions , find_ts_remaining
from rpmUtils . miscutils import splitFilename
transaction_helpers = True
except :
transaction_helpers = False
2012-09-29 00:49:02 +02:00
DOCUMENTATION = '''
- - -
module : yum
2013-11-19 00:55:49 +01:00
version_added : historical
2012-09-29 00:49:02 +02:00
short_description : Manages packages with the I ( yum ) package manager
description :
2014-03-24 18:27:32 +01:00
- Installs , upgrade , removes , and lists packages and groups with the I ( yum ) package manager .
2012-09-29 00:49:02 +02:00
options :
name :
description :
2015-06-03 15:48:19 +02:00
- " Package name, or package specifier with version, like C(name-1.0). When using state=latest, this can be ' * ' which means run: yum -y update. You can also pass a url or a local path to a rpm file (using state=present). To operate on several packages this can accept a comma separated list of packages or (as of 2.0) a list of packages. "
2012-09-29 00:49:02 +02:00
required : true
default : null
2015-11-24 00:42:40 +01:00
aliases : [ ' pkg ' ]
2014-11-12 01:49:56 +01:00
exclude :
description :
2015-05-05 22:58:41 +02:00
- " Package name(s) to exclude when state=present, or latest "
2014-11-12 01:49:56 +01:00
required : false
version_added : " 2.0 "
default : null
2012-09-29 00:49:02 +02:00
list :
description :
2013-12-26 19:46:09 +01:00
- Various ( non - idempotent ) commands for usage with C ( / usr / bin / ansible ) and I ( not ) playbooks . See examples .
2012-09-29 00:49:02 +02:00
required : false
default : null
state :
description :
2015-11-24 00:42:40 +01:00
- Whether to install ( C ( present ) or C ( installed ) , C ( latest ) ) , or remove ( C ( absent ) or C ( removed ) ) a package .
2012-09-29 00:49:02 +02:00
required : false
2015-11-24 00:42:40 +01:00
choices : [ " present " , " installed " , " latest " , " absent " , " removed " ]
2012-09-29 00:49:02 +02:00
default : " present "
2012-10-24 06:21:24 +02:00
enablerepo :
description :
2014-05-16 15:22:12 +02:00
- I ( Repoid ) of repositories to enable for the install / update operation .
These repos will not persist beyond the transaction .
2014-05-16 15:44:32 +02:00
When specifying multiple repos , separate them with a " , " .
2012-10-24 06:21:24 +02:00
required : false
2012-11-22 15:16:20 +01:00
version_added : " 0.9 "
2012-10-24 06:21:24 +02:00
default : null
aliases : [ ]
2015-04-21 19:05:54 +02:00
2012-10-24 06:21:24 +02:00
disablerepo :
description :
2014-05-16 15:22:12 +02:00
- I ( Repoid ) of repositories to disable for the install / update operation .
These repos will not persist beyond the transaction .
2014-05-16 15:44:32 +02:00
When specifying multiple repos , separate them with a " , " .
2012-10-24 06:21:24 +02:00
required : false
2012-11-22 15:16:20 +01:00
version_added : " 0.9 "
2012-10-24 06:21:24 +02:00
default : null
aliases : [ ]
2013-04-23 18:12:37 +02:00
conf_file :
description :
- The remote yum configuration file to use for the transaction .
required : false
2013-11-28 03:23:03 +01:00
version_added : " 0.6 "
2013-04-23 18:12:37 +02:00
default : null
aliases : [ ]
disable_gpg_check :
description :
- Whether to disable the GPG checking of signatures of packages being
installed . Has an effect only if state is I ( present ) or I ( latest ) .
required : false
version_added : " 1.2 "
default : " no "
choices : [ " yes " , " no " ]
aliases : [ ]
2014-02-27 18:18:25 +01:00
2014-09-28 20:30:39 +02:00
update_cache :
description :
- Force updating the cache . Has an effect only if state is I ( present )
or I ( latest ) .
required : false
version_added : " 1.9 "
default : " no "
choices : [ " yes " , " no " ]
aliases : [ ]
2015-11-29 20:51:22 +01:00
validate_certs :
description :
- This only applies if using a https url as the source of the rpm . e . g . for localinstall . If set to C ( no ) , the SSL certificates will not be validated .
- This should only set to C ( no ) used on personally controlled sites using self - signed certificates as it avoids verifying the source site .
- Prior to 2.1 the code worked as if this was set to C ( yes ) .
required : false
default : " yes "
choices : [ " yes " , " no " ]
version_added : " 2.1 "
2015-07-09 17:16:17 +02:00
notes :
- When used with a loop of package names in a playbook , ansible optimizes
the call to the yum module . Instead of calling the module with a single
package each time through the loop , ansible calls the module once with all
of the package names from the loop .
- In versions prior to 1.9 .2 this module installed and removed each package
given to the yum module separately . This caused problems when packages
specified by filename or url had to be installed or removed together . In
1.9 .2 this was fixed so that packages are installed in one yum
transaction . However , if one of the packages adds a new yum repository
that the other packages come from ( such as epel - release ) then that package
needs to be installed in a separate task . This mimics yum ' s command line
behaviour .
2015-10-26 16:36:30 +01:00
- ' Yum itself has two types of groups. " Package groups " are specified in the
rpm itself while " environment groups " are specified in a separate file
( usually by the distribution ) . Unfortunately , this division becomes
apparent to ansible users because ansible needs to operate on the group
of packages in a single transaction and yum requires groups to be specified
in different ways when used in that way . Package groups are specified as
2015-10-27 20:51:48 +01:00
" @development-tools " and environment groups are " @^gnome-desktop-environment " .
2015-10-26 16:36:30 +01:00
Use the " yum group list " command to see which category of group the group
you want to install falls into . '
2012-09-29 00:49:02 +02:00
# informational: requirements for nodes
2015-01-11 04:27:10 +01:00
requirements : [ yum ]
2015-07-09 17:16:17 +02:00
author :
2015-06-15 21:53:30 +02:00
- " Ansible Core Team "
- " Seth Vidal "
2012-09-29 00:49:02 +02:00
'''
2013-06-14 11:53:43 +02:00
EXAMPLES = '''
2013-12-26 19:46:09 +01:00
- name : install the latest version of Apache
yum : name = httpd state = latest
- name : remove the Apache package
2014-06-25 16:21:43 +02:00
yum : name = httpd state = absent
2013-12-26 19:46:09 +01:00
2014-03-07 20:53:31 +01:00
- name : install the latest version of Apache from the testing repo
2014-06-25 16:21:43 +02:00
yum : name = httpd enablerepo = testing state = present
2013-12-26 19:46:09 +01:00
2015-01-28 15:29:29 +01:00
- name : install one specific version of Apache
yum : name = httpd - 2.2 .29 - 1.4 . amzn1 state = present
2013-12-26 19:46:09 +01:00
- name : upgrade all packages
yum : name = * state = latest
- name : install the nginx rpm from a remote repo
yum : name = http : / / nginx . org / packages / centos / 6 / noarch / RPMS / nginx - release - centos - 6 - 0. el6 . ngx . noarch . rpm state = present
- name : install nginx rpm from a local file
yum : name = / usr / local / src / nginx - release - centos - 6 - 0. el6 . ngx . noarch . rpm state = present
- name : install the ' Development tools ' package group
yum : name = " @Development tools " state = present
2015-10-26 16:36:30 +01:00
- name : install the ' Gnome desktop ' environment group
yum : name = " @^gnome-desktop-environment " state = present
2013-06-14 11:53:43 +02:00
'''
2015-06-24 17:12:49 +02:00
# 64k. Number of bytes to read at a time when manually downloading pkgs via a url
BUFSIZE = 65536
2012-08-02 07:47:48 +02:00
def_qf = " % {name} - % {version} - % {release} . % {arch} "
2015-12-13 18:16:28 +01:00
rpmbin = None
2012-08-15 01:33:11 +02:00
2015-01-12 01:02:29 +01:00
def yum_base ( conf_file = None ) :
2012-08-15 01:33:11 +02:00
2012-08-14 00:13:50 +02:00
my = yum . YumBase ( )
my . preconf . debuglevel = 0
my . preconf . errorlevel = 0
2015-12-09 18:59:16 +01:00
my . preconf . plugins = True
2012-08-14 00:13:50 +02:00
if conf_file and os . path . exists ( conf_file ) :
my . preconf . fn = conf_file
2015-06-16 15:57:32 +02:00
if os . geteuid ( ) != 0 :
if hasattr ( my , ' setCacheDir ' ) :
my . setCacheDir ( )
else :
cachedir = yum . misc . getCacheDir ( )
my . repos . setCacheDir ( cachedir )
my . conf . cache = 0
2012-08-14 00:13:50 +02:00
return my
2015-06-15 18:51:15 +02:00
def ensure_yum_utils ( module ) :
2014-02-27 18:18:25 +01:00
2015-06-15 18:51:15 +02:00
repoquerybin = module . get_bin_path ( ' repoquery ' , required = False )
if module . params [ ' install_repoquery ' ] and not repoquerybin and not module . check_mode :
2014-02-27 18:18:25 +01:00
yum_path = module . get_bin_path ( ' yum ' )
if yum_path :
2015-06-15 18:51:15 +02:00
rc , so , se = module . run_command ( ' %s -y install yum-utils ' % yum_path )
repoquerybin = module . get_bin_path ( ' repoquery ' , required = False )
return repoquerybin
2014-02-27 18:18:25 +01:00
2012-08-14 00:13:50 +02:00
def po_to_nevra ( po ) :
2012-08-15 01:33:11 +02:00
2012-08-14 00:13:50 +02:00
if hasattr ( po , ' ui_nevra ' ) :
return po . ui_nevra
else :
return ' %s - %s - %s . %s ' % ( po . name , po . version , po . release , po . arch )
2015-05-20 20:46:39 +02:00
def is_installed ( module , repoq , pkgspec , conf_file , qf = def_qf , en_repos = None , dis_repos = None , is_pkg = False ) :
if en_repos is None :
en_repos = [ ]
if dis_repos is None :
dis_repos = [ ]
2012-08-15 01:33:11 +02:00
2015-12-13 18:16:28 +01:00
if not repoq :
2012-08-14 00:13:50 +02:00
pkgs = [ ]
try :
my = yum_base ( conf_file )
2012-10-24 06:21:24 +02:00
for rid in dis_repos :
my . repos . disableRepo ( rid )
2015-03-27 17:07:51 +01:00
for rid in en_repos :
my . repos . enableRepo ( rid )
2015-12-13 18:16:28 +01:00
2015-07-01 23:14:55 +02:00
e , m , u = my . rpmdb . matchPackageNames ( [ pkgspec ] )
2012-08-14 00:13:50 +02:00
pkgs = e + m
2015-12-13 18:16:28 +01:00
if not pkgs and not is_pkg :
2012-08-14 00:13:50 +02:00
pkgs . extend ( my . returnInstalledPackagesByDep ( pkgspec ) )
2016-05-20 16:48:10 +02:00
except Exception :
e = get_exception ( )
2012-08-14 00:13:50 +02:00
module . fail_json ( msg = " Failure talking to yum: %s " % e )
return [ po_to_nevra ( p ) for p in pkgs ]
2012-08-15 01:33:11 +02:00
2012-08-14 00:13:50 +02:00
else :
2015-12-13 18:16:28 +01:00
global rpmbin
if not rpmbin :
rpmbin = module . get_bin_path ( ' rpm ' , required = True )
2012-08-15 01:33:11 +02:00
2015-12-13 18:16:28 +01:00
cmd = [ rpmbin , ' -q ' , ' --qf ' , qf , pkgspec ]
2016-01-20 21:09:32 +01:00
# rpm localizes messages and we're screen scraping so make sure we use
# the C locale
lang_env = dict ( LANG = ' C ' , LC_ALL = ' C ' , LC_MESSAGES = ' C ' )
rc , out , err = module . run_command ( cmd , environ_update = lang_env )
2015-12-13 18:16:28 +01:00
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 ]
2016-01-20 21:09:32 +01:00
rc2 , out2 , err2 = module . run_command ( cmd , environ_update = lang_env )
2013-07-04 23:32:09 +02:00
else :
2015-07-01 23:14:55 +02:00
rc2 , out2 , err2 = ( 0 , ' ' , ' ' )
2015-12-13 18:16:28 +01:00
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
2012-08-02 07:47:48 +02:00
return [ ]
2015-05-20 20:46:39 +02:00
def is_available ( module , repoq , pkgspec , conf_file , qf = def_qf , en_repos = None , dis_repos = None ) :
if en_repos is None :
en_repos = [ ]
if dis_repos is None :
dis_repos = [ ]
2012-08-15 01:33:11 +02:00
2012-08-14 00:13:50 +02:00
if not repoq :
2012-08-15 01:33:11 +02:00
2012-08-14 00:13:50 +02:00
pkgs = [ ]
try :
my = yum_base ( conf_file )
2012-10-24 06:21:24 +02:00
for rid in dis_repos :
my . repos . disableRepo ( rid )
2015-03-27 17:07:51 +01:00
for rid in en_repos :
my . repos . enableRepo ( rid )
2012-10-24 06:21:24 +02:00
2012-08-14 00:13:50 +02:00
e , m , u = my . pkgSack . matchPackageNames ( [ pkgspec ] )
pkgs = e + m
if not pkgs :
pkgs . extend ( my . returnPackagesByDep ( pkgspec ) )
2016-05-20 16:48:10 +02:00
except Exception :
e = get_exception ( )
2012-08-14 00:13:50 +02:00
module . fail_json ( msg = " Failure talking to yum: %s " % e )
return [ po_to_nevra ( p ) for p in pkgs ]
2012-08-15 01:33:11 +02:00
2012-08-14 00:13:50 +02:00
else :
2013-02-01 22:47:53 +01:00
myrepoq = list ( repoq )
2014-02-25 20:52:45 +01:00
2014-09-30 01:33:40 +02:00
r_cmd = [ ' --disablerepo ' , ' , ' . join ( dis_repos ) ]
myrepoq . extend ( r_cmd )
2013-02-01 22:47:53 +01:00
2014-09-30 01:33:40 +02:00
r_cmd = [ ' --enablerepo ' , ' , ' . join ( en_repos ) ]
myrepoq . extend ( r_cmd )
2012-08-15 01:33:11 +02:00
2013-02-01 22:47:53 +01:00
cmd = myrepoq + [ " --qf " , qf , pkgspec ]
Update modules to use run_command in module_common.py
This updates apt, apt_repository, command, cron, easy_install, facter,
fireball, git, group, mount, ohai, pip, service, setup, subversion,
supervisorctl, svr4pkg, user, and yum to take advantage of run_command
in module_common.py.
2013-01-12 07:10:21 +01:00
rc , out , err = module . run_command ( cmd )
2012-08-14 00:13:50 +02:00
if rc == 0 :
return [ p for p in out . split ( ' \n ' ) if p . strip ( ) ]
else :
2013-01-31 23:23:10 +01:00
module . fail_json ( msg = ' Error from repoquery: %s : %s ' % ( cmd , err ) )
2012-10-24 06:46:15 +02:00
2012-08-02 07:47:48 +02:00
return [ ]
2015-05-20 20:46:39 +02:00
def is_update ( module , repoq , pkgspec , conf_file , qf = def_qf , en_repos = None , dis_repos = None ) :
if en_repos is None :
en_repos = [ ]
if dis_repos is None :
dis_repos = [ ]
2012-08-15 01:33:11 +02:00
2012-08-14 00:13:50 +02:00
if not repoq :
2012-08-15 01:33:11 +02:00
2012-08-14 00:13:50 +02:00
retpkgs = [ ]
pkgs = [ ]
updates = [ ]
2012-08-15 01:33:11 +02:00
2012-08-14 00:13:50 +02:00
try :
my = yum_base ( conf_file )
2012-10-24 06:21:24 +02:00
for rid in dis_repos :
my . repos . disableRepo ( rid )
2015-03-27 17:07:51 +01:00
for rid in en_repos :
my . repos . enableRepo ( rid )
2012-10-24 06:21:24 +02:00
2012-08-14 00:13:50 +02:00
pkgs = my . returnPackagesByDep ( pkgspec ) + my . returnInstalledPackagesByDep ( pkgspec )
if not pkgs :
e , m , u = my . pkgSack . matchPackageNames ( [ pkgspec ] )
pkgs = e + m
updates = my . doPackageLists ( pkgnarrow = ' updates ' ) . updates
2016-05-20 16:48:10 +02:00
except Exception :
e = get_exception ( )
2012-08-14 00:13:50 +02:00
module . fail_json ( msg = " Failure talking to yum: %s " % e )
for pkg in pkgs :
if pkg in updates :
retpkgs . append ( pkg )
return set ( [ po_to_nevra ( p ) for p in retpkgs ] )
2012-08-07 02:07:02 +02:00
2012-08-14 00:13:50 +02:00
else :
2013-02-01 22:47:53 +01:00
myrepoq = list ( repoq )
2014-09-30 01:33:40 +02:00
r_cmd = [ ' --disablerepo ' , ' , ' . join ( dis_repos ) ]
myrepoq . extend ( r_cmd )
2013-02-01 18:39:02 +01:00
2014-09-30 01:33:40 +02:00
r_cmd = [ ' --enablerepo ' , ' , ' . join ( en_repos ) ]
myrepoq . extend ( r_cmd )
2012-08-15 01:33:11 +02:00
2013-02-01 22:47:53 +01:00
cmd = myrepoq + [ " --pkgnarrow=updates " , " --qf " , qf , pkgspec ]
Update modules to use run_command in module_common.py
This updates apt, apt_repository, command, cron, easy_install, facter,
fireball, git, group, mount, ohai, pip, service, setup, subversion,
supervisorctl, svr4pkg, user, and yum to take advantage of run_command
in module_common.py.
2013-01-12 07:10:21 +01:00
rc , out , err = module . run_command ( cmd )
2012-08-14 00:13:50 +02:00
if rc == 0 :
return set ( [ p for p in out . split ( ' \n ' ) if p . strip ( ) ] )
else :
2013-01-31 23:23:10 +01:00
module . fail_json ( msg = ' Error from repoquery: %s : %s ' % ( cmd , err ) )
2012-08-14 00:13:50 +02:00
2015-06-15 18:51:15 +02:00
return set ( )
2012-08-02 07:47:48 +02:00
2015-05-20 20:46:39 +02:00
def what_provides ( module , repoq , req_spec , conf_file , qf = def_qf , en_repos = None , dis_repos = None ) :
if en_repos is None :
en_repos = [ ]
if dis_repos is None :
dis_repos = [ ]
2012-08-15 01:33:11 +02:00
2012-08-14 00:13:50 +02:00
if not repoq :
2012-08-15 01:33:11 +02:00
2012-08-14 00:13:50 +02:00
pkgs = [ ]
try :
my = yum_base ( conf_file )
2012-10-24 06:21:24 +02:00
for rid in dis_repos :
my . repos . disableRepo ( rid )
2015-03-27 17:07:51 +01:00
for rid in en_repos :
my . repos . enableRepo ( rid )
2012-10-24 06:21:24 +02:00
2012-08-14 00:13:50 +02:00
pkgs = my . returnPackagesByDep ( req_spec ) + my . returnInstalledPackagesByDep ( req_spec )
if not pkgs :
e , m , u = my . pkgSack . matchPackageNames ( [ req_spec ] )
pkgs . extend ( e )
pkgs . extend ( m )
e , m , u = my . rpmdb . matchPackageNames ( [ req_spec ] )
pkgs . extend ( e )
pkgs . extend ( m )
2016-05-20 16:48:10 +02:00
except Exception :
e = get_exception ( )
2012-08-14 00:13:50 +02:00
module . fail_json ( msg = " Failure talking to yum: %s " % e )
return set ( [ po_to_nevra ( p ) for p in pkgs ] )
2012-08-15 01:33:11 +02:00
2012-08-14 00:13:50 +02:00
else :
2013-02-01 22:47:53 +01:00
myrepoq = list ( repoq )
2014-09-30 01:33:40 +02:00
r_cmd = [ ' --disablerepo ' , ' , ' . join ( dis_repos ) ]
myrepoq . extend ( r_cmd )
2013-02-01 18:39:02 +01:00
2014-09-30 01:33:40 +02:00
r_cmd = [ ' --enablerepo ' , ' , ' . join ( en_repos ) ]
myrepoq . extend ( r_cmd )
2014-02-25 20:52:45 +01:00
2013-02-01 22:47:53 +01:00
cmd = myrepoq + [ " --qf " , qf , " --whatprovides " , req_spec ]
Update modules to use run_command in module_common.py
This updates apt, apt_repository, command, cron, easy_install, facter,
fireball, git, group, mount, ohai, pip, service, setup, subversion,
supervisorctl, svr4pkg, user, and yum to take advantage of run_command
in module_common.py.
2013-01-12 07:10:21 +01:00
rc , out , err = module . run_command ( cmd )
2013-02-01 22:47:53 +01:00
cmd = myrepoq + [ " --qf " , qf , req_spec ]
Update modules to use run_command in module_common.py
This updates apt, apt_repository, command, cron, easy_install, facter,
fireball, git, group, mount, ohai, pip, service, setup, subversion,
supervisorctl, svr4pkg, user, and yum to take advantage of run_command
in module_common.py.
2013-01-12 07:10:21 +01:00
rc2 , out2 , err2 = module . run_command ( cmd )
2012-08-14 00:13:50 +02:00
if rc == 0 and rc2 == 0 :
out + = out2
2012-10-19 22:28:39 +02:00
pkgs = set ( [ p for p in out . split ( ' \n ' ) if p . strip ( ) ] )
if not pkgs :
pkgs = is_installed ( module , repoq , req_spec , conf_file , qf = qf )
return pkgs
2012-08-14 00:13:50 +02:00
else :
2012-10-24 06:46:15 +02:00
module . fail_json ( msg = ' Error from repoquery: %s : %s ' % ( cmd , err + err2 ) )
2015-06-15 18:51:15 +02:00
return set ( )
2012-03-10 00:33:58 +01:00
2014-01-22 21:29:50 +01:00
def transaction_exists ( pkglist ) :
"""
checks the package list to see if any packages are
involved in an incomplete transaction
"""
conflicts = [ ]
if not transaction_helpers :
return conflicts
# first, we create a list of the package 'nvreas'
# so we can compare the pieces later more easily
pkglist_nvreas = [ ]
for pkg in pkglist :
pkglist_nvreas . append ( splitFilename ( pkg ) )
# next, we build the list of packages that are
# contained within an unfinished transaction
unfinished_transactions = find_unfinished_transactions ( )
for trans in unfinished_transactions :
steps = find_ts_remaining ( trans )
for step in steps :
# the action is install/erase/etc., but we only
# care about the package spec contained in the step
( action , step_spec ) = step
( n , v , r , e , a ) = splitFilename ( step_spec )
# and see if that spec is in the list of packages
# requested for installation/updating
for pkg in pkglist_nvreas :
# if the name and arch match, we're going to assume
# this package is part of a pending transaction
# the label is just for display purposes
label = " %s - %s " % ( n , a )
if n == pkg [ 0 ] and a == pkg [ 4 ] :
if label not in conflicts :
conflicts . append ( " %s - %s " % ( n , a ) )
break
return conflicts
2013-01-22 05:27:07 +01:00
def local_nvra ( module , path ) :
2012-08-14 22:23:40 +02:00
""" return nvra of a local rpm passed in """
2015-01-11 04:27:10 +01:00
ts = rpm . TransactionSet ( )
ts . setVSFlags ( rpm . _RPMVSF_NOSIGNATURES )
fd = os . open ( path , os . O_RDONLY )
try :
header = ts . hdrFromFdno ( fd )
finally :
os . close ( fd )
return ' %s - %s - %s . %s ' % ( header [ rpm . RPMTAG_NAME ] ,
header [ rpm . RPMTAG_VERSION ] ,
header [ rpm . RPMTAG_RELEASE ] ,
header [ rpm . RPMTAG_ARCH ] )
2012-08-14 22:23:40 +02:00
2016-03-23 23:59:36 +01:00
def local_name ( module , path ) :
""" return package name of a local rpm passed in """
ts = rpm . TransactionSet ( )
ts . setVSFlags ( rpm . _RPMVSF_NOSIGNATURES )
fd = os . open ( path , os . O_RDONLY )
try :
header = ts . hdrFromFdno ( fd )
finally :
os . close ( fd )
return header [ rpm . RPMTAG_NAME ]
2012-08-02 07:47:48 +02:00
def pkg_to_dict ( pkgstr ) :
2012-08-15 01:33:11 +02:00
2012-08-02 07:47:48 +02:00
if pkgstr . strip ( ) :
n , e , v , r , a , repo = pkgstr . split ( ' | ' )
else :
return { ' error_parsing ' : pkgstr }
2012-08-07 02:07:02 +02:00
2012-03-10 00:33:58 +01:00
d = {
2012-08-02 07:47:48 +02:00
' name ' : n ,
' arch ' : a ,
' epoch ' : e ,
' release ' : r ,
' version ' : v ,
' repo ' : repo ,
' nevra ' : ' %s : %s - %s - %s . %s ' % ( e , n , v , r , a )
2012-08-12 00:13:29 +02:00
}
2012-08-07 02:07:02 +02:00
2012-08-02 07:47:48 +02:00
if repo == ' installed ' :
2012-03-10 04:06:44 +01:00
d [ ' yumstate ' ] = ' installed '
2012-03-10 00:33:58 +01:00
else :
2012-03-10 04:06:44 +01:00
d [ ' yumstate ' ] = ' available '
2012-08-02 07:47:48 +02:00
return d
2013-01-22 16:27:08 +01:00
def repolist ( module , repoq , qf = " % {repoid} " ) :
2012-08-15 01:33:11 +02:00
2012-08-09 16:12:22 +02:00
cmd = repoq + [ " --qf " , qf , " -a " ]
Update modules to use run_command in module_common.py
This updates apt, apt_repository, command, cron, easy_install, facter,
fireball, git, group, mount, ohai, pip, service, setup, subversion,
supervisorctl, svr4pkg, user, and yum to take advantage of run_command
in module_common.py.
2013-01-12 07:10:21 +01:00
rc , out , err = module . run_command ( cmd )
2012-08-02 07:47:48 +02:00
ret = [ ]
if rc == 0 :
ret = set ( [ p for p in out . split ( ' \n ' ) if p . strip ( ) ] )
return ret
2012-08-07 02:07:02 +02:00
2015-06-14 02:08:32 +02:00
def list_stuff ( module , repoquerybin , conf_file , stuff ) :
2012-08-15 01:33:11 +02:00
2012-08-02 07:47:48 +02:00
qf = " % {name} | % {epoch} | % {version} | % {release} | % {arch} | % {repoid} "
2015-12-13 18:16:28 +01:00
# 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 "
2015-06-14 02:08:32 +02:00
repoq = [ repoquerybin , ' --show-duplicates ' , ' --plugins ' , ' --quiet ' ]
2012-08-02 07:47:48 +02:00
if conf_file and os . path . exists ( conf_file ) :
2012-08-09 16:12:22 +02:00
repoq + = [ ' -c ' , conf_file ]
2012-03-10 00:33:58 +01:00
if stuff == ' installed ' :
2015-12-13 18:16:28 +01:00
return [ pkg_to_dict ( p ) for p in sorted ( is_installed ( module , repoq , ' -a ' , conf_file , qf = is_installed_qf ) ) if p . strip ( ) ]
2012-03-10 00:33:58 +01:00
elif stuff == ' updates ' :
2015-12-13 18:16:28 +01:00
return [ pkg_to_dict ( p ) for p in sorted ( is_update ( module , repoq , ' -a ' , conf_file , qf = qf ) ) if p . strip ( ) ]
2012-03-10 00:33:58 +01:00
elif stuff == ' available ' :
2015-12-13 18:16:28 +01:00
return [ pkg_to_dict ( p ) for p in sorted ( is_available ( module , repoq , ' -a ' , conf_file , qf = qf ) ) if p . strip ( ) ]
2012-03-10 00:33:58 +01:00
elif stuff == ' repos ' :
2015-12-13 18:16:28 +01:00
return [ dict ( repoid = name , state = ' enabled ' ) for name in sorted ( repolist ( module , repoq ) ) if name . strip ( ) ]
2012-03-10 00:33:58 +01:00
else :
2015-12-13 18:16:28 +01:00
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 ( ) ]
2012-03-10 00:33:58 +01:00
2012-10-24 06:21:24 +02:00
def install ( module , items , repoq , yum_basecmd , conf_file , en_repos , dis_repos ) :
2012-08-15 01:33:11 +02:00
2015-06-11 13:39:42 +02:00
pkgs = [ ]
2012-03-12 21:31:13 +01:00
res = { }
2012-08-02 23:02:37 +02:00
res [ ' results ' ] = [ ]
2012-08-02 07:47:48 +02:00
res [ ' msg ' ] = ' '
res [ ' rc ' ] = 0
res [ ' changed ' ] = False
2015-05-23 05:16:56 +02:00
tempdir = tempfile . mkdtemp ( )
2014-03-07 20:53:31 +01:00
2012-08-02 07:47:48 +02:00
for spec in items :
pkg = None
# check if pkgspec is installed (if possible for idempotence)
# localpkg
2013-04-08 11:54:27 +02:00
if spec . endswith ( ' .rpm ' ) and ' :// ' not in spec :
2012-08-07 02:07:02 +02:00
# get the pkg name-v-r.arch
2012-08-24 19:51:07 +02:00
if not os . path . exists ( spec ) :
res [ ' msg ' ] + = " No Package file matching ' %s ' found on system " % spec
module . fail_json ( * * res )
2016-03-23 23:59:36 +01:00
pkg_name = local_name ( module , spec )
2012-08-02 07:47:48 +02:00
# look for them in the rpmdb
2016-03-23 23:59:36 +01:00
if is_installed ( module , repoq , pkg_name , conf_file , en_repos = en_repos , dis_repos = dis_repos ) :
2012-08-02 07:47:48 +02:00
# if they are there, skip it
continue
pkg = spec
2013-04-08 11:54:27 +02:00
# URL
elif ' :// ' in spec :
2016-03-23 23:59:36 +01:00
# download package so that we can check if it's already installed
package = os . path . join ( tempdir , str ( spec . rsplit ( ' / ' , 1 ) [ 1 ] ) )
try :
rsp , info = fetch_url ( module , spec )
f = open ( package , ' w ' )
data = rsp . read ( BUFSIZE )
while data :
f . write ( data )
2015-06-24 17:12:49 +02:00
data = rsp . read ( BUFSIZE )
2016-03-23 23:59:36 +01:00
f . close ( )
2016-05-20 16:48:10 +02:00
except Exception :
e = get_exception ( )
2016-03-23 23:59:36 +01:00
shutil . rmtree ( tempdir )
module . fail_json ( msg = " Failure downloading %s , %s " % ( spec , e ) )
pkg_name = local_name ( module , package )
if is_installed ( module , repoq , pkg_name , conf_file , en_repos = en_repos , dis_repos = dis_repos ) :
# if it's there, skip it
continue
pkg = package
2013-04-08 11:54:27 +02:00
2012-08-02 07:47:48 +02:00
#groups :(
2015-07-01 23:14:55 +02:00
elif spec . startswith ( ' @ ' ) :
2012-08-02 07:47:48 +02:00
# complete wild ass guess b/c it's a group
pkg = spec
# range requires or file-requires or pkgname :(
2012-03-14 05:38:38 +01:00
else :
2013-07-04 23:32:09 +02:00
# most common case is the pkg is already installed and done
# short circuit all the bs - and search for it as a pkg in is_installed
# if you find it then we're done
if not set ( [ ' * ' , ' ? ' ] ) . intersection ( set ( spec ) ) :
2015-06-12 19:06:25 +02:00
installed_pkgs = is_installed ( module , repoq , spec , conf_file , en_repos = en_repos , dis_repos = dis_repos , is_pkg = True )
if installed_pkgs :
res [ ' results ' ] . append ( ' %s providing %s is already installed ' % ( installed_pkgs [ 0 ] , spec ) )
2013-07-04 23:32:09 +02:00
continue
2012-08-02 07:47:48 +02:00
# look up what pkgs provide this
2012-10-24 06:46:15 +02:00
pkglist = what_provides ( module , repoq , spec , conf_file , en_repos = en_repos , dis_repos = dis_repos )
2012-08-02 07:47:48 +02:00
if not pkglist :
res [ ' msg ' ] + = " No Package matching ' %s ' found available, installed or updated " % spec
2012-08-15 01:29:09 +02:00
module . fail_json ( * * res )
2012-08-07 02:07:02 +02:00
2014-01-22 21:29:50 +01:00
# if any of the packages are involved in a transaction, fail now
# so that we don't hang on the yum operation later
conflicts = transaction_exists ( pkglist )
if len ( conflicts ) > 0 :
res [ ' msg ' ] + = " The following packages have pending transactions: %s " % " , " . join ( conflicts )
module . fail_json ( * * res )
2012-08-02 07:47:48 +02:00
# if any of them are installed
# then nothing to do
2012-08-07 02:07:02 +02:00
2012-08-02 07:47:48 +02:00
found = False
for this in pkglist :
2013-07-04 23:32:09 +02:00
if is_installed ( module , repoq , this , conf_file , en_repos = en_repos , dis_repos = dis_repos , is_pkg = True ) :
2012-08-02 07:47:48 +02:00
found = True
2012-08-02 23:02:37 +02:00
res [ ' results ' ] . append ( ' %s providing %s is already installed ' % ( this , spec ) )
2012-10-19 22:28:39 +02:00
break
2012-08-07 02:07:02 +02:00
2012-12-12 17:51:24 +01:00
# if the version of the pkg you have installed is not in ANY repo, but there are
# other versions in the repos (both higher and lower) then the previous checks won't work.
# so we check one more time. This really only works for pkgname - not for file provides or virt provides
# but virt provides should be all caught in what_provides on its own.
# highly irritating
if not found :
if is_installed ( module , repoq , spec , conf_file , en_repos = en_repos , dis_repos = dis_repos ) :
found = True
res [ ' results ' ] . append ( ' package providing %s is already installed ' % ( spec ) )
2012-08-02 07:47:48 +02:00
if found :
continue
2014-02-16 20:20:56 +01:00
2012-08-02 07:47:48 +02:00
# if not - then pass in the spec as what to install
2012-08-07 02:07:02 +02:00
# we could get here if nothing provides it but that's not
# the error we're catching here
2012-08-02 07:47:48 +02:00
pkg = spec
2012-08-07 02:07:02 +02:00
2015-06-11 13:39:42 +02:00
pkgs . append ( pkg )
if pkgs :
cmd = yum_basecmd + [ ' install ' ] + pkgs
2013-02-18 00:18:43 +01:00
if module . check_mode :
2015-05-23 05:16:56 +02:00
# Remove rpms downloaded for EL5 via url
try :
shutil . rmtree ( tempdir )
2016-05-20 16:48:10 +02:00
except Exception :
e = get_exception ( )
2015-05-23 05:16:56 +02:00
module . fail_json ( msg = " Failure deleting temp directory %s , %s " % ( tempdir , e ) )
2015-07-01 23:14:55 +02:00
2015-08-20 22:02:29 +02:00
module . exit_json ( changed = True , results = res [ ' results ' ] , changes = dict ( installed = pkgs ) )
2013-02-18 00:18:43 +01:00
2015-06-11 16:13:28 +02:00
changed = True
2016-03-15 16:55:50 +01:00
lang_env = dict ( LANG = ' C ' , LC_ALL = ' C ' , LC_MESSAGES = ' C ' )
rc , out , err = module . run_command ( cmd , environ_update = lang_env )
2012-11-08 12:02:32 +01:00
2015-06-11 13:39:42 +02:00
if ( rc == 1 ) :
for spec in items :
# Fail on invalid urls:
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
module . fail_json ( changed = False , msg = err , rc = 1 )
if ( rc != 0 and ' Nothing to do ' in err ) or ' Nothing to do ' in out :
2013-04-08 11:54:27 +02:00
# avoid failing in the 'Nothing To Do' case
2013-09-10 19:10:53 +02:00
# this may happen with an URL spec.
# for an already installed group,
# we get rc = 0 and 'Nothing to do' in out, not in err.
2013-04-08 11:54:27 +02:00
rc = 0
err = ' '
out = ' %s : Nothing to do ' % spec
changed = False
2015-06-11 13:39:42 +02:00
res [ ' rc ' ] = rc
2012-11-08 12:02:32 +01:00
res [ ' results ' ] . append ( out )
res [ ' msg ' ] + = err
2012-03-12 21:31:13 +01:00
# FIXME - if we did an install - go and check the rpmdb to see if it actually installed
2015-06-11 13:39:42 +02:00
# look for each pkg in rpmdb
# look for each pkg via obsoletes
2013-04-08 11:54:27 +02:00
2015-06-11 13:39:42 +02:00
# Record change
2015-06-11 16:13:28 +02:00
res [ ' changed ' ] = changed
2012-08-07 02:07:02 +02:00
2015-05-23 05:16:56 +02:00
# Remove rpms downloaded for EL5 via url
try :
shutil . rmtree ( tempdir )
2016-05-20 16:48:10 +02:00
except Exception :
e = get_exception ( )
2015-05-23 05:16:56 +02:00
module . fail_json ( msg = " Failure deleting temp directory %s , %s " % ( tempdir , e ) )
2015-06-15 18:51:15 +02:00
return res
2012-08-07 02:07:02 +02:00
2012-03-10 00:33:58 +01:00
2012-10-24 06:21:24 +02:00
def remove ( module , items , repoq , yum_basecmd , conf_file , en_repos , dis_repos ) :
2012-08-15 01:27:02 +02:00
2015-06-11 16:21:30 +02:00
pkgs = [ ]
2012-08-02 07:47:48 +02:00
res = { }
2012-08-02 23:02:37 +02:00
res [ ' results ' ] = [ ]
2012-08-02 07:47:48 +02:00
res [ ' msg ' ] = ' '
res [ ' changed ' ] = False
res [ ' rc ' ] = 0
2012-08-07 02:07:02 +02:00
2012-10-30 04:48:21 +01:00
for pkg in items :
is_group = False
# group remove - this is doom on a stick
if pkg . startswith ( ' @ ' ) :
is_group = True
2012-03-10 00:33:58 +01:00
else :
2012-10-30 04:48:21 +01:00
if not is_installed ( module , repoq , pkg , conf_file , en_repos = en_repos , dis_repos = dis_repos ) :
res [ ' results ' ] . append ( ' %s is not installed ' % pkg )
2012-08-02 07:47:48 +02:00
continue
2012-03-10 00:33:58 +01:00
2015-06-11 16:21:30 +02:00
pkgs . append ( pkg )
if pkgs :
2012-10-30 04:48:21 +01:00
# run an actual yum transaction
2015-06-12 12:18:14 +02:00
cmd = yum_basecmd + [ " remove " ] + pkgs
2013-02-18 00:18:43 +01:00
if module . check_mode :
2015-08-20 22:02:29 +02:00
module . exit_json ( changed = True , results = res [ ' results ' ] , changes = dict ( removed = pkgs ) )
2013-02-18 00:18:43 +01:00
Update modules to use run_command in module_common.py
This updates apt, apt_repository, command, cron, easy_install, facter,
fireball, git, group, mount, ohai, pip, service, setup, subversion,
supervisorctl, svr4pkg, user, and yum to take advantage of run_command
in module_common.py.
2013-01-12 07:10:21 +01:00
rc , out , err = module . run_command ( cmd )
2012-08-07 02:07:02 +02:00
2015-06-11 16:21:30 +02:00
res [ ' rc ' ] = rc
2012-11-08 12:02:32 +01:00
res [ ' results ' ] . append ( out )
2015-06-11 16:21:30 +02:00
res [ ' msg ' ] = err
2012-11-08 12:02:32 +01:00
# compile the results into one batch. If anything is changed
# then mark changed
# at the end - if we've end up failed then fail out of the rest
# of the process
2012-10-30 04:48:21 +01:00
# at this point we should check to see if the pkg is no longer present
2015-06-11 16:21:30 +02:00
for pkg in pkgs :
if not pkg . startswith ( ' @ ' ) : # we can't sensibly check for a group being uninstalled reliably
# look to see if the pkg shows up from is_installed. If it doesn't
if not is_installed ( module , repoq , pkg , conf_file , en_repos = en_repos , dis_repos = dis_repos ) :
res [ ' changed ' ] = True
else :
module . fail_json ( * * res )
2012-10-30 04:48:21 +01:00
2012-08-02 07:47:48 +02:00
if rc != 0 :
2012-10-30 04:48:21 +01:00
module . fail_json ( * * res )
2015-06-15 18:51:15 +02:00
return res
2012-03-12 21:31:13 +01:00
2012-10-24 06:21:24 +02:00
def latest ( module , items , repoq , yum_basecmd , conf_file , en_repos , dis_repos ) :
2012-08-15 01:33:11 +02:00
2012-08-02 07:47:48 +02:00
res = { }
2012-08-02 23:02:37 +02:00
res [ ' results ' ] = [ ]
2012-08-02 07:47:48 +02:00
res [ ' msg ' ] = ' '
res [ ' changed ' ] = False
res [ ' rc ' ] = 0
2015-07-01 23:14:55 +02:00
pkgs = { }
pkgs [ ' update ' ] = [ ]
pkgs [ ' install ' ] = [ ]
updates = { }
update_all = False
cmd = None
# determine if we're doing an update all
if ' * ' in items :
update_all = True
# run check-update to see if we have packages pending
rc , out , err = module . run_command ( yum_basecmd + [ ' check-update ' ] )
if rc == 0 and update_all :
res [ ' results ' ] . append ( ' Nothing to do here, all packages are up to date ' )
return res
elif rc == 100 :
available_updates = out . split ( ' \n ' )
# build update dictionary
for line in available_updates :
line = line . split ( )
# ignore irrelevant lines
# FIXME... revisit for something less kludgy
if ' * ' in line or len ( line ) != 3 or ' . ' not in line [ 0 ] :
2013-07-05 04:13:46 +02:00
continue
2012-08-14 00:13:50 +02:00
else :
2015-07-01 23:14:55 +02:00
pkg , version , repo = line
2015-08-20 22:02:29 +02:00
name , dist = pkg . rsplit ( ' . ' , 1 )
2015-07-01 23:14:55 +02:00
updates . update ( { name : { ' version ' : version , ' dist ' : dist , ' repo ' : repo } } )
elif rc == 1 :
res [ ' msg ' ] = err
res [ ' rc ' ] = rc
module . fail_json ( * * res )
2012-08-14 00:13:50 +02:00
2015-07-01 23:14:55 +02:00
if update_all :
cmd = yum_basecmd + [ ' update ' ]
2015-10-08 18:55:52 +02:00
will_update = set ( updates . keys ( ) )
will_update_from_other_package = dict ( )
2015-07-01 23:14:55 +02:00
else :
2015-10-08 18:55:52 +02:00
will_update = set ( )
will_update_from_other_package = dict ( )
2015-07-01 23:14:55 +02:00
for spec in items :
# some guess work involved with groups. update @<group> will install the group if missing
if spec . startswith ( ' @ ' ) :
pkgs [ ' update ' ] . append ( spec )
continue
# dep/pkgname - find it
else :
if is_installed ( module , repoq , spec , conf_file , en_repos = en_repos , dis_repos = dis_repos ) :
pkgs [ ' update ' ] . append ( spec )
else :
pkgs [ ' install ' ] . append ( spec )
2012-10-24 06:46:15 +02:00
pkglist = what_provides ( module , repoq , spec , conf_file , en_repos = en_repos , dis_repos = dis_repos )
2015-07-01 23:14:55 +02:00
# FIXME..? may not be desirable to throw an exception here if a single package is missing
2012-08-02 07:47:48 +02:00
if not pkglist :
res [ ' msg ' ] + = " No Package matching ' %s ' found available, installed or updated " % spec
2012-11-08 12:02:32 +01:00
module . fail_json ( * * res )
2015-07-01 23:14:55 +02:00
2012-08-14 00:13:50 +02:00
nothing_to_do = True
2012-08-02 07:47:48 +02:00
for this in pkglist :
2015-07-01 23:14:55 +02:00
if spec in pkgs [ ' install ' ] and is_available ( module , repoq , this , conf_file , en_repos = en_repos , dis_repos = dis_repos ) :
2012-08-14 00:13:50 +02:00
nothing_to_do = False
break
2015-07-01 23:14:55 +02:00
2015-10-08 18:55:52 +02:00
# this contains the full NVR and spec could contain wildcards
# or virtual provides (like "python-*" or "smtp-daemon") while
# updates contains name only.
this_name_only = ' - ' . join ( this . split ( ' - ' ) [ : - 2 ] )
if spec in pkgs [ ' update ' ] and this_name_only in updates . keys ( ) :
nothing_to_do = False
will_update . add ( spec )
# Massage the updates list
if spec != this_name_only :
# For reporting what packages would be updated more
# succinctly
will_update_from_other_package [ spec ] = this_name_only
break
2015-07-01 23:14:55 +02:00
2012-08-02 07:47:48 +02:00
if nothing_to_do :
2012-08-02 23:02:37 +02:00
res [ ' results ' ] . append ( " All packages providing %s are up to date " % spec )
2012-08-02 07:47:48 +02:00
continue
2012-08-07 02:07:02 +02:00
2014-01-22 21:29:50 +01:00
# if any of the packages are involved in a transaction, fail now
# so that we don't hang on the yum operation later
conflicts = transaction_exists ( pkglist )
if len ( conflicts ) > 0 :
res [ ' msg ' ] + = " The following packages have pending transactions: %s " % " , " . join ( conflicts )
module . fail_json ( * * res )
2015-07-01 23:14:55 +02:00
# check_mode output
if module . check_mode :
2015-08-20 22:02:29 +02:00
to_update = [ ]
2015-07-01 23:14:55 +02:00
for w in will_update :
if w . startswith ( ' @ ' ) :
2015-08-20 22:02:29 +02:00
to_update . append ( ( w , None ) )
2015-07-01 23:14:55 +02:00
msg = ' %s will be updated ' % w
2015-10-08 18:55:52 +02:00
elif w not in updates :
other_pkg = will_update_from_other_package [ w ]
to_update . append ( ( w , ' because of (at least) %s - %s . %s from %s ' % ( other_pkg , updates [ other_pkg ] [ ' version ' ] , updates [ other_pkg ] [ ' dist ' ] , updates [ other_pkg ] [ ' repo ' ] ) ) )
2015-07-01 23:14:55 +02:00
else :
2015-08-20 22:02:29 +02:00
to_update . append ( ( w , ' %s . %s from %s ' % ( updates [ w ] [ ' version ' ] , updates [ w ] [ ' dist ' ] , updates [ w ] [ ' repo ' ] ) ) )
2013-02-18 00:18:43 +01:00
2015-08-20 22:02:29 +02:00
res [ ' changes ' ] = dict ( installed = pkgs [ ' install ' ] , updated = to_update )
2012-03-27 20:15:48 +02:00
2015-07-01 23:14:55 +02:00
if len ( will_update ) > 0 or len ( pkgs [ ' install ' ] ) > 0 :
res [ ' changed ' ] = True
2012-11-08 12:02:32 +01:00
2015-07-01 23:14:55 +02:00
return res
2012-03-12 21:31:13 +01:00
2015-07-01 23:14:55 +02:00
# run commands
if cmd : # update all
rc , out , err = module . run_command ( cmd )
res [ ' changed ' ] = True
else :
if len ( pkgs [ ' install ' ] ) > 0 : # install missing
cmd = yum_basecmd + [ ' install ' ] + pkgs [ ' install ' ]
rc , out , err = module . run_command ( cmd )
res [ ' changed ' ] = True
2012-08-02 07:47:48 +02:00
else :
2015-07-01 23:14:55 +02:00
rc , out , err = [ 0 , ' ' , ' ' ]
if len ( will_update ) > 0 : # update present
cmd = yum_basecmd + [ ' update ' ] + pkgs [ ' update ' ]
rc2 , out2 , err2 = module . run_command ( cmd )
2012-08-02 07:47:48 +02:00
res [ ' changed ' ] = True
2015-07-01 23:14:55 +02:00
else :
rc2 , out2 , err2 = [ 0 , ' ' , ' ' ]
if not update_all :
rc + = rc2
out + = out2
err + = err2
res [ ' rc ' ] + = rc
res [ ' msg ' ] + = err
res [ ' results ' ] . append ( out )
if rc :
res [ ' failed ' ] = True
2012-08-07 02:07:02 +02:00
2015-06-15 18:51:15 +02:00
return res
2012-03-12 21:31:13 +01:00
2015-04-21 19:05:54 +02:00
def ensure ( module , state , pkgs , conf_file , enablerepo , disablerepo ,
2015-06-15 18:51:15 +02:00
disable_gpg_check , exclude , repoq ) :
2012-08-15 01:33:11 +02:00
2015-06-14 02:08:32 +02:00
yumbin = module . get_bin_path ( ' yum ' )
2013-09-10 19:10:53 +02:00
# need debug level 2 to get 'Nothing to do' for groupinstall.
yum_basecmd = [ yumbin , ' -d ' , ' 2 ' , ' -y ' ]
2012-08-15 01:33:11 +02:00
2012-08-02 07:47:48 +02:00
if conf_file and os . path . exists ( conf_file ) :
2012-08-09 16:12:22 +02:00
yum_basecmd + = [ ' -c ' , conf_file ]
2012-08-14 00:13:50 +02:00
if repoq :
repoq + = [ ' -c ' , conf_file ]
2012-10-24 06:21:24 +02:00
dis_repos = [ ]
en_repos = [ ]
if disablerepo :
dis_repos = disablerepo . split ( ' , ' )
2014-09-30 01:33:40 +02:00
r_cmd = [ ' --disablerepo= %s ' % disablerepo ]
yum_basecmd . extend ( r_cmd )
2012-10-24 06:21:24 +02:00
if enablerepo :
en_repos = enablerepo . split ( ' , ' )
2014-09-30 01:33:40 +02:00
r_cmd = [ ' --enablerepo= %s ' % enablerepo ]
2014-02-25 20:52:45 +01:00
yum_basecmd . extend ( r_cmd )
2012-10-24 06:21:24 +02:00
2014-11-12 01:49:56 +01:00
if exclude :
e_cmd = [ ' --exclude= %s ' % exclude ]
yum_basecmd . extend ( e_cmd )
2015-06-14 02:08:32 +02:00
2013-01-31 23:23:10 +01:00
if state in [ ' installed ' , ' present ' , ' latest ' ] :
2014-09-28 20:30:39 +02:00
if module . params . get ( ' update_cache ' ) :
module . run_command ( yum_basecmd + [ ' makecache ' ] )
2013-01-31 23:23:10 +01:00
my = yum_base ( conf_file )
try :
2014-09-30 01:33:40 +02:00
if disablerepo :
my . repos . disableRepo ( disablerepo )
2013-08-17 14:08:45 +02:00
current_repos = my . repos . repos . keys ( )
2014-09-30 01:33:40 +02:00
if enablerepo :
2013-01-31 23:23:10 +01:00
try :
2014-09-30 01:33:40 +02:00
my . repos . enableRepo ( enablerepo )
2013-08-17 14:08:45 +02:00
new_repos = my . repos . repos . keys ( )
for i in new_repos :
if not i in current_repos :
rid = my . repos . getRepo ( i )
a = rid . repoXML . repoid
current_repos = new_repos
2016-05-20 16:48:10 +02:00
except yum . Errors . YumBaseError :
e = get_exception ( )
2015-04-10 20:59:33 +02:00
module . fail_json ( msg = " Error setting/accessing repos: %s " % ( e ) )
2016-05-20 16:48:10 +02:00
except yum . Errors . YumBaseError :
e = get_exception ( )
2013-01-31 23:23:10 +01:00
module . fail_json ( msg = " Error accessing repos: %s " % e )
2012-08-14 00:13:50 +02:00
if state in [ ' installed ' , ' present ' ] :
2013-04-23 18:12:37 +02:00
if disable_gpg_check :
yum_basecmd . append ( ' --nogpgcheck ' )
2015-06-15 18:51:15 +02:00
res = install ( module , pkgs , repoq , yum_basecmd , conf_file , en_repos , dis_repos )
2012-08-14 00:13:50 +02:00
elif state in [ ' removed ' , ' absent ' ] :
2015-06-15 18:51:15 +02:00
res = remove ( module , pkgs , repoq , yum_basecmd , conf_file , en_repos , dis_repos )
2012-08-14 00:13:50 +02:00
elif state == ' latest ' :
2013-04-23 18:12:37 +02:00
if disable_gpg_check :
yum_basecmd . append ( ' --nogpgcheck ' )
2015-06-15 18:51:15 +02:00
res = latest ( module , pkgs , repoq , yum_basecmd , conf_file , en_repos , dis_repos )
else :
# should be caught by AnsibleModule argument_spec
2015-06-15 19:46:59 +02:00
module . fail_json ( msg = " we should never get here unless this all "
" failed " , changed = False , results = ' ' , errors = ' unepected state ' )
2012-08-09 16:12:22 +02:00
2015-06-15 18:51:15 +02:00
return res
2012-08-07 02:07:02 +02:00
2015-12-13 18:16:28 +01:00
2012-03-10 00:33:58 +01:00
def main ( ) :
2012-08-15 01:33:11 +02:00
2012-08-12 00:16:10 +02:00
# state=installed name=pkgspec
# state=removed name=pkgspec
# state=latest name=pkgspec
2012-03-10 00:33:58 +01:00
#
2012-04-01 08:35:19 +02:00
# informational commands:
# list=installed
# list=updates
# list=available
# list=repos
# list=pkgspec
2012-08-07 02:07:02 +02:00
2012-07-25 16:15:41 +02:00
module = AnsibleModule (
2012-07-26 02:14:15 +02:00
argument_spec = dict (
2015-04-21 19:05:54 +02:00
name = dict ( aliases = [ ' pkg ' ] , type = " list " ) ,
2014-11-12 01:49:56 +01:00
exclude = dict ( required = False , default = None ) ,
2012-07-26 02:14:15 +02:00
# removed==absent, installed==present, these are accepted as aliases
state = dict ( default = ' installed ' , choices = [ ' absent ' , ' present ' , ' installed ' , ' removed ' , ' latest ' ] ) ,
2012-10-24 06:21:24 +02:00
enablerepo = dict ( ) ,
disablerepo = dict ( ) ,
2012-08-09 19:22:51 +02:00
list = dict ( ) ,
2012-08-02 07:47:48 +02:00
conf_file = dict ( default = None ) ,
2013-10-11 14:45:13 +02:00
disable_gpg_check = dict ( required = False , default = " no " , type = ' bool ' ) ,
2014-09-28 20:30:39 +02:00
update_cache = dict ( required = False , default = " no " , type = ' bool ' ) ,
2015-12-06 20:54:05 +01:00
validate_certs = dict ( required = False , default = " yes " , type = ' bool ' ) ,
2014-02-27 19:42:05 +01:00
# this should not be needed, but exists as a failsafe
2014-02-27 19:16:30 +01:00
install_repoquery = dict ( required = False , default = " yes " , type = ' bool ' ) ,
2012-08-12 00:13:29 +02:00
) ,
2012-08-12 00:16:10 +02:00
required_one_of = [ [ ' name ' , ' list ' ] ] ,
2013-02-18 00:18:43 +01:00
mutually_exclusive = [ [ ' name ' , ' list ' ] ] ,
supports_check_mode = True
2012-07-25 16:15:41 +02:00
)
2012-03-10 08:19:57 +01:00
2012-07-25 16:15:41 +02:00
params = module . params
2014-02-27 18:18:25 +01:00
2012-08-02 02:33:13 +02:00
if params [ ' list ' ] :
2015-06-15 18:51:15 +02:00
repoquerybin = ensure_yum_utils ( module )
2015-06-14 02:08:32 +02:00
if not repoquerybin :
2012-08-14 00:13:50 +02:00
module . fail_json ( msg = " repoquery is required to use list= with this module. Please install the yum-utils package. " )
2015-06-14 02:08:32 +02:00
results = dict ( results = list_stuff ( module , repoquerybin , params [ ' conf_file ' ] , params [ ' list ' ] ) )
2012-08-07 02:07:02 +02:00
2012-04-12 02:47:38 +02:00
else :
2015-06-15 18:51:15 +02:00
# 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.
# Use repoquery in those cases.
2015-06-16 15:28:46 +02:00
my = yum_base ( params [ ' conf_file ' ] )
2015-06-15 18:51:15 +02:00
# A sideeffect of accessing conf is that the configuration is
# loaded and plugins are discovered
my . conf
repoquery = None
2015-08-21 00:30:32 +02:00
try :
yum_plugins = my . plugins . _plugins
except AttributeError :
pass
else :
if ' rhnplugin ' in yum_plugins :
repoquerybin = ensure_yum_utils ( module )
if repoquerybin :
repoquery = [ repoquerybin , ' --show-duplicates ' , ' --plugins ' , ' --quiet ' ]
2015-06-15 18:51:15 +02:00
2015-04-21 19:05:54 +02:00
pkg = [ p . strip ( ) for p in params [ ' name ' ] ]
2014-11-12 01:49:56 +01:00
exclude = params [ ' exclude ' ]
2012-08-12 00:13:29 +02:00
state = params [ ' state ' ]
2012-10-24 06:21:24 +02:00
enablerepo = params . get ( ' enablerepo ' , ' ' )
disablerepo = params . get ( ' disablerepo ' , ' ' )
2013-04-23 18:12:37 +02:00
disable_gpg_check = params [ ' disable_gpg_check ' ]
2015-06-15 18:51:15 +02:00
results = ensure ( module , state , pkg , params [ ' conf_file ' ] , enablerepo ,
disablerepo , disable_gpg_check , exclude , repoquery )
if repoquery :
2015-12-13 18:16:28 +01:00
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. ' )
2015-06-15 18:51:15 +02:00
module . exit_json ( * * results )
2012-03-14 05:38:38 +01:00
2013-12-02 21:13:49 +01:00
# import module snippets
2013-12-02 21:11:23 +01:00
from ansible . module_utils . basic import *
2015-05-29 22:37:47 +02:00
from ansible . module_utils . urls import *
if __name__ == ' __main__ ' :
main ( )