ia64/xen-unstable

view tools/python/xen/xend/server/XMLRPCServer.py @ 15853:0c14d0bf369e

Fix error message and wait time for xm block-detach command.

- Wait time
When xm requests a block device detach to xend, xm makes two
requests. At first, xm requests the block device detach by device
class 'vbd'. Next, xm requests the block device detaching by
device class 'tap'.
As a result, the wait time is 200 seconds because each of
the block device detaching requests causes time-out.
- Misleading error message
Because the last request is by device class 'tap' to xend,
the keyword "(tap)" is included in the error message.

This patch fixes the number of times of the block device detaching
request to one time. At first, xm makes inquiries about device
class of a detaching target device to xend. Then xm requires the
block device detaching by xend returned device class. The wait
time becomes 100 seconds because the block device detaching request
is one time. And the error message is also fixed.

Signed-off-by: Masaki Kanno <kanno.masaki@jp.fujitsu.com>
author kfraser@localhost.localdomain
date Fri Sep 07 11:30:18 2007 +0100 (2007-09-07)
parents 7e6ef2b914aa
children 5255eac35270
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) 2006 Anthony Liguori <aliguori@us.ibm.com>
16 # Copyright (C) 2006 XenSource Ltd.
17 #============================================================================
19 import errno
20 import socket
21 import types
22 import xmlrpclib
23 from xen.util.xmlrpclib2 import UnixXMLRPCServer, TCPXMLRPCServer
24 try:
25 from SSLXMLRPCServer import SSLXMLRPCServer
26 ssl_enabled = True
27 except ImportError:
28 ssl_enabled = False
30 from xen.xend import XendAPI, XendDomain, XendDomainInfo, XendNode
31 from xen.xend import XendLogging, XendDmesg
32 from xen.xend.XendClient import XML_RPC_SOCKET
33 from xen.xend.XendConstants import DOM_STATE_RUNNING
34 from xen.xend.XendLogging import log
35 from xen.xend.XendError import XendInvalidDomain
37 # vcpu_avail is a long and is not needed by the clients. It's far easier
38 # to just remove it then to try and marshal the long.
39 def fixup_sxpr(sexpr):
40 ret = []
41 for k in sexpr:
42 if type(k) in (list, tuple):
43 if len(k) != 2 or k[0] != 'vcpu_avail':
44 ret.append(fixup_sxpr(k))
45 else:
46 ret.append(k)
47 return ret
49 def lookup(domid):
50 info = XendDomain.instance().domain_lookup(domid)
51 return info
53 def dispatch(domid, fn, args):
54 info = lookup(domid)
55 return getattr(info, fn)(*args)
57 def domain(domid, full = 0):
58 info = lookup(domid)
59 return fixup_sxpr(info.sxpr(not full))
61 def domains(detail = True, full = False):
62 return domains_with_state(detail, DOM_STATE_RUNNING, full)
64 def domains_with_state(detail, state, full):
65 if detail:
66 domains = XendDomain.instance().list_sorted(state)
67 return map(lambda dom: fixup_sxpr(dom.sxpr(not full)), domains)
68 else:
69 return XendDomain.instance().list_names(state)
71 def domain_create(config):
72 info = XendDomain.instance().domain_create(config)
73 return fixup_sxpr(info.sxpr())
75 def domain_restore(src, paused=False):
76 info = XendDomain.instance().domain_restore(src, paused)
77 return fixup_sxpr(info.sxpr())
79 def get_log():
80 f = open(XendLogging.getLogFilename(), 'r')
81 try:
82 return f.read()
83 finally:
84 f.close()
86 methods = ['device_create', 'device_configure',
87 'destroyDevice','getDeviceSxprs',
88 'setMemoryTarget', 'setName', 'setVCpuCount', 'shutdown',
89 'send_sysrq', 'getVCPUInfo', 'waitForDevices',
90 'getRestartCount', 'getBlockDeviceClass']
92 exclude = ['domain_create', 'domain_restore']
94 class XMLRPCServer:
95 def __init__(self, auth, use_xenapi, use_tcp = False,
96 ssl_key_file = None, ssl_cert_file = None,
97 host = "localhost", port = 8006, path = XML_RPC_SOCKET,
98 hosts_allowed = None):
100 self.use_tcp = use_tcp
101 self.port = port
102 self.host = host
103 self.path = path
104 self.hosts_allowed = hosts_allowed
106 self.ssl_key_file = ssl_key_file
107 self.ssl_cert_file = ssl_cert_file
109 self.ready = False
110 self.running = True
111 self.auth = auth
112 self.xenapi = use_xenapi and XendAPI.XendAPI(auth) or None
114 def run(self):
115 authmsg = (self.auth == XendAPI.AUTH_NONE and
116 "; authentication has been disabled for this server." or
117 ".")
119 try:
120 if self.use_tcp:
121 using_ssl = self.ssl_key_file and self.ssl_cert_file
123 log.info("Opening %s XML-RPC server on %s%d%s",
124 using_ssl and 'HTTPS' or 'TCP',
125 self.host and '%s:' % self.host or
126 'all interfaces, port ',
127 self.port, authmsg)
129 if using_ssl:
130 if not ssl_enabled:
131 raise ValueError("pyOpenSSL not installed. "
132 "Unable to start HTTPS XML-RPC server")
133 self.server = SSLXMLRPCServer(
134 (self.host, self.port),
135 self.hosts_allowed,
136 self.xenapi is not None,
137 logRequests = False,
138 ssl_key_file = self.ssl_key_file,
139 ssl_cert_file = self.ssl_cert_file)
140 else:
141 self.server = TCPXMLRPCServer(
142 (self.host, self.port),
143 self.hosts_allowed,
144 self.xenapi is not None,
145 logRequests = False)
147 else:
148 log.info("Opening Unix domain socket XML-RPC server on %s%s",
149 self.path, authmsg)
150 self.server = UnixXMLRPCServer(self.path, self.hosts_allowed,
151 self.xenapi is not None,
152 logRequests = False)
153 except socket.error, exn:
154 log.error('Cannot start server: %s!', exn.args[1])
155 ready = True
156 running = False
157 return
158 except Exception, e:
159 log.exception('Cannot start server: %s!', e)
160 ready = True
161 running = False
162 return
164 # Register Xen API Functions
165 # -------------------------------------------------------------------
166 # exportable functions are ones that do not begin with '_'
167 # and has the 'api' attribute.
169 for meth_name in dir(self.xenapi):
170 if meth_name[0] != '_':
171 meth = getattr(self.xenapi, meth_name)
172 if callable(meth) and hasattr(meth, 'api'):
173 self.server.register_function(meth, getattr(meth, 'api'))
175 self.server.register_instance(XendAPI.XendAPIAsyncProxy(self.xenapi))
177 # Legacy deprecated xm xmlrpc api
178 # --------------------------------------------------------------------
180 # Functions in XendDomainInfo
181 for name in methods:
182 fn = eval("lambda domid, *args: dispatch(domid, '%s', args)"%name)
183 self.server.register_function(fn, "xend.domain.%s" % name)
185 inst = XendDomain.instance()
187 for name in dir(inst):
188 fn = getattr(inst, name)
189 if name.startswith("domain_") and callable(fn):
190 if name not in exclude:
191 self.server.register_function(fn, "xend.domain.%s" % name[7:])
193 # Functions in XendNode and XendDmesg
194 for type, lst, n in [(XendNode, ['info', 'send_debug_keys'], 'node'),
195 (XendDmesg, ['info', 'clear'], 'node.dmesg')]:
196 inst = type.instance()
197 for name in lst:
198 self.server.register_function(getattr(inst, name),
199 "xend.%s.%s" % (n, name))
201 # A few special cases
202 self.server.register_function(domain, 'xend.domain')
203 self.server.register_function(domains, 'xend.domains')
204 self.server.register_function(domains_with_state,
205 'xend.domains_with_state')
206 self.server.register_function(get_log, 'xend.node.log')
207 self.server.register_function(domain_create, 'xend.domain.create')
208 self.server.register_function(domain_restore, 'xend.domain.restore')
210 self.server.register_introspection_functions()
211 self.ready = True
213 # Custom runloop so we can cleanup when exiting.
214 # -----------------------------------------------------------------
215 try:
216 while self.running:
217 self.server.handle_request()
218 finally:
219 self.shutdown()
221 def cleanup(self):
222 log.debug('XMLRPCServer.cleanup()')
223 if hasattr(self, 'server'):
224 try:
225 # This is here to make sure the socket is actually
226 # cleaned up when close() is called. Otherwise
227 # SO_REUSEADDR doesn't take effect. To replicate,
228 # try 'xend reload' and look for EADDRINUSE.
229 #
230 # May be caued by us calling close() outside of
231 # the listen()ing thread.
232 self.server.socket.shutdown(2)
233 except socket.error, e:
234 pass # ignore any socket errors
235 try:
236 self.server.socket.close()
237 except socket.error, e:
238 pass
240 def shutdown(self):
241 self.running = False
242 if self.ready:
243 self.ready = False
244 self.cleanup()