diff options
author | David Shrewsbury <shrewsbury.dave@gmail.com> | 2016-06-23 17:14:59 -0400 |
---|---|---|
committer | James Cammarata <jimi@sngx.net> | 2016-07-07 11:31:11 -0500 |
commit | c8d68860079083ecf71da6d70b2dffceaaf54a6c (patch) | |
tree | 8369b92241a7142199221918a88cbe6fa47ac24c | |
parent | 9bcb552872b0352d02a3284e554c59806b1f8ec0 (diff) | |
download | ansible-modules-core-c8d68860079083ecf71da6d70b2dffceaaf54a6c.tar.gz |
Use os.rename() in async_wrapper
Because the async_status module will read from the same file that
the async_wrapper module is writing, it's possible that the file
may not be fully synced during a read, causing spurious failures.
Use a temp file to do an atomic operation on the file. We can't
use atomic_move() here as that doesn't work properly under async.
Also, let's not read concurrently from the same file the subprocess
is writing to. Instead, capture stdout/stderr via PIPE and write to
the file to avoid nasty races.
(cherry picked from commit 4e239f6ce0d8ed96d734ef6ca75fa745c3925045)
-rw-r--r-- | utilities/logic/async_wrapper.py | 17 |
1 files changed, 12 insertions, 5 deletions
diff --git a/utilities/logic/async_wrapper.py b/utilities/logic/async_wrapper.py index ecdaf28e..284838af 100644 --- a/utilities/logic/async_wrapper.py +++ b/utilities/logic/async_wrapper.py @@ -73,19 +73,23 @@ def daemonize_self(): def _run_module(wrapped_cmd, jid, job_path): - jobfile = open(job_path, "w") + tmp_job_path = job_path + ".tmp" + jobfile = open(tmp_job_path, "w") jobfile.write(json.dumps({ "started" : 1, "ansible_job_id" : jid })) jobfile.close() - jobfile = open(job_path, "w") + os.rename(tmp_job_path, job_path) + jobfile = open(tmp_job_path, "w") result = {} outdata = '' try: cmd = shlex.split(wrapped_cmd) - script = subprocess.Popen(cmd, shell=False, stdin=None, stdout=jobfile, stderr=jobfile) - script.communicate() - outdata = file(job_path).read() + script = subprocess.Popen(cmd, shell=False, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + (outdata, stderr) = script.communicate() result = json.loads(outdata) + if stderr: + result['stderr'] = stderr + jobfile.write(json.dumps(result)) except (OSError, IOError), e: result = { @@ -95,6 +99,7 @@ def _run_module(wrapped_cmd, jid, job_path): } result['ansible_job_id'] = jid jobfile.write(json.dumps(result)) + except: result = { "failed" : 1, @@ -104,7 +109,9 @@ def _run_module(wrapped_cmd, jid, job_path): } result['ansible_job_id'] = jid jobfile.write(json.dumps(result)) + jobfile.close() + os.rename(tmp_job_path, job_path) #################### |