adcn
script
#!/bin/bash #----------------------------------------------------------------------------- # # /usr/local/sbin/adcn # ftp://ftp.sci.usq.edu.au/pub/jacek/beowulf-utils # # Add Disk-less Client Node # # Version : 0.0.5 # # Date : 5 September 1998 # # Author : Jacek Radajewski # jacek@usq.edu.au # # Purpose : This script adds a new node to a disk-less-client Beowulf cluster. # adcn assumes Red Hat 5.0 or 5.1 and might not work on other versions # of Red Hat or other distributions of Linux . adcn uses the /tftpboot/Template # directory to create NFS root file system for the client node. # /tftpboot/Template should be created with the setup_template script, # which can be found at ftp://ftp.sci.usq.edu.au/pub/jacek/beowulf-utils # # Command line options : # # -f # Force installation even if unknown Linux release. adcn normally checks for # for version of Red Hat Linux, and if the version number is not 5.0 or 5.1 # then adcn will give up. adcn will also give up if the Linux distribution # is not Red Hat. This option ignores release and version checking. # # -i ip address # IP address of the new disk-less client node. # # -m hardware address # MAC (hardware) address of the new disk-less client node. -m is ignored when # used together with the -l option. # # -l interface # listen to RARP requests on interface and use the 'sniffed' address # as the hardware address of the new disk-less client node. # This overides -m option # # -c client name # hostname of the new disk-less client node. # You must specify first name only, not the FQDN. # For example node1 and NOT node1.beowulf.my.domain # # -d domain name # This is optional and if not specified # the DNS domain of the server will be used. # # -n netmask address of the new node. Default value is used if this is not specified # # -g gateway address. Server's IP is used as the default value if gateway is not # specified. Using # # -N network address # # -b broadcast address # # -s list supported distributions and version of Linux # # -h help # #----------------------------------------------------------------------------- show_help () { echo -e "adcn options\n" echo "[-f] : force installation even if adcn does not support this" echo " distribution of Linux or version of Red Hat Linux" echo " -i ip_address : IP Addrees of the disk-less client node" echo "[-m mac_address] : MAC or hardware address of the disk-less client node" echo " -l interface : Listen for RARP request on the interface and use the sniffed" echo " hardware address as the hardware address of client node" echo " If -m is specified with this option, given MAC address is" echo " ignored. (not implemented)" echo " -c client_name : Host name of the disk-less client node. This must the first" echo " name of the node and not the fully qualified domain name" echo "[-d domain_name] : Domain name. If not specified servers domain will be used." echo "[-n netmask] : Netmask address. If not specified the default netmask" echo " 255.255.255.0 will be used. For clusters with more than 255" echo " nodes this should be changed to 255.255.0.0" echo "[-g gateway] : Default gateway for the disk-less client node. If not" echo " specified, server node is used as the default gateway" echo "[-N net_address] : Network address" echo "[-b broadcast] : Broadcast address" echo "[-h] : This help message" echo "[-s] : List supported distributions and versions of Linux" exit 0 } # set few default values before processing command line arguments export FORCE=false export LISTEN=false export SERVER=$(/bin/hostname) export DOMAIN=$(/bin/dnsdomainname) export HOST=none export IPADDR=none export MACADDR=none export NETMASK=255.255.255.0 export BROADCAST=10.0.0.255 export NETWORK=10.0.0.0 export GATEWAY=10.0.0.1 # process command line options while getopts ":fhd:i:m:c:n:g:N:b:l:" opt; do case $opt in f ) export FORCE=true;; d ) export DOMAIN=$OPTARG;; i ) export IPADDR=$OPTARG;; m ) export MACADDR=$OPTARG;; c ) export HOST=$OPTARG;; n ) export NETMASK=$OPTARG;; g ) export GATEWAY=$OPTARG;; N ) export NETWORK=$OPTARG;; b ) export BROADCAST=$OPTARG;; l ) export L_INTERFACE=$OPTARG export LISTEN=true;; h ) show_help;; \? ) echo 'adcn -h for help' exit 1 esac done # check if everything is set if [ $HOST = 'none' ] || [ $IPADDR = 'none' ] || [ $MACADDR = 'none' ] ; then echo 'adcn -h for help' exit 1 fi # make sure that the host name is not a FQDN echo $HOST | grep "\." > /dev/null 2>&1 if [ $? = 0 ] ; then echo "Host name cannot be a fully qualified domain name. Use -d to set domain." exit 1 fi # simple and incomplete check of the MAC address if [ $(echo $MACADDR | cut -f 6 -d ":")test = "test" ] ; then echo "$MACADDR is not a valid MAC address" exit 1 fi echo "Adding $HOST.$DOMAIN - IP- $IPADDR - MAC- $MACADDR to the cluster ... " # check linux release but not if forced install # at this stage only check for Red Hat 5.0 if [ $FORCE = 'false' ] ; then if [ -f /etc/redhat-release ] ; then cat /etc/redhat-release | grep "Hurricane" > /dev/null 2>&1 if [ $? = 0 ] ; then export REDHAT=Hurricane else echo "This script might not work with Red Hat Linux $(cat /etc/redhat-release)" echo "Use -f to force installation" exit 1 fi else echo "Can't find /etc/redhat-release file." echo "Not a Red Hat Linux distribution. Giving up" echo "Use -f to force installation. Good luck." exit 1 fi fi # the location of our template # you must create template before you run this script !!! # use the setup_template script to create the template # and then customize it for your needs export TEMPLATE_DIR=/tftpboot/Template export DEST_DIR=/tftpboot/$IPADDR #umask 022 #----------------------------------------------------------------------------- # check if this IP address already exists if [ -f $DEST_DIR ] ; then echo "$DEST_DIR entry exists. Giving up." exit 1 fi # do few other checks before going ahead if [ ! -d $TEMPLATE_DIR ] ; then echo "Cannot find Template directory $TEMPLATE_DIR. Giving up." exit 1 fi #-------------------------------------------------------------------- # create the root directory for new node /bin/mkdir /tftpboot/$IPADDR # we also want the name of the new node to be a link to the real (IP address) # directory /bin/ln -sf /tftpboot/$IPADDR /tftpboot/$HOST /bin/ln -sf /tftpboot/$IPADDR /tftpboot/$HOST.$DOMAIN # create sub directories /bin/mkdir $DEST_DIR/bin /bin/mkdir $DEST_DIR/boot /bin/mkdir $DEST_DIR/dev /bin/mkdir $DEST_DIR/etc /bin/mkdir $DEST_DIR/home /bin/mkdir $DEST_DIR/lib /bin/mkdir $DEST_DIR/mnt /bin/mkdir $DEST_DIR/proc /bin/mkdir $DEST_DIR/root /bin/mkdir $DEST_DIR/sbin /bin/mkdir $DEST_DIR/tmp /bin/mkdir $DEST_DIR/usr /bin/mkdir $DEST_DIR/var /bin/chmod 777 $DEST_DIR/tmp echo "Building NFS root file system ..." #----------------------------------------------------------------------------- # we now create the files in all of the directories # we make hard links to files in our Template directory #----------------------------------------------------------------------------- #----------------------------------------------------------------------------- # /bin echo -n " /bin " cd $TEMPLATE_DIR/bin for directory in $(/usr/bin/find . -not -name '.' -type d) ; do /bin/mkdir $DEST_DIR/bin/$directory done for file in $(/usr/bin/find . -type f -maxdepth 1 -follow) ; do /bin/ln $TEMPLATE_DIR/bin/$file $DEST_DIR/bin/$file done #----------------------------------------------------------------------------- # /boot echo -n " /boot " cd $TEMPLATE_DIR/boot for directory in $(/usr/bin/find . -not -name '.' -type d) ; do /bin/mkdir $DEST_DIR/boot/$directory done for file in $(/usr/bin/find . -type f -maxdepth 1) ; do /bin/ln $TEMPLATE_DIR/boot/$file $DEST_DIR/boot/$file done #----------------------------------------------------------------------------- # /dev #----------------------------------------------------------------------------- echo -n " /dev " cd $TEMPLATE_DIR/dev # Linking of devices is still very shaky. There are problems # with linking /dev/fd, /dev/stdin, /dev/stderr, and /dev/stdout # directories. These are done manually. /bin/ln -sf ../proc/self/fd $DEST_DIR/dev/fd /bin/ln -f $TEMPLATE_DIR/dev/stdin $DEST_DIR/dev/stdin /bin/ln -f $TEMPLATE_DIR/dev/stdout $DEST_DIR/dev/stdout /bin/ln -f $TEMPLATE_DIR/dev/stderr $DEST_DIR/dev/stderr for directory in $(/usr/bin/find . -not -name '.' -type d) ; do /bin/mkdir $DEST_DIR/dev/$directory done # link files block, character, then normal files (e.g. MAKEDEV) for file in $(/usr/bin/find . -type c -follow -mount) ; do /bin/ln -fd $TEMPLATE_DIR/dev/$file $DEST_DIR/dev/$file done for file in $(/usr/bin/find . -type b -follow -mount) ; do /bin/ln -fd $TEMPLATE_DIR/dev/$file $DEST_DIR/dev/$file done for file in $(/usr/bin/find . -type f -follow -mount) ; do /bin/ln -fd $TEMPLATE_DIR/dev/$file $DEST_DIR/dev/$file 2>/dev/null done #----------------------------------------------------------------------------- # /etc #----------------------------------------------------------------------------- echo -n " /etc " cd $TEMPLATE_DIR/etc for directory in $(/usr/bin/find . -not -name '.' -type d) ; do /bin/mkdir $DEST_DIR/etc/$directory done for file in $(/usr/bin/find . -type f -follow) ; do /bin/ln -f $TEMPLATE_DIR/etc/$file $DEST_DIR/etc/$file done #----------------------------------------------------------------------------- # /lib #----------------------------------------------------------------------------- echo -n " /lib " cd $TEMPLATE_DIR/lib for file in $(/usr/bin/find . -type f -follow -maxdepth 1) ; do /bin/ln -f $TEMPLATE_DIR/lib/$file $DEST_DIR/lib/$file done #----------------------------------------------------------------------------- # /root #----------------------------------------------------------------------------- echo -n " /root " cd $TEMPLATE_DIR/root for file in $(/usr/bin/find . -type f -maxdepth 1) ; do /bin/ln -f $TEMPLATE_DIR/root/$file $DEST_DIR/root/$file done #----------------------------------------------------------------------------- # /sbin #----------------------------------------------------------------------------- echo -n " /sbin " cd $TEMPLATE_DIR/sbin for directory in $(/usr/bin/find . -not -name '.' -type d -follow) ; do /bin/mkdir $DEST_DIR/sbin/$directory done for file in $(/usr/bin/find . -type f -follow) ; do /bin/ln -f $TEMPLATE_DIR/sbin/$file $DEST_DIR/sbin/$file done #----------------------------------------------------------------------------- # /var #----------------------------------------------------------------------------- echo -n " /var " cd $TEMPLATE_DIR/var for directory in $(/usr/bin/find . -not -name '.' -type d -follow) ; do /bin/mkdir $DEST_DIR/var/$directory done for file in $(/usr/bin/find . -type f -follow -mount) ; do /bin/ln $TEMPLATE_DIR/var/$file $DEST_DIR/var/$file done #----------------------------------------------------------------------------- # Now we create network configuration files for the node # First we remove all existing configuration scripts #----------------------------------------------------------------------------- echo -e "\nCreating network scripts ..." # clean up ... /bin/rm -f $DEST_DIR/etc/sysconfig/network /bin/rm -f $DEST_DIR/etc/sysconfig/network-scripts/ifcfg-eth* # /etc/HOSTNAME echo "$HOST.$DOMAIN" > $DEST_DIR/etc/HOSTNAME # create client's /etc/sysconfig/network echo "NETWORKING=yes" \ >> $DEST_DIR/etc/sysconfig/network echo "HOSTNAME=$HOST.$DOMAIN" \ >> $DEST_DIR/etc/sysconfig/network echo "DOMAINNAME=$DOMAIN" \ >> $DEST_DIR/etc/sysconfig/network echo "GATEWAY=$GATEWAY" \ >> $DEST_DIR/etc/sysconfig/network echo "GATEWAYDEV=eth0" \ >> $DEST_DIR/etc/sysconfig/network #----------------------------------------------------------------------------- # create client's /etc/sysconfig/network-scripts/ifcfg-eth0 # if you have more than one interface per node you will have # to add/change script #----------------------------------------------------------------------------- echo "DEVICE=eth0" \ >> $DEST_DIR/etc/sysconfig/network-scripts/ifcfg-eth0 echo "IPADDR=$IPADDR" \ >> $DEST_DIR/etc/sysconfig/network-scripts/ifcfg-eth0 echo "NETMASK=$NETMASK" \ >> $DEST_DIR/etc/sysconfig/network-scripts/ifcfg-eth0 echo "NETWORK=$NETWORK" \ >> $DEST_DIR/etc/sysconfig/network-scripts/ifcfg-eth0 echo "BROADCAST=$BROADCAST" \ >> $DEST_DIR/etc/sysconfig/network-scripts/ifcfg-eth0 echo "ONBOOT=yes" \ >> $DEST_DIR/etc/sysconfig/network-scripts/ifcfg-eth0 echo "BOOTPROTO=none" \ >> $DEST_DIR/etc/sysconfig/network-scripts/ifcfg-eth0 #----------------------------------------------------------------------------- # add the RARP entry # Our server will use this to anwser client's RARP request and tell it # it's IP address #----------------------------------------------------------------------------- /sbin/rarp -s $HOST $MACADDR echo "/sbin/rarp -s $HOST $MACADDR" >> /etc/rc.d/init.d/rarp #----------------------------------------------------------------------------- # add the new machine to /etc/exports #----------------------------------------------------------------------------- echo "/tftpboot/$IPADDR/ $HOST.$DOMAIN (rw,no_all_squash,no_root_squash)" >> /etc/exports echo "/usr $HOST.$DOMAIN (rw,no_all_squash,no_root_squash)" >> /etc/exports echo "/bin $HOST.$DOMAIN (rw,no_all_squash,no_root_squash)" >> /etc/exports echo "/sbin $HOST.$DOMAIN (rw,no_all_squash,no_root_squash)" >> /etc/exports echo "/lib $HOST.$DOMAIN (rw,no_all_squash,no_root_squash)" >> /etc/exports echo "/home $HOST.$DOMAIN (rw,no_all_squash,no_root_squash)" >> /etc/exports # restart the nfsd and mountd daemons on the server /usr/bin/killall -HUP rpc.nfsd /usr/bin/killall -HUP rpc.mountd # create /etc/fstab entry /bin/rm -f $DEST_DIR/etc/fstab echo "$SERVER:/tftpboot/$IPADDR / nfs hard,intr,rw" >> $DEST_DIR/etc/fstab echo "$SERVER:/usr /usr nfs soft,intr,rw" >> $DEST_DIR/etc/fstab echo "$SERVER:/bin /bin nfs soft,intr,rw" >> $DEST_DIR/etc/fstab echo "$SERVER:/sbin /sbin nfs soft,intr,rw" >> $DEST_DIR/etc/fstab echo "$SERVER:/lib /lib nfs soft,intr,rw" >> $DEST_DIR/etc/fstab echo "$SERVER:/home /home nfs hard,intr,rw" >> $DEST_DIR/etc/fstab /bin/rm -f $DEST_DIR/etc/mtab /bin/touch $DEST_DIR/etc/mtab # some other files have to be unique for each client /bin/rm -f $DEST_DIR/var/log/wtmp* /bin/touch $DEST_DIR/var/log/wtmp /bin/rm -f $DEST_DIR/var/log/lastlog* /bin/touch $DEST_DIR/var/log/lastlog echo "Done."