ia64/xen-unstable

changeset 6074:12deebfb7f87

Updates to SV. New look. Removed and simplified lots of files.
author twilkie@paploo.uk.xensource.com
date Tue Aug 09 12:55:18 2005 +0000 (2005-08-09)
parents a1f7e01b0990
children 2379e795ca69
files 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
     1.1 --- a/tools/python/xen/sv/CreateDomain.py	Tue Aug 09 10:42:51 2005 +0000
     1.2 +++ b/tools/python/xen/sv/CreateDomain.py	Tue Aug 09 12:55:18 2005 +0000
     1.3 @@ -17,37 +17,69 @@ class CreateDomain( Wizard ):
     1.4                     CreateFinish ]
     1.5      
     1.6      	Wizard.__init__( self, urlWriter, "Create Domain", sheets )
     1.7 -       
     1.8 +
     1.9 +    def op_finish( self, request ):
    1.10 +        pass
    1.11 +    
    1.12  class CreatePage0( Sheet ):
    1.13  
    1.14 +    title = "General"
    1.15 +    
    1.16      def __init__( self, urlWriter ):
    1.17          Sheet.__init__( self, urlWriter, "General", 0 )
    1.18          self.addControl( InputControl( 'name', 'VM Name', 'VM Name:', "[\\w|\\S]+", "You must enter a name in this field" ) )
    1.19          self.addControl( InputControl( 'memory', '64', 'Memory (Mb):', "[\\d]+", "You must enter a number in this field" ) )
    1.20          self.addControl( InputControl( 'cpu', '0', 'CPU:', "[\\d]+", "You must enter a number in this feild" ) )
    1.21          self.addControl( InputControl( 'cpu_weight', '1', 'CPU Weight:', "[\\d]+", "You must enter a number in this feild" ) )
    1.22 +        self.addControl( InputControl( 'vcpus', '1', 'Virtual CPUs:', '[\\d]+', "You must enter a number in this feild") )
    1.23                          
    1.24  class CreatePage1( Sheet ):
    1.25  
    1.26 +    title = "Setup Kernel Image"
    1.27 +
    1.28      def __init__( self, urlWriter ):
    1.29          Sheet.__init__( self, urlWriter, "Setup Kernel Image", 1 )
    1.30 -# For now we don't need to select a builder...
    1.31 -#        self.addControl( ListControl( 'builder', [('linux', 'Linux'), ('netbsd', 'NetBSD')], 'Kernel Type:' ) )
    1.32 -        self.addControl( FileControl( 'kernel', '/boot/vmlinuz-2.6.9-xenU', 'Kernel Image:' ) )
    1.33 +        self.addControl( ListControl( 'builder', [('linux', 'Linux'), ('netbsd', 'NetBSD')], 'Domain Builder:' ) )
    1.34 +        self.addControl( FileControl( 'kernel', '/boot/vmlinuz-2.6.12-xenU', 'Kernel Image:' ) )
    1.35          self.addControl( InputControl( 'extra', '', 'Kernel Command Line Parameters:' ) )
    1.36 +        self.addControl( ListControl( 'use-initrd', [('yes', 'Yes'), ('no', 'No')], 'Use an Initial Ram Disk?:' ) )
    1.37 +        self.addControl( FileControl( 'initrd', '/boot/initrd-2.6.12-xenU.img', 'Initial Ram Disk:' ) )
    1.38 +
    1.39 +    def validate( self, request ):
    1.40 +        if not self.passback: self.parseForm( request )
    1.41 +        check = True
    1.42 +        request.write( previous_values.get( '>>>>>use-initrd' ) )
    1.43 +        previous_values = ssxp2hash( string2sxp( self.passback ) ) #get the map for quick reference
    1.44 +        if DEBUG: print previous_values
    1.45 +        for (feild, control) in self.feilds:
    1.46 +            if feild == 'initrd' and previous_values.get( 'use-initrd' ) != 'no':
    1.47 +                request.write( previous_values.get( '>>>>>use-initrd' ) )
    1.48 +                if control.validate( previous_values.get( feild ) ):
    1.49 +                    check = False
    1.50 +            elif not control.validate( previous_values.get( feild ) ):
    1.51 +                check = False
    1.52 +
    1.53 +            if DEBUG: print "> %s = %s" % (feild, previous_values.get( feild ))
    1.54 +
    1.55 +        return check
    1.56 +                                                 
    1.57  
    1.58  class CreatePage2( Sheet ):
    1.59  
    1.60 +    title = "Choose number of VBDS"
    1.61 +
    1.62      def __init__( self, urlWriter ):
    1.63      	Sheet.__init__( self, urlWriter, "Setup Virtual Block Device", 2 )
    1.64          self.addControl( InputControl( 'num_vbds', '1', 'Number of VBDs:', '[\\d]+', "You must enter a number in this field" ) )
    1.65  
    1.66  class CreatePage3( Sheet ):
    1.67  
    1.68 +    title = "Setup VBDS"
    1.69 +
    1.70      def __init__( self, urlWriter ):
    1.71          Sheet.__init__( self, urlWriter, "Setup Virtual Block Device", 3 )
    1.72          
    1.73 -    def write_BODY( self, request, err ):
    1.74 +    def write_BODY( self, request ):
    1.75          if not self.passback: self.parseForm( request )
    1.76      
    1.77      	previous_values = sxp2hash( string2sxp( self.passback ) ) #get the hash for quick reference
    1.78 @@ -61,10 +93,12 @@ class CreatePage3( Sheet ):
    1.79              
    1.80          self.addControl( InputControl( 'root', '/dev/sda1', 'Root device (in VM):' ) )
    1.81          
    1.82 -        Sheet.write_BODY( self, request, err )
    1.83 +        Sheet.write_BODY( self, request )
    1.84                  
    1.85  class CreatePage4( Sheet ):
    1.86  
    1.87 +    title = "Network Setting"
    1.88 +
    1.89      def __init__( self, urlWriter ):        
    1.90          Sheet.__init__( self, urlWriter, "Network settings", 4 )
    1.91          self.addControl( ListControl( 'dhcp', [('off', 'No'), ('dhcp', 'Yes')], 'Use DHCP:' ) )
    1.92 @@ -76,26 +110,27 @@ class CreatePage4( Sheet ):
    1.93                   
    1.94  class CreateFinish( Sheet ):
    1.95  
    1.96 +    title = "Finish"
    1.97 +
    1.98      def __init__( self, urlWriter ):
    1.99          Sheet.__init__( self, urlWriter, "All Done", 5 )
   1.100          
   1.101 -    def write_BODY( self, request, err ):
   1.102 +    def write_BODY( self, request ):
   1.103      
   1.104          if not self.passback: self.parseForm( request )
   1.105          
   1.106          xend_sxp = self.translate_sxp( string2sxp( self.passback ) )
   1.107 +
   1.108 +        request.write( "<pre>%s</pre>" % sxp2prettystring( xend_sxp ) )
   1.109          
   1.110          try:
   1.111 -            dom_sxp = server.xend_domain_create( xend_sxp )
   1.112 -            success = "Your domain was successfully created.\n"
   1.113 -        except:
   1.114 -            success = "There was an error creating your domain.\nThe configuration used is as follows:\n"
   1.115 -            dom_sxp = xend_sxp
   1.116 -            
   1.117 -            
   1.118 -        
   1.119 -        pt = PreTab( success + sxp2prettystring( dom_sxp ) )
   1.120 -        pt.write_BODY( request )
   1.121 +            server.xend_domain_create( xend_sxp )
   1.122 +            request.write( "<p>You domain had been successfully created.</p>" )
   1.123 +        except Exception, e:
   1.124 +            request.write( "<p>There was an error creating your domain.<br/>The configuration used is as follows:\n</p>" )
   1.125 +            request.write( "<pre>%s</pre>" % sxp2prettystring( xend_sxp ) )
   1.126 +            request.write( "<p>The error was:</p>" )
   1.127 +            request.write( "<pre>%s</pre>" % str( e ) )
   1.128  
   1.129          request.write( "<input type='hidden' name='passback' value=\"%s\"></p>" % self.passback )
   1.130          request.write( "<input type='hidden' name='sheet' value='%s'></p>" % self.location )
   1.131 @@ -117,6 +152,7 @@ class CreateFinish( Sheet ):
   1.132          vals.maxmem =   get( 'maxmem' )
   1.133          vals.cpu =  	get( 'cpu' )
   1.134          vals.cpu_weight = get( 'cpu_weight' )
   1.135 +        vals.vcpus = get( 'vcpus' )
   1.136          
   1.137          vals.builder =  get( 'builder' )       
   1.138          vals.kernel =   get( 'kernel' )
   1.139 @@ -128,7 +164,7 @@ class CreateFinish( Sheet ):
   1.140          vbds = []
   1.141          
   1.142          for i in range( int( get( 'num_vbds' ) ) ):
   1.143 -            vbds.append( ( get( 'vbd%s_dom0' % i ), get('vbd%s_domU' % i ), get( 'vbd%s_mode' % i ) ) )
   1.144 +            vbds.append( ( get( 'vbd%s_dom0' % i ), get('vbd%s_domU' % i ), get( 'vbd%s_mode' % i ), None ) )
   1.145          
   1.146          vals.disk = vbds    
   1.147              
   1.148 @@ -141,6 +177,9 @@ class CreateFinish( Sheet ):
   1.149          vals.restart = None
   1.150          vals.console = None
   1.151          vals.ramdisk = None
   1.152 +        vals.ssidref = -1
   1.153 +        vals.bootloader = None
   1.154 +        vals.usb = []
   1.155          
   1.156          #setup vifs
   1.157          
   1.158 @@ -155,9 +194,11 @@ class CreateFinish( Sheet ):
   1.159          dhcp = get( 'dhcp' )
   1.160          
   1.161          vals.cmdline_ip = "%s:%s:%s:%s:%s:eth0:%s" % (ip, nfs, gate, mask, host, dhcp)
   1.162 +
   1.163 +        opts = None
   1.164          
   1.165          try:
   1.166 -            return make_config( vals )
   1.167 -        except:
   1.168 -            return [["Error creating domain config."]]    
   1.169 +            return make_config( opts, vals )
   1.170 +        except Exception, e:
   1.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]]    
   1.172          
     2.1 --- a/tools/python/xen/sv/Daemon.py	Tue Aug 09 10:42:51 2005 +0000
     2.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.3 @@ -1,110 +0,0 @@
     2.4 -###########################################################
     2.5 -## XenSV Web Control Interface Daemon
     2.6 -## Copyright (C) 2004, K A Fraser (University of Cambridge)
     2.7 -## Copyright (C) 2004, Mike Wray <mike.wray@hp.com>
     2.8 -## Copyright (C) 2004, Tom Wilkie <tw275@cam.ac.uk>
     2.9 -###########################################################
    2.10 -
    2.11 -import os
    2.12 -import os.path
    2.13 -import sys
    2.14 -import re
    2.15 -
    2.16 -from xen.sv.params import *
    2.17 -
    2.18 -from twisted.internet import reactor
    2.19 -from twisted.web import static, server, script
    2.20 -
    2.21 -from xen.util.ip import _readline, _readlines
    2.22 -
    2.23 -class Daemon:
    2.24 -    """The xend daemon.
    2.25 -    """
    2.26 -    def __init__(self):
    2.27 -        self.shutdown = 0
    2.28 -        self.traceon = 0
    2.29 -
    2.30 -    def daemon_pids(self):
    2.31 -        pids = []
    2.32 -        pidex = '(?P<pid>\d+)'
    2.33 -        pythonex = '(?P<python>\S*python\S*)'
    2.34 -        cmdex = '(?P<cmd>.*)'
    2.35 -        procre = re.compile('^\s*' + pidex + '\s*' + pythonex + '\s*' + cmdex + '$')
    2.36 -        xendre = re.compile('^/usr/sbin/xend\s*(start|restart)\s*.*$')
    2.37 -        procs = os.popen('ps -e -o pid,args 2>/dev/null')
    2.38 -        for proc in procs:
    2.39 -            pm = procre.match(proc)
    2.40 -            if not pm: continue
    2.41 -            xm = xendre.match(pm.group('cmd'))
    2.42 -            if not xm: continue
    2.43 -            #print 'pid=', pm.group('pid'), 'cmd=', pm.group('cmd')
    2.44 -            pids.append(int(pm.group('pid')))
    2.45 -        return pids
    2.46 -
    2.47 -    def new_cleanup(self, kill=0):
    2.48 -        err = 0
    2.49 -        pids = self.daemon_pids()
    2.50 -        if kill:
    2.51 -            for pid in pids:
    2.52 -                print "Killing daemon pid=%d" % pid
    2.53 -                os.kill(pid, signal.SIGHUP)
    2.54 -        elif pids:
    2.55 -            err = 1
    2.56 -            print "Daemon already running: ", pids
    2.57 -        return err
    2.58 -            
    2.59 -    def cleanup(self, kill=False):
    2.60 -        # No cleanup to do if PID_FILE is empty.
    2.61 -        if not os.path.isfile(PID_FILE) or not os.path.getsize(PID_FILE):
    2.62 -            return 0
    2.63 -        # Read the pid of the previous invocation and search active process list.
    2.64 -        pid = open(PID_FILE, 'r').read()
    2.65 -        lines = _readlines(os.popen('ps ' + pid + ' 2>/dev/null'))
    2.66 -        for line in lines:
    2.67 -            if re.search('^ *' + pid + '.+xensv', line):
    2.68 -                if not kill:
    2.69 -                    print "Daemon is already running (pid %d)" % int(pid)
    2.70 -                    return 1
    2.71 -                # Old daemon is still active: terminate it.
    2.72 -                os.kill(int(pid), 1)
    2.73 -        # Delete the stale PID_FILE.
    2.74 -        os.remove(PID_FILE)
    2.75 -        return 0
    2.76 -
    2.77 -    def start(self, trace=0):
    2.78 -        if self.cleanup(kill=False):
    2.79 -            return 1
    2.80 -   
    2.81 -        # Fork -- parent writes PID_FILE and exits.
    2.82 -        pid = os.fork()
    2.83 -        if pid:
    2.84 -            # Parent
    2.85 -            pidfile = open(PID_FILE, 'w')
    2.86 -            pidfile.write(str(pid))
    2.87 -            pidfile.close()
    2.88 -            return 0
    2.89 -        # Child
    2.90 -        self.run()
    2.91 -        return 0
    2.92 -
    2.93 -    def stop(self):
    2.94 -        return self.cleanup(kill=True)
    2.95 -
    2.96 -    def run(self):
    2.97 -	root = static.File( SV_ROOT )
    2.98 -        root.indexNames = [ 'Main.rpy' ]
    2.99 -        root.processors = { '.rpy': script.ResourceScript }
   2.100 -        reactor.listenTCP( SV_PORT, server.Site( root ) )
   2.101 -        reactor.run()
   2.102 -
   2.103 -    def exit(self):
   2.104 -        reactor.disconnectAll()
   2.105 -        sys.exit(0)
   2.106 -
   2.107 -def instance():
   2.108 -    global inst
   2.109 -    try:
   2.110 -        inst
   2.111 -    except:
   2.112 -        inst = Daemon()
   2.113 -    return inst
     3.1 --- a/tools/python/xen/sv/DomInfo.py	Tue Aug 09 10:42:51 2005 +0000
     3.2 +++ b/tools/python/xen/sv/DomInfo.py	Tue Aug 09 12:55:18 2005 +0000
     3.3 @@ -4,6 +4,7 @@ from xen.xend import PrettyPrint
     3.4  from xen.sv.HTMLBase import HTMLBase
     3.5  from xen.sv.util import *
     3.6  from xen.sv.GenTabbed import *
     3.7 +from xen.sv.Wizard import *
     3.8  
     3.9  DEBUG=1
    3.10  
    3.11 @@ -12,33 +13,69 @@ class DomInfo( GenTabbed ):
    3.12      def __init__( self, urlWriter ):
    3.13          
    3.14          self.dom = 0;
    3.15 -    
    3.16 -        def tabUrlWriter( tab ):
    3.17 -            return urlWriter( "&dom=%s%s" % ( self.dom, tab ) )
    3.18 -        
    3.19 -        GenTabbed.__init__( self, "Domain Info", tabUrlWriter, [ 'General', 'SXP', 'Devices' ], [ DomGeneralTab, DomSXPTab, NullTab ]  )
    3.20 +                   
    3.21 +        GenTabbed.__init__( self, "Domain Info", urlWriter, [ 'General', 'SXP', 'Devices', 'Migrate', 'Save' ], [ DomGeneralTab, DomSXPTab, DomDeviceTab, DomMigrateTab, DomSaveTab ]  )
    3.22  
    3.23      def write_BODY( self, request ):
    3.24 -        dom = request.args.get('dom')
    3.25 -        
    3.26 -        if dom is None or len(dom) != 1:
    3.27 +        try:
    3.28 +            dom = int( getVar( 'dom', request ) )
    3.29 +        except:
    3.30              request.write( "<p>Please Select a Domain</p>" )
    3.31              return None
    3.32 -        else:
    3.33 -            self.dom = dom[0]
    3.34 -        
    3.35 +       
    3.36          GenTabbed.write_BODY( self, request )
    3.37          
    3.38      def write_MENU( self, request ):
    3.39 -        pass
    3.40 +       domains = []
    3.41 +
    3.42 +       try:
    3.43 +           domains = server.xend_domains()
    3.44 +           domains.sort()
    3.45 +       except:
    3.46 +           pass
    3.47 +
    3.48 +       request.write( "\n<table style='border:0px solid white' cellspacing='0' cellpadding='0' border='0' width='100%'>\n" )
    3.49 +       request.write( "<tr class='domainInfoHead'>" )
    3.50 +       request.write( "<td class='domainInfoHead' align='center'>Domain</td>\n" )
    3.51 +       request.write( "<td class='domainInfoHead' align='center'>Name</td>\n" )
    3.52 +       request.write( "<td class='domainInfoHead' align='center'>State</td>\n" )
    3.53 +       request.write( "<td class='domainInfoHead' align='center'></td>\n" )
    3.54 +       request.write( "</tr>" )
    3.55  
    3.56 +       odd = True
    3.57 +       if not domains is None:
    3.58 +           for domain in domains:
    3.59 +               odd = not odd;
    3.60 +               if odd:
    3.61 +                   request.write( "<tr class='domainInfoOdd'>\n" )
    3.62 +               else:
    3.63 +                   request.write( "<tr class='domainInfoEven'>\n" )
    3.64 +               domInfo = getDomInfo( domain )
    3.65 +               request.write( "<td class='domainInfo' align='center'>%(id)s</td>\n" % domInfo )
    3.66 +               url = self.urlWriter( "&dom=%(id)s" % domInfo )
    3.67 +               request.write( "<td class='domainInfo' align='center'><a href='%s'>%s</a></td>\n" % ( url, domInfo['name'] ) )
    3.68 +               request.write( "<td class='domainInfo' align='center'>%(state)5s</td>\n" % domInfo )
    3.69 +               if domInfo[ 'id' ] != "0":
    3.70 +                   request.write( "<td class='domainInfo' align='center'>" )
    3.71 +                   if domInfo[ 'state' ][ 2 ] == "-":
    3.72 +                       request.write( "<img src='images/small-pause.png' onclick='doOp2( \"pause\", \"%(dom)-4s\" )'>" % domInfo )
    3.73 +                   else:
    3.74 +                       request.write( "<img src='images/small-unpause.png' onclick='doOp2( \"unpause\", \"%(dom)-4s\" )'>" % domInfo )
    3.75 +                   request.write( "<img src='images/small-destroy.png' onclick='doOp2( \"destroy\", \"%(dom)-4s\" )'></td>" % domInfo )
    3.76 +               else:
    3.77 +                   request.write( "<td>&nbsp;</td>" )
    3.78 +               request.write( "</tr>\n" )
    3.79 +       else:
    3.80 +           request.write( "<tr colspan='10'><p class='small'>Error getting domain list<br/>Perhaps XenD not running?</p></tr>")
    3.81 +       request.write( "</table>" )
    3.82 +       
    3.83  class DomGeneralTab( CompositeTab ):
    3.84 -    def __init__( self ):
    3.85 -       CompositeTab.__init__( self, [ DomGenTab, DomActionTab ] )        
    3.86 -        
    3.87 +    def __init__( self, urlWriter ):
    3.88 +       CompositeTab.__init__( self, [ DomGenTab, DomActionTab ], urlWriter )        
    3.89 +       
    3.90  class DomGenTab( GeneralTab ):
    3.91  
    3.92 -    def __init__( self ):
    3.93 +    def __init__( self, urlWriter ):
    3.94      
    3.95          titles = {}
    3.96      
    3.97 @@ -60,13 +97,13 @@ class DomGenTab( GeneralTab ):
    3.98              request.write( "<p>Please Select a Domain</p>" )
    3.99              return None
   3.100              
   3.101 -        self.dict = getDomInfoHash( self.dom )
   3.102 +        self.dict = getDomInfo( self.dom )
   3.103          
   3.104          GeneralTab.write_BODY( self, request )
   3.105              
   3.106  class DomSXPTab( PreTab ):
   3.107  
   3.108 -    def __init__( self ):
   3.109 +    def __init__( self, urlWriter ):
   3.110          self.dom = 0
   3.111          PreTab.__init__( self, "" )
   3.112  
   3.113 @@ -86,15 +123,15 @@ class DomSXPTab( PreTab ):
   3.114          self.source = sxp2prettystring( domInfo )
   3.115          
   3.116          PreTab.write_BODY( self, request )
   3.117 -        
   3.118 +       
   3.119  class DomActionTab( ActionTab ):
   3.120  
   3.121 -    def __init__( self ):
   3.122 -    	actions = { "shutdown" : "shutdown",
   3.123 -        	    "reboot" : "reboot",
   3.124 -                    "pause" : "pause",
   3.125 -                    "unpause" : "unpause",
   3.126 -                    "destroy" : "destroy" }
   3.127 +    def __init__( self, urlWriter ):
   3.128 +    	actions = { "shutdown" : "Shutdown",
   3.129 +        	    "reboot" : "Reboot",
   3.130 +                    "pause" : "Pause",
   3.131 +                    "unpause" : "Unpause",
   3.132 +                    "destroy" : "Destroy" }
   3.133          ActionTab.__init__( self, actions )    
   3.134          
   3.135      def op_shutdown( self, request ):
   3.136 @@ -141,8 +178,91 @@ class DomActionTab( ActionTab ):
   3.137             	server.xend_domain_destroy( int( dom ), "halt" )
   3.138             except:
   3.139             	pass
   3.140 -        
   3.141 -    
   3.142 -    
   3.143 -        
   3.144 +
   3.145 +class DomDeviceTab( CompositeTab ):
   3.146 +
   3.147 +    def __init__( self, urlWriter ):
   3.148 +        CompositeTab.__init__( self, [ DomDeviceListTab, DomDeviceOptionsTab, DomDeviceActionTab ], urlWriter )
   3.149 +
   3.150 +class DomDeviceListTab( NullTab ):
   3.151 +
   3.152 +    title = "Device List"
   3.153 +
   3.154 +    def __init__( self, urlWriter ):
   3.155 +        pass
   3.156 +
   3.157 +class DomDeviceOptionsTab( NullTab ):
   3.158 +
   3.159 +    title = "Device Options"
   3.160 +
   3.161 +    def __init__( self, urlWriter ):
   3.162 +        pass
   3.163 +
   3.164 +class DomDeviceActionTab( ActionTab ):
   3.165 +
   3.166 +    def __init__( self, urlWriter ):
   3.167 +        ActionTab.__init__( self, { "addvcpu" : "Add VCPU", "addvbd" : "Add VBD", "addvif" : "Add VIF" } )
   3.168 +
   3.169 +class DomMigrateTab( CompositeTab ):
   3.170 +
   3.171 +    def __init__( self, urlWriter ):
   3.172 +        CompositeTab.__init__( self, [ DomMigrateExtraTab, DomMigrateActionTab ], urlWriter ) 
   3.173 +
   3.174 +class DomMigrateExtraTab( Sheet ):
   3.175 +
   3.176 +    def __init__( self, urlWriter ):
   3.177 +        Sheet.__init__( self, urlWriter, "Configure Migration", 0)
   3.178 +        self.addControl( TickControl('live', 'True', 'Live migrate:') )
   3.179 +        self.addControl( InputControl('rate', '0', 'Rate limit:') )
   3.180 +        self.addControl( InputControl( 'dest', 'host.domain', 'Name or IP address:', ".*") )
   3.181 +                                                                                                            
   3.182 +class DomMigrateActionTab( ActionTab ):
   3.183  
   3.184 +    def __init__( self, urlWriter ):
   3.185 +        actions = { "migrate" : "Migrate" }
   3.186 +        ActionTab.__init__( self, actions )
   3.187 +                
   3.188 +    def op_migrate( self, request ):
   3.189 +        try:
   3.190 +            domid = int( getVar( 'dom', request ) )
   3.191 +            live  = getVar( 'live', request )
   3.192 +            rate  = getVar( 'rate', request )
   3.193 +            dest  = getVar( 'dest', request )
   3.194 +            dom_sxp = server.xend_domain_migrate( domid, dest, live == 'True', rate )
   3.195 +            success = "Your domain was successfully Migrated.\n"
   3.196 +        except Exception, e:
   3.197 +            success = "There was an error migrating your domain\n"
   3.198 +            dom_sxp = str(e)
   3.199 +                                                        
   3.200 +class DomSaveTab( CompositeTab ):
   3.201 +
   3.202 +    def __init__( self, urlWriter ):
   3.203 +        CompositeTab.__init__( self, [ DomSaveExtraTab, DomSaveActionTab ], urlWriter ) 
   3.204 +
   3.205 +class DomSaveExtraTab( Sheet ):
   3.206 +
   3.207 +    title = "Save location"
   3.208 +
   3.209 +    def __init__( self, urlWriter ):
   3.210 +        Sheet.__init__( self, urlWriter, "Save Domain to file", 0 )
   3.211 +        self.addControl( InputControl( 'file', '', 'Suspend file name:', ".*") )
   3.212 +               
   3.213 +class DomSaveActionTab( ActionTab ):
   3.214 +
   3.215 +    def __init__( self, urlWriter ):
   3.216 +        actions = { "save" : "Save" }
   3.217 +        ActionTab.__init__( self, actions )
   3.218 +
   3.219 +    def op_save( self, request ):
   3.220 +
   3.221 +        try:
   3.222 +            dom_sxp = server.xend_domain_save( config['domid'], config['file'] )
   3.223 +            success = "Your domain was successfully saved.\n"
   3.224 +        except Exception, e:
   3.225 +            success = "There was an error saving your domain\n"
   3.226 +            dom_sxp = str(e)
   3.227 +                                                                                       
   3.228 +        try:
   3.229 +            dom = int( getVar( 'dom', request ) )
   3.230 +        except:
   3.231 +            pass
     4.1 --- a/tools/python/xen/sv/DomList.py	Tue Aug 09 10:42:51 2005 +0000
     4.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.3 @@ -1,81 +0,0 @@
     4.4 -from xen.xend.XendClient import server
     4.5 -from xen.xend import sxp
     4.6 -
     4.7 -from xen.sv.HTMLBase import HTMLBase
     4.8 -from xen.sv.util import *
     4.9 -
    4.10 -class DomList( HTMLBase ):
    4.11 -    
    4.12 -    isLeaf = True
    4.13 -
    4.14 -    def __init__( self, urlWriter ):
    4.15 -        HTMLBase.__init__(self)
    4.16 -        self.urlWriter = urlWriter
    4.17 -        
    4.18 -    def write_MENU( self, request ):
    4.19 -    	return self.write_BODY( request, head=True, long=False ) 
    4.20 -
    4.21 -    def write_BODY( self, request, head=True, long=True ):
    4.22 -        
    4.23 -    	domains = []
    4.24 -    
    4.25 -        try:
    4.26 -            domains = server.xend_domains()
    4.27 -            domains.sort()
    4.28 -  	except:
    4.29 -            pass
    4.30 -                
    4.31 -        request.write( "\n<table style='border:0px solid white' cellspacing='0' cellpadding='0' border='0' width='100%'>\n" )
    4.32 -        
    4.33 -        if head:
    4.34 -            request.write( "<tr class='domainInfoHead'>" )
    4.35 -            self.write_DOMAIN_HEAD( request, long )
    4.36 -            request.write( "</tr>" )
    4.37 -        
    4.38 -        odd = True
    4.39 -        
    4.40 -        if not domains is None:
    4.41 -            for domain in domains:
    4.42 -                if odd:
    4.43 -                    request.write( "<tr class='domainInfoOdd'>\n" )
    4.44 -                    odd = False
    4.45 -                else:
    4.46 -                    request.write( "<tr class='domainInfoEven'>\n" )
    4.47 -                    odd = True
    4.48 -                self.write_DOMAIN( request, getDomInfoHash( domain ), long )
    4.49 -                request.write( "</tr>\n" )
    4.50 -        else:
    4.51 -        	request.write( "<tr colspan='10'><p class='small'>Error getting domain list<br/>Perhaps XenD not running?</p></tr>")
    4.52 -                
    4.53 -        request.write( "</table>\n" )
    4.54 -            
    4.55 -    def write_DOMAIN( self, request, domInfoHash, long=True ):   
    4.56 -        request.write( "<td class='domainInfo' align='center'>%(id)s</td>\n" % domInfoHash )
    4.57 -
    4.58 -        url = self.urlWriter( "&mod=info&dom=%(id)s" % domInfoHash )
    4.59 -
    4.60 -        request.write( "<td class='domainInfo' align='center'><a href='%s'>%s</a></td>\n" % ( url, domInfoHash['name'] ) )
    4.61 -        if long: 
    4.62 -            request.write( "<td class='domainInfo' align='center'>%(memory)5s</td>\n" % domInfoHash )
    4.63 -            request.write( "<td class='domainInfo' align='center'>%(cpu)2s</td>\n" % domInfoHash )
    4.64 -        request.write( "<td class='domainInfo' align='center'>%(state)5s</td>\n" % domInfoHash )
    4.65 -        if domInfoHash[ 'id' ] != "0":
    4.66 -            request.write( "<td class='domainInfo' align='center'>" )
    4.67 -            
    4.68 -            if domInfoHash[ 'state' ][ 2 ] == "-":
    4.69 -                request.write( "<img src='images/small-pause.png' onclick='doOp2( \"pause\", \"%(dom)-4s\" )'>" % domInfoHash )
    4.70 -            else:
    4.71 -                request.write( "<img src='images/small-unpause.png' onclick='doOp2( \"unpause\", \"%(dom)-4s\" )'>" % domInfoHash )              
    4.72 -            
    4.73 -            request.write( "<img src='images/small-destroy.png' onclick='doOp2( \"destroy\", \"%(dom)-4s\" )'></td>" % domInfoHash)
    4.74 -        else:
    4.75 -            request.write( "<td>&nbsp;</td>" )
    4.76 -
    4.77 -    def write_DOMAIN_HEAD( self, request, long=True ):
    4.78 -        request.write( "<td class='domainInfoHead' align='center'>Domain</td>\n" )      
    4.79 -        request.write( "<td class='domainInfoHead' align='center'>Name</td>\n" )      
    4.80 -        if long:
    4.81 -            request.write( "<td class='domainInfoHead' align='center'>Memory / Mb</td>\n" )      
    4.82 -            request.write( "<td class='domainInfoHead' align='center'>CPU</td>\n" )      
    4.83 -        request.write( "<td class='domainInfoHead' align='center'>State</td>\n" )      
    4.84 -        request.write( "<td class='domainInfoHead' align='center'></td>\n" )
     5.1 --- a/tools/python/xen/sv/GenTabbed.py	Tue Aug 09 10:42:51 2005 +0000
     5.2 +++ b/tools/python/xen/sv/GenTabbed.py	Tue Aug 09 12:55:18 2005 +0000
     5.3 @@ -1,7 +1,6 @@
     5.4  import types
     5.5  
     5.6  from xen.sv.HTMLBase import HTMLBase
     5.7 -from xen.sv.TabView import TabView
     5.8  from xen.sv.util import getVar
     5.9  
    5.10  class GenTabbed( HTMLBase ):
    5.11 @@ -12,39 +11,44 @@ class GenTabbed( HTMLBase ):
    5.12          self.tabObjects = tabObjects
    5.13          self.urlWriter = urlWriter
    5.14          self.title = title
    5.15 -
    5.16 -    def write_BODY( self, request, urlWriter = None ):
    5.17 -        try:
    5.18 -            tab = int( getVar( 'tab', request, 0 ) )
    5.19 -        except:
    5.20 -            tab = 0
    5.21 +        
    5.22 +    def write_BODY( self, request ):
    5.23 +        if not self.__dict__.has_key( "tab" ):
    5.24 +            try:
    5.25 +                self.tab = int( getVar( 'tab', request, 0 ) )
    5.26 +            except:
    5.27 +                self.tab = 0
    5.28              
    5.29 -        request.write( "<table style='' width='100%' border='0' cellspacing='0' cellpadding='0'>" )
    5.30 -        request.write( "<tr><td>" )
    5.31 -        request.write( "<p align='center'><u>%s</u></p>" % self.title )
    5.32 +        request.write( "\n<div class='title'>%s</div>" % self.title )
    5.33 +        
    5.34 +        TabView( self.tab, self.tabStrings, self.urlWriter ).write_BODY( request )
    5.35          
    5.36 -        TabView( tab, self.tabStrings, self.urlWriter ).write_BODY( request )
    5.37 -        
    5.38 -        request.write( "</td></tr><tr><td>" )
    5.39 +        try:
    5.40 +            request.write( "\n<div class='tab'>" )
    5.41 +            render_tab = self.tabObjects[ self.tab ]
    5.42 +            render_tab( self.urlWriter ).write_BODY( request )
    5.43 +            request.write( "\n</div>" )
    5.44 +        except Exception, e:
    5.45 +            request.write( "\n<p>Error Rendering Tab</p>" )
    5.46 +            request.write( "\n<p>%s</p>" % str( e ) )
    5.47 +
    5.48 +        request.write( "\n<input type=\"hidden\" name=\"tab\" value=\"%d\">" % self.tab )
    5.49 +
    5.50 +    def perform( self, request ):
    5.51 +        request.write( "Tab> perform" )
    5.52 +        request.write( "<br/>op: " + str( getVar( 'op', request ) ) )
    5.53 +        request.write( "<br/>args: " + str( getVar( 'args', request ) ) )
    5.54 +        request.write( "<br/>tab: " + str( getVar( 'tab', request ) ) )      
    5.55  
    5.56          try:
    5.57 -            render_tab = self.tabObjects[ tab ]
    5.58 -            render_tab().write_BODY( request )
    5.59 +            action = getVar( 'op', request, 0 )
    5.60 +            if action == "tab":
    5.61 +                self.tab = int( getVar( 'args', request ) )
    5.62 +            else:
    5.63 +                this.tab = int( getVar( 'tab', request, 0 ) )
    5.64 +                self.tabObjects[ self.tab ]( self.urlWriter ).perform( request )
    5.65          except:
    5.66 -            request.write( "<p>Error Rendering Tab</p>" )
    5.67 -       
    5.68 -        request.write( "</td></tr></table>" )
    5.69 -       
    5.70 -    def perform( self, request ):
    5.71 -        try:
    5.72 -            tab = int( getVar( 'tab', request, 0 ) )
    5.73 -        except:
    5.74 -            tab = 0;
    5.75 -            
    5.76 -        op_tab = self.tabObjects[ tab ]
    5.77 -        
    5.78 -        if op_tab:
    5.79 -            op_tab().perform( request )
    5.80 +            pass
    5.81          
    5.82  class PreTab( HTMLBase ):
    5.83  
    5.84 @@ -53,12 +57,9 @@ class PreTab( HTMLBase ):
    5.85          self.source = source
    5.86      
    5.87      def write_BODY( self, request ):
    5.88 -        
    5.89 -        request.write( "<div style='display: block; overflow: auto; border: 0px solid black; width: 540px; padding: 5px; z-index:0; align: center'><pre>" )
    5.90 -        
    5.91 +        request.write( "\n<pre>" )
    5.92          request.write( self.source )
    5.93 -        
    5.94 -        request.write( "</pre></div>" )
    5.95 +        request.write( "\n</pre>" )
    5.96  
    5.97  class GeneralTab( HTMLBase ):
    5.98                          
    5.99 @@ -69,7 +70,7 @@ class GeneralTab( HTMLBase ):
   5.100                          
   5.101      def write_BODY( self, request ): 
   5.102          
   5.103 -        request.write( "<table width='100%' cellspacing='0' cellpadding='0' border='0'>" )
   5.104 +        request.write( "\n<table width='100%' cellspacing='0' cellpadding='0' border='0'>" )
   5.105          
   5.106          def writeAttr( niceName, attr, formatter=None ):
   5.107              if type( attr ) is types.TupleType:
   5.108 @@ -80,7 +81,7 @@ class GeneralTab( HTMLBase ):
   5.109                      temp = formatter( self.dict[ attr ] )
   5.110                  else:
   5.111                      temp = str( self.dict[ attr ] )
   5.112 -                request.write( "<tr><td width='50%%'><p>%s:</p></td><td width='50%%'><p>%s</p></td></tr>" % ( niceName, temp ) )
   5.113 +                request.write( "\n<tr><td width='50%%'><p>%s:</p></td><td width='50%%'><p>%s</p></td></tr>" % ( niceName, temp ) )
   5.114          
   5.115          for niceName, attr in self.titles.items():
   5.116              writeAttr( niceName, attr )
   5.117 @@ -89,16 +90,12 @@ class GeneralTab( HTMLBase ):
   5.118  
   5.119  class NullTab( HTMLBase ):
   5.120      
   5.121 -    def __init__( self ):
   5.122 -        HTMLBase.__init__( self )
   5.123 -        self.title = "Null Tab"
   5.124 -
   5.125 -    def __init__( self, title ):
   5.126 +    def __init__( self, title="Null Tab" ):
   5.127          HTMLBase.__init__( self )
   5.128          self.title = title
   5.129 -        
   5.130 +
   5.131      def write_BODY( self, request ):
   5.132 -        request.write( "<p>%s</p>" % self.title )
   5.133 +        request.write( "\n<p>%s</p>" % self.title )
   5.134  
   5.135  class ActionTab( HTMLBase ):
   5.136  
   5.137 @@ -107,29 +104,44 @@ class ActionTab( HTMLBase ):
   5.138          HTMLBase.__init__( self )
   5.139          
   5.140      def write_BODY( self, request ):
   5.141 -        request.write( "<p align='center'><table cellspacing='3' cellpadding='2' border='0'><tr>" )
   5.142 -    
   5.143 -        for ( command, text ) in self.actions.items():
   5.144 -            request.write( "<td style='border: 1px solid black; background-color: grey' onmouseover='buttonMouseOver( this )' onmouseout='buttonMouseOut( this )'>" )
   5.145 -            request.write( "<p><a href='javascript: doOp( \"%s\" );'>%s</a></p></td>" % (command, text) )
   5.146 - 
   5.147 -        request.write("</table></p>")        
   5.148 -        
   5.149 +        for item in self.actions.items():
   5.150 +            try:
   5.151 +                ((op, attr), title) = item
   5.152 +            except:
   5.153 +                (op, title) = item
   5.154 +                attr = ""
   5.155 +            request.write( "\n<div class='button' onclick=\"doOp2( '%s', '%s' )\">%s</a></div>" % (op, attr, title) )
   5.156 +
   5.157  class CompositeTab( HTMLBase ):
   5.158  
   5.159 -    def __init__( self, tabs ):
   5.160 +    def __init__( self, tabs, urlWriter ):
   5.161      	HTMLBase.__init__( self )
   5.162          self.tabs = tabs
   5.163 +        self.urlWriter = urlWriter
   5.164          
   5.165      def write_BODY( self, request ):
   5.166      	for tab in self.tabs:
   5.167 -            request.write( "<br/>" )
   5.168 -            tab().write_BODY( request )
   5.169 +            tab( self.urlWriter ).write_BODY( request )
   5.170              
   5.171      def perform( self, request ):
   5.172      	for tab in self.tabs:
   5.173 -            tab().perform( request )
   5.174 -    
   5.175 -    
   5.176 -       
   5.177 -        
   5.178 +            tab( self.urlWriter ).perform( request )
   5.179 +
   5.180 +class TabView( HTMLBase ):
   5.181 +
   5.182 +        # tab - int, id into tabs of selected tab
   5.183 +        # tabs - list of strings, tab names
   5.184 +        # urlWriter -
   5.185 +        def __init__( self, tab, tabs, urlWriter ):
   5.186 +            HTMLBase.__init__(self)
   5.187 +            self.tab = tab
   5.188 +            self.tabs = tabs
   5.189 +            self.urlWriter = urlWriter
   5.190 +
   5.191 +        def write_BODY( self, request ):
   5.192 +            for i in range( len( self.tabs ) ):
   5.193 +                if self.tab == i:
   5.194 +                    at = " id='activeTab'"
   5.195 +                else:
   5.196 +                    at = ""
   5.197 +                request.write( "\n<div%s class='tabButton' onclick=\"doOp2( 'tab', '%d' )\">%s</div>" % ( at, i, self.tabs[ i ] ) )
     6.1 --- a/tools/python/xen/sv/HTMLBase.py	Tue Aug 09 10:42:51 2005 +0000
     6.2 +++ b/tools/python/xen/sv/HTMLBase.py	Tue Aug 09 12:55:18 2005 +0000
     6.3 @@ -12,26 +12,17 @@ class HTMLBase:
     6.4          return self.render_GET( request )
     6.5          
     6.6      def render_GET( self, request ):
     6.7 -        self.write_TOP( request )
     6.8 -        self.write_BODY( request )
     6.9 -        self.write_BOTTOM( request )
    6.10 -        return ''
    6.11 -                
    6.12 +        pass
    6.13 +    
    6.14      def write_BODY( self, request ):
    6.15 -        request.write( "BODY" )
    6.16 +        pass
    6.17          
    6.18      def write_TOP( self, request ):
    6.19 -        request.write( '<html><head><title>Xen</title><link rel="stylesheet" type="text/css" href="inc/style.css" />' )
    6.20 -        request.write( '<script src="inc/script.js"></script>' )
    6.21 -        request.write( '</head><body>' )
    6.22 -        request.write('<form method="post" action="%s">' % request.uri)
    6.23 -
    6.24 +        pass
    6.25 +    
    6.26      def write_BOTTOM( self, request ):
    6.27 -        request.write('<input type="hidden" name="op" value="">')
    6.28 -        request.write('<input type="hidden" name="args" value="">')
    6.29 -        request.write('</form>')
    6.30 -        request.write( "</body></html>" )
    6.31 -
    6.32 +        pass
    6.33 +    
    6.34      def get_op_method(self, op):
    6.35          """Get the method for an operation.
    6.36          For operation 'foo' looks for 'op_foo'.
     7.1 --- a/tools/python/xen/sv/Main.py	Tue Aug 09 10:42:51 2005 +0000
     7.2 +++ b/tools/python/xen/sv/Main.py	Tue Aug 09 12:55:18 2005 +0000
     7.3 @@ -1,113 +1,90 @@
     7.4 +
     7.5  from xen.sv.HTMLBase import HTMLBase
     7.6 -from xen.sv.DomList  import DomList
     7.7  from xen.sv.NodeInfo import NodeInfo
     7.8  from xen.sv.DomInfo  import DomInfo
     7.9  from xen.sv.CreateDomain import CreateDomain
    7.10 -from xen.sv.MigrateDomain import MigrateDomain
    7.11 -from xen.sv.SaveDomain import SaveDomain
    7.12  from xen.sv.RestoreDomain import RestoreDomain
    7.13  
    7.14 -from xen.xend.XendClient import server
    7.15 -
    7.16  from xen.sv.util import getVar
    7.17  
    7.18 -class Main( HTMLBase ):
    7.19 -    
    7.20 -    isLeaf = True
    7.21 -
    7.22 -    def __init__( self, urlWriter = None ):
    7.23 -        self.modules = { "node": NodeInfo, 
    7.24 -                         "list": DomList, 
    7.25 -                         "info": DomInfo,
    7.26 -                         "create": CreateDomain,
    7.27 -                         "migrate" : MigrateDomain,
    7.28 -                         "save" : SaveDomain,
    7.29 -                         "restore" : RestoreDomain }
    7.30 +# adapter to make this all work with mod_python
    7.31 +# as opposed to Twisted
    7.32 +# (c) Tom Wilkie 2005
    7.33  
    7.34 -        # ordered list of module menus to display
    7.35 -        self.module_menus = [ "node", "create", "migrate", "save",
    7.36 -                              "restore", "list" ]
    7.37 -        HTMLBase.__init__(self)
    7.38 -        
    7.39 -    def render_POST( self, request ):
    7.40 -    
    7.41 -    	#decide what module post'd the action
    7.42 -                
    7.43 -    	args = getVar( 'args', request )
    7.44 +class Args:
    7.45 +    def __init__( self, req ):
    7.46 +        from mod_python.util import FieldStorage
    7.47 +        self.fieldStorage = FieldStorage( req, True )
    7.48  
    7.49 -        mod = getVar( 'mod', request )
    7.50 -                
    7.51 -        if not mod is None and args is None:
    7.52 -            module = self.modules[ mod ]
    7.53 -            #check module exists
    7.54 -            if module:
    7.55 -               module( self.mainUrlWriter ).perform( request )
    7.56 +    # return a list of values for the given key,
    7.57 +    # or None if key not there
    7.58 +    def get( self, var ):
    7.59 +        retVar = self.fieldStorage.getlist( var )
    7.60 +        if len( retVar ) == 0:
    7.61 +            return None
    7.62          else:
    7.63 -            self.perform( request )     
    7.64 -    
    7.65 -        return self.render_GET( request )
    7.66 +            return retVar
    7.67 +
    7.68 +    # return a list of tuples,
    7.69 +    # (key, value) where value is a list of values
    7.70 +    def items( self ):
    7.71 +        result = [];
    7.72 +        for key in self.fieldStorage.keys():
    7.73 +            result.append( (key, self.fieldStorage.getlist( key ) ) )
    7.74 +        return result
    7.75 +                                                                                                                                                            
    7.76 +class TwistedAdapter:
    7.77 +    def __init__( self, req ):
    7.78 +        self.args = Args( req )
    7.79 +        self.uri = req.unparsed_uri
    7.80 +        self.url = req.uri
    7.81 +        self.write = req.write
    7.82 +
    7.83 +# This is the Main class
    7.84 +# It peices together all the modules
    7.85  
    7.86 -    def mainUrlWriter( self, module ):
    7.87 -    	def fun( f ):
    7.88 -            return "Main.rpy?mod=%s%s" % ( module, f )
    7.89 -        return fun    
    7.90 -        
    7.91 -    def write_BODY( self, request ):
    7.92 -    
    7.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" )
    7.94 -        request.write( "<tr>\n" )
    7.95 -        request.write( " <td width='15px'>&nbsp;</td>" )
    7.96 -        request.write( " <td width='175px' align='center' valign'center'>" )
    7.97 -        request.write( "  <table cellspacing='0' cellpadding='0' border='0' width='100%' height='100%'>" )
    7.98 -        request.write( "   <tr><td height='140px' align='center' valign='bottom'><a href='http://www.cl.cam.ac.uk/Research/SRG/netos/xen/'>" )
    7.99 -        request.write( "   <img src='images/xen.png' width='150' height='75' border='0'/></a><br/></td></tr>" )
   7.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>")
   7.101 -        request.write( "   <tr><td align='center' valign='top'>" )
   7.102 +class Main:
   7.103 +    def __init__( self ):
   7.104 +        self.modules = { "node": NodeInfo, 
   7.105 +                         "create": CreateDomain,
   7.106 +                         "restore" : RestoreDomain,
   7.107 +                         "info": DomInfo }
   7.108 +
   7.109 +        self.init_done = False
   7.110 +
   7.111 +    def init_modules( self, request ):
   7.112 +        for moduleName, module in self.modules.iteritems():
   7.113 +            self.modules[ moduleName ] = module( self.urlWriter( moduleName, request.url ) )             
   7.114  
   7.115 -        for modName in self.module_menus:
   7.116 -            self.modules[modName]( self.mainUrlWriter( modName ) ).write_MENU( request )
   7.117 -        
   7.118 -        request.write( "   </td></tr>" )
   7.119 -        request.write( "  </table>" )
   7.120 -        request.write( " &nbsp;" )
   7.121 -        request.write( " </td>\n" )
   7.122 -        request.write( " <td width='15px'>&nbsp;</td>" )
   7.123 -        request.write( " <td width='558px' align='left' valign='top'>" )
   7.124 -        request.write( "  <table cellspacing='0' cellpadding='0' border='0' width='100%' height='100%'>" )
   7.125 -        request.write( "   <tr><td height='20px'></td></tr>" )
   7.126 -        request.write( "   <tr><td align='center' valign='top'>" )
   7.127 -        
   7.128 -        modName = getVar('mod', request)
   7.129 -        
   7.130 -        if modName is None:
   7.131 +    def render_menu( self, request ):
   7.132 +        if not self.init_done:
   7.133 +            self.init_modules( request )
   7.134 +            self.init_done = True
   7.135 +            
   7.136 +        for moduleName, module in self.modules.iteritems():
   7.137 +            module.write_MENU( request )
   7.138 +            request.write( "\n" )
   7.139 +
   7.140 +    def render_main( self, request ):
   7.141 +        if not self.init_done:
   7.142 +            self.init_modules( request )
   7.143 +            self.init_done = True
   7.144 +                                   
   7.145 +        moduleName = getVar('mod', request)
   7.146 +        if moduleName not in self.modules:
   7.147              request.write( '<p>Please select a module</p>' )
   7.148          else:
   7.149 -            module = self.modules[ modName ]
   7.150 -            if module:
   7.151 -               module( self.mainUrlWriter( modName ) ).write_BODY( request )  
   7.152 -            else:
   7.153 -               request.write( '<p>Invalid module. Please select another</p>' )
   7.154 -    
   7.155 -        request.write( "   </td></tr>" )
   7.156 -        request.write( "  </table>" )
   7.157 -        request.write( " </td>\n" )
   7.158 -        request.write( " <td width='17px'>&nbsp;</td>" )
   7.159 -        request.write( "</tr>\n" )
   7.160 -        
   7.161 -        request.write( "</table>\n" )
   7.162 +            module = self.modules[ moduleName ]
   7.163 +            module.write_BODY( request )
   7.164 +
   7.165 +    def do_POST( self, request ): 
   7.166 +        if not self.init_done:
   7.167 +            self.init_modules( request )
   7.168 +            self.init_done = True                       
   7.169          
   7.170 -                
   7.171 -    def op_destroy( self, request ):
   7.172 -    	dom = getVar( 'dom', request )
   7.173 -        if not dom is None and dom != "0":
   7.174 -            server.xend_domain_destroy( int( dom ), "halt" ) 
   7.175 -                 
   7.176 -    def op_pause( self, request ):
   7.177 -    	dom = getVar( 'dom', request )
   7.178 -        if not dom is None and dom != "0":
   7.179 -            server.xend_domain_pause( int( dom ) )      
   7.180 -    
   7.181 -    def op_unpause( self, request ):
   7.182 -    	dom = getVar( 'dom', request )
   7.183 -        if not dom is None and dom != "0":
   7.184 -            server.xend_domain_unpause( int( dom ) )      
   7.185 +    	moduleName = getVar( 'mod', request )      
   7.186 +        if moduleName in self.modules:
   7.187 +            self.modules[ moduleName ].perform( request )
   7.188 +
   7.189 +    def urlWriter( self, module, url ):
   7.190 +        return lambda x: "%s?mod=%s%s" % ( url, module, x )
     8.1 --- a/tools/python/xen/sv/MigrateDomain.py	Tue Aug 09 10:42:51 2005 +0000
     8.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.3 @@ -1,74 +0,0 @@
     8.4 -from xen.sv.Wizard import *
     8.5 -from xen.sv.util import *
     8.6 -from xen.sv.GenTabbed import PreTab
     8.7 -
     8.8 -from xen.xm.create import make_config, OptVals
     8.9 -
    8.10 -from xen.xend.XendClient import server
    8.11 -
    8.12 -class MigrateDomain( Wizard ):
    8.13 -    def __init__( self, urlWriter ):
    8.14 -
    8.15 -        sheets = [ ChooseMigrateDomain,
    8.16 -                   DoMigrate ]
    8.17 -
    8.18 -        Wizard.__init__( self, urlWriter, "Migrate Domain", sheets )
    8.19 -
    8.20 -
    8.21 -class ChooseMigrateDomain( Sheet ):
    8.22 -    def __init__( self, urlWriter ):
    8.23 -        Sheet.__init__( self, urlWriter, "Configure Migration", 0)
    8.24 -	domains = []
    8.25 -	domnames = []
    8.26 -
    8.27 -        try:
    8.28 -            domains = server.xend_domains()
    8.29 -            domains.sort()
    8.30 -        except:
    8.31 -            pass
    8.32 -
    8.33 -        for i in domains:
    8.34 -            if i != 'Domain-0': domnames.append((i,i))
    8.35 -        
    8.36 -        self.addControl( ListControl('domid',
    8.37 -                                     domnames,
    8.38 -                                     'Domain ID:') )
    8.39 -        self.addControl( TickControl('live',
    8.40 -                                     'True',
    8.41 -                                     'Live migrate:') )
    8.42 -        self.addControl( InputControl('rate',
    8.43 -                                      '0',
    8.44 -                                      'Rate limit:') )
    8.45 -        self.addControl( InputControl( 'dest', 'myhost.mydomain',
    8.46 -                                       'Name or IP address:',
    8.47 -                                       ".*") )
    8.48 -
    8.49 -class DoMigrate( Sheet ):
    8.50 -    def __init__(self, urlWriter ):
    8.51 -        Sheet.__init__(self, urlWriter, "Migration Done", 1)
    8.52 -
    8.53 -    def write_BODY( self, request, err ):
    8.54 -
    8.55 -        if not self.passback: self.parseForm( request )
    8.56 -
    8.57 -#        print string2sxp(self.passback)
    8.58 -        
    8.59 -        config = ssxp2hash ( string2sxp( self.passback ) )
    8.60 -      
    8.61 -        try:
    8.62 -            print config
    8.63 -            print config['domid'], config['dest']
    8.64 -            dom_sxp = server.xend_domain_migrate( config['domid'],
    8.65 -                                                  config['dest'],
    8.66 -                                                  config.get('live') == 'True',
    8.67 -                                                  config['rate'] )
    8.68 -            success = "Your domain was successfully Migrated.\n"
    8.69 -        except Exception, e:
    8.70 -            success = "There was an error migrating your domain\n"
    8.71 -            dom_sxp = str(e)
    8.72 -        
    8.73 -        pt = PreTab( success + dom_sxp ) # sxp2prettystring( dom_sxp ) )
    8.74 -        pt.write_BODY( request )
    8.75 -
    8.76 -        request.write( "<input type='hidden' name='passback' value=\"%s\"></p>" % self.passback )
    8.77 -        request.write( "<input type='hidden' name='sheet' value='%s'></p>" % self.location )
     9.1 --- a/tools/python/xen/sv/NodeInfo.py	Tue Aug 09 10:42:51 2005 +0000
     9.2 +++ b/tools/python/xen/sv/NodeInfo.py	Tue Aug 09 12:55:18 2005 +0000
     9.3 @@ -6,18 +6,18 @@ from xen.sv.GenTabbed import *
     9.4  class NodeInfo( GenTabbed ):
     9.5  
     9.6      def __init__( self, urlWriter ):  
     9.7 -        GenTabbed.__init__( self, "Node Details", urlWriter, [ 'General', 'Dmesg', ], [ NodeGeneralTab, NodeDmesgTab ] )
     9.8 +        GenTabbed.__init__( self, "Node Details", urlWriter, [ 'General', 'Dmesg', 'SXP' ], [ NodeGeneralTab, NodeDmesgTab, NodeSXPTab ] )
     9.9      
    9.10      def write_MENU( self, request ):
    9.11          request.write( "<p class='small'><a href='%s'>Node details</a></p>" % self.urlWriter( '' ) )
    9.12  
    9.13  class NodeGeneralTab( CompositeTab ):
    9.14 -    def __init__( self ):
    9.15 -    	CompositeTab.__init__( self, [ NodeInfoTab, NodeActionTab ] )        
    9.16 +    def __init__( self, urlWriter ):
    9.17 +    	CompositeTab.__init__( self, [ NodeInfoTab, NodeActionTab ], urlWriter )        
    9.18          
    9.19  class NodeInfoTab( GeneralTab ):
    9.20                          
    9.21 -    def __init__( self ):
    9.22 +    def __init__( self, urlWriter ):
    9.23           
    9.24      	nodeInfo = {}
    9.25          try:
    9.26 @@ -41,7 +41,7 @@ class NodeInfoTab( GeneralTab ):
    9.27  
    9.28  class NodeDmesgTab( PreTab ):
    9.29  
    9.30 -    def __init__( self ):
    9.31 +    def __init__( self, urlWriter ):
    9.32      	try:
    9.33              dmesg = server.xend_node_get_dmesg()
    9.34          except:
    9.35 @@ -50,7 +50,7 @@ class NodeDmesgTab( PreTab ):
    9.36    
    9.37  class NodeActionTab( ActionTab ):
    9.38  
    9.39 -    def __init__( self ):
    9.40 +    def __init__( self, urlWriter ):
    9.41          ActionTab.__init__( self, { "shutdown" : "shutdown",
    9.42          	"reboot" : "reboot" } )    
    9.43          
    9.44 @@ -61,3 +61,13 @@ class NodeActionTab( ActionTab ):
    9.45      def op_reboot( self, request ):
    9.46          if debug: print ">NodeReboot"
    9.47          server.xend_node_reboot()
    9.48 +
    9.49 +class NodeSXPTab( PreTab ):
    9.50 +
    9.51 +    def __init__( self, urlWriter ):
    9.52 +        try:
    9.53 +            nodeSXP = sxp2string( server.xend_node() )
    9.54 +        except:
    9.55 +            nodeSXP = 'Error getting node sxp'
    9.56 +
    9.57 +        PreTab.__init__( self, nodeSXP )
    10.1 --- a/tools/python/xen/sv/RestoreDomain.py	Tue Aug 09 10:42:51 2005 +0000
    10.2 +++ b/tools/python/xen/sv/RestoreDomain.py	Tue Aug 09 12:55:18 2005 +0000
    10.3 @@ -16,6 +16,8 @@ class RestoreDomain( Wizard ):
    10.4  
    10.5  
    10.6  class ChooseRestoreDomain( Sheet ):
    10.7 +    title = "Configure Restore"
    10.8 +
    10.9      def __init__( self, urlWriter ):
   10.10          Sheet.__init__( self, urlWriter, "Configure Restore", 0)
   10.11          
   10.12 @@ -24,6 +26,8 @@ class ChooseRestoreDomain( Sheet ):
   10.13                                         ".*") )
   10.14  
   10.15  class DoRestore( Sheet ):
   10.16 +    title = "Restore Done"
   10.17 +    
   10.18      def __init__(self, urlWriter ):
   10.19          Sheet.__init__(self, urlWriter, "Restore Done", 1)
   10.20  
    11.1 --- a/tools/python/xen/sv/SaveDomain.py	Tue Aug 09 10:42:51 2005 +0000
    11.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.3 @@ -1,62 +0,0 @@
    11.4 -from xen.sv.Wizard import *
    11.5 -from xen.sv.util import *
    11.6 -from xen.sv.GenTabbed import PreTab
    11.7 -
    11.8 -from xen.xm.create import make_config, OptVals
    11.9 -
   11.10 -from xen.xend.XendClient import server
   11.11 -
   11.12 -class SaveDomain( Wizard ):
   11.13 -    def __init__( self, urlWriter ):
   11.14 -
   11.15 -        sheets = [ ChooseSaveDomain,
   11.16 -                   DoSave ]
   11.17 -
   11.18 -        Wizard.__init__( self, urlWriter, "Save Domain", sheets )
   11.19 -
   11.20 -
   11.21 -class ChooseSaveDomain( Sheet ):
   11.22 -    def __init__( self, urlWriter ):
   11.23 -        Sheet.__init__( self, urlWriter, "Configure Save", 0)
   11.24 -        
   11.25 -	domains = []
   11.26 -	domnames = []
   11.27 -
   11.28 -	try:
   11.29 -            domains = server.xend_domains()
   11.30 -            domains.sort()
   11.31 -        except:
   11.32 -            pass
   11.33 -
   11.34 -        for i in domains:
   11.35 -            if i != 'Domain-0': domnames.append((i,i))
   11.36 -        
   11.37 -        self.addControl( ListControl('domid',
   11.38 -                                     domnames,
   11.39 -                                     'Domain ID:') )
   11.40 -        self.addControl( InputControl( 'file', '',
   11.41 -                                       'Suspend file name:',
   11.42 -                                       ".*") )
   11.43 -
   11.44 -class DoSave( Sheet ):
   11.45 -    def __init__(self, urlWriter ):
   11.46 -        Sheet.__init__(self, urlWriter, "Save Done", 1)
   11.47 -
   11.48 -    def write_BODY( self, request, err ):
   11.49 -
   11.50 -        if not self.passback: self.parseForm( request )
   11.51 -        config = ssxp2hash ( string2sxp( self.passback ) )
   11.52 -      
   11.53 -        try:
   11.54 -            dom_sxp = server.xend_domain_save( config['domid'],
   11.55 -                                                  config['file'] )
   11.56 -            success = "Your domain was successfully saved.\n"
   11.57 -        except Exception, e:
   11.58 -            success = "There was an error saving your domain\n"
   11.59 -            dom_sxp = str(e)
   11.60 -        
   11.61 -        pt = PreTab( success + dom_sxp ) # sxp2prettystring( dom_sxp ) )
   11.62 -        pt.write_BODY( request )
   11.63 -
   11.64 -        request.write( "<input type='hidden' name='passback' value=\"%s\"></p>" % self.passback )
   11.65 -        request.write( "<input type='hidden' name='sheet' value='%s'></p>" % self.location )
    12.1 --- a/tools/python/xen/sv/TabView.py	Tue Aug 09 10:42:51 2005 +0000
    12.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.3 @@ -1,26 +0,0 @@
    12.4 -from xen.sv.HTMLBase import HTMLBase
    12.5 -
    12.6 -class TabView( HTMLBase ):
    12.7 -
    12.8 -    # tab - int, id into tabs of selected tab
    12.9 -    # tabs - list of strings, tab names
   12.10 -    # urlWriter - 
   12.11 -    def __init__( self, tab, tabs, urlWriter ):
   12.12 -        HTMLBase.__init__(self)
   12.13 -        self.tab = tab
   12.14 -        self.tabs = tabs
   12.15 -        self.urlWriter = urlWriter
   12.16 -
   12.17 -    def write_BODY( self, request ):
   12.18 -        request.write( "<table style='' border='0' cellspacing='3' cellpadding='2' align='center'>" )
   12.19 -        request.write( "<tr height='22'>" )                  
   12.20 -    
   12.21 -        for i in range( len( self.tabs ) ):
   12.22 -            if self.tab == i:
   12.23 -                backgroundColor = "white"
   12.24 -            else:
   12.25 -                backgroundColor = "grey"
   12.26 -        
   12.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 ] ) )
   12.28 -  
   12.29 -        request.write( "</tr></table>" )
    13.1 --- a/tools/python/xen/sv/Wizard.py	Tue Aug 09 10:42:51 2005 +0000
    13.2 +++ b/tools/python/xen/sv/Wizard.py	Tue Aug 09 12:55:18 2005 +0000
    13.3 @@ -1,71 +1,44 @@
    13.4  from xen.sv.util import *
    13.5  from xen.sv.HTMLBase import HTMLBase
    13.6 +from xen.sv.GenTabbed import GenTabbed, ActionTab
    13.7  from xen.xend import sxp
    13.8  
    13.9  import re
   13.10  
   13.11  DEBUG = 0
   13.12  
   13.13 -class Wizard( HTMLBase ):
   13.14 +class Wizard( GenTabbed ):
   13.15  
   13.16      def __init__( self, urlWriter, title, sheets ):
   13.17 -        HTMLBase.__init__( self )
   13.18          self.title = title
   13.19          self.sheets = sheets
   13.20          self.urlWriter = urlWriter
   13.21 +        self.offset = 0
   13.22 +        GenTabbed.__init__( self, title, urlWriter, map( lambda x: x.title, sheets ), sheets ) 
   13.23          
   13.24      def write_MENU( self, request ):
   13.25      	request.write( "<p class='small'><a href='%s'>%s</a></p>" % (self.urlWriter( '' ), self.title) ) 
   13.26      
   13.27      def write_BODY( self, request ):
   13.28 -        
   13.29 -   	request.write( "<table width='100%' border='0' cellspacing='0' cellpadding='0'><tr><td>" )
   13.30 -        request.write( "<p align='center'><u>%s</u></p></td></tr><tr><td>" % self.title )
   13.31 -        
   13.32 -        currSheet = getVar( 'sheet', request )
   13.33 -    
   13.34 -        if not currSheet is None:
   13.35 -            currSheet = int( currSheet )
   13.36 -        else:
   13.37 -            currSheet = 0
   13.38 +        GenTabbed.write_BODY( self, request )
   13.39 +        actionTab = ActionTab( { ("tab", str(self.tab-1)) : "< Prev", ("tab", str(self.tab+1)) : "Next >", "finish" : "Finish" } )
   13.40 +        actionTab.write_BODY( request )
   13.41 +
   13.42 +    def perform( self, request ):
   13.43 +        try:
   13.44 +            action = getVar( 'op', request, 0 )
   13.45 +            if action == "tab":
   13.46 +                self.tab = int( getVar( 'args', request ) )
   13.47 +                oldtab = int( getVar( 'tab', request ) )
   13.48 +                if not self.tabObjects[ oldtab ]( self.urlWriter ).validate( request ):
   13.49 +                    self.tab = oldtab
   13.50 +            else:
   13.51 +                self.tab = int( getVar( 'tab', request, 0 ) )
   13.52 +                self.tabObjects[ self.tab ]( self.urlWriter ).perform( request )
   13.53 +                getattr( self, "op_" +  getVar( "op", request ), None )( request )
   13.54 +        except:
   13.55 +            pass
   13.56              
   13.57 -        sheet = self.sheets[ currSheet ]( self.urlWriter )
   13.58 -        
   13.59 -        err = not sheet.validate( request )
   13.60 -        
   13.61 -        if not err:    
   13.62 -            op = getVar( 'op', request )
   13.63 -        
   13.64 -            if op == 'next':
   13.65 -               currSheet += 1
   13.66 -            elif op == 'prev':
   13.67 -               currSheet -= 1
   13.68 -             
   13.69 -            sheet = self.sheets[ currSheet ]( self.urlWriter )
   13.70 -        
   13.71 -        if getVar( 'visited-sheet%s' % currSheet, request ):
   13.72 -            sheet.write_BODY( request, err )
   13.73 -        else:
   13.74 -            sheet.write_BODY( request, False )
   13.75 -
   13.76 -        
   13.77 -        request.write( "</td></tr><tr><td><table width='100%' border='0' cellspacing='0' cellpadding='0'><tr>" )
   13.78 -        request.write( "<td width='80%'></td><td width='20%' align='center'><p align='center'>" )
   13.79 -	if currSheet > 0:
   13.80 -       	    request.write( "<img src='images/previous.png' onclick='doOp( \"prev\" )' onmouseover='update( \"wizText\", \"Previous\" )' onmouseout='update( \"wizText\", \"&nbsp;\" )'>&nbsp;" )
   13.81 -        if currSheet < ( len( self.sheets ) - 2 ):        
   13.82 -            request.write( "<img src='images/next.png' onclick='doOp( \"next\" )' onmouseover='update( \"wizText\", \"Next\" )' onmouseout='update( \"wizText\", \"&nbsp;\" )'>" )
   13.83 -        elif currSheet == ( len( self.sheets ) - 2 ):
   13.84 -            request.write( "<img src='images/finish.png' onclick='doOp( \"next\" )' onmouseover='update( \"wizText\", \"Finish\" )' onmouseout='update( \"wizText\", \"&nbsp;\" )'>" )
   13.85 -        request.write( "</p><p align='center'><span id='wizText'></span></p></td></tr></table>" )
   13.86 -        request.write( "</td></tr></table>" )
   13.87 -        
   13.88 -    def op_next( self, request ):
   13.89 -    	pass
   13.90 -        
   13.91 -    def op_prev( self, request ):
   13.92 -    	pass
   13.93 -        
   13.94      def op_finish( self, request ):
   13.95      	pass  
   13.96          
   13.97 @@ -80,7 +53,7 @@ class Sheet( HTMLBase ):
   13.98          self.passback = None
   13.99          
  13.100      def parseForm( self, request ):
  13.101 -    	do_not_parse = [ 'mod', 'op', 'sheet', 'passback' ] 
  13.102 +    	do_not_parse = [ 'mod', 'op', 'passback' ] 
  13.103      
  13.104      	passed_back = request.args
  13.105          
  13.106 @@ -103,7 +76,7 @@ class Sheet( HTMLBase ):
  13.107          
  13.108          if DEBUG: print self.passback
  13.109          
  13.110 -    def write_BODY( self, request, err ):
  13.111 +    def write_BODY( self, request ):
  13.112      
  13.113      	if not self.passback: self.parseForm( request )
  13.114          
  13.115 @@ -115,14 +88,13 @@ class Sheet( HTMLBase ):
  13.116          
  13.117      	for (feild, control) in self.feilds:
  13.118              control.write_Control( request, previous_values.get( feild ) )
  13.119 -            if err and not control.validate( previous_values.get( feild ) ):
  13.120 +            if previous_values.get( feild ) is not None and not control.validate( previous_values.get( feild ) ):
  13.121              	control.write_Help( request )
  13.122              
  13.123          request.write( "</table>" )
  13.124              
  13.125          request.write( "<input type='hidden' name='passback' value=\"%s\"></p>" % self.passback )
  13.126 -        request.write( "<input type='hidden' name='sheet' value='%s'></p>" % self.location )
  13.127 -        request.write( "<input type='hidden' name='visited-sheet%s' value='True'></p>" % self.location )
  13.128 +        #request.write( "<input type='hidden' name='visited-sheet%s' value='True'></p>" % self.location )
  13.129                  
  13.130      def addControl( self, control ):
  13.131      	self.feilds.append( [ control.getName(), control ] )
  13.132 @@ -133,7 +105,7 @@ class Sheet( HTMLBase ):
  13.133              
  13.134      	check = True
  13.135          
  13.136 -        previous_values = ssxp2hash( string2sxp( self.passback ) ) #get the hash for quick reference
  13.137 +        previous_values = ssxp2hash( string2sxp( self.passback ) ) #get the map for quick reference
  13.138      	if DEBUG: print previous_values
  13.139        
  13.140        	for (feild, control) in self.feilds:
  13.141 @@ -258,12 +230,16 @@ class TickControl( SheetControl ):
  13.142          
  13.143      def write_Control( self, request, persistedValue ):
  13.144          request.write( "<tr><td width='50%%'><p>%s</p></td><td width='50%%'>" % self.humanText )
  13.145 +
  13.146 +        #request.write( str( persistedValue ) )
  13.147 +
  13.148 +        #TODO: Theres a problem with this: it doesn't persist an untick, because the browsers don't pass it back. Need a fix...
  13.149          
  13.150          if persistedValue == 'True':
  13.151      	    request.write( "<input type='checkbox' name='%s' value='True' checked>" % self.getName() )
  13.152          else:
  13.153      	    request.write( "<input type='checkbox' name='%s' value='True'>" % self.getName() )
  13.154              
  13.155 -        request.write( "</select></td></tr>" )
  13.156 +        request.write( "</td></tr>" )
  13.157  
  13.158        
    14.1 --- a/tools/python/xen/sv/params.py	Tue Aug 09 10:42:51 2005 +0000
    14.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.3 @@ -1,3 +0,0 @@
    14.4 -SV_PORT = 8080
    14.5 -SV_ROOT = "/var/lib/xen/sv/"
    14.6 -PID_FILE = "/var/run/xen-sv.pid"
    15.1 --- a/tools/python/xen/sv/util.py	Tue Aug 09 10:42:51 2005 +0000
    15.2 +++ b/tools/python/xen/sv/util.py	Tue Aug 09 12:55:18 2005 +0000
    15.3 @@ -4,7 +4,7 @@ from xen.xend import PrettyPrint
    15.4  
    15.5  import types
    15.6  
    15.7 -def getDomInfoHash( domain ):
    15.8 +def getDomInfo( domain ):
    15.9      domInfoHash = {}
   15.10      try:
   15.11          domInfoHash = sxp2hash( server.xend_domain( domain ) )
    16.1 Binary file tools/sv/images/internet.jpg has changed
    17.1 Binary file tools/sv/images/internet.psd has changed
    18.1 Binary file tools/sv/images/orb_01.jpg has changed
    19.1 Binary file tools/sv/images/orb_02.jpg has changed
    20.1 Binary file tools/sv/images/seperator-left-highlight.jpg has changed
    21.1 Binary file tools/sv/images/seperator-right-highlight.jpg has changed
    22.1 Binary file tools/sv/images/seperator.jpg has changed
    23.1 --- a/tools/sv/inc/style.css	Tue Aug 09 10:42:51 2005 +0000
    23.2 +++ b/tools/sv/inc/style.css	Tue Aug 09 12:55:18 2005 +0000
    23.3 @@ -1,32 +1,95 @@
    23.4 +.small  {
    23.5 +	font-size: 10px
    23.6 +}
    23.7  
    23.8 -P       {font-family: verdana, arial; font-size: 12px; color: black}
    23.9 -.small  {font-size: 10px}
   23.10 +TD.domainInfo     { 
   23.11 +	font-size: 10px; 
   23.12 +	color: black
   23.13 +}
   23.14  
   23.15 -TD.domainInfo     {font-family: verdana, arial; font-size: 10px; color: black}
   23.16 -TD.domainInfoHead {font-family: verdana, arial; font-size: 10px; color: white; font-face: bold}
   23.17 +TD.domainInfoHead {
   23.18 +	font-size: 10px; 
   23.19 +	color: white; 
   23.20 +	font-face: bold
   23.21 +}
   23.22  
   23.23  TD.domainInfoHead {background-color: black}
   23.24  TR.domainInfoOdd  {background-color: white}
   23.25  TR.domainInfoEven {background-color: lightgrey}
   23.26  
   23.27  body { 
   23.28 -	width: 670px;
   23.29 -	margin: 0px;
   23.30 -	padding: 0px;
   23.31 -	background-color: #fff;
   23.32 -	background-image: url(../images/orb_02.jpg);
   23.33 -	background-repeat: repeat-y;
   23.34 -	background-position: left top;
   23.35 -	font-family: Arial, Helvetica, sans-serif;
   23.36 -	font-weight: bold;
   23.37 -	color: #333333;
   23.38 -	letter-spacing: 0px;
   23.39 -	scrollbar-base-color: #333333;
   23.40 -	scrollbar-track-color: #666666;
   23.41 -	scrollbar-face-color: #fff;
   23.42 -	
   23.43 -	
   23.44 -	}
   23.45 -        
   23.46 -.button (cursor:hand)
   23.47 -	
   23.48 +	margin: 	0px;
   23.49 +	padding: 	0px;
   23.50 +	font-family: 	Arial, Helvetica, sans-serif;
   23.51 +	font-size:	12px;
   23.52 +	color: 		#000000;
   23.53 +}
   23.54 +
   23.55 +div#menu {
   23.56 +        position:       absolute;
   23.57 +        left:           10px;
   23.58 +        top:            10px;
   23.59 +        width:          160px;
   23.60 +        padding:        10px;
   23.61 +        border:         0px solid black;
   23.62 +        text-align:     center;
   23.63 +}
   23.64 +
   23.65 +div#main {
   23.66 +        position:       absolute;
   23.67 +        left:           200px;
   23.68 +        top:            10px;
   23.69 +        right:          10px;
   23.70 +        padding:        10px;
   23.71 +        border:         0px solid black;
   23.72 +}
   23.73 +
   23.74 +div.button {
   23.75 +        float:          right;
   23.76 +        margin:         10px 0px 0px 10px;
   23.77 +        padding:        5px;
   23.78 +        text-align:     center;
   23.79 +        border:         1px solid black;
   23.80 +        background:     gray;
   23.81 +	cursor:		hand;
   23.82 +}
   23.83 +
   23.84 +div.tabButton {
   23.85 +	position:	relative;
   23.86 +	top: 		0px;
   23.87 +        float:          left;
   23.88 +        margin:         0px 10px -1px 0px;
   23.89 +        padding:        5px;
   23.90 +        text-align:     center;
   23.91 +        border:         1px solid black;
   23.92 +        background:     gray;
   23.93 +	cursor: 	hand;
   23.94 +}
   23.95 +
   23.96 +div.tabButton#activeTab {
   23.97 +	top:		0px;
   23.98 +        background:     white;
   23.99 +        border-color:   black black white black;
  23.100 +}
  23.101 +
  23.102 +div.button:hover, div.tabButton:hover {
  23.103 +        background:     white;
  23.104 +}
  23.105 +
  23.106 +div.button a, div.tabButton a {
  23.107 +        font-size:      12px;
  23.108 +	font-weight:	bold;
  23.109 +}
  23.110 +
  23.111 +div.title {
  23.112 +	float:          right;
  23.113 +	font-size:	14px;
  23.114 +	font-weight:	bold;
  23.115 +}
  23.116 +
  23.117 +div.tab {
  23.118 +        overflow:       auto;
  23.119 +        clear:          both;
  23.120 +        border:         1px solid black;
  23.121 +        padding:        10px;
  23.122 +}
    24.1 --- a/tools/sv/index.psp	Tue Aug 09 10:42:51 2005 +0000
    24.2 +++ b/tools/sv/index.psp	Tue Aug 09 12:55:18 2005 +0000
    24.3 @@ -7,158 +7,29 @@ debug = True and False
    24.4  for path in sys.path:
    24.5      if debug: req.write( path + "<br/>" )
    24.6  
    24.7 -from xen.sv.HTMLBase import HTMLBase
    24.8 -from xen.sv.DomList  import DomList
    24.9 -from xen.sv.NodeInfo import NodeInfo
   24.10 -from xen.sv.DomInfo  import DomInfo
   24.11 -from xen.sv.CreateDomain import CreateDomain
   24.12 -from xen.sv.MigrateDomain import MigrateDomain
   24.13 -from xen.sv.SaveDomain import SaveDomain
   24.14 -from xen.sv.RestoreDomain import RestoreDomain
   24.15 -
   24.16 -from xen.xend.XendClient import server
   24.17 -
   24.18 -from xen.sv.util import getVar
   24.19 -
   24.20 -# adapter to make this all work with mod_python
   24.21 -# (c) Tom Wilkie 2005
   24.22 -
   24.23 -class TwistedAdapter:
   24.24 -
   24.25 -    def write( self, text ):
   24.26 -        req.write( text )
   24.27 -
   24.28 -    class Args:
   24.29 -
   24.30 -        from mod_python.util import FieldStorage
   24.31 -
   24.32 -        fieldStorage = FieldStorage( req, True )
   24.33 -
   24.34 -        # return a list of values for the given key,
   24.35 -        # or None if key not there
   24.36 -        def get( self, var ):
   24.37 -            retVar = self.fieldStorage.getlist( var )
   24.38 -            if len( retVar ) == 0:
   24.39 -                return None
   24.40 -            else:
   24.41 -                return retVar
   24.42 -
   24.43 -        # return a list of tuples, 
   24.44 -        # (key, value) where value is a list of values
   24.45 -	def items( self ):
   24.46 -            result = [];
   24.47 -            for key in self.fieldStorage.keys():
   24.48 -            	result.append( (key, self.fieldStorage.getlist( key ) ) )
   24.49 -	    return result
   24.50 -
   24.51 -    args = Args()
   24.52 -
   24.53 -    uri = req.unparsed_uri
   24.54 -
   24.55 -
   24.56 -class Main( HTMLBase ):
   24.57 -    
   24.58 -    isLeaf = True
   24.59 -
   24.60 -    def __init__( self, urlWriter = None ):
   24.61 -        self.modules = { "node": NodeInfo, 
   24.62 -                         "list": DomList, 
   24.63 -                         "info": DomInfo,
   24.64 -                         "create": CreateDomain,
   24.65 -                         "migrate" : MigrateDomain,
   24.66 -                         "save" : SaveDomain,
   24.67 -                         "restore" : RestoreDomain }
   24.68 -
   24.69 -        # ordered list of module menus to display
   24.70 -        self.module_menus = [ "node", "create", "migrate", "save",
   24.71 -                              "restore", "list" ]
   24.72 -        HTMLBase.__init__(self)
   24.73 -        
   24.74 -    def render_POST( self, request ):
   24.75 -    
   24.76 -    	#decide what module post'd the action
   24.77 -                
   24.78 -    	args = getVar( 'args', request )
   24.79 -
   24.80 -        mod = getVar( 'mod', request )
   24.81 -                
   24.82 -        if mod in self.modules and args is None:
   24.83 -            module = self.modules[ mod ]
   24.84 -            #check module exists
   24.85 -            if module:
   24.86 -               module( self.mainUrlWriter ).perform( request )
   24.87 -        else:
   24.88 -            self.perform( request )     
   24.89 -    
   24.90 -        return self.render_GET( request )
   24.91 -
   24.92 -    #TODO: need to make this get the request uri automatically
   24.93 -    def mainUrlWriter( self, module ):
   24.94 -    	def fun( f ):
   24.95 -            return "index.psp?mod=%s%s" % ( module, f )
   24.96 -        return fun    
   24.97 -        
   24.98 -    def write_BODY( self, request ):
   24.99 -    
  24.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" )
  24.101 -        request.write( "<tr>\n" )
  24.102 -        request.write( " <td width='15px'>&nbsp;</td>" )
  24.103 -        request.write( " <td width='175px' align='center' valign'center'>" )
  24.104 -        request.write( "  <table cellspacing='0' cellpadding='0' border='0' width='100%' height='100%'>" )
  24.105 -        request.write( "   <tr><td height='140px' align='center' valign='bottom'><a href='http://www.cl.cam.ac.uk/Research/SRG/netos/xen/'>" )
  24.106 -        request.write( "   <img src='images/xen.png' width='150' height='75' border='0'/></a><br/></td></tr>" )
  24.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>")
  24.108 -        request.write( "   <tr><td align='center' valign='top'>" )
  24.109 -
  24.110 -        for modName in self.module_menus:
  24.111 -            self.modules[modName]( self.mainUrlWriter( modName ) ).write_MENU( request )
  24.112 -        
  24.113 -        request.write( "   </td></tr>" )
  24.114 -        request.write( "  </table>" )
  24.115 -        request.write( " &nbsp;" )
  24.116 -        request.write( " </td>\n" )
  24.117 -        request.write( " <td width='15px'>&nbsp;</td>" )
  24.118 -        request.write( " <td width='558px' align='left' valign='top'>" )
  24.119 -        request.write( "  <table cellspacing='0' cellpadding='0' border='0' width='100%' height='100%'>" )
  24.120 -        request.write( "   <tr><td height='20px'></td></tr>" )
  24.121 -        request.write( "   <tr><td align='center' valign='top'>" )
  24.122 -        
  24.123 -        modName = getVar('mod', request)
  24.124 -        
  24.125 -        if modName not in self.modules:
  24.126 -            request.write( '<p>Please select a module</p>' )
  24.127 -        else:
  24.128 -            module = self.modules[ modName ]
  24.129 -            if module:
  24.130 -               module( self.mainUrlWriter( modName ) ).write_BODY( request )  
  24.131 -            else:
  24.132 -               request.write( '<p>Invalid module. Please select another</p>' )
  24.133 -    
  24.134 -        request.write( "   </td></tr>" )
  24.135 -        request.write( "  </table>" )
  24.136 -        request.write( " </td>\n" )
  24.137 -        request.write( " <td width='17px'>&nbsp;</td>" )
  24.138 -        request.write( "</tr>\n" )
  24.139 -        
  24.140 -        request.write( "</table>\n" )
  24.141 -        
  24.142 -                
  24.143 -    def op_destroy( self, request ):
  24.144 -    	dom = getVar( 'dom', request )
  24.145 -        if not dom is None and dom != "0":
  24.146 -            server.xend_domain_destroy( int( dom ), "halt" ) 
  24.147 -                 
  24.148 -    def op_pause( self, request ):
  24.149 -    	dom = getVar( 'dom', request )
  24.150 -        if not dom is None and dom != "0":
  24.151 -            server.xend_domain_pause( int( dom ) )      
  24.152 -    
  24.153 -    def op_unpause( self, request ):
  24.154 -    	dom = getVar( 'dom', request )
  24.155 -        if not dom is None and dom != "0":
  24.156 -            server.xend_domain_unpause( int( dom ) )      
  24.157 +from xen.sv.Main import Main, TwistedAdapter
  24.158  
  24.159  main = Main()
  24.160 -
  24.161 -main.render_POST( TwistedAdapter() )
  24.162 +request = TwistedAdapter( req )
  24.163 +main.do_POST( request )
  24.164  %>
  24.165 +<html>
  24.166 +<head>
  24.167 +	<title>XenSV</title>
  24.168 +	<script src="inc/script.js"></script>
  24.169 +	<link rel="StyleSheet" type="text/css" href="inc/style.css">
  24.170 +</head>
  24.171 +<body>
  24.172 +    <form method="post" action="<%=request.uri%>">
  24.173 +        <div id="menu">
  24.174 +		<img src="images/xen.png">
  24.175 +		<% main.render_menu( request ) %>
  24.176 +	</div>
  24.177 +	<div id="main">
  24.178 +		<% main.render_main( request ) %>
  24.179 +	</div>
  24.180 +	<input type="hidden" name="op" value="">
  24.181 +        <input type="hidden" name="args" value="">
  24.182 +    </form>
  24.183 +</body>
  24.184 +</html>