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
2012-03-10 00:33:58 +01:00
import traceback
2012-08-02 07:47:48 +02:00
import os
2012-08-14 00:13:50 +02:00
import yum
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 :
2013-08-25 04:46:41 +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. "
2012-09-29 00:49:02 +02:00
required : true
default : null
aliases : [ ]
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 :
2013-08-25 04:46:41 +02:00
- Whether to install ( C ( present ) , C ( latest ) ) , or remove ( C ( absent ) ) a package .
2012-09-29 00:49:02 +02:00
required : false
choices : [ " present " , " latest " , " absent " ]
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 : [ ]
2012-10-24 15:08:42 +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 : [ ]
2012-09-29 00:49:02 +02:00
notes : [ ]
# informational: requirements for nodes
requirements : [ yum , rpm ]
author : Seth Vidal
'''
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
- 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
2013-06-14 11:53:43 +02:00
'''
2012-08-02 07:47:48 +02:00
def_qf = " % {name} - % {version} - % {release} . % {arch} "
2012-08-15 01:33:11 +02:00
2012-08-02 23:02:37 +02:00
repoquery = ' /usr/bin/repoquery '
2012-08-14 00:13:50 +02:00
if not os . path . exists ( repoquery ) :
repoquery = None
2012-08-02 07:47:48 +02:00
2012-08-15 01:33:11 +02:00
yumbin = ' /usr/bin/yum '
2012-08-14 00:13:50 +02:00
2013-09-10 19:10:53 +02:00
import syslog
def log ( msg ) :
syslog . openlog ( ' ansible-yum ' , 0 , syslog . LOG_USER )
syslog . syslog ( syslog . LOG_NOTICE , msg )
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
if conf_file and os . path . exists ( conf_file ) :
my . preconf . fn = conf_file
return my
2014-02-27 18:18:25 +01:00
def install_yum_utils ( module ) :
if not module . check_mode :
yum_path = module . get_bin_path ( ' yum ' )
if yum_path :
rc , so , se = module . run_command ( ' %s -y install yum-utils ' % yum_path )
if rc == 0 :
this_path = module . get_bin_path ( ' repoquery ' )
global repoquery
repoquery = this_path
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 )
2013-07-04 23:32:09 +02:00
def is_installed ( module , repoq , pkgspec , conf_file , qf = def_qf , en_repos = [ ] , dis_repos = [ ] , is_pkg = False ) :
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 en_repos :
my . repos . enableRepo ( rid )
for rid in dis_repos :
my . repos . disableRepo ( rid )
2012-08-14 00:13:50 +02:00
e , m , u = my . rpmdb . matchPackageNames ( [ pkgspec ] )
pkgs = e + m
if not pkgs :
pkgs . extend ( my . returnInstalledPackagesByDep ( pkgspec ) )
except Exception , e :
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 :
2012-08-15 01:33:11 +02:00
2012-08-14 00:13:50 +02:00
cmd = repoq + [ " --disablerepo=* " , " --pkgnarrow=installed " , " --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 )
2013-07-04 23:32:09 +02:00
if not is_pkg :
cmd = repoq + [ " --disablerepo=* " , " --pkgnarrow=installed " , " --qf " , qf , " --whatprovides " , pkgspec ]
rc2 , out2 , err2 = module . run_command ( cmd )
else :
rc2 , out2 , err2 = ( 0 , ' ' , ' ' )
2012-08-14 00:13:50 +02:00
if rc == 0 and rc2 == 0 :
out + = out2
return [ p for p in out . split ( ' \n ' ) if p . strip ( ) ]
else :
2012-10-24 06:46:15 +02:00
module . fail_json ( msg = ' Error from repoquery: %s : %s ' % ( cmd , err + err2 ) )
2012-08-14 00:13:50 +02:00
2012-08-02 07:47:48 +02:00
return [ ]
2012-10-24 06:21:24 +02:00
def is_available ( module , repoq , pkgspec , conf_file , qf = def_qf , en_repos = [ ] , 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 en_repos :
my . repos . enableRepo ( rid )
for rid in dis_repos :
my . repos . disableRepo ( rid )
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 ) )
except Exception , e :
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
for repoid in dis_repos :
r_cmd = [ ' --disablerepo ' , repoid ]
myrepoq . extend ( r_cmd )
2013-02-01 22:47:53 +01:00
2013-02-01 18:39:02 +01:00
for repoid in en_repos :
r_cmd = [ ' --enablerepo ' , repoid ]
2013-02-01 22:47:53 +01:00
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-14 00:13:50 +02:00
2012-08-02 07:47:48 +02:00
return [ ]
2012-10-24 06:21:24 +02:00
def is_update ( module , repoq , pkgspec , conf_file , qf = def_qf , en_repos = [ ] , 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 en_repos :
my . repos . enableRepo ( rid )
for rid in dis_repos :
my . repos . disableRepo ( rid )
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
except Exception , e :
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 )
2013-02-01 18:39:02 +01:00
for repoid in dis_repos :
r_cmd = [ ' --disablerepo ' , repoid ]
2013-02-01 22:47:53 +01:00
myrepoq . extend ( r_cmd )
2013-02-01 18:39:02 +01:00
2014-02-25 20:52:45 +01:00
for repoid in en_repos :
r_cmd = [ ' --enablerepo ' , repoid ]
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
2012-08-02 07:47:48 +02:00
return [ ]
2012-10-24 06:21:24 +02:00
def what_provides ( module , repoq , req_spec , conf_file , qf = def_qf , en_repos = [ ] , 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 en_repos :
my . repos . enableRepo ( rid )
for rid in dis_repos :
my . repos . disableRepo ( rid )
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 )
except Exception , e :
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 )
2013-02-01 18:39:02 +01:00
for repoid in dis_repos :
r_cmd = [ ' --disablerepo ' , repoid ]
2013-02-01 22:47:53 +01:00
myrepoq . extend ( r_cmd )
2013-02-01 18:39:02 +01:00
2014-02-25 20:52:45 +01:00
for repoid in en_repos :
r_cmd = [ ' --enablerepo ' , repoid ]
myrepoq . extend ( r_cmd )
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 ) )
2012-08-14 00:13:50 +02:00
return [ ]
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 """
cmd = [ ' /bin/rpm ' , ' -qp ' , ' --qf ' ,
2012-08-24 19:51:07 +02:00
' % {name} - % {version} - % {release} . % {arch} \n ' , path ]
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 22:23:40 +02:00
if rc != 0 :
return None
nvra = out . split ( ' \n ' ) [ 0 ]
return nvra
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
2012-08-14 00:13:50 +02:00
def list_stuff ( module , 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} "
2012-08-10 03:29:59 +02:00
repoq = [ repoquery , ' --show-duplicates ' , ' --plugins ' , ' --quiet ' , ' -q ' ]
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 ' :
2012-08-14 00:13:50 +02:00
return [ pkg_to_dict ( p ) for p in is_installed ( module , repoq , ' -a ' , conf_file , qf = qf ) if p . strip ( ) ]
2012-03-10 00:33:58 +01:00
elif stuff == ' updates ' :
2012-08-14 00:13:50 +02:00
return [ pkg_to_dict ( p ) for p in is_update ( module , repoq , ' -a ' , conf_file , qf = qf ) if p . strip ( ) ]
2012-03-10 00:33:58 +01:00
elif stuff == ' available ' :
2012-08-14 00:13:50 +02:00
return [ pkg_to_dict ( p ) for p in is_available ( module , repoq , ' -a ' , conf_file , qf = qf ) if p . strip ( ) ]
2012-03-10 00:33:58 +01:00
elif stuff == ' repos ' :
2013-01-22 16:27:08 +01:00
return [ dict ( repoid = name , state = ' enabled ' ) for name in repolist ( module , repoq ) if name . strip ( ) ]
2012-03-10 00:33:58 +01:00
else :
2012-08-14 00:13:50 +02:00
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 ( ) ]
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
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
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 )
2013-01-22 05:27:07 +01:00
nvra = local_nvra ( module , spec )
2012-08-02 07:47:48 +02:00
# look for them in the rpmdb
2012-10-24 06:46:15 +02:00
if is_installed ( module , repoq , nvra , 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 :
pkg = spec
2012-08-02 07:47:48 +02:00
#groups :(
elif spec . startswith ( ' @ ' ) :
# 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 ) ) :
pkgs = is_installed ( module , repoq , spec , conf_file , en_repos = en_repos , dis_repos = dis_repos , is_pkg = True )
if pkgs :
res [ ' results ' ] . append ( ' %s providing %s is already installed ' % ( pkgs [ 0 ] , spec ) )
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
2014-03-24 18:27:32 +01:00
cmd = yum_basecmd + [ ' install ' , pkg ]
2013-02-18 00:18:43 +01:00
if module . check_mode :
module . exit_json ( changed = True )
2013-04-08 11:54:27 +02:00
changed = True
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-11-08 12:02:32 +01:00
2013-12-18 17:40:44 +01:00
# Fail on invalid urls:
2014-01-15 05:20:31 +01:00
if ( rc == 1 and ' :// ' in spec and ( ' No package %s available. ' % spec in out or ' Cannot open: %s . Skipping. ' % spec in err ) ) :
2013-12-18 17:40:44 +01:00
err = ' Package at %s could not be installed ' % spec
module . fail_json ( changed = False , msg = err , rc = 1 )
elif ( 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
2012-11-08 12:02:32 +01:00
res [ ' rc ' ] + = rc
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
# look for the pkg in rpmdb
# look for the pkg via obsoletes
2013-04-08 11:54:27 +02:00
# accumulate any changes
res [ ' changed ' ] | = changed
2012-08-07 02:07:02 +02:00
2012-08-02 07:47:48 +02:00
module . exit_json ( * * 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
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
2012-10-30 04:48:21 +01:00
# run an actual yum transaction
2012-08-09 16:12:22 +02:00
cmd = yum_basecmd + [ " remove " , pkg ]
2013-02-18 00:18:43 +01:00
if module . check_mode :
module . exit_json ( changed = True )
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
2012-11-08 12:02:32 +01:00
res [ ' rc ' ] + = rc
res [ ' results ' ] . append ( out )
res [ ' msg ' ] + = err
# 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
if not is_group : # 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 :
2012-11-08 12:02:32 +01:00
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 )
2012-11-08 12:02:32 +01:00
2012-08-02 07:47:48 +02:00
module . exit_json ( * * 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
2012-08-07 02:07:02 +02:00
2012-08-02 07:47:48 +02:00
for spec in items :
2012-08-15 01:33:11 +02:00
2012-08-02 07:47:48 +02:00
pkg = None
2012-08-08 16:43:45 +02:00
basecmd = ' update '
2013-07-05 04:13:46 +02:00
cmd = ' '
2012-08-02 07:47:48 +02:00
# groups, again
if spec . startswith ( ' @ ' ) :
pkg = spec
2013-07-05 04:13:46 +02:00
elif spec == ' * ' : #update all
# use check-update to see if there is any need
rc , out , err = module . run_command ( yum_basecmd + [ ' check-update ' ] )
if rc == 100 :
cmd = yum_basecmd + [ basecmd ]
else :
res [ ' results ' ] . append ( ' All packages up to date ' )
continue
2012-08-02 07:47:48 +02:00
# dep/pkgname - find it
2012-03-27 19:58:49 +02:00
else :
2012-10-24 06:46:15 +02:00
if is_installed ( module , repoq , spec , conf_file , en_repos = en_repos , dis_repos = dis_repos ) :
2012-08-14 00:13:50 +02:00
basecmd = ' update '
else :
basecmd = ' install '
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-11-08 12:02:32 +01:00
module . fail_json ( * * res )
2012-08-14 00:13:50 +02:00
nothing_to_do = True
2012-08-02 07:47:48 +02:00
for this in pkglist :
2012-10-24 06:46:15 +02:00
if basecmd == ' 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
2014-09-12 18:19:00 +02:00
if basecmd == ' update ' and is_update ( 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
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 )
2012-08-02 07:47:48 +02:00
pkg = spec
2013-07-05 04:13:46 +02:00
if not cmd :
cmd = yum_basecmd + [ basecmd , pkg ]
2013-02-18 00:18:43 +01:00
if module . check_mode :
return module . exit_json ( changed = True )
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-03-27 20:15:48 +02:00
2012-11-08 12:02:32 +01:00
res [ ' rc ' ] + = rc
res [ ' results ' ] . append ( out )
res [ ' msg ' ] + = err
2012-03-12 21:31:13 +01:00
# FIXME if it is - update it and check to see if it applied
# check to see if there is no longer an update available for the pkgspec
2012-08-02 07:47:48 +02:00
if rc :
res [ ' failed ' ] = True
else :
res [ ' changed ' ] = True
2012-08-07 02:07:02 +02:00
2012-08-02 07:47:48 +02:00
module . exit_json ( * * res )
2012-03-12 21:31:13 +01:00
2013-04-23 18:12:37 +02:00
def ensure ( module , state , pkgspec , conf_file , enablerepo , disablerepo ,
disable_gpg_check ) :
2012-08-15 01:33:11 +02:00
2012-08-02 07:47:48 +02:00
# take multiple args comma separated
2012-08-09 16:12:22 +02:00
items = pkgspec . split ( ' , ' )
2012-07-26 02:14:15 +02:00
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-10-24 06:21:24 +02:00
2012-08-14 00:13:50 +02:00
if not repoquery :
repoq = None
else :
repoq = [ repoquery , ' --show-duplicates ' , ' --plugins ' , ' --quiet ' , ' -q ' ]
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 ( ' , ' )
if enablerepo :
en_repos = enablerepo . split ( ' , ' )
2014-02-25 20:52:45 +01:00
for repoid in dis_repos :
r_cmd = [ ' --disablerepo= %s ' % repoid ]
yum_basecmd . extend ( r_cmd )
2012-10-24 06:21:24 +02:00
for repoid in en_repos :
2014-02-25 20:52:45 +01:00
r_cmd = [ ' --enablerepo= %s ' % repoid ]
2012-10-24 06:21:24 +02:00
yum_basecmd . extend ( r_cmd )
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 :
for r in dis_repos :
my . repos . disableRepo ( r )
2013-08-17 14:08:45 +02:00
current_repos = my . repos . repos . keys ( )
2013-01-31 23:23:10 +01:00
for r in en_repos :
try :
my . repos . enableRepo ( r )
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
2013-01-31 23:23:10 +01:00
except yum . Errors . YumBaseError , e :
module . fail_json ( msg = " Error setting/accessing repo %s : %s " % ( r , e ) )
except yum . Errors . YumBaseError , e :
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 ' )
2012-10-24 06:21:24 +02:00
install ( module , items , repoq , yum_basecmd , conf_file , en_repos , dis_repos )
2012-08-14 00:13:50 +02:00
elif state in [ ' removed ' , ' absent ' ] :
2012-10-24 06:21:24 +02:00
remove ( module , items , 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 ' )
2012-10-24 06:21:24 +02:00
latest ( module , items , repoq , yum_basecmd , conf_file , en_repos , dis_repos )
2012-08-09 16:12:22 +02:00
2012-08-07 02:07:02 +02:00
# should be caught by AnsibleModule argument_spec
2012-08-02 07:47:48 +02:00
return dict ( changed = False , failed = True , results = ' ' , errors = ' unexpected state ' )
2012-08-07 02:07:02 +02: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 (
2012-08-15 01:27:02 +02:00
name = dict ( aliases = [ ' pkg ' ] ) ,
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 ' ) ,
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
2014-02-27 19:42:05 +01:00
# this should not be needed, but exists as a failsafe
2012-07-25 16:15:41 +02:00
params = module . params
2014-02-27 19:42:05 +01:00
if params [ ' install_repoquery ' ] and not repoquery and not module . check_mode :
2014-02-27 18:18:25 +01:00
install_yum_utils ( module )
2012-08-02 02:33:13 +02:00
if params [ ' list ' ] :
2012-08-14 00:13:50 +02:00
if not repoquery :
module . fail_json ( msg = " repoquery is required to use list= with this module. Please install the yum-utils package. " )
results = dict ( results = list_stuff ( module , params [ ' conf_file ' ] , params [ ' list ' ] ) )
2012-07-26 02:14:15 +02:00
module . exit_json ( * * results )
2012-08-07 02:07:02 +02:00
2012-04-12 02:47:38 +02:00
else :
2012-08-12 00:16:10 +02:00
pkg = params [ ' name ' ]
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 ' ]
res = ensure ( module , state , pkg , params [ ' conf_file ' ] , enablerepo ,
disablerepo , disable_gpg_check )
2012-08-12 00:13:29 +02:00
module . fail_json ( msg = " we should never get here unless this all failed " , * * res )
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 *
2012-07-25 16:15:41 +02:00
main ( )