9aa8547016
* adds new connection plugin `network_cli` which builds on paramiko * adds new plugin `terminal` used for manipulating network_cli terminals * adds new field to play_context `network_os` settable as ansible_network_os This commit adds the plugins necesary to establish a persistent cli connection to network devices of ssh. It builds on the paramiko connection plugin to create a shell environment that will persistent through ansible-connection. The `newtork_cli` plugin then uses the network_os in the instance of PlayContext to load the appropriate network OS environment plugin for handling opening and closing of shells as well as privilege escalation.
75 lines
2.4 KiB
Python
75 lines
2.4 KiB
Python
#
|
|
# (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/>.
|
|
#
|
|
from __future__ import (absolute_import, division, print_function)
|
|
__metaclass__ = type
|
|
|
|
import re
|
|
import json
|
|
|
|
from ansible.plugins.terminal import TerminalBase
|
|
from ansible.errors import AnsibleConnectionFailure
|
|
|
|
|
|
class TerminalModule(TerminalBase):
|
|
|
|
terminal_prompts_re = [
|
|
re.compile(r"[\r\n]?[\w+\-\.:\/\[\]]+(?:\([^\)]+\)){,3}(?:>|#) ?$"),
|
|
re.compile(r"\[\w+\@[\w\-\.]+(?: [^\]])\] ?[>#\$] ?$")
|
|
]
|
|
|
|
terminal_errors_re = [
|
|
re.compile(r"% ?Error"),
|
|
re.compile(r"^% \w+", re.M),
|
|
re.compile(r"% ?Bad secret"),
|
|
re.compile(r"invalid input", re.I),
|
|
re.compile(r"(?:incomplete|ambiguous) command", re.I),
|
|
re.compile(r"connection timed out", re.I),
|
|
re.compile(r"[^\r\n]+ not found", re.I),
|
|
re.compile(r"'[^']' +returned error code: ?\d+"),
|
|
]
|
|
|
|
def authorize(self, passwd=None):
|
|
if self._get_prompt().endswith('#'):
|
|
return
|
|
|
|
cmd = {'command': 'enable'}
|
|
if passwd:
|
|
cmd['prompt'] = r"[\r\n]?password: $"
|
|
cmd['answer'] = passwd
|
|
|
|
try:
|
|
self._exec_cli_command(json.dumps(cmd))
|
|
self._exec_cli_command('terminal pager 0')
|
|
except AnsibleConnectionFailure:
|
|
raise AnsibleConnectionFailure('unable to elevate privilege to enable mode')
|
|
|
|
def on_deauthorize(self):
|
|
prompt = self._get_prompt()
|
|
if prompt is None:
|
|
# if prompt is None most likely the terminal is hung up at a prompt
|
|
return
|
|
|
|
if '(config' in prompt:
|
|
self._exec_cli_command('end')
|
|
self._exec_cli_command('disable')
|
|
|
|
elif prompt.endswith('#'):
|
|
self._exec_cli_command('disable')
|
|
|
|
|