diff --git a/.rootkeys b/.rootkeys
index b8f1f7b07b..40189aedaa 100644
--- a/.rootkeys
+++ b/.rootkeys
@@ -365,6 +365,35 @@
40c9c469yrm31i60pGKslTi2Zgpotg tools/python/xen/xend/server/messages.py
40c9c46925x-Rjb0Cv2f1-l2jZrPYg tools/python/xen/xend/server/netif.py
40c9c469ZqILEQ8x6yWy0_51jopiCg tools/python/xen/xend/server/params.py
+40fcefb2qm13BbRZBydAatOavaS0fQ tools/python/xen/xend/sv/DomInfo.py
+40fcefb2-RIU8GB67mJMRzybME9bxw tools/python/xen/xend/sv/DomList.py
+40fcefb23FfQn-ZBCbcHqA0cPGqQxw tools/python/xen/xend/sv/GenTabbed.py
+40fcefb2QZAn3u3sX-M7NXBjOv5HGg tools/python/xen/xend/sv/HTMLBase.py
+40fcefb2vnfDbl4w_yCTedROPuqs0g tools/python/xen/xend/sv/Main.py
+40fcefb2K1xqVVT4D-p7nL2GzS4scg tools/python/xen/xend/sv/Main.rpy
+40fcefb24h-04WaHag-Tg4nxWPhTig tools/python/xen/xend/sv/NodeInfo.py
+40fcefb2Sif__6AqrANeBQZZfvP-6w tools/python/xen/xend/sv/TabView.py
+40fcefb23s0sQlDfl4sPP0Un8oZGhg tools/python/xen/xend/sv/XendClientDeferred.py
+40fcefb2DqteqCCZYDCvvh4Q5jBd0w tools/python/xen/xend/sv/__init__.py
+40fcefb2Nhe-sT74KBB_3mYQg9Dl4Q tools/python/xen/xend/sv/images/internet copy.jpg
+40fcefb2QmVa4xdjdnSTXEdF2fZCDA tools/python/xen/xend/sv/images/internet.jpg
+40fcefb2g8Ez5jJIPHGN_KX7GtxV4w tools/python/xen/xend/sv/images/internet.psd
+40fcefb3wXQMsl9WkgQAVtdrupm4sw tools/python/xen/xend/sv/images/left-end-highlight.jpg
+40fcefb3K6ESt5sQhD9aCQRscQIlXQ tools/python/xen/xend/sv/images/left-end-no-highlight.jpg
+40fcefb3BUT98zPzW8kAFKuxGdh4XA tools/python/xen/xend/sv/images/middle-highlight.jpg
+40fcefb38OTgsUKHBpwshLLIsiIaCA tools/python/xen/xend/sv/images/middle-no-highlight.jpg
+40fcefb32SPtrw36c4S6YGFlLvkKuw tools/python/xen/xend/sv/images/orb_01.jpg
+40fcefb3Ok5qkX3iM7ZEPVkRInrUpg tools/python/xen/xend/sv/images/orb_02.jpg
+40fcefb3JnT5XeKTuVF4yUMGOtuNZg tools/python/xen/xend/sv/images/right-end-highlight.jpg
+40fcefb3-DuYOS7noo2W7b_0p7TOUg tools/python/xen/xend/sv/images/right-end-no-highlight.jpg
+40fcefb3qNbAZR5FYGPAZ9sFPVMTDA tools/python/xen/xend/sv/images/seperator-left-highlight.jpg
+40fcefb3dgsa24WLk_BJeYQHrDLuOg tools/python/xen/xend/sv/images/seperator-right-highlight.jpg
+40fcefb3FtiX4Pd2kT8wDlp8u8xRhQ tools/python/xen/xend/sv/images/seperator.jpg
+40fcefb3yMSrZvApO9ToIi-iQwnchA tools/python/xen/xend/sv/images/xen.png
+40fcefb310mW7U0p7JMoBQVnjf76xg tools/python/xen/xend/sv/inc/bottom.htm
+40fcefb3zGC9XNBkSwTEobCoq8YClA tools/python/xen/xend/sv/inc/style.css
+40fcefb4oxovdYkUvExZSkHN0cy_Ow tools/python/xen/xend/sv/inc/top.htm
+40fcefb4rnaZNjqsBu7A5V2rlLyqRw tools/python/xen/xend/sv/util.py
40c9c469LNxLVizOUpOjEaTKKCm8Aw tools/python/xen/xend/sxp.py
40d05079aFRp6NQdo5wIh5Ly31c0cg tools/python/xen/xm/__init__.py
40cf2937gKQcATgXKGtNeWb1PDH5nA tools/python/xen/xm/create.py
diff --git a/tools/python/xen/xend/server/SrvServer.py b/tools/python/xen/xend/server/SrvServer.py
index 9bc42f4217..1ce3446058 100644
--- a/tools/python/xen/xend/server/SrvServer.py
+++ b/tools/python/xen/xend/server/SrvServer.py
@@ -25,8 +25,8 @@
# todo Support security settings etc. in the config file.
# todo Support command-line args.
-from twisted.web import server
-from twisted.web import resource
+from twisted.web import server, static
+from twisted.web import resource, script
from twisted.internet import reactor
from xen.xend import XendRoot
@@ -44,8 +44,12 @@ def create(port=None, interface=None, bridge=0):
if bridge or xroot.rebooted:
Vifctl.network('start')
root = resource.Resource()
+ sv = static.File( "/usr/lib/python2.2/site-packages/xen/xend/sv/" )
+ sv.indexNames=['Main.rpy']
+ sv.processors={'.rpy':script.ResourceScript}
xend = SrvRoot()
root.putChild('xend', xend)
+ root.putChild('sv', sv)
site = server.Site(root)
reactor.listenTCP(port, site, interface=interface)
diff --git a/tools/python/xen/xend/sv/DomInfo.py b/tools/python/xen/xend/sv/DomInfo.py
new file mode 100755
index 0000000000..3c5642a770
--- /dev/null
+++ b/tools/python/xen/xend/sv/DomInfo.py
@@ -0,0 +1,99 @@
+from HTMLBase import HTMLBase
+from XendClientDeferred import server
+from xen.xend import PrettyPrint
+
+from xen.xend.sv.util import *
+from xen.xend.sv.GenTabbed import *
+
+class DomInfo( GenTabbed ):
+
+ def __init__( self, urlWriter, callback ):
+
+ self.dom = 0;
+
+ def tabUrlWriter( tab ):
+ return urlWriter( "mod=info&dom=%s%s" % ( self.dom, tab ) )
+
+ GenTabbed.__init__( self, tabUrlWriter, [ 'General', 'SXP', 'Devices' ], [ DomGenTab, DomSXPTab, NullTab ], callback )
+
+ def write_BODY( self, request ):
+ dom = request.args.get('dom')
+
+ if dom is None or len(dom) != 1:
+ request.write( "
Please Select a Domain
" )
+ return None
+ else:
+ self.dom = dom[0]
+
+ GenTabbed.write_BODY( self, request )
+
+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, "General Domain Info", {}, titles )
+
+ def write_BODY( self, request, callback ):
+ dom = request.args.get('dom')
+
+ if dom is None or len(dom) != 1:
+ request.write( "Please Select a Domain
" )
+ return None
+ else:
+ self.dom = dom[0]
+
+ deferred = getDomInfoHash( self.dom )
+ deferred.addCallback( self.continue_BODY, request, callback )
+
+ def continue_BODY( self, dict, request, callback ):
+
+ self.dict = dict
+
+ GeneralTab.write_BODY( self, request, callback )
+
+class DomSXPTab( PreTab ):
+
+ def __init__( self ):
+ self.dom = 0
+ PreTab.__init__( self, "" )
+
+ def fn( self, x, request ):
+ class tmp:
+ def __init__( self ):
+ self.str = ""
+ def write( self, str ):
+ self.str = self.str + str
+ temp = tmp()
+ PrettyPrint.prettyprint( x, out=temp )
+ self.source = temp.str
+ return request
+
+ def fn2( self, request, callback ):
+ PreTab.write_BODY( self, request, callback )
+
+ def write_BODY( self, request, callback ):
+ dom = request.args.get('dom')
+
+ if dom is None or len(dom) != 1:
+ request.write( "Please Select a Domain
" )
+ return None
+ else:
+ self.dom = dom[0]
+
+ deferred = server.xend_domain( self.dom )
+
+ deferred.addCallback( self.fn, request )
+ deferred.addCallback( self.fn2, callback )
+ def errback( x ):
+ print ">err ", x
+ deferred.addErrback( errback )
\ No newline at end of file
diff --git a/tools/python/xen/xend/sv/DomList.py b/tools/python/xen/xend/sv/DomList.py
new file mode 100755
index 0000000000..8fa74dff93
--- /dev/null
+++ b/tools/python/xen/xend/sv/DomList.py
@@ -0,0 +1,101 @@
+from twisted.web import resource
+from twisted.web.server import NOT_DONE_YET
+
+from XendClientDeferred import server as XendServer
+from xen.xend import sxp
+
+from xen.xend.sv.HTMLBase import HTMLBase
+from xen.xend.sv.util import *
+
+from twisted.internet import reactor
+
+class DomList( HTMLBase ):
+
+ isLeaf = True
+
+ def __init__( self, urlWriter, callback ):
+ HTMLBase.__init__(self)
+ self.urlWriter = urlWriter
+ self.head = None
+ self.long = None
+ self.rendered_domains = {}
+ self.domCount = 0
+ self.callback = callback
+
+ def write_BODY( self, request, head=True, long=True ):
+ deferred = XendServer.xend_domains()
+ deferred.addCallback( self.get_domain_info, request )
+ deferred.addErrback( self.errback )
+
+ self.head = head
+ self.long = long
+
+ def errback( self, err ):
+ print 'errback>', err
+
+ def get_domain_info( self, domains, request ):
+
+ self.domCount = len( domains )
+
+ for domain in domains:
+ deferred = getDomInfoHash( domain )
+ deferred.addCallback( self.render_domain, request )
+ deferred.addErrback( self.errback )
+
+ def render_domain( self, domInfoHash, request ):
+
+ domStr = "%(dom)-4d | \n" % domInfoHash
+
+ url = self.urlWriter( "mod=info&dom=%(dom)-4d" % domInfoHash )
+
+ domStr += "%s | \n" % ( url, domInfoHash['name'] )
+
+ if self.long:
+ domStr += "%(mem)7d | \n" % domInfoHash
+ domStr += "%(cpu)3d | \n" % domInfoHash
+
+ domStr += "%(state)5s | \n" % domInfoHash
+
+ if self.long:
+ domStr += "%(cpu_time)7.1f | \n" % domInfoHash
+
+ self.rendered_domains[ domInfoHash[ 'dom' ] ] = domStr
+ self.domCount -= 1
+
+ if self.domCount == 0:
+ self.finish_write_BODY( request )
+
+ def finish_write_BODY( self, request ):
+
+ request.write( "\n\n" )
+
+ if self.head:
+ request.write( "" )
+ self.write_DOMAIN_HEAD( request, self.long )
+ request.write( "
" )
+
+ odd = True
+ for domain in self.rendered_domains.values():
+ if odd:
+ request.write( "\n" )
+ odd = False
+ else:
+ request.write( "
\n" )
+ odd = True
+ request.write( domain )
+ request.write( "
\n" )
+
+ request.write( "
\n" )
+
+ self.callback( request )
+
+ def write_DOMAIN_HEAD( self, request, long=True ):
+ request.write( "Domain | \n" )
+ request.write( "Name | \n" )
+ if long:
+ request.write( "Memory / Mb | \n" )
+ request.write( "CPU | \n" )
+ request.write( "State | \n" )
+ if long:
+ request.write( "CPU time / s | \n" )
+
diff --git a/tools/python/xen/xend/sv/GenTabbed.py b/tools/python/xen/xend/sv/GenTabbed.py
new file mode 100755
index 0000000000..4f34a0692c
--- /dev/null
+++ b/tools/python/xen/xend/sv/GenTabbed.py
@@ -0,0 +1,103 @@
+import types
+
+from HTMLBase import HTMLBase
+from TabView import TabView
+
+class GenTabbed( HTMLBase ):
+
+ def __init__( self, urlWriter, tabStrings, tabObjects, callback ):
+ HTMLBase.__init__(self)
+ self.tab = 0;
+ self.tabStrings = tabStrings
+ self.tabObjects = tabObjects
+ self.urlWriter = urlWriter
+ self.callback = callback
+
+ def write_BODY( self, request, urlWriter = None ):
+ tab = request.args.get('tab')
+
+ if tab is None or len( tab) != 1:
+ self.tab = 0
+ else:
+ self.tab = int( tab[0] )
+
+ request.write( "" )
+ request.write( "| " )
+
+ TabView( self.tab, self.tabStrings, self.urlWriter ).write_BODY( request )
+
+ request.write( " |
| " )
+
+ render_tab = self.tabObjects[ self.tab ]()
+
+ if render_tab is None:
+ request.write( " Bad Tab " )
+ self.finish_BODY( request )
+ else:
+ render_tab.write_BODY( request, self.finish_BODY )
+
+ def finish_BODY( self, request ):
+
+ request.write( " |
" )
+
+ self.callback( request )
+
+class PreTab( HTMLBase ):
+
+ def __init__( self, source ):
+ HTMLBase.__init__( self )
+ self.source = source
+
+ def write_BODY( self, request, callback ):
+
+ request.write( "" )
+
+ request.write( self.source )
+
+ request.write( "
" )
+
+ callback( request )
+
+class GeneralTab( HTMLBase ):
+
+ def __init__( self, title, dict, titles ):
+ HTMLBase.__init__( self )
+ self.title = title
+ self.dict = dict
+ self.titles = titles
+
+ def write_BODY( self, request, callback ):
+
+ request.write( "%s
" % self.title )
+
+ request.write( "" )
+
+ 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( "%s: | %s |
" % ( niceName, temp ) )
+
+ for niceName, attr in self.titles.items():
+ writeAttr( niceName, attr )
+
+ request.write( "
" )
+
+ callback( request )
+
+class NullTab( HTMLBase ):
+
+ def __init__( self ):
+ HTMLBase.__init__( self )
+ self.title = "Null Tab"
+
+ def write_BODY( self, request, callback ):
+ request.write( "%s
" % self.title )
+ callback( request )
+
+
\ No newline at end of file
diff --git a/tools/python/xen/xend/sv/HTMLBase.py b/tools/python/xen/xend/sv/HTMLBase.py
new file mode 100755
index 0000000000..da8c03b366
--- /dev/null
+++ b/tools/python/xen/xend/sv/HTMLBase.py
@@ -0,0 +1,30 @@
+from twisted.web import server, resource
+from twisted.internet import reactor
+
+class HTMLBase( resource.Resource ):
+
+ isLeaf = True
+
+ defaultPath = "/usr/lib/python2.2/site-packages/xen/xend/sv/"
+
+ def __init__( self ):
+ resource.Resource.__init__(self)
+
+ def render_GET( self, request ):
+ self.write_TOP( request )
+ return self.write_BODY( request, self.finish_render_GET )
+
+ def finish_render_GET( self, request ):
+ self.write_BOTTOM( request )
+ request.finish()
+
+ def write_BODY( self, request ):
+ request.write( "BODY" )
+
+ def write_TOP( self, request ):
+ f = open( self.defaultPath + 'inc/top.htm', 'r' )
+ request.write( f.read() )
+
+ def write_BOTTOM( self, request ):
+ f = open( self.defaultPath + 'inc/bottom.htm', 'r' )
+ request.write( f.read() )
\ No newline at end of file
diff --git a/tools/python/xen/xend/sv/Main.py b/tools/python/xen/xend/sv/Main.py
new file mode 100755
index 0000000000..366e8a8124
--- /dev/null
+++ b/tools/python/xen/xend/sv/Main.py
@@ -0,0 +1,81 @@
+from twisted.web import resource
+from twisted.web.server import NOT_DONE_YET
+
+from xen.xend.XendClient import server as XendServer
+from xen.xend import sxp
+
+from HTMLBase import HTMLBase
+
+from xen.xend.sv import DomList, NodeInfo, DomInfo
+
+class Main( HTMLBase ):
+
+ isLeaf = True
+
+ def __init__( self ):
+ HTMLBase.__init__(self)
+
+ def render_POST( self, request ):
+ return self.render_GET( request )
+
+ def mainUrlWriter( self, s ):
+ return "Main.rpy?%s" % s
+
+ def write_BODY( self, request, callback ):
+
+ self.callback = callback
+
+ request.write( "\n\n" )
+ request.write( "\n" )
+ request.write( " | | " )
+ request.write( " " )
+ request.write( " " )
+ request.write( " " )
+ request.write( "  | " )
+ request.write( " | " )
+
+ request.write( " Node details " )
+ request.write( " Domains summary " )
+
+ DomList.DomList( self.mainUrlWriter, self.continue_BODY ).write_BODY( request, True, False )
+
+ return NOT_DONE_YET
+
+ def continue_BODY( self, request ):
+ request.write( " | " )
+ request.write( " " )
+ request.write( " " )
+ request.write( " | \n" )
+ request.write( " | " )
+ request.write( " " )
+ request.write( " " )
+ request.write( " | " )
+ request.write( " | " )
+
+ mod = request.args.get('mod')
+
+ if mod is None or len(mod) != 1:
+ request.write( ' Please select a module ' )
+ self.finish_BODY( request )
+ elif mod[0] == 'info':
+ DomInfo.DomInfo( self.mainUrlWriter, self.finish_BODY ).write_BODY( request )
+ elif mod[0] == 'list':
+ DomList.DomList( self.mainUrlWriter, self.finish_BODY ).write_BODY( request )
+ elif mod[0] == 'node':
+ NodeInfo.NodeInfo( self.mainUrlWriter, self.finish_BODY ).write_BODY( request )
+ else:
+ request.write( 'Invalid module. Please select another ' )
+ self.finish_BODY( request )
+
+ def finish_BODY( self, request ):
+
+ request.write( " | " )
+ request.write( " " )
+ request.write( " | \n" )
+ request.write( " | " )
+ request.write( "
\n" )
+
+ request.write( "
\n" )
+
+ self.callback( request )
+
\ No newline at end of file
diff --git a/tools/python/xen/xend/sv/Main.rpy b/tools/python/xen/xend/sv/Main.rpy
new file mode 100755
index 0000000000..90698027a6
--- /dev/null
+++ b/tools/python/xen/xend/sv/Main.rpy
@@ -0,0 +1,3 @@
+from xen.xend.sv.Main import *
+
+resource = Main()
\ No newline at end of file
diff --git a/tools/python/xen/xend/sv/NodeInfo.py b/tools/python/xen/xend/sv/NodeInfo.py
new file mode 100755
index 0000000000..7d69f4eb50
--- /dev/null
+++ b/tools/python/xen/xend/sv/NodeInfo.py
@@ -0,0 +1,47 @@
+from xen.xend import XendDmesg
+from xen.xend import XendNode
+
+from xen.xend.sv.util import *
+from xen.xend.sv.GenTabbed import *
+from xen.xend.sv.HTMLBase import HTMLBase
+
+class NodeInfo( GenTabbed ):
+
+ def __init__( self, urlWriter, callback ):
+
+ def newUrlWriter( url ):
+ return urlWriter( "mod=node%s" % url )
+
+ GenTabbed.__init__( self, newUrlWriter, [ 'General', 'Dmesg' ], [ NodeGeneralTab, NodeDmesgTab ], callback )
+
+class NodeGeneralTab( GeneralTab ):
+
+ def __init__( self ):
+
+ nodeInfo = XendNode.instance().info()
+
+ dictNodeInfo = {}
+
+ for l in nodeInfo:
+ dictNodeInfo[ l[0] ] = l[1]
+
+ 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, title="General Node Info", dict=dictNodeInfo, titles=dictTitles )
+
+class NodeDmesgTab( PreTab ):
+
+ def __init__( self ):
+ self.xd = XendDmesg.instance()
+ PreTab.__init__( self, self.xd.info()[0] )
+
\ No newline at end of file
diff --git a/tools/python/xen/xend/sv/TabView.py b/tools/python/xen/xend/sv/TabView.py
new file mode 100755
index 0000000000..70c485c329
--- /dev/null
+++ b/tools/python/xen/xend/sv/TabView.py
@@ -0,0 +1,49 @@
+from xen.xend.sv.HTMLBase import HTMLBase
+
+class TabView( HTMLBase ):
+
+ def __init__( self, tab, tabs, urlWriter ):
+ HTMLBase.__init__(self)
+ self.tab = tab # interger - tab id
+ self.tabs = tabs
+ self.urlWriter = urlWriter
+
+ def write_BODY( self, request ):
+ request.write( "" )
+ request.write( "" )
+
+ if self.tab == 0:
+ image = "left-end-highlight.jpg"
+ else:
+ image = "left-end-no-highlight.jpg"
+
+ request.write( " | " % image )
+
+ count = len( self.tabs )
+
+ for i in range( count ):
+
+ if i == self.tab:
+ image = "middle-highlight.jpg"
+ else:
+ image = "middle-no-highlight.jpg"
+
+ request.write( "%s | " % ( image, self.urlWriter( "&tab=%s" % i ), self.tabs[ i ] ) )
+
+ if i < count-1:
+ if i == self.tab:
+ image = "seperator-left-highlight.jpg"
+ elif self.tab == i+1:
+ image = "seperator-right-highlight.jpg"
+ else:
+ image = "seperator.jpg"
+
+ request.write( " | " % image )
+
+ if self.tab == count - 1:
+ image = "right-end-highlight.jpg"
+ else:
+ image = "right-end-no-highlight.jpg"
+
+ request.write( " | " % image )
+ request.write( "
" )
diff --git a/tools/python/xen/xend/sv/XendClientDeferred.py b/tools/python/xen/xend/sv/XendClientDeferred.py
new file mode 100755
index 0000000000..9f8a16d129
--- /dev/null
+++ b/tools/python/xen/xend/sv/XendClientDeferred.py
@@ -0,0 +1,363 @@
+# Copyright (C) 2004 Tom Wilkie
+# Copyright (C) 2004 Mike Wray
+"""Client API for the HTTP interface on xend.
+Callable as a script - see main().
+
+This API is the 'control-plane' for xend.
+The 'data-plane' is done separately. For example, consoles
+are accessed via sockets on xend, but the list of consoles
+is accessible via this API.
+
+This one is similar to mikes, but works in an async fashion
+"""
+import sys
+import httplib
+import types
+from StringIO import StringIO
+import urlparse
+
+from xen.xend.encode import *
+from xen.xend.sxp import *
+from xen.xend.PrettyPrint import prettyprint
+
+from twisted.protocols.http import HTTPClient
+from twisted.internet.protocol import ClientCreator
+from twisted.internet.defer import Deferred
+from twisted.internet import reactor
+
+DEBUG = 0
+
+class XendRequest( HTTPClient ):
+ def __init__(self, deferred, urls):
+ self.urls = urls
+ self.deferred = deferred
+
+ def connectionMade(self):
+ self.sendCommand('GET', self.urls[2])
+ self.sendHeader('Host', '%s:%d' % (self.urls[0], self.urls[1]) )
+ self.endHeaders()
+
+ def handleResponse(self, data):
+ self.deferred.callback( data )
+
+def process_SXP( sexp ):
+ pin = Parser()
+ pin.input(sexp)
+ pin.input_eof()
+ return pin.get_val()
+
+def xend_request(url, method, data=None):
+ """Make a request to xend.
+
+ url xend request url
+ method http method: POST or GET
+ data request argument data (dict)
+ """
+ urlinfo = urlparse.urlparse(url)
+ (uproto, ulocation, upath, uparam, uquery, ufrag) = urlinfo
+ (hdr, args) = encode_data(data)
+ if data and method == 'GET':
+ upath += '?' + args
+ args = None
+ if method == "POST" and upath.endswith('/'):
+ upath = upath[:-1]
+
+ deferred = Deferred()
+
+ clientCreator = ClientCreator( reactor, XendRequest, deferred, (ulocation, 8000, upath) )
+ clientCreator.connectTCP( ulocation, 8000 )
+
+ deferred.addCallback( process_SXP )
+
+ return deferred
+
+class XendError(RuntimeError):
+ pass
+
+class Foo(httplib.HTTPResponse):
+
+ def begin(self):
+ fin = self.fp
+ while(1):
+ buf = fin.readline()
+ print "***", buf
+ if buf == '':
+ print
+ sys.exit()
+
+
+def sxprio(sxpr):
+ """Convert an sxpr to a string.
+ """
+ io = StringIO()
+ sxp.show(sxpr, out=io)
+ print >> io
+ io.seek(0)
+ return io
+
+def fileof(val):
+ """Converter for passing configs.
+ Handles lists, files directly.
+ Assumes a string is a file name and passes its contents.
+ """
+ if isinstance(val, types.ListType):
+ return sxprio(val)
+ if isinstance(val, types.StringType):
+ return file(val)
+ if hasattr(val, 'readlines'):
+ return val
+
+# todo: need to sort of what urls/paths are using for objects.
+# e.g. for domains at the moment return '0'.
+# should probably return abs path w.r.t. server, e.g. /xend/domain/0.
+# As an arg, assume abs path is obj uri, otherwise just id.
+
+# Function to convert to full url: Xend.uri(path), e.g.
+# maps /xend/domain/0 to http://wray-m-3.hpl.hp.com:8000/xend/domain/0
+# And should accept urls for ids?
+
+def urljoin(location, root, prefix='', rest=''):
+ prefix = str(prefix)
+ rest = str(rest)
+ base = 'http://' + location + root + prefix
+ url = urlparse.urljoin(base, rest)
+ return url
+
+def nodeurl(location, root, id=''):
+ return urljoin(location, root, 'node/', id)
+
+def domainurl(location, root, id=''):
+ return urljoin(location, root, 'domain/', id)
+
+def consoleurl(location, root, id=''):
+ return urljoin(location, root, 'console/', id)
+
+def deviceurl(location, root, id=''):
+ return urljoin(location, root, 'device/', id)
+
+def vneturl(location, root, id=''):
+ return urljoin(location, root, 'vnet/', id)
+
+def eventurl(location, root, id=''):
+ return urljoin(location, root, 'event/', id)
+
+def xend_get(url, args=None):
+ """Make a xend request using GET.
+ Requests using GET are 'safe' and may be repeated without
+ nasty side-effects.
+ """
+ return xend_request(url, "GET", args)
+
+def xend_call(url, data):
+ """Make xend request using POST.
+ Requests using POST potentially cause side-effects and should
+ not be repeated unless it really is wanted to do the side
+ effect again.
+ """
+ return xend_request(url, "POST", data)
+
+class Xend:
+
+ """Default location of the xend server."""
+ SRV_DEFAULT = "localhost"
+
+ """Default path to the xend root on the server."""
+ ROOT_DEFAULT = "/xend/"
+
+ def __init__(self, srv=None, root=None):
+ self.bind(srv, root)
+
+ def bind(self, srv=None, root=None):
+ """Bind to a given server.
+
+ srv server location (host:port)
+ root server xend root path
+ """
+ if srv is None: srv = self.SRV_DEFAULT
+ if root is None: root = self.ROOT_DEFAULT
+ if not root.endswith('/'): root += '/'
+ self.location = srv
+ self.root = root
+
+ def nodeurl(self, id=''):
+ return nodeurl(self.location, self.root, id)
+
+ def domainurl(self, id=''):
+ return domainurl(self.location, self.root, id)
+
+ def consoleurl(self, id=''):
+ return consoleurl(self.location, self.root, id)
+
+ def deviceurl(self, id=''):
+ return deviceurl(self.location, self.root, id)
+
+ def vneturl(self, id=''):
+ return vneturl(self.location, self.root, id)
+
+ def eventurl(self, id=''):
+ return eventurl(self.location, self.root, id)
+
+ def xend(self):
+ return xend_get(urljoin(self.location, self.root))
+
+ def xend_node(self):
+ return xend_get(self.nodeurl())
+
+ def xend_node_cpu_rrobin_slice_set(self, slice):
+ return xend_call(self.nodeurl(),
+ {'op' : 'cpu_rrobin_slice_set',
+ 'slice' : slice })
+
+ def xend_node_cpu_bvt_slice_set(self, ctx_allow):
+ return xend_call(self.nodeurl(),
+ {'op' : 'cpu_bvt_slice_set',
+ 'ctx_allow' : ctx_allow })
+
+ def xend_node_cpu_fbvt_slice_set(self, ctx_allow):
+ return xend_call(self.nodeurl(),
+ {'op' : 'cpu_fbvt_slice_set',
+ 'ctx_allow' : ctx_allow })
+
+ def xend_domains(self):
+ return xend_get(self.domainurl())
+
+ def xend_domain_create(self, conf):
+ return xend_call(self.domainurl(),
+ {'op' : 'create',
+ 'config' : fileof(conf) })
+
+ def xend_domain(self, id):
+ return xend_get(self.domainurl(id))
+
+ def xend_domain_unpause(self, id):
+ return xend_call(self.domainurl(id),
+ {'op' : 'unpause'})
+
+ def xend_domain_pause(self, id):
+ return xend_call(self.domainurl(id),
+ {'op' : 'pause'})
+
+ def xend_domain_shutdown(self, id, reason):
+ return xend_call(self.domainurl(id),
+ {'op' : 'shutdown',
+ 'reason' : reason })
+
+ def xend_domain_destroy(self, id):
+ return xend_call(self.domainurl(id),
+ {'op' : 'destroy'})
+
+ def xend_domain_save(self, id, filename):
+ return xend_call(self.domainurl(id),
+ {'op' : 'save',
+ 'file' : filename})
+
+ def xend_domain_restore(self, id, filename):
+ return xend_call(self.domainurl(id),
+ {'op' : 'restore',
+ 'file' : filename })
+
+ def xend_domain_migrate(self, id, dst):
+ return xend_call(self.domainurl(id),
+ {'op' : 'migrate',
+ 'destination': dst})
+
+ def xend_domain_pincpu(self, id, cpu):
+ return xend_call(self.domainurl(id),
+ {'op' : 'pincpu',
+ 'cpu' : cpu})
+
+ def xend_domain_cpu_bvt_set(self, id, mcuadv, warp, warpl, warpu):
+ return xend_call(self.domainurl(id),
+ {'op' : 'cpu_bvt_set',
+ 'mcuadv' : mcuadv,
+ 'warp' : warp,
+ 'warpl' : warpl,
+ 'warpu' : warpu })
+
+ def xend_domain_cpu_fbvt_set(self, id, mcuadv, warp, warpl, warpu):
+ return xend_call(self.domainurl(id),
+ {'op' : 'cpu_fbvt_set',
+ 'mcuadv' : mcuadv,
+ 'warp' : warp,
+ 'warpl' : warpl,
+ 'warpu' : warpu })
+
+
+ def xend_domain_cpu_atropos_set(self, id, period, slice, latency, xtratime):
+ return xend_call(self.domainurl(id),
+ {'op' : 'cpu_atropos_set',
+ 'period' : period,
+ 'slice' : slice,
+ 'latency' : latency,
+ 'xtratime': xtratime })
+
+ def xend_domain_vifs(self, id):
+ return xend_get(self.domainurl(id),
+ { 'op' : 'vifs' })
+
+ def xend_domain_vif_ip_add(self, id, vif, ipaddr):
+ return xend_call(self.domainurl(id),
+ {'op' : 'vif_ip_add',
+ 'vif' : vif,
+ 'ip' : ipaddr })
+
+ def xend_domain_vbds(self, id):
+ return xend_get(self.domainurl(id),
+ {'op' : 'vbds'})
+
+ def xend_domain_vbd(self, id, vbd):
+ return xend_get(self.domainurl(id),
+ {'op' : 'vbd',
+ 'vbd' : vbd})
+
+ def xend_consoles(self):
+ return xend_get(self.consoleurl())
+
+ def xend_console(self, id):
+ return xend_get(self.consoleurl(id))
+
+ def xend_vnets(self):
+ return xend_get(self.vneturl())
+
+ def xend_vnet_create(self, conf):
+ return xend_call(self.vneturl(),
+ {'op': 'create', 'config': fileof(conf) })
+
+ def xend_vnet(self, id):
+ return xend_get(self.vneturl(id))
+
+ def xend_vnet_delete(self, id):
+ return xend_call(self.vneturl(id),
+ {'op': 'delete'})
+
+ def xend_event_inject(self, sxpr):
+ val = xend_call(self.eventurl(),
+ {'op': 'inject', 'event': fileof(sxpr) })
+
+def main(argv):
+ """Call an API function:
+
+ python XendClient.py fn args...
+
+ The leading 'xend_' on the function can be omitted.
+ Example:
+
+ > python XendClient.py domains
+ (domain 0 8)
+ > python XendClient.py domain 0
+ (domain (id 0) (name Domain-0) (memory 128))
+ """
+ server = Xend()
+ fn = argv[1]
+ if not fn.startswith('xend'):
+ fn = 'xend_' + fn
+ args = argv[2:]
+ deferred = getattr(server, fn)(*args)
+ deferred.addCallback( prettyprint )
+ reactor.run()
+ print
+
+if __name__ == "__main__":
+ main(sys.argv)
+else:
+ server = Xend()
diff --git a/tools/python/xen/xend/sv/__init__.py b/tools/python/xen/xend/sv/__init__.py
new file mode 100755
index 0000000000..8d1c8b69c3
--- /dev/null
+++ b/tools/python/xen/xend/sv/__init__.py
@@ -0,0 +1 @@
+
diff --git a/tools/python/xen/xend/sv/images/internet copy.jpg b/tools/python/xen/xend/sv/images/internet copy.jpg
new file mode 100755
index 0000000000..92eafeb9fe
Binary files /dev/null and b/tools/python/xen/xend/sv/images/internet copy.jpg differ
diff --git a/tools/python/xen/xend/sv/images/internet.jpg b/tools/python/xen/xend/sv/images/internet.jpg
new file mode 100755
index 0000000000..74a03c3a78
Binary files /dev/null and b/tools/python/xen/xend/sv/images/internet.jpg differ
diff --git a/tools/python/xen/xend/sv/images/internet.psd b/tools/python/xen/xend/sv/images/internet.psd
new file mode 100644
index 0000000000..a2e9d1754f
Binary files /dev/null and b/tools/python/xen/xend/sv/images/internet.psd differ
diff --git a/tools/python/xen/xend/sv/images/left-end-highlight.jpg b/tools/python/xen/xend/sv/images/left-end-highlight.jpg
new file mode 100644
index 0000000000..3922eb593a
Binary files /dev/null and b/tools/python/xen/xend/sv/images/left-end-highlight.jpg differ
diff --git a/tools/python/xen/xend/sv/images/left-end-no-highlight.jpg b/tools/python/xen/xend/sv/images/left-end-no-highlight.jpg
new file mode 100644
index 0000000000..ded4e3933b
Binary files /dev/null and b/tools/python/xen/xend/sv/images/left-end-no-highlight.jpg differ
diff --git a/tools/python/xen/xend/sv/images/middle-highlight.jpg b/tools/python/xen/xend/sv/images/middle-highlight.jpg
new file mode 100644
index 0000000000..db9829d9bf
Binary files /dev/null and b/tools/python/xen/xend/sv/images/middle-highlight.jpg differ
diff --git a/tools/python/xen/xend/sv/images/middle-no-highlight.jpg b/tools/python/xen/xend/sv/images/middle-no-highlight.jpg
new file mode 100644
index 0000000000..da3b4f68a0
Binary files /dev/null and b/tools/python/xen/xend/sv/images/middle-no-highlight.jpg differ
diff --git a/tools/python/xen/xend/sv/images/orb_01.jpg b/tools/python/xen/xend/sv/images/orb_01.jpg
new file mode 100755
index 0000000000..e30efc4985
Binary files /dev/null and b/tools/python/xen/xend/sv/images/orb_01.jpg differ
diff --git a/tools/python/xen/xend/sv/images/orb_02.jpg b/tools/python/xen/xend/sv/images/orb_02.jpg
new file mode 100755
index 0000000000..e5ebc8e4b1
Binary files /dev/null and b/tools/python/xen/xend/sv/images/orb_02.jpg differ
diff --git a/tools/python/xen/xend/sv/images/right-end-highlight.jpg b/tools/python/xen/xend/sv/images/right-end-highlight.jpg
new file mode 100644
index 0000000000..1ffee341ab
Binary files /dev/null and b/tools/python/xen/xend/sv/images/right-end-highlight.jpg differ
diff --git a/tools/python/xen/xend/sv/images/right-end-no-highlight.jpg b/tools/python/xen/xend/sv/images/right-end-no-highlight.jpg
new file mode 100644
index 0000000000..0ddd058d67
Binary files /dev/null and b/tools/python/xen/xend/sv/images/right-end-no-highlight.jpg differ
diff --git a/tools/python/xen/xend/sv/images/seperator-left-highlight.jpg b/tools/python/xen/xend/sv/images/seperator-left-highlight.jpg
new file mode 100644
index 0000000000..c90f4ffd12
Binary files /dev/null and b/tools/python/xen/xend/sv/images/seperator-left-highlight.jpg differ
diff --git a/tools/python/xen/xend/sv/images/seperator-right-highlight.jpg b/tools/python/xen/xend/sv/images/seperator-right-highlight.jpg
new file mode 100644
index 0000000000..f37e6cd546
Binary files /dev/null and b/tools/python/xen/xend/sv/images/seperator-right-highlight.jpg differ
diff --git a/tools/python/xen/xend/sv/images/seperator.jpg b/tools/python/xen/xend/sv/images/seperator.jpg
new file mode 100644
index 0000000000..c77e2c5500
Binary files /dev/null and b/tools/python/xen/xend/sv/images/seperator.jpg differ
diff --git a/tools/python/xen/xend/sv/images/xen.png b/tools/python/xen/xend/sv/images/xen.png
new file mode 100644
index 0000000000..344c361b3c
Binary files /dev/null and b/tools/python/xen/xend/sv/images/xen.png differ
diff --git a/tools/python/xen/xend/sv/inc/bottom.htm b/tools/python/xen/xend/sv/inc/bottom.htm
new file mode 100755
index 0000000000..4d4a7e5285
--- /dev/null
+++ b/tools/python/xen/xend/sv/inc/bottom.htm
@@ -0,0 +1,2 @@
+