Index: package_tags/invirt-remote/0.3.14/debian/changelog
===================================================================
--- package_tags/invirt-remote/0.3.14/debian/changelog	(revision 2346)
+++ package_tags/invirt-remote/0.3.14/debian/changelog	(revision 2346)
@@ -0,0 +1,379 @@
+invirt-remote (0.3.14) unstable; urgency=low
+
+  * Maybe we won't be /quite/ so ionice to the dd over a deleted LV.
+
+ -- Evan Broder <broder@mit.edu>  Sun, 03 May 2009 03:46:13 -0400
+
+invirt-remote (0.3.13) unstable; urgency=low
+
+  * I totally failed to patch the right server.
+
+ -- Evan Broder <broder@mit.edu>  Fri, 03 Apr 2009 20:02:34 -0400
+
+invirt-remote (0.3.12) unstable; urgency=low
+
+  * ionice the dd to wipe out deleted LVs so it doesn't hose the system.
+  * availability takes way too long to type.
+
+ -- Evan Broder <broder@mit.edu>  Thu, 02 Apr 2009 20:35:17 -0400
+
+invirt-remote (0.3.11) unstable; urgency=low
+
+  * Print errors to stderr on nocreate and nolvm so that the website
+    actually notices.
+
+ -- Evan Broder <broder@mit.edu>  Wed, 18 Mar 2009 19:37:38 -0400
+
+invirt-remote (0.3.10) unstable; urgency=low
+
+  * Let invirt-remote-proxy know all the possible subcommands.
+  * Accept /etc/invirt/{nocreate,nolvm} on remote-server.
+
+ -- Greg Price <price@mit.edu>  Mon, 16 Mar 2009 21:22:13 -0400
+
+invirt-remote (0.3.9) unstable; urgency=low
+
+  * Include a CDROM in listvms, if there is one.
+
+ -- Evan Broder <broder@mit.edu>  Thu, 12 Mar 2009 17:20:15 -0400
+
+invirt-remote (0.3.8) unstable; urgency=low
+
+  * Allow anyone on the adminacl to issue web remctls.
+
+ -- Evan Broder <broder@mit.edu>  Fri, 27 Feb 2009 21:28:19 -0500
+
+invirt-remote (0.3.7) unstable; urgency=low
+
+  * Add an availability remctl for when we get around to letting us make
+    web remctls.
+
+ -- Evan Broder <broder@mit.edu>  Thu, 26 Feb 2009 01:04:07 -0500
+
+invirt-remote (0.3.6) unstable; urgency=low
+
+  * Don't confuse KB with KiB, or MB with MiB.
+
+ -- Anders Kaseorg <andersk@mit.edu>  Tue, 17 Feb 2009 04:58:06 -0500
+
+invirt-remote (0.3.5) unstable; urgency=low
+
+  * updated quota support to refer to renamed owner table columns
+
+ -- Peter A. Iannucci <iannucci@mit.edu>  Tue, 17 Feb 2009 02:13:44 -0500
+
+invirt-remote (0.3.4) unstable; urgency=low
+
+  * modified host/usr/sbin/invirt-availability and invirt-vmcontrol to stat
+    /etc/invirt/nocreate; if it exists, they advertise zero free memory and
+    refuse to create VMs
+  * added memory quota validation to invirt-remote-create
+
+ -- Peter A. Iannucci <iannucci@mit.edu>  Tue, 17 Feb 2009 01:31:20 -0500
+
+invirt-remote (0.3.3) unstable; urgency=low
+
+  * added remctl web availability to calculate memory available to new VMs
+  * removed remctl web info
+
+ -- Peter A. Iannucci <iannucci@mit.edu>  Thu, 12 Feb 2009 23:26:24 -0500
+
+invirt-remote (0.3.2) unstable; urgency=low
+
+  * in invirt-remote-listvms, ignore another way VMs can disappear
+
+ -- Greg Price <price@mit.edu>  Thu, 05 Feb 2009 13:43:46 -0500
+
+invirt-remote (0.3.1) unstable; urgency=low
+
+  * invirt.remote.bcast: provide stderr text when remctl fails
+  * create /etc/remctl/remconffs in -server, not -host
+
+ -- Greg Price <price@mit.edu>  Sat, 31 Jan 2009 14:33:08 -0500
+
+invirt-remote (0.3.0) unstable; urgency=low
+
+  * Instead of immediately deleting LVs, overwrite them with zeros to
+    avoid leaking information from one VM to another.
+
+ -- Evan Broder <broder@mit.edu>  Wed, 21 Jan 2009 02:57:30 -0500
+
+invirt-remote (0.2.2) unstable; urgency=low
+
+  * config.{authn[0] => kerberos}.realm
+
+ -- Evan Broder <broder@mit.edu>  Wed, 10 Dec 2008 23:18:45 -0500
+
+invirt-remote (0.2.1) unstable; urgency=low
+
+  * Be sure to create /etc/remctl/remconffs
+
+ -- Evan Broder <broder@mit.edu>  Mon, 08 Dec 2008 09:25:43 -0500
+
+invirt-remote (0.2.0) unstable; urgency=low
+
+  * Merge invirt-remote-server and invirt-remote-host into invirt-remote
+    (LP: #305682)
+
+ -- Evan Broder <broder@mit.edu>  Sun, 07 Dec 2008 18:33:59 -0500
+
+invirt-remote-server (0.1.6) unstable; urgency=low
+
+  * Fix a gen_config -> gen_files
+
+ -- Greg Price <price@mit.edu>  Sat, 22 Nov 2008 19:27:36 -0500
+
+invirt-remote-server (0.1.5) unstable; urgency=low
+
+  * Fix a typo in calling /lib/init/gen-files.sh
+
+ -- Evan Broder <broder@mit.edu>  Sat, 22 Nov 2008 05:43:06 -0500
+
+invirt-remote-server (0.1.4) unstable; urgency=low
+
+  * Steal some init script ideas from debathena-pyhesiodfs
+
+ -- Evan Broder <broder@mit.edu>  Sat, 22 Nov 2008 05:31:49 -0500
+
+invirt-remote-server (0.1.3) unstable; urgency=low
+
+  * Switched to using "raw" select expressions instead of using the ORM;
+    allows the same speed as the old object-based system but without any
+    caching necessary.
+
+ -- Quentin Smith <quentin@mit.edu>  Fri, 21 Nov 2008 04:15:50 -0500
+
+invirt-remote-server (0.1.2) unstable; urgency=low
+
+  * Update remctl help with new reboot functionality
+
+ -- Evan Broder <broder@mit.edu>  Thu, 20 Nov 2008 10:57:39 -0500
+
+invirt-remote-server (0.1.1) unstable; urgency=low
+
+  * Now that we're doing real caching, cache for less time
+
+ -- Evan Broder <broder@mit.edu>  Mon, 17 Nov 2008 13:18:23 -0500
+
+invirt-remote-server (0.1.0) unstable; urgency=low
+
+  * Add real caching to remconffs
+
+ -- Evan Broder <broder@mit.edu>  Mon, 17 Nov 2008 13:05:32 -0500
+
+invirt-remote-server (0.0.18) unstable; urgency=low
+
+  * Add a "help" command for the control remctl
+
+ -- Evan Broder <broder@mit.edu>  Sat, 15 Nov 2008 19:02:19 -0500
+
+invirt-remote-server (0.0.17) unstable; urgency=low
+
+  * Get the host with the most RAM based on the maximum recoverable
+    memory, not the memory currently available to Xen
+
+ -- Evan Broder <broder@mit.edu>  Sat, 15 Nov 2008 10:30:10 -0500
+
+invirt-remote-server (0.0.16) unstable; urgency=low
+
+  * When returning from a bcast, put together the stdout, not the stderr
+
+ -- Evan Broder <broder@mit.edu>  Mon, 10 Nov 2008 16:19:33 -0500
+
+invirt-remote-server (0.0.15) unstable; urgency=low
+
+  * Include invirt.remote Python module
+  * Ignore erroneous responses from a server if it's because the server is
+    down
+
+ -- Evan Broder <broder@mit.edu>  Mon, 10 Nov 2008 15:19:28 -0500
+
+invirt-remote-server (0.0.14) unstable; urgency=low
+
+  * Don't depend on invirt-mail-config
+
+ -- Evan Broder <broder@mit.edu>  Thu, 06 Nov 2008 22:51:19 -0500
+
+invirt-remote-server (0.0.13) unstable; urgency=low
+
+  * Depend on invirt-mail-config
+
+ -- Evan Broder <broder@mit.edu>  Thu, 06 Nov 2008 21:49:27 -0500
+
+invirt-remote-server (0.0.12) unstable; urgency=low
+
+  * shorten initscript with std-init, correct the usage message
+
+ -- Greg Price <price@mit.edu>  Wed, 05 Nov 2008 19:59:18 -0500
+
+invirt-remote-server (0.0.11) unstable; urgency=low
+
+  * Don't proxy requests for the VNC cert if the requested hostname isn't
+    an Invirt host
+
+ -- Evan Broder <broder@mit.edu>  Tue, 28 Oct 2008 23:17:10 -0400
+
+invirt-remote-server (0.0.10) unstable; urgency=low
+
+  * All remctls of type 'web' have the same ACL - glob them together
+
+ -- Evan Broder <broder@mit.edu>  Tue, 28 Oct 2008 23:05:42 -0400
+
+invirt-remote-server (0.0.9) unstable; urgency=low
+
+  * Add support for a `web vnccert` remctl call
+
+ -- Evan Broder <broder@mit.edu>  Tue, 28 Oct 2008 22:45:29 -0400
+
+invirt-remote-server (0.0.8) unstable; urgency=low
+
+  * sipb-xen-base -> invirt-base
+
+ -- Evan Broder <broder@mit.edu>  Tue, 28 Oct 2008 04:23:32 -0400
+
+invirt-remote-server (0.0.7) unstable; urgency=low
+
+  * sipb-xen-database-common -> invirt-database
+
+ -- Evan Broder <broder@mit.edu>  Sat, 25 Oct 2008 21:03:13 -0400
+
+invirt-remote-server (0.0.6) unstable; urgency=low
+
+  * Remove dependency on sipb-xen-chrony-config - we need to take care of
+    the clock, but chrony isn't the right answer
+
+ -- Evan Broder <broder@mit.edu>  Sat, 25 Oct 2008 19:16:08 -0400
+
+invirt-remote-server (0.0.5) unstable; urgency=low
+
+  * Rename a remaining sipb-xen file to invirt
+
+ -- Evan Broder <broder@mit.edu>  Fri, 24 Oct 2008 22:21:30 -0400
+
+invirt-remote-server (0.0.4) unstable; urgency=low
+
+  * Kill DEB_AUTO_UPDATE_DEBIAN_CONTROL
+
+ -- Evan Broder <broder@mit.edu>  Fri, 24 Oct 2008 13:49:45 -0400
+
+invirt-remote-server (0.0.3) unstable; urgency=low
+
+  * Standardize on "Invirt project"
+
+ -- Evan Broder <broder@mit.edu>  Fri, 24 Oct 2008 13:33:25 -0400
+
+invirt-remote-server (0.0.2) unstable; urgency=low
+
+  * oops, update control from control.in
+  * configurize web acl
+
+ -- Greg Price <price@mit.edu>  Fri, 24 Oct 2008 00:28:08 -0400
+
+invirt-remote-server (0.0.1) unstable; urgency=low
+
+  * sipb-xen -> invirt
+
+ -- Greg Price <price@mit.edu>  Thu, 23 Oct 2008 23:58:36 -0400
+
+sipb-xen-remote-server (0.10.2) unstable; urgency=low
+
+  * There's a race condition for if the VM gets powered off between the
+    listvms and the actual request. Solve the problem correctly by using a
+    non-conflicting error code to indicate an invalid command
+
+ -- Evan Broder <broder@mit.edu>  Wed, 22 Oct 2008 00:46:38 -0400
+
+sipb-xen-remote-server (0.10.1) unstable; urgency=low
+
+  * Make both list-host and listhost valid commands, and for parity with
+    list-long, document list-host
+
+ -- Evan Broder <broder@mit.edu>  Wed, 22 Oct 2008 00:36:32 -0400
+
+sipb-xen-remote-server (0.10) unstable; urgency=low
+
+  * If a command is invalid, but the machine's on, give an actually useful
+    error message
+
+ -- Evan Broder <broder@mit.edu>  Wed, 22 Oct 2008 00:29:50 -0400
+
+sipb-xen-remote-server (0.9.2) unstable; urgency=low
+
+  * Expose an interface to the autoinstaller over remctl
+  * Validate options to be passed to the autoinstaller on the remctl
+    server
+
+ -- Evan Broder <broder@mit.edu>  Thu, 09 Oct 2008 02:06:00 -0400
+
+sipb-xen-remote-server (0.9.1) unstable; urgency=low
+
+  * Fix a bug in the database handling code
+
+ -- Evan Broder <broder@mit.edu>  Fri, 03 Oct 2008 18:42:48 -0400
+
+sipb-xen-remote-server (0.9) unstable; urgency=low
+
+  [Evan Broder]
+  * Make the acl/ subdir of RemConfFS listable
+  
+  [Greg Price]
+  * Update RemConfFS for new SQLAlchemy code
+
+ -- Evan Broder <broder@mit.edu>  Wed, 01 Oct 2008 19:28:23 -0400
+
+sipb-xen-remote-server (0.8) unstable; urgency=low
+
+  * Use RouteFS for RemConfFS
+
+ -- Evan Broder <broder@mit.edu>  Wed, 01 Oct 2008 02:21:00 -0400
+
+sipb-xen-remote-server (0.7) unstable; urgency=low
+
+  * depend on sipb-xen-base
+
+ -- Greg Price <price@mit.edu>  Tue, 30 Sep 2008 20:47:05 -0400
+
+sipb-xen-remote-server (0.6) unstable; urgency=low
+
+  * sipb_xen_database -> invirt.config
+
+ -- Yang Zhang <y_z@mit.edu>  Sun,  3 Aug 2008 00:54:59 -0400
+
+sipb-xen-remote-server (0.5) unstable; urgency=low
+
+  * use invirt config in sipb-xen-remconffs, sipb-xen-remctl-help,
+    sipb-xen-remote-proxy
+
+ -- Yang Zhang <y_z@mit.edu>  Sun,  3 Aug 2008 00:32:59 -0400
+
+sipb-xen-remote-server (0.4) unstable; urgency=low
+
+  * use invirt.config to get hostnames
+  * refactoring: extracted bcast() function into invirt.remote package
+
+ -- Yang Zhang <y_z@mit.edu>  Sat,  2 Aug 2008 20:34:50 -0400
+
+sipb-xen-remote-server (0.3) unstable; urgency=low
+
+  * Fill in all the code to make the package work (mostly weeks ago.)
+  * sipb-xen-remote-listvms aggregates listvms across hosts (with
+    y_z, broder, andersk)
+  * sipb-xen-remctl-help gives help
+  * sipb-xen-remote-control proxies to where a machine is running
+  * sipb-xen-remote-create chooses where to boot by load-balancing
+
+ -- Greg Price <price@mit.edu>  Thu, 24 Jul 2008 21:34:20 -0400
+
+sipb-xen-remote-server (0.2) unstable; urgency=low
+
+  * FUSE filesystem for remctl configuration.
+  * Remove *register calls, since the FUSE keeps things up to date.
+  * An init script to keep the FUSE fs up.
+
+ -- Greg Price <price@mit.edu>  Sat, 10 May 2008 22:04:32 -0400
+
+sipb-xen-remote-server (0.1) unstable; urgency=low
+
+  * First draft.
+
+ -- Greg Price <price@mit.edu>  Sun, 30 Mar 2008 01:08:50 -0400
Index: package_tags/invirt-remote/0.3.14/debian/compat
===================================================================
--- package_tags/invirt-remote/0.3.14/debian/compat	(revision 2346)
+++ package_tags/invirt-remote/0.3.14/debian/compat	(revision 2346)
@@ -0,0 +1,1 @@
+5
Index: package_tags/invirt-remote/0.3.14/debian/control
===================================================================
--- package_tags/invirt-remote/0.3.14/debian/control	(revision 2346)
+++ package_tags/invirt-remote/0.3.14/debian/control	(revision 2346)
@@ -0,0 +1,28 @@
+Source: invirt-remote
+Section: servers
+Priority: important
+Maintainer: Invirt project <invirt@mit.edu>
+Build-Depends: cdbs (>= 0.4.23-1.1), debhelper (>= 5),
+ python-all-dev (>=2.3.5-11), python-support (>= 0.5.3),
+ python-setuptools, python-debian, python-apt
+Standards-Version: 3.8.0
+
+Package: invirt-remote-server
+Architecture: all
+Provides: ${diverted-files}, ${python:Provides}
+Conflicts: ${diverted-files}
+Depends: ${shlibs:Depends}, ${misc:Depends}, ${python:Depends},
+ daemon, debathena-kerberos-config, fuse-utils, openssh-server,
+ python-routefs, invirt-database, invirt-base, remctl-server,
+ remctl-client
+XB-Python-Version: ${python:Versions}
+Description: Invirt remote-control server
+ This package should be installed to set up the remote-control server.
+
+Package: invirt-remote-host
+Architecture: all
+Depends: ${misc:Depends}, remctl-server, invirt-console-host,
+ invirt-vnc-server, python-cjson, python-yaml, util-linux
+Description: Installs the Invirt host remctl configuration
+ This is the remctl configuration for an Invirt host. It allows any
+ commands to be run from the Invirt remote server
Index: package_tags/invirt-remote/0.3.14/debian/copyright
===================================================================
--- package_tags/invirt-remote/0.3.14/debian/copyright	(revision 2346)
+++ package_tags/invirt-remote/0.3.14/debian/copyright	(revision 2346)
@@ -0,0 +1,16 @@
+This software was written as part of the Invirt project <invirt@mit.edu>.
+
+Copyright :
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+On Debian systems, the complete text of the GNU General Public License
+can be found in the file /usr/share/common-licenses/GPL.
Index: package_tags/invirt-remote/0.3.14/debian/invirt-remote-host.init
===================================================================
--- package_tags/invirt-remote/0.3.14/debian/invirt-remote-host.init	(revision 2346)
+++ package_tags/invirt-remote/0.3.14/debian/invirt-remote-host.init	(revision 2346)
@@ -0,0 +1,36 @@
+#!/bin/bash
+### BEGIN INIT INFO
+# Provides:          invirt-remote-host
+# Required-Start:    $local_fs $remote_fs
+# Required-Stop:     $local_fs $remote_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: remctl configuration for an Invirt host
+# Description:
+### END INIT INFO 
+
+PACKAGE=invirt-remote-host
+
+. /lib/lsb/init-functions
+
+gen_config()
+{
+    for i in /etc/remctl/acl/remote
+    do mako-render $i.mako > $i
+    done
+}
+
+case "$1" in
+  start|reload|force-reload|restart)
+    log_begin_msg "Reloading config for $PACKAGE"
+    gen_config
+    log_end_msg $?
+    invoke-rc.d openbsd-inetd start # returns 1 if inetd is running
+    [ $? -eq 1 ] && exit 0
+    ;;
+  stop)
+    ;;
+  *)
+    log_success_msg "Usage: /etc/init.d/$PACKAGE {start|reload|force-reload|restart|stop}"
+    ;;
+esac
Index: package_tags/invirt-remote/0.3.14/debian/invirt-remote-host.install
===================================================================
--- package_tags/invirt-remote/0.3.14/debian/invirt-remote-host.install	(revision 2346)
+++ package_tags/invirt-remote/0.3.14/debian/invirt-remote-host.install	(revision 2346)
@@ -0,0 +1,1 @@
+host/* .
Index: package_tags/invirt-remote/0.3.14/debian/invirt-remote-server.dirs
===================================================================
--- package_tags/invirt-remote/0.3.14/debian/invirt-remote-server.dirs	(revision 2346)
+++ package_tags/invirt-remote/0.3.14/debian/invirt-remote-server.dirs	(revision 2346)
@@ -0,0 +1,1 @@
+etc/remctl/remconffs
Index: package_tags/invirt-remote/0.3.14/debian/invirt-remote-server.init
===================================================================
--- package_tags/invirt-remote/0.3.14/debian/invirt-remote-server.init	(revision 2346)
+++ package_tags/invirt-remote/0.3.14/debian/invirt-remote-server.init	(revision 2346)
@@ -0,0 +1,79 @@
+#! /bin/sh
+### BEGIN INIT INFO
+# Provides:          invirt-remote-server
+# Required-Start:    $local_fs $remote_fs
+# Required-Stop:     $local_fs $remote_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: Invirt remctl configuration filesystem
+# Description:       
+### END INIT INFO
+
+# Author: Invirt project <invirt@mit.edu>
+
+PATH=/sbin:/usr/sbin:/bin:/usr/bin
+NAME=invirt-remote-server
+DESC="the Invirt remctl configuration filesystem"
+DAEMON=/usr/sbin/invirt-remconffs
+MOUNTPOINT="/etc/remctl/remconffs"
+DAEMON_ARGS="-f $MOUNTPOINT"
+PIDFILE=/var/run/$NAME.pid
+SCRIPTNAME=/etc/init.d/$NAME
+GEN_FILES=/etc/remctl/acl/web
+
+# Exit if the package is not installed
+[ -x "$DAEMON" ] || exit 0
+
+. /lib/init/gen-files.sh
+. /lib/init/std-init.sh
+
+#
+# Function that starts the daemon/service
+#
+do_start()
+{
+    # Return
+    #   0 if daemon has been started
+    #   1 if daemon was already running
+    #   2 if daemon could not be started
+    
+    # Try to make sure fuse is setup
+    [ -e /dev/fuse ] || modprobe fuse || return 2
+    
+    if cat /proc/mounts | grep " $MOUNTPOINT " >/dev/null 2>&1; then
+        return 1
+    fi
+    
+    gen_files
+    
+    daemon -r -O daemon.info -E daemon.err -n $NAME -- $DAEMON $DAEMON_ARGS || return 2
+}
+
+#
+# Function that stops the daemon/service
+#
+do_stop()
+{
+    # Return
+    #   0 if daemon has been stopped
+    #   1 if daemon was already stopped
+    #   2 if daemon could not be stopped
+    #   other if a failure occurred
+    
+    if ! cat /proc/mounts | grep " $MOUNTPOINT " >/dev/null 2>&1; then
+        return 1
+    fi
+    
+    daemon --stop -n $NAME
+    RETVAL="$?"
+    [ "$RETVAL" = 2 ] && return 2
+    # Many daemons don't delete their pidfiles when they exit.
+    rm -f $PIDFILE
+}
+
+do_reload()
+{
+    gen_files
+}
+
+std_init "$1"
Index: package_tags/invirt-remote/0.3.14/debian/invirt-remote-server.install
===================================================================
--- package_tags/invirt-remote/0.3.14/debian/invirt-remote-server.install	(revision 2346)
+++ package_tags/invirt-remote/0.3.14/debian/invirt-remote-server.install	(revision 2346)
@@ -0,0 +1,2 @@
+server/* .
+debian/tmp/* .
Index: package_tags/invirt-remote/0.3.14/debian/pycompat
===================================================================
--- package_tags/invirt-remote/0.3.14/debian/pycompat	(revision 2346)
+++ package_tags/invirt-remote/0.3.14/debian/pycompat	(revision 2346)
@@ -0,0 +1,1 @@
+2
Index: package_tags/invirt-remote/0.3.14/debian/rules
===================================================================
--- package_tags/invirt-remote/0.3.14/debian/rules	(revision 2346)
+++ package_tags/invirt-remote/0.3.14/debian/rules	(revision 2346)
@@ -0,0 +1,9 @@
+#!/usr/bin/make -f
+
+DEB_PYTHON_SYSTEM=pysupport
+
+include /usr/share/cdbs/1/rules/debhelper.mk
+include /usr/share/cdbs/1/class/python-distutils.mk
+
+clean::
+	rm -rf invirt.remote.egg-info
Index: package_tags/invirt-remote/0.3.14/host/etc/remctl/acl/remote.mako
===================================================================
--- package_tags/invirt-remote/0.3.14/host/etc/remctl/acl/remote.mako	(revision 2346)
+++ package_tags/invirt-remote/0.3.14/host/etc/remctl/acl/remote.mako	(revision 2346)
@@ -0,0 +1,2 @@
+<% from invirt.config import structs as cfg %>\
+host/${cfg.remote.hostname}@${cfg.kerberos.realm}
Index: package_tags/invirt-remote/0.3.14/host/etc/remctl/conf.d/invirt-remote-host
===================================================================
--- package_tags/invirt-remote/0.3.14/host/etc/remctl/conf.d/invirt-remote-host	(revision 2346)
+++ package_tags/invirt-remote/0.3.14/host/etc/remctl/conf.d/invirt-remote-host	(revision 2346)
@@ -0,0 +1,2 @@
+remote web     /usr/sbin/invirt-remote /etc/remctl/acl/remote
+remote control /usr/sbin/invirt-remote /etc/remctl/acl/remote
Index: package_tags/invirt-remote/0.3.14/host/usr/sbin/invirt-availability
===================================================================
--- package_tags/invirt-remote/0.3.14/host/usr/sbin/invirt-availability	(revision 2346)
+++ package_tags/invirt-remote/0.3.14/host/usr/sbin/invirt-availability	(revision 2346)
@@ -0,0 +1,62 @@
+#!/usr/bin/env python
+"""
+Gathers availability data for the VM host it's running on.
+"""
+
+from subprocess import PIPE, Popen, call
+import sys
+import yaml
+import os
+
+# return the amount of memory in kibibytes represented by s
+def parseUnits(s):
+    num, unit = s.split(' ')
+    assert unit == 'kB', "unexpected unit"
+    return int(num)
+
+def main(argv):
+    """
+    Calculate the amount of memory available for new VMs
+    The numbers returned by xm info and xm info -c are in MiB
+    The numbers in /proc/xen/balloon are in KiB
+    All math is done in kibibytes for consistency
+    Output is in MiB
+
+    Bail if /etc/invirt/nocreate exists
+    """
+    try:
+        os.stat('/etc/invirt/nocreate')
+        print 0
+        return 0
+    except OSError:
+        pass
+
+    p = Popen(['/usr/sbin/xm', 'info'], stdout=PIPE)
+    output = p.communicate()[0]
+    if p.returncode != 0:
+        raise RuntimeError("Command '%s' returned non-zero exit status %d"
+                           % ('/usr/sbin/xm info', p.returncode)) 
+    xminfo = yaml.load(output, yaml.CSafeLoader)
+
+    free_memory = int(xminfo['free_memory']) * 1024
+
+    ballooninfo = yaml.load(open('/proc/xen/balloon', 'r').read())
+    currentallocation = parseUnits(ballooninfo['Current allocation'])
+    minimumtarget = parseUnits(ballooninfo['Minimum target'])
+
+    p = Popen(['/usr/sbin/xm', 'info', '-c'], stdout=PIPE)
+    output = p.communicate()[0]
+    if p.returncode != 0:
+        raise RuntimeError("Command '%s' returned non-zero exit status %d"
+                           % ('/usr/sbin/xm info -c', p.returncode)) 
+    xminfoc = yaml.load(output, yaml.CSafeLoader)
+
+    # In kibibytes
+    dom0minmem = int(xminfoc['dom0-min-mem']) * 1024
+
+    dom0_spare_memory = currentallocation - max(minimumtarget, dom0minmem)
+    print int((free_memory + dom0_spare_memory)/1024)
+    return 0
+
+if __name__ == '__main__':
+    sys.exit(main(sys.argv))
Index: package_tags/invirt-remote/0.3.14/host/usr/sbin/invirt-listvms
===================================================================
--- package_tags/invirt-remote/0.3.14/host/usr/sbin/invirt-listvms	(revision 2346)
+++ package_tags/invirt-remote/0.3.14/host/usr/sbin/invirt-listvms	(revision 2346)
@@ -0,0 +1,54 @@
+#!/usr/bin/python
+
+import sys
+import time
+from xen.lowlevel import xs
+
+xsc = xs.xs()
+
+def live_vms():
+    domids = set(xsc.ls('', '/local/domain'))
+    domids.discard('0')
+
+    vms = dict()
+
+    for domid in domids:
+        try:
+            name, data = get_dom(int(domid))
+        except (xs.Error, TypeError):
+            continue # went down since we started
+        if name is not None and name.startswith('d_'):
+            name = name[2:]
+            vms[name] = data
+    return vms
+
+def get_dom(domid):
+    name = xsc.read('', '/local/domain/%d/name' % domid)
+    data = dict()
+    data['domid'] = domid
+    # presence of a graphical console
+    data['console'] = xsc.read('', '/local/domain/%d/device/vfb/0/state' % domid)
+    # uptime
+    data['vm'] = xsc.read('', '/local/domain/%d/vm' % domid)
+    data['start_time'] = float(xsc.read('', '%s/start_time' % data['vm']))
+    data['uptime'] = time.time()-data['start_time']
+    # CD, if there is one
+    vbds = xsc.ls('', '/local/domain/%d/device/vbd' % domid)
+    for vbd in vbds:
+        dev = '/local/domain/%d/device/vbd/%s' % (domid, vbd)
+        if xsc.read('', '%s/device-type' % dev) == 'cdrom':
+            data['cdrom'] = xsc.read('', '%s/params' % xsc.read('', '%s/backend' % dev))
+    
+    return name, data
+
+if __name__ == '__main__':
+    vms = live_vms()
+    if '--json' in sys.argv[1:]:
+        import cjson
+        print cjson.encode(vms)
+    elif '--pickle' in sys.argv[1:]:
+        import cPickle
+        cPickle.dump(vms, sys.stdout, cPickle.HIGHEST_PROTOCOL)
+    else:
+        import yaml
+        print yaml.dump(vms, Dumper=yaml.CSafeDumper, default_flow_style=False)
Index: package_tags/invirt-remote/0.3.14/host/usr/sbin/invirt-lvm
===================================================================
--- package_tags/invirt-remote/0.3.14/host/usr/sbin/invirt-lvm	(revision 2346)
+++ package_tags/invirt-remote/0.3.14/host/usr/sbin/invirt-lvm	(revision 2346)
@@ -0,0 +1,102 @@
+#!/usr/bin/env python
+
+import sys
+import time
+import os
+import random
+import string
+from subprocess import call, PIPE, Popen
+from invirt.config import structs as config
+
+def check(b):
+    if not b:
+        exit(1)
+
+vg = "xenvg"
+prefix = "d_"
+
+subcommand = sys.argv[1]
+
+def ensureoff(machine):
+    # Make sure the machine is off, but we don't care about errors if it is already off.
+    rv = call(["/usr/sbin/xm", "destroy", prefix + machine],
+              stderr=PIPE)
+
+if subcommand == "lvcreate-all":
+    from invirt import database
+    import re
+    database.connect()
+    for d in Disk.select():
+        check(re.match('^[A-Za-z0-9]+$', d.guest_device_name))
+        machine = Machine.get(d.machine_id)
+        check(re.match('^[A-Za-z0-9][A-Za-z0-9._-]*$', machine.name))
+        lvname = prefix + machine.name + "_" + d.guest_device_name
+        if not os.path.exists("/dev/%s/%s" % (vg, lvname)):
+            # LV doesn't exist
+            print >>sys.stderr, "Creating LV %s..." % (lvname,)
+            rv = call(["/sbin/lvcreate", "-L", str(d.size) + "M", "-n", lvname, vg])
+            if rv != 0:
+                print >>sys.stderr, "Error creating LV %s\n" %(lvname,)
+                sys.exit(1)
+else:
+    machine = sys.argv[2]
+    disk = sys.argv[3]
+    lvname = prefix + machine + "_" + disk
+    lvpath = "/dev/" + vg + "/" + lvname
+if subcommand == "lvremove":
+    def error():
+        print >>sys.stderr, "Error removing LV %s\n" % lvname
+        sys.exit(1)
+    
+    # Rename the LV to something else so we can wipe it before reusing
+    # the space
+    while True:
+        new_lvname = "old_%s_%s" % (lvname, ''.join(random.choice(string.ascii_letters) for i in xrange(6)))
+        new_lvpath = "/dev/%s/%s" % (vg, new_lvname)
+        p = Popen(["/sbin/lvrename", lvpath, new_lvpath], stdout=PIPE, stderr=PIPE)
+        rv = p.wait()
+        if rv == 5 and 'already exists in volume group' in p.stderr.read():
+            continue
+        elif rv != 0:
+            error()
+        else:
+            break
+    ensureoff(machine)
+    
+    # Fork. The child process wipes the LV and then deletes
+    # it. There's not really anything sane to do with errors (since
+    # this is running non-interactively), so let's just drop them on
+    # the floor for now.
+    if os.fork() == 0:
+        call(["/usr/bin/ionice", "-c", "2", "-n", "7", "/bin/dd", "if=/dev/zero", "of=%s" % new_lvpath])
+        call(["/sbin/lvchange", "-a", "n", new_lvpath])
+        call(["/sbin/lvchange", "-a", "ey", new_lvpath])
+        call(["/sbin/lvremove", "--force", new_lvpath])
+elif subcommand == "lvresize":
+    size = sys.argv[4]
+    ensureoff(machine)
+    p = Popen(["/sbin/lvresize", "-L", size + "M", lvpath],
+              stdin=PIPE, stderr=PIPE)
+    print >> p.stdin, 'y'
+    err = p.stderr.read()
+    if p.wait() != 0 and 'matches existing size' not in err:
+        print >> sys.stderr, "Error resizing LV %s:\n" %(lvname,)
+        print >> sys.stderr, err
+        sys.exit(1)
+    print >> sys.stderr, err
+elif subcommand == "lvrename":
+    newmachine = sys.argv[4]
+    newlvname = prefix + newmachine + "_" + disk
+    ensureoff(machine)
+    ensureoff(newmachine)    
+    rv = call(["/sbin/lvrename", vg, lvname, newlvname])
+    if rv != 0:
+        print >>sys.stderr, "Error renaming LV %s\n" %(lvname,)
+        sys.exit(1)
+elif subcommand == "lvcreate":
+    size = sys.argv[4]
+    rv = call(["/sbin/lvcreate", "-L", size + "M", "-n", lvname, vg])
+    if rv != 0:
+        print >>sys.stderr, "Error creating LV %s\n" %(lvname,)
+        sys.exit(1)
+
Index: package_tags/invirt-remote/0.3.14/host/usr/sbin/invirt-remote
===================================================================
--- package_tags/invirt-remote/0.3.14/host/usr/sbin/invirt-remote	(revision 2346)
+++ package_tags/invirt-remote/0.3.14/host/usr/sbin/invirt-remote	(revision 2346)
@@ -0,0 +1,41 @@
+#!/bin/sh
+# invirt-remote TYPE SERVICE [ARGS...]
+#
+# We carry out the remctl command proxied to us by the remote-control server.
+
+TYPE="$1"
+SERVICE="$2"
+shift; shift;
+
+case "$TYPE" in
+    control)
+        # $SERVICE is hostname
+        COMMAND=/usr/sbin/invirt-vmcontrol
+    ;;
+    web)
+        case "$SERVICE" in
+            lvcreate|lvremove|lvrename|lvresize)
+                COMMAND=/usr/sbin/invirt-lvm
+            ;;
+            listvms)
+                COMMAND=/usr/sbin/invirt-listvms
+            ;;
+            availability|avail)
+                COMMAND=/usr/sbin/invirt-availability
+            ;;
+            vnccert)
+                COMMAND=/usr/bin/invirt-vnc-getcert
+                ;;
+            *)
+                echo "ERROR: invalid subcommand"
+                exit 34
+                ;;
+        esac
+    ;;
+    *)
+        echo "ERROR: invalid command"
+        exit 34
+        ;;
+esac
+
+$COMMAND "$SERVICE" "$@"
Index: package_tags/invirt-remote/0.3.14/host/usr/sbin/invirt-vmcontrol
===================================================================
--- package_tags/invirt-remote/0.3.14/host/usr/sbin/invirt-vmcontrol	(revision 2346)
+++ package_tags/invirt-remote/0.3.14/host/usr/sbin/invirt-vmcontrol	(revision 2346)
@@ -0,0 +1,48 @@
+#!/bin/bash
+# invirt-vmcontrol MACHINE ACTION
+#
+# remctl should have already verified that the user is authorized to
+# control the machine.  So, we just need to execute the action requested.
+#
+# $0 and $1 come from the trusted remctl source.
+#
+# $2 and so on are user-provided, and thus sketchy.
+
+ORIGMACHINE="$1"
+ACTION="$2"
+MACHINE="d_$ORIGMACHINE"
+
+case "$ACTION" in
+    list|vcpu-list|uptime)
+        xm "$ACTION" "$MACHINE"
+	;;
+    destroy|shutdown|reboot)
+	xm "$ACTION" "$MACHINE"
+	/usr/sbin/invirt-update-conserver </dev/null >/dev/null 2>&1 &
+	;;
+    install|create)
+	shift; shift;
+	if [ -f "/etc/invirt/nocreate" ]; then
+		echo "Host $HOSTNAME is currently refusing VM creation." && exit 2
+	fi
+	xm list "$MACHINE" >/dev/null 2>/dev/null && echo "$MACHINE already exists" && exit 1
+	if [ "$ACTION" = "install" ]; then
+	    xm create invirt-database machine_name="$ORIGMACHINE" installer_options="$(printf '%q ' "$@")"
+	elif [ -n "$1" ]; then
+	    xm create invirt-database machine_name="$ORIGMACHINE" cdrom_image="$1"
+	else
+	    xm create invirt-database machine_name="$ORIGMACHINE"
+	fi
+	(sleep 4; /usr/sbin/invirt-update-conserver) </dev/null >/dev/null 2>&1 &
+	;;
+    list-long)
+	xm list --long "$MACHINE"
+	;;
+    vnctoken)
+        invirt-vnc-authtoken "$ORIGMACHINE"
+        ;;
+    *)
+        echo "ERROR: Invalid Command"
+        exit 34
+        ;;
+esac
Index: package_tags/invirt-remote/0.3.14/python/remote/__init__.py
===================================================================
--- package_tags/invirt-remote/0.3.14/python/remote/__init__.py	(revision 2346)
+++ package_tags/invirt-remote/0.3.14/python/remote/__init__.py	(revision 2346)
@@ -0,0 +1,1 @@
+from bcast import bcast
Index: package_tags/invirt-remote/0.3.14/python/remote/bcast.py
===================================================================
--- package_tags/invirt-remote/0.3.14/python/remote/bcast.py	(revision 2346)
+++ package_tags/invirt-remote/0.3.14/python/remote/bcast.py	(revision 2346)
@@ -0,0 +1,22 @@
+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, stderr=PIPE))
+             for host in hosts]
+    outputs = dict((s, p.communicate()) for (s, p) in pipes)
+    for (s, p) in pipes:
+        if p.returncode != 0:
+            if outputs[s][1].startswith('remctl: cannot connect to %s' % s):
+                del outputs[s]
+            else:
+                raise RuntimeError("remctl to host %s returned non-zero exit status %d; stderr:\n%s"
+                                   % (s, p.returncode, outputs[s][1]))
+    return [(s, yaml.load(o[0], yaml.CSafeLoader)) for (s, o) in outputs.iteritems()]
Index: package_tags/invirt-remote/0.3.14/server/etc/remctl/acl/web.mako
===================================================================
--- package_tags/invirt-remote/0.3.14/server/etc/remctl/acl/web.mako	(revision 2346)
+++ package_tags/invirt-remote/0.3.14/server/etc/remctl/acl/web.mako	(revision 2346)
@@ -0,0 +1,2 @@
+<% from invirt.config import structs as cfg %>\
+daemon/${cfg.web.hostname}@${cfg.kerberos.realm}\
Index: package_tags/invirt-remote/0.3.14/server/etc/remctl/conf.d/invirt-web
===================================================================
--- package_tags/invirt-remote/0.3.14/server/etc/remctl/conf.d/invirt-web	(revision 2346)
+++ package_tags/invirt-remote/0.3.14/server/etc/remctl/conf.d/invirt-web	(revision 2346)
@@ -0,0 +1,3 @@
+web ALL          /usr/sbin/invirt-remote-proxy-web /etc/remctl/remconffs/adminacl
+control help	 /usr/sbin/invirt-remctl-help	ANYUSER
+help ALL	 /usr/sbin/invirt-remctl-help	ANYUSER
Index: package_tags/invirt-remote/0.3.14/server/etc/remctl/conf.d/remconffs
===================================================================
--- package_tags/invirt-remote/0.3.14/server/etc/remctl/conf.d/remconffs	(revision 2346)
+++ package_tags/invirt-remote/0.3.14/server/etc/remctl/conf.d/remconffs	(revision 2346)
@@ -0,0 +1,1 @@
+include /etc/remctl/remconffs/conf
Index: package_tags/invirt-remote/0.3.14/server/usr/sbin/invirt-remconffs
===================================================================
--- package_tags/invirt-remote/0.3.14/server/usr/sbin/invirt-remconffs	(revision 2346)
+++ package_tags/invirt-remote/0.3.14/server/usr/sbin/invirt-remconffs	(revision 2346)
@@ -0,0 +1,98 @@
+#!/usr/bin/python
+
+import routefs
+from routes import Mapper
+
+from syslog import *
+from time import time
+import sqlalchemy as sa
+
+from invirt import database
+from invirt.config import structs as config
+
+class RemConfFS(routefs.RouteFS):
+    """
+    RemConfFS creates a filesytem for configuring remctl, like this:
+    /
+    |-- adminacl
+    |-- acl
+    |   |-- machine1
+    |   ...
+    |   `-- machinen
+    `-- conf
+    
+    The machine list and the acls are drawn from a database.
+    """
+    
+    def __init__(self, *args, **kw):
+        """Initialize the filesystem and set it to allow_other access besides
+        the user who mounts the filesystem (i.e. root)
+        """
+        super(RemConfFS, self).__init__(*args, **kw)
+        self.fuse_args.add("allow_other", True)
+        
+        openlog('invirt-remconffs ', LOG_PID, LOG_DAEMON)
+        
+        syslog(LOG_DEBUG, 'Init complete.')
+    
+    def make_map(self):
+        m = Mapper()
+        m.connect('', controller='getroot')
+        m.connect('acl', controller='getmachines')
+        m.connect('acl/:machine', controller='getacl')
+        m.connect('adminacl', controller='getadmin')
+        m.connect('conf', controller='getconf')
+        return m
+    
+    def getroot(self, **kw):
+        return ['adminacl', 'acl', 'conf']
+    
+    def getacl(self, machine, **kw):
+        """Build the ACL file for a machine
+        """
+        s = sa.sql.select([database.machine_access_table.c.user], # Field to select from
+                          sa.sql.and_( # where clause
+                database.machine_table.c.machine_id==database.machine_access_table.c.machine_id, # join field
+                database.machine_table.c.name == machine), # filter field
+                          from_obj=[database.machine_access_table, database.machine_table]) # from tables
+        users = [self.userToPrinc(acl[0]) for acl in
+                 database.session.execute(s)]
+        return "\n".join(users
+                 + ['include /etc/remctl/acl/web',
+                    ''])
+    
+    def getconf(self, **kw):
+        """Build the master conf file, with all machines
+        """
+        return '\n'.join("control %s /usr/sbin/invirt-remote-proxy-control"
+                 " /etc/remctl/remconffs/acl/%s"
+                 % (machine_name, machine_name)
+                 for machine_name in self.getmachines())+'\n'
+    
+    def getmachines(self, **kw):
+        """Get the list of VMs in the database. Does not cache to prevent race conditions."""
+        return list(row[0] for row in database.session.execute(sa.sql.select([database.Machine.c.name])))
+
+    def getadmin(self, **kw):
+        """
+        Get the list of administrators for the global ACL.
+        """
+        acl = [self.userToPrinc(row[0]) for row in database.session.execute(sa.sql.select([database.admins_table.c.user]))]
+        acl.append('include /etc/remctl/acl/web\n')
+        return '\n'.join(acl)
+    
+    def userToPrinc(self, user):
+        """Convert Kerberos v4-style names to v5-style and append a default
+        realm if none is specified
+        """
+        if '@' in user:
+            (princ, realm) = user.split('@')
+        else:
+            princ = user
+            realm = config.kerberos.realm
+        
+        return princ.replace('.', '/') + '@' + realm
+
+if __name__ == '__main__':
+    database.connect()
+    routefs.main(RemConfFS)
Index: package_tags/invirt-remote/0.3.14/server/usr/sbin/invirt-remctl-help
===================================================================
--- package_tags/invirt-remote/0.3.14/server/usr/sbin/invirt-remctl-help	(revision 2346)
+++ package_tags/invirt-remote/0.3.14/server/usr/sbin/invirt-remctl-help	(revision 2346)
@@ -0,0 +1,42 @@
+#!/usr/bin/python
+"""
+Help on using the Invirt remctl functions.
+"""
+import sys
+from invirt.config import structs as config
+
+help = [
+    ('list',      'show your VM\'s state (with xm list)'),
+    ('list-host',  'show on what host, if any, your VM is running'),
+    ('list-long', 'show your VM\'s state as an sexp (with xm list --long)'),
+    ('vcpu-list', 'show your VM\'s state (with xm vcpu-list)'),
+    ('uptime',    'show your VM\'s state (with xm uptime)'),
+    ('destroy',   'shut down your VM, hard (with xm destroy)'),
+    ('shutdown',  'shut down your VM, softly if paravm (with xm shutdown)'),
+    ('create',    'start up your VM (with xm create)'),
+    ('reboot',    'reboot your VM (with xm reboot)'),
+    ('install',   'autoinstall your VM (takes a series of key=value pairs; \n\t\tvalid arguments include mirror, dist, arch, imagesize,\n\t\tand noinstall)'),
+    #also CD images on create/reboot
+]
+helpdict = dict(help)
+
+
+def print_help(name, text):
+    print '  %-9s : %s' % (name, text)
+
+def main(args):
+    args = [n for n in args if n in helpdict]
+    print 'remctl %s control <machine> <command>' % config.remote.hostname
+    if args:
+        for name in args:
+            print_help(name, helpdict[name])
+    else:
+        for name, text in help:
+            print_help(name, text)
+        
+    return 0
+
+if __name__ == '__main__':
+    sys.exit(main(sys.argv[1:]))
+
+# vim:et:sw=4:ts=4
Index: package_tags/invirt-remote/0.3.14/server/usr/sbin/invirt-remote-availability
===================================================================
--- package_tags/invirt-remote/0.3.14/server/usr/sbin/invirt-remote-availability	(revision 2346)
+++ package_tags/invirt-remote/0.3.14/server/usr/sbin/invirt-remote-availability	(revision 2346)
@@ -0,0 +1,15 @@
+#!/usr/bin/python
+
+"""
+Retrieve and print out the availability value for all Invirt hosts
+"""
+
+from invirt import remote
+import yaml
+import sys
+
+def main(argv):
+    print yaml.dump(dict(remote.bcast('availability')), default_flow_style=False)
+
+if __name__ == '__main__':
+    sys.exit(main(sys.argv))
Index: package_tags/invirt-remote/0.3.14/server/usr/sbin/invirt-remote-control
===================================================================
--- package_tags/invirt-remote/0.3.14/server/usr/sbin/invirt-remote-control	(revision 2346)
+++ package_tags/invirt-remote/0.3.14/server/usr/sbin/invirt-remote-control	(revision 2346)
@@ -0,0 +1,45 @@
+#!/usr/bin/python
+"""
+Sends remctl commands about a running VM to the host it's running on.
+"""
+
+from subprocess import PIPE, Popen, call
+import sys
+import yaml
+
+def main(argv):
+    if len(argv) < 3:
+        print >>sys.stderr, "usage: invirt-remote-control <machine> <command>"
+        return 2
+    machine_name = argv[1]
+    command = argv[2]
+
+    p = Popen(['/usr/sbin/invirt-remote-proxy-web', 'listvms'], stdout=PIPE)
+    output = p.communicate()[0]
+    if p.returncode != 0:
+        raise RuntimeError("Command '%s' returned non-zero exit status %d"
+                           % ('invirt-remote-proxy-web', p.returncode)) 
+    vms = yaml.load(output, yaml.CSafeLoader)
+
+    if machine_name not in vms:
+        print >>sys.stderr, "machine '%s' is not on" % machine_name
+        return 1
+    host = vms[machine_name]['host']
+
+    p = Popen(['remctl', host, 'remote', 'control'] + argv[1:],
+              stdout=PIPE, stderr=PIPE)
+    (out, err) = p.communicate()
+    if p.returncode == 1:
+        print >>sys.stderr, "machine '%s' is not on" % machine_name
+        return 1
+    elif p.returncode == 34:
+        print >>sys.stderr, "ERROR: invalid command"
+        return 34
+    sys.stderr.write(err)
+    sys.stdout.write(out)
+    return p.returncode
+
+if __name__ == '__main__':
+    sys.exit(main(sys.argv))
+
+# vim:et:sw=4:ts=4
Index: package_tags/invirt-remote/0.3.14/server/usr/sbin/invirt-remote-create
===================================================================
--- package_tags/invirt-remote/0.3.14/server/usr/sbin/invirt-remote-create	(revision 2346)
+++ package_tags/invirt-remote/0.3.14/server/usr/sbin/invirt-remote-create	(revision 2346)
@@ -0,0 +1,86 @@
+#!/usr/bin/python
+
+"""
+Picks a host to "create" (boot) a VM on, and does so.
+
+Current load-balancing algorithm: wherever there's more free RAM.
+
+TODO: use a lock to avoid creating the same VM twice in a race
+"""
+
+from invirt.remote import bcast
+from subprocess import PIPE, Popen, call
+import sys
+import yaml
+import invirt.database
+
+def maxMemory(owner, xmlist):
+    """
+    Return the memory available for a new machine.
+    """
+    machines = invirt.database.Machine.query().filter_by(owner=owner)
+    (quota_total, quota_single) = invirt.database.Owner.getMemoryQuotas(owner)
+
+    active_machines = [m for m in machines if m.name in xmlist]
+    mem_usage = sum([x.memory for x in active_machines])
+    return min(quota_single, quota_total - mem_usage)
+
+def choose_host():
+    # Query each of the hosts.
+    results = bcast('availability')
+    return max((int(o), s) for (s, o) in results)[1]
+
+def main(argv):
+    if len(argv) < 3:
+        print >> sys.stderr, "usage: invirt-remote-create <operation> <machine> [<other args...>]"
+        return 2
+    operation = argv[1]
+    machine_name = argv[2]
+    args = argv[3:]
+
+    invirt.database.connect()
+
+    if operation == 'install':
+        options = dict(arg.split('=', 1) for arg in args)
+        valid_keys = set(('mirror', 'dist', 'arch', 'imagesize', 'noinstall'))
+        if not set(options.keys()).issubset(valid_keys):
+            print >> sys.stderr, "Invalid argument. Use the help command to see valid arguments to install"
+            return 1
+        if any(' ' in val for val in options.values()):
+            print >> sys.stderr, "Arguments to the autoinstaller cannot contain spaces"
+            return 1
+
+    p = Popen(['/usr/sbin/invirt-remote-proxy-web', 'listvms'], stdout=PIPE)
+    output = p.communicate()[0]
+    if p.returncode != 0:
+        raise RuntimeError("Command '%s' returned non-zero exit status %d"
+                           % ('invirt-remote-proxy-web', p.returncode)) 
+    vms = yaml.load(output, yaml.CSafeLoader)
+
+    if machine_name in vms:
+        host = vms[machine_name]['host']
+        print >> sys.stderr, ("machine '%s' is already running on host %s"
+                              % (machine_name, host))
+        return 1
+
+    if operation == "create":
+        machine = invirt.database.Machine.query().filter_by(name=machine_name).first()
+
+        owner = machine.owner
+        vm_memory = machine.memory
+
+        max_memory = maxMemory(owner, vms.keys())
+        if vm_memory > max_memory:
+            print >>sys.stderr, "owner %s requested %d MiB of memory for vm %s; %d MiB allowed" % (owner, vm_memory, machine_name, max_memory)
+            return 1
+
+    host = choose_host()
+    print 'Creating on host %s...' % host
+    sys.stdout.flush()
+    return call(['remctl', host, 'remote', 'control',
+                 machine_name, operation] + args)
+
+if __name__ == '__main__':
+    sys.exit(main(sys.argv))
+
+# vim:et:sw=4:ts=4
Index: package_tags/invirt-remote/0.3.14/server/usr/sbin/invirt-remote-listhost
===================================================================
--- package_tags/invirt-remote/0.3.14/server/usr/sbin/invirt-remote-listhost	(revision 2346)
+++ package_tags/invirt-remote/0.3.14/server/usr/sbin/invirt-remote-listhost	(revision 2346)
@@ -0,0 +1,33 @@
+#!/usr/bin/python
+"""
+Say what host a running VM is on.
+"""
+
+from subprocess import PIPE, Popen, call
+import sys
+import yaml
+
+def main(argv):
+    if len(argv) < 2:
+        print >>sys.stderr, "usage: invirt-remote-listhost <machine>"
+        return 2
+    machine_name = argv[1]
+
+    p = Popen(['/usr/sbin/invirt-remote-proxy-web', 'listvms'], stdout=PIPE)
+    output = p.communicate()[0]
+    if p.returncode != 0:
+        raise RuntimeError("Command '%s' returned non-zero exit status %d"
+                           % ('invirt-remote-proxy-web', p.returncode)) 
+    vms = yaml.load(output, yaml.CSafeLoader)
+
+    if machine_name not in vms:
+        print >>sys.stderr, "machine '%s' is not on" % machine_name
+        return 2
+
+    print vms[machine_name]['host']
+    return 0
+
+if __name__ == '__main__':
+    sys.exit(main(sys.argv))
+
+# vim:et:sw=4:ts=4
Index: package_tags/invirt-remote/0.3.14/server/usr/sbin/invirt-remote-listvms
===================================================================
--- package_tags/invirt-remote/0.3.14/server/usr/sbin/invirt-remote-listvms	(revision 2346)
+++ package_tags/invirt-remote/0.3.14/server/usr/sbin/invirt-remote-listvms	(revision 2346)
@@ -0,0 +1,28 @@
+#!/usr/bin/python
+
+"""
+Collates the results of listvms from multiple VM servers.  Part of the xvm
+suite.
+"""
+
+from invirt.remote import bcast
+import sys
+import yaml
+
+def main(argv):
+    # Query each of the hosts.
+    results = filter(lambda (_, x): x is not None, bcast('listvms'))
+
+    # 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__':
+    sys.exit(main(sys.argv))
+
+# vim:et:sw=4:ts=4
Index: package_tags/invirt-remote/0.3.14/server/usr/sbin/invirt-remote-listvmsd
===================================================================
--- package_tags/invirt-remote/0.3.14/server/usr/sbin/invirt-remote-listvmsd	(revision 2346)
+++ package_tags/invirt-remote/0.3.14/server/usr/sbin/invirt-remote-listvmsd	(revision 2346)
@@ -0,0 +1,71 @@
+#!/usr/bin/perl
+
+# NOTE: In development; not actually used yet.
+
+#Collates the results of listvms from multiple VM servers.  Part of the xvm
+#suite.
+
+use Net::Remctl ();
+use JSON;
+
+our @servers = qw/black-mesa.mit.edu sx-blade-2.mit.edu/;
+
+our %connections;
+
+sub openConnections() {
+    foreach (@servers) { openConnection($_); }
+}
+
+sub openConnection($) {
+    my ($server) = @_;
+    my $remctl = Net::Remctl->new;
+    $remctl->open($server)
+        or die "Cannot connect to $server: ", $remctl->error, "\n";
+    $connections{$server} = $remctl;
+}
+
+sub doListVMs() {
+    foreach my $remctl (values %connections) {
+	$remctl->command("remote", "web", "listvms", "--json");
+    }
+    my %vmstate;
+    foreach my $server (keys %connections) {
+	my $remctl = $connections{$server};
+	my $jsonData = '';
+	do {
+	    $output = $remctl->output;
+	    if ($output->type eq 'output') {
+		if ($output->stream == 1) {
+		    $jsonData .= $output->data;
+		} elsif ($output->stream == 2) {
+		    print STDERR $output->data;
+		}
+	    } elsif ($output->type eq 'error') {
+		warn $output->error, "\n";
+	    } elsif ($output->type eq 'status') {
+		if ($output->status != 0) {
+		    warn "Exit status was ".$output->status;
+		}
+	    } elsif ($output->type eq 'done') {
+		#next;
+	    } else {
+		die "Unknown output token from library: ", $output->type, "\n";
+	    }
+	} while ($output->type ne 'done');
+	my $vmlist = jsonToObj($jsonData);
+	foreach my $key (keys %$vmlist) {
+	    $vmstate{$key} = $vmlist->{$key};
+	    $vmstate{$key}{"host"} = $server;
+	}
+    }
+    return %vmstate;
+}
+
+openConnections();
+
+use Data::Dumper;
+use Benchmark;
+print Dumper({doListVMs()});
+timethis(100, sub {doListVMs()});
+
+# vim:et:sw=4:ts=4
Index: package_tags/invirt-remote/0.3.14/server/usr/sbin/invirt-remote-proxy
===================================================================
--- package_tags/invirt-remote/0.3.14/server/usr/sbin/invirt-remote-proxy	(revision 2346)
+++ package_tags/invirt-remote/0.3.14/server/usr/sbin/invirt-remote-proxy	(revision 2346)
@@ -0,0 +1,44 @@
+#!/bin/bash
+# invoke as invirt-remote-proxy-$TYPE, with "TYPE" in the remctl sense.
+
+klist -s || kinit -k
+
+TYPE="${0##*-}"
+case "$TYPE" in
+    control )
+	MACHINE="$1"; SERVICE="$2"; shift; shift ;;
+    * )
+	SERVICE="$1"; shift ;;
+esac
+
+case "$TYPE/$SERVICE" in
+    web/listvms )
+	invirt-remote-listvms "$@" ;;
+    web/vnccert )
+        invirt-remote-vnccert "$@" ;;
+    web/availability | web/avail )
+        invirt-remote-availability "$@" ;;
+    web/lvcreate | web/lvremove | web/lvrename | web/lvresize )
+        if [ -f "/etc/invirt/nolvm" ]; then
+            echo "LVM operations are temporarily disabled for maintenance, sorry." >&2
+            exit 2
+        fi
+        remctl "$(invirt-getconf hosts.0.hostname)" remote "$TYPE" "$SERVICE" "$@" ;;
+    control/help )
+        invirt-remctl-help ;;
+    control/create|control/install )
+        if [ -f "/etc/invirt/nocreate" ]; then
+            echo "Booting VMs is temporarily disabled for maintenance, sorry." >&2
+            exit 2
+        fi
+	invirt-remote-create "$SERVICE" "$MACHINE" "$@" ;;
+    control/listhost|control/list-host )
+	invirt-remote-listhost "$MACHINE" "$@" ;;
+    control/* )
+	# Everything but create must go where the VM is already running.
+	invirt-remote-control "$MACHINE" "$SERVICE" "$@" ;;
+    * )
+        echo "ERROR: invalid subcommand"
+        exit 34
+        ;;
+esac
Index: package_tags/invirt-remote/0.3.14/server/usr/sbin/invirt-remote-proxy-control
===================================================================
--- package_tags/invirt-remote/0.3.14/server/usr/sbin/invirt-remote-proxy-control	(revision 2346)
+++ package_tags/invirt-remote/0.3.14/server/usr/sbin/invirt-remote-proxy-control	(revision 2346)
@@ -0,0 +1,1 @@
+link invirt-remote-proxy
Index: package_tags/invirt-remote/0.3.14/server/usr/sbin/invirt-remote-proxy-web
===================================================================
--- package_tags/invirt-remote/0.3.14/server/usr/sbin/invirt-remote-proxy-web	(revision 2346)
+++ package_tags/invirt-remote/0.3.14/server/usr/sbin/invirt-remote-proxy-web	(revision 2346)
@@ -0,0 +1,1 @@
+link invirt-remote-proxy
Index: package_tags/invirt-remote/0.3.14/server/usr/sbin/invirt-remote-vnccert
===================================================================
--- package_tags/invirt-remote/0.3.14/server/usr/sbin/invirt-remote-vnccert	(revision 2346)
+++ package_tags/invirt-remote/0.3.14/server/usr/sbin/invirt-remote-vnccert	(revision 2346)
@@ -0,0 +1,26 @@
+#!/usr/bin/python
+
+"""
+Retrieves the VNC certificate from an Invirt host
+"""
+
+from invirt.config import structs as config
+from subprocess import Popen, call, PIPE
+import sys
+
+
+def main(argv):
+    if len(argv) < 2:
+        print >> sys.stderr, "usage: invirt-remote-vnccert <host>"
+        return 2
+    
+    host = argv[1]
+    
+    if host not in list(i.hostname for i in config.hosts):
+        print >> sys.stderr, "Invalid hostname specified"
+        return 1
+    
+    return call(['remctl', host, 'remote', 'web', 'vnccert'])
+
+if __name__ == '__main__':
+    sys.exit(main(sys.argv))
Index: package_tags/invirt-remote/0.3.14/setup.py
===================================================================
--- package_tags/invirt-remote/0.3.14/setup.py	(revision 2346)
+++ package_tags/invirt-remote/0.3.14/setup.py	(revision 2346)
@@ -0,0 +1,23 @@
+#!/usr/bin/python
+
+from os import path
+from debian_bundle.changelog import Changelog
+from debian_bundle.deb822 import Deb822
+from email.utils import parseaddr
+from setuptools import setup
+
+version = Changelog(open(path.join(path.dirname(__file__), 'debian/changelog')).read()).\
+    get_version().full_version
+
+maintainer_full = Deb822(open(path.join(path.dirname(__file__), 'debian/control')))['Maintainer']
+maintainer, maintainer_email = parseaddr(maintainer_full)
+
+setup(
+    name='invirt.remote',
+    version=version,
+    maintainer=maintainer,
+    maintainer_email=maintainer_email,
+    
+    packages = ['invirt.remote'],
+    package_dir = {'invirt': 'python'}
+)
