ia64/xen-unstable

changeset 4634:d781b9d08e80

bitkeeper revision 1.1327.2.4 (426918a34Af7gihN8mTkq-P3KrAZXg)

Remove twisted from save/migrate handling.
This needs to use threads, so add thread support for
http server requests.

Signed-off-by: Mike Wray <mike.wray@hp.com>
author mjw@wray-m-3.hpl.hp.com
date Fri Apr 22 15:30:43 2005 +0000 (2005-04-22)
parents 40af907d69a9
children b6ad195cf599
files tools/python/xen/web/SrvBase.py tools/python/xen/web/SrvDir.py tools/python/xen/web/connection.py tools/python/xen/web/http.py tools/python/xen/web/httpserver.py tools/python/xen/web/protocol.py tools/python/xen/xend/XendDomain.py tools/python/xen/xend/XendMigrate.py tools/python/xen/xend/server/SrvConsole.py tools/python/xen/xend/server/SrvConsoleDir.py tools/python/xen/xend/server/SrvDaemon.py tools/python/xen/xend/server/SrvDmesg.py tools/python/xen/xend/server/SrvDomain.py tools/python/xen/xend/server/SrvDomainDir.py tools/python/xen/xend/server/SrvNode.py tools/python/xen/xend/server/SrvVnetDir.py tools/python/xen/xend/server/SrvXendLog.py tools/python/xen/xend/server/usbif.py
line diff
     1.1 --- a/tools/python/xen/web/SrvBase.py	Thu Apr 21 14:11:29 2005 +0000
     1.2 +++ b/tools/python/xen/web/SrvBase.py	Fri Apr 22 15:30:43 2005 +0000
     1.3 @@ -2,6 +2,7 @@
     1.4  
     1.5  import types
     1.6  
     1.7 +
     1.8  from xen.xend import sxp
     1.9  from xen.xend import PrettyPrint
    1.10  from xen.xend.Args import ArgError
    1.11 @@ -10,6 +11,7 @@ from xen.xend.XendLogging import log
    1.12  
    1.13  import resource
    1.14  import http
    1.15 +import httpserver
    1.16  import defer
    1.17  
    1.18  def uri_pathlist(p):
    1.19 @@ -29,19 +31,8 @@ class SrvBase(resource.Resource):
    1.20  
    1.21      
    1.22      def use_sxp(self, req):
    1.23 -        """Determine whether to send an SXP response to a request.
    1.24 -        Uses SXP if there is no User-Agent, no Accept, or application/sxp is in Accept.
    1.25 -
    1.26 -        req		request
    1.27 -        returns 1 for SXP, 0 otherwise
    1.28 -        """
    1.29 -        ok = 0
    1.30 -        user_agent = req.getHeader('User-Agent')
    1.31 -        accept = req.getHeader('Accept')
    1.32 -        if (not user_agent) or (not accept) or (accept.find(sxp.mime_type) >= 0):
    1.33 -            ok = 1
    1.34 -        return ok
    1.35 -
    1.36 +        return req.useSxp()
    1.37 +    
    1.38      def get_op_method(self, op):
    1.39          """Get the method for an operation.
    1.40          For operation 'foo' looks for 'op_foo'.
    1.41 @@ -60,7 +51,7 @@ class SrvBase(resource.Resource):
    1.42  
    1.43          The method must return a list when req.use_sxp is true
    1.44          and an HTML string otherwise (or list).
    1.45 -        Methods may also return a Deferred (for incomplete processing).
    1.46 +        Methods may also return a ThreadRequest (for incomplete processing).
    1.47  
    1.48          req	request
    1.49          """
    1.50 @@ -76,85 +67,10 @@ class SrvBase(resource.Resource):
    1.51              req.write("Operation not implemented: " + op)
    1.52              return ''
    1.53          else:
    1.54 -            return self._perform(op, op_method, req)
    1.55 -
    1.56 -    def _perform(self, op, op_method, req):
    1.57 -        try:
    1.58 -            val = op_method(op, req)
    1.59 -        except Exception, err:
    1.60 -            self._perform_err(err, op, req)
    1.61 -            return ''
    1.62 -            
    1.63 -        if isinstance(val, defer.Deferred):
    1.64 -            val.addCallback(self._perform_cb, op, req, dfr=1)
    1.65 -            val.addErrback(self._perform_err, op, req, dfr=1)
    1.66 -            return server.NOT_DONE_YET
    1.67 -        else:
    1.68 -            self._perform_cb(val, op, req, dfr=0)
    1.69 -            return ''
    1.70 -
    1.71 -    def _perform_cb(self, val, op, req, dfr=0):
    1.72 -        """Callback to complete the request.
    1.73 -        May be called from a Deferred.
    1.74 -
    1.75 -        @param err: the error
    1.76 -        @param req: request causing the error
    1.77 -        @param dfr: deferred flag
    1.78 -        """
    1.79 -        if isinstance(val, resource.ErrorPage):
    1.80 -            req.write(val.render(req))
    1.81 -        elif self.use_sxp(req):
    1.82 -            req.setHeader("Content-Type", sxp.mime_type)
    1.83 -            sxp.show(val, out=req)
    1.84 -        else:
    1.85 -            req.write('<html><head></head><body>')
    1.86 -            self.print_path(req)
    1.87 -            if isinstance(val, types.ListType):
    1.88 -                req.write('<code><pre>')
    1.89 -                PrettyPrint.prettyprint(val, out=req)
    1.90 -                req.write('</pre></code>')
    1.91 -            else:
    1.92 -                req.write(str(val))
    1.93 -            req.write('</body></html>')
    1.94 -        if dfr:
    1.95 -            req.finish()
    1.96 -
    1.97 -    def _perform_err(self, err, op, req, dfr=0):
    1.98 -        """Error callback to complete a request.
    1.99 -        May be called from a Deferred.
   1.100 -
   1.101 -        @param err: the error
   1.102 -        @param req: request causing the error
   1.103 -        @param dfr: deferred flag
   1.104 -        """
   1.105 -        if not (isinstance(err, ArgError) or
   1.106 -                  isinstance(err, sxp.ParseError) or
   1.107 -                  isinstance(err, XendError)):
   1.108 -            if dfr:
   1.109 -                return err
   1.110 -            else:
   1.111 -                raise
   1.112 -        #log.exception("op=%s: %s", op, str(err))
   1.113 -        if self.use_sxp(req):
   1.114 -            req.setHeader("Content-Type", sxp.mime_type)
   1.115 -            sxp.show(['xend.err', str(err)], out=req)
   1.116 -        else:
   1.117 -            req.setHeader("Content-Type", "text/plain")
   1.118 -            req.write('Error ')
   1.119 -            req.write(': ')
   1.120 -            req.write(str(err))
   1.121 -        if dfr:
   1.122 -            req.finish()
   1.123 -        
   1.124 +            return op_method(op, req)
   1.125  
   1.126      def print_path(self, req):
   1.127          """Print the path with hyperlinks.
   1.128          """
   1.129 -        pathlist = [x for x in req.prepath if x != '' ]
   1.130 -        s = "/"
   1.131 -        req.write('<h1><a href="/">/</a>')
   1.132 -        for x in pathlist:
   1.133 -            s += x + "/"
   1.134 -            req.write(' <a href="%s">%s</a>/' % (s, x))
   1.135 -        req.write("</h1>")
   1.136 +        req.printPath()
   1.137  
     2.1 --- a/tools/python/xen/web/SrvDir.py	Thu Apr 21 14:11:29 2005 +0000
     2.2 +++ b/tools/python/xen/web/SrvDir.py	Fri Apr 22 15:30:43 2005 +0000
     2.3 @@ -47,9 +47,6 @@ class SrvDir(SrvBase):
     2.4          self.table = {}
     2.5          self.order = []
     2.6  
     2.7 -    def __repr__(self):
     2.8 -        return "<SrvDir %x %s>" %(id(self), self.table.keys())
     2.9 -
    2.10      def noChild(self, msg):
    2.11          return resource.ErrorPage(http.NOT_FOUND, msg=msg)
    2.12  
     3.1 --- a/tools/python/xen/web/connection.py	Thu Apr 21 14:11:29 2005 +0000
     3.2 +++ b/tools/python/xen/web/connection.py	Fri Apr 22 15:30:43 2005 +0000
     3.3 @@ -72,6 +72,8 @@ class SocketServerConnection:
     3.4                  return True
     3.5  
     3.6      def dataReceived(self, data):
     3.7 +        if not self.connected:
     3.8 +            return True
     3.9          if not self.protocol:
    3.10              return True
    3.11          try:
    3.12 @@ -79,7 +81,7 @@ class SocketServerConnection:
    3.13          except SystemExit:
    3.14              raise
    3.15          except Exception, ex:
    3.16 -            self.disconnect(ex)
    3.17 +            self.loseConnection(ex)
    3.18              return True
    3.19          return False
    3.20  
    3.21 @@ -261,7 +263,7 @@ class SocketClientConnection:
    3.22          except SystemExit:
    3.23              raise
    3.24          except Exception, ex:
    3.25 -            self.disconnect(ex)
    3.26 +            self.loseConnection(ex)
    3.27  
    3.28      def mainLoop(self):
    3.29          # Something a protocol could call.
    3.30 @@ -282,7 +284,7 @@ class SocketClientConnection:
    3.31              if ex.args[0] in (EWOULDBLOCK, EAGAIN, EINTR):
    3.32                  return False
    3.33              else:
    3.34 -                self.disconnect(ex)
    3.35 +                self.loseConnection(ex)
    3.36                  return True
    3.37  
    3.38      def read(self):
    3.39 @@ -293,7 +295,7 @@ class SocketClientConnection:
    3.40              if ex.args[0] in (EWOULDBLOCK, EAGAIN, EINTR):
    3.41                  return None
    3.42              else:
    3.43 -                self.disconnect(ex)
    3.44 +                self.loseConnection(ex)
    3.45                  return True
    3.46          
    3.47      def dataReceived(self, data):
    3.48 @@ -304,11 +306,11 @@ class SocketClientConnection:
    3.49          except SystemExit:
    3.50              raise
    3.51          except Exception, ex:
    3.52 -            self.disconnect(ex)
    3.53 +            self.loseConnection(ex)
    3.54              return True
    3.55          return False
    3.56  
    3.57 -    def disconnect(self, reason=None):
    3.58 +    def loseConnection(self, reason=None):
    3.59          self.thread = None
    3.60          self.closeSocket(reason)
    3.61          self.closeProtocol(reason)
    3.62 @@ -350,6 +352,8 @@ class SocketConnector:
    3.63  
    3.64      def __init__(self, factory):
    3.65          self.factoryStarted = False
    3.66 +        self.clientLost = False
    3.67 +        self.clientFailed = False
    3.68          self.factory = factory
    3.69          self.state = "disconnected"
    3.70          self.transport = None
    3.71 @@ -364,11 +368,14 @@ class SocketConnector:
    3.72          if self.state != "disconnected":
    3.73              raise socket.error(EINVAL, "cannot connect in state " + self.state)
    3.74          self.state = "connecting"
    3.75 +        self.clientLost = False
    3.76 +        self.clientFailed = False
    3.77          if not self.factoryStarted:
    3.78              self.factoryStarted = True
    3.79              self.factory.doStart()
    3.80 -        self.factory.startedConnecting()
    3.81 +        self.factory.startedConnecting(self)
    3.82          self.connectTransport()
    3.83 +        self.state = "connected"
    3.84  
    3.85      def stopConnecting(self):
    3.86          if self.state != "connecting":
    3.87 @@ -380,8 +387,12 @@ class SocketConnector:
    3.88          return self.factory.buildProtocol(addr)
    3.89  
    3.90      def connectionLost(self, reason=None):
    3.91 -        self.factory.doStop()
    3.92 +        if not self.clientLost:
    3.93 +            self.clientLost = True
    3.94 +            self.factory.clientConnectionLost(self, reason)
    3.95  
    3.96      def connectionFailed(self, reason=None):
    3.97 -        self.factory.doStop()
    3.98 +        if not self.clientFailed:
    3.99 +            self.clientFailed = True
   3.100 +            self.factory.clientConnectionFailed(self, reason)
   3.101          
     4.1 --- a/tools/python/xen/web/http.py	Thu Apr 21 14:11:29 2005 +0000
     4.2 +++ b/tools/python/xen/web/http.py	Fri Apr 22 15:30:43 2005 +0000
     4.3 @@ -282,7 +282,6 @@ class HttpRequest:
     4.4              header_count += 1
     4.5              if line == '\r\n' or line == '\n' or line == '':
     4.6                  break
     4.7 -        #print 'parseRequestHeaders>', header_bytes
     4.8          header_input = StringIO(header_bytes)
     4.9          self.request_headers = Message(header_input)
    4.10  
    4.11 @@ -329,7 +328,6 @@ class HttpRequest:
    4.12          self.content.seek(0,0)
    4.13  
    4.14      def parseRequest(self):
    4.15 -        #print 'parseRequest>'
    4.16          self.request_line = self.rin.readline()
    4.17          self.parseRequestLine()
    4.18          self.parseRequestHeaders()
    4.19 @@ -338,7 +336,6 @@ class HttpRequest:
    4.20          self.setCloseConnection(connection_mode)
    4.21          self.readContent()
    4.22          self.parseRequestArgs()
    4.23 -        #print 'parseRequest<'
    4.24  
    4.25      def setCloseConnection(self, mode):
    4.26          if not mode: return
    4.27 @@ -347,8 +344,10 @@ class HttpRequest:
    4.28              self.close_connection = True
    4.29          elif (mode == 'keep-alive') and (self.http_version >= (1, 1)):
    4.30              self.close_connection = False
    4.31 -        #print 'setCloseConnection>', mode, self.close_connection
    4.32          
    4.33 +    def getCloseConnection(self):
    4.34 +        return self.close_connection
    4.35 +
    4.36      def getHeader(self, k, v=None):
    4.37          return self.request_headers.get(k, v)
    4.38  
    4.39 @@ -365,7 +364,6 @@ class HttpRequest:
    4.40          self.response_status = status
    4.41  
    4.42      def setResponseHeader(self, k, v):
    4.43 -        #print 'setResponseHeader>', k, v
    4.44          k = k.lower()
    4.45          self.response_headers[k] = v
    4.46          if k == 'connection':
    4.47 @@ -432,7 +430,6 @@ class HttpRequest:
    4.48          self.send("\r\n")
    4.49          
    4.50      def sendResponse(self):
    4.51 -        #print 'sendResponse>'
    4.52          if self.response_sent:
    4.53              return
    4.54          self.response_sent = True
    4.55 @@ -443,7 +440,6 @@ class HttpRequest:
    4.56              self.output.seek(0, 0)
    4.57              body = self.output.getvalue()
    4.58              body_length = len(body)
    4.59 -            #print 'sendResponse> body=', body_length, body
    4.60              self.setResponseHeader("Content-Length", body_length)
    4.61          if self.http_version > (0, 9):
    4.62              self.send("%s %d %s\r\n" % (self.http_version_string,
    4.63 @@ -451,17 +447,19 @@ class HttpRequest:
    4.64                                           self.response_status))
    4.65              self.sendResponseHeaders()
    4.66          if send_body:
    4.67 -            #print 'sendResponse> writing body'
    4.68              self.send(body)
    4.69 +        self.flush()
    4.70  
    4.71      def write(self, data):
    4.72 -        #print 'write>', data
    4.73          self.output.write(data)
    4.74  
    4.75      def send(self, data):
    4.76 -        #print 'send>', len(data), '|%s|' % data
    4.77 +        #print 'send>', data
    4.78          self.out.write(data)
    4.79  
    4.80 +    def flush(self):
    4.81 +        self.out.flush()
    4.82 +
    4.83      def hasNoBody(self):
    4.84          return ((self.request_method == "HEAD") or
    4.85                  (self.response_code in NO_BODY_CODES) or
     5.1 --- a/tools/python/xen/web/httpserver.py	Thu Apr 21 14:11:29 2005 +0000
     5.2 +++ b/tools/python/xen/web/httpserver.py	Fri Apr 22 15:30:43 2005 +0000
     5.3 @@ -1,27 +1,137 @@
     5.4 +import threading
     5.5 +
     5.6  import string
     5.7  import socket
     5.8 +import types
     5.9  from urllib import quote, unquote
    5.10  
    5.11 +from xen.xend import sxp
    5.12 +from xen.xend.Args import ArgError
    5.13 +from xen.xend.XendError import XendError
    5.14 +
    5.15  import http
    5.16 +from resource import Resource, ErrorPage
    5.17  from SrvDir import SrvDir
    5.18  
    5.19 -class HttpServerRequest(http.HttpRequest):
    5.20 +class ThreadRequest:
    5.21 +    """A request to complete processing using a thread.
    5.22 +    """
    5.23 +    
    5.24 +    def __init__(self, processor, req, fn, args, kwds):
    5.25 +        self.processor = processor
    5.26 +        self.req = req
    5.27 +        self.fn = fn
    5.28 +        self.args = args
    5.29 +        self.kwds = kwds
    5.30 +        
    5.31 +    def run(self):
    5.32 +        self.processor.setInThread()
    5.33 +        thread = threading.Thread(target=self.main)
    5.34 +        thread.setDaemon(True)
    5.35 +        thread.start()
    5.36 +
    5.37 +    def call(self):
    5.38 +        try:
    5.39 +            self.fn(*self.args, **self.kwds)
    5.40 +        except SystemExit:
    5.41 +            raise
    5.42 +        except Exception, ex:
    5.43 +            self.req.resultErr(ex)
    5.44 +        self.req.finish()
    5.45 +
    5.46 +    def main(self):
    5.47 +        self.call()
    5.48 +        self.processor.process()
    5.49 +       
    5.50 +
    5.51 +class RequestProcessor:
    5.52 +    """Processor for requests on a connection to an http server.
    5.53 +    Requests are executed synchonously unless they ask for a thread by returning
    5.54 +    a ThreadRequest.
    5.55 +    """
    5.56 +
    5.57 +    done = False
    5.58 +
    5.59 +    inThread = False
    5.60  
    5.61 -    def __init__(self, server, addr, srd, srw):
    5.62 -        #print 'HttpServerRequest>', addr
    5.63 +    def __init__(self, server, sock, addr):
    5.64          self.server = server
    5.65 +        self.sock = sock
    5.66 +        self.srd = sock.makefile('rb')
    5.67 +        self.srw = sock.makefile('wb')
    5.68 +        self.srvaddr = server.getServerAddr()
    5.69 +
    5.70 +    def isInThread(self):
    5.71 +        return self.inThread
    5.72 +
    5.73 +    def setInThread(self):
    5.74 +        self.inThread = True
    5.75 +
    5.76 +    def getServer(self):
    5.77 +        return self.server
    5.78 +
    5.79 +    def getRequest(self):
    5.80 +        return HttpServerRequest(self, self.srvaddr, self.srd, self.srw)
    5.81 +
    5.82 +    def close(self):
    5.83 +        try:
    5.84 +            self.sock.close()
    5.85 +        except:
    5.86 +            pass
    5.87 +
    5.88 +    def finish(self):
    5.89 +        self.done = True
    5.90 +        self.close()
    5.91 +
    5.92 +    def process(self):
    5.93 +        while not self.done:
    5.94 +            req = self.getRequest()
    5.95 +            res = req.process()
    5.96 +            if isinstance(res, ThreadRequest):
    5.97 +                if self.isInThread():
    5.98 +                    res.call()
    5.99 +                else:
   5.100 +                    res.run()
   5.101 +                    break
   5.102 +            else:
   5.103 +                req.finish()
   5.104 +                                        
   5.105 +class HttpServerRequest(http.HttpRequest):
   5.106 +    """A single request to an http server.
   5.107 +    """
   5.108 +
   5.109 +    def __init__(self, processor, addr, srd, srw):
   5.110 +        self.processor = processor
   5.111          self.prepath = ''
   5.112          http.HttpRequest.__init__(self, addr, srd, srw)
   5.113  
   5.114 +    def getServer(self):
   5.115 +        return self.processor.getServer()
   5.116 +
   5.117      def process(self):
   5.118 -        #print 'HttpServerRequest>process', 'path=', self.request_path
   5.119 -        self.prepath = []
   5.120 -        self.postpath = map(unquote, string.split(self.request_path[1:], '/'))
   5.121 -        res = self.getResource()
   5.122 -        self.render(res)
   5.123 +        """Process the request. If the return value is a ThreadRequest
   5.124 +        it is evaluated in a thread.
   5.125 +        """
   5.126 +        try:
   5.127 +            self.prepath = []
   5.128 +            self.postpath = map(unquote, string.split(self.request_path[1:], '/'))
   5.129 +            resource = self.getResource()
   5.130 +            return self.render(resource)
   5.131 +        except SystemExit:
   5.132 +            raise
   5.133 +        except Exception, ex:
   5.134 +            self.processError(ex)
   5.135 +
   5.136 +    def processError(self, ex):
   5.137 +        import traceback; traceback.print_exc()
   5.138 +        self.sendError(http.INTERNAL_SERVER_ERROR, msg=str(ex))
   5.139 +        self.setCloseConnection('close')
   5.140 +
   5.141 +    def finish(self):
   5.142          self.sendResponse()
   5.143 -        return self.close_connection
   5.144 -    
   5.145 +        if self.close_connection:
   5.146 +            self.processor.finish()
   5.147 +
   5.148      def prePathURL(self):
   5.149          url_host = self.getRequestHostname()
   5.150          port = self.getPort()
   5.151 @@ -37,25 +147,111 @@ class HttpServerRequest(http.HttpRequest
   5.152          return ('%s://%s/%s' % (url_proto, url_host, url_path))
   5.153  
   5.154      def getResource(self):
   5.155 -        return self.server.getResource(self)
   5.156 +        return self.getServer().getResource(self)
   5.157  
   5.158 -    def render(self, res):
   5.159 -        #print 'HttpServerRequest>render', res
   5.160 -        if res is None:
   5.161 +    def render(self, resource):
   5.162 +        val = None
   5.163 +        if resource is None:
   5.164              self.sendError(http.NOT_FOUND)
   5.165          else:
   5.166 -            res.render(self)
   5.167 +            try:
   5.168 +                while True:
   5.169 +                    val = resource.render(self)
   5.170 +                    if not isinstance(val, Resource):
   5.171 +                        break
   5.172 +                val = self.result(val)
   5.173 +            except SystemExit:
   5.174 +                raise
   5.175 +            except Exception, ex:
   5.176 +                self.resultErr(ex)
   5.177 +        return val
   5.178 +
   5.179 +    def threadRequest(self, _fn, *_args, **_kwds):
   5.180 +        """Create a request to finish request processing in a thread.
   5.181 +        Use this to create a ThreadRequest to return from rendering a
   5.182 +        resource if you need a thread to complete processing.
   5.183 +        """
   5.184 +        return ThreadRequest(self.processor, self, _fn, _args, _kwds)
   5.185 +            
   5.186 +    def result(self, val):
   5.187 +        if isinstance(val, Exception):
   5.188 +            return self.resultErr(val)
   5.189 +        else:
   5.190 +            return self.resultVal(val)
   5.191 +
   5.192 +    def resultVal(self, val):
   5.193 +        """Callback to complete the request.
   5.194  
   5.195 +        @param val: the value
   5.196 +        """
   5.197 +        if isinstance(val, ThreadRequest):
   5.198 +            return val
   5.199 +        elif self.useSxp():
   5.200 +            self.setHeader("Content-Type", sxp.mime_type)
   5.201 +            sxp.show(val, out=self)
   5.202 +        else:
   5.203 +            self.write('<html><head></head><body>')
   5.204 +            self.printPath()
   5.205 +            if isinstance(val, types.ListType):
   5.206 +                self.write('<code><pre>')
   5.207 +                PrettyPrint.prettyprint(val, out=self)
   5.208 +                self.write('</pre></code>')
   5.209 +            else:
   5.210 +                self.write(str(val))
   5.211 +            self.write('</body></html>')
   5.212 +        return None
   5.213 +
   5.214 +    def resultErr(self, err):
   5.215 +        """Error callback to complete a request.
   5.216 +
   5.217 +        @param err: the error
   5.218 +        """
   5.219 +        if not isinstance(err, (ArgError, sxp.ParseError, XendError)):
   5.220 +            raise
   5.221 +        #log.exception("op=%s: %s", op, str(err))
   5.222 +        if self.useSxp():
   5.223 +            self.setHeader("Content-Type", sxp.mime_type)
   5.224 +            sxp.show(['xend.err', str(err)], out=self)
   5.225 +        else:
   5.226 +            self.setHeader("Content-Type", "text/plain")
   5.227 +            self.write('Error ')
   5.228 +            self.write(': ')
   5.229 +            self.write(str(err))
   5.230 +        return None
   5.231 +
   5.232 +    def useSxp(self):
   5.233 +        """Determine whether to send an SXP response to a request.
   5.234 +        Uses SXP if there is no User-Agent, no Accept, or application/sxp is in Accept.
   5.235 +
   5.236 +        returns 1 for SXP, 0 otherwise
   5.237 +        """
   5.238 +        ok = 0
   5.239 +        user_agent = self.getHeader('User-Agent')
   5.240 +        accept = self.getHeader('Accept')
   5.241 +        if (not user_agent) or (not accept) or (accept.find(sxp.mime_type) >= 0):
   5.242 +            ok = 1
   5.243 +        return ok
   5.244 +
   5.245 +    def printPath(self):
   5.246 +        pathlist = [x for x in self.prepath if x != '' ]
   5.247 +        s = "/"
   5.248 +        self.write('<h1><a href="/">/</a>')
   5.249 +        for x in pathlist:
   5.250 +            s += x + "/"
   5.251 +            self.write(' <a href="%s">%s</a>/' % (s, x))
   5.252 +        self.write("</h1>")
   5.253 +        
   5.254  class HttpServer:
   5.255  
   5.256 -    request_queue_size = 5
   5.257 +    backlog = 5
   5.258 +
   5.259 +    closed = False
   5.260  
   5.261      def __init__(self, interface='', port=8080, root=None):
   5.262          if root is None:
   5.263              root = SrvDir()
   5.264          self.interface = interface
   5.265          self.port = port
   5.266 -        self.closed = False
   5.267          self.root = root
   5.268  
   5.269      def getRoot(self):
   5.270 @@ -73,13 +269,12 @@ class HttpServer:
   5.271          self.close()
   5.272  
   5.273      def bind(self):
   5.274 -        #print 'bind>', self.interface, self.port
   5.275          self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
   5.276          self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
   5.277          self.socket.bind((self.interface, self.port))
   5.278  
   5.279      def listen(self):
   5.280 -        self.socket.listen(self.request_queue_size)
   5.281 +        self.socket.listen(self.backlog)
   5.282  
   5.283      def accept(self):
   5.284          return self.socket.accept()
   5.285 @@ -96,33 +291,27 @@ class HttpServer:
   5.286              pass
   5.287  
   5.288      def acceptRequest(self):
   5.289 -        #print 'acceptRequest>'
   5.290          try:
   5.291              (sock, addr) = self.accept()
   5.292 -            #print 'acceptRequest>', sock, addr
   5.293              self.processRequest(sock, addr)
   5.294          except socket.error:
   5.295              return
   5.296  
   5.297      def processRequest(self, sock, addr):
   5.298 -        #print 'processRequest>', sock, addr
   5.299 -        srd = sock.makefile('rb')
   5.300 -        srw = sock.makefile('wb')
   5.301 -        srvaddr = (socket.gethostname(), self.port)
   5.302 -        while True:
   5.303 -            #print 'HttpServerRequest...'
   5.304 -            req = HttpServerRequest(self, srvaddr, srd, srw)
   5.305 -            close = req.process()
   5.306 -            srw.flush()
   5.307 -            #print 'HttpServerRequest close=', close
   5.308 -            if close:
   5.309 -                break
   5.310          try:
   5.311 -            #print 'close...'
   5.312 -            sock.close()
   5.313 -        except:
   5.314 -            pass
   5.315 -        #print 'processRequest<', sock, addr
   5.316 +            rp = RequestProcessor(self, sock, addr)
   5.317 +            rp.process()
   5.318 +        except SystemExit:
   5.319 +            raise
   5.320 +        except Exception, ex:
   5.321 +            print 'HttpServer>processRequest> exception: ', ex
   5.322 +            try:
   5.323 +                sock.close()
   5.324 +            except:
   5.325 +                pass
   5.326 +
   5.327 +    def getServerAddr(self):
   5.328 +        return (socket.gethostname(), self.port)
   5.329  
   5.330      def getResource(self, req):
   5.331          return self.root.getRequestResource(req)
     6.1 --- a/tools/python/xen/web/protocol.py	Thu Apr 21 14:11:29 2005 +0000
     6.2 +++ b/tools/python/xen/web/protocol.py	Fri Apr 22 15:30:43 2005 +0000
     6.3 @@ -1,29 +1,52 @@
     6.4  class Factory:
     6.5 +    """Generic protocol factory.
     6.6 +    """
     6.7 +
     6.8 +    starts = 0
     6.9  
    6.10      def __init__(self):
    6.11          pass
    6.12  
    6.13 -    def startedConnecting(self):
    6.14 -        print 'ServerProtocolFactory>startedConnecting>'
    6.15 -        pass
    6.16 -
    6.17      def doStart(self):
    6.18 -        print 'ServerProtocolFactory>doStart>'
    6.19 -        pass
    6.20 +        if self.starts == 0:
    6.21 +            self.startFactory()
    6.22 +        self.starts += 1
    6.23  
    6.24      def doStop(self):
    6.25 -        print 'ServerProtocolFactory>doStop>'
    6.26 -        pass
    6.27 +        if self.starts > 0:
    6.28 +            self.starts -= 1
    6.29 +        else:
    6.30 +            return
    6.31 +        if self.starts == 0:
    6.32 +            self.stopFactory()
    6.33  
    6.34      def buildProtocol(self, addr):
    6.35 -        print 'ServerProtocolFactory>buildProtocol>', addr
    6.36          return Protocol(self)
    6.37  
    6.38 +    def startFactory(self):
    6.39 +        pass
    6.40 +
    6.41 +    def stopFactory(self):
    6.42 +        pass
    6.43 +
    6.44  class ServerFactory(Factory):
    6.45 +    """Factory for server protocols.
    6.46 +    """
    6.47      pass
    6.48      
    6.49  class ClientFactory(Factory):
    6.50 -    pass
    6.51 +    """Factory for client protocols.
    6.52 +    """
    6.53 +    
    6.54 +    def startedConnecting(self, connector):
    6.55 +        pass
    6.56 +
    6.57 +    def clientConnectionLost(self, connector, reason):
    6.58 +        pass
    6.59 +
    6.60 +    def clientConnectionFailed(self, connector, reason):
    6.61 +        pass
    6.62 +
    6.63  
    6.64  class Protocol:
    6.65  
    6.66 @@ -65,23 +88,32 @@ class Protocol:
    6.67          else:
    6.68              return None
    6.69  
    6.70 -class TestClientFactory(Factory):
    6.71 +class TestClientFactory(ClientFactory):
    6.72  
    6.73      def buildProtocol(self, addr):
    6.74 -        print 'TestClientProtocolFactory>buildProtocol>', addr
    6.75 +        print 'TestClientFactory>buildProtocol>', addr
    6.76          return TestClientProtocol(self)
    6.77      
    6.78 +    def startedConnecting(self, connector):
    6.79 +        print 'TestClientFactory>startedConnecting>', connector
    6.80 +
    6.81 +    def clientConnectionLost(self, connector, reason):
    6.82 +        print 'TestClientFactory>clientConnectionLost>', connector, reason
    6.83 +
    6.84 +    def clientConnectionFailed(self, connector, reason):
    6.85 +        print 'TestClientFactory>clientConnectionFailed>', connector, reason
    6.86 +
    6.87  class TestClientProtocol(Protocol):
    6.88  
    6.89      def connectionMade(self, addr):
    6.90 -        print 'TestProtocol>connectionMade>', addr
    6.91 +        print 'TestClientProtocol>connectionMade>', addr
    6.92          self.write("hello")
    6.93          self.write("there")
    6.94  
    6.95  class TestServerFactory(Factory):
    6.96  
    6.97      def buildProtocol(self, addr):
    6.98 -        print 'TestServerProtocolFactory>buildProtocol>', addr
    6.99 +        print 'TestServerFactory>buildProtocol>', addr
   6.100          return TestServerProtocol(self)
   6.101      
   6.102  class TestServerProtocol(Protocol):
     7.1 --- a/tools/python/xen/xend/XendDomain.py	Thu Apr 21 14:11:29 2005 +0000
     7.2 +++ b/tools/python/xen/xend/XendDomain.py	Fri Apr 22 15:30:43 2005 +0000
     7.3 @@ -369,7 +369,7 @@ class XendDomain:
     7.4  
     7.5          @param id: domain id
     7.6          """
     7.7 -        dominfo = xen_domain(id)
     7.8 +        dominfo = self.xen_domain(id)
     7.9          if dominfo:
    7.10              d = self.domain_by_id.get(id)
    7.11              if d:
    7.12 @@ -454,7 +454,6 @@ class XendDomain:
    7.13  
    7.14          @param src:      source file
    7.15          @param progress: output progress if true
    7.16 -        @return: deferred
    7.17          """
    7.18          xmigrate = XendMigrate.instance()
    7.19          return xmigrate.restore_begin(src)
    7.20 @@ -667,7 +666,6 @@ class XendDomain:
    7.21          """Start domain migration.
    7.22  
    7.23          @param id: domain id
    7.24 -        @return: deferred
    7.25          """
    7.26          # Need a cancel too?
    7.27          # Don't forget to cancel restart for it.
    7.28 @@ -681,7 +679,6 @@ class XendDomain:
    7.29          @param id:       domain id
    7.30          @param dst:      destination file
    7.31          @param progress: output progress if true
    7.32 -        @return: deferred
    7.33          """
    7.34          dominfo = self.domain_lookup(id)
    7.35          xmigrate = XendMigrate.instance()
     8.1 --- a/tools/python/xen/xend/XendMigrate.py	Thu Apr 21 14:11:29 2005 +0000
     8.2 +++ b/tools/python/xen/xend/XendMigrate.py	Fri Apr 22 15:30:43 2005 +0000
     8.3 @@ -1,6 +1,7 @@
     8.4  # Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
     8.5  
     8.6  import traceback
     8.7 +import threading
     8.8  
     8.9  import errno
    8.10  import sys
    8.11 @@ -8,12 +9,8 @@ import socket
    8.12  import time
    8.13  import types
    8.14  
    8.15 -from twisted.internet import reactor
    8.16 -from twisted.internet import defer
    8.17 -#defer.Deferred.debug = 1
    8.18 -from twisted.internet.protocol import Protocol
    8.19 -from twisted.internet.protocol import ClientFactory
    8.20 -from twisted.python.failure import Failure
    8.21 +from xen.web import reactor
    8.22 +from xen.web.protocol import Protocol, ClientFactory
    8.23  
    8.24  import sxp
    8.25  import XendDB
    8.26 @@ -37,11 +34,13 @@ class Xfrd(Protocol):
    8.27          self.parser = sxp.Parser()
    8.28          self.xinfo = xinfo
    8.29  
    8.30 -    def connectionMade(self):
    8.31 +    def connectionMade(self, addr=None):
    8.32          # Send hello.
    8.33          self.request(['xfr.hello', XFR_PROTO_MAJOR, XFR_PROTO_MINOR])
    8.34          # Send request.
    8.35          self.xinfo.request(self)
    8.36 +        # Run the transport mainLoop which reads from the peer.
    8.37 +        self.transport.mainLoop()
    8.38  
    8.39      def request(self, req):
    8.40          sxp.show(req, out=self.transport)
    8.41 @@ -60,7 +59,6 @@ class Xfrd(Protocol):
    8.42          if self.parser.at_eof():
    8.43              self.loseConnection()
    8.44              
    8.45 -
    8.46  class XfrdClientFactory(ClientFactory):
    8.47      """Factory for clients of the migration/save daemon xfrd.
    8.48      """
    8.49 @@ -68,7 +66,33 @@ class XfrdClientFactory(ClientFactory):
    8.50      def __init__(self, xinfo):
    8.51          #ClientFactory.__init__(self)
    8.52          self.xinfo = xinfo
    8.53 +        self.readyCond = threading.Condition()
    8.54 +        self.ready = False
    8.55 +        self.err = None
    8.56  
    8.57 +    def start(self):
    8.58 +        print 'XfrdClientFactory>start>'
    8.59 +        reactor.connectTCP('localhost', XFRD_PORT, self)
    8.60 +        try:
    8.61 +            self.readyCond.acquire()
    8.62 +            while not self.ready:
    8.63 +                self.readyCond.wait()
    8.64 +        finally:
    8.65 +            self.readyCond.release()
    8.66 +        print 'XfrdClientFactory>start>', 'err=', self.err
    8.67 +        if self.err:
    8.68 +            raise self.err
    8.69 +        return 0
    8.70 +
    8.71 +    def notifyReady(self):
    8.72 +        try:
    8.73 +            self.readyCond.acquire()
    8.74 +            self.ready = True
    8.75 +            self.err = self.xinfo.error_summary()
    8.76 +            self.readyCond.notify()
    8.77 +        finally:
    8.78 +            self.readyCond.release()
    8.79 +            
    8.80      def startedConnecting(self, connector):
    8.81          pass
    8.82  
    8.83 @@ -76,10 +100,72 @@ class XfrdClientFactory(ClientFactory):
    8.84          return Xfrd(self.xinfo)
    8.85  
    8.86      def clientConnectionLost(self, connector, reason):
    8.87 -        pass
    8.88 +        print "XfrdClientFactory>clientConnectionLost>", reason
    8.89 +        self.notifyReady()
    8.90  
    8.91      def clientConnectionFailed(self, connector, reason):
    8.92 +        print "XfrdClientFactory>clientConnectionFailed>", reason
    8.93          self.xinfo.error(reason)
    8.94 +        self.notifyReady()
    8.95 +
    8.96 +class SuspendHandler:
    8.97 +
    8.98 +    def __init__(self, xinfo, vmid, timeout):
    8.99 +        self.xinfo = xinfo
   8.100 +        self.vmid = vmid
   8.101 +        self.timeout = timeout
   8.102 +        self.readyCond = threading.Condition()
   8.103 +        self.ready = False
   8.104 +        self.err = None
   8.105 +
   8.106 +    def start(self):
   8.107 +        self.subscribe(on=True)
   8.108 +        timer = reactor.callLater(self.timeout, self.onTimeout)
   8.109 +        try:
   8.110 +            self.readyCond.acquire()
   8.111 +            while not self.ready:
   8.112 +                self.readyCond.wait()
   8.113 +        finally:
   8.114 +            self.readyCond.release()
   8.115 +            self.subscribe(on=False)
   8.116 +            timer.cancel()
   8.117 +        if self.err:
   8.118 +            raise XendError(self.err)
   8.119 +
   8.120 +    def notifyReady(self, err=None):
   8.121 +        try:
   8.122 +            self.readyCond.acquire()
   8.123 +            if not self.ready:
   8.124 +                self.ready = True
   8.125 +                self.err = err
   8.126 +                self.readyCond.notify()
   8.127 +        finally:
   8.128 +            self.readyCond.release()
   8.129 +
   8.130 +    def subscribe(self, on=True):
   8.131 +        # Subscribe to 'suspended' events so we can tell when the
   8.132 +        # suspend completes. Subscribe to 'died' events so we can tell if
   8.133 +        # the domain died.
   8.134 +        if on:
   8.135 +            action = eserver.subscribe
   8.136 +        else:
   8.137 +            action = eserver.unsubscribe
   8.138 +        action('xend.domain.suspended', self.onSuspended)
   8.139 +        action('xend.domain.died', self.onDied)
   8.140 +
   8.141 +    def onSuspended(self, e, v):
   8.142 +        if v[1] != self.vmid: return
   8.143 +        print 'SuspendHandler>onSuspended>', e, v
   8.144 +        self.notifyReady()
   8.145 +                
   8.146 +    def onDied(self, e, v):
   8.147 +        if v[1] != self.vmid: return
   8.148 +        print 'SuspendHandler>onDied>', e, v
   8.149 +        self.notifyReady('Domain %s died while suspending' % self.vmid)
   8.150 +
   8.151 +    def onTimeout(self):
   8.152 +         print 'SuspendHandler>onTimeout>'
   8.153 +         self.notifyReady('Domain %s suspend timed out' % self.vmid)
   8.154  
   8.155  class XfrdInfo:
   8.156      """Abstract class for info about a session with xfrd.
   8.157 @@ -88,18 +174,17 @@ class XfrdInfo:
   8.158  
   8.159      """Suspend timeout (seconds).
   8.160      We set a timeout because suspending a domain can hang."""
   8.161 -    timeout = 10
   8.162 +    timeout = 30
   8.163  
   8.164      def __init__(self):
   8.165          from xen.xend import XendDomain
   8.166          self.xd = XendDomain.instance()
   8.167 -        self.deferred = defer.Deferred()
   8.168          self.suspended = {}
   8.169          self.paused = {}
   8.170          self.state = 'init'
   8.171          # List of errors encountered.
   8.172          self.errors = []
   8.173 -        
   8.174 +            
   8.175      def vmconfig(self):
   8.176          dominfo = self.xd.domain_get(self.src_dom)
   8.177          if dominfo:
   8.178 @@ -110,11 +195,10 @@ class XfrdInfo:
   8.179  
   8.180      def add_error(self, err):
   8.181          """Add an error to the error list.
   8.182 -        Returns the error added (which may have been unwrapped if it
   8.183 -        was a Twisted Failure).
   8.184 +        Returns the error added.
   8.185          """
   8.186 -        while isinstance(err, Failure):
   8.187 -            err = err.value
   8.188 +        #while isinstance(err, Failure):
   8.189 +        #    err = err.value
   8.190          if err not in self.errors:
   8.191              self.errors.append(err)
   8.192          return err
   8.193 @@ -122,6 +206,8 @@ class XfrdInfo:
   8.194      def error_summary(self, msg=None):
   8.195          """Get a XendError summarising the errors (if any).
   8.196          """
   8.197 +        if not self.errors:
   8.198 +            return None
   8.199          if msg is None:
   8.200              msg = "errors"
   8.201          if self.errors:
   8.202 @@ -136,34 +222,27 @@ class XfrdInfo:
   8.203          return self.errors
   8.204  
   8.205      def error(self, err):
   8.206 +        print 'XfrdInfo>error>', err
   8.207          self.state = 'error'
   8.208          self.add_error(err)
   8.209 -        if not self.deferred.called:
   8.210 -            self.deferred.errback(self.error_summary())
   8.211  
   8.212      def dispatch(self, xfrd, val):
   8.213 -        
   8.214 -        def cbok(v):
   8.215 -            if v is None: return
   8.216 -            sxp.show(v, out=xfrd.transport)
   8.217 -
   8.218 -        def cberr(err):
   8.219 -            v = ['xfr.err', errno.EINVAL]
   8.220 -            sxp.show(v, out=xfrd.transport)
   8.221 -            self.error(err)
   8.222 -
   8.223 +        print 'XfrdInfo>dispatch>', val
   8.224          op = sxp.name(val)
   8.225          op = op.replace('.', '_')
   8.226          if op.startswith('xfr_'):
   8.227              fn = getattr(self, op, self.unknown)
   8.228          else:
   8.229              fn = self.unknown
   8.230 -        val = fn(xfrd, val)
   8.231 -        if isinstance(val, defer.Deferred):
   8.232 -            val.addCallback(cbok)
   8.233 -            val.addErrback(cberr)
   8.234 -        else:
   8.235 -            cbok(val)
   8.236 +        try:
   8.237 +            val = fn(xfrd, val)
   8.238 +            if val:
   8.239 +                sxp.show(val, out=xfrd.transport)
   8.240 +        except Exception, err:
   8.241 +            print 'XfrdInfo>dispatch> error:', err
   8.242 +            val = ['xfr.err', errno.EINVAL]
   8.243 +            sxp.show(val, out=xfrd.transport)
   8.244 +            self.error(err)
   8.245  
   8.246      def unknown(self, xfrd, val):
   8.247          xfrd.loseConnection()
   8.248 @@ -172,6 +251,7 @@ class XfrdInfo:
   8.249      def xfr_err(self, xfrd, val):
   8.250          # If we get an error with non-zero code the operation failed.
   8.251          # An error with code zero indicates hello success.
   8.252 +        print 'XfrdInfo>xfr_err>', val
   8.253          v = sxp.child0(val)
   8.254          err = int(sxp.child0(val))
   8.255          if not err: return
   8.256 @@ -220,50 +300,19 @@ class XfrdInfo:
   8.257          return ['xfr.err', val]
   8.258  
   8.259      def xfr_vm_suspend(self, xfrd, val):
   8.260 -        """Suspend a domain. Suspending takes time, so we return
   8.261 -        a Deferred that is called when the suspend completes.
   8.262 +        """Suspend a domain.
   8.263          Suspending can hang, so we set a timeout and fail if it
   8.264          takes too long.
   8.265          """
   8.266          try:
   8.267              vmid = sxp.child0(val)
   8.268 -            d = defer.Deferred()
   8.269 -            # Subscribe to 'suspended' events so we can tell when the
   8.270 -            # suspend completes. Subscribe to 'died' events so we can tell if
   8.271 -            # the domain died. Set a timeout and error handler so the subscriptions
   8.272 -            # will be cleaned up if suspending hangs or there is an error.
   8.273 -            def onSuspended(e, v):
   8.274 -                if v[1] != vmid: return
   8.275 -                subscribe(on=0)
   8.276 -                if not d.called:
   8.277 -                    d.callback(v)
   8.278 -                
   8.279 -            def onDied(e, v):
   8.280 -                if v[1] != vmid: return
   8.281 -                if not d.called:
   8.282 -                    d.errback(XendError('Domain %s died while suspending' % vmid))
   8.283 -                
   8.284 -            def subscribe(on=1):
   8.285 -                if on:
   8.286 -                    action = eserver.subscribe
   8.287 -                else:
   8.288 -                    action = eserver.unsubscribe
   8.289 -                action('xend.domain.suspended', onSuspended)
   8.290 -                action('xend.domain.died', onDied)
   8.291 -
   8.292 -            def cberr(err):
   8.293 -                subscribe(on=0)
   8.294 -                self.add_error("suspend failed")
   8.295 -                self.add_error(err)
   8.296 -                return err
   8.297 -
   8.298 -            d.addErrback(cberr)
   8.299 -            d.setTimeout(self.timeout)
   8.300 -            subscribe()
   8.301 +            h = SuspendHandler(self, vmid, self.timeout)
   8.302              val = self.xd.domain_shutdown(vmid, reason='suspend')
   8.303              self.suspended[vmid] = 1
   8.304 -            return d
   8.305 +            h.start()
   8.306 +            print 'xfr_vm_suspend> suspended', vmid
   8.307          except Exception, err:
   8.308 +            print 'xfr_vm_suspend> err', err
   8.309              self.add_error("suspend failed")
   8.310              self.add_error(err)
   8.311              traceback.print_exc()
   8.312 @@ -271,6 +320,7 @@ class XfrdInfo:
   8.313          return ['xfr.err', val]
   8.314  
   8.315      def connectionLost(self, reason=None):
   8.316 +        print 'XfrdInfo>connectionLost>', reason
   8.317          for vmid in self.suspended:
   8.318              try:
   8.319                  self.xd.domain_destroy(vmid)
   8.320 @@ -336,10 +386,11 @@ class XendMigrateInfo(XfrdInfo):
   8.321          self.state = 'ok'
   8.322          self.dst_dom = dom
   8.323          self.xd.domain_destroy(self.src_dom)
   8.324 -        if not self.deferred.called:
   8.325 -            self.deferred.callback(self)
   8.326 +        #if not self.deferred.called:
   8.327 +        #    self.deferred.callback(self)
   8.328  
   8.329      def connectionLost(self, reason=None):
   8.330 +        print 'XendMigrateInfo>connectionLost>', reason
   8.331          XfrdInfo.connectionLost(self, reason)
   8.332          if self.state =='ok':
   8.333              log.info('Migrate OK: ' + str(self.sxpr()))
   8.334 @@ -386,10 +437,11 @@ class XendSaveInfo(XfrdInfo):
   8.335      def xfr_save_ok(self, xfrd, val):
   8.336          self.state = 'ok'
   8.337          self.xd.domain_destroy(self.src_dom)
   8.338 -        if not self.deferred.called:
   8.339 -            self.deferred.callback(self)
   8.340 +        #if not self.deferred.called:
   8.341 +        #    self.deferred.callback(self)
   8.342  
   8.343      def connectionLost(self, reason=None):
   8.344 +        print 'XendSaveInfo>connectionLost>', reason
   8.345          XfrdInfo.connectionLost(self, reason)
   8.346          if self.state =='ok':
   8.347              log.info('Save OK: ' + str(self.sxpr()))
   8.348 @@ -493,29 +545,17 @@ class XendMigrate:
   8.349  
   8.350      def session_begin(self, info):
   8.351          """Add the session to the table and start it.
   8.352 -        Set up callbacks to remove the session from the table
   8.353 -        when it finishes.
   8.354 +        Remove the session from the table when it finishes.
   8.355  
   8.356          @param info: session
   8.357          @return: deferred
   8.358          """
   8.359 -        dfr = defer.Deferred()
   8.360 -        def cbok(val):
   8.361 -            self._delete_session(info.xid)
   8.362 -            if not dfr.called:
   8.363 -                dfr.callback(val)
   8.364 -            return val
   8.365 -        def cberr(err):
   8.366 +        self._add_session(info)
   8.367 +        try:
   8.368 +            xcf = XfrdClientFactory(info)
   8.369 +            return xcf.start()
   8.370 +        finally:
   8.371              self._delete_session(info.xid)
   8.372 -            if not dfr.called:
   8.373 -                dfr.errback(err)
   8.374 -            return err
   8.375 -        self._add_session(info)
   8.376 -        info.deferred.addCallback(cbok)
   8.377 -        info.deferred.addErrback(cberr)
   8.378 -        xcf = XfrdClientFactory(info)
   8.379 -        reactor.connectTCP('localhost', XFRD_PORT, xcf)
   8.380 -        return dfr
   8.381      
   8.382      def migrate_begin(self, dominfo, host, port=XFRD_PORT, live=0, resource=0):
   8.383          """Begin to migrate a domain to another host.
     9.1 --- a/tools/python/xen/xend/server/SrvConsole.py	Thu Apr 21 14:11:29 2005 +0000
     9.2 +++ b/tools/python/xen/xend/server/SrvConsole.py	Fri Apr 22 15:30:43 2005 +0000
     9.3 @@ -21,22 +21,18 @@ class SrvConsole(SrvDir):
     9.4          return self.perform(req)
     9.5          
     9.6      def render_GET(self, req):
     9.7 -        try:
     9.8 -            if self.use_sxp(req):
     9.9 -                req.setHeader("Content-Type", sxp.mime_type)
    9.10 -                sxp.show(self.info.sxpr(), out=req)
    9.11 -            else:
    9.12 -                req.write('<html><head></head><body>')
    9.13 -                self.print_path(req)
    9.14 -                #self.ls()
    9.15 -                req.write('<p>%s</p>' % self.info)
    9.16 -                req.write('<p><a href="%s">Connect to domain %d</a></p>'
    9.17 -                          % (self.info.uri(), self.info.dom))
    9.18 -                self.form(req)
    9.19 -                req.write('</body></html>')
    9.20 -            return ''
    9.21 -        except Exception, ex:
    9.22 -            self._perform_err(ex, req)
    9.23 +        if self.use_sxp(req):
    9.24 +            req.setHeader("Content-Type", sxp.mime_type)
    9.25 +            sxp.show(self.info.sxpr(), out=req)
    9.26 +        else:
    9.27 +            req.write('<html><head></head><body>')
    9.28 +            self.print_path(req)
    9.29 +            #self.ls()
    9.30 +            req.write('<p>%s</p>' % self.info)
    9.31 +            req.write('<p><a href="%s">Connect to domain %d</a></p>'
    9.32 +                      % (self.info.uri(), self.info.dom))
    9.33 +            self.form(req)
    9.34 +            req.write('</body></html>')
    9.35  
    9.36      def form(self, req):
    9.37          req.write('<form method="post" action="%s">' % req.prePathURL())
    10.1 --- a/tools/python/xen/xend/server/SrvConsoleDir.py	Thu Apr 21 14:11:29 2005 +0000
    10.2 +++ b/tools/python/xen/xend/server/SrvConsoleDir.py	Fri Apr 22 15:30:43 2005 +0000
    10.3 @@ -31,20 +31,16 @@ class SrvConsoleDir(SrvDir):
    10.4          return v
    10.5  
    10.6      def render_GET(self, req):
    10.7 -        try:
    10.8 -            if self.use_sxp(req):
    10.9 -                req.setHeader("Content-Type", sxp.mime_type)
   10.10 -                self.ls_console(req, 1)
   10.11 -            else:
   10.12 -                req.write("<html><head></head><body>")
   10.13 -                self.print_path(req)
   10.14 -                self.ls(req)
   10.15 -                self.ls_console(req)
   10.16 -                #self.form(req.wfile)
   10.17 -                req.write("</body></html>")
   10.18 -            return ''
   10.19 -        except Exception, ex:
   10.20 -            self._perform_err(ex, req)
   10.21 +        if self.use_sxp(req):
   10.22 +            req.setHeader("Content-Type", sxp.mime_type)
   10.23 +            self.ls_console(req, 1)
   10.24 +        else:
   10.25 +            req.write("<html><head></head><body>")
   10.26 +            self.print_path(req)
   10.27 +            self.ls(req)
   10.28 +            self.ls_console(req)
   10.29 +            #self.form(req.wfile)
   10.30 +            req.write("</body></html>")
   10.31  
   10.32      def ls_console(self, req, use_sxp=0):
   10.33          url = req.prePathURL()
    11.1 --- a/tools/python/xen/xend/server/SrvDaemon.py	Thu Apr 21 14:11:29 2005 +0000
    11.2 +++ b/tools/python/xen/xend/server/SrvDaemon.py	Fri Apr 22 15:30:43 2005 +0000
    11.3 @@ -17,9 +17,6 @@ import StringIO
    11.4  import traceback
    11.5  import time
    11.6  
    11.7 -#from twisted.internet import pollreactor; pollreactor.install()
    11.8 -from twisted.internet import reactor
    11.9 -
   11.10  from xen.lowlevel import xu
   11.11  
   11.12  from xen.xend import sxp
   11.13 @@ -330,8 +327,6 @@ class Daemon:
   11.14              self.daemonize()
   11.15              print 'running serverthread...'
   11.16              serverthread.start()
   11.17 -            print 'running reactor...'
   11.18 -            reactor.run()
   11.19          except Exception, ex:
   11.20              print >>sys.stderr, 'Exception starting xend:', ex
   11.21              if DEBUG:
   11.22 @@ -356,7 +351,7 @@ class Daemon:
   11.23          self.channelF.start()
   11.24  
   11.25      def exit(self, rc=0):
   11.26 -        reactor.disconnectAll()
   11.27 +        #reactor.disconnectAll()
   11.28          self.channelF.stop()
   11.29          # Calling sys.exit() raises a SystemExit exception, which only
   11.30          # kills the current thread. Calling os._exit() makes the whole
    12.1 --- a/tools/python/xen/xend/server/SrvDmesg.py	Thu Apr 21 14:11:29 2005 +0000
    12.2 +++ b/tools/python/xen/xend/server/SrvDmesg.py	Fri Apr 22 15:30:43 2005 +0000
    12.3 @@ -19,19 +19,15 @@ class SrvDmesg(SrvDir):
    12.4          self.perform(req)
    12.5  
    12.6      def render_GET(self, req):
    12.7 -        try:
    12.8 -            if self.use_sxp(req):
    12.9 -                req.setHeader("Content-Type", "text/plain")
   12.10 -                req.write(self.info())
   12.11 -            else:
   12.12 -                req.write('<html><head></head><body>')
   12.13 -                self.print_path(req)
   12.14 -                req.write('<pre>')
   12.15 -                req.write(self.info())
   12.16 -                req.write('</pre></body></html>')
   12.17 -            return ''
   12.18 -        except Exception, ex:
   12.19 -            self._perform_err(ex, req)
   12.20 +        if self.use_sxp(req):
   12.21 +            req.setHeader("Content-Type", "text/plain")
   12.22 +            req.write(self.info())
   12.23 +        else:
   12.24 +            req.write('<html><head></head><body>')
   12.25 +            self.print_path(req)
   12.26 +            req.write('<pre>')
   12.27 +            req.write(self.info())
   12.28 +            req.write('</pre></body></html>')
   12.29              
   12.30      def info(self):
   12.31          return self.xd.info()
    13.1 --- a/tools/python/xen/xend/server/SrvDomain.py	Thu Apr 21 14:11:29 2005 +0000
    13.2 +++ b/tools/python/xen/xend/server/SrvDomain.py	Fri Apr 22 15:30:43 2005 +0000
    13.3 @@ -26,24 +26,27 @@ class SrvDomain(SrvDir):
    13.4          not a domain name.
    13.5          """
    13.6          fn = FormFn(self.xd.domain_configure,
    13.7 -                    [['dom', 'int'],
    13.8 +                    [['dom',    'int'],
    13.9                       ['config', 'sxpr']])
   13.10 -        deferred = fn(req.args, {'dom': self.dom.dom})
   13.11 -        return deferred
   13.12 +        return fn(req.args, {'dom': self.dom.dom})
   13.13  
   13.14      def op_unpause(self, op, req):
   13.15          val = self.xd.domain_unpause(self.dom.name)
   13.16          return val
   13.17          
   13.18      def op_pause(self, op, req):
   13.19 +        # Pause doesn't need a thread, but request one for testing.
   13.20 +        return req.threadRequest(self.do_pause, op, req)
   13.21 +
   13.22 +    def do_pause(self, op, req):
   13.23          val = self.xd.domain_pause(self.dom.name)
   13.24          return val
   13.25  
   13.26      def op_shutdown(self, op, req):
   13.27          fn = FormFn(self.xd.domain_shutdown,
   13.28 -                    [['dom', 'str'],
   13.29 +                    [['dom',    'str'],
   13.30                       ['reason', 'str'],
   13.31 -                     ['key', 'int']])
   13.32 +                     ['key',    'int']])
   13.33          val = fn(req.args, {'dom': self.dom.id})
   13.34          req.setResponseCode(http.ACCEPTED)
   13.35          req.setHeader("Location", "%s/.." % req.prePathURL())
   13.36 @@ -51,42 +54,39 @@ class SrvDomain(SrvDir):
   13.37  
   13.38      def op_destroy(self, op, req):
   13.39          fn = FormFn(self.xd.domain_destroy,
   13.40 -                    [['dom', 'str'],
   13.41 +                    [['dom',    'str'],
   13.42                       ['reason', 'str']])
   13.43          val = fn(req.args, {'dom': self.dom.id})
   13.44          req.setHeader("Location", "%s/.." % req.prePathURL())
   13.45          return val
   13.46  
   13.47      def op_save(self, op, req):
   13.48 +        return req.threadRequest(self.do_save, op, req)
   13.49 +
   13.50 +    def do_save(self, op, req):
   13.51          fn = FormFn(self.xd.domain_save,
   13.52 -                    [['dom', 'str'],
   13.53 +                    [['dom',  'str'],
   13.54                       ['file', 'str']])
   13.55 -        deferred = fn(req.args, {'dom': self.dom.id})
   13.56 -        deferred.addCallback(self._op_save_cb, req)
   13.57 -        return deferred
   13.58 -
   13.59 -    def _op_save_cb(self, val, req):
   13.60 +        val = fn(req.args, {'dom': self.dom.id})
   13.61          return 0
   13.62  
   13.63      def op_migrate(self, op, req):
   13.64 +        return req.threadRequest(self.do_migrate, op, req)
   13.65 +    
   13.66 +    def do_migrate(self, op, req):
   13.67          fn = FormFn(self.xd.domain_migrate,
   13.68 -                    [['dom', 'str'],
   13.69 +                    [['dom',         'str'],
   13.70                       ['destination', 'str'],
   13.71 -                     ['live', 'int'],
   13.72 -                     ['resource', 'int']])
   13.73 -        deferred = fn(req.args, {'dom': self.dom.id})
   13.74 -        deferred.addCallback(self._op_migrate_cb, req)
   13.75 -        return deferred
   13.76 -
   13.77 -    def _op_migrate_cb(self, info, req):
   13.78 -        print '_op_migrate_cb>', info, req
   13.79 +                     ['live',        'int'],
   13.80 +                     ['resource',    'int']])
   13.81 +        info = fn(req.args, {'dom': self.dom.id})
   13.82          #req.setResponseCode(http.ACCEPTED)
   13.83          host = info.dst_host
   13.84          port = info.dst_port
   13.85          dom  = info.dst_dom
   13.86          url = "http://%s:%d/xend/domain/%d" % (host, port, dom)
   13.87          req.setHeader("Location", url)
   13.88 -        print '_op_migrate_cb> url=', url
   13.89 +        print 'do_migrate> url=', url
   13.90          return url
   13.91  
   13.92      def op_pincpu(self, op, req):
   13.93 @@ -98,57 +98,57 @@ class SrvDomain(SrvDir):
   13.94  
   13.95      def op_cpu_bvt_set(self, op, req):
   13.96          fn = FormFn(self.xd.domain_cpu_bvt_set,
   13.97 -                    [['dom', 'str'],
   13.98 -                     ['mcuadv', 'int'],
   13.99 -                     ['warpback', 'int'],
  13.100 +                    [['dom',       'str'],
  13.101 +                     ['mcuadv',    'int'],
  13.102 +                     ['warpback',  'int'],
  13.103                       ['warpvalue', 'int'],
  13.104 -                     ['warpl', 'long'],
  13.105 -                     ['warpu', 'long']])
  13.106 +                     ['warpl',     'long'],
  13.107 +                     ['warpu',     'long']])
  13.108          val = fn(req.args, {'dom': self.dom.id})
  13.109          return val
  13.110      
  13.111      def op_maxmem_set(self, op, req):
  13.112          fn = FormFn(self.xd.domain_maxmem_set,
  13.113 -                    [['dom', 'str'],
  13.114 +                    [['dom',    'str'],
  13.115                       ['memory', 'int']])
  13.116          val = fn(req.args, {'dom': self.dom.id})
  13.117          return val
  13.118  
  13.119      def op_device_create(self, op, req):
  13.120          fn = FormFn(self.xd.domain_device_create,
  13.121 -                    [['dom', 'str'],
  13.122 +                    [['dom',    'str'],
  13.123                       ['config', 'sxpr']])
  13.124 -        d = fn(req.args, {'dom': self.dom.id})
  13.125 -        return d
  13.126 +        val = fn(req.args, {'dom': self.dom.id})
  13.127 +        return val
  13.128  
  13.129      def op_device_refresh(self, op, req):
  13.130          fn = FormFn(self.xd.domain_device_refresh,
  13.131 -                    [['dom', 'str'],
  13.132 +                    [['dom',  'str'],
  13.133                       ['type', 'str'],
  13.134 -                     ['idx', 'str']])
  13.135 +                     ['idx',  'str']])
  13.136          val = fn(req.args, {'dom': self.dom.id})
  13.137          return val
  13.138  
  13.139      def op_device_destroy(self, op, req):
  13.140          fn = FormFn(self.xd.domain_device_destroy,
  13.141 -                    [['dom', 'str'],
  13.142 +                    [['dom',  'str'],
  13.143                       ['type', 'str'],
  13.144 -                     ['idx', 'str']])
  13.145 +                     ['idx',  'str']])
  13.146          val = fn(req.args, {'dom': self.dom.id})
  13.147          return val
  13.148                  
  13.149      def op_device_configure(self, op, req):
  13.150          fn = FormFn(self.xd.domain_device_configure,
  13.151 -                    [['dom', 'str'],
  13.152 +                    [['dom',    'str'],
  13.153                       ['config', 'sxpr'],
  13.154 -                     ['idx', 'str']])
  13.155 -        d = fn(req.args, {'dom': self.dom.id})
  13.156 -        return d
  13.157 +                     ['idx',    'str']])
  13.158 +        val = fn(req.args, {'dom': self.dom.id})
  13.159 +        return val
  13.160  
  13.161      def op_vif_credit_limit(self, op, req):
  13.162          fn = FormFn(self.xd.domain_vif_credit_limit,
  13.163 -                    [['dom', 'str'],
  13.164 -                     ['vif', 'int'],
  13.165 +                    [['dom',    'str'],
  13.166 +                     ['vif',    'int'],
  13.167                       ['credit', 'int'],
  13.168                       ['period', 'int']])
  13.169          val = fn(req.args, {'dom': self.dom.id})
  13.170 @@ -178,7 +178,7 @@ class SrvDomain(SrvDir):
  13.171  
  13.172      def op_mem_target_set(self, op, req):
  13.173          fn = FormFn(self.xd.domain_mem_target_set,
  13.174 -                    [['dom', 'str'],
  13.175 +                    [['dom',    'str'],
  13.176                       ['target', 'int']])
  13.177          val = fn(req.args, {'dom': self.dom.id})
  13.178          return val
    14.1 --- a/tools/python/xen/xend/server/SrvDomainDir.py	Thu Apr 21 14:11:29 2005 +0000
    14.2 +++ b/tools/python/xen/xend/server/SrvDomainDir.py	Fri Apr 22 15:30:43 2005 +0000
    14.3 @@ -68,7 +68,7 @@ class SrvDomainDir(SrvDir):
    14.4              raise XendError("Error creating domain: " + str(ex))
    14.5  
    14.6      def _op_create_cb(self, dominfo, configstring, req):
    14.7 -        """Callback to handle deferred domain creation.
    14.8 +        """Callback to handle domain creation.
    14.9          """
   14.10          dom = dominfo.name
   14.11          domurl = "%s/%s" % (req.prePathURL(), dom)
   14.12 @@ -90,14 +90,13 @@ class SrvDomainDir(SrvDir):
   14.13      def op_restore(self, op, req):
   14.14          """Restore a domain from file.
   14.15  
   14.16 -        @return: deferred
   14.17          """
   14.18 +        return req.threadRequest(self.do_restore, op, req)
   14.19 +
   14.20 +    def do_restore(self, op, req):
   14.21          fn = FormFn(self.xd.domain_restore,
   14.22                      [['file', 'str']])
   14.23          dominfo = fn(req.args)
   14.24 -        return self._op_restore_cb(dominfo, req)
   14.25 -
   14.26 -    def _op_restore_cb(self, dominfo, req):
   14.27          dom = dominfo.name
   14.28          domurl = "%s/%s" % (req.prePathURL(), dom)
   14.29          req.setResponseCode(http.CREATED)
   14.30 @@ -116,20 +115,16 @@ class SrvDomainDir(SrvDir):
   14.31          return self.perform(req)
   14.32  
   14.33      def render_GET(self, req):
   14.34 -        try:
   14.35 -            if self.use_sxp(req):
   14.36 -                req.setHeader("Content-Type", sxp.mime_type)
   14.37 -                self.ls_domain(req, 1)
   14.38 -            else:
   14.39 -                req.write("<html><head></head><body>")
   14.40 -                self.print_path(req)
   14.41 -                self.ls(req)
   14.42 -                self.ls_domain(req)
   14.43 -                self.form(req)
   14.44 -                req.write("</body></html>")
   14.45 -            return ''
   14.46 -        except Exception, ex:
   14.47 -            self._perform_err(ex, req)
   14.48 +        if self.use_sxp(req):
   14.49 +            req.setHeader("Content-Type", sxp.mime_type)
   14.50 +            self.ls_domain(req, 1)
   14.51 +        else:
   14.52 +            req.write("<html><head></head><body>")
   14.53 +            self.print_path(req)
   14.54 +            self.ls(req)
   14.55 +            self.ls_domain(req)
   14.56 +            self.form(req)
   14.57 +            req.write("</body></html>")
   14.58  
   14.59      def ls_domain(self, req, use_sxp=0):
   14.60          url = req.prePathURL()
    15.1 --- a/tools/python/xen/xend/server/SrvNode.py	Thu Apr 21 14:11:29 2005 +0000
    15.2 +++ b/tools/python/xen/xend/server/SrvNode.py	Fri Apr 22 15:30:43 2005 +0000
    15.3 @@ -35,26 +35,22 @@ class SrvNode(SrvDir):
    15.4          return self.perform(req)
    15.5  
    15.6      def render_GET(self, req):
    15.7 -        try:
    15.8 -            if self.use_sxp(req):
    15.9 -                req.setHeader("Content-Type", sxp.mime_type)
   15.10 -                sxp.show(['node'] + self.info(), out=req)
   15.11 -            else:
   15.12 -                url = req.prePathURL()
   15.13 -                if not url.endswith('/'):
   15.14 -                    url += '/'
   15.15 -                req.write('<html><head></head><body>')
   15.16 -                self.print_path(req)
   15.17 -                req.write('<ul>')
   15.18 -                for d in self.info():
   15.19 -                    req.write('<li> %10s: %s' % (d[0], str(d[1])))
   15.20 -                req.write('<li><a href="%sdmesg">Xen dmesg output</a>' % url)
   15.21 -                req.write('<li><a href="%slog>Xend log</a>' % url)
   15.22 -                req.write('</ul>')
   15.23 -                req.write('</body></html>')
   15.24 -            return ''
   15.25 -        except Exception, ex:
   15.26 -            self._perform_err(ex, req)
   15.27 +        if self.use_sxp(req):
   15.28 +            req.setHeader("Content-Type", sxp.mime_type)
   15.29 +            sxp.show(['node'] + self.info(), out=req)
   15.30 +        else:
   15.31 +            url = req.prePathURL()
   15.32 +            if not url.endswith('/'):
   15.33 +                url += '/'
   15.34 +            req.write('<html><head></head><body>')
   15.35 +            self.print_path(req)
   15.36 +            req.write('<ul>')
   15.37 +            for d in self.info():
   15.38 +                req.write('<li> %10s: %s' % (d[0], str(d[1])))
   15.39 +            req.write('<li><a href="%sdmesg">Xen dmesg output</a>' % url)
   15.40 +            req.write('<li><a href="%slog>Xend log</a>' % url)
   15.41 +            req.write('</ul>')
   15.42 +            req.write('</body></html>')
   15.43              
   15.44      def info(self):
   15.45          return self.xn.info()
    16.1 --- a/tools/python/xen/xend/server/SrvVnetDir.py	Thu Apr 21 14:11:29 2005 +0000
    16.2 +++ b/tools/python/xen/xend/server/SrvVnetDir.py	Fri Apr 22 15:30:43 2005 +0000
    16.3 @@ -75,20 +75,16 @@ class SrvVnetDir(SrvDir):
    16.4          return self.perform(req)
    16.5  
    16.6      def render_GET(self, req):
    16.7 -        try:
    16.8 -            if self.use_sxp(req):
    16.9 -                req.setHeader("Content-Type", sxp.mime_type)
   16.10 -                self.ls_vnet(req, 1)
   16.11 -            else:
   16.12 -                req.write("<html><head></head><body>")
   16.13 -                self.print_path(req)
   16.14 -                self.ls(req)
   16.15 -                self.ls_vnet(req)
   16.16 -                self.form(req)
   16.17 -                req.write("</body></html>")
   16.18 -            return ''
   16.19 -        except Exception, ex:
   16.20 -            self._perform_err(ex, req)
   16.21 +        if self.use_sxp(req):
   16.22 +            req.setHeader("Content-Type", sxp.mime_type)
   16.23 +            self.ls_vnet(req, 1)
   16.24 +        else:
   16.25 +            req.write("<html><head></head><body>")
   16.26 +            self.print_path(req)
   16.27 +            self.ls(req)
   16.28 +            self.ls_vnet(req)
   16.29 +            self.form(req)
   16.30 +            req.write("</body></html>")
   16.31  
   16.32      def ls_vnet(self, req, use_sxp=0):
   16.33          url = req.prePathURL()
    17.1 --- a/tools/python/xen/xend/server/SrvXendLog.py	Thu Apr 21 14:11:29 2005 +0000
    17.2 +++ b/tools/python/xen/xend/server/SrvXendLog.py	Fri Apr 22 15:30:43 2005 +0000
    17.3 @@ -18,7 +18,4 @@ class SrvXendLog(SrvDir):
    17.4          self.logfile.encoding = None
    17.5  
    17.6      def render_GET(self, req):
    17.7 -        try:
    17.8 -            return self.logfile.render(req)
    17.9 -        except Exception, ex:
   17.10 -            self._perform_err(ex, 'log', req)
   17.11 +        return self.logfile.render(req)
    18.1 --- a/tools/python/xen/xend/server/usbif.py	Thu Apr 21 14:11:29 2005 +0000
    18.2 +++ b/tools/python/xen/xend/server/usbif.py	Fri Apr 22 15:30:43 2005 +0000
    18.3 @@ -62,7 +62,6 @@ class UsbBackend:
    18.4          """Connect the controller to the usbif control interface.
    18.5  
    18.6          @param recreate: true if after xend restart
    18.7 -        @return: deferred
    18.8          """
    18.9          log.debug("Connecting usbif %s", str(self))
   18.10          if recreate or self.connected or self.connecting: