mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-04-25 03:41:25 -07:00
Allow persistent connection plugins to queue messages back to ansible-connection (#49977)
* Connections can queue messages to be returned from ansible-connection * Provide fallback for invalid display level * Strip display from plugins * Route messages through helper method to try to avoid improper appends
This commit is contained in:
parent
49993a55e5
commit
1829a72885
13 changed files with 75 additions and 83 deletions
|
@ -192,9 +192,6 @@ from ansible.module_utils._text import to_bytes, to_text
|
|||
from ansible.playbook.play_context import PlayContext
|
||||
from ansible.plugins.connection import NetworkConnectionBase
|
||||
from ansible.plugins.loader import cliconf_loader, terminal_loader, connection_loader
|
||||
from ansible.utils.display import Display
|
||||
|
||||
display = Display()
|
||||
|
||||
|
||||
class AnsibleCmdRespRecv(Exception):
|
||||
|
@ -230,16 +227,16 @@ class Connection(NetworkConnectionBase):
|
|||
|
||||
self.cliconf = cliconf_loader.get(self._network_os, self)
|
||||
if self.cliconf:
|
||||
display.vvvv('loaded cliconf plugin for network_os %s' % self._network_os)
|
||||
self.queue_message('vvvv', 'loaded cliconf plugin for network_os %s' % self._network_os)
|
||||
self._sub_plugin = {'type': 'cliconf', 'name': self._network_os, 'obj': self.cliconf}
|
||||
else:
|
||||
display.vvvv('unable to load cliconf for network_os %s' % self._network_os)
|
||||
self.queue_message('vvvv', 'unable to load cliconf for network_os %s' % self._network_os)
|
||||
else:
|
||||
raise AnsibleConnectionFailure(
|
||||
'Unable to automatically determine host network os. Please '
|
||||
'manually configure ansible_network_os value for this host'
|
||||
)
|
||||
display.display('network_os is set to %s' % self._network_os, log_only=True)
|
||||
self.queue_message('log', 'network_os is set to %s' % self._network_os)
|
||||
|
||||
def _get_log_channel(self):
|
||||
name = "p=%s u=%s | " % (os.getpid(), getpass.getuser())
|
||||
|
@ -282,15 +279,15 @@ class Connection(NetworkConnectionBase):
|
|||
play_context = PlayContext()
|
||||
play_context.deserialize(pc_data)
|
||||
|
||||
messages = ['updating play_context for connection']
|
||||
self.queue_message('vvvv', 'updating play_context for connection')
|
||||
if self._play_context.become ^ play_context.become:
|
||||
if play_context.become is True:
|
||||
auth_pass = play_context.become_pass
|
||||
self._terminal.on_become(passwd=auth_pass)
|
||||
messages.append('authorizing connection')
|
||||
self.queue_message('vvvv', 'authorizing connection')
|
||||
else:
|
||||
self._terminal.on_unbecome()
|
||||
messages.append('deauthorizing connection')
|
||||
self.queue_message('vvvv', 'deauthorizing connection')
|
||||
|
||||
self._play_context = play_context
|
||||
|
||||
|
@ -299,8 +296,6 @@ class Connection(NetworkConnectionBase):
|
|||
if hasattr(self, 'disable_response_logging'):
|
||||
self.disable_response_logging()
|
||||
|
||||
return messages
|
||||
|
||||
def _connect(self):
|
||||
'''
|
||||
Connects to the remote device and starts the terminal
|
||||
|
@ -313,7 +308,7 @@ class Connection(NetworkConnectionBase):
|
|||
ssh = self.paramiko_conn._connect()
|
||||
|
||||
host = self.get_option('host')
|
||||
display.vvvv('ssh connection done, setting terminal', host=host)
|
||||
self.queue_message('vvvv', 'ssh connection done, setting terminal')
|
||||
|
||||
self._ssh_shell = ssh.ssh.invoke_shell()
|
||||
self._ssh_shell.settimeout(self.get_option('persistent_command_timeout'))
|
||||
|
@ -322,20 +317,20 @@ class Connection(NetworkConnectionBase):
|
|||
if not self._terminal:
|
||||
raise AnsibleConnectionFailure('network os %s is not supported' % self._network_os)
|
||||
|
||||
display.vvvv('loaded terminal plugin for network_os %s' % self._network_os, host=host)
|
||||
self.queue_message('vvvv', 'loaded terminal plugin for network_os %s' % self._network_os)
|
||||
|
||||
self.receive(prompts=self._terminal.terminal_initial_prompt, answer=self._terminal.terminal_initial_answer,
|
||||
newline=self._terminal.terminal_inital_prompt_newline)
|
||||
|
||||
display.vvvv('firing event: on_open_shell()', host=host)
|
||||
self.queue_message('vvvv', 'firing event: on_open_shell()')
|
||||
self._terminal.on_open_shell()
|
||||
|
||||
if self._play_context.become and self._play_context.become_method == 'enable':
|
||||
display.vvvv('firing event: on_become', host=host)
|
||||
self.queue_message('vvvv', 'firing event: on_become')
|
||||
auth_pass = self._play_context.become_pass
|
||||
self._terminal.on_become(passwd=auth_pass)
|
||||
|
||||
display.vvvv('ssh connection has completed successfully', host=host)
|
||||
self.queue_message('vvvv', 'ssh connection has completed successfully')
|
||||
self._connected = True
|
||||
|
||||
return self
|
||||
|
@ -346,17 +341,17 @@ class Connection(NetworkConnectionBase):
|
|||
'''
|
||||
# only close the connection if its connected.
|
||||
if self._connected:
|
||||
display.debug("closing ssh connection to device", host=self._play_context.remote_addr)
|
||||
self.queue_message('debug', "closing ssh connection to device")
|
||||
if self._ssh_shell:
|
||||
display.debug("firing event: on_close_shell()")
|
||||
self.queue_message('debug', "firing event: on_close_shell()")
|
||||
self._terminal.on_close_shell()
|
||||
self._ssh_shell.close()
|
||||
self._ssh_shell = None
|
||||
display.debug("cli session is now closed")
|
||||
self.queue_message('debug', "cli session is now closed")
|
||||
|
||||
self.paramiko_conn.close()
|
||||
self.paramiko_conn = None
|
||||
display.debug("ssh connection has been closed successfully")
|
||||
self.queue_message('debug', "ssh connection has been closed successfully")
|
||||
super(Connection, self).close()
|
||||
|
||||
def receive(self, command=None, prompts=None, answer=None, newline=True, prompt_retry_check=False, check_all=False):
|
||||
|
@ -451,19 +446,19 @@ class Connection(NetworkConnectionBase):
|
|||
response = self.receive(command, prompt, answer, newline, prompt_retry_check, check_all)
|
||||
return to_text(response, errors='surrogate_or_strict')
|
||||
except (socket.timeout, AttributeError):
|
||||
display.vvvv(traceback.format_exc(), host=self._play_context.remote_addr)
|
||||
self.queue_message('error', traceback.format_exc())
|
||||
raise AnsibleConnectionFailure("timeout value %s seconds reached while trying to send command: %s"
|
||||
% (self._ssh_shell.gettimeout(), command.strip()))
|
||||
|
||||
def _handle_buffer_read_timeout(self, signum, frame):
|
||||
display.vvvv("Response received, triggered 'persistent_buffer_read_timeout' timer of %s seconds"
|
||||
% self.get_option('persistent_buffer_read_timeout'), host=self._play_context.remote_addr)
|
||||
self.queue_message('vvvv', "Response received, triggered 'persistent_buffer_read_timeout' timer of %s seconds" %
|
||||
self.get_option('persistent_buffer_read_timeout'))
|
||||
raise AnsibleCmdRespRecv()
|
||||
|
||||
def _handle_command_timeout(self, signum, frame):
|
||||
msg = 'command timeout triggered, timeout value is %s secs.\nSee the timeout setting options in the Network Debug and Troubleshooting Guide.'\
|
||||
% self.get_option('persistent_command_timeout')
|
||||
display.display(msg, log_only=True)
|
||||
self.queue_message('log', msg)
|
||||
raise AnsibleConnectionFailure(msg)
|
||||
|
||||
def _strip(self, data):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue