added sipb-xen-remote-listvms to aggregate results from multiple vm servers
authorYang Zhang <y_z@mit.edu>
Fri, 23 May 2008 18:23:30 +0000 (14:23 -0400)
committerYang Zhang <y_z@mit.edu>
Fri, 23 May 2008 18:23:30 +0000 (14:23 -0400)
svn path=/trunk/packages/sipb-xen-remote-server/; revision=538

files/etc/remctl/conf.d/sipb-xen-web
files/usr/sbin/sipb-xen-remote-listvms [new file with mode: 0755]

index f79ebbf..eff5884 100644 (file)
@@ -4,4 +4,4 @@ web lvrename     /usr/sbin/sipb-xen-remote-proxy-web /etc/remctl/acl/web
 web lvresize     /usr/sbin/sipb-xen-remote-proxy-web /etc/remctl/acl/web
 web lvcopy       /usr/sbin/sipb-xen-remote-proxy-web /etc/remctl/acl/web
 web vmboot       /usr/sbin/sipb-xen-remote-proxy-web /etc/remctl/acl/web
-web listvms      /usr/sbin/sipb-xen-remote-proxy-web /etc/remctl/acl/web
+web listvms      /usr/sbin/sipb-xen-remote-listvms   /etc/remctl/acl/web
diff --git a/files/usr/sbin/sipb-xen-remote-listvms b/files/usr/sbin/sipb-xen-remote-listvms
new file mode 100755 (executable)
index 0000000..4f16a98
--- /dev/null
@@ -0,0 +1,110 @@
+#!/usr/bin/env python2.5
+
+"""
+Collates the results of listvms from multiple VM servers.  Part of the xvm
+suite.
+"""
+
+from itertools import chain
+from subprocess import CalledProcessError, PIPE, Popen
+from sys import argv
+
+###
+
+import compiler
+
+class Unsafe_Source_Error(Exception):
+    def __init__(self,error,descr = None,node = None):
+        self.error = error
+        self.descr = descr
+        self.node = node
+        self.lineno = getattr(node,"lineno",None)
+        
+    def __repr__(self):
+        return "Line %d.  %s: %s" % (self.lineno, self.error, self.descr)
+    __str__ = __repr__    
+           
+class SafeEval(object):
+    
+    def visit(self, node,**kw):
+        cls = node.__class__
+        meth = getattr(self,'visit'+cls.__name__,self.default)
+        return meth(node, **kw)
+            
+    def default(self, node, **kw):
+        for child in node.getChildNodes():
+            return self.visit(child, **kw)
+            
+    visitExpression = default
+    
+    def visitConst(self, node, **kw):
+        return node.value
+
+    def visitDict(self,node,**kw):
+        return dict([(self.visit(k),self.visit(v)) for k,v in node.items])
+        
+    def visitTuple(self,node, **kw):
+        return tuple(self.visit(i) for i in node.nodes)
+        
+    def visitList(self,node, **kw):
+        return [self.visit(i) for i in node.nodes]
+
+class SafeEvalWithErrors(SafeEval):
+
+    def default(self, node, **kw):
+        raise Unsafe_Source_Error("Unsupported source construct",
+                                node.__class__,node)
+            
+    def visitName(self,node, **kw):
+        if node.name == 'None': return None
+        raise Unsafe_Source_Error("Strings must be quoted", 
+                                 node.name, node)
+                                 
+    # Add more specific errors if desired
+            
+def safe_eval(source, fail_on_error = True):
+    if source.strip() == '': return None
+    walker = fail_on_error and SafeEvalWithErrors() or SafeEval()
+    try:
+        ast = compiler.parse(source,"eval")
+    except SyntaxError, err:
+        raise
+    try:
+        return walker.visit(ast)
+    except Unsafe_Source_Error, err:
+        raise
+
+###
+
+def run(cmd):
+  """
+  Run the given command (a list of program and argument strings) and return the
+  stdout as a string, raising a CalledProcessError if the program exited with a
+  non-zero status.
+  """
+  p = Popen(cmd, stdout=PIPE)
+  stdout = p.communicate()[0]
+  if p.returncode != 0: raise CalledProcessError(p.returncode, cmd)
+  return stdout
+
+def main(argv):
+  # Query each of the server for their VMs.
+  # run('kinit -k host/sipb-vm-58.mit.edu'.split())
+  # TODO get `servers` from a real list of all the VM hosts (instead of
+  # hardcoding the list here)
+  servers = [ 'black-mesa.mit.edu', 'sx-blade-2.mit.edu' ]
+  # XXX
+  results = [ safe_eval(run(['remctl', server, 'remote', 'web', 'listvms'] + argv[1:]))
+              for server in servers ]
+  results = filter( lambda x: x is not None, results )
+
+  # Merge the results and print.
+  merged = {}
+  for result in results: merged.update(result)
+  print merged
+  print '.'
+
+if __name__ == '__main__':
+  main(argv)
+
+# vim:et:sw=2:ts=2