functions-extractimage.sh revision 247705
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-extractimage.sh 247705 2013-03-03 09:47:47Z jpaetzel $ 27 28# Functions which perform the extraction / installation of system to disk 29 30. ${BACKEND}/functions-mountoptical.sh 31 32# Performs the extraction of data to disk from FreeBSD dist files 33start_extract_dist() 34{ 35 if [ -z "$1" ] ; then exit_err "Called dist extraction with no directory set!"; fi 36 if [ -z "$INSFILE" ]; then exit_err "Called extraction with no install file set!"; fi 37 local DDIR="$1" 38 39 # Check if we are doing an upgrade, and if so use our exclude list 40 if [ "${INSTALLMODE}" = "upgrade" ]; then 41 TAROPTS="-X ${PROGDIR}/conf/exclude-from-upgrade" 42 else 43 TAROPTS="" 44 fi 45 46 # Loop though and extract dist files 47 for di in $INSFILE 48 do 49 # Check the MANIFEST see if we have an archive size / count 50 if [ -e "${DDIR}/MANIFEST" ]; then 51 count=`grep "^${di}.txz" ${DDIR}/MANIFEST | awk '{print $3}'` 52 if [ ! -z "$count" ] ; then 53 echo "INSTALLCOUNT: $count" 54 fi 55 fi 56 echo_log "pc-sysinstall: Starting Extraction (${di})" 57 tar -xpv -C ${FSMNT} -f ${DDIR}/${di}.txz ${TAROPTS} >&1 2>&1 58 if [ $? -ne 0 ]; then 59 exit_err "ERROR: Failed extracting the dist file: $di" 60 fi 61 done 62 63 # Check if this was a FTP download and clean it up now 64 if [ "${INSTALLMEDIUM}" = "ftp" ]; then 65 echo_log "Cleaning up downloaded archives" 66 rm -rf ${DDIR} 67 fi 68 69 echo_log "pc-sysinstall: Extraction Finished" 70} 71 72# Performs the extraction of data to disk from a uzip or tar archive 73start_extract_uzip_tar() 74{ 75 if [ -z "$INSFILE" ]; then 76 exit_err "ERROR: Called extraction with no install file set!" 77 fi 78 79 # Check if we have a .count file, and echo it out for a front-end to use in progress bars 80 if [ -e "${INSFILE}.count" ]; then 81 echo "INSTALLCOUNT: `cat ${INSFILE}.count`" 82 fi 83 84 # Check if we are doing an upgrade, and if so use our exclude list 85 if [ "${INSTALLMODE}" = "upgrade" ]; then 86 TAROPTS="-X ${PROGDIR}/conf/exclude-from-upgrade" 87 else 88 TAROPTS="" 89 fi 90 91 echo_log "pc-sysinstall: Starting Extraction" 92 93 case ${PACKAGETYPE} in 94 uzip) 95 if ! kldstat -v | grep -q "geom_uzip" ; then 96 exit_err "Kernel module geom_uzip not loaded" 97 fi 98 99 # Start by mounting the uzip image 100 MDDEVICE=`mdconfig -a -t vnode -o readonly -f ${INSFILE}` 101 mkdir -p ${FSMNT}.uzip 102 mount -r /dev/${MDDEVICE}.uzip ${FSMNT}.uzip 103 if [ $? -ne 0 ] 104 then 105 exit_err "ERROR: Failed mounting the ${INSFILE}" 106 fi 107 cd ${FSMNT}.uzip 108 109 # Copy over all the files now! 110 tar cvf - . 2>/dev/null | tar -xpv -C ${FSMNT} ${TAROPTS} -f - 2>&1 | tee -a ${FSMNT}/.tar-extract.log 111 if [ $? -ne 0 ] 112 then 113 cd / 114 echo "TAR failure occurred:" >>${LOGOUT} 115 cat ${FSMNT}/.tar-extract.log | grep "tar:" >>${LOGOUT} 116 umount ${FSMNT}.uzip 117 mdconfig -d -u ${MDDEVICE} 118 exit_err "ERROR: Failed extracting the tar image" 119 fi 120 121 # All finished, now lets umount and cleanup 122 cd / 123 umount ${FSMNT}.uzip 124 mdconfig -d -u ${MDDEVICE} 125 ;; 126 tar) 127 tar -xpv -C ${FSMNT} -f ${INSFILE} ${TAROPTS} >&1 2>&1 128 if [ $? -ne 0 ]; then 129 exit_err "ERROR: Failed extracting the tar image" 130 fi 131 ;; 132 esac 133 134 # Check if this was a FTP download and clean it up now 135 if [ "${INSTALLMEDIUM}" = "ftp" ] 136 then 137 echo_log "Cleaning up downloaded archive" 138 rm ${INSFILE} 139 rm ${INSFILE}.count >/dev/null 2>/dev/null 140 rm ${INSFILE}.md5 >/dev/null 2>/dev/null 141 fi 142 143 echo_log "pc-sysinstall: Extraction Finished" 144 145}; 146 147# Performs the extraction of data to disk from a directory with split files 148start_extract_split() 149{ 150 if [ -z "${INSDIR}" ] 151 then 152 exit_err "ERROR: Called extraction with no install directory set!" 153 fi 154 155 echo_log "pc-sysinstall: Starting Extraction" 156 157 # Used by install.sh 158 DESTDIR="${FSMNT}" 159 export DESTDIR 160 161 HERE=`pwd` 162 DIRS=`ls -d ${INSDIR}/*|grep -Ev '(uzip|kernels|src)'` 163 for dir in ${DIRS} 164 do 165 cd "${dir}" 166 if [ -f "install.sh" ] 167 then 168 echo_log "Extracting" `basename ${dir}` 169 echo "y" | sh install.sh >/dev/null 170 if [ $? -ne 0 ] 171 then 172 exit_err "ERROR: Failed extracting ${dir}" 173 fi 174 else 175 exit_err "ERROR: ${dir}/install.sh does not exist" 176 fi 177 done 178 cd "${HERE}" 179 180 KERNELS=`ls -d ${INSDIR}/*|grep kernels` 181 cd "${KERNELS}" 182 if [ -f "install.sh" ] 183 then 184 echo_log "Extracting" `basename ${KERNELS}` 185 echo "y" | sh install.sh generic >/dev/null 186 if [ $? -ne 0 ] 187 then 188 exit_err "ERROR: Failed extracting ${KERNELS}" 189 fi 190 rm -rf "${FSMNT}/boot/kernel" 191 mv "${FSMNT}/boot/GENERIC" "${FSMNT}/boot/kernel" 192 else 193 exit_err "ERROR: ${KERNELS}/install.sh does not exist" 194 fi 195 cd "${HERE}" 196 197 SOURCE=`ls -d ${INSDIR}/*|grep src` 198 cd "${SOURCE}" 199 if [ -f "install.sh" ] 200 then 201 echo_log "Extracting" `basename ${SOURCE}` 202 echo "y" | sh install.sh all >/dev/null 203 if [ $? -ne 0 ] 204 then 205 exit_err "ERROR: Failed extracting ${SOURCE}" 206 fi 207 else 208 exit_err "ERROR: ${SOURCE}/install.sh does not exist" 209 fi 210 cd "${HERE}" 211 212 echo_log "pc-sysinstall: Extraction Finished" 213}; 214 215# Function which will attempt to fetch the dist file(s) before we start 216fetch_dist_file() 217{ 218 get_value_from_cfg ftpPath 219 if [ -z "$VAL" ] 220 then 221 exit_err "ERROR: Install medium was set to ftp, but no ftpPath was provided!" 222 fi 223 224 FTPPATH="${VAL}" 225 226 # Check if we have a /usr partition to save the download 227 if [ -d "${FSMNT}/usr" ] 228 then 229 DLDIR="${FSMNT}/usr/.fetch.$$" 230 else 231 DLDIR="${FSMNT}/.fetch.$$" 232 fi 233 mkdir -p ${DLDIR} 234 235 # Do the fetch of the dist archive(s) now 236 for di in $INSFILE 237 do 238 fetch_file "${FTPPATH}/${di}.txz" "${DLDIR}/${di}.txz" "1" 239 done 240 241 # Check to see if there is a MANIFEST file for this install 242 fetch_file "${FTPPATH}/MANIFEST" "${DLDIR}/MANIFEST" "0" 243 244 export DLDIR 245}; 246 247# Function which will attempt to fetch the install file before we start 248# the install 249fetch_install_file() 250{ 251 get_value_from_cfg ftpPath 252 if [ -z "$VAL" ] 253 then 254 exit_err "ERROR: Install medium was set to ftp, but no ftpPath was provided!" 255 fi 256 257 FTPPATH="${VAL}" 258 259 # Check if we have a /usr partition to save the download 260 if [ -d "${FSMNT}/usr" ] 261 then 262 OUTFILE="${FSMNT}/usr/.fetch-${INSFILE}" 263 else 264 OUTFILE="${FSMNT}/.fetch-${INSFILE}" 265 fi 266 267 # Do the fetch of the archive now 268 fetch_file "${FTPPATH}/${INSFILE}" "${OUTFILE}" "1" 269 270 # Check to see if there is a .count file for this install 271 fetch_file "${FTPPATH}/${INSFILE}.count" "${OUTFILE}.count" "0" 272 273 # Check to see if there is a .md5 file for this install 274 fetch_file "${FTPPATH}/${INSFILE}.md5" "${OUTFILE}.md5" "0" 275 276 # Done fetching, now reset the INSFILE to our downloaded archived 277 export INSFILE="${OUTFILE}" 278 279}; 280 281# Function which will download freebsd install files 282fetch_split_files() 283{ 284 get_ftpHost 285 if [ -z "$VAL" ] 286 then 287 exit_err "ERROR: Install medium was set to ftp, but no ftpHost was provided!" 288 fi 289 FTPHOST="${VAL}" 290 291 get_ftpDir 292 if [ -z "$VAL" ] 293 then 294 exit_err "ERROR: Install medium was set to ftp, but no ftpDir was provided!" 295 fi 296 FTPDIR="${VAL}" 297 298 # Check if we have a /usr partition to save the download 299 if [ -d "${FSMNT}/usr" ] 300 then 301 OUTFILE="${FSMNT}/usr/.fetch-${INSFILE}" 302 else 303 OUTFILE="${FSMNT}/.fetch-${INSFILE}" 304 fi 305 306 DIRS="base catpages dict doc games info manpages proflibs kernels src" 307 if [ "${FBSD_ARCH}" = "amd64" ] 308 then 309 DIRS="${DIRS} lib32" 310 fi 311 312 for d in ${DIRS} 313 do 314 mkdir -p "${OUTFILE}/${d}" 315 done 316 317 318 NETRC="${OUTFILE}/.netrc" 319 cat <<EOF >"${NETRC}" 320machine ${FTPHOST} 321login anonymous 322password anonymous 323macdef INSTALL 324bin 325prompt 326EOF 327 328 for d in ${DIRS} 329 do 330 cat <<EOF >>"${NETRC}" 331cd ${FTPDIR}/${d} 332lcd ${OUTFILE}/${d} 333mreget * 334EOF 335 done 336 337 cat <<EOF >>"${NETRC}" 338bye 339 340 341EOF 342 343 # Fetch the files via ftp 344 echo "$ INSTALL" | ftp -N "${NETRC}" "${FTPHOST}" 345 346 # Done fetching, now reset the INSFILE to our downloaded archived 347 export INSFILE="${OUTFILE}" 348} 349 350# Function which does the rsync download from the server specified in cfg 351start_rsync_copy() 352{ 353 # Load our rsync config values 354 get_value_from_cfg rsyncPath 355 if [ -z "${VAL}" ]; then 356 exit_err "ERROR: rsyncPath is unset! Please check your config and try again." 357 fi 358 export RSYNCPATH="${VAL}" 359 360 get_value_from_cfg rsyncHost 361 if [ -z "${VAL}" ]; then 362 exit_err "ERROR: rsyncHost is unset! Please check your config and try again." 363 fi 364 export RSYNCHOST="${VAL}" 365 366 get_value_from_cfg rsyncUser 367 if [ -z "${VAL}" ]; then 368 exit_err "ERROR: rsyncUser is unset! Please check your config and try again." 369 fi 370 export RSYNCUSER="${VAL}" 371 372 get_value_from_cfg rsyncPort 373 if [ -z "${VAL}" ]; then 374 exit_err "ERROR: rsyncPort is unset! Please check your config and try again." 375 fi 376 export RSYNCPORT="${VAL}" 377 378 COUNT=1 379 while 380 z=1 381 do 382 if [ ${COUNT} -gt ${RSYNCTRIES} ] 383 then 384 exit_err "ERROR: Failed rsync command!" 385 break 386 fi 387 388 rsync -avvzHsR \ 389 --rsync-path="rsync --fake-super" \ 390 -e "ssh -p ${RSYNCPORT}" \ 391 ${RSYNCUSER}@${RSYNCHOST}:${RSYNCPATH}/./ ${FSMNT} 392 if [ $? -ne 0 ] 393 then 394 echo "Rsync failed! Tries: ${COUNT}" 395 else 396 break 397 fi 398 399 COUNT=$((COUNT+1)) 400 done 401 402}; 403 404start_image_install() 405{ 406 if [ -z "${IMAGE_FILE}" ] 407 then 408 exit_err "ERROR: installMedium set to image but no image file specified!" 409 fi 410 411 # We are ready to start mounting, lets read the config and do it 412 while read line 413 do 414 echo $line | grep -q "^disk0=" 2>/dev/null 415 if [ $? -eq 0 ] 416 then 417 # Found a disk= entry, lets get the disk we are working on 418 get_value_from_string "${line}" 419 strip_white_space "$VAL" 420 DISK="$VAL" 421 fi 422 423 echo $line | grep -q "^commitDiskPart" 2>/dev/null 424 if [ $? -eq 0 ] 425 then 426 # Found our flag to commit this disk setup / lets do sanity check and do it 427 if [ -n "${DISK}" ] 428 then 429 430 # Write the image 431 write_image "${IMAGE_FILE}" "${DISK}" 432 433 # Increment our disk counter to look for next disk and unset 434 unset DISK 435 break 436 437 else 438 exit_err "ERROR: commitDiskPart was called without procceding disk<num>= and partition= entries!!!" 439 fi 440 fi 441 442 done <${CFGF} 443}; 444 445# Entrance function, which starts the installation process 446init_extraction() 447{ 448 # Figure out what file we are using to install from via the config 449 get_value_from_cfg installFile 450 451 if [ -n "${VAL}" ] 452 then 453 export INSFILE="${VAL}" 454 else 455 # If no installFile specified, try our defaults 456 if [ "$INSTALLTYPE" = "FreeBSD" ] 457 then 458 case $PACKAGETYPE in 459 uzip) INSFILE="${FBSD_UZIP_FILE}" ;; 460 tar) INSFILE="${FBSD_TAR_FILE}" ;; 461 dist) 462 get_value_from_cfg_with_spaces distFiles 463 if [ -z "$VAL" ] ; then 464 exit_err "No dist files specified!" 465 fi 466 INSFILE="${VAL}" 467 ;; 468 split) 469 INSDIR="${FBSD_BRANCH_DIR}" 470 471 # This is to trick opt_mount into not failing 472 INSFILE="${INSDIR}" 473 ;; 474 esac 475 else 476 case $PACKAGETYPE in 477 uzip) INSFILE="${UZIP_FILE}" ;; 478 tar) INSFILE="${TAR_FILE}" ;; 479 dist) 480 get_value_from_cfg_with_spaces distFiles 481 if [ -z "$VAL" ] ; then 482 exit_err "No dist files specified!" 483 fi 484 INSFILE="${VAL}" 485 ;; 486 esac 487 fi 488 export INSFILE 489 fi 490 491 # Lets start by figuring out what medium we are using 492 case ${INSTALLMEDIUM} in 493 dvd|usb) 494 # Lets start by mounting the disk 495 opt_mount 496 if [ -n "${INSDIR}" ] 497 then 498 INSDIR="${CDMNT}/${INSDIR}" ; export INSDIR 499 start_extract_split 500 501 else 502 if [ "$PACKAGETYPE" = "dist" ] ; then 503 start_extract_dist "${CDMNT}/usr/freebsd-dist" 504 else 505 INSFILE="${CDMNT}/${INSFILE}" ; export INSFILE 506 start_extract_uzip_tar 507 fi 508 fi 509 ;; 510 511 ftp) 512 case $PACKAGETYPE in 513 split) 514 fetch_split_files 515 516 INSDIR="${INSFILE}" ; export INSDIR 517 start_extract_split 518 ;; 519 dist) 520 fetch_dist_file 521 start_extract_dist "$DLDIR" 522 ;; 523 *) 524 fetch_install_file 525 start_extract_uzip_tar 526 ;; 527 esac 528 ;; 529 530 sftp) ;; 531 532 rsync) start_rsync_copy ;; 533 image) start_image_install ;; 534 local) 535 get_value_from_cfg localPath 536 if [ -z "$VAL" ] 537 then 538 exit_err "Install medium was set to local, but no localPath was provided!" 539 fi 540 LOCALPATH=$VAL 541 if [ "$PACKAGETYPE" = "dist" ] ; then 542 INSFILE="${INSFILE}" ; export INSFILE 543 start_extract_dist "$LOCALPATH" 544 else 545 INSFILE="${LOCALPATH}/${INSFILE}" ; export INSFILE 546 start_extract_uzip_tar 547 fi 548 ;; 549 *) exit_err "ERROR: Unknown install medium" ;; 550 esac 551 552}; 553