debuggers.hg
changeset 4655:a838a908e38e
bitkeeper revision 1.1327.2.2 (4267a9b3MhPpljnjQ5IbfLdzcW2K3w)
Remove twisted from the HTTP server and replace with a
threaded server. Add classes to provide tcp and unix servers
using threads instead of twisted. Remove use of twisted from
the consoles, event server and HTTP resources
Signed-off-by: Mike Wray <mike.wray@hp.com>
Remove twisted from the HTTP server and replace with a
threaded server. Add classes to provide tcp and unix servers
using threads instead of twisted. Remove use of twisted from
the consoles, event server and HTTP resources
Signed-off-by: Mike Wray <mike.wray@hp.com>
line diff
1.1 --- a/.rootkeys Wed Apr 20 08:45:19 2005 +0000 1.2 +++ b/.rootkeys Thu Apr 21 13:25:07 2005 +0000 1.3 @@ -879,6 +879,19 @@ 4055ee4dwy4l0MghZosxoiu6zmhc9Q tools/pyt 1.4 40c9c468IienauFHQ_xJIcqnPJ8giQ tools/python/xen/util/ip.py 1.5 41dde8b0yuJX-S79w4xJKxBQ-Mhp1A tools/python/xen/util/memmap.py 1.6 4059c6a0pnxhG8hwSOivXybbGOwuXw tools/python/xen/util/tempfile.py 1.7 +4267a9b16u4IEPhjRryesk6A17sobA tools/python/xen/web/SrvBase.py 1.8 +4267a9b1FfCUjW7m9anLERcx9lwhJg tools/python/xen/web/SrvDir.py 1.9 +4267a9b1uMXIfzB6-81ZLqMCyTgJmw tools/python/xen/web/__init__.py 1.10 +4267a9b1i_zVq36tt2iQejVuR6DGFw tools/python/xen/web/connection.py 1.11 +4267a9b1Z2SpO9v-zEDApywETZPDwA tools/python/xen/web/defer.py 1.12 +4267a9b1KzSWZwWKYrGRc9bUhow_7Q tools/python/xen/web/http.py 1.13 +4267a9b1KWNZhhmZnySe_nLASwO47g tools/python/xen/web/httpserver.py 1.14 +4267a9b21miObgEJLAgtLTAKRBK8uQ tools/python/xen/web/protocol.py 1.15 +4267a9b2pA22-lF37dB7XfapMNroGw tools/python/xen/web/reactor.py 1.16 +4267a9b2AbH-azu7SXIUETXC39tu-A tools/python/xen/web/resource.py 1.17 +4267a9b21XhDCpkVXtgea3ko8uS16g tools/python/xen/web/static.py 1.18 +4267a9b2q7UA0cU5-KATCWX6O-TKsA tools/python/xen/web/tcp.py 1.19 +4267a9b2XqvzKDWxfAdV22c3mO6NHA tools/python/xen/web/unix.py 1.20 40c9c468SNuObE_YWARyS0hzTPSzKg tools/python/xen/xend/Args.py 1.21 41597996WNvJA-DVCBmc0xU9w_XmoA tools/python/xen/xend/Blkctl.py 1.22 40c9c468Um_qc66OQeLEceIz1pgD5g tools/python/xen/xend/EventServer.py 1.23 @@ -907,7 +920,6 @@ 40c9c468DCpMe542varOolW1Xc68ew tools/pyt 1.24 40c9c468IxQabrKJSWs0aEjl-27mRQ tools/python/xen/xend/server/SrvConsole.py 1.25 40c9c4689Io5bxfbYIfRiUvsiLX0EQ tools/python/xen/xend/server/SrvConsoleDir.py 1.26 40c9c468woSmBByfeXA4o_jGf2gCgA tools/python/xen/xend/server/SrvDaemon.py 1.27 -40c9c468kACsmkqjxBWKHRo071L26w tools/python/xen/xend/server/SrvDeviceDir.py 1.28 40c9c468EQZJVkCLds-OhesJVVyZbQ tools/python/xen/xend/server/SrvDir.py 1.29 40eee3a0m38EwYXfCSFIjWNwG6jx_A tools/python/xen/xend/server/SrvDmesg.py 1.30 40c9c468TyHZUq8sk0FF_vxM6Sozrg tools/python/xen/xend/server/SrvDomain.py 1.31 @@ -924,7 +936,6 @@ 40c9c4692hckPol_EK0EGB16ZyDsyQ tools/pyt 1.32 40c9c469N2-b3GqpLHHHPZykJPLVvA tools/python/xen/xend/server/channel.py 1.33 40c9c469hJ_IlatRne-9QEa0-wlquw tools/python/xen/xend/server/console.py 1.34 40c9c469UcNJh_NuLU0ytorM0Lk5Ow tools/python/xen/xend/server/controller.py 1.35 -40d83983OXjt-y3HjSCcuoPp9rzvmw tools/python/xen/xend/server/domain.py 1.36 4266169exkN9o3hA8vxe8Er0BZv1Xw tools/python/xen/xend/server/event.py 1.37 40c9c469yrm31i60pGKslTi2Zgpotg tools/python/xen/xend/server/messages.py 1.38 40c9c46925x-Rjb0Cv2f1-l2jZrPYg tools/python/xen/xend/server/netif.py
2.1 --- a/tools/python/setup.py Wed Apr 20 08:45:19 2005 +0000 2.2 +++ b/tools/python/setup.py Thu Apr 21 13:25:07 2005 +0000 2.3 @@ -43,6 +43,7 @@ setup(name = 'xen', 2.4 'xen.xend.server', 2.5 'xen.sv', 2.6 'xen.xm', 2.7 + 'xen.web', 2.8 ], 2.9 ext_package = "xen.lowlevel", 2.10 ext_modules = [ xc, xu ]
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/tools/python/xen/web/SrvBase.py Thu Apr 21 13:25:07 2005 +0000 3.3 @@ -0,0 +1,160 @@ 3.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com> 3.5 + 3.6 +import types 3.7 + 3.8 +from xen.xend import sxp 3.9 +from xen.xend import PrettyPrint 3.10 +from xen.xend.Args import ArgError 3.11 +from xen.xend.XendError import XendError 3.12 +from xen.xend.XendLogging import log 3.13 + 3.14 +import resource 3.15 +import http 3.16 +import defer 3.17 + 3.18 +def uri_pathlist(p): 3.19 + """Split a path into a list. 3.20 + p path 3.21 + return list of path elements 3.22 + """ 3.23 + l = [] 3.24 + for x in p.split('/'): 3.25 + if x == '': continue 3.26 + l.append(x) 3.27 + return l 3.28 + 3.29 +class SrvBase(resource.Resource): 3.30 + """Base class for services. 3.31 + """ 3.32 + 3.33 + 3.34 + def use_sxp(self, req): 3.35 + """Determine whether to send an SXP response to a request. 3.36 + Uses SXP if there is no User-Agent, no Accept, or application/sxp is in Accept. 3.37 + 3.38 + req request 3.39 + returns 1 for SXP, 0 otherwise 3.40 + """ 3.41 + ok = 0 3.42 + user_agent = req.getHeader('User-Agent') 3.43 + accept = req.getHeader('Accept') 3.44 + if (not user_agent) or (not accept) or (accept.find(sxp.mime_type) >= 0): 3.45 + ok = 1 3.46 + return ok 3.47 + 3.48 + def get_op_method(self, op): 3.49 + """Get the method for an operation. 3.50 + For operation 'foo' looks for 'op_foo'. 3.51 + 3.52 + op operation name 3.53 + returns method or None 3.54 + """ 3.55 + op_method_name = 'op_' + op 3.56 + return getattr(self, op_method_name, None) 3.57 + 3.58 + def perform(self, req): 3.59 + """General operation handler for posted operations. 3.60 + For operation 'foo' looks for a method op_foo and calls 3.61 + it with op_foo(op, req). Replies with code 500 if op_foo 3.62 + is not found. 3.63 + 3.64 + The method must return a list when req.use_sxp is true 3.65 + and an HTML string otherwise (or list). 3.66 + Methods may also return a Deferred (for incomplete processing). 3.67 + 3.68 + req request 3.69 + """ 3.70 + op = req.args.get('op') 3.71 + if op is None or len(op) != 1: 3.72 + req.setResponseCode(http.NOT_ACCEPTABLE, "Invalid request") 3.73 + return '' 3.74 + op = op[0] 3.75 + op_method = self.get_op_method(op) 3.76 + if op_method is None: 3.77 + req.setResponseCode(http.NOT_IMPLEMENTED, "Operation not implemented: " + op) 3.78 + req.setHeader("Content-Type", "text/plain") 3.79 + req.write("Operation not implemented: " + op) 3.80 + return '' 3.81 + else: 3.82 + return self._perform(op, op_method, req) 3.83 + 3.84 + def _perform(self, op, op_method, req): 3.85 + try: 3.86 + val = op_method(op, req) 3.87 + except Exception, err: 3.88 + self._perform_err(err, op, req) 3.89 + return '' 3.90 + 3.91 + if isinstance(val, defer.Deferred): 3.92 + val.addCallback(self._perform_cb, op, req, dfr=1) 3.93 + val.addErrback(self._perform_err, op, req, dfr=1) 3.94 + return server.NOT_DONE_YET 3.95 + else: 3.96 + self._perform_cb(val, op, req, dfr=0) 3.97 + return '' 3.98 + 3.99 + def _perform_cb(self, val, op, req, dfr=0): 3.100 + """Callback to complete the request. 3.101 + May be called from a Deferred. 3.102 + 3.103 + @param err: the error 3.104 + @param req: request causing the error 3.105 + @param dfr: deferred flag 3.106 + """ 3.107 + if isinstance(val, resource.ErrorPage): 3.108 + req.write(val.render(req)) 3.109 + elif self.use_sxp(req): 3.110 + req.setHeader("Content-Type", sxp.mime_type) 3.111 + sxp.show(val, out=req) 3.112 + else: 3.113 + req.write('<html><head></head><body>') 3.114 + self.print_path(req) 3.115 + if isinstance(val, types.ListType): 3.116 + req.write('<code><pre>') 3.117 + PrettyPrint.prettyprint(val, out=req) 3.118 + req.write('</pre></code>') 3.119 + else: 3.120 + req.write(str(val)) 3.121 + req.write('</body></html>') 3.122 + if dfr: 3.123 + req.finish() 3.124 + 3.125 + def _perform_err(self, err, op, req, dfr=0): 3.126 + """Error callback to complete a request. 3.127 + May be called from a Deferred. 3.128 + 3.129 + @param err: the error 3.130 + @param req: request causing the error 3.131 + @param dfr: deferred flag 3.132 + """ 3.133 + if not (isinstance(err, ArgError) or 3.134 + isinstance(err, sxp.ParseError) or 3.135 + isinstance(err, XendError)): 3.136 + if dfr: 3.137 + return err 3.138 + else: 3.139 + raise 3.140 + #log.exception("op=%s: %s", op, str(err)) 3.141 + if self.use_sxp(req): 3.142 + req.setHeader("Content-Type", sxp.mime_type) 3.143 + sxp.show(['xend.err', str(err)], out=req) 3.144 + else: 3.145 + req.setHeader("Content-Type", "text/plain") 3.146 + req.write('Error ') 3.147 + req.write(': ') 3.148 + req.write(str(err)) 3.149 + if dfr: 3.150 + req.finish() 3.151 + 3.152 + 3.153 + def print_path(self, req): 3.154 + """Print the path with hyperlinks. 3.155 + """ 3.156 + pathlist = [x for x in req.prepath if x != '' ] 3.157 + s = "/" 3.158 + req.write('<h1><a href="/">/</a>') 3.159 + for x in pathlist: 3.160 + s += x + "/" 3.161 + req.write(' <a href="%s">%s</a>/' % (s, x)) 3.162 + req.write("</h1>") 3.163 +
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/tools/python/xen/web/SrvDir.py Thu Apr 21 13:25:07 2005 +0000 4.3 @@ -0,0 +1,115 @@ 4.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com> 4.5 + 4.6 +import types 4.7 + 4.8 +from xen.xend import sxp 4.9 +from xen.xend import PrettyPrint 4.10 +from xen.xend.Args import ArgError 4.11 +from xen.xend.XendError import XendError 4.12 +#from xen.xend.XendLogging import log 4.13 + 4.14 +import resource 4.15 +import http 4.16 + 4.17 +from xen.web.SrvBase import SrvBase 4.18 + 4.19 +class SrvConstructor: 4.20 + """Delayed constructor for sub-servers. 4.21 + Does not import the sub-server class or create the object until needed. 4.22 + """ 4.23 + 4.24 + def __init__(self, klass): 4.25 + """Create a constructor. It is assumed that the class 4.26 + should be imported as 'import klass from klass'. 4.27 + 4.28 + klass name of its class 4.29 + """ 4.30 + self.klass = klass 4.31 + self.obj = None 4.32 + 4.33 + def getobj(self): 4.34 + """Get the sub-server object, importing its class and instantiating it if 4.35 + necessary. 4.36 + """ 4.37 + if not self.obj: 4.38 + exec 'from xen.xend.server.%s import %s' % (self.klass, self.klass) 4.39 + klassobj = eval(self.klass) 4.40 + self.obj = klassobj() 4.41 + return self.obj 4.42 + 4.43 +class SrvDir(SrvBase): 4.44 + """Base class for directory servlets. 4.45 + """ 4.46 + isLeaf = False 4.47 + 4.48 + def __init__(self): 4.49 + SrvBase.__init__(self) 4.50 + self.table = {} 4.51 + self.order = [] 4.52 + 4.53 + def __repr__(self): 4.54 + return "<SrvDir %x %s>" %(id(self), self.table.keys()) 4.55 + 4.56 + def noChild(self, msg): 4.57 + return resource.ErrorPage(http.NOT_FOUND, msg=msg) 4.58 + 4.59 + def getChild(self, x, req): 4.60 + if x == '': return self 4.61 + try: 4.62 + val = self.get(x) 4.63 + except XendError, ex: 4.64 + return self.noChild(str(ex)) 4.65 + if val is None: 4.66 + return self.noChild('Not found: ' + str(x)) 4.67 + else: 4.68 + return val 4.69 + 4.70 + def get(self, x): 4.71 + val = self.table.get(x) 4.72 + if isinstance(val, SrvConstructor): 4.73 + val = val.getobj() 4.74 + return val 4.75 + 4.76 + def add(self, x, v=None): 4.77 + if v is None: 4.78 + v = 'SrvDir' 4.79 + if isinstance(v, types.StringType): 4.80 + v = SrvConstructor(v) 4.81 + self.table[x] = v 4.82 + self.order.append(x) 4.83 + return v 4.84 + 4.85 + def render_GET(self, req): 4.86 + try: 4.87 + if self.use_sxp(req): 4.88 + req.setHeader("Content-type", sxp.mime_type) 4.89 + self.ls(req, 1) 4.90 + else: 4.91 + req.write('<html><head></head><body>') 4.92 + self.print_path(req) 4.93 + self.ls(req) 4.94 + self.form(req) 4.95 + req.write('</body></html>') 4.96 + return '' 4.97 + except Exception, ex: 4.98 + self._perform_err(ex, "GET", req) 4.99 + 4.100 + def ls(self, req, use_sxp=0): 4.101 + url = req.prePathURL() 4.102 + if not url.endswith('/'): 4.103 + url += '/' 4.104 + if use_sxp: 4.105 + req.write('(ls ') 4.106 + for k in self.order: 4.107 + req.write(' ' + k) 4.108 + req.write(')') 4.109 + else: 4.110 + req.write('<ul>') 4.111 + for k in self.order: 4.112 + v = self.get(k) 4.113 + req.write('<li><a href="%s%s">%s</a></li>' 4.114 + % (url, k, k)) 4.115 + req.write('</ul>') 4.116 + 4.117 + def form(self, req): 4.118 + pass
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/tools/python/xen/web/__init__.py Thu Apr 21 13:25:07 2005 +0000 5.3 @@ -0,0 +1,1 @@ 5.4 +
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/tools/python/xen/web/connection.py Thu Apr 21 13:25:07 2005 +0000 6.3 @@ -0,0 +1,387 @@ 6.4 +import sys 6.5 +import threading 6.6 +import select 6.7 +import socket 6.8 + 6.9 +from errno import EAGAIN, EINTR, EWOULDBLOCK 6.10 + 6.11 +"""General classes to support server and client sockets, without 6.12 +specifying what kind of socket they are. There are subclasses 6.13 +for TCP and unix-domain sockets (see tcp.py and unix.py). 6.14 +""" 6.15 + 6.16 +"""We make sockets non-blocking so that operations like accept() 6.17 +don't block. We also select on a timeout. Otherwise we have no way 6.18 +of getting the threads to shutdown. 6.19 +""" 6.20 +SELECT_TIMEOUT = 2.0 6.21 + 6.22 +class SocketServerConnection: 6.23 + """An accepted connection to a server. 6.24 + """ 6.25 + 6.26 + def __init__(self, sock, protocol, addr, server): 6.27 + self.sock = sock 6.28 + self.protocol = protocol 6.29 + self.addr = addr 6.30 + self.server = server 6.31 + self.buffer_n = 1024 6.32 + self.thread = None 6.33 + self.connected = True 6.34 + protocol.setTransport(self) 6.35 + protocol.connectionMade(addr) 6.36 + 6.37 + def run(self): 6.38 + self.thread = threading.Thread(target=self.main) 6.39 + #self.thread.setDaemon(True) 6.40 + self.thread.start() 6.41 + 6.42 + def main(self): 6.43 + while True: 6.44 + if not self.thread: break 6.45 + if self.select(): break 6.46 + if not self.thread: break 6.47 + data = self.read() 6.48 + if data is None: continue 6.49 + if data is True: break 6.50 + if self.dataReceived(data): break 6.51 + 6.52 + def select(self): 6.53 + try: 6.54 + select.select([self.sock], [], [], SELECT_TIMEOUT) 6.55 + return False 6.56 + except socket.error, ex: 6.57 + if ex.args[0] in (EWOULDBLOCK, EAGAIN, EINTR): 6.58 + return False 6.59 + else: 6.60 + self.loseConnection(ex) 6.61 + return True 6.62 + 6.63 + def read(self): 6.64 + try: 6.65 + data = self.sock.recv(self.buffer_n) 6.66 + if data == '': 6.67 + self.loseConnection() 6.68 + return True 6.69 + return data 6.70 + except socket.error, ex: 6.71 + if ex.args[0] in (EWOULDBLOCK, EAGAIN, EINTR): 6.72 + return None 6.73 + else: 6.74 + self.loseConnection(ex) 6.75 + return True 6.76 + 6.77 + def dataReceived(self, data): 6.78 + if not self.protocol: 6.79 + return True 6.80 + try: 6.81 + self.protocol.dataReceived(data) 6.82 + except SystemExit: 6.83 + raise 6.84 + except Exception, ex: 6.85 + self.disconnect(ex) 6.86 + return True 6.87 + return False 6.88 + 6.89 + def write(self, data): 6.90 + self.sock.send(data) 6.91 + 6.92 + def loseConnection(self, reason=None): 6.93 + self.thread = None 6.94 + self.closeSocket(reason) 6.95 + self.closeProtocol(reason) 6.96 + 6.97 + def closeSocket(self, reason): 6.98 + try: 6.99 + self.sock.close() 6.100 + except SystemExit: 6.101 + raise 6.102 + except: 6.103 + pass 6.104 + 6.105 + def closeProtocol(self, reason): 6.106 + try: 6.107 + if self.connected: 6.108 + self.connected = False 6.109 + if self.protocol: 6.110 + self.protocol.connectionLost(reason) 6.111 + except SystemExit: 6.112 + raise 6.113 + except: 6.114 + pass 6.115 + 6.116 + def getHost(self): 6.117 + return self.sock.getsockname() 6.118 + 6.119 + def getPeer(self): 6.120 + return self.addr 6.121 + 6.122 +class SocketListener: 6.123 + """A server socket, running listen in a thread. 6.124 + Accepts connections and runs a thread for each one. 6.125 + """ 6.126 + 6.127 + def __init__(self, factory, backlog=None): 6.128 + if backlog is None: 6.129 + backlog = 5 6.130 + self.factory = factory 6.131 + self.sock = None 6.132 + self.backlog = backlog 6.133 + self.thread = None 6.134 + 6.135 + def createSocket(self): 6.136 + raise NotImplementedError() 6.137 + 6.138 + def acceptConnection(self, sock, protocol, addr): 6.139 + return SocketServerConnection(sock, protocol, addr, self) 6.140 + 6.141 + def startListening(self): 6.142 + if self.sock or self.thread: 6.143 + raise IOError("already listening") 6.144 + self.sock = self.createSocket() 6.145 + self.sock.setblocking(0) 6.146 + self.sock.listen(self.backlog) 6.147 + self.run() 6.148 + 6.149 + def stopListening(self, reason=None): 6.150 + self.loseConnection(reason) 6.151 + 6.152 + def run(self): 6.153 + self.factory.doStart() 6.154 + self.thread = threading.Thread(target=self.main) 6.155 + #self.thread.setDaemon(True) 6.156 + self.thread.start() 6.157 + 6.158 + def main(self): 6.159 + while True: 6.160 + if not self.thread: break 6.161 + if self.select(): break 6.162 + if self.accept(): break 6.163 + 6.164 + def select(self): 6.165 + try: 6.166 + select.select([self.sock], [], [], SELECT_TIMEOUT) 6.167 + return False 6.168 + except socket.error, ex: 6.169 + if ex.args[0] in (EWOULDBLOCK, EAGAIN, EINTR): 6.170 + return False 6.171 + else: 6.172 + self.loseConnection(ex) 6.173 + return True 6.174 + 6.175 + def accept(self): 6.176 + try: 6.177 + (sock, addr) = self.sock.accept() 6.178 + sock.setblocking(0) 6.179 + return self.accepted(sock, addr) 6.180 + except socket.error, ex: 6.181 + if ex.args[0] in (EWOULDBLOCK, EAGAIN, EINTR): 6.182 + return False 6.183 + else: 6.184 + self.loseConnection(ex) 6.185 + return True 6.186 + 6.187 + def accepted(self, sock, addr): 6.188 + protocol = self.factory.buildProtocol(addr) 6.189 + if protocol is None: 6.190 + self.loseConnection() 6.191 + return True 6.192 + connection = self.acceptConnection(sock, protocol, addr) 6.193 + connection.run() 6.194 + return False 6.195 + 6.196 + def loseConnection(self, reason=None): 6.197 + self.thread = None 6.198 + self.closeSocket(reason) 6.199 + self.closeFactory(reason) 6.200 + 6.201 + def closeSocket(self, reason): 6.202 + try: 6.203 + self.sock.close() 6.204 + except SystemExit: 6.205 + raise 6.206 + except Exception, ex: 6.207 + pass 6.208 + 6.209 + def closeFactory(self, reason): 6.210 + try: 6.211 + self.factory.doStop() 6.212 + except SystemExit: 6.213 + raise 6.214 + except: 6.215 + pass 6.216 + 6.217 +class SocketClientConnection: 6.218 + """A connection to a server from a client. 6.219 + 6.220 + Call connectionMade() on the protocol in a thread when connected. 6.221 + It is completely up to the protocol what to do. 6.222 + """ 6.223 + 6.224 + def __init__(self, connector): 6.225 + self.addr = None 6.226 + self.connector = connector 6.227 + self.buffer_n = 1024 6.228 + self.connected = False 6.229 + 6.230 + def createSocket (self): 6.231 + raise NotImplementedError() 6.232 + 6.233 + def write(self, data): 6.234 + if self.sock: 6.235 + return self.sock.send(data) 6.236 + else: 6.237 + return 0 6.238 + 6.239 + def connect(self, timeout): 6.240 + #todo: run a timer to cancel on timeout? 6.241 + try: 6.242 + sock = self.createSocket() 6.243 + sock.connect(self.addr) 6.244 + self.sock = sock 6.245 + self.connected = True 6.246 + self.protocol = self.connector.buildProtocol(self.addr) 6.247 + self.protocol.setTransport(self) 6.248 + except SystemExit: 6.249 + raise 6.250 + except Exception, ex: 6.251 + self.connector.connectionFailed(ex) 6.252 + return False 6.253 + 6.254 + self.thread = threading.Thread(target=self.main) 6.255 + #self.thread.setDaemon(True) 6.256 + self.thread.start() 6.257 + return True 6.258 + 6.259 + def main(self): 6.260 + try: 6.261 + # Call the protocol in a thread. 6.262 + # Up to it what to do. 6.263 + self.protocol.connectionMade(self.addr) 6.264 + except SystemExit: 6.265 + raise 6.266 + except Exception, ex: 6.267 + self.disconnect(ex) 6.268 + 6.269 + def mainLoop(self): 6.270 + # Something a protocol could call. 6.271 + while True: 6.272 + if not self.thread: break 6.273 + if self.select(): break 6.274 + if not self.thread: break 6.275 + data = self.read() 6.276 + if data is None: continue 6.277 + if data is True: break 6.278 + if self.dataReceived(data): break 6.279 + 6.280 + def select(self): 6.281 + try: 6.282 + select.select([self.sock], [], [], SELECT_TIMEOUT) 6.283 + return False 6.284 + except socket.error, ex: 6.285 + if ex.args[0] in (EWOULDBLOCK, EAGAIN, EINTR): 6.286 + return False 6.287 + else: 6.288 + self.disconnect(ex) 6.289 + return True 6.290 + 6.291 + def read(self): 6.292 + try: 6.293 + data = self.sock.recv(self.buffer_n) 6.294 + return data 6.295 + except socket.error, ex: 6.296 + if ex.args[0] in (EWOULDBLOCK, EAGAIN, EINTR): 6.297 + return None 6.298 + else: 6.299 + self.disconnect(ex) 6.300 + return True 6.301 + 6.302 + def dataReceived(self, data): 6.303 + if not self.protocol: 6.304 + return True 6.305 + try: 6.306 + self.protocol.dataReceived(data) 6.307 + except SystemExit: 6.308 + raise 6.309 + except Exception, ex: 6.310 + self.disconnect(ex) 6.311 + return True 6.312 + return False 6.313 + 6.314 + def disconnect(self, reason=None): 6.315 + self.thread = None 6.316 + self.closeSocket(reason) 6.317 + self.closeProtocol(reason) 6.318 + self.closeConnector(reason) 6.319 + 6.320 + def closeSocket(self, reason): 6.321 + try: 6.322 + if self.sock: 6.323 + self.sock.close() 6.324 + except SystemExit: 6.325 + raise 6.326 + except: 6.327 + pass 6.328 + 6.329 + def closeProtocol(self, reason): 6.330 + try: 6.331 + if self.connected: 6.332 + self.connected = False 6.333 + if self.protocol: 6.334 + self.protocol.connectionLost(reason) 6.335 + except SystemExit: 6.336 + raise 6.337 + except: 6.338 + pass 6.339 + self.protocol = None 6.340 + 6.341 + def closeConnector(self, reason): 6.342 + try: 6.343 + self.connector.connectionLost(reason) 6.344 + except SystemExit: 6.345 + raise 6.346 + except: 6.347 + pass 6.348 + 6.349 +class SocketConnector: 6.350 + """A client socket. Connects to a server and runs the client protocol 6.351 + in a thread. 6.352 + """ 6.353 + 6.354 + def __init__(self, factory): 6.355 + self.factoryStarted = False 6.356 + self.factory = factory 6.357 + self.state = "disconnected" 6.358 + self.transport = None 6.359 + 6.360 + def getDestination(self): 6.361 + raise NotImplementedError() 6.362 + 6.363 + def connectTransport(self): 6.364 + raise NotImplementedError() 6.365 + 6.366 + def connect(self): 6.367 + if self.state != "disconnected": 6.368 + raise socket.error(EINVAL, "cannot connect in state " + self.state) 6.369 + self.state = "connecting" 6.370 + if not self.factoryStarted: 6.371 + self.factoryStarted = True 6.372 + self.factory.doStart() 6.373 + self.factory.startedConnecting() 6.374 + self.connectTransport() 6.375 + 6.376 + def stopConnecting(self): 6.377 + if self.state != "connecting": 6.378 + return 6.379 + self.state = "disconnected" 6.380 + self.transport.disconnect() 6.381 + 6.382 + def buildProtocol(self, addr): 6.383 + return self.factory.buildProtocol(addr) 6.384 + 6.385 + def connectionLost(self, reason=None): 6.386 + self.factory.doStop() 6.387 + 6.388 + def connectionFailed(self, reason=None): 6.389 + self.factory.doStop() 6.390 +
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/tools/python/xen/web/defer.py Thu Apr 21 13:25:07 2005 +0000 7.3 @@ -0,0 +1,3 @@ 7.4 + 7.5 +class Deferred: 7.6 + pass
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/tools/python/xen/web/http.py Thu Apr 21 13:25:07 2005 +0000 8.3 @@ -0,0 +1,516 @@ 8.4 +#============================================================================ 8.5 +# This library is free software; you can redistribute it and/or 8.6 +# modify it under the terms of version 2.1 of the GNU Lesser General Public 8.7 +# License as published by the Free Software Foundation. 8.8 +# 8.9 +# This library is distributed in the hope that it will be useful, 8.10 +# but WITHOUT ANY WARRANTY; without even the implied warranty of 8.11 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 8.12 +# Lesser General Public License for more details. 8.13 +# 8.14 +# You should have received a copy of the GNU Lesser General Public 8.15 +# License along with this library; if not, write to the Free Software 8.16 +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 8.17 +# 8.18 +#============================================================================ 8.19 +# Parts of this library are derived from Twisted: 8.20 +# Copyright (C) 2001 Matthew W. Lefkowitz 8.21 +# 8.22 +# Copyright (C) 2005 Mike Wray <mike.wray@hp.com> 8.23 +#============================================================================ 8.24 + 8.25 +from mimetools import Message 8.26 +from cStringIO import StringIO 8.27 +import math 8.28 +import time 8.29 +import cgi 8.30 + 8.31 +CONTINUE = 100 8.32 +SWITCHING_PROTOCOLS = 101 8.33 + 8.34 +OK = 200 8.35 +CREATED = 201 8.36 +ACCEPTED = 202 8.37 +NON_AUTHORITATIVE_INFORMATION = 203 8.38 +NO_CONTENT = 204 8.39 +RESET_CONTENT = 205 8.40 +PARTIAL_CONTENT = 206 8.41 +MULTI_STATUS = 207 8.42 + 8.43 +MULTIPLE_CHOICE = 300 8.44 +MOVED_PERMANENTLY = 301 8.45 +FOUND = 302 8.46 +SEE_OTHER = 303 8.47 +NOT_MODIFIED = 304 8.48 +USE_PROXY = 305 8.49 +TEMPORARY_REDIRECT = 307 8.50 + 8.51 +BAD_REQUEST = 400 8.52 +UNAUTHORIZED = 401 8.53 +PAYMENT_REQUIRED = 402 8.54 +FORBIDDEN = 403 8.55 +NOT_FOUND = 404 8.56 +NOT_ALLOWED = 405 8.57 +NOT_ACCEPTABLE = 406 8.58 +PROXY_AUTH_REQUIRED = 407 8.59 +REQUEST_TIMEOUT = 408 8.60 +CONFLICT = 409 8.61 +GONE = 410 8.62 +LENGTH_REQUIRED = 411 8.63 +PRECONDITION_FAILED = 412 8.64 +REQUEST_ENTITY_TOO_LARGE = 413 8.65 +REQUEST_URI_TOO_LONG = 414 8.66 +UNSUPPORTED_MEDIA_TYPE = 415 8.67 +REQUESTED_RANGE_NOT_SATISFIABLE = 416 8.68 +EXPECTATION_FAILED = 417 8.69 + 8.70 +INTERNAL_SERVER_ERROR = 500 8.71 +NOT_IMPLEMENTED = 501 8.72 +BAD_GATEWAY = 502 8.73 +SERVICE_UNAVAILABLE = 503 8.74 +GATEWAY_TIMEOUT = 504 8.75 +VERSION_NOT_SUPPORTED = 505 8.76 +INSUFFICIENT_STORAGE_SPACE = 507 8.77 +NOT_EXTENDED = 510 8.78 + 8.79 +NO_BODY_CODES = [ NO_CONTENT, NOT_MODIFIED ] 8.80 + 8.81 + 8.82 +STATUS = { 8.83 + CONTINUE : "Continue", 8.84 + SWITCHING_PROTOCOLS : "Switching protocols", 8.85 + 8.86 + OK : "OK", 8.87 + CREATED : "Created", 8.88 + ACCEPTED : "Accepted", 8.89 + NON_AUTHORITATIVE_INFORMATION : "Non-authoritative information", 8.90 + NO_CONTENT : "No content", 8.91 + RESET_CONTENT : "Reset content", 8.92 + PARTIAL_CONTENT : "Partial content", 8.93 + MULTI_STATUS : "Multi-status", 8.94 + 8.95 + MULTIPLE_CHOICE : "Multiple choice", 8.96 + MOVED_PERMANENTLY : "Moved permanently", 8.97 + FOUND : "Found", 8.98 + SEE_OTHER : "See other", 8.99 + NOT_MODIFIED : "Not modified", 8.100 + USE_PROXY : "Use proxy", 8.101 + TEMPORARY_REDIRECT : "Temporary redirect", 8.102 + 8.103 + BAD_REQUEST : "Bad request", 8.104 + UNAUTHORIZED : "Unauthorized", 8.105 + PAYMENT_REQUIRED : "Payment required", 8.106 + FORBIDDEN : "Forbidden", 8.107 + NOT_FOUND : "Not found", 8.108 + NOT_ALLOWED : "Not allowed", 8.109 + NOT_ACCEPTABLE : "Not acceptable", 8.110 + PROXY_AUTH_REQUIRED : "Proxy authentication required", 8.111 + REQUEST_TIMEOUT : "Request timeout", 8.112 + CONFLICT : "Conflict", 8.113 + GONE : "Gone", 8.114 + LENGTH_REQUIRED : "Length required", 8.115 + PRECONDITION_FAILED : "Precondition failed", 8.116 + REQUEST_ENTITY_TOO_LARGE : "Request entity too large", 8.117 + REQUEST_URI_TOO_LONG : "Request URI too long", 8.118 + UNSUPPORTED_MEDIA_TYPE : "Unsupported media type", 8.119 + REQUESTED_RANGE_NOT_SATISFIABLE : "Requested range not satisfiable", 8.120 + EXPECTATION_FAILED : "Expectation failed", 8.121 + 8.122 + INTERNAL_SERVER_ERROR : "Internal server error", 8.123 + NOT_IMPLEMENTED : "Not implemented", 8.124 + BAD_GATEWAY : "Bad gateway", 8.125 + SERVICE_UNAVAILABLE : "Service unavailable", 8.126 + GATEWAY_TIMEOUT : "Gateway timeout", 8.127 + VERSION_NOT_SUPPORTED : "HTTP version not supported", 8.128 + INSUFFICIENT_STORAGE_SPACE : "Insufficient storage space", 8.129 + NOT_EXTENDED : "Not extended", 8.130 + } 8.131 + 8.132 +def getStatus(code): 8.133 + return STATUS.get(code, "unknown") 8.134 + 8.135 +MULTIPART_FORM_DATA = 'multipart/form-data' 8.136 +URLENCODED = 'application/x-www-form-urlencoded' 8.137 + 8.138 +parseQueryArgs = cgi.parse_qs 8.139 + 8.140 +def timegm(year, month, day, hour, minute, second): 8.141 + """Convert time tuple in GMT to seconds since epoch, GMT""" 8.142 + EPOCH = 1970 8.143 + assert year >= EPOCH 8.144 + assert 1 <= month <= 12 8.145 + days = 365*(year-EPOCH) + calendar.leapdays(EPOCH, year) 8.146 + for i in range(1, month): 8.147 + days = days + calendar.mdays[i] 8.148 + if month > 2 and calendar.isleap(year): 8.149 + days = days + 1 8.150 + days = days + day - 1 8.151 + hours = days*24 + hour 8.152 + minutes = hours*60 + minute 8.153 + seconds = minutes*60 + second 8.154 + return seconds 8.155 + 8.156 +def stringToDatetime(dateString): 8.157 + """Convert an HTTP date string to seconds since epoch.""" 8.158 + parts = dateString.split(' ') 8.159 + day = int(parts[1]) 8.160 + month = int(monthname.index(parts[2])) 8.161 + year = int(parts[3]) 8.162 + hour, min, sec = map(int, parts[4].split(':')) 8.163 + return int(timegm(year, month, day, hour, min, sec)) 8.164 + 8.165 +class HttpRequest: 8.166 + 8.167 + http_version = (1, 1) 8.168 + 8.169 + http_version_string = ("HTTP/%d.%d" % http_version) 8.170 + 8.171 + max_content_length = 10000 8.172 + max_headers = 500 8.173 + 8.174 + request_line = None 8.175 + request_method = None 8.176 + request_uri = None 8.177 + request_path = None 8.178 + request_query = None 8.179 + request_version = None 8.180 + content_length = 0 8.181 + content = None 8.182 + etag = None 8.183 + close_connection = True 8.184 + response_code = 200 8.185 + response_status = "OK" 8.186 + response_sent = False 8.187 + cached = False 8.188 + last_modified = None 8.189 + 8.190 + forceSSL = False 8.191 + 8.192 + def __init__(self, host, rin, out): 8.193 + self.host = host 8.194 + self.rin = rin 8.195 + self.out = out 8.196 + self.request_args = {} 8.197 + self.args = self.request_args 8.198 + self.request_headers = {} 8.199 + self.request_cookies = {} 8.200 + self.response_headers = {} 8.201 + self.response_cookies = {} 8.202 + self.output = StringIO() 8.203 + self.parseRequest() 8.204 + 8.205 + def isSecure(self): 8.206 + return self.forceSSL 8.207 + 8.208 + def getRequestMethod(self): 8.209 + return self.request_method 8.210 + 8.211 + def trim(self, str, ends): 8.212 + for end in ends: 8.213 + if str.endswith(end): 8.214 + str = str[ : -len(end) ] 8.215 + break 8.216 + return str 8.217 + 8.218 + def requestError(self, code, msg=None): 8.219 + self.sendError(code, msg) 8.220 + raise ValueError(self.response_status) 8.221 + 8.222 + def sendError(self, code, msg=None): 8.223 + self.setResponseCode(code, msg=msg) 8.224 + self.sendResponse() 8.225 + 8.226 + def parseRequestVersion(self, version): 8.227 + try: 8.228 + if not version.startswith('HTTP/'): 8.229 + raise ValueError 8.230 + version_string = version.split('/', 1)[1] 8.231 + version_codes = version_string.split('.') 8.232 + if len(version_codes) != 2: 8.233 + raise ValueError 8.234 + request_version = (int(version_codes[0]), int(version_codes[1])) 8.235 + except (ValueError, IndexError): 8.236 + self.requestError(400, "Bad request version (%s)" % `version`) 8.237 + 8.238 + def parseRequestLine(self): 8.239 + line = self.trim(self.request_line, ['\r\n', '\n']) 8.240 + line_fields = line.split() 8.241 + n = len(line_fields) 8.242 + if n == 3: 8.243 + [method, uri, version] = line_fields 8.244 + elif n == 2: 8.245 + [method, uri] = line_fields 8.246 + version = 'HTTP/0.9' 8.247 + else: 8.248 + self.requestError(BAD_REQUEST, 8.249 + "Bad request (%s)" % `line`) 8.250 + 8.251 + request_version = self.parseRequestVersion(version) 8.252 + 8.253 + if request_version > (2, 0): 8.254 + self.requestError(VERSION_NOT_SUPPORTED, 8.255 + "HTTP version not supported (%s)" % `version`) 8.256 + #if request_version >= (1, 1) and self.http_version >= (1, 1): 8.257 + # self.close_connection = False 8.258 + #else: 8.259 + # self.close_connection = True 8.260 + 8.261 + self.request_method = method 8.262 + self.method = method 8.263 + self.request_uri = uri 8.264 + self.request_version = version 8.265 + 8.266 + uri_query = uri.split('?') 8.267 + if len(uri_query) == 1: 8.268 + self.request_path = uri 8.269 + else: 8.270 + self.request_path = uri_query[0] 8.271 + self.request_query = uri_query[1] 8.272 + self.request_args = parseQueryArgs(self.request_query) 8.273 + self.args = self.request_args 8.274 + 8.275 + 8.276 + def parseRequestHeaders(self): 8.277 + header_bytes = "" 8.278 + header_count = 0 8.279 + while True: 8.280 + if header_count >= self.max_headers: 8.281 + self.requestError(BAD_REQUEST, 8.282 + "Bad request (too many headers)") 8.283 + line = self.rin.readline() 8.284 + header_bytes += line 8.285 + header_count += 1 8.286 + if line == '\r\n' or line == '\n' or line == '': 8.287 + break 8.288 + #print 'parseRequestHeaders>', header_bytes 8.289 + header_input = StringIO(header_bytes) 8.290 + self.request_headers = Message(header_input) 8.291 + 8.292 + def parseRequestCookies(self): 8.293 + cookie_hdr = self.getHeader("cookie") 8.294 + if not cookie_hdr: return 8.295 + for cookie in cookie_hdr.split(';'): 8.296 + try: 8.297 + cookie = cookie.lstrip() 8.298 + (k, v) = cookie.split('=', 1) 8.299 + self.request_cookies[k] = v 8.300 + except ValueError: 8.301 + pass 8.302 + 8.303 + def parseRequestArgs(self): 8.304 + if ((self.content is None) or 8.305 + (self.request_method != "POST")): 8.306 + return 8.307 + content_type = self.getHeader('content-type') 8.308 + if not content_type: 8.309 + return 8.310 + (encoding, params) = cgi.parse_header(content_type) 8.311 + if encoding == URLENCODED: 8.312 + xargs = cgi.parse_qs(self.content.getvalue(), 8.313 + keep_blank_values=True) 8.314 + elif encoding == MULTIPART_FORM_DATA: 8.315 + xargs = cgi.parse_multipart(self.content, params) 8.316 + else: 8.317 + xargs = {} 8.318 + self.request_args.update(xargs) 8.319 + 8.320 + def getCookie(self, k): 8.321 + return self.request_cookies[k] 8.322 + 8.323 + def readContent(self): 8.324 + try: 8.325 + self.content_length = int(self.getHeader("Content-Length")) 8.326 + except: 8.327 + return 8.328 + if self.content_length > self.max_content_length: 8.329 + self.requestError(REQUEST_ENTITY_TOO_LARGE) 8.330 + self.content = self.rin.read(self.content_length) 8.331 + self.content = StringIO(self.content) 8.332 + self.content.seek(0,0) 8.333 + 8.334 + def parseRequest(self): 8.335 + #print 'parseRequest>' 8.336 + self.request_line = self.rin.readline() 8.337 + self.parseRequestLine() 8.338 + self.parseRequestHeaders() 8.339 + self.parseRequestCookies() 8.340 + connection_mode = self.getHeader('Connection') 8.341 + self.setCloseConnection(connection_mode) 8.342 + self.readContent() 8.343 + self.parseRequestArgs() 8.344 + #print 'parseRequest<' 8.345 + 8.346 + def setCloseConnection(self, mode): 8.347 + if not mode: return 8.348 + mode = mode.lower() 8.349 + if mode == 'close': 8.350 + self.close_connection = True 8.351 + elif (mode == 'keep-alive') and (self.http_version >= (1, 1)): 8.352 + self.close_connection = False 8.353 + #print 'setCloseConnection>', mode, self.close_connection 8.354 + 8.355 + def getHeader(self, k, v=None): 8.356 + return self.request_headers.get(k, v) 8.357 + 8.358 + def getRequestMethod(self): 8.359 + return self.request_method 8.360 + 8.361 + def getRequestPath(self): 8.362 + return self.request_path 8.363 + 8.364 + def setResponseCode(self, code, status=None, msg=None): 8.365 + self.response_code = code 8.366 + if not status: 8.367 + status = getStatus(code) 8.368 + self.response_status = status 8.369 + 8.370 + def setResponseHeader(self, k, v): 8.371 + #print 'setResponseHeader>', k, v 8.372 + k = k.lower() 8.373 + self.response_headers[k] = v 8.374 + if k == 'connection': 8.375 + self.setCloseConnection(v) 8.376 + 8.377 + setHeader = setResponseHeader 8.378 + 8.379 + def setLastModified(self, when): 8.380 + # time.time() may be a float, but the HTTP-date strings are 8.381 + # only good for whole seconds. 8.382 + when = long(math.ceil(when)) 8.383 + if (not self.last_modified) or (self.last_modified < when): 8.384 + self.lastModified = when 8.385 + 8.386 + modified_since = self.getHeader('if-modified-since') 8.387 + if modified_since: 8.388 + modified_since = stringToDatetime(modified_since) 8.389 + if modified_since >= when: 8.390 + self.setResponseCode(NOT_MODIFIED) 8.391 + self.cached = True 8.392 + 8.393 + def setContentType(self, ty): 8.394 + self.setResponseHeader("Content-Type", ty) 8.395 + 8.396 + def setEtag(self, etag): 8.397 + if etag: 8.398 + self.etag = etag 8.399 + 8.400 + tags = self.getHeader("if-none-match") 8.401 + if tags: 8.402 + tags = tags.split() 8.403 + if (etag in tags) or ('*' in tags): 8.404 + if self.request_method in ("HEAD", "GET"): 8.405 + code = NOT_MODIFIED 8.406 + else: 8.407 + code = PRECONDITION_FAILED 8.408 + self.setResponseCode(code) 8.409 + self.cached = True 8.410 + 8.411 + def addCookie(self, k, v, expires=None, domain=None, path=None, 8.412 + max_age=None, comment=None, secure=None): 8.413 + cookie = v 8.414 + if expires != None: 8.415 + cookie += "; Expires=%s" % expires 8.416 + if domain != None: 8.417 + cookie += "; Domain=%s" % domain 8.418 + if path != None: 8.419 + cookie += "; Path=%s" % path 8.420 + if max_age != None: 8.421 + cookie += "; Max-Age=%s" % max_age 8.422 + if comment != None: 8.423 + cookie += "; Comment=%s" % comment 8.424 + if secure: 8.425 + cookie += "; Secure" 8.426 + self.response_cookies[k] = cookie 8.427 + 8.428 + def sendResponseHeaders(self): 8.429 + if self.etag: 8.430 + self.setResponseHeader("ETag", self.etag) 8.431 + for (k, v) in self.response_headers.items(): 8.432 + self.send("%s: %s\r\n" % (k.capitalize(), v)) 8.433 + for (k, v) in self.response_cookies.items(): 8.434 + self.send("Set-Cookie: %s=%s\r\n" % (k, v)) 8.435 + self.send("\r\n") 8.436 + 8.437 + def sendResponse(self): 8.438 + #print 'sendResponse>' 8.439 + if self.response_sent: 8.440 + return 8.441 + self.response_sent = True 8.442 + send_body = self.hasBody() 8.443 + if not self.close_connection: 8.444 + self.setResponseHeader("Connection", "keep-alive") 8.445 + if send_body: 8.446 + self.output.seek(0, 0) 8.447 + body = self.output.getvalue() 8.448 + body_length = len(body) 8.449 + #print 'sendResponse> body=', body_length, body 8.450 + self.setResponseHeader("Content-Length", body_length) 8.451 + if self.http_version > (0, 9): 8.452 + self.send("%s %d %s\r\n" % (self.http_version_string, 8.453 + self.response_code, 8.454 + self.response_status)) 8.455 + self.sendResponseHeaders() 8.456 + if send_body: 8.457 + #print 'sendResponse> writing body' 8.458 + self.send(body) 8.459 + 8.460 + def write(self, data): 8.461 + #print 'write>', data 8.462 + self.output.write(data) 8.463 + 8.464 + def send(self, data): 8.465 + #print 'send>', len(data), '|%s|' % data 8.466 + self.out.write(data) 8.467 + 8.468 + def hasNoBody(self): 8.469 + return ((self.request_method == "HEAD") or 8.470 + (self.response_code in NO_BODY_CODES) or 8.471 + self.cached) 8.472 + 8.473 + def hasBody(self): 8.474 + return not self.hasNoBody() 8.475 + 8.476 + def process(self): 8.477 + pass 8.478 + return self.close_connection 8.479 + 8.480 + def getRequestHostname(self): 8.481 + """Get the hostname that the user passed in to the request. 8.482 + 8.483 + Uses the 'Host:' header if it is available, and the 8.484 + host we are listening on otherwise. 8.485 + """ 8.486 + return (self.getHeader('host') or 8.487 + socket.gethostbyaddr(self.getHostAddr())[0] 8.488 + ).split(':')[0] 8.489 + 8.490 + def getHost(self): 8.491 + return self.host 8.492 + 8.493 + def getHostAddr(self): 8.494 + return self.host[0] 8.495 + 8.496 + def getPort(self): 8.497 + return self.host[1] 8.498 + 8.499 + def setHost(self, host, port, ssl=0): 8.500 + """Change the host and port the request thinks it's using. 8.501 + 8.502 + This method is useful for working with reverse HTTP proxies (e.g. 8.503 + both Squid and Apache's mod_proxy can do this), when the address 8.504 + the HTTP client is using is different than the one we're listening on. 8.505 + 8.506 + For example, Apache may be listening on https://www.example.com, and then 8.507 + forwarding requests to http://localhost:8080, but we don't want HTML produced 8.508 + to say 'http://localhost:8080', they should say 'https://www.example.com', 8.509 + so we do:: 8.510 + 8.511 + request.setHost('www.example.com', 443, ssl=1) 8.512 + 8.513 + """ 8.514 + self.forceSSL = ssl 8.515 + self.received_headers["host"] = host 8.516 + self.host = (host, port) 8.517 + 8.518 + 8.519 +
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/tools/python/xen/web/httpserver.py Thu Apr 21 13:25:07 2005 +0000 9.3 @@ -0,0 +1,144 @@ 9.4 +import string 9.5 +import socket 9.6 +from urllib import quote, unquote 9.7 + 9.8 +import http 9.9 +from SrvDir import SrvDir 9.10 + 9.11 +class HttpServerRequest(http.HttpRequest): 9.12 + 9.13 + def __init__(self, server, addr, srd, srw): 9.14 + #print 'HttpServerRequest>', addr 9.15 + self.server = server 9.16 + self.prepath = '' 9.17 + http.HttpRequest.__init__(self, addr, srd, srw) 9.18 + 9.19 + def process(self): 9.20 + #print 'HttpServerRequest>process', 'path=', self.request_path 9.21 + self.prepath = [] 9.22 + self.postpath = map(unquote, string.split(self.request_path[1:], '/')) 9.23 + res = self.getResource() 9.24 + self.render(res) 9.25 + self.sendResponse() 9.26 + return self.close_connection 9.27 + 9.28 + def prePathURL(self): 9.29 + url_host = self.getRequestHostname() 9.30 + port = self.getPort() 9.31 + if self.isSecure(): 9.32 + url_proto = "https" 9.33 + default_port = 443 9.34 + else: 9.35 + url_proto = "http" 9.36 + default_port = 80 9.37 + if port != default_port: 9.38 + url_host += (':%d' % port) 9.39 + url_path = quote(string.join(self.prepath, '/')) 9.40 + return ('%s://%s/%s' % (url_proto, url_host, url_path)) 9.41 + 9.42 + def getResource(self): 9.43 + return self.server.getResource(self) 9.44 + 9.45 + def render(self, res): 9.46 + #print 'HttpServerRequest>render', res 9.47 + if res is None: 9.48 + self.sendError(http.NOT_FOUND) 9.49 + else: 9.50 + res.render(self) 9.51 + 9.52 +class HttpServer: 9.53 + 9.54 + request_queue_size = 5 9.55 + 9.56 + def __init__(self, interface='', port=8080, root=None): 9.57 + if root is None: 9.58 + root = SrvDir() 9.59 + self.interface = interface 9.60 + self.port = port 9.61 + self.closed = False 9.62 + self.root = root 9.63 + 9.64 + def getRoot(self): 9.65 + return self.root 9.66 + 9.67 + def getPort(self): 9.68 + return self.port 9.69 + 9.70 + def run(self): 9.71 + self.bind() 9.72 + self.listen() 9.73 + self.requestLoop() 9.74 + 9.75 + def stop(self): 9.76 + self.close() 9.77 + 9.78 + def bind(self): 9.79 + #print 'bind>', self.interface, self.port 9.80 + self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 9.81 + self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 9.82 + self.socket.bind((self.interface, self.port)) 9.83 + 9.84 + def listen(self): 9.85 + self.socket.listen(self.request_queue_size) 9.86 + 9.87 + def accept(self): 9.88 + return self.socket.accept() 9.89 + 9.90 + def requestLoop(self): 9.91 + while not self.closed: 9.92 + self.acceptRequest() 9.93 + 9.94 + def close(self): 9.95 + self.closed = True 9.96 + try: 9.97 + self.socket.close() 9.98 + except: 9.99 + pass 9.100 + 9.101 + def acceptRequest(self): 9.102 + #print 'acceptRequest>' 9.103 + try: 9.104 + (sock, addr) = self.accept() 9.105 + #print 'acceptRequest>', sock, addr 9.106 + self.processRequest(sock, addr) 9.107 + except socket.error: 9.108 + return 9.109 + 9.110 + def processRequest(self, sock, addr): 9.111 + #print 'processRequest>', sock, addr 9.112 + srd = sock.makefile('rb') 9.113 + srw = sock.makefile('wb') 9.114 + srvaddr = (socket.gethostname(), self.port) 9.115 + while True: 9.116 + #print 'HttpServerRequest...' 9.117 + req = HttpServerRequest(self, srvaddr, srd, srw) 9.118 + close = req.process() 9.119 + srw.flush() 9.120 + #print 'HttpServerRequest close=', close 9.121 + if close: 9.122 + break 9.123 + try: 9.124 + #print 'close...' 9.125 + sock.close() 9.126 + except: 9.127 + pass 9.128 + #print 'processRequest<', sock, addr 9.129 + 9.130 + def getResource(self, req): 9.131 + return self.root.getRequestResource(req) 9.132 + 9.133 + 9.134 +def main(): 9.135 + root = SrvDir() 9.136 + a = root.add("a", SrvDir()) 9.137 + b = root.add("b", SrvDir()) 9.138 + server = HttpServer(root=root) 9.139 + server.run() 9.140 + 9.141 +if __name__ == "__main__": 9.142 + main() 9.143 + 9.144 + 9.145 + 9.146 + 9.147 +
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/tools/python/xen/web/protocol.py Thu Apr 21 13:25:07 2005 +0000 10.3 @@ -0,0 +1,94 @@ 10.4 +class Factory: 10.5 + 10.6 + def __init__(self): 10.7 + pass 10.8 + 10.9 + def startedConnecting(self): 10.10 + print 'ServerProtocolFactory>startedConnecting>' 10.11 + pass 10.12 + 10.13 + def doStart(self): 10.14 + print 'ServerProtocolFactory>doStart>' 10.15 + pass 10.16 + 10.17 + def doStop(self): 10.18 + print 'ServerProtocolFactory>doStop>' 10.19 + pass 10.20 + 10.21 + def buildProtocol(self, addr): 10.22 + print 'ServerProtocolFactory>buildProtocol>', addr 10.23 + return Protocol(self) 10.24 + 10.25 +class ServerFactory(Factory): 10.26 + pass 10.27 + 10.28 +class ClientFactory(Factory): 10.29 + pass 10.30 + 10.31 +class Protocol: 10.32 + 10.33 + factory = None 10.34 + transport = None 10.35 + connected = False 10.36 + 10.37 + def __init__(self, factory): 10.38 + self.factory = factory 10.39 + 10.40 + def setTransport(self, transport): 10.41 + self.transport = transport 10.42 + self.connected = bool(transport) 10.43 + 10.44 + def getTransport(self): 10.45 + return self.transport 10.46 + 10.47 + def connectionMade(self, addr): 10.48 + print 'Protocol>connectionMade>', addr 10.49 + pass 10.50 + 10.51 + def connectionLost(self, reason=None): 10.52 + print 'Protocol>connectionLost>', reason 10.53 + pass 10.54 + 10.55 + def dataReceived(self, data): 10.56 + print 'Protocol>dataReceived>' 10.57 + pass 10.58 + 10.59 + def write(self, data): 10.60 + if self.transport: 10.61 + return self.transport.write(data) 10.62 + else: 10.63 + return 0 10.64 + 10.65 + def read(self): 10.66 + if self.transport: 10.67 + return self.transport.read() 10.68 + else: 10.69 + return None 10.70 + 10.71 +class TestClientFactory(Factory): 10.72 + 10.73 + def buildProtocol(self, addr): 10.74 + print 'TestClientProtocolFactory>buildProtocol>', addr 10.75 + return TestClientProtocol(self) 10.76 + 10.77 +class TestClientProtocol(Protocol): 10.78 + 10.79 + def connectionMade(self, addr): 10.80 + print 'TestProtocol>connectionMade>', addr 10.81 + self.write("hello") 10.82 + self.write("there") 10.83 + 10.84 +class TestServerFactory(Factory): 10.85 + 10.86 + def buildProtocol(self, addr): 10.87 + print 'TestServerProtocolFactory>buildProtocol>', addr 10.88 + return TestServerProtocol(self) 10.89 + 10.90 +class TestServerProtocol(Protocol): 10.91 + 10.92 + def dataReceived(self, data): 10.93 + print 'TestServerProtocol>dataReceived>', len(data), data 10.94 + #sys.exit(0) 10.95 + import os 10.96 + os._exit(0) 10.97 +
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/tools/python/xen/web/reactor.py Thu Apr 21 13:25:07 2005 +0000 11.3 @@ -0,0 +1,9 @@ 11.4 +from threading import Timer 11.5 + 11.6 +from unix import listenUNIX, connectUNIX 11.7 +from tcp import listenTCP, connectTCP 11.8 + 11.9 +def callLater(_delay, _fn, *args, **kwds): 11.10 + timer = Timer(_delay, _fn, args=args, kwargs=kwds) 11.11 + timer.start() 11.12 + return timer
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 12.2 +++ b/tools/python/xen/web/resource.py Thu Apr 21 13:25:07 2005 +0000 12.3 @@ -0,0 +1,91 @@ 12.4 +import http 12.5 + 12.6 +def findResource(resource, request): 12.7 + """Traverse resource tree to find who will handle the request.""" 12.8 + while request.postpath and not resource.isLeaf: 12.9 + #print 'findResource:', resource, request.postpath 12.10 + pathElement = request.postpath.pop(0) 12.11 + request.prepath.append(pathElement) 12.12 + next = resource.getPathResource(pathElement, request) 12.13 + if not next: break 12.14 + resource = next 12.15 + return resource 12.16 + 12.17 +class Resource: 12.18 + 12.19 + isLeaf = False 12.20 + 12.21 + def __init__(self): 12.22 + self.children = {} 12.23 + 12.24 + def getRequestResource(self, req): 12.25 + return findResource(self, req) 12.26 + 12.27 + def getChild(self, path, request): 12.28 + return None 12.29 + 12.30 + def getPathResource(self, path, request): 12.31 + #print 'getPathResource>', self, path 12.32 + if self.children.has_key(path): 12.33 + val = self.children[path] 12.34 + else: 12.35 + val = self.getChild(path, request) 12.36 + #print 'getPathResource<', val 12.37 + return val 12.38 + 12.39 + def putChild(self, path, child): 12.40 + self.children[path] = child 12.41 + #child.server = self.server 12.42 + 12.43 + def render(self, req): 12.44 + meth = getattr(self, 'render_' + req.getRequestMethod(), self.unsupported) 12.45 + return meth(req) 12.46 + 12.47 + def supportedMethods(self): 12.48 + l = [] 12.49 + s = 'render_' 12.50 + for x in dir(self): 12.51 + if x.startswith(s): 12.52 + l.append(x[len(s):]) 12.53 + return l 12.54 + 12.55 + def render_HEAD(self, req): 12.56 + return self.render_GET(req) 12.57 + 12.58 + def render_GET(self, req): 12.59 + req.setContentType("text/plain") 12.60 + req.write("GET") 12.61 + 12.62 + def render_POST(self, req): 12.63 + req.setContentType("text/plain") 12.64 + req.write("POST") 12.65 + 12.66 + def unsupported(self, req): 12.67 + req.setHeader("Accept", ",".join(self.supportedMethods())) 12.68 + req.setResponseCode(http.NOT_IMPLEMENTED) 12.69 + req.setContentType("text/plain") 12.70 + req.write("Request method not supported (%s)" % req.getRequestMethod()) 12.71 + 12.72 +class ErrorPage(Resource): 12.73 + 12.74 + isLeaf = True 12.75 + 12.76 + def __init__(self, code, status=None, msg=None): 12.77 + Resource.__init__(self) 12.78 + if status is None: 12.79 + status = http.getStatus(code) 12.80 + if msg is None: 12.81 + msg = status 12.82 + self.code = code 12.83 + self.status = status 12.84 + self.msg = msg 12.85 + 12.86 + def render(self, req): 12.87 + req.setResponseCode(self.code, self.status) 12.88 + req.setContentType("text/plain") 12.89 + req.write(self.msg) 12.90 + 12.91 + 12.92 + 12.93 + 12.94 +
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 13.2 +++ b/tools/python/xen/web/static.py Thu Apr 21 13:25:07 2005 +0000 13.3 @@ -0,0 +1,46 @@ 13.4 +import os 13.5 + 13.6 +from resource import Resource 13.7 + 13.8 +class File(Resource): 13.9 + 13.10 + isLeaf = True 13.11 + 13.12 + def __init__(self, filename, defaultType=None): 13.13 + if defaultType is None: 13.14 + defaultType = "text/plain" 13.15 + self.filename = filename 13.16 + self.type = defaultType 13.17 + self.encoding = None 13.18 + 13.19 + def getFileSize(self): 13.20 + try: 13.21 + info = os.stat(self.filename) 13.22 + return info.st_size 13.23 + except: 13.24 + return 0 13.25 + 13.26 + def render(self, req): 13.27 + if self.type: 13.28 + req.setHeader('Content-Type', self.type) 13.29 + if self.encoding: 13.30 + rew.setHeader('Content-Encoding', self.encoding) 13.31 + req.setHeader('Content-Length', self.getFileSize()) 13.32 + try: 13.33 + io = file(self.filename, "r") 13.34 + while True: 13.35 + buf = io.read(1024) 13.36 + if not buf: 13.37 + break 13.38 + req.write(buf) 13.39 + except IOError: 13.40 + pass 13.41 + try: 13.42 + if io: 13.43 + io.close() 13.44 + except: 13.45 + pass 13.46 + return '' 13.47 + 13.48 + 13.49 +
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 14.2 +++ b/tools/python/xen/web/tcp.py Thu Apr 21 13:25:07 2005 +0000 14.3 @@ -0,0 +1,90 @@ 14.4 +import sys 14.5 +import socket 14.6 +import types 14.7 + 14.8 +from connection import * 14.9 +from protocol import * 14.10 + 14.11 +class TCPServerConnection(SocketServerConnection): 14.12 + pass 14.13 + 14.14 +class TCPListener(SocketListener): 14.15 + 14.16 + def __init__(self, port, factory, backlog=None, interface=''): 14.17 + SocketListener.__init__(self, factory, backlog=backlog) 14.18 + self.port = port 14.19 + self.interface = interface 14.20 + 14.21 + def createSocket(self): 14.22 + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 14.23 + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 14.24 + addr = (self.interface, self.port) 14.25 + sock.bind(addr) 14.26 + return sock 14.27 + 14.28 + def acceptConnection(self, sock, protocol, addr): 14.29 + return TCPServerConnection(sock, protocol, addr, self) 14.30 + 14.31 +class TCPClientConnection(SocketClientConnection): 14.32 + 14.33 + def __init__(self, host, port, bindAddress, connector): 14.34 + SocketClientConnection.__init__(self, connector) 14.35 + self.addr = (host, port) 14.36 + self.bindAddress = bindAddress 14.37 + 14.38 + def createSocket(self): 14.39 + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 14.40 + if self.bindAddress is not None: 14.41 + sock.bind(self.bindAddress) 14.42 + return sock 14.43 + 14.44 +class TCPConnector(SocketConnector): 14.45 + 14.46 + def __init__(self, host, port, factory, timeout=None, bindAddress=None): 14.47 + SocketConnector.__init__(self, factory) 14.48 + self.host = host 14.49 + self.port = self.servicePort(port) 14.50 + self.bindAddress = bindAddress 14.51 + self.timeout = timeout 14.52 + 14.53 + def servicePort(self, port): 14.54 + if isinstance(port, types.StringTypes): 14.55 + try: 14.56 + port = socket.getservbyname(port, 'tcp') 14.57 + except socket.error, ex: 14.58 + raise IOError("unknown service: " + ex) 14.59 + return port 14.60 + 14.61 + def getDestination(self): 14.62 + return (self.host, self.port) 14.63 + 14.64 + def connectTransport(self): 14.65 + self.transport = TCPClientConnection( 14.66 + self.host, self.port, self.bindAddress, self) 14.67 + self.transport.connect(self.timeout) 14.68 + 14.69 +def listenTCP(port, factory, interface='', backlog=None): 14.70 + l = TCPListener(port, factory, interface=interface, backlog=backlog) 14.71 + l.startListening() 14.72 + return l 14.73 + 14.74 +def connectTCP(host, port, factory, timeout=None, bindAddress=None): 14.75 + c = TCPConnector(host, port, factory, timeout=timeout, bindAddress=bindAddress) 14.76 + c.connect() 14.77 + return c 14.78 + 14.79 +def main(argv): 14.80 + host = 'localhost' 14.81 + port = 8005 14.82 + if argv[1] == "client": 14.83 + c = connectTCP(host, port, TestClientFactory()) 14.84 + print 'client:', c 14.85 + else: 14.86 + s = listenTCP(port, TestServerFactory()) 14.87 + print 'server:', s 14.88 + 14.89 +if __name__ == "__main__": 14.90 + main(sys.argv) 14.91 + 14.92 + 14.93 +
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 15.2 +++ b/tools/python/xen/web/unix.py Thu Apr 21 13:25:07 2005 +0000 15.3 @@ -0,0 +1,76 @@ 15.4 +import sys 15.5 +import socket 15.6 +import os 15.7 + 15.8 +from connection import * 15.9 +from protocol import * 15.10 + 15.11 +class UnixServerConnection(SocketServerConnection): 15.12 + pass 15.13 + 15.14 +class UnixListener(SocketListener): 15.15 + 15.16 + def __init__(self, path, factory, backlog=None): 15.17 + SocketListener.__init__(self, factory, backlog=backlog) 15.18 + self.path = path 15.19 + 15.20 + def createSocket(self): 15.21 + try: 15.22 + os.unlink(self.path) 15.23 + except SystemExit: 15.24 + raise 15.25 + except Exception, ex: 15.26 + pass 15.27 + sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) 15.28 + sock.bind(self.path) 15.29 + return sock 15.30 + 15.31 + def acceptConnection(self, sock, protocol, addr): 15.32 + return UnixServerConnection(sock, protocol, addr, self) 15.33 + 15.34 +class UnixClientConnection(SocketClientConnection): 15.35 + 15.36 + def __init__(self, addr, connector): 15.37 + SocketClientConnection.__init__(self, connector) 15.38 + self.addr = addr 15.39 + 15.40 + def createSocket(self): 15.41 + sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) 15.42 + return sock 15.43 + 15.44 +class UnixConnector(SocketConnector): 15.45 + 15.46 + def __init__(self, path, factory, timeout=None): 15.47 + SocketConnector.__init__(self, factory) 15.48 + self.addr = path 15.49 + self.timeout = timeout 15.50 + 15.51 + def getDestination(self): 15.52 + return self.addr 15.53 + 15.54 + def connectTransport(self): 15.55 + self.transport = UnixClientConnection(self.addr, self) 15.56 + self.transport.connect(self.timeout) 15.57 + 15.58 +def listenUNIX(path, factory, backlog=None): 15.59 + l = UnixListener(path, factory, backlog=backlog) 15.60 + l.startListening() 15.61 + return l 15.62 + 15.63 +def connectUNIX(path, factory, timeout=None): 15.64 + c = UnixConnector(path, factory, timeout=timeout) 15.65 + c.connect() 15.66 + return c 15.67 + 15.68 +def main(argv): 15.69 + path = "/tmp/test-foo" 15.70 + if argv[1] == "client": 15.71 + c = connectUNIX(path, TestClientFactory()) 15.72 + print "client:", c 15.73 + else: 15.74 + s = listenUNIX(path, TestServeractory()) 15.75 + print "server:", s 15.76 + 15.77 +if __name__ == "__main__": 15.78 + main(sys.argv) 15.79 +
16.1 --- a/tools/python/xen/xend/EventServer.py Wed Apr 20 08:45:19 2005 +0000 16.2 +++ b/tools/python/xen/xend/EventServer.py Thu Apr 21 13:25:07 2005 +0000 16.3 @@ -3,8 +3,10 @@ 16.4 16.5 """ 16.6 import string 16.7 +from threading import Lock 16.8 16.9 -from twisted.internet import reactor 16.10 +#from twisted.internet import reactor 16.11 +from xen.web import reactor 16.12 16.13 # subscribe a.b.c h: map a.b.c -> h 16.14 # subscribe a.b.* h: map a.b.* -> h 16.15 @@ -38,20 +40,30 @@ class EventServer: 16.16 self.handlers = {} 16.17 self.run = run 16.18 self.queue = [] 16.19 + self.lock = Lock() 16.20 16.21 def start(self): 16.22 """Enable event handling. Sends any queued events. 16.23 """ 16.24 - self.run = 1 16.25 - for (e,v) in self.queue: 16.26 + try: 16.27 + self.lock.acquire() 16.28 + self.run = 1 16.29 + queue = self.queue 16.30 + self.queue = [] 16.31 + finally: 16.32 + self.lock.release() 16.33 + for (e,v) in queue: 16.34 self.inject(e, v) 16.35 - self.queue = [] 16.36 16.37 def stop(self): 16.38 """Suspend event handling. Events injected while suspended 16.39 are queued until we are started again. 16.40 """ 16.41 - self.run = 0 16.42 + try: 16.43 + self.lock.acquire() 16.44 + self.run = 0 16.45 + finally: 16.46 + self.lock.release() 16.47 16.48 def subscribe(self, event, handler): 16.49 """Subscribe to an event. For example 'a.b.c.d'. 16.50 @@ -62,21 +74,29 @@ class EventServer: 16.51 event event name 16.52 handler event handler fn(event, val) 16.53 """ 16.54 - hl = self.handlers.get(event) 16.55 - if hl is None: 16.56 - self.handlers[event] = [handler] 16.57 - else: 16.58 - hl.append(handler) 16.59 + try: 16.60 + self.lock.acquire() 16.61 + hl = self.handlers.get(event) 16.62 + if hl is None: 16.63 + self.handlers[event] = [handler] 16.64 + else: 16.65 + hl.append(handler) 16.66 + finally: 16.67 + self.lock.release() 16.68 16.69 def unsubscribe_all(self, event=None): 16.70 """Unsubscribe all handlers for a given event, or all handlers. 16.71 16.72 event event (optional) 16.73 """ 16.74 - if event == None: 16.75 - self.handlers.clear() 16.76 - elif event in self.handlers: 16.77 - del self.handlers[event] 16.78 + try: 16.79 + self.lock.acquire() 16.80 + if event == None: 16.81 + self.handlers.clear() 16.82 + elif event in self.handlers: 16.83 + del self.handlers[event] 16.84 + finally: 16.85 + self.lock.release() 16.86 16.87 def unsubscribe(self, event, handler): 16.88 """Unsubscribe a given event and handler. 16.89 @@ -84,11 +104,15 @@ class EventServer: 16.90 event event 16.91 handler handler 16.92 """ 16.93 - hl = self.handlers.get(event) 16.94 - if hl is None: 16.95 - return 16.96 - if handler in hl: 16.97 - hl.remove(handler) 16.98 + try: 16.99 + self.lock.acquire() 16.100 + hl = self.handlers.get(event) 16.101 + if hl is None: 16.102 + return 16.103 + if handler in hl: 16.104 + hl.remove(handler) 16.105 + finally: 16.106 + self.lock.release() 16.107 16.108 def inject(self, event, val, async=1): 16.109 """Inject an event. Handlers for it are called if running, otherwise 16.110 @@ -97,13 +121,18 @@ class EventServer: 16.111 event event type 16.112 val event value 16.113 """ 16.114 - if self.run: 16.115 - if async: 16.116 - reactor.callLater(0, self.call_handlers, event, val) 16.117 - else: 16.118 - self.notify_handlers(event, val) 16.119 + try: 16.120 + self.lock.acquire() 16.121 + if not self.run: 16.122 + self.queue.append( (event, val) ) 16.123 + return 16.124 + finally: 16.125 + self.lock.release() 16.126 + 16.127 + if async: 16.128 + reactor.callLater(0, self.call_handlers, event, val) 16.129 else: 16.130 - self.queue.append( (event, val) ) 16.131 + self.notify_handlers(event, val) 16.132 16.133 def call_handlers(self, event, val): 16.134 """Internal method to call event handlers. 16.135 @@ -121,13 +150,19 @@ class EventServer: 16.136 event event type 16.137 val event value 16.138 """ 16.139 - hl = self.handlers.get(key) 16.140 - if hl is None: 16.141 - return 16.142 - # Copy the handler list so that handlers can call 16.143 - # subscribe/unsubscribe safely - python list iteration 16.144 - # is not safe against list modification. 16.145 - for h in hl[:]: 16.146 + try: 16.147 + self.lock.acquire() 16.148 + hl = self.handlers.get(key) 16.149 + if hl is None: 16.150 + return 16.151 + # Copy the handler list so that handlers can call 16.152 + # subscribe/unsubscribe safely - python list iteration 16.153 + # is not safe against list modification. 16.154 + hl = hl[:] 16.155 + finally: 16.156 + self.lock.release() 16.157 + # Must not hold the lock while calling the handlers. 16.158 + for h in hl: 16.159 try: 16.160 h(event, val) 16.161 except:
17.1 --- a/tools/python/xen/xend/XendDomain.py Wed Apr 20 08:45:19 2005 +0000 17.2 +++ b/tools/python/xen/xend/XendDomain.py Thu Apr 21 13:25:07 2005 +0000 17.3 @@ -201,6 +201,7 @@ class XendDomain: 17.4 if domid in doms: 17.5 try: 17.6 self._new_domain(config, doms[domid]) 17.7 + self.update_domain(domid) 17.8 except Exception, ex: 17.9 log.exception("Error recreating domain info: id=%s", domid) 17.10 self._delete_domain(domid) 17.11 @@ -301,11 +302,11 @@ class XendDomain: 17.12 destroyed = 0 17.13 for d in casualties: 17.14 id = str(d['dom']) 17.15 - print 'reap>', id 17.16 + #print 'reap>', id 17.17 dominfo = self.domain_by_id.get(id) 17.18 name = (dominfo and dominfo.name) or '??' 17.19 if dominfo and dominfo.is_terminated(): 17.20 - print 'reap> already terminated:', id 17.21 + #print 'reap> already terminated:', id 17.22 continue 17.23 log.debug('XendDomain>reap> domain died name=%s id=%s', name, id) 17.24 if d['shutdown']: 17.25 @@ -725,9 +726,9 @@ class XendDomain: 17.26 @param devconfig: device configuration 17.27 """ 17.28 dominfo = self.domain_lookup(id) 17.29 - self.refresh_schedule() 17.30 val = dominfo.device_create(devconfig) 17.31 self.update_domain(dominfo.id) 17.32 + self.refresh_schedule() 17.33 return val 17.34 17.35 def domain_device_configure(self, id, devconfig, idx): 17.36 @@ -739,9 +740,9 @@ class XendDomain: 17.37 @return: updated device configuration 17.38 """ 17.39 dominfo = self.domain_lookup(id) 17.40 - self.refresh_schedule() 17.41 val = dominfo.device_configure(devconfig, idx) 17.42 self.update_domain(dominfo.id) 17.43 + self.refresh_schedule() 17.44 return val 17.45 17.46 def domain_device_refresh(self, id, type, idx): 17.47 @@ -752,9 +753,9 @@ class XendDomain: 17.48 @param type: device type 17.49 """ 17.50 dominfo = self.domain_lookup(id) 17.51 - self.refresh_schedule() 17.52 val = dominfo.device_refresh(type, idx) 17.53 self.update_domain(dominfo.id) 17.54 + self.refresh_schedule() 17.55 return val 17.56 17.57 def domain_device_destroy(self, id, type, idx): 17.58 @@ -765,9 +766,9 @@ class XendDomain: 17.59 @param type: device type 17.60 """ 17.61 dominfo = self.domain_lookup(id) 17.62 - self.refresh_schedule() 17.63 val = dominfo.device_destroy(type, idx) 17.64 self.update_domain(dominfo.id) 17.65 + self.refresh_schedule() 17.66 return val 17.67 17.68 def domain_devtype_ls(self, id, type): 17.69 @@ -778,7 +779,7 @@ class XendDomain: 17.70 @return: device indexes 17.71 """ 17.72 dominfo = self.domain_lookup(id) 17.73 - return dominfo.get_devices(type) 17.74 + return dominfo.getDeviceIndexes(type) 17.75 17.76 def domain_devtype_get(self, id, type, idx): 17.77 """Get a device from a domain. 17.78 @@ -789,16 +790,16 @@ class XendDomain: 17.79 @return: device object (or None) 17.80 """ 17.81 dominfo = self.domain_lookup(id) 17.82 - return dominfo.get_device_by_index(type, idx) 17.83 + return dominfo.getDeviceByIndex(type, idx) 17.84 17.85 def domain_vif_credit_limit(self, id, vif, credit, period): 17.86 """Limit the vif's transmission rate 17.87 """ 17.88 dominfo = self.domain_lookup(id) 17.89 - try: 17.90 - return dominfo.limit_vif(vif, credit, period) 17.91 - except Exception, ex: 17.92 - raise XendError(str(ex)) 17.93 + dev = dominfo.getDeviceById('vif', vif) 17.94 + if not dev: 17.95 + raise XendError("invalid vif") 17.96 + return dev.setCreditLimit(credit, period) 17.97 17.98 def domain_vif_ls(self, id): 17.99 """Get list of virtual network interface (vif) indexes for a domain.
18.1 --- a/tools/python/xen/xend/XendDomainInfo.py Wed Apr 20 08:45:19 2005 +0000 18.2 +++ b/tools/python/xen/xend/XendDomainInfo.py Thu Apr 21 13:25:07 2005 +0000 18.3 @@ -4,7 +4,7 @@ 18.4 Includes support for domain construction, using 18.5 open-ended configurations. 18.6 18.7 -Author: Mike Wray <mike.wray@hpl.hp.com> 18.8 +Author: Mike Wray <mike.wray@hp.com> 18.9 18.10 """ 18.11 18.12 @@ -25,16 +25,9 @@ import sxp 18.13 from XendLogging import log 18.14 from XendError import VmError 18.15 from XendRoot import get_component 18.16 -#import XendConsole; xendConsole = XendConsole.instance() 18.17 18.18 from PrettyPrint import prettyprint 18.19 18.20 -"""The length of domain names that Xen can handle. 18.21 -The names stored in Xen itself are not used for much, and 18.22 -xend can handle domain names of any length. 18.23 -""" 18.24 -MAX_DOMAIN_NAME = 15 18.25 - 18.26 """Flag for a block device backend domain.""" 18.27 SIF_BLK_BE_DOMAIN = (1<<4) 18.28 18.29 @@ -279,7 +272,6 @@ class XendDomainInfo: 18.30 18.31 self.channel = None 18.32 self.controllers = {} 18.33 - self.devices = {} 18.34 18.35 self.configs = [] 18.36 18.37 @@ -386,10 +378,6 @@ class XendDomainInfo: 18.38 ctrl = self.getDeviceController(type) 18.39 return ctrl.getDeviceByIndex(idx) 18.40 18.41 - def getDeviceIndex(self, type, dev): 18.42 - ctrl = self.getDeviceController(type) 18.43 - return ctrl.getDeviceIndex(dev) 18.44 - 18.45 def getDeviceConfig(self, type, id): 18.46 ctrl = self.getDeviceController(type) 18.47 return ctrl.getDeviceConfig(id) 18.48 @@ -398,6 +386,10 @@ class XendDomainInfo: 18.49 ctrl = self.getDeviceController(type) 18.50 return ctrl.getDeviceIds() 18.51 18.52 + def getDeviceIndexes(self, type): 18.53 + ctrl = self.getDeviceController(type) 18.54 + return ctrl.getDeviceIndexes() 18.55 + 18.56 def getDeviceConfigs(self, type): 18.57 ctrl = self.getDeviceController(type) 18.58 return ctrl.getDeviceConfigs() 18.59 @@ -451,16 +443,19 @@ class XendDomainInfo: 18.60 return sxpr 18.61 18.62 def sxpr_devices(self): 18.63 - sxpr = ['devices'] 18.64 + sxpr = [] 18.65 for ty in self.getDeviceTypes(): 18.66 - devs = [ ty ] 18.67 - devs += self.getDeviceSxprs(ty) 18.68 - sxpr.append(devs) 18.69 + devs = self.getDeviceSxprs(ty) 18.70 + sxpr += devs 18.71 + if sxpr: 18.72 + sxpr.insert(0, 'devices') 18.73 + else: 18.74 + sxpr = None 18.75 return sxpr 18.76 18.77 def check_name(self, name): 18.78 - """Check if a vm name is valid. Valid names start with a non-digit 18.79 - and contain alphabetic characters, digits, or characters in '_-.:/+'. 18.80 + """Check if a vm name is valid. Valid names contain alphabetic characters, 18.81 + digits, or characters in '_-.:/+'. 18.82 The same name cannot be used for more than one vm at the same time. 18.83 18.84 @param name: name 18.85 @@ -469,8 +464,6 @@ class XendDomainInfo: 18.86 if self.recreate: return 18.87 if name is None or name == '': 18.88 raise VmError('missing vm name') 18.89 - if name[0] in string.digits: 18.90 - raise VmError('invalid vm name') 18.91 for c in name: 18.92 if c in string.digits: continue 18.93 if c in '_-.:/+': continue 18.94 @@ -585,14 +578,11 @@ class XendDomainInfo: 18.95 val = None 18.96 if self.savedinfo is None: 18.97 return val 18.98 - devinfo = sxp.child(self.savedinfo, 'devices') 18.99 - if devinfo is None: 18.100 - return val 18.101 - devs = sxp.child(devinfo, type) 18.102 - if devs is None: 18.103 + devices = sxp.child(self.savedinfo, 'devices') 18.104 + if devices is None: 18.105 return val 18.106 index = str(index) 18.107 - for d in sxp.children(devs): 18.108 + for d in sxp.children(devices, type): 18.109 dindex = sxp.child_value(d, 'index') 18.110 if dindex is None: continue 18.111 if str(dindex) == index: 18.112 @@ -603,19 +593,6 @@ class XendDomainInfo: 18.113 def get_device_recreate(self, type, index): 18.114 return self.get_device_savedinfo(type, index) or self.recreate 18.115 18.116 - def limit_vif(self, vif, credit, period): 18.117 - """Limit the rate of a virtual interface 18.118 - @param vif: vif 18.119 - @param credit: vif credit in bytes 18.120 - @param period: vif period in uSec 18.121 - @return: 0 on success 18.122 - """ 18.123 - #todo: all wrong 18.124 - #ctrl = xend.netif_create(self.dom, recreate=self.recreate) 18.125 - #d = ctrl.limitDevice(vif, credit, period) 18.126 - #return d 18.127 - pass 18.128 - 18.129 def add_config(self, val): 18.130 """Add configuration data to a virtual machine. 18.131 18.132 @@ -662,8 +639,6 @@ class XendDomainInfo: 18.133 if ctrl.isDestroyed(): continue 18.134 ctrl.destroyController(reboot=reboot) 18.135 if not reboot: 18.136 - self.devices = {} 18.137 - self.device_index = {} 18.138 self.configs = [] 18.139 self.ipaddrs = [] 18.140 18.141 @@ -674,11 +649,6 @@ class XendDomainInfo: 18.142 print "image:" 18.143 sxp.show(self.image) 18.144 print 18.145 - for dl in self.devices: 18.146 - for dev in dl: 18.147 - print "device:" 18.148 - sxp.show(dev) 18.149 - print 18.150 for val in self.configs: 18.151 print "config:" 18.152 sxp.show(val) 18.153 @@ -1011,9 +981,9 @@ class XendDomainInfo: 18.154 at creation time, for example when it uses NFS root. 18.155 18.156 """ 18.157 - blkif = self.getDeviceController("blkif", error=False) 18.158 + blkif = self.getDeviceController("vbd", error=False) 18.159 if not blkif: 18.160 - blkif = self.createDeviceController("blkif") 18.161 + blkif = self.createDeviceController("vbd") 18.162 backend = blkif.getBackend(0) 18.163 backend.connect(recreate=self.recreate) 18.164 18.165 @@ -1210,19 +1180,19 @@ from server import console 18.166 controller.addDevControllerClass("console", console.ConsoleController) 18.167 18.168 from server import blkif 18.169 -controller.addDevControllerClass("blkif", blkif.BlkifController) 18.170 -add_device_handler("vbd", "blkif") 18.171 +controller.addDevControllerClass("vbd", blkif.BlkifController) 18.172 +add_device_handler("vbd", "vbd") 18.173 18.174 from server import netif 18.175 -controller.addDevControllerClass("netif", netif.NetifController) 18.176 -add_device_handler("vif", "netif") 18.177 +controller.addDevControllerClass("vif", netif.NetifController) 18.178 +add_device_handler("vif", "vif") 18.179 18.180 from server import pciif 18.181 -controller.addDevControllerClass("pciif", pciif.PciController) 18.182 -add_device_handler("pci", "pciif") 18.183 +controller.addDevControllerClass("pci", pciif.PciController) 18.184 +add_device_handler("pci", "pci") 18.185 18.186 from xen.xend.server import usbif 18.187 -controller.addDevControllerClass("usbif", usbif.UsbifController) 18.188 -add_device_handler("usb", "usbif") 18.189 +controller.addDevControllerClass("usb", usbif.UsbifController) 18.190 +add_device_handler("usb", "usb") 18.191 18.192 #============================================================================
19.1 --- a/tools/python/xen/xend/scheduler.py Wed Apr 20 08:45:19 2005 +0000 19.2 +++ b/tools/python/xen/xend/scheduler.py Thu Apr 21 13:25:07 2005 +0000 19.3 @@ -6,18 +6,20 @@ class Scheduler: 19.4 self.lock = threading.Lock() 19.5 self.schedule = {} 19.6 19.7 - def later(self, _delay, _name, _fn, args): 19.8 + def later(self, _delay, _name, _fn, args, kwargs={}): 19.9 """Schedule a function to be called later (if not already scheduled). 19.10 19.11 @param _delay: delay in seconds 19.12 @param _name: schedule name 19.13 @param _fn: function 19.14 - @param args: arguments 19.15 + @param args: arguments (list) 19.16 + @param kwargs keyword arguments (map) 19.17 """ 19.18 try: 19.19 self.lock.acquire() 19.20 if self.schedule.get(_name): return 19.21 - timer = threading.Timer(_delay, _fn, args=args) 19.22 + runargs = [ _name, _fn, args, kwargs ] 19.23 + timer = threading.Timer(_delay, self._run, args=runargs) 19.24 self.schedule[_name] = timer 19.25 finally: 19.26 self.lock.release() 19.27 @@ -28,14 +30,22 @@ class Scheduler: 19.28 19.29 @param name: schedule name to cancel 19.30 """ 19.31 + timer = self._remove(name) 19.32 + if timer: 19.33 + timer.cancel() 19.34 + 19.35 + def _remove(self, name): 19.36 try: 19.37 self.lock.acquire() 19.38 timer = self.schedule.get(name) 19.39 - if not timer: 19.40 - return 19.41 - del self.schedule[name] 19.42 + if timer: 19.43 + del self.schedule[name] 19.44 + return timer 19.45 finally: 19.46 self.lock.release() 19.47 - timer.cancel() 19.48 + 19.49 + def _run(self, name, fn, args, kwargs): 19.50 + self._remove(name) 19.51 + fn(*args, **kwargs) 19.52 19.53
20.1 --- a/tools/python/xen/xend/server/SrvBase.py Wed Apr 20 08:45:19 2005 +0000 20.2 +++ b/tools/python/xen/xend/server/SrvBase.py Thu Apr 21 13:25:07 2005 +0000 20.3 @@ -1,185 +1,2 @@ 20.4 # Copyright (C) 2004 Mike Wray <mike.wray@hp.com> 20.5 - 20.6 -import cgi 20.7 - 20.8 -import os 20.9 -import sys 20.10 -import types 20.11 -import StringIO 20.12 - 20.13 -from twisted.internet import defer 20.14 -from twisted.internet import reactor 20.15 -from twisted.protocols import http 20.16 -from twisted.web import error 20.17 -from twisted.web import resource 20.18 -from twisted.web import server 20.19 -from twisted.python.failure import Failure 20.20 - 20.21 -from xen.xend import sxp 20.22 -from xen.xend import PrettyPrint 20.23 -from xen.xend.Args import ArgError 20.24 -from xen.xend.XendError import XendError 20.25 -from xen.xend.XendLogging import log 20.26 - 20.27 -def uri_pathlist(p): 20.28 - """Split a path into a list. 20.29 - p path 20.30 - return list of path elements 20.31 - """ 20.32 - l = [] 20.33 - for x in p.split('/'): 20.34 - if x == '': continue 20.35 - l.append(x) 20.36 - return l 20.37 - 20.38 -class SrvBase(resource.Resource): 20.39 - """Base class for services. 20.40 - """ 20.41 - 20.42 - def parse_form(self, req, method): 20.43 - """Parse the data for a request, GET using the URL, POST using encoded data. 20.44 - Posts should use enctype='multipart/form-data' in the <form> tag, 20.45 - rather than 'application/x-www-form-urlencoded'. Only 'multipart/form-data' 20.46 - handles file upload. 20.47 - 20.48 - req request 20.49 - returns a cgi.FieldStorage instance 20.50 - """ 20.51 - env = {} 20.52 - env['REQUEST_METHOD'] = method 20.53 - if self.query: 20.54 - env['QUERY_STRING'] = self.query 20.55 - val = cgi.FieldStorage(fp=req.rfile, headers=req.headers, environ=env) 20.56 - return val 20.57 - 20.58 - def use_sxp(self, req): 20.59 - """Determine whether to send an SXP response to a request. 20.60 - Uses SXP if there is no User-Agent, no Accept, or application/sxp is in Accept. 20.61 - 20.62 - req request 20.63 - returns 1 for SXP, 0 otherwise 20.64 - """ 20.65 - ok = 0 20.66 - user_agent = req.getHeader('User-Agent') 20.67 - accept = req.getHeader('Accept') 20.68 - if (not user_agent) or (not accept) or (accept.find(sxp.mime_type) >= 0): 20.69 - ok = 1 20.70 - return ok 20.71 - 20.72 - def get_op_method(self, op): 20.73 - """Get the method for an operation. 20.74 - For operation 'foo' looks for 'op_foo'. 20.75 - 20.76 - op operation name 20.77 - returns method or None 20.78 - """ 20.79 - op_method_name = 'op_' + op 20.80 - return getattr(self, op_method_name, None) 20.81 - 20.82 - def perform(self, req): 20.83 - """General operation handler for posted operations. 20.84 - For operation 'foo' looks for a method op_foo and calls 20.85 - it with op_foo(op, req). Replies with code 500 if op_foo 20.86 - is not found. 20.87 - 20.88 - The method must return a list when req.use_sxp is true 20.89 - and an HTML string otherwise (or list). 20.90 - Methods may also return a Deferred (for incomplete processing). 20.91 - 20.92 - req request 20.93 - """ 20.94 - op = req.args.get('op') 20.95 - if op is None or len(op) != 1: 20.96 - req.setResponseCode(http.NOT_ACCEPTABLE, "Invalid request") 20.97 - return '' 20.98 - op = op[0] 20.99 - op_method = self.get_op_method(op) 20.100 - if op_method is None: 20.101 - req.setResponseCode(http.NOT_IMPLEMENTED, "Operation not implemented: " + op) 20.102 - req.setHeader("Content-Type", "text/plain") 20.103 - req.write("Operation not implemented: " + op) 20.104 - return '' 20.105 - else: 20.106 - return self._perform(op, op_method, req) 20.107 - 20.108 - def _perform(self, op, op_method, req): 20.109 - try: 20.110 - val = op_method(op, req) 20.111 - except Exception, err: 20.112 - self._perform_err(err, op, req) 20.113 - return '' 20.114 - 20.115 - if isinstance(val, defer.Deferred): 20.116 - val.addCallback(self._perform_cb, op, req, dfr=1) 20.117 - val.addErrback(self._perform_err, op, req, dfr=1) 20.118 - return server.NOT_DONE_YET 20.119 - else: 20.120 - self._perform_cb(val, op, req, dfr=0) 20.121 - return '' 20.122 - 20.123 - def _perform_cb(self, val, op, req, dfr=0): 20.124 - """Callback to complete the request. 20.125 - May be called from a Deferred. 20.126 - 20.127 - @param err: the error 20.128 - @param req: request causing the error 20.129 - @param dfr: deferred flag 20.130 - """ 20.131 - if isinstance(val, error.ErrorPage): 20.132 - req.write(val.render(req)) 20.133 - elif self.use_sxp(req): 20.134 - req.setHeader("Content-Type", sxp.mime_type) 20.135 - sxp.show(val, out=req) 20.136 - else: 20.137 - req.write('<html><head></head><body>') 20.138 - self.print_path(req) 20.139 - if isinstance(val, types.ListType): 20.140 - req.write('<code><pre>') 20.141 - PrettyPrint.prettyprint(val, out=req) 20.142 - req.write('</pre></code>') 20.143 - else: 20.144 - req.write(str(val)) 20.145 - req.write('</body></html>') 20.146 - if dfr: 20.147 - req.finish() 20.148 - 20.149 - def _perform_err(self, err, op, req, dfr=0): 20.150 - """Error callback to complete a request. 20.151 - May be called from a Deferred. 20.152 - 20.153 - @param err: the error 20.154 - @param req: request causing the error 20.155 - @param dfr: deferred flag 20.156 - """ 20.157 - if isinstance(err, Failure): 20.158 - err = err.getErrorMessage() 20.159 - elif not (isinstance(err, ArgError) or 20.160 - isinstance(err, sxp.ParseError) or 20.161 - isinstance(err, XendError)): 20.162 - if dfr: 20.163 - return err 20.164 - else: 20.165 - raise 20.166 - log.exception("op=%s: %s", op, str(err)) 20.167 - if self.use_sxp(req): 20.168 - req.setHeader("Content-Type", sxp.mime_type) 20.169 - sxp.show(['xend.err', str(err)], out=req) 20.170 - else: 20.171 - req.setHeader("Content-Type", "text/plain") 20.172 - req.write('Error ') 20.173 - req.write(': ') 20.174 - req.write(str(err)) 20.175 - if dfr: 20.176 - req.finish() 20.177 - 20.178 - 20.179 - def print_path(self, req): 20.180 - """Print the path with hyperlinks. 20.181 - """ 20.182 - pathlist = [x for x in req.prepath if x != '' ] 20.183 - s = "/" 20.184 - req.write('<h1><a href="/">/</a>') 20.185 - for x in pathlist: 20.186 - s += x + "/" 20.187 - req.write(' <a href="%s">%s</a>/' % (s, x)) 20.188 - req.write("</h1>") 20.189 +from xen.web.SrvBase import *
21.1 --- a/tools/python/xen/xend/server/SrvDaemon.py Wed Apr 20 08:45:19 2005 +0000 21.2 +++ b/tools/python/xen/xend/server/SrvDaemon.py Thu Apr 21 13:25:07 2005 +0000 21.3 @@ -17,20 +17,14 @@ import StringIO 21.4 import traceback 21.5 import time 21.6 21.7 -from twisted.internet import pollreactor 21.8 -pollreactor.install() 21.9 - 21.10 +#from twisted.internet import pollreactor; pollreactor.install() 21.11 from twisted.internet import reactor 21.12 -from twisted.internet import protocol 21.13 -from twisted.internet import abstract 21.14 -from twisted.internet import defer 21.15 21.16 from xen.lowlevel import xu 21.17 21.18 from xen.xend import sxp 21.19 from xen.xend import PrettyPrint 21.20 -from xen.xend import EventServer 21.21 -eserver = EventServer.instance() 21.22 +from xen.xend import EventServer; eserver = EventServer.instance() 21.23 from xen.xend.XendError import XendError 21.24 from xen.xend.server import SrvServer 21.25 from xen.xend import XendRoot 21.26 @@ -331,16 +325,20 @@ class Daemon: 21.27 log.info("Xend Daemon started") 21.28 self.createFactories() 21.29 self.listenEvent(xroot) 21.30 - self.listenVirq() 21.31 self.listenChannels() 21.32 - SrvServer.create(bridge=1) 21.33 + serverthread = SrvServer.create(bridge=1) 21.34 self.daemonize() 21.35 + print 'running serverthread...' 21.36 + serverthread.start() 21.37 + print 'running reactor...' 21.38 reactor.run() 21.39 except Exception, ex: 21.40 print >>sys.stderr, 'Exception starting xend:', ex 21.41 + if DEBUG: 21.42 + traceback.print_exc() 21.43 + log.exception("Exception starting xend") 21.44 self.exit(1) 21.45 21.46 - 21.47 def createFactories(self): 21.48 self.channelF = channel.channelFactory() 21.49 21.50 @@ -350,18 +348,22 @@ class Daemon: 21.51 return event.listenEvent(self, port, interface) 21.52 21.53 def listenChannels(self): 21.54 - self.channelF.start() 21.55 - 21.56 - def listenVirq(self): 21.57 def virqReceived(virq): 21.58 print 'virqReceived>', virq 21.59 eserver.inject('xend.virq', virq) 21.60 + 21.61 self.channelF.setVirqHandler(virqReceived) 21.62 + self.channelF.start() 21.63 21.64 def exit(self, rc=0): 21.65 reactor.disconnectAll() 21.66 self.channelF.stop() 21.67 - sys.exit(rc) 21.68 + # Calling sys.exit() raises a SystemExit exception, which only 21.69 + # kills the current thread. Calling os._exit() makes the whole 21.70 + # Python process exit immediately. There doesn't seem to be another 21.71 + # way to exit a Python with running threads. 21.72 + #sys.exit(rc) 21.73 + os._exit(rc) 21.74 21.75 def instance(): 21.76 global inst
22.1 --- a/tools/python/xen/xend/server/SrvDeviceDir.py Wed Apr 20 08:45:19 2005 +0000 22.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 22.3 @@ -1,9 +0,0 @@ 22.4 -# Copyright (C) 2004 Mike Wray <mike.wray@hp.com> 22.5 - 22.6 -from SrvDir import SrvDir 22.7 - 22.8 -class SrvDeviceDir(SrvDir): 22.9 - """Device directory. 22.10 - """ 22.11 - 22.12 - pass
23.1 --- a/tools/python/xen/xend/server/SrvDir.py Wed Apr 20 08:45:19 2005 +0000 23.2 +++ b/tools/python/xen/xend/server/SrvDir.py Thu Apr 21 13:25:07 2005 +0000 23.3 @@ -1,111 +1,3 @@ 23.4 # Copyright (C) 2004 Mike Wray <mike.wray@hp.com> 23.5 - 23.6 -from twisted.protocols import http 23.7 -from twisted.web import error 23.8 - 23.9 -from xen.xend import sxp 23.10 -from xen.xend.XendError import XendError 23.11 - 23.12 -from SrvBase import SrvBase 23.13 - 23.14 -class SrvError(error.ErrorPage): 23.15 - 23.16 - def render(self, request): 23.17 - val = error.ErrorPage.render(self, request) 23.18 - request.setResponseCode(self.code, self.brief) 23.19 - return val 23.20 - 23.21 -class SrvConstructor: 23.22 - """Delayed constructor for sub-servers. 23.23 - Does not import the sub-server class or create the object until needed. 23.24 - """ 23.25 - 23.26 - def __init__(self, klass): 23.27 - """Create a constructor. It is assumed that the class 23.28 - should be imported as 'import klass from klass'. 23.29 - 23.30 - klass name of its class 23.31 - """ 23.32 - self.klass = klass 23.33 - self.obj = None 23.34 - 23.35 - def getobj(self): 23.36 - """Get the sub-server object, importing its class and instantiating it if 23.37 - necessary. 23.38 - """ 23.39 - if not self.obj: 23.40 - exec 'from %s import %s' % (self.klass, self.klass) 23.41 - klassobj = eval(self.klass) 23.42 - self.obj = klassobj() 23.43 - return self.obj 23.44 - 23.45 -class SrvDir(SrvBase): 23.46 - """Base class for directory servlets. 23.47 - """ 23.48 - isLeaf = False 23.49 - 23.50 - def __init__(self): 23.51 - SrvBase.__init__(self) 23.52 - self.table = {} 23.53 - self.order = [] 23.54 - 23.55 - def noChild(self, msg): 23.56 - return SrvError(http.NOT_FOUND, msg, msg) 23.57 - 23.58 - def getChild(self, x, req): 23.59 - if x == '': return self 23.60 - try: 23.61 - val = self.get(x) 23.62 - except XendError, ex: 23.63 - return self.noChild(str(ex)) 23.64 - if val is None: 23.65 - return self.noChild('Not found ' + str(x)) 23.66 - else: 23.67 - return val 23.68 - 23.69 - def get(self, x): 23.70 - val = self.table.get(x) 23.71 - if val is not None: 23.72 - val = val.getobj() 23.73 - return val 23.74 - 23.75 - def add(self, x, xclass = None): 23.76 - if xclass is None: 23.77 - xclass = 'SrvDir' 23.78 - self.table[x] = SrvConstructor(xclass) 23.79 - self.order.append(x) 23.80 - 23.81 - def render_GET(self, req): 23.82 - try: 23.83 - if self.use_sxp(req): 23.84 - req.setHeader("Content-type", sxp.mime_type) 23.85 - self.ls(req, 1) 23.86 - else: 23.87 - req.write('<html><head></head><body>') 23.88 - self.print_path(req) 23.89 - self.ls(req) 23.90 - self.form(req) 23.91 - req.write('</body></html>') 23.92 - return '' 23.93 - except Exception, ex: 23.94 - self._perform_err(ex, "GET", req) 23.95 - 23.96 - def ls(self, req, use_sxp=0): 23.97 - url = req.prePathURL() 23.98 - if not url.endswith('/'): 23.99 - url += '/' 23.100 - if use_sxp: 23.101 - req.write('(ls ') 23.102 - for k in self.order: 23.103 - req.write(' ' + k) 23.104 - req.write(')') 23.105 - else: 23.106 - req.write('<ul>') 23.107 - for k in self.order: 23.108 - v = self.get(k) 23.109 - req.write('<li><a href="%s%s">%s</a></li>' 23.110 - % (url, k, k)) 23.111 - req.write('</ul>') 23.112 - 23.113 - def form(self, req): 23.114 - pass 23.115 +from xen.web.SrvBase import * 23.116 +from xen.web.SrvDir import *
24.1 --- a/tools/python/xen/xend/server/SrvDomain.py Wed Apr 20 08:45:19 2005 +0000 24.2 +++ b/tools/python/xen/xend/server/SrvDomain.py Thu Apr 21 13:25:07 2005 +0000 24.3 @@ -1,6 +1,6 @@ 24.4 # Copyright (C) 2004 Mike Wray <mike.wray@hp.com> 24.5 24.6 -from twisted.protocols import http 24.7 +from xen.web import http 24.8 24.9 from xen.xend import sxp 24.10 from xen.xend import XendDomain
25.1 --- a/tools/python/xen/xend/server/SrvDomainDir.py Wed Apr 20 08:45:19 2005 +0000 25.2 +++ b/tools/python/xen/xend/server/SrvDomainDir.py Thu Apr 21 13:25:07 2005 +0000 25.3 @@ -3,9 +3,7 @@ 25.4 import traceback 25.5 from StringIO import StringIO 25.6 25.7 -from twisted.protocols import http 25.8 -from twisted.web import error 25.9 -from twisted.python.failure import Failure 25.10 +from xen.web import http 25.11 25.12 from xen.xend import sxp 25.13 from xen.xend import XendDomain
26.1 --- a/tools/python/xen/xend/server/SrvRoot.py Wed Apr 20 08:45:19 2005 +0000 26.2 +++ b/tools/python/xen/xend/server/SrvRoot.py Thu Apr 21 13:25:07 2005 +0000 26.3 @@ -17,7 +17,6 @@ class SrvRoot(SrvDir): 26.4 ('domain', 'SrvDomainDir' ), 26.5 ('console', 'SrvConsoleDir' ), 26.6 ('event', 'SrvEventDir' ), 26.7 - ('device', 'SrvDeviceDir' ), 26.8 ('vnet', 'SrvVnetDir' ), 26.9 ] 26.10 26.11 @@ -28,3 +27,7 @@ class SrvRoot(SrvDir): 26.12 for (name, klass) in self.subdirs: 26.13 self.get(name) 26.14 xroot.start() 26.15 + 26.16 + def __repr__(self): 26.17 + return "<SrvRoot %x %s>" %(id(self), self.table.keys()) 26.18 +
27.1 --- a/tools/python/xen/xend/server/SrvServer.py Wed Apr 20 08:45:19 2005 +0000 27.2 +++ b/tools/python/xen/xend/server/SrvServer.py Thu Apr 21 13:25:07 2005 +0000 27.3 @@ -25,16 +25,15 @@ 27.4 # todo Support security settings etc. in the config file. 27.5 # todo Support command-line args. 27.6 27.7 -from twisted.web import server, static 27.8 -from twisted.web import resource, script 27.9 -from twisted.internet import reactor 27.10 +from threading import Thread 27.11 + 27.12 +from xen.web.httpserver import HttpServer 27.13 27.14 from xen.xend import XendRoot 27.15 xroot = XendRoot.instance() 27.16 - 27.17 from xen.xend import Vifctl 27.18 - 27.19 from SrvRoot import SrvRoot 27.20 +from SrvDir import SrvDir 27.21 27.22 def create(port=None, interface=None, bridge=0): 27.23 if port is None: 27.24 @@ -43,16 +42,8 @@ def create(port=None, interface=None, br 27.25 interface = xroot.get_xend_address() 27.26 if bridge: 27.27 Vifctl.network('start') 27.28 - root = resource.Resource() 27.29 - xend = SrvRoot() 27.30 - root.putChild('xend', xend) 27.31 - site = server.Site(root) 27.32 - reactor.listenTCP(port, site, interface=interface) 27.33 - 27.34 -def main(port=None, interface=None): 27.35 - create(port, interface) 27.36 - reactor.run() 27.37 - 27.38 - 27.39 -if __name__ == '__main__': 27.40 - main() 27.41 + root = SrvDir() 27.42 + root.putChild('xend', SrvRoot()) 27.43 + server = HttpServer(root=root, interface=interface, port=port) 27.44 + thread = Thread(name="XendHttpServer", target=server.run) 27.45 + return thread
28.1 --- a/tools/python/xen/xend/server/SrvUsbif.py Wed Apr 20 08:45:19 2005 +0000 28.2 +++ b/tools/python/xen/xend/server/SrvUsbif.py Thu Apr 21 13:25:07 2005 +0000 28.3 @@ -1,6 +1,6 @@ 28.4 # Copyright (C) 2004 Mike Wray <mike.wray@hp.com> 28.5 28.6 -from twisted.protocols import http 28.7 +from xen.web import http 28.8 28.9 from xen.xend import sxp 28.10 from xen.xend import XendDomain
29.1 --- a/tools/python/xen/xend/server/SrvXendLog.py Wed Apr 20 08:45:19 2005 +0000 29.2 +++ b/tools/python/xen/xend/server/SrvXendLog.py Thu Apr 21 13:25:07 2005 +0000 29.3 @@ -1,6 +1,6 @@ 29.4 # Copyright (C) 2004 Mike Wray <mike.wray@hp.com> 29.5 29.6 -from twisted.web import static 29.7 +from xen.web import static 29.8 29.9 from xen.xend import XendRoot 29.10 29.11 @@ -21,4 +21,4 @@ class SrvXendLog(SrvDir): 29.12 try: 29.13 return self.logfile.render(req) 29.14 except Exception, ex: 29.15 - self._perform_err(ex, req) 29.16 + self._perform_err(ex, 'log', req)
30.1 --- a/tools/python/xen/xend/server/blkif.py Wed Apr 20 08:45:19 2005 +0000 30.2 +++ b/tools/python/xen/xend/server/blkif.py Thu Apr 21 13:25:07 2005 +0000 30.3 @@ -249,16 +249,13 @@ class BlkDev(Dev): 30.4 self.configure(self.config, recreate=recreate) 30.5 30.6 def init(self, recreate=False, reboot=False): 30.7 - print 'BlkDev>init>' 30.8 self.frontendDomain = self.getDomain() 30.9 self.frontendChannel = self.getChannel() 30.10 backend = self.getBackend() 30.11 self.backendChannel = backend.backendChannel 30.12 self.backendId = backend.id 30.13 - print 'BlkDev>init<' 30.14 30.15 def configure(self, config, change=False, recreate=False): 30.16 - print 'BlkDev>configure>' 30.17 if change: 30.18 raise XendError("cannot reconfigure vbd") 30.19 self.config = config 30.20 @@ -282,15 +279,12 @@ class BlkDev(Dev): 30.21 except: 30.22 raise XendError('invalid backend domain') 30.23 30.24 - print 'BlkDev>configure<' 30.25 return self.config 30.26 30.27 def attach(self, recreate=False, change=False): 30.28 - print 'BlkDev>attach>', self 30.29 if recreate: 30.30 - print 'attach>', 'recreate=', recreate 30.31 node = sxp.child_value(recreate, 'node') 30.32 - print 'attach>', 'node=', node 30.33 + print 'BlkDev>attach>', 'recreate=', recreate, 'node=', node 30.34 self.setNode(node) 30.35 else: 30.36 node = Blkctl.block('bind', self.type, self.params) 30.37 @@ -298,7 +292,6 @@ class BlkDev(Dev): 30.38 self.attachBackend() 30.39 if change: 30.40 self.interfaceChanged() 30.41 - print 'BlkDev>attach<', self 30.42 30.43 def unbind(self): 30.44 if self.node is None: return 30.45 @@ -401,13 +394,10 @@ class BlkDev(Dev): 30.46 """Attach the device to its controller. 30.47 30.48 """ 30.49 - print 'BlkDev>attachBackend>' 30.50 self.getBackend().connect() 30.51 self.send_be_vbd_create() 30.52 - print 'BlkDev>attachBackend<' 30.53 30.54 def send_be_vbd_create(self): 30.55 - print 'BlkDev>send_be_vbd_create>' 30.56 msg = packMsg('blkif_be_vbd_create_t', 30.57 { 'domid' : self.frontendDomain, 30.58 'blkif_handle' : self.backendId, 30.59 @@ -443,7 +433,6 @@ class BlkifController(DevController): 30.60 self.rcvr = None 30.61 30.62 def initController(self, recreate=False, reboot=False): 30.63 - print 'BlkifController>initController>' 30.64 self.destroyed = False 30.65 # Add our handlers for incoming requests. 30.66 self.rcvr = CtrlMsgRcvr(self.getChannel()) 30.67 @@ -457,7 +446,6 @@ class BlkifController(DevController): 30.68 if reboot: 30.69 self.rebootBackends() 30.70 self.rebootDevices() 30.71 - print 'BlkifController>initController<' 30.72 30.73 def sxpr(self): 30.74 val = ['blkif', ['dom', self.getDomain()]]
31.1 --- a/tools/python/xen/xend/server/console.py Wed Apr 20 08:45:19 2005 +0000 31.2 +++ b/tools/python/xen/xend/server/console.py Thu Apr 21 13:25:07 2005 +0000 31.3 @@ -2,7 +2,7 @@ 31.4 31.5 import socket 31.6 31.7 -from twisted.internet import reactor, protocol 31.8 +from xen.web import reactor, protocol 31.9 31.10 from xen.lowlevel import xu 31.11 31.12 @@ -24,14 +24,13 @@ class ConsoleProtocol(protocol.Protocol) 31.13 self.console = console 31.14 self.id = id 31.15 self.addr = None 31.16 - self.binary = 0 31.17 31.18 - def connectionMade(self): 31.19 + def connectionMade(self, addr=None): 31.20 peer = self.transport.getPeer() 31.21 - self.addr = (peer.host, peer.port) 31.22 + self.addr = addr 31.23 if self.console.connect(self.addr, self): 31.24 self.transport.write("Cannot connect to console %d on domain %d\n" 31.25 - % (self.id, self.console.dom)) 31.26 + % (self.id, self.console.getDomain())) 31.27 self.loseConnection() 31.28 return 31.29 else: 31.30 @@ -49,6 +48,7 @@ class ConsoleProtocol(protocol.Protocol) 31.31 return len(data) 31.32 31.33 def connectionLost(self, reason=None): 31.34 + print 'ConsoleProtocol>connectionLost>', reason 31.35 log.info("Console disconnected %s %s %s", 31.36 str(self.id), str(self.addr[0]), str(self.addr[1])) 31.37 eserver.inject('xend.console.disconnect', 31.38 @@ -85,7 +85,6 @@ class ConsoleDev(Dev): 31.39 STATUS_LISTENING = 'listening' 31.40 31.41 def __init__(self, controller, id, config, recreate=False): 31.42 - print 'Console>' 31.43 Dev.__init__(self, controller, id, config) 31.44 self.status = self.STATUS_NEW 31.45 self.addr = None 31.46 @@ -108,7 +107,6 @@ class ConsoleDev(Dev): 31.47 [self.id, self.getDomain(), self.console_port]) 31.48 31.49 def init(self, recreate=False, reboot=False): 31.50 - print 'Console>init>' 31.51 self.destroyed = False 31.52 self.channel = self.getChannel() 31.53 self.listen() 31.54 @@ -165,6 +163,7 @@ class ConsoleDev(Dev): 31.55 def destroy(self, change=False, reboot=False): 31.56 """Close the console. 31.57 """ 31.58 + print 'ConsoleDev>destroy>', self, reboot 31.59 if reboot: 31.60 return 31.61 self.status = self.STATUS_CLOSED 31.62 @@ -175,7 +174,8 @@ class ConsoleDev(Dev): 31.63 def listen(self): 31.64 """Listen for TCP connections to the console port.. 31.65 """ 31.66 - if self.closed(): return 31.67 + if self.closed(): 31.68 + return 31.69 if self.listener: 31.70 pass 31.71 else: 31.72 @@ -193,8 +193,10 @@ class ConsoleDev(Dev): 31.73 31.74 returns 0 if ok, negative otherwise 31.75 """ 31.76 - if self.closed(): return -1 31.77 - if self.connected(): return -1 31.78 + if self.closed(): 31.79 + return -1 31.80 + if self.connected(): 31.81 + return -1 31.82 self.addr = addr 31.83 self.conn = conn 31.84 self.status = self.STATUS_CONNECTED 31.85 @@ -204,6 +206,7 @@ class ConsoleDev(Dev): 31.86 def disconnect(self, conn=None): 31.87 """Disconnect the TCP connection to the console. 31.88 """ 31.89 + print 'ConsoleDev>disconnect>', conn 31.90 if conn and conn != self.conn: return 31.91 if self.conn: 31.92 self.conn.loseConnection() 31.93 @@ -288,6 +291,7 @@ class ConsoleController(DevController): 31.94 self.rebootDevices() 31.95 31.96 def destroyController(self, reboot=False): 31.97 + print 'ConsoleController>destroyController>', self, reboot 31.98 self.destroyed = True 31.99 self.destroyDevices(reboot=reboot) 31.100 self.rcvr.deregisterChannel() 31.101 @@ -312,4 +316,6 @@ class ConsoleController(DevController): 31.102 console = self.getDevice(0) 31.103 if console: 31.104 console.receiveOutput(msg) 31.105 + else: 31.106 + log.warning('no console: domain %d', self.getDomain()) 31.107
32.1 --- a/tools/python/xen/xend/server/controller.py Wed Apr 20 08:45:19 2005 +0000 32.2 +++ b/tools/python/xen/xend/server/controller.py Thu Apr 21 13:25:07 2005 +0000 32.3 @@ -83,7 +83,8 @@ class CtrlMsgRcvr: 32.4 def lostChannel(self): 32.5 """Called when the channel to the domain is lost. 32.6 """ 32.7 - print 'CtrlMsgRcvr>lostChannel>', 32.8 + if DEBUG: 32.9 + print 'CtrlMsgRcvr>lostChannel>', 32.10 self.channel = None 32.11 32.12 def registerChannel(self): 32.13 @@ -234,14 +235,12 @@ class DevController: 32.14 raise NotImplementedError() 32.15 32.16 def createDevice(self, config, recreate=False, change=False): 32.17 - print 'DevController>createDevice>', 'config=', config, 'recreate=', recreate, 'change=', change 32.18 dev = self.newDevice(self.nextDeviceId(), config, recreate=recreate) 32.19 dev.init(recreate=recreate) 32.20 self.addDevice(dev) 32.21 idx = self.getDeviceIndex(dev) 32.22 recreate = self.vm.get_device_recreate(self.getType(), idx) 32.23 dev.attach(recreate=recreate, change=change) 32.24 - print 'DevController>createDevice<' 32.25 32.26 def configureDevice(self, id, config, change=False): 32.27 """Reconfigure an existing device. 32.28 @@ -290,6 +289,9 @@ class DevController: 32.29 def getDeviceIds(self): 32.30 return [ dev.getId() for dev in self.device_order ] 32.31 32.32 + def getDeviceIndexes(self): 32.33 + return range(0, len(self.device_order)) 32.34 + 32.35 def getDevices(self): 32.36 return self.device_order 32.37 32.38 @@ -314,7 +316,6 @@ class DevController: 32.39 self.device_order.remove(dev) 32.40 32.41 def rebootDevices(self): 32.42 - print 'DevController>rebootDevices>', self 32.43 for dev in self.getDevices(): 32.44 dev.reboot() 32.45 32.46 @@ -405,7 +406,6 @@ class Dev: 32.47 def reboot(self): 32.48 """Reconnect device when the domain is rebooted. 32.49 """ 32.50 - print 'Dev>reboot>', self 32.51 self.init(reboot=True) 32.52 self.attach() 32.53
33.1 --- a/tools/python/xen/xend/server/domain.py Wed Apr 20 08:45:19 2005 +0000 33.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 33.3 @@ -1,58 +0,0 @@ 33.4 -# Copyright (C) 2004 Mike Wray <mike.wray@hp.com> 33.5 - 33.6 -from xen.xend.XendError import XendError 33.7 - 33.8 -import channel 33.9 -import controller 33.10 -from messages import * 33.11 - 33.12 -class DomainControllerFactory(controller.ControllerFactory): 33.13 - """Factory for creating domain controllers. 33.14 - """ 33.15 - 33.16 - def createController(self, dom): 33.17 - """Create a domain controller. 33.18 - 33.19 - dom domain 33.20 - 33.21 - returns domain controller 33.22 - """ 33.23 - return DomainController(self, dom) 33.24 - 33.25 -class DomainController(controller.Controller): 33.26 - """Generic controller for a domain. 33.27 - Used for domain shutdown. 33.28 - """ 33.29 - 33.30 - """Map shutdown reasons to the message type to use. 33.31 - """ 33.32 - reasons = {'poweroff' : 'shutdown_poweroff_t', 33.33 - 'reboot' : 'shutdown_reboot_t', 33.34 - 'suspend' : 'shutdown_suspend_t', 33.35 - 'sysrq' : 'shutdown_sysrq_t' } 33.36 - 33.37 - def __init__(self, factory, dom): 33.38 - controller.Controller.__init__(self, factory, dom) 33.39 - self.addMethod(CMSG_SHUTDOWN, 0, None) 33.40 - self.addMethod(CMSG_MEM_REQUEST, 0, None) 33.41 - self.registerChannel() 33.42 - 33.43 - def shutdown(self, reason, key=0): 33.44 - """Shutdown a domain. 33.45 - 33.46 - reason shutdown reason 33.47 - key sysrq key (only if reason is 'sysrq') 33.48 - """ 33.49 - msgtype = self.reasons.get(reason) 33.50 - if not msgtype: 33.51 - raise XendError('invalid reason:' + reason) 33.52 - extra = {} 33.53 - if reason == 'sysrq': extra['key'] = key 33.54 - print extra 33.55 - self.writeRequest(packMsg(msgtype, extra)) 33.56 - 33.57 - def mem_target_set(self, target): 33.58 - """Set domain memory target in pages. 33.59 - """ 33.60 - msg = packMsg('mem_request_t', { 'target' : target * (1 << 8)} ) 33.61 - self.writeRequest(msg)
34.1 --- a/tools/python/xen/xend/server/event.py Wed Apr 20 08:45:19 2005 +0000 34.2 +++ b/tools/python/xen/xend/server/event.py Thu Apr 21 13:25:07 2005 +0000 34.3 @@ -1,4 +1,7 @@ 34.4 -from twisted.internet import reactor, protocol, defer 34.5 +import sys 34.6 +import StringIO 34.7 + 34.8 +from xen.web import reactor, protocol 34.9 34.10 from xen.lowlevel import xu 34.11 34.12 @@ -64,7 +67,10 @@ class EventProtocol(protocol.Protocol): 34.13 sxp.show(sxpr, out=io) 34.14 print >> io 34.15 io.seek(0) 34.16 - return self.transport.write(io.getvalue()) 34.17 + if self.transport: 34.18 + return self.transport.write(io.getvalue()) 34.19 + else: 34.20 + return 0 34.21 34.22 def send_result(self, res): 34.23 return self.send_reply(['ok', res]) 34.24 @@ -135,10 +141,10 @@ class EventProtocol(protocol.Protocol): 34.25 34.26 def op_info(self, name, req): 34.27 val = ['info'] 34.28 - val += self.daemon.consoles() 34.29 - val += self.daemon.blkifs() 34.30 - val += self.daemon.netifs() 34.31 - val += self.daemon.usbifs() 34.32 + #val += self.daemon.consoles() 34.33 + #val += self.daemon.blkifs() 34.34 + #val += self.daemon.netifs() 34.35 + #val += self.daemon.usbifs() 34.36 return val 34.37 34.38 def op_sys_subscribe(self, name, v): 34.39 @@ -175,7 +181,6 @@ class EventProtocol(protocol.Protocol): 34.40 import controller 34.41 controller.DEBUG = (mode == 'on') 34.42 34.43 - 34.44 class EventFactory(protocol.Factory): 34.45 """Asynchronous handler for the event server socket. 34.46 """ 34.47 @@ -191,8 +196,6 @@ class EventFactory(protocol.Factory): 34.48 proto.factory = self 34.49 return proto 34.50 34.51 - 34.52 def listenEvent(daemon, port, interface): 34.53 - protocol = EventFactory(daemon) 34.54 - return reactor.listenTCP(port, protocol, interface=interface) 34.55 - 34.56 + factory = EventFactory(daemon) 34.57 + return reactor.listenTCP(port, factory, interface=interface)
35.1 --- a/tools/python/xen/xend/server/netif.py Wed Apr 20 08:45:19 2005 +0000 35.2 +++ b/tools/python/xen/xend/server/netif.py Thu Apr 21 13:25:07 2005 +0000 35.3 @@ -4,8 +4,6 @@ 35.4 35.5 import random 35.6 35.7 -from twisted.internet import defer 35.8 - 35.9 from xen.xend import sxp 35.10 from xen.xend import Vifctl 35.11 from xen.xend.XendError import XendError, VmError 35.12 @@ -420,7 +418,6 @@ class NetifController(DevController): 35.13 @param id: interface id 35.14 @param config: device configuration 35.15 @param recreate: recreate flag (true after xend restart) 35.16 - @return: deferred 35.17 """ 35.18 return NetDev(self, id, config, recreate=recreate) 35.19