server.py 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. #!/usr/bin/env python
  2. import errno
  3. import json
  4. import os
  5. from os import path
  6. import struct
  7. import warnings
  8. warnings.filterwarnings('ignore', 'libevent')
  9. import gevent.pywsgi
  10. import reloader
  11. DATA_DIR = path.expanduser('~/sysvitals_data')
  12. handlers = None
  13. def main():
  14. global handlers
  15. handlers = {
  16. 'data': get_data,
  17. 'datum': post_datum,
  18. }
  19. server = gevent.pywsgi.WSGIServer(('0.0.0.0', 8892), application)
  20. reloader.init(server)
  21. server.serve_forever()
  22. def application(environ, start_response):
  23. split = environ['PATH_INFO'][1:].split('/')
  24. if split[0] == 'v1':
  25. handler = handlers.get(split[2])
  26. if handler:
  27. start_response('200 OK', [('Content-type', 'text/plain')])
  28. return [handler(split, environ)]
  29. else:
  30. print 'no handler for', split
  31. else:
  32. print 'split was', split
  33. formats = {
  34. 'cpu': 'f',
  35. 'mem': 'q',
  36. 'net': 'q',
  37. 'disk': 'q',
  38. }
  39. def get_data(split, environ):
  40. group = int(split[1])
  41. client_id = int(split[3])
  42. data_path = path.join(DATA_DIR, str(group), str(client_id))
  43. with open(data_path, 'r') as f:
  44. buf = f.read()
  45. rval = {}
  46. index = 0
  47. while index < len(buf):
  48. # read the key
  49. key_size = ord(buf[index])
  50. fmt = '%dp' % (key_size + 1)
  51. data = struct.unpack(fmt, buf[index:index+key_size+1])
  52. key = data[0]
  53. # get the format_code
  54. split = key.split('.')
  55. stat_group = split[0]
  56. format_code = formats[stat_group]
  57. # read the data
  58. fmt = '%dp 1440%s' % (key_size + 1, format_code)
  59. size = struct.calcsize(fmt)
  60. data = struct.unpack(fmt, buf[index:index+size])
  61. dict_insert(rval, split, data[1:])
  62. index += size
  63. return json.dumps(rval)
  64. def dict_insert(d, split, value):
  65. if len(split) > 1:
  66. d.setdefault(split[0], {})
  67. dict_insert(d[split[0]], split[1:], value)
  68. else:
  69. d[split[0]] = value
  70. def post_datum(split, environ):
  71. group = int(split[1])
  72. body = json.load(environ['wsgi.input'])
  73. client_id = body['client_id']
  74. group_dir = path.join(DATA_DIR, str(group))
  75. try:
  76. os.makedirs(group_dir)
  77. except OSError as e:
  78. if e.errno != errno.EEXIST:
  79. raise
  80. with open(path.join(group_dir, str(client_id)), 'w') as f:
  81. for stat_group, stats in body.items():
  82. if stat_group == 'client_id':
  83. continue
  84. format_code = formats[stat_group]
  85. for stat, data in stats.items():
  86. key = '%s.%s' % (stat_group, stat)
  87. write_stat(f, key.encode('utf-8'), format_code, data)
  88. return '{"status": "ok"}'
  89. def write_stat(f, key, format_code, data):
  90. fmt = '%dp 1440%s' % (len(key) + 1, format_code)
  91. array = [-1] * 1440
  92. array[0] = data
  93. f.write(struct.pack(fmt, key, *array))
  94. main()