ia64/xen-unstable

view tools/python/xen/xend/server/XMLRPCServer.py @ 12788:565cd8f32c70

Close the server when instructed, so that we can reload on the same port, and
diagnose a server that fails to start.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author Ewan Mellor <ewan@xensource.com>
date Mon Dec 04 13:57:18 2006 +0000 (2006-12-04)
parents bbcaa0cad3d2
children e45948c4dba4
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
25 from xen.xend import XendAPI, XendDomain, XendDomainInfo, XendNode
26 from xen.xend import XendLogging, XendDmesg
27 from xen.xend.XendClient import XML_RPC_SOCKET
28 from xen.xend.XendConstants import DOM_STATE_RUNNING
29 from xen.xend.XendLogging import log
30 from xen.xend.XendError import XendInvalidDomain
32 # vcpu_avail is a long and is not needed by the clients. It's far easier
33 # to just remove it then to try and marshal the long.
34 def fixup_sxpr(sexpr):
35 ret = []
36 for k in sexpr:
37 if type(k) in (types.ListType, types.TupleType):
38 if len(k) != 2 or k[0] != 'vcpu_avail':
39 ret.append(fixup_sxpr(k))
40 else:
41 ret.append(k)
42 return ret
44 def lookup(domid):
45 info = XendDomain.instance().domain_lookup(domid)
46 if not info:
47 raise XendInvalidDomain(str(domid))
48 return info
50 def dispatch(domid, fn, args):
51 info = lookup(domid)
52 return getattr(info, fn)(*args)
54 def domain(domid, full = 0):
55 info = lookup(domid)
56 return fixup_sxpr(info.sxpr(not full))
58 def domains(detail = True, full = False):
59 return domains_with_state(detail, DOM_STATE_RUNNING, full)
61 def domains_with_state(detail, state, full):
62 if detail:
63 domains = XendDomain.instance().list_sorted(state)
64 return map(lambda dom: fixup_sxpr(dom.sxpr(not full)), domains)
65 else:
66 return XendDomain.instance().list_names(state)
68 def domain_create(config):
69 info = XendDomain.instance().domain_create(config)
70 return fixup_sxpr(info.sxpr())
72 def domain_restore(src, paused=False):
73 info = XendDomain.instance().domain_restore(src, paused)
74 return fixup_sxpr(info.sxpr())
76 def get_log():
77 f = open(XendLogging.getLogFilename(), 'r')
78 try:
79 return f.read()
80 finally:
81 f.close()
83 methods = ['device_create', 'device_configure',
84 'destroyDevice','getDeviceSxprs',
85 'setMemoryTarget', 'setName', 'setVCpuCount', 'shutdown',
86 'send_sysrq', 'getVCPUInfo', 'waitForDevices',
87 'getRestartCount']
89 exclude = ['domain_create', 'domain_restore']
91 class XMLRPCServer:
92 def __init__(self, auth, use_tcp=False, host = "localhost", port = 8006,
93 path = XML_RPC_SOCKET, hosts_allowed = None):
94 self.use_tcp = use_tcp
95 self.port = port
96 self.host = host
97 self.path = path
98 self.hosts_allowed = hosts_allowed
100 self.ready = False
101 self.running = True
102 self.auth = auth
103 self.xenapi = XendAPI.XendAPI(auth)
105 def run(self):
106 authmsg = (self.auth == XendAPI.AUTH_NONE and
107 "; authentication has been disabled for this server." or
108 ".")
110 try:
111 if self.use_tcp:
112 log.info("Opening TCP XML-RPC server on %s%d%s",
113 self.host and '%s:' % self.host or
114 'all interfaces, port ',
115 self.port, authmsg)
116 self.server = TCPXMLRPCServer((self.host, self.port),
117 self.hosts_allowed,
118 logRequests = False)
119 else:
120 log.info("Opening Unix domain socket XML-RPC server on %s%s",
121 self.path, authmsg)
122 self.server = UnixXMLRPCServer(self.path, self.hosts_allowed,
123 logRequests = False)
124 except socket.error, exn:
125 log.error('Cannot start server: %s!', exn.args[1])
126 ready = True
127 running = False
128 return
130 # Register Xen API Functions
131 # -------------------------------------------------------------------
132 # exportable functions are ones that do not begin with '_'
133 # and has the 'api' attribute.
135 for meth_name in dir(self.xenapi):
136 meth = getattr(self.xenapi, meth_name)
137 if meth_name[0] != '_' and callable(meth) and hasattr(meth, 'api'):
138 self.server.register_function(meth, getattr(meth, 'api'))
140 # Legacy deprecated xm xmlrpc api
141 # --------------------------------------------------------------------
143 # Functions in XendDomainInfo
144 for name in methods:
145 fn = eval("lambda domid, *args: dispatch(domid, '%s', args)"%name)
146 self.server.register_function(fn, "xend.domain.%s" % name)
148 inst = XendDomain.instance()
150 for name in dir(inst):
151 fn = getattr(inst, name)
152 if name.startswith("domain_") and callable(fn):
153 if name not in exclude:
154 self.server.register_function(fn, "xend.domain.%s" % name[7:])
156 # Functions in XendNode and XendDmesg
157 for type, lst, n in [(XendNode, ['info'], 'node'),
158 (XendDmesg, ['info', 'clear'], 'node.dmesg')]:
159 inst = type.instance()
160 for name in lst:
161 self.server.register_function(getattr(inst, name),
162 "xend.%s.%s" % (n, name))
164 # A few special cases
165 self.server.register_function(domain, 'xend.domain')
166 self.server.register_function(domains, 'xend.domains')
167 self.server.register_function(domains_with_state,
168 'xend.domains_with_state')
169 self.server.register_function(get_log, 'xend.node.log')
170 self.server.register_function(domain_create, 'xend.domain.create')
171 self.server.register_function(domain_restore, 'xend.domain.restore')
173 self.server.register_introspection_functions()
174 self.ready = True
176 # Custom runloop so we can cleanup when exiting.
177 # -----------------------------------------------------------------
178 try:
179 self.server.socket.settimeout(1.0)
180 while self.running:
181 self.server.handle_request()
182 finally:
183 self.cleanup()
185 def cleanup(self):
186 log.debug("XMLRPCServer.cleanup()")
187 try:
188 self.server.socket.close()
189 except Exception, exn:
190 log.exception(exn)
191 pass
193 def shutdown(self):
194 self.running = False
195 self.ready = False