functions-extractimage.sh revision 212337
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 212337 2010-09-08 20:10:24Z imp $
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 a uzip or tar archive
33start_extract_uzip_tar()
34{
35  if [ -z "$INSFILE" ]
36  then
37    exit_err "ERROR: Called extraction with no install file set!"
38  fi
39
40  # Check if we have a .count file, and echo it out for a front-end to use in progress bars
41  if [ -e "${INSFILE}.count" ]
42  then
43    echo "INSTALLCOUNT: `cat ${INSFILE}.count`"
44  fi
45
46  # Check if we are doing an upgrade, and if so use our exclude list
47  if [ "${INSTALLMODE}" = "upgrade" ]
48  then
49   TAROPTS="-X ${PROGDIR}/conf/exclude-from-upgrade"
50  else
51   TAROPTS=""
52  fi
53
54  echo_log "pc-sysinstall: Starting Extraction"
55
56  case ${PACKAGETYPE} in
57    uzip)
58	  # Start by mounting the uzip image
59      MDDEVICE=`mdconfig -a -t vnode -o readonly -f ${INSFILE}`
60      mkdir -p ${FSMNT}.uzip
61      mount -r /dev/${MDDEVICE}.uzip ${FSMNT}.uzip
62      if [ "$?" != "0" ]
63      then
64        exit_err "ERROR: Failed mounting the ${INSFILE}"
65      fi
66      cd ${FSMNT}.uzip
67
68      # Copy over all the files now!
69      tar cvf - . 2>/dev/null | tar -xpv -C ${FSMNT} ${TAROPTS} -f - 2>&1 | tee -a ${FSMNT}/.tar-extract.log
70      if [ "$?" != "0" ]
71      then
72        cd /
73        echo "TAR failure occured:" >>${LOGOUT}
74        cat ${FSMNT}/.tar-extract.log | grep "tar:" >>${LOGOUT}
75        umount ${FSMNT}.uzip
76        mdconfig -d -u ${MDDEVICE}
77        exit_err "ERROR: Failed extracting the tar image"
78      fi
79
80      # All finished, now lets umount and cleanup
81      cd /
82      umount ${FSMNT}.uzip
83      mdconfig -d -u ${MDDEVICE}
84       ;;
85    tar)
86	  tar -xpv -C ${FSMNT} -f ${INSFILE} ${TAROPTS} >&1 2>&1
87      if [ "$?" != "0" ]
88      then
89        exit_err "ERROR: Failed extracting the tar image"
90      fi
91      ;;
92  esac
93
94  # Check if this was a FTP download and clean it up now
95  if [ "${INSTALLMEDIUM}" = "ftp" ]
96  then
97    echo_log "Cleaning up downloaded archive"
98    rm ${INSFILE} 
99    rm ${INSFILE}.count >/dev/null 2>/dev/null 
100    rm ${INSFILE}.md5 >/dev/null 2>/dev/null
101  fi
102
103  echo_log "pc-sysinstall: Extraction Finished"
104
105};
106
107# Performs the extraction of data to disk from a directory with split files
108start_extract_split()
109{
110  if [ -z "${INSDIR}" ]
111  then
112    exit_err "ERROR: Called extraction with no install directory set!"
113  fi
114
115  echo_log "pc-sysinstall: Starting Extraction"
116
117  # Used by install.sh
118  DESTDIR="${FSMNT}"
119  export DESTDIR
120
121  HERE=`pwd`
122  DIRS=`ls -d ${INSDIR}/*|grep -Ev '(uzip|kernels|src)'`
123  for dir in ${DIRS}
124  do
125    cd "${dir}"
126    if [ -f "install.sh" ]
127    then
128      echo_log "Extracting" `basename ${dir}`
129      echo "y" | sh install.sh >/dev/null
130      if [ "$?" != "0" ]
131      then
132        exit_err "ERROR: Failed extracting ${dir}"
133      fi
134    else
135      exit_err "ERROR: ${dir}/install.sh does not exist"
136    fi
137  done
138  cd "${HERE}"
139  
140  KERNELS=`ls -d ${INSDIR}/*|grep kernels`
141  cd "${KERNELS}"
142  if [ -f "install.sh" ]
143  then
144    echo_log "Extracting" `basename ${KERNELS}`
145    echo "y" | sh install.sh generic >/dev/null
146    if [ "$?" != "0" ]
147    then
148      exit_err "ERROR: Failed extracting ${KERNELS}"
149    fi
150    mv "${FSMNT}/boot/GENERIC" "${FSMNT}/boot/kernel"
151  else
152    exit_err "ERROR: ${KERNELS}/install.sh does not exist"
153  fi
154  cd "${HERE}"
155
156  SOURCE=`ls -d ${INSDIR}/*|grep src`
157  cd "${SOURCE}"
158  if [ -f "install.sh" ]
159  then
160    echo_log "Extracting" `basename ${SOURCE}`
161    echo "y" | sh install.sh all >/dev/null
162    if [ "$?" != "0" ]
163    then
164      exit_err "ERROR: Failed extracting ${SOURCE}"
165    fi
166  else
167    exit_err "ERROR: ${SOURCE}/install.sh does not exist"
168  fi
169  cd "${HERE}"
170
171  echo_log "pc-sysinstall: Extraction Finished"
172};
173
174# Function which will attempt to fetch the install file before we start
175# the install
176fetch_install_file()
177{
178  get_value_from_cfg ftpPath
179  if [ -z "$VAL" ]
180  then
181    exit_err "ERROR: Install medium was set to ftp, but no ftpPath was provided!" 
182  fi
183
184  FTPPATH="${VAL}"
185  
186  # Check if we have a /usr partition to save the download
187  if [ -d "${FSMNT}/usr" ]
188  then
189    OUTFILE="${FSMNT}/usr/.fetch-${INSFILE}"
190  else
191    OUTFILE="${FSMNT}/.fetch-${INSFILE}"
192  fi
193
194  # Do the fetch of the archive now
195  fetch_file "${FTPPATH}/${INSFILE}" "${OUTFILE}" "1"
196
197  # Check to see if there is a .count file for this install
198  fetch_file "${FTPPATH}/${INSFILE}.count" "${OUTFILE}.count" "0"
199
200  # Check to see if there is a .md5 file for this install
201  fetch_file "${FTPPATH}/${INSFILE}.md5" "${OUTFILE}.md5" "0"
202
203  # Done fetching, now reset the INSFILE to our downloaded archived
204  INSFILE="${OUTFILE}" ; export INSFILE
205
206};
207
208# Function which will download freebsd install files
209fetch_split_files()
210{
211  get_ftpHost
212  if [ -z "$VAL" ]
213  then
214    exit_err "ERROR: Install medium was set to ftp, but no ftpHost was provided!" 
215  fi
216  FTPHOST="${VAL}"
217
218  get_ftpDir
219  if [ -z "$VAL" ]
220  then
221    exit_err "ERROR: Install medium was set to ftp, but no ftpDir was provided!" 
222  fi
223  FTPDIR="${VAL}"
224
225  # Check if we have a /usr partition to save the download
226  if [ -d "${FSMNT}/usr" ]
227  then
228    OUTFILE="${FSMNT}/usr/.fetch-${INSFILE}"
229  else
230    OUTFILE="${FSMNT}/.fetch-${INSFILE}"
231  fi
232
233  DIRS="base catpages dict doc games info manpages proflibs kernels src"
234  if [ "${FBSD_ARCH}" = "amd64" ]
235  then
236    DIRS="${DIRS} lib32"
237  fi
238
239  for d in ${DIRS}
240  do
241    mkdir -p "${OUTFILE}/${d}"
242  done
243
244
245  NETRC="${OUTFILE}/.netrc"
246  cat<<EOF>"${NETRC}"
247machine ${FTPHOST}
248login anonymous
249password anonymous
250macdef INSTALL
251bin
252prompt
253EOF
254
255  for d in ${DIRS}
256  do
257    cat<<EOF>>"${NETRC}"
258cd ${FTPDIR}/${d}
259lcd ${OUTFILE}/${d}
260mreget *
261EOF
262  done
263
264  cat<<EOF>>"${NETRC}"
265bye
266
267
268EOF
269
270  # Fetch the files via ftp
271  echo "$ INSTALL" | ftp -N "${NETRC}" "${FTPHOST}"
272
273  # Done fetching, now reset the INSFILE to our downloaded archived
274  INSFILE="${OUTFILE}" ; export INSFILE
275}
276
277# Function which does the rsync download from the server specifed in cfg
278start_rsync_copy()
279{
280  # Load our rsync config values
281  get_value_from_cfg rsyncPath
282  if [ -z "${VAL}" ]; then
283    exit_err "ERROR: rsyncPath is unset! Please check your config and try again."
284  fi
285  RSYNCPATH="${VAL}" ; export RSYNCPATH
286
287  get_value_from_cfg rsyncHost
288  if [  -z "${VAL}" ]; then
289    exit_err "ERROR: rsyncHost is unset! Please check your config and try again."
290  fi
291  RSYNCHOST="${VAL}" ; export RSYNCHOST
292
293  get_value_from_cfg rsyncUser
294  if [ -z "${VAL}" ]; then
295    exit_err "ERROR: rsyncUser is unset! Please check your config and try again."
296  fi
297  RSYNCUSER="${VAL}" ; export RSYNCUSER
298
299  get_value_from_cfg rsyncPort
300  if [ -z "${VAL}" ]; then
301    exit_err "ERROR: rsyncPort is unset! Please check your config and try again."
302  fi
303  RSYNCPORT="${VAL}" ; export RSYNCPORT
304
305  COUNT="1"
306  while
307  z=1
308  do
309    if [ ${COUNT} -gt ${RSYNCTRIES} ]
310    then
311     exit_err "ERROR: Failed rsync command!"
312     break
313    fi
314
315    rsync -avvzHsR \
316    --rsync-path="rsync --fake-super" \
317    -e "ssh -p ${RSYNCPORT}" \
318    ${RSYNCUSER}@${RSYNCHOST}:${RSYNCPATH}/./ ${FSMNT}
319    if [ "$?" != "0" ]
320    then
321      echo "Rsync failed! Tries: ${COUNT}"
322    else
323      break
324    fi
325
326    COUNT="`expr ${COUNT} + 1`"
327  done 
328
329};
330
331
332# Entrance function, which starts the installation process
333init_extraction()
334{
335  # Figure out what file we are using to install from via the config
336  get_value_from_cfg installFile
337
338  if [ ! -z "${VAL}" ]
339  then
340    INSFILE="${VAL}" ; export INSFILE
341  else
342    # If no installFile specified, try our defaults
343    if [ "$INSTALLTYPE" = "FreeBSD" ]
344    then
345      case $PACKAGETYPE in
346        uzip) INSFILE="${FBSD_UZIP_FILE}" ;;
347        tar) INSFILE="${FBSD_TAR_FILE}" ;;
348        split)
349          INSDIR="${FBSD_BRANCH_DIR}"
350
351          # This is to trick opt_mount into not failing
352          INSFILE="${INSDIR}"
353          ;;
354      esac
355    else
356      case $PACKAGETYPE in
357        uzip) INSFILE="${UZIP_FILE}" ;;
358        tar) INSFILE="${TAR_FILE}" ;;
359      esac
360    fi
361    export INSFILE
362  fi
363
364  # Lets start by figuring out what medium we are using
365  case ${INSTALLMEDIUM} in
366    dvd|usb)
367      # Lets start by mounting the disk 
368      opt_mount 
369      if [ ! -z "${INSDIR}" ]
370      then
371        INSDIR="${CDMNT}/${INSDIR}" ; export INSDIR
372	    start_extract_split
373
374      else
375        INSFILE="${CDMNT}/${INSFILE}" ; export INSFILE
376        start_extract_uzip_tar
377      fi
378      ;;
379
380    ftp)
381      if [ "$PACKAGETYPE" = "split" ]
382      then
383        fetch_split_files
384
385        INSDIR="${INSFILE}" ; export INSDIR
386        start_extract_split
387      else
388        fetch_install_file
389        start_extract_uzip_tar 
390      fi
391      ;;
392
393    sftp) ;;
394
395    rsync) start_rsync_copy ;;
396    *) exit_err "ERROR: Unknown install medium" ;;
397  esac
398
399};
400