functions.sh revision 225657
179455Sobrien#!/bin/sh 279455Sobrien#- 379455Sobrien# Copyright (c) 2010 iXsystems, Inc. All rights reserved. 479455Sobrien# 579455Sobrien# Redistribution and use in source and binary forms, with or without 679455Sobrien# modification, are permitted provided that the following conditions 779455Sobrien# are met: 879455Sobrien# 1. Redistributions of source code must retain the above copyright 979455Sobrien# notice, this list of conditions and the following disclaimer. 1079455Sobrien# 2. Redistributions in binary form must reproduce the above copyright 1179455Sobrien# notice, this list of conditions and the following disclaimer in the 1279455Sobrien# documentation and/or other materials provided with the distribution. 1379455Sobrien# 1479455Sobrien# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1579455Sobrien# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1679455Sobrien# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1779455Sobrien# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1879455Sobrien# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1979455Sobrien# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2079455Sobrien# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2179455Sobrien# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2279455Sobrien# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2379455Sobrien# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2479455Sobrien# SUCH DAMAGE. 2579455Sobrien# 2679455Sobrien# $FreeBSD: head/usr.sbin/pc-sysinstall/backend/functions.sh 225657 2011-09-19 05:12:53Z jpaetzel $ 2779455Sobrien 2879455Sobrien# functions.sh 29241806Suqs# Library of functions which pc-sysinstall may call upon 3079455Sobrien 3179455Sobrien# Function which displays the help-index file 3279455Sobriendisplay_help() 3379455Sobrien{ 3479455Sobrien if [ -e "${PROGDIR}/doc/help-index" ] 3579455Sobrien then 3679455Sobrien cat ${PROGDIR}/doc/help-index 3779455Sobrien else 3879455Sobrien echo "Error: ${PROGDIR}/doc/help-index not found" 3979455Sobrien exit 1 4079455Sobrien fi 4179455Sobrien}; 4279455Sobrien 43203872Skib# Function which displays the help for a specified command 44203872Skibdisplay_command_help() 4592839Simp{ 46203872Skib if [ -z "$1" ] 4779455Sobrien then 48125471Sbde echo "Error: No command specified to display help for" 49125471Sbde exit 1 50125471Sbde fi 51125471Sbde 52125471Sbde if [ -e "${PROGDIR}/doc/help-${1}" ] 53125471Sbde then 54125471Sbde cat ${PROGDIR}/doc/help-${1} 55125471Sbde else 56125471Sbde echo "Error: ${PROGDIR}/doc/help-${1} not found" 57125471Sbde exit 1 58125471Sbde fi 59125471Sbde}; 60125471Sbde 61125471Sbde# Function to convert bytes to megabytes 62125471Sbdeconvert_byte_to_megabyte() 63125471Sbde{ 64125471Sbde if [ -z "${1}" ] 65125471Sbde then 66125469Sbde echo "Error: No bytes specified!" 67125469Sbde exit 1 68125469Sbde fi 69125469Sbde 70125469Sbde expr -e ${1} / 1048576 71125469Sbde}; 72241806Suqs 73125469Sbde# Function to convert blocks to megabytes 74125485Sbdeconvert_blocks_to_megabyte() 75125469Sbde{ 76125469Sbde if [ -z "${1}" ] ; then 77203874Skib echo "Error: No blocks specified!" 78203874Skib exit 1 79125469Sbde fi 80241806Suqs 81125469Sbde expr -e ${1} / 2048 82241806Suqs}; 83125469Sbde 84125469Sbde# Takes $1 and strips the whitespace out of it, returns VAL 85125469Sbdestrip_white_space() 86125469Sbde{ 87241806Suqs if [ -z "${1}" ] 88125469Sbde then 89125469Sbde echo "Error: No value setup to strip whitespace from!" 90125469Sbde 91209364Sbrian exit 1 92209364Sbrian fi 93241806Suqs 94125469Sbde export VAL=`echo "$1" | tr -d ' '` 95125469Sbde}; 96125469Sbde 97125485Sbde# Displays an error message and exits with error 1 98125485Sbdeexit_err() 99125485Sbde{ 100125485Sbde # Echo the message for the users benefit 101203874Skib echo "EXITERROR: $1" 102125485Sbde 103125485Sbde # Save this error to the log file 104125485Sbde echo "EXITERROR: ${1}" >>$LOGOUT 105125485Sbde 106125485Sbde # Check if we need to unmount any file-systems after this failure 107125485Sbde unmount_all_filesystems_failure 108125485Sbde 109125485Sbde echo "For more details see log file: $LOGOUT" 110125485Sbde 111125485Sbde exit 1 112125469Sbde}; 113125485Sbde 114125485Sbde# Run-command, don't halt if command exits with non-0 115125485Sbderc_nohalt() 116125485Sbde{ 117125485Sbde CMD="$1" 118125485Sbde 119125485Sbde if [ -z "${CMD}" ] 120125485Sbde then 121125485Sbde exit_err "Error: missing argument in rc_nohalt()" 122125485Sbde fi 123125485Sbde 124125469Sbde echo "Running: ${CMD}" >>${LOGOUT} 125125469Sbde ${CMD} >>${LOGOUT} 2>>${LOGOUT} 126125469Sbde 127125469Sbde}; 128125469Sbde 12979455Sobrien# Run-command, halt if command exits with non-0 13079455Sobrienrc_halt() 13179455Sobrien{ 13279455Sobrien CMD="$1" 133203872Skib 13479455Sobrien if [ -z "${CMD}" ] 13579455Sobrien then 13679455Sobrien exit_err "Error: missing argument in rc_halt()" 13779455Sobrien fi 13879455Sobrien 13979455Sobrien echo "Running: ${CMD}" >>${LOGOUT} 14079455Sobrien eval ${CMD} >>${LOGOUT} 2>>${LOGOUT} 14179455Sobrien STATUS="$?" 14279455Sobrien if [ "${STATUS}" != "0" ] 14379455Sobrien then 14479455Sobrien exit_err "Error ${STATUS}: ${CMD}" 14579455Sobrien fi 14679455Sobrien}; 14779455Sobrien 14879455Sobrien# Run-command w/echo to screen, halt if command exits with non-0 14979455Sobrienrc_halt_echo() 15079455Sobrien{ 15179455Sobrien CMD="$1" 15279455Sobrien 15379455Sobrien if [ -z "${CMD}" ] 15479455Sobrien then 15579455Sobrien exit_err "Error: missing argument in rc_halt_echo()" 15679455Sobrien fi 15779455Sobrien 15879455Sobrien echo "Running: ${CMD}" >>${LOGOUT} 15979455Sobrien ${CMD} 2>&1 | tee -a ${LOGOUT} 16079455Sobrien STATUS="$?" 16179455Sobrien if [ "$STATUS" != "0" ] 16279455Sobrien then 16379455Sobrien exit_err "Error ${STATUS}: $CMD" 164203872Skib fi 16579455Sobrien 16679455Sobrien}; 167241806Suqs 16879455Sobrien# Run-command w/echo, don't halt if command exits with non-0 169241806Suqsrc_nohalt_echo() 17079455Sobrien{ 171241806Suqs CMD="$1" 17279455Sobrien 17379455Sobrien if [ -z "${CMD}" ] 17479455Sobrien then 175203874Skib exit_err "Error: missing argument in rc_nohalt_echo()" 176203874Skib fi 17779455Sobrien 17879455Sobrien echo "Running: ${CMD}" >>${LOGOUT} 179241806Suqs ${CMD} 2>&1 | tee -a ${LOGOUT} 18079455Sobrien 18179455Sobrien}; 18279455Sobrien 183203874Skib# Echo to the screen and to the log 184203874Skibecho_log() 185241806Suqs{ 18679455Sobrien STR="$1" 18779455Sobrien 18879455Sobrien if [ -z "${STR}" ] 18979455Sobrien then 19079455Sobrien exit_err "Error: missing argument in echo_log()" 19179455Sobrien fi 19279455Sobrien 19379455Sobrien echo "${STR}" | tee -a ${LOGOUT} 19479455Sobrien}; 19579455Sobrien 19679455Sobrien# Make sure we have a numeric 19779455Sobrienis_num() 19879455Sobrien{ 19979455Sobrien expr $1 + 1 2>/dev/null 200203872Skib return $? 20179455Sobrien} 20279455Sobrien 20379455Sobrien# Function which uses "fetch" to download a file, and display a progress report 20479455Sobrienfetch_file() 20579455Sobrien{ 206203872Skib 20779455Sobrien FETCHFILE="$1" 20879455Sobrien FETCHOUTFILE="$2" 20979455Sobrien EXITFAILED="$3" 21079455Sobrien 21179455Sobrien SIZEFILE="${TMPDIR}/.fetchSize" 212241806Suqs EXITFILE="${TMPDIR}/.fetchExit" 213203872Skib 21479455Sobrien rm ${SIZEFILE} 2>/dev/null >/dev/null 215241806Suqs rm ${FETCHOUTFILE} 2>/dev/null >/dev/null 21679455Sobrien 21779455Sobrien fetch -s "${FETCHFILE}" >${SIZEFILE} 21879455Sobrien SIZE="`cat ${SIZEFILE}`" 219203872Skib SIZE="`expr ${SIZE} / 1024`" 22079455Sobrien echo "FETCH: ${FETCHFILE}" 221203874Skib echo "FETCH: ${FETCHOUTFILE}" >>${LOGOUT} 22279455Sobrien 22379455Sobrien ( fetch -o ${FETCHOUTFILE} "${FETCHFILE}" >/dev/null 2>/dev/null ; echo "$?" > ${EXITFILE} ) & 22479455Sobrien PID="$!" 22579455Sobrien while 22679455Sobrien z=1 22779455Sobrien do 22879455Sobrien 22979455Sobrien if [ -e "${FETCHOUTFILE}" ] 23079455Sobrien then 23179455Sobrien DSIZE=`du -k ${FETCHOUTFILE} | tr -d '\t' | cut -d '/' -f 1` 232102231Strhodes if [ $(is_num "$DSIZE") ] ; then 23379455Sobrien if [ $SIZE -lt $DSIZE ] ; then DSIZE="$SIZE"; fi 23479455Sobrien echo "SIZE: ${SIZE} DOWNLOADED: ${DSIZE}" 235203874Skib echo "SIZE: ${SIZE} DOWNLOADED: ${DSIZE}" >>${LOGOUT} 23679455Sobrien fi 23779455Sobrien fi 23879455Sobrien 23979455Sobrien # Check if the download is finished 24079455Sobrien ps -p ${PID} >/dev/null 2>/dev/null 24179455Sobrien if [ $? -ne 0 ] 24279455Sobrien then 24379455Sobrien break; 24479455Sobrien fi 245268631Spfg 24679455Sobrien sleep 2 24779455Sobrien done 24879455Sobrien 24979455Sobrien echo "FETCHDONE" 25079455Sobrien 25179455Sobrien EXIT="`cat ${EXITFILE}`" 25279455Sobrien if [ "${EXIT}" != "0" -a "$EXITFAILED" = "1" ] 25379455Sobrien then 25479455Sobrien exit_err "Error: Failed to download ${FETCHFILE}" 25579455Sobrien fi 25679455Sobrien 25779455Sobrien return $EXIT 25879455Sobrien 25979455Sobrien}; 26079455Sobrien 26179455Sobrien# Function to return a the zpool name for this device 26279455Sobrienget_zpool_name() 26379455Sobrien{ 26479455Sobrien DEVICE="$1" 265268631Spfg 26679455Sobrien # Set the base name we use for zpools 26779455Sobrien BASENAME="tank" 26879455Sobrien 26979455Sobrien if [ ! -d "${TMPDIR}/.zpools" ] ; then 27079455Sobrien mkdir -p ${TMPDIR}/.zpools 27179455Sobrien fi 27279455Sobrien 27379455Sobrien if [ -e "${TMPDIR}/.zpools/${DEVICE}" ] ; then 27479455Sobrien cat ${TMPDIR}/.zpools/${DEVICE} 27579455Sobrien return 0 27679455Sobrien else 27779455Sobrien # Need to generate a zpool name for this device 27879455Sobrien NUM=`ls ${TMPDIR}/.zpools/ | wc -l | sed 's| ||g'` 27979455Sobrien NEWNAME="${BASENAME}${NUM}" 28079455Sobrien mkdir -p ${TMPDIR}/.zpools/`dirname $DEVICE` 28179455Sobrien echo "$NEWNAME" >${TMPDIR}/.zpools/${DEVICE} 28279455Sobrien echo "${NEWNAME}" 28379455Sobrien return 28479455Sobrien fi 28579455Sobrien}; 28679455Sobrien 28779455Sobrieniscompressed() 28879455Sobrien{ 28979455Sobrien local FILE 29079455Sobrien local RES 29179455Sobrien 29279455Sobrien FILE="$1" 29379455Sobrien RES=1 29479455Sobrien 29579455Sobrien if echo "${FILE}" | \ 29679455Sobrien grep -qiE '\.(Z|lzo|lzw|lzma|gz|bz2|xz|zip)$' 2>&1 29779455Sobrien then 29879455Sobrien RES=0 29979455Sobrien fi 30079455Sobrien 30179455Sobrien return ${RES} 30279455Sobrien} 30379455Sobrien 30479455Sobrienget_compression_type() 30579455Sobrien{ 30679455Sobrien local FILE 30779455Sobrien local SUFFIX 30879455Sobrien 30979455Sobrien FILE="$1" 31079455Sobrien SUFFIX=`echo "${FILE}" | sed -E 's|^(.+)\.(.+)$|\2|'` 31179455Sobrien 312203872Skib VAL="" 313203872Skib SUFFIX=`echo "${SUFFIX}" | tr A-Z a-z` 314203872Skib case "${SUFFIX}" in 315203872Skib z) VAL="lzw" ;; 316203872Skib lzo) VAL="lzo" ;; 31779455Sobrien lzw) VAL="lzw" ;; 31879455Sobrien lzma) VAL="lzma" ;; 31979455Sobrien gz) VAL="gzip" ;; 32079455Sobrien bz2) VAL="bzip2" ;; 32179455Sobrien xz) VAL="xz" ;; 32279455Sobrien zip) VAL="zip" ;; 323241807Suqs esac 32492839Simp 32579455Sobrien export VAL 32679455Sobrien} 32779455Sobrien 32879455Sobrienwrite_image() 32979455Sobrien{ 33079455Sobrien local DEVICE_FILE 33179455Sobrien 33279455Sobrien IMAGE_FILE="$1" 33379455Sobrien DEVICE_FILE="$2" 33479455Sobrien 33579455Sobrien if [ -z "${IMAGE_FILE}" ] 336203872Skib then 33779455Sobrien exit_err "ERROR: Image file not specified!" 33879455Sobrien fi 33979455Sobrien 34079455Sobrien if [ -z "${DEVICE_FILE}" ] 34179455Sobrien then 34279455Sobrien exit_err "ERROR: Device file not specified!" 343175853Syar fi 34479455Sobrien 345175853Syar if [ ! -f "${IMAGE_FILE}" ] 34679455Sobrien then 34779455Sobrien exit_err "ERROR: '${IMAGE_FILE}' does not exist!" 34879455Sobrien fi 34979455Sobrien 35079455Sobrien DEVICE_FILE="${DEVICE_FILE#/dev/}" 351203872Skib DEVICE_FILE="/dev/${DEVICE_FILE}" 35279455Sobrien 353175854Syar if [ ! -c "${DEVICE_FILE}" ] 35479455Sobrien then 35579455Sobrien exit_err "ERROR: '${DEVICE_FILE}' is not a character device!" 35679455Sobrien fi 357203872Skib 35879455Sobrien if iscompressed "${IMAGE_FILE}" 35979455Sobrien then 36079455Sobrien local COMPRESSION 36179455Sobrien 36279455Sobrien get_compression_type "${IMAGE_FILE}" 36379455Sobrien COMPRESSION="${VAL}" 36479455Sobrien 365203872Skib case "${COMPRESSION}" in 36679455Sobrien lzw) 36779455Sobrien rc_halt "uncompress ${IMAGE_FILE} -c | dd of=${DEVICE_FILE}" 36879455Sobrien IMAGE_FILE="${IMAGE_FILE%.Z}" 36979455Sobrien ;; 37079455Sobrien 37179455Sobrien lzo) 37279455Sobrien rc_halt "lzop -d $IMAGE_{FILE} -c | dd of=${DEVICE_FILE}" 37379455Sobrien IMAGE_FILE="${IMAGE_FILE%.lzo}" 37479455Sobrien ;; 37579455Sobrien 376203872Skib lzma) 37779455Sobrien rc_halt "lzma -d ${IMAGE_FILE} -c | dd of=${DEVICE_FILE}" 37879455Sobrien IMAGE_FILE="${IMAGE_FILE%.lzma}" 37979455Sobrien ;; 38079455Sobrien 38179455Sobrien gzip) 38279455Sobrien rc_halt "gunzip ${IMAGE_FILE} -c | dd of=${DEVICE_FILE}" 38379455Sobrien IMAGE_FILE="${IMAGE_FILE%.gz}" 38479455Sobrien ;; 38579455Sobrien 38679455Sobrien bzip2) 38779455Sobrien rc_halt "bunzip2 ${IMAGE_FILE} -c | dd of=${DEVICE_FILE}" 388203872Skib IMAGE_FILE="${IMAGE_FILE%.bz2}" 38979455Sobrien ;; 39079455Sobrien 39179455Sobrien xz) 39279455Sobrien rc_halt "xz -d ${IMAGE_FILE} -c | dd of=${DEVICE_FILE}" 39379455Sobrien IMAGE_FILE="${IMAGE_FILE%.xz}" 394203872Skib ;; 39579455Sobrien 39679455Sobrien zip) 39779455Sobrien rc_halt "unzip ${IMAGE_FILE} -c | dd of=${DEVICE_FILE}" 39879455Sobrien IMAGE_FILE="${IMAGE_FILE%.zip}" 39979455Sobrien ;; 40079455Sobrien 40179455Sobrien *) 40279455Sobrien exit_err "ERROR: ${COMPRESSION} compression is not supported" 40379455Sobrien ;; 40479455Sobrien esac 40579455Sobrien 406203872Skib else 407203872Skib rc_halt "dd if=${IMAGE_FILE} of=${DEVICE_FILE}" 40879455Sobrien 40979455Sobrien fi 41079455Sobrien}; 41179455Sobrien 41279455Sobrien# Setup and install on a new disk / partition 41379455Sobrieninstall_fresh() 41479455Sobrien{ 41579455Sobrien # Lets start setting up the disk slices now 41679455Sobrien setup_disk_slice 41779455Sobrien 41879455Sobrien if [ -z "${ROOTIMAGE}" ] 41992839Simp then 42079455Sobrien 42179455Sobrien # Disk setup complete, now lets parse WORKINGSLICES and setup the bsdlabels 42279455Sobrien setup_disk_label 42379455Sobrien 42479455Sobrien # Now we've setup the bsdlabels, lets go ahead and run newfs / zfs 42579455Sobrien # to setup the filesystems 42679455Sobrien setup_filesystems 42779455Sobrien 42879455Sobrien # Lets mount the partitions now 42979455Sobrien mount_all_filesystems 43079455Sobrien 43179455Sobrien # We are ready to begin extraction, lets start now 43279455Sobrien init_extraction 433241806Suqs 43479455Sobrien # Check if we have any optional modules to load 43579455Sobrien install_components 43679455Sobrien 43779455Sobrien # Check if we have any packages to install 43879455Sobrien install_packages 439268632Spfg 440268632Spfg # Do any localization in configuration 441268632Spfg run_localize 442268632Spfg 443268632Spfg # Save any networking config on the installed system 444268632Spfg save_networking_install 445268632Spfg 446241806Suqs # Now add any users 447268632Spfg setup_users 44879455Sobrien 44979455Sobrien # Do any last cleanup / setup before unmounting 45079455Sobrien run_final_cleanup 45179455Sobrien 45279455Sobrien # Now run any commands specified 45379455Sobrien run_commands 45479455Sobrien 45579455Sobrien # Unmount and finish up 45679455Sobrien unmount_all_filesystems 45792839Simp fi 45879455Sobrien 45979455Sobrien echo_log "Installation finished!" 46079455Sobrien}; 46179455Sobrien 46279455Sobrien# Extract the system to a pre-mounted directory 46379455Sobrieninstall_extractonly() 46479455Sobrien{ 46579455Sobrien # We are ready to begin extraction, lets start now 46679455Sobrien init_extraction 46779455Sobrien 46879455Sobrien # Check if we have any optional modules to load 46979455Sobrien install_components 47079455Sobrien 47179455Sobrien # Check if we have any packages to install 47279455Sobrien install_packages 47379455Sobrien 47479455Sobrien # Do any localization in configuration 47579455Sobrien run_localize 476268632Spfg 477268632Spfg # Save any networking config on the installed system 47879455Sobrien save_networking_install 47979455Sobrien 48079455Sobrien # Now add any users 48179455Sobrien setup_users 48279455Sobrien 48379455Sobrien # Now run any commands specified 48479455Sobrien run_commands 48579455Sobrien 48679455Sobrien # Set a hostname on the install system 48779455Sobrien setup_hostname 48879455Sobrien 48979455Sobrien # Set the root_pw if it is specified 49079455Sobrien set_root_pw 49179455Sobrien 49279455Sobrien echo_log "Installation finished!" 49379455Sobrien}; 49479455Sobrien 49579455Sobrieninstall_image() 49679455Sobrien{ 49779455Sobrien # We are ready to begin extraction, lets start now 498268632Spfg init_extraction 49979455Sobrien 50079455Sobrien echo_log "Installation finished!" 501268632Spfg}; 50279455Sobrien 50379455Sobrieninstall_upgrade() 50479455Sobrien{ 50579455Sobrien # We're going to do an upgrade, skip all the disk setup 50679455Sobrien # and start by mounting the target drive/slices 50779455Sobrien mount_upgrade 50879455Sobrien 509268632Spfg # Start the extraction process 51079455Sobrien init_extraction 51179455Sobrien 51279455Sobrien # Do any localization in configuration 51379455Sobrien run_localize 51479455Sobrien 515268632Spfg # Now run any commands specified 516268632Spfg run_commands 51779455Sobrien 518268632Spfg # Merge any old configuration files 519268632Spfg merge_old_configs 520268632Spfg 521268632Spfg # Check if we have any optional modules to load 522268632Spfg install_components 523268632Spfg 52479455Sobrien # Check if we have any packages to install 52579455Sobrien install_packages 52679455Sobrien 52779455Sobrien # All finished, unmount the file-systems 52879455Sobrien unmount_upgrade 52979455Sobrien 53079455Sobrien echo_log "Upgrade finished!" 53179455Sobrien}; 53279455Sobrien