New Fedora Diskless init script
From MythTV Official Wiki
Author | unknown |
Description | New Fedora Diskless init script |
Supports |
#!/bin/bash # # disklessrc file for initrd (Initial Ram Disk) # # Copyright (C) 2003 Daniel Walsh <dwalsh@redhat.com> # # Copyright (C) 2005, 2006 Jason Vas Dias <jvdias@redhat.com> (Red Hat Inc.) # # Taken in part from James A. McQuillan <jam@McQuil.Com> linuxrc for LTSP # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # export LD_LIBRARY_PATH=/lib:/usr/lib:/usr/kerberos/lib MODULE="" PCICLASS="0200 0280 0680" # # This function is used to load the ETHERNET module # loadmodules() { for MODULE in $1; do { echo -n "Loading $MODULE module... " if ! `grep "^$MODULE[ \ ]" /proc/modules > /dev/null`; then if modprobe $MODULE; then echo " Loaded $MODULE OK." ; else e=$? echo "Module $MODULE load failed: $e"; return $e; fi; else echo "module already loaded" fi } done return 0; } # # This function is used to find the correct module for hardware # devices of PCI Class ID arguments that are on the PCI bus: # findModules() { matchClasses=(${1}) (/sbin/lspci -n | sed 's/Class\ //' | while read id class vendev rev; # pciutils < 2.2 inserts 'Class' as 2nd string; >= 2.2 does not :-( do class=${class%:} if [ ${#matchClasses[@]} -gt 0 ]; then found=0 for matchClass in ${matchClasses[@]}; do [ ${matchClass} = ${class} ] && found=1; done; [ $found -eq 0 ] && continue; fi; vendor='0x'"`printf '%8s' ${vendev%:*} | /sbin/sed 's/ /0/g'`" device='0x'"`printf '%8s' ${vendev#*:} | /sbin/sed 's/ /0/g'`" (/sbin/grep '[^# ][^# ]*[\ \ ][\ \ ]*'$vendor'[\ \ ]'$device /lib/modules/`/sbin/uname -r`/modules.pcimap) | (while read m rest; do echo $m; done) done ) | /sbin/uniq } # # This function is used to load the correct ETHERNET modules # findhardware() { no_modules=13 findModules "$PCICLASS" | while read MODULE; do echo "Found Ethernet Card Module: $MODULE" loadmodules $MODULE && no_modules=0 ; done return $no_modules; } # # This function is used to mount files/directories from the snapshot directory # over the root directory. # mountfile () { snapshotfile=/mnt/.snapshot/${2}${1} dir=`dirname $snapshotfile` # # Check if file already exists in snapshot directory. If not attempt to copy # from root directory to snapshot directory. # if [ ! -e $snapshotfile ]; then mkdir -p $dir echo "${1} missing from client specific area." if [ -e /mnt/${1} ] ; then echo "Copying ${1}" rsync -a /mnt/${1} $snapshotfile else echo "Creating ${1}" touch $snapshotfile fi else # If dev directory already exists in snapshot directory, check if the root # /dev directory is newer. If it is rsync the root directory over the # snapshot directory. if [ ${1} == "/dev" -a ${1} -nt ${dir}/dev ]; then echo "RSYNC-ing /dev"; rsync -a /mnt/${1} $snapshotfile fi fi # # Mount the snapshotfile over the root file so the client will have r/w access # mount -n -o bind /mnt/.snapshot/${2}${1} /mnt/${1} } echo "===============================================================================" echo "Running /disklessrc" echo "Mounting /proc" /bin/mount -n -t proc /proc /proc if [ "${INITRD_DBG}" = "1" ]; then exec /bin/bash; fi if [ -w /proc/progress ]; then echo 40 "Detecting network card" >/proc/progress; fi if [ -z "${ETHERNET}" ]; then export ETHERNET="eth0"; fi # # Bring up the loopback interface first to avoid RHEL-4-U2's kernel-2.6.9-12.2.EL # getting an Oops panic later on when the IPv6 module is loaded # /sbin/ifconfig lo 127.0.0.1 netmask 255.0.0.0 up # # Attempt to find and load the network card module # findhardware "$PCICLASS" # # load the NFS module # if [ ! -d /proc/sys/fs/nfs ]; then loadmodules nfs if [ $? -ne 0 ]; then exec /bin/bash; fi; fi; # Mount initrd root rw, and mount /tmp echo "Mounting /" mount -n -o remount,rw / mount -n -t tmpfs /dev/shm /tmp if [ "${INITRD_DBG}" = "2" ]; then exec /bin/bash; fi # # Setup dhclient to retrieve IP address # cat <<EOF >/tmp/dhclient.conf interface "$ETHERNET" { request subnet-mask, broadcast-address, routers, domain-name, domain-name-servers, host-name, root-path; } EOF # # dhclient runs as a daemon. Once it acquires the info from the # server, it runs a script called /sbin/dhclient-script. That script # will take care of configuring the interface. # if [ "${INITRD_DBG}" = "3" ]; then exec /bin/bash; fi if [ -w /proc/progress ]; then echo 50 "Sending DHCP request" >/proc/progress; fi # Ensure host/domain name are set to '' before running dhclient /sbin/hostname '(none)' # for network_functions' need_hostname() /sbin/domainname '' # Run dhclient - # dhclient MAY set hostname and domainname if sent in DHCP options by server # echo "Running dhclient" /bin/dhclient -1 -cf /tmp/dhclient.conf -pf /tmp/dhclient.pid -lf /tmp/dhclient.leases $ETHERNET >/tmp/dhclient.out 2>&1 if [ $? -ne 0 ]; then exec /bin/bash if [ -w /proc/progress ]; then echo f >/proc/progress; fi echo cat /tmp/dhclient.out echo echo "ERROR! dhclient failed!" echo exit 1 fi # wait for some time for dhclient to create the resolv.conf file; otherwise # hostname lookup is pretty pointless, and we may end up doing the pivot_root # BEFORE dhclient creates the resolv.conf file :-) t=0 while [ "$t" -lt 20 ] && [ ! -e /etc/resolv.conf ]; do sleep 1; ((t=t+1)); done # if [ ! -e /etc/resolv.conf ]; then echo '********' echo 'WARNING: /etc/resolv.conf not created - DNS service unavailable.'; echo '********' fi; # Set up the hostname, domainname and SNAPSHOT name for the diskless client: # hname=`/bin/hostname` dhhname="${hname}" dname=`/bin/domainname` if [ "${hname}" = '(none)' ]; then /sbin/hostname ''; hname=''; else echo "DHCP host-name option received: $hname"; fi IP=`/sbin/ip addr show ${ETHERNET} scope global primary | grep '^[\ \ ]*inet.*scope global '${ETHERNET} | sed 's/^.*inet\ //;s/[\/\ ].*$//'`; if [ -z "${hname}" ]; then if dnsptr=`(/sbin/host $IP 2>/dev/null || echo '';) | /sbin/grep 'domain name pointer' | /sbin/tail -n 1`; then hname=${dnsptr//*\ }; hname=${hname%.}; elif [ -n "${SNAPSHOT}" ]; then hname=${SNAPSHOT}; elif [ -n "$IP" ]; then hname=${IP}; echo "WARNING: no DNS PTR record found for $IP and no host-name set with DHCP"; else echo "ERROR! No IP address obtained and no SNAPSHOT= setting."; echo; exit 1; fi; fi; if [ -n "${hname}" ] && [ -z "${SNAPSHOT}" ]; then SNAPSHOT=${hname} elif [ -z "${SNAPSHOT}" ]; then SNAPSHOT=${IP} fi; if [ -n "${hname}" ]; then if [[ $hname = *\.* ]]; then if [ -z "${dname}" ] && [ -z "${NISDOMAIN}" ]; then # "nis-domain" dhcp option NOT sent. if [ ${hname} != ${IP} ]; then dname=${hname#*\.} else # hostname was IP address. # set domainname to proper dns reverse IP domain name dname=${hname%\.*} IFS='.' octs=($dname) unset IFS dname='' for oct in ${octs[@]}; do dname="$oct.$dname"; done dname="${dname}in-addr.arpa." fi; if [ -n "${dname}" ] ; then /sbin/domainname ${dname} echo "Domain Name set to ${dname}" fi; fi; if [ "${NISDOMAIN}" = '(none)' ]; then unset NISDOMAIN; fi if [ ${hname} != ${IP} ]; then hname=${hname%%\.*}; else hname=${hname##*\.}; fi; fi; if [ "${hname}" != "${dhhname}" ]; then /sbin/hostname ${hname}; echo "Host Name set to ${hname}" fi; fi; # # Mount the NFS root-path from the diskless server # if [ "${INITRD_DBG}" = "4" ]; then exec /bin/bash; fi if [ -z "${NFSROOT}" ]; then if [ -w /proc/progress ]; then echo f >/proc/progress; fi echo echo "ERROR! No root-path. Check your DHCP configuration, to make" echo " sure that the 'option root-path' is specified" echo exit 1 fi NFS_IP=` echo ${NFSROOT} | cut -d : -f 1` NFS_DIR=`echo ${NFSROOT} | cut -d : -f 2` if [ -w /proc/progress ]; then echo 55 "Mounting root filesystem" >/proc/progress; fi echo "Mounting root filesystem: ${NFS_DIR}/root from: ${NFS_IP}" mount -n -o nosharecache,nolock,ro,rsize=32768,async,intr ${NFS_IP}:${NFS_DIR}/root /mnt if [ $? -ne 0 ]; then if [ -w /proc/progress ]; then echo f >/proc/progress; fi echo echo "ERROR! Failed to mount the root directory via NFS!" echo " Possible reasons include:" echo echo " 1) NFS services may not be running on the server" echo " 2) Workstation IP does not map to a hostname, either" echo " in /etc/hosts, or in DNS" echo " 3) Wrong address for NFS server in the DHCP config file" echo " 4) Wrong pathname for root directory in the DHCP config file" echo exit 1 fi if [ "${INITRD_DBG}" = "5" ]; then exec /bin/bash; fi export LD_LIBRARY_PATH=/mnt/usr/lib64:/mnt/usr/lib:/mnt/lib64:/mnt/lib export PATH=/mnt/usr/sbin:/mnt/usr/bin:/mnt/sbin:/mnt/bin:$PATH # # Mount the snapshot directory from the server and then mount files # in the snapshot/files file over the the shared ones # echo Mounting Snapshot directories mount -n -t nfs $NFS_IP:${NFS_DIR}/snapshot /mnt/.snapshot -o nosharecache,rw,nolock,rsize=32768,wsize=32768,async,intr && { for i in `grep -v "^#" /mnt/.snapshot/files`; do if [ -e /mnt/$i ]; then mountfile $i ${SNAPSHOT} fi; done if [ -e /mnt/.snapshot/files.custom ]; then for i in `grep -v "^#" /mnt/.snapshot/files.custom`; do if [ -e /mnt/$i ]; then mountfile $i ${SNAPSHOT} fi; done fi RELEASE=`uname -r` for i in `ls /mnt/lib/modules/$RELEASE/modules.*`; do if [ -e /mnt/$i ]; then mountfile $i ${SNAPSHOT} fi; done /mnt/sbin/ifup lo } if [ "${INITRD_DBG}" = "6" ]; then exec /bin/bash; fi # # Copy the files written by dhclient to new root: # [ -e /etc/resolv.conf ] && cp -fp /etc/resolv.conf /mnt/etc/resolv.conf 2>/dev/null [ -e /etc/yp.conf ] && cp -fp /etc/yp.conf /mnt/etc/yp.conf 2>/dev/null [ -e /etc/ntp.conf ] && cp -fp /etc/ntp.conf /mnt/etc/ntp.conf 2>/dev/null [ -e /etc/ntp/step-kickers ] && cp -fp /etc/ntp/step-tickers /mnt/etc/ntp/step-tickers 2>/dev/null # This will allow dhclient to be re-run for nfs interface by initscripts (keep_old_ip=yes): cp -fp /tmp/dhclient.leases /mnt/var/lib/dhcp/dhclient-eth0.leases 2>/dev/null cp -fp /tmp/dhclient.leases /mnt/var/lib/dhclient/dhclient-eth0.leases 2>/dev/null if [ "${INITRD_DBG}" = "7" ]; then exec /bin/bash; fi #echo "Mounting the devfs filesystem" #mount -n -t devfs /devfs /dev # # Complete the network boot by killing the dhcp client. # Umount file systems that are no longer used. # Start the init process to run the NFS Roots bootup sequence. # if [ "${INITRD_DBG}" = "8" ]; then exec /bin/bash; fi /bin/kill -TERM `cat /tmp/dhclient.pid` echo "Running /sbin/init" umount /tmp echo 0x100 > /mnt/proc/sys/kernel/real-root-dev # Some useful environment variables to stop initscripts / dhclient-script # doing silly things: export keep_old_ip=yes export fastboot=yes export READONLY=yes exec /sbin/switch_root -c /dev/console /mnt /sbin/init