@ -57,30 +57,6 @@ options:
required : false
required : false
default : null
default : null
version_added : " 2.2 "
version_added : " 2.2 "
dest :
description :
- Configures a destination file to write the source template or config
updates to . The path to the destination file can either be a full
path on the Ansible control host or a relative path from the
playbook or role root directory . This will , by default , overwrite any
previously created file . See I ( append ) to change the behavior .
- When the I ( dest ) argument is used , the output from processing the
configuration lines is written to a file and not to the actual
device . If theI ( dest ) argument is omitted , then the configuration
is written to the device .
required : false
default : null
version_added : " 2.2 "
append :
description :
- Changes the default behavior when writing the configuration out
to a remote file on disk . By default if I ( dest ) is specified , the
file is overridden . By setting this argument to true , the remote
file ( if it exists ) is appended to .
required : false
default : no
choices : [ ' yes ' , ' no ' ]
version_added : " 2.2 "
before :
before :
description :
description :
- The ordered set of commands to push on to the command stack if
- The ordered set of commands to push on to the command stack if
@ -122,17 +98,44 @@ options:
required : false
required : false
default : line
default : line
choices : [ ' line ' , ' block ' ]
choices : [ ' line ' , ' block ' ]
update_config :
force :
description :
description :
- This arugment will either cause or prevent the changed commands
- The force argument instructs the module to not consider the
from being sent to the remote device . The set to true , the
current devices running - config . When set to true , this will
remote IOS device will be configured with the updated commands
cause the module to push the contents of I ( src ) into the device
and when set to false , the remote device will not be updated .
without first checking if already configured .
- Note this argument should be considered deprecated . To achieve
the equivalient , set the match argument to none . This argument
will be removed in a future release .
required : false
required : false
default : yes
default : false
choices : [ ' yes ' , ' no ' ]
choices : [ " true " , " false " ]
version_added : " 2.2 "
update :
description :
- The I ( update ) argument controls how the configuration statements
are processed on the remote device . Valid choices for the I ( update )
argument are I ( merge ) and I ( check ) . When the argument is set to
I ( merge ) , the configuration changes are merged with the current
device running configuration . When the argument is set to I ( check )
the configuration updates are determined but not actually configured
on the remote device .
required : false
default : merge
choices : [ ' merge ' , ' check ' ]
version_added : " 2.2 "
version_added : " 2.2 "
backup_config :
commit :
description :
- This argument specifies the update method to use when applying the
configuration changes to the remote node . If the value is set to
I ( merge ) the configuration updates are merged with the running -
config . If the value is set to I ( check ) , no changes are made to
the remote host .
required : false
default : merge
choices : [ ' merge ' , ' check ' ]
version_added : " 2.2 "
backup :
description :
description :
- This argument will cause the module to create a full backup of
- This argument will cause the module to create a full backup of
the current C ( running - config ) from the remote device before any
the current C ( running - config ) from the remote device before any
@ -143,39 +146,80 @@ options:
default : no
default : no
choices : [ ' yes ' , ' no ' ]
choices : [ ' yes ' , ' no ' ]
version_added : " 2.2 "
version_added : " 2.2 "
config :
description :
- The C ( config ) argument allows the playbook desginer to supply
the base configuration to be used to validate configuration
changes necessary . If this argument is provided , the module
will not download the running - config from the remote node .
required : false
default : null
version_added : " 2.2 "
default :
description :
- This argument specifies whether or not to collect all defaults
when getting the remote device running config . When enabled ,
the module will get the current config by issuing the command
C ( show running - config all ) .
required : false
default : no
choices : [ ' yes ' , ' no ' ]
version_added : " 2.2 "
save :
description :
- The C ( save ) argument instructs the module to save the running -
config to the startup - config at the conclusion of the module
running . If check mode is specified , this argument is ignored .
required : false
default : no
choices : [ ' yes ' , ' no ' ]
version_added : " 2.2 "
state :
description :
- This argument specifies whether or not the running - config is
present on the remote device . When set to I ( absent ) the
running - config on the remote device is erased .
required : false
default : no
choices : [ ' yes ' , ' no ' ]
version_added : " 2.2 "
"""
"""
EXAMPLES = """
EXAMPLES = """
- ios_config :
# Note: examples below use the following provider dict to handle
lines : [ ' hostname {{ inventory_hostname }} ' ]
# transport and authentication to the node.
force : yes
vars :
cli :
host : " {{ inventory_hostname }} "
username : cisco
password : cisco
transport : cli
- name : configure top level configuration
ios_config :
lines : hostname { { inventory_hostname } }
provider : " {{ cli }} "
- name : configure interface settings
ios_config :
lines :
- description test interface
- ip address 172.31 .1 .1 255.255 .255 .0
parents : interface Ethernet1
provider : " {{ cli }} "
- ios_config :
- name : load new acl into device
ios_config :
lines :
lines :
- 10 permit ip host 1.1 .1 .1 any log
- 10 permit ip host 1.1 .1 .1 any log
- 20 permit ip host 2.2 .2 .2 any log
- 20 permit ip host 2.2 .2 .2 any log
- 30 permit ip host 3.3 .3 .3 any log
- 30 permit ip host 3.3 .3 .3 any log
- 40 permit ip host 4.4 .4 .4 any log
- 40 permit ip host 4.4 .4 .4 any log
- 50 permit ip host 5.5 .5 .5 any log
- 50 permit ip host 5.5 .5 .5 any log
parents : [ ' ip access-list extended test ' ]
parents : ip access - list extended test
before : [ ' no ip access-list extended test ' ]
before : no ip access - list extended test
match : exact
match : exact
provider : " {{ cli }} "
- ios_config :
lines :
- 10 permit ip host 1.1 .1 .1 any log
- 20 permit ip host 2.2 .2 .2 any log
- 30 permit ip host 3.3 .3 .3 any log
- 40 permit ip host 4.4 .4 .4 any log
parents : [ ' ip access-list extended test ' ]
before : [ ' no ip access-list extended test ' ]
replace : block
- ios_config :
commands : " {{ lookup( ' file ' , ' datcenter1.txt ' )}} "
parents : [ ' ip access-list test ' ]
before : [ ' no ip access-list test ' ]
replace : block
"""
"""
@ -185,16 +229,23 @@ updates:
returned : always
returned : always
type : list
type : list
sample : [ ' ... ' , ' ... ' ]
sample : [ ' ... ' , ' ... ' ]
backup_path :
description : The full path to the backup file
returned : when backup is yes
type : path
sample : / playbooks / ansible / backup / ios_config .2016 - 07 - 16 @ 22 : 28 : 34
responses :
responses :
description : The set of responses from issuing the commands on the device
description : The set of responses from issuing the commands on the device
returned : when not check_mode
returned : when not check_mode
type : list
type : list
sample : [ ' ... ' , ' ... ' ]
sample : [ ' ... ' , ' ... ' ]
"""
"""
import re
from ansible . module_utils . basic import get_exception
from ansible . module_utils . ios import NetworkModule , NetworkError
from ansible . module_utils . netcfg import NetworkConfig , dumps
from ansible . module_utils . netcfg import NetworkConfig , dumps
from ansible . module_utils . network import NetworkModule
from ansible . module_utils . netcli import Command
from ansible . module_utils . ios import load_config , get_config , ios_argument_spec
def invoke ( name , * args , * * kwargs ) :
def invoke ( name , * args , * * kwargs ) :
func = globals ( ) . get ( name )
func = globals ( ) . get ( name )
@ -204,11 +255,28 @@ def invoke(name, *args, **kwargs):
def check_args ( module , warnings ) :
def check_args ( module , warnings ) :
if module . params [ ' parents ' ] :
if module . params [ ' parents ' ] :
if not module . params [ ' lines ' ] or module . params [ ' src ' ] :
if not module . params [ ' lines ' ] or module . params [ ' src ' ] :
warnings . append ( ' ignoring unne eded argument parents' )
warnings . append ( ' ignoring unne cessary argument parents' )
if module . params [ ' match ' ] == ' none ' and module . params [ ' replace ' ] :
if module . params [ ' match ' ] == ' none ' and module . params [ ' replace ' ] :
warnings . append ( ' ignorning unneeded argument replace ' )
warnings . append ( ' ignorning unnecessary argument replace ' )
if module . params [ ' dest ' ] and module . params [ ' save_config ' ] is True :
if module . params [ ' force ' ] :
warnings . append ( ' config will not be saved with dest argument used ' )
warnings . append ( ' The force argument is deprecated, please use '
' match=none instead. This argument will be '
' removed in the future ' )
def get_config ( module , result ) :
defaults = module . params [ ' default ' ]
if defaults is True :
key = ' __configall__ '
else :
key = ' __config__ '
contents = module . params [ ' config ' ] or result . get ( key )
if not contents :
contents = module . config . get_config ( include_defaults = defaults )
result [ key ] = contents
return NetworkConfig ( indent = 1 , contents = contents )
def get_candidate ( module ) :
def get_candidate ( module ) :
candidate = NetworkConfig ( indent = 1 )
candidate = NetworkConfig ( indent = 1 )
@ -219,6 +287,65 @@ def get_candidate(module):
candidate . add ( module . params [ ' lines ' ] , parents = parents )
candidate . add ( module . params [ ' lines ' ] , parents = parents )
return candidate
return candidate
def load_backup ( module ) :
try :
module . cli ( [ ' exit ' , ' config replace flash:/ansible-rollback force ' ] )
except NetworkError :
module . fail_json ( msg = ' unable to rollback configuration ' )
def backup_config ( module ) :
cmd = ' copy running-config flash:/ansible-rollback '
cmd = Command ( cmd , prompt = re . compile ( ' \ ? $ ' ) , response = ' \n ' )
module . cli ( cmd )
def load_config ( module , commands , result ) :
if not module . check_mode and module . params [ ' update ' ] != ' check ' :
module . config ( commands )
result [ ' changed ' ] = module . params [ ' update ' ] != ' check '
result [ ' updates ' ] = commands . split ( ' \n ' )
def present ( module , result ) :
match = module . params [ ' match ' ]
replace = module . params [ ' replace ' ]
candidate = get_candidate ( module )
if match != ' none ' :
config = get_config ( module , result )
configobjs = candidate . difference ( config , match = match , replace = replace )
else :
config = None
configobjs = candidate . items
if configobjs :
commands = dumps ( configobjs , ' commands ' )
if module . params [ ' before ' ] :
commands [ : 0 ] = module . params [ ' before ' ]
if module . params [ ' after ' ] :
commands . extend ( module . params [ ' after ' ] )
# create a backup copy of the current running-config on
# device flash drive
backup_config ( module )
# send the configuration commands to the device and merge
# them with the current running config
load_config ( module , commands , result )
# remove the backup copy of the running-config since its
# no longer needed
module . cli ( ' delete /force flash:/ansible-rollback ' )
if module . params [ ' save ' ] and not module . check_mode :
module . config . save_config ( )
def absent ( module , result ) :
if not module . check_mode :
module . cli ( ' write erase ' )
result [ ' changed ' ] = True
def main ( ) :
def main ( ) :
argument_spec = dict (
argument_spec = dict (
@ -233,10 +360,20 @@ def main():
match = dict ( default = ' line ' , choices = [ ' line ' , ' strict ' , ' exact ' , ' none ' ] ) ,
match = dict ( default = ' line ' , choices = [ ' line ' , ' strict ' , ' exact ' , ' none ' ] ) ,
replace = dict ( default = ' line ' , choices = [ ' line ' , ' block ' ] ) ,
replace = dict ( default = ' line ' , choices = [ ' line ' , ' block ' ] ) ,
update_config = dict ( type = ' bool ' , default = False ) ,
# this argument is deprecated in favor of setting match: none
backup_config = dict ( type = ' bool ' , default = False )
# it will be removed in a future version
force = dict ( default = False , type = ' bool ' ) ,
update = dict ( choices = [ ' merge ' , ' check ' ] , default = ' merge ' ) ,
backup = dict ( type = ' bool ' , default = False ) ,
config = dict ( ) ,
default = dict ( type = ' bool ' , default = False ) ,
save = dict ( type = ' bool ' , default = False ) ,
state = dict ( choices = [ ' present ' , ' absent ' ] , default = ' present ' )
)
)
argument_spec . update ( ios_argument_spec )
mutually_exclusive = [ ( ' lines ' , ' src ' ) ]
mutually_exclusive = [ ( ' lines ' , ' src ' ) ]
@ -245,48 +382,25 @@ def main():
mutually_exclusive = mutually_exclusive ,
mutually_exclusive = mutually_exclusive ,
supports_check_mode = True )
supports_check_mode = True )
module. check_mode = not module . params [ ' update_config ' ]
state = module . params [ ' state ' ]
parents = module . params [ ' parents ' ] or list ( )
if module . params [ ' force ' ] is True :
module . params [ ' match ' ] = ' none '
match = module . params [ ' match ' ]
replace = module . params [ ' replace ' ]
warnings = list ( )
warnings = list ( )
invoke ( ' check_args ' , module , warnings )
check_args ( module , warnings )
result = dict ( changed = False , saved = False )
candidate = get_candidate ( module )
if module . params [ ' match ' ] != ' none ' :
config = get_config ( module )
configobjs = candidate . difference ( config , match = match , replace = replace )
else :
configobjs = candidate . items
if module . params [ ' backup_config ' ] :
result [ ' __backup__ ' ] = module . cli ( ' show running-config ' ) [ 0 ]
commands = list ( )
result = dict ( changed = False , warnings = warnings )
if configobjs :
commands = dumps ( configobjs , ' commands ' )
commands = commands . split ( ' \n ' )
if module . params [ ' before ' ] :
commands [ : 0 ] = module . params [ ' before ' ]
if module . params [ ' after ' ] :
if module . params [ ' backup ' ] :
commands . extend ( module . params [ ' after ' ] )
result [ ' __backup__ ' ] = module . config . get_config ( )
if not module . check_mode :
response = load_config ( module , commands , nodiff = True )
result . update ( * * response )
result [ ' changed ' ] = True
result [ ' updates ' ] = commands
try :
result [ ' connected ' ] = module . connected
invoke ( state , module , result )
except NetworkError :
load_backup ( module )
exc = get_exception ( )
module . fail_json ( msg = str ( exc ) )
module . exit_json ( * * result )
module . exit_json ( * * result )