ia64/xen-unstable

changeset 1661:11fc1027833b

bitkeeper revision 1.1041.5.1 (40e51d24Wg4h3PKvj5VuOULXCYhqbg)

Merge http://xen.bkbits.net:8080/xeno-unstable.bk
into gandalf.hpl.hp.com:/var/bk/xeno-unstable.bk
author xenbk@gandalf.hpl.hp.com
date Fri Jul 02 08:30:28 2004 +0000 (2004-07-02)
parents d9a96380ff94 6edc06968b87
children 52c04d5d2a8e
files .rootkeys tools/examples/xmdefaults tools/python/xen/xend/XendClient.py tools/python/xen/xend/server/SrvDomainDir.py tools/python/xen/xend/server/blkif.py tools/python/xen/xend/server/channel.py tools/python/xen/xend/server/console.py tools/python/xen/xend/server/controller.py tools/python/xen/xend/server/cstruct.py tools/python/xen/xend/server/domain.py tools/python/xen/xend/server/messages.py tools/python/xen/xend/server/netif.py tools/python/xen/xm/create.py tools/python/xen/xm/help.py tools/python/xen/xm/main.py tools/python/xen/xm/opts.py
line diff
     1.1 --- a/.rootkeys	Thu Jul 01 23:32:40 2004 +0000
     1.2 +++ b/.rootkeys	Fri Jul 02 08:30:28 2004 +0000
     1.3 @@ -257,7 +257,6 @@ 40c9c4692hckPol_EK0EGB16ZyDsyQ tools/pyt
     1.4  40c9c469N2-b3GqpLHHHPZykJPLVvA tools/python/xen/xend/server/channel.py
     1.5  40c9c469hJ_IlatRne-9QEa0-wlquw tools/python/xen/xend/server/console.py
     1.6  40c9c469UcNJh_NuLU0ytorM0Lk5Ow tools/python/xen/xend/server/controller.py
     1.7 -40c9c469vHh-qLiiubdbKEQbJf18Zw tools/python/xen/xend/server/cstruct.py
     1.8  40d83983OXjt-y3HjSCcuoPp9rzvmw tools/python/xen/xend/server/domain.py
     1.9  40c9c469yrm31i60pGKslTi2Zgpotg tools/python/xen/xend/server/messages.py
    1.10  40c9c46925x-Rjb0Cv2f1-l2jZrPYg tools/python/xen/xend/server/netif.py
    1.11 @@ -265,6 +264,7 @@ 40c9c469ZqILEQ8x6yWy0_51jopiCg tools/pyt
    1.12  40c9c469LNxLVizOUpOjEaTKKCm8Aw tools/python/xen/xend/sxp.py
    1.13  40d05079aFRp6NQdo5wIh5Ly31c0cg tools/python/xen/xm/__init__.py
    1.14  40cf2937gKQcATgXKGtNeWb1PDH5nA tools/python/xen/xm/create.py
    1.15 +40e41cd2w0I4En6qrJn4em8HkK_oxQ tools/python/xen/xm/help.py
    1.16  40cf2937isyS250zyd0Q2GuEDoNXfQ tools/python/xen/xm/main.py
    1.17  40cf2937PSslwBliN1g7ofDy2H_RhA tools/python/xen/xm/opts.py
    1.18  40cf2937Z8WCNOnO2FcWdubvEAF9QQ tools/python/xen/xm/shutdown.py
     2.1 --- a/tools/examples/xmdefaults	Thu Jul 01 23:32:40 2004 +0000
     2.2 +++ b/tools/examples/xmdefaults	Fri Jul 02 08:30:28 2004 +0000
     2.3 @@ -2,17 +2,24 @@
     2.4  #============================================================================
     2.5  # Python defaults setup for 'xm create'.
     2.6  # Edit this file to reflect the configuration of your system.
     2.7 -# This file expects the variable 'vmid' to be set.
     2.8 +
     2.9  #============================================================================
    2.10  
    2.11 -try:
    2.12 -    vmid = int(vmid) # convert to integer
    2.13 -except:
    2.14 -    raise ValueError, "Variable 'vmid' must be an integer"
    2.15 +# Define script variables here.
    2.16 +# xm_vars is defined automatically, use xm_vars.var() to define a variable.
    2.17  
    2.18 -if vmid <= 0:
    2.19 -    raise ValueError, "Variable 'vmid' must be greater than 0" 
    2.20 +def vmid_check(var, val):
    2.21 +    val = int(val)
    2.22 +    if val <= 0:
    2.23 +        raise ValueError
    2.24 +    return val
    2.25 +    
    2.26 +xm_vars.var('vmid',
    2.27 +            use="Virtual machine id. Integer greater than 0.",
    2.28 +            check=vmid_check)
    2.29  
    2.30 +# This checks the script variables.
    2.31 +xm_vars.check()
    2.32  
    2.33  #----------------------------------------------------------------------------
    2.34  # Kernel image file.
     3.1 --- a/tools/python/xen/xend/XendClient.py	Thu Jul 01 23:32:40 2004 +0000
     3.2 +++ b/tools/python/xen/xend/XendClient.py	Fri Jul 02 08:30:28 2004 +0000
     3.3 @@ -1,6 +1,11 @@
     3.4  # Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
     3.5  """Client API for the HTTP interface on xend.
     3.6  Callable as a script - see main().
     3.7 +
     3.8 +This API is the 'control-plane' for xend.
     3.9 +The 'data-plane' is done separately. For example, consoles
    3.10 +are accessed via sockets on xend, but the list of consoles
    3.11 +is accessible via this API.
    3.12  """
    3.13  import sys
    3.14  import httplib
    3.15 @@ -27,6 +32,8 @@ class Foo(httplib.HTTPResponse):
    3.16  
    3.17  
    3.18  def sxprio(sxpr):
    3.19 +    """Convert an sxpr to a string.
    3.20 +    """
    3.21      io = StringIO()
    3.22      sxp.show(sxpr, out=io)
    3.23      print >> io
    3.24 @@ -80,6 +87,12 @@ def eventurl(location, root, id=''):
    3.25      return urljoin(location, root, 'event/', id)
    3.26  
    3.27  def xend_request(url, method, data=None):
    3.28 +    """Make a request to xend.
    3.29 +
    3.30 +    url    xend request url
    3.31 +    method http method: POST or GET
    3.32 +    data   request argument data (dict)
    3.33 +    """
    3.34      urlinfo = urlparse.urlparse(url)
    3.35      (uproto, ulocation, upath, uparam, uquery, ufrag) = urlinfo
    3.36      if DEBUG: print url, urlinfo
    3.37 @@ -122,20 +135,37 @@ def xend_request(url, method, data=None)
    3.38      return val
    3.39  
    3.40  def xend_get(url, args=None):
    3.41 +    """Make a xend request using GET.
    3.42 +    Requests using GET are 'safe' and may be repeated without
    3.43 +    nasty side-effects.
    3.44 +    """
    3.45      return xend_request(url, "GET", args)
    3.46  
    3.47  def xend_call(url, data):
    3.48 +    """Make xend request using POST.
    3.49 +    Requests using POST potentially cause side-effects and should
    3.50 +    not be repeated unless it really is wanted to do the side
    3.51 +    effect again.
    3.52 +    """
    3.53      return xend_request(url, "POST", data)
    3.54  
    3.55  class Xend:
    3.56  
    3.57 +    """Default location of the xend server."""
    3.58      SRV_DEFAULT = "localhost:8000"
    3.59 +
    3.60 +    """Default path to the xend root on the server."""
    3.61      ROOT_DEFAULT = "/xend/"
    3.62  
    3.63      def __init__(self, srv=None, root=None):
    3.64          self.bind(srv, root)
    3.65  
    3.66      def bind(self, srv=None, root=None):
    3.67 +        """Bind to a given server.
    3.68 +
    3.69 +        srv  server location (host:port)
    3.70 +        root server xend root path
    3.71 +        """
    3.72          if srv is None: srv = self.SRV_DEFAULT
    3.73          if root is None: root = self.ROOT_DEFAULT
    3.74          if not root.endswith('/'): root += '/'
     4.1 --- a/tools/python/xen/xend/server/SrvDomainDir.py	Thu Jul 01 23:32:40 2004 +0000
     4.2 +++ b/tools/python/xen/xend/server/SrvDomainDir.py	Fri Jul 02 08:30:28 2004 +0000
     4.3 @@ -1,5 +1,6 @@
     4.4  # Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
     4.5  
     4.6 +import traceback
     4.7  from StringIO import StringIO
     4.8  
     4.9  from twisted.protocols import http
    4.10 @@ -24,6 +25,7 @@ class SrvDomainDir(SrvDir):
    4.11          val = None
    4.12          try:
    4.13              dom = self.xd.domain_get(x)
    4.14 +            if not dom: raise KeyError('No such domain')
    4.15              val = SrvDomain(dom)
    4.16          except KeyError, ex:
    4.17              print 'SrvDomainDir>', ex
    4.18 @@ -38,6 +40,9 @@ class SrvDomainDir(SrvDir):
    4.19          return v
    4.20  
    4.21      def op_create(self, op, req):
    4.22 +        """Create a domain.
    4.23 +        Expects the domain config in request parameter 'config' in SXP format.
    4.24 +        """
    4.25          ok = 0
    4.26          try:
    4.27              configstring = req.args.get('config')[0]
    4.28 @@ -48,7 +53,8 @@ class SrvDomainDir(SrvDir):
    4.29              config = pin.get_val()
    4.30              ok = 1
    4.31          except Exception, ex:
    4.32 -            print 'op_create>', ex
    4.33 +            print 'op_create> Exception in config', ex
    4.34 +            traceback.print_exc()
    4.35          if not ok:
    4.36              req.setResponseCode(http.BAD_REQUEST, "Invalid configuration")
    4.37              return "Invalid configuration"
    4.38 @@ -60,10 +66,10 @@ class SrvDomainDir(SrvDir):
    4.39              deferred.addCallback(self._cb_op_create, configstring, req)
    4.40              return deferred
    4.41          except Exception, ex:
    4.42 -            raise
    4.43 -            #return ['err', str(ex) ]
    4.44 -            #req.setResponseCode(http.BAD_REQUEST, "Error creating domain")
    4.45 -            #return str(ex)
    4.46 +            print 'op_create> Exception creating domain:'
    4.47 +            traceback.print_exc()
    4.48 +            req.setResponseCode(http.BAD_REQUEST, "Error creating domain")
    4.49 +            return str(ex)
    4.50              #return error.ErrorPage(http.BAD_REQUEST,
    4.51              #                       "Error creating domain",
    4.52              #                       str(ex))
    4.53 @@ -90,6 +96,8 @@ class SrvDomainDir(SrvDir):
    4.54              return val
    4.55  
    4.56      def op_restore(self, op, req):
    4.57 +        """Restore a domain from file.
    4.58 +        """
    4.59          fn = FormFn(self.xd.domain_restore,
    4.60                      [['file', 'str']])
    4.61          val = fn(req.args)
    4.62 @@ -131,6 +139,8 @@ class SrvDomainDir(SrvDir):
    4.63              req.write('</ul>')
    4.64  
    4.65      def form(self, req):
    4.66 +        """Generate the form(s) for domain dir operations.
    4.67 +        """
    4.68          req.write('<form method="post" action="%s" enctype="multipart/form-data">'
    4.69                    % req.prePathURL())
    4.70          req.write('<button type="submit" name="op" value="create">Create Domain</button>')
     5.1 --- a/tools/python/xen/xend/server/blkif.py	Thu Jul 01 23:32:40 2004 +0000
     5.2 +++ b/tools/python/xen/xend/server/blkif.py	Fri Jul 02 08:30:28 2004 +0000
     5.3 @@ -1,3 +1,5 @@
     5.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
     5.5 +
     5.6  from twisted.internet import defer
     5.7  
     5.8  from xen.xend import sxp
     5.9 @@ -28,6 +30,11 @@ class BlkifControllerFactory(controller.
    5.10          self.registerChannel()
    5.11  
    5.12      def createInstance(self, dom, recreate=0):
    5.13 +        """Create a block device controller for a domain.
    5.14 +
    5.15 +        dom      domain
    5.16 +        recreate if true it's a recreate (after xend restart)
    5.17 +        """
    5.18          d = self.addDeferred()
    5.19          blkif = self.getInstanceByDom(dom)
    5.20          if blkif:
    5.21 @@ -42,29 +49,50 @@ class BlkifControllerFactory(controller.
    5.22          return d
    5.23  
    5.24      def getDomainDevices(self, dom):
    5.25 +        """Get the block devices for a domain.
    5.26 +
    5.27 +        dom domain
    5.28 +
    5.29 +        returns devices
    5.30 +        """
    5.31          blkif = self.getInstanceByDom(dom)
    5.32          return (blkif and blkif.getDevices()) or []
    5.33  
    5.34      def getDomainDevice(self, dom, vdev):
    5.35 +        """Get a block device from a domain.
    5.36 +
    5.37 +        dom  domain
    5.38 +        vdev device index
    5.39 +
    5.40 +        returns device
    5.41 +        """
    5.42          blkif = self.getInstanceByDom(dom)
    5.43          return (blkif and blkif.getDevice(vdev)) or None
    5.44  
    5.45      def setControlDomain(self, dom, recreate=0):
    5.46 +        """Set the back-end block device controller domain.
    5.47 +
    5.48 +        dom      domain
    5.49 +        recreate if true it's a recreate (after xend restart)
    5.50 +        """
    5.51          if self.dom == dom: return
    5.52          self.deregisterChannel()
    5.53          if not recreate:
    5.54              self.attached = 0
    5.55          self.dom = dom
    5.56          self.registerChannel()
    5.57 -        #
    5.58 -        #if xend.blkif.be_port:
    5.59 -        #    xend.blkif.recovery = True
    5.60 -        #xend.blkif.be_port = xend.main.port_from_dom(dom)
    5.61  
    5.62      def getControlDomain(self):
    5.63 +        """Get the back-end block device controller domain.
    5.64 +        """
    5.65          return self.dom
    5.66  
    5.67      def reattachDevice(self, dom, vdev):
    5.68 +        """Reattach a device (on changing control domain).
    5.69 +
    5.70 +        dom  domain
    5.71 +        vdev device index
    5.72 +        """
    5.73          blkif = self.getInstanceByDom(dom)
    5.74          if blkif:
    5.75              blkif.reattachDevice(vdev)
    5.76 @@ -83,6 +111,9 @@ class BlkifControllerFactory(controller.
    5.77          return attached
    5.78                           
    5.79      def reattached(self):
    5.80 +        """Notify all block interface we have been reattached
    5.81 +        (after changing control domain).
    5.82 +        """
    5.83          for blkif in self.getInstances():
    5.84              blkif.reattached()
    5.85  
    5.86 @@ -147,7 +178,6 @@ class BlkDev(controller.Dev):
    5.87          return val
    5.88  
    5.89      def destroy(self):
    5.90 -        print 'BlkDev>destroy>', self.vdev
    5.91          PrettyPrint.prettyprint(self.sxpr())
    5.92          self.controller.send_be_vbd_destroy(self.vdev)
    5.93          
    5.94 @@ -157,7 +187,6 @@ class BlkifController(controller.Control
    5.95      """
    5.96      
    5.97      def __init__(self, factory, dom):
    5.98 -        #print 'BlkifController> dom=', dom
    5.99          controller.Controller.__init__(self, factory, dom)
   5.100          self.devices = {}
   5.101  
   5.102 @@ -172,7 +201,6 @@ class BlkifController(controller.Control
   5.103          self.attached = 1
   5.104          self.evtchn = None
   5.105          self.registerChannel()
   5.106 -        #print 'BlkifController<', 'dom=', self.dom, 'idx=', self.idx
   5.107  
   5.108      def sxpr(self):
   5.109          val = ['blkif', ['dom', self.dom]]
   5.110 @@ -183,8 +211,6 @@ class BlkifController(controller.Control
   5.111          return val
   5.112  
   5.113      def lostChannel(self):
   5.114 -        print 'BlkifController>lostChannel>', 'dom=', self.dom
   5.115 -        #self.destroyDevices()
   5.116          controller.Controller.lostChannel(self)
   5.117  
   5.118      def getDevices(self):
   5.119 @@ -201,8 +227,14 @@ class BlkifController(controller.Control
   5.120  
   5.121      def attachDevice(self, vdev, mode, segment, recreate=0):
   5.122          """Attach a device to the specified interface.
   5.123 +
   5.124 +        vdev     device index
   5.125 +        mode     read/write mode
   5.126 +        segment  segment
   5.127 +        recreate if true it's being recreated (after xend restart)
   5.128 +
   5.129 +        returns deferred
   5.130          """
   5.131 -        #print 'BlkifController>attach_device>', self.dom, vdev, mode, segment
   5.132          dev = self.addDevice(vdev, mode, segment)
   5.133          if not dev: return -1
   5.134          if recreate:
   5.135 @@ -214,13 +246,11 @@ class BlkifController(controller.Control
   5.136          return d
   5.137  
   5.138      def destroy(self):
   5.139 -        print 'BlkifController>destroy> dom=', self.dom
   5.140          def cb_destroy(val):
   5.141              self.send_be_destroy()
   5.142          d = self.factory.addDeferred()
   5.143          d.addCallback(cb_destroy)
   5.144          self.send_be_disconnect()
   5.145 -        #self.destroyDevices()
   5.146  
   5.147      def destroyDevices(self):
   5.148          for dev in self.getDevices():
   5.149 @@ -276,11 +306,6 @@ class BlkifController(controller.Control
   5.150          self.factory.writeRequest(msg)
   5.151          pass
   5.152  
   5.153 -    #def recv_fe_interface_status_changed(self, msg, req):
   5.154 -    #    (hnd, status, chan) = unpackMsg('blkif_fe_interface_status_changed_t', msg)
   5.155 -    #    print 'recv_fe_interface_status_changed>', hnd, status, chan
   5.156 -    #   pass
   5.157 -
   5.158      def send_fe_interface_status_changed(self):
   5.159          msg = packMsg('blkif_fe_interface_status_changed_t',
   5.160                        { 'handle' : 0,
     6.1 --- a/tools/python/xen/xend/server/channel.py	Thu Jul 01 23:32:40 2004 +0000
     6.2 +++ b/tools/python/xen/xend/server/channel.py	Fri Jul 02 08:30:28 2004 +0000
     6.3 @@ -1,3 +1,5 @@
     6.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
     6.5 +
     6.6  import xen.lowlevel.xc; xc = xen.lowlevel.xc.new()
     6.7  from xen.lowlevel import xu
     6.8  from messages import msgTypeName
     6.9 @@ -24,14 +26,11 @@ class ChannelFactory:
    6.10          self.notifier = xu.notifier()
    6.11      
    6.12      def addChannel(self, channel):
    6.13 -        """Add a channel.
    6.14 +        """Add a channel. Registers with the notifier.
    6.15          """
    6.16          idx = channel.idx
    6.17          self.channels[idx] = channel
    6.18          self.notifier.bind(idx)
    6.19 -        # Try to wake it up
    6.20 -        #self.notifier.unmask(idx)
    6.21 -        #channel.notify()
    6.22  
    6.23      def getChannel(self, idx):
    6.24          """Get the channel with the given index (if any).
    6.25 @@ -40,6 +39,7 @@ class ChannelFactory:
    6.26  
    6.27      def delChannel(self, idx):
    6.28          """Remove the channel with the given index (if any).
    6.29 +        Deregisters with the notifier.
    6.30          """
    6.31          if idx in self.channels:
    6.32              del self.channels[idx]
    6.33 @@ -288,6 +288,8 @@ class Channel(BaseChannel):
    6.34                     self.getRemotePort()))
    6.35  
    6.36      def handleNotification(self):
    6.37 +        """Process outstanding messages in repsonse to notification on the port.
    6.38 +        """
    6.39          if self.closed:
    6.40              print 'handleNotification> Notification on closed channel', self
    6.41              return
    6.42 @@ -299,6 +301,8 @@ class Channel(BaseChannel):
    6.43              self.notify()
    6.44  
    6.45      def notify(self):
    6.46 +        """Notify the other end of the port that messages have been processed.
    6.47 +        """
    6.48          if self.closed: return
    6.49          self.port.notify()
    6.50  
     7.1 --- a/tools/python/xen/xend/server/console.py	Thu Jul 01 23:32:40 2004 +0000
     7.2 +++ b/tools/python/xen/xend/server/console.py	Fri Jul 02 08:30:28 2004 +0000
     7.3 @@ -1,3 +1,4 @@
     7.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
     7.5  
     7.6  from twisted.internet import reactor
     7.7  from twisted.internet import protocol
     7.8 @@ -12,11 +13,6 @@ import controller
     7.9  from messages import *
    7.10  from params import *
    7.11  
    7.12 -"""Telnet binary option."""
    7.13 -TRANSMIT_BINARY = '0'
    7.14 -WILL = chr(251)
    7.15 -IAC = chr(255)
    7.16 -
    7.17  class ConsoleProtocol(protocol.Protocol):
    7.18      """Asynchronous handler for a console TCP socket.
    7.19      """
    7.20 @@ -36,19 +32,12 @@ class ConsoleProtocol(protocol.Protocol)
    7.21              self.loseConnection()
    7.22              return
    7.23          else:
    7.24 -            # KAF: A nice quiet successful connect. Don't bother with telnet
    7.25 -            # control sequence -- telnet is not the appropriate protocol here. 
    7.26 +            # KAF: A nice quiet successful connect.
    7.27              #self.transport.write("Connected to console %d on domain %d\n"
    7.28              #                     % (self.idx, self.controller.dom))
    7.29 -            #self.setTelnetTransmitBinary()
    7.30              eserver.inject('xend.console.connect',
    7.31                             [self.idx, self.addr[0], self.addr[1]])
    7.32  
    7.33 -    def setTelnetTransmitBinary(self):
    7.34 -        """Send the sequence to set the telnet TRANSMIT-BINARY option.
    7.35 -        """
    7.36 -        self.write(IAC + WILL + TRANSMIT_BINARY)
    7.37 -
    7.38      def dataReceived(self, data):
    7.39          if self.controller.handleInput(self, data):
    7.40              self.loseConnection()
    7.41 @@ -105,7 +94,6 @@ class ConsoleController(controller.Contr
    7.42      """
    7.43  
    7.44      def __init__(self, factory, dom, console_port):
    7.45 -        #print 'ConsoleController> dom=', dom, type(dom)
    7.46          controller.Controller.__init__(self, factory, dom)
    7.47          self.majorTypes = [ CMSG_CONSOLE ]
    7.48          self.status = "new"
    7.49 @@ -118,7 +106,6 @@ class ConsoleController(controller.Contr
    7.50          self.registerChannel()
    7.51          self.listener = None
    7.52          self.listen()
    7.53 -        #print 'ConsoleController<', 'dom=', self.dom, 'idx=', self.idx
    7.54  
    7.55      def sxpr(self):
    7.56          val =['console',
    7.57 @@ -143,7 +130,6 @@ class ConsoleController(controller.Contr
    7.58  
    7.59      def close(self):
    7.60          try:
    7.61 -            #print 'ConsoleController> close dom=', self.dom
    7.62              self.status = "closed"
    7.63              if self.conn:
    7.64                  self.conn.loseConnection()
    7.65 @@ -183,11 +169,11 @@ class ConsoleController(controller.Contr
    7.66          self.listen()
    7.67  
    7.68      def requestReceived(self, msg, type, subtype):
    7.69 -        #print '***Console', self.dom, msg.get_payload()
    7.70          self.rbuf.write(msg.get_payload())
    7.71          self.handleOutput()
    7.72          
    7.73      def responseReceived(self, msg, type, subtype):
    7.74 +        # Just ignore responses.
    7.75          pass
    7.76  
    7.77      def produceRequests(self):
    7.78 @@ -215,18 +201,14 @@ class ConsoleController(controller.Contr
    7.79          Sends it to the connected console (if any).
    7.80          """
    7.81          if self.closed():
    7.82 -            #print 'Console>handleOutput> closed'
    7.83              return -1
    7.84          if not self.conn:
    7.85 -            #print 'Console>handleOutput> not connected'
    7.86              return 0
    7.87          while not self.rbuf.empty():
    7.88              try:
    7.89 -                #print 'Console>handleOutput> writing...'
    7.90                  bytes = self.conn.write(self.rbuf.peek())
    7.91                  if bytes > 0:
    7.92                      self.rbuf.discard(bytes)
    7.93              except socket.error, error:
    7.94                  pass
    7.95 -        #print 'Console>handleOutput<'
    7.96          return 0
     8.1 --- a/tools/python/xen/xend/server/controller.py	Thu Jul 01 23:32:40 2004 +0000
     8.2 +++ b/tools/python/xen/xend/server/controller.py	Fri Jul 02 08:30:28 2004 +0000
     8.3 @@ -1,3 +1,5 @@
     8.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
     8.5 +
     8.6  from twisted.internet import defer
     8.7  
     8.8  import channel
     8.9 @@ -5,6 +7,15 @@ from messages import msgTypeName
    8.10  
    8.11  class CtrlMsgRcvr:
    8.12      """Abstract class for things that deal with a control interface to a domain.
    8.13 +
    8.14 +    Instance variables:
    8.15 +
    8.16 +    dom       : the domain we are a control interface for
    8.17 +    majorTypes: list of major message types we are interested in
    8.18 +    subTypes  : mapping of message subtypes to methods
    8.19 +    
    8.20 +    channel   : channel to the domain
    8.21 +    idx       : channel index
    8.22      """
    8.23  
    8.24  
    8.25 @@ -17,6 +28,12 @@ class CtrlMsgRcvr:
    8.26          self.idx = None
    8.27  
    8.28      def requestReceived(self, msg, type, subtype):
    8.29 +        """Dispatch a request to handlers.
    8.30 +
    8.31 +        msg     message
    8.32 +        type    major message type
    8.33 +        subtype minor message type
    8.34 +        """
    8.35          method = self.subTypes.get(subtype)
    8.36          if method:
    8.37              method(msg, 1)
    8.38 @@ -25,6 +42,12 @@ class CtrlMsgRcvr:
    8.39                     % (msgTypeName(type, subtype), type, subtype)), self
    8.40          
    8.41      def responseReceived(self, msg, type, subtype):
    8.42 +        """Dispatch a response to handlers.
    8.43 +
    8.44 +        msg     message
    8.45 +        type    major message type
    8.46 +        subtype minor message type
    8.47 +        """
    8.48          method = self.subTypes.get(subtype)
    8.49          if method:
    8.50              method(msg, 0)
    8.51 @@ -33,9 +56,14 @@ class CtrlMsgRcvr:
    8.52                     % (msgTypeName(type, subtype), type, subtype)), self
    8.53  
    8.54      def lostChannel(self):
    8.55 +        """Called when the channel to the domain is lost.
    8.56 +        """
    8.57          pass
    8.58      
    8.59      def registerChannel(self):
    8.60 +        """Register interest in our major message types with the
    8.61 +        channel to our domain.
    8.62 +        """
    8.63          #print 'CtrlMsgRcvr>registerChannel>', self
    8.64          self.channel = self.channelFactory.domChannel(self.dom)
    8.65          self.idx = self.channel.getIndex()
    8.66 @@ -43,21 +71,32 @@ class CtrlMsgRcvr:
    8.67              self.channel.registerDevice(self.majorTypes, self)
    8.68          
    8.69      def deregisterChannel(self):
    8.70 +        """Deregister interest in our major message types with the
    8.71 +        channel to our domain.
    8.72 +        """
    8.73          #print 'CtrlMsgRcvr>deregisterChannel>', self
    8.74          if self.channel:
    8.75              self.channel.deregisterDevice(self)
    8.76              del self.channel
    8.77  
    8.78      def produceRequests(self):
    8.79 +        """Produce any queued requests.
    8.80 +
    8.81 +        return number produced
    8.82 +        """
    8.83          return 0
    8.84  
    8.85      def writeRequest(self, msg):
    8.86 +        """Write a request to the channel.
    8.87 +        """
    8.88          if self.channel:
    8.89              self.channel.writeRequest(msg)
    8.90          else:
    8.91              print 'CtrlMsgRcvr>writeRequest>', 'no channel!', self
    8.92  
    8.93      def writeResponse(self, msg):
    8.94 +        """Write a response to the channel.
    8.95 +        """
    8.96          if self.channel:
    8.97              self.channel.writeResponse(msg)
    8.98          else:
    8.99 @@ -66,6 +105,13 @@ class CtrlMsgRcvr:
   8.100  class ControllerFactory(CtrlMsgRcvr):
   8.101      """Abstract class for factories creating controllers.
   8.102      Maintains a table of instances.
   8.103 +
   8.104 +    Instance variables:
   8.105 +
   8.106 +    instances : mapping of index to controller instance
   8.107 +    dlist     : list of deferreds
   8.108 +    dom       : domain
   8.109 +    timeout   : deferred timeout
   8.110      """
   8.111  
   8.112      def __init__(self):
   8.113 @@ -77,34 +123,49 @@ class ControllerFactory(CtrlMsgRcvr):
   8.114          self.timeout = 10
   8.115          
   8.116      def addInstance(self, instance):
   8.117 +        """Add a controller instance (under its index).
   8.118 +        """
   8.119          self.instances[instance.idx] = instance
   8.120  
   8.121      def getInstance(self, idx):
   8.122 +        """Get a controller instance from its index.
   8.123 +        """
   8.124          return self.instances.get(idx)
   8.125  
   8.126      def getInstances(self):
   8.127 +        """Get a list of all controller instances.
   8.128 +        """
   8.129          return self.instances.values()
   8.130  
   8.131      def getInstanceByDom(self, dom):
   8.132 +        """Get the controller instance for the given domain.
   8.133 +        """
   8.134          for inst in self.instances.values():
   8.135              if inst.dom == dom:
   8.136                  return inst
   8.137          return None
   8.138  
   8.139      def delInstance(self, instance):
   8.140 -        #print 'ControllerFactory>delInstance>', instance.idx
   8.141 +        """Delete an instance from the table.
   8.142 +        """
   8.143          if instance.idx in self.instances:
   8.144 -            #print 'ControllerFactory>delInstance> remove', instance.idx
   8.145              del self.instances[instance.idx]
   8.146  
   8.147      def createInstance(self, dom, recreate=0):
   8.148 +        """Create an instance. Define in a subclass.
   8.149 +        """
   8.150          raise NotImplementedError()
   8.151  
   8.152      def instanceClosed(self, instance):
   8.153 -        #print 'ControllerFactory>instanceClosed>', instance.idx, instance
   8.154 +        """Callback called when an instance is closed (usually by the instance).
   8.155 +        """
   8.156          self.delInstance(instance)
   8.157  
   8.158      def addDeferred(self):
   8.159 +        """Add a deferred object.
   8.160 +
   8.161 +        returns deferred
   8.162 +        """
   8.163          d = defer.Deferred()
   8.164          if self.timeout > 0:
   8.165              # The deferred will error if not called before timeout.
   8.166 @@ -113,11 +174,19 @@ class ControllerFactory(CtrlMsgRcvr):
   8.167          return d
   8.168  
   8.169      def callDeferred(self, *args):
   8.170 +        """Call the top deferred object
   8.171 +
   8.172 +        args arguments
   8.173 +        """
   8.174          if self.dlist:
   8.175              d = self.dlist.pop(0)
   8.176              d.callback(*args)
   8.177  
   8.178      def errDeferred(self, *args):
   8.179 +        """Signal an error to the top deferred object.
   8.180 +
   8.181 +        args arguments
   8.182 +        """
   8.183          if self.dlist:
   8.184              d = self.dlist.pop(0)
   8.185              d.errback(*args)
   8.186 @@ -134,15 +203,20 @@ class Controller(CtrlMsgRcvr):
   8.187          self.idx = None
   8.188  
   8.189      def close(self):
   8.190 +        """Close the controller.
   8.191 +        """
   8.192          self.deregisterChannel()
   8.193          self.lostChannel()
   8.194  
   8.195      def lostChannel(self):
   8.196 -        #print 'Controller>lostChannel>', self, self.factory
   8.197 +        """The controller channel has been lost.
   8.198 +        """
   8.199          self.factory.instanceClosed(self)
   8.200  
   8.201  class Dev:
   8.202 -
   8.203 +    """Abstract class for a device attached to a device controller.
   8.204 +    """
   8.205 +    
   8.206      def __init__(self, controller):
   8.207          self.controller = controller
   8.208          self.props = {}
   8.209 @@ -160,9 +234,6 @@ class Dev:
   8.210          if k in self.props:
   8.211              del self.props[k]
   8.212  
   8.213 -    #def __repr__(self):
   8.214 -    #    return str(self.sxpr())
   8.215 -
   8.216      def sxpr(self):
   8.217          raise NotImplementedError()
   8.218  
     9.1 --- a/tools/python/xen/xend/server/cstruct.py	Thu Jul 01 23:32:40 2004 +0000
     9.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.3 @@ -1,269 +0,0 @@
     9.4 -import struct
     9.5 -
     9.6 -class Struct:
     9.7 -
     9.8 -    maxDepth = 10
     9.9 -
    9.10 -    base = ['x', 'B', 'H', 'I', 'L', 'Q', 'c', 'h', 'i', 'l', 'q', ]
    9.11 -
    9.12 -    sizes = {'B': 1,
    9.13 -            'H': 2,
    9.14 -            'I': 4,
    9.15 -            'L': 4,
    9.16 -            'Q': 8,
    9.17 -            'c': 1,
    9.18 -            'h': 2,
    9.19 -            'i': 4,
    9.20 -            'l': 4,
    9.21 -            'q': 8,
    9.22 -            'x': 1,
    9.23 -            }
    9.24 -
    9.25 -    formats = {
    9.26 -        'int8'          : 'B',
    9.27 -        'int16'         : 'H',
    9.28 -        'int32'         : 'I',
    9.29 -        'int64'         : 'Q',
    9.30 -        'u8'            : 'B',
    9.31 -        'u16'           : 'H',
    9.32 -        'u32'           : 'I',
    9.33 -        'u64'           : 'Q'
    9.34 -        }
    9.35 -
    9.36 -    def typedef(self, name, val):
    9.37 -        self.formats[name] = val
    9.38 -
    9.39 -    def struct(self, name, *f):
    9.40 -        self.typedef(name, StructInfo(self, f))
    9.41 -        
    9.42 -    def getType(self, name):
    9.43 -        return self.formats[name]
    9.44 -
    9.45 -    def format(self, ty):
    9.46 -        d = 0
    9.47 -        f = ty
    9.48 -        while d < self.maxDepth:
    9.49 -            d += 1
    9.50 -            f = self.formats[f]
    9.51 -            if isinstance(f, StructInfo):
    9.52 -                return f.format()
    9.53 -            if f in self.base:
    9.54 -                return f
    9.55 -        return -1
    9.56 -
    9.57 -    def alignedformat(self, ty):
    9.58 -        fmt = self.format(ty)
    9.59 -        #print 'alignedformat> %s |%s|' %(ty, fmt)
    9.60 -        afmt = self.align(fmt)
    9.61 -        #print 'alignedformat< %s |%s| |%s|' % (ty, fmt, afmt)
    9.62 -        return afmt
    9.63 -
    9.64 -    def align(self, fmt):
    9.65 -        n1 = 0
    9.66 -        afmt = ''
    9.67 -        for a in fmt:
    9.68 -            n2 = self.getSize(a)
    9.69 -            m = n1 % n2
    9.70 -            if m:
    9.71 -                d = (n2 - m)
    9.72 -                afmt += 'x' * d
    9.73 -                n1 += d
    9.74 -            afmt += a
    9.75 -            n1 += n2
    9.76 -        return afmt
    9.77 -
    9.78 -    def fmtsize(self, fmt):
    9.79 -        s = 0
    9.80 -        for f in fmt:
    9.81 -            s += self.getSize(f)
    9.82 -        return s
    9.83 -
    9.84 -    def getSize(self, f):
    9.85 -        return self.sizes[f]
    9.86 -
    9.87 -    def pack(self, ty, data):
    9.88 -        return self.getType(ty).pack(data)
    9.89 -
    9.90 -    def unpack(self, ty, data):
    9.91 -        return self.getType(ty).unpack(data)
    9.92 -
    9.93 -    def show(self):
    9.94 -        l = self.formats.keys()
    9.95 -        l.sort()
    9.96 -        for v in l:
    9.97 -            print "%-35s %-10s %s" % (v, self.format(v), self.alignedformat(v))
    9.98 -
    9.99 -
   9.100 -class StructInfo:
   9.101 -
   9.102 -    def __init__(self, s, f):
   9.103 -        self.fmt = None
   9.104 -        self.structs = s
   9.105 -        self.fields = f
   9.106 -
   9.107 -    def alignedformat(self):
   9.108 -        if self.afmt: return self.afmt
   9.109 -        self.afmt = self.structs.align(self.format())
   9.110 -        return self.afmt
   9.111 -    
   9.112 -    def format(self):
   9.113 -        if self.fmt: return self.fmt
   9.114 -        fmt = ""
   9.115 -        for (ty, name) in self.fields:
   9.116 -            fmt += self.formatString(ty)
   9.117 -        self.fmt = fmt
   9.118 -        return fmt
   9.119 -
   9.120 -    def formatString(self, ty):
   9.121 -        if ty in self.fields:
   9.122 -            ty = self.fields[ty]
   9.123 -        return self.structs.format(ty)
   9.124 -
   9.125 -    def pack(self, *args):
   9.126 -        return struct.pack(self.alignedformat(), *args)
   9.127 -
   9.128 -    def unpack(self, data):
   9.129 -        return struct.unpack(self.alignedformat(), data)
   9.130 -
   9.131 -types = Struct()
   9.132 -
   9.133 -types.typedef('short'         , 'h')
   9.134 -types.typedef('int'           , 'i')
   9.135 -types.typedef('long'          , 'l')
   9.136 -types.typedef('unsigned short', 'H')
   9.137 -types.typedef('unsigned int'  , 'I')
   9.138 -types.typedef('unsigned long' , 'L')
   9.139 -types.typedef('domid_t'       , 'u64')
   9.140 -types.typedef('blkif_vdev_t'  , 'u16')
   9.141 -types.typedef('blkif_pdev_t'  , 'u16')
   9.142 -types.typedef('blkif_sector_t', 'u64')
   9.143 -
   9.144 -types.struct('u8[6]',
   9.145 -             ('u8', 'a1'),
   9.146 -             ('u8', 'a2'),
   9.147 -             ('u8', 'a3'),
   9.148 -             ('u8', 'a4'),
   9.149 -             ('u8', 'a5'),
   9.150 -             ('u8', 'a6'))
   9.151 -             
   9.152 -types.struct('blkif_fe_interface_status_changed_t',
   9.153 -    ('unsigned int',    'handle'),
   9.154 -    ('unsigned int',    'status'),
   9.155 -    ('unsigned int',    'evtchn'))
   9.156 -
   9.157 -types.struct('blkif_fe_driver_status_changed_t',
   9.158 -    ('unsigned int',    'status'),
   9.159 -    ('unsigned int',    'nr_interfaces'))
   9.160 -
   9.161 -types.struct('blkif_fe_interface_connect_t',
   9.162 -    ('unsigned int' ,   'handle'),
   9.163 -    ('unsigned long',   'shmem_frame'))
   9.164 -
   9.165 -types.struct('blkif_fe_interface_disconnect_t',
   9.166 -    ('unsigned int',   'handle'))
   9.167 -
   9.168 -types.struct('blkif_extent_t',
   9.169 -    ('blkif_pdev_t'  , 'device'),
   9.170 -    ('blkif_sector_t', 'sector_start'),
   9.171 -    ('blkif_sector_t', 'sector_length'))
   9.172 -
   9.173 -types.struct('blkif_be_create_t', 
   9.174 -    ('domid_t'     ,   'domid'),
   9.175 -    ('unsigned int',   'blkif_handle'),
   9.176 -    ('unsigned int',   'status'))
   9.177 -             
   9.178 -types.struct('blkif_be_destroy_t',
   9.179 -    ('domid_t'     ,   'domid'),
   9.180 -    ('unsigned int',   'blkif_handle'),
   9.181 -    ('unsigned int',   'status'))
   9.182 -
   9.183 -types.struct('blkif_be_connect_t',
   9.184 -    ('domid_t'      ,  'domid'),
   9.185 -    ('unsigned int' ,  'blkif_handle'),
   9.186 -    ('unsigned int' ,  'evtchn'),
   9.187 -    ('unsigned long',  'shmem_frame'),
   9.188 -    ('unsigned int' ,  'status'))
   9.189 -
   9.190 -types.struct('blkif_be_disconnect_t',
   9.191 -    ('domid_t'     ,   'domid'),
   9.192 -    ('unsigned int',   'blkif_handle'),
   9.193 -    ('unsigned int',   'status'))
   9.194 -
   9.195 -types.struct('blkif_be_vbd_create_t', 
   9.196 -    ('domid_t'     ,   'domid'),         #Q
   9.197 -    ('unsigned int',   'blkif_handle'),  #I
   9.198 -    ('blkif_vdev_t',   'vdevice'),       #H
   9.199 -    ('int'         ,   'readonly'),      #i
   9.200 -    ('unsigned int',   'status'))        #I
   9.201 -
   9.202 -types.struct('blkif_be_vbd_destroy_t', 
   9.203 -    ('domid_t'     ,   'domid'),
   9.204 -    ('unsigned int',   'blkif_handle'),
   9.205 -    ('blkif_vdev_t',   'vdevice'),
   9.206 -    ('unsigned int',   'status'))
   9.207 -
   9.208 -types.struct('blkif_be_vbd_grow_t', 
   9.209 -    ('domid_t'       , 'domid'),         #Q
   9.210 -    ('unsigned int'  , 'blkif_handle'),  #I
   9.211 -    ('blkif_vdev_t'  , 'vdevice'),       #H   
   9.212 -    ('blkif_extent_t', 'extent'),        #HQQ
   9.213 -    ('unsigned int'  , 'status'))        #I
   9.214 -
   9.215 -types.struct('blkif_be_vbd_shrink_t', 
   9.216 -    ('domid_t'     ,   'domid'),
   9.217 -    ('unsigned int',   'blkif_handle'),
   9.218 -    ('blkif_vdev_t',   'vdevice'),
   9.219 -    ('unsigned int',   'status'))
   9.220 -
   9.221 -types.struct('blkif_be_driver_status_changed_t',
   9.222 -    ('unsigned int',   'status'),
   9.223 -    ('unsigned int',   'nr_interfaces'))
   9.224 -
   9.225 -types.struct('netif_fe_interface_status_changed_t',
   9.226 -    ('unsigned int',   'handle'),
   9.227 -    ('unsigned int',   'status'),
   9.228 -    ('unsigned int',   'evtchn'),
   9.229 -    ('u8[6]',          'mac'))
   9.230 -
   9.231 -types.struct('netif_fe_driver_status_changed_t',
   9.232 -    ('unsigned int',   'status'),
   9.233 -    ('unsigned int',   'nr_interfaces'))
   9.234 -
   9.235 -types.struct('netif_fe_interface_connect_t',
   9.236 -    ('unsigned int',   'handle'),
   9.237 -    ('unsigned long',  'tx_shmem_frame'),
   9.238 -    ('unsigned long',  'rx_shmem_frame'))
   9.239 -
   9.240 -types.struct('netif_fe_interface_disconnect_t',
   9.241 -    ('unsigned int',   'handle'))
   9.242 -
   9.243 -types.struct('netif_be_create_t', 
   9.244 -    ('domid_t'     ,   'domid'),
   9.245 -    ('unsigned int',   'netif_handle'),
   9.246 -    ('u8[6]'       ,   'mac'),
   9.247 -    ('unsigned int',   'status'))
   9.248 -
   9.249 -types.struct('netif_be_destroy_t',
   9.250 -    ('domid_t'     ,   'domid'),
   9.251 -    ('unsigned int',   'netif_handle'),
   9.252 -    ('unsigned int',   'status'))
   9.253 -
   9.254 -types.struct('netif_be_connect_t', 
   9.255 -    ('domid_t'      ,  'domid'),
   9.256 -    ('unsigned int' ,  'netif_handle'),
   9.257 -    ('unsigned int' ,  'evtchn'),
   9.258 -    ('unsigned long',  'tx_shmem_frame'),
   9.259 -    ('unsigned long',  'rx_shmem_frame'),
   9.260 -    ('unsigned int' ,  'status'))
   9.261 -
   9.262 -types.struct('netif_be_disconnect_t',
   9.263 -    ('domid_t'     ,   'domid'),
   9.264 -    ('unsigned int',   'netif_handle'),
   9.265 -    ('unsigned int',   'status'))
   9.266 -
   9.267 -types.struct('netif_be_driver_status_changed_t',
   9.268 -    ('unsigned int',   'status'),
   9.269 -    ('unsigned int',   'nr_interfaces'))
   9.270 -
   9.271 -if 1 or __name__ == "__main__":
   9.272 -    types.show()
    10.1 --- a/tools/python/xen/xend/server/domain.py	Thu Jul 01 23:32:40 2004 +0000
    10.2 +++ b/tools/python/xen/xend/server/domain.py	Fri Jul 02 08:30:28 2004 +0000
    10.3 @@ -1,3 +1,5 @@
    10.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    10.5 +
    10.6  import channel
    10.7  import controller
    10.8  from messages import *
    10.9 @@ -7,11 +9,23 @@ class DomainControllerFactory(controller
   10.10      """
   10.11  
   10.12      def createInstance(self, dom):
   10.13 +        """Create a domain controller.
   10.14 +
   10.15 +        dom domain
   10.16 +
   10.17 +        returns domain controller
   10.18 +        """
   10.19          d = DomainController(self, dom)
   10.20          self.addInstance(d)
   10.21          return d
   10.22      
   10.23      def getInstanceByDom(self, dom):
   10.24 +        """Get a domain controller for a domain, creating if necessary.
   10.25 +
   10.26 +        dom domain
   10.27 +
   10.28 +        returns domain controller
   10.29 +        """
   10.30          for inst in self.instances.values():
   10.31              if inst.dom == dom:
   10.32                  return inst
   10.33 @@ -21,8 +35,11 @@ class DomainControllerFactory(controller
   10.34  
   10.35  class DomainController(controller.Controller):
   10.36      """Generic controller for a domain.
   10.37 +    Used for domain shutdown.
   10.38      """
   10.39  
   10.40 +    """Map shutdown reasons to the message type to use.
   10.41 +    """
   10.42      reasons = {'poweroff' : 'shutdown_poweroff_t',
   10.43                 'reboot'   : 'shutdown_reboot_t',
   10.44                 'suspend'  : 'shutdown_suspend_t' }
   10.45 @@ -34,6 +51,10 @@ class DomainController(controller.Contro
   10.46          print 'DomainController>', self, self.channel, self.idx
   10.47  
   10.48      def shutdown(self, reason):
   10.49 +        """Shutdown a domain.
   10.50 +
   10.51 +        reason shutdown reason
   10.52 +        """
   10.53          msgtype = self.reasons.get(reason)
   10.54          if not msgtype:
   10.55              raise ValueError('invalid reason:' + reason)
    11.1 --- a/tools/python/xen/xend/server/messages.py	Thu Jul 01 23:32:40 2004 +0000
    11.2 +++ b/tools/python/xen/xend/server/messages.py	Fri Jul 02 08:30:28 2004 +0000
    11.3 @@ -148,6 +148,9 @@ netif_formats = {
    11.4  msg_formats.update(netif_formats)
    11.5  
    11.6  #============================================================================
    11.7 +# Domain shutdown message types.
    11.8 +#============================================================================
    11.9 +
   11.10  CMSG_SHUTDOWN = 6
   11.11  
   11.12  CMSG_SHUTDOWN_POWEROFF  = 0
   11.13 @@ -177,6 +180,14 @@ class Msg:
   11.14      pass
   11.15  
   11.16  def packMsg(ty, params):
   11.17 +    """Pack a message.
   11.18 +    Any 'mac' parameter is passed in as an int[6] array and converted.
   11.19 +
   11.20 +    ty     message type name
   11.21 +    params message parameter dict
   11.22 +
   11.23 +    returns xu message
   11.24 +    """
   11.25      if DEBUG: print '>packMsg', ty, params
   11.26      (major, minor) = msg_formats[ty]
   11.27      args = {}
   11.28 @@ -194,6 +205,15 @@ def packMsg(ty, params):
   11.29      return msg
   11.30  
   11.31  def unpackMsg(ty, msg):
   11.32 +    """Unpack a message.
   11.33 +    Any mac addresses in the message are converted to int[6] array
   11.34 +    in the return dict.
   11.35 +
   11.36 +    ty  message type
   11.37 +    msg xu message
   11.38 +
   11.39 +    returns parameter dict
   11.40 +    """
   11.41      args = msg.get_payload()
   11.42      mac = [0, 0, 0, 0, 0, 0]
   11.43      macs = []
   11.44 @@ -212,6 +232,13 @@ def unpackMsg(ty, msg):
   11.45      return args
   11.46  
   11.47  def msgTypeName(ty, subty):
   11.48 +    """Convert a message type, subtype pair (ints) to a message type name (string).
   11.49 +
   11.50 +    ty    integer message type
   11.51 +    subty integer message subtype
   11.52 +
   11.53 +    returns message type name (or None)
   11.54 +    """
   11.55      for (name, info) in msg_formats.items():
   11.56          if info[0] == ty and info[1] == subty:
   11.57              return name
    12.1 --- a/tools/python/xen/xend/server/netif.py	Thu Jul 01 23:32:40 2004 +0000
    12.2 +++ b/tools/python/xen/xend/server/netif.py	Fri Jul 02 08:30:28 2004 +0000
    12.3 @@ -1,3 +1,5 @@
    12.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    12.5 +
    12.6  import random
    12.7  
    12.8  from twisted.internet import defer
    12.9 @@ -30,8 +32,12 @@ class NetifControllerFactory(controller.
   12.10  
   12.11      def createInstance(self, dom, recreate=0):
   12.12          """Create or find the network interface controller for a domain.
   12.13 +
   12.14 +        dom      domain
   12.15 +        recreate if true this is a recreate (xend restarted)
   12.16 +
   12.17 +        returns netif controller
   12.18          """
   12.19 -        #print 'netif>createInstance> dom=', dom
   12.20          netif = self.getInstanceByDom(dom)
   12.21          if netif is None:
   12.22              netif = NetifController(self, dom)
   12.23 @@ -39,15 +45,31 @@ class NetifControllerFactory(controller.
   12.24          return netif
   12.25  
   12.26      def getDomainDevices(self, dom):
   12.27 +        """Get the network device controllers for a domain.
   12.28 +
   12.29 +        dom  domain
   12.30 +        
   12.31 +        returns netif controller
   12.32 +        """
   12.33          netif = self.getInstanceByDom(dom)
   12.34          return (netif and netif.getDevices()) or []
   12.35  
   12.36      def getDomainDevice(self, dom, vif):
   12.37 +        """Get a virtual network interface device for a domain.
   12.38 +
   12.39 +        dom domain
   12.40 +        vif virtual interface index
   12.41 +
   12.42 +        returns NetDev
   12.43 +        """
   12.44          netif = self.getInstanceByDom(dom)
   12.45          return (netif and netif.getDevice(vif)) or None
   12.46          
   12.47      def setControlDomain(self, dom, recreate=0):
   12.48          """Set the 'back-end' device driver domain.
   12.49 +
   12.50 +        dom      domain
   12.51 +        recreate if true this is a recreate (xend restarted)
   12.52          """
   12.53          if self.dom == dom: return
   12.54          self.deregisterChannel()
   12.55 @@ -55,13 +77,10 @@ class NetifControllerFactory(controller.
   12.56              self.attached = 0
   12.57          self.dom = dom
   12.58          self.registerChannel()
   12.59 -        #
   12.60 -        #if xend.netif.be_port.remote_dom != 0:
   12.61 -        #    xend.netif.recovery = True
   12.62 -        #    xend.netif.be_port = xend.main.port_from_dom(dom)
   12.63 -        #
   12.64  
   12.65      def getControlDomain(self):
   12.66 +        """Get the domain id of the back-end control domain.
   12.67 +        """
   12.68          return self.dom
   12.69  
   12.70      def recv_be_create(self, msg, req):
   12.71 @@ -88,23 +107,6 @@ class NetifControllerFactory(controller.
   12.72                  netif.reattach_devices()
   12.73              self.attached = 1
   12.74  
   12.75 -##         pl = msg.get_payload()
   12.76 -##         status = pl['status']
   12.77 -##         if status == NETIF_DRIVER_STATUS_UP:
   12.78 -##             if xend.netif.recovery:
   12.79 -##                 print "New netif backend now UP, notifying guests:"
   12.80 -##                 for netif_key in interface.list.keys():
   12.81 -##                     netif = interface.list[netif_key]
   12.82 -##                     netif.create()
   12.83 -##                     print "  Notifying %d" % netif.dom
   12.84 -##                     msg = xu.message(
   12.85 -##                         CMSG_NETIF_FE,
   12.86 -##                         CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED, 0,
   12.87 -##                         { 'handle' : 0, 'status' : 1 })
   12.88 -##                     netif.ctrlif_tx_req(xend.main.port_from_dom(netif.dom),msg)
   12.89 -##                 print "Done notifying guests"
   12.90 -##                 recovery = False
   12.91 -                
   12.92  class NetDev(controller.Dev):
   12.93      """Info record for a network device.
   12.94      """
   12.95 @@ -130,9 +132,13 @@ class NetDev(controller.Dev):
   12.96          return val
   12.97  
   12.98      def get_vifname(self):
   12.99 +        """Get the virtual interface device name.
  12.100 +        """
  12.101          return "vif%d.%d" % (self.controller.dom, self.vif)
  12.102  
  12.103      def get_mac(self):
  12.104 +        """Get the MAC address as a string.
  12.105 +        """
  12.106          return ':'.join(map(lambda x: "%x" % x, self.mac))
  12.107  
  12.108      def vifctl_params(self):
  12.109 @@ -141,23 +147,30 @@ class NetDev(controller.Dev):
  12.110                   'ipaddr': self.ipaddr }
  12.111  
  12.112      def up(self, bridge=None, ipaddr=[]):
  12.113 +        """Bring the device up.
  12.114 +
  12.115 +        bridge ethernet bridge to connect to
  12.116 +        ipaddr list of ipaddrs to filter using iptables
  12.117 +        """
  12.118          self.bridge = bridge
  12.119          self.ipaddr = ipaddr
  12.120          Vifctl.up(self.get_vifname(), **self.vifctl_params())
  12.121  
  12.122      def down(self):
  12.123 +        """Bring the device down.
  12.124 +        """
  12.125          Vifctl.down(self.get_vifname(), **self.vifctl_params())
  12.126  
  12.127      def destroy(self):
  12.128 +        """Destroy the device's resources and disconnect from the back-end
  12.129 +        device controller.
  12.130 +        """
  12.131          def cb_destroy(val):
  12.132              self.controller.send_be_destroy(self.vif)
  12.133 -        print 'NetDev>destroy>', 'vif=', self.vif
  12.134 -        PrettyPrint.prettyprint(self.sxpr())
  12.135          self.down()
  12.136          d = self.controller.factory.addDeferred()
  12.137          d.addCallback(cb_destroy)
  12.138          self.controller.send_be_disconnect(self.vif)
  12.139 -        #self.controller.send_be_destroy(self.vif)
  12.140          
  12.141  
  12.142  class NetifController(controller.Controller):
  12.143 @@ -165,7 +178,6 @@ class NetifController(controller.Control
  12.144      """
  12.145      
  12.146      def __init__(self, factory, dom):
  12.147 -        #print 'NetifController> dom=', dom
  12.148          controller.Controller.__init__(self, factory, dom)
  12.149          self.devices = {}
  12.150          
  12.151 @@ -178,21 +190,22 @@ class NetifController(controller.Control
  12.152                  self.recv_fe_interface_connect,
  12.153              }
  12.154          self.registerChannel()
  12.155 -        #print 'NetifController<', 'dom=', self.dom, 'idx=', self.idx
  12.156  
  12.157      def sxpr(self):
  12.158          val = ['netif', ['dom', self.dom]]
  12.159          return val
  12.160      
  12.161      def randomMAC(self):
  12.162 -        # VIFs get a random MAC address with a "special" vendor id.
  12.163 -        # 
  12.164 -        # NB. The vendor is currently an "obsolete" one that used to belong
  12.165 -        # to DEC (AA-00-00). Using it is probably a bit rude :-)
  12.166 -        # 
  12.167 -        # NB2. The first bit of the first random octet is set to zero for
  12.168 -        # all dynamic MAC addresses. This may allow us to manually specify
  12.169 -        # MAC addresses for some VIFs with no fear of clashes.
  12.170 +        """Generate a random MAC address.
  12.171 +
  12.172 +        The OUI (Organisation Unique Identifier) used is AA:00:00, which
  12.173 +        is a currently unassigned one that used to belong to DEC.
  12.174 +
  12.175 +        The remaining 3 fields are random, with the first bit of the first
  12.176 +        random field set 0.
  12.177 +
  12.178 +        returns array of 6 ints
  12.179 +        """
  12.180          mac = [ 0xaa, 0x00, 0x00,
  12.181                  random.randint(0x00, 0x7f),
  12.182                  random.randint(0x00, 0xff),
  12.183 @@ -200,29 +213,46 @@ class NetifController(controller.Control
  12.184          return mac
  12.185  
  12.186      def lostChannel(self):
  12.187 -        print 'NetifController>lostChannel>', 'dom=', self.dom
  12.188 -        #self.destroyDevices()
  12.189 +        """Method called when the channel has been lost.
  12.190 +        """
  12.191          controller.Controller.lostChannel(self)
  12.192  
  12.193      def getDevices(self):
  12.194 +        """Get a list of the devices.
  12.195 +        """
  12.196          return self.devices.values()
  12.197  
  12.198      def getDevice(self, vif):
  12.199 +        """Get a device.
  12.200 +
  12.201 +        vif device index
  12.202 +
  12.203 +        returns device (or None)
  12.204 +        """
  12.205          return self.devices.get(vif)
  12.206  
  12.207      def addDevice(self, vif, vmac):
  12.208 +        """Add a network interface. If vmac is None a random MAC is
  12.209 +        assigned. If specified, vmac must be a string of the form
  12.210 +        XX:XX:XX:XX:XX where X is hex digit.
  12.211 +
  12.212 +        vif device index
  12.213 +        vmac device MAC 
  12.214 +
  12.215 +        returns device
  12.216 +        """
  12.217          if vmac is None:
  12.218              mac = self.randomMAC()
  12.219          else:
  12.220              mac = [ int(x, 16) for x in vmac.split(':') ]
  12.221          if len(mac) != 6: raise ValueError("invalid mac")
  12.222 -        #print "attach_device>", "vif=", vif, "mac=", mac
  12.223          dev = NetDev(self, vif, mac)
  12.224          self.devices[vif] = dev
  12.225          return dev
  12.226  
  12.227      def destroy(self):
  12.228 -        print 'NetifController>destroy>', 'dom=', self.dom
  12.229 +        """Destroy the controller and all devices.
  12.230 +        """
  12.231          self.destroyDevices()
  12.232          
  12.233      def destroyDevices(self):
  12.234 @@ -306,7 +336,6 @@ class NetifController(controller.Control
  12.235          self.factory.writeRequest(msg)
  12.236  
  12.237      def send_be_destroy(self, vif):
  12.238 -        print 'NetifController>send_be_destroy>', 'dom=', self.dom, 'vif=', vif
  12.239          PrettyPrint.prettyprint(self.sxpr())
  12.240          dev = self.devices[vif]
  12.241          del self.devices[vif]
    13.1 --- a/tools/python/xen/xm/create.py	Thu Jul 01 23:32:40 2004 +0000
    13.2 +++ b/tools/python/xen/xm/create.py	Fri Jul 02 08:30:28 2004 +0000
    13.3 @@ -1,4 +1,5 @@
    13.4  # Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    13.5 +
    13.6  """Domain creation.
    13.7  """
    13.8  import string
    13.9 @@ -15,12 +16,22 @@ from xen.xm.opts import *
   13.10  gopts = Opts(use="""[options]
   13.11  
   13.12  Create a domain.
   13.13 +
   13.14 +Domain creation parameters can be set by command-line switches, from
   13.15 +a python configuration script or an SXP config file. See documentation
   13.16 +for --defaults, --config. Configuration variables can be set using
   13.17 +VAR=VAL on the command line. For example vmid=3 sets vmid to 3.
   13.18 +
   13.19  """)
   13.20  
   13.21  gopts.opt('help', short='h',
   13.22           fn=set_true, default=0,
   13.23           use="Print this help.")
   13.24  
   13.25 +gopts.opt('help_config',
   13.26 +          fn=set_true, default=0,
   13.27 +          use="Print help for configuration file.")
   13.28 +
   13.29  gopts.opt('quiet', short='q',
   13.30           fn=set_true, default=0,
   13.31           use="Quiet.")
   13.32 @@ -31,24 +42,40 @@ gopts.opt('path', val='PATH',
   13.33  
   13.34  gopts.opt('defaults', short='f', val='FILE',
   13.35           fn=set_value, default='xmdefaults',
   13.36 -         use="Use the given default script.")
   13.37 +         use="""Use the given Python defaults script.
   13.38 +The defaults script is loaded after arguments have been processed.
   13.39 +Each command-line option sets a configuration variable named after
   13.40 +its long option name, and these variables are placed in the
   13.41 +environment of the script before it is loaded.
   13.42 +Variables for options that may be repeated have list values.
   13.43 +Other variables can be set using VAR=VAL on the command line.
   13.44 +
   13.45 +After the script is loaded, option values that were not set on the
   13.46 +command line are replaced by the values set in the script.
   13.47 +""")
   13.48  
   13.49  gopts.opt('config', short='F', val='FILE',
   13.50           fn=set_value, default=None,
   13.51 -         use='Domain configuration to use (SXP).')
   13.52 +         use="""Domain configuration to use (SXP).
   13.53 +SXP is the underlying configuration format used by Xen.
   13.54 +SXP configs can be hand-written or generated from Python defaults
   13.55 +scripts, using the -n (dryrun) option to print the config.
   13.56 +""")
   13.57  
   13.58  gopts.opt('load', short='L', val='FILE',
   13.59            fn=set_value, default=None,
   13.60            use='Domain saved state to load.')
   13.61  
   13.62 -gopts.opt('define', short='D', val='VAR=VAL',
   13.63 -         fn=set_var, default=None,
   13.64 -         use="""Set a variable before loading defaults, e.g. '-D vmid=3'
   13.65 -         to set vmid. May be repeated to set more thanone variable.""")
   13.66 +#gopts.opt('define', short='D', val='VAR=VAL',
   13.67 +#         fn=set_var, default=None,
   13.68 +#         use="""Set a variable before loading defaults, e.g. '-D vmid=3'
   13.69 +#         to set vmid. May be repeated to set more than one variable.""")
   13.70  
   13.71  gopts.opt('dryrun', short='n',
   13.72           fn=set_true, default=0,
   13.73 -         use="Dry run - print the config but don't create the domain.")
   13.74 +         use="""Dry run - print the config but don't create the domain.
   13.75 +The defaults file is loaded and the SXP configuration is created and printed.         
   13.76 +""")
   13.77  
   13.78  gopts.opt('name', short='N', val='NAME',
   13.79            fn=set_value, default=None,
   13.80 @@ -352,7 +379,15 @@ def main(argv):
   13.81      args = opts.parse(argv)
   13.82      if opts.vals.help:
   13.83          opts.usage()
   13.84 +    if opts.vals.help or opts.vals.help_config:
   13.85 +        opts.load_defaults(help=1)
   13.86 +    if opts.vals.help or opts.vals.help_config:
   13.87          return
   13.88 +    # Process remaining args as config variables.
   13.89 +    for arg in args:
   13.90 +        if '=' in arg:
   13.91 +            (var, val) = arg.strip().split('=')
   13.92 +            gopts.setvar(var.strip(), val.strip())
   13.93      if opts.vals.config:
   13.94          pass
   13.95      else:
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/tools/python/xen/xm/help.py	Fri Jul 02 08:30:28 2004 +0000
    14.3 @@ -0,0 +1,82 @@
    14.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    14.5 +
    14.6 +"""Variable definition and help support for Python defaults files.
    14.7 +"""
    14.8 +
    14.9 +import sys
   14.10 +
   14.11 +class Vars:
   14.12 +    """A set of configuration variables.
   14.13 +    """
   14.14 +
   14.15 +    def __init__(self, name, help, env):
   14.16 +        """Create a variable set.
   14.17 +
   14.18 +        name name of the defaults file
   14.19 +        help help flag
   14.20 +        env  local environment
   14.21 +        """
   14.22 +        self.name = name
   14.23 +        self.help = help
   14.24 +        self.env = env
   14.25 +        self.vars = []
   14.26 +
   14.27 +    def var(self, name, use=None, check=None):
   14.28 +        """Define a configuration variable.
   14.29 +        If provided, the check function will be called as check(var, val)
   14.30 +        where var is the variable name and val is its value (string).
   14.31 +        It should return a new value for the variable, or raise ValueError if
   14.32 +        the value is not acceptable.
   14.33 +
   14.34 +        name  variable name
   14.35 +        use   variable usage string
   14.36 +        check variable check function
   14.37 +        """
   14.38 +        self.vars.append(Var(name, use, check))
   14.39 +
   14.40 +    def check(self):
   14.41 +        """Execute the variable checks or print help, depending on the value
   14.42 +        of the help flag passed to the constructor.
   14.43 +        """
   14.44 +        if self.help:
   14.45 +            self.doHelp()
   14.46 +        else:
   14.47 +            for v in self.vars:
   14.48 +                v.doCheck(self.env)
   14.49 +
   14.50 +    def doHelp(self, out=sys.stderr):
   14.51 +        """Print help for the variables.
   14.52 +        """
   14.53 +        if self.vars:
   14.54 +            print >>out, "\nConfiguration variables for %s:\n" % self.name
   14.55 +            for v in self.vars:
   14.56 +                v.doHelp(out)
   14.57 +            print >>out
   14.58 +
   14.59 +class Var:
   14.60 +    """A single variable.
   14.61 +    """
   14.62 +
   14.63 +    def __init__(self, name, use, check):
   14.64 +        """Create a variable.
   14.65 +
   14.66 +        name  variable name
   14.67 +        use   variable use string
   14.68 +        check variable value check function
   14.69 +        """
   14.70 +        self.name = name
   14.71 +        self.use = use or ''
   14.72 +        self.check = check
   14.73 +
   14.74 +    def doCheck(self, env):
   14.75 +        """Execute the check and set the variable to the new value.
   14.76 +        """
   14.77 +        if not self.check: return
   14.78 +        env[self.name] = self.check(self.name, env.get(self.name))
   14.79 +
   14.80 +    def doHelp(self, out):
   14.81 +        """Print help for the variable.
   14.82 +        """
   14.83 +        print >>out, "%-12s" % self.name, self.use
   14.84 +
   14.85 +        
    15.1 --- a/tools/python/xen/xm/main.py	Thu Jul 01 23:32:40 2004 +0000
    15.2 +++ b/tools/python/xen/xm/main.py	Fri Jul 02 08:30:28 2004 +0000
    15.3 @@ -5,10 +5,12 @@ import os
    15.4  import os.path
    15.5  import sys
    15.6  from getopt import getopt
    15.7 +import socket
    15.8  
    15.9  from xen.xend import PrettyPrint
   15.10  from xen.xend import sxp
   15.11  from xen.xend.XendClient import server
   15.12 +from xen.xend.XendClient import main as xend_client_main
   15.13  from xen.xm import create, shutdown
   15.14  
   15.15  class Prog:
   15.16 @@ -65,6 +67,13 @@ class Xm:
   15.17          sys.exit(1)
   15.18  
   15.19      def main(self, args):
   15.20 +        try:
   15.21 +            self.main_call(args)
   15.22 +        except socket.error, ex:
   15.23 +            print >>sys.stderr, ex
   15.24 +            self.err("Error connecting to xend, is xend running?")
   15.25 +
   15.26 +    def main_call(self, args):
   15.27          """Main entry point. Dispatches to the progs.
   15.28          """
   15.29          self.name = args[0]
   15.30 @@ -444,5 +453,21 @@ class ProgConsole(Prog):
   15.31  
   15.32  xm.prog(ProgConsole)
   15.33  
   15.34 +class ProgCall(Prog):
   15.35 +    name = "call"
   15.36 +    info = "Call xend api functions."
   15.37 +
   15.38 +    def help (self, args):
   15.39 +        print "call fn argss..."
   15.40 +        print """
   15.41 +        Call a xend HTTP API function. The leading 'xend_' on the function
   15.42 +can be omitted. See xen.xend.XendClient for the API functions.
   15.43 +"""
   15.44 +
   15.45 +    def main(self, args):
   15.46 +        xend_client_main(args)
   15.47 +
   15.48 +xm.prog(ProgCall)
   15.49 +
   15.50  def main(args):
   15.51      xm.main(args)
    16.1 --- a/tools/python/xen/xm/opts.py	Thu Jul 01 23:32:40 2004 +0000
    16.2 +++ b/tools/python/xen/xm/opts.py	Fri Jul 02 08:30:28 2004 +0000
    16.3 @@ -259,7 +259,7 @@ class Opts:
    16.4          for opt in self.options:
    16.5              opt.show()
    16.6  
    16.7 -    def load_defaults(self):
    16.8 +    def load_defaults(self, help=0):
    16.9          """Load a defaults script. Assumes these options set:
   16.10          'path'    search path
   16.11          'default' script name
   16.12 @@ -270,12 +270,12 @@ class Opts:
   16.13              else:
   16.14                  p = self.vals.defaults
   16.15              if os.path.exists(p):
   16.16 -                self.load(p)
   16.17 +                self.load(p, help)
   16.18                  break
   16.19          else:
   16.20              self.err("Cannot open defaults file %s" % self.vals.defaults)
   16.21  
   16.22 -    def load(self, defaults, help=0):
   16.23 +    def load(self, defaults, help):
   16.24          """Load a defaults file. Local variables in the file
   16.25          are used to set options with the same names.
   16.26          Variables are not used to set options that are already specified.
   16.27 @@ -290,11 +290,17 @@ class Opts:
   16.28          cmd = '\n'.join(["import sys",
   16.29                           "import os",
   16.30                           "import os.path",
   16.31 -                         "import xen.util.ip",
   16.32 +                         "from xen.xm.help import Vars",
   16.33 +                         "from xen.util import ip",
   16.34                           "xm_file = '%s'" % defaults,
   16.35 -                         "xm_help = %d" % help ])
   16.36 +                         "xm_help = %d" % help,
   16.37 +                         "xm_vars = Vars(xm_file, xm_help, locals())",
   16.38 +                         ])
   16.39          exec cmd in globals, locals
   16.40 -        execfile(defaults, globals, locals)
   16.41 +        try:
   16.42 +            execfile(defaults, globals, locals)
   16.43 +        except:
   16.44 +            if not help: raise
   16.45          if help: return
   16.46          # Extract the values set by the script and set the corresponding
   16.47          # options, if not set on the command line.