# This file contains bash functions that are used by osbash on the host. source "$LIB_DIR/functions" #------------------------------------------------------------------------------- # Conditional execution #------------------------------------------------------------------------------- # TODO: Create a help function and display it under help by default or with # option --help (-h). # exec_cmd is used for conditional execution: # # OSBASH=exec_cmd # # Execute command only if OSBASH is set: # ${OSBASH:-:} cmd args # # Execute command only if OSBASH is not set: # ${OSBASH:+:} cmd args # # Disable actual call to VBoxManage (selectively override configuration): # OSBASH= cmd args # # Enable call to VBoxManage (selectively override configuration): # OSBASH=exec_cmd cmd args function exec_cmd { local cmd=$1 shift $cmd "$@" } OSBASH=exec_cmd #------------------------------------------------------------------------------- function get_base_disk_path { echo $DISK_DIR/base-$VM_ACCESS-$DISTRO.vdi } #------------------------------------------------------------------------------- # ssh #------------------------------------------------------------------------------- # Download Vagrant insecure private key if necessary function check_vagrant_private_key { local KEY_NAME="vagrant" local KEY_URL=https://raw.githubusercontent.com/mitchellh/vagrant/master/keys/$KEY_NAME local VAGRANT_KEY_DIR=$LIB_DIR/vagrant-ssh-keys if [ ! -f "$VAGRANT_KEY_DIR/$KEY_NAME" ]; then download "$KEY_URL" "$VAGRANT_KEY_DIR" $KEY_NAME chmod 400 "$VAGRANT_KEY_DIR/$KEY_NAME" fi } function strip_top_dir { local FULL_PATH=$1 echo "${FULL_PATH/$TOP_DIR\//}" } # Copy files or directories to VM (incl. implied directories; HOME is TOP_DIR) function vm_scp_to_vm { local SSH_PORT=$1 shift check_vagrant_private_key while (($#)); do local SRC_PATH=$1 shift local TARGET_PATH=$(strip_top_dir "$SRC_PATH") local TARGET_DIR=$(dirname "$TARGET_PATH") vm_ssh "$SSH_PORT" "mkdir -p $TARGET_DIR" scp -q -r \ -i "$LIB_DIR/vagrant-ssh-keys/vagrant" \ -o "UserKnownHostsFile /dev/null" \ -o "StrictHostKeyChecking no" \ -P "$SSH_PORT" \ "$SRC_PATH" "$VM_SHELL_USER@localhost:$TARGET_PATH" done } # Execute commands via ssh function vm_ssh { local SSH_PORT=$1 shift check_vagrant_private_key ssh -q \ -i "$LIB_DIR/vagrant-ssh-keys/vagrant" \ -o "UserKnownHostsFile /dev/null" \ -o "StrictHostKeyChecking no" \ -p "$SSH_PORT" \ "$VM_SHELL_USER@localhost" "$@" } function wait_for_ssh { local SSH_PORT=$1 echo "Waiting for ssh server to respond on local port $SSH_PORT" while [ : ]; do if vm_ssh "$SSH_PORT" exit ; then break else echo -n . sleep 1 fi done } # Copy one script to VM and execute it via ssh; log output to separate file function ssh_exec_script { local SSH_PORT=$1 local SCRIPT_PATH=$2 vm_scp_to_vm "$SSH_PORT" "$SCRIPT_PATH" local REMOTE_PATH=$(strip_top_dir "$SCRIPT_PATH") echo -en "\n$(date) start $REMOTE_PATH" local SCRIPT_NAME="$(basename "$SCRIPT_PATH" .sh)" local PREFIX=$(get_next_prefix "$LOG_DIR" "auto") local LOG_PATH=$LOG_DIR/${PREFIX}_${SCRIPT_NAME}.auto vm_ssh "$SSH_PORT" "bash $REMOTE_PATH" > "$LOG_PATH" 2>&1 echo -en "\n$(date) done" } # Wait for sshd, prepare autostart dirs, and execute autostart scripts on VM function ssh_process_autostart { local SSH_PORT=$1 wait_for_ssh "$SSH_PORT" vm_ssh "$SSH_PORT" "rm -rf lib config autostart" vm_scp_to_vm "$SSH_PORT" "$TOP_DIR/lib" "$TOP_DIR/config" local SCR_PATH="" for SCRIPT_PATH in "$AUTOSTART_DIR/"*.sh; do ssh_exec_script "$SSH_PORT" "$SCRIPT_PATH" done touch "$STATUS_DIR/done" } #------------------------------------------------------------------------------- # Autostart mechanism #------------------------------------------------------------------------------- function autostart_reset { clean_dir "$AUTOSTART_DIR" clean_dir "$STATUS_DIR" } function wait_for_autofiles { local DONE=false shopt -s nullglob ${WBATCH:-:} wbatch_wait_auto # Return if we are just faking it for wbatch ${OSBASH:+:} return 0 until $DONE ; do if [ -f "$STATUS_DIR/done" ]; then DONE=true rm "$STATUS_DIR/done" # Return only after checking for remaining *.sh.begin files fi # Note: begin files are only visible with a VirtualBox shared folder local PROCESSING=("$STATUS_DIR"/*.sh.begin) if [ -n "${PROCESSING[0]-}" ]; then for f in "${PROCESSING[@]}"; do echo >&2 -en "\nVM processing $(basename "$f" .begin)" rm "$f" done fi echo >&2 -n . sleep 1 done echo } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # Prepending numbers ensures scripts will be executed in the order they # were added to the queue. function _autostart_queue { local SRC_DIR=${1%/*} # if SRC_DIR is a code, turn it into a real path local SRC_DIR="$(src_dir_code_to_dir "$SRC_DIR")" local SRC_NAME=${1##*/} # If we get a target name, file will be renamed local TARGET_NAME=${2:-$SRC_NAME} if [[ $TARGET_NAME = *.sh ]]; then # Create target file name like 01_apt_init.sh local PREFIX=$(get_next_prefix "$AUTOSTART_DIR" "sh" 2) TARGET_NAME="${PREFIX}_$TARGET_NAME" fi if [ "$SRC_NAME" = "$TARGET_NAME" ]; then echo >&2 -e "\t$SRC_NAME" else echo >&2 -e "\t$SRC_NAME -> $TARGET_NAME" fi local SRC_PATH=$SRC_DIR/$SRC_NAME cp -- "$SRC_PATH" "$AUTOSTART_DIR/$TARGET_NAME" ${WBATCH:-:} wbatch_cp_auto "$SRC_PATH" "$AUTOSTART_DIR/$TARGET_NAME" } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # Print to the console which file requested guest scripts to run function log_autostart_source { # If the caller doesn't provide a config file, log the caller's source file local SRC_FILE=${1:-${BASH_SOURCE[1]##*/}} echo >&2 "Copying autostart files set in $SRC_FILE" } # autostart # e.g. autostart osbash init_xxx_node.sh init_controller_node.sh function autostart_and_rename { local SRC_DIR=$1 local SRC_FILE=$2 local TARGET_FILE=$3 # Don't log this file -- log our caller's source file log_autostart_source "${BASH_SOURCE[1]##*/}" _autostart_queue "$SRC_DIR/$SRC_FILE" "$TARGET_FILE" } # autostart [ ...] # e.g. autostart scripts prepare_home.sh apt_init.sh function autostart { local SRC_DIR=$1 shift # Don't log this file -- log our caller's source file log_autostart_source "${BASH_SOURCE[1]##*/}" while (($#)); do local SRC_FILE=$1 shift _autostart_queue "$SRC_DIR/$SRC_FILE" done } function autostart_from_config { local CONFIG_FILE=$1 log_autostart_source "$CONFIG_FILE" get_script_paths_from_config "$CONFIG_FILE" | while read SCR_PATH; do _autostart_queue "$SCR_PATH" done } #------------------------------------------------------------------------------- # Functions to get install ISO images #------------------------------------------------------------------------------- function download { local URL=$1 local DEST_DIR=$2 local DEST_FILE=$3 local RC=0 local WGET=$(which wget) mkdir -pv "$DEST_DIR" if [ -n "$WGET" ]; then $WGET --output-document "$DEST_DIR/$DEST_FILE" "$URL"||RC=$? else # Mac OS X has curl instead of wget local CURL=$(which curl) if [ -n "$CURL" ]; then $CURL "$URL" -o "$DEST_DIR/$DEST_FILE"||RC=$? fi fi if [ $RC -ne 0 ]; then echo >&2 "Unable to download $URL, quitting." exit 1 fi } function get_iso_name { basename "${ISO_URL:-}" } function find_install-iso { local ISO_NAME=$1 if [ ! -f "$ISO_DIR/$ISO_NAME" ]; then echo >&2 "$ISO_NAME not in $ISO_DIR; downloading" download "$ISO_URL" "$ISO_DIR" "$ISO_NAME" fi } # vim: set ai ts=4 sw=4 et ft=sh: