Blame chrooter/chrooter.sh

Ivan Mahonin e71c94
#!/bin/bash
Ivan Mahonin e71c94
Ivan Mahonin e71c94
set -e
Ivan Mahonin e71c94
Ivan Mahonin e71c94
OLDDIR=`pwd`
Ivan Mahonin e71c94
BASE_DIR=$(cd `dirname "$0"`; pwd)
Ivan Mahonin e71c94
cd "$OLDDIR"
Ivan Mahonin e71c94
Ivan Mahonin e71c94
INSTANCE_NAME=`uuidgen`
Ivan Mahonin e71c94
INSTANCE_NAME="chrooter-$INSTANCE_NAME"
Ivan Mahonin e71c94
PRIVILEGED=
Ivan Mahonin e71c94
IMAGE_MOUNT_DIR=
Ivan Mahonin e71c94
COMMAND_ERROR=
Ivan Mahonin e71c94
Ivan Mahonin e71c94
image_mount_add() {
Ivan Mahonin e71c94
	echo "Mount: $1 -> $2"
Ivan Mahonin e71c94
	sudo mkdir -p "$IMAGE_MOUNT_DIR$2"
Ivan Mahonin 3082cf
	sudo mount --bind "$1" "$IMAGE_MOUNT_DIR$2"
Ivan Mahonin ec0475
	echo "umount -f \"$IMAGE_MOUNT_DIR$2\" \\" >> "/tmp/$INSTANCE_NAME.umount.sh"
Ivan Mahonin ec0475
	echo "|| (echo \"next try after 10 seconds\" && sleep 10 && umount -f \"$IMAGE_MOUNT_DIR$2\") \\" >> "/tmp/$INSTANCE_NAME.umount.sh"
Ivan Mahonin ec0475
	echo "|| (echo \"final try after 10 seconds\" && sleep 10 && umount -f \"$IMAGE_MOUNT_DIR$2\")" >> "/tmp/$INSTANCE_NAME.umount.sh"
Ivan Mahonin e71c94
}
Ivan Mahonin e71c94
Ivan Mahonin e71c94
image_mount() {
Ivan Mahonin e71c94
	echo "Mount image: $1"
Ivan Mahonin e71c94
Ivan Mahonin e71c94
	if [ ! -z "$IMAGE_MOUNT_DIR" ]; then
Ivan Mahonin e71c94
		echo "Image already mounted"
Ivan Mahonin e71c94
		return 1
Ivan Mahonin e71c94
	fi
Ivan Mahonin e71c94
	if [ -z "$1" ]; then
Ivan Mahonin e71c94
		echo "Image name was not set"
Ivan Mahonin e71c94
		return 1
Ivan Mahonin e71c94
	fi	
Ivan Mahonin e71c94
	
Ivan Mahonin e71c94
	local IMAGE_NAME="$(echo $1 | tr "/:" "_")"
Ivan Mahonin e71c94
	local IMAGE_FILE="$BASE_DIR/image/$IMAGE_NAME.tgz"
Ivan Mahonin e71c94
	
Ivan Mahonin e71c94
	echo "Unpack image: $1"
Ivan Mahonin e71c94
	IMAGE_MOUNT_DIR="/tmp/$INSTANCE_NAME"
Ivan Mahonin e71c94
	mkdir -p "$IMAGE_MOUNT_DIR"
Ivan Mahonin e71c94
	cd "$IMAGE_MOUNT_DIR"
Ivan Mahonin e71c94
	sudo tar -xzf $IMAGE_FILE
Ivan Mahonin e71c94
	cd "$OLDDIR"
Ivan Mahonin e71c94
	
Ivan Mahonin e71c94
	echo "Add -.chroot.sh file"
Ivan Mahonin e71c94
	sudo mv "/tmp/$INSTANCE_NAME.chroot.sh" "$IMAGE_MOUNT_DIR"
Ivan Mahonin e71c94
	sudo chmod a+x "$IMAGE_MOUNT_DIR/$INSTANCE_NAME.chroot.sh"
Ivan Mahonin e71c94
	
Ivan Mahonin e71c94
    set -- "${@:2}"
Ivan Mahonin e71c94
	echo "Mount subs: $@"
Ivan Mahonin e71c94
	echo "#!/bin/sh" > "/tmp/$INSTANCE_NAME.umount.sh"
Ivan Mahonin e71c94
	echo "" >> "/tmp/$INSTANCE_NAME.umount.sh"
Ivan Mahonin e71c94
	echo "set -e" >> "/tmp/$INSTANCE_NAME.umount.sh"
Ivan Mahonin e71c94
	chmod a+x "/tmp/$INSTANCE_NAME.umount.sh"
Ivan Mahonin e71c94
	if [ ! -z "$PRIVILEGED" ]; then
Ivan Mahonin e71c94
		echo "Mount /proc and /dev for priveleged feature"
Ivan Mahonin e71c94
		image_mount_add /proc /proc
Ivan Mahonin e71c94
		image_mount_add /dev /dev
Ivan Mahonin e71c94
	fi
Ivan Mahonin e71c94
    for ARG in $@; do
Ivan Mahonin e71c94
		SRC="$(echo "$ARG" | cut -d':' -f 1)"
Ivan Mahonin e71c94
		DEST="$(echo "$ARG" | cut -d':' -f 2-)"
Ivan Mahonin e71c94
		image_mount_add $SRC $DEST
Ivan Mahonin e71c94
	done
Ivan Mahonin e71c94
}
Ivan Mahonin e71c94
Ivan Mahonin e71c94
image_unmount() {
Ivan Mahonin e71c94
	echo "Unmount image"
Ivan Mahonin e71c94
	
Ivan Mahonin e71c94
	if [ -z "$IMAGE_MOUNT_DIR" ]; then
Ivan Mahonin e71c94
		echo "Image not mounted"
Ivan Mahonin e71c94
		return 1
Ivan Mahonin e71c94
	fi
Ivan Mahonin e71c94
Ivan Mahonin e71c94
	echo "Unmount subs"
Ivan Mahonin ec0475
	sudo "/tmp/$INSTANCE_NAME.umount.sh"
Ivan Mahonin e71c94
	sudo rm -f "/tmp/$INSTANCE_NAME.umount.sh"
Ivan Mahonin e71c94
Ivan Mahonin e71c94
	echo "Remove -.chroot.sh file"
Ivan Mahonin e71c94
	sudo rm -f "$IMAGE_MOUNT_DIR/$INSTANCE_NAME.chroot.sh"
Ivan Mahonin e71c94
	
Ivan Mahonin e71c94
	if [ ! -z $1 ]; then
Ivan Mahonin e71c94
		echo "Save image: $1"
Ivan Mahonin e71c94
		
Ivan Mahonin e71c94
		local IMAGE_NAME="$(echo $1 | tr "/:" "_")"
Ivan Mahonin e71c94
		local IMAGE_FILE="$BASE_DIR/image/$IMAGE_NAME.tgz"
Ivan Mahonin e71c94
		local IMAGE_DIR=`dirname "$IMAGE_FILE"`
Ivan Mahonin e71c94
		mkdir -p "$IMAGE_DIR"
Ivan Mahonin e71c94
		
Ivan Mahonin e71c94
		cd "$IMAGE_MOUNT_DIR"
Ivan Mahonin e71c94
		sudo tar -czf $IMAGE_FILE .
Ivan Mahonin e71c94
		cd "$OLDDIR"
Ivan Mahonin e71c94
	fi
Ivan Mahonin e71c94
	
Ivan Mahonin e71c94
	echo "Remove unpacked image"
Ivan Mahonin e71c94
	sudo rm -rf --one-file-system "$IMAGE_MOUNT_DIR"
Ivan Mahonin e71c94
	IMAGE_MOUNT_DIR=
Ivan Mahonin e71c94
}
Ivan Mahonin e71c94
Ivan Mahonin e71c94
image_command() {
Ivan Mahonin e71c94
	echo "Run command: $@"
Ivan Mahonin e71c94
	
Ivan Mahonin e71c94
	if [ -z "$IMAGE_MOUNT_DIR" ]; then
Ivan Mahonin e71c94
		echo "Image not mounted"
Ivan Mahonin e71c94
		return 1
Ivan Mahonin e71c94
	fi
Ivan Mahonin e71c94
Ivan Mahonin 3082cf
	if ! env -i /usr/bin/sudo -i chroot "$IMAGE_MOUNT_DIR" "/$INSTANCE_NAME.chroot.sh" $@; then
Ivan Mahonin e71c94
		COMMAND_ERROR=1
Ivan Mahonin e71c94
		echo "Command returned with error"
Ivan Mahonin e71c94
	fi
Ivan Mahonin e71c94
}
Ivan Mahonin e71c94
Ivan Mahonin e71c94
chroot_file_begin() {
Ivan Mahonin e71c94
	echo "#!/bin/sh" > "/tmp/$INSTANCE_NAME.chroot.sh"
Ivan Mahonin e71c94
	echo "" >> "/tmp/$INSTANCE_NAME.chroot.sh"
Ivan Mahonin e71c94
}
Ivan Mahonin e71c94
Ivan Mahonin e71c94
chroot_file_env() {
Ivan Mahonin e71c94
    echo "Set env: $1=\"$2\""
Ivan Mahonin e71c94
	echo "export $1=\"$2\"" >> "/tmp/$INSTANCE_NAME.chroot.sh"
Ivan Mahonin e71c94
}
Ivan Mahonin e71c94
Ivan Mahonin e71c94
chroot_file_end() {
Ivan Mahonin e71c94
	echo "\$@" >> "/tmp/$INSTANCE_NAME.chroot.sh"
Ivan Mahonin e71c94
}
Ivan Mahonin e71c94
Ivan Mahonin e71c94
import() {
Ivan Mahonin e71c94
	echo "Import $2"
Ivan Mahonin e71c94
	
Ivan Mahonin e71c94
	if [ ! "$1" = "-" ]; then
Ivan Mahonin e71c94
    	echo "Unknown commandline argument $1"
Ivan Mahonin e71c94
	fi
Ivan Mahonin e71c94
	if [ -z "$2" ]; then
Ivan Mahonin e71c94
    	echo "Image name was not set"
Ivan Mahonin e71c94
    	return 1
Ivan Mahonin e71c94
	fi
Ivan Mahonin e71c94
	
Ivan Mahonin e71c94
		
Ivan Mahonin e71c94
	local IMAGE_NAME="$(echo $2 | tr "/:" "_")"
Ivan Mahonin e71c94
	local IMAGE_FILE="$BASE_DIR/image/$IMAGE_NAME.tgz"
Ivan Mahonin e71c94
	local IMAGE_DIR=`dirname "$IMAGE_FILE"`
Ivan Mahonin e71c94
	mkdir -p "$IMAGE_DIR"
Ivan Mahonin e71c94
	cat "/dev/stdin" > $IMAGE_FILE
Ivan Mahonin e71c94
}
Ivan Mahonin e71c94
Ivan Mahonin e71c94
build() {
Ivan Mahonin e71c94
	echo "Build"
Ivan Mahonin e71c94
	
Ivan Mahonin e71c94
	local IMAGE_NAME=
Ivan Mahonin e71c94
	local WORK_DIR=
Ivan Mahonin e71c94
		
Ivan Mahonin e71c94
	chroot_file_begin
Ivan Mahonin e71c94
    local MODE=
Ivan Mahonin e71c94
    for ARG in $@; do
Ivan Mahonin e71c94
    	if [ -z "$WORK_DIR" ]; then
Ivan Mahonin e71c94
	    	if [ "$MODE" = "-t" ]; then
Ivan Mahonin e71c94
	    		IMAGE_NAME="$ARG"
Ivan Mahonin e71c94
	    		echo "Set image name: $IMAGE_NAME"
Ivan Mahonin e71c94
	    		MODE=
Ivan Mahonin e71c94
	    		continue
Ivan Mahonin e71c94
	    	fi
Ivan Mahonin e71c94
	    fi
Ivan Mahonin e71c94
    	
Ivan Mahonin e71c94
    	if [ ! -z "$MODE" ]; then
Ivan Mahonin e71c94
    		echo "Unknown commandline argument: $MODE"
Ivan Mahonin e71c94
    	fi
Ivan Mahonin e71c94
Ivan Mahonin e71c94
    	MODE=
Ivan Mahonin e71c94
    	if [ ! -z "$WORK_DIR" ]; then
Ivan Mahonin e71c94
    		echo "Unknown commandline argument: $ARG"
Ivan Mahonin e71c94
		elif [ "${ARG:0:1}" = "-" ]; then
Ivan Mahonin e71c94
    		SUBMODE="$(echo "$ARG" | cut -d'=' -f 1)"
Ivan Mahonin e71c94
    		SUBVALUE="$(echo "$ARG" | cut -d'=' -f 2-)"
Ivan Mahonin e71c94
    		if [ "$SUBMODE" = "--build-arg" ]; then
Ivan Mahonin e71c94
    			ENVKEY="$(echo "$SUBVALUE" | cut -d'=' -f 1)"
Ivan Mahonin e71c94
    			ENVVALUE="$(echo "$SUBVALUE" | cut -d'=' -f 2-)"
Ivan Mahonin e71c94
    			chroot_file_env "$ENVKEY" "$ENVVALUE"
Ivan Mahonin e71c94
    			continue
Ivan Mahonin e71c94
    		else
Ivan Mahonin e71c94
    			MODE=$ARG
Ivan Mahonin e71c94
    		fi
Ivan Mahonin e71c94
    	else
Ivan Mahonin e71c94
			WORK_DIR=$ARG
Ivan Mahonin e71c94
			echo "Set work dir: $WORK_DIR"
Ivan Mahonin e71c94
		fi
Ivan Mahonin e71c94
	done
Ivan Mahonin e71c94
	if [ ! -z "$MODE" ]; then
Ivan Mahonin e71c94
		echo "Unknown commandline argument $MODE"
Ivan Mahonin e71c94
	fi
Ivan Mahonin e71c94
	chroot_file_end
Ivan Mahonin e71c94
Ivan Mahonin e71c94
	if [ -z "$IMAGE_NAME" ]; then
Ivan Mahonin e71c94
		echo "Image name was not set"
Ivan Mahonin e71c94
		return 1
Ivan Mahonin e71c94
	fi
Ivan Mahonin e71c94
								
Ivan Mahonin e71c94
	local DOCKERFILE="$WORK_DIR/Dockerfile"
Ivan Mahonin e71c94
	if [ ! -f "$DOCKERFILE" ]; then
Ivan Mahonin e71c94
		echo "Dockerfile not found at: $DOCKERFILE"
Ivan Mahonin e71c94
		return 1
Ivan Mahonin e71c94
	fi
Ivan Mahonin e71c94
Ivan Mahonin e71c94
	echo "Read $DOCKERFILE"
Ivan Mahonin e71c94
	FULLROW=
Ivan Mahonin e71c94
	while read ROW; do
Ivan Mahonin e71c94
		FULLROW="$FULLROW$ROW"
Ivan Mahonin e71c94
		LASTCHAR=$((${#ROW}-1))
Ivan Mahonin e71c94
		if [ ! "${ROW:LASTCHAR:1}" = "\\" ]; then
Ivan Mahonin e71c94
			if [ "${FULLROW:0:5}" = "FROM " ]; then
Ivan Mahonin e71c94
				image_mount "${FULLROW:5}"
Ivan Mahonin e71c94
			elif [ "${ROW:0:4}" = "RUN " ]; then
Ivan Mahonin e71c94
				image_command "${FULLROW:4}"
Ivan Mahonin e71c94
			elif [ ! "${FULLROW:0:1}" = "#" ]; then
Ivan Mahonin e71c94
				if [ ! -z "$FULLROW" ]; then
Ivan Mahonin e71c94
					echo "Unknown command: $FULLROW"
Ivan Mahonin e71c94
				fi 
Ivan Mahonin e71c94
			fi
Ivan Mahonin e71c94
			FULLROW=
Ivan Mahonin e71c94
		fi
Ivan Mahonin e71c94
		if [ ! -z "$COMMAND_ERROR" ]; then
Ivan Mahonin e71c94
			echo "Cancel build"
Ivan Mahonin e71c94
			IMAGE_NAME=""
Ivan Mahonin e71c94
			break
Ivan Mahonin e71c94
		fi
Ivan Mahonin e71c94
	done < "$DOCKERFILE"
Ivan Mahonin e71c94
	
Ivan Mahonin e71c94
	image_unmount "$IMAGE_NAME"
Ivan Mahonin e71c94
}
Ivan Mahonin e71c94
Ivan Mahonin e71c94
run() {
Ivan Mahonin e71c94
	local IMAGE_NAME=
Ivan Mahonin e71c94
	local COMMAND=
Ivan Mahonin e71c94
	local SUBMOUNT=
Ivan Mahonin e71c94
	
Ivan Mahonin e71c94
	chroot_file_begin
Ivan Mahonin e71c94
    local MODE=
Ivan Mahonin e71c94
    for ARG in $@; do
Ivan Mahonin e71c94
    	if [ ! -z "$COMMAND" ]; then
Ivan Mahonin e71c94
	    	COMMAND="$COMMAND $ARG"
Ivan Mahonin e71c94
    	else
Ivan Mahonin e71c94
	    	if [ "$MODE" = "-e" ]; then
Ivan Mahonin e71c94
				ENVKEY="$(echo "$ARG" | cut -d'=' -f 1)"
Ivan Mahonin e71c94
				ENVVALUE="$(echo "$ARG" | cut -d'=' -f 2-)"
Ivan Mahonin e71c94
				chroot_file_env "$ENVKEY" "$ENVVALUE"
Ivan Mahonin e71c94
				MODE=
Ivan Mahonin e71c94
				continue
Ivan Mahonin e71c94
	    	elif [ "$MODE" = "-v" ]; then
Ivan Mahonin e71c94
				SUBMOUNT="$SUBMOUNT$ARG "
Ivan Mahonin e71c94
	    		echo "Add submount: $ARG"
Ivan Mahonin e71c94
				MODE=
Ivan Mahonin e71c94
				continue
Ivan Mahonin e71c94
	    	elif [ "$MODE" = "--name" ]; then
Ivan Mahonin e71c94
	    		echo "Set name: $ARG (not uses)"
Ivan Mahonin e71c94
				MODE=
Ivan Mahonin e71c94
				continue
Ivan Mahonin e71c94
	    	fi
Ivan Mahonin e71c94
	    
Ivan Mahonin e71c94
	    	if [ ! -z "$MODE" ]; then
Ivan Mahonin e71c94
	    		echo "Unknown commandline argument $MODE"
Ivan Mahonin e71c94
	    	fi
Ivan Mahonin e71c94
	    	    	    	    	
Ivan Mahonin e71c94
	    	MODE=
Ivan Mahonin e71c94
	    	if [ -z "$MODE" ]; then
Ivan Mahonin e71c94
	    		if [ "$ARG" = "--privileged=true" ]; then
Ivan Mahonin e71c94
	    			PRIVILEGED=1
Ivan Mahonin e71c94
	    			echo "Set privileged: true"
Ivan Mahonin e71c94
	    		elif [ "${ARG:0:1}" = "-" ]; then
Ivan Mahonin e71c94
    				MODE=$ARG
Ivan Mahonin e71c94
		    	elif [ -z "$IMAGE_NAME" ]; then
Ivan Mahonin e71c94
		    		IMAGE_NAME=$ARG
Ivan Mahonin e71c94
	    			echo "Set image name: $IMAGE_NAME"
Ivan Mahonin e71c94
		    	elif [ -z "$COMMAND" ]; then
Ivan Mahonin e71c94
	    			COMMAND=$ARG
Ivan Mahonin e71c94
	    		fi
Ivan Mahonin e71c94
	    	fi
Ivan Mahonin e71c94
		fi
Ivan Mahonin e71c94
	done
Ivan Mahonin e71c94
	if [ ! -z "$MODE" ]; then
Ivan Mahonin e71c94
		echo "Unknown commandline argument $MODE"
Ivan Mahonin e71c94
	fi
Ivan Mahonin e71c94
	chroot_file_end
Ivan Mahonin e71c94
	echo "Set command: $COMMAND"
Ivan Mahonin e71c94
Ivan Mahonin e71c94
	if [ -z "$COMMAND" ]; then
Ivan Mahonin e71c94
		echo "Command was not set"
Ivan Mahonin e71c94
		return 1
Ivan Mahonin e71c94
	fi
Ivan Mahonin e71c94
Ivan Mahonin e71c94
	image_mount "$IMAGE_NAME" $SUBMOUNT
Ivan Mahonin e71c94
	image_command $COMMAND
Ivan Mahonin e71c94
	image_unmount
Ivan Mahonin e71c94
}
Ivan Mahonin e71c94
Ivan Mahonin e71c94
Ivan Mahonin e71c94
if [ "$1" = "import" ]; then
Ivan Mahonin e71c94
    set -- "${@:2}"
Ivan Mahonin e71c94
    import $@
Ivan Mahonin e71c94
elif [ "$1" = "build" ]; then
Ivan Mahonin e71c94
    set -- "${@:2}"
Ivan Mahonin e71c94
    build $@
Ivan Mahonin e71c94
elif [ "$1" = "run" ]; then
Ivan Mahonin e71c94
    set -- "${@:2}"
Ivan Mahonin e71c94
    run $@
Ivan Mahonin e71c94
else
Ivan Mahonin e71c94
	echo "Unknown command: $1"
Ivan Mahonin ec0475
	COMMAND_ERROR=1
Ivan Mahonin ec0475
fi
Ivan Mahonin ec0475
Ivan Mahonin ec0475
if [ ! -z "$COMMAND_ERROR" ]; then
Ivan Mahonin ec0475
	false
Ivan Mahonin e71c94
fi