more debug logs for free, network_cli, paramiko and add hostname context to debugging messages (#39205)
* Add hostname context to debugging messages * Set paramiko's channel
This commit is contained in:
parent
f91d961cb4
commit
bbfe7a8b2f
4 changed files with 30 additions and 11 deletions
|
@ -157,6 +157,7 @@ options:
|
||||||
- name: ANSIBLE_PERSISTENT_COMMAND_TIMEOUT
|
- name: ANSIBLE_PERSISTENT_COMMAND_TIMEOUT
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import getpass
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
|
@ -221,6 +222,11 @@ class Connection(ConnectionBase):
|
||||||
raise AttributeError("'%s' object has no attribute '%s'" % (self.__class__.__name__, name))
|
raise AttributeError("'%s' object has no attribute '%s'" % (self.__class__.__name__, name))
|
||||||
return getattr(self._cliconf, name)
|
return getattr(self._cliconf, name)
|
||||||
|
|
||||||
|
def _get_log_channel(self):
|
||||||
|
name = "p=%s u=%s | " % (os.getpid(), getpass.getuser())
|
||||||
|
name += "paramiko [%s]" % self._play_context.remote_addr
|
||||||
|
return name
|
||||||
|
|
||||||
def get_prompt(self):
|
def get_prompt(self):
|
||||||
"""Returns the current prompt from the device"""
|
"""Returns the current prompt from the device"""
|
||||||
return self._matched_prompt
|
return self._matched_prompt
|
||||||
|
@ -284,6 +290,7 @@ class Connection(ConnectionBase):
|
||||||
return
|
return
|
||||||
|
|
||||||
self.paramiko_conn = connection_loader.get('paramiko', self._play_context, '/dev/null')
|
self.paramiko_conn = connection_loader.get('paramiko', self._play_context, '/dev/null')
|
||||||
|
self.paramiko_conn._set_log_channel(self._get_log_channel())
|
||||||
self.paramiko_conn.set_options(direct={'look_for_keys': not bool(self._play_context.password and not self._play_context.private_key_file)})
|
self.paramiko_conn.set_options(direct={'look_for_keys': not bool(self._play_context.password and not self._play_context.private_key_file)})
|
||||||
self.paramiko_conn.force_persistence = self.force_persistence
|
self.paramiko_conn.force_persistence = self.force_persistence
|
||||||
ssh = self.paramiko_conn._connect()
|
ssh = self.paramiko_conn._connect()
|
||||||
|
@ -363,7 +370,7 @@ class Connection(ConnectionBase):
|
||||||
'''
|
'''
|
||||||
# only close the connection if its connected.
|
# only close the connection if its connected.
|
||||||
if self._connected:
|
if self._connected:
|
||||||
display.debug("closing ssh connection to device")
|
display.debug("closing ssh connection to device", host=self._play_context.remote_addr)
|
||||||
if self._ssh_shell:
|
if self._ssh_shell:
|
||||||
display.debug("firing event: on_close_shell()")
|
display.debug("firing event: on_close_shell()")
|
||||||
self._terminal.on_close_shell()
|
self._terminal.on_close_shell()
|
||||||
|
|
|
@ -228,6 +228,7 @@ class Connection(ConnectionBase):
|
||||||
''' SSH based connections with Paramiko '''
|
''' SSH based connections with Paramiko '''
|
||||||
|
|
||||||
transport = 'paramiko'
|
transport = 'paramiko'
|
||||||
|
_log_channel = None
|
||||||
|
|
||||||
def _cache_key(self):
|
def _cache_key(self):
|
||||||
return "%s__%s__" % (self._play_context.remote_addr, self._play_context.remote_user)
|
return "%s__%s__" % (self._play_context.remote_addr, self._play_context.remote_user)
|
||||||
|
@ -240,6 +241,10 @@ class Connection(ConnectionBase):
|
||||||
self.ssh = SSH_CONNECTION_CACHE[cache_key] = self._connect_uncached()
|
self.ssh = SSH_CONNECTION_CACHE[cache_key] = self._connect_uncached()
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
def _set_log_channel(self, name):
|
||||||
|
'''Mimic paramiko.SSHClient.set_log_channel'''
|
||||||
|
self._log_channel = name
|
||||||
|
|
||||||
def _parse_proxy_command(self, port=22):
|
def _parse_proxy_command(self, port=22):
|
||||||
proxy_command = None
|
proxy_command = None
|
||||||
# Parse ansible_ssh_common_args, specifically looking for ProxyCommand
|
# Parse ansible_ssh_common_args, specifically looking for ProxyCommand
|
||||||
|
@ -297,6 +302,10 @@ class Connection(ConnectionBase):
|
||||||
|
|
||||||
ssh = paramiko.SSHClient()
|
ssh = paramiko.SSHClient()
|
||||||
|
|
||||||
|
# override paramiko's default logger name
|
||||||
|
if self._log_channel is not None:
|
||||||
|
ssh.set_log_channel(self._log_channel)
|
||||||
|
|
||||||
self.keyfile = os.path.expanduser("~/.ssh/known_hosts")
|
self.keyfile = os.path.expanduser("~/.ssh/known_hosts")
|
||||||
|
|
||||||
if self.get_option('host_key_checking'):
|
if self.get_option('host_key_checking'):
|
||||||
|
|
|
@ -91,15 +91,15 @@ class StrategyModule(StrategyBase):
|
||||||
# peek at the next task for the host, to see if there's
|
# peek at the next task for the host, to see if there's
|
||||||
# anything to do do for this host
|
# anything to do do for this host
|
||||||
(state, task) = iterator.get_next_task_for_host(host, peek=True)
|
(state, task) = iterator.get_next_task_for_host(host, peek=True)
|
||||||
display.debug("free host state: %s" % state)
|
display.debug("free host state: %s" % state, host=host_name)
|
||||||
display.debug("free host task: %s" % task)
|
display.debug("free host task: %s" % task, host=host_name)
|
||||||
if host_name not in self._tqm._unreachable_hosts and task:
|
if host_name not in self._tqm._unreachable_hosts and task:
|
||||||
|
|
||||||
# set the flag so the outer loop knows we've still found
|
# set the flag so the outer loop knows we've still found
|
||||||
# some work which needs to be done
|
# some work which needs to be done
|
||||||
work_to_do = True
|
work_to_do = True
|
||||||
|
|
||||||
display.debug("this host has work to do")
|
display.debug("this host has work to do", host=host_name)
|
||||||
|
|
||||||
# check to see if this host is blocked (still executing a previous task)
|
# check to see if this host is blocked (still executing a previous task)
|
||||||
if host_name not in self._blocked_hosts or not self._blocked_hosts[host_name]:
|
if host_name not in self._blocked_hosts or not self._blocked_hosts[host_name]:
|
||||||
|
@ -114,19 +114,19 @@ class StrategyModule(StrategyBase):
|
||||||
# corresponding action plugin
|
# corresponding action plugin
|
||||||
action = None
|
action = None
|
||||||
|
|
||||||
display.debug("getting variables")
|
display.debug("getting variables", host=host_name)
|
||||||
task_vars = self._variable_manager.get_vars(play=iterator._play, host=host, task=task)
|
task_vars = self._variable_manager.get_vars(play=iterator._play, host=host, task=task)
|
||||||
self.add_tqm_variables(task_vars, play=iterator._play)
|
self.add_tqm_variables(task_vars, play=iterator._play)
|
||||||
templar = Templar(loader=self._loader, variables=task_vars)
|
templar = Templar(loader=self._loader, variables=task_vars)
|
||||||
display.debug("done getting variables")
|
display.debug("done getting variables", host=host_name)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
task.name = to_text(templar.template(task.name, fail_on_undefined=False), nonstring='empty')
|
task.name = to_text(templar.template(task.name, fail_on_undefined=False), nonstring='empty')
|
||||||
display.debug("done templating")
|
display.debug("done templating", host=host_name)
|
||||||
except:
|
except:
|
||||||
# just ignore any errors during task name templating,
|
# just ignore any errors during task name templating,
|
||||||
# we don't care if it just shows the raw name
|
# we don't care if it just shows the raw name
|
||||||
display.debug("templating failed for some reason")
|
display.debug("templating failed for some reason", host=host_name)
|
||||||
|
|
||||||
run_once = templar.template(task.run_once) or action and getattr(action, 'BYPASS_HOST_LOOP', False)
|
run_once = templar.template(task.run_once) or action and getattr(action, 'BYPASS_HOST_LOOP', False)
|
||||||
if run_once:
|
if run_once:
|
||||||
|
@ -143,7 +143,7 @@ class StrategyModule(StrategyBase):
|
||||||
# If there is no metadata, the default behavior is to not allow duplicates,
|
# If there is no metadata, the default behavior is to not allow duplicates,
|
||||||
# if there is metadata, check to see if the allow_duplicates flag was set to true
|
# if there is metadata, check to see if the allow_duplicates flag was set to true
|
||||||
if task._role._metadata is None or task._role._metadata and not task._role._metadata.allow_duplicates:
|
if task._role._metadata is None or task._role._metadata and not task._role._metadata.allow_duplicates:
|
||||||
display.debug("'%s' skipped because role has already run" % task)
|
display.debug("'%s' skipped because role has already run" % task, host=host_name)
|
||||||
del self._blocked_hosts[host_name]
|
del self._blocked_hosts[host_name]
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
|
|
@ -191,9 +191,12 @@ class Display:
|
||||||
def vvvvvv(self, msg, host=None):
|
def vvvvvv(self, msg, host=None):
|
||||||
return self.verbose(msg, host=host, caplevel=5)
|
return self.verbose(msg, host=host, caplevel=5)
|
||||||
|
|
||||||
def debug(self, msg):
|
def debug(self, msg, host=None):
|
||||||
if C.DEFAULT_DEBUG:
|
if C.DEFAULT_DEBUG:
|
||||||
|
if host is None:
|
||||||
self.display("%6d %0.5f: %s" % (os.getpid(), time.time(), msg), color=C.COLOR_DEBUG)
|
self.display("%6d %0.5f: %s" % (os.getpid(), time.time(), msg), color=C.COLOR_DEBUG)
|
||||||
|
else:
|
||||||
|
self.display("%6d %0.5f [%s]: %s" % (os.getpid(), time.time(), host, msg), color=C.COLOR_DEBUG)
|
||||||
|
|
||||||
def verbose(self, msg, host=None, caplevel=2):
|
def verbose(self, msg, host=None, caplevel=2):
|
||||||
if self.verbosity > caplevel:
|
if self.verbosity > caplevel:
|
||||||
|
|
Loading…
Reference in a new issue