Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
executable file 241 lines (217 sloc) 5.17 KB
#!/bin/bash
#set -ex
# Let's go to our directory. VMs and images are stored relative to here.
cd "$(dirname $(readlink --canonicalize "$0"))"
info () {
>/dev/stderr echo "INFO: $*"
}
warn () {
>/dev/stderr echo "WARNING: $*"
}
err () {
>/dev/stderr echo "ERROR: $*"
}
die () {
err "$*"
exit 1
}
len () {
echo $#
}
# Check for dependencies.
for DEP in qemu-system-x86_64 qemu-img vde_switch cloud-localds tmux socat; do
if ! command -v $DEP >/dev/null; then
err "Dependency $DEP not found. Please install it and try again."
err "You can see the list of dependencies (and the corresponding packages"
err "for some Linux distros) on this page:"
err "https://github.com/jpetazzo/littleboxes"
die ""
fi
done
_help="$(basename "$0") - a tool to manipulate little boxes"
_cmd () {
COMMAND=$1
shift
ARGS=""
while [ $# -gt 1 ]; do
ARGS="$ARGS $1"
shift
done
eval _args_$COMMAND=\"$ARGS\"
HELP=$1
_help=$(printf "%s\n%-10s\t%s" "$_help" "$COMMAND" "$HELP")
}
_cmd_ () {
echo "$_help"
}
_cmd attach VM "Attach to the console of a running VM"
_cmd_attach () {
if [ $(_cmd_state "$VM") != running ]; then
die "VM $VM doesn't seem to be running."
fi
info "Press ENTER to attach to console of VM $1."
info "The default login and password is 'ubuntu'."
info "Once attached, press 'Ctrl-B D' to detach."
read
tmux attach-session -t "$VM"
}
_cmd pull IMAGE "Pull a VM image"
_cmd_pull () {
if [ -d images/$IMAGE ]; then
die "Image $IMAGE already exists. Refusing to overwrite it."
fi
mkdir images/$IMAGE
wget https://cloud-images.ubuntu.com/$IMAGE/current/$IMAGE-server-cloudimg-amd64-disk1.img -O images/$IMAGE/hda
}
_cmd create IMAGE VM "Create a VM from an image"
_cmd_create () {
if [ ! -d images/$IMAGE ]; then
die "Image $IMAGE doesn't exist."
fi
if [ -d vms/$VM ]; then
die "VM $VM already exists."
fi
mkdir vms/$VM
qemu-img create -f qcow2 -b $PWD/images/$IMAGE/hda vms/$VM/hda
cloud-localds --disk-format qcow2 --hostname $VM vms/$VM/hdb cloud-init
_cmd_config $VM
}
_cmd config VM "(Re)configure a VM"
_cmd_config () {
if [ ! -d vms/$VM ]; then
die "VM $VM doesn't exist."
fi
THREEBYTES="$(($RANDOM%256)) $(($RANDOM%256)) $(($RANDOM%256))"
echo $THREEBYTES >vms/$VM/threebytes
MAC=$(printf "52:54:00:%02x:%02x:%02x" $THREEBYTES)
LOOPBACK=127.$(echo $THREEBYTES | tr " " ".")
cat >vms/$VM/run.sh <<EOF
extra=,hostfwd=tcp:$LOOPBACK:22222-:22
qemu-system-x86_64 -m 1024 -enable-kvm \
-nographic \
-pidfile vms/$VM/pid \
-hda vms/$VM/hda -hdb vms/$VM/hdb \
-device e1000,netdev=n01 \
-netdev user,id=n01\$extra \
-device e1000,netdev=n02,mac=$MAC \
-netdev vde,id=n02
rm vms/$VM/pid
EOF
}
_cmd rmv VM "Remove a VM"
_cmd_rmv () {
STATE=$(_cmd_state "$VM")
if [ "$STATE" != stopped ]; then
die "I can only remove a VM if it is stopped. Current state is '$STATE'."
fi
rm -rf vms/$VM
}
_cmd ssh VM "SSH into a VM"
_cmd_ssh () {
STATE=$(_cmd_state "$VM")
if [ "$STATE" != running ]; then
die "The VM doesn't seem to be running."
fi
ssh \
-o UserKnownHostsFile=/dev/null \
-o StrictHostKeyChecking=no \
-l ubuntu -p 22222 \
127.$(tr " " "." < vms/$VM/threebytes)
}
_cmd sshproxy VM "Connect to the SSH port of a VM"
_cmd_sshproxy () {
VM=$(cut -d. -f1 <<<$VM)
STATE=$(_cmd_state "$VM")
if [ "$STATE" != running ]; then
die "The VM doesn't seem to be running."
fi
socat - TCP-CONNECT:127.$(tr " " "." < vms/$VM/threebytes):22222
}
_cmd start VM "Start a VM"
_cmd_start () {
STATE=$(_cmd_state "$VM")
case "$STATE" in
running)
die "The VM seems to be already running."
;;
stopped)
_cmd_vde
tmux new-session -d -s "$VM" "sh vms/$VM/run.sh"
info "VM $VM started."
;;
*)
die "The VM is in an unexpected state: $STATE."
;;
esac
}
_cmd state VM "Check status of a VM"
_cmd_state () {
if [ ! -d "vms/$VM" ]; then
die "VM $VM doesn't exist."
fi
if [ -f vms/$VM/pid ]; then
PID=$(cat vms/$VM/pid)
if [ -d /proc/$PID ]; then
echo running
else
warn "PID file exists, but process $PID doesn't exist. Removing stale PID file."
rm vms/$VM/pid
echo stopped
fi
else
echo stopped
fi
}
_cmd stop VM "Stop a VM"
_cmd_stop () {
STATE=$(_cmd_state "$VM")
if [ "$STATE" != running ]; then
die "VM $VM doesn't seem to be running. I cannot stop it."
fi
PID=$(cat vms/$VM/pid)
kill $PID
info "Sent signal to stop VM."
}
_cmd lsi "List images"
_cmd_lsi () {
for DIR in images/*; do
if [ -d "$DIR" ]; then
IMAGE=$(basename $DIR)
SIZE=$(du -sh $DIR | cut -f1)
echo "$IMAGE ($SIZE)"
fi
done
}
_cmd lsv "List VMs"
_cmd_lsv () {
for DIR in vms/*; do
if [ -d "$DIR" ]; then
VM=$(basename $DIR)
SIZE=$(du -sh $DIR | cut -f1)
STATUS=$(_cmd_state "$VM")
echo "$VM ($SIZE, $STATUS)"
fi
done
}
_cmd vde "Make sure that VDE is running"
_cmd_vde () {
if [ ! -S /tmp/vde.ctl/ctl ]; then
vde_switch -d
fi
}
cmd=$1
shift
fun=_cmd_$cmd
eval args=\$_args_$cmd
for arg in $args; do
if [ "$1" = "" ]; then
if [ $(len $args) = 1 ]; then
die "Command $cmd is expecting one argument:$args. It seems to be missing."
else
die "Command $cmd is expecting the following arguments:$args. $arg seems to be missing."
fi
fi
eval $arg=$1
shift
done
$fun "$@"