setup-violin-mpath.sh
If you spend any time configuring Linux device multipathing then you probably find yourself regularly editing the /etc/multipath.conf file. I have to do this whenever I am presenting new LUNs from Violin storage to a database server – and it was getting a little bit tiring… so, I thought I’d script it. To be honest I have no idea if it will help anyone else, but it’s certainly saving me a lot of time.
Requirement
What I want is to create a set of LUNs on the storage array, let’s say eight LUNs called SLOBDATA1 … SLOBDATA_8 and maybe another two called SLOBRECO1 and SLOBRECO2. These are presented over fibre-channel to the database server, which sees them via multiple paths. By default, multipath devices will be configured for them with unfriendly names. I just want to see them with nice names like /dev/mapper/slobdata1, /dev/mapper/slobdata2 and so on.
The Manual Way
The process I usually have to follow (as root) when installing Oracle on Violin is this:
- Create and export LUNs so that they are presented to the server in question
- Rescan the SCSI bus on the server: rescan-scsi-bus.sh
- Flush all unused multipath device maps: multipath -F
- Detect all new multipath devices: multipath -v1
At this point, the newly-mapped LUNs all appear with names such as /dev/mapper/mpatha, /dev/mapper/mpathb etc… The next steps are the ones that I have automated with the below script.
- For each LUN an entry needs to be placed in the /etc/multipath.conf file giving it an alias. I usually use the sq_inq command (part of the sg3_utils package) to extract the LUN name from the storage array, which I can then set the alias to match:
[root@half-server4 ~]# ls -l /dev/mapper/mpathd lrwxrwxrwx 1 root root 7 Feb 7 17:06 /dev/mapper/mpathd -> ../dm-9 [root@half-server4 ~]# sg_inq -i /dev/dm-9 | egrep 'vendor id|vendor specific' designator_type: T10 vendor identification, code_set: ASCII vendor id: VIOLIN vendor specific: 41148F00134:SLOBDATA4:1AFC6D752375E975
The vendor specific string there shows me three values: the array container name “4118F00134”, the LUN name “SLOBDATA4″and the device serial “1AFC6D752375E975”. The latter is what I need to configure the multipath.conf file, but we’re still not quite done… we need the UUID in order to configure the entry in the file:
- Query the device to find the UUID by using the udevadm info command:
root@half-server4 ~]# udevadm info --query=all --path=/block/dm-9 | grep DM_UUID
E: DM_UUID=mpath-SVIOLIN_SAN_ARRAY_1AFC6D752375E975
Now that I have the UUID (shown in red) I can configure an entry in the multipath.conf file that looks like this:
multipath { wwid SVIOLIN_SAN_ARRAY_1AFC6D752375E975 alias slobdata4 }
Phew. That was a lot of effort… and I have to do it another nine times for the other LUNs. What about if I need more than ten LUNS? What if I need hundreds?
The Automated Way
The script below comes in to play once the devices have been presented to the server and the multipath mapper has given them all unfriendly names (e.g. mpatha, mpathb etc). For each device found it will check the vendor ID (for the string VIOLIN, but you can modify this if you have other storage), read the LUN name, query for the UUID and then print out the relevant multipath.conf entry to standard out. This can then be checked, cut and pasted into /etc/multipath.conf
Right now it only works for Red Hat 6 or Oracle Linux 6. I haven’t yet had the time or inclination to make it suitable for RH5 / OL5 or any of the SUSE Linux variants. As always, the standard disclaimer applies:
The tools and scripts found here are supplied for education purposes only and come with no warranty, either expressly or implied. Use at your own risk and please test thoroughly before use in a environment where you care about data and availability.
Here’s the shell script (the master copy is located at my GitHub repository):
#!/bin/bash # setup-violin-mpath.sh - script for configuring the multipath.conf file with Violin devices # Author: flashdba (http://flashdba.com) # The output can be cut and pasted into the "multipaths {}" section of /etc/multipath.conf # Alternatively the -l option can be used to print a list of devices # # For educational purposes only - no warranty is provided # Test thoroughly - use at your own risk # TODO: Currently only written for use with Red Hat 6 / Oracle Linux 6 / SLES 11 # Setup variables and arrays VERBOSE=0 LISTMODE=0 MULTIPATH_DEVICES=() # Setup print functions echoerr() { echo "Error: $@" 1>&2; } echovrb() { [[ "$VERBOSE" = 1 ]] && echo "Info : ${@}" 1>&2; } echoout() { echo "$@"; } echolst() { echo "$@" | tr '±' '\t' | expand -t 5 1>&2; } # Function for printing usage information usage() { echo "" 1>&2 if [ "$#" -gt 0 ]; then echo "Error: $@" 1>&2 echo "" 1>&2 fi echo "Usage: $0 [-v ]" 1>&2 echo "" 1>&2 echo " Script for configuring the /etc/multipath.conf file" 1>&2 echo " Creates entries for the \"multipath \{\}\" section" 1>&2 echo " Requires the sg3_utils package to be present" 1>&2 echo " Errors and info are printed to stderr" 1>&2 echo "" 1>&2 echo " Options:" 1>&2 echo " -h Help (print help and version information)" 1>&2 echo " -l List (print a list of devices and their details)" 1>&2 echo " -v Verbose (show processing details)" 1>&2 echo "" 1>&2 exit 1 } while getopts ":hvl" opt; do case $opt in h) usage ;; v) VERBOSE=1 echovrb "Running in verbose mode" ;; l) LISTMODE=1 echovrb "Running in list mode" ;; \?) echo "Invalid option: -$OPTARG" >&2 usage ;; esac done # Check that the s3_utils package has been installed and is in the path if hash sg_inq 2> /dev/null; then echovrb "Using sg_inq `sg_inq -V 2>&1`" else echoerr "sg3_utils package not installed - exiting..." exit 1 fi # Build a list of multipath devices to scan MULTIPATH_FILELIST=$( ls -1 /dev/dm-* ) # Iterate through the list for MPDEVICE in $MULTIPATH_FILELIST; do echovrb "Issuing inquiry to device $MPDEVICE" # Issue sg3 inquiry to device SG3_OUTPUT=`sg_inq -i $MPDEVICE 2> /dev/null` SG3_RETVAL=$? # If inquiry returned error code then skip if [ "$SG3_RETVAL" -ne 0 ]; then echovrb "Skipping device $MPDEVICE" continue fi # Scan output to find vendor id SG3_VENDORID=`echo "$SG3_OUTPUT" | grep "vendor id:" | cut -d':' -f2- | sed 's/^ *//g' | sed 's/ *$//g' ` 2> /dev/null # Check the vendor is VIOLIN otherwise skip if [ "$SG3_VENDORID" != "VIOLIN" ]; then echovrb "Ignoring device on $MPDEVICE with vendor id = $SG3_VENDORID" continue fi # Get the sysfs device location (required for udevinfo) MPATH_DEVBASE=`basename $MPDEVICE` MPATH_SYSFS="/block/$MPATH_DEVBASE" # Process device specific details LUN_CONTAINER=`echo "$SG3_OUTPUT" | grep "vendor specific:" | cut -d':' -f2 | sed 's/^ *//g'` LUN_NAME=`echo "$SG3_OUTPUT" | grep "vendor specific:" | cut -d':' -f3` LUN_SERIAL=`echo "$SG3_OUTPUT" | grep "vendor specific:" | cut -d':' -f4` LUN_UUID=`udevadm info --query=property --path=$MPATH_SYSFS 2> /dev/null | grep "DM_UUID=" | sed 's/^DM_UUID=mpath-*//g'` echovrb "Found Violin device on $MPDEVICE: Container = $LUN_CONTAINER LUN Name = $LUN_NAME Serial = $LUN_SERIAL UUID = $LUN_UUID" # Add details to an array variable of Violin devices MULTIPATH_DEVICES+=(`echo "$LUN_NAME:$LUN_UUID:$LUN_CONTAINER:$LUN_SERIAL:$MPDEVICE"`) done # Sort the array into alphabetical order based on LUN name echovrb "Sorting discovered devices into alphabetical order..." MULTIPATH_DEVICES=($(for MPDEVICE in ${MULTIPATH_DEVICES[@]}; do echo $MPDEVICE done | sort)) echovrb "Sort complete" if [ "$LISTMODE" = 1 ]; then echolst "Device Name±Container ±LUN Name±WWID" echolst "-----------±-----------±--------±----------------------------------" else if [ -r /etc/multipath.conf ]; then echovrb "Backup up /etc/multipath.conf to /tmp" cp /etc/multipath.conf /tmp fi fi echovrb "Printing multipath.conf configuration details..." echovrb "" # Now print the multipath.conf output for each device, converting the LUN name to lowercase for MPDEVICE in ${MULTIPATH_DEVICES[@]}; do MP_WWID=`echo $MPDEVICE | cut -d':' -f2` MP_ALIAS=`echo $MPDEVICE | cut -d':' -f1 | tr '[:upper:]' '[:lower:]'` MP_CONTAINER=`echo $MPDEVICE | cut -d':' -f3` MP_DEVNAME=`echo $MPDEVICE | cut -d':' -f5` if [ "$LISTMODE" = 1 ]; then echolst "$MP_DEVNAME ±$MP_CONTAINER±$MP_ALIAS±$MP_WWID" else echoout " multipath {" echoout " # Container $MP_CONTAINER" echoout " wwid $MP_WWID" echoout " alias $MP_ALIAS" echoout " }" fi done echovrb "Successful completion" exit 0
Very impressive script u have made. Can I use this script for EMC storage?
Thanks,
Varun
No, not in it’s current state. But you may be able to modify it.