run_temlpate_ssh(); report ValueError message; use subprocess.Popen instead of os.popen
diff --git a/xos/openstack_observer/ansible.py b/xos/openstack_observer/ansible.py
index 4466cb3..9858f63 100644
--- a/xos/openstack_observer/ansible.py
+++ b/xos/openstack_observer/ansible.py
@@ -7,6 +7,8 @@
 import string
 import random
 import re
+import traceback
+import subprocess
 from xos.config import Config, XOS_DIR
 
 try:
@@ -47,7 +49,7 @@
 def shellquote(s):
     return "'" + s.replace("'", "'\\''") + "'"
 
-def run_template(name, opts,path='', expected_num=None):
+def run_template(name, opts,path='', expected_num=None, ansible_config=None, ansible_hosts=None, run_ansible_script=None):
     template = os_template_env.get_template(name)
     buffer = template.render(opts)
 
@@ -64,25 +66,35 @@
     f.write(buffer)
     f.flush()
 
-    
+    # This is messy -- there's no way to specify ansible config file from
+    # the command line, but we can specify it using the environment.
+    env = os.environ.copy()
+    if ansible_config:
+       env["ANSIBLE_CONFIG"] = ansible_config
+    if ansible_hosts:
+       env["ANSIBLE_HOSTS"] = ansible_hosts
+
     if (not Config().observer_pretend):
-        run = os.popen(XOS_DIR + '/observer/run_ansible %s'%shellquote(fqp))
+        if not run_ansible_script:
+            run_ansible_script = os.path.join(XOS_DIR, "/observer/run_ansible")
+
+        #run = os.popen(XOS_DIR + '/observer/run_ansible %s'%shellquote(fqp), env=env)
+        run = subprocess.Popen("%s %s" % (run_ansible_script, shellquote(fqp)), shell=True, stdout=subprocess.PIPE, env=env).stdout
         msg = run.read()
         status = run.close()
 
         
     else:
         msg = open(fqp+'.out').read()
-        
+
     try:
         ok_results = parse_output(msg)
-        if (len(ok_results) != expected_num):
-            raise ValueError('Unexpected num')
+        if (expected_num is not None) and (len(ok_results) != expected_num):
+            raise ValueError('Unexpected num %s!=%d' % (str(expected_num), len(ok_results)) )
     except ValueError,e:
-        all_fatal = re.findall(r'^msg: (.*)',msg,re.MULTILINE)
+        all_fatal = [e.message] + re.findall(r'^msg: (.*)',msg,re.MULTILINE)
         all_fatal2 = re.findall(r'^ERROR: (.*)',msg,re.MULTILINE)
 
-
         all_fatal.extend(all_fatal2)
         try:
             error = ' // '.join(all_fatal)
@@ -92,6 +104,44 @@
 
     return ok_results
 
+def run_template_ssh(name, opts, path='', expected_num=None):
+    instance_id = opts["instance_id"]
+    sliver_name = opts["sliver_name"]
+    hostname = opts["hostname"]
+    private_key = opts["private_key"]
+
+    (private_key_handle, private_key_pathname) = tempfile.mkstemp()
+    (config_handle, config_pathname) = tempfile.mkstemp()
+    (hosts_handle, hosts_pathname) = tempfile.mkstemp()
+
+    try:
+        proxy_command = "ProxyCommand ssh -q -i %s %s@%s" % (private_key_pathname, instance_id, hostname)
+
+        os.write(private_key_handle, private_key)
+        os.close(private_key_handle)
+
+        os.write(config_handle, "[ssh_connection]\n")
+        os.write(config_handle, 'ssh_args = -o "%s"\n' % proxy_command)
+        os.write(config_handle, 'scp_if_ssh = True\n')
+        os.close(config_handle)
+
+        os.write(hosts_handle, "[%s]\n" % sliver_name)
+        os.write(hosts_handle, "%s ansible_ssh_private_key_file=%s\n" % (hostname, private_key_pathname))
+        os.close(hosts_handle)
+
+        print "ANSIBLE_CONFIG=%s" % config_pathname
+        print "ANSIBLE_HOSTS=%s" % hosts_pathname
+
+        return run_template(name, opts, path, expected_num, ansible_config = config_pathname, ansible_hosts = hosts_pathname, run_ansible_script="/opt/xos/observer/run_ansible_verbose")
+
+    finally:
+        #os.remove(private_key_pathname)
+        #os.remove(config_pathname)
+        #os.remove(hosts_pathname)
+        pass
+
+
+
 def main():
     run_template('ansible/sync_user_deployments.yaml',{ "endpoint" : "http://172.31.38.128:5000/v2.0/",
              "name" : "Sapan Bhatia",