server.py 2.3 KB

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