PageRenderTime 40ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/tools/python/xen/xend/server/SrvServer.py

https://gitlab.com/wkyu/gxen
Python | 261 lines | 219 code | 16 blank | 26 comment | 27 complexity | 0f6c7a7ebea8a126b2c86afd8bf186a2 MD5 | raw file
  1. #============================================================================
  2. # This library is free software; you can redistribute it and/or
  3. # modify it under the terms of version 2.1 of the GNU Lesser General Public
  4. # License as published by the Free Software Foundation.
  5. #
  6. # This library is distributed in the hope that it will be useful,
  7. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  9. # Lesser General Public License for more details.
  10. #
  11. # You should have received a copy of the GNU Lesser General Public
  12. # License along with this library; if not, write to the Free Software
  13. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  14. #============================================================================
  15. # Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com>
  16. # Copyright (C) 2006 XenSource Ltd.
  17. #============================================================================
  18. """Example xend HTTP
  19. Can be accessed from a browser or from a program.
  20. Do 'python SrvServer.py' to run the server.
  21. Then point a web browser at http://localhost:8000/xend and follow the links.
  22. Most are stubs, except /domain which has a list of domains and a 'create domain'
  23. button.
  24. You can also access the server from a program.
  25. Do 'python XendClient.py' to run a few test operations.
  26. The data served differs depending on the client (as defined by User-Agent
  27. and Accept in the HTTP headers). If the client is a browser, data
  28. is returned in HTML, with interactive forms. If the client is a program,
  29. data is returned in SXP format, with no forms.
  30. The server serves to the world by default. To restrict it to the local host
  31. change 'interface' in main().
  32. Mike Wray <mike.wray@hp.com>
  33. """
  34. # todo Support security settings etc. in the config file.
  35. # todo Support command-line args.
  36. import fcntl
  37. import re
  38. import time
  39. import signal
  40. from threading import Thread
  41. from xen.web.httpserver import HttpServer, UnixHttpServer
  42. from xen.xend import XendNode, XendOptions, XendAPI
  43. from xen.xend.XendLogging import log
  44. from xen.xend.XendClient import XEN_API_SOCKET
  45. from xen.xend.XendDomain import instance as xenddomain
  46. from xen.xend.XendCPUPool import XendCPUPool
  47. from xen.web.SrvDir import SrvDir
  48. from SrvRoot import SrvRoot
  49. from XMLRPCServer import XMLRPCServer
  50. xoptions = XendOptions.instance()
  51. class XendServers:
  52. def __init__(self, root):
  53. self.servers = []
  54. self.root = root
  55. self.running = False
  56. self.cleaningUp = False
  57. self.reloadingConfig = False
  58. def add(self, server):
  59. self.servers.append(server)
  60. def cleanup(self, signum = 0, frame = None, reloading = False):
  61. log.debug("SrvServer.cleanup()")
  62. self.cleaningUp = True
  63. for server in self.servers:
  64. try:
  65. server.shutdown()
  66. except:
  67. pass
  68. # clean up domains for those that have on_xend_stop
  69. if not reloading:
  70. xenddomain().cleanup_domains()
  71. self.running = False
  72. def reloadConfig(self, signum = 0, frame = None):
  73. log.debug("SrvServer.reloadConfig()")
  74. self.reloadingConfig = True
  75. self.cleanup(signum, frame, reloading = True)
  76. def start(self, status):
  77. # Running the network script will spawn another process, which takes
  78. # the status fd with it unless we set FD_CLOEXEC. Failing to do this
  79. # causes the read in SrvDaemon to hang even when we have written here.
  80. if status:
  81. fcntl.fcntl(status, fcntl.F_SETFD, fcntl.FD_CLOEXEC)
  82. # Prepare to catch SIGTERM (received when 'xend stop' is executed)
  83. # and call each server's cleanup if possible
  84. signal.signal(signal.SIGTERM, self.cleanup)
  85. signal.signal(signal.SIGHUP, self.reloadConfig)
  86. while True:
  87. threads = []
  88. for server in self.servers:
  89. if server.ready:
  90. continue
  91. thread = Thread(target=server.run,
  92. name=server.__class__.__name__)
  93. thread.setDaemon(True)
  94. thread.start()
  95. threads.append(thread)
  96. # check for when all threads have initialized themselves and then
  97. # close the status pipe
  98. retryCount = 0
  99. threads_left = True
  100. while threads_left:
  101. threads_left = False
  102. for server in self.servers:
  103. if not server.ready:
  104. threads_left = True
  105. break
  106. if threads_left:
  107. time.sleep(.5)
  108. retryCount += 1
  109. if retryCount > 60:
  110. for server in self.servers:
  111. if not server.ready:
  112. log.error("Server " +
  113. server.__class__.__name__ +
  114. " did not initialise!")
  115. break
  116. if status:
  117. status.write('0')
  118. status.close()
  119. status = None
  120. # auto start pools before domains are started
  121. try:
  122. XendCPUPool.autostart_pools()
  123. except Exception, e:
  124. log.exception("Failed while autostarting pools")
  125. # Reaching this point means we can auto start domains
  126. try:
  127. xenddomain().autostart_domains()
  128. except Exception, e:
  129. log.exception("Failed while autostarting domains")
  130. # loop to keep main thread alive until it receives a SIGTERM
  131. self.running = True
  132. while self.running:
  133. time.sleep(100000000)
  134. if self.reloadingConfig:
  135. log.info("Restarting all XML-RPC and Xen-API servers...")
  136. self.cleaningUp = False
  137. self.reloadingConfig = False
  138. xoptions.set_config()
  139. self.servers = []
  140. _loadConfig(self, self.root, True)
  141. else:
  142. break
  143. def _loadConfig(servers, root, reload):
  144. if xoptions.get_xend_http_server():
  145. servers.add(HttpServer(root,
  146. xoptions.get_xend_address(),
  147. xoptions.get_xend_port()))
  148. if xoptions.get_xend_unix_server():
  149. path = xoptions.get_xend_unix_path()
  150. log.info('unix path=' + path)
  151. servers.add(UnixHttpServer(root, path))
  152. api_cfg = xoptions.get_xen_api_server()
  153. if api_cfg:
  154. try:
  155. for server_cfg in api_cfg:
  156. # Parse the xen-api-server config
  157. ssl_key_file = None
  158. ssl_cert_file = None
  159. auth_method = XendAPI.AUTH_NONE
  160. hosts_allowed = None
  161. host_addr = server_cfg[0].split(':', 1)
  162. if len(host_addr) == 1:
  163. if host_addr[0].lower() == 'unix':
  164. use_tcp = False
  165. host = 'localhost'
  166. port = 0
  167. else:
  168. use_tcp = True
  169. host = ''
  170. port = int(host_addr[0])
  171. else:
  172. use_tcp = True
  173. host = str(host_addr[0])
  174. port = int(host_addr[1])
  175. if len(server_cfg) > 1:
  176. if server_cfg[1] in [XendAPI.AUTH_PAM, XendAPI.AUTH_NONE]:
  177. auth_method = server_cfg[1]
  178. if len(server_cfg) > 2 and len(server_cfg[2]):
  179. hosts_allowed = map(re.compile, server_cfg[2].split(' '))
  180. if len(server_cfg) > 4:
  181. # SSL key and cert file
  182. ssl_key_file = server_cfg[3]
  183. ssl_cert_file = server_cfg[4]
  184. servers.add(XMLRPCServer(auth_method, True, use_tcp = use_tcp,
  185. ssl_key_file = ssl_key_file,
  186. ssl_cert_file = ssl_cert_file,
  187. host = host, port = port,
  188. path = XEN_API_SOCKET,
  189. hosts_allowed = hosts_allowed))
  190. except (ValueError, TypeError), exn:
  191. log.exception('Xen API Server init failed')
  192. log.error('Xen-API server configuration %s is invalid.', api_cfg)
  193. if xoptions.get_xend_tcp_xmlrpc_server():
  194. addr = xoptions.get_xend_tcp_xmlrpc_server_address()
  195. port = xoptions.get_xend_tcp_xmlrpc_server_port()
  196. ssl_key_file = xoptions.get_xend_tcp_xmlrpc_server_ssl_key_file()
  197. ssl_cert_file = xoptions.get_xend_tcp_xmlrpc_server_ssl_cert_file()
  198. if ssl_key_file and ssl_cert_file:
  199. servers.add(XMLRPCServer(XendAPI.AUTH_PAM, False, use_tcp = True,
  200. ssl_key_file = ssl_key_file,
  201. ssl_cert_file = ssl_cert_file,
  202. host = addr, port = port))
  203. else:
  204. servers.add(XMLRPCServer(XendAPI.AUTH_PAM, False, use_tcp = True,
  205. host = addr, port = port))
  206. if xoptions.get_xend_unix_xmlrpc_server():
  207. servers.add(XMLRPCServer(XendAPI.AUTH_PAM, False))
  208. def create():
  209. root = SrvDir()
  210. root.putChild('xend', SrvRoot())
  211. servers = XendServers(root)
  212. _loadConfig(servers, root, False)
  213. return servers