Merge invirt-remote-host and invirt-remote-server into invirt-remote 0.2.0
authorEvan Broder <broder@mit.edu>
Sun, 7 Dec 2008 23:53:01 +0000 (18:53 -0500)
committerEvan Broder <broder@mit.edu>
Sun, 7 Dec 2008 23:53:01 +0000 (18:53 -0500)
svn path=/trunk/packages/invirt-remote/; revision=1822

25 files changed:
debian/changelog
debian/control
debian/invirt-remote-host.init [new file with mode: 0755]
debian/invirt-remote-host.install [new file with mode: 0644]
debian/invirt-remote-server.install
host/etc/remctl/acl/remote.mako [new file with mode: 0644]
host/etc/remctl/conf.d/invirt-remote-host [new file with mode: 0644]
host/usr/sbin/invirt-listvms [new file with mode: 0755]
host/usr/sbin/invirt-lvm [new file with mode: 0755]
host/usr/sbin/invirt-remote [new file with mode: 0755]
host/usr/sbin/invirt-vmcontrol [new file with mode: 0755]
server/etc/remctl/acl/web.mako [moved from files/etc/remctl/acl/web.mako with 100% similarity]
server/etc/remctl/conf.d/invirt-web [moved from files/etc/remctl/conf.d/invirt-web with 100% similarity]
server/etc/remctl/conf.d/remconffs [moved from files/etc/remctl/conf.d/remconffs with 100% similarity]
server/usr/sbin/invirt-remconffs [moved from files/usr/sbin/invirt-remconffs with 100% similarity]
server/usr/sbin/invirt-remctl-help [moved from files/usr/sbin/invirt-remctl-help with 100% similarity]
server/usr/sbin/invirt-remote-control [moved from files/usr/sbin/invirt-remote-control with 100% similarity]
server/usr/sbin/invirt-remote-create [moved from files/usr/sbin/invirt-remote-create with 100% similarity]
server/usr/sbin/invirt-remote-listhost [moved from files/usr/sbin/invirt-remote-listhost with 100% similarity]
server/usr/sbin/invirt-remote-listvms [moved from files/usr/sbin/invirt-remote-listvms with 100% similarity]
server/usr/sbin/invirt-remote-listvmsd [moved from files/usr/sbin/invirt-remote-listvmsd with 100% similarity]
server/usr/sbin/invirt-remote-proxy [moved from files/usr/sbin/invirt-remote-proxy with 100% similarity]
server/usr/sbin/invirt-remote-proxy-control [moved from files/usr/sbin/invirt-remote-proxy-control with 100% similarity]
server/usr/sbin/invirt-remote-proxy-web [moved from files/usr/sbin/invirt-remote-proxy-web with 100% similarity]
server/usr/sbin/invirt-remote-vnccert [moved from files/usr/sbin/invirt-remote-vnccert with 100% similarity]

index 0f33741..d0502bc 100644 (file)
@@ -1,3 +1,10 @@
+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
index 51de82e..50e6222 100644 (file)
@@ -1,4 +1,4 @@
-Source: invirt-remote-server
+Source: invirt-remote
 Section: servers
 Priority: important
 Maintainer: Invirt project <invirt@mit.edu>
@@ -18,3 +18,11 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${python:Depends},
 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
+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
diff --git a/debian/invirt-remote-host.init b/debian/invirt-remote-host.init
new file mode 100755 (executable)
index 0000000..d3c3849
--- /dev/null
@@ -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
diff --git a/debian/invirt-remote-host.install b/debian/invirt-remote-host.install
new file mode 100644 (file)
index 0000000..260c50b
--- /dev/null
@@ -0,0 +1 @@
+host/* .
diff --git a/host/etc/remctl/acl/remote.mako b/host/etc/remctl/acl/remote.mako
new file mode 100644 (file)
index 0000000..8a223ff
--- /dev/null
@@ -0,0 +1,2 @@
+<% from invirt.config import structs as cfg %>\
+host/${cfg.remote.hostname}@${cfg.authn[0].realm}
diff --git a/host/etc/remctl/conf.d/invirt-remote-host b/host/etc/remctl/conf.d/invirt-remote-host
new file mode 100644 (file)
index 0000000..b62acac
--- /dev/null
@@ -0,0 +1,2 @@
+remote web     /usr/sbin/invirt-remote /etc/remctl/acl/remote
+remote control /usr/sbin/invirt-remote /etc/remctl/acl/remote
diff --git a/host/usr/sbin/invirt-listvms b/host/usr/sbin/invirt-listvms
new file mode 100755 (executable)
index 0000000..890931a
--- /dev/null
@@ -0,0 +1,48 @@
+#!/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.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']
+    
+    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)
diff --git a/host/usr/sbin/invirt-lvm b/host/usr/sbin/invirt-lvm
new file mode 100755 (executable)
index 0000000..6367216
--- /dev/null
@@ -0,0 +1,89 @@
+#!/usr/bin/env python
+
+import sys
+import os.path
+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)
+    # I know this is the wrong answer, but sometimes the first
+    # lvchange -a n fails for no particularly good reason, so this is
+    # a pretty good workaround
+    call(["/sbin/lvchange", "-a", "n", lvpath])
+    rv = call(["/sbin/lvchange", "-a", "n", lvpath])
+    if rv != 0:
+        error()
+    rv = call(["/sbin/lvchange", "-a", "ey", lvpath])
+    if rv != 0:
+        error()
+    rv = call(["/sbin/lvremove", "--force", lvpath])
+    if rv != 0:
+        error()
+    ensureoff(machine)
+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)
+    
+
diff --git a/host/usr/sbin/invirt-remote b/host/usr/sbin/invirt-remote
new file mode 100755 (executable)
index 0000000..8511f60
--- /dev/null
@@ -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
+               ;;
+           info)
+               COMMAND=/usr/sbin/xm
+               ;;
+            vnccert)
+                COMMAND=/usr/bin/invirt-vnc-getcert
+                ;;
+            *)
+                echo "ERROR: invalid subcommand"
+                exit 34
+                ;;
+        esac
+       ;;
+    *)
+        echo "ERROR: invalid command"
+        exit 34
+        ;;
+esac
+
+$COMMAND "$SERVICE" "$@"
diff --git a/host/usr/sbin/invirt-vmcontrol b/host/usr/sbin/invirt-vmcontrol
new file mode 100755 (executable)
index 0000000..70bff12
--- /dev/null
@@ -0,0 +1,45 @@
+#!/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;
+       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