Merge pull request #4485 from privateip/nxos_config

update nxos_config with new arguments
This commit is contained in:
Peter Sprygada 2016-08-22 15:43:53 -04:00 committed by GitHub
commit 7c4618d8c2

View file

@ -37,7 +37,8 @@ options:
in the device running-config. Be sure to note the configuration in the device running-config. Be sure to note the configuration
command syntax as some commands are automatically modified by the command syntax as some commands are automatically modified by the
device config parser. device config parser.
required: true required: false
default: null
parents: parents:
description: description:
- The ordered set of parents that uniquely identify the section - The ordered set of parents that uniquely identify the section
@ -46,6 +47,17 @@ options:
level or global commands. level or global commands.
required: false required: false
default: null 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: 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
@ -71,9 +83,12 @@ options:
match is set to I(strict), command lines are matched with respect match is set to I(strict), command lines are matched with respect
to position. Finally if match is set to I(exact), command lines to position. Finally if match is set to I(exact), command lines
must be an equal match. 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 required: false
default: line default: line
choices: ['line', 'strict', 'exact'] choices: ['line', 'strict', 'exact', 'none']
replace: replace:
description: description:
- Instructs the module on the way to perform the configuration - 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 current devices running-config. When set to true, this will
cause the module to push the contents of I(src) into the device cause the module to push the contents of I(src) into the device
without first checking if already configured. 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: false default: false
choices: [ "true", "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: config:
description: description:
- The module, by default, will connect to the remote device and - The module, by default, will connect to the remote device and
@ -105,12 +136,55 @@ options:
config for comparison. config for comparison.
required: false required: false
default: null 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 = """ EXAMPLES = """
- nxos_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: 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: - nxos_config:
lines: lines:
@ -119,9 +193,10 @@ EXAMPLES = """
- 30 permit ip 3.3.3.3/32 any log - 30 permit ip 3.3.3.3/32 any log
- 40 permit ip 4.4.4.4/32 any log - 40 permit ip 4.4.4.4/32 any log
- 50 permit ip 5.5.5.5/32 any log - 50 permit ip 5.5.5.5/32 any log
parents: ['ip access-list test'] parents: ip access-list test
before: ['no ip access-list test'] before: no ip access-list test
match: exact match: exact
provider: "{{ cli }}"
- nxos_config: - nxos_config:
lines: lines:
@ -129,16 +204,10 @@ EXAMPLES = """
- 20 permit ip 2.2.2.2/32 any log - 20 permit ip 2.2.2.2/32 any log
- 30 permit ip 3.3.3.3/32 any log - 30 permit ip 3.3.3.3/32 any log
- 40 permit ip 4.4.4.4/32 any log - 40 permit ip 4.4.4.4/32 any log
parents: ['ip access-list test'] parents: ip access-list test
before: ['no ip access-list test'] before: no ip access-list test
replace: block replace: block
provider: "{{ cli }}"
- nxos_config:
lines: "{{lookup('file', 'datcenter1.txt')}}"
parents: ['ip access-list test']
before: ['no ip access-list test']
replace: block
""" """
RETURN = """ RETURN = """
@ -147,83 +216,179 @@ updates:
returned: always returned: always
type: list type: list
sample: ['...', '...'] sample: ['...', '...']
responses:
description: The set of responses from issuing the commands on the device
retured: when not check_mode
type: list
sample: ['...', '...']
""" """
import time
def get_config(module): from ansible.module_utils.netcfg import NetworkConfig, dumps
config = module.params['config'] or dict() from ansible.module_utils.nxos import NetworkModule, NetworkError
if not config and not module.params['force']: from ansible.module_utils.basic import get_exception
config = module.config
return config
def invoke(name, *args, **kwargs):
func = globals().get(name)
if func:
return func(*args, **kwargs)
def main(): def check_args(module, warnings):
if module.params['save'] and module.check_mode:
argument_spec = dict( warnings.append('will not save configuration due to checkmode')
lines=dict(aliases=['commands'], required=True, type='list'), if module.params['parents'] and module.params['src']:
parents=dict(type='list'), warnings.append('ignoring parents argument when src specified')
before=dict(type='list'), if module.params['force']:
after=dict(type='list'), warnings.append('The force argument is deprecated, please use '
match=dict(default='line', choices=['line', 'strict', 'exact']), 'match=none instead. This argument will be '
replace=dict(default='line', choices=['line', 'block']), 'removed in the future')
force=dict(default=False, type='bool'),
config=dict()
)
module = get_module(argument_spec=argument_spec,
supports_check_mode=True)
lines = module.params['lines']
parents = module.params['parents'] or list()
before = module.params['before']
after = module.params['after']
match = module.params['match']
replace = module.params['replace']
contents = get_config(module)
config = module.parse_config(contents)
if not module.params['force']:
contents = get_config(module)
config = NetworkConfig(contents=contents, indent=2)
def get_candidate(module):
candidate = NetworkConfig(indent=2) candidate = NetworkConfig(indent=2)
candidate.add(lines, parents=parents) 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
commands = candidate.difference(config, path=parents, match=match, replace=replace) def get_config(module, result):
defaults = module.params['defaults']
if defaults is True:
key = '__configall__'
else: else:
commands = parents key = '__config__'
commands.extend(lines)
result = dict(changed=False) contents = module.params['config'] or result.get(key)
if commands: if not contents:
if before: contents = module.config.get_config(include_defaults=defaults)
commands[:0] = before result[key] = contents
if after: return NetworkConfig(indent=1, contents=contents)
commands.extend(after)
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: if not module.check_mode:
commands = [str(c).strip() for c in commands] checkpoint = 'ansible_%s' % int(time.time())
response = module.configure(commands) module.cli(['checkpoint %s' % checkpoint], output='text')
result['responses'] = response result['__checkpoint__'] = checkpoint
module.config.load_config(commands)
result['changed'] = True 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 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'], 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', 'none']),
replace=dict(default='line', choices=['line', 'block']),
# this argument is deprecated in favor of setting match: none
# 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(),
defaults=dict(type='bool', default=False),
save=dict(type='bool', default=False),
state=dict(default='present', choices=['absent', 'present'])
)
mutually_exclusive = [('lines', 'src')]
module = NetworkModule(argument_spec=argument_spec,
connect_on_load=False,
mutually_exclusive=mutually_exclusive,
supports_check_mode=True)
state = module.params['state']
if module.params['force'] is True:
module.params['match'] = 'none'
warnings = list()
check_args(module, warnings)
result = dict(changed=False, warnings=warnings)
try:
invoke(state, module, result)
except NetworkError:
load_checkpoint(module, result)
exc = get_exception()
module.fail_json(msg=str(exc), **exc.kwargs)
module.exit_json(**result) 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__': if __name__ == '__main__':
main() main()