index.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  1. """
  2. This is a RESTful interface implemented using Flask micro framework.
  3. The API is driven by configuration that is organized in terms of the monitoring classes
  4. The API is both restful and websocket/socketio enabled.
  5. We designed the classes to be reusable (and powered by labels):
  6. 'monitoring-type':
  7. 'class':'<class-name>'
  8. 'config':<labeled-class-specific-configuration>'
  9. @TODO:
  10. - In order to make this Saas we need to have the configuration be session driven
  11. - Add socketio, so that each section of the dashboard updates independently
  12. """
  13. from flask import Flask, session, request, redirect, Response
  14. from flask.templating import render_template
  15. from flask_session import Session
  16. import time
  17. import sys
  18. import os
  19. import json
  20. import re
  21. import monitor
  22. import Queue
  23. from utils.transport import *
  24. from utils.workers import ThreadManager, Factory
  25. from utils.ml import ML,AnomalyDetection,AnalyzeAnomaly
  26. import utils.params as SYS_ARGS
  27. import atexit
  28. app = Flask(__name__)
  29. app.config['SECRET_KEY'] = '!h8-[0v8]247-4-360'
  30. #app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX=?RT'
  31. PARAMS = SYS_ARGS.PARAMS
  32. f = open(PARAMS['path'])
  33. CONFIG = json.loads(f.read())
  34. f.close()
  35. #
  36. #
  37. #from threading import Thread, RLock
  38. p = CONFIG['store']['args']
  39. class_read = CONFIG['store']['class']['read']
  40. class_write= CONFIG['store']['class']['write']
  41. factory = DataSourceFactory()
  42. # gReader = factory.instance(type=class_read,args=p)
  43. @app.route('/')
  44. def home():
  45. context = PARAMS['context']
  46. if 'title' in PARAMS :
  47. title = PARAMS['title']
  48. else:
  49. title = 'Dashboard'
  50. apps = []
  51. try:
  52. gReader = factory.instance(type=class_read,args=p)
  53. apps = gReader.view('summary/nodes',key=p['uid'])
  54. except Exception, e:
  55. print (e)
  56. return render_template('dashboard.html',context=context,title=title,app_names=apps)
  57. @app.route('/1/get/nodes')
  58. def get_nodes():
  59. """
  60. This function returns the labels of applications for every node registered
  61. @param None
  62. e.g: apps@zulu.org
  63. """
  64. r = []
  65. try:
  66. gReader = factory.instance(type=class_read,args=p)
  67. r = gReader.view('summary/nodes',key=p['uid'])
  68. except Exception,e:
  69. print (e)
  70. return json.dumps(r)
  71. @app.route('/1/get/apps')
  72. def get_apps():
  73. """
  74. This function returns the applications for a given node
  75. @param node identifier e.g: apps@zulu.org
  76. """
  77. r = []
  78. try:
  79. node_id = request.args.get('node')
  80. gReader = factory.instance(type=class_read,args=p)
  81. r = gReader.view('summary/app_names',key=p['uid'])
  82. r = r[node_id]
  83. print r
  84. except Exception,e:
  85. print (e)
  86. return json.dumps(r)
  87. @app.route('/1/get/summary/<id>')
  88. def get_summary(id):
  89. """
  90. This function returns the summary i.e an overall assessment of resource usage
  91. It will pull information out of the user's data-store (database & document) specified in the configuration
  92. @param id {app_resources|app_status|folder_size}
  93. """
  94. r = []
  95. try:
  96. gReader = factory.instance(type=class_read,args=p)
  97. #if id == 'apps_resources' :
  98. # r = gReader.view('summary/app_resources',key=p['uid'])
  99. #else:
  100. # r = gReader.view('summary/folder_size',key=p['uid'])
  101. id='summary/'+id.strip()
  102. print p
  103. print id
  104. r = gReader.view(id,key=p['uid'])
  105. except Exception,e:
  106. print (e)
  107. return json.dumps(r)
  108. @app.route("/1/sys/usage/trend")
  109. def get_usage_trend():
  110. """
  111. This function returns cpu/memory usage for the entire system being monitored. It will return the 24 most recent observations in the logs
  112. @param None
  113. @return {memory_usage:[],cpu_usage:[],app_count:value,memory_available:[]}
  114. """
  115. r = {}
  116. try:
  117. gReader = factory.instance(type=class_read,args=p)
  118. r = gReader.view('summary/resource_usage_trend',key=p['uid'])
  119. except Exception,e:
  120. print (e)
  121. return json.dumps(r)
  122. @app.route("/1/app/usage/trend")
  123. def get_usage_detail():
  124. """
  125. This function returns detailed information about usage per application monitored. It will return the 24 most recent observations in the logs
  126. @param node node identifier e.g: apps@zulu.io
  127. @return {node_x:{app_1:{memory_usage:[],cpu_usage:[]}},...}
  128. """
  129. r = {}
  130. try:
  131. id = request.args.get('node')
  132. app_id = request.args.get('app')
  133. gReader = factory.instance(type=class_read,args=p)
  134. r = gReader.view('summary/app_resource_usage_details',key=p['uid'])
  135. r = r[id][app_id]
  136. except Exception,e:
  137. print (e)
  138. return json.dumps(r)
  139. @app.route('/1/app/status')
  140. def app_status() :
  141. """
  142. This function aggregates the number of crashes/running/idle instances found in the past 24 log entries
  143. for a particular application
  144. @param nid node identifier e.g: app@zulu.io
  145. @param app application identifier e.g: kate, firefox, chrome ... specified in the configuraiton
  146. """
  147. r = []
  148. try:
  149. nid = request.args.get('node') # Node identifier
  150. aid = request.args.get('app') # application identifier
  151. gReader = factory.instance(type=class_read,args=p)
  152. r = gReader.view('summary/app_status_details',key=p['uid'])
  153. #
  154. #@TODO: Once the back-end enables the nodes in which the application is running, uncomment the line below
  155. #
  156. print[nid,aid]
  157. r = r[nid][aid]
  158. except Exception,e:
  159. print e
  160. return json.dumps(r)
  161. #@app.route('/get/<id>')
  162. #def procs(id):
  163. #try:
  164. #gReader = factory.instance(type=class_read,args=p)
  165. #data = gReader.read()
  166. #ahandler = AnalyzeAnomaly()
  167. #learn = {}
  168. #if 'learn' in data :
  169. #for row in data['learn'] :
  170. #label = row['label']
  171. #learn[label] = row
  172. #r = {}
  173. #for label in data :
  174. #if label not in ['learn','folders'] :
  175. #index = len(data[label]) - 1
  176. #row = data[label][index]
  177. #r[label] = row
  178. ##
  179. ## Let us determine if this is a normal operation or not
  180. ## We will update the status of the information ...
  181. ##
  182. #for row in r[label] :
  183. #index = r[label].index(row)
  184. #if row['label'] in learn:
  185. #id = row['label']
  186. #px = ahandler.predict([row],learn[id])
  187. #if px :
  188. ## row['anomaly'] = px[1]==1
  189. #print ""
  190. #print label,' *** ',index
  191. #row = dict(row,**px)
  192. #r[label][index] =row
  193. ##
  194. ## @TODO:
  195. ## Compile a report here that will be sent to the mailing list
  196. ##
  197. #except Exception, e:
  198. #print e
  199. #r = []
  200. #return json.dumps(r)
  201. """
  202. This function/endpoint will assess n-virtual environments and return the results
  203. @TODO: Should this be stored for future mining (I don't think so but could be wrong)
  204. """
  205. @app.route('/sandbox')
  206. def sandbox():
  207. global CONFIG
  208. if 'sandbox' in CONFIG: #CONFIG['monitor']:
  209. #handler = HANDLERS['sandbox']['class']
  210. #conf = HANDLERS['sandbox']['config']
  211. r = []
  212. # p = Factory.instance('sandbox',CONFIG)
  213. handler = monitor.Sandbox()
  214. conf = CONFIG['sandbox']
  215. for id in conf:
  216. try:
  217. handler.init(conf[id])
  218. r.append (dict(handler.composite(),**{"label":id}))
  219. except Exception,e:
  220. pass
  221. else:
  222. r = []
  223. return json.dumps(r)
  224. #@app.route('/trends')
  225. #def trends ():
  226. #id = request.args.get('id')
  227. #app = request.args.get('app').strip()
  228. #p = CONFIG['store']['args']
  229. #class_read = CONFIG['store']['class']['read']
  230. #gReader = factory.instance(type=class_read,args=p)
  231. #r = gReader.read()
  232. #if id in r:
  233. #r = r[id] #--matrix
  234. #series = []
  235. #for row in r:
  236. #series += [item for item in row if str(item['label'])== app]
  237. #if len(series) > 12 :
  238. #beg = len(series) - 8
  239. #series = series[beg:]
  240. #return json.dumps(series)
  241. #else:
  242. #return "[]"
  243. #@app.route('/download',methods=['POST'])
  244. #def requirements():
  245. #stream = request.form['missing']
  246. #print stream
  247. #stream = "\n".join(json.loads(stream))
  248. #headers = {"content-disposition":"attachment; filename=requirements.txt"}
  249. #return Response(stream,mimetype='text/plain',headers=headers)
  250. @app.route('/dashboard')
  251. def dashboard():
  252. context = PARAMS['context']
  253. if 'title' in PARAMS :
  254. title = PARAMS['title']
  255. else:
  256. title = 'Dashboard'
  257. apps = []
  258. try:
  259. gReader = factory.instance(type=class_read,args=p)
  260. apps = gReader.view('summary/app_names',key=p['uid'])
  261. except Exception, e:
  262. print (e)
  263. return render_template('dashboard.html',context=context,title=title,app_names=apps)
  264. @app.route('/upgrade')
  265. def upgrade():
  266. context = PARAMS['context']
  267. if 'title' in PARAMS :
  268. title = PARAMS['title']
  269. else:
  270. title = 'Upgrade'
  271. return render_template('upgrade.html',context=context,title=title)
  272. @app.route('/user')
  273. def user():
  274. context = PARAMS['context']
  275. if 'title' in PARAMS :
  276. title = PARAMS['title']
  277. else:
  278. title = 'Upgrade'
  279. return render_template('user.html',context=context,title=title)
  280. #"""
  281. #This function is designed to trigger learning for anomaly detection
  282. #@TODO: forward this to a socket i.e non-blocking socket
  283. #"""
  284. #@app.route('/anomalies/get')
  285. #def learn():
  286. #global CONFIG
  287. #p = CONFIG['store']['args']
  288. #class_read = CONFIG['store']['class']['read']
  289. #gReader = factory.instance(type=class_read,args=p)
  290. #d = gReader.read()
  291. #if 'learn' in d :
  292. #info = d['learn']
  293. #del d['learn']
  294. #else :
  295. #info = []
  296. #r = []
  297. #if 'id' in request.args:
  298. #id = request.args['id']
  299. #d = d[id]
  300. #params = {}
  301. #for item in info:
  302. #label = item['label']
  303. #params[label] = item
  304. ##apps = list(set(ML.Extract(['label'],d)))
  305. #r = []
  306. #if params :
  307. ##
  308. ## If we have parameters available
  309. #p = AnomalyDetection()
  310. #apps = params.keys()
  311. #for name in apps :
  312. #if name not in params:
  313. #continue
  314. #_info = params[name]
  315. #try:
  316. #xo = ML.Filter('label',name,d)
  317. #except Exception,e:
  318. #xo = []
  319. ##print name,e
  320. #if len(xo) == 0:
  321. #continue
  322. #xo = [xo[ len(xo) -1]]
  323. #value = p.predict(xo,_info)[0]
  324. #if len(value):
  325. #report = dict(_info,**{'predicton':value})
  326. #r.append(report)
  327. ##print app,value
  328. ##if value is not None:
  329. ## r.append(value)
  330. #return json.dumps(r)
  331. """
  332. This function returns anomalies for a given context or group of processes
  333. The information returned is around precision/recall and f-score and parameters
  334. """
  335. #@app.route('/anomalies/status')
  336. #def anomalies_status():
  337. #global CONFIG
  338. #p = CONFIG['store']['args']
  339. #class_read = CONFIG['store']['class']['read']
  340. #gReader = factory.instance(type=class_read,args=p)
  341. #d = gReader.read()
  342. #if 'learn' in d :
  343. #info = d['learn']
  344. #del d['learn']
  345. #else :
  346. #info = []
  347. #print info
  348. #r = []
  349. #if 'id' in request.args:
  350. #id = request.args['id']
  351. #r = info
  352. #return json.dumps(r)
  353. #@app.route('/folders')
  354. #def get_folders():
  355. #global CONFIG
  356. #p = CONFIG['store']['args']
  357. #class_read = CONFIG['store']['class']['read']
  358. #gReader = factory.instance(type=class_read,args=p)
  359. #d = gReader.read()
  360. #if 'folders' in d:
  361. #d = d['folders']
  362. #hosts = set([row[0]['id'] for row in d])
  363. #m = {}
  364. #for id in hosts:
  365. #for row in d:
  366. #if id == row[0]['id'] :
  367. #m[id] = row
  368. #d = m.values()
  369. #for row in d:
  370. #print row[0]['id']
  371. ## index = len(d) - 1
  372. ## d = d[index]
  373. ## m = {}
  374. ## for row in d :
  375. ## key = row.keys()[0]
  376. ## row = row[key]
  377. ## if key not in m:
  378. ## r.append(row)
  379. ## m[key] = len(r) -1
  380. ## else:
  381. ## index = m[key]
  382. ## r[index] = row
  383. ## d = r
  384. #else:
  385. #d = []
  386. #return json.dumps(d)
  387. if __name__== '__main__':
  388. # ThreadManager.start(CONFIG)
  389. if 'port' not in SYS_ARGS.PARAMS :
  390. SYS_ARGS.PARAMS['port'] = 8484
  391. PORT = int(SYS_ARGS.PARAMS['port'])
  392. app.run(host='0.0.0.0' ,port=PORT,debug=True,threaded=True)