ia64/xen-unstable

changeset 4617: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>
author mjw@wray-m-3.hpl.hp.com
date Thu Apr 21 13:25:07 2005 +0000 (2005-04-21)
parents c69fbe48a357
children 40af907d69a9
files .rootkeys tools/python/setup.py tools/python/xen/web/SrvBase.py tools/python/xen/web/SrvDir.py tools/python/xen/web/__init__.py tools/python/xen/web/connection.py tools/python/xen/web/defer.py tools/python/xen/web/http.py tools/python/xen/web/httpserver.py tools/python/xen/web/protocol.py tools/python/xen/web/reactor.py tools/python/xen/web/resource.py tools/python/xen/web/static.py tools/python/xen/web/tcp.py tools/python/xen/web/unix.py tools/python/xen/xend/EventServer.py tools/python/xen/xend/XendDomain.py tools/python/xen/xend/XendDomainInfo.py tools/python/xen/xend/scheduler.py tools/python/xen/xend/server/SrvBase.py tools/python/xen/xend/server/SrvDaemon.py tools/python/xen/xend/server/SrvDeviceDir.py tools/python/xen/xend/server/SrvDir.py tools/python/xen/xend/server/SrvDomain.py tools/python/xen/xend/server/SrvDomainDir.py tools/python/xen/xend/server/SrvRoot.py tools/python/xen/xend/server/SrvServer.py tools/python/xen/xend/server/SrvUsbif.py tools/python/xen/xend/server/SrvXendLog.py tools/python/xen/xend/server/blkif.py tools/python/xen/xend/server/console.py tools/python/xen/xend/server/controller.py tools/python/xen/xend/server/domain.py tools/python/xen/xend/server/event.py tools/python/xen/xend/server/netif.py
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