#!/usr/bin/env sh VM_NAME=boot2docker-vm VBM=VBoxManage DOCKER_PORT=4243 SSH_HOST_PORT=2022 VM_DISK=./boot2docker.vmdk VM_DISK_SIZE=40000 VM_MEM=1024 BOOT2DOCKER_ISO=./boot2docker.iso test -f $HOME/.boot2docker/profile && . $HOME/.boot2docker/profile get_latest_release_name() { local LRN LRN=$(curl 'https://api.github.com/repos/steeve/boot2docker/releases' 2>/dev/null|grep -o -m 1 -e "\"tag_name\":[[:space:]]*\"[a-z0-9.]*\""|head -1|cut -d: -f2|tr -d ' "') if [ -z "$LRN" ]; then echo "ERROR" else echo "$LRN" fi } download_latest() { LATEST_RELEASE=$(get_latest_release_name) if [ ! "$LATEST_RELEASE" = "ERROR" ]; then log "Latest version is $LATEST_RELEASE, downloading..." mkdir -p "${BOOT2DOCKER_ISO%/*}" curl -L -o "$BOOT2DOCKER_ISO" "https://github.com/steeve/boot2docker/releases/download/$LATEST_RELEASE/boot2docker.iso" log "Done" else log "Could not get lastest release name! Cannot download boot2docker.iso." fi } log() { echo "[`date +"%Y-%m-%d %H:%M:%S"`] ${*}" } init() { if `$VBM showvminfo $VM_NAME > /dev/null 2>&1`; then echo "$VM_NAME Virtual Box vm already exists" exit 1 fi VM_OSTYPE=Linux26_64 VM_NIC=virtio unamestr=`uname` case $unamestr in Linux) VM_CPUS=`nproc`;; Darwin) VM_CPUS=`sysctl -n hw.physicalcpu`;; *) echo "$unamestr not yet supported - please raise an issue" ; exit 1 esac log "Creating VM $VM_NAME" $VBM createvm --name $VM_NAME --register log "Setting VM settings" TXUX_SUPPORT="" if $($VBM modifyvm|grep -q "\-\-vtxux"); then TXUX_SUPPORT="--vtxux on" fi if ! $VBM modifyvm $VM_NAME \ --ostype $VM_OSTYPE \ --cpus $VM_CPUS \ --memory $VM_MEM \ --rtcuseutc on \ --acpi on \ --ioapic on \ --hpet on \ --hwvirtex on \ --vtxvpid on \ $TXUX_SUPPORT \ --largepages on \ --nestedpaging on \ --firmware bios \ --bioslogofadein off --bioslogofadeout off --bioslogodisplaytime 0 --biosbootmenu disabled \ --boot1 dvd; then echo "An error occured, upgrade VirtualBox or try to disable some options" delete exit 1 fi log "Setting VM networking" $VBM modifyvm $VM_NAME \ --nic1 nat \ --nictype1 $VM_NIC \ --cableconnected1 on if `$VBM showvminfo $VM_NAME | grep Rule | grep ssh > /dev/null`; then $VBM modifyvm $VM_NAME \ --natpf1 delete "ssh" fi if `$VBM showvminfo $VM_NAME | grep Rule | grep docker > /dev/null`; then $VBM modifyvm $VM_NAME \ --natpf1 delete "docker" fi $VBM modifyvm $VM_NAME \ --natpf1 "ssh,tcp,127.0.0.1,$SSH_HOST_PORT,,22" \ --natpf1 "docker,tcp,127.0.0.1,$DOCKER_PORT,,4243" if [ ! -e $BOOT2DOCKER_ISO ]; then log "boot2docker.iso not found." download_latest fi log "Setting VM disks" if `$VBM showvminfo $VM_NAME | grep SATA > /dev/null`; then $VBM storagectl $VM_NAME --name "SATA" --remove fi if [ ! -e $VM_DISK ]; then log "Creating $VM_DISK_SIZE Meg hard drive..." # closemedium may complain when not needed $VBM closemedium disk $VM_DISK > /dev/null 2>&1 ## make a simple text file, and use that as the flag to say 'format me' $VBM createhd --format VMDK --filename $VM_DISK --size $VM_DISK_SIZE echo "boot2docker, please format-me" | cat - /dev/zero | head -c 5242880 > format-flag.txt # 5M $VBM convertfromraw format-flag.txt format-flag.vmdk --format VMDK $VBM clonehd format-flag.vmdk $VM_DISK --existing $VBM closemedium disk format-flag.vmdk > /dev/null 2>&1 && rm format-flag.txt format-flag.vmdk fi $VBM storagectl $VM_NAME --name "SATA" --add sata --hostiocache on $VBM storageattach $VM_NAME --storagectl "SATA" --port 0 --device 0 --type dvddrive --medium $BOOT2DOCKER_ISO $VBM storageattach $VM_NAME --storagectl "SATA" --port 1 --device 0 --type hdd --medium $VM_DISK log "Done." log "You can now type boot2docker up and wait for the VM to start." } do_ssh() { is_installed || status ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p $SSH_HOST_PORT docker@localhost $1 } start() { is_installed || status if ! is_running; then if is_paused; then log "Resuming $VM_NAME" $VBM controlvm $VM_NAME resume > /dev/null wait_vm log "Resumed." else log "Starting $VM_NAME..." $VBM startvm $VM_NAME --type headless > /dev/null & wait_vm log "Started." fi else log "$VM_NAME is already running." fi } wait_vm() { while ! echo "ping" | nc localhost $SSH_HOST_PORT > /dev/null 2>&1; do sleep 1 done } pause() { is_installed || status if is_running; then log "Pausing $VM_NAME..." $VBM controlvm $VM_NAME pause > /dev/null else log "$VM_NAME is not running." fi } stop() { is_installed || status if is_running; then log "Shutting down $VM_NAME..." $VBM controlvm $VM_NAME acpipowerbutton > /dev/null while is_running; do sleep 1 done else log "$VM_NAME is not running." fi } restart() { is_installed || status if is_running; then stop && sleep 1 && start else start fi } info() { if is_installed; then $VBM showvminfo $VM_NAME else echo "$VM_NAME does not exist." fi } is_installed() { $VBM list vms | grep "$VM_NAME" > /dev/null } is_running() { info | grep "State:\s\+running" > /dev/null } is_paused() { info | grep "State:\s\+paused" > /dev/null } is_stopped() { info | grep "State:\s\+powered off" > /dev/null } is_aborted() { info | grep "State:\s\+aborted" > /dev/null } status() { if is_running; then log "$VM_NAME is running." exit 0 elif is_paused; then log "$VM_NAME is suspended." exit 1 elif is_stopped; then log "$VM_NAME is stopped." exit 1 else log "$VM_NAME does not exist." exit 1 fi } delete() { if [ ! is_stopped ] || [ ! is_aborted ]; then log "$VM_NAME needs to be stopped to delete it." exit 1 fi $VBM unregistervm --delete $VM_NAME } case $1 in init | setup) init;; start | up) start;; pause | suspend) pause;; stop | halt | down) stop;; restart) restart;; status) status;; info) info;; delete) delete;; ssh) shift; do_ssh "$@";; download) download_latest;; *) echo "Usage $0 {init|start|up|pause|stop|restart|status|info|delete|ssh|download}"; exit 1 esac