From 135d34325495b38cb91ec03ba55b3b1c56c06b72 Mon Sep 17 00:00:00 2001 From: saichint Date: Mon, 26 Mar 2018 23:57:14 -0700 Subject: [PATCH] fix nxos_udld_interface issue (#37527) --- .../network/nxos/nxos_udld_interface.py | 196 ++++++++---------- .../tests/common/sanity.yaml | 61 ++++-- 2 files changed, 131 insertions(+), 126 deletions(-) diff --git a/lib/ansible/modules/network/nxos/nxos_udld_interface.py b/lib/ansible/modules/network/nxos/nxos_udld_interface.py index 258bd222b5..479f72eaff 100644 --- a/lib/ansible/modules/network/nxos/nxos_udld_interface.py +++ b/lib/ansible/modules/network/nxos/nxos_udld_interface.py @@ -110,27 +110,11 @@ changed: ''' -from ansible.module_utils.network.nxos.nxos import get_config, load_config, run_commands -from ansible.module_utils.network.nxos.nxos import get_capabilities, nxos_argument_spec +from ansible.module_utils.network.nxos.nxos import load_config, run_commands +from ansible.module_utils.network.nxos.nxos import nxos_argument_spec from ansible.module_utils.basic import AnsibleModule -def execute_show_command(command, module, command_type='cli_show'): - device_info = get_capabilities(module) - network_api = device_info.get('network_api', 'nxapi') - - if network_api == 'cliconf': - if 'show run' not in command: - command += ' | json' - cmds = [command] - body = run_commands(module, cmds) - elif network_api == 'nxapi': - cmds = [command] - body = run_commands(module, cmds) - - return body - - def flatten_list(command_lists): flat_command_list = [] for command in command_lists: @@ -142,75 +126,61 @@ def flatten_list(command_lists): def get_udld_interface(module, interface): - command = 'show udld {0}'.format(interface) + command = 'show run udld all | section ' + interface.title() + '$' interface_udld = {} mode = None + mode_str = None try: - body = execute_show_command(command, module)[0] - table = body['TABLE_interface']['ROW_interface'] - - status = str(table.get('mib-port-status', None)) - # Note: 'mib-aggresive-mode' is NOT a typo - agg = str(table.get('mib-aggresive-mode', 'disabled')) - - if agg == 'enabled': + body = run_commands(module, [{'command': command, 'output': 'text'}])[0] + if 'aggressive' in body: mode = 'aggressive' - else: - mode = status - + mode_str = 'aggressive' + elif 'no udld enable' in body: + mode = 'disabled' + mode_str = 'no udld enable' + elif 'no udld disable' in body: + mode = 'enabled' + mode_str = 'no udld disable' + elif 'udld disable' in body: + mode = 'disabled' + mode_str = 'udld disable' + elif 'udld enable' in body: + mode = 'enabled' + mode_str = 'udld enable' interface_udld['mode'] = mode except (KeyError, AttributeError, IndexError): interface_udld = {} - return interface_udld + return interface_udld, mode_str def get_commands_config_udld_interface1(delta, interface, module, existing): commands = [] - if delta: - mode = delta['mode'] - if mode == 'aggressive': - command = 'udld aggressive' - if mode == 'enabled': - command = 'no udld aggressive ; udld enable' - elif mode == 'disabled': - command = 'no udld aggressive ; no udld enable' - if command: - commands.append(command) - commands.insert(0, 'interface {0}'.format(interface)) + mode = delta['mode'] + if mode == 'aggressive': + commands.append('udld aggressive') + else: + commands.append('no udld aggressive') + commands.insert(0, 'interface {0}'.format(interface)) return commands def get_commands_config_udld_interface2(delta, interface, module, existing): commands = [] - if delta: - mode = delta['mode'] - if mode == 'aggressive': - command = 'udld aggressive' - if mode == 'enabled': - command = 'no udld aggressive ; no udld disable' - elif mode == 'disabled': - command = 'no udld aggressive ; udld disable' - if command: - commands.append(command) - commands.insert(0, 'interface {0}'.format(interface)) - - return commands - - -def get_commands_remove_udld_interface1(delta, interface, module, existing): - commands = [] - - if delta: - mode = delta['mode'] - if mode == 'aggressive': - command = 'no udld aggressive' - if mode == 'enabled': - command = 'no udld enable' - elif mode == 'disabled': + existing, mode_str = get_udld_interface(module, interface) + mode = delta['mode'] + if mode == 'enabled': + if mode_str == 'no udld enable': command = 'udld enable' + else: + command = 'no udld disable' + else: + if mode_str == 'no udld disable': + command = 'udld disable' + else: + command = 'no udld enable' if command: commands.append(command) commands.insert(0, 'interface {0}'.format(interface)) @@ -218,17 +188,24 @@ def get_commands_remove_udld_interface1(delta, interface, module, existing): return commands -def get_commands_remove_udld_interface2(delta, interface, module, existing): +def get_commands_remove_udld_interface(delta, interface, module, existing): commands = [] + existing, mode_str = get_udld_interface(module, interface) - if delta: - mode = delta['mode'] - if mode == 'aggressive': - command = 'no udld aggressive' + mode = delta['mode'] + if mode == 'aggressive': + command = 'no udld aggressive' + else: if mode == 'enabled': - command = 'udld disable' + if mode_str == 'udld enable': + command = 'no udld enable' + else: + command = 'udld disable' elif mode == 'disabled': - command = 'no udld disable' + if mode_str == 'no udld disable': + command = 'udld disable' + else: + command = 'no udld enable' if command: commands.append(command) commands.insert(0, 'interface {0}'.format(interface)) @@ -256,61 +233,54 @@ def main(): state = module.params['state'] proposed = dict(mode=mode) - existing = get_udld_interface(module, interface) + existing, mode_str = get_udld_interface(module, interface) end_state = existing delta = dict(set(proposed.items()).difference(existing.items())) changed = False commands = [] + cmds = [] if state == 'present': if delta: command = get_commands_config_udld_interface1(delta, interface, module, existing) commands.append(command) - elif state == 'absent': + cmds = flatten_list(commands) + if module.check_mode: + module.exit_json(changed=True, commands=cmds) + else: + changed = True + load_config(module, cmds) + + if delta['mode'] == 'enabled' or delta['mode'] == 'disabled': + commands = [] + command = get_commands_config_udld_interface2(delta, interface, + module, existing) + commands.append(command) + cmds = flatten_list(commands) + if module.check_mode: + module.exit_json(changed=True, commands=cmds) + else: + load_config(module, cmds) + + else: common = set(proposed.items()).intersection(existing.items()) if common: - command = get_commands_remove_udld_interface1( + command = get_commands_remove_udld_interface( dict(common), interface, module, existing ) - commands.append(command) + cmds = flatten_list(commands) + if module.check_mode: + module.exit_json(changed=True, commands=cmds) + else: + changed = True + load_config(module, cmds) - cmds = flatten_list(commands) - if cmds: - if module.check_mode: - module.exit_json(changed=True, commands=cmds) - else: - changed = True - # set the return_error to True for load_config - msgs = load_config(module, cmds, True) - # since there are multiple commands sent simultaneously - # the output will have one error code for each command. - # For commands which are successful, it is empty - for item in msgs: - if item: - err_str = '' - if isinstance(item, list) and item['msg']: - err_str = item['msg'] - elif isinstance(item, str): - err_str = item - if 'rejecting a config that is valid only for' in err_str: - commands = [] - if state == 'present': - command = get_commands_config_udld_interface2(delta, interface, - module, existing) - elif state == 'absent': - command = get_commands_remove_udld_interface2( - dict(common), interface, module, existing - ) - commands.append(command) - - cmds = flatten_list(commands) - load_config(module, cmds) - - end_state = get_udld_interface(module, interface) - if 'configure' in cmds: - cmds.pop(0) + if not module.check_mode: + end_state, mode_str = get_udld_interface(module, interface) + if 'configure' in cmds: + cmds.pop(0) results = {} results['proposed'] = proposed diff --git a/test/integration/targets/nxos_udld_interface/tests/common/sanity.yaml b/test/integration/targets/nxos_udld_interface/tests/common/sanity.yaml index 15e594f6c4..c56ed23eef 100644 --- a/test/integration/targets/nxos_udld_interface/tests/common/sanity.yaml +++ b/test/integration/targets/nxos_udld_interface/tests/common/sanity.yaml @@ -4,10 +4,13 @@ when: ansible_connection == "local" - set_fact: udld_run="true" +- set_fact: udld_enable="true" - set_fact: udld_run="false" - when: ((platform is search('N9K-F')) and (imagetag and (imagetag is version('F3', 'lt')))) + when: ((platform is search('N9K-F')) and (imagetag and (imagetag is version_compare('F3', 'lt')))) - set_fact: udld_run="false" when: titanium +- set_fact: udld_enable="false" + when: imagetag and (imagetag is version_compare('N1', 'eq')) # Select interface for test - set_fact: intname="{{ nxos_int1 }}" @@ -46,21 +49,53 @@ that: - "result.changed == false" - - name: ensure interface has mode enabled - nxos_udld_interface: &conf2 - interface: "{{ intname }}" - mode: enabled - state: present - provider: "{{ connection }}" - register: result + - block: - - assert: *true + - name: ensure interface has mode enabled + nxos_udld_interface: &conf2 + interface: "{{ intname }}" + mode: enabled + state: present + provider: "{{ connection }}" + register: result - - name: "Conf2 Idempotence" - nxos_udld_interface: *conf2 - register: result + - assert: *true - - assert: *false + - name: "Conf2 Idempotence" + nxos_udld_interface: *conf2 + register: result + + - assert: *false + + - name: ensure interface has mode aggressive + nxos_udld_interface: *conf1 + register: result + + - assert: *true + + - name: "Conf1 Idempotence" + nxos_udld_interface: *conf1 + register: result + + - assert: *false + + - name: ensure interface has mode disabled + nxos_udld_interface: &conf3 + interface: "{{ intname }}" + mode: disabled + state: present + provider: "{{ connection }}" + register: result + + - assert: *true + + - name: "Conf3 Idempotence" + nxos_udld_interface: *conf3 + register: result + + - assert: *false + + when: udld_enable - name: Remove the config nxos_udld_interface: &remove