This script is intended to be used on IBM Blade Server HS20/HS21 to install the multipath tools on Debian.
#!/bin/bash # # file: multipath.sh # author: Sylvain Bolay # e-mail: sylvain.bolay@irovision.ch # date: May 29, 2007 # # GOALS: # distro="Debian" distroFile="/etc/issue" kernel="2.6.18" backupExt=`date +%y%m%d%H%M%S` date echo -e "Script to configure multipath on SAN" echo -e "with the Debian stable etch distribution\n" echo -n "Checking distribution... " #check distro if [ ! -f $distroFile ]; then echo "ABORTED!" echo "The $distroFile file is not present!" echo "This script is for a Debian distribution!" exit fi if [ `grep -c -i "Debian" /etc/issue` -eq 0 ]; then echo "ABORTED!" echo "This script is for a Debian distribution!" exit fi #check kernel if [ `uname -r | grep -c $kernel` -eq 0 ]; then echo "ABORTED!" echo "Your kernel version is: " uname -r echo "This does not match kernel >= $kernel." exit fi #end of "Checking distribution..." echo "done" echo -n "Checking tools&drivers... " #udev provides udevinfo needed thereafter for package in grep mawk udev multipath-tools multipath-tools-initramfs dmsetup firmware-qlogic; do if [ `dpkg -s $package | grep -c installed` -eq 0 ]; then echo "ABORTED!" echo "$package missing! Please apt-get $package!" if [ $package == "firmware-qlogic" ]; then echo "$package is located in the non-free section!" echo "You may have to update your sources.list file to apt-get it!" fi exit fi done #end of "Checking tools&drivers..." echo "done" echo -n "Backup and Create configuration files... " #Check if multipath.rules exist file="/etc/udev/rules.d/multipath.rules" if [ ! -f $file ]; then echo "ABORTED!" echo "$file doesn't exist!" exit fi initramfstoolsETC="/etc/initramfs-tools" initramfstoolsUSR="/usr/share/initramfs-tools" if [ ! -d $initramfstoolsUSR ]; then echo "ABORTED!" echo "$initramfstoolsUSR directory is missing!" exit fi # backup (I do not check if the backup directory already exists or not) # I should find in "/etc/initramfs-tools/scripts/local-top" the file multipath_script if [ -d $initramfstoolsETC ]; then mv $initramfstoolsETC $initramfstoolsETC.$backupExt fi cp -r $initramfstoolsUSR $initramfstoolsETC #end of "Backup and Create configuration files... " echo "done" echo -n "Check module availability... " #add module to "modules" file modulesFile="$initramfstoolsETC/modules" if [ -f $modulesFile ]; then # dm-mpath and dm-multipath are from /usr/share/doc/multipath-tools/FAQ impulse! # for now, I suppressed dm-mpath!!!! # scsi_mod sd_mod dm-mod dm-multipath dm-round-robin and # dm-emc are from http://www.tuxyturvy.com/files/mkinitrd.mp entries for module in scsi_mod sd_mod dm-mod dm-multipath dm-round-robin dm-emc; do if [ `modinfo $module 2>&1 | grep -c "modinfo: could not find module"` -gt 0 ]; then echo "ABORTED!" echo "$module module does not exist." exit fi echo $module >> $modulesFile done fi #end of "Check module availability... " echo "done" echo -n "Modifing configurations files... " #Create the initramfs.conf initramfsconf="$initramfstoolsETC/initramfs.conf" #PARANOIA if [ -f $initramfsconf ]; then mv $initramfsconf /tmp/$initramfsconf.$backupExt echo "I put your $initramfsconf into /tmp with the extension: $backupExt" fi cat << MSG >> $initramfsconf MODULES=most BUSYBOX=y BOOT=local DEVICE=eth0 NFSROOT=auto MSG #Create the update-initramfs.conf updateinitramfsconf="$initramfstoolsETC/update-initramfs.conf" #PARANOIA if [ -f $updateinitramfsconf ]; then mv $updateinitramfsconf /tmp/$updateinitramfsconf.$backupExt echo "I put your $updateinitramfsconf into /tmp with the extension: $backupExt" fi cat << MSG >> $updateinitramfsconf update_initramfs=yes backup_initramfs=yes MSG #Create the multipath.conf (very small conf!!!) multipathConf="/etc/multipath.conf" #backup if [ -f $multipathConf ]; then mv $multipathConf $multipathConf.$backupExt fi #I dont know yet how to automatically determine the working disk! #I can try to identify the disk with rdev alias="os" disk="sda" wwid=`/sbin/scsi_id -g -u -p 0x83 -s /block/$disk` wwid_udev=`udevinfo --query=all --name=/dev/sda1 | grep "ID_SERIAL=" | awk '{ print $2 }' | cut -d '=' -f2` vendor=`udevinfo --query=all --name=/dev/sda1 | grep "ID_VENDOR=" | awk '{ print $2 }' | cut -d '=' -f2` #model=`udevinfo --query=all --name=/dev/sda1 | grep "ID_MODEL=" | awk '{ print $2 }' | cut -d '=' -f2` model=`/sbin/scsi_id -g -p 0x80 -s /block/$disk | awk '{ print $2 }'` #adjust the vendor string length to 8 ; #this is fixed by the multipath source code to work properly #vendorSize=8 #new setting to allow .* at the end! vendorSize=6 size=${#vendor} if [ $size -gt $vendorSize ]; then vendor=`expr substr $vendor 1 $vendorSize` vendor=${vendor}.* elif [ $size -lt $vendorSize ]; then vendor=${vendor}.* #THIS DO NOT WORK #for (( i=$size+1; i <= $vendorSize; i++ )) do #vendor=${vendor}" " #done fi #echo "The vendor ($vendor) string length is about: ${#vendor}" #adjust the model string length to 16 ; #this is fixed by the multipath source code to work properly modelSize=16 #new setting to allow .* at the end! modelSize=14 size=${#model} if [ $size -gt $modelSize ]; then model=`expr substr $model 1 $modelSize` model=${model}.* elif [ $size -lt $modelSize ]; then model=${model}.* #THIS DO NOT WORK #for (( i=$size+1; i <= $modelSize; i++ )) do #model=$model" " #done fi #echo "The model ($model) string length is about: ${#model}" if [ $wwid != $wwid_udev ]; then echo "ABORTED!" echo "The wwid provided by scsi_id and by udevinfo does not match!" echo "scsi_id: $wwid / udevinfo: $wwid_udev" exit fi #add defaults #Warning space between keywords and { is imperative #You can check if if works correctly by trying: multipath -d -v2 cat << MSG >> $multipathConf defaults { udev_dir /dev polling_interval 2 #selector "round-robin 0" #path_grouping_policy group_by_serial getuid_callout "/sbin/scsi_id -g -u -p 0x83 -s /block/%n" #prio_callout "/sbin/mpath_prio_tpc /dev/%n" #path_checker tur #rr_min_io 1000 #rr_weight uniform #failback immediate #no_path_retry 300 user_friendly_names yes } MSG #add blacklist cat << MSG >> $multipathConf blacklist { devnode "^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*" devnode "^hd[a-z][[0-9]*]" devnode "^cciss!c[0-9]d[0-9]*[p[0-9]*]" } MSG #add multipaths cat << MSG >> $multipathConf multipaths { multipath { wwid $wwid alias $alias } } MSG #add devices cat << MSG >> $multipathConf devices { device { #vendor must be exactly 8 char length vendor "$vendor" #product must be exactly 16 char length product "$model" path_grouping_policy group_by_serial getuid_callout "/sbin/scsi_id -g -u -p 0x83 -s /block/%n" prio_callout "/sbin/mpath_prio_tpc /dev/%n" path_checker tur path_selector "round-robin 0" failback immediate prio_callout "/sbin/mpath_prio_tpc /dev/%n" features "1 queue_if_no_path" no_path_retry 300 } } MSG #Create an add-on for /etc/initramfs-tools/hooks/multipath_hook as multipath_hook.1 multipathHook="$initramfstoolsETC/hooks/multipath_hook_1" #PARANOIA if [ -f $multipathHook ]; then mv $multipathHook /tmp/multipath_hook.$backupExt echo "I put your $multipathHook into /tmp with the extension: $backupExt" fi cat << MSG >> $multipathHook #!/bin/sh PREREQ="" prereqs() { echo "\$PREREQ" } case \$1 in # get pre-requisites prereqs) prereqs exit 0 ;; esac . /usr/share/initramfs-tools/hook-functions copy_exec $multipathConf /etc/ for helper in /sbin/mpath_prio_*; do copy_exec \$helper /sbin done MSG #chmod $multipathHook to be executable chmod +x $multipathHook #end of "Modifing configurations files... " echo "done" echo -n "Checking multipath configuration file... " foundAlias=0 if [ `multipath -d -v2 | grep -c $alias` -gt 0 ]; then foundAlias=1 fi if [ `multipath -ll | grep -c $alias` -gt 0 ]; then foundAlias=1 fi if [ ! foundAlias ]; then echo "ABORTED!" echo "It seems that the $multipathConf as a problem." echo "I was not able to detect the alias "$alias" while" echo "trying multipath -d -v2" fi #end of "Checking multipath configuration file... " echo "done" echo "I only looked at /block/$disk for now!" echo "If you need to add some more devices, you should update your $multipathConf" echo -e "and re-run: update-initramfs -t -c -v -k `uname -r` " echo "Create initrd... " #Create initrd based on "/usr/share/doc/multipath-tools-initramfs/README.Debian" kernel=`uname -r` initrd="/boot/initrd.img-`uname -r`" bckinitrd="$initrd-$backupExt-original" if [ -f $initrd ]; then mv $initrd $bckinitrd echo "I backuped your $initrd as $bckinitrd" else echo "ABORTED!" echo "I tried to find your initrd in $initrd but couldn't find it!" echo "Did I make a mistake???" echo "Anyway, I will create a new initrd file as $initrd" echo "You may have to update your grub/menu.lst" fi update-initramfs -t -c -v -k `uname -r` #rename the newly created initrd mpinitrd="$initrd-$backupExt-multipath" mv $initrd $mpinitrd #restore the backuped initrd cp $bckinitrd $initrd #end of "Create initrd..." echo "done" echo -n "Auto-Configuration of GRUB..." #TODO: auto-configure /boot/grub/menu.lst and /etc/fstab #Update the /boot/grub/menu.lst menulst="/boot/grub/menu.lst" #PARANOIA if [ -f $menulst ]; then cp $menulst $menulst.$backupExt fi cat << MSG >> $menulst title Debian GNU/Linux, kernel $kernel with multipath (V: $backupExt) root (hd0,0) kernel /boot/vmlinuz-$kernel root=/dev/mapper/${alias}1 ro initrd $mpinitrd savedefault MSG #end of "Auto-Configuration of GRUB..." echo "done" echo "Dont forget to add entries in your /etc/fstab. This should be something like:" echo "<file system> <mount point> <type> <options> <dump> <pass>" echo "/dev/mapper/${alias}1 / reiserfs notail 0 1" echo "/dev/mapper/${alias}2 none swap sw 0 0" echo "" echo "WARNING:" echo "You can check after rebooting if the settings are taken from the 'default' entry " echo "of your multipath.conf file or are correctly handled by the 'device' entry" echo "by issuing the multipath -v3 command and checking if beside your settings" echo "the comments are '(config file default)' or '(controller setting)' respectively" exit