Add -vvv support for debugging activity
This commit is contained in:
parent
c82f06258c
commit
846186e2fc
10 changed files with 39 additions and 14 deletions
|
@ -15,6 +15,7 @@ Ansible Changes By Release
|
||||||
* better changed=True/False detection in user module on older Linux distros
|
* better changed=True/False detection in user module on older Linux distros
|
||||||
* when using paramiko and SFTP is not accessible, do not traceback, but return a nice human readable msg
|
* when using paramiko and SFTP is not accessible, do not traceback, but return a nice human readable msg
|
||||||
* nicer errors from modules when arguments are not key=value
|
* nicer errors from modules when arguments are not key=value
|
||||||
|
* use -vvv for extreme debug levels. -v gives more playbook output as before, -vv not really used yet
|
||||||
|
|
||||||
0.6 "Cabo" -- August 6, 2012
|
0.6 "Cabo" -- August 6, 2012
|
||||||
|
|
||||||
|
|
|
@ -96,7 +96,7 @@ class Cli(object):
|
||||||
pattern=pattern,
|
pattern=pattern,
|
||||||
callbacks=self.callbacks, sudo=options.sudo,
|
callbacks=self.callbacks, sudo=options.sudo,
|
||||||
sudo_pass=sudopass,sudo_user=options.sudo_user,
|
sudo_pass=sudopass,sudo_user=options.sudo_user,
|
||||||
transport=options.connection, verbose=options.verbose
|
transport=options.connection
|
||||||
)
|
)
|
||||||
|
|
||||||
if options.seconds:
|
if options.seconds:
|
||||||
|
|
|
@ -81,15 +81,14 @@ def main(args):
|
||||||
for playbook in args:
|
for playbook in args:
|
||||||
|
|
||||||
stats = callbacks.AggregateStats()
|
stats = callbacks.AggregateStats()
|
||||||
playbook_cb = callbacks.PlaybookCallbacks(verbose=options.verbose)
|
playbook_cb = callbacks.PlaybookCallbacks(verbose=utils.VERBOSITY)
|
||||||
runner_cb = callbacks.PlaybookRunnerCallbacks(stats, verbose=options.verbose)
|
runner_cb = callbacks.PlaybookRunnerCallbacks(stats, verbose=utils.VERBOSITY)
|
||||||
|
|
||||||
pb = ansible.playbook.PlayBook(
|
pb = ansible.playbook.PlayBook(
|
||||||
playbook=playbook,
|
playbook=playbook,
|
||||||
module_path=options.module_path,
|
module_path=options.module_path,
|
||||||
host_list=options.inventory,
|
host_list=options.inventory,
|
||||||
forks=options.forks,
|
forks=options.forks,
|
||||||
verbose=options.verbose,
|
|
||||||
remote_user=options.remote_user,
|
remote_user=options.remote_user,
|
||||||
remote_pass=sshpass,
|
remote_pass=sshpass,
|
||||||
callbacks=playbook_cb,
|
callbacks=playbook_cb,
|
||||||
|
|
|
@ -28,6 +28,13 @@ if os.path.exists("/usr/bin/cowsay"):
|
||||||
elif os.path.exists("/usr/games/cowsay"):
|
elif os.path.exists("/usr/games/cowsay"):
|
||||||
cowsay = "/usr/games/cowsay"
|
cowsay = "/usr/games/cowsay"
|
||||||
|
|
||||||
|
def vvv(msg, host=None):
|
||||||
|
if utils.VERBOSITY > 2:
|
||||||
|
if host is None:
|
||||||
|
print stringc(msg, 'blue')
|
||||||
|
else:
|
||||||
|
print stringc("<%s> %s" % (host, msg), 'blue')
|
||||||
|
|
||||||
class AggregateStats(object):
|
class AggregateStats(object):
|
||||||
''' holds stats about per-host activity during playbook runs '''
|
''' holds stats about per-host activity during playbook runs '''
|
||||||
|
|
||||||
|
@ -242,11 +249,11 @@ class CliRunnerCallbacks(DefaultRunnerCallbacks):
|
||||||
class PlaybookRunnerCallbacks(DefaultRunnerCallbacks):
|
class PlaybookRunnerCallbacks(DefaultRunnerCallbacks):
|
||||||
''' callbacks used for Runner() from /usr/bin/ansible-playbook '''
|
''' callbacks used for Runner() from /usr/bin/ansible-playbook '''
|
||||||
|
|
||||||
def __init__(self, stats, verbose=False):
|
def __init__(self, stats, verbose=utils.VERBOSITY):
|
||||||
|
|
||||||
|
self.verbose = verbose
|
||||||
self.stats = stats
|
self.stats = stats
|
||||||
self._async_notified = {}
|
self._async_notified = {}
|
||||||
self.verbose = verbose
|
|
||||||
|
|
||||||
def on_unreachable(self, host, msg):
|
def on_unreachable(self, host, msg):
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,6 @@ class PlayBook(object):
|
||||||
remote_port = C.DEFAULT_REMOTE_PORT,
|
remote_port = C.DEFAULT_REMOTE_PORT,
|
||||||
transport = C.DEFAULT_TRANSPORT,
|
transport = C.DEFAULT_TRANSPORT,
|
||||||
private_key_file = C.DEFAULT_PRIVATE_KEY_FILE,
|
private_key_file = C.DEFAULT_PRIVATE_KEY_FILE,
|
||||||
verbose = False,
|
|
||||||
callbacks = None,
|
callbacks = None,
|
||||||
runner_callbacks = None,
|
runner_callbacks = None,
|
||||||
stats = None,
|
stats = None,
|
||||||
|
@ -94,7 +93,6 @@ class PlayBook(object):
|
||||||
self.remote_pass = remote_pass
|
self.remote_pass = remote_pass
|
||||||
self.remote_port = remote_port
|
self.remote_port = remote_port
|
||||||
self.transport = transport
|
self.transport = transport
|
||||||
self.verbose = verbose
|
|
||||||
self.callbacks = callbacks
|
self.callbacks = callbacks
|
||||||
self.runner_callbacks = runner_callbacks
|
self.runner_callbacks = runner_callbacks
|
||||||
self.stats = stats
|
self.stats = stats
|
||||||
|
@ -191,7 +189,7 @@ class PlayBook(object):
|
||||||
private_key_file=self.private_key_file,
|
private_key_file=self.private_key_file,
|
||||||
setup_cache=self.SETUP_CACHE, basedir=self.basedir,
|
setup_cache=self.SETUP_CACHE, basedir=self.basedir,
|
||||||
conditional=task.only_if, callbacks=self.runner_callbacks,
|
conditional=task.only_if, callbacks=self.runner_callbacks,
|
||||||
verbose=self.verbose, sudo=task.play.sudo, sudo_user=task.play.sudo_user,
|
sudo=task.play.sudo, sudo_user=task.play.sudo_user,
|
||||||
transport=task.play.transport, sudo_pass=self.sudo_pass, is_playbook=True
|
transport=task.play.transport, sudo_pass=self.sudo_pass, is_playbook=True
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -272,7 +270,7 @@ class PlayBook(object):
|
||||||
forks=self.forks, module_path=self.module_path, timeout=self.timeout, remote_user=play.remote_user,
|
forks=self.forks, module_path=self.module_path, timeout=self.timeout, remote_user=play.remote_user,
|
||||||
remote_pass=self.remote_pass, remote_port=play.remote_port, private_key_file=self.private_key_file,
|
remote_pass=self.remote_pass, remote_port=play.remote_port, private_key_file=self.private_key_file,
|
||||||
setup_cache=self.SETUP_CACHE, callbacks=self.runner_callbacks, sudo=play.sudo, sudo_user=play.sudo_user,
|
setup_cache=self.SETUP_CACHE, callbacks=self.runner_callbacks, sudo=play.sudo, sudo_user=play.sudo_user,
|
||||||
verbose=self.verbose, transport=play.transport, sudo_pass=self.sudo_pass, is_playbook=True
|
transport=play.transport, sudo_pass=self.sudo_pass, is_playbook=True
|
||||||
).run()
|
).run()
|
||||||
self.stats.compute(setup_results, setup=True)
|
self.stats.compute(setup_results, setup=True)
|
||||||
|
|
||||||
|
|
|
@ -122,7 +122,6 @@ class Runner(object):
|
||||||
transport=C.DEFAULT_TRANSPORT, # 'ssh', 'paramiko', 'local'
|
transport=C.DEFAULT_TRANSPORT, # 'ssh', 'paramiko', 'local'
|
||||||
conditional='True', # run only if this fact expression evals to true
|
conditional='True', # run only if this fact expression evals to true
|
||||||
callbacks=None, # used for output
|
callbacks=None, # used for output
|
||||||
verbose=False, # whether to show more or less
|
|
||||||
sudo=False, # whether to run sudo or not
|
sudo=False, # whether to run sudo or not
|
||||||
sudo_user=C.DEFAULT_SUDO_USER, # ex: 'root'
|
sudo_user=C.DEFAULT_SUDO_USER, # ex: 'root'
|
||||||
module_vars=None, # a playbooks internals thing
|
module_vars=None, # a playbooks internals thing
|
||||||
|
@ -147,7 +146,6 @@ class Runner(object):
|
||||||
self.pattern = pattern
|
self.pattern = pattern
|
||||||
self.module_args = module_args
|
self.module_args = module_args
|
||||||
self.timeout = timeout
|
self.timeout = timeout
|
||||||
self.verbose = verbose
|
|
||||||
self.remote_user = remote_user
|
self.remote_user = remote_user
|
||||||
self.remote_pass = remote_pass
|
self.remote_pass = remote_pass
|
||||||
self.remote_port = remote_port
|
self.remote_port = remote_port
|
||||||
|
|
|
@ -20,6 +20,7 @@ import os
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
from ansible import errors
|
from ansible import errors
|
||||||
|
from ansible.callbacks import vvv
|
||||||
|
|
||||||
class LocalConnection(object):
|
class LocalConnection(object):
|
||||||
''' Local based connections '''
|
''' Local based connections '''
|
||||||
|
@ -44,6 +45,7 @@ class LocalConnection(object):
|
||||||
raise errors.AnsibleError("sudo with password is presently only supported on the paramiko (SSH) connection type")
|
raise errors.AnsibleError("sudo with password is presently only supported on the paramiko (SSH) connection type")
|
||||||
cmd = "sudo -u {0} -s {1}".format(sudo_user, cmd)
|
cmd = "sudo -u {0} -s {1}".format(sudo_user, cmd)
|
||||||
|
|
||||||
|
vvv("EXEC %s" % cmd, host=self.host)
|
||||||
p = subprocess.Popen(cmd, shell=True, stdin=None,
|
p = subprocess.Popen(cmd, shell=True, stdin=None,
|
||||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
stdout, stderr = p.communicate()
|
stdout, stderr = p.communicate()
|
||||||
|
@ -52,6 +54,7 @@ class LocalConnection(object):
|
||||||
def put_file(self, in_path, out_path):
|
def put_file(self, in_path, out_path):
|
||||||
''' transfer a file from local to local '''
|
''' transfer a file from local to local '''
|
||||||
|
|
||||||
|
vvv("PUT %s TO %s" % (in_path, out_path), host=self.host)
|
||||||
if not os.path.exists(in_path):
|
if not os.path.exists(in_path):
|
||||||
raise errors.AnsibleFileNotFound("file or module does not exist: %s" % in_path)
|
raise errors.AnsibleFileNotFound("file or module does not exist: %s" % in_path)
|
||||||
try:
|
try:
|
||||||
|
@ -64,6 +67,7 @@ class LocalConnection(object):
|
||||||
raise errors.AnsibleError("failed to transfer file to %s" % out_path)
|
raise errors.AnsibleError("failed to transfer file to %s" % out_path)
|
||||||
|
|
||||||
def fetch_file(self, in_path, out_path):
|
def fetch_file(self, in_path, out_path):
|
||||||
|
vvv("FETCH %s TO %s" % (in_path, out_path), host=self.host)
|
||||||
''' fetch a file from local to local -- for copatibility '''
|
''' fetch a file from local to local -- for copatibility '''
|
||||||
self.put_file(in_path, out_path)
|
self.put_file(in_path, out_path)
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,8 @@ import subprocess
|
||||||
import pipes
|
import pipes
|
||||||
import socket
|
import socket
|
||||||
import random
|
import random
|
||||||
|
from ansible import utils
|
||||||
|
from ansible.callbacks import vvv
|
||||||
from ansible import errors
|
from ansible import errors
|
||||||
|
|
||||||
# prevent paramiko warning noise -- see http://stackoverflow.com/questions/3920502/
|
# prevent paramiko warning noise -- see http://stackoverflow.com/questions/3920502/
|
||||||
|
@ -84,6 +86,7 @@ class ParamikoConnection(object):
|
||||||
|
|
||||||
if not self.runner.sudo or not sudoable:
|
if not self.runner.sudo or not sudoable:
|
||||||
quoted_command = '"$SHELL" -c ' + pipes.quote(cmd)
|
quoted_command = '"$SHELL" -c ' + pipes.quote(cmd)
|
||||||
|
vvv("EXEC %s" % quoted_command, host=self.host)
|
||||||
chan.exec_command(quoted_command)
|
chan.exec_command(quoted_command)
|
||||||
else:
|
else:
|
||||||
# Rather than detect if sudo wants a password this time, -k makes
|
# Rather than detect if sudo wants a password this time, -k makes
|
||||||
|
@ -98,6 +101,7 @@ class ParamikoConnection(object):
|
||||||
prompt = '[sudo via ansible, key=%s] password: ' % randbits
|
prompt = '[sudo via ansible, key=%s] password: ' % randbits
|
||||||
sudocmd = 'sudo -k && sudo -p "%s" -u %s -- "$SHELL" -c %s' % (
|
sudocmd = 'sudo -k && sudo -p "%s" -u %s -- "$SHELL" -c %s' % (
|
||||||
prompt, sudo_user, pipes.quote(cmd))
|
prompt, sudo_user, pipes.quote(cmd))
|
||||||
|
vvv("EXEC %s" % sudo_cmd, host=self.host)
|
||||||
sudo_output = ''
|
sudo_output = ''
|
||||||
try:
|
try:
|
||||||
chan.exec_command(sudocmd)
|
chan.exec_command(sudocmd)
|
||||||
|
@ -120,6 +124,7 @@ class ParamikoConnection(object):
|
||||||
|
|
||||||
def put_file(self, in_path, out_path):
|
def put_file(self, in_path, out_path):
|
||||||
''' transfer a file from local to remote '''
|
''' transfer a file from local to remote '''
|
||||||
|
vvv("PUT %s TO %s" % (in_path, out_path), host=self.host)
|
||||||
if not os.path.exists(in_path):
|
if not os.path.exists(in_path):
|
||||||
raise errors.AnsibleFileNotFound("file or module does not exist: %s" % in_path)
|
raise errors.AnsibleFileNotFound("file or module does not exist: %s" % in_path)
|
||||||
try:
|
try:
|
||||||
|
@ -134,6 +139,7 @@ class ParamikoConnection(object):
|
||||||
|
|
||||||
def fetch_file(self, in_path, out_path):
|
def fetch_file(self, in_path, out_path):
|
||||||
''' save a remote file to the specified path '''
|
''' save a remote file to the specified path '''
|
||||||
|
vvv("FETCH %s TO %s" % (in_path, out_path), host=self.host)
|
||||||
try:
|
try:
|
||||||
sftp = self.ssh.open_sftp()
|
sftp = self.ssh.open_sftp()
|
||||||
except:
|
except:
|
||||||
|
|
|
@ -23,6 +23,7 @@ import pipes
|
||||||
import random
|
import random
|
||||||
import select
|
import select
|
||||||
import fcntl
|
import fcntl
|
||||||
|
from ansible.callbacks import vvv
|
||||||
from ansible import errors
|
from ansible import errors
|
||||||
|
|
||||||
class SSHConnection(object):
|
class SSHConnection(object):
|
||||||
|
@ -72,6 +73,7 @@ class SSHConnection(object):
|
||||||
prompt, sudo_user, pipes.quote(cmd))
|
prompt, sudo_user, pipes.quote(cmd))
|
||||||
sudo_output = ''
|
sudo_output = ''
|
||||||
ssh_cmd.append(sudocmd)
|
ssh_cmd.append(sudocmd)
|
||||||
|
vvv("EXEC %s" % ssh_cmd, host=self.host)
|
||||||
p = subprocess.Popen(ssh_cmd, stdin=subprocess.PIPE,
|
p = subprocess.Popen(ssh_cmd, stdin=subprocess.PIPE,
|
||||||
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
if self.runner.sudo_pass:
|
if self.runner.sudo_pass:
|
||||||
|
@ -92,6 +94,7 @@ class SSHConnection(object):
|
||||||
fcntl.fcntl(p.stdout, fcntl.F_SETFL, fcntl.fcntl(p.stdout, fcntl.F_GETFL) & ~os.O_NONBLOCK)
|
fcntl.fcntl(p.stdout, fcntl.F_SETFL, fcntl.fcntl(p.stdout, fcntl.F_GETFL) & ~os.O_NONBLOCK)
|
||||||
else:
|
else:
|
||||||
ssh_cmd.append(cmd)
|
ssh_cmd.append(cmd)
|
||||||
|
vvv("EXEC %s" % ssh_cmd, host=self.host)
|
||||||
p = subprocess.Popen(ssh_cmd, stdin=subprocess.PIPE,
|
p = subprocess.Popen(ssh_cmd, stdin=subprocess.PIPE,
|
||||||
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
|
|
||||||
|
@ -114,6 +117,7 @@ class SSHConnection(object):
|
||||||
|
|
||||||
def put_file(self, in_path, out_path):
|
def put_file(self, in_path, out_path):
|
||||||
''' transfer a file from local to remote '''
|
''' transfer a file from local to remote '''
|
||||||
|
vvv("PUT %s TO %s" % (in_path, out_path), host=self.host)
|
||||||
if not os.path.exists(in_path):
|
if not os.path.exists(in_path):
|
||||||
raise errors.AnsibleFileNotFound("file or module does not exist: %s" % in_path)
|
raise errors.AnsibleFileNotFound("file or module does not exist: %s" % in_path)
|
||||||
sftp_cmd = ["sftp"] + self.common_args + [self.host]
|
sftp_cmd = ["sftp"] + self.common_args + [self.host]
|
||||||
|
@ -125,6 +129,7 @@ class SSHConnection(object):
|
||||||
|
|
||||||
def fetch_file(self, in_path, out_path):
|
def fetch_file(self, in_path, out_path):
|
||||||
''' fetch a file from remote to local '''
|
''' fetch a file from remote to local '''
|
||||||
|
vvv("FETCH %s TO %s" % (in_path, out_path), host=self.host)
|
||||||
sftp_cmd = ["sftp"] + self.common_args + [self.host]
|
sftp_cmd = ["sftp"] + self.common_args + [self.host]
|
||||||
p = subprocess.Popen(sftp_cmd, stdin=subprocess.PIPE,
|
p = subprocess.Popen(sftp_cmd, stdin=subprocess.PIPE,
|
||||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
|
|
@ -29,6 +29,8 @@ from ansible import color
|
||||||
from ansible import __version__
|
from ansible import __version__
|
||||||
import ansible.constants as C
|
import ansible.constants as C
|
||||||
|
|
||||||
|
VERBOSITY=0
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import json
|
import json
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
@ -318,12 +320,17 @@ class SortedOptParser(optparse.OptionParser):
|
||||||
self.option_list.sort(key=operator.methodcaller('get_opt_string'))
|
self.option_list.sort(key=operator.methodcaller('get_opt_string'))
|
||||||
return optparse.OptionParser.format_help(self, formatter=None)
|
return optparse.OptionParser.format_help(self, formatter=None)
|
||||||
|
|
||||||
|
def increment_debug(option, opt, value, parser):
|
||||||
|
global VERBOSITY
|
||||||
|
VERBOSITY += 1
|
||||||
|
|
||||||
def base_parser(constants=C, usage="", output_opts=False, runas_opts=False, async_opts=False, connect_opts=False):
|
def base_parser(constants=C, usage="", output_opts=False, runas_opts=False, async_opts=False, connect_opts=False):
|
||||||
''' create an options parser for any ansible script '''
|
''' create an options parser for any ansible script '''
|
||||||
|
|
||||||
parser = SortedOptParser(usage, version=version("%prog"))
|
parser = SortedOptParser(usage, version=version("%prog"))
|
||||||
parser.add_option('-v','--verbose', default=False, action="store_true",
|
parser.add_option('-v','--verbose', default=False, action="callback",
|
||||||
help='verbose mode')
|
callback=increment_debug, help="verbose mode (-vvv for more)")
|
||||||
|
|
||||||
parser.add_option('-f','--forks', dest='forks', default=constants.DEFAULT_FORKS, type='int',
|
parser.add_option('-f','--forks', dest='forks', default=constants.DEFAULT_FORKS, type='int',
|
||||||
help="specify number of parallel processes to use (default=%s)" % constants.DEFAULT_FORKS)
|
help="specify number of parallel processes to use (default=%s)" % constants.DEFAULT_FORKS)
|
||||||
parser.add_option('-i', '--inventory-file', dest='inventory',
|
parser.add_option('-i', '--inventory-file', dest='inventory',
|
||||||
|
|
Loading…
Reference in a new issue