S.Çağlar Onur | 3e92b4d | 2015-02-09 13:34:11 -0500 | [diff] [blame] | 1 | #!/usr/bin/env python |
Sapan Bhatia | 88181f2 | 2014-11-19 15:25:38 -0500 | [diff] [blame] | 2 | import jinja2 |
| 3 | import tempfile |
| 4 | import os |
| 5 | import json |
Sapan | 810240c | 2014-12-02 23:50:37 -0500 | [diff] [blame] | 6 | import pdb |
| 7 | import string |
| 8 | import random |
Sapan Bhatia | 58da661 | 2015-01-23 16:15:37 +0000 | [diff] [blame] | 9 | import re |
Scott Baker | dec77b5 | 2015-05-04 18:20:14 -0700 | [diff] [blame] | 10 | import traceback |
| 11 | import subprocess |
Sapan Bhatia | 84cdde7 | 2015-04-15 13:31:12 -0400 | [diff] [blame] | 12 | from xos.config import Config, XOS_DIR |
Scott Baker | 7069c16 | 2015-02-04 16:59:45 -0800 | [diff] [blame] | 13 | |
Sapan Bhatia | 88181f2 | 2014-11-19 15:25:38 -0500 | [diff] [blame] | 14 | try: |
| 15 | step_dir = Config().observer_steps_dir |
Sapan | 810240c | 2014-12-02 23:50:37 -0500 | [diff] [blame] | 16 | sys_dir = Config().observer_sys_dir |
Sapan Bhatia | 88181f2 | 2014-11-19 15:25:38 -0500 | [diff] [blame] | 17 | except: |
Scott Baker | 7069c16 | 2015-02-04 16:59:45 -0800 | [diff] [blame] | 18 | step_dir = XOS_DIR + '/observer/steps' |
Sapan | 810240c | 2014-12-02 23:50:37 -0500 | [diff] [blame] | 19 | sys_dir = '/opt/opencloud' |
Sapan Bhatia | 88181f2 | 2014-11-19 15:25:38 -0500 | [diff] [blame] | 20 | |
| 21 | os_template_loader = jinja2.FileSystemLoader( searchpath=step_dir) |
| 22 | os_template_env = jinja2.Environment(loader=os_template_loader) |
| 23 | |
| 24 | def parse_output(msg): |
| 25 | lines = msg.splitlines() |
| 26 | results = [] |
| 27 | print msg |
| 28 | |
| 29 | for l in lines: |
Sapan | 810240c | 2014-12-02 23:50:37 -0500 | [diff] [blame] | 30 | magic_str = 'ok: [127.0.0.1] => ' |
| 31 | magic_str2 = 'changed: [127.0.0.1] => ' |
Sapan Bhatia | 88181f2 | 2014-11-19 15:25:38 -0500 | [diff] [blame] | 32 | if (l.startswith(magic_str)): |
Sapan | 810240c | 2014-12-02 23:50:37 -0500 | [diff] [blame] | 33 | w = len(magic_str) |
| 34 | str = l[w:] |
| 35 | d = json.loads(str) |
| 36 | results.append(d) |
| 37 | elif (l.startswith(magic_str2)): |
| 38 | w = len(magic_str2) |
| 39 | str = l[w:] |
| 40 | d = json.loads(str) |
| 41 | results.append(d) |
Sapan Bhatia | 88181f2 | 2014-11-19 15:25:38 -0500 | [diff] [blame] | 42 | |
| 43 | |
| 44 | return results |
Sapan | 810240c | 2014-12-02 23:50:37 -0500 | [diff] [blame] | 45 | |
| 46 | def id_generator(size=6, chars=string.ascii_uppercase + string.digits): |
| 47 | return ''.join(random.choice(chars) for _ in range(size)) |
| 48 | |
Sapan Bhatia | 58da661 | 2015-01-23 16:15:37 +0000 | [diff] [blame] | 49 | def shellquote(s): |
| 50 | return "'" + s.replace("'", "'\\''") + "'" |
| 51 | |
Scott Baker | dec77b5 | 2015-05-04 18:20:14 -0700 | [diff] [blame] | 52 | def run_template(name, opts,path='', expected_num=None, ansible_config=None, ansible_hosts=None, run_ansible_script=None): |
Sapan Bhatia | 88181f2 | 2014-11-19 15:25:38 -0500 | [diff] [blame] | 53 | template = os_template_env.get_template(name) |
| 54 | buffer = template.render(opts) |
Sapan | 810240c | 2014-12-02 23:50:37 -0500 | [diff] [blame] | 55 | |
Sapan | 810240c | 2014-12-02 23:50:37 -0500 | [diff] [blame] | 56 | try: |
| 57 | objname = opts['ansible_tag'] |
| 58 | except: |
| 59 | objname= id_generator() |
Sapan Bhatia | 58da661 | 2015-01-23 16:15:37 +0000 | [diff] [blame] | 60 | |
Sapan | 810240c | 2014-12-02 23:50:37 -0500 | [diff] [blame] | 61 | os.system('mkdir -p %s'%'/'.join([sys_dir,path])) |
| 62 | fqp = '/'.join([sys_dir,path,objname]) |
| 63 | |
Sapan Bhatia | 6d6b76c | 2015-03-13 18:43:46 -0400 | [diff] [blame] | 64 | |
Sapan | 810240c | 2014-12-02 23:50:37 -0500 | [diff] [blame] | 65 | f = open(fqp,'w') |
Sapan Bhatia | 88181f2 | 2014-11-19 15:25:38 -0500 | [diff] [blame] | 66 | f.write(buffer) |
| 67 | f.flush() |
Sapan | 810240c | 2014-12-02 23:50:37 -0500 | [diff] [blame] | 68 | |
Scott Baker | dec77b5 | 2015-05-04 18:20:14 -0700 | [diff] [blame] | 69 | # This is messy -- there's no way to specify ansible config file from |
| 70 | # the command line, but we can specify it using the environment. |
| 71 | env = os.environ.copy() |
| 72 | if ansible_config: |
| 73 | env["ANSIBLE_CONFIG"] = ansible_config |
| 74 | if ansible_hosts: |
| 75 | env["ANSIBLE_HOSTS"] = ansible_hosts |
| 76 | |
Sapan Bhatia | c7a09c8 | 2015-04-15 13:31:37 -0400 | [diff] [blame] | 77 | if (not Config().observer_pretend): |
Scott Baker | dec77b5 | 2015-05-04 18:20:14 -0700 | [diff] [blame] | 78 | if not run_ansible_script: |
Scott Baker | 2f8608b | 2015-05-04 18:30:09 -0700 | [diff] [blame] | 79 | run_ansible_script = os.path.join(XOS_DIR, "observer/run_ansible") |
Scott Baker | dec77b5 | 2015-05-04 18:20:14 -0700 | [diff] [blame] | 80 | |
| 81 | #run = os.popen(XOS_DIR + '/observer/run_ansible %s'%shellquote(fqp), env=env) |
| 82 | run = subprocess.Popen("%s %s" % (run_ansible_script, shellquote(fqp)), shell=True, stdout=subprocess.PIPE, env=env).stdout |
Sapan Bhatia | 01dd5d2 | 2015-03-13 18:51:02 -0400 | [diff] [blame] | 83 | msg = run.read() |
| 84 | status = run.close() |
Sapan Bhatia | 88181f2 | 2014-11-19 15:25:38 -0500 | [diff] [blame] | 85 | |
Sapan Bhatia | 01dd5d2 | 2015-03-13 18:51:02 -0400 | [diff] [blame] | 86 | |
| 87 | else: |
| 88 | msg = open(fqp+'.out').read() |
Scott Baker | dec77b5 | 2015-05-04 18:20:14 -0700 | [diff] [blame] | 89 | |
Sapan Bhatia | 6d6b76c | 2015-03-13 18:43:46 -0400 | [diff] [blame] | 90 | try: |
| 91 | ok_results = parse_output(msg) |
Scott Baker | dec77b5 | 2015-05-04 18:20:14 -0700 | [diff] [blame] | 92 | if (expected_num is not None) and (len(ok_results) != expected_num): |
| 93 | raise ValueError('Unexpected num %s!=%d' % (str(expected_num), len(ok_results)) ) |
Sapan Bhatia | 6d6b76c | 2015-03-13 18:43:46 -0400 | [diff] [blame] | 94 | except ValueError,e: |
Scott Baker | dec77b5 | 2015-05-04 18:20:14 -0700 | [diff] [blame] | 95 | all_fatal = [e.message] + re.findall(r'^msg: (.*)',msg,re.MULTILINE) |
Sapan Bhatia | 6d6b76c | 2015-03-13 18:43:46 -0400 | [diff] [blame] | 96 | all_fatal2 = re.findall(r'^ERROR: (.*)',msg,re.MULTILINE) |
Sapan Bhatia | 01dd5d2 | 2015-03-13 18:51:02 -0400 | [diff] [blame] | 97 | |
Sapan Bhatia | 01dd5d2 | 2015-03-13 18:51:02 -0400 | [diff] [blame] | 98 | all_fatal.extend(all_fatal2) |
Sapan Bhatia | b2cef88 | 2014-12-21 02:33:13 -0500 | [diff] [blame] | 99 | try: |
Sapan Bhatia | 6d6b76c | 2015-03-13 18:43:46 -0400 | [diff] [blame] | 100 | error = ' // '.join(all_fatal) |
| 101 | except: |
| 102 | pass |
| 103 | raise Exception(error) |
Sapan Bhatia | b2cef88 | 2014-12-21 02:33:13 -0500 | [diff] [blame] | 104 | |
Sapan Bhatia | 88181f2 | 2014-11-19 15:25:38 -0500 | [diff] [blame] | 105 | return ok_results |
| 106 | |
Scott Baker | dec77b5 | 2015-05-04 18:20:14 -0700 | [diff] [blame] | 107 | def run_template_ssh(name, opts, path='', expected_num=None): |
| 108 | instance_id = opts["instance_id"] |
| 109 | sliver_name = opts["sliver_name"] |
| 110 | hostname = opts["hostname"] |
| 111 | private_key = opts["private_key"] |
| 112 | |
| 113 | (private_key_handle, private_key_pathname) = tempfile.mkstemp() |
| 114 | (config_handle, config_pathname) = tempfile.mkstemp() |
| 115 | (hosts_handle, hosts_pathname) = tempfile.mkstemp() |
| 116 | |
| 117 | try: |
Scott Baker | f16ed22 | 2015-05-06 15:47:15 -0700 | [diff] [blame] | 118 | proxy_command = "ProxyCommand ssh -q -i %s -o StrictHostKeyChecking=no %s@%s" % (private_key_pathname, instance_id, hostname) |
Scott Baker | dec77b5 | 2015-05-04 18:20:14 -0700 | [diff] [blame] | 119 | |
| 120 | os.write(private_key_handle, private_key) |
| 121 | os.close(private_key_handle) |
| 122 | |
| 123 | os.write(config_handle, "[ssh_connection]\n") |
Scott Baker | f16ed22 | 2015-05-06 15:47:15 -0700 | [diff] [blame] | 124 | os.write(config_handle, 'ssh_args = -o "%s" -o StrictHostKeyChecking=no\n' % proxy_command) |
Scott Baker | dec77b5 | 2015-05-04 18:20:14 -0700 | [diff] [blame] | 125 | os.write(config_handle, 'scp_if_ssh = True\n') |
| 126 | os.close(config_handle) |
| 127 | |
| 128 | os.write(hosts_handle, "[%s]\n" % sliver_name) |
| 129 | os.write(hosts_handle, "%s ansible_ssh_private_key_file=%s\n" % (hostname, private_key_pathname)) |
| 130 | os.close(hosts_handle) |
| 131 | |
| 132 | print "ANSIBLE_CONFIG=%s" % config_pathname |
| 133 | print "ANSIBLE_HOSTS=%s" % hosts_pathname |
| 134 | |
| 135 | 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") |
| 136 | |
| 137 | finally: |
| 138 | #os.remove(private_key_pathname) |
| 139 | #os.remove(config_pathname) |
| 140 | #os.remove(hosts_pathname) |
| 141 | pass |
| 142 | |
| 143 | |
| 144 | |
Sapan Bhatia | 88181f2 | 2014-11-19 15:25:38 -0500 | [diff] [blame] | 145 | def main(): |
Sapan | 810240c | 2014-12-02 23:50:37 -0500 | [diff] [blame] | 146 | run_template('ansible/sync_user_deployments.yaml',{ "endpoint" : "http://172.31.38.128:5000/v2.0/", |
| 147 | "name" : "Sapan Bhatia", |
| 148 | "email": "gwsapan@gmail.com", |
| 149 | "password": "foobar", |
| 150 | "admin_user":"admin", |
| 151 | "admin_password":"6a789bf69dd647e2", |
| 152 | "admin_tenant":"admin", |
| 153 | "tenant":"demo", |
| 154 | "roles":['user','admin'] }) |