#!/bin/sh #- # Copyright (c) 2010 iXsystems, Inc. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # $FreeBSD: stable/11/usr.sbin/pc-sysinstall/backend/functions-cleanup.sh 240165 2012-09-06 14:59:53Z jpaetzel $ # Functions which perform the final cleanup after an install # Finishes up with ZFS setup before unmounting proc zfs_cleanup_unmount { # Loop through our FS and see if we have any ZFS partitions to cleanup for PART in [$[ls $(PARTDIR)]] { setglobal PARTDEV = $[echo $PART | sed 's|-|/|g] setglobal PARTFS = $[cat $(PARTDIR)/$(PART) | cut -d '#' -f 1] setglobal PARTMNT = $[cat $(PARTDIR)/$(PART) | cut -d '#' -f 2] setglobal ZPOOLNAME = $[get_zpool_name $(PARTDEV)] if test $PARTFS = "ZFS" { # Check if we have multiple zfs mounts specified for ZMNT in [$[echo $(PARTMNT) | sed 's|,| |g]] { if test $(ZMNT) = "/" { # Make sure we haven't already added the zfs boot line when # Creating a dedicated "/boot" partition cat $(FSMNT)/boot/loader.conf !2 >/dev/null | grep -q "vfs.root.mountfrom=" !2 >/dev/null if test $Status -ne 0 { echo "vfs.root.mountfrom=\"zfs:$(ZPOOLNAME)/ROOT/default\"" >> $(FSMNT)/boot/loader.conf } export FOUNDZFSROOT="$(ZPOOLNAME)" } } setglobal FOUNDZFS = '"1'" } } if test -n $(FOUNDZFS) { # Check if we need to add our ZFS flags to rc.conf, src.conf and loader.conf cat $(FSMNT)/boot/loader.conf !2 >/dev/null | grep -q 'zfs_load="YES"' !2 >/dev/null if test $Status -ne 0 { echo 'zfs_load="YES"' >>$(FSMNT)/boot/loader.conf } cat $(FSMNT)/etc/rc.conf !2 >/dev/null | grep -q 'zfs_enable="YES"' !2 >/dev/null if test $Status -ne 0 { echo 'zfs_enable="YES"' >>$(FSMNT)/etc/rc.conf } sleep 2 # Copy over any ZFS cache data cp /boot/zfs/* $(FSMNT)/boot/zfs/ # Copy the hostid so that our zfs cache works cp /etc/hostid $(FSMNT)/etc/hostid } # Loop through our FS and see if we have any ZFS partitions to cleanup for PART in [$[ls $(PARTDIR)]] { setglobal PARTDEV = $[echo $PART | sed 's|-|/|g] setglobal PARTFS = $[cat $(PARTDIR)/$(PART) | cut -d '#' -f 1] setglobal PARTMNT = $[cat $(PARTDIR)/$(PART) | cut -d '#' -f 2] setglobal PARTENC = $[cat $(PARTDIR)/$(PART) | cut -d '#' -f 3] setglobal ZPOOLNAME = $[get_zpool_name $(PARTDEV)] if test $PARTFS = "ZFS" { # Create a list of zpool names we can export echo $ZPOOLEXPORTS | grep -q "$ZPOOLNAME " if test $Status -ne 0 { export ZPOOLEXPORTS="$ZPOOLNAME $ZPOOLEXPORTS" } # Check if we have multiple zfs mounts specified for ZMNT in [$[echo $(PARTMNT) | sed 's|,| |g]] { setglobal ZMNT = $[echo $ZMNT | cut -d '(' -f 1] setglobal PARTMNTREV = ""$(ZMNT) $(PARTMNTREV)"" } for ZMNT in [$(PARTMNTREV)] { if test $(ZMNT) = "/" { continue ; } # Some ZFS like /swap aren't mounted, and dont need unmounting mount | grep -q "$(FSMNT)$(ZMNT)" if test $Status -eq 0 { rc_halt "zfs unmount $(ZPOOLNAME)$(ZMNT)" rc_halt "zfs set mountpoint=$(ZMNT) $(ZPOOLNAME)$(ZMNT)" } sleep 2 } } } }; # Function which performs the specific setup for using a /boot partition proc setup_dedicated_boot_part { setglobal ROOTFS = $(1) setglobal ROOTFSTYPE = $(2) setglobal BOOTFS = $(3) setglobal BOOTMNT = $(4) # Set the root mount in loader.conf echo "vfs.root.mountfrom=\"$(ROOTFSTYPE):$(ROOTFS)\"" >> $(FSMNT)/boot/loader.conf rc_halt "mkdir -p $(FSMNT)/$(BOOTMNT)/boot" rc_halt "mv $(FSMNT)/boot/* $(FSMNT)$(BOOTMNT)/boot/" rc_halt "mv $(FSMNT)$(BOOTMNT)/boot $(FSMNT)/boot/" rc_halt "umount $(BOOTFS)" rc_halt "mount $(BOOTFS) $(FSMNT)$(BOOTMNT)" rc_halt "rmdir $(FSMNT)/boot" # Strip the '/' from BOOTMNT before making symlink setglobal BOOTMNTNS = $[echo $(BOOTMNT) | sed 's|/||g] rc_halt "chroot $(FSMNT) ln -s $(BOOTMNTNS)/boot /boot" }; # Function which creates the /etc/fstab for the installed system proc setup_fstab { setglobal FSTAB = ""$(FSMNT)/etc/fstab"" rm $(FSTAB) >/dev/null !2 >/dev/null # Create the header echo "# Device Mountpoint FStype Options Dump Pass" >> $(FSTAB) # Loop through the partitions, and start creating /etc/fstab for PART in [$[ls $(PARTDIR)]] { setglobal PARTDEV = $[echo $PART | sed 's|-|/|g] setglobal PARTFS = $[cat $(PARTDIR)/$(PART) | cut -d '#' -f 1] setglobal PARTMNT = $[cat $(PARTDIR)/$(PART) | cut -d '#' -f 2] setglobal PARTENC = $[cat $(PARTDIR)/$(PART) | cut -d '#' -f 3] setglobal PARTLABEL = $[cat $(PARTDIR)/$(PART) | cut -d '#' -f 4] # Unset EXT setglobal EXT = ''"" # Set mount options for file-systems match $PARTFS { with UFS+J setglobal MNTOPTS = '"rw,noatime,async'" with SWAP setglobal MNTOPTS = '"sw'" with * setglobal MNTOPTS = '"rw,noatime'" } # Figure out if we are using a glabel, or the raw name for this entry if test -n $(PARTLABEL) { setglobal DEVICE = ""label/$(PARTLABEL)"" } else { # Check if using encryption if test $(PARTENC) = "ON" { setglobal EXT = '".eli'" } if test $(PARTFS) = "UFS+J" { setglobal EXT = ""$(EXT).journal"" } setglobal DEVICE = ""$(PARTDEV)$(EXT)"" } # Set our ROOTFSTYPE for loader.conf if necessary check_for_mount $(PARTMNT) "/" if test $Status -eq 0 { if test $(PARTFS) = "ZFS" { setglobal ROOTFSTYPE = '"zfs'" setglobal ZPOOLNAME = $[get_zpool_name $(PARTDEV)] setglobal ROOTFS = ""$(ZPOOLNAME)/ROOT/default"" } else { setglobal ROOTFS = $(DEVICE) setglobal ROOTFSTYPE = '"ufs'" } } # Only create non-zfs partitions if test $(PARTFS) != "ZFS" { # Make sure geom_journal is loaded if test $(PARTFS) = "UFS+J" { setup_gjournal } # Save the BOOTFS for call at the end if test $(PARTMNT) = "/boot" { setglobal BOOTFS = ""$(PARTDEV)$(EXT)"" setglobal BOOTMNT = $(BOOT_PART_MOUNT) setglobal PARTMNT = $(BOOTMNT) } # Echo out the fstab entry now if test $(PARTFS) = "SWAP" { echo "/dev/$(DEVICE) none swap $(MNTOPTS) 0 0" >> $(FSTAB) } else { echo "/dev/$(DEVICE) $(PARTMNT) ufs $(MNTOPTS) 1 1" >> $(FSTAB) } } # End of ZFS Check } # Setup some specific PC-BSD fstab options if test $INSTALLTYPE != "FreeBSD" { echo "procfs /proc procfs rw 0 0" >> $(FSTAB) echo "linprocfs /compat/linux/proc linprocfs rw 0 0" >> $(FSTAB) } # If we have a dedicated /boot, run the post-install setup of it now if test ! -z $(BOOTMNT) { setup_dedicated_boot_part $(ROOTFS) $(ROOTFSTYPE) $(BOOTFS) $(BOOTMNT) } }; # Setup our disk mirroring with gmirror proc setup_gmirror { cat $(FSMNT)/boot/loader.conf !2 >/dev/null | grep -q 'geom_mirror_load="YES"' !2 >/dev/null if test $Status -ne 0 { echo 'geom_mirror_load="YES"' >>$(FSMNT)/boot/loader.conf } }; # Function which saves geli keys and sets up loading of them at boot proc setup_geli_loading { # Make our keys dir mkdir -p $(FSMNT)/boot/keys >/dev/null !2 >/dev/null cd $(GELIKEYDIR) for KEYFILE in [$[ls]] { # Figure out the partition name based on keyfile name removing .key setglobal PART = $[echo $(KEYFILE) | cut -d '.' -f 1] setglobal PARTDEV = $[echo $(PART) | sed 's|-|/|g] setglobal PARTNAME = $[echo $(PART) | sed 's|-dev-||g] rc_halt "geli configure -b $(PARTDEV)" # If no passphrase, setup key files if test ! -e "$(PARTDIR)-enc/$(PART)-encpass" { echo "geli_$(PARTNAME)_keyfile0_load=\"YES\"" >> $(FSMNT)/boot/loader.conf echo "geli_$(PARTNAME)_keyfile0_type=\"$(PARTNAME):geli_keyfile0\"" >> $(FSMNT)/boot/loader.conf echo "geli_$(PARTNAME)_keyfile0_name=\"/boot/keys/$(PARTNAME).key\"" >> $(FSMNT)/boot/loader.conf # Copy the key to the disk rc_halt "cp $(GELIKEYDIR)/$(KEYFILE) $(FSMNT)/boot/keys/$(PARTNAME).key" } } # Make sure we have geom_eli set to load at boot cat $(FSMNT)/boot/loader.conf !2 >/dev/null | grep -q 'geom_eli_load="YES"' !2 >/dev/null if test $Status -ne 0 { echo 'geom_eli_load="YES"' >>$(FSMNT)/boot/loader.conf } }; # Function to generate a random hostname if none was specified proc gen_hostname { setglobal RAND = $[jot -r 1 1 9000] if test $INSTALLTYPE = "FreeBSD" { setglobal VAL = ""freebsd-$(RAND)"" } else { setglobal VAL = ""pcbsd-$(RAND)"" } export VAL }; # Function which sets up the hostname for the system proc setup_hostname { get_value_from_cfg hostname setglobal HOSTNAME = $(VAL) # If we don't have a hostname, make one up if test -z $(HOSTNAME) { gen_hostname setglobal HOSTNAME = $(VAL) } # Clean up any saved hostname cat $(FSMNT)/etc/rc.conf | grep -v "hostname=" >$(FSMNT)/etc/rc.conf.new mv $(FSMNT)/etc/rc.conf.new $(FSMNT)/etc/rc.conf # Set the hostname now echo_log "Setting hostname: $(HOSTNAME)" echo "hostname=\"$(HOSTNAME)\"" >> $(FSMNT)/etc/rc.conf sed -i -e "s|my.domain|$(HOSTNAME) $(HOSTNAME)|g" $(FSMNT)/etc/hosts }; # Check and make sure geom_journal is enabled on the system proc setup_gjournal { # Make sure we have geom_journal set to load at boot cat $(FSMNT)/boot/loader.conf !2 >/dev/null | grep -q 'geom_journal_load="YES"' !2 >/dev/null if test $Status -ne 0 { echo 'geom_journal_load="YES"' >>$(FSMNT)/boot/loader.conf } }; # Function which sets the root password from the install config proc set_root_pw { # Get the plaintext string get_value_from_cfg_with_spaces rootPass local PW="$(VAL)" # Get the encrypted string get_value_from_cfg_with_spaces rootEncPass local ENCPW="$(VAL)" # If we don't have a root pass, return if test -z $(PW) -a -z $(ENCPW) { return 0 ; } echo_log "Setting root password" # Check if setting plaintext password if test -n $(PW) { echo $(PW) > $(FSMNT)/.rootpw run_chroot_cmd "cat /.rootpw | pw usermod root -h 0" rc_halt "rm $(FSMNT)/.rootpw" } # Check if setting encrypted password if test -n $(ENCPW) { echo $(ENCPW) > $(FSMNT)/.rootpw run_chroot_cmd "cat /.rootpw | pw usermod root -H 0" rc_halt "rm $(FSMNT)/.rootpw" } }; proc run_final_cleanup { # Check if we need to run any gmirror setup ls $(MIRRORCFGDIR)/* >/dev/null !2 >/dev/null if test $Status -eq 0 { # Lets setup gmirror now setup_gmirror } # Check if we need to save any geli keys ls $(GELIKEYDIR)/* >/dev/null !2 >/dev/null if test $Status -eq 0 { # Lets setup geli loading setup_geli_loading } # Set a hostname on the install system setup_hostname # Set the root_pw if it is specified set_root_pw # Generate the fstab for the installed system setup_fstab };