source: src-sh/pc-sysinstall/backend/functions.sh @ 108f03c

9.2-releasereleng/10.0releng/10.0.1releng/10.0.2
Last change on this file since 108f03c was 108f03c, checked in by Kris Moore <kris@…>, 15 months ago

Add a potential fix to pc-sysinstall, to correct an issue with ZFS related
panics

  • Property mode set to 100755
File size: 11.2 KB
Line 
1#!/bin/sh
2#-
3# Copyright (c) 2010 iXsystems, Inc.  All rights reserved.
4#
5# Redistribution and use in source and binary forms, with or without
6# modification, are permitted provided that the following conditions
7# are met:
8# 1. Redistributions of source code must retain the above copyright
9#    notice, this list of conditions and the following disclaimer.
10# 2. Redistributions in binary form must reproduce the above copyright
11#    notice, this list of conditions and the following disclaimer in the
12#    documentation and/or other materials provided with the distribution.
13#
14# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24# SUCH DAMAGE.
25#
26# $FreeBSD: head/usr.sbin/pc-sysinstall/backend/functions.sh 247735 2013-03-03 23:07:27Z jpaetzel $
27
28# functions.sh
29# Library of functions which pc-sysinstall may call upon
30
31# Function which displays the help-index file
32display_help()
33{
34  if [ -e "${PROGDIR}/doc/help-index" ]
35  then
36    cat ${PROGDIR}/doc/help-index
37  else
38    echo "Error: ${PROGDIR}/doc/help-index not found"
39    exit 1
40  fi
41};
42
43# Function which displays the help for a specified command
44display_command_help()
45{
46  if [ -z "$1" ]
47  then
48    echo "Error: No command specified to display help for"
49    exit 1
50  fi
51 
52  if [ -e "${PROGDIR}/doc/help-${1}" ]
53  then
54    cat ${PROGDIR}/doc/help-${1}
55  else
56    echo "Error: ${PROGDIR}/doc/help-${1} not found"
57    exit 1
58  fi
59};
60
61# Function to convert bytes to megabytes
62convert_byte_to_megabyte()
63{
64  if [ -z "${1}" ]
65  then
66    echo "Error: No bytes specified!"
67    exit 1
68  fi
69
70  expr -e ${1} / 1048576
71};
72
73# Function to convert blocks to megabytes
74convert_blocks_to_megabyte()
75{
76  if [ -z "${1}" ] ; then
77    echo "Error: No blocks specified!"
78    exit 1
79  fi
80
81  expr -e ${1} / 2048
82};
83
84# Takes $1 and strips the whitespace out of it, returns VAL
85strip_white_space()
86{
87  if [ -z "${1}" ]
88  then
89    echo "Error: No value setup to strip whitespace from!"
90
91    exit 1
92  fi
93
94  export VAL=`echo "$1" | tr -d ' '`
95};
96
97# Displays an error message and exits with error 1
98exit_err()
99{
100  # Echo the message for the users benefit
101  echo "EXITERROR: $1"
102
103  # Save this error to the log file
104  echo "EXITERROR: ${1}" >>$LOGOUT
105
106  # Check if we need to unmount any file-systems after this failure
107  unmount_all_filesystems_failure
108
109  echo "For more details see log file: $LOGOUT"
110
111  exit 1
112};
113
114# Run-command, don't halt if command exits with non-0
115rc_nohalt()
116{
117  CMD="$1"
118
119  if [ -z "${CMD}" ]
120  then
121    exit_err "Error: missing argument in rc_nohalt()"
122  fi
123
124  # Fixes some panics we saw
125  sync
126  sleep 0.01
127
128  echo "Running: ${CMD}" >>${LOGOUT}
129  ${CMD} >>${LOGOUT} 2>>${LOGOUT}
130
131};
132
133# Run-command, halt if command exits with non-0
134rc_halt()
135{
136  CMD="$1"
137
138  if [ -z "${CMD}" ]
139  then
140    exit_err "Error: missing argument in rc_halt()"
141  fi
142
143  # Fixes some panics we saw
144  sync
145  sleep 0.01
146
147  echo "Running: ${CMD}" >>${LOGOUT}
148  eval ${CMD} >>${LOGOUT} 2>>${LOGOUT}
149  STATUS="$?"
150  if [ "${STATUS}" != "0" ]
151  then
152    exit_err "Error ${STATUS}: ${CMD}"
153  fi
154};
155
156# Run-command w/echo to screen, halt if command exits with non-0
157rc_halt_echo()
158{
159  CMD="$1"
160
161  if [ -z "${CMD}" ]
162  then
163    exit_err "Error: missing argument in rc_halt_echo()"
164  fi
165
166  echo "Running: ${CMD}" >>${LOGOUT}
167  ${CMD} 2>&1 | tee -a ${LOGOUT} 
168  STATUS="$?"
169  if [ "$STATUS" != "0" ]
170  then
171    exit_err "Error ${STATUS}: $CMD"
172  fi
173
174};
175
176# Run-command w/echo, don't halt if command exits with non-0
177rc_nohalt_echo()
178{
179  CMD="$1"
180
181  if [ -z "${CMD}" ]
182  then
183    exit_err "Error: missing argument in rc_nohalt_echo()"
184  fi
185
186  echo "Running: ${CMD}" >>${LOGOUT}
187  ${CMD} 2>&1 | tee -a ${LOGOUT} 
188
189};
190
191# Echo to the screen and to the log
192echo_log()
193{
194  STR="$1"
195
196  if [ -z "${STR}" ]
197  then
198    exit_err "Error: missing argument in echo_log()"
199  fi
200
201  echo "${STR}" | tee -a ${LOGOUT} 
202};
203
204# Make sure we have a numeric
205is_num()
206{
207  expr $1 + 1 2>/dev/null
208  return $?
209}
210
211# Function which uses "fetch" to download a file, and display a progress report
212fetch_file()
213{
214
215  FETCHFILE="$1"
216  FETCHOUTFILE="$2"
217  EXITFAILED="$3"
218
219  EXITFILE="${TMPDIR}/.fetchExit"
220
221  rm ${FETCHOUTFILE} 2>/dev/null >/dev/null
222
223  SIZE=$(( `fetch -s "${FETCHFILE}"` / 1024 ))
224  echo "FETCH: ${FETCHFILE}"
225  echo "FETCH: ${FETCHOUTFILE}" >>${LOGOUT}
226
227  ( fetch -o ${FETCHOUTFILE} "${FETCHFILE}" >/dev/null 2>/dev/null ; echo "$?" > ${EXITFILE} ) &
228  PID="$!"
229  while
230  z=1
231  do
232
233    if [ -e "${FETCHOUTFILE}" ]
234    then
235      DSIZE=`du -k ${FETCHOUTFILE} | tr -d '\t' | cut -d '/' -f 1`
236      if [ $(is_num "$DSIZE") ] ; then
237      if [ $SIZE -lt $DSIZE ] ; then DSIZE="$SIZE"; fi
238        echo "SIZE: ${SIZE} DOWNLOADED: ${DSIZE}"
239        echo "SIZE: ${SIZE} DOWNLOADED: ${DSIZE}" >>${LOGOUT}
240      fi
241    fi
242
243    # Check if the download is finished
244    ps -p ${PID} >/dev/null 2>/dev/null
245    if [ $? -ne 0 ]
246    then
247      break;
248    fi
249
250    sleep 2
251  done
252
253  echo "FETCHDONE"
254
255  EXIT="`cat ${EXITFILE}`"
256  if [ "${EXIT}" != "0" -a "$EXITFAILED" = "1" ]
257  then
258    exit_err "Error: Failed to download ${FETCHFILE}"
259  fi
260
261  return $EXIT
262
263};
264
265# Function to return a the zpool name for this device
266get_zpool_name()
267{
268  DEVICE="$1"
269
270  # Set the base name we use for zpools
271  BASENAME="tank"
272
273  if [ ! -d "${TMPDIR}/.zpools" ] ; then
274    mkdir -p ${TMPDIR}/.zpools
275  fi
276
277  if [ -e "${TMPDIR}/.zpools/${DEVICE}" ] ; then
278    cat ${TMPDIR}/.zpools/${DEVICE}
279    return 0
280  else
281    # Need to generate a zpool name for this device
282    NUM=`ls ${TMPDIR}/.zpools/ | wc -l | sed 's| ||g'`
283
284    # Is it used in another zpool?
285    while :
286    do
287      NEWNAME="${BASENAME}${NUM}"
288      zpool list | grep -qw "${NEWNAME}"
289      local chk1=$?
290      zpool import | grep -qw "${NEWNAME}"
291      local chk2=$?
292      if [ $chk1 -eq 1 -a $chk2 -eq 1 ] ; then break ; fi
293      NUM=$((NUM+1))
294    done
295
296    # Now save the new tank name
297    mkdir -p ${TMPDIR}/.zpools/`dirname $DEVICE`
298    echo "$NEWNAME" >${TMPDIR}/.zpools/${DEVICE} 
299    echo "${NEWNAME}"
300    return 0
301  fi
302};
303
304iscompressed()
305{
306  local FILE
307  local RES
308
309  FILE="$1"
310  RES=1
311
312  if echo "${FILE}" | \
313    grep -qiE '\.(Z|lzo|lzw|lzma|gz|bz2|xz|zip)$' 2>&1
314  then
315    RES=0
316  fi
317
318  return ${RES}
319}
320
321get_compression_type()
322{
323  local FILE
324  local SUFFIX
325
326  FILE="$1"
327  SUFFIX=`echo "${FILE}" | sed -E 's|^(.+)\.(.+)$|\2|'`
328
329  VAL=""
330  SUFFIX=`echo "${SUFFIX}" | tr A-Z a-z`
331  case "${SUFFIX}" in
332    z) VAL="lzw" ;;
333    lzo) VAL="lzo" ;;
334    lzw) VAL="lzw" ;;
335    lzma) VAL="lzma" ;;
336    gz) VAL="gzip" ;;
337    bz2) VAL="bzip2" ;;
338    xz) VAL="xz" ;;
339    zip) VAL="zip" ;;
340  esac
341
342  export VAL
343}
344
345write_image()
346{
347  local DEVICE_FILE
348
349  IMAGE_FILE="$1"
350  DEVICE_FILE="$2"
351
352  if [ -z "${IMAGE_FILE}" ]
353  then
354    exit_err "ERROR: Image file not specified!"
355  fi
356 
357  if [ -z "${DEVICE_FILE}" ]
358  then
359    exit_err "ERROR: Device file not specified!"
360  fi
361 
362  if [ ! -f "${IMAGE_FILE}" ]
363  then
364    exit_err "ERROR: '${IMAGE_FILE}' does not exist!"
365  fi
366
367  DEVICE_FILE="${DEVICE_FILE#/dev/}"
368  DEVICE_FILE="/dev/${DEVICE_FILE}"
369 
370  if [ ! -c "${DEVICE_FILE}" ]
371  then
372    exit_err "ERROR: '${DEVICE_FILE}' is not a character device!"
373  fi
374
375  if iscompressed "${IMAGE_FILE}"
376  then
377        local COMPRESSION
378
379    get_compression_type "${IMAGE_FILE}"
380        COMPRESSION="${VAL}"
381
382    case "${COMPRESSION}" in
383      lzw)
384        rc_halt "uncompress ${IMAGE_FILE} -c | dd of=${DEVICE_FILE}"
385        IMAGE_FILE="${IMAGE_FILE%.Z}"
386        ;;
387
388      lzo)
389        rc_halt "lzop -d $IMAGE_{FILE} -c | dd of=${DEVICE_FILE}"
390        IMAGE_FILE="${IMAGE_FILE%.lzo}"
391        ;;
392
393      lzma)
394        rc_halt "lzma -d ${IMAGE_FILE} -c | dd of=${DEVICE_FILE}"
395        IMAGE_FILE="${IMAGE_FILE%.lzma}"
396        ;;
397
398      gzip)
399        rc_halt "gunzip ${IMAGE_FILE} -c | dd of=${DEVICE_FILE}"
400        IMAGE_FILE="${IMAGE_FILE%.gz}"
401        ;;
402
403      bzip2)
404        rc_halt "bunzip2 ${IMAGE_FILE} -c | dd of=${DEVICE_FILE}"
405        IMAGE_FILE="${IMAGE_FILE%.bz2}"
406        ;;
407
408      xz)
409        rc_halt "xz -d ${IMAGE_FILE} -c | dd of=${DEVICE_FILE}"
410        IMAGE_FILE="${IMAGE_FILE%.xz}"
411        ;;
412
413      zip)
414        rc_halt "unzip ${IMAGE_FILE} -c | dd of=${DEVICE_FILE}"
415        IMAGE_FILE="${IMAGE_FILE%.zip}"
416        ;;
417
418      *) 
419        exit_err "ERROR: ${COMPRESSION} compression is not supported"
420        ;;
421    esac
422
423  else
424    rc_halt "dd if=${IMAGE_FILE} of=${DEVICE_FILE}"
425
426  fi
427};
428
429# Setup and install on a new disk / partition
430install_fresh()
431{
432  # Lets start setting up the disk slices now
433  setup_disk_slice
434 
435  if [ -z "${ROOTIMAGE}" ]
436  then
437
438    # Disk setup complete, now lets parse WORKINGSLICES and setup the bsdlabels
439    setup_disk_label
440 
441    # Now we've setup the bsdlabels, lets go ahead and run newfs / zfs
442    # to setup the filesystems
443    setup_filesystems
444
445    # Lets mount the partitions now
446    mount_all_filesystems
447
448    # We are ready to begin extraction, lets start now
449    init_extraction
450
451    # Check if we have any optional modules to load
452    install_components
453
454    # Check if we have any packages to install
455    install_packages
456
457    # Do any localization in configuration
458    run_localize
459 
460    # Save any networking config on the installed system
461    save_networking_install
462
463    # Now add any users
464    setup_users
465
466    # Do any last cleanup / setup before unmounting
467    run_final_cleanup
468
469    # Now run any commands specified
470    run_commands
471
472    # Unmount and finish up
473    unmount_all_filesystems
474  fi
475
476  echo_log "Installation finished!"
477};
478
479# Extract the system to a pre-mounted directory
480install_extractonly()
481{
482  # We are ready to begin extraction, lets start now
483  init_extraction
484
485  # Check if we have any optional modules to load
486  install_components
487
488  # Check if we have any packages to install
489  install_packages
490
491  # Do any localization in configuration
492  run_localize
493
494  # Save any networking config on the installed system
495  save_networking_install
496
497  # Now add any users
498  setup_users
499
500  # Now run any commands specified
501  run_commands
502 
503  # Set a hostname on the install system
504  setup_hostname
505     
506  # Set the root_pw if it is specified
507  set_root_pw
508
509  echo_log "Installation finished!"
510};
511
512install_image()
513{
514  # We are ready to begin extraction, lets start now
515  init_extraction
516
517  echo_log "Installation finished!"
518};
519
520install_upgrade()
521{
522  # We're going to do an upgrade, skip all the disk setup
523  # and start by mounting the target drive/slices
524  mount_upgrade
525 
526  # Start the extraction process
527  init_extraction
528
529  # Do any localization in configuration
530  run_localize
531
532  # Now run any commands specified
533  run_commands
534 
535  # Merge any old configuration files
536  merge_old_configs
537
538  # Check if we have any optional modules to load
539  install_components
540
541  # Check if we have any packages to install
542  install_packages
543
544  # All finished, unmount the file-systems
545  unmount_upgrade
546
547  echo_log "Upgrade finished!"
548};
Note: See TracBrowser for help on using the repository browser.