mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-10-31 11:22:27 +00:00 
			
		
		
		
	git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/branches/2.8@16254 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
		
			
				
	
	
		
			1829 lines
		
	
	
		
			58 KiB
		
	
	
	
		
			Bash
		
	
	
	
	
	
			
		
		
	
	
			1829 lines
		
	
	
		
			58 KiB
		
	
	
	
		
			Bash
		
	
	
	
	
	
| #!/bin/sh
 | |
| #
 | |
| # "SystemImager" 
 | |
| #
 | |
| #  Copyright (C) 1999-2011 Brian Elliott Finley <brian@thefinleys.com>
 | |
| #
 | |
| #  $Id: functions 4559 2011-07-05 21:04:36Z finley $
 | |
| #  vi: set filetype=sh et ts=4:
 | |
| #
 | |
| #  Others who have contributed to this code:
 | |
| #   Charles C. Bennett, Jr. <ccb@acm.org>
 | |
| #   Sean Dague <japh@us.ibm.com>
 | |
| #   Dann Frazier <dannf@dannf.org>
 | |
| #   Curtis Zinzilieta <czinzilieta@valinux.com>
 | |
| #
 | |
| 
 | |
| 
 | |
| ################################################################################
 | |
| #
 | |
| #   Variables
 | |
| #
 | |
| PATH=/sbin:/bin:/usr/bin:/usr/sbin:/tmp
 | |
| LD_LIBRARY_PATH=/lib
 | |
| SCRIPTS=scripts
 | |
| SCRIPTS_DIR=/scripts
 | |
| TORRENTS=torrents
 | |
| TORRENTS_DIR=/torrents
 | |
| FLAMETHROWER_DIRECTORY_DIR=/var/lib/systemimager/flamethrower
 | |
| BOEL_BINARIES_DIR=/tmp/boel_binaries
 | |
| VERSION="4.3.0"
 | |
| FLAVOR="standard"
 | |
| IMAGESERVER=$XCATMASTER
 | |
| #
 | |
| ################################################################################
 | |
| 
 | |
| 
 | |
| ################################################################################
 | |
| #
 | |
| #   Subroutines
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| #  logmsg
 | |
| #
 | |
| # Usage: log a message, redirects to console / syslog depending on usage
 | |
| logmsg() {
 | |
|     # log to console
 | |
|     echo $@
 | |
|     # log to temporary file (which will go away when we reboot)
 | |
|     # this is good for envs that have bad consoles
 | |
|     local FILE=/tmp/si.log
 | |
|     echo $@ >> $FILE || shellout
 | |
|     
 | |
|     # if syslog is running, log to it.  In order to avoid hangs we have to 
 | |
|     # add the "logger: " part in case $@ is ""
 | |
|     if [ ! -z $USELOGGER ] ;
 | |
|         then logger "logger: $@"
 | |
|     fi
 | |
| }
 | |
| 
 | |
| 
 | |
| ################################################################################
 | |
| #
 | |
| #  check_version
 | |
| #
 | |
| # Usage: check_version
 | |
| check_version() {
 | |
|     logmsg
 | |
|     logmsg check_version
 | |
|     INITRD_VERSION=$VERSION
 | |
|     KERNEL_VERSION=`uname -r | sed -e s/.*boel_v//`
 | |
|     if [ "$INITRD_VERSION" != "$KERNEL_VERSION" ] ; then
 | |
|         logmsg "FATAL: Kernel version ($KERNEL_VERSION) doesn't match initrd version ($INITRD_VERSION)!"
 | |
|         shellout
 | |
|     fi
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| #  get_arch
 | |
| #
 | |
| # Usage: get_arch; echo $ARCH
 | |
| get_arch() {
 | |
|     logmsg
 | |
|     logmsg get_arch
 | |
|     ARCH=`uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/`
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| #  adjust_arch
 | |
| #
 | |
| #  based on info in /proc adjust the ARCH variable.  This needs to run
 | |
| #  after proc is mounted.
 | |
| #
 | |
| adjust_arch() {
 | |
|     logmsg
 | |
|     logmsg adjust_arch
 | |
|     if [ "ppc64" = "$ARCH" ] ; then
 | |
|         # This takes a little bit of futzing with due to all the PPC platforms that exist.
 | |
|         if [ -d /proc/iSeries ] ; then
 | |
|             ARCH=ppc64-iSeries
 | |
|             logmsg "Detected ppc64 is really an iSeries partition..."
 | |
|         fi
 | |
|         if grep -qs PS3 /proc/cpuinfo; then
 | |
|             ARCH=ppc64-ps3
 | |
|         fi
 | |
|     fi
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| #  write_variables
 | |
| #
 | |
| # Usage: write_variables
 | |
| write_variables() {
 | |
| 
 | |
|     logmsg
 | |
|     logmsg write_variables
 | |
| 
 | |
|     # pass all variables set here on to the hostname.sh script
 | |
|     rm -f /tmp/variables.txt
 | |
|     
 | |
|     echo "HOSTNAME=$HOSTNAME"                   >> /tmp/variables.txt || shellout
 | |
|     echo "DOMAINNAME=$DOMAINNAME"               >> /tmp/variables.txt
 | |
|     
 | |
|     echo "DEVICE=$DEVICE"                       >> /tmp/variables.txt
 | |
|     echo "IPADDR=$IPADDR"                       >> /tmp/variables.txt
 | |
|     echo "NETMASK=$NETMASK"                     >> /tmp/variables.txt
 | |
|     echo "NETWORK=$NETWORK"                     >> /tmp/variables.txt
 | |
|     echo "BROADCAST=$BROADCAST"                 >> /tmp/variables.txt
 | |
|     
 | |
|     echo "GATEWAY=$GATEWAY"                     >> /tmp/variables.txt
 | |
|     echo "GATEWAYDEV=$GATEWAYDEV"               >> /tmp/variables.txt
 | |
|     
 | |
|     echo "IMAGESERVER=$IMAGESERVER"             >> /tmp/variables.txt
 | |
|     echo "IMAGENAME=$IMAGENAME"                 >> /tmp/variables.txt
 | |
|     
 | |
|     echo "LOG_SERVER=$LOG_SERVER"               >> /tmp/variables.txt
 | |
|     echo "LOG_SERVER_PORT=$LOG_SERVER_PORT" 	>> /tmp/variables.txt
 | |
|     echo "USELOGGER=$USELOGGER"                 >> /tmp/variables.txt
 | |
|     
 | |
|     echo "TMPFS_STAGING=$TMPFS_STAGING"         >> /tmp/variables.txt
 | |
|     
 | |
|     echo "SSH=$SSH"	           	 		        >> /tmp/variables.txt
 | |
|     echo "SSHD=$SSHD"	            		    >> /tmp/variables.txt
 | |
|     echo "SSH_USER=$SSH_USER"	            	>> /tmp/variables.txt
 | |
|     echo "SSH_DOWNLOAD_URL=$SSH_DOWNLOAD_URL"	>> /tmp/variables.txt
 | |
|     
 | |
|     echo "FLAMETHROWER_DIRECTORY_PORTBASE=$FLAMETHROWER_DIRECTORY_PORTBASE"	>> /tmp/variables.txt
 | |
|     
 | |
|     echo "MONITOR_SERVER=$MONITOR_SERVER"       >> /tmp/variables.txt
 | |
|     echo "MONITOR_PORT=$MONITOR_PORT"           >> /tmp/variables.txt
 | |
|     echo "MONITOR_CONSOLE=$MONITOR_CONSOLE"     >> /tmp/variables.txt
 | |
|     
 | |
|     echo "BITTORRENT=$BITTORRENT"                           >> /tmp/variables.txt
 | |
|     echo "BITTORRENT_STAGING=$BITTORRENT_STAGING"           >> /tmp/variables.txt
 | |
|     echo "BITTORRENT_POLLING_TIME=$BITTORRENT_POLLING_TIME" >> /tmp/variables.txt
 | |
|     echo "BITTORRENT_SEED_WAIT=$BITTORRENT_SEED_WAIT"       >> /tmp/variables.txt
 | |
|     echo "BITTORRENT_UPLOAD_MIN=$BITTORRENT_UPLOAD_MIN"     >> /tmp/variables.txt
 | |
|     
 | |
|     echo "GROUPNAMES=\"$GROUPNAMES\""               >> /tmp/variables.txt
 | |
|     echo "GROUP_OVERRIDES=\"$GROUP_OVERRIDES\""     >> /tmp/variables.txt
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| #   Description:
 | |
| #   watches the tmpfs filesystem (/) and gives warnings and/or does a shellout
 | |
| #
 | |
| #   Usage: tmpfs_watcher
 | |
| #
 | |
| tmpfs_watcher() {
 | |
| 
 | |
|     logmsg
 | |
|     logmsg tmpfs_watcher
 | |
| 
 | |
|     # Note: Transfer to staging area can fail if tmpfs runs out of inodes.
 | |
|     {
 | |
|         while :; do
 | |
|             DF=`df -k / | egrep ' /$' | sed -e 's/  */ /g' -e 's/.*[0-9] //' -e 's/%.*//'`
 | |
|             [ $DF -ge 95 ] && logmsg "WARNING: Your tmpfs filesystem is ${DF}% full!"
 | |
|             [ $DF -ge 99 ] && logmsg "         Search the FAQ for tmpfs to learn about sizing options."
 | |
|             [ $DF -ge 99 ] && shellout
 | |
|             sleep 1
 | |
|         done
 | |
|         unset DF
 | |
|     }&
 | |
|     TMPFS_WATCHER_PID=$!
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| #   Description:
 | |
| #   Exit with the message stored in /etc/issue.
 | |
| #
 | |
| #   Usage: $COMMAND || shellout
 | |
| #
 | |
| shellout() {
 | |
| 
 | |
|     logmsg "Last command exited with $?"
 | |
|     COUNT="$RETRY"
 | |
|     logmsg "Killing off running processes."
 | |
|     kill -9 $TMPFS_WATCHER_PID  >/dev/null 2>/dev/null
 | |
|     killall -9 udp-receiver rsync  >/dev/null 2>/dev/null
 | |
|     write_variables
 | |
|     cat /etc/issue
 | |
|     if [ ! -z $USELOGGER ] ;
 | |
|         then cat /etc/issue | logger
 | |
|     fi
 | |
|     if [ ! -z $MONITOR_SERVER ]; then
 | |
|     	logmsg "Installation failed!! Stopping report task."
 | |
|         stop_report_task -1
 | |
|     fi
 | |
|     exec sh > /dev/console 2>&1
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| #   Description:  
 | |
| #   Count the specified number, printing each number, and exit only the count
 | |
| #   loop when <ctrl>+<c> is hit (SIGINT, or Signal 2).  Thanks to 
 | |
| #   CCB <ccb@acm.org> for this chunk of code.  -BEF-
 | |
| #
 | |
| #   Usage: 
 | |
| #   count_loop 35
 | |
| #   count_loop $ETHER_SLEEP
 | |
| #
 | |
| count_loop() {
 | |
| 
 | |
|   COUNT=$1
 | |
| 
 | |
|   trap 'echo ; echo "Skipping ETHER_SLEEP -> Caught <ctrl>+<c>" ; I=$COUNT' INT
 | |
| 
 | |
|   I=0
 | |
|   while [ $I -lt $COUNT ]; do
 | |
|     I=$(( $I + 1 ))
 | |
|     logmsg -n "$I "
 | |
|     sleep 1
 | |
|   done
 | |
| 
 | |
|   trap INT
 | |
| 
 | |
|   logmsg
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| # Usage: get_torrents_directory
 | |
| #
 | |
| get_torrents_directory() {
 | |
|     if [ ! "x$BITTORRENT" = "xy" ]; then
 | |
|         return
 | |
|     fi
 | |
| 
 | |
|     logmsg
 | |
|     logmsg get_torrents_directory
 | |
| 
 | |
|     if [ ! -z $FLAMETHROWER_DIRECTORY_PORTBASE ]; then
 | |
|         #
 | |
|         # We're using Multicast, so we should already have a directory 
 | |
|         # full of scripts.  Break out here, so that we don't try to pull
 | |
|         # the scripts dir again (that would be redundant).
 | |
|         #
 | |
|         MODULE_NAME="autoinstall_torrents"
 | |
|         DIR="${SCRIPTS_DIR}"
 | |
|         RETRY=7
 | |
|         flamethrower_client
 | |
| 
 | |
|     else
 | |
|         mkdir -p ${TORRENTS_DIR}
 | |
|         CMD="rsync -a ${IMAGESERVER}::${TORRENTS}/ ${TORRENTS_DIR}/"
 | |
|         logmsg "$CMD"
 | |
|         $CMD
 | |
|     fi
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| # Usage: get_scripts_directory
 | |
| #
 | |
| get_scripts_directory() {
 | |
|     logmsg
 | |
|     logmsg get_scripts_directory
 | |
| 
 | |
|     if [ ! -z $FLAMETHROWER_DIRECTORY_PORTBASE ]; then
 | |
|         #
 | |
|         # We're using Multicast, so we should already have a directory 
 | |
|         # full of scripts.  Break out here, so that we don't try to pull
 | |
|         # the scripts dir again (that would be redundant).
 | |
|         #
 | |
|         MODULE_NAME="autoinstall_scripts"
 | |
|         DIR="${SCRIPTS_DIR}"
 | |
|         RETRY=7
 | |
|         flamethrower_client
 | |
| 
 | |
|     else
 | |
|         mkdir -p ${SCRIPTS_DIR}
 | |
|         CMD="rsync -a ${IMAGESERVER}::${SCRIPTS}/ ${SCRIPTS_DIR}/"
 | |
|         logmsg "$CMD"
 | |
|         $CMD || shellout
 | |
|     fi
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| # Usage: get_flamethrower_directory
 | |
| #
 | |
| get_flamethrower_directory() {
 | |
|     logmsg
 | |
|     logmsg Using multicast...
 | |
|     logmsg get_flamethrower_directory
 | |
| 
 | |
|     MODULE_NAME=flamethrower_directory
 | |
|     DIR=${FLAMETHROWER_DIRECTORY_DIR}
 | |
|     RETRY=7
 | |
|     PORTBASE=9000
 | |
|     flamethrower_client
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| # Usage: 
 | |
| #
 | |
| #   MODULE_NAME=my_module   # Required
 | |
| #   DIR=/my/destination/dir # Required
 | |
| #   [RETRY=7]               # Optional
 | |
| #   [PORTBASE=9000]         # Required if a sourceable file called $MODULE_NAME
 | |
| #                           #   doesn't exist
 | |
| #   [FLAMETHROWER_TARPIPE]  # If not empty, untar received data directly,
 | |
| #                           # without storing it to a temporary file
 | |
| #
 | |
| #   flamethrower_client
 | |
| #
 | |
| flamethrower_client() {
 | |
| 
 | |
|     if [ ! -z $FLAMETHROWER_TARPIPE ]; then
 | |
| 	FLAMETHROWER_TARPIPE=tarpipe
 | |
|     fi
 | |
|     logmsg
 | |
|     logmsg "flamethrower_client(${MODULE_NAME}) $FLAMETHROWER_TARPIPE "
 | |
|     logmsg ---------------------------------------------------------------------
 | |
| 
 | |
|     # validate
 | |
|     if [ -z $PORTBASE ]; then
 | |
|         if [ -f ${FLAMETHROWER_DIRECTORY_DIR}/${MODULE_NAME} ]; then
 | |
| 	    . ${FLAMETHROWER_DIRECTORY_DIR}/${MODULE_NAME}
 | |
| 	else
 | |
| 	    logmsg WARNING WARNING WARNING WARNING WARNING
 | |
|             logmsg You must either set PORTBASE, or have a sourceable file called
 | |
|             logmsg ${FLAMETHROWER_DIRECTORY_DIR}/MODULE_NAME
 | |
| 	    # allow for now to continue until overrides get their modules
 | |
| 	    return
 | |
|             #shellout
 | |
|         fi
 | |
|     fi
 | |
|     if [ -z $DIR ]; then
 | |
|         logmsg "Must set DIR !!!"
 | |
| 	shellout
 | |
|     else
 | |
|         mkdir -p $DIR
 | |
|     fi
 | |
| 
 | |
|     # build command
 | |
|     UDP_RECEIVER_OPTIONS="--interface ${DEVICE} --portbase $PORTBASE --nokbd"
 | |
|     if [ ! -z $TTL ]; then
 | |
|         UDP_RECEIVER_OPTIONS="$UDP_RECEIVER_OPTIONS --ttl $TTL"
 | |
|     fi
 | |
|     if [ "$NOSYNC" = "on" ]; then
 | |
|         UDP_RECEIVER_OPTIONS="$UDP_RECEIVER_OPTIONS --nosync"
 | |
|     fi
 | |
|     if [ "$ASYNC" = "on" ]; then
 | |
|         UDP_RECEIVER_OPTIONS="$UDP_RECEIVER_OPTIONS --async"
 | |
|     fi
 | |
|     if [ ! -z $MCAST_ALL_ADDR ]; then
 | |
|         UDP_RECEIVER_OPTIONS="$UDP_RECEIVER_OPTIONS --mcast-all-addr $MCAST_ALL_ADDR"
 | |
|     fi
 | |
| 
 | |
|     # Which tar opts should we use?  If our tar has --overwrite capability, use it.
 | |
|     #   Summary: busybox tar doesn't (boel_binaries and prior).
 | |
|     #            Debian patched gnu tar does (image and on).
 | |
|     #            We want this option enabled for the image to ensure proper directory
 | |
|     #            permissions. -BEF-
 | |
|     tar --help 2>&1 | grep -q overwrite && TAR_OPTS='--overwrite -xp' || TAR_OPTS='-x'
 | |
| 
 | |
|     # set vars
 | |
|     [ -z $RETRY ] && RETRY=0
 | |
|     COUNT=0
 | |
|     FLAMETHROWER_CLIENT_SLEEP=3
 | |
| 
 | |
|     # it's the new new style (loop)
 | |
|     SUCCESS="Not Yet"
 | |
|     until [ "$SUCCESS" = "yes" ]
 | |
|     do
 | |
|         # receive cast
 | |
|         #   example udp-receiver command:
 | |
|         #   udp-receiver --interface lo --portbase 9002 --nokbd --nosync --file /tmp/multicast.tar
 | |
| 
 | |
|         if [ ! -z $FLAMETHROWER_TARPIPE ]; then
 | |
| 	    TAR_OPTS="$TAR_OPTS -f -"
 | |
| 	    logmsg "udp-receiver $UDP_RECEIVER_OPTIONS | tar $TAR_OPTS -C $DIR"
 | |
| 	    udp-receiver $UDP_RECEIVER_OPTIONS | tar $TAR_OPTS -C $DIR
 | |
| 	    TAR_EXIT_STATUS=$?
 | |
| 	    UDP_RECEIVER_EXIT_STATUS=0
 | |
| 	else
 | |
| 	    logmsg udp-receiver $UDP_RECEIVER_OPTIONS --file /tmp/multicast.tar
 | |
| 	    udp-receiver $UDP_RECEIVER_OPTIONS --file /tmp/multicast.tar
 | |
| 	    UDP_RECEIVER_EXIT_STATUS=$?
 | |
| 
 | |
|             # untar it
 | |
| 	    if [ "$UDP_RECEIVER_EXIT_STATUS" = "0" ]; then
 | |
| 		logmsg tar ${TAR_OPTS} -f /tmp/multicast.tar -C ${DIR}
 | |
| 		tar ${TAR_OPTS} -f /tmp/multicast.tar -C ${DIR}
 | |
| 		TAR_EXIT_STATUS=$?
 | |
| 	    fi
 | |
|             # discard used tarball like an old sock (recommended by: Ramon Bastiaans <bastiaans@sara.nl>)
 | |
| 	    rm -f /tmp/multicast.tar
 | |
| 	fi
 | |
| 
 | |
|         # did everything work properly
 | |
|         if [ $UDP_RECEIVER_EXIT_STATUS -eq 0 ] && [ $TAR_EXIT_STATUS -eq 0 ]; then
 | |
|             SUCCESS=yes
 | |
|         else
 | |
|             if [ $COUNT -lt $RETRY ]; then
 | |
|                 COUNT=$(( $COUNT + 1 ))
 | |
|                 logmsg "flamethrower_client: Proceeding with retry $COUNT of $RETRY"
 | |
|             else
 | |
|                 logmsg
 | |
|                 logmsg "flamethrower_client: FATAL: Initial attempt and $RETRY retries failed!"
 | |
|                 shellout
 | |
|             fi
 | |
|         fi
 | |
| 
 | |
|         # sleep apnea
 | |
|         sleep_loop $FLAMETHROWER_CLIENT_SLEEP
 | |
|     done
 | |
| 
 | |
|     # done
 | |
|     logmsg 'finished!'
 | |
|     logmsg 
 | |
| 
 | |
|     # Unset vars, so next module (which may not have them set) won't use then unintentially
 | |
|     unset TTL
 | |
|     unset NOSYNC
 | |
|     unset ASYNC
 | |
|     unset MCAST_ALL_ADDR
 | |
|     unset RETRY
 | |
|     unset COUNT
 | |
|     unset DIR
 | |
|     unset PORTBASE
 | |
|     unset UDP_RECEIVER_EXIT_STATUS
 | |
|     unset UDP_RECEIVER_OPTIONS
 | |
|     unset TAR_EXIT_STATUS
 | |
|     unset TAR_OPTS
 | |
|     unset SUCCESS
 | |
|     unset FLAMETHROWER_TARPIPE
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| #   Autodetect a staging directory for the bittorrent tarball
 | |
| #
 | |
| #   Usage: bittorrent_autodetect_staging_dir torrent
 | |
| #
 | |
| bittorrent_autodetect_staging_dir() {
 | |
|     torrent=$1
 | |
|     if [ ! -f $torrent ]; then
 | |
|         logmsg "warning: torrent file $torrent does not exist!"
 | |
|         return
 | |
|     fi
 | |
| 
 | |
|     # List of preferred staging directory (/tmp = ramdisk staging)
 | |
|     preferred_dirs="/tmp /a/tmp `df 2>/dev/null | sed '1d' | sed 's/[[:space:]]\+/ /g' | cut -d' ' -f6`"
 | |
| 
 | |
|     # Use a breathing room of 100MB (this should be enough for a lot of cases)
 | |
|     breathing_room=102400
 | |
| 
 | |
|     # Evaluate torrent size
 | |
|     torrent_size=$((`/bin/torrentinfo-console $torrent | sed -ne 's/^file size\.*: \([0-9]\+\).*$/\1/p'` / 1024 + $breathing_room))
 | |
| 
 | |
|     # Find a directory to host the image tarball
 | |
|     for dir in $preferred_dirs; do
 | |
|         [ ! -d $dir ] && continue;
 | |
|         dir_space=`df $dir 2>/dev/null | sed '1d' | sed 's/[[:space:]]\+/ /g' | cut -d' ' -f4 | sed -ne '$p'`
 | |
|         [ -z $dir_space ] && continue
 | |
|         [ $torrent_size -lt $dir_space ] && echo $dir && return
 | |
|     done
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| #   Download a file using bittorrent.
 | |
| #
 | |
| #   Usage: bittorrent_get_file torrent destination
 | |
| #
 | |
| bittorrent_get_file() {
 | |
|         torrent=$1
 | |
|         destination=$2
 | |
| 
 | |
|         # Bittorrent log file
 | |
|         bittorrent_log=/tmp/bittorrent-`basename ${torrent}`.log
 | |
|         # Time to poll bittorrent events
 | |
|         bittorrent_polling_time=${BITTORRENT_POLLING_TIME:-5}
 | |
|         # Wait after the download is finished to seed the other peers
 | |
|         bittorrent_seed_wait=${BITTORRENT_SEED_WAIT:-n}
 | |
|         # Minimum upload rate threshold (in KB/s), if lesser stop seeding
 | |
|         bittorrent_upload_min=${BITTORRENT_UPLOAD_MIN:-50}
 | |
| 
 | |
|         # Start downloading.
 | |
|         /bin/bittorrent-console --no_upnp --no_start_trackerless_client --max_upload_rate 0 --display_interval 1 --rerequest_interval 1 --bind ${IPADDR} --save_in ${destination} ${torrent} > $bittorrent_log &
 | |
|         pid=$!
 | |
|         if [ ! -d /proc/$pid ]; then
 | |
|             logmsg "error: couldn't run bittorrent-console!"
 | |
|             shellout
 | |
|         fi
 | |
|         unset pid
 | |
| 
 | |
|         # Wait for BitTorrent log to appear.
 | |
|         while [ ! -e $bittorrent_log ]; do
 | |
|             sleep 1
 | |
|         done
 | |
| 
 | |
|         # Checking download...
 | |
|         while :; do
 | |
|             while :; do
 | |
|                 status=`grep 'percent done:' $bittorrent_log | sed -ne '$p' | sed 's/percent done: *//' | sed -ne '/^[0-9]*\.[0-9]*$/p'`
 | |
|                 [ ! -z "$status" ] && break
 | |
|             done
 | |
|             logmsg "percent done: $status %"
 | |
|             if [ "$status" = "100.0" ]; then
 | |
|                 # Sleep until upload rate reaches the minimum threshold
 | |
|                 while [ "$bittorrent_seed_wait" = "y" ]; do
 | |
|                     sleep $bittorrent_polling_time
 | |
|                     while :; do
 | |
|                         upload_rate=`grep 'upload rate:' $bittorrent_log | sed -ne '$p' | sed 's/upload rate: *\([0-9]*\)\.[0-9]* .*$/\1/' | sed -ne '/^\([0-9]*\)$/p'`
 | |
|                         [ ! -z $upload_rate ] && break
 | |
|                     done
 | |
|                     logmsg "upload rate: $upload_rate KB/s"
 | |
|                     [ $upload_rate -lt $bittorrent_upload_min ] && break
 | |
|                 done
 | |
|                 logmsg "Download completed"
 | |
|                 unset bittorrent_log upload_rate counter
 | |
|                 break
 | |
|             fi
 | |
|             sleep $bittorrent_polling_time
 | |
|         done
 | |
| 
 | |
|         unset bittorrent_polling_time
 | |
|         unset bittorrent_seed_wait
 | |
|         unset bittorrent_upload_min
 | |
|         unset torrent
 | |
|         unset destination
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| #   Stop bittorrent client.
 | |
| #
 | |
| #   Usage: bittorrent_stop
 | |
| #
 | |
| bittorrent_stop() {
 | |
|     # Try to kill all the BitTorrent processes
 | |
|     btclient="bittorrent-console"
 | |
| 
 | |
|     logmsg "killing BitTorrent client..."
 | |
|     killall -15 $btclient >/dev/null 2>&1
 | |
| 
 | |
|     # Forced kill after 5 secs.
 | |
|     sleep 5
 | |
|     killall -9 $btclient >/dev/null 2>&1
 | |
| 
 | |
|     # Remove bittorrent logs.
 | |
|     rm -rf /tmp/bittorrent*.log
 | |
|     unset btclient
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| #   Get other binaries, kernel module tree, and miscellaneous other stuff that
 | |
| #   got put in the binaries tarball. -BEF-
 | |
| #
 | |
| get_boel_binaries_tarball() {
 | |
| 
 | |
|     logmsg
 | |
|     logmsg get_boel_binaries_tarball
 | |
| #    mkdir -p ${BOEL_BINARIES_DIR}
 | |
| #
 | |
| #    if [ ! -z $SSH_DOWNLOAD_URL ]; then
 | |
| #        # If we're using SSH, get the boel_binaries from a web server.
 | |
| #        logmsg "SSH_DOWNLOAD_URL variable is set, so we will install over SSH!"
 | |
| #
 | |
| #        if [ ! -z $FLAMETHROWER_DIRECTORY_PORTBASE ]; then
 | |
| #            logmsg "FLAMETHROWER_DIRECTORY_PORTBASE is also set, but I will be conservative and proceed with SSH."
 | |
| #        fi
 | |
| #
 | |
| #        # Remove possible trailing / from URL
 | |
| #        SSH_DOWNLOAD_URL=`echo $SSH_DOWNLOAD_URL | sed 's/\/$//'`
 | |
| #
 | |
| #        cd ${BOEL_BINARIES_DIR}
 | |
| #        CMD="wget ${SSH_DOWNLOAD_URL}/${ARCH}/${FLAVOR}/boel_binaries.tar.gz"
 | |
| #        logmsg "$CMD"
 | |
| #        $CMD || shellout
 | |
| #
 | |
| #    elif [ "x$BITTORRENT" = "xy" ]; then
 | |
| #
 | |
| #        # Download BOEL binaries from peers
 | |
| #        bittorrent_tarball="boel_binaries.tar.gz"
 | |
| #        logmsg "Start downloading ${bittorrent_tarball} (${ARCH}) using bittorrent"
 | |
| #        logmsg ""
 | |
| #        logmsg "--> INFO: remember to start /etc/init.d/systemimager-server-bittorrent on the image server!"
 | |
| #        logmsg ""
 | |
| #        bittorrent_get_file ${TORRENTS_DIR}/${ARCH}-${bittorrent_tarball}.torrent ${BOEL_BINARIES_DIR}
 | |
| #        cd ${BOEL_BINARIES_DIR} && mv ${ARCH}-${bittorrent_tarball} ${bittorrent_tarball}
 | |
| #        unset bittorrent_tarball
 | |
| #
 | |
| #    elif [ ! -z $FLAMETHROWER_DIRECTORY_PORTBASE ]; then
 | |
| #
 | |
| #        MODULE_NAME="boot-${ARCH}-${FLAVOR}"
 | |
| #        DIR="${BOEL_BINARIES_DIR}"
 | |
| #        RETRY=7
 | |
| #        flamethrower_client
 | |
| #
 | |
| #    else
 | |
| #        # Use rsync
 | |
| #        CMD="rsync -av ${IMAGESERVER}::boot/${ARCH}/${FLAVOR}/boel_binaries.tar.gz ${BOEL_BINARIES_DIR}"
 | |
| #        logmsg "$CMD"
 | |
| #        $CMD || shellout
 | |
| #    fi
 | |
| #
 | |
| #    # Untar the tarball
 | |
| #    tar -C / -xzf ${BOEL_BINARIES_DIR}/boel_binaries.tar.gz || shellout
 | |
| #    chown -R 0.0 /lib/modules || shellout
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| # Parse tmpfs options from /proc/cpuinfo
 | |
| # 
 | |
| parse_tmpfs_opts() {
 | |
|     logmsg
 | |
|     logmsg parse_tmpfs_opts
 | |
|     tmpfs_size=$(tr ' ' '\n' < /proc/cmdline | grep tmpfs_size\= | sed 's/.*=//')
 | |
|     tmpfs_nr_blocks=$(tr ' ' '\n' < /proc/cmdline | grep tmpfs_nr_blocks\= | sed 's/.*=//')
 | |
|     tmpfs_nr_inodes=$(tr ' ' '\n' < /proc/cmdline | grep tmpfs_nr_inodes\= | sed 's/.*=//')
 | |
|     tmpfs_mode=$(tr ' ' '\n' < /proc/cmdline | grep tmpfs_mode\= | sed 's/.*=//')
 | |
| 
 | |
|     if [ "$tmpfs_size" != "" ]; then
 | |
|         tmpfs_opts="size=$tmpfs_size"
 | |
|     fi
 | |
| 
 | |
|     if [ "$tmpfs_nr_blocks" != "" ]; then
 | |
|         if [ "$tmpfs_opts" != "" ]; then
 | |
|             tmpfs_opts="${tmpfs_opts},nr_blocks=$tmpfs_nr_blocks"
 | |
|         else
 | |
|             tmpfs_opts="nr_blocks=$tmpfs_nr_blocks"
 | |
|         fi
 | |
|     fi
 | |
| 
 | |
|     if [ "$tmpfs_nr_inodes" != "" ]; then
 | |
|         if [ "$tmpfs_opts" != "" ]; then
 | |
|             tmpfs_opts="${tmpfs_opts},nr_inodes=$tmpfs_nr_inodes"
 | |
|         else
 | |
|             tmpfs_opts="nr_inodes=$tmpfs_nr_inodes"
 | |
|             fi
 | |
|     fi
 | |
| 
 | |
|     if [ "$tmpfs_mode" != "" ]; then
 | |
|         if [ "$tmpfs_opts" != "" ]; then
 | |
|             tmpfs_opts="${tmpfs_opts},mode=$tmpfs_mode"
 | |
|         else
 | |
|             tmpfs_opts="mode=$tmpfs_mode"
 | |
|         fi
 | |
|     fi
 | |
| 
 | |
|     if [ "$tmpfs_opts" != "" ]; then
 | |
|         tmpfs_opts="-o $tmpfs_opts"
 | |
|     fi
 | |
| 
 | |
|     unset tmpfs_size
 | |
|     unset tmpfs_nr_blocks
 | |
|     unset tmpfs_nr_inodes
 | |
|     unset tmpfs_mode
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| #   Switch root to tmpfs
 | |
| #
 | |
| #switch_root_to_tmpfs() {
 | |
| #    local MODULE=tmpfs
 | |
| #    logmsg
 | |
| #    logmsg switch_root_to_tmpfs
 | |
| #    logmsg "Loading $MODULE... "
 | |
| #    modprobe $MODULE 2>/dev/null && logmsg "done!" || logmsg "Didn't load -- assuming it's built into the kernel."
 | |
| #    parse_tmpfs_opts
 | |
| #
 | |
| #    # Switch root over to tmpfs so we don't have to worry about the size of
 | |
| #    # the tarball and binaries that users may decide to copy over. -BEF-
 | |
| #    if [ -d /old_root ]; then
 | |
| #        logmsg
 | |
| #        logmsg "already switched to tmpfs..."
 | |
| #    else
 | |
| #        logmsg
 | |
| #        logmsg "switching root to tmpfs..."
 | |
| #
 | |
| #        mkdir -p /new_root || shellout
 | |
| #        mount tmpfs /new_root -t tmpfs $tmpfs_opts || shellout
 | |
| #
 | |
| #        cd / || shellout
 | |
| #        cp -a `/bin/ls | grep -v -E '^(new_root|dev)$'` /new_root/ || shellout
 | |
| #
 | |
| #		mkdir -p /new_root/dev || shellout
 | |
| #		mount -t devtmpfs -o mode=0755 none /new_root/dev || shellout
 | |
| #
 | |
| #        cd /new_root || shellout
 | |
| #        mkdir -p old_root || shellout
 | |
| #        pivot_root . old_root || switch_root
 | |
| #    fi
 | |
| #
 | |
| #    unset tmpfs_opts
 | |
| #}
 | |
| #
 | |
| ################################################################################
 | |
| ################################################################################
 | |
| #
 | |
| mount_initial_filesystems() {
 | |
| 
 | |
|     # Much of this taken from "init" from an Ubuntu Lucid initrd.img
 | |
|     logmsg
 | |
|     logmsg mount_initial_filesystems
 | |
| 
 | |
|     [ -d /dev ]  || mkdir -m 0755 /dev
 | |
|     [ -d /root ] || mkdir -m 0700 /root
 | |
|     [ -d /sys ]  || mkdir /sys
 | |
|     [ -d /proc ] || mkdir /proc
 | |
|     [ -d /tmp ]  || mkdir /tmp
 | |
| 
 | |
|     mkdir -p /var/lock
 | |
| 
 | |
|     mount -t sysfs -o nodev,noexec,nosuid none /sys
 | |
|     mount -t proc  -o nodev,noexec,nosuid none /proc
 | |
| 
 | |
|     # Note that this only becomes /dev on the real filesystem if udev's scripts
 | |
|     # are used; which they will be, but it's worth pointing out
 | |
|     if ! mount -t devtmpfs -o mode=0755 none /dev; then
 | |
|         mount -t tmpfs -o mode=0755 none /dev
 | |
|         mknod -m 0600 /dev/console c 5 1
 | |
|         mknod -m 0666 /dev/null c 1 3
 | |
|         mknod -m 0660 /dev/kmsg c 1 11
 | |
|     fi
 | |
| 
 | |
|     mkdir /dev/pts
 | |
|     mount -t devpts -o noexec,nosuid,gid=5,mode=0620 none /dev/pts || true
 | |
| 
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| ################################################################################
 | |
| #
 | |
| monitor_save_dmesg() {
 | |
|     if [ -z $MONITOR_SERVER ]; then
 | |
|         return
 | |
|     fi
 | |
|     logmsg
 | |
|     logmsg monitor_save_dmesg
 | |
|     dmesg -s 16392 > /tmp/si_monitor.log
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| start_udevd() {
 | |
|     logmsg
 | |
|     logmsg start_udevd
 | |
|     echo -n "  "
 | |
|     /etc/init.d/udev start
 | |
| 
 | |
|     # If udev failed fall back to a static /dev
 | |
|     if [ $? -ne 0 ]; then
 | |
|         logmsg "failed!"
 | |
| #XXX -delete me -BEF- -        logmsg "Creating a static /dev..."
 | |
| #        cd / && tar -xzf dev.tar.gz || shellout
 | |
|         logmsg done
 | |
|     fi
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| # Configure loopback interface (may as well)
 | |
| ifconfig_loopback() {
 | |
|     logmsg
 | |
|     logmsg ifconfig_loopback
 | |
|     ifconfig lo 127.0.0.1
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| # Load any modules that were placed in the my_modules directory prior to
 | |
| # running "make initrd.gz".  -BEF-
 | |
| load_my_modules() {
 | |
|     logmsg
 | |
|     logmsg load_my_modules
 | |
|     cd /my_modules || shellout
 | |
|     sh ./INSMOD_COMMANDS
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| # read in varibles obtained from kernel appends
 | |
| #
 | |
| read_kernel_append_parameters() {
 | |
|     logmsg
 | |
|     logmsg read_kernel_append_parameters
 | |
| 
 | |
|     . /tmp/kernel_append_parameter_variables.txt
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| # Variable-ize /proc/cmdline arguments
 | |
| #
 | |
| variableize_kernel_append_parameters() {
 | |
|     logmsg
 | |
|     logmsg variableize_kernel_append_parameters
 | |
|     cat /proc/cmdline | tr ' ' '\n' | grep '=' > /tmp/kernel_append_parameter_variables.txt
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| # Look for local.cfg file
 | |
| #   This code inspired by Ian McLeod <ian@valinux.com>
 | |
| #
 | |
| read_local_cfg() {
 | |
|     logmsg
 | |
|     logmsg read_local_cfg
 | |
| 
 | |
|     if [ "x$SKIP_LOCAL_CFG" = "xy" ]; then
 | |
|         logmsg "Skipping local.cfg: option SKIP_LOCAL_CFG=y has been specified"
 | |
|         return
 | |
|     fi
 | |
| 
 | |
|     # Try with local.cfg directly from initrd.
 | |
|     if [ -f /local.cfg ]; then
 | |
|         cp -f /local.cfg /tmp/local.cfg
 | |
|     fi
 | |
| 
 | |
|     #
 | |
|     # BEGIN try hard drive
 | |
|     #
 | |
|     if [ ! -z "$LAST_ROOT" ]; then
 | |
| 
 | |
|         logmsg
 | |
|         logmsg "Checking for /local.cfg file on hard drive..."
 | |
|         mkdir /last_root
 | |
|         logmsg "Mounting hard drive..."
 | |
|         mount $LAST_ROOT /last_root -o ro > /dev/null 2>&1
 | |
|         if [ $? != 0 ]; then
 | |
|             logmsg "FATAL: Couldn't mount hard drive!"
 | |
|             logmsg "Your kernel must have all necessary block and filesystem drivers compiled in"
 | |
|             logmsg "statically (not modules) in order to use a local.cfg on your hard drive.  The"
 | |
|             logmsg "standard SystemImager kernel is modular, so you will need to compile your own"
 | |
|             logmsg "kernel.  See the SystemImager documentation for details.  To proceed at this"
 | |
|             logmsg "point, you will need to unset the LAST_ROOT append parameter by typing"
 | |
|             logmsg ""systemimager LAST_ROOT=", or similar, at your boot prompt.  This will not use"
 | |
|             logmsg "the local.cfg file on your hard drive, but will still use one on a floppy."
 | |
|             shellout
 | |
|         fi
 | |
| 
 | |
|         if [ -f /last_root/local.cfg ]; then
 | |
|             logmsg "Found /local.cfg on hard drive."
 | |
|             logmsg "Copying /local.cfg settings to /tmp/local.cfg."
 | |
|             cat /last_root/local.cfg >> /tmp/local.cfg || shellout
 | |
|         else
 | |
|             logmsg "No /local.cfg on hard drive."
 | |
|         fi
 | |
|         logmsg "Unmounting hard drive..."
 | |
|         umount /last_root || shellout
 | |
|         logmsg
 | |
|     fi
 | |
|     # END try hard drive
 | |
| 
 | |
|     ### BEGIN try floppy ###
 | |
|     logmsg "Checking for floppy diskette."
 | |
|     logmsg 'YOU MAY SEE SOME "wrong magic" ERRORS HERE, AND THAT IS NORMAL.'
 | |
|     mkdir -p /floppy
 | |
|     mount /dev/fd0 /floppy -o ro > /dev/null 2>&1
 | |
|     if [ $? = 0 ]; then
 | |
|         logmsg "Found floppy diskette."
 | |
|         if [ -f /floppy/local.cfg ]; then
 | |
|             logmsg "Found /local.cfg on floppy."
 | |
|             logmsg "Copying /local.cfg settings to /tmp/local.cfg."
 | |
|             logmsg "NOTE: local.cfg settings from a floppy will override settings from"
 | |
|             logmsg "      a local.cfg file on your hard drive and DHCP."
 | |
|             # We use cat instead of copy, so that floppy settings can
 | |
|             # override hard disk settings. -BEF-
 | |
|             cat /floppy/local.cfg >> /tmp/local.cfg || shellout
 | |
|         else
 | |
|             logmsg "No /local.cfg on floppy diskette."
 | |
|         fi
 | |
|     else
 | |
|         logmsg "No floppy diskette in drive."
 | |
|     fi
 | |
|     ### END try floppy ###
 | |
| 
 | |
|     # /tmp/local.cfg may be created from a local.cfg file on the hard drive, or a
 | |
|     # floppy.  If both are used, settings on the floppy take precedence. -BEF-
 | |
|     if [ -f /tmp/local.cfg ]; then
 | |
|         logmsg "Reading configuration from /tmp/local.cfg"
 | |
|         . /tmp/local.cfg || shellout
 | |
|     fi
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| #   Configure network interface using local.cfg settings if possible, else
 | |
| #   use DHCP. -BEF-
 | |
| #
 | |
| start_network() {
 | |
|     logmsg
 | |
|     logmsg start_network
 | |
|     if [ ! -z $IPADDR ]; then
 | |
| 
 | |
|         # configure interface and add default gateway
 | |
|         ifconfig $DEVICE $IPADDR  netmask $NETMASK  broadcast $BROADCAST
 | |
|         if [ $? != 0 ]; then
 | |
|             logmsg
 | |
|             logmsg "I couldn't configure the network interface using your pre-boot settings:"
 | |
|             logmsg "  DEVICE:     $DEVICE"
 | |
|             logmsg "  IPADDR:     $IPADDR"
 | |
|             logmsg "  NETMASK:    $NETMASK"
 | |
|             logmsg "  BROADCAST:  $BROADCAST"
 | |
|             logmsg
 | |
|             shellout
 | |
|         fi
 | |
| 
 | |
|         if [ ! -z $GATEWAY ]; then
 | |
|             route add default gw $GATEWAY
 | |
|             if [ $? != 0 ]; then
 | |
|                 logmsg
 | |
|                 logmsg "The command \"route add default gw $GATEWAY\" failed."
 | |
|                 logmsg "Check your pre-boot network settings."
 | |
|                 logmsg
 | |
|                 shellout
 | |
|             fi
 | |
|         fi
 | |
| 
 | |
|     else
 | |
| 
 | |
|         ### try dhcp ###
 | |
|         logmsg "IP Address not set with pre-boot settings."
 | |
|         
 | |
|         ### BEGIN ether sleep ###
 | |
|         # Give the switch time to start passing packets.  Some switches won't
 | |
|         # forward packets until 30 seconds or so after an interface comes up.
 | |
|         # This means the dhcp server won't even get the request for 30 seconds.
 | |
|         # Many ethernet cards aren't considered "up" by the switch until the
 | |
|         # driver is loaded.  Because the driver is compiled directly into the
 | |
|         # kernel here, the driver is definitely loaded at this point. 
 | |
|         # 
 | |
|         # Default is 0.  The recommended setting of ETHER_SLEEP=35 can be set 
 | |
|         # with a local.cfg file. -BEF-
 | |
|         #
 | |
|         [ -z $ETHER_SLEEP ] && ETHER_SLEEP=0
 | |
|         logmsg
 | |
|         logmsg "sleep $ETHER_SLEEP:  This is to give your switch (if you're using one) time to"
 | |
|         logmsg "           recognize your ethernet card before we try the network."
 | |
|         logmsg "           Tip: You can use <ctrl>+<c> to pass the time (pun intended)."
 | |
|         logmsg
 | |
|         count_loop $ETHER_SLEEP
 | |
|         logmsg
 | |
|         ### END ether sleep ###
 | |
|         
 | |
|         # create directory to catch dhcp information
 | |
|         DHCLIENT_DIR="/var/state/dhcp"
 | |
|         mkdir -p $DHCLIENT_DIR
 | |
|         
 | |
|         # combine systemimager code to the stock debian dhclient-script
 | |
|         # and make executable
 | |
|         cat /etc/dhclient-script.si-prefix \
 | |
|             /etc/dhclient-script.debian-dist \
 | |
|             > /etc/dhclient-script
 | |
|         chmod +x /etc/dhclient-script
 | |
| 
 | |
|         # be sure AF_PACKET is supported in the kernel
 | |
|         [ -f /lib/modules/`uname -r`/modules.dep ] && modprobe af_packet &> /dev/null
 | |
|         
 | |
|         # get info via dhcp
 | |
|         logmsg
 | |
|         logmsg "dhclient"
 | |
|         dhclient $DEVICE
 | |
|         if [ ! -s ${DHCLIENT_DIR}/dhclient.leases ]; then
 | |
|             logmsg
 | |
|             logmsg "I couldn't configure the network interface using DHCP."
 | |
|             logmsg
 | |
|             shellout
 | |
|         fi
 | |
|         
 | |
|         if [ -z ${DEVICE} ]; then
 | |
|             # Figure out which interface actually got configured.
 | |
|             # Suggested by James Oakley.
 | |
|             #
 | |
|             DEVICE=`grep interface ${DHCLIENT_DIR}/dhclient.leases | \
 | |
|                 sed -e 's/^.*interface "//' -e 's/";//'`
 | |
|         fi
 | |
|         
 | |
|         # read dhcp info in as variables -- this file will be created by 
 | |
|         # the /etc/dhclient-start script that is run automatically by
 | |
|         # dhclient.
 | |
|         . /tmp/dhcp_info.${DEVICE} || shellout
 | |
|         ### END dhcp ###
 | |
|         
 | |
|         # Re-read configuration information from local.cfg to over-ride
 | |
|         # DHCP settings, if necessary. -BEF-
 | |
|         if [ -f /tmp/local.cfg ]; then
 | |
|             logmsg
 | |
|             logmsg "Overriding any DHCP settings with pre-boot local.cfg settings."
 | |
|             . /tmp/local.cfg || shellout
 | |
|         fi
 | |
| 
 | |
|         logmsg
 | |
|         logmsg "Overriding any DHCP settings with pre-boot settings from kernel append"
 | |
|         logmsg "parameters."
 | |
|         read_kernel_append_parameters
 | |
|     fi
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| #   Ping test
 | |
| ping_test() {
 | |
|     logmsg
 | |
|     logmsg ping_test
 | |
| 
 | |
|     # The reason we don't ping the IMAGESERVER if FLAMETHROWER_DIRECTORY_PORTBASE
 | |
|     # is set, is that the client may never be given, know, or need to know, the 
 | |
|     # IP address of the imageserver because the client is receiving _all_ of it's
 | |
|     # data via multicast, which is more like listening to a channel, as compared 
 | |
|     # with connecting directly to a server.  -BEF-
 | |
|     #
 | |
|     if [ ! -z "$FLAMETHROWER_DIRECTORY_PORTBASE" ]; then
 | |
|         PING_DESTINATION=$GATEWAY
 | |
|         HOST_TYPE="default gateway"
 | |
|     else
 | |
|         PING_DESTINATION=$IMAGESERVER
 | |
|         HOST_TYPE="SystemImager server"
 | |
|     fi 
 | |
|     logmsg
 | |
|     logmsg "Pinging your $HOST_TYPE to ensure we have network connectivity."
 | |
|     logmsg
 | |
| 
 | |
| 
 | |
|     # Ping test code submitted by Grant Noruschat <grant@eigen.ee.ualberta.ca>
 | |
|     # modified slightly by Brian Finley.
 | |
|     PING_COUNT=1
 | |
|     PING_EXIT_STATUS=1
 | |
|     while [ "$PING_EXIT_STATUS" != "0" ]
 | |
|     do
 | |
|         logmsg "PING ATTEMPT $PING_COUNT: "
 | |
|         ping -c 1 $PING_DESTINATION
 | |
|         PING_EXIT_STATUS=$?
 | |
| 
 | |
|         if [ "$PING_EXIT_STATUS" = "0" ]; then
 | |
|             logmsg
 | |
|             logmsg "  We have connectivity to your $HOST_TYPE!"
 | |
|         fi
 | |
| 
 | |
|         PING_COUNT=$(( $PING_COUNT + 1 ))
 | |
|         if [ "$PING_COUNT" = "4" ]; then
 | |
|             logmsg
 | |
|             logmsg "  WARNING:  Failed ping test."
 | |
|             logmsg "            Despite this seemingly depressing result, I will attempt"
 | |
|             logmsg "            to proceed with the install.  Your $HOST_TYPE may be"
 | |
|             logmsg "            configured to not respond to pings, but it wouldn't hurt"
 | |
|             logmsg "            to double check that your networking equipment is"
 | |
|             logmsg "            working properly!"
 | |
|             logmsg
 | |
|             sleep 5
 | |
|             PING_EXIT_STATUS=0
 | |
|         fi
 | |
|     done
 | |
| 
 | |
|     unset PING_DESTINATION
 | |
|     unset HOST_TYPE
 | |
| 
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| start_syslogd() {
 | |
|     logmsg
 | |
|     logmsg start_syslogd
 | |
|     if [ ! -z $LOG_SERVER ]; then
 | |
|         logmsg "Starting syslogd..."
 | |
|         [ -z $LOG_SERVER_PORT ] && LOG_SERVER_PORT="514"
 | |
|         syslogd -R ${LOG_SERVER}:${LOG_SERVER_PORT}
 | |
|         # as long as we are starting syslogd, start klogd as well, in case
 | |
|         # there is a kernel issue that happens
 | |
|         klogd
 | |
|         # set USELOGGER=1 so logmsg knows to do the right thing
 | |
|         USELOGGER=1
 | |
|         logmsg "Successfully started syslogd!"
 | |
|     fi
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| show_loaded_modules() {
 | |
|     # Show loaded modules
 | |
|     logmsg ">> Loaded kernel modules:"
 | |
|     for m in `cut -d' ' -f1 /proc/modules`; do
 | |
|         logmsg "$m"
 | |
|     done
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| get_hostname_by_hosts_file() {
 | |
| 
 | |
|     logmsg
 | |
|     logmsg get_hostname_by_hosts_file
 | |
| 
 | |
|     #
 | |
|     # Look in $FILE for that magic joy.
 | |
|     #
 | |
|     FILE=${SCRIPTS_DIR}/hosts
 | |
|     if [ -e $FILE ]; then
 | |
| 
 | |
|         logmsg "Hosts file exists..."
 | |
| 
 | |
|         # add escape characters to IPADDR so that it can be used to find HOSTNAME below
 | |
|         IPADDR_ESCAPED=`echo "$IPADDR" | sed -e 's/\./\\\./g'`
 | |
|         
 | |
|         # get HOSTNAME by parsing hosts file
 | |
|         logmsg "Searching for this machine's hostname in $FILE by IP: $IPADDR"
 | |
|         
 | |
|         # Command summary by line:
 | |
|         # 1: convert tabs to spaces -- contains a literal tab: <ctrl>+<v> then <tab>
 | |
|         # 2: remove comments
 | |
|         # 3: add a space at the beginning of every line
 | |
|         # 4: get line with IP address (no more no less)
 | |
|         # 5: strip out ip address
 | |
|         # 6: strip out space(s) before first hostname on line
 | |
|         # 7: remove any aliases on line
 | |
|         # 8: remove domain name, leaving naught but the hostname, naked as the day it were born
 | |
|         
 | |
|         HOSTNAME=`
 | |
|             sed 's/[[:space:]]/ /g' $FILE | \
 | |
|             grep -v '^ *#' | \
 | |
|             sed 's/^/ /' | \
 | |
|             grep " $IPADDR_ESCAPED " | \
 | |
|             sed 's/ [0-9]*\.[0-9]*\.[0-9]*\.[0-9]*//' | \
 | |
|             sed 's/ *//' | \
 | |
|             sed 's/ .*//' | \
 | |
|             sed 's/\..*$//g'
 | |
|         `
 | |
|     else
 | |
|         logmsg "No hosts file."
 | |
|     fi
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| get_hostname_by_dns() {
 | |
| 
 | |
|     logmsg
 | |
|     logmsg get_hostname_by_dns
 | |
| 
 | |
|     # Get base hostname.  For example, www7.domain.com will become www7. -BEF-
 | |
|     HOSTNAME=`nslookup $IPADDR | sed -ne "s/^Address 1:[[:space:]]\+$IPADDR[[:space:]]\+\([^\.]\+\).*$/\1/p"`
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| get_base_hostname() {
 | |
|     BASE_HOSTNAME=`echo $HOSTNAME | sed "s/[.0-9].*$//"` 
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| get_group_name() {
 | |
|     if [ -f ${SCRIPTS_DIR}/cluster.txt ]; then
 | |
|         [ -z "$GROUPNAMES" ] && \
 | |
|             GROUPNAMES=`unique $(grep "^${HOSTNAME}:" ${SCRIPTS_DIR}/cluster.txt | cut -d: -f2 | tr "\n" ' ')`
 | |
|         [ -z "$IMAGENAME" ] && \
 | |
|             IMAGENAME=`grep "^${HOSTNAME}:" ${SCRIPTS_DIR}/cluster.txt | cut -d: -f3 | grep -v '^[[:space:]]*$' | sed -ne '1p'`
 | |
|         if [ -z "$GROUP_OVERRIDES" ]; then
 | |
|             GROUP_OVERRIDES=`reverse $(unique $(grep "^${HOSTNAME}:" ${SCRIPTS_DIR}/cluster.txt | cut -d: -f4 | tr "\n" ' '))`
 | |
|             # Add the global override on top (least important).
 | |
|             GROUP_OVERRIDES="`sed -ne 's/^# global_override=:\([^:]*\):$/\1/p' ${SCRIPTS_DIR}/cluster.txt` $GROUP_OVERRIDES"
 | |
|         fi
 | |
|     fi
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| choose_autoinstall_script() {
 | |
| 
 | |
|     logmsg
 | |
|     logmsg choose_autoinstall_script
 | |
| 
 | |
|     #
 | |
|     # Get the base hostname for the last attempt at choosing an autoinstall
 | |
|     # script.  For example, if the hostname is compute99, then try to get 
 | |
|     # compute.master. -BEF-
 | |
|     #
 | |
|     get_base_hostname
 | |
| 
 | |
|     # Get group name (defined in /etc/systemimager/cluster.xml on the image
 | |
|     # server). -AR-
 | |
|     get_group_name
 | |
| 
 | |
|     # 
 | |
|     # If SCRIPTNAME is specified as a kernel append, or via local.cfg, then use that script.
 | |
|     #
 | |
|     if [ ! -z $SCRIPTNAME ]; then
 | |
|         #
 | |
|         # SCRIPTNAME was specified, but let's be flexible.  Try explicit first, then .master, .sh. -BEF-
 | |
|         #
 | |
|         SCRIPTNAMES="${SCRIPTS_DIR}/${SCRIPTNAME} ${SCRIPTS_DIR}/${SCRIPTNAME}.sh ${SCRIPTS_DIR}/${SCRIPTNAME}.master"
 | |
| 
 | |
|     else
 | |
|         # 
 | |
|         # If SCRIPTNAME was not specified, choose one, in order of preference.  First hit wins.
 | |
|         # Order of preference is:
 | |
|         #   HOSTNAME                (i.e. node001.sh)
 | |
|         #   GROUPNAMES              (i.e. Login.sh) - see /etc/systemimager/cluster.xml on the image server
 | |
|         #   BASE_HOSTNAME           (i.e. node.sh)
 | |
|         #   IMAGENAME               (i.e. ubuntu7_04.sh)
 | |
|         #
 | |
|         [ ! -z $HOSTNAME ] && \
 | |
|             SCRIPTNAMES="${SCRIPTNAMES} ${SCRIPTS_DIR}/${HOSTNAME}.sh ${SCRIPTS_DIR}/${HOSTNAME}.master"
 | |
|         for GROUPNAME in $GROUPNAMES; do
 | |
|             SCRIPTNAMES="${SCRIPTNAMES} ${SCRIPTS_DIR}/${GROUPNAME}.sh ${SCRIPTS_DIR}/${GROUPNAME}.master"
 | |
|         done
 | |
|         unset GROUPNAME
 | |
|         [ ! -z $BASE_HOSTNAME ] && \
 | |
|             SCRIPTNAMES="${SCRIPTNAMES} ${SCRIPTS_DIR}/${BASE_HOSTNAME}.sh ${SCRIPTS_DIR}/${BASE_HOSTNAME}.master"
 | |
|         [ ! -z $IMAGENAME ] && \
 | |
|             SCRIPTNAMES="${SCRIPTNAMES} ${SCRIPTS_DIR}/${IMAGENAME}.sh ${SCRIPTS_DIR}/${IMAGENAME}.master"
 | |
|     fi
 | |
| 
 | |
|     #
 | |
|     # Choose a winner!
 | |
|     #
 | |
|     for SCRIPTNAME in $SCRIPTNAMES
 | |
|     do
 | |
|         [ -e $SCRIPTNAME ] && break
 | |
|     done
 | |
| 
 | |
|     # Did we really find one, or just exit the loop without a 'break'
 | |
|     if [ ! -e $SCRIPTNAME ]; then
 | |
|         logmsg "FATAL: couldn't find any of the following autoinstall scripts!"
 | |
|         logmsg "---"
 | |
|         logmsg ${SCRIPTNAMES}
 | |
|         logmsg "---"
 | |
| 	logmsg "Be sure that at least one of the scripts above exists in"
 | |
|         logmsg "the autoinstall scripts directory on your image server."
 | |
|         logmsg
 | |
|         logmsg "See also: si_mkautoinstallscript(8)."
 | |
|         shellout
 | |
|     fi
 | |
|     logmsg "Using autoinstall script: ${SCRIPTNAME}"
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| run_autoinstall_script() {
 | |
| 
 | |
|     logmsg
 | |
|     logmsg run_autoinstall_script
 | |
| 
 | |
|     # Run the autoinstall script.
 | |
|     chmod 755 $SCRIPTNAME || shellout
 | |
|     logmsg ">>> $SCRIPTNAME"
 | |
|     $SCRIPTNAME || shellout
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| # Description: remove duplicated elements from a list, preserving the order.
 | |
| #
 | |
| unique() {
 | |
|     ret=
 | |
|     for i in $*; do
 | |
|         flag=0
 | |
|         for j in $ret; do
 | |
|             [ "$i" = "$j" ] && flag=1 && break
 | |
|         done
 | |
|         [ $flag -eq 0 ] && ret="$ret $i"
 | |
|     done
 | |
|     echo $ret
 | |
|     unset i j flag ret
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| # Description: reverse a list
 | |
| #
 | |
| reverse() {
 | |
|     ret=
 | |
|     for i in $*; do
 | |
|         ret="$i $ret"
 | |
|     done
 | |
|     echo $ret
 | |
|     unset i
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| run_pre_install_scripts() {
 | |
| 
 | |
|     logmsg
 | |
|     logmsg run_pre_install_scripts
 | |
| 
 | |
|     get_base_hostname
 | |
| 
 | |
|     # Get group name (defined in /etc/systemimager/cluster.xml on the image
 | |
|     # server). -AR-
 | |
|     get_group_name
 | |
| 
 | |
|     if [ -e "${SCRIPTS_DIR}/pre-install/" ]; then
 | |
| 
 | |
|         cd ${SCRIPTS_DIR}/pre-install/
 | |
| 
 | |
|         PRE_INSTALL_SCRIPTS="$PRE_INSTALL_SCRIPTS `ls | grep "^[0-9][0-9]all\..*"`"
 | |
|         PRE_INSTALL_SCRIPTS="$PRE_INSTALL_SCRIPTS `ls | grep "^[0-9][0-9]${IMAGENAME}\..*"`"
 | |
|         PRE_INSTALL_SCRIPTS="$PRE_INSTALL_SCRIPTS `ls | grep "^[0-9][0-9]${BASE_HOSTNAME}\..*"`"
 | |
|         for GROUPNAME in ${GROUPNAMES}; do
 | |
|             PRE_INSTALL_SCRIPTS="$PRE_INSTALL_SCRIPTS `ls | grep "^[0-9][0-9]${GROUPNAME}\..*"`"
 | |
|         done
 | |
|         unset GROUPNAME
 | |
|         PRE_INSTALL_SCRIPTS="$PRE_INSTALL_SCRIPTS `ls | grep "^[0-9][0-9]${HOSTNAME}\..*"`"
 | |
| 
 | |
|         # Now, to get rid of those pesky newlines. -BEF-
 | |
|         PRE_INSTALL_SCRIPTS=`echo $PRE_INSTALL_SCRIPTS | tr '\n' ' '`
 | |
|         
 | |
|         if [ ! -z "`echo ${PRE_INSTALL_SCRIPTS}|sed 's/ //'`" ]; then
 | |
| 
 | |
|             for PRE_INSTALL_SCRIPT in `unique $PRE_INSTALL_SCRIPTS`
 | |
|             do
 | |
|                 logmsg ">>> $PRE_INSTALL_SCRIPT"
 | |
|                 chmod +x $PRE_INSTALL_SCRIPT || shellout
 | |
|                 ./$PRE_INSTALL_SCRIPT || shellout
 | |
|             done
 | |
|         else
 | |
|             logmsg "No pre-install scripts found."
 | |
|         fi
 | |
| 
 | |
|         if [ -e "/tmp/pre-install_variables.txt" ]; then
 | |
|             . /tmp/pre-install_variables.txt
 | |
|         fi
 | |
| 
 | |
|     fi
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| run_post_install_scripts() {
 | |
| 
 | |
|     logmsg
 | |
|     logmsg run_post_install_scripts
 | |
| 
 | |
|     get_base_hostname
 | |
| 
 | |
|     # Get group name (defined in /etc/systemimager/cluster.xml on the image
 | |
|     # server). -AR-
 | |
|     get_group_name
 | |
| 
 | |
|     if [ -e "${SCRIPTS_DIR}/post-install/" ]; then
 | |
| 
 | |
|         # make a copy of variables.txt available to post-install scripts -BEF-
 | |
|         cp -f /tmp/variables.txt ${SCRIPTS_DIR}/post-install/
 | |
| 
 | |
|         cd ${SCRIPTS_DIR}/post-install/
 | |
| 
 | |
|         POST_INSTALL_SCRIPTS="$POST_INSTALL_SCRIPTS `ls | grep "^[0-9][0-9]all\..*" | grep -v "~$" `"
 | |
|         POST_INSTALL_SCRIPTS="$POST_INSTALL_SCRIPTS `ls | grep "^[0-9][0-9]${IMAGENAME}\..*" | grep -v "~$" `"
 | |
|         POST_INSTALL_SCRIPTS="$POST_INSTALL_SCRIPTS `ls | grep "^[0-9][0-9]${BASE_HOSTNAME}\..*" | grep -v "~$" `"
 | |
|         for GROUPNAME in ${GROUPNAMES}; do
 | |
|             POST_INSTALL_SCRIPTS="$POST_INSTALL_SCRIPTS `ls | grep "^[0-9][0-9]${GROUPNAME}\..*" | grep -v "~$" `"
 | |
|         done
 | |
|         POST_INSTALL_SCRIPTS="$POST_INSTALL_SCRIPTS `ls | grep "^[0-9][0-9]${HOSTNAME}\..*" | grep -v "~$" `"
 | |
| 
 | |
|         # Now, to get rid of those pesky newlines. -BEF-
 | |
|         POST_INSTALL_SCRIPTS=`echo $POST_INSTALL_SCRIPTS | tr '\n' ' '`
 | |
|         
 | |
|         if [ ! -z "`echo ${POST_INSTALL_SCRIPTS}|sed 's/ //'`" ]; then
 | |
| 
 | |
|             mkdir -p /a/tmp/post-install/ || shellout
 | |
| 
 | |
|             rsync -a ${SCRIPTS_DIR}/post-install/ /a/tmp/post-install/ || shellout
 | |
| 
 | |
|             for POST_INSTALL_SCRIPT in `unique $POST_INSTALL_SCRIPTS`
 | |
|             do
 | |
|                 if [ -e "$POST_INSTALL_SCRIPT" ]; then
 | |
|                     logmsg ">>> $POST_INSTALL_SCRIPT"
 | |
|                     chmod +x /a/tmp/post-install/$POST_INSTALL_SCRIPT || shellout
 | |
|                     chroot /a/ /tmp/post-install/$POST_INSTALL_SCRIPT || shellout
 | |
|                 fi
 | |
|             done
 | |
|         else
 | |
|             logmsg "No post-install scripts found."
 | |
|         fi
 | |
| 
 | |
|         # Clean up post-install script directory.
 | |
|         rm -rf /a/tmp/post-install/ || shellout
 | |
|     fi
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| #   Stuff for SSH installs
 | |
| #
 | |
| 
 | |
| 
 | |
| start_sshd() {
 | |
|     mkdir -p /root/.ssh/ || shellout
 | |
| 
 | |
|     # download ssh authorized_keys if it's not present into the initrd.
 | |
|     if [ ! -f /root/.ssh/authorized_keys ]; then
 | |
|         if [ -z $SSH_DOWNLOAD_URL ]; then
 | |
|             logmsg
 | |
|             logmsg "error: authorized_keys not found and SSH_DOWNLOAD_URL not defined in the installation parameters!"
 | |
|             logmsg "sshd can't be started!"
 | |
|             shellout
 | |
|         fi
 | |
|         CMD="wget ${SSH_DOWNLOAD_URL}/${ARCH}/ssh/authorized_keys"
 | |
|         logmsg
 | |
|         logmsg $CMD
 | |
|         $CMD || shellout
 | |
|     fi
 | |
| 
 | |
|     # set permissions to 600 -- otherwise, sshd will refuse to use it
 | |
|     chmod 600 /root/.ssh/authorized_keys || shellout
 | |
| 
 | |
|     # must be owned by root
 | |
|     chown -R 0.0 /root/
 | |
|         
 | |
|     # create a private host key for this autoinstall client
 | |
|     logmsg
 | |
|     logmsg "Using ssh-keygen to create this hosts private key"
 | |
|     logmsg
 | |
|     mkdir -p /var/empty || shellout
 | |
|     if [ ! -f /etc/ssh/ssh_host_dsa_key ]; then
 | |
|         ssh-keygen -t dsa -N "" -f /etc/ssh/ssh_host_dsa_key || shellout
 | |
|     fi
 | |
|     if [ ! -f /etc/ssh/ssh_host_rsa_key ]; then
 | |
|         ssh-keygen -t rsa -N "" -f /etc/ssh/ssh_host_rsa_key || shellout
 | |
|     fi
 | |
| 
 | |
|     # try to mount devpts (sometimes it's not really necessary)
 | |
|     mkdir -p /dev/pts
 | |
|     mount -t devpts none /dev/pts >/dev/null 2>&1
 | |
| 
 | |
|     # fire up sshd
 | |
|     mkdir -p /var/run/sshd || shellout
 | |
|     chmod 0755 /var/run/sshd || shellout
 | |
|     /usr/sbin/sshd || shellout
 | |
|     logmsg "sshd started"
 | |
|     touch /tmp/sshd_started
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| start_ssh() {
 | |
| 
 | |
|     # create root's ssh dir
 | |
|     mkdir -p /root/.ssh
 | |
| 
 | |
|     ############################################################################
 | |
|     #
 | |
|     # If a private key exists, put it in the right place so this autoinstall
 | |
|     # client can use it to authenticate itself to the imageserver.
 | |
|     #
 | |
|     if [ -e /root/.ssh/id_dsa ]; then
 | |
|         # (ssh2 dsa style user private key)
 | |
|         PRIVATE_KEY=/root/.ssh/id_dsa
 | |
|         chmod 600 $PRIVATE_KEY         || shellout
 | |
|     elif [ -e /root/.ssh/id_rsa ]; then
 | |
|         # (ssh2 rsa style user private key)
 | |
|         PRIVATE_KEY=/root/.ssh/id_rsa
 | |
|         chmod 600 $PRIVATE_KEY         || shellout
 | |
|     elif [ -e /floppy/id_dsa ]; then
 | |
|         # (ssh2 dsa style user private key) from floppy
 | |
|         PRIVATE_KEY=/root/.ssh/id_dsa
 | |
|         cp /floppy/id_dsa $PRIVATE_KEY || shellout
 | |
|         chmod 600 $PRIVATE_KEY         || shellout
 | |
|     elif [ -e /floppy/id_rsa ]; then
 | |
|         #
 | |
|         # (ssh2 rsa style user private key) from floppy
 | |
|         PRIVATE_KEY=/root/.ssh/id_rsa
 | |
|         cp /floppy/id_rsa $PRIVATE_KEY || shellout
 | |
|         chmod 600 $PRIVATE_KEY         || shellout
 | |
|     fi
 | |
|     #
 | |
|     ############################################################################
 | |
| 
 | |
|     # If we have a private key from the media above, go ahead and open secure tunnel
 | |
|     # to the imageserver and continue with the autoinstall like normal.
 | |
|     if [ ! -z $PRIVATE_KEY ]; then
 | |
| 
 | |
|         # With the prep ready, start the ssh tunnel connection.
 | |
|         #
 | |
|         # Determine if we should run interactive and set redirection options appropriately.
 | |
|         # So if the key is blank, go interactive. (Suggested by Don Stocks <don_stocks@leaseloan.com>)
 | |
|         if [ -s $PRIVATE_KEY ]; then
 | |
|             # key is *not* blank
 | |
|             REDIRECTION_OPTIONS="> /dev/null 2>&1"
 | |
|         else
 | |
|             # key is blank - go interactive
 | |
|             REDIRECTION_OPTIONS=""
 | |
|         fi
 | |
| 
 | |
|         # Default ssh user is root.
 | |
|         [ -z $SSH_USER ] && SSH_USER=root
 | |
| 
 | |
|         CMD="ssh -N -l $SSH_USER -n -f -L873:127.0.0.1:873 $IMAGESERVER $REDIRECTION_OPTIONS"
 | |
|         logmsg $CMD
 | |
|         $CMD || shellout
 | |
|         
 | |
|         # Since we're using SSH, change the $IMAGESERVER variable to reflect
 | |
|         # the forwarded connection.
 | |
|         IMAGESERVER=127.0.0.1
 | |
| 
 | |
|     else
 | |
|         ########################################################################
 | |
|         #
 | |
|         # Looks like we didn't get a private key so let's just fire up
 | |
|         # sshd and wait for someone to connect to us to initiate the
 | |
|         # next step of the autoinstall.
 | |
|         #
 | |
|         if [ -z $HOSTNAME ]; then
 | |
|             logmsg
 | |
|             logmsg "Trying to get hostname via DNS..."
 | |
|             logmsg
 | |
|             get_hostname_by_dns
 | |
|         fi
 | |
|         
 | |
|         if [ -z $HOSTNAME ]; then
 | |
|             HOST_OR_IP=$IPADDR
 | |
|         else
 | |
|             HOST_OR_IP=$HOSTNAME
 | |
|         fi
 | |
| 
 | |
|         if [ ! -f /tmp/sshd_started ]; then
 | |
|             start_sshd
 | |
|             # Give sshd time to initialize before we yank the parent process
 | |
|             # rug out from underneath it.
 | |
|             sleep 15
 | |
|         fi
 | |
| 
 | |
|         logmsg
 | |
|         logmsg
 | |
|         logmsg "Started sshd.  You must now go to your imageserver and issue"
 | |
|         logmsg "the following command:"
 | |
|         logmsg
 | |
|         logmsg " \"si_pushinstall --hosts ${HOST_OR_IP}\"."
 | |
|         logmsg
 | |
|         logmsg
 | |
| 
 | |
|         # Since we're using SSH, change the $IMAGESERVER variable to reflect
 | |
|         # the forwarded connection.
 | |
|         IMAGESERVER=127.0.0.1
 | |
| 
 | |
|         while [ ! -f /tmp/si_pushupdate.completed ]; do
 | |
|             sleep 5
 | |
|         done
 | |
|     fi
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| #  send_monitor_msg
 | |
| #
 | |
| #   Description:
 | |
| #   Redirect a message to the monitor server.
 | |
| #
 | |
| #   Usage: send_monitor_msg "var=$msg"
 | |
| #
 | |
| 
 | |
| send_monitor_msg() {
 | |
|     if [ -z $MONITOR_SERVER ]; then
 | |
|         return
 | |
|     fi
 | |
|     if [ -z $MONITOR_PORT ]; then
 | |
|         MONITOR_PORT=8181
 | |
|     fi
 | |
| 
 | |
|     # Message to send.
 | |
|     msg=`echo "$@"`
 | |
| 
 | |
|     # Get the client mac address.
 | |
|     if [ -z "$mac" ]; then
 | |
|         mac=`ifconfig $DEVICE 2>/dev/null | sed -ne "s/.*HWaddr //p" | sed "s/ //g" | sed s/:/./g`
 | |
|     fi
 | |
| 
 | |
|     # Collect some special info only after proc file system is mounted.
 | |
|     if [ `mount 2>/dev/null | grep proc > /dev/null; echo $?` -eq 0 ]; then
 | |
|         # Collect the CPU info.
 | |
|         if [ -z "$cpu" ]; then
 | |
|             cpu=$(echo `cat /proc/cpuinfo | grep "cpu\|clock\|model name\|cpu MHz" | grep -v "cpu family" | sed -ne '1,2p' | sed "s/.*: //" | sed "s/^\([0-9\.]*\)MHz$/(\1 MHz)/" | sed "s/^\([0-9\.]*\)$/(\1 MHz)/"` | sed "s/\(MHz)\)/\1 |/g" | sed "s/ |$//")
 | |
|         fi
 | |
| 
 | |
|         # Collect the number of CPUs.     
 | |
|         if [ -z "$ncpus" ]; then
 | |
|             ncpus=$((`cat /proc/cpuinfo | grep "^processor" | sed -n '$p' | sed "s/.*: \([0-9]\)*$/\1/"` + 1))
 | |
|         fi
 | |
| 
 | |
|         # Collect the kernel information.
 | |
|         if [ -z "$kernel_name" ]; then
 | |
|             kernel_name=`uname -r`
 | |
|         fi
 | |
| 
 | |
|         # Collect the amount of phyisical memory.
 | |
|         if [ -z "$mem" ]; then
 | |
|             mem=`cat /proc/meminfo | sed -ne "s/MemTotal: *//p" | sed "s/ kB//"`
 | |
|         fi
 | |
| 
 | |
|         # Evaluate the amount of available RAM.
 | |
|         tmpfs=`df | grep tmpfs | grep "/$" | sed "s/.* \([0-9]*%\) .*/\1/"`
 | |
| 
 | |
|         # Evaluate the uptime of the client.
 | |
|         time=`cat /proc/uptime | sed "s/\..*//"`
 | |
|     fi
 | |
| 
 | |
|     # Report the message to the monitor server.
 | |
|     send_msg=`echo "mac=$mac:ip=$IPADDR:host=$HOSTNAME:cpu=$cpu:ncpus=$ncpus:kernel=$kernel_name:mem=$mem:os=$IMAGENAME:tmpfs=$tmpfs:time=$time:$msg"`
 | |
| 
 | |
|     # Send data to monitor server.
 | |
|     echo "$send_msg" | nc $MONITOR_SERVER $MONITOR_PORT
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| #  send_monitor_stdout
 | |
| #
 | |
| #   Description:
 | |
| #   Redirect a stdout of a command to the monitor console.
 | |
| #
 | |
| #   Usage: <cmd> | send_monitor_stdout
 | |
| #
 | |
| 
 | |
| send_monitor_stdout() {
 | |
|     while read l; do
 | |
|         # echo to the console -AR-
 | |
|         echo "$l"
 | |
|         # Send the message to the monitor daemon.
 | |
|         if [ "x$MONITOR_CONSOLE" = "xy" ]; then
 | |
|             MONITOR_CONSOLE=yes
 | |
|         fi
 | |
|         if [ "x$MONITOR_CONSOLE" = "xyes" ]; then
 | |
|             # Log message into the global monitor log.
 | |
|             echo "$l" >> /tmp/si_monitor.log
 | |
|         fi
 | |
|     done
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| #   Initialize the monitor server
 | |
| #
 | |
| 
 | |
| init_monitor_server() {
 | |
|     # Send initialization status.
 | |
|     send_monitor_msg "status=0:first_timestamp=on:speed=0"
 | |
|     logmsg "Monitoring initialized."
 | |
|     # Start client log gathering server: for each connection
 | |
|     # to the local client on port 8181 the full log is sent
 | |
|     # to the requestor. -AR-
 | |
|     if [ "x$MONITOR_CONSOLE" = "xy" ]; then
 | |
|         MONITOR_CONSOLE=yes
 | |
|     fi
 | |
|     if [ "x$MONITOR_CONSOLE" = "xyes" ]; then
 | |
|         while :; do nc -p 8181 -l < /tmp/si_monitor.log; done &
 | |
|     fi
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| #   Report installation status to the monitor server
 | |
| #
 | |
| 
 | |
| start_report_task() {
 | |
|     # Reporting interval (in sec).
 | |
|     REPORT_INTERVAL=10
 | |
| 
 | |
|     # Evaluate image size.
 | |
|     logmsg "Evaluating image size..."
 | |
|     if [ ! "x$BITTORRENT" = "xy" ]; then
 | |
|         IMAGESIZE=`rsync -av --numeric-ids $IMAGESERVER::$IMAGENAME | grep "total size" | sed -e "s/total size is \([0-9]*\).*/\1/"`
 | |
|     else
 | |
|         if [ -f "${TORRENTS_DIR}/image-${IMAGENAME}.tar.torrent" ]; then
 | |
|             torrent_file="${TORRENTS_DIR}/image-${IMAGENAME}.tar.torrent"
 | |
|         elif [ -f "${TORRENTS_DIR}/image-${IMAGENAME}.tar.gz.torrent" ]; then
 | |
|             torrent_file="${TORRENTS_DIR}/image-${IMAGENAME}.tar.gz.torrent"
 | |
|         else
 | |
|             logmsg "error: cannot find a valid torrent file for image ${IMAGENAME}"
 | |
|             shellout
 | |
|         fi
 | |
|         IMAGESIZE=`/bin/torrentinfo-console $torrent_file | sed -ne "s/file size\.*: \([0-9]*\) .*$/\1/p"`
 | |
|     fi
 | |
|     IMAGESIZE=`expr $IMAGESIZE / 1024`
 | |
|     logmsg "  --> Image size = `expr $IMAGESIZE / 1024`MiB"
 | |
| 
 | |
|     # Evaluate disks size.
 | |
|     LIST=`df 2>/dev/null | grep "/" | sed "s/  */ /g" | cut -d' ' -f3 | sed -ne 's/^\([0-9]*\)$/\1+/p'`0
 | |
|     DISKSIZE=`echo $LIST | bc`
 | |
| 
 | |
|     # Spawn the report task -AR-
 | |
|     {
 | |
|     TOT=0; CURR_SIZE=0
 | |
|     while :; do
 | |
|         LIST=`df 2>/dev/null | grep "/" | sed "s/  */ /g" | cut -d' ' -f3 | sed -ne 's/^\([0-9]*\)$/\1+/p'`0
 | |
|         TOT=`echo $LIST | bc`
 | |
| 
 | |
|         # Evaluate bandwidth.
 | |
|         speed=`echo "scale=2; (($TOT - $DISKSIZE) - $CURR_SIZE) / $REPORT_INTERVAL" | bc`
 | |
|         speed=`echo "scale=2; if ($speed >= 0) { print $speed; } else { print 0; }" | bc`
 | |
| 
 | |
|         # Evaluate status.
 | |
|         CURR_SIZE=$(($TOT - $DISKSIZE))
 | |
|         status=`echo "scale=2; $CURR_SIZE * 100 / $IMAGESIZE" | bc`
 | |
|         if [ `echo "scale=2; $status <= 0" | bc` -eq 1 ]; then 
 | |
|             status=1
 | |
|         elif [ `echo "scale=2; $status >= 100" | bc` -eq 1 ]; then
 | |
|             status=99
 | |
|         fi
 | |
| 
 | |
|         # Send status and bandwidth to the monitor server.
 | |
|         send_monitor_msg "status=$status:speed=$speed"
 | |
|         
 | |
|         # Wait $REPORT_INTERVAL sec between each report -AR-
 | |
|         sleep $REPORT_INTERVAL
 | |
|     done
 | |
|     }&
 | |
| 
 | |
|     logmsg "Report task started."
 | |
|     REPORT_PID=$!
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| #   Stop to report installation status to the monitor server
 | |
| #
 | |
| 
 | |
| stop_report_task() {
 | |
|     if [ ! -z $REPORT_PID ]; then
 | |
|         kill -9 $REPORT_PID
 | |
|         logmsg "Report task stopped."
 | |
|     fi
 | |
| 
 | |
|     # Try to report the error to the monitor server.
 | |
|     send_monitor_msg "status=$1:speed=0"
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| #   Beep incessantly
 | |
| #
 | |
| beep_incessantly() {
 | |
|     local SECONDS=1
 | |
|     local MINUTES
 | |
|     local MINUTES_X_SIXTY
 | |
|     { while :;
 | |
|         do
 | |
|             echo -n -e "\\a"
 | |
|             if [ $SECONDS -lt 60 ]; then 
 | |
|                 logmsg "I have been done for $SECONDS seconds.  Reboot me already!"
 | |
|             else
 | |
|                 MINUTES=`echo "$SECONDS / 60"|bc`
 | |
|                 MINUTES_X_SIXTY=`echo "$MINUTES * 60"|bc`
 | |
|                 if [ "$MINUTES_X_SIXTY" = "$SECONDS" ]; then 
 | |
|                     logmsg "I have been done for $MINUTES minutes now.  Reboot me already!"
 | |
|                 fi  
 | |
|             fi
 | |
|             sleep 1
 | |
|             SECONDS=`echo "$SECONDS + 1"|bc`
 | |
|         done
 | |
|     }
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| #   Beep incessantly
 | |
| #
 | |
| # Usage: beep [$COUNT [$INTERVAL]]
 | |
| # Usage: beep
 | |
| beep() {
 | |
|     local COUNT=$1
 | |
|     local INTERVAL=$2
 | |
| 
 | |
|     [ -z $COUNT ] && COUNT=1
 | |
|     [ -z $INTERVAL ] && INTERVAL=1
 | |
| 
 | |
|     local COUNTED=0
 | |
|     until [ "$COUNTED" = "$COUNT" ]
 | |
|     do
 | |
|         echo -n -e "\\a"
 | |
|         sleep $INTERVAL
 | |
|         COUNTED=$(( $COUNTED + 1 ))
 | |
|     done
 | |
| }
 | |
| #
 | |
| ################################################################################
 | |
| #
 | |
| #   Print out dots while sleeping
 | |
| #
 | |
| # Usage: sleep_loop [[$COUNT [$INTERVAL]] $CHARACTER]
 | |
| # Usage: sleep_loop
 | |
| sleep_loop() {
 | |
|     local COUNT=$1
 | |
|     local INTERVAL=$2
 | |
|     local CHARACTER=$3
 | |
|     local COUNTED
 | |
| 
 | |
|     [ -z $COUNT ] && COUNT=1
 | |
|     [ -z $INTERVAL ] && INTERVAL=1
 | |
|     [ -z $CHARACTER ] && CHARACTER=.
 | |
| 
 | |
|     COUNTED=0
 | |
|     until [ "$COUNTED" = "$COUNT" ]
 | |
|     do
 | |
|         echo -n "$CHARACTER"
 | |
|         sleep $INTERVAL
 | |
|         COUNTED=$(( $COUNTED + 1 ))
 | |
|     done
 | |
| }
 | |
| #
 | |
| ################################################################################
 |