# HG changeset patch
# User anthony@xxxxxxxxxxxxxxxxxxxxx
# Node ID 095ac0d95d9cc154ec8fc3dba1a67f02f79771ac
# Parent c369d960f96ba4fd7c9c6920cfa60c46a764323c
Add an XML-RPC interface to Xend.
This introduces a enhanced client library (xmlrpclib2) that supports XML-RPC
over a domain socket (also working around a bug in Python's handling of NIL).
This also introduces a new server that runs along side of the existing
S-Expression/HTTP server.
This changeset makes no change to the normal operation of Xend. xm still goes
through S-Expression/HTTP -- there's just another option for interacting with
Xend.
Signed-off-by: Anthony Liguori <aliguori@xxxxxxxxxx>
diff -r c369d960f96b -r 095ac0d95d9c tools/python/xen/xend/server/SrvServer.py
--- a/tools/python/xen/xend/server/SrvServer.py Tue Feb 28 16:45:20 2006
+++ b/tools/python/xen/xend/server/SrvServer.py Tue Feb 28 22:08:47 2006
@@ -51,6 +51,7 @@
from xen.web.SrvDir import SrvDir
from SrvRoot import SrvRoot
+from XMLRPCServer import XMLRPCServer
xroot = XendRoot.instance()
@@ -113,4 +114,5 @@
path = xroot.get_xend_unix_path()
log.info('unix path=' + path)
servers.add(UnixHttpServer(path=path, root=root))
+ servers.add(XMLRPCServer())
return servers
diff -r c369d960f96b -r 095ac0d95d9c tools/python/xen/util/xmlrpclib2.py
--- /dev/null Tue Feb 28 16:45:20 2006
+++ b/tools/python/xen/util/xmlrpclib2.py Tue Feb 28 22:08:47 2006
@@ -0,0 +1,109 @@
+#============================================================================
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General Public
+# License as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#============================================================================
+# Copyright (C) 2006 Anthony Liguori <aliguori@xxxxxxxxxx>
+#============================================================================
+
+"""
+An enhanced XML-RPC client/server interface for Python.
+"""
+
+from httplib import HTTPConnection, HTTP
+from xmlrpclib import Transport
+from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler
+import xmlrpclib, socket, os, traceback
+
+# A new ServerProxy that also supports httpu urls. An http URL comes in the
+# form:
+#
+# httpu:///absolute/path/to/socket.sock
+#
+# It assumes that the RPC handler is /RPC2. This problem needs to be improved
+
+class HTTPUnixConnection(HTTPConnection):
+ def connect(self):
+ self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+ self.sock.connect(self.host)
+
+class HTTPUnix(HTTP):
+ _connection_class = HTTPUnixConnection
+
+class UnixTransport(Transport):
+ def request(self, host, handler, request_body, verbose=0):
+ self.__handler = handler
+ return Transport.request(self, host, '/RPC2', request_body, verbose)
+ def make_connection(self, host):
+ return HTTPUnix(self.__handler)
+
+class ServerProxy(xmlrpclib.ServerProxy):
+ def __init__(self, uri, transport=None, encoding=None, verbose=0,
+ allow_none=1):
+ if transport == None:
+ protocol = uri.split(':')[0]
+ if protocol == 'httpu':
+ uri = 'http:' + ':'.join(uri.split(':')[1:])
+ transport = UnixTransport()
+ xmlrpclib.ServerProxy.__init__(self, uri, transport, encoding,
+ verbose, allow_none)
+
+# This is a base XML-RPC server for TCP. It sets allow_reuse_address to
+# true, and has an improved marshaller that serializes unknown exceptions
+# with full traceback information.
+
+class TCPXMLRPCServer(SimpleXMLRPCServer):
+ allow_reuse_address = True
+
+ def _marshaled_dispatch(self, data, dispatch_method = None):
+ params, method = xmlrpclib.loads(data)
+ try:
+ if dispatch_method is not None:
+ response = dispatch_method(method, params)
+ else:
+ response = self._dispatch(method, params)
+
+ response = (response,)
+ response = xmlrpclib.dumps(response,
+ methodresponse=1,
+ allow_none=1)
+ except xmlrpclib.Fault, fault:
+ response = xmlrpclib.dumps(exc)
+ except:
+ response = xmlrpclib.dumps(
+ xmlrpclib.Fault(1, traceback.format_exc())
+ )
+
+ return response
+
+# This is a XML-RPC server that sits on a Unix domain socket.
+# It implements proper support for allow_reuse_address by
+# unlink()'ing an existing socket.
+
+class UnixXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
+ def address_string(self):
+ try:
+ return SimpleXMLRPCRequestHandler.address_string(self)
+ except ValueError, e:
+ return self.client_address[:2]
+
+class UnixXMLRPCServer(TCPXMLRPCServer):
+ address_family = socket.AF_UNIX
+
+ def __init__(self, addr, requestHandler=UnixXMLRPCRequestHandler,
+ logRequests=1):
+ if self.allow_reuse_address:
+ try:
+ os.unlink(addr)
+ except OSError, exc:
+ pass
+ TCPXMLRPCServer.__init__(self, addr, requestHandler, logRequests)
diff -r c369d960f96b -r 095ac0d95d9c
tools/python/xen/xend/server/XMLRPCServer.py
--- /dev/null Tue Feb 28 16:45:20 2006
+++ b/tools/python/xen/xend/server/XMLRPCServer.py Tue Feb 28 22:08:47 2006
@@ -0,0 +1,97 @@
+#============================================================================
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General Public
+# License as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#============================================================================
+# Copyright (C) 2006 Anthony Liguori <aliguori@xxxxxxxxxx>
+#============================================================================
+
+from xen.xend import (XendDomain, XendDomainInfo, XendNode,
+ XendLogging, XendDmesg)
+from xen.util.xmlrpclib2 import UnixXMLRPCServer
+
+def lookup(domid):
+ return XendDomain.instance().domain_lookup_by_name_or_id(domid)
+
+def dispatch(domid, fn, args):
+ info = lookup(domid)
+ return getattr(info, fn)(*args)
+
+def domain(domid):
+ info = lookup(domid)
+ return info.sxpr()
+
+def domains(detail=1):
+ if detail < 1:
+ return XendDomain.instance().list_names()
+ else:
+ domains = XendDomain.instance().list_sorted()
+ return map(lambda dom: dom.sxpr(), domains)
+
+def domain_create(config):
+ info = XendDomain.instance().domain_create(config)
+ return info.sxpr()
+
+def domain_restore(src):
+ info = XendDomain.instance().domain_restore(src)
+ return info.sxpr()
+
+def get_log():
+ f = open(XendLogging.getLogFilename(), 'r')
+ ret = f.read()
+ f.close()
+ return ret
+
+methods = ['device_create', 'destroyDevice', 'getDeviceSxprs',
+ 'setMemoryTarget', 'setName', 'setVCpuCount', 'shutdown',
+ 'send_sysrq', 'getVCPUInfo', 'waitForDevices']
+
+exclude = ['domain_create', 'domain_restore']
+
+class XMLRPCServer:
+ def __init__(self):
+ self.ready = False
+
+ def run(self):
+ self.server = UnixXMLRPCServer("/var/run/xend-xmlrpc.sock")
+
+ # Functions in XendDomainInfo
+ for name in methods:
+ fn = eval("lambda domid, *args: dispatch(domid, '%s', args)"%name)
+ self.server.register_function(fn, "xend.domain.%s" % name)
+
+ # Functions in XendDomain
+ inst = XendDomain.instance()
+ for name in dir(inst):
+ fn = getattr(inst, name)
+ if name.startswith("domain_") and callable(fn):
+ if name not in exclude:
+ self.server.register_function(fn, "xend.domain.%s" %
name[7:])
+
+ # Functions in XendNode and XendDmesg
+ for type, lst, n in [(XendNode, ['info', 'cpu_bvt_slice_set'], 'node'),
+ (XendDmesg, ['info', 'clear'], 'node.dmesg')]:
+ inst = type.instance()
+ for name in lst:
+ self.server.register_function(getattr(inst, name),
+ "xend.%s.%s" % (n, name))
+
+ # A few special cases
+ self.server.register_function(domain, 'xend.domain')
+ self.server.register_function(domains, 'xend.domains')
+ self.server.register_function(get_log, 'xend.node.log')
+ self.server.register_function(domain_create, 'xend.domain.create')
+ self.server.register_function(domain_restore, 'xend.domain.restore')
+
+ self.server.register_introspection_functions()
+ self.ready = True
+ self.server.serve_forever()
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|