Index: trunk/packages/sipb-xen-base/files/usr/sbin/invirt-getconf
===================================================================
--- trunk/packages/sipb-xen-base/files/usr/sbin/invirt-getconf	(revision 815)
+++ trunk/packages/sipb-xen-base/files/usr/sbin/invirt-getconf	(revision 816)
@@ -17,5 +17,5 @@
 """
 
-from invirt.config import load
+from invirt.config import default_src_path, default_cache_path, load
 from sys import argv, exit, stderr, stdout
 from optparse import OptionParser
@@ -28,8 +28,8 @@
                 description = __doc__.strip().split('\n\n')[0])
         parser.add_option('-s', '--src',
-                default = '/etc/invirt/master.yaml',
+                default = default_src_path,
                 help = 'the source YAML configuration file to read from')
         parser.add_option('-c', '--cache',
-                default = '/var/lib/invirt/invirt.json',
+                default = default_cache_path,
                 help = 'path to the JSON cache')
         parser.add_option('-r', '--refresh',
@@ -81,6 +81,8 @@
             else:
                 import yaml
+                try:    dumper = yaml.CSafeDumper
+                except: dumper = yaml.SafeDumper
                 yaml.dump(conf, stdout,
-                          Dumper=yaml.CSafeDumper, default_flow_style=False)
+                          Dumper = dumper, default_flow_style = False)
     except invirt_exception, ex:
         print >> stderr, ex
Index: trunk/packages/sipb-xen-base/files/usr/share/python-support/sipb-xen-base/invirt/config.py
===================================================================
--- trunk/packages/sipb-xen-base/files/usr/share/python-support/sipb-xen-base/invirt/config.py	(revision 815)
+++ trunk/packages/sipb-xen-base/files/usr/share/python-support/sipb-xen-base/invirt/config.py	(revision 816)
@@ -1,4 +1,5 @@
 import json
 from invirt.common import *
+from os import rename
 from os.path import getmtime
 
@@ -75,5 +76,5 @@
                         lambda f: f.write(json.write(ns.cfg)))
                 except: pass # silent failure
-                else: os.rename(cache_path + '.tmp', cache_path)
+                else: rename(cache_path + '.tmp', cache_path)
         except IOError:
             ns.cfg = with_closing(file(src_path)) (
Index: trunk/packages/sipb-xen-base/files/usr/share/python-support/sipb-xen-base/invirt/remote.py
===================================================================
--- trunk/packages/sipb-xen-base/files/usr/share/python-support/sipb-xen-base/invirt/remote.py	(revision 816)
+++ trunk/packages/sipb-xen-base/files/usr/share/python-support/sipb-xen-base/invirt/remote.py	(revision 816)
@@ -0,0 +1,19 @@
+from subprocess import PIPE, Popen
+from invirt.config import structs as config
+import yaml
+
+def bcast(cmd, hosts = [h.hostname for h in config.hosts]):
+    """
+    Given a command and a list of hostnames or IPs, issue the command to all
+    the nodes and return a list of (host, output) pairs (the order should be
+    the same as the order of the hosts).
+    """
+    pipes = [(host,
+              Popen(['remctl', host, 'remote', 'web', cmd], stdout=PIPE))
+             for host in hosts]
+    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))
+    return [(s, yaml.load(o, yaml.CSafeLoader)) for (s, o) in outputs]
Index: trunk/packages/sipb-xen-remote-server/config.todo
===================================================================
--- trunk/packages/sipb-xen-remote-server/config.todo	(revision 815)
+++ trunk/packages/sipb-xen-remote-server/config.todo	(revision 816)
@@ -2,5 +2,3 @@
 files/usr/sbin/sipb-xen-remconffs: db uri
 files/usr/sbin/sipb-xen-remote-proxy: any one host name
-files/usr/sbin/sipb-xen-remote-create: host hostnames
-files/usr/sbin/sipb-xen-remote-listvms: host hostnames
 files/usr/sbin/sipb-xen-remctl-help: remote-proxy hostname
Index: trunk/packages/sipb-xen-remote-server/files/usr/sbin/sipb-xen-remote-create
===================================================================
--- trunk/packages/sipb-xen-remote-server/files/usr/sbin/sipb-xen-remote-create	(revision 815)
+++ trunk/packages/sipb-xen-remote-server/files/usr/sbin/sipb-xen-remote-create	(revision 816)
@@ -1,3 +1,4 @@
 #!/usr/bin/python
+
 """
 Picks a host to "create" (boot) a VM on, and does so.
@@ -8,36 +9,21 @@
 """
 
-
+from invirt.remote import bcast
 from subprocess import PIPE, Popen, call
 import sys
 import yaml
 
-
 def choose_host():
     # Query each of the hosts.
-    # 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']
-    pipes = [(server,
-              Popen(['remctl', server, 'remote', 'web', 'info'], 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]
     # XXX will the output of 'xm info' always be parseable YAML?
-
-    return max( (int(o['free_memory']), s) for (s, o) in results )[1]
-
+    results = bcast('info')
+    return max((int(o['free_memory']), s) for (s, o) in results)[1]
 
 def main(argv):
     if len(argv) < 2:
-        print >>sys.stderr, "usage: sipb-xen-remote-create <machine> [<other args...>]"
+        print >> sys.stderr, "usage: sipb-xen-remote-create <machine> [<other args...>]"
         return 2
     machine_name = argv[1]
     args = argv[2:]
-
 
     p = Popen(['/usr/sbin/sipb-xen-remote-proxy-web', 'listvms'], stdout=PIPE)
@@ -50,8 +36,7 @@
     if machine_name in vms:
         host = vms[machine_name]['host']
-        print >>sys.stderr, ("machine '%s' is already running on host %s"
-                             % (machine_name, host))
+        print >> sys.stderr, ("machine '%s' is already running on host %s"
+                              % (machine_name, host))
         return 1
-
 
     host = choose_host()
Index: trunk/packages/sipb-xen-remote-server/files/usr/sbin/sipb-xen-remote-listvms
===================================================================
--- trunk/packages/sipb-xen-remote-server/files/usr/sbin/sipb-xen-remote-listvms	(revision 815)
+++ trunk/packages/sipb-xen-remote-server/files/usr/sbin/sipb-xen-remote-listvms	(revision 816)
@@ -6,24 +6,11 @@
 """
 
-from subprocess import PIPE, Popen
+from invirt.remote import bcast
 import sys
 import yaml
 
 def main(argv):
-    # 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)
+    # Query each of the hosts.
+    results = filter(lambda (_, x): x is not None, bcast('listvms'))
 
     # Merge the results and print.
@@ -37,5 +24,5 @@
 
 if __name__ == '__main__':
-    main(sys.argv)
+    sys.exit(main(sys.argv))
 
 # vim:et:sw=4:ts=4
