# # "SystemImager" # # Copyright (C) 1999-2003 Brian Elliott Finley # # $Id: functions,v 1.46.4.1 2004/05/28 19:36:23 brianfinley Exp $ # # Others who have contributed to this code: # Charles C. Bennett, Jr. # Sean Dague # Dann Frazier # Curtis Zinzilieta # ################################################################################# # # Variables # PATH=/sbin:/bin:/usr/bin:/usr/sbin:/tmp SCRIPTS=scripts SCRIPTS_DIR=/scripts FLAMETHROWER_DIRECTORY_DIR=/var/lib/systemimager/flamethrower BOEL_BINARIES_DIR=/tmp/boel_binaries VERSION="3.2.3" FLAVOR="standard" #DEBUG=1 # XXX Make sure this is commented out for releases. -BEF- # ################################################################################ ################################################################################# # # Subroutines # ################################################################################# # # get_arch # # Usage: get_arch; echo $ARCH get_arch() { echo echo 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() { echo echo 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 echo "Detected ppc64 is really an iSeries partition..." fi fi } # ################################################################################# # # write_variables # # Usage: write_variables write_variables() { echo echo 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 "TMPFS_STAGING=$TMPFS_STAGING" >> /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 } # ################################################################################ # # Description: # Dann's spinner # # Usage: start_spinner # Also see: stop_spinner # start_spinner() { { while :; do echo -ne "\b/"; sleep 1; echo -ne "\b-"; sleep 1; echo -ne "\b\\"; sleep 1; echo -ne "\b|"; sleep 1; done }& SPINNER_PID=$! } # ################################################################################ # # Usage: stop_spinner # Also see: start_spinner # stop_spinner() { echo echo "stop_spinner" kill -9 $SPINNER_PID } # ################################################################################ # # Description: # watches the tmpfs filesystem (/) and gives warnings and/or does a shellout # # Usage: tmpfs_watcher # tmpfs_watcher() { echo echo tmpfs_watcher # Note: Transfer to staging area can fail if tmpfs runs out of inodes. { while :; do DF=`df -k / | grep -v 'Filesystem' | sed -e 's/ */ /g' -e 's/.*[0-9] //' -e 's/%.*//'` [ $DF -ge 95 ] && echo "WARNING: Your tmpfs filesystem is ${DF}% full!" [ $DF -ge 99 ] && echo " 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() { COUNT="$RETRY" echo "Killing off running processes." kill -9 $TMPFS_WATCHER_PID killall -9 udp-receiver rsync write_variables cat /etc/issue exec sh } # ################################################################################ # # Description: # Count the specified number, printing each number, and exit only the count # loop when + is hit (SIGINT, or Signal 2). Thanks to # CCB 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 +" ; I=$COUNT' INT I=0 while [ $I -lt $COUNT ]; do I=$(( $I + 1 )) echo -n "$I " sleep 1 done trap INT echo } # ################################################################################ # # Usage: get_scripts_directory # get_scripts_directory() { echo echo get_scripts_directory MODULE_NAME="autoinstall_scripts" DIR="${SCRIPTS_DIR}" RETRY=7 flamethrower_client } # ################################################################################ # # Usage: get_flamethrower_directory # get_flamethrower_directory() { echo echo Using multicast... echo 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_client # flamethrower_client() { echo echo "flamethrower_client(${MODULE_NAME})" echo --------------------------------------------------------------------- # validate if [ -z $PORTBASE ]; then . ${FLAMETHROWER_DIRECTORY_DIR}/${MODULE_NAME} if [ $? != 0 ]; then echo You must either set PORTBASE, or have a sourceable file called echo ${FLAMETHROWER_DIRECTORY_DIR}/MODULE_NAME shellout fi fi if [ -z $DIR ]; then echo Must set DIR 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 echo 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 echo 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 ) rm -f /tmp/multicast.tar # 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 )) echo "flamethrower_client: Proceeding with retry $COUNT of $RETRY" else echo echo "flamethrower_client: FATAL: Initial attempt and $RETRY retries failed!" shellout fi fi # sleep apnea sleep_loop $FLAMETHROWER_CLIENT_SLEEP done # done echo 'finished!' echo # 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 } # ################################################################################ # # Get other binaries, kernel module tree, and miscellaneous other stuff that # got put in the binaries tarball. -BEF- # get_boel_binaries_tarball() { echo echo 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. echo "SSH_DOWNLOAD_URL variable is set, so we will install over SSH!" if [ ! -z $FLAMETHROWER_DIRECTORY_PORTBASE ]; then echo "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" echo "$CMD" $CMD || shellout 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}" echo "$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 } # ################################################################################# # # Switch root to tmpfs # switch_root_to_tmpfs() { mount_proc 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/.*=//') umount /proc 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 echo echo "switch_root_to_tmpfs" # 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- mkdir -p /new_root || shellout mount tmpfs /new_root -t tmpfs $tmpfs_opts || shellout cd / || shellout rsync -a bin etc lib my_modules root sbin tmp usr var /new_root/ || shellout cd /new_root || shellout mkdir -p old_root || shellout pivot_root . old_root || shellout unset tmpfs_size unset tmpfs_nr_blocks unset tmpfs_nr_inodes unset tmpfs_mode unset tmpfs_opts } # ################################################################################# # mount_dev_on_devfs() { echo echo mount_dev_on_devfs # Re-mount /dev on devfs. -BEF- mkdir -p /dev || shellout mount devfs /dev -t devfs || shellout # Crank up devfsd /sbin/devfsd /dev || shellout } # ################################################################################# # # Now mount proc. -BEF- mount_proc() { echo echo mount_proc mkdir -p proc || shellout mount proc /proc -t proc || shellout } # ################################################################################# # # Configure loopback interface (may as well) ifconfig_loopback() { echo echo 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() { echo echo load_my_modules cd /my_modules || shellout sh ./INSMOD_COMMANDS } # ################################################################################ # # Look for local.cfg file # This code inspired by Ian McLeod # read_local_cfg() { echo echo read_local_cfg # BEGIN try hard drive # # this must be on two lines in order to substitute the newline cat /proc/cmdline | sed "s/ /\\ /g" | sed -n "s/=/=/p" > /tmp/last_root.$$ # suck in variable . /tmp/last_root.$$ if [ ! -z "$LAST_ROOT" ]; then echo echo "Checking for /local.cfg file on hard drive..." mkdir /last_root echo "Mounting hard drive..." mount $LAST_ROOT /last_root -o ro > /dev/null 2>&1 if [ $? != 0 ]; then echo "FATAL: Couldn't mount hard drive!" echo "Your kernel must have all necessary block and filesystem drivers compiled in" echo "statically (not modules) in order to use a local.cfg on your hard drive. The" echo "standard SystemImager kernel is modular, so you will need to compile your own" echo "kernel. See the SystemImager documentation for details. To proceed at this" echo "point, you will need to unset the LAST_ROOT append parameter by typing" echo ""systemimager LAST_ROOT=", or similar, at your boot prompt. This will not use" echo "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 echo "Found /local.cfg on hard drive." echo "Copying /local.cfg settings to /tmp/local.cfg." cat /last_root/local.cfg >> /tmp/local.cfg || shellout else echo "No /local.cfg on hard drive." fi echo "Unmounting hard drive..." umount /last_root || shellout echo fi # END try hard drive ### BEGIN try floppy ### echo "Checking for floppy diskette." echo '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 echo "Found floppy diskette." if [ -f /floppy/local.cfg ]; then echo "Found /local.cfg on floppy." echo "Copying /local.cfg settings to /tmp/local.cfg." echo "NOTE: local.cfg settings from a floppy will override settings from" echo " 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 echo "No /local.cfg on floppy diskette." fi else echo "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 echo "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() { echo echo start_network if [ ! -z $IPADDR ]; then # configure interface and add default gateway ifconfig $DEVICE $IPADDR netmask $NETMASK broadcast $BROADCAST if [ $? != 0 ]; then echo echo "I couldn't configure the network interface using the local.cfg file." echo "Check the entries in your /local.cfg file." echo shellout fi if [ ! -z $GATEWAY ]; then route add default gw $GATEWAY if [ $? != 0 ]; then echo echo "The command \"route add default gw $GATEWAY\" failed." echo "Check the entries in your /local.cfg file." echo shellout fi fi else ### try dhcp ### echo "IP Address not set by local.cfg. I will use DHCP." ### 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 echo echo "sleep $ETHER_SLEEP: This is to give your switch (if you're using one) time to" echo " recognize your ethernet card before we try the network." echo " Tip: You can use + to pass the time (pun intended)." echo count_loop $ETHER_SLEEP echo ### 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.systemimager-prefix \ /etc/dhclient-script.debian-dist \ > /etc/dhclient-script chmod +x /etc/dhclient-script # get info via dhcp echo echo "dhclient" dhclient if [ ! -s ${DHCLIENT_DIR}/dhclient.leases ]; then echo echo "I couldn't configure the network interface using DHCP." echo 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 echo "Override DHCP settings with local.cfg settings by re-reading (/tmp/local.cfg)." . /tmp/local.cfg || shellout fi fi } # ################################################################################ # # Ping test ping_test() { echo echo ping_test if [ ! -z "$FLAMETHROWER_DIRECTORY_PORTBASE" ]; then PING_DESTINATION=$GATEWAY HOST_TYPE="default gateway" else PING_DESTINATION=$IMAGESERVER fi echo echo "Pinging your $HOST_TYPE to ensure we have network connectivity." echo # Ping test code submitted by Grant Noruschat # modified slightly by PING_COUNT=1 PING_EXIT_STATUS=1 while [ "$PING_EXIT_STATUS" != "0" ] do echo "PING ATTEMPT $PING_COUNT: " ping -c 1 $PING_DESTINATION PING_EXIT_STATUS=$? if [ "$PING_EXIT_STATUS" = "0" ]; then echo echo " We have connectivity to your $HOST_TYPE!" fi PING_COUNT=$(( $PING_COUNT + 1 )) if [ "$PING_COUNT" = "4" ]; then echo echo " WARNING: Failed ping test." echo " Despite this seemingly depressing result, I will attempt" echo " to proceed with the install. Your $HOST_TYPE may be" echo " configured to not respond to pings, but it wouldn't hurt" echo " to double check that your networking equipment is" echo " working properly!" echo sleep 5 PING_EXIT_STATUS=0 fi done unset PING_DESTINATION unset HOST_TYPE } # ################################################################################ # start_syslogd() { echo echo start_syslogd if [ ! -z $LOG_SERVER ]; then echo -n "Starting syslogd..." [ -z $LOG_SERVER_PORT ] && LOG_SERVER_PORT="514" syslogd -R ${LOG_SERVER}:${LOG_SERVER_PORT} echo "done!" fi } # ################################################################################ # # Detect what we can. # Note: Modules that are needed during the initial boot stages of BOEL should # be copied to the "skel/my_modules" directory prior to creating your # custom initrd.gz. -BEF- # autodetect_hardware_and_load_modules() { echo echo autodetect_hardware_and_load_modules echo -n "Detecting hardware: " MODULES=`discover --module bridge ethernet ide scsi usb` echo $MODULES # Prepend with other modules that we will probably need. MODULES="sd_mod ide-disk $MODULES" for MODULE in $MODULES do echo echo "Loading $MODULE..." modprobe $MODULE 2>/dev/null || echo "Assuming $MODULE is compiled into the kernel, not needed, or already loaded." done } # ################################################################################ # get_hostname_by_hosts_file() { if [ ! -z $FLAMETHROWER_DIRECTORY_PORTBASE ]; then # FLAMETHROWER_DIRECTORY_PORTBASE is set, therfore we should have a hosts file in ${SCRIPTS_DIR} echo "Using hosts file pulled over by multicast." else # Try pulling hosts file from imageserver -BEF- mkdir -p ${SCRIPTS_DIR} CMD="rsync -aL ${IMAGESERVER}::${SCRIPTS}/hosts ${SCRIPTS_DIR}/ >/dev/null 2>&1" echo "$CMD" $CMD fi # # Look in $FILE for that magic joy. # FILE=${SCRIPTS_DIR}/hosts if [ -e $FILE ]; then # 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 echo "Looking for hostname of this host in $FILE by IP: $IPADDR" # Command summary by line: # 1: convert tabs to spaces -- contains a literal tab: + then # 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 echo "Couldn't find hosts file: $FILE" fi } # ################################################################################ # get_hostname_by_dns() { # Get base hostname. For example, www7.domain.com will become www7. -BEF- echo "Trying to get hostname via DNS..." HOSTNAME=`nslookup $IPADDR | grep "^Name:" | sed -e 's/Name:[[:space:]]*//' -e 's/\..*$//g'` } # ################################################################################ # run_autoinstall_script() { echo echo run_autoinstall_script # Run the autoinstall script. FILE="${SCRIPTS_DIR}/$SCRIPTNAME" if [ -f $FILE ]; then chmod 755 $FILE || shellout echo echo "I will now run the autoinstall script: $FILE" echo $FILE || shellout else echo echo "FATAL: Your autoinstall script doesn't appear to exist: $FILE" echo " Be sure this script exists in the autoinstall scripts directory" echo " on your image server." shellout fi } # ################################################################################ # # Get ssh_tarball # get_ssh_tarball() { # Remove possible trailing / from URL SSH_DOWNLOAD_URL=`echo $SSH_DOWNLOAD_URL | sed 's/\/$//'` cd /tmp CMD="wget ${SSH_DOWNLOAD_URL}/${ARCH}/ssh/systemimager_ssh.tar.gz" echo "$CMD" $CMD || shellout # Untar the tarball tar -C / -xzf /tmp/systemimager_ssh.tar.gz || shellout } # ################################################################################ # # Stuff for SSH installs # start_ssh() { get_ssh_tarball # create root's ssh dir mkdir /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. # # (ssh2 dsa style user private key) if [ -e /floppy/id_dsa ]; then PRIVATE_KEY=/root/.ssh/id_dsa cp /floppy/id_dsa $PRIVATE_KEY || shellout chmod 600 $PRIVATE_KEY || shellout fi # # (ssh2 rsa style user private key) if [ -e /floppy/id_rsa ]; then 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. # the sleep command executes remotely. Just need something long here # as the connection will be severed when the newly imaged client reboots # 14400 = 4 hours...if we're not imaged by then....oh boy! # # Determine if we should run interactive and set redirection options appropriately. # So if the key is blank, go interactive. (Suggested by Don Stocks ) if [ -s $PRIVATE_KEY ]; then # key is *not* blank REDIRECTION_OPTIONS="> /dev/null 2>&1" else # key is blank - go interactive REDIRECTION_OPTIONS="" fi CMD="ssh -l $SSH_USER -n -f -L873:127.0.0.1:873 $IMAGESERVER sleep 14400 $REDIRECTION_OPTIONS" echo $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 from the floppy, so let's just # fire up sshd and wait for someone to connect to us to initiate the # next step of the autoinstall. -BEF- # # download authorized_keys # (public keys of users allowed to ssh *in* to this machine) cd /root/.ssh/ || shellout CMD="wget ${SSH_DOWNLOAD_URL}/${ARCH}/ssh/authorized_keys" echo echo $CMD $CMD || shellout # 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/ # Since we're using SSH, change the $IMAGESERVER variable to reflect # the forwarded connection. IMAGESERVER=127.0.0.1 # save variables for autoinstall script write_variables || shellout # create a private host key for this autoinstall client echo echo "Using ssh-keygen to create this hosts private key" echo mkdir -p /var/empty || shellout ssh-keygen -t dsa -N "" -f /etc/ssh/ssh_host_dsa_key || shellout ssh-keygen -t rsa -N "" -f /etc/ssh/ssh_host_rsa_key || shellout # if hostname not set, try DNS if [ -z $HOSTNAME ]; then echo echo "Trying to get hostname via DNS..." echo get_hostname_by_dns fi if [ -z $HOSTNAME ]; then HOST_OR_IP=$IPADDR else HOST_OR_IP=$HOSTNAME fi echo echo echo "Starting sshd. You must now go to your imageserver and issue" echo "the following command:" echo echo " \"pushupdate -continue-install -image -client ${HOST_OR_IP}\"." echo echo # fire up sshd and wait mkdir -p /var/run/sshd || shellout chmod 0755 /var/run/sshd || shellout sshd || shellout # Give sshd time to initialize before we yank the parent process # rug out from underneath it. sleep 15 # remove rug exit 1 fi } # ################################################################################ # # Pull over the autoinstall script SCRIPTNAME # get_script() { echo echo "get_script" echo "I will now try to get the autoinstall script: $SCRIPTNAME" if [ -e ${SCRIPTS_DIR}/${SCRIPTNAME} ]; then echo "Excellent! It's already here -- in the ${SCRIPTS_DIR} directory." elif [ ! -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). # break else mkdir -p ${SCRIPTS_DIR} CMD="rsync -aL ${IMAGESERVER}::${SCRIPTS}/${SCRIPTNAME} ${SCRIPTS_DIR}" echo "$CMD" $CMD fi } # ################################################################################ # # Beep incessantly # beep_incessantly() { SECONDS=1 { while :; do echo -n -e "\\a" if [ $SECONDS -lt 60 ]; then echo "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 echo "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() { COUNT=$1 INTERVAL=$2 [ -z $COUNT ] && COUNT=1 [ -z $INTERVAL ] && INTERVAL=1 COUNTED=0 until [ "$COUNTED" = "$COUNT" ] do echo -n -e "\\a" sleep $INTERVAL COUNTED=$(( $COUNTED + 1 )) done unset COUNT unset COUNTED unset INTERVAL } # ################################################################################ # # Print out dots while sleeping # # Usage: sleep_loop [[$COUNT [$INTERVAL]] $CHARACTER] # Usage: sleep_loop sleep_loop() { COUNT=$1 INTERVAL=$2 CHARACTER=$3 [ -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 unset CHARACTER unset COUNT unset COUNTED unset INTERVAL } # ################################################################################