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$
27209513Simp
28209513Simp# Functions which perform the final cleanup after an install
29209513Simp
30209513Simp# Finishes up with ZFS setup before unmounting
31209513Simpzfs_cleanup_unmount()
32209513Simp{
33209513Simp  # Loop through our FS and see if we have any ZFS partitions to cleanup
34209513Simp  for PART in `ls ${PARTDIR}`
35209513Simp  do
36220909Sjpaetzel    PARTDEV=`echo $PART | sed 's|-|/|g'`
37232899Sjpaetzel    PARTFS="`cat ${PARTDIR}/${PART} | cut -d '#' -f 1`"
38232899Sjpaetzel    PARTMNT="`cat ${PARTDIR}/${PART} | cut -d '#' -f 2`"
39220909Sjpaetzel    ZPOOLNAME=$(get_zpool_name "${PARTDEV}")
40209513Simp
41209513Simp    if [ "$PARTFS" = "ZFS" ]
42209513Simp    then
43209513Simp      # Check if we have multiple zfs mounts specified
44209513Simp      for ZMNT in `echo ${PARTMNT} | sed 's|,| |g'`
45209513Simp      do
46209513Simp        if [ "${ZMNT}" = "/" ]
47209513Simp        then
48209513Simp          # Make sure we haven't already added the zfs boot line when
49209513Simp          # Creating a dedicated "/boot" partition
50220059Sjpaetzel          cat ${FSMNT}/boot/loader.conf 2>/dev/null | grep -q "vfs.root.mountfrom=" 2>/dev/null
51220059Sjpaetzel          if [ $? -ne 0 ] ; then
52240165Sjpaetzel            echo "vfs.root.mountfrom=\"zfs:${ZPOOLNAME}/ROOT/default\"" >> ${FSMNT}/boot/loader.conf
53209513Simp          fi
54220059Sjpaetzel          export FOUNDZFSROOT="${ZPOOLNAME}"
55209513Simp        fi
56209513Simp      done
57209513Simp      FOUNDZFS="1"
58209513Simp    fi
59209513Simp  done
60209513Simp
61220059Sjpaetzel  if [ -n "${FOUNDZFS}" ]
62209513Simp  then
63209513Simp    # Check if we need to add our ZFS flags to rc.conf, src.conf and loader.conf
64220059Sjpaetzel    cat ${FSMNT}/boot/loader.conf 2>/dev/null | grep -q 'zfs_load="YES"' 2>/dev/null
65220059Sjpaetzel    if [ $? -ne 0 ]
66209513Simp    then
67209513Simp      echo 'zfs_load="YES"' >>${FSMNT}/boot/loader.conf
68209513Simp    fi
69220059Sjpaetzel    cat ${FSMNT}/etc/rc.conf 2>/dev/null | grep -q 'zfs_enable="YES"' 2>/dev/null
70220059Sjpaetzel    if [ $? -ne 0 ]
71209513Simp    then
72209513Simp      echo 'zfs_enable="YES"' >>${FSMNT}/etc/rc.conf
73209513Simp    fi
74209513Simp
75209513Simp    sleep 2
76209513Simp    # Copy over any ZFS cache data
77209513Simp    cp /boot/zfs/* ${FSMNT}/boot/zfs/
78209513Simp
79209513Simp    # Copy the hostid so that our zfs cache works
80209513Simp    cp /etc/hostid ${FSMNT}/etc/hostid
81209513Simp  fi
82209513Simp
83209513Simp  # Loop through our FS and see if we have any ZFS partitions to cleanup
84209513Simp  for PART in `ls ${PARTDIR}`
85209513Simp  do
86220909Sjpaetzel    PARTDEV=`echo $PART | sed 's|-|/|g'`
87232899Sjpaetzel    PARTFS="`cat ${PARTDIR}/${PART} | cut -d '#' -f 1`"
88232899Sjpaetzel    PARTMNT="`cat ${PARTDIR}/${PART} | cut -d '#' -f 2`"
89232899Sjpaetzel    PARTENC="`cat ${PARTDIR}/${PART} | cut -d '#' -f 3`"
90220909Sjpaetzel    ZPOOLNAME=$(get_zpool_name "${PARTDEV}")
91209513Simp
92209513Simp    if [ "$PARTFS" = "ZFS" ]
93209513Simp    then
94220909Sjpaetzel
95220909Sjpaetzel      # Create a list of zpool names we can export
96220909Sjpaetzel      echo $ZPOOLEXPORTS | grep -q "$ZPOOLNAME "
97220909Sjpaetzel      if [ $? -ne 0 ] ; then
98220909Sjpaetzel        export ZPOOLEXPORTS="$ZPOOLNAME $ZPOOLEXPORTS"
99220909Sjpaetzel      fi
100220909Sjpaetzel
101209513Simp      # Check if we have multiple zfs mounts specified
102209513Simp      for ZMNT in `echo ${PARTMNT} | sed 's|,| |g'`
103209513Simp      do
104232899Sjpaetzel	ZMNT="`echo $ZMNT | cut -d '(' -f 1`"
105209513Simp        PARTMNTREV="${ZMNT} ${PARTMNTREV}"
106209513Simp      done
107209513Simp
108209513Simp      for ZMNT in ${PARTMNTREV}
109209513Simp      do
110232899Sjpaetzel        if [ "${ZMNT}" = "/" ] ; then continue ; fi
111232899Sjpaetzel        # Some ZFS like /swap aren't mounted, and dont need unmounting
112232899Sjpaetzel        mount | grep -q "${FSMNT}${ZMNT}"
113232899Sjpaetzel	if [ $? -eq 0 ] ; then
114232899Sjpaetzel          rc_halt "zfs unmount ${ZPOOLNAME}${ZMNT}"
115209513Simp          rc_halt "zfs set mountpoint=${ZMNT} ${ZPOOLNAME}${ZMNT}"
116209513Simp        fi
117232899Sjpaetzel        sleep 2
118209513Simp      done
119209513Simp    fi
120209513Simp  done
121209513Simp
122209513Simp};
123209513Simp
124209513Simp# Function which performs the specific setup for using a /boot partition
125209513Simpsetup_dedicated_boot_part()
126209513Simp{
127209513Simp  ROOTFS="${1}"
128209513Simp  ROOTFSTYPE="${2}"
129209513Simp  BOOTFS="${3}"
130209513Simp  BOOTMNT="${4}"
131209513Simp
132209513Simp  # Set the root mount in loader.conf
133209513Simp  echo "vfs.root.mountfrom=\"${ROOTFSTYPE}:${ROOTFS}\"" >> ${FSMNT}/boot/loader.conf
134209513Simp  rc_halt "mkdir -p ${FSMNT}/${BOOTMNT}/boot"
135209513Simp  rc_halt "mv ${FSMNT}/boot/* ${FSMNT}${BOOTMNT}/boot/"
136209513Simp  rc_halt "mv ${FSMNT}${BOOTMNT}/boot ${FSMNT}/boot/"
137220909Sjpaetzel  rc_halt "umount ${BOOTFS}"
138220909Sjpaetzel  rc_halt "mount ${BOOTFS} ${FSMNT}${BOOTMNT}"
139209513Simp  rc_halt "rmdir ${FSMNT}/boot"
140209513Simp
141209513Simp  # Strip the '/' from BOOTMNT before making symlink
142209513Simp  BOOTMNTNS="`echo ${BOOTMNT} | sed 's|/||g'`"
143209513Simp  rc_halt "chroot ${FSMNT} ln -s ${BOOTMNTNS}/boot /boot"
144209513Simp  
145209513Simp};
146209513Simp
147209513Simp# Function which creates the /etc/fstab for the installed system
148209513Simpsetup_fstab()
149209513Simp{
150209513Simp  FSTAB="${FSMNT}/etc/fstab"
151209513Simp  rm ${FSTAB} >/dev/null 2>/dev/null
152209513Simp
153209513Simp  # Create the header
154209513Simp  echo "# Device		Mountpoint		FStype		Options	Dump Pass" >> ${FSTAB}
155209513Simp
156209513Simp  # Loop through the partitions, and start creating /etc/fstab
157209513Simp  for PART in `ls ${PARTDIR}`
158209513Simp  do
159220909Sjpaetzel    PARTDEV=`echo $PART | sed 's|-|/|g'`
160232899Sjpaetzel    PARTFS="`cat ${PARTDIR}/${PART} | cut -d '#' -f 1`"
161232899Sjpaetzel    PARTMNT="`cat ${PARTDIR}/${PART} | cut -d '#' -f 2`"
162232899Sjpaetzel    PARTENC="`cat ${PARTDIR}/${PART} | cut -d '#' -f 3`"
163232899Sjpaetzel    PARTLABEL="`cat ${PARTDIR}/${PART} | cut -d '#' -f 4`"
164209513Simp
165209513Simp    # Unset EXT
166209513Simp    EXT=""
167209513Simp
168210700Simp    # Set mount options for file-systems
169210700Simp    case $PARTFS in
170210700Simp      UFS+J) MNTOPTS="rw,noatime,async" ;;
171211730Simp      SWAP) MNTOPTS="sw" ;;
172211730Simp      *) MNTOPTS="rw,noatime" ;;
173210700Simp    esac
174210700Simp
175210700Simp
176209513Simp    # Figure out if we are using a glabel, or the raw name for this entry
177220059Sjpaetzel    if [ -n "${PARTLABEL}" ]
178209513Simp    then
179209513Simp      DEVICE="label/${PARTLABEL}"
180209513Simp    else
181209513Simp      # Check if using encryption 
182209513Simp      if [ "${PARTENC}" = "ON" ] ; then
183209513Simp        EXT=".eli"
184209513Simp      fi
185209513Simp
186209513Simp      if [ "${PARTFS}" = "UFS+J" ] ; then
187209513Simp        EXT="${EXT}.journal"
188209513Simp      fi
189220909Sjpaetzel      DEVICE="${PARTDEV}${EXT}"
190209513Simp    fi
191209513Simp
192209513Simp
193209513Simp    # Set our ROOTFSTYPE for loader.conf if necessary
194209513Simp    check_for_mount "${PARTMNT}" "/"
195220059Sjpaetzel    if [ $? -eq 0 ] ; then
196209513Simp      if [ "${PARTFS}" = "ZFS" ] ; then
197209513Simp        ROOTFSTYPE="zfs"
198240165Sjpaetzel        ZPOOLNAME=$(get_zpool_name "${PARTDEV}")
199240165Sjpaetzel        ROOTFS="${ZPOOLNAME}/ROOT/default"
200209513Simp      else
201209513Simp        ROOTFS="${DEVICE}"
202209513Simp        ROOTFSTYPE="ufs"
203209513Simp      fi
204209513Simp    fi
205209513Simp
206209513Simp    # Only create non-zfs partitions
207209513Simp    if [ "${PARTFS}" != "ZFS" ]
208209513Simp    then
209209513Simp
210209513Simp      # Make sure geom_journal is loaded
211209513Simp      if [ "${PARTFS}" = "UFS+J" ] ; then
212209513Simp        setup_gjournal
213209513Simp      fi
214209513Simp
215209513Simp      # Save the BOOTFS for call at the end
216209513Simp      if [ "${PARTMNT}" = "/boot" ] ; then
217220909Sjpaetzel        BOOTFS="${PARTDEV}${EXT}"
218209513Simp        BOOTMNT="${BOOT_PART_MOUNT}"
219209513Simp        PARTMNT="${BOOTMNT}"
220209513Simp      fi
221209513Simp
222209513Simp      # Echo out the fstab entry now
223209513Simp      if [ "${PARTFS}" = "SWAP" ]
224209513Simp      then
225222365Skevlo        echo "/dev/${DEVICE}	none		swap	${MNTOPTS}	0	0" >> ${FSTAB}
226209513Simp      else
227222365Skevlo        echo "/dev/${DEVICE}	${PARTMNT}		ufs	${MNTOPTS}	1	1" >> ${FSTAB}
228209513Simp      fi
229209513Simp
230209513Simp    fi # End of ZFS Check
231209513Simp  done
232209513Simp
233209513Simp  # Setup some specific PC-BSD fstab options
234209513Simp  if [ "$INSTALLTYPE" != "FreeBSD" ]
235209513Simp  then
236209513Simp    echo "procfs			/proc			procfs		rw		0	0" >> ${FSTAB}
237209513Simp    echo "linprocfs		/compat/linux/proc	linprocfs	rw		0	0" >> ${FSTAB}
238209513Simp  fi
239209513Simp
240209513Simp  # If we have a dedicated /boot, run the post-install setup of it now
241209513Simp  if [ ! -z "${BOOTMNT}" ] ; then 
242209513Simp    setup_dedicated_boot_part "${ROOTFS}" "${ROOTFSTYPE}" "${BOOTFS}" "${BOOTMNT}"
243209513Simp  fi
244209513Simp
245209513Simp};
246209513Simp
247209513Simp# Setup our disk mirroring with gmirror
248209513Simpsetup_gmirror()
249209513Simp{
250220059Sjpaetzel  cat ${FSMNT}/boot/loader.conf 2>/dev/null | grep -q 'geom_mirror_load="YES"' 2>/dev/null
251220059Sjpaetzel  if [ $? -ne 0 ]
252209513Simp  then
253209513Simp    echo 'geom_mirror_load="YES"' >>${FSMNT}/boot/loader.conf
254209513Simp  fi
255209513Simp
256209513Simp};
257209513Simp
258209513Simp# Function which saves geli keys and sets up loading of them at boot
259209513Simpsetup_geli_loading()
260209513Simp{
261209513Simp
262209513Simp  # Make our keys dir
263209513Simp  mkdir -p ${FSMNT}/boot/keys >/dev/null 2>/dev/null
264209513Simp
265209513Simp  cd ${GELIKEYDIR}
266220909Sjpaetzel  for KEYFILE in `ls`
267209513Simp  do
268209513Simp     # Figure out the partition name based on keyfile name removing .key
269209513Simp     PART="`echo ${KEYFILE} | cut -d '.' -f 1`"
270220909Sjpaetzel     PARTDEV="`echo ${PART} | sed 's|-|/|g'`"
271220909Sjpaetzel     PARTNAME="`echo ${PART} | sed 's|-dev-||g'`"
272209513Simp
273220909Sjpaetzel     rc_halt "geli configure -b ${PARTDEV}"
274209513Simp
275220909Sjpaetzel     # If no passphrase, setup key files
276220909Sjpaetzel     if [ ! -e "${PARTDIR}-enc/${PART}-encpass" ] ; then
277220909Sjpaetzel       echo "geli_${PARTNAME}_keyfile0_load=\"YES\"" >> ${FSMNT}/boot/loader.conf 
278220909Sjpaetzel       echo "geli_${PARTNAME}_keyfile0_type=\"${PARTNAME}:geli_keyfile0\"" >> ${FSMNT}/boot/loader.conf 
279220909Sjpaetzel       echo "geli_${PARTNAME}_keyfile0_name=\"/boot/keys/${PARTNAME}.key\"" >> ${FSMNT}/boot/loader.conf 
280220909Sjpaetzel
281220909Sjpaetzel       # Copy the key to the disk
282220909Sjpaetzel       rc_halt "cp ${GELIKEYDIR}/${KEYFILE} ${FSMNT}/boot/keys/${PARTNAME}.key"
283209513Simp     fi
284209513Simp
285209513Simp  done
286209513Simp
287209513Simp  # Make sure we have geom_eli set to load at boot
288220059Sjpaetzel  cat ${FSMNT}/boot/loader.conf 2>/dev/null | grep -q 'geom_eli_load="YES"' 2>/dev/null
289220059Sjpaetzel  if [ $? -ne 0 ]
290209513Simp  then
291209513Simp    echo 'geom_eli_load="YES"' >>${FSMNT}/boot/loader.conf
292209513Simp  fi
293209513Simp
294209513Simp};
295209513Simp
296209513Simp
297209513Simp# Function to generate a random hostname if none was specified
298209513Simpgen_hostname()
299209513Simp{
300209513Simp  RAND="`jot -r 1 1 9000`"
301209513Simp
302209513Simp  if [ "$INSTALLTYPE" = "FreeBSD" ]
303209513Simp  then
304209513Simp    VAL="freebsd-${RAND}" 
305209513Simp  else
306209513Simp    VAL="pcbsd-${RAND}" 
307209513Simp  fi
308209513Simp
309209513Simp  export VAL
310209513Simp
311209513Simp};
312209513Simp
313209513Simp# Function which sets up the hostname for the system
314209513Simpsetup_hostname()
315209513Simp{
316209513Simp
317209513Simp  get_value_from_cfg hostname
318209513Simp  HOSTNAME="${VAL}"
319209513Simp
320209513Simp  # If we don't have a hostname, make one up
321209513Simp  if [ -z "${HOSTNAME}" ]
322209513Simp  then
323209513Simp    gen_hostname
324209513Simp    HOSTNAME="${VAL}"
325209513Simp  fi
326209513Simp
327209513Simp  # Clean up any saved hostname
328209513Simp  cat ${FSMNT}/etc/rc.conf | grep -v "hostname=" >${FSMNT}/etc/rc.conf.new
329209513Simp  mv ${FSMNT}/etc/rc.conf.new ${FSMNT}/etc/rc.conf
330209513Simp
331209513Simp  # Set the hostname now
332209513Simp  echo_log "Setting hostname: ${HOSTNAME}"
333209513Simp  echo "hostname=\"${HOSTNAME}\"" >> ${FSMNT}/etc/rc.conf
334209513Simp  sed -i -e "s|my.domain|${HOSTNAME} ${HOSTNAME}|g" ${FSMNT}/etc/hosts
335209513Simp
336209513Simp};
337209513Simp
338209513Simp
339209513Simp# Check and make sure geom_journal is enabled on the system
340209513Simpsetup_gjournal()
341209513Simp{
342209513Simp
343209513Simp  # Make sure we have geom_journal set to load at boot
344220059Sjpaetzel  cat ${FSMNT}/boot/loader.conf 2>/dev/null | grep -q 'geom_journal_load="YES"' 2>/dev/null
345220059Sjpaetzel  if [ $? -ne 0 ]
346209513Simp  then
347209513Simp    echo 'geom_journal_load="YES"' >>${FSMNT}/boot/loader.conf
348209513Simp  fi
349209513Simp
350209513Simp};
351209513Simp
352209513Simp# Function which sets the root password from the install config
353209513Simpset_root_pw()
354209513Simp{
355217234Sjpaetzel  # Get the plaintext string
356209513Simp  get_value_from_cfg_with_spaces rootPass
357217234Sjpaetzel  local PW="${VAL}"
358209513Simp
359217234Sjpaetzel  # Get the encrypted string
360217234Sjpaetzel  get_value_from_cfg_with_spaces rootEncPass
361217234Sjpaetzel  local ENCPW="${VAL}"
362217234Sjpaetzel
363209513Simp  # If we don't have a root pass, return
364217234Sjpaetzel  if [ -z "${PW}" -a -z "${ENCPW}" ] ; then return 0 ; fi
365209513Simp
366209513Simp  echo_log "Setting root password"
367209513Simp
368217234Sjpaetzel  # Check if setting plaintext password
369220059Sjpaetzel  if [ -n "${PW}" ] ; then
370217234Sjpaetzel    echo "${PW}" > ${FSMNT}/.rootpw
371217234Sjpaetzel    run_chroot_cmd "cat /.rootpw | pw usermod root -h 0"
372217234Sjpaetzel    rc_halt "rm ${FSMNT}/.rootpw"
373217234Sjpaetzel  fi
374217234Sjpaetzel
375217234Sjpaetzel  # Check if setting encrypted password
376220059Sjpaetzel  if [ -n "${ENCPW}" ] ; then
377217234Sjpaetzel    echo "${ENCPW}" > ${FSMNT}/.rootpw
378217234Sjpaetzel    run_chroot_cmd "cat /.rootpw | pw usermod root -H 0"
379217234Sjpaetzel    rc_halt "rm ${FSMNT}/.rootpw"
380217234Sjpaetzel  fi
381217234Sjpaetzel
382209513Simp};
383209513Simp
384209513Simp
385209513Simprun_final_cleanup()
386209513Simp{
387211730Simp  # Check if we need to run any gmirror setup
388211730Simp  ls ${MIRRORCFGDIR}/* >/dev/null 2>/dev/null
389220059Sjpaetzel  if [ $? -eq 0 ]
390211730Simp  then
391211730Simp    # Lets setup gmirror now
392211730Simp    setup_gmirror
393211730Simp  fi
394209513Simp
395211730Simp  # Check if we need to save any geli keys
396211730Simp  ls ${GELIKEYDIR}/* >/dev/null 2>/dev/null
397220059Sjpaetzel  if [ $? -eq 0 ]
398211730Simp  then
399211730Simp    # Lets setup geli loading
400211730Simp    setup_geli_loading
401211730Simp  fi
402209513Simp
403211730Simp  # Set a hostname on the install system
404211730Simp  setup_hostname
405209513Simp
406211730Simp  # Set the root_pw if it is specified
407211730Simp  set_root_pw
408209513Simp
409211730Simp  # Generate the fstab for the installed system
410211730Simp  setup_fstab
411209513Simp};
412