CORD-1025 run ansible_runner in a subprocess
Change-Id: I39b8c9e4b1941c73f5b7c7f8fdf7aff4553c8bb4
diff --git a/xos/synchronizers/base/ansible_helper.py b/xos/synchronizers/base/ansible_helper.py
index 3040a26..8b36de5 100644
--- a/xos/synchronizers/base/ansible_helper.py
+++ b/xos/synchronizers/base/ansible_helper.py
@@ -4,6 +4,7 @@
import tempfile
import os
import json
+import pickle
import pdb
import string
import random
@@ -49,41 +50,49 @@
return (opts, os.path.join(pathed_sys_dir,objname))
-def run_playbook(ansible_hosts, ansible_config, fqp, opts):#, q):
+def run_playbook(ansible_hosts, ansible_config, fqp, opts):
+ args = {"ansible_hosts": ansible_hosts,
+ "ansible_config": ansible_config,
+ "fqp": fqp,
+ "opts": opts}
+
+ keep_temp_files = getattr(Config(), "observer_keep_temp_files", False)
+
+ dir = tempfile.mkdtemp()
+ args_fn = None
+ result_fn = None
try:
- if ansible_config:
- os.environ["ANSIBLE_CONFIG"] = ansible_config
- else:
- try:
- del os.environ["ANSIBLE_CONFIG"]
- except KeyError:
- pass
+ logger.info("creating args file in %s" % dir)
- if ansible_hosts:
- os.environ["ANSIBLE_HOSTS"] = ansible_hosts
- else:
- try:
- del os.environ["ANSIBLE_HOSTS"]
- except KeyError:
- pass
+ args_fn = os.path.join(dir, "args")
+ result_fn = os.path.join(dir, "result")
- import ansible_runner
- reload(ansible_runner)
+ open(args_fn, "w").write(pickle.dumps(args))
- # Dropped support for observer_pretend - to be redone
- runner = ansible_runner.Runner(
- playbook=fqp,
- run_data=opts,
- host_file=ansible_hosts)
+ ansible_main_fn = os.path.join(os.path.dirname(__file__), "ansible_main.py")
- stats,aresults = runner.run()
- except Exception, e:
- logger.log_exc("Exception executing playbook",extra={'exception':str(e)})
+ os.system("python %s %s %s" % (ansible_main_fn, args_fn, result_fn))
+
+ result = pickle.loads(open(result_fn).read())
+
+ if hasattr(result, "exception"):
+ logger.log_error("Exception in playbook: %s" % result["exception"])
+
+ stats = result.get("stats", None)
+ aresults = result.get("aresults", None)
+ except:
+ logger.log_exc("Exception running ansible_main")
stats = None
aresults = None
+ finally:
+ if not keep_temp_files:
+ if args_fn and os.path.exists(args_fn):
+ os.remove(args_fn)
+ if result_fn and os.path.exists(result_fn):
+ os.remove(result_fn)
+ os.rmdir(dir)
- #q.put([stats,aresults])
- return (stats,aresults)
+ return (stats, aresults)
def run_template(name, opts, path='', expected_num=None, ansible_config=None, ansible_hosts=None, run_ansible_script=None, object=None):
global uglylock
@@ -114,7 +123,9 @@
stats,aresults = run_playbook(ansible_hosts,ansible_config,fqp,opts)
uglylock.release()
-
+
+ error_msg = []
+
output_file = fqp + '.out'
try:
if (aresults is None):
@@ -124,8 +135,6 @@
total_unreachable = 0
failed = 0
- error_msg = []
-
ofile = open(output_file, 'w')
for x in aresults:
@@ -174,11 +183,14 @@
raise ValueError('Ansible playbook failed.')
except ValueError,e:
- try:
- error = ' // '.join(error_msg)
- except:
- pass
- raise Exception(error)
+ if error_msg:
+ try:
+ error = ' // '.join(error_msg)
+ except:
+ error = "failed to join error_msg"
+ raise Exception(error)
+ else:
+ raise
diff --git a/xos/synchronizers/base/ansible_main.py b/xos/synchronizers/base/ansible_main.py
new file mode 100644
index 0000000..2df23b9
--- /dev/null
+++ b/xos/synchronizers/base/ansible_main.py
@@ -0,0 +1,57 @@
+import os
+import pickle
+import sys
+#import json
+import traceback
+
+sys.path.append("/opt/xos")
+
+def run_playbook(ansible_hosts, ansible_config, fqp, opts):
+ try:
+ if ansible_config:
+ os.environ["ANSIBLE_CONFIG"] = ansible_config
+ else:
+ try:
+ del os.environ["ANSIBLE_CONFIG"]
+ except KeyError:
+ pass
+
+ if ansible_hosts:
+ os.environ["ANSIBLE_HOSTS"] = ansible_hosts
+ else:
+ try:
+ del os.environ["ANSIBLE_HOSTS"]
+ except KeyError:
+ pass
+
+ import ansible_runner
+ reload(ansible_runner)
+
+ # Dropped support for observer_pretend - to be redone
+ runner = ansible_runner.Runner(
+ playbook=fqp,
+ run_data=opts,
+ host_file=ansible_hosts)
+
+ stats,aresults = runner.run()
+ except Exception, e:
+ return {"stats": None, "aresults": None, "exception": traceback.format_exc()}
+
+ return {"stats": stats, "aresults": aresults}
+
+def main():
+ input_fn = sys.argv[1]
+ result_fn = sys.argv[2]
+
+ args = pickle.loads(open(input_fn).read())
+ ansible_hosts = args["ansible_hosts"]
+ ansible_config = args["ansible_config"]
+ fqp = args["fqp"]
+ opts = args["opts"]
+
+ result = run_playbook(ansible_hosts, ansible_config, fqp, opts)
+
+ open(result_fn, "w").write(pickle.dumps(result))
+
+if __name__ == "__main__":
+ main()
diff --git a/xos/synchronizers/new_base/ansible_helper.py b/xos/synchronizers/new_base/ansible_helper.py
index 7c914d8..8b36de5 100644
--- a/xos/synchronizers/new_base/ansible_helper.py
+++ b/xos/synchronizers/new_base/ansible_helper.py
@@ -1,14 +1,17 @@
#!/usr/bin/env python
+
import jinja2
import tempfile
import os
import json
+import pickle
import pdb
import string
import random
import re
import traceback
import subprocess
+import threading
from xos.config import Config, XOS_DIR
from xos.logger import observer_logger as logger
from multiprocessing import Process, Queue
@@ -47,42 +50,60 @@
return (opts, os.path.join(pathed_sys_dir,objname))
-def run_playbook(ansible_hosts, ansible_config, fqp, opts, q):
+def run_playbook(ansible_hosts, ansible_config, fqp, opts):
+ args = {"ansible_hosts": ansible_hosts,
+ "ansible_config": ansible_config,
+ "fqp": fqp,
+ "opts": opts}
+
+ keep_temp_files = getattr(Config(), "observer_keep_temp_files", False)
+
+ dir = tempfile.mkdtemp()
+ args_fn = None
+ result_fn = None
try:
- if ansible_config:
- os.environ["ANSIBLE_CONFIG"] = ansible_config
- else:
- try:
- del os.environ["ANSIBLE_CONFIG"]
- except KeyError:
- pass
+ logger.info("creating args file in %s" % dir)
- if ansible_hosts:
- os.environ["ANSIBLE_HOSTS"] = ansible_hosts
- else:
- try:
- del os.environ["ANSIBLE_HOSTS"]
- except KeyError:
- pass
+ args_fn = os.path.join(dir, "args")
+ result_fn = os.path.join(dir, "result")
- import ansible_runner
- reload(ansible_runner)
+ open(args_fn, "w").write(pickle.dumps(args))
- # Dropped support for observer_pretend - to be redone
- runner = ansible_runner.Runner(
- playbook=fqp,
- run_data=opts,
- host_file=ansible_hosts)
+ ansible_main_fn = os.path.join(os.path.dirname(__file__), "ansible_main.py")
- stats,aresults = runner.run()
- except Exception, e:
- logger.log_exc("Exception executing playbook",extra={'exception':str(e)})
+ os.system("python %s %s %s" % (ansible_main_fn, args_fn, result_fn))
+
+ result = pickle.loads(open(result_fn).read())
+
+ if hasattr(result, "exception"):
+ logger.log_error("Exception in playbook: %s" % result["exception"])
+
+ stats = result.get("stats", None)
+ aresults = result.get("aresults", None)
+ except:
+ logger.log_exc("Exception running ansible_main")
stats = None
aresults = None
+ finally:
+ if not keep_temp_files:
+ if args_fn and os.path.exists(args_fn):
+ os.remove(args_fn)
+ if result_fn and os.path.exists(result_fn):
+ os.remove(result_fn)
+ os.rmdir(dir)
- q.put([stats,aresults])
+ return (stats, aresults)
def run_template(name, opts, path='', expected_num=None, ansible_config=None, ansible_hosts=None, run_ansible_script=None, object=None):
+ global uglylock
+ try:
+ if (uglylock):
+ pass
+ except NameError:
+ uglylock = threading.Lock()
+
+ uglylock.acquire()
+
template = os_template_env.get_template(name)
buffer = template.render(opts)
@@ -92,11 +113,18 @@
f.write(buffer)
f.flush()
+ """
q = Queue()
p = Process(target=run_playbook, args=(ansible_hosts, ansible_config, fqp, opts, q,))
p.start()
stats,aresults = q.get()
p.join()
+ """
+ stats,aresults = run_playbook(ansible_hosts,ansible_config,fqp,opts)
+
+ uglylock.release()
+
+ error_msg = []
output_file = fqp + '.out'
try:
@@ -107,8 +135,6 @@
total_unreachable = 0
failed = 0
- error_msg = []
-
ofile = open(output_file, 'w')
for x in aresults:
@@ -157,11 +183,14 @@
raise ValueError('Ansible playbook failed.')
except ValueError,e:
- try:
- error = ' // '.join(error_msg)
- except:
- pass
- raise Exception(error)
+ if error_msg:
+ try:
+ error = ' // '.join(error_msg)
+ except:
+ error = "failed to join error_msg"
+ raise Exception(error)
+ else:
+ raise
diff --git a/xos/synchronizers/new_base/ansible_main.py b/xos/synchronizers/new_base/ansible_main.py
new file mode 100644
index 0000000..2df23b9
--- /dev/null
+++ b/xos/synchronizers/new_base/ansible_main.py
@@ -0,0 +1,57 @@
+import os
+import pickle
+import sys
+#import json
+import traceback
+
+sys.path.append("/opt/xos")
+
+def run_playbook(ansible_hosts, ansible_config, fqp, opts):
+ try:
+ if ansible_config:
+ os.environ["ANSIBLE_CONFIG"] = ansible_config
+ else:
+ try:
+ del os.environ["ANSIBLE_CONFIG"]
+ except KeyError:
+ pass
+
+ if ansible_hosts:
+ os.environ["ANSIBLE_HOSTS"] = ansible_hosts
+ else:
+ try:
+ del os.environ["ANSIBLE_HOSTS"]
+ except KeyError:
+ pass
+
+ import ansible_runner
+ reload(ansible_runner)
+
+ # Dropped support for observer_pretend - to be redone
+ runner = ansible_runner.Runner(
+ playbook=fqp,
+ run_data=opts,
+ host_file=ansible_hosts)
+
+ stats,aresults = runner.run()
+ except Exception, e:
+ return {"stats": None, "aresults": None, "exception": traceback.format_exc()}
+
+ return {"stats": stats, "aresults": aresults}
+
+def main():
+ input_fn = sys.argv[1]
+ result_fn = sys.argv[2]
+
+ args = pickle.loads(open(input_fn).read())
+ ansible_hosts = args["ansible_hosts"]
+ ansible_config = args["ansible_config"]
+ fqp = args["fqp"]
+ opts = args["opts"]
+
+ result = run_playbook(ansible_hosts, ansible_config, fqp, opts)
+
+ open(result_fn, "w").write(pickle.dumps(result))
+
+if __name__ == "__main__":
+ main()