#!/usr/bin/python -tt
# -*- coding: utf-8 -*-
# (c) 2012, Red Hat, Inc
# Written by Seth Vidal <skvidal at fedoraproject.org>
# (c) 2014, Epic Games, Inc.
#
# 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/>.
#
import traceback
import os
import yum
import rpm
import syslog
import platform
import tempfile
import shutil
from distutils . version import LooseVersion
try :
from yum . misc import find_unfinished_transactions , find_ts_remaining
from rpmUtils . miscutils import splitFilename
transaction_helpers = True
except :
transaction_helpers = False
DOCUMENTATION = '''
- - -
module : yum
version_added : historical
short_description : Manages packages with the I ( yum ) package manager
description :
- Installs , upgrade , removes , and lists packages and groups with the I ( yum ) package manager .
options :
name :
description :
- " 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. To operate on several packages this can accept a comma separated list of packages or (as of 2.0) a list of packages. "
required : true
default : null
aliases : [ ]
exclude :
description :
- " Package name(s) to exclude when state=present, or latest "
required : false
version_added : " 2.0 "
default : null
list :
description :
- Various ( non - idempotent ) commands for usage with C ( / usr / bin / ansible ) and I ( not ) playbooks . See examples .
required : false
default : null
state :
description :
- Whether to install ( C ( present ) , C ( latest ) ) , or remove ( C ( absent ) ) a package .
required : false
choices : [ " present " , " latest " , " absent " ]
default : " present "
enablerepo :
description :
- I ( Repoid ) of repositories to enable for the install / update operation .
These repos will not persist beyond the transaction .
When specifying multiple repos , separate them with a " , " .
required : false
version_added : " 0.9 "
default : null
aliases : [ ]
disablerepo :
description :
- I ( Repoid ) of repositories to disable for the install / update operation .
These repos will not persist beyond the transaction .
When specifying multiple repos , separate them with a " , " .
required : false
version_added : " 0.9 "
default : null
aliases : [ ]
conf_file :
description :
- The remote yum configuration file to use for the transaction .
required : false
version_added : " 0.6 "
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 : [ ]
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 : [ ]
notes : [ ]
# informational: requirements for nodes
requirements : [ yum ]
author :
- " Ansible Core Team "
- " Seth Vidal "
'''
EXAMPLES = '''
- name : install the latest version of Apache
yum : name = httpd state = latest
- name : remove the Apache package
yum : name = httpd state = absent
- name : install the latest version of Apache from the testing repo
yum : name = httpd enablerepo = testing state = present
- name : install one specific version of Apache
yum : name = httpd - 2.2 .29 - 1.4 . amzn1 state = present
- 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
'''
def_qf = " % {name} - % {version} - % {release} . % {arch} "
repoquery = ' /usr/bin/repoquery '
if not os . path . exists ( repoquery ) :
repoquery = None
yumbin = ' /usr/bin/yum '
def log ( msg ) :
syslog . openlog ( ' ansible-yum ' , 0 , syslog . LOG_USER )
syslog . syslog ( syslog . LOG_NOTICE , msg )
def yum_base ( conf_file = None ) :
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
if os . geteuid ( ) != 0 :
if hasattr ( my , ' setCacheDir ' ) :
my . setCacheDir ( )
else :
cachedir = yum . misc . getCacheDir ( )
my . repos . setCacheDir ( cachedir )
my . conf . cache = 0
return my
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
def po_to_nevra ( po ) :
if hasattr ( po , ' ui_nevra ' ) :
return po . ui_nevra
else :
return ' %s - %s - %s . %s ' % ( po . name , po . version , po . release , po . arch )
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 = [ ]
if not repoq :
pkgs = [ ]
try :
my = yum_base ( conf_file )
for rid in dis_repos :
my . repos . disableRepo ( rid )
for rid in en_repos :
my . repos . enableRepo ( rid )
e , m , u = my . rpmdb . matchPackageNames ( [ pkgspec ] )
pkgs = e + m
if not pkgs :
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 ]
else :
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.
12 years ago
rc , out , err = module . run_command ( cmd )
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 , ' ' , ' ' )
if rc == 0 and rc2 == 0 :
out + = out2
return [ p for p in out . split ( ' \n ' ) if p . strip ( ) ]
else :
module . fail_json ( msg = ' Error from repoquery: %s : %s ' % ( cmd , err + err2 ) )
return [ ]
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 = [ ]
if not repoq :
pkgs = [ ]
try :
my = yum_base ( conf_file )
for rid in dis_repos :
my . repos . disableRepo ( rid )
for rid in en_repos :
my . repos . enableRepo ( rid )
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 ]
else :
myrepoq = list ( repoq )
r_cmd = [ ' --disablerepo ' , ' , ' . join ( dis_repos ) ]
myrepoq . extend ( r_cmd )
r_cmd = [ ' --enablerepo ' , ' , ' . join ( en_repos ) ]
myrepoq . extend ( r_cmd )
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.
12 years ago
rc , out , err = module . run_command ( cmd )
if rc == 0 :
return [ p for p in out . split ( ' \n ' ) if p . strip ( ) ]
else :
module . fail_json ( msg = ' Error from repoquery: %s : %s ' % ( cmd , err ) )
return [ ]
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 = [ ]
if not repoq :
retpkgs = [ ]
pkgs = [ ]
updates = [ ]
try :
my = yum_base ( conf_file )
for rid in dis_repos :
my . repos . disableRepo ( rid )
for rid in en_repos :
my . repos . enableRepo ( rid )
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 ] )
else :
myrepoq = list ( repoq )
r_cmd = [ ' --disablerepo ' , ' , ' . join ( dis_repos ) ]
myrepoq . extend ( r_cmd )
r_cmd = [ ' --enablerepo ' , ' , ' . join ( en_repos ) ]
myrepoq . extend ( r_cmd )
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.
12 years ago
rc , out , err = module . run_command ( cmd )
if rc == 0 :
return set ( [ p for p in out . split ( ' \n ' ) if p . strip ( ) ] )
else :
module . fail_json ( msg = ' Error from repoquery: %s : %s ' % ( cmd , err ) )
return [ ]
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 = [ ]
if not repoq :
pkgs = [ ]
try :
my = yum_base ( conf_file )
for rid in dis_repos :
my . repos . disableRepo ( rid )
for rid in en_repos :
my . repos . enableRepo ( rid )
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 ] )
else :
myrepoq = list ( repoq )
r_cmd = [ ' --disablerepo ' , ' , ' . join ( dis_repos ) ]
myrepoq . extend ( r_cmd )
r_cmd = [ ' --enablerepo ' , ' , ' . join ( en_repos ) ]
myrepoq . extend ( r_cmd )
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.
12 years ago
rc , out , err = module . run_command ( cmd )
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.
12 years ago
rc2 , out2 , err2 = module . run_command ( cmd )
if rc == 0 and rc2 == 0 :
out + = out2
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
else :
module . fail_json ( msg = ' Error from repoquery: %s : %s ' % ( cmd , err + err2 ) )
return [ ]
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
def local_nvra ( module , path ) :
""" return nvra 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 ' %s - %s - %s . %s ' % ( header [ rpm . RPMTAG_NAME ] ,
header [ rpm . RPMTAG_VERSION ] ,
header [ rpm . RPMTAG_RELEASE ] ,
header [ rpm . RPMTAG_ARCH ] )
def pkg_to_dict ( pkgstr ) :
if pkgstr . strip ( ) :
n , e , v , r , a , repo = pkgstr . split ( ' | ' )
else :
return { ' error_parsing ' : pkgstr }
d = {
' name ' : n ,
' arch ' : a ,
' epoch ' : e ,
' release ' : r ,
' version ' : v ,
' repo ' : repo ,
' nevra ' : ' %s : %s - %s - %s . %s ' % ( e , n , v , r , a )
}
if repo == ' installed ' :
d [ ' yumstate ' ] = ' installed '
else :
d [ ' yumstate ' ] = ' available '
return d
def repolist ( module , repoq , qf = " % {repoid} " ) :
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.
12 years ago
rc , out , err = module . run_command ( cmd )
ret = [ ]
if rc == 0 :
ret = set ( [ p for p in out . split ( ' \n ' ) if p . strip ( ) ] )
return ret
def list_stuff ( module , conf_file , stuff ) :
qf = " % {name} | % {epoch} | % {version} | % {release} | % {arch} | % {repoid} "
repoq = [ repoquery , ' --show-duplicates ' , ' --plugins ' , ' --quiet ' ]
if conf_file and os . path . exists ( conf_file ) :
repoq + = [ ' -c ' , conf_file ]
if stuff == ' installed ' :
return [ pkg_to_dict ( p ) for p in is_installed ( module , repoq , ' -a ' , conf_file , qf = qf ) if p . strip ( ) ]
elif stuff == ' updates ' :
return [ pkg_to_dict ( p ) for p in is_update ( module , repoq , ' -a ' , conf_file , qf = qf ) if p . strip ( ) ]
elif stuff == ' available ' :
return [ pkg_to_dict ( p ) for p in is_available ( module , repoq , ' -a ' , conf_file , qf = qf ) if p . strip ( ) ]
elif stuff == ' repos ' :
return [ dict ( repoid = name , state = ' enabled ' ) for name in repolist ( module , repoq ) if name . strip ( ) ]
else :
return [ pkg_to_dict ( p ) for p in is_installed ( module , repoq , stuff , conf_file , qf = qf ) + is_available ( module , repoq , stuff , conf_file , qf = qf ) if p . strip ( ) ]
def install ( module , items , repoq , yum_basecmd , conf_file , en_repos , dis_repos ) :
pkgs = [ ]
res = { }
res [ ' results ' ] = [ ]
res [ ' msg ' ] = ' '
res [ ' rc ' ] = 0
res [ ' changed ' ] = False
tempdir = tempfile . mkdtemp ( )
for spec in items :
pkg = None
# check if pkgspec is installed (if possible for idempotence)
# localpkg
if spec . endswith ( ' .rpm ' ) and ' :// ' not in spec :
# get the pkg name-v-r.arch
if not os . path . exists ( spec ) :
res [ ' msg ' ] + = " No Package file matching ' %s ' found on system " % spec
module . fail_json ( * * res )
nvra = local_nvra ( module , spec )
# look for them in the rpmdb
if is_installed ( module , repoq , nvra , conf_file , en_repos = en_repos , dis_repos = dis_repos ) :
# if they are there, skip it
continue
pkg = spec
# URL
elif ' :// ' in spec :
pkg = spec
# Check if Enterprise Linux 5 or less, as yum on those versions do not support installing via url
distribution_version = get_distribution_version ( )
distribution = platform . dist ( )
if distribution [ 0 ] == " redhat " and LooseVersion ( distribution_version ) < LooseVersion ( " 6 " ) :
package = os . path . join ( tempdir , str ( pkg . rsplit ( ' / ' , 1 ) [ 1 ] ) )
try :
rsp , info = fetch_url ( module , pkg )
data = rsp . read ( )
f = open ( package , ' w ' )
f . write ( data )
f . close ( )
pkg = package
except Exception , e :
shutil . rmtree ( tempdir )
module . fail_json ( msg = " Failure downloading %s , %s " % ( spec , e ) )
#groups :(
elif spec . startswith ( ' @ ' ) :
# complete wild ass guess b/c it's a group
pkg = spec
# range requires or file-requires or pkgname :(
else :
# 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 ) ) :
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 ) )
continue
# look up what pkgs provide this
pkglist = what_provides ( module , repoq , spec , conf_file , en_repos = en_repos , dis_repos = dis_repos )
if not pkglist :
res [ ' msg ' ] + = " No Package matching ' %s ' found available, installed or updated " % spec
module . fail_json ( * * res )
# 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 )
# if any of them are installed
# then nothing to do
found = False
for this in pkglist :
if is_installed ( module , repoq , this , conf_file , en_repos = en_repos , dis_repos = dis_repos , is_pkg = True ) :
found = True
res [ ' results ' ] . append ( ' %s providing %s is already installed ' % ( this , spec ) )
break
# 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 ) )
if found :
continue
# if not - then pass in the spec as what to install
# we could get here if nothing provides it but that's not
# the error we're catching here
pkg = spec
pkgs . append ( pkg )
if pkgs :
cmd = yum_basecmd + [ ' install ' ] + pkgs
if module . check_mode :
# Remove rpms downloaded for EL5 via url
try :
shutil . rmtree ( tempdir )
except Exception , e :
module . fail_json ( msg = " Failure deleting temp directory %s , %s " % ( tempdir , e ) )
module . exit_json ( changed = True )
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.
12 years ago
rc , out , err = module . run_command ( cmd )
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 :
# avoid failing in the 'Nothing To Do' case
# 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.
rc = 0
err = ' '
out = ' %s : Nothing to do ' % spec
changed = False
res [ ' rc ' ] = rc
res [ ' results ' ] . append ( out )
res [ ' msg ' ] + = err
# FIXME - if we did an install - go and check the rpmdb to see if it actually installed
# look for each pkg in rpmdb
# look for each pkg via obsoletes
# Record change
res [ ' changed ' ] = changed
# Remove rpms downloaded for EL5 via url
try :
shutil . rmtree ( tempdir )
except Exception , e :
module . fail_json ( msg = " Failure deleting temp directory %s , %s " % ( tempdir , e ) )
module . exit_json ( * * res )
def remove ( module , items , repoq , yum_basecmd , conf_file , en_repos , dis_repos ) :
pkgs = [ ]
res = { }
res [ ' results ' ] = [ ]
res [ ' msg ' ] = ' '
res [ ' changed ' ] = False
res [ ' rc ' ] = 0
for pkg in items :
is_group = False
# group remove - this is doom on a stick
if pkg . startswith ( ' @ ' ) :
is_group = True
else :
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 )
continue
pkgs . append ( pkg )
if pkgs :
# run an actual yum transaction
cmd = yum_basecmd + [ " remove " ] + pkgs
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.
12 years ago
rc , out , err = module . run_command ( cmd )
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
# at this point we should check to see if the pkg is no longer present
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 )
if rc != 0 :
module . fail_json ( * * res )
module . exit_json ( * * res )
def latest ( module , items , repoq , yum_basecmd , conf_file , en_repos , dis_repos ) :
res = { }
res [ ' results ' ] = [ ]
res [ ' msg ' ] = ' '
res [ ' changed ' ] = False
res [ ' rc ' ] = 0
for spec in items :
pkg = None
basecmd = ' update '
cmd = ' '
# groups, again
if spec . startswith ( ' @ ' ) :
pkg = spec
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
# dep/pkgname - find it
else :
if is_installed ( module , repoq , spec , conf_file , en_repos = en_repos , dis_repos = dis_repos ) :
basecmd = ' update '
else :
basecmd = ' install '
pkglist = what_provides ( module , repoq , spec , conf_file , en_repos = en_repos , dis_repos = dis_repos )
if not pkglist :
res [ ' msg ' ] + = " No Package matching ' %s ' found available, installed or updated " % spec
module . fail_json ( * * res )
nothing_to_do = True
for this in pkglist :
if basecmd == ' install ' and is_available ( module , repoq , this , conf_file , en_repos = en_repos , dis_repos = dis_repos ) :
nothing_to_do = False
break
if basecmd == ' update ' and is_update ( module , repoq , this , conf_file , en_repos = en_repos , dis_repos = dis_repos ) :
nothing_to_do = False
break
if nothing_to_do :
res [ ' results ' ] . append ( " All packages providing %s are up to date " % spec )
continue
# 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 )
pkg = spec
if not cmd :
cmd = yum_basecmd + [ basecmd , pkg ]
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.
12 years ago
rc , out , err = module . run_command ( cmd )
res [ ' rc ' ] + = rc
res [ ' results ' ] . append ( out )
res [ ' msg ' ] + = err
# 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
if rc :
res [ ' failed ' ] = True
else :
res [ ' changed ' ] = True
module . exit_json ( * * res )
def ensure ( module , state , pkgs , conf_file , enablerepo , disablerepo ,
disable_gpg_check , exclude ) :
# need debug level 2 to get 'Nothing to do' for groupinstall.
yum_basecmd = [ yumbin , ' -d ' , ' 2 ' , ' -y ' ]
if not repoquery :
repoq = None
else :
repoq = [ repoquery , ' --show-duplicates ' , ' --plugins ' , ' --quiet ' ]
if conf_file and os . path . exists ( conf_file ) :
yum_basecmd + = [ ' -c ' , conf_file ]
if repoq :
repoq + = [ ' -c ' , conf_file ]
dis_repos = [ ]
en_repos = [ ]
if disablerepo :
dis_repos = disablerepo . split ( ' , ' )
r_cmd = [ ' --disablerepo= %s ' % disablerepo ]
yum_basecmd . extend ( r_cmd )
if enablerepo :
en_repos = enablerepo . split ( ' , ' )
r_cmd = [ ' --enablerepo= %s ' % enablerepo ]
yum_basecmd . extend ( r_cmd )
if exclude :
e_cmd = [ ' --exclude= %s ' % exclude ]
yum_basecmd . extend ( e_cmd )
if state in [ ' installed ' , ' present ' , ' latest ' ] :
if module . params . get ( ' update_cache ' ) :
module . run_command ( yum_basecmd + [ ' makecache ' ] )
my = yum_base ( conf_file )
try :
if disablerepo :
my . repos . disableRepo ( disablerepo )
current_repos = my . repos . repos . keys ( )
if enablerepo :
try :
my . repos . enableRepo ( enablerepo )
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
except yum . Errors . YumBaseError , e :
module . fail_json ( msg = " Error setting/accessing repos: %s " % ( e ) )
except yum . Errors . YumBaseError , e :
module . fail_json ( msg = " Error accessing repos: %s " % e )
if state in [ ' installed ' , ' present ' ] :
if disable_gpg_check :
yum_basecmd . append ( ' --nogpgcheck ' )
install ( module , pkgs , repoq , yum_basecmd , conf_file , en_repos , dis_repos )
elif state in [ ' removed ' , ' absent ' ] :
remove ( module , pkgs , repoq , yum_basecmd , conf_file , en_repos , dis_repos )
elif state == ' latest ' :
if disable_gpg_check :
yum_basecmd . append ( ' --nogpgcheck ' )
latest ( module , pkgs , repoq , yum_basecmd , conf_file , en_repos , dis_repos )
# should be caught by AnsibleModule argument_spec
return dict ( changed = False , failed = True , results = ' ' , errors = ' unexpected state ' )
def main ( ) :
# state=installed name=pkgspec
# state=removed name=pkgspec
# state=latest name=pkgspec
#
# informational commands:
# list=installed
# list=updates
# list=available
# list=repos
# list=pkgspec
module = AnsibleModule (
argument_spec = dict (
name = dict ( aliases = [ ' pkg ' ] , type = " list " ) ,
exclude = dict ( required = False , default = None ) ,
# removed==absent, installed==present, these are accepted as aliases
state = dict ( default = ' installed ' , choices = [ ' absent ' , ' present ' , ' installed ' , ' removed ' , ' latest ' ] ) ,
enablerepo = dict ( ) ,
disablerepo = dict ( ) ,
list = dict ( ) ,
conf_file = dict ( default = None ) ,
disable_gpg_check = dict ( required = False , default = " no " , type = ' bool ' ) ,
update_cache = dict ( required = False , default = " no " , type = ' bool ' ) ,
# this should not be needed, but exists as a failsafe
install_repoquery = dict ( required = False , default = " yes " , type = ' bool ' ) ,
) ,
required_one_of = [ [ ' name ' , ' list ' ] ] ,
mutually_exclusive = [ [ ' name ' , ' list ' ] ] ,
supports_check_mode = True
)
# this should not be needed, but exists as a failsafe
params = module . params
if params [ ' install_repoquery ' ] and not repoquery and not module . check_mode :
install_yum_utils ( module )
if params [ ' list ' ] :
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 ' ] ) )
module . exit_json ( * * results )
else :
pkg = [ p . strip ( ) for p in params [ ' name ' ] ]
exclude = params [ ' exclude ' ]
state = params [ ' state ' ]
enablerepo = params . get ( ' enablerepo ' , ' ' )
disablerepo = params . get ( ' disablerepo ' , ' ' )
disable_gpg_check = params [ ' disable_gpg_check ' ]
res = ensure ( module , state , pkg , params [ ' conf_file ' ] , enablerepo ,
disablerepo , disable_gpg_check , exclude )
module . fail_json ( msg = " we should never get here unless this all failed " , * * res )
# import module snippets
from ansible . module_utils . basic import *
from ansible . module_utils . urls import *
if __name__ == ' __main__ ' :
main ( )