From 9f76ba28ae735037d1126f8ee55c7da81f423071 Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Thu, 8 Oct 2009 11:37:42 -0400 Subject: initial scattered import --- .gitignore | 1 + README | 32 ++++++++++++++++++++++++ TODO | 18 ++++++++++++++ di-maker | 30 +++++++++++++++++++++++ kvm-creator | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ kvm-manager | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 237 insertions(+) create mode 100644 .gitignore create mode 100644 README create mode 100644 TODO create mode 100755 di-maker create mode 100755 kvm-creator create mode 100755 kvm-manager 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 +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 +# 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" < +# 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" <&1 +exec chpst -e ../env /usr/local/sbin/kvm-manager log +EOF + cat > "/etc/sv/kvm/$NAME/run" <&1 +exec chpst -e ./env /usr/local/sbin/kvm-manager up +EOF + cat > "/etc/sv/kvm/$NAME/finish" <&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 +# 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 -- cgit v1.2.3