# HG changeset patch
# User twilkie@xxxxxxxxxxxxxxxxxxxxxxx
# Node ID 12deebfb7f87fbcf2f0a0f60c732fb181570d342
# Parent  a1f7e01b0990a378584e718e6d48eac38824fdb9
Updates to SV. New look. Removed and simplified lots of files.
diff -r a1f7e01b0990 -r 12deebfb7f87 tools/python/xen/sv/CreateDomain.py
--- a/tools/python/xen/sv/CreateDomain.py       Tue Aug  9 10:42:51 2005
+++ b/tools/python/xen/sv/CreateDomain.py       Tue Aug  9 12:55:18 2005
@@ -17,26 +17,56 @@
                    CreateFinish ]
     
        Wizard.__init__( self, urlWriter, "Create Domain", sheets )
-       
+
+    def op_finish( self, request ):
+        pass
+    
 class CreatePage0( Sheet ):
 
+    title = "General"
+    
     def __init__( self, urlWriter ):
         Sheet.__init__( self, urlWriter, "General", 0 )
         self.addControl( InputControl( 'name', 'VM Name', 'VM Name:', 
"[\\w|\\S]+", "You must enter a name in this field" ) )
         self.addControl( InputControl( 'memory', '64', 'Memory (Mb):', 
"[\\d]+", "You must enter a number in this field" ) )
         self.addControl( InputControl( 'cpu', '0', 'CPU:', "[\\d]+", "You must 
enter a number in this feild" ) )
         self.addControl( InputControl( 'cpu_weight', '1', 'CPU Weight:', 
"[\\d]+", "You must enter a number in this feild" ) )
+        self.addControl( InputControl( 'vcpus', '1', 'Virtual CPUs:', 
'[\\d]+', "You must enter a number in this feild") )
                         
 class CreatePage1( Sheet ):
 
+    title = "Setup Kernel Image"
+
     def __init__( self, urlWriter ):
         Sheet.__init__( self, urlWriter, "Setup Kernel Image", 1 )
-# For now we don't need to select a builder...
-#        self.addControl( ListControl( 'builder', [('linux', 'Linux'), 
('netbsd', 'NetBSD')], 'Kernel Type:' ) )
-        self.addControl( FileControl( 'kernel', '/boot/vmlinuz-2.6.9-xenU', 
'Kernel Image:' ) )
+        self.addControl( ListControl( 'builder', [('linux', 'Linux'), 
('netbsd', 'NetBSD')], 'Domain Builder:' ) )
+        self.addControl( FileControl( 'kernel', '/boot/vmlinuz-2.6.12-xenU', 
'Kernel Image:' ) )
         self.addControl( InputControl( 'extra', '', 'Kernel Command Line 
Parameters:' ) )
+        self.addControl( ListControl( 'use-initrd', [('yes', 'Yes'), ('no', 
'No')], 'Use an Initial Ram Disk?:' ) )
+        self.addControl( FileControl( 'initrd', 
'/boot/initrd-2.6.12-xenU.img', 'Initial Ram Disk:' ) )
+
+    def validate( self, request ):
+        if not self.passback: self.parseForm( request )
+        check = True
+        request.write( previous_values.get( '>>>>>use-initrd' ) )
+        previous_values = ssxp2hash( string2sxp( self.passback ) ) #get the 
map for quick reference
+        if DEBUG: print previous_values
+        for (feild, control) in self.feilds:
+            if feild == 'initrd' and previous_values.get( 'use-initrd' ) != 
'no':
+                request.write( previous_values.get( '>>>>>use-initrd' ) )
+                if control.validate( previous_values.get( feild ) ):
+                    check = False
+            elif not control.validate( previous_values.get( feild ) ):
+                check = False
+
+            if DEBUG: print "> %s = %s" % (feild, previous_values.get( feild ))
+
+        return check
+                                                 
 
 class CreatePage2( Sheet ):
+
+    title = "Choose number of VBDS"
 
     def __init__( self, urlWriter ):
        Sheet.__init__( self, urlWriter, "Setup Virtual Block Device", 2 )
@@ -44,10 +74,12 @@
 
 class CreatePage3( Sheet ):
 
+    title = "Setup VBDS"
+
     def __init__( self, urlWriter ):
         Sheet.__init__( self, urlWriter, "Setup Virtual Block Device", 3 )
         
-    def write_BODY( self, request, err ):
+    def write_BODY( self, request ):
         if not self.passback: self.parseForm( request )
     
        previous_values = sxp2hash( string2sxp( self.passback ) ) #get the hash 
for quick reference
@@ -61,9 +93,11 @@
             
         self.addControl( InputControl( 'root', '/dev/sda1', 'Root device (in 
VM):' ) )
         
-        Sheet.write_BODY( self, request, err )
+        Sheet.write_BODY( self, request )
                 
 class CreatePage4( Sheet ):
+
+    title = "Network Setting"
 
     def __init__( self, urlWriter ):        
         Sheet.__init__( self, urlWriter, "Network settings", 4 )
@@ -76,26 +110,27 @@
                  
 class CreateFinish( Sheet ):
 
+    title = "Finish"
+
     def __init__( self, urlWriter ):
         Sheet.__init__( self, urlWriter, "All Done", 5 )
         
-    def write_BODY( self, request, err ):
+    def write_BODY( self, request ):
     
         if not self.passback: self.parseForm( request )
         
         xend_sxp = self.translate_sxp( string2sxp( self.passback ) )
+
+        request.write( "<pre>%s</pre>" % sxp2prettystring( xend_sxp ) )
         
         try:
-            dom_sxp = server.xend_domain_create( xend_sxp )
-            success = "Your domain was successfully created.\n"
-        except:
-            success = "There was an error creating your domain.\nThe 
configuration used is as follows:\n"
-            dom_sxp = xend_sxp
-            
-            
-        
-        pt = PreTab( success + sxp2prettystring( dom_sxp ) )
-        pt.write_BODY( request )
+            server.xend_domain_create( xend_sxp )
+            request.write( "<p>You domain had been successfully created.</p>" )
+        except Exception, e:
+            request.write( "<p>There was an error creating your 
domain.<br/>The configuration used is as follows:\n</p>" )
+            request.write( "<pre>%s</pre>" % sxp2prettystring( xend_sxp ) )
+            request.write( "<p>The error was:</p>" )
+            request.write( "<pre>%s</pre>" % str( e ) )
 
         request.write( "<input type='hidden' name='passback' 
value=\"%s\"></p>" % self.passback )
         request.write( "<input type='hidden' name='sheet' value='%s'></p>" % 
self.location )
@@ -117,6 +152,7 @@
         vals.maxmem =   get( 'maxmem' )
         vals.cpu =     get( 'cpu' )
         vals.cpu_weight = get( 'cpu_weight' )
+        vals.vcpus = get( 'vcpus' )
         
         vals.builder =  get( 'builder' )       
         vals.kernel =   get( 'kernel' )
@@ -128,7 +164,7 @@
         vbds = []
         
         for i in range( int( get( 'num_vbds' ) ) ):
-            vbds.append( ( get( 'vbd%s_dom0' % i ), get('vbd%s_domU' % i ), 
get( 'vbd%s_mode' % i ) ) )
+            vbds.append( ( get( 'vbd%s_dom0' % i ), get('vbd%s_domU' % i ), 
get( 'vbd%s_mode' % i ), None ) )
         
         vals.disk = vbds    
             
@@ -141,6 +177,9 @@
         vals.restart = None
         vals.console = None
         vals.ramdisk = None
+        vals.ssidref = -1
+        vals.bootloader = None
+        vals.usb = []
         
         #setup vifs
         
@@ -155,9 +194,11 @@
         dhcp = get( 'dhcp' )
         
         vals.cmdline_ip = "%s:%s:%s:%s:%s:eth0:%s" % (ip, nfs, gate, mask, 
host, dhcp)
+
+        opts = None
         
         try:
-            return make_config( vals )
-        except:
-            return [["Error creating domain config."]]    
-        
+            return make_config( opts, vals )
+        except Exception, e:
+            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]]    
+        
diff -r a1f7e01b0990 -r 12deebfb7f87 tools/python/xen/sv/DomInfo.py
--- a/tools/python/xen/sv/DomInfo.py    Tue Aug  9 10:42:51 2005
+++ b/tools/python/xen/sv/DomInfo.py    Tue Aug  9 12:55:18 2005
@@ -4,6 +4,7 @@
 from xen.sv.HTMLBase import HTMLBase
 from xen.sv.util import *
 from xen.sv.GenTabbed import *
+from xen.sv.Wizard import *
 
 DEBUG=1
 
@@ -12,33 +13,69 @@
     def __init__( self, urlWriter ):
         
         self.dom = 0;
-    
-        def tabUrlWriter( tab ):
-            return urlWriter( "&dom=%s%s" % ( self.dom, tab ) )
-        
-        GenTabbed.__init__( self, "Domain Info", tabUrlWriter, [ 'General', 
'SXP', 'Devices' ], [ DomGeneralTab, DomSXPTab, NullTab ]  )
+                   
+        GenTabbed.__init__( self, "Domain Info", urlWriter, [ 'General', 
'SXP', 'Devices', 'Migrate', 'Save' ], [ DomGeneralTab, DomSXPTab, 
DomDeviceTab, DomMigrateTab, DomSaveTab ]  )
 
     def write_BODY( self, request ):
-        dom = request.args.get('dom')
-        
-        if dom is None or len(dom) != 1:
+        try:
+            dom = int( getVar( 'dom', request ) )
+        except:
             request.write( "<p>Please Select a Domain</p>" )
             return None
-        else:
-            self.dom = dom[0]
-        
+       
         GenTabbed.write_BODY( self, request )
         
     def write_MENU( self, request ):
-        pass
-
+       domains = []
+
+       try:
+           domains = server.xend_domains()
+           domains.sort()
+       except:
+           pass
+
+       request.write( "\n<table style='border:0px solid white' cellspacing='0' 
cellpadding='0' border='0' width='100%'>\n" )
+       request.write( "<tr class='domainInfoHead'>" )
+       request.write( "<td class='domainInfoHead' 
align='center'>Domain</td>\n" )
+       request.write( "<td class='domainInfoHead' align='center'>Name</td>\n" )
+       request.write( "<td class='domainInfoHead' align='center'>State</td>\n" 
)
+       request.write( "<td class='domainInfoHead' align='center'></td>\n" )
+       request.write( "</tr>" )
+
+       odd = True
+       if not domains is None:
+           for domain in domains:
+               odd = not odd;
+               if odd:
+                   request.write( "<tr class='domainInfoOdd'>\n" )
+               else:
+                   request.write( "<tr class='domainInfoEven'>\n" )
+               domInfo = getDomInfo( domain )
+               request.write( "<td class='domainInfo' 
align='center'>%(id)s</td>\n" % domInfo )
+               url = self.urlWriter( "&dom=%(id)s" % domInfo )
+               request.write( "<td class='domainInfo' align='center'><a 
href='%s'>%s</a></td>\n" % ( url, domInfo['name'] ) )
+               request.write( "<td class='domainInfo' 
align='center'>%(state)5s</td>\n" % domInfo )
+               if domInfo[ 'id' ] != "0":
+                   request.write( "<td class='domainInfo' align='center'>" )
+                   if domInfo[ 'state' ][ 2 ] == "-":
+                       request.write( "<img src='images/small-pause.png' 
onclick='doOp2( \"pause\", \"%(dom)-4s\" )'>" % domInfo )
+                   else:
+                       request.write( "<img src='images/small-unpause.png' 
onclick='doOp2( \"unpause\", \"%(dom)-4s\" )'>" % domInfo )
+                   request.write( "<img src='images/small-destroy.png' 
onclick='doOp2( \"destroy\", \"%(dom)-4s\" )'></td>" % domInfo )
+               else:
+                   request.write( "<td> </td>" )
+               request.write( "</tr>\n" )
+       else:
+           request.write( "<tr colspan='10'><p class='small'>Error getting 
domain list<br/>Perhaps XenD not running?</p></tr>")
+       request.write( "</table>" )
+       
 class DomGeneralTab( CompositeTab ):
-    def __init__( self ):
-       CompositeTab.__init__( self, [ DomGenTab, DomActionTab ] )        
-        
+    def __init__( self, urlWriter ):
+       CompositeTab.__init__( self, [ DomGenTab, DomActionTab ], urlWriter )   
     
+       
 class DomGenTab( GeneralTab ):
 
-    def __init__( self ):
+    def __init__( self, urlWriter ):
     
         titles = {}
     
@@ -60,13 +97,13 @@
             request.write( "<p>Please Select a Domain</p>" )
             return None
             
-        self.dict = getDomInfoHash( self.dom )
+        self.dict = getDomInfo( self.dom )
         
         GeneralTab.write_BODY( self, request )
             
 class DomSXPTab( PreTab ):
 
-    def __init__( self ):
+    def __init__( self, urlWriter ):
         self.dom = 0
         PreTab.__init__( self, "" )
 
@@ -86,15 +123,15 @@
         self.source = sxp2prettystring( domInfo )
         
         PreTab.write_BODY( self, request )
-        
+       
 class DomActionTab( ActionTab ):
 
-    def __init__( self ):
-       actions = { "shutdown" : "shutdown",
-                   "reboot" : "reboot",
-                    "pause" : "pause",
-                    "unpause" : "unpause",
-                    "destroy" : "destroy" }
+    def __init__( self, urlWriter ):
+       actions = { "shutdown" : "Shutdown",
+                   "reboot" : "Reboot",
+                    "pause" : "Pause",
+                    "unpause" : "Unpause",
+                    "destroy" : "Destroy" }
         ActionTab.__init__( self, actions )    
         
     def op_shutdown( self, request ):
@@ -141,8 +178,91 @@
                server.xend_domain_destroy( int( dom ), "halt" )
            except:
                pass
-        
-    
-    
-        
-
+
+class DomDeviceTab( CompositeTab ):
+
+    def __init__( self, urlWriter ):
+        CompositeTab.__init__( self, [ DomDeviceListTab, DomDeviceOptionsTab, 
DomDeviceActionTab ], urlWriter )
+
+class DomDeviceListTab( NullTab ):
+
+    title = "Device List"
+
+    def __init__( self, urlWriter ):
+        pass
+
+class DomDeviceOptionsTab( NullTab ):
+
+    title = "Device Options"
+
+    def __init__( self, urlWriter ):
+        pass
+
+class DomDeviceActionTab( ActionTab ):
+
+    def __init__( self, urlWriter ):
+        ActionTab.__init__( self, { "addvcpu" : "Add VCPU", "addvbd" : "Add 
VBD", "addvif" : "Add VIF" } )
+
+class DomMigrateTab( CompositeTab ):
+
+    def __init__( self, urlWriter ):
+        CompositeTab.__init__( self, [ DomMigrateExtraTab, DomMigrateActionTab 
], urlWriter ) 
+
+class DomMigrateExtraTab( Sheet ):
+
+    def __init__( self, urlWriter ):
+        Sheet.__init__( self, urlWriter, "Configure Migration", 0)
+        self.addControl( TickControl('live', 'True', 'Live migrate:') )
+        self.addControl( InputControl('rate', '0', 'Rate limit:') )
+        self.addControl( InputControl( 'dest', 'host.domain', 'Name or IP 
address:', ".*") )
+                                                                               
                             
+class DomMigrateActionTab( ActionTab ):
+
+    def __init__( self, urlWriter ):
+        actions = { "migrate" : "Migrate" }
+        ActionTab.__init__( self, actions )
+                
+    def op_migrate( self, request ):
+        try:
+            domid = int( getVar( 'dom', request ) )
+            live  = getVar( 'live', request )
+            rate  = getVar( 'rate', request )
+            dest  = getVar( 'dest', request )
+            dom_sxp = server.xend_domain_migrate( domid, dest, live == 'True', 
rate )
+            success = "Your domain was successfully Migrated.\n"
+        except Exception, e:
+            success = "There was an error migrating your domain\n"
+            dom_sxp = str(e)
+                                                        
+class DomSaveTab( CompositeTab ):
+
+    def __init__( self, urlWriter ):
+        CompositeTab.__init__( self, [ DomSaveExtraTab, DomSaveActionTab ], 
urlWriter ) 
+
+class DomSaveExtraTab( Sheet ):
+
+    title = "Save location"
+
+    def __init__( self, urlWriter ):
+        Sheet.__init__( self, urlWriter, "Save Domain to file", 0 )
+        self.addControl( InputControl( 'file', '', 'Suspend file name:', ".*") 
)
+               
+class DomSaveActionTab( ActionTab ):
+
+    def __init__( self, urlWriter ):
+        actions = { "save" : "Save" }
+        ActionTab.__init__( self, actions )
+
+    def op_save( self, request ):
+
+        try:
+            dom_sxp = server.xend_domain_save( config['domid'], config['file'] 
)
+            success = "Your domain was successfully saved.\n"
+        except Exception, e:
+            success = "There was an error saving your domain\n"
+            dom_sxp = str(e)
+                                                                               
        
+        try:
+            dom = int( getVar( 'dom', request ) )
+        except:
+            pass
diff -r a1f7e01b0990 -r 12deebfb7f87 tools/python/xen/sv/GenTabbed.py
--- a/tools/python/xen/sv/GenTabbed.py  Tue Aug  9 10:42:51 2005
+++ b/tools/python/xen/sv/GenTabbed.py  Tue Aug  9 12:55:18 2005
@@ -1,7 +1,6 @@
 import types
 
 from xen.sv.HTMLBase import HTMLBase
-from xen.sv.TabView import TabView
 from xen.sv.util import getVar
 
 class GenTabbed( HTMLBase ):
@@ -12,39 +11,44 @@
         self.tabObjects = tabObjects
         self.urlWriter = urlWriter
         self.title = title
+        
+    def write_BODY( self, request ):
+        if not self.__dict__.has_key( "tab" ):
+            try:
+                self.tab = int( getVar( 'tab', request, 0 ) )
+            except:
+                self.tab = 0
+            
+        request.write( "\n<div class='title'>%s</div>" % self.title )
+        
+        TabView( self.tab, self.tabStrings, self.urlWriter ).write_BODY( 
request )
+        
+        try:
+            request.write( "\n<div class='tab'>" )
+            render_tab = self.tabObjects[ self.tab ]
+            render_tab( self.urlWriter ).write_BODY( request )
+            request.write( "\n</div>" )
+        except Exception, e:
+            request.write( "\n<p>Error Rendering Tab</p>" )
+            request.write( "\n<p>%s</p>" % str( e ) )
 
-    def write_BODY( self, request, urlWriter = None ):
-        try:
-            tab = int( getVar( 'tab', request, 0 ) )
-        except:
-            tab = 0
-            
-        request.write( "<table style='' width='100%' border='0' 
cellspacing='0' cellpadding='0'>" )
-        request.write( "<tr><td>" )
-        request.write( "<p align='center'><u>%s</u></p>" % self.title )
-        
-        TabView( tab, self.tabStrings, self.urlWriter ).write_BODY( request )
-        
-        request.write( "</td></tr><tr><td>" )
+        request.write( "\n<input type=\"hidden\" name=\"tab\" value=\"%d\">" % 
self.tab )
+
+    def perform( self, request ):
+        request.write( "Tab> perform" )
+        request.write( "<br/>op: " + str( getVar( 'op', request ) ) )
+        request.write( "<br/>args: " + str( getVar( 'args', request ) ) )
+        request.write( "<br/>tab: " + str( getVar( 'tab', request ) ) )      
 
         try:
-            render_tab = self.tabObjects[ tab ]
-            render_tab().write_BODY( request )
+            action = getVar( 'op', request, 0 )
+            if action == "tab":
+                self.tab = int( getVar( 'args', request ) )
+            else:
+                this.tab = int( getVar( 'tab', request, 0 ) )
+                self.tabObjects[ self.tab ]( self.urlWriter ).perform( request 
)
         except:
-            request.write( "<p>Error Rendering Tab</p>" )
-       
-        request.write( "</td></tr></table>" )
-       
-    def perform( self, request ):
-        try:
-            tab = int( getVar( 'tab', request, 0 ) )
-        except:
-            tab = 0;
-            
-        op_tab = self.tabObjects[ tab ]
-        
-        if op_tab:
-            op_tab().perform( request )
+            pass
         
 class PreTab( HTMLBase ):
 
@@ -53,12 +57,9 @@
         self.source = source
     
     def write_BODY( self, request ):
-        
-        request.write( "<div style='display: block; overflow: auto; border: 
0px solid black; width: 540px; padding: 5px; z-index:0; align: center'><pre>" )
-        
+        request.write( "\n<pre>" )
         request.write( self.source )
-        
-        request.write( "</pre></div>" )
+        request.write( "\n</pre>" )
 
 class GeneralTab( HTMLBase ):
                         
@@ -69,7 +70,7 @@
                         
     def write_BODY( self, request ): 
         
-        request.write( "<table width='100%' cellspacing='0' cellpadding='0' 
border='0'>" )
+        request.write( "\n<table width='100%' cellspacing='0' cellpadding='0' 
border='0'>" )
         
         def writeAttr( niceName, attr, formatter=None ):
             if type( attr ) is types.TupleType:
@@ -80,7 +81,7 @@
                     temp = formatter( self.dict[ attr ] )
                 else:
                     temp = str( self.dict[ attr ] )
-                request.write( "<tr><td width='50%%'><p>%s:</p></td><td 
width='50%%'><p>%s</p></td></tr>" % ( niceName, temp ) )
+                request.write( "\n<tr><td width='50%%'><p>%s:</p></td><td 
width='50%%'><p>%s</p></td></tr>" % ( niceName, temp ) )
         
         for niceName, attr in self.titles.items():
             writeAttr( niceName, attr )
@@ -89,16 +90,12 @@
 
 class NullTab( HTMLBase ):
     
-    def __init__( self ):
-        HTMLBase.__init__( self )
-        self.title = "Null Tab"
-
-    def __init__( self, title ):
+    def __init__( self, title="Null Tab" ):
         HTMLBase.__init__( self )
         self.title = title
-        
+
     def write_BODY( self, request ):
-        request.write( "<p>%s</p>" % self.title )
+        request.write( "\n<p>%s</p>" % self.title )
 
 class ActionTab( HTMLBase ):
 
@@ -107,29 +104,44 @@
         HTMLBase.__init__( self )
         
     def write_BODY( self, request ):
-        request.write( "<p align='center'><table cellspacing='3' 
cellpadding='2' border='0'><tr>" )
-    
-        for ( command, text ) in self.actions.items():
-            request.write( "<td style='border: 1px solid black; 
background-color: grey' onmouseover='buttonMouseOver( this )' 
onmouseout='buttonMouseOut( this )'>" )
-            request.write( "<p><a href='javascript: doOp( \"%s\" 
);'>%s</a></p></td>" % (command, text) )
- 
-        request.write("</table></p>")        
-        
+        for item in self.actions.items():
+            try:
+                ((op, attr), title) = item
+            except:
+                (op, title) = item
+                attr = ""
+            request.write( "\n<div class='button' onclick=\"doOp2( '%s', '%s' 
)\">%s</a></div>" % (op, attr, title) )
+
 class CompositeTab( HTMLBase ):
 
-    def __init__( self, tabs ):
+    def __init__( self, tabs, urlWriter ):
        HTMLBase.__init__( self )
         self.tabs = tabs
+        self.urlWriter = urlWriter
         
     def write_BODY( self, request ):
        for tab in self.tabs:
-            request.write( "<br/>" )
-            tab().write_BODY( request )
+            tab( self.urlWriter ).write_BODY( request )
             
     def perform( self, request ):
        for tab in self.tabs:
-            tab().perform( request )
-    
-    
-       
-        
+            tab( self.urlWriter ).perform( request )
+
+class TabView( HTMLBase ):
+
+        # tab - int, id into tabs of selected tab
+        # tabs - list of strings, tab names
+        # urlWriter -
+        def __init__( self, tab, tabs, urlWriter ):
+            HTMLBase.__init__(self)
+            self.tab = tab
+            self.tabs = tabs
+            self.urlWriter = urlWriter
+
+        def write_BODY( self, request ):
+            for i in range( len( self.tabs ) ):
+                if self.tab == i:
+                    at = " id='activeTab'"
+                else:
+                    at = ""
+                request.write( "\n<div%s class='tabButton' onclick=\"doOp2( 
'tab', '%d' )\">%s</div>" % ( at, i, self.tabs[ i ] ) )
diff -r a1f7e01b0990 -r 12deebfb7f87 tools/python/xen/sv/HTMLBase.py
--- a/tools/python/xen/sv/HTMLBase.py   Tue Aug  9 10:42:51 2005
+++ b/tools/python/xen/sv/HTMLBase.py   Tue Aug  9 12:55:18 2005
@@ -12,26 +12,17 @@
         return self.render_GET( request )
         
     def render_GET( self, request ):
-        self.write_TOP( request )
-        self.write_BODY( request )
-        self.write_BOTTOM( request )
-        return ''
-                
+        pass
+    
     def write_BODY( self, request ):
-        request.write( "BODY" )
+        pass
         
     def write_TOP( self, request ):
-        request.write( '<html><head><title>Xen</title><link rel="stylesheet" 
type="text/css" href="inc/style.css" />' )
-        request.write( '<script src="inc/script.js"></script>' )
-        request.write( '</head><body>' )
-        request.write('<form method="post" action="%s">' % request.uri)
-
+        pass
+    
     def write_BOTTOM( self, request ):
-        request.write('<input type="hidden" name="op" value="">')
-        request.write('<input type="hidden" name="args" value="">')
-        request.write('</form>')
-        request.write( "</body></html>" )
-
+        pass
+    
     def get_op_method(self, op):
         """Get the method for an operation.
         For operation 'foo' looks for 'op_foo'.
diff -r a1f7e01b0990 -r 12deebfb7f87 tools/python/xen/sv/Main.py
--- a/tools/python/xen/sv/Main.py       Tue Aug  9 10:42:51 2005
+++ b/tools/python/xen/sv/Main.py       Tue Aug  9 12:55:18 2005
@@ -1,113 +1,90 @@
+
 from xen.sv.HTMLBase import HTMLBase
-from xen.sv.DomList  import DomList
 from xen.sv.NodeInfo import NodeInfo
 from xen.sv.DomInfo  import DomInfo
 from xen.sv.CreateDomain import CreateDomain
-from xen.sv.MigrateDomain import MigrateDomain
-from xen.sv.SaveDomain import SaveDomain
 from xen.sv.RestoreDomain import RestoreDomain
-
-from xen.xend.XendClient import server
 
 from xen.sv.util import getVar
 
-class Main( HTMLBase ):
-    
-    isLeaf = True
+# adapter to make this all work with mod_python
+# as opposed to Twisted
+# (c) Tom Wilkie 2005
 
-    def __init__( self, urlWriter = None ):
+class Args:
+    def __init__( self, req ):
+        from mod_python.util import FieldStorage
+        self.fieldStorage = FieldStorage( req, True )
+
+    # return a list of values for the given key,
+    # or None if key not there
+    def get( self, var ):
+        retVar = self.fieldStorage.getlist( var )
+        if len( retVar ) == 0:
+            return None
+        else:
+            return retVar
+
+    # return a list of tuples,
+    # (key, value) where value is a list of values
+    def items( self ):
+        result = [];
+        for key in self.fieldStorage.keys():
+            result.append( (key, self.fieldStorage.getlist( key ) ) )
+        return result
+                                                                               
                                                                             
+class TwistedAdapter:
+    def __init__( self, req ):
+        self.args = Args( req )
+        self.uri = req.unparsed_uri
+        self.url = req.uri
+        self.write = req.write
+
+# This is the Main class
+# It peices together all the modules
+
+class Main:
+    def __init__( self ):
         self.modules = { "node": NodeInfo, 
-                         "list": DomList, 
-                         "info": DomInfo,
                          "create": CreateDomain,
-                         "migrate" : MigrateDomain,
-                         "save" : SaveDomain,
-                         "restore" : RestoreDomain }
+                         "restore" : RestoreDomain,
+                         "info": DomInfo }
 
-        # ordered list of module menus to display
-        self.module_menus = [ "node", "create", "migrate", "save",
-                              "restore", "list" ]
-        HTMLBase.__init__(self)
-        
-    def render_POST( self, request ):
-    
-       #decide what module post'd the action
-                
-       args = getVar( 'args', request )
+        self.init_done = False
 
-        mod = getVar( 'mod', request )
-                
-        if not mod is None and args is None:
-            module = self.modules[ mod ]
-            #check module exists
-            if module:
-               module( self.mainUrlWriter ).perform( request )
-        else:
-            self.perform( request )     
-    
-        return self.render_GET( request )
+    def init_modules( self, request ):
+        for moduleName, module in self.modules.iteritems():
+            self.modules[ moduleName ] = module( self.urlWriter( moduleName, 
request.url ) )             
 
-    def mainUrlWriter( self, module ):
-       def fun( f ):
-            return "Main.rpy?mod=%s%s" % ( module, f )
-        return fun    
-        
-    def write_BODY( self, request ):
-    
-        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" )
-        request.write( "<tr>\n" )
-        request.write( " <td width='15px'> </td>" )
-        request.write( " <td width='175px' align='center' valign'center'>" )
-        request.write( "  <table cellspacing='0' cellpadding='0' border='0' 
width='100%' height='100%'>" )
-        request.write( "   <tr><td height='140px' align='center' 
valign='bottom'><a href='http://www.cl.cam.ac.uk/Research/SRG/netos/xen/'>" )
-        request.write( "   <img src='images/xen.png' width='150' height='75' 
border='0'/></a><br/></td></tr>" )
-        request.write( "   <tr><td height='60px' align='center'><p 
class='small'>SV Web Interface<br/>(C) <a href='mailto:tw275@xxxxxxxxx'>Tom 
Wilkie</a> 2004</p></td></tr>")
-        request.write( "   <tr><td align='center' valign='top'>" )
+    def render_menu( self, request ):
+        if not self.init_done:
+            self.init_modules( request )
+            self.init_done = True
+            
+        for moduleName, module in self.modules.iteritems():
+            module.write_MENU( request )
+            request.write( "\n" )
 
-        for modName in self.module_menus:
-            self.modules[modName]( self.mainUrlWriter( modName ) ).write_MENU( 
request )
-        
-        request.write( "   </td></tr>" )
-        request.write( "  </table>" )
-        request.write( "  " )
-        request.write( " </td>\n" )
-        request.write( " <td width='15px'> </td>" )
-        request.write( " <td width='558px' align='left' valign='top'>" )
-        request.write( "  <table cellspacing='0' cellpadding='0' border='0' 
width='100%' height='100%'>" )
-        request.write( "   <tr><td height='20px'></td></tr>" )
-        request.write( "   <tr><td align='center' valign='top'>" )
-        
-        modName = getVar('mod', request)
-        
-        if modName is None:
+    def render_main( self, request ):
+        if not self.init_done:
+            self.init_modules( request )
+            self.init_done = True
+                                   
+        moduleName = getVar('mod', request)
+        if moduleName not in self.modules:
             request.write( '<p>Please select a module</p>' )
         else:
-            module = self.modules[ modName ]
-            if module:
-               module( self.mainUrlWriter( modName ) ).write_BODY( request )  
-            else:
-               request.write( '<p>Invalid module. Please select another</p>' )
-    
-        request.write( "   </td></tr>" )
-        request.write( "  </table>" )
-        request.write( " </td>\n" )
-        request.write( " <td width='17px'> </td>" )
-        request.write( "</tr>\n" )
+            module = self.modules[ moduleName ]
+            module.write_BODY( request )
+
+    def do_POST( self, request ): 
+        if not self.init_done:
+            self.init_modules( request )
+            self.init_done = True                       
         
-        request.write( "</table>\n" )
-        
-                
-    def op_destroy( self, request ):
-       dom = getVar( 'dom', request )
-        if not dom is None and dom != "0":
-            server.xend_domain_destroy( int( dom ), "halt" ) 
-                 
-    def op_pause( self, request ):
-       dom = getVar( 'dom', request )
-        if not dom is None and dom != "0":
-            server.xend_domain_pause( int( dom ) )      
-    
-    def op_unpause( self, request ):
-       dom = getVar( 'dom', request )
-        if not dom is None and dom != "0":
-            server.xend_domain_unpause( int( dom ) )      
+       moduleName = getVar( 'mod', request )      
+        if moduleName in self.modules:
+            self.modules[ moduleName ].perform( request )
+
+    def urlWriter( self, module, url ):
+        return lambda x: "%s?mod=%s%s" % ( url, module, x )
diff -r a1f7e01b0990 -r 12deebfb7f87 tools/python/xen/sv/NodeInfo.py
--- a/tools/python/xen/sv/NodeInfo.py   Tue Aug  9 10:42:51 2005
+++ b/tools/python/xen/sv/NodeInfo.py   Tue Aug  9 12:55:18 2005
@@ -6,18 +6,18 @@
 class NodeInfo( GenTabbed ):
 
     def __init__( self, urlWriter ):  
-        GenTabbed.__init__( self, "Node Details", urlWriter, [ 'General', 
'Dmesg', ], [ NodeGeneralTab, NodeDmesgTab ] )
+        GenTabbed.__init__( self, "Node Details", urlWriter, [ 'General', 
'Dmesg', 'SXP' ], [ NodeGeneralTab, NodeDmesgTab, NodeSXPTab ] )
     
     def write_MENU( self, request ):
         request.write( "<p class='small'><a href='%s'>Node details</a></p>" % 
self.urlWriter( '' ) )
 
 class NodeGeneralTab( CompositeTab ):
-    def __init__( self ):
-       CompositeTab.__init__( self, [ NodeInfoTab, NodeActionTab ] )        
+    def __init__( self, urlWriter ):
+       CompositeTab.__init__( self, [ NodeInfoTab, NodeActionTab ], urlWriter 
)        
         
 class NodeInfoTab( GeneralTab ):
                         
-    def __init__( self ):
+    def __init__( self, urlWriter ):
          
        nodeInfo = {}
         try:
@@ -41,7 +41,7 @@
 
 class NodeDmesgTab( PreTab ):
 
-    def __init__( self ):
+    def __init__( self, urlWriter ):
        try:
             dmesg = server.xend_node_get_dmesg()
         except:
@@ -50,7 +50,7 @@
   
 class NodeActionTab( ActionTab ):
 
-    def __init__( self ):
+    def __init__( self, urlWriter ):
         ActionTab.__init__( self, { "shutdown" : "shutdown",
                "reboot" : "reboot" } )    
         
@@ -61,3 +61,13 @@
     def op_reboot( self, request ):
         if debug: print ">NodeReboot"
         server.xend_node_reboot()
+
+class NodeSXPTab( PreTab ):
+
+    def __init__( self, urlWriter ):
+        try:
+            nodeSXP = sxp2string( server.xend_node() )
+        except:
+            nodeSXP = 'Error getting node sxp'
+
+        PreTab.__init__( self, nodeSXP )
diff -r a1f7e01b0990 -r 12deebfb7f87 tools/python/xen/sv/RestoreDomain.py
--- a/tools/python/xen/sv/RestoreDomain.py      Tue Aug  9 10:42:51 2005
+++ b/tools/python/xen/sv/RestoreDomain.py      Tue Aug  9 12:55:18 2005
@@ -16,6 +16,8 @@
 
 
 class ChooseRestoreDomain( Sheet ):
+    title = "Configure Restore"
+
     def __init__( self, urlWriter ):
         Sheet.__init__( self, urlWriter, "Configure Restore", 0)
         
@@ -24,6 +26,8 @@
                                        ".*") )
 
 class DoRestore( Sheet ):
+    title = "Restore Done"
+    
     def __init__(self, urlWriter ):
         Sheet.__init__(self, urlWriter, "Restore Done", 1)
 
diff -r a1f7e01b0990 -r 12deebfb7f87 tools/python/xen/sv/Wizard.py
--- a/tools/python/xen/sv/Wizard.py     Tue Aug  9 10:42:51 2005
+++ b/tools/python/xen/sv/Wizard.py     Tue Aug  9 12:55:18 2005
@@ -1,71 +1,44 @@
 from xen.sv.util import *
 from xen.sv.HTMLBase import HTMLBase
+from xen.sv.GenTabbed import GenTabbed, ActionTab
 from xen.xend import sxp
 
 import re
 
 DEBUG = 0
 
-class Wizard( HTMLBase ):
+class Wizard( GenTabbed ):
 
     def __init__( self, urlWriter, title, sheets ):
-        HTMLBase.__init__( self )
         self.title = title
         self.sheets = sheets
         self.urlWriter = urlWriter
+        self.offset = 0
+        GenTabbed.__init__( self, title, urlWriter, map( lambda x: x.title, 
sheets ), sheets ) 
         
     def write_MENU( self, request ):
        request.write( "<p class='small'><a href='%s'>%s</a></p>" % 
(self.urlWriter( '' ), self.title) ) 
     
     def write_BODY( self, request ):
-        
-       request.write( "<table width='100%' border='0' cellspacing='0' 
cellpadding='0'><tr><td>" )
-        request.write( "<p align='center'><u>%s</u></p></td></tr><tr><td>" % 
self.title )
-        
-        currSheet = getVar( 'sheet', request )
-    
-        if not currSheet is None:
-            currSheet = int( currSheet )
-        else:
-            currSheet = 0
-            
-        sheet = self.sheets[ currSheet ]( self.urlWriter )
-        
-        err = not sheet.validate( request )
-        
-        if not err:    
-            op = getVar( 'op', request )
-        
-            if op == 'next':
-               currSheet += 1
-            elif op == 'prev':
-               currSheet -= 1
-             
-            sheet = self.sheets[ currSheet ]( self.urlWriter )
-        
-        if getVar( 'visited-sheet%s' % currSheet, request ):
-            sheet.write_BODY( request, err )
-        else:
-            sheet.write_BODY( request, False )
-
-        
-        request.write( "</td></tr><tr><td><table width='100%' border='0' 
cellspacing='0' cellpadding='0'><tr>" )
-        request.write( "<td width='80%'></td><td width='20%' align='center'><p 
align='center'>" )
-       if currSheet > 0:
-                   request.write( "<img src='images/previous.png' 
onclick='doOp( \"prev\" )' onmouseover='update( \"wizText\", \"Previous\" )' 
onmouseout='update( \"wizText\", \" \" )'> " )
-        if currSheet < ( len( self.sheets ) - 2 ):        
-            request.write( "<img src='images/next.png' onclick='doOp( \"next\" 
)' onmouseover='update( \"wizText\", \"Next\" )' onmouseout='update( 
\"wizText\", \" \" )'>" )
-        elif currSheet == ( len( self.sheets ) - 2 ):
-            request.write( "<img src='images/finish.png' onclick='doOp( 
\"next\" )' onmouseover='update( \"wizText\", \"Finish\" )' onmouseout='update( 
\"wizText\", \" \" )'>" )
-        request.write( "</p><p align='center'><span 
id='wizText'></span></p></td></tr></table>" )
-        request.write( "</td></tr></table>" )
-        
-    def op_next( self, request ):
-       pass
-        
-    def op_prev( self, request ):
-       pass
-        
+        GenTabbed.write_BODY( self, request )
+        actionTab = ActionTab( { ("tab", str(self.tab-1)) : "< Prev", ("tab", 
str(self.tab+1)) : "Next >", "finish" : "Finish" } )
+        actionTab.write_BODY( request )
+
+    def perform( self, request ):
+        try:
+            action = getVar( 'op', request, 0 )
+            if action == "tab":
+                self.tab = int( getVar( 'args', request ) )
+                oldtab = int( getVar( 'tab', request ) )
+                if not self.tabObjects[ oldtab ]( self.urlWriter ).validate( 
request ):
+                    self.tab = oldtab
+            else:
+                self.tab = int( getVar( 'tab', request, 0 ) )
+                self.tabObjects[ self.tab ]( self.urlWriter ).perform( request 
)
+                getattr( self, "op_" +  getVar( "op", request ), None )( 
request )
+        except:
+            pass
+            
     def op_finish( self, request ):
        pass  
         
@@ -80,7 +53,7 @@
         self.passback = None
         
     def parseForm( self, request ):
-       do_not_parse = [ 'mod', 'op', 'sheet', 'passback' ] 
+       do_not_parse = [ 'mod', 'op', 'passback' ] 
     
        passed_back = request.args
         
@@ -103,7 +76,7 @@
         
         if DEBUG: print self.passback
         
-    def write_BODY( self, request, err ):
+    def write_BODY( self, request ):
     
        if not self.passback: self.parseForm( request )
         
@@ -115,14 +88,13 @@
         
        for (feild, control) in self.feilds:
             control.write_Control( request, previous_values.get( feild ) )
-            if err and not control.validate( previous_values.get( feild ) ):
+            if previous_values.get( feild ) is not None and not 
control.validate( previous_values.get( feild ) ):
                control.write_Help( request )
             
         request.write( "</table>" )
             
         request.write( "<input type='hidden' name='passback' 
value=\"%s\"></p>" % self.passback )
-        request.write( "<input type='hidden' name='sheet' value='%s'></p>" % 
self.location )
-        request.write( "<input type='hidden' name='visited-sheet%s' 
value='True'></p>" % self.location )
+        #request.write( "<input type='hidden' name='visited-sheet%s' 
value='True'></p>" % self.location )
                 
     def addControl( self, control ):
        self.feilds.append( [ control.getName(), control ] )
@@ -133,7 +105,7 @@
             
        check = True
         
-        previous_values = ssxp2hash( string2sxp( self.passback ) ) #get the 
hash for quick reference
+        previous_values = ssxp2hash( string2sxp( self.passback ) ) #get the 
map for quick reference
        if DEBUG: print previous_values
       
        for (feild, control) in self.feilds:
@@ -258,12 +230,16 @@
         
     def write_Control( self, request, persistedValue ):
         request.write( "<tr><td width='50%%'><p>%s</p></td><td width='50%%'>" 
% self.humanText )
+
+        #request.write( str( persistedValue ) )
+
+        #TODO: Theres a problem with this: it doesn't persist an untick, 
because the browsers don't pass it back. Need a fix...
         
         if persistedValue == 'True':
            request.write( "<input type='checkbox' name='%s' value='True' 
checked>" % self.getName() )
         else:
            request.write( "<input type='checkbox' name='%s' value='True'>" % 
self.getName() )
             
-        request.write( "</select></td></tr>" )
+        request.write( "</td></tr>" )
 
       
diff -r a1f7e01b0990 -r 12deebfb7f87 tools/python/xen/sv/util.py
--- a/tools/python/xen/sv/util.py       Tue Aug  9 10:42:51 2005
+++ b/tools/python/xen/sv/util.py       Tue Aug  9 12:55:18 2005
@@ -4,7 +4,7 @@
 
 import types
 
-def getDomInfoHash( domain ):
+def getDomInfo( domain ):
     domInfoHash = {}
     try:
         domInfoHash = sxp2hash( server.xend_domain( domain ) )
diff -r a1f7e01b0990 -r 12deebfb7f87 tools/sv/inc/style.css
--- a/tools/sv/inc/style.css    Tue Aug  9 10:42:51 2005
+++ b/tools/sv/inc/style.css    Tue Aug  9 12:55:18 2005
@@ -1,32 +1,95 @@
+.small  {
+       font-size: 10px
+}
 
-P       {font-family: verdana, arial; font-size: 12px; color: black}
-.small  {font-size: 10px}
+TD.domainInfo     { 
+       font-size: 10px; 
+       color: black
+}
 
-TD.domainInfo     {font-family: verdana, arial; font-size: 10px; color: black}
-TD.domainInfoHead {font-family: verdana, arial; font-size: 10px; color: white; 
font-face: bold}
+TD.domainInfoHead {
+       font-size: 10px; 
+       color: white; 
+       font-face: bold
+}
 
 TD.domainInfoHead {background-color: black}
 TR.domainInfoOdd  {background-color: white}
 TR.domainInfoEven {background-color: lightgrey}
 
 body { 
-       width: 670px;
-       margin: 0px;
-       padding: 0px;
-       background-color: #fff;
-       background-image: url(../images/orb_02.jpg);
-       background-repeat: repeat-y;
-       background-position: left top;
-       font-family: Arial, Helvetica, sans-serif;
-       font-weight: bold;
-       color: #333333;
-       letter-spacing: 0px;
-       scrollbar-base-color: #333333;
-       scrollbar-track-color: #666666;
-       scrollbar-face-color: #fff;
-       
-       
-       }
-        
-.button (cursor:hand)
-       
+       margin:         0px;
+       padding:        0px;
+       font-family:    Arial, Helvetica, sans-serif;
+       font-size:      12px;
+       color:          #000000;
+}
+
+div#menu {
+        position:       absolute;
+        left:           10px;
+        top:            10px;
+        width:          160px;
+        padding:        10px;
+        border:         0px solid black;
+        text-align:     center;
+}
+
+div#main {
+        position:       absolute;
+        left:           200px;
+        top:            10px;
+        right:          10px;
+        padding:        10px;
+        border:         0px solid black;
+}
+
+div.button {
+        float:          right;
+        margin:         10px 0px 0px 10px;
+        padding:        5px;
+        text-align:     center;
+        border:         1px solid black;
+        background:     gray;
+       cursor:         hand;
+}
+
+div.tabButton {
+       position:       relative;
+       top:            0px;
+        float:          left;
+        margin:         0px 10px -1px 0px;
+        padding:        5px;
+        text-align:     center;
+        border:         1px solid black;
+        background:     gray;
+       cursor:         hand;
+}
+
+div.tabButton#activeTab {
+       top:            0px;
+        background:     white;
+        border-color:   black black white black;
+}
+
+div.button:hover, div.tabButton:hover {
+        background:     white;
+}
+
+div.button a, div.tabButton a {
+        font-size:      12px;
+       font-weight:    bold;
+}
+
+div.title {
+       float:          right;
+       font-size:      14px;
+       font-weight:    bold;
+}
+
+div.tab {
+        overflow:       auto;
+        clear:          both;
+        border:         1px solid black;
+        padding:        10px;
+}
diff -r a1f7e01b0990 -r 12deebfb7f87 tools/sv/index.psp
--- a/tools/sv/index.psp        Tue Aug  9 10:42:51 2005
+++ b/tools/sv/index.psp        Tue Aug  9 12:55:18 2005
@@ -7,158 +7,29 @@
 for path in sys.path:
     if debug: req.write( path + "<br/>" )
 
-from xen.sv.HTMLBase import HTMLBase
-from xen.sv.DomList  import DomList
-from xen.sv.NodeInfo import NodeInfo
-from xen.sv.DomInfo  import DomInfo
-from xen.sv.CreateDomain import CreateDomain
-from xen.sv.MigrateDomain import MigrateDomain
-from xen.sv.SaveDomain import SaveDomain
-from xen.sv.RestoreDomain import RestoreDomain
-
-from xen.xend.XendClient import server
-
-from xen.sv.util import getVar
-
-# adapter to make this all work with mod_python
-# (c) Tom Wilkie 2005
-
-class TwistedAdapter:
-
-    def write( self, text ):
-        req.write( text )
-
-    class Args:
-
-        from mod_python.util import FieldStorage
-
-        fieldStorage = FieldStorage( req, True )
-
-        # return a list of values for the given key,
-        # or None if key not there
-        def get( self, var ):
-            retVar = self.fieldStorage.getlist( var )
-            if len( retVar ) == 0:
-                return None
-            else:
-                return retVar
-
-        # return a list of tuples, 
-        # (key, value) where value is a list of values
-       def items( self ):
-            result = [];
-            for key in self.fieldStorage.keys():
-               result.append( (key, self.fieldStorage.getlist( key ) ) )
-           return result
-
-    args = Args()
-
-    uri = req.unparsed_uri
-
-
-class Main( HTMLBase ):
-    
-    isLeaf = True
-
-    def __init__( self, urlWriter = None ):
-        self.modules = { "node": NodeInfo, 
-                         "list": DomList, 
-                         "info": DomInfo,
-                         "create": CreateDomain,
-                         "migrate" : MigrateDomain,
-                         "save" : SaveDomain,
-                         "restore" : RestoreDomain }
-
-        # ordered list of module menus to display
-        self.module_menus = [ "node", "create", "migrate", "save",
-                              "restore", "list" ]
-        HTMLBase.__init__(self)
-        
-    def render_POST( self, request ):
-    
-       #decide what module post'd the action
-                
-       args = getVar( 'args', request )
-
-        mod = getVar( 'mod', request )
-                
-        if mod in self.modules and args is None:
-            module = self.modules[ mod ]
-            #check module exists
-            if module:
-               module( self.mainUrlWriter ).perform( request )
-        else:
-            self.perform( request )     
-    
-        return self.render_GET( request )
-
-    #TODO: need to make this get the request uri automatically
-    def mainUrlWriter( self, module ):
-       def fun( f ):
-            return "index.psp?mod=%s%s" % ( module, f )
-        return fun    
-        
-    def write_BODY( self, request ):
-    
-        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" )
-        request.write( "<tr>\n" )
-        request.write( " <td width='15px'> </td>" )
-        request.write( " <td width='175px' align='center' valign'center'>" )
-        request.write( "  <table cellspacing='0' cellpadding='0' border='0' 
width='100%' height='100%'>" )
-        request.write( "   <tr><td height='140px' align='center' 
valign='bottom'><a href='http://www.cl.cam.ac.uk/Research/SRG/netos/xen/'>" )
-        request.write( "   <img src='images/xen.png' width='150' height='75' 
border='0'/></a><br/></td></tr>" )
-        request.write( "   <tr><td height='60px' align='center'><p 
class='small'>SV Web Interface<br/>(C) <a href='mailto:tw275@xxxxxxxxx'>Tom 
Wilkie</a> 2004</p></td></tr>")
-        request.write( "   <tr><td align='center' valign='top'>" )
-
-        for modName in self.module_menus:
-            self.modules[modName]( self.mainUrlWriter( modName ) ).write_MENU( 
request )
-        
-        request.write( "   </td></tr>" )
-        request.write( "  </table>" )
-        request.write( "  " )
-        request.write( " </td>\n" )
-        request.write( " <td width='15px'> </td>" )
-        request.write( " <td width='558px' align='left' valign='top'>" )
-        request.write( "  <table cellspacing='0' cellpadding='0' border='0' 
width='100%' height='100%'>" )
-        request.write( "   <tr><td height='20px'></td></tr>" )
-        request.write( "   <tr><td align='center' valign='top'>" )
-        
-        modName = getVar('mod', request)
-        
-        if modName not in self.modules:
-            request.write( '<p>Please select a module</p>' )
-        else:
-            module = self.modules[ modName ]
-            if module:
-               module( self.mainUrlWriter( modName ) ).write_BODY( request )  
-            else:
-               request.write( '<p>Invalid module. Please select another</p>' )
-    
-        request.write( "   </td></tr>" )
-        request.write( "  </table>" )
-        request.write( " </td>\n" )
-        request.write( " <td width='17px'> </td>" )
-        request.write( "</tr>\n" )
-        
-        request.write( "</table>\n" )
-        
-                
-    def op_destroy( self, request ):
-       dom = getVar( 'dom', request )
-        if not dom is None and dom != "0":
-            server.xend_domain_destroy( int( dom ), "halt" ) 
-                 
-    def op_pause( self, request ):
-       dom = getVar( 'dom', request )
-        if not dom is None and dom != "0":
-            server.xend_domain_pause( int( dom ) )      
-    
-    def op_unpause( self, request ):
-       dom = getVar( 'dom', request )
-        if not dom is None and dom != "0":
-            server.xend_domain_unpause( int( dom ) )      
+from xen.sv.Main import Main, TwistedAdapter
 
 main = Main()
-
-main.render_POST( TwistedAdapter() )
+request = TwistedAdapter( req )
+main.do_POST( request )
 %>
+<html>
+<head>
+       <title>XenSV</title>
+       <script src="inc/script.js"></script>
+       <link rel="StyleSheet" type="text/css" href="inc/style.css">
+</head>
+<body>
+    <form method="post" action="<%=request.uri%>">
+        <div id="menu">
+               <img src="images/xen.png">
+               <% main.render_menu( request ) %>
+       </div>
+       <div id="main">
+               <% main.render_main( request ) %>
+       </div>
+       <input type="hidden" name="op" value="">
+        <input type="hidden" name="args" value="">
+    </form>
+</body>
+</html>
diff -r a1f7e01b0990 -r 12deebfb7f87 tools/python/xen/sv/Daemon.py
--- a/tools/python/xen/sv/Daemon.py     Tue Aug  9 10:42:51 2005
+++ /dev/null   Tue Aug  9 12:55:18 2005
@@ -1,110 +0,0 @@
-###########################################################
-## XenSV Web Control Interface Daemon
-## Copyright (C) 2004, K A Fraser (University of Cambridge)
-## Copyright (C) 2004, Mike Wray <mike.wray@xxxxxx>
-## Copyright (C) 2004, Tom Wilkie <tw275@xxxxxxxxx>
-###########################################################
-
-import os
-import os.path
-import sys
-import re
-
-from xen.sv.params import *
-
-from twisted.internet import reactor
-from twisted.web import static, server, script
-
-from xen.util.ip import _readline, _readlines
-
-class Daemon:
-    """The xend daemon.
-    """
-    def __init__(self):
-        self.shutdown = 0
-        self.traceon = 0
-
-    def daemon_pids(self):
-        pids = []
-        pidex = '(?P<pid>\d+)'
-        pythonex = '(?P<python>\S*python\S*)'
-        cmdex = '(?P<cmd>.*)'
-        procre = re.compile('^\s*' + pidex + '\s*' + pythonex + '\s*' + cmdex 
+ '$')
-        xendre = re.compile('^/usr/sbin/xend\s*(start|restart)\s*.*$')
-        procs = os.popen('ps -e -o pid,args 2>/dev/null')
-        for proc in procs:
-            pm = procre.match(proc)
-            if not pm: continue
-            xm = xendre.match(pm.group('cmd'))
-            if not xm: continue
-            #print 'pid=', pm.group('pid'), 'cmd=', pm.group('cmd')
-            pids.append(int(pm.group('pid')))
-        return pids
-
-    def new_cleanup(self, kill=0):
-        err = 0
-        pids = self.daemon_pids()
-        if kill:
-            for pid in pids:
-                print "Killing daemon pid=%d" % pid
-                os.kill(pid, signal.SIGHUP)
-        elif pids:
-            err = 1
-            print "Daemon already running: ", pids
-        return err
-            
-    def cleanup(self, kill=False):
-        # No cleanup to do if PID_FILE is empty.
-        if not os.path.isfile(PID_FILE) or not os.path.getsize(PID_FILE):
-            return 0
-        # Read the pid of the previous invocation and search active process 
list.
-        pid = open(PID_FILE, 'r').read()
-        lines = _readlines(os.popen('ps ' + pid + ' 2>/dev/null'))
-        for line in lines:
-            if re.search('^ *' + pid + '.+xensv', line):
-                if not kill:
-                    print "Daemon is already running (pid %d)" % int(pid)
-                    return 1
-                # Old daemon is still active: terminate it.
-                os.kill(int(pid), 1)
-        # Delete the stale PID_FILE.
-        os.remove(PID_FILE)
-        return 0
-
-    def start(self, trace=0):
-        if self.cleanup(kill=False):
-            return 1
-   
-        # Fork -- parent writes PID_FILE and exits.
-        pid = os.fork()
-        if pid:
-            # Parent
-            pidfile = open(PID_FILE, 'w')
-            pidfile.write(str(pid))
-            pidfile.close()
-            return 0
-        # Child
-        self.run()
-        return 0
-
-    def stop(self):
-        return self.cleanup(kill=True)
-
-    def run(self):
-       root = static.File( SV_ROOT )
-        root.indexNames = [ 'Main.rpy' ]
-        root.processors = { '.rpy': script.ResourceScript }
-        reactor.listenTCP( SV_PORT, server.Site( root ) )
-        reactor.run()
-
-    def exit(self):
-        reactor.disconnectAll()
-        sys.exit(0)
-
-def instance():
-    global inst
-    try:
-        inst
-    except:
-        inst = Daemon()
-    return inst
diff -r a1f7e01b0990 -r 12deebfb7f87 tools/python/xen/sv/DomList.py
--- a/tools/python/xen/sv/DomList.py    Tue Aug  9 10:42:51 2005
+++ /dev/null   Tue Aug  9 12:55:18 2005
@@ -1,81 +0,0 @@
-from xen.xend.XendClient import server
-from xen.xend import sxp
-
-from xen.sv.HTMLBase import HTMLBase
-from xen.sv.util import *
-
-class DomList( HTMLBase ):
-    
-    isLeaf = True
-
-    def __init__( self, urlWriter ):
-        HTMLBase.__init__(self)
-        self.urlWriter = urlWriter
-        
-    def write_MENU( self, request ):
-       return self.write_BODY( request, head=True, long=False ) 
-
-    def write_BODY( self, request, head=True, long=True ):
-        
-       domains = []
-    
-        try:
-            domains = server.xend_domains()
-            domains.sort()
-       except:
-            pass
-                
-        request.write( "\n<table style='border:0px solid white' 
cellspacing='0' cellpadding='0' border='0' width='100%'>\n" )
-        
-        if head:
-            request.write( "<tr class='domainInfoHead'>" )
-            self.write_DOMAIN_HEAD( request, long )
-            request.write( "</tr>" )
-        
-        odd = True
-        
-        if not domains is None:
-            for domain in domains:
-                if odd:
-                    request.write( "<tr class='domainInfoOdd'>\n" )
-                    odd = False
-                else:
-                    request.write( "<tr class='domainInfoEven'>\n" )
-                    odd = True
-                self.write_DOMAIN( request, getDomInfoHash( domain ), long )
-                request.write( "</tr>\n" )
-        else:
-               request.write( "<tr colspan='10'><p class='small'>Error getting 
domain list<br/>Perhaps XenD not running?</p></tr>")
-                
-        request.write( "</table>\n" )
-            
-    def write_DOMAIN( self, request, domInfoHash, long=True ):   
-        request.write( "<td class='domainInfo' align='center'>%(id)s</td>\n" % 
domInfoHash )
-
-        url = self.urlWriter( "&mod=info&dom=%(id)s" % domInfoHash )
-
-        request.write( "<td class='domainInfo' align='center'><a 
href='%s'>%s</a></td>\n" % ( url, domInfoHash['name'] ) )
-        if long: 
-            request.write( "<td class='domainInfo' 
align='center'>%(memory)5s</td>\n" % domInfoHash )
-            request.write( "<td class='domainInfo' 
align='center'>%(cpu)2s</td>\n" % domInfoHash )
-        request.write( "<td class='domainInfo' 
align='center'>%(state)5s</td>\n" % domInfoHash )
-        if domInfoHash[ 'id' ] != "0":
-            request.write( "<td class='domainInfo' align='center'>" )
-            
-            if domInfoHash[ 'state' ][ 2 ] == "-":
-                request.write( "<img src='images/small-pause.png' 
onclick='doOp2( \"pause\", \"%(dom)-4s\" )'>" % domInfoHash )
-            else:
-                request.write( "<img src='images/small-unpause.png' 
onclick='doOp2( \"unpause\", \"%(dom)-4s\" )'>" % domInfoHash )              
-            
-            request.write( "<img src='images/small-destroy.png' 
onclick='doOp2( \"destroy\", \"%(dom)-4s\" )'></td>" % domInfoHash)
-        else:
-            request.write( "<td> </td>" )
-
-    def write_DOMAIN_HEAD( self, request, long=True ):
-        request.write( "<td class='domainInfoHead' 
align='center'>Domain</td>\n" )      
-        request.write( "<td class='domainInfoHead' align='center'>Name</td>\n" 
)      
-        if long:
-            request.write( "<td class='domainInfoHead' align='center'>Memory / 
Mb</td>\n" )      
-            request.write( "<td class='domainInfoHead' 
align='center'>CPU</td>\n" )      
-        request.write( "<td class='domainInfoHead' 
align='center'>State</td>\n" )      
-        request.write( "<td class='domainInfoHead' align='center'></td>\n" )
diff -r a1f7e01b0990 -r 12deebfb7f87 tools/python/xen/sv/MigrateDomain.py
--- a/tools/python/xen/sv/MigrateDomain.py      Tue Aug  9 10:42:51 2005
+++ /dev/null   Tue Aug  9 12:55:18 2005
@@ -1,74 +0,0 @@
-from xen.sv.Wizard import *
-from xen.sv.util import *
-from xen.sv.GenTabbed import PreTab
-
-from xen.xm.create import make_config, OptVals
-
-from xen.xend.XendClient import server
-
-class MigrateDomain( Wizard ):
-    def __init__( self, urlWriter ):
-
-        sheets = [ ChooseMigrateDomain,
-                   DoMigrate ]
-
-        Wizard.__init__( self, urlWriter, "Migrate Domain", sheets )
-
-
-class ChooseMigrateDomain( Sheet ):
-    def __init__( self, urlWriter ):
-        Sheet.__init__( self, urlWriter, "Configure Migration", 0)
-       domains = []
-       domnames = []
-
-        try:
-            domains = server.xend_domains()
-            domains.sort()
-        except:
-            pass
-
-        for i in domains:
-            if i != 'Domain-0': domnames.append((i,i))
-        
-        self.addControl( ListControl('domid',
-                                     domnames,
-                                     'Domain ID:') )
-        self.addControl( TickControl('live',
-                                     'True',
-                                     'Live migrate:') )
-        self.addControl( InputControl('rate',
-                                      '0',
-                                      'Rate limit:') )
-        self.addControl( InputControl( 'dest', 'myhost.mydomain',
-                                       'Name or IP address:',
-                                       ".*") )
-
-class DoMigrate( Sheet ):
-    def __init__(self, urlWriter ):
-        Sheet.__init__(self, urlWriter, "Migration Done", 1)
-
-    def write_BODY( self, request, err ):
-
-        if not self.passback: self.parseForm( request )
-
-#        print string2sxp(self.passback)
-        
-        config = ssxp2hash ( string2sxp( self.passback ) )
-      
-        try:
-            print config
-            print config['domid'], config['dest']
-            dom_sxp = server.xend_domain_migrate( config['domid'],
-                                                  config['dest'],
-                                                  config.get('live') == 'True',
-                                                  config['rate'] )
-            success = "Your domain was successfully Migrated.\n"
-        except Exception, e:
-            success = "There was an error migrating your domain\n"
-            dom_sxp = str(e)
-        
-        pt = PreTab( success + dom_sxp ) # sxp2prettystring( dom_sxp ) )
-        pt.write_BODY( request )
-
-        request.write( "<input type='hidden' name='passback' 
value=\"%s\"></p>" % self.passback )
-        request.write( "<input type='hidden' name='sheet' value='%s'></p>" % 
self.location )
diff -r a1f7e01b0990 -r 12deebfb7f87 tools/python/xen/sv/SaveDomain.py
--- a/tools/python/xen/sv/SaveDomain.py Tue Aug  9 10:42:51 2005
+++ /dev/null   Tue Aug  9 12:55:18 2005
@@ -1,62 +0,0 @@
-from xen.sv.Wizard import *
-from xen.sv.util import *
-from xen.sv.GenTabbed import PreTab
-
-from xen.xm.create import make_config, OptVals
-
-from xen.xend.XendClient import server
-
-class SaveDomain( Wizard ):
-    def __init__( self, urlWriter ):
-
-        sheets = [ ChooseSaveDomain,
-                   DoSave ]
-
-        Wizard.__init__( self, urlWriter, "Save Domain", sheets )
-
-
-class ChooseSaveDomain( Sheet ):
-    def __init__( self, urlWriter ):
-        Sheet.__init__( self, urlWriter, "Configure Save", 0)
-        
-       domains = []
-       domnames = []
-
-       try:
-            domains = server.xend_domains()
-            domains.sort()
-        except:
-            pass
-
-        for i in domains:
-            if i != 'Domain-0': domnames.append((i,i))
-        
-        self.addControl( ListControl('domid',
-                                     domnames,
-                                     'Domain ID:') )
-        self.addControl( InputControl( 'file', '',
-                                       'Suspend file name:',
-                                       ".*") )
-
-class DoSave( Sheet ):
-    def __init__(self, urlWriter ):
-        Sheet.__init__(self, urlWriter, "Save Done", 1)
-
-    def write_BODY( self, request, err ):
-
-        if not self.passback: self.parseForm( request )
-        config = ssxp2hash ( string2sxp( self.passback ) )
-      
-        try:
-            dom_sxp = server.xend_domain_save( config['domid'],
-                                                  config['file'] )
-            success = "Your domain was successfully saved.\n"
-        except Exception, e:
-            success = "There was an error saving your domain\n"
-            dom_sxp = str(e)
-        
-        pt = PreTab( success + dom_sxp ) # sxp2prettystring( dom_sxp ) )
-        pt.write_BODY( request )
-
-        request.write( "<input type='hidden' name='passback' 
value=\"%s\"></p>" % self.passback )
-        request.write( "<input type='hidden' name='sheet' value='%s'></p>" % 
self.location )
diff -r a1f7e01b0990 -r 12deebfb7f87 tools/python/xen/sv/TabView.py
--- a/tools/python/xen/sv/TabView.py    Tue Aug  9 10:42:51 2005
+++ /dev/null   Tue Aug  9 12:55:18 2005
@@ -1,26 +0,0 @@
-from xen.sv.HTMLBase import HTMLBase
-
-class TabView( HTMLBase ):
-
-    # tab - int, id into tabs of selected tab
-    # tabs - list of strings, tab names
-    # urlWriter - 
-    def __init__( self, tab, tabs, urlWriter ):
-        HTMLBase.__init__(self)
-        self.tab = tab
-        self.tabs = tabs
-        self.urlWriter = urlWriter
-
-    def write_BODY( self, request ):
-        request.write( "<table style='' border='0' cellspacing='3' 
cellpadding='2' align='center'>" )
-        request.write( "<tr height='22'>" )                  
-    
-        for i in range( len( self.tabs ) ):
-            if self.tab == i:
-                backgroundColor = "white"
-            else:
-                backgroundColor = "grey"
-        
-            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 ] ) )
-  
-        request.write( "</tr></table>" )
diff -r a1f7e01b0990 -r 12deebfb7f87 tools/python/xen/sv/params.py
--- a/tools/python/xen/sv/params.py     Tue Aug  9 10:42:51 2005
+++ /dev/null   Tue Aug  9 12:55:18 2005
@@ -1,3 +0,0 @@
-SV_PORT = 8080
-SV_ROOT = "/var/lib/xen/sv/"
-PID_FILE = "/var/run/xen-sv.pid"
diff -r a1f7e01b0990 -r 12deebfb7f87 tools/sv/images/internet.jpg
--- a/tools/sv/images/internet.jpg      Tue Aug  9 10:42:51 2005
+++ /dev/null   Tue Aug  9 12:55:18 2005
@@ -1,322 +0,0 @@
-ÿØÿà |