ia64/xen-unstable

changeset 1978:4b46fe967cdd

bitkeeper revision 1.1108.35.2 (4108f181qIC17s1k7tUAzAMnlIZwBA)

Add support for getting the xend log.
Needed response headers and mime-types in the xend client code.
Add command groups in xm help.
author mjw@wray-m-3.hpl.hp.com
date Thu Jul 29 12:45:53 2004 +0000 (2004-07-29)
parents 696863c77c79
children 7fdc6f3e894c
files .rootkeys tools/python/xen/xend/XendClient.py tools/python/xen/xend/XendDmesg.py tools/python/xen/xend/XendLogging.py tools/python/xen/xend/server/SrvDmesg.py tools/python/xen/xend/server/SrvNode.py tools/python/xen/xend/server/SrvXendLog.py tools/python/xen/xm/main.py tools/python/xen/xm/shutdown.py
line diff
     1.1 --- a/.rootkeys	Thu Jul 29 11:33:04 2004 +0000
     1.2 +++ b/.rootkeys	Thu Jul 29 12:45:53 2004 +0000
     1.3 @@ -433,6 +433,7 @@ 40c9c4694eu5759Dehr4Uhakei0EMg tools/pyt
     1.4  40c9c469TaZ83ypsrktmPSHLEZiP5w tools/python/xen/xend/server/SrvRoot.py
     1.5  40c9c469W3sgDMbBJYQdz5wbQweL0Q tools/python/xen/xend/server/SrvServer.py
     1.6  40c9c469aq7oXrE1Ngqf3_lBqL0RoQ tools/python/xen/xend/server/SrvVnetDir.py
     1.7 +4108f181GtRoD1U9TBuJXMfBbGJwdQ tools/python/xen/xend/server/SrvXendLog.py
     1.8  40c9c469Y_aimoOFfUZoS-4eV8gEKg tools/python/xen/xend/server/__init__.py
     1.9  40c9c4692hckPol_EK0EGB16ZyDsyQ tools/python/xen/xend/server/blkif.py
    1.10  40c9c469N2-b3GqpLHHHPZykJPLVvA tools/python/xen/xend/server/channel.py
     2.1 --- a/tools/python/xen/xend/XendClient.py	Thu Jul 29 11:33:04 2004 +0000
     2.2 +++ b/tools/python/xen/xend/XendClient.py	Thu Jul 29 12:45:53 2004 +0000
     2.3 @@ -130,7 +130,6 @@ class XendRequest:
     2.4  class XendClientProtocol:
     2.5      """Abstract class for xend clients.
     2.6      """
     2.7 -
     2.8      def xendRequest(self, url, method, args=None):
     2.9          """Make a request to xend.
    2.10          Implement in a subclass.
    2.11 @@ -176,6 +175,9 @@ class XendClientProtocol:
    2.12          """Handle the data returned in response to the request.
    2.13          """
    2.14          if data is None: return None
    2.15 +        type = self.getHeader('Content-Type')
    2.16 +        if type != sxp.mime_type:
    2.17 +            return data
    2.18          try:
    2.19              pin = sxp.Parser()
    2.20              pin.input(data);
    2.21 @@ -194,11 +196,22 @@ class XendClientProtocol:
    2.22          """
    2.23          raise err
    2.24  
    2.25 +    def getHeader(self, key):
    2.26 +        """Get a header from the response.
    2.27 +        Case is ignored in the key.
    2.28 +
    2.29 +        @param key: header key
    2.30 +        @return: header
    2.31 +        """
    2.32 +        raise NotImplementedError()
    2.33 +
    2.34  class SynchXendClientProtocol(XendClientProtocol):
    2.35      """A synchronous xend client. This will make a request, wait for
    2.36      the reply and return the result.
    2.37      """
    2.38  
    2.39 +    resp = None
    2.40 +
    2.41      def xendRequest(self, url, method, args=None):
    2.42          """Make a request to xend.
    2.43  
    2.44 @@ -211,6 +224,7 @@ class SynchXendClientProtocol(XendClient
    2.45          if DEBUG: conn.set_debuglevel(1)
    2.46          conn.request(method, url.fullpath(), self.request.data, self.request.headers)
    2.47          resp = conn.getresponse()
    2.48 +        self.resp = resp
    2.49          val = self.handleStatus(resp.version, resp.status, resp.reason)
    2.50          if val is None:
    2.51              data = None
    2.52 @@ -220,6 +234,10 @@ class SynchXendClientProtocol(XendClient
    2.53          val = self.handleResponse(data)
    2.54          return val
    2.55  
    2.56 +    def getHeader(self, key):
    2.57 +        return self.resp.getheader(key)
    2.58 +
    2.59 +
    2.60  class AsynchXendClient(http.HTTPClient):
    2.61      """A subclass of twisted's HTTPClient to deal with a connection to xend.
    2.62      Makes the request when connected, and delegates handling responses etc.
    2.63 @@ -245,6 +263,9 @@ class AsynchXendClient(http.HTTPClient):
    2.64      def handleStatus(self, version, status, message):
    2.65          return self.protocol.handleStatus(version, status, message)
    2.66  
    2.67 +    def handleHeader(self, key, val):
    2.68 +        return self.protocol.handleHeader(key, val)
    2.69 +
    2.70      def handleResponse(self, data):
    2.71          return self.protocol.handleResponse(data)
    2.72  
    2.73 @@ -257,47 +278,7 @@ class AsynchXendClientProtocol(XendClien
    2.74      """
    2.75      def __init__(self):
    2.76          self.err = None
    2.77 -
    2.78 -    def xendRequest(self, url, method, args=None):
    2.79 -        """Make a request to xend. The returned deferred is called when
    2.80 -        the result is available.
    2.81 -
    2.82 -        @param url:    xend request url
    2.83 -        @param method: http method: POST or GET
    2.84 -        @param args:   request arguments (dict)
    2.85 -        @return: deferred
    2.86 -        """
    2.87 -        request = XendRequest(url, method, args)
    2.88 -        self.deferred = Deferred()
    2.89 -        clientCreator = ClientCreator(reactor, AsynchXendClient, self, request)
    2.90 -        clientCreator.connectTCP(url.host, url.port)
    2.91 -        return self.deferred
    2.92 -
    2.93 -    def callErrback(self, err):
    2.94 -        if not self.deferred.called:
    2.95 -            self.err = err
    2.96 -            self.deferred.errback(err)
    2.97 -        return err
    2.98 -
    2.99 -    def callCallback(self, val):
   2.100 -        if not self.deferred.called:
   2.101 -            self.deferred.callback(val)
   2.102 -        return val
   2.103 -
   2.104 -    def handleException(self, err):
   2.105 -        return self.callErrback(err)
   2.106 -
   2.107 -    def handleResponse(self, data):
   2.108 -        if self.err: return self.err
   2.109 -        val = XendClientProtocol.handleResponse(self, data)
   2.110 -        if isinstance(val, Exception):
   2.111 -            self.callErrback(val)
   2.112 -        else:
   2.113 -            self.callCallback(val)
   2.114 -        return val
   2.115 -
   2.116 -    def __init__(self):
   2.117 -        self.err = None
   2.118 +        self.headers = {}
   2.119  
   2.120      def xendRequest(self, url, method, args=None):
   2.121          """Make a request to xend. The returned deferred is called when
   2.122 @@ -328,6 +309,12 @@ class AsynchXendClientProtocol(XendClien
   2.123      def handleException(self, err):
   2.124          return self.callErrback(err)
   2.125  
   2.126 +    def handleHeader(self, key, val):
   2.127 +        self.headers[key.lower()] = val
   2.128 +
   2.129 +    def getHeader(self, key):
   2.130 +        return self.headers.get(key.lower())
   2.131 +
   2.132      def handleResponse(self, data):
   2.133          if self.err: return self.err
   2.134          val = XendClientProtocol.handleResponse(self, data)
   2.135 @@ -397,9 +384,6 @@ class Xend:
   2.136      def eventurl(self, id=''):
   2.137          return self.url.relative('event/' + str(id))
   2.138  
   2.139 -    def dmesgurl(self, id=''):
   2.140 -        return self.url.relative('node/dmesg/' + str(id))
   2.141 -
   2.142      def xend(self):
   2.143          return self.xendGet(self.url)
   2.144  
   2.145 @@ -408,14 +392,17 @@ class Xend:
   2.146          
   2.147      def xend_node_shutdown(self):
   2.148          return self.xendPost(self.nodeurl(),
   2.149 -                {'op'      : 'shutdown'})
   2.150 +                             {'op'      : 'shutdown'})
   2.151                  
   2.152      def xend_node_restart(self):
   2.153          return self.xendPost(self.nodeurl(),
   2.154 -                {'op'      : 'reboot'})
   2.155 +                             {'op'      : 'reboot'})
   2.156  
   2.157      def xend_node_dmesg(self):
   2.158 -        return self.xendGet(self.dmesgurl())
   2.159 +        return self.xendGet(self.nodeurl('dmesg'))
   2.160 +
   2.161 +    def xend_node_log(self):
   2.162 +        return self.xendGet(self.nodeurl('log'))
   2.163  
   2.164      def xend_node_cpu_rrobin_slice_set(self, slice):
   2.165          return self.xendPost(self.nodeurl(),
     3.1 --- a/tools/python/xen/xend/XendDmesg.py	Thu Jul 29 11:33:04 2004 +0000
     3.2 +++ b/tools/python/xen/xend/XendDmesg.py	Thu Jul 29 12:45:53 2004 +0000
     3.3 @@ -1,4 +1,4 @@
     3.4 -# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
     3.5 + # Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
     3.6  
     3.7  """Get dmesg output for this node.
     3.8  """
     3.9 @@ -11,7 +11,7 @@ class XendDmesg:
    3.10          self.xc = xen.lowlevel.xc.new()
    3.11  
    3.12      def info(self):
    3.13 -        return [ self.xc.readconsolering() ]
    3.14 +        return self.xc.readconsolering()
    3.15          
    3.16  
    3.17  def instance():
     4.1 --- a/tools/python/xen/xend/XendLogging.py	Thu Jul 29 11:33:04 2004 +0000
     4.2 +++ b/tools/python/xen/xend/XendLogging.py	Thu Jul 29 12:45:53 2004 +0000
     4.3 @@ -44,6 +44,7 @@ class XendLogging:
     4.4                                             mode='a',
     4.5                                             maxBytes=self.maxBytes,
     4.6                                             backupCount=self.backupCount)
     4.7 +        self.logfilename = filename
     4.8          self.logfile.setFormatter(Formatter(self.logFileFormat, self.dateFormat))
     4.9          log = self.getLogger()
    4.10          log.addHandler(self.logfile)
    4.11 @@ -51,6 +52,9 @@ class XendLogging:
    4.12      def getLogFile(self):
    4.13          return self.logfile
    4.14  
    4.15 +    def getLogFilename(self):
    4.16 +        return self.logfilename
    4.17 +
    4.18      def initLogStderr(self):
    4.19          self.logstderr = StreamHandler()
    4.20          self.logstderr.setFormatter(Formatter(self.logStderrFormat, self.dateFormat))
     5.1 --- a/tools/python/xen/xend/server/SrvDmesg.py	Thu Jul 29 11:33:04 2004 +0000
     5.2 +++ b/tools/python/xen/xend/server/SrvDmesg.py	Thu Jul 29 12:45:53 2004 +0000
     5.3 @@ -1,10 +1,12 @@
     5.4  # Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
     5.5  
     5.6  import os
     5.7 -from SrvDir import SrvDir
     5.8 +
     5.9  from xen.xend import sxp
    5.10  from xen.xend import XendDmesg
    5.11  
    5.12 +from SrvDir import SrvDir
    5.13 +
    5.14  class SrvDmesg(SrvDir):
    5.15      """Xen Dmesg output.
    5.16      """
    5.17 @@ -16,13 +18,13 @@ class SrvDmesg(SrvDir):
    5.18      def render_GET(self, req):
    5.19          try:
    5.20              if self.use_sxp(req):
    5.21 -                req.setHeader("Content-Type", sxp.mime_type)
    5.22 -                sxp.show(['dmesg'] + self.info(), out=req)
    5.23 +                req.setHeader("Content-Type", "text/plain")
    5.24 +                req.write(self.info())
    5.25              else:
    5.26                  req.write('<html><head></head><body>')
    5.27 +                self.print_path(req)
    5.28                  req.write('<pre>')
    5.29 -                self.print_path(req)
    5.30 -                req.write(self.info()[0])
    5.31 +                req.write(self.info())
    5.32                  req.write('</pre></body></html>')
    5.33              return ''
    5.34          except Exception, ex:
     6.1 --- a/tools/python/xen/xend/server/SrvNode.py	Thu Jul 29 11:33:04 2004 +0000
     6.2 +++ b/tools/python/xen/xend/server/SrvNode.py	Thu Jul 29 12:45:53 2004 +0000
     6.3 @@ -1,6 +1,7 @@
     6.4  # Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
     6.5  
     6.6  import os
     6.7 +
     6.8  from SrvDir import SrvDir
     6.9  from xen.xend import sxp
    6.10  from xen.xend import XendNode
    6.11 @@ -14,6 +15,7 @@ class SrvNode(SrvDir):
    6.12          SrvDir.__init__(self)
    6.13          self.xn = XendNode.instance()
    6.14          self.add('dmesg', 'SrvDmesg')
    6.15 +        self.add('log', 'SrvXendLog')
    6.16  
    6.17      def op_shutdown(self, op, req):
    6.18          val = self.xn.shutdown()
    6.19 @@ -58,7 +60,8 @@ class SrvNode(SrvDir):
    6.20                  req.write('<ul>')
    6.21                  for d in self.info():
    6.22                      req.write('<li> %10s: %s' % (d[0], str(d[1])))
    6.23 -                req.write('<li><a href="' + url + 'dmesg">Xen dmesg output</a>')
    6.24 +                req.write('<li><a href="%sdmesg">Xen dmesg output</a>' % url)
    6.25 +                req.write('<li><a href="%slog>Xend log</a>' % url)
    6.26                  req.write('</ul>')
    6.27                  req.write('</body></html>')
    6.28              return ''
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/tools/python/xen/xend/server/SrvXendLog.py	Thu Jul 29 12:45:53 2004 +0000
     7.3 @@ -0,0 +1,24 @@
     7.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
     7.5 +
     7.6 +from twisted.web import static
     7.7 +
     7.8 +from xen.xend import XendRoot
     7.9 +
    7.10 +from SrvDir import SrvDir
    7.11 +
    7.12 +class SrvXendLog(SrvDir):
    7.13 +    """Xend log.
    7.14 +    """
    7.15 +
    7.16 +    def __init__(self):
    7.17 +        SrvDir.__init__(self)
    7.18 +        logging = XendRoot.instance().get_logging()
    7.19 +        self.logfile = static.File(logging.getLogFilename(), defaultType="text/plain")
    7.20 +        self.logfile.type = "text/plain"
    7.21 +        self.logfile.encoding = None
    7.22 +
    7.23 +    def render_GET(self, req):
    7.24 +        try:
    7.25 +            return self.logfile.render(req)
    7.26 +        except Exception, ex:
    7.27 +            self._perform_err(ex, req)
     8.1 --- a/tools/python/xen/xm/main.py	Thu Jul 29 11:33:04 2004 +0000
     8.2 +++ b/tools/python/xen/xm/main.py	Thu Jul 29 12:45:53 2004 +0000
     8.3 @@ -13,6 +13,39 @@ from xen.xend.XendClient import XendErro
     8.4  from xen.xend.XendClient import main as xend_client_main
     8.5  from xen.xm import create, destroy, shutdown
     8.6  
     8.7 +class Group:
     8.8 +
     8.9 +    name = ""
    8.10 +    info = ""
    8.11 +    
    8.12 +    def __init__(self, xm):
    8.13 +        self.xm = xm
    8.14 +        self.progs = {}
    8.15 +
    8.16 +    def addprog(self, prog):
    8.17 +        self.progs[prog.name] = prog
    8.18 +
    8.19 +    def getprog(self, name):
    8.20 +        return self.progs.get(name)
    8.21 +
    8.22 +    def proglist(self):
    8.23 +        kl = self.progs.keys()
    8.24 +        kl.sort()
    8.25 +        return [ self.getprog(k) for k in kl ]
    8.26 +
    8.27 +    def help(self, args):
    8.28 +        if self.info:
    8.29 +            print 
    8.30 +            print self.info
    8.31 +            print
    8.32 +        else:
    8.33 +            print
    8.34 +        
    8.35 +    def shortHelp(self, args):
    8.36 +        self.help(args)
    8.37 +        for p in self.proglist():
    8.38 +            p.shortHelp(args)
    8.39 +
    8.40  class Prog:
    8.41      """Base class for sub-programs.
    8.42      """
    8.43 @@ -61,6 +94,7 @@ class Xm:
    8.44          self.name = 'xm'
    8.45          self.unknown = ProgUnknown(self)
    8.46          self.progs = {}
    8.47 +        self.groups = {}
    8.48  
    8.49      def err(self, msg):
    8.50          print >>sys.stderr, "Error:", msg
    8.51 @@ -101,6 +135,7 @@ class Xm:
    8.52          """
    8.53          p = pklass(self)
    8.54          self.progs[p.name] = p
    8.55 +        self.getgroup(p.group).addprog(p)
    8.56          return p
    8.57  
    8.58      def getprog(self, name, val=None):
    8.59 @@ -123,26 +158,57 @@ class Xm:
    8.60  
    8.61          return self.progs.get(match, val)
    8.62  
    8.63 -    def proglist(self):
    8.64 -        """Get a list of sub-programs, ordered by group.
    8.65 -        """
    8.66 -        groups = {}
    8.67 -        for p in self.progs.values():
    8.68 -            l = groups.get(p.group, [])
    8.69 -            l.append(p)
    8.70 -            groups[p.group] = l
    8.71 -        kl = groups.keys()
    8.72 +    def group(self, klass):
    8.73 +        g = klass(self)
    8.74 +        self.groups[g.name] = g
    8.75 +        return g
    8.76 +
    8.77 +    def getgroup(self, name):
    8.78 +        return self.groups[name]
    8.79 +
    8.80 +    def grouplist(self):
    8.81 +        kl = self.groups.keys()
    8.82          kl.sort()
    8.83 -        pl = []
    8.84 -        for k in kl:
    8.85 -            l = groups[k]
    8.86 -            l.sort()
    8.87 -            pl += l
    8.88 -        return pl
    8.89 +        return [ self.getgroup(k) for k in kl ]
    8.90          
    8.91  # Create the application object, then add the sub-program classes.
    8.92  xm = Xm()
    8.93  
    8.94 +class GroupAll(Group):
    8.95 +
    8.96 +    name = "all"
    8.97 +    info = ""
    8.98 +
    8.99 +xm.group(GroupAll)
   8.100 +
   8.101 +class GroupDomain(Group):
   8.102 +
   8.103 +    name = "domain"
   8.104 +    info = "Commands on domains:"
   8.105 +    
   8.106 +xm.group(GroupDomain)
   8.107 +
   8.108 +class GroupScheduler(Group):
   8.109 +
   8.110 +    name = "scheduler"
   8.111 +    info = "Comands controlling scheduling:"
   8.112 +
   8.113 +xm.group(GroupScheduler)
   8.114 +
   8.115 +class GroupHost(Group):
   8.116 +
   8.117 +    name = "host"
   8.118 +    info = "Commands related to the xen host (node):"
   8.119 +
   8.120 +xm.group(GroupHost)
   8.121 +
   8.122 +class GroupConsole(Group):
   8.123 +
   8.124 +    name = "console"
   8.125 +    info = "Commands related to consoles:"
   8.126 +
   8.127 +xm.group(GroupConsole)
   8.128 +
   8.129  class ProgHelp(Prog):
   8.130  
   8.131      name = "help"
   8.132 @@ -157,8 +223,8 @@ class ProgHelp(Prog):
   8.133              else:
   8.134                  print '%s: Unknown command: %s' % (self.name, name)
   8.135          else:
   8.136 -            for p in self.xm.proglist():
   8.137 -                p.shortHelp(args)
   8.138 +            for g in self.xm.grouplist():
   8.139 +                g.shortHelp(args)
   8.140              print "\nTry '%s help CMD' for help on CMD" % self.xm.name
   8.141  
   8.142      main = help
   8.143 @@ -220,7 +286,7 @@ xm.prog(ProgRestore)
   8.144  class ProgList(Prog):
   8.145      group = 'domain'
   8.146      name = "list"
   8.147 -    info = """List info about domains."""
   8.148 +    info = """List information about domains."""
   8.149  
   8.150      short_options = 'l'
   8.151      long_options = ['long']
   8.152 @@ -512,7 +578,7 @@ class ProgConsole(Prog):
   8.153      info = """Open a console to a domain."""
   8.154      
   8.155      def help(self, args):
   8.156 -        print "console DOM"
   8.157 +        print args[0], "DOM"
   8.158          print "\nOpen a console to domain DOM."
   8.159  
   8.160      def main(self, args):
   8.161 @@ -533,7 +599,7 @@ class ProgCall(Prog):
   8.162      info = "Call xend api functions."
   8.163  
   8.164      def help (self, args):
   8.165 -        print "call fn argss..."
   8.166 +        print args[0], "function args..."
   8.167          print """
   8.168          Call a xend HTTP API function. The leading 'xend_' on the function
   8.169  can be omitted. See xen.xend.XendClient for the API functions.
   8.170 @@ -550,9 +616,19 @@ class ProgDmesg(Prog):
   8.171      info  = """Print Xen boot output."""
   8.172  
   8.173      def main(self, args):
   8.174 -        print server.xend_node_dmesg()[1]
   8.175 +        print server.xend_node_dmesg()
   8.176  
   8.177  xm.prog(ProgDmesg)
   8.178  
   8.179 +class ProgLog(Prog):
   8.180 +    group = 'host'
   8.181 +    name  =  "log"
   8.182 +    info  = """Print the xend log."""
   8.183 +
   8.184 +    def main(self, args):
   8.185 +        print server.xend_node_log()
   8.186 +
   8.187 +xm.prog(ProgLog)
   8.188 +
   8.189  def main(args):
   8.190      xm.main(args)
     9.1 --- a/tools/python/xen/xm/shutdown.py	Thu Jul 29 11:33:04 2004 +0000
     9.2 +++ b/tools/python/xen/xm/shutdown.py	Thu Jul 29 12:45:53 2004 +0000
     9.3 @@ -9,7 +9,8 @@ import time
     9.4  from xen.xend.XendClient import server
     9.5  from xen.xm.opts import *
     9.6  
     9.7 -DOM0 = 'Domain-0'
     9.8 +DOM0_NAME = 'Domain-0'
     9.9 +DOM0_ID = '0'
    9.10  
    9.11  gopts = Opts(use="""[options] [DOM]
    9.12  
    9.13 @@ -38,8 +39,9 @@ gopts.opt('reboot', short='R',
    9.14  
    9.15  def shutdown(opts, doms, mode, wait):
    9.16      if doms == None: doms = server.xend_domains()
    9.17 -    if DOM0 in doms:
    9.18 -        doms.remove(DOM0)
    9.19 +    for x in [DOM0_NAME, DOM0_ID]:
    9.20 +        if x in doms:
    9.21 +            doms.remove(x)
    9.22      for d in doms:
    9.23          server.xend_domain_shutdown(d, mode)
    9.24      if wait: