server.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. #!/usr/bin/env python
  2. import warnings
  3. warnings.filterwarnings('ignore', 'libevent')
  4. import gevent.monkey
  5. gevent.monkey.patch_all(thread=False)
  6. import copy
  7. import datetime
  8. import errno
  9. import json
  10. import os
  11. from os import path
  12. import traceback
  13. import urlparse
  14. import gevent.pywsgi
  15. import fileio
  16. import reloader
  17. DATA_DIR = path.expanduser('~/sysvitals_data')
  18. handlers = None
  19. def main():
  20. global handlers
  21. handlers = {
  22. 'data': get_data,
  23. 'datum': post_datum,
  24. }
  25. server = gevent.pywsgi.WSGIServer(('0.0.0.0', 8892), application)
  26. reloader.init(server)
  27. server.serve_forever()
  28. def application(environ, start_response):
  29. try:
  30. split = environ['PATH_INFO'][1:].split('/')
  31. qs = environ['QUERY_STRING']
  32. if qs:
  33. query = urlparse.parse_qs(qs, True, True)
  34. for k, v in query.items():
  35. if len(v) > 1:
  36. start_response('400 Bad Request', [('Content-type', 'text/plain')])
  37. return ['duplicate query parameter: ' + k]
  38. query[k] = v[0]
  39. else:
  40. query = {}
  41. if split[0] == 'v1':
  42. handler = handlers.get(split[2])
  43. if handler:
  44. body = json.dumps(handler(split, query, environ))
  45. start_response('200 OK', [('Content-type', 'application/json')])
  46. return [body]
  47. else:
  48. print 'no handler for', split
  49. else:
  50. print 'split was', split
  51. start_response('404 Not Found', [('Content-type', 'text/plain')])
  52. return ['404 Not Found']
  53. except:
  54. traceback.print_exc()
  55. start_response('500 Internal Server Error', [('Content-type', 'text/plain')])
  56. return ['ruh roh']
  57. def get_data(split, query, environ):
  58. group = int(split[1])
  59. server_id = int(split[3])
  60. start = datetime.datetime.strptime(query['start'], '%Y-%m-%d').date()
  61. end = datetime.datetime.strptime(query['end'], '%Y-%m-%d').date()
  62. server_dir = path.join(DATA_DIR, str(group), str(server_id))
  63. rval = {}
  64. c = start
  65. while c <= end:
  66. date_str = c.isoformat()
  67. with open(path.join(server_dir, date_str), 'r') as f:
  68. stats = fileio.read_stats(f)
  69. rval[date_str] = stats
  70. c += datetime.timedelta(days=1)
  71. return rval
  72. def post_datum(split, query, environ):
  73. group = int(split[1])
  74. server_id = int(split[3])
  75. body = json.load(environ['wsgi.input'])
  76. server_dir = path.join(DATA_DIR, str(group), str(server_id))
  77. try:
  78. os.makedirs(server_dir)
  79. except OSError as e:
  80. if e.errno != errno.EEXIST:
  81. raise
  82. # we floor to the minute, so this rounds to the nearest minute
  83. now = datetime.datetime.utcnow() + datetime.timedelta(seconds=29)
  84. data_path = path.join(server_dir, now.date().isoformat())
  85. try:
  86. with open(data_path, 'r') as f:
  87. stats = fileio.read_stats(f)
  88. except IOError as e:
  89. if e.errno != errno.ENOENT:
  90. raise
  91. stats = copy.deepcopy(fileio.TEMPLATE)
  92. index = now.hour * 60 + now.minute
  93. data = {}
  94. for field, subfields in stats.items():
  95. field_data = {}
  96. if field == 'disk':
  97. disk = stats['disk']
  98. for mountpoint, datum in body['disk'].items(): # iterate through body to get new mountpoints
  99. disk.setdefault(mountpoint, {'total': [-1] * 1440, 'used': [-1] * 1440})
  100. field_data[mountpoint] = {}
  101. for subfield, array in disk[mountpoint].items():
  102. array = list(array)
  103. array[index] = datum[subfield]
  104. field_data[mountpoint][subfield] = array
  105. else:
  106. for subfield, array in subfields.items():
  107. array = list(array)
  108. array[index] = body[field][subfield]
  109. field_data[subfield] = array
  110. data[field] = field_data
  111. with open(data_path, 'w') as f:
  112. fileio.write_datum(f, data)
  113. return {'status': 'ok'}
  114. main()