From b440544e738bbf064a916f7710022465cca2fb32 Mon Sep 17 00:00:00 2001 From: Ganesh Nalawade Date: Fri, 9 Mar 2018 19:24:23 +0530 Subject: [PATCH] eos_config module exit session gracefully (#37244) Fixes #36979 If `abort` is not issued in the top level session prompt the existing session goes to pending state. The fix is to come out of config mode by issuing `end` command and again to same config session and execute `abort` which `abort` is issued at the top level session prompt. --- lib/ansible/module_utils/network/eos/eos.py | 23 ++++++++--- .../eos_config/templates/basic/cmds.j2 | 4 ++ .../eos_config/tests/cli/check_mode.yaml | 40 +++++++++++++++++++ 3 files changed, 61 insertions(+), 6 deletions(-) create mode 100644 test/integration/targets/eos_config/templates/basic/cmds.j2 create mode 100644 test/integration/targets/eos_config/tests/cli/check_mode.yaml diff --git a/lib/ansible/module_utils/network/eos/eos.py b/lib/ansible/module_utils/network/eos/eos.py index 343104eea59..a05a2c0854d 100644 --- a/lib/ansible/module_utils/network/eos/eos.py +++ b/lib/ansible/module_utils/network/eos/eos.py @@ -32,7 +32,7 @@ import time from ansible.module_utils._text import to_text, to_native from ansible.module_utils.basic import env_fallback, return_values -from ansible.module_utils.connection import Connection +from ansible.module_utils.connection import Connection, ConnectionError from ansible.module_utils.network.common.utils import to_list, ComplexList from ansible.module_utils.six import iteritems from ansible.module_utils.urls import fetch_url @@ -121,6 +121,13 @@ class Cli: return self._connection + def close_session(self, session): + conn = self._get_connection() + # to close session gracefully execute abort in top level session prompt. + conn.get('end') + conn.get('configure session %s' % session) + conn.get('abort') + @property def supports_sessions(self): if self._session_support is not None: @@ -206,8 +213,10 @@ class Cli: try: self.send_config(commands) - except: - conn.get('abort') + except ConnectionError as exc: + conn.get('end') + message = getattr(exc, 'err', exc) + self._module.fail_json(msg="Error on executing commands %s" % commands, data=to_text(message, errors='surrogate_then_replace')) conn.get('end') return {} @@ -235,8 +244,10 @@ class Cli: try: self.send_config(commands) - except: - conn.get('abort') + except ConnectionError as exc: + self.close_session(session) + message = getattr(exc, 'err', exc) + self._module.fail_json(msg="Error on executing commands %s" % commands, data=to_text(message, errors='surrogate_then_replace')) out = conn.get('show session-config diffs') if out: @@ -245,7 +256,7 @@ class Cli: if commit: conn.get('commit') else: - conn.get('abort') + self.close_session(session) return result diff --git a/test/integration/targets/eos_config/templates/basic/cmds.j2 b/test/integration/targets/eos_config/templates/basic/cmds.j2 new file mode 100644 index 00000000000..c68cce8e17c --- /dev/null +++ b/test/integration/targets/eos_config/templates/basic/cmds.j2 @@ -0,0 +1,4 @@ +ip access-list test + 10 permit ip host 192.168.0.2 host 192.168.0.1 + 20 permit ip host 192.168.0.1 host 192.168.0.2 +! diff --git a/test/integration/targets/eos_config/tests/cli/check_mode.yaml b/test/integration/targets/eos_config/tests/cli/check_mode.yaml new file mode 100644 index 00000000000..efcdcb833fd --- /dev/null +++ b/test/integration/targets/eos_config/tests/cli/check_mode.yaml @@ -0,0 +1,40 @@ +--- +- debug: msg="START cli/check_mode.yaml on connection={{ ansible_connection }}" + +- name: invalid configuration in check mode + eos_config: + lines: + - ip address 119.31.1.1 255.255.255.256 + parents: interface Loopback911 + check_mode: 1 + environment: + ANSIBLE_EOS_USE_SESSIONS: 1 + register: result + ignore_errors: yes + +- assert: + that: + - "result.msg is defined" + - "result.failed == true" + - "'Error on executing commands' in result.msg" + +- name: valid configuration in check mode + eos_config: + before: + - "no ip access-list test" + src: basic/cmds.j2 + check_mode: yes + register: config + +- name: check if session is removed + eos_command: + commands: + - show configuration sessions | json + provider: "{{ cli }}" + register: result + +- assert: + that: + - "config.session not in result.stdout[0].sessions" + +- debug: msg="END cli/check_mode.yaml on connection={{ ansible_connection }}"