ia64/xen-unstable

changeset 6076:2379e795ca69

merge
author kaf24@firebug.cl.cam.ac.uk
date Tue Aug 09 13:04:31 2005 +0000 (2005-08-09)
parents f01ba22e044c 12deebfb7f87
children 356b14d5ffc8
files linux-2.6-xen-sparse/arch/xen/i386/kernel/Makefile tools/python/xen/sv/CreateDomain.py tools/python/xen/sv/DomInfo.py tools/python/xen/sv/GenTabbed.py tools/python/xen/sv/HTMLBase.py tools/python/xen/sv/Main.py tools/python/xen/sv/NodeInfo.py tools/python/xen/sv/RestoreDomain.py tools/python/xen/sv/Wizard.py tools/python/xen/sv/util.py tools/sv/inc/style.css tools/sv/index.psp
line diff
     2.1 --- a/tools/python/xen/sv/CreateDomain.py	Tue Aug 09 10:47:41 2005 +0000
     2.2 +++ b/tools/python/xen/sv/CreateDomain.py	Tue Aug 09 13:04:31 2005 +0000
     2.3 @@ -17,37 +17,69 @@ class CreateDomain( Wizard ):
     2.4                     CreateFinish ]
     2.5      
     2.6      	Wizard.__init__( self, urlWriter, "Create Domain", sheets )
     2.7 -       
     2.8 +
     2.9 +    def op_finish( self, request ):
    2.10 +        pass
    2.11 +    
    2.12  class CreatePage0( Sheet ):
    2.13  
    2.14 +    title = "General"
    2.15 +    
    2.16      def __init__( self, urlWriter ):
    2.17          Sheet.__init__( self, urlWriter, "General", 0 )
    2.18          self.addControl( InputControl( 'name', 'VM Name', 'VM Name:', "[\\w|\\S]+", "You must enter a name in this field" ) )
    2.19          self.addControl( InputControl( 'memory', '64', 'Memory (Mb):', "[\\d]+", "You must enter a number in this field" ) )
    2.20          self.addControl( InputControl( 'cpu', '0', 'CPU:', "[\\d]+", "You must enter a number in this feild" ) )
    2.21          self.addControl( InputControl( 'cpu_weight', '1', 'CPU Weight:', "[\\d]+", "You must enter a number in this feild" ) )
    2.22 +        self.addControl( InputControl( 'vcpus', '1', 'Virtual CPUs:', '[\\d]+', "You must enter a number in this feild") )
    2.23                          
    2.24  class CreatePage1( Sheet ):
    2.25  
    2.26 +    title = "Setup Kernel Image"
    2.27 +
    2.28      def __init__( self, urlWriter ):
    2.29          Sheet.__init__( self, urlWriter, "Setup Kernel Image", 1 )
    2.30 -# For now we don't need to select a builder...
    2.31 -#        self.addControl( ListControl( 'builder', [('linux', 'Linux'), ('netbsd', 'NetBSD')], 'Kernel Type:' ) )
    2.32 -        self.addControl( FileControl( 'kernel', '/boot/vmlinuz-2.6.9-xenU', 'Kernel Image:' ) )
    2.33 +        self.addControl( ListControl( 'builder', [('linux', 'Linux'), ('netbsd', 'NetBSD')], 'Domain Builder:' ) )
    2.34 +        self.addControl( FileControl( 'kernel', '/boot/vmlinuz-2.6.12-xenU', 'Kernel Image:' ) )
    2.35          self.addControl( InputControl( 'extra', '', 'Kernel Command Line Parameters:' ) )
    2.36 +        self.addControl( ListControl( 'use-initrd', [('yes', 'Yes'), ('no', 'No')], 'Use an Initial Ram Disk?:' ) )
    2.37 +        self.addControl( FileControl( 'initrd', '/boot/initrd-2.6.12-xenU.img', 'Initial Ram Disk:' ) )
    2.38 +
    2.39 +    def validate( self, request ):
    2.40 +        if not self.passback: self.parseForm( request )
    2.41 +        check = True
    2.42 +        request.write( previous_values.get( '>>>>>use-initrd' ) )
    2.43 +        previous_values = ssxp2hash( string2sxp( self.passback ) ) #get the map for quick reference
    2.44 +        if DEBUG: print previous_values
    2.45 +        for (feild, control) in self.feilds:
    2.46 +            if feild == 'initrd' and previous_values.get( 'use-initrd' ) != 'no':
    2.47 +                request.write( previous_values.get( '>>>>>use-initrd' ) )
    2.48 +                if control.validate( previous_values.get( feild ) ):
    2.49 +                    check = False
    2.50 +            elif not control.validate( previous_values.get( feild ) ):
    2.51 +                check = False
    2.52 +
    2.53 +            if DEBUG: print "> %s = %s" % (feild, previous_values.get( feild ))
    2.54 +
    2.55 +        return check
    2.56 +                                                 
    2.57  
    2.58  class CreatePage2( Sheet ):
    2.59  
    2.60 +    title = "Choose number of VBDS"
    2.61 +
    2.62      def __init__( self, urlWriter ):
    2.63      	Sheet.__init__( self, urlWriter, "Setup Virtual Block Device", 2 )
    2.64          self.addControl( InputControl( 'num_vbds', '1', 'Number of VBDs:', '[\\d]+', "You must enter a number in this field" ) )
    2.65  
    2.66  class CreatePage3( Sheet ):
    2.67  
    2.68 +    title = "Setup VBDS"
    2.69 +
    2.70      def __init__( self, urlWriter ):
    2.71          Sheet.__init__( self, urlWriter, "Setup Virtual Block Device", 3 )
    2.72          
    2.73 -    def write_BODY( self, request, err ):
    2.74 +    def write_BODY( self, request ):
    2.75          if not self.passback: self.parseForm( request )
    2.76      
    2.77      	previous_values = sxp2hash( string2sxp( self.passback ) ) #get the hash for quick reference
    2.78 @@ -61,10 +93,12 @@ class CreatePage3( Sheet ):
    2.79              
    2.80          self.addControl( InputControl( 'root', '/dev/sda1', 'Root device (in VM):' ) )
    2.81          
    2.82 -        Sheet.write_BODY( self, request, err )
    2.83 +        Sheet.write_BODY( self, request )
    2.84                  
    2.85  class CreatePage4( Sheet ):
    2.86  
    2.87 +    title = "Network Setting"
    2.88 +
    2.89      def __init__( self, urlWriter ):        
    2.90          Sheet.__init__( self, urlWriter, "Network settings", 4 )
    2.91          self.addControl( ListControl( 'dhcp', [('off', 'No'), ('dhcp', 'Yes')], 'Use DHCP:' ) )
    2.92 @@ -76,26 +110,27 @@ class CreatePage4( Sheet ):
    2.93                   
    2.94  class CreateFinish( Sheet ):
    2.95  
    2.96 +    title = "Finish"
    2.97 +
    2.98      def __init__( self, urlWriter ):
    2.99          Sheet.__init__( self, urlWriter, "All Done", 5 )
   2.100          
   2.101 -    def write_BODY( self, request, err ):
   2.102 +    def write_BODY( self, request ):
   2.103      
   2.104          if not self.passback: self.parseForm( request )
   2.105          
   2.106          xend_sxp = self.translate_sxp( string2sxp( self.passback ) )
   2.107 +
   2.108 +        request.write( "<pre>%s</pre>" % sxp2prettystring( xend_sxp ) )
   2.109          
   2.110          try:
   2.111 -            dom_sxp = server.xend_domain_create( xend_sxp )
   2.112 -            success = "Your domain was successfully created.\n"
   2.113 -        except:
   2.114 -            success = "There was an error creating your domain.\nThe configuration used is as follows:\n"
   2.115 -            dom_sxp = xend_sxp
   2.116 -            
   2.117 -            
   2.118 -        
   2.119 -        pt = PreTab( success + sxp2prettystring( dom_sxp ) )
   2.120 -        pt.write_BODY( request )
   2.121 +            server.xend_domain_create( xend_sxp )
   2.122 +            request.write( "<p>You domain had been successfully created.</p>" )
   2.123 +        except Exception, e:
   2.124 +            request.write( "<p>There was an error creating your domain.<br/>The configuration used is as follows:\n</p>" )
   2.125 +            request.write( "<pre>%s</pre>" % sxp2prettystring( xend_sxp ) )
   2.126 +            request.write( "<p>The error was:</p>" )
   2.127 +            request.write( "<pre>%s</pre>" % str( e ) )
   2.128  
   2.129          request.write( "<input type='hidden' name='passback' value=\"%s\"></p>" % self.passback )
   2.130          request.write( "<input type='hidden' name='sheet' value='%s'></p>" % self.location )
   2.131 @@ -117,6 +152,7 @@ class CreateFinish( Sheet ):
   2.132          vals.maxmem =   get( 'maxmem' )
   2.133          vals.cpu =  	get( 'cpu' )
   2.134          vals.cpu_weight = get( 'cpu_weight' )
   2.135 +        vals.vcpus = get( 'vcpus' )
   2.136          
   2.137          vals.builder =  get( 'builder' )       
   2.138          vals.kernel =   get( 'kernel' )
   2.139 @@ -128,7 +164,7 @@ class CreateFinish( Sheet ):
   2.140          vbds = []
   2.141          
   2.142          for i in range( int( get( 'num_vbds' ) ) ):
   2.143 -            vbds.append( ( get( 'vbd%s_dom0' % i ), get('vbd%s_domU' % i ), get( 'vbd%s_mode' % i ) ) )
   2.144 +            vbds.append( ( get( 'vbd%s_dom0' % i ), get('vbd%s_domU' % i ), get( 'vbd%s_mode' % i ), None ) )
   2.145          
   2.146          vals.disk = vbds    
   2.147              
   2.148 @@ -141,6 +177,9 @@ class CreateFinish( Sheet ):
   2.149          vals.restart = None
   2.150          vals.console = None
   2.151          vals.ramdisk = None
   2.152 +        vals.ssidref = -1
   2.153 +        vals.bootloader = None
   2.154 +        vals.usb = []
   2.155          
   2.156          #setup vifs
   2.157          
   2.158 @@ -155,9 +194,11 @@ class CreateFinish( Sheet ):
   2.159          dhcp = get( 'dhcp' )
   2.160          
   2.161          vals.cmdline_ip = "%s:%s:%s:%s:%s:eth0:%s" % (ip, nfs, gate, mask, host, dhcp)
   2.162 +
   2.163 +        opts = None
   2.164          
   2.165          try:
   2.166 -            return make_config( vals )
   2.167 -        except:
   2.168 -            return [["Error creating domain config."]]    
   2.169 +            return make_config( opts, vals )
   2.170 +        except Exception, e:
   2.171 +            return [["There was an error creating the domain config SXP.  This is typically due to an interface change in xm/create.py:make_config", e]]    
   2.172          
     3.1 --- a/tools/python/xen/sv/Daemon.py	Tue Aug 09 10:47:41 2005 +0000
     3.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.3 @@ -1,110 +0,0 @@
     3.4 -###########################################################
     3.5 -## XenSV Web Control Interface Daemon
     3.6 -## Copyright (C) 2004, K A Fraser (University of Cambridge)
     3.7 -## Copyright (C) 2004, Mike Wray <mike.wray@hp.com>
     3.8 -## Copyright (C) 2004, Tom Wilkie <tw275@cam.ac.uk>
     3.9 -###########################################################
    3.10 -
    3.11 -import os
    3.12 -import os.path
    3.13 -import sys
    3.14 -import re
    3.15 -
    3.16 -from xen.sv.params import *
    3.17 -
    3.18 -from twisted.internet import reactor
    3.19 -from twisted.web import static, server, script
    3.20 -
    3.21 -from xen.util.ip import _readline, _readlines
    3.22 -
    3.23 -class Daemon:
    3.24 -    """The xend daemon.
    3.25 -    """
    3.26 -    def __init__(self):
    3.27 -        self.shutdown = 0
    3.28 -        self.traceon = 0
    3.29 -
    3.30 -    def daemon_pids(self):
    3.31 -        pids = []
    3.32 -        pidex = '(?P<pid>\d+)'
    3.33 -        pythonex = '(?P<python>\S*python\S*)'
    3.34 -        cmdex = '(?P<cmd>.*)'
    3.35 -        procre = re.compile('^\s*' + pidex + '\s*' + pythonex + '\s*' + cmdex + '$')
    3.36 -        xendre = re.compile('^/usr/sbin/xend\s*(start|restart)\s*.*$')
    3.37 -        procs = os.popen('ps -e -o pid,args 2>/dev/null')
    3.38 -        for proc in procs:
    3.39 -            pm = procre.match(proc)
    3.40 -            if not pm: continue
    3.41 -            xm = xendre.match(pm.group('cmd'))
    3.42 -            if not xm: continue
    3.43 -            #print 'pid=', pm.group('pid'), 'cmd=', pm.group('cmd')
    3.44 -            pids.append(int(pm.group('pid')))
    3.45 -        return pids
    3.46 -
    3.47 -    def new_cleanup(self, kill=0):
    3.48 -        err = 0
    3.49 -        pids = self.daemon_pids()
    3.50 -        if kill:
    3.51 -            for pid in pids:
    3.52 -                print "Killing daemon pid=%d" % pid
    3.53 -                os.kill(pid, signal.SIGHUP)
    3.54 -        elif pids:
    3.55 -            err = 1
    3.56 -            print "Daemon already running: ", pids
    3.57 -        return err
    3.58 -            
    3.59 -    def cleanup(self, kill=False):
    3.60 -        # No cleanup to do if PID_FILE is empty.
    3.61 -        if not os.path.isfile(PID_FILE) or not os.path.getsize(PID_FILE):
    3.62 -            return 0
    3.63 -        # Read the pid of the previous invocation and search active process list.
    3.64 -        pid = open(PID_FILE, 'r').read()
    3.65 -        lines = _readlines(os.popen('ps ' + pid + ' 2>/dev/null'))
    3.66 -        for line in lines:
    3.67 -            if re.search('^ *' + pid + '.+xensv', line):
    3.68 -                if not kill:
    3.69 -                    print "Daemon is already running (pid %d)" % int(pid)
    3.70 -                    return 1
    3.71 -                # Old daemon is still active: terminate it.
    3.72 -                os.kill(int(pid), 1)
    3.73 -        # Delete the stale PID_FILE.
    3.74 -        os.remove(PID_FILE)
    3.75 -        return 0
    3.76 -
    3.77 -    def start(self, trace=0):
    3.78 -        if self.cleanup(kill=False):
    3.79 -            return 1
    3.80 -   
    3.81 -        # Fork -- parent writes PID_FILE and exits.
    3.82 -        pid = os.fork()
    3.83 -        if pid:
    3.84 -            # Parent
    3.85 -            pidfile = open(PID_FILE, 'w')
    3.86 -            pidfile.write(str(pid))
    3.87 -            pidfile.close()
    3.88 -            return 0
    3.89 -        # Child
    3.90 -        self.run()
    3.91 -        return 0
    3.92 -
    3.93 -    def stop(self):
    3.94 -        return self.cleanup(kill=True)
    3.95 -
    3.96 -    def run(self):
    3.97 -	root = static.File( SV_ROOT )
    3.98 -        root.indexNames = [ 'Main.rpy' ]
    3.99 -        root.processors = { '.rpy': script.ResourceScript }
   3.100 -        reactor.listenTCP( SV_PORT, server.Site( root ) )
   3.101 -        reactor.run()
   3.102 -
   3.103 -    def exit(self):
   3.104 -        reactor.disconnectAll()
   3.105 -        sys.exit(0)
   3.106 -
   3.107 -def instance():
   3.108 -    global inst
   3.109 -    try:
   3.110 -        inst
   3.111 -    except:
   3.112 -        inst = Daemon()
   3.113 -    return inst
     4.1 --- a/tools/python/xen/sv/DomInfo.py	Tue Aug 09 10:47:41 2005 +0000
     4.2 +++ b/tools/python/xen/sv/DomInfo.py	Tue Aug 09 13:04:31 2005 +0000
     4.3 @@ -4,6 +4,7 @@ from xen.xend import PrettyPrint
     4.4  from xen.sv.HTMLBase import HTMLBase
     4.5  from xen.sv.util import *
     4.6  from xen.sv.GenTabbed import *
     4.7 +from xen.sv.Wizard import *
     4.8  
     4.9  DEBUG=1
    4.10  
    4.11 @@ -12,33 +13,69 @@ class DomInfo( GenTabbed ):
    4.12      def __init__( self, urlWriter ):
    4.13          
    4.14          self.dom = 0;
    4.15 -    
    4.16 -        def tabUrlWriter( tab ):
    4.17 -            return urlWriter( "&dom=%s%s" % ( self.dom, tab ) )
    4.18 -        
    4.19 -        GenTabbed.__init__( self, "Domain Info", tabUrlWriter, [ 'General', 'SXP', 'Devices' ], [ DomGeneralTab, DomSXPTab, NullTab ]  )
    4.20 +                   
    4.21 +        GenTabbed.__init__( self, "Domain Info", urlWriter, [ 'General', 'SXP', 'Devices', 'Migrate', 'Save' ], [ DomGeneralTab, DomSXPTab, DomDeviceTab, DomMigrateTab, DomSaveTab ]  )
    4.22  
    4.23      def write_BODY( self, request ):
    4.24 -        dom = request.args.get('dom')
    4.25 -        
    4.26 -        if dom is None or len(dom) != 1:
    4.27 +        try:
    4.28 +            dom = int( getVar( 'dom', request ) )
    4.29 +        except:
    4.30              request.write( "<p>Please Select a Domain</p>" )
    4.31              return None
    4.32 -        else:
    4.33 -            self.dom = dom[0]
    4.34 -        
    4.35 +       
    4.36          GenTabbed.write_BODY( self, request )
    4.37          
    4.38      def write_MENU( self, request ):
    4.39 -        pass
    4.40 +       domains = []
    4.41 +
    4.42 +       try:
    4.43 +           domains = server.xend_domains()
    4.44 +           domains.sort()
    4.45 +       except:
    4.46 +           pass
    4.47 +
    4.48 +       request.write( "\n<table style='border:0px solid white' cellspacing='0' cellpadding='0' border='0' width='100%'>\n" )
    4.49 +       request.write( "<tr class='domainInfoHead'>" )
    4.50 +       request.write( "<td class='domainInfoHead' align='center'>Domain</td>\n" )
    4.51 +       request.write( "<td class='domainInfoHead' align='center'>Name</td>\n" )
    4.52 +       request.write( "<td class='domainInfoHead' align='center'>State</td>\n" )
    4.53 +       request.write( "<td class='domainInfoHead' align='center'></td>\n" )
    4.54 +       request.write( "</tr>" )
    4.55  
    4.56 +       odd = True
    4.57 +       if not domains is None:
    4.58 +           for domain in domains:
    4.59 +               odd = not odd;
    4.60 +               if odd:
    4.61 +                   request.write( "<tr class='domainInfoOdd'>\n" )
    4.62 +               else:
    4.63 +                   request.write( "<tr class='domainInfoEven'>\n" )
    4.64 +               domInfo = getDomInfo( domain )
    4.65 +               request.write( "<td class='domainInfo' align='center'>%(id)s</td>\n" % domInfo )
    4.66 +               url = self.urlWriter( "&dom=%(id)s" % domInfo )
    4.67 +               request.write( "<td class='domainInfo' align='center'><a href='%s'>%s</a></td>\n" % ( url, domInfo['name'] ) )
    4.68 +               request.write( "<td class='domainInfo' align='center'>%(state)5s</td>\n" % domInfo )
    4.69 +               if domInfo[ 'id' ] != "0":
    4.70 +                   request.write( "<td class='domainInfo' align='center'>" )
    4.71 +                   if domInfo[ 'state' ][ 2 ] == "-":
    4.72 +                       request.write( "<img src='images/small-pause.png' onclick='doOp2( \"pause\", \"%(dom)-4s\" )'>" % domInfo )
    4.73 +                   else:
    4.74 +                       request.write( "<img src='images/small-unpause.png' onclick='doOp2( \"unpause\", \"%(dom)-4s\" )'>" % domInfo )
    4.75 +                   request.write( "<img src='images/small-destroy.png' onclick='doOp2( \"destroy\", \"%(dom)-4s\" )'></td>" % domInfo )
    4.76 +               else:
    4.77 +                   request.write( "<td>&nbsp;</td>" )
    4.78 +               request.write( "</tr>\n" )
    4.79 +       else:
    4.80 +           request.write( "<tr colspan='10'><p class='small'>Error getting domain list<br/>Perhaps XenD not running?</p></tr>")
    4.81 +       request.write( "</table>" )
    4.82 +       
    4.83  class DomGeneralTab( CompositeTab ):
    4.84 -    def __init__( self ):
    4.85 -       CompositeTab.__init__( self, [ DomGenTab, DomActionTab ] )        
    4.86 -        
    4.87 +    def __init__( self, urlWriter ):
    4.88 +       CompositeTab.__init__( self, [ DomGenTab, DomActionTab ], urlWriter )        
    4.89 +       
    4.90  class DomGenTab( GeneralTab ):
    4.91  
    4.92 -    def __init__( self ):
    4.93 +    def __init__( self, urlWriter ):
    4.94      
    4.95          titles = {}
    4.96      
    4.97 @@ -60,13 +97,13 @@ class DomGenTab( GeneralTab ):
    4.98              request.write( "<p>Please Select a Domain</p>" )
    4.99              return None
   4.100              
   4.101 -        self.dict = getDomInfoHash( self.dom )
   4.102 +        self.dict = getDomInfo( self.dom )
   4.103          
   4.104          GeneralTab.write_BODY( self, request )
   4.105              
   4.106  class DomSXPTab( PreTab ):
   4.107  
   4.108 -    def __init__( self ):
   4.109 +    def __init__( self, urlWriter ):
   4.110          self.dom = 0
   4.111          PreTab.__init__( self, "" )
   4.112  
   4.113 @@ -86,15 +123,15 @@ class DomSXPTab( PreTab ):
   4.114          self.source = sxp2prettystring( domInfo )
   4.115          
   4.116          PreTab.write_BODY( self, request )
   4.117 -        
   4.118 +       
   4.119  class DomActionTab( ActionTab ):
   4.120  
   4.121 -    def __init__( self ):
   4.122 -    	actions = { "shutdown" : "shutdown",
   4.123 -        	    "reboot" : "reboot",
   4.124 -                    "pause" : "pause",
   4.125 -                    "unpause" : "unpause",
   4.126 -                    "destroy" : "destroy" }
   4.127 +    def __init__( self, urlWriter ):
   4.128 +    	actions = { "shutdown" : "Shutdown",
   4.129 +        	    "reboot" : "Reboot",
   4.130 +                    "pause" : "Pause",
   4.131 +                    "unpause" : "Unpause",
   4.132 +                    "destroy" : "Destroy" }
   4.133          ActionTab.__init__( self, actions )    
   4.134          
   4.135      def op_shutdown( self, request ):
   4.136 @@ -141,8 +178,91 @@ class DomActionTab( ActionTab ):
   4.137             	server.xend_domain_destroy( int( dom ), "halt" )
   4.138             except:
   4.139             	pass
   4.140 -        
   4.141 -    
   4.142 -    
   4.143 -        
   4.144 +
   4.145 +class DomDeviceTab( CompositeTab ):
   4.146 +
   4.147 +    def __init__( self, urlWriter ):
   4.148 +        CompositeTab.__init__( self, [ DomDeviceListTab, DomDeviceOptionsTab, DomDeviceActionTab ], urlWriter )
   4.149 +
   4.150 +class DomDeviceListTab( NullTab ):
   4.151 +
   4.152 +    title = "Device List"
   4.153 +
   4.154 +    def __init__( self, urlWriter ):
   4.155 +        pass
   4.156 +
   4.157 +class DomDeviceOptionsTab( NullTab ):
   4.158 +
   4.159 +    title = "Device Options"
   4.160 +
   4.161 +    def __init__( self, urlWriter ):
   4.162 +        pass
   4.163 +
   4.164 +class DomDeviceActionTab( ActionTab ):
   4.165 +
   4.166 +    def __init__( self, urlWriter ):
   4.167 +        ActionTab.__init__( self, { "addvcpu" : "Add VCPU", "addvbd" : "Add VBD", "addvif" : "Add VIF" } )
   4.168 +
   4.169 +class DomMigrateTab( CompositeTab ):
   4.170 +
   4.171 +    def __init__( self, urlWriter ):
   4.172 +        CompositeTab.__init__( self, [ DomMigrateExtraTab, DomMigrateActionTab ], urlWriter ) 
   4.173 +
   4.174 +class DomMigrateExtraTab( Sheet ):
   4.175 +
   4.176 +    def __init__( self, urlWriter ):
   4.177 +        Sheet.__init__( self, urlWriter, "Configure Migration", 0)
   4.178 +        self.addControl( TickControl('live', 'True', 'Live migrate:') )
   4.179 +        self.addControl( InputControl('rate', '0', 'Rate limit:') )
   4.180 +        self.addControl( InputControl( 'dest', 'host.domain', 'Name or IP address:', ".*") )
   4.181 +                                                                                                            
   4.182 +class DomMigrateActionTab( ActionTab ):
   4.183  
   4.184 +    def __init__( self, urlWriter ):
   4.185 +        actions = { "migrate" : "Migrate" }
   4.186 +        ActionTab.__init__( self, actions )
   4.187 +                
   4.188 +    def op_migrate( self, request ):
   4.189 +        try:
   4.190 +            domid = int( getVar( 'dom', request ) )
   4.191 +            live  = getVar( 'live', request )
   4.192 +            rate  = getVar( 'rate', request )
   4.193 +            dest  = getVar( 'dest', request )
   4.194 +            dom_sxp = server.xend_domain_migrate( domid, dest, live == 'True', rate )
   4.195 +            success = "Your domain was successfully Migrated.\n"
   4.196 +        except Exception, e:
   4.197 +            success = "There was an error migrating your domain\n"
   4.198 +            dom_sxp = str(e)
   4.199 +                                                        
   4.200 +class DomSaveTab( CompositeTab ):
   4.201 +
   4.202 +    def __init__( self, urlWriter ):
   4.203 +        CompositeTab.__init__( self, [ DomSaveExtraTab, DomSaveActionTab ], urlWriter ) 
   4.204 +
   4.205 +class DomSaveExtraTab( Sheet ):
   4.206 +
   4.207 +    title = "Save location"
   4.208 +
   4.209 +    def __init__( self, urlWriter ):
   4.210 +        Sheet.__init__( self, urlWriter, "Save Domain to file", 0 )
   4.211 +        self.addControl( InputControl( 'file', '', 'Suspend file name:', ".*") )
   4.212 +               
   4.213 +class DomSaveActionTab( ActionTab ):
   4.214 +
   4.215 +    def __init__( self, urlWriter ):
   4.216 +        actions = { "save" : "Save" }
   4.217 +        ActionTab.__init__( self, actions )
   4.218 +
   4.219 +    def op_save( self, request ):
   4.220 +
   4.221 +        try:
   4.222 +            dom_sxp = server.xend_domain_save( config['domid'], config['file'] )
   4.223 +            success = "Your domain was successfully saved.\n"
   4.224 +        except Exception, e:
   4.225 +            success = "There was an error saving your domain\n"
   4.226 +            dom_sxp = str(e)
   4.227 +                                                                                       
   4.228 +        try:
   4.229 +            dom = int( getVar( 'dom', request ) )
   4.230 +        except:
   4.231 +            pass
     5.1 --- a/tools/python/xen/sv/DomList.py	Tue Aug 09 10:47:41 2005 +0000
     5.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.3 @@ -1,81 +0,0 @@
     5.4 -from xen.xend.XendClient import server
     5.5 -from xen.xend import sxp
     5.6 -
     5.7 -from xen.sv.HTMLBase import HTMLBase
     5.8 -from xen.sv.util import *
     5.9 -
    5.10 -class DomList( HTMLBase ):
    5.11 -    
    5.12 -    isLeaf = True
    5.13 -
    5.14 -    def __init__( self, urlWriter ):
    5.15 -        HTMLBase.__init__(self)
    5.16 -        self.urlWriter = urlWriter
    5.17 -        
    5.18 -    def write_MENU( self, request ):
    5.19 -    	return self.write_BODY( request, head=True, long=False ) 
    5.20 -
    5.21 -    def write_BODY( self, request, head=True, long=True ):
    5.22 -        
    5.23 -    	domains = []
    5.24 -    
    5.25 -        try:
    5.26 -            domains = server.xend_domains()
    5.27 -            domains.sort()
    5.28 -  	except:
    5.29 -            pass
    5.30 -                
    5.31 -        request.write( "\n<table style='border:0px solid white' cellspacing='0' cellpadding='0' border='0' width='100%'>\n" )
    5.32 -        
    5.33 -        if head:
    5.34 -            request.write( "<tr class='domainInfoHead'>" )
    5.35 -            self.write_DOMAIN_HEAD( request, long )
    5.36 -            request.write( "</tr>" )
    5.37 -        
    5.38 -        odd = True
    5.39 -        
    5.40 -        if not domains is None:
    5.41 -            for domain in domains:
    5.42 -                if odd:
    5.43 -                    request.write( "<tr class='domainInfoOdd'>\n" )
    5.44 -                    odd = False
    5.45 -                else:
    5.46 -                    request.write( "<tr class='domainInfoEven'>\n" )
    5.47 -                    odd = True
    5.48 -                self.write_DOMAIN( request, getDomInfoHash( domain ), long )
    5.49 -                request.write( "</tr>\n" )
    5.50 -        else:
    5.51 -        	request.write( "<tr colspan='10'><p class='small'>Error getting domain list<br/>Perhaps XenD not running?</p></tr>")
    5.52 -                
    5.53 -        request.write( "</table>\n" )
    5.54 -            
    5.55 -    def write_DOMAIN( self, request, domInfoHash, long=True ):   
    5.56 -        request.write( "<td class='domainInfo' align='center'>%(id)s</td>\n" % domInfoHash )
    5.57 -
    5.58 -        url = self.urlWriter( "&mod=info&dom=%(id)s" % domInfoHash )
    5.59 -
    5.60 -        request.write( "<td class='domainInfo' align='center'><a href='%s'>%s</a></td>\n" % ( url, domInfoHash['name'] ) )
    5.61 -        if long: 
    5.62 -            request.write( "<td class='domainInfo' align='center'>%(memory)5s</td>\n" % domInfoHash )
    5.63 -            request.write( "<td class='domainInfo' align='center'>%(cpu)2s</td>\n" % domInfoHash )
    5.64 -        request.write( "<td class='domainInfo' align='center'>%(state)5s</td>\n" % domInfoHash )
    5.65 -        if domInfoHash[ 'id' ] != "0":
    5.66 -            request.write( "<td class='domainInfo' align='center'>" )
    5.67 -            
    5.68 -            if domInfoHash[ 'state' ][ 2 ] == "-":
    5.69 -                request.write( "<img src='images/small-pause.png' onclick='doOp2( \"pause\", \"%(dom)-4s\" )'>" % domInfoHash )
    5.70 -            else:
    5.71 -                request.write( "<img src='images/small-unpause.png' onclick='doOp2( \"unpause\", \"%(dom)-4s\" )'>" % domInfoHash )              
    5.72 -            
    5.73 -            request.write( "<img src='images/small-destroy.png' onclick='doOp2( \"destroy\", \"%(dom)-4s\" )'></td>" % domInfoHash)
    5.74 -        else:
    5.75 -            request.write( "<td>&nbsp;</td>" )
    5.76 -
    5.77 -    def write_DOMAIN_HEAD( self, request, long=True ):
    5.78 -        request.write( "<td class='domainInfoHead' align='center'>Domain</td>\n" )      
    5.79 -        request.write( "<td class='domainInfoHead' align='center'>Name</td>\n" )      
    5.80 -        if long:
    5.81 -            request.write( "<td class='domainInfoHead' align='center'>Memory / Mb</td>\n" )      
    5.82 -            request.write( "<td class='domainInfoHead' align='center'>CPU</td>\n" )      
    5.83 -        request.write( "<td class='domainInfoHead' align='center'>State</td>\n" )      
    5.84 -        request.write( "<td class='domainInfoHead' align='center'></td>\n" )
     6.1 --- a/tools/python/xen/sv/GenTabbed.py	Tue Aug 09 10:47:41 2005 +0000
     6.2 +++ b/tools/python/xen/sv/GenTabbed.py	Tue Aug 09 13:04:31 2005 +0000
     6.3 @@ -1,7 +1,6 @@
     6.4  import types
     6.5  
     6.6  from xen.sv.HTMLBase import HTMLBase
     6.7 -from xen.sv.TabView import TabView
     6.8  from xen.sv.util import getVar
     6.9  
    6.10  class GenTabbed( HTMLBase ):
    6.11 @@ -12,39 +11,44 @@ class GenTabbed( HTMLBase ):
    6.12          self.tabObjects = tabObjects
    6.13          self.urlWriter = urlWriter
    6.14          self.title = title
    6.15 -
    6.16 -    def write_BODY( self, request, urlWriter = None ):
    6.17 -        try:
    6.18 -            tab = int( getVar( 'tab', request, 0 ) )
    6.19 -        except:
    6.20 -            tab = 0
    6.21 +        
    6.22 +    def write_BODY( self, request ):
    6.23 +        if not self.__dict__.has_key( "tab" ):
    6.24 +            try:
    6.25 +                self.tab = int( getVar( 'tab', request, 0 ) )
    6.26 +            except:
    6.27 +                self.tab = 0
    6.28              
    6.29 -        request.write( "<table style='' width='100%' border='0' cellspacing='0' cellpadding='0'>" )
    6.30 -        request.write( "<tr><td>" )
    6.31 -        request.write( "<p align='center'><u>%s</u></p>" % self.title )
    6.32 +        request.write( "\n<div class='title'>%s</div>" % self.title )
    6.33 +        
    6.34 +        TabView( self.tab, self.tabStrings, self.urlWriter ).write_BODY( request )
    6.35          
    6.36 -        TabView( tab, self.tabStrings, self.urlWriter ).write_BODY( request )
    6.37 -        
    6.38 -        request.write( "</td></tr><tr><td>" )
    6.39 +        try:
    6.40 +            request.write( "\n<div class='tab'>" )
    6.41 +            render_tab = self.tabObjects[ self.tab ]
    6.42 +            render_tab( self.urlWriter ).write_BODY( request )
    6.43 +            request.write( "\n</div>" )
    6.44 +        except Exception, e:
    6.45 +            request.write( "\n<p>Error Rendering Tab</p>" )
    6.46 +            request.write( "\n<p>%s</p>" % str( e ) )
    6.47 +
    6.48 +        request.write( "\n<input type=\"hidden\" name=\"tab\" value=\"%d\">" % self.tab )
    6.49 +
    6.50 +    def perform( self, request ):
    6.51 +        request.write( "Tab> perform" )
    6.52 +        request.write( "<br/>op: " + str( getVar( 'op', request ) ) )
    6.53 +        request.write( "<br/>args: " + str( getVar( 'args', request ) ) )
    6.54 +        request.write( "<br/>tab: " + str( getVar( 'tab', request ) ) )      
    6.55  
    6.56          try:
    6.57 -            render_tab = self.tabObjects[ tab ]
    6.58 -            render_tab().write_BODY( request )
    6.59 +            action = getVar( 'op', request, 0 )
    6.60 +            if action == "tab":
    6.61 +                self.tab = int( getVar( 'args', request ) )
    6.62 +            else:
    6.63 +                this.tab = int( getVar( 'tab', request, 0 ) )
    6.64 +                self.tabObjects[ self.tab ]( self.urlWriter ).perform( request )
    6.65          except:
    6.66 -            request.write( "<p>Error Rendering Tab</p>" )
    6.67 -       
    6.68 -        request.write( "</td></tr></table>" )
    6.69 -       
    6.70 -    def perform( self, request ):
    6.71 -        try:
    6.72 -            tab = int( getVar( 'tab', request, 0 ) )
    6.73 -        except:
    6.74 -            tab = 0;
    6.75 -            
    6.76 -        op_tab = self.tabObjects[ tab ]
    6.77 -        
    6.78 -        if op_tab:
    6.79 -            op_tab().perform( request )
    6.80 +            pass
    6.81          
    6.82  class PreTab( HTMLBase ):
    6.83  
    6.84 @@ -53,12 +57,9 @@ class PreTab( HTMLBase ):
    6.85          self.source = source
    6.86      
    6.87      def write_BODY( self, request ):
    6.88 -        
    6.89 -        request.write( "<div style='display: block; overflow: auto; border: 0px solid black; width: 540px; padding: 5px; z-index:0; align: center'><pre>" )
    6.90 -        
    6.91 +        request.write( "\n<pre>" )
    6.92          request.write( self.source )
    6.93 -        
    6.94 -        request.write( "</pre></div>" )
    6.95 +        request.write( "\n</pre>" )
    6.96  
    6.97  class GeneralTab( HTMLBase ):
    6.98                          
    6.99 @@ -69,7 +70,7 @@ class GeneralTab( HTMLBase ):
   6.100                          
   6.101      def write_BODY( self, request ): 
   6.102          
   6.103 -        request.write( "<table width='100%' cellspacing='0' cellpadding='0' border='0'>" )
   6.104 +        request.write( "\n<table width='100%' cellspacing='0' cellpadding='0' border='0'>" )
   6.105          
   6.106          def writeAttr( niceName, attr, formatter=None ):
   6.107              if type( attr ) is types.TupleType:
   6.108 @@ -80,7 +81,7 @@ class GeneralTab( HTMLBase ):
   6.109                      temp = formatter( self.dict[ attr ] )
   6.110                  else:
   6.111                      temp = str( self.dict[ attr ] )
   6.112 -                request.write( "<tr><td width='50%%'><p>%s:</p></td><td width='50%%'><p>%s</p></td></tr>" % ( niceName, temp ) )
   6.113 +                request.write( "\n<tr><td width='50%%'><p>%s:</p></td><td width='50%%'><p>%s</p></td></tr>" % ( niceName, temp ) )
   6.114          
   6.115          for niceName, attr in self.titles.items():
   6.116              writeAttr( niceName, attr )
   6.117 @@ -89,16 +90,12 @@ class GeneralTab( HTMLBase ):
   6.118  
   6.119  class NullTab( HTMLBase ):
   6.120      
   6.121 -    def __init__( self ):
   6.122 -        HTMLBase.__init__( self )
   6.123 -        self.title = "Null Tab"
   6.124 -
   6.125 -    def __init__( self, title ):
   6.126 +    def __init__( self, title="Null Tab" ):
   6.127          HTMLBase.__init__( self )
   6.128          self.title = title
   6.129 -        
   6.130 +
   6.131      def write_BODY( self, request ):
   6.132 -        request.write( "<p>%s</p>" % self.title )
   6.133 +        request.write( "\n<p>%s</p>" % self.title )
   6.134  
   6.135  class ActionTab( HTMLBase ):
   6.136  
   6.137 @@ -107,29 +104,44 @@ class ActionTab( HTMLBase ):
   6.138          HTMLBase.__init__( self )
   6.139          
   6.140      def write_BODY( self, request ):
   6.141 -        request.write( "<p align='center'><table cellspacing='3' cellpadding='2' border='0'><tr>" )
   6.142 -    
   6.143 -        for ( command, text ) in self.actions.items():
   6.144 -            request.write( "<td style='border: 1px solid black; background-color: grey' onmouseover='buttonMouseOver( this )' onmouseout='buttonMouseOut( this )'>" )
   6.145 -            request.write( "<p><a href='javascript: doOp( \"%s\" );'>%s</a></p></td>" % (command, text) )
   6.146 - 
   6.147 -        request.write("</table></p>")        
   6.148 -        
   6.149 +        for item in self.actions.items():
   6.150 +            try:
   6.151 +                ((op, attr), title) = item
   6.152 +            except:
   6.153 +                (op, title) = item
   6.154 +                attr = ""
   6.155 +            request.write( "\n<div class='button' onclick=\"doOp2( '%s', '%s' )\">%s</a></div>" % (op, attr, title) )
   6.156 +
   6.157  class CompositeTab( HTMLBase ):
   6.158  
   6.159 -    def __init__( self, tabs ):
   6.160 +    def __init__( self, tabs, urlWriter ):
   6.161      	HTMLBase.__init__( self )
   6.162          self.tabs = tabs
   6.163 +        self.urlWriter = urlWriter
   6.164          
   6.165      def write_BODY( self, request ):
   6.166      	for tab in self.tabs:
   6.167 -            request.write( "<br/>" )
   6.168 -            tab().write_BODY( request )
   6.169 +            tab( self.urlWriter ).write_BODY( request )
   6.170              
   6.171      def perform( self, request ):
   6.172      	for tab in self.tabs:
   6.173 -            tab().perform( request )
   6.174 -    
   6.175 -    
   6.176 -       
   6.177 -        
   6.178 +            tab( self.urlWriter ).perform( request )
   6.179 +
   6.180 +class TabView( HTMLBase ):
   6.181 +
   6.182 +        # tab - int, id into tabs of selected tab
   6.183 +        # tabs - list of strings, tab names
   6.184 +        # urlWriter -
   6.185 +        def __init__( self, tab, tabs, urlWriter ):
   6.186 +            HTMLBase.__init__(self)
   6.187 +            self.tab = tab
   6.188 +            self.tabs = tabs
   6.189 +            self.urlWriter = urlWriter
   6.190 +
   6.191 +        def write_BODY( self, request ):
   6.192 +            for i in range( len( self.tabs ) ):
   6.193 +                if self.tab == i:
   6.194 +                    at = " id='activeTab'"
   6.195 +                else:
   6.196 +                    at = ""
   6.197 +                request.write( "\n<div%s class='tabButton' onclick=\"doOp2( 'tab', '%d' )\">%s</div>" % ( at, i, self.tabs[ i ] ) )
     7.1 --- a/tools/python/xen/sv/HTMLBase.py	Tue Aug 09 10:47:41 2005 +0000
     7.2 +++ b/tools/python/xen/sv/HTMLBase.py	Tue Aug 09 13:04:31 2005 +0000
     7.3 @@ -12,26 +12,17 @@ class HTMLBase:
     7.4          return self.render_GET( request )
     7.5          
     7.6      def render_GET( self, request ):
     7.7 -        self.write_TOP( request )
     7.8 -        self.write_BODY( request )
     7.9 -        self.write_BOTTOM( request )
    7.10 -        return ''
    7.11 -                
    7.12 +        pass
    7.13 +    
    7.14      def write_BODY( self, request ):
    7.15 -        request.write( "BODY" )
    7.16 +        pass
    7.17          
    7.18      def write_TOP( self, request ):
    7.19 -        request.write( '<html><head><title>Xen</title><link rel="stylesheet" type="text/css" href="inc/style.css" />' )
    7.20 -        request.write( '<script src="inc/script.js"></script>' )
    7.21 -        request.write( '</head><body>' )
    7.22 -        request.write('<form method="post" action="%s">' % request.uri)
    7.23 -
    7.24 +        pass
    7.25 +    
    7.26      def write_BOTTOM( self, request ):
    7.27 -        request.write('<input type="hidden" name="op" value="">')
    7.28 -        request.write('<input type="hidden" name="args" value="">')
    7.29 -        request.write('</form>')
    7.30 -        request.write( "</body></html>" )
    7.31 -
    7.32 +        pass
    7.33 +    
    7.34      def get_op_method(self, op):
    7.35          """Get the method for an operation.
    7.36          For operation 'foo' looks for 'op_foo'.
     8.1 --- a/tools/python/xen/sv/Main.py	Tue Aug 09 10:47:41 2005 +0000
     8.2 +++ b/tools/python/xen/sv/Main.py	Tue Aug 09 13:04:31 2005 +0000
     8.3 @@ -1,113 +1,90 @@
     8.4 +
     8.5  from xen.sv.HTMLBase import HTMLBase
     8.6 -from xen.sv.DomList  import DomList
     8.7  from xen.sv.NodeInfo import NodeInfo
     8.8  from xen.sv.DomInfo  import DomInfo
     8.9  from xen.sv.CreateDomain import CreateDomain
    8.10 -from xen.sv.MigrateDomain import MigrateDomain
    8.11 -from xen.sv.SaveDomain import SaveDomain
    8.12  from xen.sv.RestoreDomain import RestoreDomain
    8.13  
    8.14 -from xen.xend.XendClient import server
    8.15 -
    8.16  from xen.sv.util import getVar
    8.17  
    8.18 -class Main( HTMLBase ):
    8.19 -    
    8.20 -    isLeaf = True
    8.21 -
    8.22 -    def __init__( self, urlWriter = None ):
    8.23 -        self.modules = { "node": NodeInfo, 
    8.24 -                         "list": DomList, 
    8.25 -                         "info": DomInfo,
    8.26 -                         "create": CreateDomain,
    8.27 -                         "migrate" : MigrateDomain,
    8.28 -                         "save" : SaveDomain,
    8.29 -                         "restore" : RestoreDomain }
    8.30 +# adapter to make this all work with mod_python
    8.31 +# as opposed to Twisted
    8.32 +# (c) Tom Wilkie 2005
    8.33  
    8.34 -        # ordered list of module menus to display
    8.35 -        self.module_menus = [ "node", "create", "migrate", "save",
    8.36 -                              "restore", "list" ]
    8.37 -        HTMLBase.__init__(self)
    8.38 -        
    8.39 -    def render_POST( self, request ):
    8.40 -    
    8.41 -    	#decide what module post'd the action
    8.42 -                
    8.43 -    	args = getVar( 'args', request )
    8.44 +class Args:
    8.45 +    def __init__( self, req ):
    8.46 +        from mod_python.util import FieldStorage
    8.47 +        self.fieldStorage = FieldStorage( req, True )
    8.48  
    8.49 -        mod = getVar( 'mod', request )
    8.50 -                
    8.51 -        if not mod is None and args is None:
    8.52 -            module = self.modules[ mod ]
    8.53 -            #check module exists
    8.54 -            if module:
    8.55 -               module( self.mainUrlWriter ).perform( request )
    8.56 +    # return a list of values for the given key,
    8.57 +    # or None if key not there
    8.58 +    def get( self, var ):
    8.59 +        retVar = self.fieldStorage.getlist( var )
    8.60 +        if len( retVar ) == 0:
    8.61 +            return None
    8.62          else:
    8.63 -            self.perform( request )     
    8.64 -    
    8.65 -        return self.render_GET( request )
    8.66 +            return retVar
    8.67 +
    8.68 +    # return a list of tuples,
    8.69 +    # (key, value) where value is a list of values
    8.70 +    def items( self ):
    8.71 +        result = [];
    8.72 +        for key in self.fieldStorage.keys():
    8.73 +            result.append( (key, self.fieldStorage.getlist( key ) ) )
    8.74 +        return result
    8.75 +                                                                                                                                                            
    8.76 +class TwistedAdapter:
    8.77 +    def __init__( self, req ):
    8.78 +        self.args = Args( req )
    8.79 +        self.uri = req.unparsed_uri
    8.80 +        self.url = req.uri
    8.81 +        self.write = req.write
    8.82 +
    8.83 +# This is the Main class
    8.84 +# It peices together all the modules
    8.85  
    8.86 -    def mainUrlWriter( self, module ):
    8.87 -    	def fun( f ):
    8.88 -            return "Main.rpy?mod=%s%s" % ( module, f )
    8.89 -        return fun    
    8.90 -        
    8.91 -    def write_BODY( self, request ):
    8.92 -    
    8.93 -        request.write( "\n<table style='border:0px solid black; background: url(images/orb_01.jpg) no-repeat' cellspacing='0' cellpadding='0' border='0' width='780px' height='536px'>\n" )
    8.94 -        request.write( "<tr>\n" )
    8.95 -        request.write( " <td width='15px'>&nbsp;</td>" )
    8.96 -        request.write( " <td width='175px' align='center' valign'center'>" )
    8.97 -        request.write( "  <table cellspacing='0' cellpadding='0' border='0' width='100%' height='100%'>" )
    8.98 -        request.write( "   <tr><td height='140px' align='center' valign='bottom'><a href='http://www.cl.cam.ac.uk/Research/SRG/netos/xen/'>" )
    8.99 -        request.write( "   <img src='images/xen.png' width='150' height='75' border='0'/></a><br/></td></tr>" )
   8.100 -        request.write( "   <tr><td height='60px' align='center'><p class='small'>SV Web Interface<br/>(C) <a href='mailto:tw275@cam.ac.uk'>Tom Wilkie</a> 2004</p></td></tr>")
   8.101 -        request.write( "   <tr><td align='center' valign='top'>" )
   8.102 +class Main:
   8.103 +    def __init__( self ):
   8.104 +        self.modules = { "node": NodeInfo, 
   8.105 +                         "create": CreateDomain,
   8.106 +                         "restore" : RestoreDomain,
   8.107 +                         "info": DomInfo }
   8.108 +
   8.109 +        self.init_done = False
   8.110 +
   8.111 +    def init_modules( self, request ):
   8.112 +        for moduleName, module in self.modules.iteritems():
   8.113 +            self.modules[ moduleName ] = module( self.urlWriter( moduleName, request.url ) )             
   8.114  
   8.115 -        for modName in self.module_menus:
   8.116 -            self.modules[modName]( self.mainUrlWriter( modName ) ).write_MENU( request )
   8.117 -        
   8.118 -        request.write( "   </td></tr>" )
   8.119 -        request.write( "  </table>" )
   8.120 -        request.write( " &nbsp;" )
   8.121 -        request.write( " </td>\n" )
   8.122 -        request.write( " <td width='15px'>&nbsp;</td>" )
   8.123 -        request.write( " <td width='558px' align='left' valign='top'>" )
   8.124 -        request.write( "  <table cellspacing='0' cellpadding='0' border='0' width='100%' height='100%'>" )
   8.125 -        request.write( "   <tr><td height='20px'></td></tr>" )
   8.126 -        request.write( "   <tr><td align='center' valign='top'>" )
   8.127 -        
   8.128 -        modName = getVar('mod', request)
   8.129 -        
   8.130 -        if modName is None:
   8.131 +    def render_menu( self, request ):
   8.132 +        if not self.init_done:
   8.133 +            self.init_modules( request )
   8.134 +            self.init_done = True
   8.135 +            
   8.136 +        for moduleName, module in self.modules.iteritems():
   8.137 +            module.write_MENU( request )
   8.138 +            request.write( "\n" )
   8.139 +
   8.140 +    def render_main( self, request ):
   8.141 +        if not self.init_done:
   8.142 +            self.init_modules( request )
   8.143 +            self.init_done = True
   8.144 +                                   
   8.145 +        moduleName = getVar('mod', request)
   8.146 +        if moduleName not in self.modules:
   8.147              request.write( '<p>Please select a module</p>' )
   8.148          else:
   8.149 -            module = self.modules[ modName ]
   8.150 -            if module:
   8.151 -               module( self.mainUrlWriter( modName ) ).write_BODY( request )  
   8.152 -            else:
   8.153 -               request.write( '<p>Invalid module. Please select another</p>' )
   8.154 -    
   8.155 -        request.write( "   </td></tr>" )
   8.156 -        request.write( "  </table>" )
   8.157 -        request.write( " </td>\n" )
   8.158 -        request.write( " <td width='17px'>&nbsp;</td>" )
   8.159 -        request.write( "</tr>\n" )
   8.160 -        
   8.161 -        request.write( "</table>\n" )
   8.162 +            module = self.modules[ moduleName ]
   8.163 +            module.write_BODY( request )
   8.164 +
   8.165 +    def do_POST( self, request ): 
   8.166 +        if not self.init_done:
   8.167 +            self.init_modules( request )
   8.168 +            self.init_done = True                       
   8.169          
   8.170 -                
   8.171 -    def op_destroy( self, request ):
   8.172 -    	dom = getVar( 'dom', request )
   8.173 -        if not dom is None and dom != "0":
   8.174 -            server.xend_domain_destroy( int( dom ), "halt" ) 
   8.175 -                 
   8.176 -    def op_pause( self, request ):
   8.177 -    	dom = getVar( 'dom', request )
   8.178 -        if not dom is None and dom != "0":
   8.179 -            server.xend_domain_pause( int( dom ) )      
   8.180 -    
   8.181 -    def op_unpause( self, request ):
   8.182 -    	dom = getVar( 'dom', request )
   8.183 -        if not dom is None and dom != "0":
   8.184 -            server.xend_domain_unpause( int( dom ) )      
   8.185 +    	moduleName = getVar( 'mod', request )      
   8.186 +        if moduleName in self.modules:
   8.187 +            self.modules[ moduleName ].perform( request )
   8.188 +
   8.189 +    def urlWriter( self, module, url ):
   8.190 +        return lambda x: "%s?mod=%s%s" % ( url, module, x )
     9.1 --- a/tools/python/xen/sv/MigrateDomain.py	Tue Aug 09 10:47:41 2005 +0000
     9.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.3 @@ -1,74 +0,0 @@
     9.4 -from xen.sv.Wizard import *
     9.5 -from xen.sv.util import *
     9.6 -from xen.sv.GenTabbed import PreTab
     9.7 -
     9.8 -from xen.xm.create import make_config, OptVals
     9.9 -
    9.10 -from xen.xend.XendClient import server
    9.11 -
    9.12 -class MigrateDomain( Wizard ):
    9.13 -    def __init__( self, urlWriter ):
    9.14 -
    9.15 -        sheets = [ ChooseMigrateDomain,
    9.16 -                   DoMigrate ]
    9.17 -
    9.18 -        Wizard.__init__( self, urlWriter, "Migrate Domain", sheets )
    9.19 -
    9.20 -
    9.21 -class ChooseMigrateDomain( Sheet ):
    9.22 -    def __init__( self, urlWriter ):
    9.23 -        Sheet.__init__( self, urlWriter, "Configure Migration", 0)
    9.24 -	domains = []
    9.25 -	domnames = []
    9.26 -
    9.27 -        try:
    9.28 -            domains = server.xend_domains()
    9.29 -            domains.sort()
    9.30 -        except:
    9.31 -            pass
    9.32 -
    9.33 -        for i in domains:
    9.34 -            if i != 'Domain-0': domnames.append((i,i))
    9.35 -        
    9.36 -        self.addControl( ListControl('domid',
    9.37 -                                     domnames,
    9.38 -                                     'Domain ID:') )
    9.39 -        self.addControl( TickControl('live',
    9.40 -                                     'True',
    9.41 -                                     'Live migrate:') )
    9.42 -        self.addControl( InputControl('rate',
    9.43 -                                      '0',
    9.44 -                                      'Rate limit:') )
    9.45 -        self.addControl( InputControl( 'dest', 'myhost.mydomain',
    9.46 -                                       'Name or IP address:',
    9.47 -                                       ".*") )
    9.48 -
    9.49 -class DoMigrate( Sheet ):
    9.50 -    def __init__(self, urlWriter ):
    9.51 -        Sheet.__init__(self, urlWriter, "Migration Done", 1)
    9.52 -
    9.53 -    def write_BODY( self, request, err ):
    9.54 -
    9.55 -        if not self.passback: self.parseForm( request )
    9.56 -
    9.57 -#        print string2sxp(self.passback)
    9.58 -        
    9.59 -        config = ssxp2hash ( string2sxp( self.passback ) )
    9.60 -      
    9.61 -        try:
    9.62 -            print config
    9.63 -            print config['domid'], config['dest']
    9.64 -            dom_sxp = server.xend_domain_migrate( config['domid'],
    9.65 -                                                  config['dest'],
    9.66 -                                                  config.get('live') == 'True',
    9.67 -                                                  config['rate'] )
    9.68 -            success = "Your domain was successfully Migrated.\n"
    9.69 -        except Exception, e:
    9.70 -            success = "There was an error migrating your domain\n"
    9.71 -            dom_sxp = str(e)
    9.72 -        
    9.73 -        pt = PreTab( success + dom_sxp ) # sxp2prettystring( dom_sxp ) )
    9.74 -        pt.write_BODY( request )
    9.75 -
    9.76 -        request.write( "<input type='hidden' name='passback' value=\"%s\"></p>" % self.passback )
    9.77 -        request.write( "<input type='hidden' name='sheet' value='%s'></p>" % self.location )
    10.1 --- a/tools/python/xen/sv/NodeInfo.py	Tue Aug 09 10:47:41 2005 +0000
    10.2 +++ b/tools/python/xen/sv/NodeInfo.py	Tue Aug 09 13:04:31 2005 +0000
    10.3 @@ -6,18 +6,18 @@ from xen.sv.GenTabbed import *
    10.4  class NodeInfo( GenTabbed ):
    10.5  
    10.6      def __init__( self, urlWriter ):  
    10.7 -        GenTabbed.__init__( self, "Node Details", urlWriter, [ 'General', 'Dmesg', ], [ NodeGeneralTab, NodeDmesgTab ] )
    10.8 +        GenTabbed.__init__( self, "Node Details", urlWriter, [ 'General', 'Dmesg', 'SXP' ], [ NodeGeneralTab, NodeDmesgTab, NodeSXPTab ] )
    10.9      
   10.10      def write_MENU( self, request ):
   10.11          request.write( "<p class='small'><a href='%s'>Node details</a></p>" % self.urlWriter( '' ) )
   10.12  
   10.13  class NodeGeneralTab( CompositeTab ):
   10.14 -    def __init__( self ):
   10.15 -    	CompositeTab.__init__( self, [ NodeInfoTab, NodeActionTab ] )        
   10.16 +    def __init__( self, urlWriter ):
   10.17 +    	CompositeTab.__init__( self, [ NodeInfoTab, NodeActionTab ], urlWriter )        
   10.18          
   10.19  class NodeInfoTab( GeneralTab ):
   10.20                          
   10.21 -    def __init__( self ):
   10.22 +    def __init__( self, urlWriter ):
   10.23           
   10.24      	nodeInfo = {}
   10.25          try:
   10.26 @@ -41,7 +41,7 @@ class NodeInfoTab( GeneralTab ):
   10.27  
   10.28  class NodeDmesgTab( PreTab ):
   10.29  
   10.30 -    def __init__( self ):
   10.31 +    def __init__( self, urlWriter ):
   10.32      	try:
   10.33              dmesg = server.xend_node_get_dmesg()
   10.34          except:
   10.35 @@ -50,7 +50,7 @@ class NodeDmesgTab( PreTab ):
   10.36    
   10.37  class NodeActionTab( ActionTab ):
   10.38  
   10.39 -    def __init__( self ):
   10.40 +    def __init__( self, urlWriter ):
   10.41          ActionTab.__init__( self, { "shutdown" : "shutdown",
   10.42          	"reboot" : "reboot" } )    
   10.43          
   10.44 @@ -61,3 +61,13 @@ class NodeActionTab( ActionTab ):
   10.45      def op_reboot( self, request ):
   10.46          if debug: print ">NodeReboot"
   10.47          server.xend_node_reboot()
   10.48 +
   10.49 +class NodeSXPTab( PreTab ):
   10.50 +
   10.51 +    def __init__( self, urlWriter ):
   10.52 +        try:
   10.53 +            nodeSXP = sxp2string( server.xend_node() )
   10.54 +        except:
   10.55 +            nodeSXP = 'Error getting node sxp'
   10.56 +
   10.57 +        PreTab.__init__( self, nodeSXP )
    11.1 --- a/tools/python/xen/sv/RestoreDomain.py	Tue Aug 09 10:47:41 2005 +0000
    11.2 +++ b/tools/python/xen/sv/RestoreDomain.py	Tue Aug 09 13:04:31 2005 +0000
    11.3 @@ -16,6 +16,8 @@ class RestoreDomain( Wizard ):
    11.4  
    11.5  
    11.6  class ChooseRestoreDomain( Sheet ):
    11.7 +    title = "Configure Restore"
    11.8 +
    11.9      def __init__( self, urlWriter ):
   11.10          Sheet.__init__( self, urlWriter, "Configure Restore", 0)
   11.11          
   11.12 @@ -24,6 +26,8 @@ class ChooseRestoreDomain( Sheet ):
   11.13                                         ".*") )
   11.14  
   11.15  class DoRestore( Sheet ):
   11.16 +    title = "Restore Done"
   11.17 +    
   11.18      def __init__(self, urlWriter ):
   11.19          Sheet.__init__(self, urlWriter, "Restore Done", 1)
   11.20  
    12.1 --- a/tools/python/xen/sv/SaveDomain.py	Tue Aug 09 10:47:41 2005 +0000
    12.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.3 @@ -1,62 +0,0 @@
    12.4 -from xen.sv.Wizard import *
    12.5 -from xen.sv.util import *
    12.6 -from xen.sv.GenTabbed import PreTab
    12.7 -
    12.8 -from xen.xm.create import make_config, OptVals
    12.9 -
   12.10 -from xen.xend.XendClient import server
   12.11 -
   12.12 -class SaveDomain( Wizard ):
   12.13 -    def __init__( self, urlWriter ):
   12.14 -
   12.15 -        sheets = [ ChooseSaveDomain,
   12.16 -                   DoSave ]
   12.17 -
   12.18 -        Wizard.__init__( self, urlWriter, "Save Domain", sheets )
   12.19 -
   12.20 -
   12.21 -class ChooseSaveDomain( Sheet ):
   12.22 -    def __init__( self, urlWriter ):
   12.23 -        Sheet.__init__( self, urlWriter, "Configure Save", 0)
   12.24 -        
   12.25 -	domains = []
   12.26 -	domnames = []
   12.27 -
   12.28 -	try:
   12.29 -            domains = server.xend_domains()
   12.30 -            domains.sort()
   12.31 -        except:
   12.32 -            pass
   12.33 -
   12.34 -        for i in domains:
   12.35 -            if i != 'Domain-0': domnames.append((i,i))
   12.36 -        
   12.37 -        self.addControl( ListControl('domid',
   12.38 -                                     domnames,
   12.39 -                                     'Domain ID:') )
   12.40 -        self.addControl( InputControl( 'file', '',
   12.41 -                                       'Suspend file name:',
   12.42 -                                       ".*") )
   12.43 -
   12.44 -class DoSave( Sheet ):
   12.45 -    def __init__(self, urlWriter ):
   12.46 -        Sheet.__init__(self, urlWriter, "Save Done", 1)
   12.47 -
   12.48 -    def write_BODY( self, request, err ):
   12.49 -
   12.50 -        if not self.passback: self.parseForm( request )
   12.51 -        config = ssxp2hash ( string2sxp( self.passback ) )
   12.52 -      
   12.53 -        try:
   12.54 -            dom_sxp = server.xend_domain_save( config['domid'],
   12.55 -                                                  config['file'] )
   12.56 -            success = "Your domain was successfully saved.\n"
   12.57 -        except Exception, e:
   12.58 -            success = "There was an error saving your domain\n"
   12.59 -            dom_sxp = str(e)
   12.60 -        
   12.61 -        pt = PreTab( success + dom_sxp ) # sxp2prettystring( dom_sxp ) )
   12.62 -        pt.write_BODY( request )
   12.63 -
   12.64 -        request.write( "<input type='hidden' name='passback' value=\"%s\"></p>" % self.passback )
   12.65 -        request.write( "<input type='hidden' name='sheet' value='%s'></p>" % self.location )
    13.1 --- a/tools/python/xen/sv/TabView.py	Tue Aug 09 10:47:41 2005 +0000
    13.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.3 @@ -1,26 +0,0 @@
    13.4 -from xen.sv.HTMLBase import HTMLBase
    13.5 -
    13.6 -class TabView( HTMLBase ):
    13.7 -
    13.8 -    # tab - int, id into tabs of selected tab
    13.9 -    # tabs - list of strings, tab names
   13.10 -    # urlWriter - 
   13.11 -    def __init__( self, tab, tabs, urlWriter ):
   13.12 -        HTMLBase.__init__(self)
   13.13 -        self.tab = tab
   13.14 -        self.tabs = tabs
   13.15 -        self.urlWriter = urlWriter
   13.16 -
   13.17 -    def write_BODY( self, request ):
   13.18 -        request.write( "<table style='' border='0' cellspacing='3' cellpadding='2' align='center'>" )
   13.19 -        request.write( "<tr height='22'>" )                  
   13.20 -    
   13.21 -        for i in range( len( self.tabs ) ):
   13.22 -            if self.tab == i:
   13.23 -                backgroundColor = "white"
   13.24 -            else:
   13.25 -                backgroundColor = "grey"
   13.26 -        
   13.27 -            request.write( "<td style='border:1px solid black; background-color: %s'><p align='center'><a href='%s'>%s</a></p></td>" % ( backgroundColor, self.urlWriter( "&tab=%s" % i ), self.tabs[ i ] ) )
   13.28 -  
   13.29 -        request.write( "</tr></table>" )
    14.1 --- a/tools/python/xen/sv/Wizard.py	Tue Aug 09 10:47:41 2005 +0000
    14.2 +++ b/tools/python/xen/sv/Wizard.py	Tue Aug 09 13:04:31 2005 +0000
    14.3 @@ -1,71 +1,44 @@
    14.4  from xen.sv.util import *
    14.5  from xen.sv.HTMLBase import HTMLBase
    14.6 +from xen.sv.GenTabbed import GenTabbed, ActionTab
    14.7  from xen.xend import sxp
    14.8  
    14.9  import re
   14.10  
   14.11  DEBUG = 0
   14.12  
   14.13 -class Wizard( HTMLBase ):
   14.14 +class Wizard( GenTabbed ):
   14.15  
   14.16      def __init__( self, urlWriter, title, sheets ):
   14.17 -        HTMLBase.__init__( self )
   14.18          self.title = title
   14.19          self.sheets = sheets
   14.20          self.urlWriter = urlWriter
   14.21 +        self.offset = 0
   14.22 +        GenTabbed.__init__( self, title, urlWriter, map( lambda x: x.title, sheets ), sheets ) 
   14.23          
   14.24      def write_MENU( self, request ):
   14.25      	request.write( "<p class='small'><a href='%s'>%s</a></p>" % (self.urlWriter( '' ), self.title) ) 
   14.26      
   14.27      def write_BODY( self, request ):
   14.28 -        
   14.29 -   	request.write( "<table width='100%' border='0' cellspacing='0' cellpadding='0'><tr><td>" )
   14.30 -        request.write( "<p align='center'><u>%s</u></p></td></tr><tr><td>" % self.title )
   14.31 -        
   14.32 -        currSheet = getVar( 'sheet', request )
   14.33 -    
   14.34 -        if not currSheet is None:
   14.35 -            currSheet = int( currSheet )
   14.36 -        else:
   14.37 -            currSheet = 0
   14.38 +        GenTabbed.write_BODY( self, request )
   14.39 +        actionTab = ActionTab( { ("tab", str(self.tab-1)) : "< Prev", ("tab", str(self.tab+1)) : "Next >", "finish" : "Finish" } )
   14.40 +        actionTab.write_BODY( request )
   14.41 +
   14.42 +    def perform( self, request ):
   14.43 +        try:
   14.44 +            action = getVar( 'op', request, 0 )
   14.45 +            if action == "tab":
   14.46 +                self.tab = int( getVar( 'args', request ) )
   14.47 +                oldtab = int( getVar( 'tab', request ) )
   14.48 +                if not self.tabObjects[ oldtab ]( self.urlWriter ).validate( request ):
   14.49 +                    self.tab = oldtab
   14.50 +            else:
   14.51 +                self.tab = int( getVar( 'tab', request, 0 ) )
   14.52 +                self.tabObjects[ self.tab ]( self.urlWriter ).perform( request )
   14.53 +                getattr( self, "op_" +  getVar( "op", request ), None )( request )
   14.54 +        except:
   14.55 +            pass
   14.56              
   14.57 -        sheet = self.sheets[ currSheet ]( self.urlWriter )
   14.58 -        
   14.59 -        err = not sheet.validate( request )
   14.60 -        
   14.61 -        if not err:    
   14.62 -            op = getVar( 'op', request )
   14.63 -        
   14.64 -            if op == 'next':
   14.65 -               currSheet += 1
   14.66 -            elif op == 'prev':
   14.67 -               currSheet -= 1
   14.68 -             
   14.69 -            sheet = self.sheets[ currSheet ]( self.urlWriter )
   14.70 -        
   14.71 -        if getVar( 'visited-sheet%s' % currSheet, request ):
   14.72 -            sheet.write_BODY( request, err )
   14.73 -        else:
   14.74 -            sheet.write_BODY( request, False )
   14.75 -
   14.76 -        
   14.77 -        request.write( "</td></tr><tr><td><table width='100%' border='0' cellspacing='0' cellpadding='0'><tr>" )
   14.78 -        request.write( "<td width='80%'></td><td width='20%' align='center'><p align='center'>" )
   14.79 -	if currSheet > 0:
   14.80 -       	    request.write( "<img src='images/previous.png' onclick='doOp( \"prev\" )' onmouseover='update( \"wizText\", \"Previous\" )' onmouseout='update( \"wizText\", \"&nbsp;\" )'>&nbsp;" )
   14.81 -        if currSheet < ( len( self.sheets ) - 2 ):        
   14.82 -            request.write( "<img src='images/next.png' onclick='doOp( \"next\" )' onmouseover='update( \"wizText\", \"Next\" )' onmouseout='update( \"wizText\", \"&nbsp;\" )'>" )
   14.83 -        elif currSheet == ( len( self.sheets ) - 2 ):
   14.84 -            request.write( "<img src='images/finish.png' onclick='doOp( \"next\" )' onmouseover='update( \"wizText\", \"Finish\" )' onmouseout='update( \"wizText\", \"&nbsp;\" )'>" )
   14.85 -        request.write( "</p><p align='center'><span id='wizText'></span></p></td></tr></table>" )
   14.86 -        request.write( "</td></tr></table>" )
   14.87 -        
   14.88 -    def op_next( self, request ):
   14.89 -    	pass
   14.90 -        
   14.91 -    def op_prev( self, request ):
   14.92 -    	pass
   14.93 -        
   14.94      def op_finish( self, request ):
   14.95      	pass  
   14.96          
   14.97 @@ -80,7 +53,7 @@ class Sheet( HTMLBase ):
   14.98          self.passback = None
   14.99          
  14.100      def parseForm( self, request ):
  14.101 -    	do_not_parse = [ 'mod', 'op', 'sheet', 'passback' ] 
  14.102 +    	do_not_parse = [ 'mod', 'op', 'passback' ] 
  14.103      
  14.104      	passed_back = request.args
  14.105          
  14.106 @@ -103,7 +76,7 @@ class Sheet( HTMLBase ):
  14.107          
  14.108          if DEBUG: print self.passback
  14.109          
  14.110 -    def write_BODY( self, request, err ):
  14.111 +    def write_BODY( self, request ):
  14.112      
  14.113      	if not self.passback: self.parseForm( request )
  14.114          
  14.115 @@ -115,14 +88,13 @@ class Sheet( HTMLBase ):
  14.116          
  14.117      	for (feild, control) in self.feilds:
  14.118              control.write_Control( request, previous_values.get( feild ) )
  14.119 -            if err and not control.validate( previous_values.get( feild ) ):
  14.120 +            if previous_values.get( feild ) is not None and not control.validate( previous_values.get( feild ) ):
  14.121              	control.write_Help( request )
  14.122              
  14.123          request.write( "</table>" )
  14.124              
  14.125          request.write( "<input type='hidden' name='passback' value=\"%s\"></p>" % self.passback )
  14.126 -        request.write( "<input type='hidden' name='sheet' value='%s'></p>" % self.location )
  14.127 -        request.write( "<input type='hidden' name='visited-sheet%s' value='True'></p>" % self.location )
  14.128 +        #request.write( "<input type='hidden' name='visited-sheet%s' value='True'></p>" % self.location )
  14.129                  
  14.130      def addControl( self, control ):
  14.131      	self.feilds.append( [ control.getName(), control ] )
  14.132 @@ -133,7 +105,7 @@ class Sheet( HTMLBase ):
  14.133              
  14.134      	check = True
  14.135          
  14.136 -        previous_values = ssxp2hash( string2sxp( self.passback ) ) #get the hash for quick reference
  14.137 +        previous_values = ssxp2hash( string2sxp( self.passback ) ) #get the map for quick reference
  14.138      	if DEBUG: print previous_values
  14.139        
  14.140        	for (feild, control) in self.feilds:
  14.141 @@ -258,12 +230,16 @@ class TickControl( SheetControl ):
  14.142          
  14.143      def write_Control( self, request, persistedValue ):
  14.144          request.write( "<tr><td width='50%%'><p>%s</p></td><td width='50%%'>" % self.humanText )
  14.145 +
  14.146 +        #request.write( str( persistedValue ) )
  14.147 +
  14.148 +        #TODO: Theres a problem with this: it doesn't persist an untick, because the browsers don't pass it back. Need a fix...
  14.149          
  14.150          if persistedValue == 'True':
  14.151      	    request.write( "<input type='checkbox' name='%s' value='True' checked>" % self.getName() )
  14.152          else:
  14.153      	    request.write( "<input type='checkbox' name='%s' value='True'>" % self.getName() )
  14.154              
  14.155 -        request.write( "</select></td></tr>" )
  14.156 +        request.write( "</td></tr>" )
  14.157  
  14.158        
    15.1 --- a/tools/python/xen/sv/params.py	Tue Aug 09 10:47:41 2005 +0000
    15.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.3 @@ -1,3 +0,0 @@
    15.4 -SV_PORT = 8080
    15.5 -SV_ROOT = "/var/lib/xen/sv/"
    15.6 -PID_FILE = "/var/run/xen-sv.pid"
    16.1 --- a/tools/python/xen/sv/util.py	Tue Aug 09 10:47:41 2005 +0000
    16.2 +++ b/tools/python/xen/sv/util.py	Tue Aug 09 13:04:31 2005 +0000
    16.3 @@ -4,7 +4,7 @@ from xen.xend import PrettyPrint
    16.4  
    16.5  import types
    16.6  
    16.7 -def getDomInfoHash( domain ):
    16.8 +def getDomInfo( domain ):
    16.9      domInfoHash = {}
   16.10      try:
   16.11          domInfoHash = sxp2hash( server.xend_domain( domain ) )
    17.1 Binary file tools/sv/images/internet.jpg has changed
    18.1 Binary file tools/sv/images/internet.psd has changed
    19.1 Binary file tools/sv/images/orb_01.jpg has changed
    20.1 Binary file tools/sv/images/orb_02.jpg has changed
    21.1 Binary file tools/sv/images/seperator-left-highlight.jpg has changed
    22.1 Binary file tools/sv/images/seperator-right-highlight.jpg has changed
    23.1 Binary file tools/sv/images/seperator.jpg has changed
    24.1 --- a/tools/sv/inc/style.css	Tue Aug 09 10:47:41 2005 +0000
    24.2 +++ b/tools/sv/inc/style.css	Tue Aug 09 13:04:31 2005 +0000
    24.3 @@ -1,32 +1,95 @@
    24.4 +.small  {
    24.5 +	font-size: 10px
    24.6 +}
    24.7  
    24.8 -P       {font-family: verdana, arial; font-size: 12px; color: black}
    24.9 -.small  {font-size: 10px}
   24.10 +TD.domainInfo     { 
   24.11 +	font-size: 10px; 
   24.12 +	color: black
   24.13 +}
   24.14  
   24.15 -TD.domainInfo     {font-family: verdana, arial; font-size: 10px; color: black}
   24.16 -TD.domainInfoHead {font-family: verdana, arial; font-size: 10px; color: white; font-face: bold}
   24.17 +TD.domainInfoHead {
   24.18 +	font-size: 10px; 
   24.19 +	color: white; 
   24.20 +	font-face: bold
   24.21 +}
   24.22  
   24.23  TD.domainInfoHead {background-color: black}
   24.24  TR.domainInfoOdd  {background-color: white}
   24.25  TR.domainInfoEven {background-color: lightgrey}
   24.26  
   24.27  body { 
   24.28 -	width: 670px;
   24.29 -	margin: 0px;
   24.30 -	padding: 0px;
   24.31 -	background-color: #fff;
   24.32 -	background-image: url(../images/orb_02.jpg);
   24.33 -	background-repeat: repeat-y;
   24.34 -	background-position: left top;
   24.35 -	font-family: Arial, Helvetica, sans-serif;
   24.36 -	font-weight: bold;
   24.37 -	color: #333333;
   24.38 -	letter-spacing: 0px;
   24.39 -	scrollbar-base-color: #333333;
   24.40 -	scrollbar-track-color: #666666;
   24.41 -	scrollbar-face-color: #fff;
   24.42 -	
   24.43 -	
   24.44 -	}
   24.45 -        
   24.46 -.button (cursor:hand)
   24.47 -	
   24.48 +	margin: 	0px;
   24.49 +	padding: 	0px;
   24.50 +	font-family: 	Arial, Helvetica, sans-serif;
   24.51 +	font-size:	12px;
   24.52 +	color: 		#000000;
   24.53 +}
   24.54 +
   24.55 +div#menu {
   24.56 +        position:       absolute;
   24.57 +        left:           10px;
   24.58 +        top:            10px;
   24.59 +        width:          160px;
   24.60 +        padding:        10px;
   24.61 +        border:         0px solid black;
   24.62 +        text-align:     center;
   24.63 +}
   24.64 +
   24.65 +div#main {
   24.66 +        position:       absolute;
   24.67 +        left:           200px;
   24.68 +        top:            10px;
   24.69 +        right:          10px;
   24.70 +        padding:        10px;
   24.71 +        border:         0px solid black;
   24.72 +}
   24.73 +
   24.74 +div.button {
   24.75 +        float:          right;
   24.76 +        margin:         10px 0px 0px 10px;
   24.77 +        padding:        5px;
   24.78 +        text-align:     center;
   24.79 +        border:         1px solid black;
   24.80 +        background:     gray;
   24.81 +	cursor:		hand;
   24.82 +}
   24.83 +
   24.84 +div.tabButton {
   24.85 +	position:	relative;
   24.86 +	top: 		0px;
   24.87 +        float:          left;
   24.88 +        margin:         0px 10px -1px 0px;
   24.89 +        padding:        5px;
   24.90 +        text-align:     center;
   24.91 +        border:         1px solid black;
   24.92 +        background:     gray;
   24.93 +	cursor: 	hand;
   24.94 +}
   24.95 +
   24.96 +div.tabButton#activeTab {
   24.97 +	top:		0px;
   24.98 +        background:     white;
   24.99 +        border-color:   black black white black;
  24.100 +}
  24.101 +
  24.102 +div.button:hover, div.tabButton:hover {
  24.103 +        background:     white;
  24.104 +}
  24.105 +
  24.106 +div.button a, div.tabButton a {
  24.107 +        font-size:      12px;
  24.108 +	font-weight:	bold;
  24.109 +}
  24.110 +
  24.111 +div.title {
  24.112 +	float:          right;
  24.113 +	font-size:	14px;
  24.114 +	font-weight:	bold;
  24.115 +}
  24.116 +
  24.117 +div.tab {
  24.118 +        overflow:       auto;
  24.119 +        clear:          both;
  24.120 +        border:         1px solid black;
  24.121 +        padding:        10px;
  24.122 +}
    25.1 --- a/tools/sv/index.psp	Tue Aug 09 10:47:41 2005 +0000
    25.2 +++ b/tools/sv/index.psp	Tue Aug 09 13:04:31 2005 +0000
    25.3 @@ -7,158 +7,29 @@ debug = True and False
    25.4  for path in sys.path:
    25.5      if debug: req.write( path + "<br/>" )
    25.6  
    25.7 -from xen.sv.HTMLBase import HTMLBase
    25.8 -from xen.sv.DomList  import DomList
    25.9 -from xen.sv.NodeInfo import NodeInfo
   25.10 -from xen.sv.DomInfo  import DomInfo
   25.11 -from xen.sv.CreateDomain import CreateDomain
   25.12 -from xen.sv.MigrateDomain import MigrateDomain
   25.13 -from xen.sv.SaveDomain import SaveDomain
   25.14 -from xen.sv.RestoreDomain import RestoreDomain
   25.15 -
   25.16 -from xen.xend.XendClient import server
   25.17 -
   25.18 -from xen.sv.util import getVar
   25.19 -
   25.20 -# adapter to make this all work with mod_python
   25.21 -# (c) Tom Wilkie 2005
   25.22 -
   25.23 -class TwistedAdapter:
   25.24 -
   25.25 -    def write( self, text ):
   25.26 -        req.write( text )
   25.27 -
   25.28 -    class Args:
   25.29 -
   25.30 -        from mod_python.util import FieldStorage
   25.31 -
   25.32 -        fieldStorage = FieldStorage( req, True )
   25.33 -
   25.34 -        # return a list of values for the given key,
   25.35 -        # or None if key not there
   25.36 -        def get( self, var ):
   25.37 -            retVar = self.fieldStorage.getlist( var )
   25.38 -            if len( retVar ) == 0:
   25.39 -                return None
   25.40 -            else:
   25.41 -                return retVar
   25.42 -
   25.43 -        # return a list of tuples, 
   25.44 -        # (key, value) where value is a list of values
   25.45 -	def items( self ):
   25.46 -            result = [];
   25.47 -            for key in self.fieldStorage.keys():
   25.48 -            	result.append( (key, self.fieldStorage.getlist( key ) ) )
   25.49 -	    return result
   25.50 -
   25.51 -    args = Args()
   25.52 -
   25.53 -    uri = req.unparsed_uri
   25.54 -
   25.55 -
   25.56 -class Main( HTMLBase ):
   25.57 -    
   25.58 -    isLeaf = True
   25.59 -
   25.60 -    def __init__( self, urlWriter = None ):
   25.61 -        self.modules = { "node": NodeInfo, 
   25.62 -                         "list": DomList, 
   25.63 -                         "info": DomInfo,
   25.64 -                         "create": CreateDomain,
   25.65 -                         "migrate" : MigrateDomain,
   25.66 -                         "save" : SaveDomain,
   25.67 -                         "restore" : RestoreDomain }
   25.68 -
   25.69 -        # ordered list of module menus to display
   25.70 -        self.module_menus = [ "node", "create", "migrate", "save",
   25.71 -                              "restore", "list" ]
   25.72 -        HTMLBase.__init__(self)
   25.73 -        
   25.74 -    def render_POST( self, request ):
   25.75 -    
   25.76 -    	#decide what module post'd the action
   25.77 -                
   25.78 -    	args = getVar( 'args', request )
   25.79 -
   25.80 -        mod = getVar( 'mod', request )
   25.81 -                
   25.82 -        if mod in self.modules and args is None:
   25.83 -            module = self.modules[ mod ]
   25.84 -            #check module exists
   25.85 -            if module:
   25.86 -               module( self.mainUrlWriter ).perform( request )
   25.87 -        else:
   25.88 -            self.perform( request )     
   25.89 -    
   25.90 -        return self.render_GET( request )
   25.91 -
   25.92 -    #TODO: need to make this get the request uri automatically
   25.93 -    def mainUrlWriter( self, module ):
   25.94 -    	def fun( f ):
   25.95 -            return "index.psp?mod=%s%s" % ( module, f )
   25.96 -        return fun    
   25.97 -        
   25.98 -    def write_BODY( self, request ):
   25.99 -    
  25.100 -        request.write( "\n<table style='border:0px solid black; background: url(images/orb_01.jpg) no-repeat' cellspacing='0' cellpadding='0' border='0' width='780px' height='536px'>\n" )
  25.101 -        request.write( "<tr>\n" )
  25.102 -        request.write( " <td width='15px'>&nbsp;</td>" )
  25.103 -        request.write( " <td width='175px' align='center' valign'center'>" )
  25.104 -        request.write( "  <table cellspacing='0' cellpadding='0' border='0' width='100%' height='100%'>" )
  25.105 -        request.write( "   <tr><td height='140px' align='center' valign='bottom'><a href='http://www.cl.cam.ac.uk/Research/SRG/netos/xen/'>" )
  25.106 -        request.write( "   <img src='images/xen.png' width='150' height='75' border='0'/></a><br/></td></tr>" )
  25.107 -        request.write( "   <tr><td height='60px' align='center'><p class='small'>SV Web Interface<br/>(C) <a href='mailto:tw275@cam.ac.uk'>Tom Wilkie</a> 2004</p></td></tr>")
  25.108 -        request.write( "   <tr><td align='center' valign='top'>" )
  25.109 -
  25.110 -        for modName in self.module_menus:
  25.111 -            self.modules[modName]( self.mainUrlWriter( modName ) ).write_MENU( request )
  25.112 -        
  25.113 -        request.write( "   </td></tr>" )
  25.114 -        request.write( "  </table>" )
  25.115 -        request.write( " &nbsp;" )
  25.116 -        request.write( " </td>\n" )
  25.117 -        request.write( " <td width='15px'>&nbsp;</td>" )
  25.118 -        request.write( " <td width='558px' align='left' valign='top'>" )
  25.119 -        request.write( "  <table cellspacing='0' cellpadding='0' border='0' width='100%' height='100%'>" )
  25.120 -        request.write( "   <tr><td height='20px'></td></tr>" )
  25.121 -        request.write( "   <tr><td align='center' valign='top'>" )
  25.122 -        
  25.123 -        modName = getVar('mod', request)
  25.124 -        
  25.125 -        if modName not in self.modules:
  25.126 -            request.write( '<p>Please select a module</p>' )
  25.127 -        else:
  25.128 -            module = self.modules[ modName ]
  25.129 -            if module:
  25.130 -               module( self.mainUrlWriter( modName ) ).write_BODY( request )  
  25.131 -            else:
  25.132 -               request.write( '<p>Invalid module. Please select another</p>' )
  25.133 -    
  25.134 -        request.write( "   </td></tr>" )
  25.135 -        request.write( "  </table>" )
  25.136 -        request.write( " </td>\n" )
  25.137 -        request.write( " <td width='17px'>&nbsp;</td>" )
  25.138 -        request.write( "</tr>\n" )
  25.139 -        
  25.140 -        request.write( "</table>\n" )
  25.141 -        
  25.142 -                
  25.143 -    def op_destroy( self, request ):
  25.144 -    	dom = getVar( 'dom', request )
  25.145 -        if not dom is None and dom != "0":
  25.146 -            server.xend_domain_destroy( int( dom ), "halt" ) 
  25.147 -                 
  25.148 -    def op_pause( self, request ):
  25.149 -    	dom = getVar( 'dom', request )
  25.150 -        if not dom is None and dom != "0":
  25.151 -            server.xend_domain_pause( int( dom ) )      
  25.152 -    
  25.153 -    def op_unpause( self, request ):
  25.154 -    	dom = getVar( 'dom', request )
  25.155 -        if not dom is None and dom != "0":
  25.156 -            server.xend_domain_unpause( int( dom ) )      
  25.157 +from xen.sv.Main import Main, TwistedAdapter
  25.158  
  25.159  main = Main()
  25.160 -
  25.161 -main.render_POST( TwistedAdapter() )
  25.162 +request = TwistedAdapter( req )
  25.163 +main.do_POST( request )
  25.164  %>
  25.165 +<html>
  25.166 +<head>
  25.167 +	<title>XenSV</title>
  25.168 +	<script src="inc/script.js"></script>
  25.169 +	<link rel="StyleSheet" type="text/css" href="inc/style.css">
  25.170 +</head>
  25.171 +<body>
  25.172 +    <form method="post" action="<%=request.uri%>">
  25.173 +        <div id="menu">
  25.174 +		<img src="images/xen.png">
  25.175 +		<% main.render_menu( request ) %>
  25.176 +	</div>
  25.177 +	<div id="main">
  25.178 +		<% main.render_main( request ) %>
  25.179 +	</div>
  25.180 +	<input type="hidden" name="op" value="">
  25.181 +        <input type="hidden" name="args" value="">
  25.182 +    </form>
  25.183 +</body>
  25.184 +</html>