aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--README32
-rw-r--r--TODO18
-rwxr-xr-xdi-maker30
-rwxr-xr-xkvm-creator75
-rwxr-xr-xkvm-manager81
6 files changed, 237 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b25c15b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+*~
diff --git a/README b/README
new file mode 100644
index 0000000..b7b416e
--- /dev/null
+++ b/README
@@ -0,0 +1,32 @@
+KVM-Manager
+
+Author: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+Date: 2009-10-08 11:22:14-0400
+
+This is a small set of scripts to make it relatively easy to manage a
+stable of kvm instances in a fairly secure and isolated fashion.
+
+The basic model is to use runit to supervise each KVM instance, with a
+single, non-privileged user account for each instance.
+
+A typical workflow to start an installer is:
+
+kvm-creator create $GUESTNAME [$DISKSIZE [$RAM [$TAP [$MAC] ] ] ]
+# set up boot media for the host ("put the installer CD in the drive"):
+ln -s /usr/local/share/ISOs/d-i.iso /home/$GUESTNAME/vms/$GUESTNAME/cd.iso
+# set up access to the account:
+mkdir -p /home/$GUESTNAME/.ssh
+cat ~/.ssh/authorized_keys >> /home/$GUESTNAME/.ssh/authorized_keys
+# start up the host
+update-service --add /etc/sv/kvm/$GUESTNAME
+
+
+To access the guest's serial console, do:
+
+ ssh -t $GUESTNAME@host.machine screen -x $GUESTNAME
+
+
+trouble getting a serial console-enabled debian
+installer ISO? try using the di-maker script.
+
+All patches, fixes, suggestions welcome!
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..3601eaf
--- /dev/null
+++ b/TODO
@@ -0,0 +1,18 @@
+TODO for KVM-Manager
+--------------------
+
+(much) better documentation
+
+file re-organization/restructuring
+
+debian packaging?
+
+more flexibility with networking (currently only supports
+ tun/tap-style bridging)
+
+/usr/local/sbin is hard-coded in places (e.g. in the run and finish
+ scripts); it probably shouldn't be.
+
+screen logging is still sub-par, and could potentially fill the host
+ disks if the kernel spew is immense -- rotate? filter through
+ svlogd somehow? same problem as cereal.
diff --git a/di-maker b/di-maker
new file mode 100755
index 0000000..d6ad5f3
--- /dev/null
+++ b/di-maker
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+# Author: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+# Date: 2009-10-08
+# License: GPL v3+
+
+set -e
+
+# depends on grub2 -- should probably be refactored to use
+# grub-mkrescue
+
+WORKDIR=$(mktemp -d)
+
+( cd "$WORKDIR" && wget http://ftp.nl.debian.org/debian/dists/lenny/main/installer-amd64/current/images/netboot/debian-installer/amd64/{linux,initrd.gz} )
+
+mkdir -p "$WORKDIR/boot/grub"
+
+cp /usr/lib/grub/x86_64-pc/stage2_eltorito "$WORKDIR/boot/grub/"
+cat > "$WORKDIR/boot/grub/menu.lst" <<EOF
+serial --unit=0 --speed=115200 --word=8 --parity=no --stop=1
+terminal serial
+
+title lenny d-i (created $(date -R))
+kernel /linux -- console=ttyS0,115200n8
+initrd /initrd.gz
+EOF
+
+genisoimage -R -input-charset utf-8 -b boot/grub/stage2_eltorito -no-emul-boot --boot-load-size 4 -boot-info-table "$WORKDIR"
+
+rm -rf "$WORKDIR"
diff --git a/kvm-creator b/kvm-creator
new file mode 100755
index 0000000..6ea989f
--- /dev/null
+++ b/kvm-creator
@@ -0,0 +1,75 @@
+#!/bin/bash
+set -x
+
+# Author: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+# Date: 2009-10-08
+# License: GPL v3+
+
+CMD="$1"
+shift
+
+NAME="$1"
+SIZE="${2:-3G}"
+RAM="${3:-512}"
+TAP="${4:-$(( $( cat /etc/sv/kvm/*/env/TAP | sed 's/^tap//' | sort -n | tail -n 1 ) + 1 ))}"
+MAC="${5:-$(cat /etc/sv/kvm/*/env/MAC | head -n1 | cut -f 1-5 -d: ):$(( $( cat /etc/sv/kvm/*/env/MAC | cut -f 6 -d: | sort -n | tail -n 1 ) + 1 ))}"
+
+VG=vg_malty0
+
+destroy() {
+
+ update-service --remove "/etc/sv/kvm/$NAME"
+ rm -rf "/etc/sv/kvm/$NAME"
+ deluser "$NAME"
+ lvremove "$VG/$NAME"
+ rm -rf "/home/$NAME"
+
+}
+
+create() {
+ set -e
+
+# FIXME: check that this stuff doesn't exist yet:
+
+ adduser "$NAME" --disabled-password --gecos "$NAME KVM user,,,"
+ mkdir "/home/$NAME/"{.ssh,vms,"vms/$NAME"}
+ touch "/home/$NAME/vms/$NAME/netboot"
+ chown "$NAME:$NAME" "/home/$NAME/"{.ssh,vms,"vms/$NAME","vms/$NAME/netboot"}
+ cp /root/.ssh/authorized_keys "/home/$NAME/.ssh/"
+ lvcreate --name "$NAME" --size "$SIZE" $VG
+ mkdir "/etc/sv/kvm/$NAME"{,/log,/env}
+ cat > "/etc/sv/kvm/$NAME/log/run" <<EOF
+#!/bin/sh
+
+exec 2>&1
+exec chpst -e ../env /usr/local/sbin/kvm-manager log
+EOF
+ cat > "/etc/sv/kvm/$NAME/run" <<EOF
+#!/bin/sh
+
+exec 2>&1
+exec chpst -e ./env /usr/local/sbin/kvm-manager up
+EOF
+ cat > "/etc/sv/kvm/$NAME/finish" <<EOF
+#!/bin/sh
+
+exec 2>&1
+exec chpst -e ./env /usr/local/sbin/kvm-manager down
+EOF
+ chmod a+x "/etc/sv/kvm/$NAME/"{run,finish,log/run}
+ echo "$NAME" > "/etc/sv/kvm/$NAME/env/OWNER"
+ echo "$NAME" > "/etc/sv/kvm/$NAME/env/VMNAME"
+ echo "$TAP" > "/etc/sv/kvm/$NAME/env/TAP"
+ echo "$RAM" > "/etc/sv/kvm/$NAME/env/RAM"
+ echo "$MAC" > "/etc/sv/kvm/$NAME/env/MAC"
+
+}
+
+demo() {
+
+ for foo in NAME TAP RAM MAC SIZE ; do
+ echo "$foo : ${!foo}"
+ done
+}
+
+"$CMD"
diff --git a/kvm-manager b/kvm-manager
new file mode 100755
index 0000000..40972ce
--- /dev/null
+++ b/kvm-manager
@@ -0,0 +1,81 @@
+#!/bin/sh
+
+set -e
+set -x
+
+# Author: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+# Date: 2009-10-08
+# License: GPL v3+
+
+## expect to pull these values from the environment:
+# VMNAME=snapper
+# OWNER=jrollins
+# TAP=tap0
+# RAM=512
+# MAC=52:54:00:12:34:56
+
+if [ -z "$VMNAME" ] ; then
+ exit 1
+fi
+
+###################
+OWNERGROUP=$(groups "$OWNER" | cut -f1 -d\ )
+OWNERHOME=$(getent passwd "$OWNER" | cut -f6 -d: )
+
+VGNAME=vg_$(hostname)0
+
+up() {
+# bring up the network tap:
+ modprobe -v tun
+ tunctl -u "$OWNER" -t "$TAP"
+ ip link set "$TAP" up
+ brctl addif br0 "$TAP"
+
+# make sure the block device is readable by the owner:
+ chgrp "$OWNERGROUP" "/dev/mapper/${VGNAME}-$VMNAME"
+
+ chpst -u "$OWNER:$OWNERGROUP" mkdir -p "$OWNERHOME/vms/$VMNAME"
+
+ CDISO="$OWNERHOME/vms/$VMNAME/cd.iso"
+ NETBOOT="$OWNERHOME/vms/$VMNAME/netboot"
+ KVMARGS=
+
+ if [ -e "$NETBOOT" ] ; then
+ KVMARGS="-boot n"
+ elif [ -e "$CDISO" ] && [ -e $(readlink -f "$CDISO") ] ; then
+ KVMARGS="-cdrom $CDISO -boot d"
+ fi
+
+ LOGNAME="$OWNERHOME/vms/$VMNAME/console"
+ ln -sfT "$LOGNAME" ./servicelog
+ if [ -e "$LOGNAME" ] ; then
+ chpst -u "$OWNER" mv "$LOGNAME" "$LOGNAME".$(date +%F_%T%z|tr : .)
+ fi
+
+ exec chpst -u "$OWNER:$OWNERGROUP:kvm" /usr/bin/screen -D -m -L -c /etc/screenrc.kvm-manager -S "$VMNAME" -t "$VMNAME" -s /bin/false /usr/bin/kvm $KVMARGS -nographic -name "$VMNAME" -m "$RAM" -net nic,"macaddr=$MAC" -net "tap,hostname=$VMNAME,ifname=$TAP,script=no,downscript=no" -no-reboot -serial stdio "/dev/mapper/${VGNAME}-$VMNAME"
+}
+
+
+down() {
+ brctl delif br0 "$TAP"
+ ip link set "$TAP" down
+ tunctl -d "$TAP"
+# no need to lock up the block device as well, since the owner might
+# prefer to manipulate the disk directly.
+}
+
+log() {
+ LOGDIR="$OWNERHOME/vms/$VMNAME/servicelog"
+ chpst -u "$OWNER" mkdir -p "$LOGDIR"
+ exec chpst -u "$OWNER" svlogd -tt "$LOGDIR"
+}
+
+case "$1" in
+ up|down|log)
+ "$1"
+ ;;
+ *)
+ echo "Usage: $0 [up|down]"
+ exit 1
+ ;;
+esac