Refactor CLI prompt mode check for network plugins (#63945)
* Refactor CLI prompt mode check for network plugins * Move the CLI prompt mode check logic from action plugin to the controller side with the cliconf plugins. * This refactor also allows the network modules to initialise the persistent connection with remote device only when it is required. * Fix review comments
This commit is contained in:
parent
73526b9d65
commit
c27e47327f
33 changed files with 209 additions and 239 deletions
|
@ -305,8 +305,9 @@ def main():
|
||||||
pc_data = to_text(init_data)
|
pc_data = to_text(init_data)
|
||||||
try:
|
try:
|
||||||
conn.update_play_context(pc_data)
|
conn.update_play_context(pc_data)
|
||||||
|
conn.set_cli_prompt_context()
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
# Only network_cli has update_play context, so missing this is
|
# Only network_cli has update_play context and set_cli_prompt_context, so missing this is
|
||||||
# not fatal e.g. netconf
|
# not fatal e.g. netconf
|
||||||
if isinstance(exc, ConnectionError) and getattr(exc, 'code', None) == -32601:
|
if isinstance(exc, ConnectionError) and getattr(exc, 'code', None) == -32601:
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -23,8 +23,6 @@ import sys
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
from ansible import constants as C
|
from ansible import constants as C
|
||||||
from ansible.module_utils._text import to_text
|
|
||||||
from ansible.module_utils.connection import Connection
|
|
||||||
from ansible.plugins.action.network import ActionModule as ActionNetworkModule
|
from ansible.plugins.action.network import ActionModule as ActionNetworkModule
|
||||||
from ansible.module_utils.network.aireos.aireos import aireos_provider_spec
|
from ansible.module_utils.network.aireos.aireos import aireos_provider_spec
|
||||||
from ansible.module_utils.network.common.utils import load_provider
|
from ansible.module_utils.network.common.utils import load_provider
|
||||||
|
@ -69,14 +67,6 @@ class ActionModule(ActionNetworkModule):
|
||||||
'msg': 'unable to open shell. Please see: ' +
|
'msg': 'unable to open shell. Please see: ' +
|
||||||
'https://docs.ansible.com/ansible/network_debug_troubleshooting.html#unable-to-open-shell'}
|
'https://docs.ansible.com/ansible/network_debug_troubleshooting.html#unable-to-open-shell'}
|
||||||
|
|
||||||
# make sure we are in the right cli context which should be
|
|
||||||
# enable mode and not config module
|
|
||||||
conn = Connection(socket_path)
|
|
||||||
out = conn.get_prompt()
|
|
||||||
if to_text(out, errors='surrogate_then_replace').strip().endswith(')#'):
|
|
||||||
display.vvvv('wrong context, sending exit to device', self._play_context.remote_addr)
|
|
||||||
conn.send_command('exit')
|
|
||||||
|
|
||||||
task_vars['ansible_socket'] = socket_path
|
task_vars['ansible_socket'] = socket_path
|
||||||
|
|
||||||
if self._play_context.become_method == 'enable':
|
if self._play_context.become_method == 'enable':
|
||||||
|
|
|
@ -23,8 +23,6 @@ import sys
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
from ansible import constants as C
|
from ansible import constants as C
|
||||||
from ansible.module_utils._text import to_text
|
|
||||||
from ansible.module_utils.connection import Connection
|
|
||||||
from ansible.plugins.action.network import ActionModule as ActionNetworkModule
|
from ansible.plugins.action.network import ActionModule as ActionNetworkModule
|
||||||
from ansible.module_utils.network.aruba.aruba import aruba_provider_spec
|
from ansible.module_utils.network.aruba.aruba import aruba_provider_spec
|
||||||
from ansible.module_utils.network.common.utils import load_provider
|
from ansible.module_utils.network.common.utils import load_provider
|
||||||
|
@ -70,14 +68,6 @@ class ActionModule(ActionNetworkModule):
|
||||||
'msg': 'unable to open shell. Please see: ' +
|
'msg': 'unable to open shell. Please see: ' +
|
||||||
'https://docs.ansible.com/ansible/network_debug_troubleshooting.html#unable-to-open-shell'}
|
'https://docs.ansible.com/ansible/network_debug_troubleshooting.html#unable-to-open-shell'}
|
||||||
|
|
||||||
# make sure we are in the right cli context which should be
|
|
||||||
# enable mode and not config module
|
|
||||||
conn = Connection(socket_path)
|
|
||||||
out = conn.get_prompt()
|
|
||||||
if to_text(out, errors='surrogate_then_replace').strip().endswith(')#'):
|
|
||||||
display.vvvv('wrong context, sending exit to device', self._play_context.remote_addr)
|
|
||||||
conn.send_command('exit')
|
|
||||||
|
|
||||||
task_vars['ansible_socket'] = socket_path
|
task_vars['ansible_socket'] = socket_path
|
||||||
|
|
||||||
if self._play_context.become_method == 'enable':
|
if self._play_context.become_method == 'enable':
|
||||||
|
|
|
@ -10,8 +10,6 @@ import sys
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
from ansible import constants as C
|
from ansible import constants as C
|
||||||
from ansible.module_utils._text import to_text
|
|
||||||
from ansible.module_utils.connection import Connection
|
|
||||||
from ansible.plugins.action.network import ActionModule as ActionNetworkModule
|
from ansible.plugins.action.network import ActionModule as ActionNetworkModule
|
||||||
from ansible.module_utils.network.cloudengine.ce import ce_provider_spec
|
from ansible.module_utils.network.cloudengine.ce import ce_provider_spec
|
||||||
from ansible.module_utils.network.common.utils import load_provider
|
from ansible.module_utils.network.common.utils import load_provider
|
||||||
|
@ -85,22 +83,5 @@ class ActionModule(ActionNetworkModule):
|
||||||
return {'failed': True, 'msg': "Connection type '%s' is not valid for '%s' module."
|
return {'failed': True, 'msg': "Connection type '%s' is not valid for '%s' module."
|
||||||
% (self._play_context.connection, self._task.action)}
|
% (self._play_context.connection, self._task.action)}
|
||||||
|
|
||||||
if (self._play_context.connection == 'local' and transport == 'cli' and self._task.action in CLI_SUPPORTED_MODULES) \
|
|
||||||
or self._play_context.connection == 'network_cli':
|
|
||||||
# make sure we are in the right cli context which should be
|
|
||||||
# enable mode and not config module
|
|
||||||
if socket_path is None:
|
|
||||||
socket_path = self._connection.socket_path
|
|
||||||
conn = Connection(socket_path)
|
|
||||||
out = conn.get_prompt()
|
|
||||||
prompt = to_text(out, errors='surrogate_then_replace').strip()
|
|
||||||
while prompt.endswith(']'):
|
|
||||||
display.vvvv('wrong context, sending exit to device', self._play_context.remote_addr)
|
|
||||||
if prompt.startswith('[*'):
|
|
||||||
conn.exec_command('clear configuration candidate')
|
|
||||||
conn.exec_command('return')
|
|
||||||
out = conn.get_prompt()
|
|
||||||
prompt = to_text(out, errors='surrogate_then_replace').strip()
|
|
||||||
|
|
||||||
result = super(ActionModule, self).run(task_vars=task_vars)
|
result = super(ActionModule, self).run(task_vars=task_vars)
|
||||||
return result
|
return result
|
||||||
|
|
|
@ -24,8 +24,6 @@ from ansible import constants as C
|
||||||
from ansible.plugins.action.network import ActionModule as ActionNetworkModule
|
from ansible.plugins.action.network import ActionModule as ActionNetworkModule
|
||||||
from ansible.module_utils.network.cnos.cnos import cnos_provider_spec
|
from ansible.module_utils.network.cnos.cnos import cnos_provider_spec
|
||||||
from ansible.module_utils.network.common.utils import load_provider
|
from ansible.module_utils.network.common.utils import load_provider
|
||||||
from ansible.module_utils.connection import Connection
|
|
||||||
from ansible.module_utils._text import to_text
|
|
||||||
from ansible.utils.display import Display
|
from ansible.utils.display import Display
|
||||||
|
|
||||||
display = Display()
|
display = Display()
|
||||||
|
@ -37,7 +35,6 @@ class ActionModule(ActionNetworkModule):
|
||||||
del tmp # tmp no longer has any effect
|
del tmp # tmp no longer has any effect
|
||||||
|
|
||||||
self._config_module = True if self._task.action == 'cnos_config' else False
|
self._config_module = True if self._task.action == 'cnos_config' else False
|
||||||
socket_path = None
|
|
||||||
|
|
||||||
if self._play_context.connection == 'local':
|
if self._play_context.connection == 'local':
|
||||||
provider = load_provider(cnos_provider_spec, self._task.args)
|
provider = load_provider(cnos_provider_spec, self._task.args)
|
||||||
|
@ -67,18 +64,5 @@ class ActionModule(ActionNetworkModule):
|
||||||
|
|
||||||
task_vars['ansible_socket'] = socket_path
|
task_vars['ansible_socket'] = socket_path
|
||||||
|
|
||||||
# make sure we are in the right cli context which should be
|
|
||||||
# enable mode and not config module or exec mode
|
|
||||||
if socket_path is None:
|
|
||||||
socket_path = self._connection.socket_path
|
|
||||||
|
|
||||||
conn = Connection(socket_path)
|
|
||||||
out = conn.get_prompt()
|
|
||||||
if to_text(out, errors='surrogate_then_replace').strip().endswith(')#'):
|
|
||||||
display.vvvv('In Config mode, sending exit to device', self._play_context.remote_addr)
|
|
||||||
conn.send_command('exit')
|
|
||||||
else:
|
|
||||||
conn.send_command('enable')
|
|
||||||
|
|
||||||
result = super(ActionModule, self).run(task_vars=task_vars)
|
result = super(ActionModule, self).run(task_vars=task_vars)
|
||||||
return result
|
return result
|
||||||
|
|
|
@ -25,8 +25,6 @@ import sys
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
from ansible import constants as C
|
from ansible import constants as C
|
||||||
from ansible.module_utils._text import to_text
|
|
||||||
from ansible.module_utils.connection import Connection
|
|
||||||
from ansible.plugins.action.network import ActionModule as ActionNetworkModule
|
from ansible.plugins.action.network import ActionModule as ActionNetworkModule
|
||||||
from ansible.module_utils.network.common.utils import load_provider
|
from ansible.module_utils.network.common.utils import load_provider
|
||||||
from ansible.module_utils.network.dellos10.dellos10 import dellos10_provider_spec
|
from ansible.module_utils.network.dellos10.dellos10 import dellos10_provider_spec
|
||||||
|
@ -41,7 +39,6 @@ class ActionModule(ActionNetworkModule):
|
||||||
del tmp # tmp no longer has any effect
|
del tmp # tmp no longer has any effect
|
||||||
|
|
||||||
self._config_module = True if self._task.action == 'dellos10_config' else False
|
self._config_module = True if self._task.action == 'dellos10_config' else False
|
||||||
socket_path = None
|
|
||||||
|
|
||||||
if self._play_context.connection == 'network_cli':
|
if self._play_context.connection == 'network_cli':
|
||||||
provider = self._task.args.get('provider', {})
|
provider = self._task.args.get('provider', {})
|
||||||
|
@ -77,17 +74,5 @@ class ActionModule(ActionNetworkModule):
|
||||||
|
|
||||||
task_vars['ansible_socket'] = socket_path
|
task_vars['ansible_socket'] = socket_path
|
||||||
|
|
||||||
# make sure we are in the right cli context which should be
|
|
||||||
# enable mode and not config module
|
|
||||||
if socket_path is None:
|
|
||||||
socket_path = self._connection.socket_path
|
|
||||||
|
|
||||||
conn = Connection(socket_path)
|
|
||||||
out = conn.get_prompt()
|
|
||||||
while to_text(out, errors='surrogate_then_replace').strip().endswith(')#'):
|
|
||||||
display.vvvv('wrong context, sending exit to device', self._play_context.remote_addr)
|
|
||||||
conn.send_command('exit')
|
|
||||||
out = conn.get_prompt()
|
|
||||||
|
|
||||||
result = super(ActionModule, self).run(task_vars=task_vars)
|
result = super(ActionModule, self).run(task_vars=task_vars)
|
||||||
return result
|
return result
|
||||||
|
|
|
@ -25,8 +25,6 @@ import sys
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
from ansible import constants as C
|
from ansible import constants as C
|
||||||
from ansible.module_utils._text import to_text
|
|
||||||
from ansible.module_utils.connection import Connection
|
|
||||||
from ansible.plugins.action.network import ActionModule as ActionNetworkModule
|
from ansible.plugins.action.network import ActionModule as ActionNetworkModule
|
||||||
from ansible.module_utils.network.dellos6.dellos6 import dellos6_provider_spec
|
from ansible.module_utils.network.dellos6.dellos6 import dellos6_provider_spec
|
||||||
from ansible.module_utils.network.common.utils import load_provider
|
from ansible.module_utils.network.common.utils import load_provider
|
||||||
|
@ -77,17 +75,5 @@ class ActionModule(ActionNetworkModule):
|
||||||
|
|
||||||
task_vars['ansible_socket'] = socket_path
|
task_vars['ansible_socket'] = socket_path
|
||||||
|
|
||||||
# make sure we are in the right cli context which should be
|
|
||||||
# enable mode and not config module
|
|
||||||
if socket_path is None:
|
|
||||||
socket_path = self._connection.socket_path
|
|
||||||
|
|
||||||
conn = Connection(socket_path)
|
|
||||||
out = conn.get_prompt()
|
|
||||||
while to_text(out, errors='surrogate_then_replace').strip().endswith(')#'):
|
|
||||||
display.vvvv('wrong context, sending exit to device', self._play_context.remote_addr)
|
|
||||||
conn.send_command('exit')
|
|
||||||
out = conn.get_prompt()
|
|
||||||
|
|
||||||
result = super(ActionModule, self).run(task_vars=task_vars)
|
result = super(ActionModule, self).run(task_vars=task_vars)
|
||||||
return result
|
return result
|
||||||
|
|
|
@ -25,8 +25,6 @@ import sys
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
from ansible import constants as C
|
from ansible import constants as C
|
||||||
from ansible.module_utils._text import to_text
|
|
||||||
from ansible.module_utils.connection import Connection
|
|
||||||
from ansible.plugins.action.network import ActionModule as ActionNetworkModule
|
from ansible.plugins.action.network import ActionModule as ActionNetworkModule
|
||||||
from ansible.module_utils.network.common.utils import load_provider
|
from ansible.module_utils.network.common.utils import load_provider
|
||||||
from ansible.module_utils.network.dellos9.dellos9 import dellos9_provider_spec
|
from ansible.module_utils.network.dellos9.dellos9 import dellos9_provider_spec
|
||||||
|
@ -77,17 +75,5 @@ class ActionModule(ActionNetworkModule):
|
||||||
|
|
||||||
task_vars['ansible_socket'] = socket_path
|
task_vars['ansible_socket'] = socket_path
|
||||||
|
|
||||||
# make sure we are in the right cli context which should be
|
|
||||||
# enable mode and not config module
|
|
||||||
if socket_path is None:
|
|
||||||
socket_path = self._connection.socket_path
|
|
||||||
|
|
||||||
conn = Connection(socket_path)
|
|
||||||
out = conn.get_prompt()
|
|
||||||
while to_text(out, errors='surrogate_then_replace').strip().endswith(')#'):
|
|
||||||
display.vvvv('wrong context, sending exit to device', self._play_context.remote_addr)
|
|
||||||
conn.send_command('exit')
|
|
||||||
out = conn.get_prompt()
|
|
||||||
|
|
||||||
result = super(ActionModule, self).run(task_vars=task_vars)
|
result = super(ActionModule, self).run(task_vars=task_vars)
|
||||||
return result
|
return result
|
||||||
|
|
|
@ -24,8 +24,6 @@ from ansible import constants as C
|
||||||
from ansible.plugins.action.network import ActionModule as ActionNetworkModule
|
from ansible.plugins.action.network import ActionModule as ActionNetworkModule
|
||||||
from ansible.module_utils.network.enos.enos import enos_provider_spec
|
from ansible.module_utils.network.enos.enos import enos_provider_spec
|
||||||
from ansible.module_utils.network.common.utils import load_provider
|
from ansible.module_utils.network.common.utils import load_provider
|
||||||
from ansible.module_utils.connection import Connection
|
|
||||||
from ansible.module_utils._text import to_text
|
|
||||||
from ansible.utils.display import Display
|
from ansible.utils.display import Display
|
||||||
|
|
||||||
display = Display()
|
display = Display()
|
||||||
|
@ -37,7 +35,7 @@ class ActionModule(ActionNetworkModule):
|
||||||
del tmp # tmp no longer has any effect
|
del tmp # tmp no longer has any effect
|
||||||
|
|
||||||
self._config_module = True if self._task.action == 'enos_config' else False
|
self._config_module = True if self._task.action == 'enos_config' else False
|
||||||
socket_path = None
|
|
||||||
if self._play_context.connection == 'local':
|
if self._play_context.connection == 'local':
|
||||||
provider = load_provider(enos_provider_spec, self._task.args)
|
provider = load_provider(enos_provider_spec, self._task.args)
|
||||||
pc = copy.deepcopy(self._play_context)
|
pc = copy.deepcopy(self._play_context)
|
||||||
|
@ -66,18 +64,5 @@ class ActionModule(ActionNetworkModule):
|
||||||
|
|
||||||
task_vars['ansible_socket'] = socket_path
|
task_vars['ansible_socket'] = socket_path
|
||||||
|
|
||||||
# make sure we are in the right cli context which should be
|
|
||||||
# enable mode and not config module or exec mode
|
|
||||||
if socket_path is None:
|
|
||||||
socket_path = self._connection.socket_path
|
|
||||||
|
|
||||||
conn = Connection(socket_path)
|
|
||||||
out = conn.get_prompt()
|
|
||||||
if to_text(out, errors='surrogate_then_replace').strip().endswith(')#'):
|
|
||||||
display.vvvv('In Config mode, sending exit to device', self._play_context.remote_addr)
|
|
||||||
conn.send_command('exit')
|
|
||||||
else:
|
|
||||||
conn.send_command('enable')
|
|
||||||
|
|
||||||
result = super(ActionModule, self).run(task_vars=task_vars)
|
result = super(ActionModule, self).run(task_vars=task_vars)
|
||||||
return result
|
return result
|
||||||
|
|
|
@ -23,8 +23,6 @@ import sys
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
from ansible import constants as C
|
from ansible import constants as C
|
||||||
from ansible.module_utils._text import to_text
|
|
||||||
from ansible.module_utils.connection import Connection
|
|
||||||
from ansible.module_utils.network.eos.eos import eos_provider_spec
|
from ansible.module_utils.network.eos.eos import eos_provider_spec
|
||||||
from ansible.plugins.action.network import ActionModule as ActionNetworkModule
|
from ansible.plugins.action.network import ActionModule as ActionNetworkModule
|
||||||
from ansible.module_utils.network.common.utils import load_provider
|
from ansible.module_utils.network.common.utils import load_provider
|
||||||
|
@ -40,7 +38,6 @@ class ActionModule(ActionNetworkModule):
|
||||||
|
|
||||||
module_name = self._task.action.split('.')[-1]
|
module_name = self._task.action.split('.')[-1]
|
||||||
self._config_module = True if module_name == 'eos_config' else False
|
self._config_module = True if module_name == 'eos_config' else False
|
||||||
socket_path = None
|
|
||||||
|
|
||||||
if self._play_context.connection in ('network_cli', 'httpapi'):
|
if self._play_context.connection in ('network_cli', 'httpapi'):
|
||||||
provider = self._task.args.get('provider', {})
|
provider = self._task.args.get('provider', {})
|
||||||
|
@ -90,19 +87,6 @@ class ActionModule(ActionNetworkModule):
|
||||||
else:
|
else:
|
||||||
return {'failed': True, 'msg': 'Connection type %s is not valid for this module' % self._play_context.connection}
|
return {'failed': True, 'msg': 'Connection type %s is not valid for this module' % self._play_context.connection}
|
||||||
|
|
||||||
if (self._play_context.connection == 'local' and transport == 'cli') or self._play_context.connection == 'network_cli':
|
|
||||||
# make sure we are in the right cli context which should be
|
|
||||||
# enable mode and not config module
|
|
||||||
if socket_path is None:
|
|
||||||
socket_path = self._connection.socket_path
|
|
||||||
|
|
||||||
conn = Connection(socket_path)
|
|
||||||
out = conn.get_prompt()
|
|
||||||
while '(config' in to_text(out, errors='surrogate_then_replace').strip():
|
|
||||||
display.vvvv('wrong context, sending exit to device', self._play_context.remote_addr)
|
|
||||||
conn.send_command('abort')
|
|
||||||
out = conn.get_prompt()
|
|
||||||
|
|
||||||
result = super(ActionModule, self).run(task_vars=task_vars)
|
result = super(ActionModule, self).run(task_vars=task_vars)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
|
@ -19,12 +19,9 @@
|
||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import (absolute_import, division, print_function)
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
import re
|
|
||||||
import sys
|
import sys
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
from ansible.module_utils._text import to_text
|
|
||||||
from ansible.module_utils.connection import Connection, ConnectionError
|
|
||||||
from ansible.plugins.action.network import ActionModule as ActionNetworkModule
|
from ansible.plugins.action.network import ActionModule as ActionNetworkModule
|
||||||
from ansible.module_utils.network.common.utils import load_provider
|
from ansible.module_utils.network.common.utils import load_provider
|
||||||
from ansible.module_utils.network.ios.ios import ios_provider_spec
|
from ansible.module_utils.network.ios.ios import ios_provider_spec
|
||||||
|
@ -40,7 +37,6 @@ class ActionModule(ActionNetworkModule):
|
||||||
|
|
||||||
module_name = self._task.action.split('.')[-1]
|
module_name = self._task.action.split('.')[-1]
|
||||||
self._config_module = True if module_name == 'ios_config' else False
|
self._config_module = True if module_name == 'ios_config' else False
|
||||||
socket_path = None
|
|
||||||
|
|
||||||
if self._play_context.connection == 'network_cli':
|
if self._play_context.connection == 'network_cli':
|
||||||
provider = self._task.args.get('provider', {})
|
provider = self._task.args.get('provider', {})
|
||||||
|
@ -79,19 +75,5 @@ class ActionModule(ActionNetworkModule):
|
||||||
else:
|
else:
|
||||||
return {'failed': True, 'msg': 'Connection type %s is not valid for this module' % self._play_context.connection}
|
return {'failed': True, 'msg': 'Connection type %s is not valid for this module' % self._play_context.connection}
|
||||||
|
|
||||||
# make sure we are in the right cli context which should be
|
|
||||||
# enable mode and not config module
|
|
||||||
if socket_path is None:
|
|
||||||
socket_path = self._connection.socket_path
|
|
||||||
|
|
||||||
conn = Connection(socket_path)
|
|
||||||
try:
|
|
||||||
out = conn.get_prompt()
|
|
||||||
if re.search(r'config.*\)#', to_text(out, errors='surrogate_then_replace').strip()):
|
|
||||||
display.vvvv('wrong context, sending end to device', self._play_context.remote_addr)
|
|
||||||
conn.send_command('end')
|
|
||||||
except ConnectionError as exc:
|
|
||||||
return {'failed': True, 'msg': to_text(exc)}
|
|
||||||
|
|
||||||
result = super(ActionModule, self).run(task_vars=task_vars)
|
result = super(ActionModule, self).run(task_vars=task_vars)
|
||||||
return result
|
return result
|
||||||
|
|
|
@ -22,9 +22,6 @@ __metaclass__ = type
|
||||||
import sys
|
import sys
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
from ansible import constants as C
|
|
||||||
from ansible.module_utils._text import to_text
|
|
||||||
from ansible.module_utils.connection import Connection
|
|
||||||
from ansible.module_utils.network.iosxr.iosxr import iosxr_provider_spec
|
from ansible.module_utils.network.iosxr.iosxr import iosxr_provider_spec
|
||||||
from ansible.plugins.action.network import ActionModule as ActionNetworkModule
|
from ansible.plugins.action.network import ActionModule as ActionNetworkModule
|
||||||
from ansible.module_utils.network.common.utils import load_provider
|
from ansible.module_utils.network.common.utils import load_provider
|
||||||
|
@ -40,7 +37,6 @@ class ActionModule(ActionNetworkModule):
|
||||||
|
|
||||||
module_name = self._task.action.split('.')[-1]
|
module_name = self._task.action.split('.')[-1]
|
||||||
self._config_module = True if module_name == 'iosxr_config' else False
|
self._config_module = True if module_name == 'iosxr_config' else False
|
||||||
socket_path = None
|
|
||||||
force_cli = module_name in ('iosxr_netconf', 'iosxr_config', 'iosxr_command', 'iosxr_facts')
|
force_cli = module_name in ('iosxr_netconf', 'iosxr_config', 'iosxr_command', 'iosxr_facts')
|
||||||
|
|
||||||
if self._play_context.connection == 'local':
|
if self._play_context.connection == 'local':
|
||||||
|
@ -86,18 +82,5 @@ class ActionModule(ActionNetworkModule):
|
||||||
else:
|
else:
|
||||||
return {'failed': True, 'msg': 'Connection type %s is not valid for this module' % self._play_context.connection}
|
return {'failed': True, 'msg': 'Connection type %s is not valid for this module' % self._play_context.connection}
|
||||||
|
|
||||||
# make sure we are in the right cli context which should be
|
|
||||||
# enable mode and not config module
|
|
||||||
if (self._play_context.connection == 'local' and pc.connection == 'network_cli') or self._play_context.connection == 'network_cli':
|
|
||||||
if socket_path is None:
|
|
||||||
socket_path = self._connection.socket_path
|
|
||||||
|
|
||||||
conn = Connection(socket_path)
|
|
||||||
out = conn.get_prompt()
|
|
||||||
while to_text(out, errors='surrogate_then_replace').strip().endswith(')#'):
|
|
||||||
display.vvvv('wrong context, sending exit to device', self._play_context.remote_addr)
|
|
||||||
conn.send_command('abort')
|
|
||||||
out = conn.get_prompt()
|
|
||||||
|
|
||||||
result = super(ActionModule, self).run(task_vars=task_vars)
|
result = super(ActionModule, self).run(task_vars=task_vars)
|
||||||
return result
|
return result
|
||||||
|
|
|
@ -22,9 +22,6 @@ __metaclass__ = type
|
||||||
import sys
|
import sys
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
from ansible import constants as C
|
|
||||||
from ansible.module_utils._text import to_text
|
|
||||||
from ansible.module_utils.connection import Connection, ConnectionError
|
|
||||||
from ansible.plugins.action.network import ActionModule as ActionNetworkModule
|
from ansible.plugins.action.network import ActionModule as ActionNetworkModule
|
||||||
from ansible.module_utils.network.common.utils import load_provider
|
from ansible.module_utils.network.common.utils import load_provider
|
||||||
from ansible.module_utils.network.ironware.ironware import ironware_provider_spec
|
from ansible.module_utils.network.ironware.ironware import ironware_provider_spec
|
||||||
|
@ -39,7 +36,6 @@ class ActionModule(ActionNetworkModule):
|
||||||
del tmp # tmp no longer has any effect
|
del tmp # tmp no longer has any effect
|
||||||
|
|
||||||
self._config_module = True if self._task.action == 'ironware_config' else False
|
self._config_module = True if self._task.action == 'ironware_config' else False
|
||||||
socket_path = None
|
|
||||||
|
|
||||||
if self._play_context.connection == 'network_cli':
|
if self._play_context.connection == 'network_cli':
|
||||||
provider = self._task.args.get('provider', {})
|
provider = self._task.args.get('provider', {})
|
||||||
|
@ -78,20 +74,5 @@ class ActionModule(ActionNetworkModule):
|
||||||
else:
|
else:
|
||||||
return {'failed': True, 'msg': 'Connection type %s is not valid for this module' % self._play_context.connection}
|
return {'failed': True, 'msg': 'Connection type %s is not valid for this module' % self._play_context.connection}
|
||||||
|
|
||||||
# make sure we are in the right cli context which should be
|
|
||||||
# enable mode and not config module
|
|
||||||
if socket_path is None:
|
|
||||||
socket_path = self._connection.socket_path
|
|
||||||
|
|
||||||
conn = Connection(socket_path)
|
|
||||||
try:
|
|
||||||
out = conn.get_prompt()
|
|
||||||
while to_text(out, errors='surrogate_then_replace').strip().endswith(')#'):
|
|
||||||
display.vvvv('wrong context, sending exit to device', self._play_context.remote_addr)
|
|
||||||
conn.send_command('exit')
|
|
||||||
out = conn.get_prompt()
|
|
||||||
except ConnectionError as exc:
|
|
||||||
return {'failed': True, 'msg': to_text(exc)}
|
|
||||||
|
|
||||||
result = super(ActionModule, self).run(task_vars=task_vars)
|
result = super(ActionModule, self).run(task_vars=task_vars)
|
||||||
return result
|
return result
|
||||||
|
|
|
@ -22,8 +22,6 @@ __metaclass__ = type
|
||||||
import sys
|
import sys
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
from ansible.module_utils._text import to_text
|
|
||||||
from ansible.module_utils.connection import Connection
|
|
||||||
from ansible.module_utils.network.common.utils import load_provider
|
from ansible.module_utils.network.common.utils import load_provider
|
||||||
from ansible.module_utils.network.junos.junos import junos_provider_spec
|
from ansible.module_utils.network.junos.junos import junos_provider_spec
|
||||||
from ansible.plugins.action.network import ActionModule as ActionNetworkModule
|
from ansible.plugins.action.network import ActionModule as ActionNetworkModule
|
||||||
|
@ -41,7 +39,6 @@ class ActionModule(ActionNetworkModule):
|
||||||
|
|
||||||
module_name = self._task.action.split('.')[-1]
|
module_name = self._task.action.split('.')[-1]
|
||||||
self._config_module = True if module_name == 'junos_config' else False
|
self._config_module = True if module_name == 'junos_config' else False
|
||||||
socket_path = None
|
|
||||||
|
|
||||||
if self._play_context.connection == 'local':
|
if self._play_context.connection == 'local':
|
||||||
provider = load_provider(junos_provider_spec, self._task.args)
|
provider = load_provider(junos_provider_spec, self._task.args)
|
||||||
|
@ -94,18 +91,5 @@ class ActionModule(ActionNetworkModule):
|
||||||
"Please see https://docs.ansible.com/ansible/latest/network/user_guide/platform_junos.html"
|
"Please see https://docs.ansible.com/ansible/latest/network/user_guide/platform_junos.html"
|
||||||
% (self._play_context.connection, module_name)}
|
% (self._play_context.connection, module_name)}
|
||||||
|
|
||||||
if (self._play_context.connection == 'local' and pc.connection == 'network_cli') or self._play_context.connection == 'network_cli':
|
|
||||||
# make sure we are in the right cli context which should be
|
|
||||||
# enable mode and not config module
|
|
||||||
if socket_path is None:
|
|
||||||
socket_path = self._connection.socket_path
|
|
||||||
|
|
||||||
conn = Connection(socket_path)
|
|
||||||
out = conn.get_prompt()
|
|
||||||
while to_text(out, errors='surrogate_then_replace').strip().endswith('#'):
|
|
||||||
display.vvvv('wrong context, sending exit to device', self._play_context.remote_addr)
|
|
||||||
conn.send_command('exit')
|
|
||||||
out = conn.get_prompt()
|
|
||||||
|
|
||||||
result = super(ActionModule, self).run(task_vars=task_vars)
|
result = super(ActionModule, self).run(task_vars=task_vars)
|
||||||
return result
|
return result
|
||||||
|
|
|
@ -24,8 +24,6 @@ import re
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from ansible import constants as C
|
from ansible import constants as C
|
||||||
from ansible.module_utils._text import to_text
|
|
||||||
from ansible.module_utils.connection import Connection
|
|
||||||
from ansible.plugins.action.network import ActionModule as ActionNetworkModule
|
from ansible.plugins.action.network import ActionModule as ActionNetworkModule
|
||||||
from ansible.module_utils.network.common.utils import load_provider
|
from ansible.module_utils.network.common.utils import load_provider
|
||||||
from ansible.module_utils.network.nxos.nxos import nxos_provider_spec
|
from ansible.module_utils.network.nxos.nxos import nxos_provider_spec
|
||||||
|
@ -56,8 +54,6 @@ class ActionModule(ActionNetworkModule):
|
||||||
self._task.args['username'] = self._play_context.connection_user
|
self._task.args['username'] = self._play_context.connection_user
|
||||||
|
|
||||||
if module_name == 'nxos_install_os':
|
if module_name == 'nxos_install_os':
|
||||||
persistent_command_timeout = 0
|
|
||||||
persistent_connect_timeout = 0
|
|
||||||
connection = self._connection
|
connection = self._connection
|
||||||
if connection.transport == 'local':
|
if connection.transport == 'local':
|
||||||
persistent_command_timeout = C.PERSISTENT_COMMAND_TIMEOUT
|
persistent_command_timeout = C.PERSISTENT_COMMAND_TIMEOUT
|
||||||
|
@ -124,21 +120,6 @@ class ActionModule(ActionNetworkModule):
|
||||||
else:
|
else:
|
||||||
return {'failed': True, 'msg': 'Connection type %s is not valid for this module' % self._play_context.connection}
|
return {'failed': True, 'msg': 'Connection type %s is not valid for this module' % self._play_context.connection}
|
||||||
|
|
||||||
if (self._play_context.connection == 'local' and transport == 'cli') or self._play_context.connection == 'network_cli':
|
|
||||||
# make sure we are in the right cli context which should be
|
|
||||||
# enable mode and not config module
|
|
||||||
if socket_path is None:
|
|
||||||
socket_path = self._connection.socket_path
|
|
||||||
|
|
||||||
conn = Connection(socket_path)
|
|
||||||
# Match prompts ending in )# except those with (maint-mode)#
|
|
||||||
config_prompt = re.compile(r'^.*\((?!maint-mode).*\)#$')
|
|
||||||
out = conn.get_prompt()
|
|
||||||
while config_prompt.match(to_text(out, errors='surrogate_then_replace').strip()):
|
|
||||||
display.vvvv('wrong context, sending exit to device', self._play_context.remote_addr)
|
|
||||||
conn.send_command('exit')
|
|
||||||
out = conn.get_prompt()
|
|
||||||
|
|
||||||
result = super(ActionModule, self).run(task_vars=task_vars)
|
result = super(ActionModule, self).run(task_vars=task_vars)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
|
@ -22,10 +22,7 @@ __metaclass__ = type
|
||||||
import sys
|
import sys
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
from ansible import constants as C
|
|
||||||
from ansible.plugins.action.network import ActionModule as ActionNetworkModule
|
from ansible.plugins.action.network import ActionModule as ActionNetworkModule
|
||||||
from ansible.module_utils._text import to_text
|
|
||||||
from ansible.module_utils.connection import Connection
|
|
||||||
from ansible.module_utils.network.common.utils import load_provider
|
from ansible.module_utils.network.common.utils import load_provider
|
||||||
from ansible.module_utils.network.vyos.vyos import vyos_provider_spec
|
from ansible.module_utils.network.vyos.vyos import vyos_provider_spec
|
||||||
from ansible.utils.display import Display
|
from ansible.utils.display import Display
|
||||||
|
@ -40,7 +37,6 @@ class ActionModule(ActionNetworkModule):
|
||||||
|
|
||||||
module_name = self._task.action.split('.')[-1]
|
module_name = self._task.action.split('.')[-1]
|
||||||
self._config_module = True if module_name == 'vyos_config' else False
|
self._config_module = True if module_name == 'vyos_config' else False
|
||||||
socket_path = None
|
|
||||||
|
|
||||||
if self._play_context.connection == 'network_cli':
|
if self._play_context.connection == 'network_cli':
|
||||||
provider = self._task.args.get('provider', {})
|
provider = self._task.args.get('provider', {})
|
||||||
|
@ -75,16 +71,5 @@ class ActionModule(ActionNetworkModule):
|
||||||
else:
|
else:
|
||||||
return {'failed': True, 'msg': 'Connection type %s is not valid for this module' % self._play_context.connection}
|
return {'failed': True, 'msg': 'Connection type %s is not valid for this module' % self._play_context.connection}
|
||||||
|
|
||||||
# make sure we are in the right cli context which should be
|
|
||||||
# enable mode and not config module
|
|
||||||
if socket_path is None:
|
|
||||||
socket_path = self._connection.socket_path
|
|
||||||
|
|
||||||
conn = Connection(socket_path)
|
|
||||||
out = conn.get_prompt()
|
|
||||||
if to_text(out, errors='surrogate_then_replace').strip().endswith('#'):
|
|
||||||
display.vvvv('wrong context, sending exit to device', self._play_context.remote_addr)
|
|
||||||
conn.send_command('exit discard')
|
|
||||||
|
|
||||||
result = super(ActionModule, self).run(task_vars=task_vars)
|
result = super(ActionModule, self).run(task_vars=task_vars)
|
||||||
return result
|
return result
|
||||||
|
|
|
@ -447,3 +447,31 @@ class CliconfBase(AnsiblePlugin):
|
||||||
|
|
||||||
if replace and not operations.get('supports_replace', False):
|
if replace and not operations.get('supports_replace', False):
|
||||||
raise ValueError("configuration replace is not supported")
|
raise ValueError("configuration replace is not supported")
|
||||||
|
|
||||||
|
def set_cli_prompt_context(self):
|
||||||
|
"""
|
||||||
|
Ensure the command prompt on device is in right mode
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def _update_cli_prompt_context(self, config_context=None, exit_command='exit'):
|
||||||
|
"""
|
||||||
|
Update the cli prompt context to ensure it is in operational mode
|
||||||
|
:param config_context: It is string value to identify if the current cli prompt ends with config mode prompt
|
||||||
|
:param exit_command: Command to execute to exit the config mode
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
out = self._connection.get_prompt()
|
||||||
|
if out is None:
|
||||||
|
raise AnsibleConnectionFailure(message=u'cli prompt is not identified from the last received'
|
||||||
|
u' response window: %s' % self._connection._last_recv_window)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
out = to_text(out, errors='surrogate_then_replace').strip()
|
||||||
|
if config_context and out.endswith(config_context):
|
||||||
|
self._connection.queue_message('vvvv', 'wrong context, sending exit to device')
|
||||||
|
self.send_command(exit_command)
|
||||||
|
out = self._connection.get_prompt()
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
|
|
@ -34,6 +34,7 @@ import json
|
||||||
|
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
|
|
||||||
|
from ansible.errors import AnsibleConnectionFailure
|
||||||
from ansible.module_utils._text import to_text
|
from ansible.module_utils._text import to_text
|
||||||
from ansible.module_utils.network.common.utils import to_list
|
from ansible.module_utils.network.common.utils import to_list
|
||||||
from ansible.plugins.cliconf import CliconfBase, enable_mode
|
from ansible.plugins.cliconf import CliconfBase, enable_mode
|
||||||
|
@ -85,3 +86,11 @@ class Cliconf(CliconfBase):
|
||||||
def get_capabilities(self):
|
def get_capabilities(self):
|
||||||
result = super(Cliconf, self).get_capabilities()
|
result = super(Cliconf, self).get_capabilities()
|
||||||
return json.dumps(result)
|
return json.dumps(result)
|
||||||
|
|
||||||
|
def set_cli_prompt_context(self):
|
||||||
|
"""
|
||||||
|
Make sure we are in the operational cli mode
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
if self._connection.connected:
|
||||||
|
self._update_cli_prompt_context(config_context=')#')
|
||||||
|
|
|
@ -86,3 +86,11 @@ class Cliconf(CliconfBase):
|
||||||
def get_capabilities(self):
|
def get_capabilities(self):
|
||||||
result = super(Cliconf, self).get_capabilities()
|
result = super(Cliconf, self).get_capabilities()
|
||||||
return json.dumps(result)
|
return json.dumps(result)
|
||||||
|
|
||||||
|
def set_cli_prompt_context(self):
|
||||||
|
"""
|
||||||
|
Make sure we are in the operational cli mode
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
if self._connection.connected:
|
||||||
|
self._update_cli_prompt_context(config_context=')#')
|
||||||
|
|
|
@ -34,6 +34,7 @@ import json
|
||||||
|
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
|
|
||||||
|
from ansible.errors import AnsibleConnectionFailure
|
||||||
from ansible.module_utils._text import to_text
|
from ansible.module_utils._text import to_text
|
||||||
from ansible.module_utils.network.common.utils import to_list
|
from ansible.module_utils.network.common.utils import to_list
|
||||||
from ansible.plugins.cliconf import CliconfBase, enable_mode
|
from ansible.plugins.cliconf import CliconfBase, enable_mode
|
||||||
|
@ -98,3 +99,24 @@ class Cliconf(CliconfBase):
|
||||||
def get_capabilities(self):
|
def get_capabilities(self):
|
||||||
result = super(Cliconf, self).get_capabilities()
|
result = super(Cliconf, self).get_capabilities()
|
||||||
return json.dumps(result)
|
return json.dumps(result)
|
||||||
|
|
||||||
|
def set_cli_prompt_context(self):
|
||||||
|
"""
|
||||||
|
Make sure we are in the operational cli mode
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
if self._connection.connected:
|
||||||
|
out = self._connection.get_prompt()
|
||||||
|
|
||||||
|
if out is None:
|
||||||
|
raise AnsibleConnectionFailure(message=u'cli prompt is not identified from the last received'
|
||||||
|
u' response window: %s' % self._connection._last_recv_window)
|
||||||
|
|
||||||
|
prompt = to_text(out, errors='surrogate_then_replace').strip()
|
||||||
|
while prompt.endswith(']'):
|
||||||
|
self._connection.queue_message('vvvv', 'wrong context, sending return to device')
|
||||||
|
if prompt.startswith('[*'):
|
||||||
|
self._connection.exec_command('clear configuration candidate')
|
||||||
|
self._connection.exec_command('return')
|
||||||
|
out = self._connection.get_prompt()
|
||||||
|
prompt = to_text(out, errors='surrogate_then_replace').strip()
|
||||||
|
|
|
@ -29,7 +29,7 @@ version_added: 2.6
|
||||||
import re
|
import re
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from itertools import chain
|
from ansible.errors import AnsibleConnectionFailure
|
||||||
from ansible.module_utils.common._collections_compat import Mapping
|
from ansible.module_utils.common._collections_compat import Mapping
|
||||||
from ansible.module_utils._text import to_bytes, to_text
|
from ansible.module_utils._text import to_bytes, to_text
|
||||||
from ansible.module_utils.network.common.utils import to_list
|
from ansible.module_utils.network.common.utils import to_list
|
||||||
|
@ -116,3 +116,21 @@ class Cliconf(CliconfBase):
|
||||||
def get_capabilities(self):
|
def get_capabilities(self):
|
||||||
result = super(Cliconf, self).get_capabilities()
|
result = super(Cliconf, self).get_capabilities()
|
||||||
return json.dumps(result)
|
return json.dumps(result)
|
||||||
|
|
||||||
|
def set_cli_prompt_context(self):
|
||||||
|
"""
|
||||||
|
Make sure we are in the operational cli mode
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
if self._connection.connected:
|
||||||
|
out = self._connection.get_prompt()
|
||||||
|
|
||||||
|
if out is None:
|
||||||
|
raise AnsibleConnectionFailure(message=u'cli prompt is not identified from the last received'
|
||||||
|
u' response window: %s' % self._connection._last_recv_window)
|
||||||
|
|
||||||
|
if to_text(out, errors='surrogate_then_replace').strip().endswith(')#'):
|
||||||
|
self._connection.queue_message('vvvv', 'In Config mode, sending exit to device')
|
||||||
|
self._connection.send_command('exit')
|
||||||
|
else:
|
||||||
|
self._connection.send_command('enable')
|
||||||
|
|
|
@ -113,3 +113,11 @@ class Cliconf(CliconfBase):
|
||||||
responses.append(out)
|
responses.append(out)
|
||||||
|
|
||||||
return responses
|
return responses
|
||||||
|
|
||||||
|
def set_cli_prompt_context(self):
|
||||||
|
"""
|
||||||
|
Make sure we are in the operational cli mode
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
if self._connection.connected:
|
||||||
|
self._update_cli_prompt_context(config_context=')#')
|
||||||
|
|
|
@ -113,3 +113,11 @@ class Cliconf(CliconfBase):
|
||||||
responses.append(out)
|
responses.append(out)
|
||||||
|
|
||||||
return responses
|
return responses
|
||||||
|
|
||||||
|
def set_cli_prompt_context(self):
|
||||||
|
"""
|
||||||
|
Make sure we are in the operational cli mode
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
if self._connection.connected:
|
||||||
|
self._update_cli_prompt_context(config_context=')#')
|
||||||
|
|
|
@ -113,3 +113,11 @@ class Cliconf(CliconfBase):
|
||||||
responses.append(out)
|
responses.append(out)
|
||||||
|
|
||||||
return responses
|
return responses
|
||||||
|
|
||||||
|
def set_cli_prompt_context(self):
|
||||||
|
"""
|
||||||
|
Make sure we are in the operational cli mode
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
if self._connection.connected:
|
||||||
|
self._update_cli_prompt_context(config_context=')#')
|
||||||
|
|
|
@ -31,7 +31,8 @@ import json
|
||||||
|
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
|
|
||||||
from ansible.module_utils._text import to_bytes, to_text
|
from ansible.errors import AnsibleConnectionFailure
|
||||||
|
from ansible.module_utils._text import to_text
|
||||||
from ansible.module_utils.network.common.utils import to_list
|
from ansible.module_utils.network.common.utils import to_list
|
||||||
from ansible.plugins.cliconf import CliconfBase, enable_mode
|
from ansible.plugins.cliconf import CliconfBase, enable_mode
|
||||||
|
|
||||||
|
@ -83,3 +84,21 @@ class Cliconf(CliconfBase):
|
||||||
def get_capabilities(self):
|
def get_capabilities(self):
|
||||||
result = super(Cliconf, self).get_capabilities()
|
result = super(Cliconf, self).get_capabilities()
|
||||||
return json.dumps(result)
|
return json.dumps(result)
|
||||||
|
|
||||||
|
def set_cli_prompt_context(self):
|
||||||
|
"""
|
||||||
|
Make sure we are in the operational cli mode
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
if self._connection.connected:
|
||||||
|
out = self._connection.get_prompt()
|
||||||
|
|
||||||
|
if out is None:
|
||||||
|
raise AnsibleConnectionFailure(message=u'cli prompt is not identified from the last received'
|
||||||
|
u' response window: %s' % self._connection._last_recv_window)
|
||||||
|
|
||||||
|
if to_text(out, errors='surrogate_then_replace').strip().endswith(')#'):
|
||||||
|
self._connection.queue_message('vvvv', 'In Config mode, sending exit to device')
|
||||||
|
self._connection.send_command('exit')
|
||||||
|
else:
|
||||||
|
self._connection.send_command('enable')
|
||||||
|
|
|
@ -286,6 +286,14 @@ class Cliconf(CliconfBase):
|
||||||
|
|
||||||
return json.dumps(result)
|
return json.dumps(result)
|
||||||
|
|
||||||
|
def set_cli_prompt_context(self):
|
||||||
|
"""
|
||||||
|
Make sure we are in the operational cli mode
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
if self._connection.connected:
|
||||||
|
self._update_cli_prompt_context(config_context='(config', exit_command='abort')
|
||||||
|
|
||||||
def _get_command_with_output(self, command, output):
|
def _get_command_with_output(self, command, output):
|
||||||
options_values = self.get_option_values()
|
options_values = self.get_option_values()
|
||||||
if output not in options_values['output']:
|
if output not in options_values['output']:
|
||||||
|
|
|
@ -34,8 +34,6 @@ import re
|
||||||
import time
|
import time
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from itertools import chain
|
|
||||||
|
|
||||||
from ansible.errors import AnsibleConnectionFailure
|
from ansible.errors import AnsibleConnectionFailure
|
||||||
from ansible.module_utils._text import to_text
|
from ansible.module_utils._text import to_text
|
||||||
from ansible.module_utils.common._collections_compat import Mapping
|
from ansible.module_utils.common._collections_compat import Mapping
|
||||||
|
@ -333,6 +331,22 @@ class Cliconf(CliconfBase):
|
||||||
else:
|
else:
|
||||||
return 'full'
|
return 'full'
|
||||||
|
|
||||||
|
def set_cli_prompt_context(self):
|
||||||
|
"""
|
||||||
|
Make sure we are in the operational cli mode
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
if self._connection.connected:
|
||||||
|
out = self._connection.get_prompt()
|
||||||
|
|
||||||
|
if out is None:
|
||||||
|
raise AnsibleConnectionFailure(message=u'cli prompt is not identified from the last received'
|
||||||
|
u' response window: %s' % self._connection._last_recv_window)
|
||||||
|
|
||||||
|
if re.search(r'config.*\)#', to_text(out, errors='surrogate_then_replace').strip()):
|
||||||
|
self._connection.queue_message('vvvv', 'wrong context, sending end to device')
|
||||||
|
self._connection.send_command('end')
|
||||||
|
|
||||||
def _extract_banners(self, config):
|
def _extract_banners(self, config):
|
||||||
banners = {}
|
banners = {}
|
||||||
banner_cmds = re.findall(r'^banner (\w+)', config, re.M)
|
banner_cmds = re.findall(r'^banner (\w+)', config, re.M)
|
||||||
|
|
|
@ -266,3 +266,11 @@ class Cliconf(CliconfBase):
|
||||||
result['device_operations'] = self.get_device_operations()
|
result['device_operations'] = self.get_device_operations()
|
||||||
result.update(self.get_option_values())
|
result.update(self.get_option_values())
|
||||||
return json.dumps(result)
|
return json.dumps(result)
|
||||||
|
|
||||||
|
def set_cli_prompt_context(self):
|
||||||
|
"""
|
||||||
|
Make sure we are in the operational cli mode
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
if self._connection.connected:
|
||||||
|
self._update_cli_prompt_context(config_context=')#', exit_command='abort')
|
||||||
|
|
|
@ -86,3 +86,11 @@ class Cliconf(CliconfBase):
|
||||||
def get_capabilities(self):
|
def get_capabilities(self):
|
||||||
result = super(Cliconf, self).get_capabilities()
|
result = super(Cliconf, self).get_capabilities()
|
||||||
return json.dumps(result)
|
return json.dumps(result)
|
||||||
|
|
||||||
|
def set_cli_prompt_context(self):
|
||||||
|
"""
|
||||||
|
Make sure we are in the operational cli mode
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
if self._connection.connected:
|
||||||
|
self._update_cli_prompt_context(config_context=')#')
|
||||||
|
|
|
@ -246,6 +246,14 @@ class Cliconf(CliconfBase):
|
||||||
result.update(self.get_option_values())
|
result.update(self.get_option_values())
|
||||||
return json.dumps(result)
|
return json.dumps(result)
|
||||||
|
|
||||||
|
def set_cli_prompt_context(self):
|
||||||
|
"""
|
||||||
|
Make sure we are in the operational cli mode
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
if self._connection.connected:
|
||||||
|
self._update_cli_prompt_context(config_context='#')
|
||||||
|
|
||||||
def _get_command_with_output(self, command, output):
|
def _get_command_with_output(self, command, output):
|
||||||
options_values = self.get_option_values()
|
options_values = self.get_option_values()
|
||||||
if output not in options_values['output']:
|
if output not in options_values['output']:
|
||||||
|
|
|
@ -258,6 +258,24 @@ class Cliconf(CliconfBase):
|
||||||
|
|
||||||
return json.dumps(result)
|
return json.dumps(result)
|
||||||
|
|
||||||
|
def set_cli_prompt_context(self):
|
||||||
|
"""
|
||||||
|
Make sure we are in the operational cli context
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
if self._connection.connected:
|
||||||
|
out = self._connection.get_prompt()
|
||||||
|
if out is None:
|
||||||
|
raise AnsibleConnectionFailure(message=u'cli prompt is not identified from the last received'
|
||||||
|
u' response window: %s' % self._connection._last_recv_window)
|
||||||
|
# Match prompts ending in )# except those with (maint-mode)#
|
||||||
|
config_prompt = re.compile(r'^.*\((?!maint-mode).*\)#$')
|
||||||
|
|
||||||
|
while config_prompt.match(to_text(out, errors='surrogate_then_replace').strip()):
|
||||||
|
self._connection.queue_message('vvvv', 'wrong context, sending exit to device')
|
||||||
|
self._connection.send_command('exit')
|
||||||
|
out = self._connection.get_prompt()
|
||||||
|
|
||||||
def _get_command_with_output(self, command, output):
|
def _get_command_with_output(self, command, output):
|
||||||
options_values = self.get_option_values()
|
options_values = self.get_option_values()
|
||||||
if output not in options_values['output']:
|
if output not in options_values['output']:
|
||||||
|
|
|
@ -266,3 +266,11 @@ class Cliconf(CliconfBase):
|
||||||
result['device_operations'] = self.get_device_operations()
|
result['device_operations'] = self.get_device_operations()
|
||||||
result.update(self.get_option_values())
|
result.update(self.get_option_values())
|
||||||
return json.dumps(result)
|
return json.dumps(result)
|
||||||
|
|
||||||
|
def set_cli_prompt_context(self):
|
||||||
|
"""
|
||||||
|
Make sure we are in the operational cli mode
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
if self._connection.connected:
|
||||||
|
self._update_cli_prompt_context(config_context='#', exit_command='exit discard')
|
||||||
|
|
|
@ -314,6 +314,7 @@ class Connection(NetworkConnectionBase):
|
||||||
self._last_response = None
|
self._last_response = None
|
||||||
self._history = list()
|
self._history = list()
|
||||||
self._command_response = None
|
self._command_response = None
|
||||||
|
self._last_recv_window = None
|
||||||
|
|
||||||
self._terminal = None
|
self._terminal = None
|
||||||
self.cliconf = None
|
self.cliconf = None
|
||||||
|
@ -541,6 +542,7 @@ class Connection(NetworkConnectionBase):
|
||||||
recv.seek(offset)
|
recv.seek(offset)
|
||||||
|
|
||||||
window = self._strip(recv.read())
|
window = self._strip(recv.read())
|
||||||
|
self._last_recv_window = window
|
||||||
window_count += 1
|
window_count += 1
|
||||||
|
|
||||||
if prompts and not handled:
|
if prompts and not handled:
|
||||||
|
|
Loading…
Reference in a new issue