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 807)
+++ 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]
