@ -37,7 +37,8 @@ options:
in the device running - config . Be sure to note the configuration
command syntax as some commands are automatically modified by the
device config parser .
required : true
required : false
default : null
parents :
description :
- The ordered set of parents that uniquely identify the section
@ -46,6 +47,17 @@ options:
level or global commands .
required : false
default : null
src :
description :
- The I ( src ) argument provides a path to the configuration file
to load into the remote system . The path can either be a full
system path to the configuration file if the value starts with /
or relative to the root of the implemented role or playbook .
This arugment is mutually exclusive with the I ( lines ) and
I ( parents ) arguments .
required : false
default : null
version_added : " 2.2 "
before :
description :
- The ordered set of commands to push on to the command stack if
@ -71,9 +83,12 @@ options:
match is set to I ( strict ) , command lines are matched with respect
to position . Finally if match is set to I ( exact ) , command lines
must be an equal match .
- Version 2.2 added a new choice I ( none ) . When match is set to
none , the configure is loaded into the remote device without
consulting the configuration .
required : false
default : line
choices : [ ' line ' , ' strict ' , ' exact ' ]
choices : [ ' line ' , ' strict ' , ' exact ' , ' none ' ]
replace :
description :
- Instructs the module on the way to perform the configuration
@ -91,9 +106,25 @@ options:
current devices running - config . When set to true , this will
cause the module to push the contents of I ( src ) into the device
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
default : false
choices : [ " true " , " false " ]
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 "
config :
description :
- The module , by default , will connect to the remote device and
@ -105,12 +136,55 @@ options:
config for comparison .
required : false
default : null
defaults :
description :
- The I ( defaults ) argument will influence how the running - config
is collected from the device . When the value is set to true ,
the command used to collect the running - config is append with
the all keyword . When the value is set to false , the command
is issued without the all keyword
required : false
default : false
version_added : " 2.2 "
save :
description :
- The I ( save ) argument will instruct the module to save the
running - config to startup - config . This operation is performed
after any changes are made to the current running config . If
no changes are made , the configuration is still saved to the
startup config . This option will always cause the module to
return changed .
required : false
default : false
version_added : " 2.2 "
state :
description :
- The I ( state ) argument specifies the state of the config
file on the device . When set to present , the configuration
is updated based on the values of the module . When the value
is set to absent , the device startup config is erased .
required : true
default : present
choices : [ ' present ' , ' absent ' ]
version_added : " 2.2 "
"""
EXAMPLES = """
- nxos_config :
lines : [ ' hostname {{ inventory_hostname }} ' ]
force : yes
# Note: examples below use the following provider dict to handle
# transport and authentication to the node.
vars :
cli :
host : " {{ inventory_hostname }} "
username : admin
password : admin
transport : cli
- name : configure top level configuration and save it
nxos_config :
lines : hostname { { inventory_hostname } }
save : yes
provider : " {{ cli }} "
- nxos_config :
lines :
@ -119,9 +193,10 @@ EXAMPLES = """
- 30 permit ip 3.3 .3 .3 / 32 any log
- 40 permit ip 4.4 .4 .4 / 32 any log
- 50 permit ip 5.5 .5 .5 / 32 any log
parents : [ ' ip access-list test ' ]
before : [ ' no ip access-list test ' ]
parents : ip access - list test
before : no ip access - list test
match : exact
provider : " {{ cli }} "
- nxos_config :
lines :
@ -129,16 +204,10 @@ EXAMPLES = """
- 20 permit ip 2.2 .2 .2 / 32 any log
- 30 permit ip 3.3 .3 .3 / 32 any log
- 40 permit ip 4.4 .4 .4 / 32 any log
parents : [ ' ip access-list test ' ]
before : [ ' no ip access-list test ' ]
replace : block
- nxos_config :
lines : " {{ lookup( ' file ' , ' datcenter1.txt ' )}} "
parents : [ ' ip access-list test ' ]
before : [ ' no ip access-list test ' ]
parents : ip access - list test
before : no ip access - list test
replace : block
provider : " {{ cli }} "
"""
RETURN = """
@ -147,83 +216,179 @@ updates:
returned : always
type : list
sample : [ ' ... ' , ' ... ' ]
responses :
description : The set of responses from issuing the commands on the device
retured : when not check_mode
type : list
sample : [ ' ... ' , ' ... ' ]
"""
import time
from ansible . module_utils . netcfg import NetworkConfig , dumps
from ansible . module_utils . nxos import NetworkModule , NetworkError
from ansible . module_utils . basic import get_exception
def invoke ( name , * args , * * kwargs ) :
func = globals ( ) . get ( name )
if func :
return func ( * args , * * kwargs )
def check_args ( module , warnings ) :
if module . params [ ' save ' ] and module . check_mode :
warnings . append ( ' will not save configuration due to checkmode ' )
if module . params [ ' parents ' ] and module . params [ ' src ' ] :
warnings . append ( ' ignoring parents argument when src specified ' )
if module . params [ ' force ' ] :
warnings . append ( ' The force argument is deprecated, please use '
' match=none instead. This argument will be '
' removed in the future ' )
def get_candidate ( module ) :
candidate = NetworkConfig ( indent = 2 )
if module . params [ ' src ' ] :
candidate . load ( module . params [ ' src ' ] )
elif module . params [ ' lines ' ] :
parents = module . params [ ' parents ' ] or list ( )
candidate . add ( module . params [ ' lines ' ] , parents = parents )
return candidate
def get_config ( module , result ) :
defaults = module . params [ ' defaults ' ]
if defaults is True :
key = ' __configall__ '
else :
key = ' __config__ '
def get_config ( module ) :
config = module . params [ ' config ' ] or dict ( )
if not config and not module . params [ ' force ' ] :
config = module . config
return 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 backup_config ( module , result ) :
if ' __config__ ' not in result :
result [ ' __config__ ' ] = module . config . get_config ( )
result [ ' __backup__ ' ] = result [ ' __config__ ' ]
def load_config ( module , commands , result ) :
if not module . check_mode :
checkpoint = ' ansible_ %s ' % int ( time . time ( ) )
module . cli ( [ ' checkpoint %s ' % checkpoint ] , output = ' text ' )
result [ ' __checkpoint__ ' ] = checkpoint
module . config . load_config ( commands )
result [ ' changed ' ] = True
def load_checkpoint ( module , result ) :
try :
checkpoint = result [ ' __checkpoint__ ' ]
module . cli ( [ ' rollback running-config checkpoint %s ' % checkpoint ,
' no checkpoint %s ' % checkpoint ] , output = ' text ' )
except KeyError :
module . fail_json ( msg = ' unable to rollback, checkpoint not found ' )
except NetworkError :
exc = get_exception ( )
msg = ' unable to rollback configuration '
module . fail_json ( msg = msg , checkpoint = checkpoint , * * exc . kwargs )
def present ( module , result ) :
match = module . params [ ' match ' ]
replace = module . params [ ' replace ' ]
update = module . params [ ' update ' ]
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 module . params [ ' backup ' ] :
backup_config ( module , result )
if configobjs :
commands = dumps ( configobjs , ' commands ' ) . split ( ' \n ' )
result [ ' updates ' ] = commands
if module . params [ ' before ' ] :
commands [ : 0 ] = module . params [ ' before ' ]
if module . params [ ' after ' ] :
commands . extend ( module . params [ ' after ' ] )
# if the update mode is set to check just return
# and do not try to load into the system
if update != ' check ' :
load_config ( module , commands , result )
# remove the checkpoint file used to restore the config
# in case of an error
if not module . check_mode :
module . cli ( ' no checkpoint %s ' % result [ ' __checkpoint__ ' ] )
if module . params [ ' save ' ] and not module . check_mode :
module . config . save_config ( )
result [ ' changed ' ] = True
def absent ( module , result ) :
if not module . check_mode :
module . cli ( ' write erase ' )
result [ ' changed ' ] = True
def main ( ) :
""" main entry point for module execution
"""
argument_spec = dict (
lines = dict ( aliases = [ ' commands ' ] , required = True , type = ' list ' ) ,
lines = dict ( aliases = [ ' commands ' ] , type = ' list ' ) ,
parents = dict ( type = ' list ' ) ,
src = dict ( type = ' path ' ) ,
before = dict ( type = ' list ' ) ,
after = dict ( type = ' list ' ) ,
match = dict ( default = ' line ' , choices = [ ' line ' , ' strict ' , ' exact ' ] ) ,
match = dict ( default = ' line ' , choices = [ ' line ' , ' strict ' , ' exact ' , ' none ' ] ) ,
replace = dict ( default = ' line ' , choices = [ ' line ' , ' block ' ] ) ,
force = dict ( default = False , type = ' bool ' ) ,
config = dict ( )
)
module = get_module ( argument_spec = argument_spec ,
supports_check_mode = True )
# this argument is deprecated in favor of setting match: none
# it will be removed in a future version
force = dict ( default = False , type = ' bool ' ) ,
lines = module . params [ ' lines ' ]
parents = module . params [ ' parents ' ] or list ( )
update = dict ( choices = [ ' merge ' , ' check ' ] , default = ' merge ' ) ,
backup = dict ( type = ' bool ' , default = False ) ,
before = module . params [ ' before ' ]
after = module . params [ ' after ' ]
config = dict ( ) ,
defaults = dict ( type = ' bool ' , default = False ) ,
match = module . params [ ' match ' ]
replace = module . params [ ' replace ' ]
save = dict ( type = ' bool ' , default = False ) ,
contents = get_config ( module )
config = module . parse_config ( contents )
state = dict ( default = ' present ' , choices = [ ' absent ' , ' present ' ] )
)
if not module . params [ ' force ' ] :
contents = get_config ( module )
config = NetworkConfig ( contents = contents , indent = 2 )
mutually_exclusive = [ ( ' lines ' , ' src ' ) ]
candidate = NetworkConfig ( indent = 2 )
candidate . add ( lines , parents = parents )
module = NetworkModule ( argument_spec = argument_spec ,
connect_on_load = False ,
mutually_exclusive = mutually_exclusive ,
supports_check_mode = True )
commands = candidate . difference ( config , path = parents , match = match , replace = replace )
else :
commands = parents
commands . extend ( lines )
state = module . params [ ' state ' ]
result = dict ( changed = False )
if module . params [ ' force ' ] is True :
module . params [ ' match ' ] = ' none '
if commands :
if before :
commands [ : 0 ] = before
warnings = list ( )
check_args ( module , warnings )
if after :
commands . extend ( after )
result = dict ( changed = False , warnings = warnings )
if not module . check_mode :
commands = [ str ( c ) . strip ( ) for c in commands ]
response = module . configure ( commands )
result [ ' responses ' ] = response
result [ ' changed ' ] = True
try :
invoke ( state , module , result )
except NetworkError :
load_checkpoint ( module , result )
exc = get_exception ( )
module . fail_json ( msg = str ( exc ) , * * exc . kwargs )
result [ ' updates ' ] = commands
module . exit_json ( * * result )
from ansible . module_utils . basic import *
from ansible . module_utils . urls import *
from ansible . module_utils . shell import *
from ansible . module_utils . netcfg import *
from ansible . module_utils . nxos import *
if __name__ == ' __main__ ' :
main ( )