1209513Simp#!/bin/sh 2209513Simp#- 3209552Simp# Copyright (c) 2010 iXsystems, Inc. All rights reserved. 4209513Simp# 5209513Simp# Redistribution and use in source and binary forms, with or without 6209513Simp# modification, are permitted provided that the following conditions 7209513Simp# are met: 8209513Simp# 1. Redistributions of source code must retain the above copyright 9209513Simp# notice, this list of conditions and the following disclaimer. 10209513Simp# 2. Redistributions in binary form must reproduce the above copyright 11209513Simp# notice, this list of conditions and the following disclaimer in the 12209513Simp# documentation and/or other materials provided with the distribution. 13209513Simp# 14209513Simp# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15209513Simp# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16209513Simp# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17209513Simp# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18209513Simp# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19209513Simp# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20209513Simp# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21209513Simp# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22209513Simp# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23209513Simp# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24209513Simp# SUCH DAMAGE. 25209513Simp# 26209513Simp# $FreeBSD: releng/11.0/usr.sbin/pc-sysinstall/backend/functions.sh 247735 2013-03-03 23:07:27Z jpaetzel $ 27209513Simp 28209513Simp# functions.sh 29209513Simp# Library of functions which pc-sysinstall may call upon 30209513Simp 31209513Simp# Function which displays the help-index file 32209513Simpdisplay_help() 33209513Simp{ 34209513Simp if [ -e "${PROGDIR}/doc/help-index" ] 35209513Simp then 36209513Simp cat ${PROGDIR}/doc/help-index 37209513Simp else 38209513Simp echo "Error: ${PROGDIR}/doc/help-index not found" 39209513Simp exit 1 40209513Simp fi 41209513Simp}; 42209513Simp 43209513Simp# Function which displays the help for a specified command 44209513Simpdisplay_command_help() 45209513Simp{ 46209513Simp if [ -z "$1" ] 47209513Simp then 48209513Simp echo "Error: No command specified to display help for" 49209513Simp exit 1 50209513Simp fi 51209513Simp 52209513Simp if [ -e "${PROGDIR}/doc/help-${1}" ] 53209513Simp then 54209513Simp cat ${PROGDIR}/doc/help-${1} 55209513Simp else 56209513Simp echo "Error: ${PROGDIR}/doc/help-${1} not found" 57209513Simp exit 1 58209513Simp fi 59209513Simp}; 60209513Simp 61209513Simp# Function to convert bytes to megabytes 62209513Simpconvert_byte_to_megabyte() 63209513Simp{ 64209513Simp if [ -z "${1}" ] 65209513Simp then 66209513Simp echo "Error: No bytes specified!" 67209513Simp exit 1 68209513Simp fi 69209513Simp 70209513Simp expr -e ${1} / 1048576 71209513Simp}; 72209513Simp 73209513Simp# Function to convert blocks to megabytes 74209513Simpconvert_blocks_to_megabyte() 75209513Simp{ 76209513Simp if [ -z "${1}" ] ; then 77209513Simp echo "Error: No blocks specified!" 78209513Simp exit 1 79209513Simp fi 80209513Simp 81209513Simp expr -e ${1} / 2048 82209513Simp}; 83209513Simp 84209513Simp# Takes $1 and strips the whitespace out of it, returns VAL 85209513Simpstrip_white_space() 86209513Simp{ 87209513Simp if [ -z "${1}" ] 88209513Simp then 89209513Simp echo "Error: No value setup to strip whitespace from!" 90209513Simp 91209513Simp exit 1 92209513Simp fi 93209513Simp 94220059Sjpaetzel export VAL=`echo "$1" | tr -d ' '` 95209513Simp}; 96209513Simp 97209513Simp# Displays an error message and exits with error 1 98209513Simpexit_err() 99209513Simp{ 100211730Simp # Echo the message for the users benefit 101225657Sjpaetzel echo "EXITERROR: $1" 102209513Simp 103211730Simp # Save this error to the log file 104225657Sjpaetzel echo "EXITERROR: ${1}" >>$LOGOUT 105209513Simp 106211730Simp # Check if we need to unmount any file-systems after this failure 107211730Simp unmount_all_filesystems_failure 108209513Simp 109211730Simp echo "For more details see log file: $LOGOUT" 110209513Simp 111211730Simp exit 1 112209513Simp}; 113209513Simp 114209513Simp# Run-command, don't halt if command exits with non-0 115209513Simprc_nohalt() 116209513Simp{ 117209513Simp CMD="$1" 118209513Simp 119209513Simp if [ -z "${CMD}" ] 120209513Simp then 121209513Simp exit_err "Error: missing argument in rc_nohalt()" 122209513Simp fi 123209513Simp 124209513Simp echo "Running: ${CMD}" >>${LOGOUT} 125209513Simp ${CMD} >>${LOGOUT} 2>>${LOGOUT} 126209513Simp 127209513Simp}; 128209513Simp 129209513Simp# Run-command, halt if command exits with non-0 130209513Simprc_halt() 131209513Simp{ 132209513Simp CMD="$1" 133209513Simp 134209513Simp if [ -z "${CMD}" ] 135209513Simp then 136209513Simp exit_err "Error: missing argument in rc_halt()" 137209513Simp fi 138209513Simp 139209513Simp echo "Running: ${CMD}" >>${LOGOUT} 140214187Simp eval ${CMD} >>${LOGOUT} 2>>${LOGOUT} 141209513Simp STATUS="$?" 142209513Simp if [ "${STATUS}" != "0" ] 143209513Simp then 144209513Simp exit_err "Error ${STATUS}: ${CMD}" 145209513Simp fi 146209513Simp}; 147209513Simp 148209513Simp# Run-command w/echo to screen, halt if command exits with non-0 149209513Simprc_halt_echo() 150209513Simp{ 151209513Simp CMD="$1" 152209513Simp 153209513Simp if [ -z "${CMD}" ] 154209513Simp then 155209513Simp exit_err "Error: missing argument in rc_halt_echo()" 156209513Simp fi 157209513Simp 158209513Simp echo "Running: ${CMD}" >>${LOGOUT} 159209513Simp ${CMD} 2>&1 | tee -a ${LOGOUT} 160209513Simp STATUS="$?" 161209513Simp if [ "$STATUS" != "0" ] 162209513Simp then 163209513Simp exit_err "Error ${STATUS}: $CMD" 164209513Simp fi 165209513Simp 166209513Simp}; 167209513Simp 168209513Simp# Run-command w/echo, don't halt if command exits with non-0 169209513Simprc_nohalt_echo() 170209513Simp{ 171209513Simp CMD="$1" 172209513Simp 173209513Simp if [ -z "${CMD}" ] 174209513Simp then 175209513Simp exit_err "Error: missing argument in rc_nohalt_echo()" 176209513Simp fi 177209513Simp 178209513Simp echo "Running: ${CMD}" >>${LOGOUT} 179209513Simp ${CMD} 2>&1 | tee -a ${LOGOUT} 180209513Simp 181209513Simp}; 182209513Simp 183209513Simp# Echo to the screen and to the log 184209513Simpecho_log() 185209513Simp{ 186209513Simp STR="$1" 187209513Simp 188209513Simp if [ -z "${STR}" ] 189209513Simp then 190209513Simp exit_err "Error: missing argument in echo_log()" 191209513Simp fi 192209513Simp 193209513Simp echo "${STR}" | tee -a ${LOGOUT} 194209513Simp}; 195209513Simp 196209513Simp# Make sure we have a numeric 197211730Simpis_num() 198211730Simp{ 199211730Simp expr $1 + 1 2>/dev/null 200211730Simp return $? 201209513Simp} 202209513Simp 203209513Simp# Function which uses "fetch" to download a file, and display a progress report 204209513Simpfetch_file() 205209513Simp{ 206209513Simp 207211730Simp FETCHFILE="$1" 208211730Simp FETCHOUTFILE="$2" 209211730Simp EXITFAILED="$3" 210209513Simp 211211730Simp EXITFILE="${TMPDIR}/.fetchExit" 212209513Simp 213211730Simp rm ${FETCHOUTFILE} 2>/dev/null >/dev/null 214209513Simp 215235453Sjpaetzel SIZE=$(( `fetch -s "${FETCHFILE}"` / 1024 )) 216211730Simp echo "FETCH: ${FETCHFILE}" 217211730Simp echo "FETCH: ${FETCHOUTFILE}" >>${LOGOUT} 218209513Simp 219211730Simp ( fetch -o ${FETCHOUTFILE} "${FETCHFILE}" >/dev/null 2>/dev/null ; echo "$?" > ${EXITFILE} ) & 220211730Simp PID="$!" 221211730Simp while 222211730Simp z=1 223211730Simp do 224209513Simp 225211730Simp if [ -e "${FETCHOUTFILE}" ] 226211730Simp then 227211730Simp DSIZE=`du -k ${FETCHOUTFILE} | tr -d '\t' | cut -d '/' -f 1` 228211730Simp if [ $(is_num "$DSIZE") ] ; then 229211730Simp if [ $SIZE -lt $DSIZE ] ; then DSIZE="$SIZE"; fi 230209513Simp echo "SIZE: ${SIZE} DOWNLOADED: ${DSIZE}" 231209513Simp echo "SIZE: ${SIZE} DOWNLOADED: ${DSIZE}" >>${LOGOUT} 232211730Simp fi 233209513Simp fi 234209513Simp 235211730Simp # Check if the download is finished 236211730Simp ps -p ${PID} >/dev/null 2>/dev/null 237220059Sjpaetzel if [ $? -ne 0 ] 238211730Simp then 239211730Simp break; 240211730Simp fi 241209513Simp 242211730Simp sleep 2 243211730Simp done 244209513Simp 245211730Simp echo "FETCHDONE" 246209513Simp 247211730Simp EXIT="`cat ${EXITFILE}`" 248211730Simp if [ "${EXIT}" != "0" -a "$EXITFAILED" = "1" ] 249211730Simp then 250211730Simp exit_err "Error: Failed to download ${FETCHFILE}" 251211730Simp fi 252209513Simp 253211730Simp return $EXIT 254209513Simp 255209513Simp}; 256209513Simp 257209513Simp# Function to return a the zpool name for this device 258209513Simpget_zpool_name() 259209513Simp{ 260209513Simp DEVICE="$1" 261209513Simp 262209513Simp # Set the base name we use for zpools 263209513Simp BASENAME="tank" 264209513Simp 265209513Simp if [ ! -d "${TMPDIR}/.zpools" ] ; then 266209513Simp mkdir -p ${TMPDIR}/.zpools 267209513Simp fi 268209513Simp 269209513Simp if [ -e "${TMPDIR}/.zpools/${DEVICE}" ] ; then 270209513Simp cat ${TMPDIR}/.zpools/${DEVICE} 271209513Simp return 0 272209513Simp else 273209513Simp # Need to generate a zpool name for this device 274209513Simp NUM=`ls ${TMPDIR}/.zpools/ | wc -l | sed 's| ||g'` 275235005Sjpaetzel 276235005Sjpaetzel # Is it used in another zpool? 277235453Sjpaetzel while : 278235005Sjpaetzel do 279235005Sjpaetzel NEWNAME="${BASENAME}${NUM}" 280247735Sjpaetzel zpool list | grep -qw "${NEWNAME}" 281247735Sjpaetzel local chk1=$? 282247735Sjpaetzel zpool import | grep -qw "${NEWNAME}" 283247735Sjpaetzel local chk2=$? 284247735Sjpaetzel if [ $chk1 -eq 1 -a $chk2 -eq 1 ] ; then break ; fi 285235005Sjpaetzel NUM=$((NUM+1)) 286235005Sjpaetzel done 287235005Sjpaetzel 288235005Sjpaetzel # Now save the new tank name 289220909Sjpaetzel mkdir -p ${TMPDIR}/.zpools/`dirname $DEVICE` 290209513Simp echo "$NEWNAME" >${TMPDIR}/.zpools/${DEVICE} 291209513Simp echo "${NEWNAME}" 292235005Sjpaetzel return 0 293209513Simp fi 294209513Simp}; 295212337Simp 296213650Simpiscompressed() 297213650Simp{ 298213650Simp local FILE 299213650Simp local RES 300213650Simp 301213650Simp FILE="$1" 302213650Simp RES=1 303213650Simp 304213650Simp if echo "${FILE}" | \ 305220059Sjpaetzel grep -qiE '\.(Z|lzo|lzw|lzma|gz|bz2|xz|zip)$' 2>&1 306213650Simp then 307213650Simp RES=0 308213650Simp fi 309213650Simp 310213650Simp return ${RES} 311213650Simp} 312213650Simp 313213650Simpget_compression_type() 314213650Simp{ 315213650Simp local FILE 316213650Simp local SUFFIX 317213650Simp 318213650Simp FILE="$1" 319213650Simp SUFFIX=`echo "${FILE}" | sed -E 's|^(.+)\.(.+)$|\2|'` 320213650Simp 321213650Simp VAL="" 322213650Simp SUFFIX=`echo "${SUFFIX}" | tr A-Z a-z` 323213650Simp case "${SUFFIX}" in 324213650Simp z) VAL="lzw" ;; 325213650Simp lzo) VAL="lzo" ;; 326213650Simp lzw) VAL="lzw" ;; 327213650Simp lzma) VAL="lzma" ;; 328213650Simp gz) VAL="gzip" ;; 329213650Simp bz2) VAL="bzip2" ;; 330213650Simp xz) VAL="xz" ;; 331213650Simp zip) VAL="zip" ;; 332213650Simp esac 333213650Simp 334213650Simp export VAL 335213650Simp} 336213650Simp 337212337Simpwrite_image() 338212337Simp{ 339213650Simp local DEVICE_FILE 340213650Simp 341212337Simp IMAGE_FILE="$1" 342212337Simp DEVICE_FILE="$2" 343212337Simp 344212337Simp if [ -z "${IMAGE_FILE}" ] 345212337Simp then 346213650Simp exit_err "ERROR: Image file not specified!" 347212337Simp fi 348212337Simp 349212337Simp if [ -z "${DEVICE_FILE}" ] 350212337Simp then 351213650Simp exit_err "ERROR: Device file not specified!" 352212337Simp fi 353212337Simp 354212337Simp if [ ! -f "${IMAGE_FILE}" ] 355212337Simp then 356213650Simp exit_err "ERROR: '${IMAGE_FILE}' does not exist!" 357212337Simp fi 358212337Simp 359212337Simp DEVICE_FILE="${DEVICE_FILE#/dev/}" 360212337Simp DEVICE_FILE="/dev/${DEVICE_FILE}" 361212337Simp 362212337Simp if [ ! -c "${DEVICE_FILE}" ] 363212337Simp then 364213650Simp exit_err "ERROR: '${DEVICE_FILE}' is not a character device!" 365212337Simp fi 366212337Simp 367213650Simp if iscompressed "${IMAGE_FILE}" 368212337Simp then 369213650Simp local COMPRESSION 370213650Simp 371213650Simp get_compression_type "${IMAGE_FILE}" 372213650Simp COMPRESSION="${VAL}" 373213650Simp 374214139Simp case "${COMPRESSION}" in 375214139Simp lzw) 376214187Simp rc_halt "uncompress ${IMAGE_FILE} -c | dd of=${DEVICE_FILE}" 377214139Simp IMAGE_FILE="${IMAGE_FILE%.Z}" 378214139Simp ;; 379214139Simp 380214139Simp lzo) 381214187Simp rc_halt "lzop -d $IMAGE_{FILE} -c | dd of=${DEVICE_FILE}" 382214139Simp IMAGE_FILE="${IMAGE_FILE%.lzo}" 383214139Simp ;; 384214139Simp 385214139Simp lzma) 386214187Simp rc_halt "lzma -d ${IMAGE_FILE} -c | dd of=${DEVICE_FILE}" 387214139Simp IMAGE_FILE="${IMAGE_FILE%.lzma}" 388214139Simp ;; 389214139Simp 390214139Simp gzip) 391214187Simp rc_halt "gunzip ${IMAGE_FILE} -c | dd of=${DEVICE_FILE}" 392214139Simp IMAGE_FILE="${IMAGE_FILE%.gz}" 393214139Simp ;; 394214139Simp 395214139Simp bzip2) 396214187Simp rc_halt "bunzip2 ${IMAGE_FILE} -c | dd of=${DEVICE_FILE}" 397214139Simp IMAGE_FILE="${IMAGE_FILE%.bz2}" 398214139Simp ;; 399214139Simp 400214139Simp xz) 401214187Simp rc_halt "xz -d ${IMAGE_FILE} -c | dd of=${DEVICE_FILE}" 402214139Simp IMAGE_FILE="${IMAGE_FILE%.xz}" 403214139Simp ;; 404214139Simp 405214139Simp zip) 406214187Simp rc_halt "unzip ${IMAGE_FILE} -c | dd of=${DEVICE_FILE}" 407214139Simp IMAGE_FILE="${IMAGE_FILE%.zip}" 408214139Simp ;; 409214139Simp 410214139Simp *) 411214139Simp exit_err "ERROR: ${COMPRESSION} compression is not supported" 412214139Simp ;; 413214139Simp esac 414214139Simp 415214139Simp else 416214187Simp rc_halt "dd if=${IMAGE_FILE} of=${DEVICE_FILE}" 417214139Simp 418212337Simp fi 419212337Simp}; 420212337Simp 421218776Sjpaetzel# Setup and install on a new disk / partition 422212337Simpinstall_fresh() 423212337Simp{ 424212337Simp # Lets start setting up the disk slices now 425212337Simp setup_disk_slice 426212337Simp 427213650Simp if [ -z "${ROOTIMAGE}" ] 428213650Simp then 429213650Simp 430213650Simp # Disk setup complete, now lets parse WORKINGSLICES and setup the bsdlabels 431213650Simp setup_disk_label 432212337Simp 433213650Simp # Now we've setup the bsdlabels, lets go ahead and run newfs / zfs 434213650Simp # to setup the filesystems 435213650Simp setup_filesystems 436212337Simp 437213650Simp # Lets mount the partitions now 438213650Simp mount_all_filesystems 439212337Simp 440213650Simp # We are ready to begin extraction, lets start now 441213650Simp init_extraction 442212337Simp 443213650Simp # Check if we have any optional modules to load 444213650Simp install_components 445212337Simp 446213650Simp # Check if we have any packages to install 447213650Simp install_packages 448212337Simp 449213650Simp # Do any localization in configuration 450213650Simp run_localize 451212337Simp 452213650Simp # Save any networking config on the installed system 453213650Simp save_networking_install 454212337Simp 455213650Simp # Now add any users 456213650Simp setup_users 457212337Simp 458213650Simp # Do any last cleanup / setup before unmounting 459213650Simp run_final_cleanup 460212337Simp 461225657Sjpaetzel # Now run any commands specified 462225657Sjpaetzel run_commands 463225657Sjpaetzel 464213650Simp # Unmount and finish up 465213650Simp unmount_all_filesystems 466213650Simp fi 467212337Simp 468212337Simp echo_log "Installation finished!" 469213650Simp}; 470212337Simp 471218776Sjpaetzel# Extract the system to a pre-mounted directory 472218776Sjpaetzelinstall_extractonly() 473218776Sjpaetzel{ 474218776Sjpaetzel # We are ready to begin extraction, lets start now 475218776Sjpaetzel init_extraction 476218776Sjpaetzel 477218776Sjpaetzel # Check if we have any optional modules to load 478218776Sjpaetzel install_components 479218776Sjpaetzel 480218776Sjpaetzel # Check if we have any packages to install 481218776Sjpaetzel install_packages 482218776Sjpaetzel 483218776Sjpaetzel # Do any localization in configuration 484218776Sjpaetzel run_localize 485218776Sjpaetzel 486218776Sjpaetzel # Save any networking config on the installed system 487218776Sjpaetzel save_networking_install 488218776Sjpaetzel 489218776Sjpaetzel # Now add any users 490218776Sjpaetzel setup_users 491218776Sjpaetzel 492218776Sjpaetzel # Now run any commands specified 493218776Sjpaetzel run_commands 494218776Sjpaetzel 495218776Sjpaetzel # Set a hostname on the install system 496218776Sjpaetzel setup_hostname 497218776Sjpaetzel 498218776Sjpaetzel # Set the root_pw if it is specified 499218776Sjpaetzel set_root_pw 500218776Sjpaetzel 501218776Sjpaetzel echo_log "Installation finished!" 502218776Sjpaetzel}; 503218776Sjpaetzel 504213650Simpinstall_image() 505213650Simp{ 506213650Simp # We are ready to begin extraction, lets start now 507213650Simp init_extraction 508213650Simp 509213650Simp echo_log "Installation finished!" 510213650Simp}; 511213650Simp 512212337Simpinstall_upgrade() 513212337Simp{ 514212337Simp # We're going to do an upgrade, skip all the disk setup 515212337Simp # and start by mounting the target drive/slices 516212337Simp mount_upgrade 517212337Simp 518212337Simp # Start the extraction process 519212337Simp init_extraction 520212337Simp 521212337Simp # Do any localization in configuration 522212337Simp run_localize 523212337Simp 524218776Sjpaetzel # Now run any commands specified 525212337Simp run_commands 526212337Simp 527212337Simp # Merge any old configuration files 528212337Simp merge_old_configs 529212337Simp 530212337Simp # Check if we have any optional modules to load 531212337Simp install_components 532212337Simp 533212337Simp # Check if we have any packages to install 534212337Simp install_packages 535212337Simp 536212337Simp # All finished, unmount the file-systems 537212337Simp unmount_upgrade 538212337Simp 539212337Simp echo_log "Upgrade finished!" 540213650Simp}; 541