ia64/xen-unstable

view tools/python/xen/xend/server/SrvServer.py @ 14701:870133a06f43

xend: Map re.compile on hosts_allow for XMLRPCServer.

Changeset 14601 removed a re.compile() map on hosts_allow,
hence breaking the tcp xmlrpc api ('str' has no attribute match
in xend-debug.log).

From: Pascal Bouchareine <pascal@gandi.net>
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Mon Apr 02 17:34:00 2007 +0100 (2007-04-02)
parents 121fb4046945
children 189efb0b27f9
line source
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 #============================================================================
19 """Example xend HTTP
21 Can be accessed from a browser or from a program.
22 Do 'python SrvServer.py' to run the server.
23 Then point a web browser at http://localhost:8000/xend and follow the links.
24 Most are stubs, except /domain which has a list of domains and a 'create domain'
25 button.
27 You can also access the server from a program.
28 Do 'python XendClient.py' to run a few test operations.
30 The data served differs depending on the client (as defined by User-Agent
31 and Accept in the HTTP headers). If the client is a browser, data
32 is returned in HTML, with interactive forms. If the client is a program,
33 data is returned in SXP format, with no forms.
35 The server serves to the world by default. To restrict it to the local host
36 change 'interface' in main().
38 Mike Wray <mike.wray@hp.com>
39 """
40 # todo Support security settings etc. in the config file.
41 # todo Support command-line args.
43 import fcntl
44 import re
45 import time
46 import signal
47 from threading import Thread
49 from xen.web.httpserver import HttpServer, UnixHttpServer
51 from xen.xend import XendNode, XendOptions, XendAPI
52 from xen.xend import Vifctl
53 from xen.xend.XendLogging import log
54 from xen.xend.XendClient import XEN_API_SOCKET
55 from xen.xend.XendDomain import instance as xenddomain
56 from xen.web.SrvDir import SrvDir
58 from SrvRoot import SrvRoot
59 from XMLRPCServer import XMLRPCServer
61 xoptions = XendOptions.instance()
64 class XendServers:
66 def __init__(self, root):
67 self.servers = []
68 self.root = root
69 self.running = False
70 self.cleaningUp = False
71 self.reloadingConfig = False
73 def add(self, server):
74 self.servers.append(server)
76 def cleanup(self, signum = 0, frame = None, reloading = False):
77 log.debug("SrvServer.cleanup()")
78 self.cleaningUp = True
79 for server in self.servers:
80 try:
81 server.shutdown()
82 except:
83 pass
85 # clean up domains for those that have on_xend_stop
86 if not reloading:
87 xenddomain().cleanup_domains()
89 self.running = False
92 def reloadConfig(self, signum = 0, frame = None):
93 log.debug("SrvServer.reloadConfig()")
94 self.reloadingConfig = True
95 self.cleanup(signum, frame, reloading = True)
97 def start(self, status):
98 # Running the network script will spawn another process, which takes
99 # the status fd with it unless we set FD_CLOEXEC. Failing to do this
100 # causes the read in SrvDaemon to hang even when we have written here.
101 if status:
102 fcntl.fcntl(status, fcntl.F_SETFD, fcntl.FD_CLOEXEC)
104 Vifctl.network('start')
106 # Prepare to catch SIGTERM (received when 'xend stop' is executed)
107 # and call each server's cleanup if possible
108 signal.signal(signal.SIGTERM, self.cleanup)
109 signal.signal(signal.SIGHUP, self.reloadConfig)
111 while True:
112 XendNode.instance().refreshBridges()
114 threads = []
115 for server in self.servers:
116 if server.ready:
117 continue
119 thread = Thread(target=server.run,
120 name=server.__class__.__name__)
121 thread.setDaemon(True)
122 thread.start()
123 threads.append(thread)
125 # check for when all threads have initialized themselves and then
126 # close the status pipe
128 retryCount = 0
129 threads_left = True
130 while threads_left:
131 threads_left = False
133 for server in self.servers:
134 if not server.ready:
135 threads_left = True
136 break
138 if threads_left:
139 time.sleep(.5)
140 retryCount += 1
141 if retryCount > 60:
142 for server in self.servers:
143 if not server.ready:
144 log.error("Server " +
145 server.__class__.__name__ +
146 " did not initialise!")
147 break
149 if status:
150 status.write('0')
151 status.close()
152 status = None
154 # Reaching this point means we can auto start domains
155 try:
156 xenddomain().autostart_domains()
157 except Exception, e:
158 log.exception("Failed while autostarting domains")
160 # loop to keep main thread alive until it receives a SIGTERM
161 self.running = True
162 while self.running:
163 time.sleep(100000000)
165 if self.reloadingConfig:
166 log.info("Restarting all XML-RPC and Xen-API servers...")
167 self.cleaningUp = False
168 self.reloadingConfig = False
169 xoptions.set_config()
170 self.servers = []
171 _loadConfig(self, self.root, True)
172 else:
173 break
175 def _loadConfig(servers, root, reload):
176 if xoptions.get_xend_http_server():
177 servers.add(HttpServer(root,
178 xoptions.get_xend_address(),
179 xoptions.get_xend_port()))
180 if xoptions.get_xend_unix_server():
181 path = xoptions.get_xend_unix_path()
182 log.info('unix path=' + path)
183 servers.add(UnixHttpServer(root, path))
185 api_cfg = xoptions.get_xen_api_server()
186 if api_cfg:
187 try:
188 for server_cfg in api_cfg:
189 # Parse the xen-api-server config
191 ssl_key_file = None
192 ssl_cert_file = None
193 auth_method = XendAPI.AUTH_NONE
194 hosts_allowed = None
196 host_addr = server_cfg[0].split(':', 1)
197 if len(host_addr) == 1:
198 if host_addr[0].lower() == 'unix':
199 use_tcp = False
200 host = 'localhost'
201 port = 0
202 else:
203 use_tcp = True
204 host = ''
205 port = int(host_addr[0])
206 else:
207 use_tcp = True
208 host = str(host_addr[0])
209 port = int(host_addr[1])
211 if len(server_cfg) > 1:
212 if server_cfg[1] in [XendAPI.AUTH_PAM, XendAPI.AUTH_NONE]:
213 auth_method = server_cfg[1]
215 if len(server_cfg) > 2 and len(server_cfg[2]):
216 hosts_allowed = map(re.compile, server_cfg[2].split(' '))
218 if len(server_cfg) > 4:
219 # SSL key and cert file
220 ssl_key_file = server_cfg[3]
221 ssl_cert_file = server_cfg[4]
224 servers.add(XMLRPCServer(auth_method, True, use_tcp = use_tcp,
225 ssl_key_file = ssl_key_file,
226 ssl_cert_file = ssl_cert_file,
227 host = host, port = port,
228 path = XEN_API_SOCKET,
229 hosts_allowed = hosts_allowed))
231 except (ValueError, TypeError), exn:
232 log.exception('Xen API Server init failed')
233 log.error('Xen-API server configuration %s is invalid.', api_cfg)
235 if xoptions.get_xend_tcp_xmlrpc_server():
236 addr = xoptions.get_xend_tcp_xmlrpc_server_address()
237 port = xoptions.get_xend_tcp_xmlrpc_server_port()
238 ssl_key_file = xoptions.get_xend_tcp_xmlrpc_server_ssl_key_file()
239 ssl_cert_file = xoptions.get_xend_tcp_xmlrpc_server_ssl_cert_file()
241 if ssl_key_file and ssl_cert_file:
242 servers.add(XMLRPCServer(XendAPI.AUTH_PAM, False, use_tcp = True,
243 ssl_key_file = ssl_key_file,
244 ssl_cert_file = ssl_cert_file,
245 host = addr, port = port))
246 else:
247 servers.add(XMLRPCServer(XendAPI.AUTH_PAM, False, use_tcp = True,
248 host = addr, port = port))
250 if xoptions.get_xend_unix_xmlrpc_server():
251 servers.add(XMLRPCServer(XendAPI.AUTH_PAM, False))
254 def create():
255 root = SrvDir()
256 root.putChild('xend', SrvRoot())
257 servers = XendServers(root)
258 _loadConfig(servers, root, False)
259 return servers