summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAn-Cheng Huang <ancheng@vyatta.com>2009-10-30 18:42:30 -0700
committerAn-Cheng Huang <ancheng@vyatta.com>2009-10-30 18:42:30 -0700
commit1f5174a65f21d1280827d7fb911232f4bfc56eb7 (patch)
tree389ce51f25870f0fb9b273951853ce79abd649d7
parentc758197af1f11727cb01188b14d0a4801448cfcd (diff)
downloadvyatta-cfg-system-1f5174a65f21d1280827d7fb911232f4bfc56eb7.tar.gz
vyatta-cfg-system-1f5174a65f21d1280827d7fb911232f4bfc56eb7.zip
add unified install-image
-rw-r--r--Makefile.am7
-rwxr-xr-xscripts/install/install-functions329
-rwxr-xr-xscripts/install/install-get-partition808
-rwxr-xr-xscripts/install/install-image170
-rwxr-xr-xscripts/install/install-image-existing133
-rwxr-xr-xscripts/install/install-image-new76
-rwxr-xr-xscripts/install/install-postinst-new201
7 files changed, 1723 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am
index 3065b533..29619127 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -20,7 +20,6 @@ bin_SCRIPTS += scripts/vyatta-functions
sbin_SCRIPTS += scripts/init-floppy
sbin_SCRIPTS += scripts/rl-system.init
sbin_SCRIPTS += scripts/install-system
-sbin_SCRIPTS += scripts/install-image
sbin_SCRIPTS += scripts/vyatta-grub-setup
sbin_SCRIPTS += scripts/standalone_root_pw_reset
sbin_SCRIPTS += scripts/vyatta-passwd-sync
@@ -44,6 +43,12 @@ sbin_SCRIPTS += scripts/vyatta-raid-event
sbin_SCRIPTS += scripts/vyatta-update-arp-params
sbin_SCRIPTS += scripts/zone-mgmt/vyatta-zone.pl
sbin_SCRIPTS += scripts/vyatta-banner.pl
+sbin_SCRIPTS += scripts/install/install-get-partition
+sbin_SCRIPTS += scripts/install/install-functions
+sbin_SCRIPTS += scripts/install/install-image-new
+sbin_SCRIPTS += scripts/install/install-image-existing
+sbin_SCRIPTS += scripts/install/install-postinst-new
+sbin_SCRIPTS += scripts/install/install-image
share_perl5_DATA = lib/Vyatta/Login/User.pm
share_perl5_DATA += lib/Vyatta/Login/RadiusServer.pm
diff --git a/scripts/install/install-functions b/scripts/install/install-functions
new file mode 100755
index 00000000..3bdc1fde
--- /dev/null
+++ b/scripts/install/install-functions
@@ -0,0 +1,329 @@
+# this provides environment and functions needed by install scripts.
+# must be sourced by the scripts.
+
+if [ -e /etc/default/vyatta ] ; then
+ . /etc/default/vyatta
+fi
+
+: ${vyatta_prefix:=/opt/vyatta}
+: ${vyatta_exec_prefix:=$vyatta_prefix}
+: ${vyatta_bindir:=${vyatta_exec_prefix}/bin}
+: ${vyatta_sysconfdir:=${vyatta_prefix}/etc}
+
+# trap signals so we can kill runaway progress indicators
+trap 'progress_indicator stop; exit 1' 1
+trap 'progress_indicator stop; exit 1' 2
+
+# mount point for the install root.
+# for union install, this is a r/w union mount.
+# for non-union install, this is the root partition mount.
+INST_ROOT=/mnt/inst_root
+
+# mount point for the writable root, i.e., the root partition.
+# this is only used for union install.
+WRITE_ROOT=/mnt/wroot
+
+# mount point for the readonly squashfs mount.
+# this is only used for union install.
+READ_ROOT=/mnt/squashfs
+
+# mount point for the ISO image.
+# this is only used when installing with an ISO image file
+# (instead of from a live CD boot).
+CD_ROOT=/mnt/cdrom
+
+# mount point for the squashfs image in the ISO image.
+# this is only used when installing with an ISO image file
+# (instead of from a live CD boot).
+CD_SQUASH_ROOT=/mnt/cdsquash
+
+# the vyatta config dir
+VYATTA_CFG_DIR=${vyatta_sysconfdir}/config
+
+# the floppy config dir
+FD_CFG_DIR=/media/floppy/config
+
+# Process ID for progress_indicator
+SPID=$$
+
+progress_indicator () {
+ case "$1" in
+ start)
+ $vyatta_bindir/progress-indicator $SPID &
+ ;;
+ *)
+ if ! rm /tmp/pi.$SPID 2>/dev/null; then
+ sleep 1
+ rm /tmp/pi.$SPID 2>/dev/null
+ fi
+ sleep 1
+ echo -n -e "\b"
+ ;;
+ esac
+}
+
+# echo to log. uses INSTALL_LOG if set.
+lecho ()
+{
+ local log=$INSTALL_LOG
+ if [ -z "$log" ]; then
+ log=/tmp/install-$$.log
+ fi
+ echo -e "$*" >>$log
+}
+
+# echo to both.
+becho ()
+{
+ lecho "$*"
+ echo -e "$*"
+}
+
+# Validates a user response. Returns the response if valid.
+# Returns the default is the user just hits enter.
+# Returns nothing if not valid. Default parameter is $1.
+# Options are in $2. If options are defined return must be a member
+# of the enum.
+get_response () {
+ ldefault=$(echo "$1" | tr [:upper:] [:lower:])
+ loptions=$(echo "$2" | tr [:upper:] [:lower:])
+
+ # get the response from the user
+ read myresponse
+ myresponse=$(echo "$myresponse" | tr [:upper:] [:lower:])
+
+ # Check to see if the user accepts the default
+ if [ -z "$myresponse" ]; then
+ echo -n $ldefault
+ elif [ -n "$loptions" ]; then
+ # make sure response is a valid option
+ for token in $loptions
+ do
+ if [ "$token" == "$myresponse" ]; then
+ echo -n "$myresponse"
+ return 0
+ fi
+ done
+ return 1
+ else
+ echo -n "$myresponse"
+ fi
+
+ return 0
+}
+
+# turn off any mounted swap partitions
+turnoffswap () {
+ if [ -f "/proc/swaps" ]; then
+ myresponse=$(cat /proc/swaps)
+ if [ -n "$myresponse" ]; then
+ lecho "turning off swaps..."
+ swapoff -a
+ fi
+ fi
+}
+
+# Return the size of the drive in MB
+get_drive_size () {
+ ldrive=$1
+
+ # Make sure you can print disk info using parted
+ parted /dev/$ldrive p >/dev/null 2>&1
+
+ # If unable to read disk, it's likely it needs a disklabel
+ if [ "$?" != "0" ]; then
+ lecho "Creating a new disklabel on $ldrive"
+ lecho "parted /dev/$ldrive mklabel msdos"
+ output=$(parted /dev/$ldrive mklabel msdos)
+
+ # Get the drive size from parted
+ lsize=$(parted /dev/$ldrive p | grep "^Disk" | awk '{ print $3 }')
+
+ if [ $(echo $lsize | grep error) ]; then
+ echo "Unable to read disk label. Exiting."
+ exit 1
+ fi
+ fi
+
+ # Get the drive size from parted
+ lsize=$(parted /dev/$ldrive p | grep "^Disk" | awk '{ print $3 }')
+ # Get the reported units (mB, GB, kB)
+ lmodifier=$(echo $lsize | sed 's/[0-9\.]//g')
+ # remove the modifier
+ lsize=$(echo $lsize | sed 's/[a-z,A-Z]//g')
+ # Remove any fractions
+ lsize=$(echo $lsize | cut -f1 -d'.')
+ # Translate our size into mB if not there already
+ if [ $lmodifier = "GB" ]; then
+ lsize=$(($lsize * 1000))
+ elif [ $lmodifier = "kB" ]; then
+ lsize=$(($lsize / 1000))
+ fi
+
+ echo $lsize
+}
+
+# Probe hardrives not shown in /proc/partitions by default
+probe_drives () {
+ # Find drives that may not be in /proc/partitions since not mounted
+ drive=$(ls /sys/block | grep '[hsv]d.')
+
+ # now exclude all drives that are read-only
+ for drive in $drive; do
+ if [ $(cat /sys/block/$drive/ro) -ne 0 ]; then
+ output=$(mount | grep $drive)
+ if [ -z "$output" ]; then
+ output=$(parted /dev/$drive p)
+ fi
+ fi
+ done
+}
+
+# Display text $1 before choice.
+# Sets the variable named by $2.
+# Note that select_drive should be wrapped
+# in the verification loop, not the included get_response.
+select_drive () {
+ local msg=$1
+ local outvar=$2
+ local drv=''
+ # list the drives in /proc/partitions. Remove partitions and empty lines.
+ # the first grep pattern looks for devices named c0d0, hda, and sda.
+ drives=$(cat /proc/partitions | \
+ awk '{ if ($4!="name") { print $4 } }' | \
+ egrep "c[0-9]d[0-9]$|[hsv]d[a-z]$" | \
+ egrep -v "^$")
+
+ # take the first drive as the default
+ drv=$(echo $drives | /usr/bin/awk '{ print $1 }')
+
+ # Add the drive sizes to the display to help the user decide
+ display=''
+ for drive in $drives; do
+ size=$(get_drive_size $drive)
+ display="$display $drive\t$size"MB"\n"
+ done
+
+ while true; do
+ # Display the drives and ask the user which one to install to
+ echo -e "$display"
+ echo
+ echo -n "$1 [$drv]:"
+ response=$(get_response "$drv" "$drives") && break
+ done
+ eval "$outvar=$response"
+
+ echo
+}
+
+# $1: user name
+# $2: encrypted password
+# $3: config file
+set_encrypted_password () {
+ sed -i -e \
+ "/ user $1 {/,/}/s/encrypted-password.*\$/encrypted-password \"$2\"/" $3
+}
+
+# interactively prompt user to change password for the specified account in
+# the specified config file
+# $1: account name
+# $2: config file
+change_password() {
+ local user=$1
+ local config=$2
+ local pwd1="1"
+ local pwd2="2"
+
+ until [ "$pwd1" == "$pwd2" ]; do
+ read -p "Enter $user password:" -r -s pwd1 <>/dev/tty 2>&0
+ echo
+ read -p "Retype $user password:" -r -s pwd2 <>/dev/tty 2>&0
+ echo
+
+ if [ "$pwd1" != "$pwd2" ]; then
+ echo "Passwords do not match"
+ fi
+ done
+
+ # escape any slashes in resulting password
+ local epwd=$(mkpasswd -H md5 "$pwd1" | sed 's:/:\\/:g')
+ set_encrypted_password "$user" "$epwd" "$config"
+}
+
+# returns true if it's a live cd boot
+is_live_cd_boot ()
+{
+ if grep -q ' /live/image [^ ]\+ ro' /proc/mounts; then
+ return 0
+ else
+ return 1
+ fi
+}
+
+# returns true if it's a union-install boot
+is_union_install ()
+{
+ if is_live_cd_boot; then
+ return 1
+ fi
+ if grep -q ' /live/image [^ ]\+ rw' /proc/mounts \
+ && grep -q 'unionfs / unionfs ' /proc/mounts; then
+ return 0
+ else
+ return 1
+ fi
+}
+
+# outputs the version string of the current running version.
+get_cur_version ()
+{
+ local ver_file=/opt/vyatta/etc/version
+ if [ -f "$ver_file" ]; then
+ grep '^Version' $ver_file | awk '{ print $3 }'
+ return
+ fi
+}
+
+# outputs the version string of the new version, i.e., the version that is
+# being installed. this can be from live CD boot or from a ISO image file.
+get_new_version ()
+{
+ ver_path=/opt/vyatta/etc/version
+ ver_file=${CD_SQUASH_ROOT}${ver_path}
+ if [ -f "$ver_file" ]; then
+ # CD_SQUASH_ROOT is set up => we are installing with a specified ISO
+ # image file. use the version string from there.
+ grep '^Version' $ver_file | awk '{ print $3 }'
+ return
+ fi
+
+ ver_file=${ver_path}
+ if is_live_cd_boot && [ -f "$ver_file" ]; then
+ # we are installing from a live CD boot
+ grep '^Version' $ver_file | awk '{ print $3 }'
+ return
+ fi
+
+ # couldn't find it
+}
+
+# try to mount. log any errors and return the appropriate status.
+# $1: arguments for mount
+try_mount ()
+{
+ args="$*"
+ output=$(eval "mount $args 2>&1")
+ status=$?
+ if [ $status == 0 ]; then
+ return 0
+ fi
+ # error
+ cat <<EOF
+Error trying to mount a partition/directory.
+Please see $INSTALL_LOG for details.
+EOF
+ lecho 'Error trying to mount a partition/directory.'
+ lecho "mount $args\n$output"
+ return 1
+}
+
diff --git a/scripts/install/install-get-partition b/scripts/install/install-get-partition
new file mode 100755
index 00000000..30316724
--- /dev/null
+++ b/scripts/install/install-get-partition
@@ -0,0 +1,808 @@
+#!/bin/bash
+
+if [ `whoami` != 'root' ] ; then
+ echo "This script must be run with root privileges."
+ exit 1
+fi
+
+# this script will write the partition type, selected partition, and selected
+# drive into the specified file
+OUTFILE=$1
+
+if [ ! -f "$OUTFILE" ]; then
+ echo "Output file does not exist. Exiting..."
+ exit 1
+fi
+
+# source in the functions
+source /opt/vyatta/sbin/install-functions
+
+# the INSTALL_LOG env var should be exported by the "caller".
+# it will be used to log messages.
+
+# Absolute minimum root partition size in MB. Below this, we won't let
+# you install.
+ROOT_MIN=1000
+# the base install drive e.g. sda
+INSTALL_DRIVE=''
+# the install partition e.g. sda1
+ROOT_PARTITION=''
+# the type of the install partition: "union", "old", or "new"
+ROOT_PARTITION_TYPE=''
+# global holding variable used in the select_partition sub
+PARTITION=''
+# default file system type
+ROOT_FSTYPE='ext3'
+
+warn_of_dire_consequences () {
+ # Give the user a requisite warning that we are about to nuke their drive
+ response=''
+ while [ -z $response ]; do
+ echo "This will destroy all data on /dev/$INSTALL_DRIVE."
+ echo -n "Continue? (Yes/No) [No]: "
+ response=$(get_response "No" "Yes No Y N")
+
+ if [ "$response" == "no" ] || [ "$response" == "n" ]; then
+ echo "Ok then. Exiting..."
+ exit 1
+ fi
+ done
+}
+
+check_for_old_raid () {
+ # First, trigger construction of previously configured RAID groups
+ echo -n "Looking for pre-existing RAID groups..."
+ raid_config=`mdadm --examine --scan`
+ if [ -z "$raid_config" ]; then
+ echo "none found."
+ return
+ fi
+
+ echo "found some."
+ echo "Trying to configure pre-existing RAID groups..."
+ mdadm --assemble --scan --auto=yes --symlink=no
+
+ # Identify physical drives
+ raid_drives=$(cat /proc/partitions | awk '{ if ($4!="name") { print $4 } }' \
+ | grep "md" | egrep -v "^$")
+ if [ -z "$raid_drives" ]; then
+ echo "Unable to configure any RAID groups."
+ return
+ fi
+
+ numraids=`echo $raid_drives | wc -w`
+ if [ $numraids -eq 1 ]; then
+ echo "The following RAID group is now configured:"
+ else
+ echo "The following RAID groups are now configured:"
+ fi
+
+ for drive in $raid_drives; do
+ cat /proc/mdstat | grep --after-context 2 ^$drive | sed -e 's/^/\t/'
+ done
+
+ if [ $numraids -eq 1 ]; then
+ echo -n "Would you like to use this one? (Yes/No) [Yes]:"
+ else
+ echo -n "Would you like to use one of these? (Yes/No) [Yes]:"
+ fi
+
+ response=$(get_response "Yes" "Yes No Y N")
+ if [ "$response" == "no" ] || [ "$response" == "n" ]; then
+ echo
+ echo "Ok. Not using existing RAID groups."
+ echo
+
+ # pick the first RAID group to be broken
+ raid_drive=$(echo $raid_drives | /usr/bin/awk '{ print $1 }')
+
+ echo "Would you like to break RAID group $raid_drive so that its"
+ echo "members can be re-used for a new installation, understanding"
+ echo -n "that doing so will destroy all data on it? (Yes/No) [No]:"
+ destroy_raid=$(get_response "No" "Yes No Y N")
+ echo
+
+ if [ "${destroy_raid:0:1}" = "y" ]; then
+ echo "OK. Breaking the RAID group $raid_drive."
+
+ members=`ls /sys/block/$raid_drive/slaves`
+
+ echo "First, stopping all existing RAID groups:"
+ mdadm --stop --scan
+
+ for member in $members ; do
+ drive=${member:0:3}
+ part=${member:3:1}
+ echo "Re-setting partition ID for RAID group $raid_drive member /dev/${member}:"
+ sfdisk --change-id /dev/$drive $part 0x83
+ echo "Clearing RAID superblock from RAID group $raid_drive member /dev/${member}."
+ mdadm --zero-superblock /dev/$member
+ done
+ else
+ echo "OK. Stopping, but not breaking, existing RAID groups:"
+ mdadm --stop --scan
+ fi
+
+ echo
+ return
+ fi
+
+ if [ $numraids -eq 1 ]; then
+ INSTALL_DRIVE=$raid_drives
+ else
+ # take the first drive as the default
+ INSTALL_DRIVE=$(echo $raid_drives | /usr/bin/awk '{ print $1 }')
+ echo -n "Which one would you like to use? ($raid_drives) [$INSTALL_DRIVE]: "
+ INSTALL_DRIVE=$(get_response "$INSTALL_DRIVE" "$drives")
+ fi
+
+ echo "Using RAID partition $INSTALL_DRIVE"
+
+ raid_degraded=`cat /sys/block/$INSTALL_DRIVE/md/degraded`
+ raid_sync_action=`cat /sys/block/$INSTALL_DRIVE/md/sync_action`
+
+ if [ "$raid_degraded" = "1" ]; then
+ echo
+ if [ "$raid_sync_action" = "recover" ]; then
+ echo "Error: This RAID set is degraded and is in the process of"
+ echo "rebuilding. It is not safe to install onto it while the"
+ echo "rebuild is in progress. Please wait for the rebuild to"
+ echo "complete and then re-start the installation. You may"
+ echo "monitor the progress of the RAID rebuild with the"
+ echo "command:"
+ echo
+ echo " show raid $INSTALL_DRIVE"
+ echo
+ exit 1
+ fi
+ echo "Warning: This RAID set is degraded, but is not in the"
+ echo "process of rebuilding. It is safe to perform the installation"
+ echo "onto a degraded RAID set that is not in the process of"
+ echo "rebuilding. You may stop the installation now and rebuild the"
+ echo "RAID set, or continue installing onto it. If you continue"
+ echo "installing, do not attempt to rebuild the RAID set until the"
+ echo "installation has completed and you have rebooted the system."
+ echo
+ fi
+
+ warn_of_dire_consequences
+
+ ROOT_PARTITION=$INSTALL_DRIVE
+
+ # make sure we aren't working on a mounted part
+ unmount "$INSTALL_DRIVE"
+
+ # check for an old config on the partition
+ check_config_partition "$ROOT_PARTITION"
+
+ # create the filesystem on the part
+ make_filesystem "$ROOT_PARTITION"
+}
+
+check_for_new_raid () {
+ # Identify physical drives
+ drives=$(cat /proc/partitions | awk '{ if ($4!="name") { print $4 } }' \
+ | egrep -v "[0-9]$" | egrep -v "^$")
+
+ numdrives=`echo $drives | wc -w`
+
+ # Need at least two drives for RAID-1. We don't yet have the code
+ # to handle selection of two from a set of 3 or more, so for now, we
+ # only support two drives.
+ #
+ if [ $numdrives -ne 2 ]; then
+ return
+ fi
+
+ drive1=`echo $drives | awk '{ print $1 }'`
+ drive2=`echo $drives | awk '{ print $2 }'`
+
+ drivesize1=$(get_drive_size $drive1)
+ drivesize2=$(get_drive_size $drive2)
+
+ # Both drives must have enough space to hold our minimum root filesystem
+ #
+ if [ $drivesize1 -lt $ROOT_MIN -o $drivesize2 -lt $ROOT_MIN ]; then
+ return
+ fi
+
+ echo "You have two disk drives:"
+ echo -e "\t$drive1 \t$drivesize1 MB"
+ echo -e "\t$drive2 \t$drivesize2 MB"
+
+ echo -n "Would you like to configure RAID-1 mirroring on them? (Yes/No) [Yes]:"
+ response=$(get_response "Yes" "Yes No Y N")
+ if [ "$response" == "no" ] || [ "$response" == "n" ]; then
+ echo "Ok. Not configuring RAID-1."
+ return
+ fi
+
+ if [ $drivesize1 -ne $drivesize2 ]; then
+ echo "Since the disks are not the same size, we will use the smaller"
+ echo "of the two sizes in configuring the RAID-1 set. This will"
+ echo "waste some space on the larger drive."
+ echo ""
+ fi
+
+ # Configure RAID-1
+ echo "This process will erase all data on both drives."
+ echo -n "Are you sure you want to do this? (Yes/No) [No]: "
+ response=$(get_response "Yes" "Yes No Y N")
+ if [ "$response" == "no" ] || [ "$response" == "n" ]; then
+ echo "Ok. Not configuring RAID-1."
+ return
+ fi
+
+ for drive in $drives; do
+ echo "Deleting old partitions on drive $drive"
+ # remove any existing partitions on that drive
+ delete_partitions "$drive"
+ done
+
+ # Need to leave space on both disks between the MBR and the start
+ # of the first partition for grub. Grub needs to embed a large
+ # boot image there when booting off RAID devices.
+ #
+ # Partition creation variables are in units of megabytes.
+ part_start_offset=2
+ part_diag_size=60
+
+ if [ $drivesize1 -lt $drivesize2 ]; then
+ root_size=$drivesize1
+ else
+ root_size=$drivesize2
+ fi
+
+ let min_size_with_diag=${MIN_ROOT}+${part_diag_size}
+ if [ $root_size -ge $min_size_with_diag ]; then
+ echo "Would you like me to create a $part_diag_size MB partition for diagnostics?"
+ echo -n "(Yes/No) [No]: "
+ diag_response=$(get_response "No" "Yes No Y N")
+ if [ "$diag_response" == "yes" ] || [ "$diag_response" == "y" ]; then
+ for drive in $drives; do
+ echo "Creating diag partition on drive $drive"
+ create_partitions "$drive" $part_diag_size $part_start_offset "no"
+ sfdisk --change-id /dev/$drive 1 0x6
+ done
+ data_dev=2
+ let part_start_offset+=$part_diag_size
+ else
+ data_dev=1
+ fi
+ fi
+
+ let root_size-=$part_start_offset
+
+ for drive in $drives; do
+ echo "Creating data partition: /dev/${drive}${data_dev}"
+ create_partitions "$drive" $root_size $part_start_offset "no"
+ sfdisk --change-id /dev/$drive $data_dev 0xfd
+ # mark data partition as bootable
+ lecho "Marking /dev/$drive partition $data_dev bootable"
+ output=$(parted /dev/$drive set $data_dev boot on 2>&1)
+ lecho "$output"
+ done
+
+ # Must give partition device time to settle
+ sleep 5
+ echo
+
+ for drive in $drives; do
+ echo "Erasing any previous RAID metadata that may exist on /dev/${drive}${data_dev}"
+ mdadm --zero-superblock /dev/${drive}${data_dev}
+ done
+
+ echo "Creating RAID-1 group on partitions: /dev/${drive1}${data_dev} /dev/${drive2}${data_dev}"
+
+ raid_dev=md0
+ mdadm --create /dev/$raid_dev --level=1 --raid-disks=2 \
+ /dev/${drive1}${data_dev} /dev/${drive2}${data_dev}
+
+ if [ $? = 0 -a -e /dev/$raid_dev ]; then
+ echo "RAID-1 group created successfully:"
+ cat /proc/mdstat | grep --after-context 2 ^$raid_dev | sed -e 's/^/\t/'
+ else
+ echo "Unable to create RAID-1 group!"
+ return
+ fi
+
+ INSTALL_DRIVE=$raid_dev
+ ROOT_PARTITION=$INSTALL_DRIVE
+ ROOT_PARTITION_TYPE=new
+
+ # Give device time to settle...
+ sleep 5
+
+ # create the filesystem on the part
+ make_filesystem "$ROOT_PARTITION"
+}
+
+# Allow the user to select a partition to work with
+# sets the global PARTITION
+# $1 is the text to display before prompt
+select_partition () {
+ minsize=$1
+ text=$2
+ exclude=$3
+
+ echo -n "Looking for appropriate partitions: "
+ progress_indicator start
+
+ # initialize out global var. using globals in this way is bad form. I know.
+ PARTITION=''
+
+ # list only the partitions in /proc/partitions.
+ parts=$(cat /proc/partitions | awk '{ if ($4!="name") { print $4 " "} }' \
+ | egrep "[0-9]" | egrep -v "loop" | tr -d '\n')
+
+ # remove any partitions we have already previously used
+ if [ -n "$exclude" ]; then
+ for part in $parts; do
+ temp=$(echo $part | egrep -v $exclude)
+ parts_temp="$parts_temp $temp"
+ done
+ parts=$parts_temp
+ fi
+
+ # Get the partition sizes for display
+ # only show linux partitions that have sizes, i.e. remove loops
+ display=''
+ myparts=''
+ for part in $parts; do
+ if [ ${part:0:2} = "md" ]; then
+ parttype="RAID"
+ else
+ rootdev=$(echo $part | sed 's/[0-9]//g')
+ parttype=$(fdisk -l /dev/$rootdev | grep $part | grep Linux)
+ fi
+ if [ -n "$parttype" ]; then
+ lsize=$(get_drive_size $part)
+ if [ "$lsize" -a $lsize -ge $minsize ]; then
+ display="$display $part\t\t$lsize"MB"\n"
+ myparts="$myparts $part"
+ fi
+ fi
+ done
+
+ progress_indicator stop
+ echo "OK"
+
+ if [ -n "$myparts" ]; then
+ lpartition=''
+ while [ -z "$lpartition" ]; do
+ # take the first partition as the default
+ lpartition=$(echo $myparts | /usr/bin/awk '{ print $1 }')
+
+ echo "I found the following partitions suitable for the Vyatta image:"
+ echo -e "Partition\tSize"
+ echo -e "$display"
+ echo
+ echo -n "$text [$lpartition]: "
+
+ lpartition=$(get_response "$lpartition" "$myparts")
+ echo
+ done
+ else
+ becho "No suitable partition sizes found. Exiting..."
+ exit 1
+ fi
+ PARTITION=$lpartition
+}
+
+rename_old_config() {
+ files=$(find /mnt/config -mindepth 1 -type f | grep -v pre-glendale)
+ for f in $files; do
+ if grep -q '/\*XORP Configuration File, v1.0\*/' $f >&/dev/null; then
+ CURTIME=$(date +%F-%H%M%S)
+ mv $f $f.pre-glendale.$CURTIME
+ fi
+ done
+}
+
+## check_config_partition
+# look to see if this partition contains a config file
+# and back it up
+check_config_partition() {
+ lpart=$1
+
+ # Cleanup from possible partial last run
+ rm -fr /mnt/config
+
+ # Look to see if this is a config partition
+ mkdir -p /mnt/tmp
+ output=$(mount /dev/$lpart /mnt/tmp 2>&1)
+ if [ $? != 0 ]; then
+ lecho "Cannot mount /dev/$lpart"."\nmount /dev/$ldrive$part /mnt/tmp\nExiting..."
+ lecho "$output"
+ else
+ # Look to see if there is a config partition there
+ if [ -f /mnt/tmp/opt/vyatta/etc/config/.vyatta_config ] \
+ || [ -f /mnt/tmp/.vyatta_config ]; then
+ response=''
+ while [ -z "$response" ]; do
+ echo "/dev/$lpart has an old configuration directory!"
+ echo -ne "Would you like me to save the data on it\nbefore I delete it? (Yes/No) [Yes]: "
+ response=$(get_response "Yes" "Yes No Y N")
+ if [ "$response" == "yes" ] || [ "$response" == "y" ]; then
+ mkdir -p /mnt/config
+ if [ -d /mnt/tmp/opt/vyatta/etc/config ]; then
+ output=$(cp -pR /mnt/tmp/opt/vyatta/etc/config/* /mnt/config)
+ else
+ output=$(cp -pR /mnt/tmp/* /mnt/config)
+ fi
+ if [ -n "$output" ]; then
+ echo -e "Warning: error in copying the old config partition.\nSee $INSTALL_LOG for more details."
+ lecho "Warning: error in copying the old config partition.\ncp -pR /mnt/tmp/* /mnt/config\n$output\n"
+ fi
+ rename_old_config
+ fi
+ done
+ fi
+ umount /mnt/tmp
+ fi
+}
+
+# Delete all existing partitions for an automated install
+# $1 is the drive to delete partitions from
+delete_partitions () {
+ ldrive=$1
+
+ # get the partitions on the drive
+ # in the first grep below we add the optional [p] in order to
+ # accomdate cciss drives
+ partitions=$(cat /proc/partitions | grep $ldrive[p]*[0-9] \
+ | awk '{ print $4 }' | sed 's/\(.*\)\([0-9]$\)/\2/g' \
+ | grep -v "^$")
+
+ # now for each part, blow it away
+ for part in $partitions; do
+ # Look to see if this is a config partition
+ check_config_partition "$ldrive$part"
+
+ lecho "Removing partition $part on /dev/$ldrive"
+ output=$(parted /dev/$ldrive rm $part)
+ status=$?
+ if [ "$status" != 0 ]; then
+ echo -e "Warning: cannot delete partition $part on $ldrive.\nPlease see $INSTALL_LOG for more details."
+ lecho "Warning: cannot delete partition $part on $ldrive.\nparted /dev/$ldrive rm $part\n$output"
+ fi
+
+ # We add a bogus sleep here because the loop needs to wait for udev
+ sleep 5
+ done
+}
+
+# make a filesystem on the drive
+# $1 is the drive to format
+make_filesystem () {
+ ldrive=$1
+
+ echo -n "Creating filesystem on /dev/$ldrive: "
+ lecho "Creating filesystem on /dev/$ldrive..."
+
+ progress_indicator start
+ output=$(mkfs -t $ROOT_FSTYPE /dev/$ldrive 2>&1)
+ status=$?
+ if [ "$status" != 0 ]; then
+ echo -e "Error: couldn't create the root filesystem.\nSee $INSTALL_LOG for further details.\nExiting..."
+ lecho "Error: couldn't create the root filesystem.\n/sbin/mke2fs -j /dev/$ldrive\n$output"
+ exit 1
+ fi
+ progress_indicator stop
+ echo "OK"
+}
+
+# create the root partition
+# $1 is the install drive e.g. sda
+# $2 is the partition size e.g. 512
+# This will set the global ROOT_PARTITION
+create_partitions() {
+ ldrive=$1
+ root_part_size=$2
+ start_offset=$3
+ initialize_fs=$4
+
+ # Make sure there is enough space on drive
+ size=$(get_drive_size "$ldrive")
+ if [ "$root_part_size" -gt "$size" ]; then
+ echo "Error: $ldrive is only $size"MB" large. Desired root is $root_part_size"
+ exit 1
+ fi
+
+ lecho "Creating root partition on /dev/$ldrive"
+
+ # make the root partition
+ output=$(parted /dev/$ldrive mkpart primary $start_offset $root_part_size)
+ status=$?
+ if [ "$status" != 0 ]; then
+ echo -e "Error creating primary partition on $ldrive.\nPlease see $INSTALL_LOG for more details.\nExiting..."
+ lecho "Error creating primary partition on $ldrive.\nparted /dev/$ldrive mkpart primary 0 $root_part_size\n$output"
+ exit 1
+ fi
+
+ # set the partition number on the device.
+ if [ -n "$( echo $ldrive | grep -E "cciss|ida" )" ]; then
+ # if this is a cciss
+ ROOT_PARTITION=$ldrive"p1"
+ else
+ # else... the rest of the world
+ ROOT_PARTITION=$ldrive"1"
+ fi
+ # udev takes time to re-add the device file, so wait for it
+ while [ ! -b "/dev/$ROOT_PARTITION" ]; do
+ sleep 1
+ done
+
+ if [ "$initialize_fs" = "yes" ]; then
+ # make the root and config file systems.
+ make_filesystem "$ROOT_PARTITION"
+ fi
+}
+
+# sets ROOT_FSTYPE based on disk size
+set_root_fstype () {
+ local drv=$1
+ local sz=$(get_drive_size "$drv")
+ # If disk is small, it is probably a CF device or virtual environment
+ # so avoid the overhead of a journal
+ if (( $sz < 11000 )); then
+ ROOT_FSTYPE=ext2
+ else
+ ROOT_FSTYPE=ext3
+ fi
+}
+
+# ask for user input on the parted and skip setup methods
+# $1 is whether or not to run parted
+# sets globals INSTALL_DRIVE, ROOT_PARTITION, CONFIG_PARTITION
+setup_method_manual() {
+ parted=$1
+
+ echo "The Vyatta install needs a minimum ${ROOT_MIN}MB root"
+ echo "with partiton type 83 (Linux)."
+ echo -e "\n\n"
+
+ # if this is parted, let the user create the partitions
+ if [ "$parted" == 'parted' ]; then
+ while [ -z "$INSTALL_DRIVE" ]; do
+ # TODO: right now we only run parted on a single drive
+ echo -e "\nI found the following drives on your system:"
+ select_drive 'Which drive would you like to run parted on?' \
+ 'INSTALL_DRIVE'
+ done
+
+ set_root_fstype "$INSTALL_DRIVE"
+
+ # Unmount the install drive if it is mounted
+ unmount "$INSTALL_DRIVE"
+
+ # Run parted and let the user configure
+ parted /dev/$INSTALL_DRIVE
+ fi
+
+ # Ask for the root partition and make sure it's valid
+ while [ -z "$ROOT_PARTITION" ]; do
+ select_partition 500 "Which partition should I install the root on?"
+ # Note that PARTITION is defined in select partition
+ ROOT_PARTITION=$PARTITION
+ unmount "$ROOT_PARTITION"
+ vd=$(grep $ROOT_PARTITION /proc/partitions | awk '{ print $4 }')
+
+ if [ -z "$vd" ]; then
+ echo
+ echo "$ROOT_PARTITION is an invalid partition. Please try again."
+ ROOT_PARTITION=""
+ fi
+ done
+
+ # check for an old config on the partition
+ check_config_partition "$ROOT_PARTITION"
+
+ # create the filesystem on the part
+ make_filesystem "$ROOT_PARTITION"
+
+ # We need to set the INSTALL_DRIVE if it wasn't set when the user ran parted
+ # We assume that we will use the boot sector of the same drive that the
+ # partition is on.
+ # TODO: Allow different drives to function as the boot device
+ if [ -z "$INSTALL_DRIVE" ]; then
+ if [ ${ROOT_PARTITION:0:2} = "md" ]; then
+ INSTALL_DRIVE=$ROOT_PARTITION
+ else
+ INSTALL_DRIVE=$(echo $ROOT_PARTITION | sed 's/[0-9]//g')
+ fi
+ fi
+}
+
+# Walk the user through the auto setup method
+# sets globals INSTALL_DRIVE, ROOT_PARTITION
+setup_method_auto () {
+ while [ -z "$INSTALL_DRIVE" ]; do
+ echo "I found the following drives on your system:"
+ select_drive 'Install the image on?' 'INSTALL_DRIVE'
+
+ # check to make sure the drive is large enough to hold the image
+ if [ -n "$INSTALL_DRIVE" ]; then
+ set_root_fstype "$INSTALL_DRIVE"
+ lsize=$(get_drive_size "$INSTALL_DRIVE")
+ total=$ROOT_MIN
+ if [ "$total" -gt "$lsize" ]; then
+ echo "Unfortunately, Vyatta requires a total of at least $total"MB" to properly install."
+ echo "$INSTALL_DRIVE is below the minimum required capacity and therefore, cannot be used to"
+ echo -e "complete the installation.\n"
+ echo "If other drives are present"
+ echo -e "Please select another drive...\n"
+
+ INSTALL_DRIVE=''
+ fi
+ fi
+ done
+
+ warn_of_dire_consequences
+
+ echo
+
+ # make sure we aren't working on a mounted part
+ unmount "$INSTALL_DRIVE"
+
+ # remove any existing partitions on that drive
+ delete_partitions "$INSTALL_DRIVE"
+
+ # Enforce minimum partition size requirement.
+ local root_part_size=0
+ while [ $ROOT_MIN -gt $root_part_size ]; do
+ # Get the size of the drive
+ size=$(get_drive_size $INSTALL_DRIVE)
+ echo -n "How big of a root partition should I create? ($ROOT_MIN"MB" - $size"MB") [$size]MB: "
+ response=$(get_response "$size")
+ # TODO: need to have better error checking on this value
+ root_part_size=$(echo "$response" | sed 's/[^0-9]//g')
+ if [ $root_part_size -lt $ROOT_MIN ] \
+ || [ $root_part_size -gt $size ]; then
+ echo "Root partion must be between $ROOT_MIN"MB" and $size"MB""
+ echo
+ root_part_size=0
+ fi
+ done
+
+ echo
+
+ # now take the data and create the partitions
+ create_partitions "$INSTALL_DRIVE" "$root_part_size" 0 "yes"
+ # mark data partition as bootable
+ lecho "Marking /dev/$INSTALL_DRIVE partition 1 as bootable"
+ output=$(parted /dev/$INSTALL_DRIVE set 1 boot on 2>&1)
+ lecho "$output"
+ # Must give partition device time to settle
+ sleep 5
+}
+
+unmount () {
+ # grab the list of mounted drives
+ # make sure to reverse sort so as to unmount up the tree
+ mounted=$(mount | grep "$1" | cut -f3 -d' ' | sort -r)
+ if [ -n "$mounted" ]; then
+ echo "I need to unmount: "
+ echo "$mounted"
+
+ response=''
+ while [ -z $response ]; do
+ echo -n "Continue (Yes/No) [No]: "
+ response=$(get_response "No" "Yes No Y N")
+ if [ "$response" == "no" ] || [ "$response" == "n" ]; then
+ echo -e "Ok then. Need to unmount to continue.\nExiting..."
+ exit 1
+ fi
+ done
+
+ for parts in "$mounted"; do
+ lecho "umount $parts"
+ output=$(umount $parts)
+ status=$?
+ if [ "$status" != 0 ]; then
+ echo -e "Exiting: error unmounting $parts.\nPlease see $INSTALL_LOG for more details."
+ lecho "Exiting: error unmounting $parts.\numount $parts\n$output"
+ exit 1
+ fi
+ done
+ fi
+}
+
+##### Main
+##
+# turn off any mounted swap files
+turnoffswap
+
+while true; do
+ # check if we are in a live CD boot
+ if ! is_live_cd_boot; then
+ # running installed system. check boot drive/partition.
+ if is_union_install; then
+ # this is a union install
+ ROOT_PARTITION_TYPE=union
+ else
+ # this is an old, non-union install
+ ROOT_PARTITION_TYPE=old
+ fi
+ while [ -z "$response" ]; do
+ cat <<EOF
+You are running an installed system. Do you want to use the current install
+EOF
+ echo -n "partition? (Yes/No) [Yes]: "
+ response=$(get_response "Yes" "Yes No Y N")
+ echo
+ done
+ if [ "$response" == "no" ] || [ "$response" == "n" ]; then
+ # for simplicity, require the current install partition if running an
+ # installed system.
+ ROOT_PARTITION_TYPE=''
+ break
+ else
+ # flag them as found but we don't actually need them
+ ROOT_PARTITION=dummy
+ INSTALL_DRIVE=dummy
+ fi
+ fi
+ if [ -n "$ROOT_PARTITION" ]; then
+ # got partition. done.
+ break
+ fi
+
+ # some drives don't show up in /proc/partitions so we need to bootstrap them
+ echo -n "Probing drives: "
+ progress_indicator start
+ probe_drives
+ progress_indicator stop
+ echo "OK"
+
+ # try old raid
+ check_for_old_raid
+ if [ -n "$ROOT_PARTITION" ]; then
+ # got partition. done.
+ break
+ fi
+
+ # try new raid
+ check_for_new_raid
+ if [ -n "$ROOT_PARTITION" ]; then
+ # got partition. done.
+ break
+ fi
+
+ cat <<EOF
+The Vyatta image will require a minimum ${ROOT_MIN}MB root.
+Would you like me to try to partition a drive automatically
+or would you rather partition it manually with parted? If
+you have already setup your partitions, you may skip this step
+
+EOF
+ PART_METHOD=''
+ while [ -z "$PART_METHOD" ]; do
+ echo -n "Partition (Auto/Parted/Skip) [Auto]: "
+ PART_METHOD=$(get_response "Auto" "Auto Parted Skip A P S")
+ done
+ echo
+
+ # TODO: Note installs assume an LBA BIOS. So no boot partition currently.
+ # also note that we are not creating a swap partition right now.
+ ROOT_PARTITION_TYPE=new
+ if [ "$PART_METHOD" == "parted" ] || [ "$PART_METHOD" == "p" ]; then
+ setup_method_manual "parted"
+ elif [ "$PART_METHOD" == "skip" ] || [ "$PART_METHOD" == "s" ]; then
+ setup_method_manual "skip"
+ elif [ "$PART_METHOD" == "auto" ] || [ "$PART_METHOD" == "a" ]; then
+ setup_method_auto
+ fi
+
+ break
+done
+
+if [ -z "$ROOT_PARTITION" ]; then
+ echo 'Partition not selected. Exiting...'
+ exit 1
+fi
+
+echo "$ROOT_PARTITION_TYPE $ROOT_PARTITION $INSTALL_DRIVE" >$OUTFILE
+becho 'Done!'
+exit 0
+
diff --git a/scripts/install/install-image b/scripts/install/install-image
new file mode 100755
index 00000000..0bf31a00
--- /dev/null
+++ b/scripts/install/install-image
@@ -0,0 +1,170 @@
+#!/bin/bash
+
+# source in the functions
+source /opt/vyatta/sbin/install-functions
+
+# export INSTALL_LOG for the scripts invoked
+export INSTALL_LOG=/tmp/install-$$.log
+
+# file for get-partition output
+PART_FILE=''
+
+fail_exit ()
+{
+ echo "$*"
+ echo 'Exiting...'
+ exit 1
+}
+
+clean_up ()
+{
+ if [ -n "$PART_FILE" ]; then
+ rm -f $PART_FILE >&/dev/null
+ fi
+ umount $CD_SQUASH_ROOT >&/dev/null || true
+ umount $CD_ROOT >&/dev/null || true
+ umount $INST_ROOT >&/dev/null || true
+ umount $READ_ROOT >&/dev/null || true
+ umount $WRITE_ROOT >&/dev/null || true
+}
+
+sig_handler () {
+ echo "ERROR: Signal received. Exiting..."
+ clean_up
+ echo "Done"
+ trap - EXIT
+ exit 1
+}
+
+exit_handler () {
+ clean_up
+}
+
+# set up the specified ISO image for install
+set_up_new_iso ()
+{
+ if [ ! -f "$NEW_ISO" ] || ! (file $NEW_ISO | grep -q 9660); then
+ fail_exit "\"$NEW_ISO\" is not a valid ISO image file."
+ fi
+
+ # make sure mount points exist
+ mkdir -p $INST_ROOT $WRITE_ROOT $READ_ROOT $CD_ROOT $CD_SQUASH_ROOT
+
+ # mount ISO
+ margs="-o loop,ro $NEW_ISO $CD_ROOT"
+ if ! try_mount "$margs"; then
+ fail_exit 'Failed to mount the new image.'
+ fi
+
+ # check squash image
+ local squash_file=$CD_ROOT/live/filesystem.squashfs
+ if [ ! -f "$squash_file" ] || ! (file $squash_file | grep -q Squashfs) \
+ || ! grep -q '^ii vyatta-version ' $CD_ROOT/live/packages.txt; then
+ fail_exit "\"$NEW_ISO\" is not a Vyatta ISO image file."
+ fi
+
+ # mount squash image
+ margs="-o loop,ro $squash_file $CD_SQUASH_ROOT"
+ if ! try_mount "$margs"; then
+ fail_exit 'Failed to mount the squashfs image.'
+ fi
+}
+
+# install new image into a newly-formatted partition.
+# will exit with error if installation fails.
+install_new ()
+{
+ local root_part=$1
+ local inst_drv=$2
+
+ if [ ! -e "/dev/$root_part" ] || [ ! -e "/dev/$inst_drv" ]; then
+ fail_exit "Invalid drive/partition ($inst_drv and $root_part)."
+ fi
+
+ # install new image
+ if ! /opt/vyatta/sbin/install-image-new "$root_part"; then
+ exit 1
+ fi
+
+ # postinst operations
+ if ! /opt/vyatta/sbin/install-postinst-new \
+ "$inst_drv" "$root_part" union; then
+ exit 1
+ fi
+}
+
+# install new image into the current boot partition.
+# will exit with error if installation fails.
+install_existing ()
+{
+ local ctype=$1
+ if ! /opt/vyatta/sbin/install-image-existing "$ctype"; then
+ exit 1
+ fi
+}
+
+# the image to be installed. only used if installing from an installed,
+# running system.
+NEW_ISO=$1
+
+if [ `whoami` != 'root' ] ; then
+ fail_exit 'This script must be run with root privileges.'
+fi
+
+trap sig_handler INT KILL
+trap exit_handler EXIT
+
+if is_live_cd_boot; then
+ if [ -n "$NEW_ISO" ]; then
+ fail_exit 'Do not specify an image when installing from a live CD.'
+ fi
+elif [ -z "$NEW_ISO" ]; then
+ fail_exit 'Must specify an image to install.'
+else
+ # installing on an installed system. set up the new image.
+ set_up_new_iso
+fi
+
+# check versions
+if is_live_cd_boot; then
+ CURVER=LIVECD
+else
+ CURVER=$(get_cur_version)
+fi
+NEWVER=$(get_new_version)
+if [ -z "$CURVER" ] || [ -z "$NEWVER" ]; then
+ fail_exit 'Cannot find release version.'
+fi
+if [ "$CURVER" == "$NEWVER" ]; then
+ fail_exit "Version \"$NEWVER\" is already installed."
+fi
+
+# get install partition
+PART_FILE=$(mktemp /tmp/inst-get-part.XXXXXX) \
+ || fail_exit 'Failed to create temporary file'
+if ! /opt/vyatta/sbin/install-get-partition $PART_FILE; then
+ exit 1
+fi
+
+# get the partition params
+root_part_type=''
+root_part=''
+inst_drv=''
+eval "read root_part_type root_part inst_drv <$PART_FILE" >&/dev/null
+rm -f $PART_FILE >&/dev/null
+
+# handle different types
+case "$root_part_type" in
+ new)
+ install_new "$root_part" "$inst_drv"
+ exit 0
+ ;;
+ union|old)
+ install_existing "$root_part_type"
+ exit 0
+ ;;
+ *)
+ fail_exit "Unknown partition type \"$root_part_type\"."
+ ;;
+esac
+
diff --git a/scripts/install/install-image-existing b/scripts/install/install-image-existing
new file mode 100755
index 00000000..0b5cba62
--- /dev/null
+++ b/scripts/install/install-image-existing
@@ -0,0 +1,133 @@
+#!/bin/bash
+
+# this script installs a new release image into a running system.
+# the new ISO image must be already mounted by caller.
+# the script sets up a new union mount for the new release. a reboot
+# is then required to boot into the newly installed release.
+
+# the current install type: "union" or "old"
+CUR_INSTALL=$1
+
+source /opt/vyatta/sbin/install-functions
+
+failure_exit () {
+ echo "$*"
+ exit 1
+}
+
+if [ `whoami` != 'root' ] ; then
+ failure_exit 'This script must be run with root privileges.'
+fi
+
+CURVER=$(sed -n 's/^Version \+: \+\([^ ]\+\)$/\1/p' \
+ ${vyatta_sysconfdir}/version 2>/dev/null)
+if [ -z "$CURVER" ]; then
+ failure_exit 'Cannot find current version.'
+fi
+
+# get new version string. this is from the squashfs image.
+NEWVER=$(grep '^Version ' ${CD_SQUASH_ROOT}${vyatta_sysconfdir}/version \
+ | tr -s ' ' | cut -d ' ' -f 3)
+if [ -z "$NEWVER" ]; then
+ failure_exit 'Cannot find new release version.'
+fi
+if [ "$CURVER" == "$NEWVER" ]; then
+ failure_exit "Cannot install the same release version \"$NEWVER\"."
+fi
+
+# start the install
+echo "Installing \"$NEWVER\" release."
+
+# this is the default if current install is union
+BOOT_DIR=/live/image/boot
+if [ "$CUR_INSTALL" == 'old' ]; then
+ BOOT_DIR=/boot
+elif [ "$CUR_INSTALL" != 'union' ]; then
+ echo 'Invalid current install type. Exiting...'
+ exit 1
+fi
+
+# create the new release directories
+REL_ROOT=$BOOT_DIR/$NEWVER
+RW_DIR="$REL_ROOT/live-rw"
+if ! mkdir -p "$RW_DIR"; then
+ failure_exit 'Cannot create directory for new release.'
+fi
+
+# copy the squashfs image and boot files
+echo "Copying new release files..."
+squash_img=${CD_ROOT}/live/filesystem.squashfs
+boot_dir=${CD_SQUASH_ROOT}/boot
+boot_files=$(find $boot_dir -maxdepth 1 -type f -o -type l 2>/dev/null)
+if [ ! -f "$squash_img" ] || [ -z "$boot_files" ]; then
+ becho 'Cannot find the files. Exiting...'
+ exit 1
+fi
+target_squash=$REL_ROOT/$NEWVER.squashfs
+cp -p $squash_img $target_squash >&/dev/null
+cp -dp $boot_files $REL_ROOT/ >&/dev/null
+
+# mount copied squashfs
+if ! try_mount "-o loop,ro $target_squash $READ_ROOT"; then
+ failure_exit 'Failed to mount new squashfs image.'
+fi
+
+# set up root for postinst
+margs="-t unionfs -o noatime,dirs=$RW_DIR=rw:$READ_ROOT=ro unionfs"
+margs="$margs $INST_ROOT"
+if ! try_mount "$margs"; then
+ failure_exit 'Failed to set up root directory for postinst.'
+fi
+
+# set up /var/run fstab entry
+PI_FSTAB=$INST_ROOT/etc/fstab
+if ! grep -q 'tmpfs /var/run ' $PI_FSTAB >&/dev/null; then
+ # replace the fstab. the default one has header that will cause
+ # it to be wiped out on live boot.
+ echo 'tmpfs /var/run tmpfs nosuid,nodev 0 0' >$PI_FSTAB
+fi
+
+# save current config if needed
+def_cfg="$VYATTA_CFG_DIR/config.boot"
+if [ -f "$def_cfg" ]; then
+ resp=''
+ while [ -z "$resp" ]; do
+ echo 'Would you like to use the current configuration'
+ echo -n 'for the new version? (Yes/No) [Yes]: '
+ resp=$(get_response "Yes" "Yes No Y N")
+ if [ "$resp" == 'yes' ] || [ "$resp" == 'y' ]; then
+ echo 'Copying current configuration...'
+ ndir=${INST_ROOT}${VYATTA_CFG_DIR}
+ mkdir -p $ndir
+ cp -p $def_cfg $ndir/
+ chgrp -R vyattacfg $ndir
+ chmod -R 775 $ndir
+ fi
+ done
+fi
+
+# postinst hook
+PI_SCRIPT=${INST_ROOT}${vyatta_sysconfdir}/install-image/postinst
+if [ -e "$PI_SCRIPT" ]; then
+ echo "Running post-install script..."
+ $PI_SCRIPT $INST_ROOT
+fi
+
+# set up grub entry (if provided)
+DEF_GRUB=${INST_ROOT}${vyatta_sysconfdir}/grub/default-union-grub-entry
+if [ -e "$DEF_GRUB" ]; then
+ echo "Setting up grub configuration..."
+ old_grub_cfg=$BOOT_DIR/grub/grub.cfg
+ new_grub_cfg=/tmp/grub.cfg.$$
+ sed -n '/^menuentry/q;p' $old_grub_cfg >$new_grub_cfg
+ cat $DEF_GRUB >>$new_grub_cfg
+ sed -n '/^menuentry/,${p}' $old_grub_cfg >>$new_grub_cfg
+ sed -i 's/^set default=[0-9]\+$/set default=0/' $new_grub_cfg
+ mv $new_grub_cfg $old_grub_cfg
+fi
+
+echo 'Done.'
+
+# done
+exit 0
+
diff --git a/scripts/install/install-image-new b/scripts/install/install-image-new
new file mode 100755
index 00000000..7294fc35
--- /dev/null
+++ b/scripts/install/install-image-new
@@ -0,0 +1,76 @@
+#!/bin/bash
+
+if [ `whoami` != 'root' ] ; then
+ echo "This script must be run with root privileges."
+ exit 1
+fi
+
+# source in the functions
+source /opt/vyatta/sbin/install-functions
+
+# the INSTALL_LOG env var should be exported by the "caller".
+# it will be used to log messages.
+
+# the install partition e.g. sda1
+ROOT_PARTITION=$1
+
+becho "Mounting /dev/$ROOT_PARTITION..."
+
+# mount the partition
+mkdir -p $WRITE_ROOT
+if ! try_mount "/dev/$ROOT_PARTITION $WRITE_ROOT"; then
+ echo 'Exiting...'
+ exit 1
+fi
+
+version=$(get_new_version)
+if [ -z "$version" ]; then
+ echo 'Cannot find new version. Exiting...'
+ exit 1
+fi
+
+# make the dir for the new version
+mkdir -p $WRITE_ROOT/boot/$version
+# make dir for backing store
+rw_dir=$WRITE_ROOT/boot/$version/live-rw
+mkdir -p $rw_dir
+
+echo Copying squashfs image...
+# these are the defaults if installing from a specified ISO image file.
+# in such cases, the ISO image has already been mounted by caller.
+squash_img=${CD_ROOT}/live/filesystem.squashfs
+boot_dir=${CD_SQUASH_ROOT}/boot
+boot_files=$(find $boot_dir -maxdepth 1 -type f -o -type l 2>/dev/null)
+if [ ! -f "$squash_img" ] || [ -z "$boot_files" ]; then
+ # maybe installing from a live CD boot?
+ squash_img=/live/image/live/filesystem.squashfs
+ boot_dir=/boot
+ boot_files=$(find $boot_dir -maxdepth 1 -type f -o -type l 2>/dev/null)
+ if [ ! -f "$squash_img" ] || [ -z "$boot_files" ]; then
+ # not a live CD boot either. give up.
+ becho 'Cannot find the squashfs image. Exiting...'
+ exit 1
+ fi
+fi
+
+target_squash=$WRITE_ROOT/boot/$version/$version.squashfs
+cp -p $squash_img $target_squash
+echo Copying kernel and initrd images...
+cp -dp $boot_files $WRITE_ROOT/boot/$version/
+
+# set up union root for postinst
+mkdir -p $INST_ROOT $READ_ROOT
+if ! try_mount "-o loop,ro -t squashfs $target_squash $READ_ROOT"; then
+ echo 'Exiting...'
+ exit 1
+fi
+margs="-t unionfs -o noatime,dirs=$rw_dir=rw:$READ_ROOT=ro unionfs $INST_ROOT"
+if ! try_mount "$margs"; then
+ echo 'Exiting...'
+ exit 1
+fi
+
+becho "Done!"
+
+exit 0
+
diff --git a/scripts/install/install-postinst-new b/scripts/install/install-postinst-new
new file mode 100755
index 00000000..84b96989
--- /dev/null
+++ b/scripts/install/install-postinst-new
@@ -0,0 +1,201 @@
+#!/bin/bash
+
+# postinst operations for installation on a "new" partition, i.e., full grub
+# setup needed, etc.
+
+if [ `whoami` != 'root' ] ; then
+ echo "This script must be run with root privileges."
+ exit 1
+fi
+
+# source in the functions
+source /opt/vyatta/sbin/install-functions
+
+# the INSTALL_LOG env var should be exported by the "caller".
+# it will be used to log messages.
+
+# the base install drive e.g. sda
+INSTALL_DRIVE=$1
+# the install partition e.g. sda1
+ROOT_PARTITION=$2
+# install type: "union" or "old"
+INSTALL_TYPE=$3
+
+# copy configuration to the config directory
+copy_config () {
+ local cfg_dir=${INST_ROOT}${VYATTA_CFG_DIR}
+
+ # create the config directory
+ mkdir -p $cfg_dir
+ chgrp vyattacfg $cfg_dir
+ chmod 775 $cfg_dir
+
+ # create our config partition marker
+ touch $cfg_dir/.vyatta_config
+
+ if [ -d /mnt/config ]; then
+ echo "Copying old configurations to config partition."
+ cp -a /mnt/config/* $cfg_dir/ >&/dev/null
+ else
+ # Find the config files and give the user the option to copy config files
+ # TODO: this needs cleaned up
+ if [ -f "${VYATTA_CFG_DIR}/config.boot" ]; then
+ config=${VYATTA_CFG_DIR}/config.boot
+ fi
+ if [ -f "${FD_CFG_DIR}/config.boot" ]; then
+ if [ -z "$config" ]; then
+ config="${FD_CFG_DIR}/config.boot"
+ else
+ config="$config ${FD_CFG_DIR}/config.boot"
+ fi
+ fi
+
+ if [ -n "$config" ]; then
+ echo "I found the following configuration files"
+ for file in $config; do
+ echo $file
+ done
+
+ default=$(echo -e $config | awk '{ print $1 }')
+
+ while [ -z "$configfile" ]; do
+ echo -n "Which one should I copy to $INSTALL_DRIVE? [$default]: "
+ configfile=$(get_response "$default" "$config")
+ done
+
+ echo
+ cp -p $configfile $cfg_dir/ >&/dev/null
+ if [ $? != 0 ]; then
+ lecho "Error copying file $configfile to config directory. Exiting..."
+ exit 1
+ fi
+ fi
+ fi
+
+ # set the permissions on the new config file
+ if [ -f "$cfg_dir/config.boot" ]; then
+ chgrp vyattacfg $cfg_dir/config.boot
+ chmod 775 $cfg_dir/config.boot
+ fi
+}
+
+# setup grub on the boot sector of a user selected drive
+install_grub () {
+ grub_inst_drv=''
+ if [ ${INSTALL_DRIVE:0:2} == "md" ]; then
+ grub_inst_drv=$INSTALL_DRIVE
+ fi
+
+ mkdir -p $grub_root/boot/grub
+
+ # Let the user choose the boot sector
+ while [ -z "$grub_inst_drv" ]
+ do
+ echo "I need to install the GRUB boot loader."
+ echo "I found the following drives on your system:"
+ select_drive "Which drive should GRUB modify the boot partition on?" \
+ 'grub_inst_drv'
+ done
+
+ echo -n "Setting up grub: "
+ lecho "Setting up grub..."
+
+ # Install grub in the boot sector of the primary drive
+ progress_indicator start
+ output=$(grub-install --no-floppy --recheck --root-directory=$grub_root \
+ /dev/$grub_inst_drv 2>&1)
+ lecho "$output"
+ progress_indicator stop
+
+ output=$(/opt/vyatta/sbin/vyatta-grub-setup $grub_setup_args \
+ "$ROOT_PARTITION" '' $grub_root 2>&1)
+ ret=$?
+ lecho "$output"
+ if [ $ret == 0 ]; then
+ echo 'OK'
+ else
+ echo 'Grub failed to install!'
+ exit 1
+ fi
+}
+
+##### Main
+
+version=$(get_new_version)
+if [ -z "$version" ]; then
+ echo 'Cannot find new version. Exiting...'
+ exit 1
+fi
+
+# these are the defaults for "union"
+grub_root=$WRITE_ROOT
+grub_setup_args="-u $version"
+if [ "$INSTALL_TYPE" == 'old' ]; then
+ grub_root=$INST_ROOT
+ grub_setup_args=''
+elif [ "$INSTALL_TYPE" != 'union' ]; then
+ echo 'Invalid install type. Exiting...'
+ exit 1
+fi
+
+# Copy the config files saved from earlier steps
+copy_config
+
+# Modify config to match system
+# Assume user wants to keep password from old config
+if [ ! -d /mnt/config ]; then
+ # Disable root login
+ set_encrypted_password root "*" "${INST_ROOT}${VYATTA_CFG_DIR}/config.boot"
+
+ echo "Enter password for administrator account"
+ change_password vyatta "${INST_ROOT}${VYATTA_CFG_DIR}/config.boot"
+fi
+
+# Install grub
+install_grub
+
+# Fix up PAM configuration for login so that invalid users are prompted
+# for password
+# XXX is this still needed? can't find this in the files any more.
+sed -i 's/requisite[ \t][ \t]*pam_securetty.so/required pam_securetty.so/' \
+ ${INST_ROOT}/etc/pam.d/login
+
+#
+# Only start the mdadm daemon if we have the root filesystem running
+# on a RAID set. Since this script is the only way that the root filesystem
+# ever gets set up, we can do this configuration here.
+#
+MDADM_CONFIG_FILE=${INST_ROOT}/etc/default/mdadm
+if [ -f "$MDADM_CONFIG_FILE" ]; then
+ if [ "${INSTALL_DRIVE:0:2}" = "md" ]; then
+ sed -i 's/^START_DAEMON.*$/START_DAEMON=true/' $MDADM_CONFIG_FILE
+ else
+ sed -i 's/^START_DAEMON.*$/START_DAEMON=false/' $MDADM_CONFIG_FILE
+ fi
+fi
+
+if [ "$INSTALL_TYPE" == 'union' ]; then
+ # make /var/run tmpfs
+ pi_fstab=$INST_ROOT/etc/fstab
+ if ! grep -q 'tmpfs /var/run ' $pi_fstab >&/dev/null; then
+ # replace the fstab. the default one has header that will cause
+ # it to be wiped out on live boot.
+ echo 'tmpfs /var/run tmpfs nosuid,nodev 0 0' >$pi_fstab
+ fi
+else
+ # not passing the write root to postinst (only needed for union)
+ WRITE_ROOT=''
+fi
+
+# postinst hook
+if [ -e /opt/vyatta/etc/install-system/postinst ]; then
+ echo "running post-install script"
+ output=$(/opt/vyatta/etc/install-system/postinst \
+ "$INST_ROOT" "$WRITE_ROOT" 2>&1)
+ lecho "$output"
+fi
+
+becho "Done!"
+
+exit 0
+