sipb-xen-remote-proxy: refactor argument parsing and passing
[invirt/packages/invirt-remote.git] / files / usr / sbin / sipb-xen-remote-listvms
index 4f16a98..6690fb9 100755 (executable)
-#!/usr/bin/env python2.5
+#!/usr/bin/python
 
 """
 Collates the results of listvms from multiple VM servers.  Part of the xvm
 suite.
 """
 
 
 """
 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
+from subprocess import PIPE, Popen
+import sys
+import yaml
 
 def main(argv):
 
 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 '.'
+    # Query each of the server for their VMs.
+    # 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
+    pipes = [(server,
+              Popen(['remctl', server, 'remote', 'web', 'listvms'], stdout=PIPE))
+             for server in servers]
+    outputs = [(s, p.communicate()[0]) for (s, p) in pipes]
+    for (s, p) in pipes:
+        if p.returncode != 0:
+            raise RuntimeError("remctl to host %s returned non-zero exit status %d"
+                               % (s, p.returncode)) 
+    results = [(s, yaml.load(o, yaml.CSafeLoader)) for (s, o) in outputs]
+    results = filter(lambda (_, x): x is not None, results)
+
+    # Merge the results and print.
+    merged = {}
+    for server, result in results:
+        for data in result.itervalues():
+            data['host'] = server
+        merged.update(result)
+
+    print yaml.dump(merged, Dumper=yaml.CSafeDumper, default_flow_style=False)
 
 if __name__ == '__main__':
 
 if __name__ == '__main__':
-  main(argv)
+    main(sys.argv)
 
 
-# vim:et:sw=2:ts=2
+# vim:et:sw=4:ts=4