rc.initdiskless revision 118638
11195Srgrimes#!/bin/sh 250472Speter# 337Srgrimes# Copyright (c) 1999 Matt Dillon 4156813Sru# All rights reserved. 5156813Sru# 6156813Sru# Redistribution and use in source and binary forms, with or without 738103Speter# modification, are permitted provided that the following conditions 873251Sgshapiro# are met: 938103Speter# 1. Redistributions of source code must retain the above copyright 10236965Sdes# notice, this list of conditions and the following disclaimer. 11231849Seadler# 2. Redistributions in binary form must reproduce the above copyright 12231849Seadler# notice, this list of conditions and the following disclaimer in the 13231849Seadler# documentation and/or other materials provided with the distribution. 14231849Seadler# 15231849Seadler# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16231849Seadler# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17231849Seadler# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18231849Seadler# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19231849Seadler# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20231849Seadler# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21231849Seadler# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22231849Seadler# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23231849Seadler# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24231849Seadler# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25253853Sjlh# SUCH DAMAGE. 26231849Seadler# 27231849Seadler# $FreeBSD: head/etc/rc.initdiskless 118638 2003-08-07 21:06:32Z fjoe $ 28231849Seadler# 29231849Seadler# PROVIDE: initdiskless 30231849Seadler# KEYWORD: FreeBSD 31231849Seadler 32231849Seadler 33231849Seadler# On entry to this script the entire system consists of a read-only root 34231849Seadler# mounted via NFS. We use the contents of /conf to create and populate 35231849Seadler# memory filesystems. The kernel has run BOOTP and configured an interface 36231849Seadler# (otherwise it would not have been able to mount the NFS root!) 37231849Seadler# 38231849Seadler# The following directories are scanned. Each sucessive directory overrides 39231849Seadler# (is merged into) the previous one. 40231849Seadler# 41231849Seadler# /conf/base universal base 42231849Seadler# /conf/default modified by a secondary universal base 43231849Seadler# /conf/${ipba} modified based on the assigned broadcast IP 44231849Seadler# /conf/${ip} modified based on the machine's assigned IP 45231849Seadler# 46231849Seadler# Each of these directories may contain any number of subdirectories which 47231849Seadler# represent directories in / on the diskless machine. The existance of 48231849Seadler# these subdirectories causes this script to create a MEMORY FILESYSTEM for 49231849Seadler# /<sub_directory_name>. For example, if /conf/base/etc exists then a 50231849Seadler# memory filesystem will be created for /etc. 51231849Seadler# 52155210Srwatson# If a subdirectory contains the file 'diskless_remount' the contents of 53255385Sdes# the file is used to remount the subdirectory prior to it being copied to 54255385Sdes# the memory filesystem. For example, if /conf/base/etc/diskless_remount 55255385Sdes# contains the string 'my.server.com:/etc' then my.server.com:/etc will be 56255385Sdes# mounted in place of the subdirectory. This allows you to avoid making 57199249Sed# duplicates of system directories in /conf. 58199249Sed# 59209134Simp# If a subdirectory contains the file 'md_size', the contents of the 60209134Simp# file is used to determine the size of the memory filesystem, in 512 61209134Simp# byte sectors. The default is 8192 (4MB). You only have to specify an 62209134Simp# md_size if the default doesn't work for you (i.e. if it is too big or 63199249Sed# too small). Note that in -current the default is 4096 (2MB). For 64209134Simp# example, /conf/base/etc/md_size might contain '16384'. 65199249Sed# 66199249Sed# If /conf/<special_dir>/SUBDIR.cpio.gz exists, the file is cpio'd into 67155210Srwatson# the specified /SUBDIR (and a memory filesystem is created for /SUBDIR 68155210Srwatson# if necessary). 69155210Srwatson# 70155210Srwatson# If /conf/<special_dir>/SUBDIR.remove exists, the file contains a list 71155210Srwatson# of paths which are rm -rf'd relative to /SUBDIR. 72155210Srwatson# 73155210Srwatson# You will almost universally want to create a /conf/base/etc containing 74155210Srwatson# a diskless_remount and possibly an md_size file. You will then almost 75183242Ssam# universally want to override rc.conf, rc.local, and fstab by creating 76183242Ssam# /conf/default/etc/{rc.conf,rc.local,fstab}. Your fstab should be sure 77183242Ssam# to mount a /usr... typically an NFS readonly /usr. 78183242Ssam# 79183242Ssam# NOTE! rc.diskless2 will create /var, /tmp, and /dev. Those filesystems 80183242Ssam# should not be specified in /conf. At least not yet. 81183242Ssam 82183242Ssamdlv=`/sbin/sysctl -n vfs.nfs.diskless_valid 2> /dev/null` 83183242Ssam[ ${dlv:=0} -eq 0 ] && exit 0 84183242Ssam 85183242Ssam# chkerr: 86183242Ssam# 87183242Ssam# Routine to check for error 88183242Ssam# 89183242Ssam# checks error code and drops into shell on failure. 90183242Ssam# if shell exits, terminates script as well as /etc/rc. 91183242Ssam# 92183242Ssamchkerr() { 93183242Ssam case $1 in 94183242Ssam 0) 95183242Ssam ;; 96183242Ssam *) 97156813Sru echo "$2 failed: dropping into /bin/sh" 98183242Ssam /bin/sh 99121911Smarkm # RESUME 10037Srgrimes ;; 101183242Ssam esac 102183242Ssam} 103158115Sume 104158115Sume# Create a generic memory disk 105193635Sedwin# 106193635Sedwinmount_md() { 107193635Sedwin /sbin/mdmfs -i 4096 -s $1 -M md $2 108193635Sedwin} 109156813Sru 11057488Speter# Create the memory filesystem if it has not already been created 11174837Sgreen# 112124214Sdescreate_md() { 11357459Smarkm if [ "x`eval echo \\$md_created_$1`" = "x" ]; then 114156813Sru if [ "x`eval echo \\$md_size_$1`" = "x" ]; then 11560677Skris md_size=4096 11660677Skris else 11760677Skris md_size=`eval echo \\$md_size_$1` 118183242Ssam fi 119183242Ssam mount_md $md_size /$1 120183242Ssam /bin/chmod 755 /$1 121183242Ssam eval md_created_$1=created 122183242Ssam fi 123183242Ssam} 124183242Ssam 125183242Ssam# DEBUGGING 126183242Ssam# 127183242Ssam# set -v 128183242Ssam 129183242Ssam# Figure out our interface and IP. 130184343Ssam# 131184343Ssambootp_ifc="" 132184343Ssambootp_ipa="" 133184343Ssambootp_ipbca="" 134183268Ssamiflist=`ifconfig -l` 135183268Ssamfor i in ${iflist} ; do 136183268Ssam set `ifconfig ${i}` 137183268Ssam while [ $# -ge 1 ] ; do 13882521Salex if [ "${bootp_ifc}" = "" -a "$1" = "inet" ] ; then 139108002Sgreen bootp_ifc=${i} ; bootp_ipa=${2} ; shift 140147Srgrimes fi 141196767Sflz if [ "${bootp_ipbca}" = "" -a "$1" = "broadcast" ] ; then 142156813Sru bootp_ipbca=$2; shift 14395144Sgshapiro fi 14495144Sgshapiro shift 145156813Sru done 146135851Sdougb if [ "${bootp_ifc}" != "" ] ; then 147156813Sru break 148135851Sdougb fi 149135851Sdougbdone 150135851Sdougbecho "Interface ${bootp_ifc} IP-Address ${bootp_ipa} Broadcast ${bootp_ipbca}" 151251512Semaste 152251512Semaste# Figure out our NFS root path 153251512Semaste# 15499451Sruset `mount -t nfs` 15599451Sruwhile [ $# -ge 1 ] ; do 15699451Sru if [ "$2" = "on" -a "$3" = "/" ]; then 157156813Sru nfsroot="$1" 158117292Sgshapiro break 159117292Sgshapiro fi 16064598Sgshapiro shift 16164598Sgshapirodone 162117292Sgshapiro 16337Srgrimes# Resolve templates in /conf/base, /conf/default, /conf/${bootp_ipbca}, 164263Srgrimes# and /conf/${bootp_ipa}. For each subdirectory found within these 16599449Sru# directories: 166263Srgrimes# 167245825Sbrooks# - calculate memory filesystem sizes. If the subdirectory (prior to 168245825Sbrooks# NFS remounting) contains the file 'md_size', the contents specified 169245825Sbrooks# in 512 byte sectors will be used to size the memory filesystem. Otherwise 170124831Sru# 8192 sectors (4MB) is used. 171156813Sru# 172173135Syar# - handle NFS remounts. If the subdirectory contains the file 173124831Sru# diskless_remount, the contents of the file is NFS mounted over 174124831Sru# the directory. For example /conf/base/etc/diskless_remount 1754487Sphk# might contain 'myserver:/etc'. NFS remounts allow you to avoid 176173135Syar# having to dup your system directories in /conf. Your server must 177173135Syar# be sure to export those filesystems -alldirs, however. 1785948Sjkh# If the diskless_remount file contains a string beginning with a 179142794Sru# '/' it is assumed that the local nfsroot should be prepended to 180142794Sru# it before attemping to the remount. This allows the root to be 181152471Sru# relocated without needing to change the remount files. 182152471Sru# 183142794Srufor i in base default ${bootp_ipbca} ${bootp_ipa} ; do 184152471Sru for j in /conf/$i/* ; do 185152471Sru # memory filesystem size specification 186142794Sru # 187149515Simp subdir=${j##*/} 188149515Simp if [ -d $j -a -f $j/md_size ]; then 189142794Sru eval md_size_$subdir=`cat $j/md_size` 190142794Sru fi 191246097Sbrooks 192246097Sbrooks # NFS remount 193246097Sbrooks # 194246097Sbrooks if [ -d $j -a -f $j/diskless_remount ]; then 1954487Sphk nfspt=`/bin/cat $j/diskless_remount` 196148282Sru if [ `expr "$nfspt" : '\(.\)'` = "/" ]; then 197148282Sru nfspt="${nfsroot}${nfspt}" 198148282Sru fi 199148282Sru mount_nfs $nfspt $j 20099449Sru chkerr $? "mount_nfs $nfspt $j" 201100872Sru fi 20299451Sru done 203142794Srudone 204100872Sru 20599451Sru# - Create all required MFS filesystems and populate them from 206100872Sru# our templates. Support both a direct template and a dir.cpio.gz 207184343Ssam# archive. Support dir.remove files containing a list of relative 208205329Sed# paths to remove. 209205335Sed# 210205329Sed# TODO: 211184343Ssam# + find a way to assign a 'group' identifier to a machine 212184443Smp# so we can use group-specific configurations; 213184343Ssam 214184343Ssamfor i in base default ${bootp_ipbca} ${bootp_ipa} ; do 215184343Ssam for j in /conf/$i/* ; do 216246097Sbrooks subdir=${j##*/} 217246097Sbrooks if [ -d $j ]; then 218246097Sbrooks create_md $subdir 219246097Sbrooks cp -Rp $j/* /$subdir 220246097Sbrooks fi 221246097Sbrooks done 222246097Sbrooks for j in /conf/$i/*.cpio.gz ; do 223246097Sbrooks subdir=${j%*.cpio.gz} 224241823Smarcel subdir=${subdir##*/} 225241823Smarcel if [ -f $j ]; then 226241823Smarcel create_md $subdir 227183242Ssam echo "Loading /$subdir from cpio archive $j" 228173135Syar (cd / ; /stand/gzip -d < $j | /stand/cpio --extract -d ) 229183242Ssam fi 230173135Syar done 231186249Sthompsa for j in /conf/$i/*.remove ; do 232173135Syar subdir=${j%*.remove} 233173135Syar subdir=${subdir##*/} 234173135Syar if [ -f $j ]; then 235173135Syar # doubly sure it is a memory disk before rm -rf'ing 236173135Syar create_md $subdir 237173135Syar (cd /$subdir; rm -rf `/bin/cat $j`) 238173135Syar fi 239155210Srwatson done 240155210Srwatsondone 241155571Srwatson 242155210Srwatson