JumpStart Disk Implementation


What is a JumpStart Disk and why do we need it?  For a normal Solaris JumpStart to succeed you need to have several services available from some machine on the same subnet as the client.  These services are provided by what we generically call boot servers.  However, sometimes it is not possible to put a boot server on a subnet or you are using a network technology like token ring or FDDI which the Sun PROM doesn't understand and thus can't use to perform a network boot.  For those machines we have come up with an alternative which we call a JumpStart Disk.  Instead of booting off of the network, we attach an external disk to the machine and boot off of it.  This allows us to JumpStart machines that do not have a boot server on their subnets.  Additionally, we decided to make the JumpStart Disk able to JumpStart machines which do not have access to any of our install servers either.  What that means is that anything we would normally get via the network needs to be put onto the JumpStart Disk.  The JumpStart disk can also support the QuickJump process described in my paper.

Note that if the machines which need some sort of non-network boot process have both floppy and CD-ROM drives, and you don't wish to use QuickJump, then Sun supports booting from the Solaris CD-ROM and reading the profile information from a floppy disk.  If this fits your needs then it might be the way to go since it is significantly easier than creating JumpStart Disks.  This process is described in the Solaris Advanced Installation Guide.

Fundamentally what we're going to do is to take all of the files that a machine doing a standard JumpStart would normally get from servers over the network and copy them onto a 2 GB or larger external disk.  The boot process is modified so that it mounts slices from the external disk instead of making NFS mounts over the network.

Knowing what scripts perform which tasks as a Sun boots during a JumpStart is essential to understanding what changes need to be made for a JumpStart Disk.  As such, that will be the first thing I cover.  I'll then cover how I setup the slices on the JumpStart Disk.  Then I'll cover the changes I made to the boot scripts and my reasons for doing it the way I did.

Note that my description of the booting process is not applicable to a general Solaris boot.  The JumpStart root image is significantly different from the root image on a Solaris machine.
 

Solaris JumpStart Boot Scripts

As with most (all?) Unicies, the kernel fires up a program called init to boot the system.  Init gets its configuration from /etc/inittab.  Init's operation is based around run levels.  To quote from the init man page:
At any given time, the system is in one of eight possible run levels.  A run level is a software configuration under which only a selected group of processes exists.
See the init(1M) man page for more information about the theory and operation of init.  For our purposes it is sufficient to know that when booting with the JumpStart root image the default run level is level 2.  Init first runs /sbin/rcS.  This script performs a number of basic steps. Note that with Solaris 2.5.1 and earlier /usr and /var are symlinks to directories in the CDROM image.  In Solaris 2.6 /sbin/rcS does a loopback mount of the full /usr in the CDROM image onto /usr.  Thus it is essential that the mount of the CDROM image succeed, even if you are using QuickJump and don't otherwise need the CDROM image.

Some further explaination of some of the steps above is warranted.  First is the step where it configures the network interfaces.  rcS runs ifconfig with the auto-revarp parameter which tells ifconfig to use RARP to get the IP addresses for each interface.  Next is the step where rcS configures the hostname, domainname and routing.  To do that rcS runs a program called /sbin/hostconfig with a parameter which tells hostconfig to use bootparams to get that information.  See the hostconfig(1M) man page for more info.  Next rcS configures all of the network interfaces with the appropriate netmask.  It gets the netmask from /netmask which according to the comments in rcS is setup by setup_install_server.  Lastly is the step where rcS figures out where to mount the CDROM image from.  If the root directory was mounted via NFS then rcS runs a program called /sbin/bpgetfile which makes a bootparams request for the install entry from bootparams and rcS mounts that.  If the root directory was mounted via UFS or HSFS (disk or cdrom) then rcS tries to mount slice 0 of whatever device the root filesystem was mounted from.

Init then runs /sbin/rc2.  In the JumpStart root image rc2 does not do anything.

Init then runs /sbin/startup.  Startup sets things up so that Openwindows will startup and run /sbin/sysconfig and then startup starts Openwindows.

/sbin/sysconfig runs sysidnet, sysidnis and sysidsys.  See the man page for these programs (they share a common man page) for more information but suffice it to say that all three programs expect you to have a working network connection, a NIS server on your subnet, etc.  sysconfig then execs /sbin/suninstall.

/sbin/suninstall is the main JumpStart script.  It is quite large and I am not going to try to describe everything it does.  However, its first step is important to us.  The first thing that suninstall does is run a script called /usr/sbin/install.d/profind.  Profind is responsible for mounting up the profile directory.  Profind first tries to mount the floppy drive as the profile directory.  If that fails then it calls /sbin/bpgetfile asking it for the install_config entry from bootparams.  Profind then tries to mount whatever path it got back from bpgetfile.

How we setup the JumpStart Disk

Ok, now that we know what the JumpStart boot scripts normally do I'm going to explain how we're going to setup the slices
on the JumpStart Disk.
 
Slice What goes there Size (MB)
0 sun4u root image 150
1 sun4m root image 150
3 dump images ~1200
4 profile directory 5
5 function directory 5
6 CDROM image 450
7 logs and saved files 10
Although the sun4m and sun4u root images are exactly the same, we need seperate partitions for the two in order to install seperate sun4m and sun4u boot blocks.  With Solaris 2.5.1 we only need about 30 MB for the root images, but with Solaris 2.6 we will need about 115 MB.  I made the root image slices large enough to accomodate either.  Slice 3 (the dump images for QuickJump) is approximate because we make that slice the remaining free space on the disk.  So on a 2.1 GB disk it is about 1200 MB.  On a 4.2 GB disk it will be about 3300 MB.  For slice 4, the CDROM image, we need about 390 MB for Solaris 2.5.1 and 335 MB for Solaris 2.6.

The JumpStart Disk thus contains all of the things we would normally mount up from the network during a JumpStart.

Pick a SCSI id for the disk that isn't in use on any of the machines that you wish to JumpStart, as we will be hardcoding the id in some scripts.  sun4m machines use ids 3 and 1 for their internal disks.  sun4u machines use ids 0 and 1 for internal disks.  Thus id 2 or id 4 might be good choices.

Modifications to Boot Scripts

As you've probably gathered by now, we need to make a few changes to the boot scripts in order to get this process to succeed on a machine which does not have any services available on its subnet.

The /sbin/rcS script is where we need to make our first changes.  rcS normally uses a program called /sbin/bpgetfile to make bootparams requests to figure out a lot of the information it needs to perform the steps above.  Also, when rcS configures the network interfaces it tells ifconfig to use RARP to get the IP addresses.  The assumption with the JumpStart Disk is that we are on a network without these services.  Since we won't be using any services on the network it is not important if the interfaces are configured incorrectly, etc.  However, it is important that the CDROM image be mounted from the right place.  So we insert a bit of code to force rcS to mount /cdrom from slice 6 on the external disk.  That code is inserted just above the call to mount.  With Solaris 2.5.1_1197 the mount call is at line 420 of rcS.  The code that we insert is:

Usrtype="ufs"
mnt_opts="ro"
Usrfs="/dev/dsk/c0t4d0s6"

/sbin/sysconfig is where we need to make our next change.  As I mentioned above sysconfig runs three programs (sysidnet, sysidnis and sysidsys), all of which expect to have services available on the local subnet.  Again, we don't need NIS or other things to be configured for our JumpStart to proceed when using a JumpStart Disk so we comment out the calls to these three programs.  However, we do want to set the correct hostname and IP address for the machine because these settings need to be stored on the machine after we restore the dump images.  The restore function in the finish script gets the hostname by running uname -n and the IP address by doing an ifconfig of the main network interface and looking for the inet entry.  Since setting these things up is what sysconfig would normally do I decided to put my code for setting them up in sysconfig.  It also allows the user to enter these things fairly early in the JumpStart and then leave the machine alone while it finishes.  If we just modified the restore function to ask for this information it would require that the user babysit the JumpStart until it gets to that point.  I added this code just after the commented out call to sysidsys but frankly it could go anywhere.  Adding it at the end of the file might make more sense (above the exec of suninstall of course).

# ----------------------------------------------------

# Figure out which network interface to use
GETIF=`ifconfig -a | grep le`
STATUS=$?
if [ $STATUS -eq 0 ]
then
    IF=`echo $GETIF | awk -F: '{ print $1 }'| head -1`
else
    GETIF=`ifconfig -a | grep hme`
    STATUS=$?
    if [ $STATUS -eq 0 ]
    then
        IF=`echo $GETIF | awk -F: '{ print $1 }'| head -1`
    else
        echo
        echo "ERROR:  Could not establish the interface name!!"
    fi
fi

correct=0
while [ $correct != 1 ]
do
    echo "Enter hostname: \c"
    read hostname
    echo "Enter IP address: \c"
    read ipaddr

    echo
    echo "You entered:"
    echo "Hostname:  $hostname"
    echo "IP:  $ipaddr"

    echo "Correct? [y/n] \c"
    read response
    if [ $response = "y" -o $response = "yes" ]; then
        correct=1
    fi
done

# Set hostname
uname -S $hostname
# Set IP address
ifconfig $IF $ipaddr

# -------------------------------------------------------------------

Note that the changes to /sbin/rcS and /sbin/sysconfig need to be made to the root images on both slice 0 and slice 1.

The last change we need to make is to /usr/sbin/install.d/profind.  As mentioned above, profind is responsible for locating and mounting the profile directory.  To do so it normally makes a bootparams request for the install_config bootparams entry for the host and mounts that directory.  We modify profind to just mount slice 4 from the JumpStart Disk.  First we insert the following function after the floppy, bootparams and cdrom functions already in the file.

qjd ()
{
    PROFILE_DISK=/dev/dsk/c0t4d0s4
    mount -F ufs -o ro ${PROFILE_DISK} ${SI_CONFIG_DIR} >/dev/null 2>&1
    if [ $? -eq 0 ]; then
        verify_config ${PROFILE_DISK} ${PROFILE_DISK}
    fi
}

Then near the bottom of the file we comment out the calls to the floppy, bootparams and cdrom functions and replace those with a call to our function.

# Search for profiles in the order:
#   floppy   (Custom JumpStart)
#   network  (Custom JumpStart)
#   cdrom    (Factory JumpStart)
#floppy
#if [ ${ESTATUS} = 1 ]; then
#    bootparams
#    if [ ${ESTATUS} = 1 ]; then
#   cdrom
#    fi
#fi

qjd
 

Creating JumpStart Disks

By now we have enough information to create a JumpStart Disk by hand.  However, doing so is not the most efficient or foolproof way of creating them.  I have setup JumpStart profiles to create them automatically, which is very handy in environments where more than one will be needed.

Acknowledgements

This concept was originally conceived by Mike Diaz of Sun Professional Services.  I and other members of Collective Technologies have since further developed the process.