Tracking NPIV Connectivity

Edit: I still love handy scripts.

Originally posted May 15, 2012 on AIXchange

IBMer Glenn Lehman posted this script on a mailing list, and with his permission I’m posting it here. Glenn offered this introduction and description: “I search for various 4-digit IBM storage types. My example is coded to recognize 2810, 2107,1750 (which translates to XIV, DS8300, DS6800).

“I share this as an intro… because prior to starting, our team was concerned with how we would keep track of all this configuration information, so I wrote and we now use my handy script. It gathers and parses and organizes all the info we wanted to track into neat columns. It’s all automatic, and all real-time.

“Our environment was all p570 frames — and strictly NPIV (no vSCSI). We have dual SAN fabrics and dual VIO servers per frame for redundancy and disk multi-pathing.

“Let me know if you find this useful, or if you make any changes or modifications so we can share it with others.”

He adds that the following should be customizable for those familiar with ksh scripting.

#!/bin/ksh
#set -x
#@============================================================================
# Script    :  Collect and display FC/Disk/SAN info for given VIOS pair
# Author    :  Glenn Lehman / IBM
#
# History  :  Created: Thu Jan 26 EST 2012
# Modify    :  Jan 30 2012 – add dph VIOS option
#          :  Jan 31 2012 – add ping test to confirm VIOS is active
#          :  Feb 06 2012 – add uniq date suffix to TMP filename
#          :  Feb 09 2012 – add disk type and count to output
#
# Usage    :  Invoke from remote LPAR with NPIV frame parameter
#=============================================================================
#
##########################  Assumptions  ################################
# There is a remote server that can access all VIO-servers & VIO -clients
#  and that remote server is where this script resides and invokes from
# There are 2 VIO-Servers in a given frame
# There is a distributive shell method configured in the environment
# The LPAR profile name is VIO-…
# Example: Profile=>  VIO-hostAix61prd
#          Hostname=> hostAix61prd
# Storage types are one of the following:
# XIV – 2810
# DS8300 – 2107
# DS6800 – 1750
# There are dual SAN Fabrics with unique domains, so that the FCIDs
# can pinpoint the fabric
# Example:
# 0x15 Fabric vs. 0x16 Fabric


##########################  Customization Step  #########################
# Assign the distributive shell command and usage options
#
DSH=’dsh -w’

function Get_lsmap
{
## capture the full lsmap output for VIO1 ##
$DSH $VIOH1 “/usr/ios/cli/ioscli lsmap -all -npiv” | cut -f2- -d’:’ > $TMP.map1
## convert to line separated stanzas ##
cat $TMP.map1 | grep -v “^ $” | \
    awk ‘
    $1 == “VFC” {print $0 “\n \n”}
    $1 != “VFC” {print $0}’ > $TMP.sep1

## capture the full lsmap output for VIO2 ##
$DSH $VIOH2 “/usr/ios/cli/ioscli lsmap -all -npiv” | cut -f2- -d’:’ > $TMP.map2
## convert to line separated stanzas ##
cat $TMP.map2 | grep -v “^ $” | \
    awk ‘
    $1 == “VFC” {print $0 “\n \n”}
    $1 != “VFC” {print $0}’ > $TMP.sep2

cat $TMP.sep1 $TMP.sep2 > $TMP.map_all
return
}

function Show_Usage
{
echo “Requires a single valid parameter that denotes a VIOS pair
using npiv mapping…”
echo
echo “Usage: $(basename ${0}) < ae2 | b12 | e40 | 88f >”
echo;echo
return
}

function Show_Header
{
echo “\t=========================================================================================”
echo “\t  $FRAME virtual (fscsi) mapping – $(date)”
echo “\t=========================================================================================”
echo ”                                          VIOS
VIOC        “
echo “VFCHOST    ID#  Partition            Server,Slot,Phys
Slot,Virt  Virtual WWPN used  Disks    FC/SAN Status”
echo “———-  —  —————–    ——————-
———  ——————  ——  —————————-

return
}

function Ping_VIOS
{
## Verify VIOS pings OK from this server
VIOS=$1
/etc/ping -c 2 $VIOS  > /dev/null
PING_RC=$?
if [[ $PING_RC != 0 ]]; then
  echo “ERROR: Remote server ping from nim0 to $VIOS failed…. aborting.”
  exit 99
fi
return
}


# —— MAiN PROGRAM BEGiNS HERE —— #
if [[ $# -ne 1 ]]; then
  Show_Usage
  exit 99
fi

## Define pretty-print variables
typeset -L11 VFCHOST
typeset -R2  PLPID
typeset -L20 PLPNAME
typeset -L21 SFCINFO
typeset -L10 CFCINFO
typeset -L8 DISKINFO
typeset -L19 PWWPN

VIOPAIR=$1

##########################  Customization Step  #########################
# Assign Server Frame keyword shortcuts for custom parameter input;
# add these to the Show_Usage “Usage” line
# Assign the various VIO-server hostnames and the Server Frame name
# for each “shortcut”
# Example: Use ae2 as shortcut for Server-9117-MMA-SN10D1AE2
#
case $VIOPAIR in
  ae2 | AE2 ) VIOH1=lbvio1-ae2; VIOH2=lbvio2-ae2;
FRAME=’Server-9117-MMA-SN10D1AE2′;;
  b12 | B12 ) VIOH1=lbvio1-b12; VIOH2=lbvio2-b12;
FRAME=’Server-9117-MMA-SN10D1B12′;;
  e40 | E40 ) VIOH1=lbvio1-e40; VIOH2=lbvio2-e40;
FRAME=’Server-9117-MMA-SN1014E40′;;
  88f | 88F ) VIOH1=lbvio1-88f; VIOH2=lbvio2-88f;
FRAME=’Server-9117-MMA-SN106988F-NDev’;;
  * ) echo “VIOS parm – $VIOPAIR – is invalid; aborting…”
      Show_Usage
      exit 99
esac

TMP=”/tmp/get_vfchosts-$(date +%s)”

## confirm VIOS pair is active and ping-able ##
Ping_VIOS $VIOH1
Ping_VIOS $VIOH2

## collect and reorganize the lsmap output ##
Get_lsmap

Show_Header

## build sorted list of vfchosts ##
grep vfchost $TMP.map1  | awk -v vioh=$VIOH1 ‘{print $0″  “vioh}’ >
$TMP.vfchost1
grep vfchost $TMP.map2  | awk -v vioh=$VIOH2 ‘{print $0″  “vioh}’ >
$TMP.vfchost2
cat $TMP.vfchost1 $TMP.vfchost2 | sort -tt -n -k 2,2 > $TMP.vfchost_all

cat $TMP.vfchost_all | while read VFCHOST PHYLOC PARTID NAME1 NAME2 VIOS; do
    PLPID=$PARTID
    LPNAME=$(echo ${NAME1}${NAME2})
    if [[ $LPNAME != “VIO-“* ]]; then
      PLPNAME=’unassigned’
      HOSTNAME=”
      VIOS=$NAME1                      # shifts position if less fields in line
    else
      LPNAME=${LPNAME%AIX}
      HOSTNAME=${LPNAME#VIO-}
      PLPNAME=$LPNAME
    fi
    SSLOT=$(echo $PHYLOC | awk -F- ‘{print $NF}’)
    PFC=$(grep -wp $PHYLOC $TMP.map_all | grep -w FC | awk ‘{print
$2}’ | cut -f2 -d’:’)
    if [[ $PFC != “fcs”* ]]; then
      PFC=’none’
    fi
    SFCINFO=”$VIOS,$SSLOT,$PFC”
    CSLOT=$(grep -wp $PHYLOC $TMP.map_all | grep VFC | awk ‘{print
$NF}’ | awk -F- ‘{print $NF}’)
    if [[ $CSLOT != “C”* ]]; then
   0;   CSLOT=’undefined’
    fi
    VFC=$(grep -wp $PHYLOC $TMP.map_all | grep VFC | awk ‘{print $3}’
| cut -f2 -d’:’)
    if [[ -n $HOSTNAME ]]; then
      $DSH $HOSTNAME “lsdev -c disk” | cut -f2- -d’:’ > $TMP.disk
      DSKCNT=$(grep -c MPIO $TMP.disk | awk ‘{print $1}’)
      ##########################  Customization Step  #########################
      # Assign the possible remote disk types based on their 4-digit
      # machine type
      #
      if ( grep -w 2810 $TMP.disk > /dev/null ); then
        DISKTYP=’XIV’
      elif ( grep -w 2107 $TMP.disk > /dev/null ); then
        DISKTYP=’DS83′
      elif ( grep -w 1750 $TMP.disk > /dev/null ); then
        DISKTYP=’DS68′
      else
        DISKTYP=’unkn’
      fi
      DISKINFO=”$DISKTYP($DSKCNT)”
      $DSH $HOSTNAME “fcstat $VFC | grep ‘Port'”  | cut -f2- -d’:’ > $TMP.fcst
      WWPN=$(grep ‘World Wide Port’ $TMP.fcst | awk ‘{print $NF}’)
      FBRC=$(grep ‘Port FC ID’ $TMP.fcst | awk ‘{print substr($NF,1,4)}’)
      TYPE=$(grep ‘Port Type’ $TMP.fcst | awk ‘{print $NF}’)
    else
      WWPN=’no active flogi  ‘
      FBRC=’….’
      TYPE=”
      DISKINFO=’unknown’
    fi
    PWWPN=$WWPN
    CFCINFO=”$CSLOT,$VFC”
    PCNT=$(grep -wp $PHYLOC $TMP.map_all | grep Ports | cut -f2 -d’:’)
    print “$VFCHOST $PLPID  $PLPNAME $SFCINFO  $CFCINFO  $PWWPN
$DISKINFO $PCNT ports logged in $FBRC $TYPE”
done
echo

## Be polite and clean up after yourself ##
rm -f $TMP.*
exit

In the process of posting this script to the blog, some of the formatting may be altered. Make the logical adjustments as need be. And if you have your own handy scripts or tools, please send them to me and I’ll share them here.