ia64/xen-unstable

view tools/python/xen/xend/server/XMLRPCServer.py @ 13642:ba3ec84c9423

[XEND] Add missing ConsoleController.py

Signed-off-by: Alastair Tse <atse@xensource.com>
author Alastair Tse <atse@xensource.com>
date Fri Jan 26 02:44:35 2007 +0000 (2007-01-26)
parents 0843e4261753
children 5165b7ecbff5
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_xenapi, use_tcp=False, host = "localhost",
93 port = 8006, 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 = use_xenapi and XendAPI.XendAPI(auth) or None
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 self.xenapi is not None,
119 logRequests = False)
120 else:
121 log.info("Opening Unix domain socket XML-RPC server on %s%s",
122 self.path, authmsg)
123 self.server = UnixXMLRPCServer(self.path, self.hosts_allowed,
124 self.xenapi is not None,
125 logRequests = False)
126 except socket.error, exn:
127 log.error('Cannot start server: %s!', exn.args[1])
128 ready = True
129 running = False
130 return
132 # Register Xen API Functions
133 # -------------------------------------------------------------------
134 # exportable functions are ones that do not begin with '_'
135 # and has the 'api' attribute.
137 for meth_name in dir(self.xenapi):
138 if meth_name[0] != '_':
139 meth = getattr(self.xenapi, meth_name)
140 if callable(meth) and hasattr(meth, 'api'):
141 self.server.register_function(meth, getattr(meth, 'api'))
143 self.server.register_instance(XendAPI.XendAPIAsyncProxy(self.xenapi))
145 # Legacy deprecated xm xmlrpc api
146 # --------------------------------------------------------------------
148 # Functions in XendDomainInfo
149 for name in methods:
150 fn = eval("lambda domid, *args: dispatch(domid, '%s', args)"%name)
151 self.server.register_function(fn, "xend.domain.%s" % name)
153 inst = XendDomain.instance()
155 for name in dir(inst):
156 fn = getattr(inst, name)
157 if name.startswith("domain_") and callable(fn):
158 if name not in exclude:
159 self.server.register_function(fn, "xend.domain.%s" % name[7:])
161 # Functions in XendNode and XendDmesg
162 for type, lst, n in [(XendNode, ['info'], 'node'),
163 (XendDmesg, ['info', 'clear'], 'node.dmesg')]:
164 inst = type.instance()
165 for name in lst:
166 self.server.register_function(getattr(inst, name),
167 "xend.%s.%s" % (n, name))
169 # A few special cases
170 self.server.register_function(domain, 'xend.domain')
171 self.server.register_function(domains, 'xend.domains')
172 self.server.register_function(domains_with_state,
173 'xend.domains_with_state')
174 self.server.register_function(get_log, 'xend.node.log')
175 self.server.register_function(domain_create, 'xend.domain.create')
176 self.server.register_function(domain_restore, 'xend.domain.restore')
178 self.server.register_introspection_functions()
179 self.ready = True
181 # Custom runloop so we can cleanup when exiting.
182 # -----------------------------------------------------------------
183 try:
184 while self.running:
185 self.server.handle_request()
186 finally:
187 self.shutdown()
189 def cleanup(self):
190 log.debug('XMLRPCServer.cleanup()')
191 if hasattr(self, 'server'):
192 try:
193 # This is here to make sure the socket is actually
194 # cleaned up when close() is called. Otherwise
195 # SO_REUSEADDR doesn't take effect. To replicate,
196 # try 'xend reload' and look for EADDRINUSE.
197 #
198 # May be caued by us calling close() outside of
199 # the listen()ing thread.
200 self.server.socket.shutdown(2)
201 except socket.error, e:
202 pass # ignore any socket errors
203 try:
204 self.server.socket.close()
205 except socket.error, e:
206 pass
208 def shutdown(self):
209 self.running = False
210 if self.ready:
211 self.ready = False
212 self.cleanup()