# HG changeset patch
# User twilkie@xxxxxxxxxxxxxxxxxxxxxxx
# Node ID df19d43b95d03054fa4534fe8449e0c05aaec1fc
# Parent ecb17ef5a587a806f7f4f017c243f963ad962868
Add XenSV back into the repository.
Now uses Python Server Pages, not twisted.
diff -r ecb17ef5a587 -r df19d43b95d0 tools/Makefile
--- a/tools/Makefile Mon Jul 25 21:19:14 2005
+++ b/tools/Makefile Tue Jul 26 13:56:30 2005
@@ -13,6 +13,7 @@
SUBDIRS += pygrub
SUBDIRS += firmware
SUBDIRS += policy
+SUBDIRS += sv
.PHONY: all install clean check check_clean ioemu eioemuinstall ioemuclean
diff -r ecb17ef5a587 -r df19d43b95d0 tools/python/setup.py
--- a/tools/python/setup.py Mon Jul 25 21:19:14 2005
+++ b/tools/python/setup.py Tue Jul 26 13:56:30 2005
@@ -51,6 +51,7 @@
'xen.xend.xenstore',
'xen.xm',
'xen.web',
+ 'xen.sv'
],
ext_package = "xen.lowlevel",
ext_modules = [ xc, xu, xs ]
diff -r ecb17ef5a587 -r df19d43b95d0 tools/python/xen/sv/CreateDomain.py
--- /dev/null Mon Jul 25 21:19:14 2005
+++ b/tools/python/xen/sv/CreateDomain.py Tue Jul 26 13:56:30 2005
@@ -0,0 +1,163 @@
+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 CreateDomain( Wizard ):
+ def __init__( self, urlWriter ):
+
+ sheets = [ CreatePage0,
+ CreatePage1,
+ CreatePage2,
+ CreatePage3,
+ CreatePage4,
+ CreateFinish ]
+
+ Wizard.__init__( self, urlWriter, "Create Domain", sheets )
+
+class CreatePage0( Sheet ):
+
+ 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" ) )
+
+class CreatePage1( Sheet ):
+
+ 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( InputControl( 'extra', '', 'Kernel Command Line
Parameters:' ) )
+
+class CreatePage2( Sheet ):
+
+ def __init__( self, urlWriter ):
+ Sheet.__init__( self, urlWriter, "Setup Virtual Block Device", 2 )
+ self.addControl( InputControl( 'num_vbds', '1', 'Number of VBDs:',
'[\\d]+', "You must enter a number in this field" ) )
+
+class CreatePage3( Sheet ):
+
+ def __init__( self, urlWriter ):
+ Sheet.__init__( self, urlWriter, "Setup Virtual Block Device", 3 )
+
+ def write_BODY( self, request, err ):
+ if not self.passback: self.parseForm( request )
+
+ previous_values = sxp2hash( string2sxp( self.passback ) ) #get the hash
for quick reference
+
+ num_vbds = previous_values.get( 'num_vbds' )
+
+ for i in range( int( num_vbds ) ):
+ self.addControl( InputControl( 'vbd%s_dom0' % i, 'phy:sda%s' %
str(i + 1), 'Device %s name:' % i ) )
+ self.addControl( InputControl( 'vbd%s_domU' % i, 'sda%s' % str(i +
1), 'Virtualized device %s:' % i ) )
+ self.addControl( ListControl( 'vbd%s_mode' % i, [('w', 'Read +
Write'), ('r', 'Read Only')], 'Device %s mode:' % i ) )
+
+ self.addControl( InputControl( 'root', '/dev/sda1', 'Root device (in
VM):' ) )
+
+ Sheet.write_BODY( self, request, err )
+
+class CreatePage4( Sheet ):
+
+ def __init__( self, urlWriter ):
+ Sheet.__init__( self, urlWriter, "Network settings", 4 )
+ self.addControl( ListControl( 'dhcp', [('off', 'No'), ('dhcp',
'Yes')], 'Use DHCP:' ) )
+ self.addControl( InputControl( 'hostname', 'hostname', 'VM Hostname:'
) )
+ self.addControl( InputControl( 'ip_addr', '1.2.3.4', 'VM IP Address:'
) )
+ self.addControl( InputControl( 'ip_subnet', '255.255.255.0', 'VM
Subnet Mask:' ) )
+ self.addControl( InputControl( 'ip_gateway', '1.2.3.4', 'VM Gateway:'
) )
+ self.addControl( InputControl( 'ip_nfs', '1.2.3.4', 'NFS Server:' ) )
+
+class CreateFinish( Sheet ):
+
+ def __init__( self, urlWriter ):
+ Sheet.__init__( self, urlWriter, "All Done", 5 )
+
+ def write_BODY( self, request, err ):
+
+ if not self.passback: self.parseForm( request )
+
+ xend_sxp = self.translate_sxp( string2sxp( self.passback ) )
+
+ 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 )
+
+ request.write( "<input type='hidden' name='passback'
value=\"%s\"></p>" % self.passback )
+ request.write( "<input type='hidden' name='sheet' value='%s'></p>" %
self.location )
+
+ def translate_sxp( self, fin_sxp ):
+ fin_hash = ssxp2hash( fin_sxp )
+
+ def get( key ):
+ ret = fin_hash.get( key )
+ if ret:
+ return ret
+ else:
+ return ""
+
+ vals = OptVals()
+
+ vals.name = get( 'name' )
+ vals.memory = get( 'memory' )
+ vals.maxmem = get( 'maxmem' )
+ vals.cpu = get( 'cpu' )
+ vals.cpu_weight = get( 'cpu_weight' )
+
+ vals.builder = get( 'builder' )
+ vals.kernel = get( 'kernel' )
+ vals.root = get( 'root' )
+ vals.extra = get( 'extra' )
+
+ #setup vbds
+
+ 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 ) ) )
+
+ vals.disk = vbds
+
+ #misc
+
+ vals.pci = []
+
+ vals.blkif = None
+ vals.netif = None
+ vals.restart = None
+ vals.console = None
+ vals.ramdisk = None
+
+ #setup vifs
+
+ vals.vif = []
+ vals.nics = 1
+
+ ip = get( 'ip_addr' )
+ nfs = get( 'ip_nfs' )
+ gate = get( 'ip_gateway' )
+ mask = get( 'ip_subnet' )
+ host = get( 'hostname' )
+ dhcp = get( 'dhcp' )
+
+ vals.cmdline_ip = "%s:%s:%s:%s:%s:eth0:%s" % (ip, nfs, gate, mask,
host, dhcp)
+
+ try:
+ return make_config( vals )
+ except:
+ return [["Error creating domain config."]]
+
diff -r ecb17ef5a587 -r df19d43b95d0 tools/python/xen/sv/Daemon.py
--- /dev/null Mon Jul 25 21:19:14 2005
+++ b/tools/python/xen/sv/Daemon.py Tue Jul 26 13:56:30 2005
@@ -0,0 +1,110 @@
+###########################################################
+## 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 ecb17ef5a587 -r df19d43b95d0 tools/python/xen/sv/DomInfo.py
--- /dev/null Mon Jul 25 21:19:14 2005
+++ b/tools/python/xen/sv/DomInfo.py Tue Jul 26 13:56:30 2005
@@ -0,0 +1,148 @@
+from xen.xend.XendClient import server
+from xen.xend import PrettyPrint
+
+from xen.sv.HTMLBase import HTMLBase
+from xen.sv.util import *
+from xen.sv.GenTabbed import *
+
+DEBUG=1
+
+class DomInfo( GenTabbed ):
+
+ 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 ] )
+
+ def write_BODY( self, request ):
+ dom = request.args.get('dom')
+
+ if dom is None or len(dom) != 1:
+ 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
+
+class DomGeneralTab( CompositeTab ):
+ def __init__( self ):
+ CompositeTab.__init__( self, [ DomGenTab, DomActionTab ] )
+
+class DomGenTab( GeneralTab ):
+
+ def __init__( self ):
+
+ titles = {}
+
+ titles[ 'ID' ] = 'dom'
+ titles[ 'Name' ] = 'name'
+ titles[ 'CPU' ] = 'cpu'
+ titles[ 'Memory' ] = ( 'mem', memoryFormatter )
+ titles[ 'State' ] = ( 'state', stateFormatter )
+ titles[ 'Total CPU' ] = ( 'cpu_time', smallTimeFormatter )
+ titles[ 'Up Time' ] = ( 'up_time', bigTimeFormatter )
+
+ GeneralTab.__init__( self, {}, titles )
+
+ def write_BODY( self, request ):
+
+ self.dom = getVar('dom', request)
+
+ if self.dom is None:
+ request.write( "<p>Please Select a Domain</p>" )
+ return None
+
+ self.dict = getDomInfoHash( self.dom )
+
+ GeneralTab.write_BODY( self, request )
+
+class DomSXPTab( PreTab ):
+
+ def __init__( self ):
+ self.dom = 0
+ PreTab.__init__( self, "" )
+
+
+ def write_BODY( self, request ):
+ self.dom = getVar('dom', request)
+
+ if self.dom is None:
+ request.write( "<p>Please Select a Domain</p>" )
+ return None
+
+ try:
+ domInfo = server.xend_domain( self.dom )
+ except:
+ domInfo = [["Error getting domain details."]]
+
+ 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" }
+ ActionTab.__init__( self, actions )
+
+ def op_shutdown( self, request ):
+ dom = getVar( 'dom', request )
+ if not dom is None and dom != '0':
+ if DEBUG: print ">DomShutDown %s" % dom
+ try:
+ server.xend_domain_shutdown( int( dom ), "halt" )
+ except:
+ pass
+
+ def op_reboot( self, request ):
+ dom = getVar( 'dom', request )
+ if not dom is None and dom != '0':
+ if DEBUG: print ">DomReboot %s" % dom
+ try:
+ server.xend_domain_shutdown( int( dom ), "reboot" )
+ except:
+ pass
+
+ def op_pause( self, request ):
+ dom = getVar( 'dom', request )
+ if not dom is None and dom != '0':
+ if DEBUG: print ">DomPause %s" % dom
+ try:
+ server.xend_domain_pause( int( dom ) )
+ except:
+ pass
+
+ def op_unpause( self, request ):
+ dom = getVar( 'dom', request )
+ if not dom is None and dom != '0':
+ if DEBUG: print ">DomUnpause %s" % dom
+ try:
+ server.xend_domain_unpause( int( dom ) )
+ except:
+ pass
+
+ def op_destroy( self, request ):
+ dom = getVar( 'dom', request )
+ if not dom is None and dom != '0':
+ if DEBUG: print ">DomDestroy %s" % dom
+ try:
+ server.xend_domain_destroy( int( dom ), "halt" )
+ except:
+ pass
+
+
+
+
+
diff -r ecb17ef5a587 -r df19d43b95d0 tools/python/xen/sv/DomList.py
--- /dev/null Mon Jul 25 21:19:14 2005
+++ b/tools/python/xen/sv/DomList.py Tue Jul 26 13:56:30 2005
@@ -0,0 +1,81 @@
+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 ecb17ef5a587 -r df19d43b95d0 tools/python/xen/sv/GenTabbed.py
--- /dev/null Mon Jul 25 21:19:14 2005
+++ b/tools/python/xen/sv/GenTabbed.py Tue Jul 26 13:56:30 2005
@@ -0,0 +1,135 @@
+import types
+
+from xen.sv.HTMLBase import HTMLBase
+from xen.sv.TabView import TabView
+from xen.sv.util import getVar
+
+class GenTabbed( HTMLBase ):
+
+ def __init__( self, title, urlWriter, tabStrings, tabObjects ):
+ HTMLBase.__init__(self)
+ self.tabStrings = tabStrings
+ self.tabObjects = tabObjects
+ self.urlWriter = urlWriter
+ self.title = title
+
+ 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>" )
+
+ try:
+ render_tab = self.tabObjects[ tab ]
+ render_tab().write_BODY( 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 )
+
+class PreTab( HTMLBase ):
+
+ def __init__( self, source ):
+ HTMLBase.__init__( self )
+ 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( self.source )
+
+ request.write( "</pre></div>" )
+
+class GeneralTab( HTMLBase ):
+
+ def __init__( self, dict, titles ):
+ HTMLBase.__init__( self )
+ self.dict = dict
+ self.titles = titles
+
+ def write_BODY( self, request ):
+
+ request.write( "<table width='100%' cellspacing='0' cellpadding='0'
border='0'>" )
+
+ def writeAttr( niceName, attr, formatter=None ):
+ if type( attr ) is types.TupleType:
+ ( attr, formatter ) = attr
+
+ if attr in self.dict:
+ if formatter:
+ 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 ) )
+
+ for niceName, attr in self.titles.items():
+ writeAttr( niceName, attr )
+
+ request.write( "</table>" )
+
+class NullTab( HTMLBase ):
+
+ def __init__( self ):
+ HTMLBase.__init__( self )
+ self.title = "Null Tab"
+
+ def __init__( self, title ):
+ HTMLBase.__init__( self )
+ self.title = title
+
+ def write_BODY( self, request ):
+ request.write( "<p>%s</p>" % self.title )
+
+class ActionTab( HTMLBase ):
+
+ def __init__( self, actions ):
+ self.actions = actions
+ 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>")
+
+class CompositeTab( HTMLBase ):
+
+ def __init__( self, tabs ):
+ HTMLBase.__init__( self )
+ self.tabs = tabs
+
+ def write_BODY( self, request ):
+ for tab in self.tabs:
+ request.write( "<br/>" )
+ tab().write_BODY( request )
+
+ def perform( self, request ):
+ for tab in self.tabs:
+ tab().perform( request )
+
+
+
+
diff -r ecb17ef5a587 -r df19d43b95d0 tools/python/xen/sv/HTMLBase.py
--- /dev/null Mon Jul 25 21:19:14 2005
+++ b/tools/python/xen/sv/HTMLBase.py Tue Jul 26 13:56:30 2005
@@ -0,0 +1,62 @@
+from xen.sv.util import *
+
+class HTMLBase:
+
+ isLeaf = True
+
+ def __init__( self ):
+ pass
+
+ def render_POST( self, request ):
+ self.perform( request )
+ return self.render_GET( request )
+
+ def render_GET( self, request ):
+ self.write_TOP( request )
+ self.write_BODY( request )
+ self.write_BOTTOM( request )
+ return ''
+
+ def write_BODY( self, request ):
+ request.write( "BODY" )
+
+ 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)
+
+ 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>" )
+
+ def get_op_method(self, op):
+ """Get the method for an operation.
+ For operation 'foo' looks for 'op_foo'.
+
+ op operation name
+ returns method or None
+ """
+ op_method_name = 'op_' + op
+ return getattr(self, op_method_name, None)
+
+ def perform(self, req):
+ """General operation handler for posted operations.
+ For operation 'foo' looks for a method op_foo and calls
+ it with op_foo(req). Replies with code 500 if op_foo
+ is not found.
+
+ The method must return a list when req.use_sxp is true
+ and an HTML string otherwise (or list).
+ Methods may also return a Deferred (for incomplete processing).
+
+ req request
+ """
+ op = req.args.get('op')
+ if not op is None and len(op) == 1:
+ op = op[0]
+ op_method = self.get_op_method(op)
+ if op_method:
+ op_method( req )
diff -r ecb17ef5a587 -r df19d43b95d0 tools/python/xen/sv/Main.py
--- /dev/null Mon Jul 25 21:19:14 2005
+++ b/tools/python/xen/sv/Main.py Tue Jul 26 13:56:30 2005
@@ -0,0 +1,113 @@
+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
+
+ 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 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 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'>" )
+
+ 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:
+ 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 ) )
diff -r ecb17ef5a587 -r df19d43b95d0 tools/python/xen/sv/MigrateDomain.py
--- /dev/null Mon Jul 25 21:19:14 2005
+++ b/tools/python/xen/sv/MigrateDomain.py Tue Jul 26 13:56:30 2005
@@ -0,0 +1,74 @@
+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 ecb17ef5a587 -r df19d43b95d0 tools/python/xen/sv/NodeInfo.py
--- /dev/null Mon Jul 25 21:19:14 2005
+++ b/tools/python/xen/sv/NodeInfo.py Tue Jul 26 13:56:30 2005
@@ -0,0 +1,63 @@
+from xen.xend.XendClient import server
+
+from xen.sv.util import *
+from xen.sv.GenTabbed import *
+
+class NodeInfo( GenTabbed ):
+
+ def __init__( self, urlWriter ):
+ GenTabbed.__init__( self, "Node Details", urlWriter, [ 'General',
'Dmesg', ], [ NodeGeneralTab, NodeDmesgTab ] )
+
+ 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 ] )
+
+class NodeInfoTab( GeneralTab ):
+
+ def __init__( self ):
+
+ nodeInfo = {}
+ try:
+ nodeInfo = sxp2hash( server.xend_node() )
+ except:
+ nodeInfo[ 'system' ] = 'Error getting node info'
+
+ dictTitles = {}
+ dictTitles[ 'System' ] = 'system'
+ dictTitles[ 'Hostname' ] = 'host'
+ dictTitles[ 'Release' ] = 'release'
+ dictTitles[ 'Version' ] ='version'
+ dictTitles[ 'Machine' ] = 'machine'
+ dictTitles[ 'Cores' ] = 'cores'
+ dictTitles[ 'Hyperthreading' ] = ( 'hyperthreads_per_core',
hyperthreadFormatter )
+ dictTitles[ 'CPU Speed' ] = ( 'cpu_mhz', cpuFormatter )
+ dictTitles[ 'Memory' ] = ( 'memory', memoryFormatter )
+ dictTitles[ 'Free Memory' ] = ( 'free_memory', memoryFormatter )
+
+ GeneralTab.__init__( self, dict=nodeInfo, titles=dictTitles )
+
+class NodeDmesgTab( PreTab ):
+
+ def __init__( self ):
+ try:
+ dmesg = server.xend_node_get_dmesg()
+ except:
+ dmesg = "Error getting node information: XenD not running?"
+ PreTab.__init__( self, dmesg )
+
+class NodeActionTab( ActionTab ):
+
+ def __init__( self ):
+ ActionTab.__init__( self, { "shutdown" : "shutdown",
+ "reboot" : "reboot" } )
+
+ def op_shutdown( self, request ):
+ if debug: print ">NodeShutDown"
+ server.xend_node_shutdown()
+
+ def op_reboot( self, request ):
+ if debug: print ">NodeReboot"
+ server.xend_node_reboot()
diff -r ecb17ef5a587 -r df19d43b95d0 tools/python/xen/sv/RestoreDomain.py
--- /dev/null Mon Jul 25 21:19:14 2005
+++ b/tools/python/xen/sv/RestoreDomain.py Tue Jul 26 13:56:30 2005
@@ -0,0 +1,46 @@
+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 RestoreDomain( Wizard ):
+ def __init__( self, urlWriter ):
+
+ sheets = [ ChooseRestoreDomain,
+ DoRestore ]
+
+ Wizard.__init__( self, urlWriter, "Restore Domain", sheets )
+
+
+class ChooseRestoreDomain( Sheet ):
+ def __init__( self, urlWriter ):
+ Sheet.__init__( self, urlWriter, "Configure Restore", 0)
+
+ self.addControl( InputControl( 'file', '',
+ 'Suspend file name:',
+ ".*") )
+
+class DoRestore( Sheet ):
+ def __init__(self, urlWriter ):
+ Sheet.__init__(self, urlWriter, "Restore 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_restore( config['file'] )
+ success = "Your domain was successfully restored.\n"
+ except Exception, e:
+ success = "There was an error restoring your domain\n"
+ dom_sxp = str(e)
+
+ pt = PreTab( success + 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 ecb17ef5a587 -r df19d43b95d0 tools/python/xen/sv/SaveDomain.py
--- /dev/null Mon Jul 25 21:19:14 2005
+++ b/tools/python/xen/sv/SaveDomain.py Tue Jul 26 13:56:30 2005
@@ -0,0 +1,62 @@
+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 ecb17ef5a587 -r df19d43b95d0 tools/python/xen/sv/TabView.py
--- /dev/null Mon Jul 25 21:19:14 2005
+++ b/tools/python/xen/sv/TabView.py Tue Jul 26 13:56:30 2005
@@ -0,0 +1,26 @@
+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 ecb17ef5a587 -r df19d43b95d0 tools/python/xen/sv/Wizard.py
--- /dev/null Mon Jul 25 21:19:14 2005
+++ b/tools/python/xen/sv/Wizard.py Tue Jul 26 13:56:30 2005
@@ -0,0 +1,269 @@
+from xen.sv.util import *
+from xen.sv.HTMLBase import HTMLBase
+from xen.xend import sxp
+
+import re
+
+DEBUG = 0
+
+class Wizard( HTMLBase ):
+
+ def __init__( self, urlWriter, title, sheets ):
+ HTMLBase.__init__( self )
+ self.title = title
+ self.sheets = sheets
+ self.urlWriter = urlWriter
+
+ 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
+
+ def op_finish( self, request ):
+ pass
+
+class Sheet( HTMLBase ):
+
+ def __init__( self, urlWriter, title, location ):
+ HTMLBase.__init__( self )
+ self.urlWriter = urlWriter
+ self.feilds = []
+ self.title = title
+ self.location = location
+ self.passback = None
+
+ def parseForm( self, request ):
+ do_not_parse = [ 'mod', 'op', 'sheet', 'passback' ]
+
+ passed_back = request.args
+
+ temp_passback = passed_back.get( "passback" )
+
+ if temp_passback is not None and len( temp_passback ) > 0:
+ temp_passback = temp_passback[ len( temp_passback )-1 ]
+ else:
+ temp_passback = "( )"
+
+ last_passback = ssxp2hash( string2sxp( temp_passback ) ) #use special
function - will work with no head on sxp
+
+ if DEBUG: print last_passback
+
+ for (key, value) in passed_back.items():
+ if key not in do_not_parse:
+ last_passback[ key ] = value[ len( value ) - 1 ]
+
+ self.passback = sxp2string( hash2sxp( last_passback ) ) #store the sxp
+
+ if DEBUG: print self.passback
+
+ def write_BODY( self, request, err ):
+
+ if not self.passback: self.parseForm( request )
+
+ request.write( "<p>%s</p>" % self.title )
+
+ previous_values = ssxp2hash( string2sxp( self.passback ) ) #get the
hash for quick reference
+
+ request.write( "<table width='100%' cellpadding='0' cellspacing='1'
border='0'>" )
+
+ for (feild, control) in self.feilds:
+ control.write_Control( request, previous_values.get( feild ) )
+ if err 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 )
+
+ def addControl( self, control ):
+ self.feilds.append( [ control.getName(), control ] )
+
+ def validate( self, request ):
+
+ if not self.passback: self.parseForm( request )
+
+ check = True
+
+ previous_values = ssxp2hash( string2sxp( self.passback ) ) #get the
hash for quick reference
+ if DEBUG: print previous_values
+
+ for (feild, control) in self.feilds:
+ if not control.validate( previous_values.get( feild ) ):
+ check = False
+ if DEBUG: print "> %s = %s" % (feild, previous_values.get(
feild ))
+
+ return check
+
+class SheetControl( HTMLBase ):
+
+ def __init__( self, reg_exp = ".*" ):
+ HTMLBase.__init__( self )
+ self.name = ""
+ self.reg_exp = reg_exp
+
+ def write_Control( self, request, persistedValue ):
+ request.write( "<tr colspan='2'><td>%s</td></tr>" % persistedValue )
+
+ def write_Help( self, request ):
+ request.write( "<tr><td align='right' colspan='2'><p
class='small'>Text must match pattern:" )
+ request.write( " %s</p></td></tr>" % self.reg_exp )
+
+ def validate( self, persistedValue ):
+ if persistedValue is None:
+ persistedValue = ""
+
+ return not re.compile( self.reg_exp ).match( persistedValue ) is None
+
+ def getName( self ):
+ return self.name
+
+ def setName( self, name ):
+ self.name = name
+
+class InputControl( SheetControl ):
+
+ def __init__( self, name, defaultValue, humanText, reg_exp = ".*",
help_text = "You must enter the appropriate details in this feild." ):
+ SheetControl.__init__( self, reg_exp )
+ self.setName( name )
+
+ self.defaultValue = defaultValue
+ self.humanText = humanText
+ self.help_text = help_text
+
+ def write_Control( self, request, persistedValue ):
+ if persistedValue is None:
+ persistedValue = self.defaultValue
+
+ request.write( "<tr><td width='50%%'><p>%s</p></td><td
width='50%%'><input size='40'type='text' name='%s' value=\"%s\"></td></tr>" %
(self.humanText, self.getName(), persistedValue) )
+
+ def write_Help( self, request ):
+ request.write( "<tr><td align='right' colspan='2'><p class='small'>" )
+ request.write( " %s</p></td></tr>" % self.help_text )
+
+class TextControl( SheetControl ):
+
+ def __init__( self, text ):
+ SheetControl.__init__( self )
+ self.text = text
+
+ def write_Control( self, request, persistedValue ):
+ request.write( "<tr><td colspan='2'><p>%s</p></td></tr>" % self.text )
+
+class SmallTextControl( SheetControl ):
+
+ def __init__( self, text ):
+ SheetControl.__init__( self )
+ self.text = text
+
+ def write_Control( self, request, persistedValue ):
+ request.write( "<tr><td colspan='2'><p class='small'>%s</p></tr></td>"
% self.text )
+
+class ListControl( SheetControl ):
+
+ def __init__( self, name, options, humanText ):
+ SheetControl.__init__( self )
+ self.setName( name )
+ self.options = options
+ self.humanText = humanText
+
+ def write_Control( self, request, persistedValue ):
+ request.write( "<tr><td width='50%%'><p>%s</p></td><td width='50%%'>"
% self.humanText )
+ request.write( "<select name='%s'>" % self.getName() )
+ for (value, text) in self.options:
+ if value == persistedValue:
+ request.write( "<option value='%s' selected>%s\n" % (value,
text) )
+ else:
+ request.write( "<option value='%s'>%s\n" % (value, text) )
+ request.write( "</select></td></tr>" )
+
+ def validate( self, persistedValue ):
+ for (value, text) in self.options:
+ if value == persistedValue:
+ return True
+
+ return False
+
+class FileControl( InputControl ):
+
+ def __init__( self, name, defaultValue, humanText, reg_exp = ".*",
help_text = "You must enter the appropriate details in this feild." ):
+ InputControl.__init__( self, name, defaultValue, humanText )
+
+ def validate( self, persistedValue ):
+ if persistedValue is None: return False
+ try:
+ open( persistedValue )
+ return True
+ except IOError, TypeError:
+ return False
+
+ def write_Help( self, request ):
+ request.write( "<tr><td colspan='2' align='right'><p
class='small'>File does not exist: you must enter a valid, absolute file
path.</p></td></tr>" )
+
+class TickControl( SheetControl ):
+
+ def __init__( self, name, defaultValue, humanText ):
+ SheetControl.__init__( self )
+ self.setName( name )
+ self.defaultValue = defaultValue
+ self.humanText = humanText
+
+ def write_Control( self, request, persistedValue ):
+ request.write( "<tr><td width='50%%'><p>%s</p></td><td width='50%%'>"
% self.humanText )
+
+ 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>" )
+
+
diff -r ecb17ef5a587 -r df19d43b95d0 tools/python/xen/sv/__init__.py
--- /dev/null Mon Jul 25 21:19:14 2005
+++ b/tools/python/xen/sv/__init__.py Tue Jul 26 13:56:30 2005
@@ -0,0 +1,1 @@
+
diff -r ecb17ef5a587 -r df19d43b95d0 tools/python/xen/sv/params.py
--- /dev/null Mon Jul 25 21:19:14 2005
+++ b/tools/python/xen/sv/params.py Tue Jul 26 13:56:30 2005
@@ -0,0 +1,3 @@
+SV_PORT = 8080
+SV_ROOT = "/var/lib/xen/sv/"
+PID_FILE = "/var/run/xen-sv.pid"
diff -r ecb17ef5a587 -r df19d43b95d0 tools/python/xen/sv/util.py
--- /dev/null Mon Jul 25 21:19:14 2005
+++ b/tools/python/xen/sv/util.py Tue Jul 26 13:56:30 2005
@@ -0,0 +1,126 @@
+from xen.xend.XendClient import server
+from xen.xend import sxp
+from xen.xend import PrettyPrint
+
+import types
+
+def getDomInfoHash( domain ):
+ domInfoHash = {}
+ try:
+ domInfoHash = sxp2hash( server.xend_domain( domain ) )
+ domInfoHash['dom'] = domain
+ except:
+ domInfoHash['name'] = "Error getting domain details"
+ return domInfoHash
+
+def sxp2hash( s ):
+ sxphash = {}
+
+ for child in sxp.children( s ):
+ if isinstance( child, types.ListType ) and len( child ) > 1:
+ if isinstance( child[1], types.ListType ) and len( child ) > 1:
+ sxphash[ child[0] ] = sxp2hash( child[1] )
+ else:
+ sxphash[ child[0] ] = child[1]
+
+ return sxphash
+
+def ssxp2hash( s ):
+ sxphash = {}
+
+ for i in s:
+ if isinstance( i, types.ListType ) and len( i ) > 1:
+ sxphash[ i[0] ] = i[1]
+
+ return sxphash
+
+def hash2sxp( h ):
+ hashsxp = []
+
+ for (key, item) in h.items():
+ hashsxp.append( [key, item] )
+
+ return hashsxp
+
+def string2sxp( string ):
+ pin = sxp.Parser()
+ pin.input( string )
+ return pin.get_val()
+
+def sxp2string( sexp ):
+ return sxp.to_string( sexp )
+
+def sxp2prettystring( sxp ):
+ class tmp:
+ def __init__( self ):
+ self.str = ""
+ def write( self, str ):
+ self.str = self.str + str
+ temp = tmp()
+ PrettyPrint.prettyprint( sxp, out=temp )
+ return temp.str
+
+def getVar( var, request, default=None ):
+
+ arg = request.args.get( var )
+
+ if arg is None:
+ return default
+ else:
+ return arg[ len( arg )-1 ]
+
+def bigTimeFormatter( time ):
+ time = float( time )
+ weeks = time // 604800
+ remainder = time % 604800
+ days = remainder // 86400
+
+ remainder = remainder % 86400
+
+ hms = smallTimeFormatter( remainder )
+
+ return "%d weeks, %d days, %s" % ( weeks, days, hms )
+
+def smallTimeFormatter( time ):
+ time = float( time )
+ hours = time // 3600
+ remainder = time % 3600
+ mins = remainder // 60
+ secs = time % 60
+ return "%02d:%02d:%04.1f (hh:mm:ss.s)" % ( hours, mins, secs )
+
+def stateFormatter( state ):
+ states = [ 'Running', 'Blocked', 'Paused', 'Shutdown', 'Crashed' ]
+
+ stateStr = ""
+
+ for i in range( len( state ) ):
+ if state[i] != "-":
+ stateStr += "%s, " % states[ i ]
+
+ return stateStr + " (%s)" % state
+
+def memoryFormatter( mem ):
+ mem = int( mem )
+ if mem >= 1024:
+ mem = float( mem ) / 1024
+ return "%3.2fGb" % mem
+ else:
+ return "%7dMb" % mem
+
+def cpuFormatter( mhz ):
+ mhz = int( mhz )
+ if mhz > 1000:
+ ghz = float( mhz ) / 1000.0
+ return "%4.2fGHz" % ghz
+ else:
+ return "%4dMHz" % mhz
+
+def hyperthreadFormatter( threads ):
+ try:
+ if int( threads ) > 1:
+ return "Yes"
+ else:
+ return "No"
+ except:
+ return "No"
diff -r ecb17ef5a587 -r df19d43b95d0 tools/sv/Makefile
--- /dev/null Mon Jul 25 21:19:14 2005
+++ b/tools/sv/Makefile Tue Jul 26 13:56:30 2005
@@ -0,0 +1,2 @@
+
+all:
diff -r ecb17ef5a587 -r df19d43b95d0 tools/sv/images/destroy.png
--- /dev/null Mon Jul 25 21:19:14 2005
+++ b/tools/sv/images/destroy.png Tue Jul 26 13:56:30 2005
@@ -0,0 +1,23 @@
+?PNG
+
+
\ No newline at end of file
+IHDR 6 6 ?EjÝ |