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:

  1. Create and export LUNs so that they are presented to the server in question
  2. Rescan the SCSI bus on the server: rescan-scsi-bus.sh
  3. Flush all unused multipath device maps: multipath -F
  4. 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.

  1. 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:

  1. 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.

#!/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

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 880 other followers