qmemman_server.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. #!/usr/bin/python
  2. import SocketServer
  3. import thread
  4. import time
  5. import xen.lowlevel.xs
  6. import sys
  7. import os
  8. from qmemman import SystemState
  9. system_state = SystemState()
  10. global_lock = thread.allocate_lock()
  11. def only_in_first_list(l1, l2):
  12. ret=[]
  13. for i in l1:
  14. if not i in l2:
  15. ret.append(i)
  16. return ret
  17. def get_req_node(domain_id):
  18. return '/local/domain/'+domain_id+'/memory/meminfo'
  19. class WatchType:
  20. def __init__(self, fn, param):
  21. self.fn = fn
  22. self.param = param
  23. class XS_Watcher:
  24. def __init__(self):
  25. self.handle = xen.lowlevel.xs.xs()
  26. self.handle.watch('/vm', WatchType(XS_Watcher.dom_list_change, None))
  27. self.watch_token_dict = {}
  28. def dom_list_change(self, param):
  29. curr = self.handle.ls('', '/local/domain')
  30. if curr == None:
  31. return
  32. global_lock.acquire()
  33. for i in only_in_first_list(curr, self.watch_token_dict.keys()):
  34. watch = WatchType(XS_Watcher.request, i)
  35. self.watch_token_dict[i] = watch
  36. self.handle.watch(get_req_node(i), watch)
  37. system_state.add_domain(i)
  38. for i in only_in_first_list(self.watch_token_dict.keys(), curr):
  39. self.handle.unwatch(get_req_node(i), self.watch_token_dict[i])
  40. self.watch_token_dict.pop(i)
  41. system_state.del_domain(i)
  42. global_lock.release()
  43. def request(self, domain_id):
  44. ret = self.handle.read('', get_req_node(domain_id))
  45. if ret == None or ret == '':
  46. return
  47. global_lock.acquire()
  48. system_state.refresh_meminfo(domain_id, ret)
  49. global_lock.release()
  50. def watch_loop(self):
  51. # sys.stderr = file('/var/log/qubes/qfileexchgd.errors', 'a')
  52. while True:
  53. result = self.handle.read_watch()
  54. token = result[1]
  55. token.fn(self, token.param)
  56. class QMemmanReqHandler(SocketServer.BaseRequestHandler):
  57. """
  58. The RequestHandler class for our server.
  59. It is instantiated once per connection to the server, and must
  60. override the handle() method to implement communication to the
  61. client.
  62. """
  63. def handle(self):
  64. got_lock = False
  65. # self.request is the TCP socket connected to the client
  66. while True:
  67. self.data = self.request.recv(1024).strip()
  68. if len(self.data) == 0:
  69. print 'EOF'
  70. if got_lock:
  71. global_lock.release()
  72. return
  73. if got_lock:
  74. print 'Second request over qmemman.sock ?'
  75. return
  76. global_lock.acquire()
  77. got_lock = True
  78. if system_state.do_balloon(int(self.data)):
  79. resp = "OK\n"
  80. else:
  81. resp = "FAIL\n"
  82. self.request.send(resp)
  83. def start_server():
  84. SOCK_PATH='/var/run/qubes/qmemman.sock'
  85. try:
  86. os.unlink(SOCK_PATH)
  87. except:
  88. pass
  89. os.umask(0)
  90. server = SocketServer.UnixStreamServer(SOCK_PATH, QMemmanReqHandler)
  91. os.umask(077)
  92. server.serve_forever()
  93. class QMemmanServer:
  94. @staticmethod
  95. def main():
  96. thread.start_new_thread(start_server, tuple([]))
  97. XS_Watcher().watch_loop()