ia64/xen-unstable

changeset 1945:7197ab066b67

bitkeeper revision 1.1108.29.1 (4107987b3YS7DchKHz1bWQKqXsXTsg)

Added xensv command: xensv start / stop -
checks for twisted and for xend
More work on wizzard, now persits values and can move back / forth
author tw275@labyrinth.cl.cam.ac.uk
date Wed Jul 28 12:13:47 2004 +0000 (2004-07-28)
parents 9711b428cf6a
children 698b17696712
files .rootkeys BitKeeper/etc/ignore tools/misc/Makefile tools/misc/xensv tools/python/xen/sv/CreateDomain.py tools/python/xen/sv/Daemon.py tools/python/xen/sv/HTMLBase.py tools/python/xen/sv/Wizzard.py tools/python/xen/sv/params.py tools/python/xen/sv/util.py
line diff
     1.1 --- a/.rootkeys	Tue Jul 27 15:04:59 2004 +0000
     1.2 +++ b/.rootkeys	Wed Jul 28 12:13:47 2004 +0000
     1.3 @@ -310,6 +310,7 @@ 3f5ef5a2dTZP0nnsFoeq2jRf3mWDDg tools/mis
     1.4  3f870808zS6T6iFhqYPGelroZlVfGQ tools/misc/xen_cpuperf.c
     1.5  405eedf6_nnNhFQ1I85lhCkLK6jFGA tools/misc/xencons
     1.6  40c9c4697z76HDfkCLdMhmaEwzFoNQ tools/misc/xend
     1.7 +4107986eMWVdBoz4tXYoOscpN_BCYg tools/misc/xensv
     1.8  4056f5155QYZdsk-1fLdjsZPFTnlhg tools/misc/xensymoops.py
     1.9  40cf2937dqM1jWW87O5OoOYND8leuA tools/misc/xm
    1.10  40c9c468icGyC5RAF1bRKsCXPDCvsA tools/python/Makefile
    1.11 @@ -372,6 +373,7 @@ 40dc4076St6AmPTmQPrtQ6LGHPxGmw tools/pyt
    1.12  40dc4076pVeE1kEEWzcUaNZin65kCA tools/python/xen/lowlevel/xu/domain_controller.h
    1.13  40dc4076CwBYRTUQDdbdU1L6KcLgSw tools/python/xen/lowlevel/xu/xu.c
    1.14  41052eb84_irpx0E9N_kqBp9eoin5g tools/python/xen/sv/CreateDomain.py
    1.15 +4107986egkTAMIHW7n-i4ShvCGWpLQ tools/python/xen/sv/Daemon.py
    1.16  40fcefb2qm13BbRZBydAatOavaS0fQ tools/python/xen/sv/DomInfo.py
    1.17  40fcefb2-RIU8GB67mJMRzybME9bxw tools/python/xen/sv/DomList.py
    1.18  40fcefb23FfQn-ZBCbcHqA0cPGqQxw tools/python/xen/sv/GenTabbed.py
    1.19 @@ -381,6 +383,7 @@ 40fcefb24h-04WaHag-Tg4nxWPhTig tools/pyt
    1.20  40fcefb2Sif__6AqrANeBQZZfvP-6w tools/python/xen/sv/TabView.py
    1.21  41052eb8UrgtUkuJPg7oY1tutVQHsg tools/python/xen/sv/Wizzard.py
    1.22  40fcefb2DqteqCCZYDCvvh4Q5jBd0w tools/python/xen/sv/__init__.py
    1.23 +4107986e6qN1IdvIDdId0AYFmDMkiQ tools/python/xen/sv/params.py
    1.24  40fcefb4rnaZNjqsBu7A5V2rlLyqRw tools/python/xen/sv/util.py
    1.25  40d8915cyoVA0hJxiBFNymL7YvDaRg tools/python/xen/util/Brctl.py
    1.26  40dfd40aGqGkiopOOgJxSF4iCbHM0Q tools/python/xen/util/__init__.py
     2.1 --- a/BitKeeper/etc/ignore	Tue Jul 27 15:04:59 2004 +0000
     2.2 +++ b/BitKeeper/etc/ignore	Wed Jul 28 12:13:47 2004 +0000
     2.3 @@ -35,3 +35,14 @@ xen/xen.*
     2.4  tools/xfrd/xfrd
     2.5  xen/tools/elf-reloc
     2.6  xen/tools/figlet/figlet
     2.7 +docs/interface.aux
     2.8 +docs/interface.log
     2.9 +docs/interface.pdf
    2.10 +docs/interface.ps
    2.11 +docs/interface.toc
    2.12 +docs/user.aux
    2.13 +docs/user.log
    2.14 +docs/user.pdf
    2.15 +docs/user.ps
    2.16 +docs/user.toc
    2.17 +tools/web-shutdown.tap
     3.1 --- a/tools/misc/Makefile	Tue Jul 27 15:04:59 2004 +0000
     3.2 +++ b/tools/misc/Makefile	Wed Jul 28 12:13:47 2004 +0000
     3.3 @@ -21,7 +21,7 @@ OBJS     = $(patsubst %.c,%.o,$(SRCS))
     3.4  TARGETS  = xen_cpuperf
     3.5  
     3.6  INSTALL_BIN  = $(TARGETS) xencons
     3.7 -INSTALL_SBIN = netfix xm xend
     3.8 +INSTALL_SBIN = netfix xm xend xensv
     3.9  
    3.10  all: $(TARGETS)
    3.11  	$(MAKE) -C miniterm
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/tools/misc/xensv	Wed Jul 28 12:13:47 2004 +0000
     4.3 @@ -0,0 +1,134 @@
     4.4 +#!/usr/bin/env python
     4.5 +#  -*- mode: python; -*-
     4.6 +#============================================================================
     4.7 +# Copyright (C) 2004 Tom Wilkie <tw275@cl.cam.ac.uk>
     4.8 +# Copyright (C) 2004 Mike Wray  <mike.wray@hp.com>
     4.9 +#============================================================================
    4.10 +
    4.11 +"""SV web interface Lives in /usr/sbin.
    4.12 +   Provides pretty HTML management interface.
    4.13 +
    4.14 +   Run:
    4.15 +
    4.16 +   sv start
    4.17 +
    4.18 +   The daemon is stopped with:
    4.19 +
    4.20 +   sv stop
    4.21 +   
    4.22 +   The daemon will be accessible from http://localhost:8080/
    4.23 +"""
    4.24 +import os
    4.25 +import sys
    4.26 +import re
    4.27 +
    4.28 +from xen.xend.server.params import PID_FILE as XEND_PID_FILE
    4.29 +
    4.30 +class CheckError(ValueError):
    4.31 +    pass
    4.32 +
    4.33 +def hline():
    4.34 +    print >>sys.stderr, "*" * 70
    4.35 +
    4.36 +def msg(message):
    4.37 +    print >>sys.stderr, "*" * 3, message
    4.38 +
    4.39 +def check_logging():
    4.40 +    """Check python logging is installed and raise an error if not.
    4.41 +    Logging is standard from Python 2.3 on.
    4.42 +    """
    4.43 +    try:
    4.44 +        import logging
    4.45 +    except ImportError:
    4.46 +        hline()
    4.47 +        msg("Python logging is not installed.")
    4.48 +        msg("Use 'make install-logging' at the xen root to install.")
    4.49 +        msg("")
    4.50 +        msg("Alternatively download and install from")
    4.51 +        msg("http://www.red-dove.com/python_logging.html")
    4.52 +        hline()
    4.53 +        raise CheckError("logging is not installed")
    4.54 +
    4.55 +def check_twisted_version():
    4.56 +    """Check twisted is installed with a supported version and print a warning if not.
    4.57 +    Raises an error if twisted is not installed.
    4.58 +    """
    4.59 +    # Supported twisted release and major version.
    4.60 +    RELEASE = 1
    4.61 +    MAJOR   = 3
    4.62 +    try:
    4.63 +        from twisted.copyright import version
    4.64 +    except ImportError:
    4.65 +        hline()
    4.66 +        msg("The Twisted framework is not installed.")
    4.67 +        msg("Use 'make install-twisted' at the xen root to install.")
    4.68 +        msg("")
    4.69 +        msg("Alternatively download and install version %d.%d or higher" % (RELEASE, MAJOR))
    4.70 +        msg("from http://www.twistedmatrix.com/products")
    4.71 +        hline()
    4.72 +        raise CheckError("twisted is not installed")
    4.73 +        
    4.74 +    
    4.75 +    (release, major, minor) = version.split('.')
    4.76 +    release = int(release)
    4.77 +    major = int(major)
    4.78 +    if release > RELEASE: return
    4.79 +    if release == RELEASE and major >= MAJOR: return
    4.80 +    hline()
    4.81 +    msg("Warning: Twisted version not supported: %s" % version)
    4.82 +    msg("Use Twisted version %d.%d.0 or higher" % (RELEASE, MAJOR))
    4.83 +    hline()
    4.84 +    
    4.85 +def check_xend():
    4.86 +    """Check xend is running
    4.87 +    """
    4.88 +    
    4.89 +    if not os.path.isfile(XEND_PID_FILE) or not os.path.getsize(XEND_PID_FILE):
    4.90 +    	hline()
    4.91 +        msg( "Warning: Xend has not been detected as running." )
    4.92 +        msg( "Please start it immediately with: xend start " )
    4.93 +        hline()
    4.94 +        return 0
    4.95 +        
    4.96 +    # Read the pid of the previous invocation and search active process list.
    4.97 +    pid = open(XEND_PID_FILE, 'r').read()
    4.98 +    lines = os.popen('ps ' + pid + ' 2>/dev/null').readlines()
    4.99 +    for line in lines:
   4.100 +        if re.search('^ *' + pid + '.+xend', line):
   4.101 +            return 1
   4.102 +
   4.103 +    hline()
   4.104 +    msg( "Warning: Xend has not been detected as running." )
   4.105 +    msg( "Please start it immediately with: xend start " )
   4.106 +    hline() 
   4.107 +    return 0
   4.108 +    
   4.109 +def main():
   4.110 +    try:
   4.111 +        check_logging()
   4.112 +        check_twisted_version()
   4.113 +        check_xend()
   4.114 +    except CheckError:
   4.115 +        sys.exit(1)
   4.116 +    
   4.117 +    from xen.sv import Daemon
   4.118 +
   4.119 +    daemon = Daemon.instance()
   4.120 +    
   4.121 +    if not sys.argv[1:]:
   4.122 +        print 'usage: %s {start|stop|restart}' % sys.argv[0]
   4.123 +    elif os.fork():
   4.124 +        pid, status = os.wait()
   4.125 +        return status >> 8
   4.126 +    elif sys.argv[1] == 'start':
   4.127 +        return daemon.start()
   4.128 +    elif sys.argv[1] == 'stop':
   4.129 +        return daemon.stop()
   4.130 +    elif sys.argv[1] == 'restart':
   4.131 +        return daemon.stop() or daemon.start()
   4.132 +    else:
   4.133 +        print 'not an option:', sys.argv[1]
   4.134 +    return 1
   4.135 +
   4.136 +if __name__ == '__main__':
   4.137 +    sys.exit(main())
     5.1 --- a/tools/python/xen/sv/CreateDomain.py	Tue Jul 27 15:04:59 2004 +0000
     5.2 +++ b/tools/python/xen/sv/CreateDomain.py	Wed Jul 28 12:13:47 2004 +0000
     5.3 @@ -14,30 +14,33 @@ class CreatePage0( Sheet ):
     5.4  
     5.5      def __init__( self, urlWriter ):
     5.6      
     5.7 -    	feilds = [( 'name', 'Name')]
     5.8 +    	feilds = [( 'name', 'VM Name:'),
     5.9 +                  ( 'memory', 'RAM (Mb):' )]
    5.10      
    5.11 -        Sheet.__init__( self, urlWriter, feilds, "Create New Domain - 1" )
    5.12 +        Sheet.__init__( self, urlWriter, feilds, "Create New Domain", 0 )
    5.13                  
    5.14  class CreatePage1( Sheet ):
    5.15  
    5.16      def __init__( self, urlWriter ):
    5.17      
    5.18 -    	feilds = [( 'name', 'Name')]
    5.19 +    	feilds = [( 'kernel_type', 'Kernel Type:'),
    5.20 +                  ( 'kernel_location', 'Kernel location:')]
    5.21          
    5.22 -        Sheet.__init__( self, urlWriter, feilds, "Create New Domain - 2" )
    5.23 +        Sheet.__init__( self, urlWriter, feilds, "Setup Kernel Image", 1 )
    5.24          
    5.25  class CreatePage2( Sheet ):
    5.26  
    5.27      def __init__( self, urlWriter ):
    5.28      
    5.29 -    	feilds = [( 'name', 'Name')]    
    5.30 +    	feilds = [( 'vbd_dom0', 'Location of vbd:'),
    5.31 +        	  ( 'vbd_dom0', 'Vitualised location:')]    
    5.32     
    5.33 -        Sheet.__init__( self, urlWriter, feilds, "Create New Domain - 3" )
    5.34 +        Sheet.__init__( self, urlWriter, feilds, "Setup Virtual Block Devices", 2 )
    5.35                  
    5.36  class CreatePage3( Sheet ):
    5.37  
    5.38      def __init__( self, urlWriter ):
    5.39      
    5.40 -    	feilds = [( 'name', 'Name')]
    5.41 +    	feilds = [( 'vifs', 'Number of Vifs:')]
    5.42          
    5.43 -        Sheet.__init__( self, urlWriter, feilds, "Create New Domain - 4" )       
    5.44 \ No newline at end of file
    5.45 +        Sheet.__init__( self, urlWriter, feilds, "Create New Domain - 4", 3 )       
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/tools/python/xen/sv/Daemon.py	Wed Jul 28 12:13:47 2004 +0000
     6.3 @@ -0,0 +1,108 @@
     6.4 +###########################################################
     6.5 +## XenSV Web Control Interface Daemon
     6.6 +## Copyright (C) 2004, K A Fraser (University of Cambridge)
     6.7 +## Copyright (C) 2004, Mike Wray <mike.wray@hp.com>
     6.8 +## Copyright (C) 2004, Tom Wilkie <tw275@cam.ac.uk>
     6.9 +###########################################################
    6.10 +
    6.11 +import os
    6.12 +import os.path
    6.13 +import sys
    6.14 +import re
    6.15 +
    6.16 +from xen.sv.params import *
    6.17 +
    6.18 +from twisted.internet import reactor
    6.19 +from twisted.web import static, server, script
    6.20 +
    6.21 +class Daemon:
    6.22 +    """The xend daemon.
    6.23 +    """
    6.24 +    def __init__(self):
    6.25 +        self.shutdown = 0
    6.26 +        self.traceon = 0
    6.27 +
    6.28 +    def daemon_pids(self):
    6.29 +        pids = []
    6.30 +        pidex = '(?P<pid>\d+)'
    6.31 +        pythonex = '(?P<python>\S*python\S*)'
    6.32 +        cmdex = '(?P<cmd>.*)'
    6.33 +        procre = re.compile('^\s*' + pidex + '\s*' + pythonex + '\s*' + cmdex + '$')
    6.34 +        xendre = re.compile('^/usr/sbin/xend\s*(start|restart)\s*.*$')
    6.35 +        procs = os.popen('ps -e -o pid,args 2>/dev/null')
    6.36 +        for proc in procs:
    6.37 +            pm = procre.match(proc)
    6.38 +            if not pm: continue
    6.39 +            xm = xendre.match(pm.group('cmd'))
    6.40 +            if not xm: continue
    6.41 +            #print 'pid=', pm.group('pid'), 'cmd=', pm.group('cmd')
    6.42 +            pids.append(int(pm.group('pid')))
    6.43 +        return pids
    6.44 +
    6.45 +    def new_cleanup(self, kill=0):
    6.46 +        err = 0
    6.47 +        pids = self.daemon_pids()
    6.48 +        if kill:
    6.49 +            for pid in pids:
    6.50 +                print "Killing daemon pid=%d" % pid
    6.51 +                os.kill(pid, signal.SIGHUP)
    6.52 +        elif pids:
    6.53 +            err = 1
    6.54 +            print "Daemon already running: ", pids
    6.55 +        return err
    6.56 +            
    6.57 +    def cleanup(self, kill=False):
    6.58 +        # No cleanup to do if PID_FILE is empty.
    6.59 +        if not os.path.isfile(PID_FILE) or not os.path.getsize(PID_FILE):
    6.60 +            return 0
    6.61 +        # Read the pid of the previous invocation and search active process list.
    6.62 +        pid = open(PID_FILE, 'r').read()
    6.63 +        lines = os.popen('ps ' + pid + ' 2>/dev/null').readlines()
    6.64 +        for line in lines:
    6.65 +            if re.search('^ *' + pid + '.+xensv', line):
    6.66 +                if not kill:
    6.67 +                    print "Daemon is already running (pid %d)" % int(pid)
    6.68 +                    return 1
    6.69 +                # Old daemon is still active: terminate it.
    6.70 +                os.kill(int(pid), 1)
    6.71 +        # Delete the stale PID_FILE.
    6.72 +        os.remove(PID_FILE)
    6.73 +        return 0
    6.74 +
    6.75 +    def start(self, trace=0):
    6.76 +        if self.cleanup(kill=False):
    6.77 +            return 1
    6.78 +   
    6.79 +        # Fork -- parent writes PID_FILE and exits.
    6.80 +        pid = os.fork()
    6.81 +        if pid:
    6.82 +            # Parent
    6.83 +            pidfile = open(PID_FILE, 'w')
    6.84 +            pidfile.write(str(pid))
    6.85 +            pidfile.close()
    6.86 +            return 0
    6.87 +        # Child
    6.88 +        self.run()
    6.89 +        return 0
    6.90 +
    6.91 +    def stop(self):
    6.92 +        return self.cleanup(kill=True)
    6.93 +
    6.94 +    def run(self):
    6.95 +	root = static.File( SV_ROOT )
    6.96 +        root.indexNames = [ 'Main.rpy' ]
    6.97 +        root.processors = { '.rpy': script.ResourceScript }
    6.98 +        reactor.listenTCP( SV_PORT, server.Site( root ) )
    6.99 +        reactor.run()
   6.100 +
   6.101 +    def exit(self):
   6.102 +        reactor.diconnectAll()
   6.103 +        sys.exit(0)
   6.104 +
   6.105 +def instance():
   6.106 +    global inst
   6.107 +    try:
   6.108 +        inst
   6.109 +    except:
   6.110 +        inst = Daemon()
   6.111 +    return inst
     7.1 --- a/tools/python/xen/sv/HTMLBase.py	Tue Jul 27 15:04:59 2004 +0000
     7.2 +++ b/tools/python/xen/sv/HTMLBase.py	Wed Jul 28 12:13:47 2004 +0000
     7.3 @@ -25,9 +25,9 @@ class HTMLBase( Resource ):
     7.4          request.write( '<html><head><title>Xen</title><link rel="stylesheet" type="text/css" href="inc/style.css" />' )
     7.5          request.write( '<script src="inc/script.js"></script>' )
     7.6          request.write( '</head><body>' )
     7.7 +        request.write('<form method="post" action="%s">' % request.uri)
     7.8  
     7.9      def write_BOTTOM( self, request ):
    7.10 -        request.write('<form method="post" action="%s">' % request.uri)
    7.11          request.write('<input type="hidden" name="op" value="">')
    7.12          request.write('</form>')
    7.13          request.write( "</body></html>" )
     8.1 --- a/tools/python/xen/sv/Wizzard.py	Tue Jul 27 15:04:59 2004 +0000
     8.2 +++ b/tools/python/xen/sv/Wizzard.py	Wed Jul 28 12:13:47 2004 +0000
     8.3 @@ -2,13 +2,14 @@ from xen.sv.util import *
     8.4  from xen.sv.HTMLBase import HTMLBase
     8.5  from xen.xend import sxp
     8.6  
     8.7 +DEBUG = 1
     8.8 +
     8.9  class Wizzard( HTMLBase ):
    8.10  
    8.11      def __init__( self, urlWriter, title, sheets ):
    8.12          HTMLBase.__init__( self )
    8.13          self.title = title
    8.14          self.sheets = sheets
    8.15 -        self.currSheet = 0
    8.16          self.urlWriter = urlWriter
    8.17          
    8.18      def write_MENU( self, request ):
    8.19 @@ -22,45 +23,90 @@ class Wizzard( HTMLBase ):
    8.20          currSheet = getVar( 'sheet', request )
    8.21      
    8.22          if not currSheet is None:
    8.23 +            currSheet = int( currSheet )
    8.24 +        else:
    8.25 +            currSheet = 0
    8.26 +            
    8.27 +        op = getVar( 'op', request )
    8.28          
    8.29 -            self.currSheet = int( currSheet )
    8.30 +        if op == 'next':
    8.31 +            currSheet += 1
    8.32 +        elif op == 'prev':
    8.33 +            currSheet -= 1    
    8.34              
    8.35 -        self.sheets[ self.currSheet ]( self.urlWriter ).write_BODY( request )
    8.36 +        self.sheets[ currSheet ]( self.urlWriter ).write_BODY( request )
    8.37          
    8.38          request.write( "</td></tr><tr><td><table width='100%' border='0' cellspacing='0' cellpadding='0'><tr>" )
    8.39 -        request.write( "<td width='80%'></td><td width='20%' align='center'>" )
    8.40 -        request.write( "<p align='center'><img src='images/previous.png' onclick='doOp( \"prev\" )' onmouseover='update( \"wizText\", \"Previous\" )' onmouseout='update( \"wizText\", \"&nbsp;\" )'>&nbsp;" )
    8.41 -        request.write( "<img src='images/next.png' onclick='doOp( \"next\" )' onmouseover='update( \"wizText\", \"Next\" )' onmouseout='update( \"wizText\", \"&nbsp;\" )'></p>" )
    8.42 -        request.write( "<p align='center'><span id='wizText'></span></p></td></tr></table>" )
    8.43 +        request.write( "<td width='80%'></td><td width='20%' align='center'><p align='center'>" )
    8.44 +	if currSheet > 0:
    8.45 +       		request.write( "<img src='images/previous.png' onclick='doOp( \"prev\" )' onmouseover='update( \"wizText\", \"Previous\" )' onmouseout='update( \"wizText\", \"&nbsp;\" )'>&nbsp;" )
    8.46 +        if currSheet < ( len( self.sheets ) - 1 ):        
    8.47 +        	request.write( "<img src='images/next.png' onclick='doOp( \"next\" )' onmouseover='update( \"wizText\", \"Next\" )' onmouseout='update( \"wizText\", \"&nbsp;\" )'>" )
    8.48 +        request.write( "</p><p align='center'><span id='wizText'></span></p></td></tr></table>" )
    8.49          request.write( "</td></tr></table>" )
    8.50          
    8.51 +    def op_next( self, request ):
    8.52 +    	pass
    8.53 +        
    8.54 +    def op_prev( self, request ):
    8.55 +    	pass  
    8.56 +        
    8.57  class Sheet( HTMLBase ):
    8.58  
    8.59 -    def __init__( self, urlWriter, feilds, title ):
    8.60 +    def __init__( self, urlWriter, feilds, title, location ):
    8.61          HTMLBase.__init__( self )
    8.62          self.urlWriter = urlWriter
    8.63          self.feilds = feilds
    8.64          self.title = title
    8.65 +        self.location = location
    8.66 +        self.passback = "()"
    8.67          
    8.68      def parseForm( self, request ):
    8.69 -    	return sxp.toString( request.args )
    8.70 +    	do_not_parse = [ 'mod', 'op', 'sheet' ] 
    8.71 +    
    8.72 +    	passed_back = request.args
    8.73 +        
    8.74 +        temp_passback = passed_back.get( "passback" )
    8.75 +        
    8.76 +        if temp_passback is not None and len( temp_passback ) > 0:
    8.77 +            temp_passback = temp_passback[ len( temp_passback )-1 ]
    8.78 +        else:
    8.79 +            temp_passback = "(passback )"        
    8.80 +        
    8.81 +        last_passback = ssxp2hash( string2sxp( temp_passback ) )
    8.82 +        
    8.83 +        if DEBUG: print last_passback
    8.84 +        
    8.85 +        try: 
    8.86 +            del passed_back[ 'passback' ]
    8.87 +        except:
    8.88 +            pass
    8.89 +        
    8.90 +        for (key, value) in passed_back.items():
    8.91 +            if key not in do_not_parse:
    8.92 +                last_passback[ key ] = value[ len( value ) - 1 ]
    8.93 +                
    8.94 +        self.passback = sxp2string( hash2sxp( last_passback ) ) #store the sxp
    8.95 +        
    8.96 +        if DEBUG: print self.passback
    8.97 +        
    8.98 +        return last_passback #return the hash
    8.99          
   8.100      def write_BODY( self, request ):
   8.101 +        
   8.102     	request.write( "<p>%s</p>" % self.title )
   8.103      
   8.104 -    	previous_values = request.args
   8.105 +    	previous_values = self.parseForm( request ) #get the hash for quick reference
   8.106          
   8.107      	for (feild, name) in self.feilds:
   8.108 -            value = sxp.child_value( previous_values, feild )
   8.109 +            value = previous_values.get( feild )
   8.110              if value is None:
   8.111              	value = ''
   8.112              request.write( "<p>%s<input type='text' name='%s' value='%s'></p>" % (name, feild, value) )
   8.113 -            
   8.114 -    def op_next( self, request ):
   8.115 -    	pass
   8.116          
   8.117 -    def op_prev( self, request ):
   8.118 -    	pass        
   8.119 +        request.write( "<input type='hidden' name='passback' value=\"%s\"></p>" % self.passback )
   8.120 +        request.write( "<input type='hidden' name='sheet' value='%s'></p>" % self.location )        
   8.121 +                 
   8.122              
   8.123      
   8.124        
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/tools/python/xen/sv/params.py	Wed Jul 28 12:13:47 2004 +0000
     9.3 @@ -0,0 +1,3 @@
     9.4 +SV_PORT = 8080
     9.5 +SV_ROOT = "/var/xen/sv/"
     9.6 +PID_FILE = "/var/xen/sv.pid"
     9.7 \ No newline at end of file
    10.1 --- a/tools/python/xen/sv/util.py	Tue Jul 27 15:04:59 2004 +0000
    10.2 +++ b/tools/python/xen/sv/util.py	Wed Jul 28 12:13:47 2004 +0000
    10.3 @@ -18,7 +18,32 @@ def sxp2hash( s ):
    10.4          else:
    10.5              sxphash[ child[0] ] = child[1]
    10.6          
    10.7 -    return sxphash   
    10.8 +    return sxphash  
    10.9 +    
   10.10 +def ssxp2hash( s ):
   10.11 +    sxphash = {}
   10.12 +    
   10.13 +    for i in s:
   10.14 +       if isinstance( i, types.ListType ) and len( i ) > 1:
   10.15 +          sxphash[ i[0] ] = i[1]
   10.16 +    
   10.17 +    return sxphash 
   10.18 +    
   10.19 +def hash2sxp( h ):
   10.20 +    hashsxp = []
   10.21 +    
   10.22 +    for (key, item) in h.items():
   10.23 +    	hashsxp.append( [key, item] )
   10.24 +        
   10.25 +    return hashsxp    
   10.26 +    
   10.27 +def string2sxp( string ):
   10.28 +    pin = sxp.Parser()
   10.29 +    pin.input( string )
   10.30 +    return pin.get_val()    
   10.31 +
   10.32 +def sxp2string( sexp ):
   10.33 +    return sxp.to_string( sexp )    
   10.34      
   10.35  def sxp2prettystring( sxp ):
   10.36      class tmp: