Commit cbc12f0d by Michael DeHaan

Various performance streamlining and making the file features usable in all…

Various performance streamlining and making the file features usable in all modules without daisy chaining.
parent 60b9316a
...@@ -179,22 +179,6 @@ class Runner(object): ...@@ -179,22 +179,6 @@ class Runner(object):
# ***************************************************** # *****************************************************
def _delete_remote_files(self, conn, files):
''' deletes one or more remote files '''
if os.getenv("ANSIBLE_KEEP_REMOTE_FILES","0") == "1":
# ability to turn off temp file deletion for debug purposes
return
if type(files) in [ str, unicode ]:
files = [ files ]
for filename in files:
if filename.find('/tmp/') == -1:
raise Exception("safeguard deletion, removal of %s is not going to happen" % filename)
self._low_level_exec_command(conn, "rm -rf %s" % filename, None)
# *****************************************************
def _transfer_str(self, conn, tmp, name, data): def _transfer_str(self, conn, tmp, name, data):
''' transfer string to remote file ''' ''' transfer string to remote file '''
...@@ -230,12 +214,12 @@ class Runner(object): ...@@ -230,12 +214,12 @@ class Runner(object):
if 'port' not in args: if 'port' not in args:
args += " port=%s" % C.ZEROMQ_PORT args += " port=%s" % C.ZEROMQ_PORT
(remote_module_path, is_new_style) = self._copy_module(conn, tmp, module_name, args, inject) (remote_module_path, is_new_style, shebang) = self._copy_module(conn, tmp, module_name, args, inject)
cmd = "chmod u+x %s" % remote_module_path
cmd_mod = ""
if self.sudo and self.sudo_user != 'root': if self.sudo and self.sudo_user != 'root':
# deal with possible umask issues once sudo'ed to other user # deal with possible umask issues once sudo'ed to other user
cmd = "chmod a+rx %s" % remote_module_path cmd_mod = "chmod a+r %s; " % remote_module_path
self._low_level_exec_command(conn, cmd, tmp)
cmd = "" cmd = ""
if not is_new_style: if not is_new_style:
...@@ -251,6 +235,13 @@ class Runner(object): ...@@ -251,6 +235,13 @@ class Runner(object):
else: else:
cmd = " ".join([str(x) for x in [remote_module_path, async_jid, async_limit, async_module]]) cmd = " ".join([str(x) for x in [remote_module_path, async_jid, async_limit, async_module]])
if not shebang:
raise errors.AnsibleError("module is missing interpreter line")
cmd = shebang.replace("#!","") + " " + cmd
if tmp.find("tmp") != -1:
cmd = cmd + "; rm -rf %s > /tmp/del.log 2>&1" % tmp
cmd = cmd_mod + cmd
res = self._low_level_exec_command(conn, cmd, tmp, sudoable=True) res = self._low_level_exec_command(conn, cmd, tmp, sudoable=True)
return ReturnData(conn=conn, result=res) return ReturnData(conn=conn, result=res)
...@@ -429,19 +420,6 @@ class Runner(object): ...@@ -429,19 +420,6 @@ class Runner(object):
else: else:
result = self.action_plugins['async'].run(conn, tmp, module_name, module_args, inject) result = self.action_plugins['async'].run(conn, tmp, module_name, module_args, inject)
if result.is_successful() and 'daisychain' in result.result:
result2 = self._executor_internal_inner(host, result.result['daisychain'], result.result.get('daisychain_args', {}), inject, port, is_chained=True)
changed = False
if result.result.get('changed',False) or result2.result.get('changed',False):
changed = True
result.result.update(result2.result)
result.result['changed'] = changed
del result.result['daisychain']
if self.module_name != 'raw':
self._delete_remote_files(conn, tmp)
conn.close() conn.close()
if not result.comm_ok: if not result.comm_ok:
...@@ -576,7 +554,13 @@ class Runner(object): ...@@ -576,7 +554,13 @@ class Runner(object):
module_data = "\n".join(module_lines) module_data = "\n".join(module_lines)
self._transfer_str(conn, tmp, module_name, module_data) self._transfer_str(conn, tmp, module_name, module_data)
return (out_path, is_new_style)
lines = module_data.split("\n")
shebang = None
if lines[0].startswith("#!"):
shebang = lines[0]
return (out_path, is_new_style, shebang)
# ***************************************************** # *****************************************************
......
...@@ -40,7 +40,7 @@ class ActionModule(object): ...@@ -40,7 +40,7 @@ class ActionModule(object):
module_name = 'command' module_name = 'command'
module_args += " #USE_SHELL" module_args += " #USE_SHELL"
(module_path, is_new_style) = self.runner._copy_module(conn, tmp, module_name, module_args, inject) (module_path, is_new_style, shebang) = self.runner._copy_module(conn, tmp, module_name, module_args, inject)
self.runner._low_level_exec_command(conn, "chmod a+rx %s" % module_path, tmp) self.runner._low_level_exec_command(conn, "chmod a+rx %s" % module_path, tmp)
return self.runner._execute_module(conn, tmp, 'async_wrapper', module_args, return self.runner._execute_module(conn, tmp, 'async_wrapper', module_args,
......
...@@ -84,14 +84,13 @@ class ActionModule(object): ...@@ -84,14 +84,13 @@ class ActionModule(object):
# run the copy module # run the copy module
module_args = "%s src=%s" % (module_args, tmp_src) module_args = "%s src=%s" % (module_args, tmp_src)
return self.runner._execute_module(conn, tmp, 'copy', module_args, inject=inject).daisychain('file', module_args) return self.runner._execute_module(conn, tmp, 'copy', module_args, inject=inject)
else: else:
# no need to transfer the file, already correct md5, but still need to set src so the file module # no need to transfer the file, already correct md5, but still need to call
# does not freak out. It's just the basename of the file. # the file module in case we want to change attributes
tmp_src = tmp + os.path.basename(source) tmp_src = tmp + os.path.basename(source)
module_args = "%s src=%s" % (module_args, tmp_src) module_args = "%s src=%s" % (module_args, tmp_src)
result = dict(changed=False, md5sum=remote_md5, transferred=False) return self.runner._execute_module(conn, tmp, 'file', module_args, inject=inject)
return ReturnData(conn=conn, result=result).daisychain('file', module_args)
...@@ -80,8 +80,9 @@ class ActionModule(object): ...@@ -80,8 +80,9 @@ class ActionModule(object):
if self.runner.sudo and self.runner.sudo_user != 'root': if self.runner.sudo and self.runner.sudo_user != 'root':
self.runner._low_level_exec_command(conn, "chmod a+r %s" % xfered, self.runner._low_level_exec_command(conn, "chmod a+r %s" % xfered,
tmp) tmp)
# run the copy module, queue the file module
# run the copy module
module_args = "%s src=%s dest=%s" % (module_args, xfered, dest) module_args = "%s src=%s dest=%s" % (module_args, xfered, dest)
return self.runner._execute_module(conn, tmp, 'copy', module_args, inject=inject).daisychain('file', module_args) return self.runner._execute_module(conn, tmp, 'copy', module_args, inject=inject)
...@@ -53,10 +53,3 @@ class ReturnData(object): ...@@ -53,10 +53,3 @@ class ReturnData(object):
def is_successful(self): def is_successful(self):
return self.comm_ok and ('failed' not in self.result) and (self.result.get('rc',0) == 0) return self.comm_ok and ('failed' not in self.result) and (self.result.get('rc',0) == 0)
def daisychain(self, module_name, module_args):
''' request a module call follow this one '''
if self.is_successful():
self.result['daisychain'] = module_name
self.result['daisychain_args'] = module_args
return self
...@@ -83,7 +83,7 @@ def main(): ...@@ -83,7 +83,7 @@ def main():
# file not written yet? That means it is running # file not written yet? That means it is running
module.exit_json(results_file=log_path, ansible_job_id=jid, started=1) module.exit_json(results_file=log_path, ansible_job_id=jid, started=1)
else: else:
module_fail_json(ansible_job_id=jid, results_file=log_path, module.fail_json(ansible_job_id=jid, results_file=log_path,
msg="Could not parse job output: %s" % data) msg="Could not parse job output: %s" % data)
if not 'started' in data: if not 'started' in data:
......
...@@ -64,18 +64,19 @@ def main(): ...@@ -64,18 +64,19 @@ def main():
module = AnsibleModule( module = AnsibleModule(
# not checking because of daisy chain to file module # not checking because of daisy chain to file module
check_invalid_arguments = False,
argument_spec = dict( argument_spec = dict(
src=dict(required=True), src=dict(required=True),
dest=dict(required=True), dest=dict(required=True),
backup=dict(default=False, choices=BOOLEANS), backup=dict(default=False, choices=BOOLEANS),
) ),
add_file_common_args=True
) )
src = os.path.expanduser(module.params['src']) src = os.path.expanduser(module.params['src'])
dest = os.path.expanduser(module.params['dest']) dest = os.path.expanduser(module.params['dest'])
backup = module.boolean(module.params.get('backup', False)) backup = module.boolean(module.params.get('backup', False))
file_args = module.load_file_common_arguments(module.params)
if not os.path.exists(src): if not os.path.exists(src):
module.fail_json(msg="Source %s failed to transfer" % (src)) module.fail_json(msg="Source %s failed to transfer" % (src))
if not os.access(src, os.R_OK): if not os.access(src, os.R_OK):
...@@ -122,15 +123,16 @@ def main(): ...@@ -122,15 +123,16 @@ def main():
else: else:
changed = False changed = False
res_args = { res_args = dict(
'dest':dest, dest = dest, src = src, md5sum = md5sum_src, changed = changed
'src':src, )
'md5sum':md5sum_src,
'changed':changed
}
if backup_file: if backup_file:
res_args['backup_file'] = backup_file res_args['backup_file'] = backup_file
module.params['dest'] = dest
file_args = module.load_file_common_arguments(module.params)
res_args['changed'] = module.set_file_attributes_if_different(file_args, res_args['changed'])
module.exit_json(**res_args) module.exit_json(**res_args)
# this is magic, see lib/ansible/module_common.py # this is magic, see lib/ansible/module_common.py
......
...@@ -108,9 +108,7 @@ def url_do_get(module, url, dest): ...@@ -108,9 +108,7 @@ def url_do_get(module, url, dest):
module.params['path'] = actualdest module.params['path'] = actualdest
else: else:
actualdest = dest actualdest = dest
info['daisychain_args'] = module.params
info['daisychain_args']['state'] = 'file'
info['daisychain_args']['dest'] = actualdest
info['actualdest'] = actualdest info['actualdest'] = actualdest
request = urllib2.Request(url) request = urllib2.Request(url)
...@@ -177,12 +175,12 @@ def main(): ...@@ -177,12 +175,12 @@ def main():
module = AnsibleModule( module = AnsibleModule(
# not checking because of daisy chain to file module # not checking because of daisy chain to file module
check_invalid_arguments = False,
argument_spec = dict( argument_spec = dict(
url = dict(required=True), url = dict(required=True),
dest = dict(required=True), dest = dict(required=True),
thirsty = dict(default='no', choices=BOOLEANS) thirsty = dict(default='no', choices=BOOLEANS)
) ),
add_file_common_args=True
) )
url = module.params['url'] url = module.params['url']
...@@ -237,6 +235,12 @@ def main(): ...@@ -237,6 +235,12 @@ def main():
os.remove(tmpsrc) os.remove(tmpsrc)
# allow file attribute changes
module.params['path'] = dest
file_args = module.load_file_common_arguments(module.params)
file_args['path'] = dest
changed = module.set_file_attributes_if_different(file_args, changed)
# Mission complete # Mission complete
module.exit_json(url=url, dest=dest, src=tmpsrc, md5sum=md5sum_src, module.exit_json(url=url, dest=dest, src=tmpsrc, md5sum=md5sum_src,
changed=changed, msg=info.get('msg',''), changed=changed, msg=info.get('msg',''),
......
# this is a virtual module that is entirely implemented server side # this is a virtual module that is entirely implemented server side
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
module: template module: template
......
...@@ -181,7 +181,9 @@ class TestRunner(unittest.TestCase): ...@@ -181,7 +181,9 @@ class TestRunner(unittest.TestCase):
assert self._run('file', ['dest=' + filedemo, 'src=/dev/null', 'state=link'])['failed'] assert self._run('file', ['dest=' + filedemo, 'src=/dev/null', 'state=link'])['failed']
assert os.path.isfile(filedemo) assert os.path.isfile(filedemo)
assert self._run('file', ['dest=' + filedemo, 'mode=604', 'state=file'])['changed'] res = self._run('file', ['dest=' + filedemo, 'mode=604', 'state=file'])
print res
assert res['changed']
assert os.path.isfile(filedemo) and os.stat(filedemo).st_mode == 0100604 assert os.path.isfile(filedemo) and os.stat(filedemo).st_mode == 0100604
assert self._run('file', ['dest=' + filedemo, 'state=absent'])['changed'] assert self._run('file', ['dest=' + filedemo, 'state=absent'])['changed']
...@@ -271,6 +273,7 @@ class TestRunner(unittest.TestCase): ...@@ -271,6 +273,7 @@ class TestRunner(unittest.TestCase):
"src=%s" % input, "src=%s" % input,
"dest=%s" % output, "dest=%s" % output,
]) ])
print result
assert os.path.exists(output) assert os.path.exists(output)
out = file(output).read() out = file(output).read()
assert out.find("first") != -1 assert out.find("first") != -1
...@@ -283,4 +286,5 @@ class TestRunner(unittest.TestCase): ...@@ -283,4 +286,5 @@ class TestRunner(unittest.TestCase):
"src=%s" % input, "src=%s" % input,
"dest=%s" % output, "dest=%s" % output,
]) ])
print result
assert result['changed'] == False assert result['changed'] == False
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment