commit
4a8dc50249
4 changed files with 53 additions and 31 deletions
|
@ -33,6 +33,8 @@ def main(args):
|
||||||
# create parser for CLI options
|
# create parser for CLI options
|
||||||
parser = OptionParser()
|
parser = OptionParser()
|
||||||
parser.usage = "ans-playbook playbook.yml ..."
|
parser.usage = "ans-playbook playbook.yml ..."
|
||||||
|
parser.add_option('-D','--debug', default=False, action="store_true",
|
||||||
|
help='enable standard error debugging of modules.')
|
||||||
parser.add_option('-f','--forks', dest='forks', default=C.DEFAULT_FORKS, type='int',
|
parser.add_option('-f','--forks', dest='forks', default=C.DEFAULT_FORKS, type='int',
|
||||||
help='set the number of forks to start up')
|
help='set the number of forks to start up')
|
||||||
parser.add_option("-i", "--inventory-file", dest="inventory",
|
parser.add_option("-i", "--inventory-file", dest="inventory",
|
||||||
|
@ -76,6 +78,7 @@ def main(args):
|
||||||
extra_vars=options.extra_vars,
|
extra_vars=options.extra_vars,
|
||||||
module_path=options.module_path,
|
module_path=options.module_path,
|
||||||
forks=options.forks,
|
forks=options.forks,
|
||||||
|
debug=options.debug,
|
||||||
verbose=True,
|
verbose=True,
|
||||||
remote_pass=sshpass,
|
remote_pass=sshpass,
|
||||||
remote_port=options.remote_port,
|
remote_port=options.remote_port,
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#######################################################
|
#######################################################
|
||||||
|
|
||||||
import utils
|
import utils
|
||||||
|
import sys
|
||||||
|
|
||||||
#######################################################
|
#######################################################
|
||||||
|
|
||||||
|
@ -146,6 +147,9 @@ class PlaybookRunnerCallbacks(DefaultRunnerCallbacks):
|
||||||
else:
|
else:
|
||||||
print "ok: [%s] => %s\n" % (host, invocation)
|
print "ok: [%s] => %s\n" % (host, invocation)
|
||||||
|
|
||||||
|
def on_error(self, host, err):
|
||||||
|
print >>sys.stderr, "stderr: [%s] => %s\n" % (host, err)
|
||||||
|
|
||||||
def on_skipped(self, host):
|
def on_skipped(self, host):
|
||||||
print "skipping: [%s]\n" % host
|
print "skipping: [%s]\n" % host
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,7 @@ class PlayBook(object):
|
||||||
remote_port = C.DEFAULT_REMOTE_PORT,
|
remote_port = C.DEFAULT_REMOTE_PORT,
|
||||||
override_hosts = None,
|
override_hosts = None,
|
||||||
extra_vars = None,
|
extra_vars = None,
|
||||||
|
debug = False,
|
||||||
verbose = False,
|
verbose = False,
|
||||||
callbacks = None,
|
callbacks = None,
|
||||||
runner_callbacks = None,
|
runner_callbacks = None,
|
||||||
|
@ -72,6 +73,7 @@ class PlayBook(object):
|
||||||
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
|
||||||
|
self.debug = debug
|
||||||
self.verbose = verbose
|
self.verbose = verbose
|
||||||
self.callbacks = callbacks
|
self.callbacks = callbacks
|
||||||
self.runner_callbacks = runner_callbacks
|
self.runner_callbacks = runner_callbacks
|
||||||
|
@ -270,7 +272,7 @@ class PlayBook(object):
|
||||||
remote_port=self.remote_port,
|
remote_port=self.remote_port,
|
||||||
setup_cache=SETUP_CACHE, basedir=self.basedir,
|
setup_cache=SETUP_CACHE, basedir=self.basedir,
|
||||||
conditional=only_if, callbacks=self.runner_callbacks,
|
conditional=only_if, callbacks=self.runner_callbacks,
|
||||||
extra_vars=self.extra_vars, sudo=sudo
|
extra_vars=self.extra_vars, debug=self.debug, sudo=sudo
|
||||||
)
|
)
|
||||||
|
|
||||||
if async_seconds == 0:
|
if async_seconds == 0:
|
||||||
|
|
|
@ -74,7 +74,7 @@ class Runner(object):
|
||||||
remote_user=C.DEFAULT_REMOTE_USER, remote_pass=C.DEFAULT_REMOTE_PASS,
|
remote_user=C.DEFAULT_REMOTE_USER, remote_pass=C.DEFAULT_REMOTE_PASS,
|
||||||
remote_port=C.DEFAULT_REMOTE_PORT, background=0, basedir=None, setup_cache=None,
|
remote_port=C.DEFAULT_REMOTE_PORT, background=0, basedir=None, setup_cache=None,
|
||||||
transport='paramiko', conditional='True', groups={}, callbacks=None, verbose=False,
|
transport='paramiko', conditional='True', groups={}, callbacks=None, verbose=False,
|
||||||
sudo=False, extra_vars=None):
|
debug=False, sudo=False, extra_vars=None):
|
||||||
|
|
||||||
if setup_cache is None:
|
if setup_cache is None:
|
||||||
setup_cache = {}
|
setup_cache = {}
|
||||||
|
@ -103,6 +103,7 @@ class Runner(object):
|
||||||
self.module_args = module_args
|
self.module_args = module_args
|
||||||
self.extra_vars = extra_vars
|
self.extra_vars = extra_vars
|
||||||
self.timeout = timeout
|
self.timeout = timeout
|
||||||
|
self.debug = debug
|
||||||
self.verbose = verbose
|
self.verbose = verbose
|
||||||
self.remote_user = remote_user
|
self.remote_user = remote_user
|
||||||
self.remote_pass = remote_pass
|
self.remote_pass = remote_pass
|
||||||
|
@ -227,16 +228,18 @@ class Runner(object):
|
||||||
|
|
||||||
# *****************************************************
|
# *****************************************************
|
||||||
|
|
||||||
def _return_from_module(self, conn, host, result, executed=None):
|
def _return_from_module(self, conn, host, result, err, executed=None):
|
||||||
''' helper function to handle JSON parsing of results '''
|
''' helper function to handle JSON parsing of results '''
|
||||||
|
|
||||||
try:
|
try:
|
||||||
result = utils.parse_json(result)
|
result = utils.parse_json(result)
|
||||||
if executed is not None:
|
if executed is not None:
|
||||||
result['invocation'] = executed
|
result['invocation'] = executed
|
||||||
return [ host, True, result ]
|
if 'stderr' in result:
|
||||||
|
err="%s%s"%(err,result['stderr'])
|
||||||
|
return [host, True, result, err]
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
return [ host, False, "%s/%s/%s" % (str(e), result, executed) ]
|
return [host, False, "%s/%s/%s" % (str(e), result, executed), err]
|
||||||
|
|
||||||
# *****************************************************
|
# *****************************************************
|
||||||
|
|
||||||
|
@ -337,7 +340,7 @@ class Runner(object):
|
||||||
inject = self.setup_cache.get(conn.host,{})
|
inject = self.setup_cache.get(conn.host,{})
|
||||||
conditional = utils.double_template(self.conditional, inject)
|
conditional = utils.double_template(self.conditional, inject)
|
||||||
if not eval(conditional):
|
if not eval(conditional):
|
||||||
return [ utils.smjson(dict(skipped=True)), 'skipped' ]
|
return [ utils.smjson(dict(skipped=True)), None, 'skipped' ]
|
||||||
|
|
||||||
if Runner._external_variable_script is not None:
|
if Runner._external_variable_script is not None:
|
||||||
self._add_variables_from_script(conn, inject)
|
self._add_variables_from_script(conn, inject)
|
||||||
|
@ -354,7 +357,8 @@ class Runner(object):
|
||||||
cmd = "%s %s" % (remote_module_path, argsfile)
|
cmd = "%s %s" % (remote_module_path, argsfile)
|
||||||
else:
|
else:
|
||||||
cmd = " ".join([str(x) for x in [remote_module_path, async_jid, async_limit, async_module, argsfile]])
|
cmd = " ".join([str(x) for x in [remote_module_path, async_jid, async_limit, async_module, argsfile]])
|
||||||
return [ self._exec_command(conn, cmd, tmp, sudoable=True), client_executed_str ]
|
res, err = self._exec_command(conn, cmd, tmp, sudoable=True)
|
||||||
|
return ( res, err, client_executed_str )
|
||||||
|
|
||||||
# *****************************************************
|
# *****************************************************
|
||||||
|
|
||||||
|
@ -387,12 +391,12 @@ class Runner(object):
|
||||||
self.module_args += " #USE_SHELL"
|
self.module_args += " #USE_SHELL"
|
||||||
|
|
||||||
module = self._transfer_module(conn, tmp, module_name)
|
module = self._transfer_module(conn, tmp, module_name)
|
||||||
(result, executed) = self._execute_module(conn, tmp, module, self.module_args)
|
(result, err, executed) = self._execute_module(conn, tmp, module, self.module_args)
|
||||||
|
|
||||||
if module_name == 'setup':
|
if module_name == 'setup':
|
||||||
self._add_result_to_setup_cache(conn, result)
|
self._add_result_to_setup_cache(conn, result)
|
||||||
|
|
||||||
return self._return_from_module(conn, host, result, executed)
|
return self._return_from_module(conn, host, result, err, executed)
|
||||||
|
|
||||||
# *****************************************************
|
# *****************************************************
|
||||||
|
|
||||||
|
@ -408,13 +412,13 @@ class Runner(object):
|
||||||
|
|
||||||
async = self._transfer_module(conn, tmp, 'async_wrapper')
|
async = self._transfer_module(conn, tmp, 'async_wrapper')
|
||||||
module = self._transfer_module(conn, tmp, module_name)
|
module = self._transfer_module(conn, tmp, module_name)
|
||||||
(result, executed) = self._execute_module(conn, tmp, async, module_args,
|
(result, err, executed) = self._execute_module(conn, tmp, async, module_args,
|
||||||
async_module=module,
|
async_module=module,
|
||||||
async_jid=self.generated_jid,
|
async_jid=self.generated_jid,
|
||||||
async_limit=self.background
|
async_limit=self.background
|
||||||
)
|
)
|
||||||
|
|
||||||
return self._return_from_module(conn, host, result, executed)
|
return self._return_from_module(conn, host, result, err, executed)
|
||||||
|
|
||||||
# *****************************************************
|
# *****************************************************
|
||||||
|
|
||||||
|
@ -436,30 +440,30 @@ class Runner(object):
|
||||||
|
|
||||||
# run the copy module
|
# run the copy module
|
||||||
args = "src=%s dest=%s" % (tmp_src, dest)
|
args = "src=%s dest=%s" % (tmp_src, dest)
|
||||||
(result1, executed) = self._execute_module(conn, tmp, module, args)
|
(result1, err, executed) = self._execute_module(conn, tmp, module, args)
|
||||||
(host, ok, data) = self._return_from_module(conn, host, result1, executed)
|
(host, ok, data, err) = self._return_from_module(conn, host, result1, err, executed)
|
||||||
|
|
||||||
if ok:
|
if ok:
|
||||||
return self._chain_file_module(conn, tmp, data, options, executed)
|
return self._chain_file_module(conn, tmp, data, err, options, executed)
|
||||||
else:
|
else:
|
||||||
return (host, ok, data)
|
return (host, ok, data, err)
|
||||||
|
|
||||||
# *****************************************************
|
# *****************************************************
|
||||||
|
|
||||||
def _chain_file_module(self, conn, tmp, data, options, executed):
|
def _chain_file_module(self, conn, tmp, data, err, options, executed):
|
||||||
''' handles changing file attribs after copy/template operations '''
|
''' handles changing file attribs after copy/template operations '''
|
||||||
|
|
||||||
old_changed = data.get('changed', False)
|
old_changed = data.get('changed', False)
|
||||||
module = self._transfer_module(conn, tmp, 'file')
|
module = self._transfer_module(conn, tmp, 'file')
|
||||||
args = ' '.join([ "%s=%s" % (k,v) for (k,v) in options.items() ])
|
args = ' '.join([ "%s=%s" % (k,v) for (k,v) in options.items() ])
|
||||||
(result2, executed2) = self._execute_module(conn, tmp, module, args)
|
(result2, err2, executed2) = self._execute_module(conn, tmp, module, args)
|
||||||
results2 = self._return_from_module(conn, conn.host, result2, executed)
|
results2 = self._return_from_module(conn, conn.host, result2, err2, executed)
|
||||||
(host, ok, data2) = results2
|
(host, ok, data2, err2) = results2
|
||||||
new_changed = data2.get('changed', False)
|
new_changed = data2.get('changed', False)
|
||||||
data.update(data2)
|
data.update(data2)
|
||||||
if old_changed or new_changed:
|
if old_changed or new_changed:
|
||||||
data['changed'] = True
|
data['changed'] = True
|
||||||
return (host, ok, data)
|
return (host, ok, data, "%s%s"%(err,err2))
|
||||||
|
|
||||||
# *****************************************************
|
# *****************************************************
|
||||||
|
|
||||||
|
@ -487,19 +491,19 @@ class Runner(object):
|
||||||
|
|
||||||
# run the template module
|
# run the template module
|
||||||
args = "src=%s dest=%s metadata=%s" % (temppath, dest, metadata)
|
args = "src=%s dest=%s metadata=%s" % (temppath, dest, metadata)
|
||||||
(result1, executed) = self._execute_module(conn, tmp, template_module, args)
|
(result1, err, executed) = self._execute_module(conn, tmp, template_module, args)
|
||||||
(host, ok, data) = self._return_from_module(conn, host, result1, executed)
|
(host, ok, data, err) = self._return_from_module(conn, host, result1, err, executed)
|
||||||
|
|
||||||
if ok:
|
if ok:
|
||||||
return self._chain_file_module(conn, tmp, data, options, executed)
|
return self._chain_file_module(conn, tmp, data, err, options, executed)
|
||||||
else:
|
else:
|
||||||
return (host, ok, data)
|
return (host, ok, data, err)
|
||||||
|
|
||||||
# *****************************************************
|
# *****************************************************
|
||||||
|
|
||||||
def _executor(self, host):
|
def _executor(self, host):
|
||||||
try:
|
try:
|
||||||
(host, ok, data) = self._executor_internal(host)
|
(host, ok, data, err) = self._executor_internal(host)
|
||||||
if not ok:
|
if not ok:
|
||||||
self.callbacks.on_unreachable(host, data)
|
self.callbacks.on_unreachable(host, data)
|
||||||
return (host, ok, data)
|
return (host, ok, data)
|
||||||
|
@ -517,7 +521,7 @@ class Runner(object):
|
||||||
|
|
||||||
ok, conn = self._connect(host)
|
ok, conn = self._connect(host)
|
||||||
if not ok:
|
if not ok:
|
||||||
return [ host, False, conn ]
|
return [ host, False, conn , None]
|
||||||
|
|
||||||
cache = self.setup_cache.get(host, {})
|
cache = self.setup_cache.get(host, {})
|
||||||
module_name = utils.template(self.module_name, cache)
|
module_name = utils.template(self.module_name, cache)
|
||||||
|
@ -538,7 +542,7 @@ class Runner(object):
|
||||||
self._delete_remote_files(conn, tmp)
|
self._delete_remote_files(conn, tmp)
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
(host, connect_ok, data) = result
|
(host, connect_ok, data, err) = result
|
||||||
if not connect_ok:
|
if not connect_ok:
|
||||||
self.callbacks.on_unreachable(host, data)
|
self.callbacks.on_unreachable(host, data)
|
||||||
else:
|
else:
|
||||||
|
@ -549,6 +553,9 @@ class Runner(object):
|
||||||
else:
|
else:
|
||||||
self.callbacks.on_ok(host, data)
|
self.callbacks.on_ok(host, data)
|
||||||
|
|
||||||
|
if self.debug and err:
|
||||||
|
self.callbacks.on_error(host, err)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
# *****************************************************
|
# *****************************************************
|
||||||
|
@ -561,17 +568,23 @@ class Runner(object):
|
||||||
conn.exec_command('/usr/bin/logger -t ansible -p auth.info "%s"' % msg, None)
|
conn.exec_command('/usr/bin/logger -t ansible -p auth.info "%s"' % msg, None)
|
||||||
# now run actual command
|
# now run actual command
|
||||||
stdin, stdout, stderr = conn.exec_command(cmd, tmp, sudoable=sudoable)
|
stdin, stdout, stderr = conn.exec_command(cmd, tmp, sudoable=sudoable)
|
||||||
if type(stdout) != str:
|
|
||||||
return "\n".join(stdout.readlines())
|
if type(stderr) != str:
|
||||||
|
err="\n".join(stderr.readlines())
|
||||||
else:
|
else:
|
||||||
return stdout
|
err=stderr
|
||||||
|
|
||||||
|
if type(stdout) != str:
|
||||||
|
return "\n".join(stdout.readlines()), err
|
||||||
|
else:
|
||||||
|
return stdout, err
|
||||||
|
|
||||||
# *****************************************************
|
# *****************************************************
|
||||||
|
|
||||||
def _get_tmp_path(self, conn):
|
def _get_tmp_path(self, conn):
|
||||||
''' gets a temporary path on a remote box '''
|
''' gets a temporary path on a remote box '''
|
||||||
|
|
||||||
result = self._exec_command(conn, "mktemp -d /tmp/ansible.XXXXXX", None, sudoable=False)
|
result, err = self._exec_command(conn, "mktemp -d /tmp/ansible.XXXXXX", None, sudoable=False)
|
||||||
cleaned = result.split("\n")[0].strip() + '/'
|
cleaned = result.split("\n")[0].strip() + '/'
|
||||||
return cleaned
|
return cleaned
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue