__init__.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. import traceback
  4. import time
  5. from datetime import timedelta
  6. import jimit as ji
  7. import json
  8. import os
  9. from flask import g, request, redirect, url_for, Response, session, Flask
  10. try:
  11. from flask_session import Session
  12. except ImportError as e:
  13. # 兼容老版本
  14. from flask.ext.session import Session
  15. try:
  16. from flask_themes2 import Themes, packaged_themes_loader
  17. except ImportError as e:
  18. # 兼容老版本
  19. from flask.ext.themes2 import Themes, packaged_themes_loader
  20. from werkzeug.debug import get_current_traceback
  21. app = Flask(__name__)
  22. from jimvc.models.initialize import logger, Init, app_config, dev_table
  23. import api_route_table
  24. import views_route_table
  25. from jimvc.models import Utils
  26. from jimvc.models import EventProcessor
  27. from jimvc.models import Database as db
  28. from jimvc.models import Config
  29. from jimvc.models import User
  30. from jimvc.api.user import blueprint as user_blueprint
  31. from jimvc.api.os_template_image import blueprint as os_template_image_blueprint
  32. from jimvc.api.os_template_image import blueprints as os_template_image_blueprints
  33. from jimvc.api.os_template_initialize_operate_set import blueprint as os_template_initialize_operate_set_blueprint
  34. from jimvc.api.os_template_initialize_operate_set import blueprints as os_template_initialize_operate_set_blueprints
  35. from jimvc.api.os_template_initialize_operate import blueprint as os_template_initialize_operate_blueprint
  36. from jimvc.api.os_template_initialize_operate import blueprints as os_template_initialize_operate_blueprints
  37. from jimvc.api.os_template_profile import blueprint as os_template_profile_blueprint
  38. from jimvc.api.os_template_profile import blueprints as os_template_profile_blueprints
  39. from jimvc.api.guest import blueprint as guest_blueprint
  40. from jimvc.api.guest import blueprints as guest_blueprints
  41. from jimvc.api.disk import blueprint as disk_blueprint
  42. from jimvc.api.disk import blueprints as disk_blueprints
  43. from jimvc.api.config import blueprint as config_blueprint
  44. from jimvc.api.ip_pool import blueprint as ip_pool_blueprint
  45. from jimvc.api.ip_pool import blueprints as ip_pool_blueprints
  46. from jimvc.api.log import blueprint as log_blueprint
  47. from jimvc.api.log import blueprints as log_blueprints
  48. from jimvc.api.host import blueprint as host_blueprint
  49. from jimvc.api.host import blueprints as host_blueprints
  50. from jimvc.api.ssh_key import blueprint as ssh_key_blueprint
  51. from jimvc.api.ssh_key import blueprints as ssh_key_blueprints
  52. from jimvc.api.snapshot import blueprint as snapshot_blueprint
  53. from jimvc.api.snapshot import blueprints as snapshot_blueprints
  54. from jimvc.api.guest_performance import blueprint as performance_blueprint
  55. from jimvc.api.guest_performance import blueprints as performance_blueprints
  56. from jimvc.api.host_performance import blueprint as host_performance_blueprint
  57. from jimvc.api.host_performance import blueprints as host_performance_blueprints
  58. from jimvc.api.dashboard import blueprint as dashboard_blueprint
  59. from jimvc.api.dashboard import blueprints as dashboard_blueprints
  60. from jimvc.api.about import blueprint as about_blueprint
  61. from jimvc.api.project import blueprint as project_blueprint
  62. from jimvc.api.project import blueprints as project_blueprints
  63. from jimvc.api.service import blueprint as service_blueprint
  64. from jimvc.api.service import blueprints as service_blueprints
  65. from jimvc.views.error_pages import *
  66. from jimvc.views.config import blueprint as view_config_blueprint
  67. from jimvc.views.misc import blueprint as view_misc_blueprint
  68. from jimvc.views.dashboard import blueprint as view_dashboard_blueprint
  69. from jimvc.views.guest import blueprint as view_guest_blueprint
  70. from jimvc.views.guest import blueprints as view_guest_blueprints
  71. from jimvc.views.disk import blueprint as view_disk_blueprint
  72. from jimvc.views.disk import blueprints as view_disk_blueprints
  73. from jimvc.views.log import blueprint as view_log_blueprint
  74. from jimvc.views.log import blueprints as view_log_blueprints
  75. from jimvc.views.os_template_image import blueprint as view_os_template_image_blueprint
  76. from jimvc.views.os_template_image import blueprints as view_os_template_image_blueprints
  77. from jimvc.views.ssh_key import blueprint as view_ssh_key_blueprint
  78. from jimvc.views.ssh_key import blueprints as view_ssh_key_blueprints
  79. from jimvc.views.snapshot import blueprint as view_snapshot_blueprint
  80. from jimvc.views.snapshot import blueprints as view_snapshot_blueprints
  81. from jimvc.views.host import blueprint as view_host_blueprint
  82. from jimvc.views.host import blueprints as view_host_blueprints
  83. from websockify.websocketproxy import WebSocketProxy
  84. __author__ = 'James Iter'
  85. __date__ = '2017/3/31'
  86. __contact__ = 'james.iter.cn@gmail.com'
  87. __copyright__ = '(c) 2017 by James Iter.'
  88. app.config = dict(app.config, **app_config)
  89. app.jinja_env.add_extension('jinja2.ext.i18n')
  90. app.jinja_env.add_extension('jinja2.ext.do')
  91. app.jinja_env.add_extension('jinja2.ext.loopcontrols')
  92. app.jinja_env.auto_reload = app.config['DEBUG']
  93. # 替换为Flask-Session
  94. app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(seconds=app_config['PERMANENT_SESSION_LIFETIME'])
  95. Session(app)
  96. Themes(app, app_identifier="JimV-C")
  97. themes_list = packaged_themes_loader(app)
  98. def instantiation_ws_vnc(listen_port, target_host, target_port):
  99. # 用于 Web noVNC 代理
  100. ws = WebSocketProxy(listen_host="0.0.0.0", listen_port=listen_port, target_host=target_host,
  101. target_port=target_port, run_once=True, daemon=True, idle_timeout=10)
  102. ws.start_server()
  103. def ws_engine_for_vnc():
  104. logger.info(msg='VNC ws engine is launched.')
  105. while True:
  106. payload = db.r.lpop(app_config['ipc_queue'])
  107. if payload is None:
  108. time.sleep(1)
  109. continue
  110. payload = json.loads(payload)
  111. c_pid = os.fork()
  112. if c_pid == 0:
  113. instantiation_ws_vnc(payload['listen_port'], payload['target_host'], payload['target_port'])
  114. # 因为 WebSocketProxy 使用了 daemon 参数,所以当执行到 ws.start_server() 时,会退出其所在的子进程,
  115. # 故而这里设置wait来处理结束的子进程的环境,避免出现僵尸进程。
  116. os.wait()
  117. def is_not_need_to_auth(endpoint):
  118. not_auth_table = [
  119. 'api_config.r_get',
  120. 'api_config.r_create',
  121. 'v_config.create',
  122. 'v_misc.login',
  123. 'v_misc.recover_password',
  124. 'v_misc.reset_password',
  125. 'api_user.r_sign_in',
  126. 'api_user.r_reset_password',
  127. 'api_user.r_send_reset_password_email',
  128. '_themes.static'
  129. ]
  130. if endpoint in not_auth_table:
  131. return True
  132. return False
  133. @app.before_request
  134. @Utils.dumps2response
  135. def r_before_request():
  136. try:
  137. g.ts = ji.Common.ts()
  138. if not is_not_need_to_auth(request.endpoint) and request.blueprint is not None and request.method != 'OPTIONS':
  139. g.config = Config()
  140. g.config.id = 1
  141. g.config.get()
  142. token = session.get('token', '')
  143. g.token = Utils.verify_token(token)
  144. user = User()
  145. user.id = g.token['uid']
  146. try:
  147. user.get()
  148. except ji.PreviewingError, e:
  149. # 如果该用户获取失败,则清除该用户对应的session。因为该用户可能已经被删除。
  150. for key in session.keys():
  151. session.pop(key=key)
  152. return json.loads(e.message)
  153. except ji.JITError, e:
  154. ret = json.loads(e.message)
  155. if ret['state']['code'] == '404':
  156. return redirect(location=url_for('v_config.create'), Response=Response)
  157. if ret['state']['sub']['code'] in ['41208']:
  158. return redirect(location=url_for('v_misc.login'), Response=Response)
  159. return ret
  160. @app.after_request
  161. @Utils.dumps2response
  162. def r_after_request(response):
  163. try:
  164. # https://developer.mozilla.org/en/HTTP_access_control
  165. # (中文版) https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS#Access-Control-Allow-Credentials
  166. # http://www.w3.org/TR/cors/
  167. # 由于浏览器同源策略,凡是发送请求url的协议、域名、端口三者之间任意一与当前页面地址不同即为跨域。
  168. if request.referrer is None:
  169. # 跑测试脚本时,用该规则。
  170. response.headers['Access-Control-Allow-Origin'] = '*'
  171. else:
  172. # 生产环境中,如果前后端分离。那么请指定具体的前端域名地址,不要用如下在开发环境中的便捷方式。
  173. # -- Access-Control-Allow-Credentials为true,携带cookie时,不允许Access-Control-Allow-Origin为通配符,是浏览器对用户的一种安全保护。
  174. # -- 至少能避免登录山寨网站,骗取用户相关信息。
  175. response.headers['Access-Control-Allow-Origin'] = '/'.join(request.referrer.split('/')[:3])
  176. response.headers['Access-Control-Allow-Credentials'] = 'true'
  177. response.headers['Access-Control-Allow-Methods'] = 'HEAD, GET, POST, DELETE, OPTIONS, PATCH, PUT'
  178. response.headers['Access-Control-Allow-Headers'] = 'X-Request-With, Content-Type'
  179. response.headers['Access-Control-Expose-Headers'] = 'Set-Cookie'
  180. # 少于session生命周期一半时,自动对其续期
  181. if not is_not_need_to_auth(request.endpoint) and hasattr(g, 'token') and \
  182. g.token['exp'] < (ji.Common.ts() + (app_config['token_ttl'] / 2)):
  183. token = Utils.generate_token(g.token['uid'])
  184. # 清除原有session,由新session代替
  185. for key in session.keys():
  186. session.pop(key=key)
  187. session['token'] = token
  188. return response
  189. except ji.JITError, e:
  190. return json.loads(e.message)
  191. @app.teardown_request
  192. def teardown_request(exception):
  193. if exception:
  194. _traceback = get_current_traceback()
  195. logger.error(_traceback.plaintext)
  196. # noinspection PyBroadException
  197. try:
  198. db.init_conn_mysql()
  199. db.init_conn_redis()
  200. app.register_blueprint(user_blueprint)
  201. app.register_blueprint(os_template_image_blueprint)
  202. app.register_blueprint(os_template_image_blueprints)
  203. app.register_blueprint(os_template_initialize_operate_set_blueprint)
  204. app.register_blueprint(os_template_initialize_operate_set_blueprints)
  205. app.register_blueprint(os_template_initialize_operate_blueprint)
  206. app.register_blueprint(os_template_initialize_operate_blueprints)
  207. app.register_blueprint(os_template_profile_blueprint)
  208. app.register_blueprint(os_template_profile_blueprints)
  209. app.register_blueprint(guest_blueprint)
  210. app.register_blueprint(guest_blueprints)
  211. app.register_blueprint(disk_blueprint)
  212. app.register_blueprint(disk_blueprints)
  213. app.register_blueprint(config_blueprint)
  214. app.register_blueprint(ip_pool_blueprint)
  215. app.register_blueprint(ip_pool_blueprints)
  216. app.register_blueprint(log_blueprint)
  217. app.register_blueprint(log_blueprints)
  218. app.register_blueprint(host_blueprint)
  219. app.register_blueprint(host_blueprints)
  220. app.register_blueprint(ssh_key_blueprint)
  221. app.register_blueprint(ssh_key_blueprints)
  222. app.register_blueprint(snapshot_blueprint)
  223. app.register_blueprint(snapshot_blueprints)
  224. app.register_blueprint(performance_blueprint)
  225. app.register_blueprint(performance_blueprints)
  226. app.register_blueprint(host_performance_blueprint)
  227. app.register_blueprint(host_performance_blueprints)
  228. app.register_blueprint(dashboard_blueprint)
  229. app.register_blueprint(dashboard_blueprints)
  230. app.register_blueprint(about_blueprint)
  231. app.register_blueprint(project_blueprint)
  232. app.register_blueprint(project_blueprints)
  233. app.register_blueprint(service_blueprint)
  234. app.register_blueprint(service_blueprints)
  235. app.register_blueprint(view_config_blueprint)
  236. app.register_blueprint(view_misc_blueprint)
  237. app.register_blueprint(view_dashboard_blueprint)
  238. app.register_blueprint(view_guest_blueprint)
  239. app.register_blueprint(view_guest_blueprints)
  240. app.register_blueprint(view_disk_blueprint)
  241. app.register_blueprint(view_disk_blueprints)
  242. app.register_blueprint(view_log_blueprint)
  243. app.register_blueprint(view_log_blueprints)
  244. app.register_blueprint(view_os_template_image_blueprint)
  245. app.register_blueprint(view_os_template_image_blueprints)
  246. app.register_blueprint(view_ssh_key_blueprint)
  247. app.register_blueprint(view_ssh_key_blueprints)
  248. app.register_blueprint(view_snapshot_blueprint)
  249. app.register_blueprint(view_snapshot_blueprints)
  250. app.register_blueprint(view_host_blueprint)
  251. app.register_blueprint(view_host_blueprints)
  252. except:
  253. logger.error(traceback.format_exc())