diff --git a/.rootkeys b/.rootkeys index 424d963f29..5ea44cb274 100644 --- a/.rootkeys +++ b/.rootkeys @@ -390,12 +390,15 @@ 40fcefb38OTgsUKHBpwshLLIsiIaCA tools/sv/images/middle-no-highlight.jpg 40fcefb32SPtrw36c4S6YGFlLvkKuw tools/sv/images/orb_01.jpg 40fcefb3Ok5qkX3iM7ZEPVkRInrUpg tools/sv/images/orb_02.jpg +41013a82ILk71xLqWFH5ZO5VmOIvBw tools/sv/images/reboot.png 40fcefb3JnT5XeKTuVF4yUMGOtuNZg tools/sv/images/right-end-highlight.jpg 40fcefb3-DuYOS7noo2W7b_0p7TOUg tools/sv/images/right-end-no-highlight.jpg 40fcefb3qNbAZR5FYGPAZ9sFPVMTDA tools/sv/images/seperator-left-highlight.jpg 40fcefb3dgsa24WLk_BJeYQHrDLuOg tools/sv/images/seperator-right-highlight.jpg 40fcefb3FtiX4Pd2kT8wDlp8u8xRhQ tools/sv/images/seperator.jpg +41013a82sUdUqBv8EoAUJii3gsZ-4g tools/sv/images/shutdown.png 40fcefb3yMSrZvApO9ToIi-iQwnchA tools/sv/images/xen.png +41013a83z27rKvWIxAfUBMVZ1eDCDg tools/sv/inc/script.js 40fcefb3zGC9XNBkSwTEobCoq8YClA tools/sv/inc/style.css 403a3edbrr8RE34gkbR40zep98SXbg tools/xentrace/Makefile 40a107afN60pFdURgBv9KwEzgRl5mQ tools/xentrace/formats diff --git a/tools/python/xen/sv/DomInfo.py b/tools/python/xen/sv/DomInfo.py index 42abdee799..a718871fd5 100755 --- a/tools/python/xen/sv/DomInfo.py +++ b/tools/python/xen/sv/DomInfo.py @@ -14,7 +14,7 @@ class DomInfo( GenTabbed ): def tabUrlWriter( tab ): return urlWriter( "mod=info&dom=%s%s" % ( self.dom, tab ) ) - GenTabbed.__init__( self, tabUrlWriter, [ 'General', 'SXP', 'Devices' ], [ DomGenTab, DomSXPTab, NullTab ] ) + GenTabbed.__init__( self, "Domain Info", tabUrlWriter, [ 'General', 'SXP', 'Devices' ], [ DomGeneralTab, DomSXPTab, NullTab ] ) def write_BODY( self, request ): dom = request.args.get('dom') @@ -27,6 +27,10 @@ class DomInfo( GenTabbed ): GenTabbed.write_BODY( self, request ) +class DomGeneralTab( CompositeTab ): + def __init__( self ): + CompositeTab.__init__( self, [ DomGenTab, DomActionTab ] ) + class DomGenTab( GeneralTab ): def __init__( self ): @@ -41,7 +45,7 @@ class DomGenTab( GeneralTab ): titles[ 'Total CPU' ] = ( 'cpu_time', smallTimeFormatter ) titles[ 'Up Time' ] = ( 'up_time', bigTimeFormatter ) - GeneralTab.__init__( self, "General Domain Info", {}, titles ) + GeneralTab.__init__( self, {}, titles ) def write_BODY( self, request ): @@ -79,4 +83,18 @@ class DomSXPTab( PreTab ): PreTab.write_BODY( self, request ) +class DomActionTab( ActionTab ): + + def __init__( self ): + ActionTab.__init__( self, { "shutdown" : ( "Shutdown the Domain", "shutdown.png" ), + "reboot" : ( "Reboot the Domain", "reboot.png" ) } ) + + def op_shutdown( self, request ): + print ">DomShutDown" + #server.xend_node_shutdown() + + def op_reboot( self, request ): + print ">DomReboot" + #server.xend_node_reboot() + diff --git a/tools/python/xen/sv/GenTabbed.py b/tools/python/xen/sv/GenTabbed.py index bfbe5b04cf..1d5bd2d22a 100755 --- a/tools/python/xen/sv/GenTabbed.py +++ b/tools/python/xen/sv/GenTabbed.py @@ -5,12 +5,13 @@ from xen.sv.TabView import TabView class GenTabbed( HTMLBase ): - def __init__( self, urlWriter, tabStrings, tabObjects ): + def __init__( self, title, urlWriter, tabStrings, tabObjects ): HTMLBase.__init__(self) self.tab = 0; self.tabStrings = tabStrings self.tabObjects = tabObjects self.urlWriter = urlWriter + self.title = title def write_BODY( self, request, urlWriter = None ): tab = request.args.get('tab') @@ -23,19 +24,34 @@ class GenTabbed( HTMLBase ): request.write( "" ) request.write( "
" ) + request.write( "

%s

" % self.title ) + TabView( self.tab, self.tabStrings, self.urlWriter ).write_BODY( request ) request.write( "
" ) - render_tab = self.tabObjects[ self.tab ]() + 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 ) + render_tab().write_BODY( request ) request.write( "
" ) + + def perform( self, request ): + tab = request.args.get('tab') + + if tab is None or len( tab) != 1: + self.tab = 0 + else: + self.tab = int( tab[0] ) + + op_tab = self.tabObjects[ self.tab ] + + if op_tab: + op_tab().perform( request ) class PreTab( HTMLBase ): @@ -45,7 +61,7 @@ class PreTab( HTMLBase ): def write_BODY( self, request ): - request.write( "
" )
+        request.write( "
" )
         
         request.write( self.source )
         
@@ -53,16 +69,13 @@ class PreTab( HTMLBase ):
 
 class GeneralTab( HTMLBase ):
                         
-    def __init__( self, title, dict, titles ):
+    def __init__( self, dict, titles ):
         HTMLBase.__init__( self )
-        self.title = title
         self.dict = dict
         self.titles = titles
                         
     def write_BODY( self, request ): 
         
-        request.write( "

%s

" % self.title ) - request.write( "" ) def writeAttr( niceName, attr, formatter=None ): @@ -90,4 +103,38 @@ class NullTab( HTMLBase ): def write_BODY( self, request ): request.write( "

%s

" % self.title ) +class ActionTab( HTMLBase ): + + def __init__( self, actions ): + self.actions = actions + HTMLBase.__init__( self ) + + def write_BODY( self, request ): + request.write("

") + + for ( command, ( text, image ) ) in self.actions.items(): + request.write("") + request.write("  ") + + request.write("

 

") + request.write("

") + +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( "
" ) + tab().write_BODY( request ) + + def perform( self, request ): + for tab in self.tabs: + tab().perform( request ) + + + diff --git a/tools/python/xen/sv/HTMLBase.py b/tools/python/xen/sv/HTMLBase.py index 4479d7e455..7c500e8a2b 100755 --- a/tools/python/xen/sv/HTMLBase.py +++ b/tools/python/xen/sv/HTMLBase.py @@ -7,6 +7,10 @@ class HTMLBase( Resource ): def __init__( self ): Resource.__init__(self) + def render_POST( self, request ): + self.perform( request ) + self.render_GET( request ) + def render_GET( self, request ): self.write_TOP( request ) self.write_BODY( request ) @@ -19,7 +23,40 @@ class HTMLBase( Resource ): def write_TOP( self, request ): request.write( 'Xen' ) + request.write( '' ) request.write( '' ) def write_BOTTOM( self, request ): + request.write('' % request.uri) + request.write('') + request.write('') request.write( "" ) + + 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 --git a/tools/python/xen/sv/Main.py b/tools/python/xen/sv/Main.py index 6b9bbfae05..50712c7710 100755 --- a/tools/python/xen/sv/Main.py +++ b/tools/python/xen/sv/Main.py @@ -1,14 +1,31 @@ from xen.sv.HTMLBase import HTMLBase -from xen.sv import DomList, NodeInfo, DomInfo +from xen.sv.DomList import DomList +from xen.sv.NodeInfo import NodeInfo +from xen.sv.DomInfo import DomInfo class Main( HTMLBase ): isLeaf = True - def __init__( self ): + def __init__( self, urlWriter = None ): + self.modules = { "node": ( "Node details", NodeInfo ), + "list": ( "Domain summary", DomList ), + "info": ( "Domain info", DomInfo ) } HTMLBase.__init__(self) def render_POST( self, request ): + + #decide what module post'd the action + + mod = request.args.get('mod') + + if not mod is None and len(mod) == 1: + modTup = self.modules[ mod[0] ] + #check module exists + if modTup: + (modName, module) = modTup + module( self.mainUrlWriter ).perform( request ) + return self.render_GET( request ) def mainUrlWriter( self, s ): @@ -25,10 +42,10 @@ class Main( HTMLBase ): request.write( " " ) request.write( " " ) request.write( "
" ) - request.write( "

Node details

" ) - request.write( "

Domains summary

" ) + for (modName, (modTitle, module)) in self.modules.items(): + request.write( "

%s

" % (modName, modTitle)) - DomList.DomList( self.mainUrlWriter ).write_BODY( request, True, False ) + DomList( self.mainUrlWriter ).write_BODY( request, True, False ) request.write( "
" ) @@ -44,14 +61,13 @@ class Main( HTMLBase ): if mod is None or len(mod) != 1: request.write( '

Please select a module

' ) - elif mod[0] == 'info': - DomInfo.DomInfo( self.mainUrlWriter ).write_BODY( request ) - elif mod[0] == 'list': - DomList.DomList( self.mainUrlWriter ).write_BODY( request ) - elif mod[0] == 'node': - NodeInfo.NodeInfo( self.mainUrlWriter ).write_BODY( request ) else: - request.write( '

Invalid module. Please select another

' ) + modTup = self.modules[ mod[0] ] + if modTup: + (modName, module) = modTup + module( self.mainUrlWriter ).write_BODY( request ) + else: + request.write( '

Invalid module. Please select another

' ) request.write( " " ) request.write( " " ) diff --git a/tools/python/xen/sv/NodeInfo.py b/tools/python/xen/sv/NodeInfo.py index 68d050b3bb..f13781bf1a 100755 --- a/tools/python/xen/sv/NodeInfo.py +++ b/tools/python/xen/sv/NodeInfo.py @@ -10,24 +10,18 @@ class NodeInfo( GenTabbed ): def newUrlWriter( url ): return urlWriter( "mod=node%s" % url ) - GenTabbed.__init__( self, newUrlWriter, [ 'General', 'Dmesg' ], [ NodeGenTab, NodeDmesgTab ] ) + GenTabbed.__init__( self, "Node Details", newUrlWriter, [ 'General', 'Dmesg', ], [ NodeGeneralTab, NodeDmesgTab ] ) -class NodeGenTab( PreTab ): +class NodeGeneralTab( CompositeTab ): def __init__( self ): - text = sxp2string( server.xend_node() ) - PreTab.__init__( self, text ) - -class NodeGeneralTab( GeneralTab ): + CompositeTab.__init__( self, [ NodeInfoTab, NodeActionTab ] ) + +class NodeInfoTab( GeneralTab ): def __init__( self ): - nodeInfo = server.xend_node() - - dictNodeInfo = {} - - for l in nodeInfo: - dictNodeInfo[ l[0] ] = l[1] - + nodeInfo = sxp2hash( server.xend_node() ) + dictTitles = {} dictTitles[ 'System' ] = 'system' dictTitles[ 'Hostname' ] = 'host' @@ -40,11 +34,24 @@ class NodeGeneralTab( GeneralTab ): dictTitles[ 'Memory' ] = ( 'memory', memoryFormatter ) dictTitles[ 'Free Memory' ] = ( 'free_memory', memoryFormatter ) - GeneralTab.__init__( self, title="General Node Info", dict=dictNodeInfo, titles=dictTitles ) + GeneralTab.__init__( self, dict=nodeInfo, titles=dictTitles ) class NodeDmesgTab( PreTab ): def __init__( self ): dmesg = server.xend_node_dmesg() PreTab.__init__( self, dmesg[ 1 ] ) + +class NodeActionTab( ActionTab ): + + def __init__( self ): + ActionTab.__init__( self, { "shutdown" : ( "Shutdown the Node", "shutdown.png" ), + "reboot" : ( "Reboot the Node", "reboot.png" ) } ) + + def op_shutdown( self, request ): + print ">NodeShutDown" + #server.xend_node_shutdown() + def op_reboot( self, request ): + print ">NodeReboot" + #server.xend_node_reboot() diff --git a/tools/python/xen/sv/util.py b/tools/python/xen/sv/util.py index 47d3519011..64503bad29 100755 --- a/tools/python/xen/sv/util.py +++ b/tools/python/xen/sv/util.py @@ -17,8 +17,13 @@ def getDomInfoHash( domain ): d['start_time'] = float( sxp.child_value( domInfo, 'start_time' ) ) return d -def sxp2hash( sxp ): - pass +def sxp2hash( s ): + sxphash = {} + + for child in sxp.children( s ): + sxphash[ child[0] ] = child[1] + + return sxphash def sxp2string( sxp ): class tmp: @@ -58,7 +63,12 @@ def stateFormatter( state ): return state def memoryFormatter( mem ): - return "%7dMb" % mem + mem = int( mem ) + if mem >= 1024: + mem = float( mem ) / 1024 + return "%3.2fGb" % mem + else: + return "%7dMb" % mem def cpuFormatter( mhz ): if mhz > 1000: diff --git a/tools/python/xen/xend/XendClient.py b/tools/python/xen/xend/XendClient.py index 2d08f36056..b0a9c8beca 100644 --- a/tools/python/xen/xend/XendClient.py +++ b/tools/python/xen/xend/XendClient.py @@ -366,6 +366,14 @@ class Xend: def xend_node(self): return self.xendGet(self.nodeurl()) + def xend_node_shutdown(self): + return self.xendPost(self.nodeurl(), + {'op' : 'shutdown'}) + + def xend_node_restart(self): + return self.xendPost(self.nodeurl(), + {'op' : 'reboot'}) + def xend_node_dmesg(self): return self.xendGet(self.dmesgurl()) diff --git a/tools/sv/Makefile b/tools/sv/Makefile index 0321a566f3..db432d18be 100755 --- a/tools/sv/Makefile +++ b/tools/sv/Makefile @@ -28,12 +28,16 @@ install: install -m0644 images/seperator.jpg $(sv_insdir)/images install -m0644 images/seperator-left-highlight.jpg $(sv_insdir)/images install -m0644 images/seperator-right-highlight.jpg $(sv_insdir)/images + + install -m0644 images/shutdown.png $(sv_insdir)/images + install -m0644 images/reboot.png $(sv_insdir)/images # make include folder mkdir -p $(sv_insdir)/inc # copy stylesheet install -m0644 inc/style.css $(sv_insdir)/inc + install -m0644 inc/script.js $(sv_insdir)/inc clean: diff --git a/tools/sv/images/reboot.png b/tools/sv/images/reboot.png new file mode 100755 index 0000000000..358e6deb8f Binary files /dev/null and b/tools/sv/images/reboot.png differ diff --git a/tools/sv/images/shutdown.png b/tools/sv/images/shutdown.png new file mode 100755 index 0000000000..48a52dce21 Binary files /dev/null and b/tools/sv/images/shutdown.png differ diff --git a/tools/sv/inc/script.js b/tools/sv/inc/script.js new file mode 100755 index 0000000000..fca5a972ab --- /dev/null +++ b/tools/sv/inc/script.js @@ -0,0 +1,15 @@ +function update( objRef, text ) +{ + if ( document.all || document.getElementById ) + { + obj = ( document.getElementById )? document.getElementById( objRef ) : document.all( objRef ); + + obj.innerHTML= text + } +} + +function doOp( op ) +{ + document.forms[0].op.value = op + document.forms[0].submit() +} diff --git a/tools/sv/inc/style.css b/tools/sv/inc/style.css index e819f9254e..263ab59b23 100644 --- a/tools/sv/inc/style.css +++ b/tools/sv/inc/style.css @@ -27,4 +27,6 @@ body { } - \ No newline at end of file + +.button (cursor:hand) +