├── .idea
└── vcs.xml
├── README.md
├── ansible_playbooks
└── test.yml
├── app.py
├── environment.py
├── handlers
├── __init__.py
└── ansible_async.py
├── libs
├── __init__.py
├── my_ansible_api.py
└── utils.py
├── logconfig
├── __init__.py
└── logconfig.py
├── requirements
└── requirements.txt
├── settings.py
└── urls.py
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 简介
2 | ---
3 |
4 | 基于Ansible2.0 开发一个异步高效的API系统, 供其他系统调用。
5 |
6 | # 组件
7 | ---
8 |
9 | + Ansible 注意版本2.0
10 | + Tornado 异步就靠他了
11 | + MongoDB 数据存储
12 |
13 | # 布局
14 | ---
15 |
16 | + handlers
17 |
18 | tornado handlers 目录, 当import envronment 模块时,
19 | 这个目录下面的所有文件都将加入到PYTHONPATH环境变量.
20 |
21 |
22 | + libs
23 |
24 | 存储Python包的目录,那些不是Tornado request handlers的模块文件都放在这里
25 | 这个目录下面的所有文件都将加入到PYTHONPATH环境变量.
26 |
27 | + logconfig
28 |
29 | python logging的配置文件存放目录, 具体可以参考python logging官方说明,
30 | 这个包主要包含一个initalize_logging的方法,用此方法可以实例华一个真正的logger实例
31 | 在settings.py 文件用此来配置日志
32 |
33 | 注意root logger在settings.py中就已经设置好了, app中仅需要调用他的子logger即可使用
34 | 具体方法如下:
35 | ```
36 | #!python
37 | import logging
38 | logger = logging.getLogger('five.' + __name__)
39 | ```
40 |
41 | + requirements
42 |
43 | pip 的requirements文件存放目录,总共分成3类,
44 |
45 | 1. common.txt 开发和生产环境都需要的包
46 | 2. devolop.txt 开发环境依赖的包
47 | 3. production.txt 生产环境依赖的包
48 |
49 | + environment.py
50 |
51 | 修改Python运行时的PYTHONPATH环境变量,这个模块会在settings.py的顶层被导入,以确保handlers和libs下的模块能被python找到。
52 |
53 | + app.py
54 |
55 | Tornado app 入口模块, 用于启动 Tornado Server.
56 |
57 | + settints.py
58 |
59 | app 配置模块
60 |
61 | + urls.py
62 |
63 | app 路由模块
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/ansible_playbooks/test.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - hosts: 192.168.10.148
3 | tasks:
4 | - name: test
5 | shell: time ls
6 |
7 | - name: sleep 2 seconds
8 | shell: sleep 2
9 |
--------------------------------------------------------------------------------
/app.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import tornado.httpserver
4 | import tornado.ioloop
5 | import tornado.web
6 | from tornado.options import options
7 |
8 | from settings import settings
9 | from urls import url_patterns
10 |
11 |
12 | class TornadoBoilerplate(tornado.web.Application):
13 | def __init__(self):
14 | tornado.web.Application.__init__(self, url_patterns, **settings)
15 |
16 |
17 | def main():
18 | app = TornadoBoilerplate()
19 | http_server = tornado.httpserver.HTTPServer(app)
20 | http_server.listen(options.port)
21 | tornado.ioloop.IOLoop.instance().start()
22 |
23 | if __name__ == "__main__":
24 | main()
--------------------------------------------------------------------------------
/environment.py:
--------------------------------------------------------------------------------
1 | # Add the project's directories to Python's site-packages path.
2 |
3 | import os
4 | import site
5 | import sys
6 |
7 | ROOT = os.path.dirname(os.path.abspath(__file__))
8 | path = lambda *a: os.path.join(ROOT, *a)
9 |
10 | prev_sys_path = list(sys.path)
11 |
12 | site.addsitedir(path('handlers'))
13 | site.addsitedir(path('libs'))
14 | if os.path.exists(path('vendor')):
15 | for directory in os.listdir(path('vendor')):
16 | full_path = path('vendor/%s' % directory)
17 | if os.path.isdir(full_path):
18 | site.addsitedir(full_path)
19 |
20 | # Move the new items to the front of sys.path. (via virtualenv)
21 | new_sys_path = []
22 | for item in list(sys.path):
23 | if item not in prev_sys_path:
24 | new_sys_path.append(item)
25 | sys.path.remove(item)
26 | sys.path[:0] = new_sys_path
27 |
28 |
--------------------------------------------------------------------------------
/handlers/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yumaojun03/ansible_async_api/c968d42173b51151b3a78abe8921eddc039bdc21/handlers/__init__.py
--------------------------------------------------------------------------------
/handlers/ansible_async.py:
--------------------------------------------------------------------------------
1 | # -*- coding:utf-8 -*-
2 | from __future__ import unicode_literals
3 |
4 | import json
5 |
6 | import logging
7 | from tornado import gen
8 | from tornado.web import HTTPError
9 | from tornado.web import RequestHandler, asynchronous
10 | from tornado.concurrent import run_on_executor
11 | from concurrent.futures import ThreadPoolExecutor
12 |
13 |
14 | from libs.my_ansible_api import Ad_Hoc, MyPlaybook
15 | from multiprocessing import cpu_count
16 |
17 | logger = logging.getLogger('tornado.app')
18 |
19 |
20 | class MainHandler(RequestHandler):
21 | def get(self):
22 | self.write("Hello, world")
23 |
24 |
25 | class CommandHandler(RequestHandler):
26 | executor = ThreadPoolExecutor(cpu_count())
27 |
28 | @asynchronous
29 | @gen.coroutine
30 | def post(self):
31 | try:
32 | data = json.loads(self.request.body)
33 | except ValueError as e:
34 | raise HTTPError(400, e.message)
35 | logger.debug("input data: %s" % data)
36 | response = yield self.exec_command(data.get("resource"), data.get("command"))
37 | self.write(str(response))
38 | self.finish()
39 |
40 | @run_on_executor
41 | def exec_command(self, resource, command):
42 | """
43 | use ansible shell module to execute command on inventory.
44 |
45 | Args:
46 | resource: inventory resource, see Resource Class
47 | command: which command you want to execute
48 | Returns:
49 | AnsibleReuslt: AnsibleResult instance, contain the all ansible return information.
50 | """
51 | res = Ad_Hoc(resource)
52 | result = res.run(command, 'shell')
53 | return result.result_deal
54 |
55 |
56 | class AdHocHandler(RequestHandler):
57 | executor = ThreadPoolExecutor(cpu_count())
58 |
59 | @asynchronous
60 | @gen.coroutine
61 | def post(self):
62 | try:
63 | data = json.loads(self.request.body)
64 | except ValueError as e:
65 | raise HTTPError(400, reason=e.message)
66 | logger.debug("input data: %s" % data)
67 | resource, module_name, module_arg = data.get("resource"), data.get("module_name"), data.get("module_arg")
68 | if not(resource and module_name and module_arg):
69 | raise HTTPError(400, reason="resource and module_name and module_arg are required.")
70 |
71 | response = yield self.ad_hoc(resource, module_name, module_arg)
72 | self.write(str(response))
73 | self.finish()
74 |
75 | @run_on_executor
76 | def ad_hoc(self, resource, module_name, module_arg):
77 | """
78 | 执行ansible hoc-ad
79 |
80 | Args:
81 | resource: ditto
82 | module_name: ditto
83 | module_arg: ditto
84 | """
85 | res = Ad_Hoc(resource)
86 | result = res.run(module_arg, module_name)
87 | return result.result_deal
88 |
89 |
90 | class PlaybookHandler(RequestHandler):
91 | executor = ThreadPoolExecutor(cpu_count())
92 |
93 | @asynchronous
94 | @gen.coroutine
95 | def post(self):
96 | try:
97 | data = json.loads(self.request.body)
98 | except ValueError as e:
99 | raise HTTPError(400, reason=e.message)
100 | logger.debug("input data: %s" % data)
101 | resource, playbook = data.get("resource"), data.get("playbook")
102 | if not(resource and playbook):
103 | raise HTTPError(400, reason="resource and playbook are required.")
104 |
105 | response = yield self.run(resource, playbook)
106 | self.write(str(response))
107 | self.finish()
108 |
109 | @run_on_executor
110 | def run(self, resource, playbook):
111 | """
112 | 执行ansible playbook
113 |
114 | Args:
115 | resource: ditto
116 | playbook: ditto
117 | """
118 | res = MyPlaybook(resource, playbook)
119 | result = res.run()
120 | return result
121 |
122 |
--------------------------------------------------------------------------------
/libs/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | from my_ansible_api import config_ansible
4 |
5 | config_ansible()
6 |
--------------------------------------------------------------------------------
/libs/my_ansible_api.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Purpose: This module is for custom ansible api for tornado.
4 | Author: Yu Maojun
5 | Date: 2016-03-20
6 | Version: 0.0.1
7 | """
8 |
9 |
10 | from __future__ import print_function, unicode_literals
11 | from ansible.inventory import Inventory
12 | from ansible.inventory.group import Group
13 | from ansible.inventory.host import Host
14 | from ansible.runner import Runner
15 | from ansible.playbook import PlayBook
16 | from ansible import callbacks, utils
17 |
18 | import os
19 | import ansible.constants as C
20 |
21 | ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
22 | PLAYBOOK_DIR = os.path.join(ROOT_DIR, 'ansible_playbooks')
23 |
24 |
25 | def config_ansible():
26 | C.HOST_KEY_CHECKING = False
27 | C.DEFAULT_MODULE_PATH = os.path.join(ROOT_DIR, 'extra_ansible_modules')
28 |
29 |
30 | class AnsibleError(StandardError):
31 | """
32 | the base AnsibleError which contains all error message.
33 |
34 | Attributes:
35 | message: the main error message
36 | kwargs: the other message data
37 | """
38 | def __init__(self, message='', **kwargs):
39 | super(AnsibleError, self).__init__(message)
40 | self.message = message
41 | for key, value in kwargs.items():
42 | setattr(self, key, value)
43 |
44 |
45 | class CommandError(AnsibleError):
46 | """
47 | the ansible command execute error.
48 | """
49 | def __init__(self, message=''):
50 | super(CommandError, self).__init__(message)
51 |
52 |
53 | class ResourceBase(object):
54 | """
55 | gen_inventory methods.
56 |
57 | Attributes:
58 | resource: the inventory's resource. format:
59 | {
60 | "group1": {
61 | "hosts": [{"hostname": "10.10.10.10", "port": "22", "username": "test", "password": "mypass"}, ...],
62 | "vars": {"var1": value1, "var2": value2, ...}
63 | }
64 | }
65 | if your pass a list, the list will add the default group(default_group)
66 | [{"hostname": "10.10.10.10", "port": "22", "username": "test", "password": "mypass"}, ...]
67 | inventory: ansible inventory object use gen_inventory to generate.
68 | Methods:
69 | gen_inventory: generate a ansible inventory object.
70 | """
71 |
72 | def __init__(self, resource):
73 | self.inventory = Inventory(host_list=[])
74 | self.resource = resource
75 | self.gen_inventory()
76 |
77 | @staticmethod
78 | def add_group_vars(group, group_vars=None):
79 | """
80 | if group_vars exists then, add group variable to group
81 |
82 | Args:
83 | group: ansible group object
84 | group_vars: group variables
85 | """
86 | assert isinstance(group, Group), "the group must be an ansible group object."
87 |
88 | if group_vars:
89 | for key, value in group_vars.iteritems():
90 | group.set_variable(key, value)
91 |
92 | @staticmethod
93 | def gen_hosts(hosts=None):
94 | """
95 | if host_vars exists then, generate hosts
96 |
97 | Args:
98 | hosts: [, , ...]
99 | Returns:
100 | host_objs: [, , ...]
101 | """
102 | assert isinstance(hosts, list), "the hosts must be a list"
103 | host_objs = []
104 | if hosts:
105 | for host in hosts:
106 | hostname = host.get("hostname")
107 | hostip = host.get('ip', hostname)
108 | hostport = host.get("port")
109 | username = host.get("username")
110 | password = host.get("password")
111 | ssh_key = host.get("ssh_key")
112 |
113 | my_host = Host(name=hostname, port=hostport)
114 | my_host.set_variable('ansible_ssh_host', hostip)
115 | my_host.set_variable('ansible_ssh_port', hostport)
116 | my_host.set_variable('ansible_ssh_user', username)
117 |
118 | if password:
119 | my_host.set_variable('ansible_ssh_pass', password)
120 | if ssh_key:
121 | my_host.set_variable('ansible_ssh_private_key_file', ssh_key)
122 |
123 | # set other variables
124 | for key, value in host.iteritems():
125 | if key not in ["hostname", "port", "username", "password", "ip", "ssh_key"]:
126 | my_host.set_variable(key, value)
127 | host_objs.append(my_host)
128 | return host_objs
129 |
130 | def my_add_group(self, hosts_vars, group_name, group_vars=None):
131 | """
132 | add hosts to group. use to generate a inventory.
133 |
134 | Args:
135 | hosts_vars: the hosts variables
136 | group_name: group name
137 | group_vars: group variables
138 | """
139 | my_group = Group(name=group_name)
140 | self.add_group_vars(my_group, group_vars)
141 | for host in self.gen_hosts(hosts_vars):
142 | my_group.add_host(host)
143 | self.inventory.add_group(my_group)
144 |
145 | def gen_inventory(self):
146 | """
147 | add hosts to an inventory.
148 | """
149 | if isinstance(self.resource, list):
150 | self.my_add_group(self.resource, 'default_group')
151 | elif isinstance(self.resource, dict):
152 | for group_name, hosts_vars in self.resource.iteritems():
153 | self.my_add_group(hosts_vars.get("hosts"), group_name, hosts_vars.get("vars"))
154 |
155 |
156 | class Ad_Hoc(ResourceBase):
157 | """
158 | execute ansible ad-hoc mode in inventory.
159 |
160 | Args:
161 | resource: the inventory resource, the resource format see MyRunner on top of this module
162 | command: which command your want to run in this resource
163 | Attributes:
164 | results_raw: the raw data returned after ansible run.
165 | """
166 | def __init__(self, resource):
167 | super(Ad_Hoc, self).__init__(resource)
168 | self.results_raw = {}
169 |
170 | def run(self, module_arg, module_name="shell", timeout=10, forks=10, pattern='*'):
171 | """
172 | run command from andible ad-hoc.
173 |
174 | Args:
175 | module_arg: ansible module argument
176 | module_name: which module want to use, default use shell
177 | timeout: set runner api
178 | forks: see runner api
179 | pattern: set runner api
180 | """
181 | hoc = Runner(module_name=module_name,
182 | module_args=module_arg,
183 | timeout=timeout,
184 | inventory=self.inventory,
185 | pattern=pattern,
186 | forks=forks,
187 | )
188 | self.results_raw = hoc.run()
189 | return AnsibleResult(self.results_raw)
190 |
191 |
192 | class AnsibleResult(object):
193 | """
194 | container ansible return result.
195 |
196 | Attributes:
197 | result_raw: ansible return raw data
198 | """
199 | def __init__(self, raw_data):
200 | self.result_raw = raw_data
201 |
202 | @property
203 | def dark(self):
204 | """
205 | return the failed dark message.
206 |
207 | Returns:
208 | failed: eg:{'failed': {'localhost': ''}}
209 | """
210 | failed = {}
211 | dark = self.result_raw.get("dark")
212 | if dark:
213 | for host, info in dark.items():
214 | failed[host] = info.get('msg')
215 | return failed
216 |
217 | @property
218 | def contacted(self):
219 | """
220 | return the contacted message.
221 |
222 | Returns:
223 | contacted: {'failed': {'host1': ''}, 'ok': {'host2': ''}}
224 | """
225 | result = {'failed': {}, 'ok': {}}
226 | contacted = self.result_raw.get("contacted")
227 | if contacted:
228 | for host, info in contacted.items():
229 | if info.get('invocation').get('module_name') in ['raw', 'shell', 'command', 'script']:
230 | if info.get('rc') == 0:
231 | result['ok'][host] = info.get('stdout') + info.get('stderr')
232 | else:
233 | result['failed'][host] = info.get('stdout') + info.get('stderr')
234 | else:
235 | if info.get('failed'):
236 | result['failed'][host] = info.get('msg')
237 | else:
238 | result['ok'][host] = info.get('changed')
239 | return result
240 |
241 | @property
242 | def result_deal(self):
243 | """
244 | deal the ansible return result.
245 |
246 | Returns:
247 | results: eg: {'failed': {'host1': ''}, 'ok': {'host2': ''}}
248 | """
249 | results = {'failed': {}, 'ok': {}}
250 | if self.dark:
251 | results['failed'].update(**self.dark)
252 | if self.contacted:
253 | results['failed'].update(**self.contacted['failed'])
254 | results['ok'].update(**self.contacted['ok'])
255 | return results
256 |
257 | def __unicode__(self):
258 | return "%s" % self.result_raw
259 |
260 | def __str__(self):
261 | return self.__unicode__()
262 |
263 |
264 | class MyPlaybook(ResourceBase):
265 | """
266 | this is my playbook object for execute playbook.
267 |
268 | Attributes:
269 | resource: resource dict ,see ResourceBase class
270 | playbook_path: relational playbook path, the default playbook directory is:
271 | """
272 | def __init__(self, resource, playbook_path):
273 | super(MyPlaybook, self).__init__(resource)
274 | self.results_raw = None
275 | self.playbook_path = playbook_path
276 |
277 | def run(self, extra_vars=None):
278 | """
279 | run ansible playbook, only surport relational path.
280 |
281 | Args:
282 | extra_vars: playbook extra variables.
283 | """
284 | stats = callbacks.AggregateStats()
285 | playbook_cb = callbacks.PlaybookCallbacks(verbose=utils.VERBOSITY)
286 | runner_cb = callbacks.PlaybookRunnerCallbacks(stats, verbose=utils.VERBOSITY)
287 | playbook_path = os.path.join(PLAYBOOK_DIR, self.playbook_path)
288 |
289 | pb = PlayBook(
290 | playbook=playbook_path,
291 | stats=stats,
292 | callbacks=playbook_cb,
293 | runner_callbacks=runner_cb,
294 | inventory=self.inventory,
295 | extra_vars=extra_vars,
296 | check=False)
297 |
298 | self.results_raw = pb.run()
299 | return self.results_raw
300 |
301 |
302 | if __name__ == "__main__":
303 | resource = [{"hostname": "192.168.10.148", "port": "22", "username": "root", "password": "mypass"}]
304 | cmd = Ad_Hoc(resource)
305 | result = cmd.run('time')
306 | print(result.result_deal)
307 |
--------------------------------------------------------------------------------
/libs/utils.py:
--------------------------------------------------------------------------------
1 | # -*- coding:utf-8 -*-
2 | from __future__ import unicode_literals
3 |
4 | from settings import mongoinfo
5 | import hashlib
6 | from pymongo import MongoClient
7 |
8 |
9 | def get_md5(s):
10 | """
11 | hash 一段字符串
12 |
13 | Args:
14 | s: 一段字符串
15 | Returns:
16 | digest: hash过后的digest
17 | """
18 | m = hashlib.md5()
19 | m.update(s)
20 | return m.hexdigest()
21 |
22 |
23 | def conn_mongodb():
24 | """
25 | 返回一个mongodb的uri,用于链接mongodb
26 | """
27 | dbhost = mongoinfo['host']
28 | dbport = mongoinfo['port']
29 | dbuser = mongoinfo['user']
30 | dbpwd = mongoinfo['password']
31 | dbname = mongoinfo['dbname']
32 | uri = 'mongodb://%s:%s@%s:%s/%s' % (dbuser, dbpwd, dbhost, dbport, dbname)
33 | return MongoClient(uri, safe=False)
34 |
--------------------------------------------------------------------------------
/logconfig/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/logconfig/logconfig.py:
--------------------------------------------------------------------------------
1 | # An extended version of the log_settings module from zamboni:
2 | # https://github.com/jbalogh/zamboni/blob/master/log_settings.py
3 |
4 | from __future__ import absolute_import
5 |
6 | from logging.config import dictConfig
7 | import os.path
8 |
9 | PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
10 | LOG_DIR = os.path.join(PROJECT_DIR, 'logs')
11 |
12 | LOGGING = {
13 | 'version': 1,
14 | 'disable_existing_loggers': True,
15 | 'formatters': {
16 | 'standard': {
17 | 'format': '%(asctime)s - %(filename)s:%(lineno)d(%(module)s:%(funcName)s) - %(levelname)s - %(message)s',
18 | 'datefmt': '%Y-%m-%d %H:%M:%S'
19 | },
20 | 'simple': {
21 | 'format': '%(asctime)s - %(levelname)s - %(message)s',
22 | 'datefmt': '%Y-%m-%d %H:%M:%S'
23 | },
24 | },
25 | 'filters': {
26 | },
27 | 'handlers': {
28 | 'null': {
29 | 'level': 'DEBUG',
30 | 'class': 'logging.NullHandler',
31 | },
32 | 'console': {
33 | 'level': 'DEBUG',
34 | 'class': 'logging.StreamHandler',
35 | 'formatter': 'standard'
36 | },
37 | 'syslog': {
38 | 'level': 'DEBUG',
39 | 'class': 'logging.handlers.SysLogHandler',
40 | 'facility': 'logging.handlers.SysLogHandler.LOG_LOCAL7',
41 | 'formatter': 'standard',
42 | },
43 | 'syslog2': {
44 | 'level': 'DEBUG',
45 | 'class': 'logging.handlers.SysLogHandler',
46 | 'facility': 'logging.handlers.SysLogHandler.LOG_LOCAL7',
47 | 'formatter': 'standard',
48 | },
49 | 'access': {
50 | 'level': 'DEBUG',
51 | 'class': 'logging.handlers.RotatingFileHandler',
52 | 'filename': os.path.join(LOG_DIR, 'access.log'),
53 | 'maxBytes': 1024*1024*2,
54 | 'backupCount': 5,
55 | 'formatter': 'standard',
56 | },
57 | 'application': {
58 | 'level': 'DEBUG',
59 | 'class': 'logging.handlers.RotatingFileHandler',
60 | 'filename': os.path.join(LOG_DIR, 'app.log'),
61 | 'maxBytes': 1024*1024*2,
62 | 'backupCount': 5,
63 | 'formatter': 'standard',
64 | },
65 | 'general': {
66 | 'level': 'DEBUG',
67 | 'class': 'logging.handlers.RotatingFileHandler',
68 | 'filename': os.path.join(LOG_DIR, 'gen.log'),
69 | 'maxBytes': 1024*1024*2,
70 | 'backupCount': 5,
71 | 'formatter': 'standard',
72 | },
73 | },
74 | 'loggers': {
75 | 'tornado': {
76 | 'handlers': ['console'],
77 | 'level': 'DEBUG',
78 | 'propagate': False
79 | },
80 | 'tornado.access': {
81 | 'handlers': ['access'],
82 | 'level': 'DEBUG',
83 | 'propagate': False,
84 | },
85 | 'tornado.app': {
86 | 'handlers': ['application'],
87 | 'level': 'DEBUG',
88 | 'propagate': True
89 | },
90 | 'tornado.gen': {
91 | 'handlers': ['general'],
92 | 'level': 'DEBUG',
93 | 'propagate': True
94 | }
95 | }
96 | }
97 |
98 |
99 | def init_logging():
100 | """
101 | initial logging
102 | """
103 | dictConfig(LOGGING)
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
--------------------------------------------------------------------------------
/requirements/requirements.txt:
--------------------------------------------------------------------------------
1 | pika==0.9.14
--------------------------------------------------------------------------------
/settings.py:
--------------------------------------------------------------------------------
1 | import tornado
2 | import tornado.template
3 | import os
4 | from tornado.options import define, options
5 |
6 | # add need module to PYTHONPATH
7 | import environment
8 |
9 |
10 | # Make filepaths relative to settings.
11 | path = lambda root, *a: os.path.join(root, *a)
12 | ROOT = os.path.dirname(os.path.abspath(__file__))
13 |
14 | define("port", default=8888, help="run on the given port", type=int)
15 | define("config", default=None, help="tornado config file")
16 | define("debug", default=True, help="debug mode")
17 | tornado.options.parse_command_line()
18 |
19 | settings = {}
20 | settings['xsrf_cookies'] = False
21 |
22 | # See PEP 391 and logconfig for formatting help. Each section of LOGGERS
23 | # will get merged into the corresponding section of log_settings.py.
24 | # Handlers and log levels are set up automatically based on LOG_LEVEL and DEBUG
25 | # unless you set them here. Messages will not propagate through a logger
26 | # unless propagate: True is set.
27 | from logconfig.logconfig import init_logging
28 | init_logging()
29 |
30 | if options.config:
31 | tornado.options.parse_config_file(options.config)
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/urls.py:
--------------------------------------------------------------------------------
1 | from handlers.ansible_async import MainHandler, CommandHandler, AdHocHandler, PlaybookHandler
2 |
3 | url_patterns = [
4 | (r"/", MainHandler),
5 | (r"/command", CommandHandler),
6 | (r"/ad_hoc", AdHocHandler),
7 | (r"/playbook", PlaybookHandler),
8 | ]
--------------------------------------------------------------------------------