nxos_vpc updates (#25452)

* Add nxos_vpc tests

* Split execute-show between get_config and run_commands
pull/25709/head
Nathaniel Case 8 years ago committed by GitHub
parent ccb5756d1f
commit 4344132a7d

@ -16,9 +16,11 @@
# along with Ansible. If not, see <http://www.gnu.org/licenses/>. # along with Ansible. If not, see <http://www.gnu.org/licenses/>.
# #
ANSIBLE_METADATA = {'metadata_version': '1.0', ANSIBLE_METADATA = {
'status': ['preview'], 'metadata_version': '1.0',
'supported_by': 'community'} 'status': ['preview'],
'supported_by': 'community',
}
DOCUMENTATION = ''' DOCUMENTATION = '''
@ -28,68 +30,68 @@ extends_documentation_fragment: nxos
version_added: "2.2" version_added: "2.2"
short_description: Manages global VPC configuration short_description: Manages global VPC configuration
description: description:
- Manages global VPC configuration - Manages global VPC configuration
author: author:
- Jason Edelman (@jedelman8) - Jason Edelman (@jedelman8)
- Gabriele Gerbino (@GGabriele) - Gabriele Gerbino (@GGabriele)
notes: notes:
- The feature vpc must be enabled before this module can be used - The feature vpc must be enabled before this module can be used
- If not using management vrf, vrf must be globally on the device - If not using management vrf, vrf must be globally on the device
before using in the pkl config before using in the pkl config
- Although source IP isn't required on the command line it is - Although source IP isn't required on the command line it is
required when using this module. The PKL VRF must also be configured required when using this module. The PKL VRF must also be configured
prior to using this module. prior to using this module.
- Both pkl_src and pkl_dest are needed when changing PKL VRF. - Both pkl_src and pkl_dest are needed when changing PKL VRF.
options: options:
domain: domain:
description: description:
- VPC domain - VPC domain
required: true required: true
role_priority: role_priority:
description: description:
- Role priority for device. Remember lower is better. - Role priority for device. Remember lower is better.
required: false required: false
default: null default: null
system_priority: system_priority:
description: description:
- System priority device. Remember they must match between peers. - System priority device. Remember they must match between peers.
required: false required: false
default: null default: null
pkl_src: pkl_src:
description: description:
- Source IP address used for peer keepalive link - Source IP address used for peer keepalive link
required: false required: false
default: null default: null
pkl_dest: pkl_dest:
description: description:
- Destination (remote) IP address used for peer keepalive link - Destination (remote) IP address used for peer keepalive link
required: false required: false
default: null default: null
pkl_vrf: pkl_vrf:
description: description:
- VRF used for peer keepalive link - VRF used for peer keepalive link
required: false required: false
default: management default: management
peer_gw: peer_gw:
description: description:
- Enables/Disables peer gateway - Enables/Disables peer gateway
required: true required: true
choices: ['true','false'] choices: ['true','false']
auto_recovery: auto_recovery:
description: description:
- Enables/Disables auto recovery - Enables/Disables auto recovery
required: true required: true
choices: ['true','false'] choices: ['true','false']
delay_restore: delay_restore:
description: description:
- manages delay restore command and config value in seconds - manages delay restore command and config value in seconds
required: false required: false
default: null default: null
state: state:
description: description:
- Manages desired state of the resource - Manages desired state of the resource
required: true required: true
choices: ['present','absent'] choices: ['present','absent']
''' '''
EXAMPLES = ''' EXAMPLES = '''
@ -102,69 +104,30 @@ EXAMPLES = '''
pkl_src: 10.1.100.20 pkl_src: 10.1.100.20
peer_gw: true peer_gw: true
auto_recovery: true auto_recovery: true
username: "{{ un }}"
password: "{{ pwd }}"
host: "{{ inventory_hostname }}"
''' '''
RETURN = ''' RETURN = '''
proposed: commands:
description: k/v pairs of parameters passed into module
returned: always
type: dict
sample: {"auto_recovery": true, "domain": "100",
"peer_gw": true, "pkl_dest": "192.168.100.4",
"pkl_src": "10.1.100.20", "pkl_vrf": "management",
"role_priority": "1000", "system_priority": "2000"}
existing:
description: k/v pairs of existing VPC configuration
returned: always
type: dict
sample: {"auto_recovery": true, "delay_restore": null,
"domain": "100", "peer_gw": true,
"pkl_dest": "192.168.100.2", "pkl_src": "10.1.100.20",
"pkl_vrf": "management", "role_priority": "1000",
"system_priority": "2000"}
end_state:
description: k/v pairs of VPC configuration after module execution
returned: always
type: dict
sample: {"auto_recovery": true, "domain": "100",
"peer_gw": true, "pkl_dest": "192.168.100.4",
"pkl_src": "10.1.100.20", "pkl_vrf": "management",
"role_priority": "1000", "system_priority": "2000"}
updates:
description: commands sent to the device description: commands sent to the device
returned: always returned: always
type: list type: list
sample: ["vpc domain 100", sample: ["vpc domain 100",
"peer-keepalive destination 192.168.100.4 source 10.1.100.20 vrf management", "peer-keepalive destination 192.168.100.4 source 10.1.100.20 vrf management",
"auto-recovery", "peer-gateway"] "auto-recovery", "peer-gateway"]
changed:
description: check to see if a change was made on the device
returned: always
type: boolean
sample: true
''' '''
from ansible.module_utils.nxos import load_config, run_commands from ansible.module_utils.nxos import get_config, load_config, run_commands
from ansible.module_utils.nxos import nxos_argument_spec, check_args from ansible.module_utils.nxos import nxos_argument_spec, check_args
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
def execute_show_command(command, module, command_type='cli_show'): CONFIG_ARGS = {
if module.params['transport'] == 'cli': 'role_priority': 'role priority {role_priority}',
if "section" not in command: 'system_priority': 'system-priority {system_priority}',
command += ' | json' 'delay_restore': 'delay restore {delay_restore}',
cmds = [command] 'peer_gw': '{peer_gw} peer-gateway',
body = run_commands(module, cmds) 'auto_recovery': '{auto_recovery} auto-recovery',
elif module.params['transport'] == 'nxapi': }
if command_type == 'cli_show_ascii':
cmds = [command]
else:
cmds = [command + ' | json']
body = run_commands(module, cmds)
return body
def flatten_list(command_lists): def flatten_list(command_lists):
@ -178,11 +141,9 @@ def flatten_list(command_lists):
def get_vrf_list(module): def get_vrf_list(module):
command = 'show vrf all'
vrf_table = None
try: try:
body = execute_show_command(command, module)[0] body = run_commands(module, ['show vrf all | json'])[0]
vrf_table = body['TABLE_vrf']['ROW_vrf'] vrf_table = body['TABLE_vrf']['ROW_vrf']
except (KeyError, AttributeError): except (KeyError, AttributeError):
return [] return []
@ -195,30 +156,13 @@ def get_vrf_list(module):
return vrf_list return vrf_list
def get_autorecovery(auto):
auto_recovery = auto.split(' ')[0]
if 'enabled' in auto_recovery.lower():
return True
else:
return False
def get_vpc_running_config(module):
command = 'show running section vpc'
body = execute_show_command(command, module, command_type='cli_show_ascii')
return body
def get_vpc(module): def get_vpc(module):
vpc = {} body = run_commands(module, ['show vpc | json'])[0]
command = 'show vpc'
body = execute_show_command(command, module)[0]
domain = str(body['vpc-domain-id']) domain = str(body['vpc-domain-id'])
auto_recovery = get_autorecovery(str( auto_recovery = 'enabled' in str(body['vpc-auto-recovery-status']).lower()
body['vpc-auto-recovery-status']))
vpc = {}
if domain != 'not configured': if domain != 'not configured':
delay_restore = None delay_restore = None
pkl_src = None pkl_src = None
@ -228,7 +172,7 @@ def get_vpc(module):
pkl_vrf = None pkl_vrf = None
peer_gw = False peer_gw = False
run = get_vpc_running_config(module)[0] run = get_config(module, flags=['section vpc'])
if run: if run:
vpc_list = run.split('\n') vpc_list = run.split('\n')
for each in vpc_list: for each in vpc_list:
@ -252,8 +196,7 @@ def get_vpc(module):
if 'peer-gateway' in each: if 'peer-gateway' in each:
peer_gw = True peer_gw = True
command = 'show vpc peer-keepalive' body = run_commands(module, ['show vpc peer-keepalive | json'])[0]
body = execute_show_command(command, module)[0]
if body: if body:
pkl_dest = body['vpc-keepalive-dest'] pkl_dest = body['vpc-keepalive-dest']
@ -272,8 +215,6 @@ def get_vpc(module):
vpc['pkl_dest'] = pkl_dest vpc['pkl_dest'] = pkl_dest
vpc['pkl_vrf'] = pkl_vrf vpc['pkl_vrf'] = pkl_vrf
vpc['peer_gw'] = peer_gw vpc['peer_gw'] = peer_gw
else:
vpc = {}
return vpc return vpc
@ -320,19 +261,11 @@ def get_commands_to_config_vpc(module, vpc, domain, existing):
else: else:
vpc['peer_gw'] = '' vpc['peer_gw'] = ''
CONFIG_ARGS = { for param in vpc:
'role_priority': 'role priority {role_priority}', command = CONFIG_ARGS.get(param)
'system_priority': 'system-priority {system_priority}', if command is not None:
'delay_restore': 'delay restore {delay_restore}', command = command.format(**vpc).strip()
'peer_gw': '{peer_gw} peer-gateway', commands.append(command)
'auto_recovery': '{auto_recovery} auto-recovery',
}
for param, value in vpc.items():
command = CONFIG_ARGS.get(param, 'DNE').format(**vpc)
if command and command != 'DNE':
commands.append(command.strip())
command = None
if commands or domain_only: if commands or domain_only:
commands.insert(0, 'vpc domain {0}'.format(domain)) commands.insert(0, 'vpc domain {0}'.format(domain))
@ -359,9 +292,6 @@ def main():
auto_recovery=dict(required=True, type='bool'), auto_recovery=dict(required=True, type='bool'),
delay_restore=dict(required=False, type='str'), delay_restore=dict(required=False, type='str'),
state=dict(choices=['absent', 'present'], default='present'), state=dict(choices=['absent', 'present'], default='present'),
include_defaults=dict(default=False),
config=dict(),
save=dict(type='bool', default=False)
) )
argument_spec.update(nxos_argument_spec) argument_spec.update(nxos_argument_spec)
@ -371,6 +301,7 @@ def main():
warnings = list() warnings = list()
check_args(module, warnings) check_args(module, warnings)
results = {'changed': False, 'warnings': warnings}
domain = module.params['domain'] domain = module.params['domain']
role_priority = module.params['role_priority'] role_priority = module.params['role_priority']
@ -407,9 +338,7 @@ def main():
'keepalive link is not on device yet. Add it' 'keepalive link is not on device yet. Add it'
' first, please.') ' first, please.')
proposed = dict((k, v) for k, v in args.items() if v is not None) proposed = dict((k, v) for k, v in args.items() if v is not None)
changed = False
existing = get_vpc(module) existing = get_vpc(module)
end_state = existing
commands = [] commands = []
if state == 'present': if state == 'present':
@ -426,25 +355,15 @@ def main():
commands.append('no vpc domain {0}'.format(domain)) commands.append('no vpc domain {0}'.format(domain))
cmds = flatten_list(commands) cmds = flatten_list(commands)
results['commands'] = cmds
if cmds: if cmds:
if module.check_mode: results['changed'] = True
module.exit_json(changed=True, commands=cmds) if not module.check_mode:
else:
changed = True
load_config(module, cmds) load_config(module, cmds)
end_state = get_vpc(module)
if 'configure' in cmds: if 'configure' in cmds:
cmds.pop(0) cmds.pop(0)
results = {}
results['proposed'] = proposed
results['existing'] = existing
results['end_state'] = end_state
results['updates'] = cmds
results['changed'] = changed
results['warnings'] = warnings
module.exit_json(**results) module.exit_json(**results)

@ -0,0 +1,20 @@
{
"vpc-domain-id": "not configured",
"vpc-peer-status": "peer-not-configured",
"vpc-peer-status-reason": "SUCCESS",
"vpc-peer-keepalive-status": "disabled",
"vpc-peer-consistency": "inconsistent",
"vpc-peer-consistency-status": "SYSERR_MCECM_MCT_DOES_NOT_EXISTS",
"vpc-per-vlan-peer-consistency": "inconsistent",
"vpc-type-2-consistency": "inconsistent",
"vpc-type-2-consistency-status": "SYSERR_MCECM_MCT_DOES_NOT_EXISTS",
"vpc-role": "none-established",
"num-of-vpcs": "0",
"peer-gateway": "disabled",
"dual-active-excluded-vlans": "-",
"vpc-graceful-consistency-check-status": "enabled",
"vpc-auto-recovery-status": "Enabled (timeout = 240 seconds)",
"operational-l3-peer": "disabled",
"vpc-isolation-status": "disabled-user",
"vpc-check-consist-note": "disabled"
}

@ -0,0 +1,30 @@
{
"TABLE_vrf": {
"ROW_vrf": [
{
"vrf_name": "coke",
"vrf_id": 4,
"vrf_state": "Up",
"vrf_reason": "--"
},
{
"vrf_name": "default",
"vrf_id": 1,
"vrf_state": "Up",
"vrf_reason": "--"
},
{
"vrf_name": "management",
"vrf_id": 2,
"vrf_state": "Up",
"vrf_reason": "--"
},
{
"vrf_name": "test-vrf",
"vrf_id": 3,
"vrf_state": "Up",
"vrf_reason": "--"
}
]
}
}

@ -0,0 +1,66 @@
# (c) 2016 Red Hat 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/>.
# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import os
from ansible.compat.tests.mock import patch
from ansible.modules.network.nxos import nxos_vpc
from .nxos_module import TestNxosModule, load_fixture, set_module_args
class TestNxosVpcModule(TestNxosModule):
module = nxos_vpc
def setUp(self):
self.mock_load_config = patch('ansible.modules.network.nxos.nxos_vpc.load_config')
self.load_config = self.mock_load_config.start()
self.mock_run_commands = patch('ansible.modules.network.nxos.nxos_vpc.run_commands')
self.run_commands = self.mock_run_commands.start()
def tearDown(self):
self.mock_load_config.stop()
self.mock_run_commands.stop()
def load_fixtures(self, commands=None):
def load_from_file(*args, **kwargs):
module, commands = args
output = list()
for command in commands:
filename = str(command).split(' | ')[0].replace(' ', '_')
filename = os.path.join('nxos_vpc', filename)
output.append(load_fixture(filename))
return output
self.load_config.return_value = None
self.run_commands.side_effect = load_from_file
def test_nxos_vpc_present(self):
set_module_args(dict(domain=100, role_priority=32667, system_priority=2000,
pkl_dest='192.168.100.4', pkl_src='10.1.100.20',
peer_gw=True, auto_recovery=True))
self.execute_module(changed=True, commands=[
'vpc domain 100', 'role priority 32667', 'system-priority 2000',
'peer-keepalive destination 192.168.100.4 source 10.1.100.20 vrf management',
'peer-gateway', 'auto-recovery',
])
Loading…
Cancel
Save