#!/bin/ksh
#set -x
Version="2.8"
###################################################################################################
#
#   Disclaimer: This Tool is for IBM support team diagnostics.
#       It is provided as is and is not supported as an IBM product
#       under any type of software maintenance agreement.
#   Author: Wayne Willcox
#   Created: 20 Feb 2018
###################################################################################################

TOPLVL="`pwd`"
# This function formats and properly displays the standard discliamer.
Disclaimer () {

        echo |awk 'BEGIN {
                   printf("\n\t TGT_PORT\n");
                   printf("\t 0 == not logged in at all\n");
                   printf("\t 1 == logged in only to the switch\n");
                   printf("\t 2 >= means your logged into the switch and however many targets are zoned to the client.\n");

                   LINES = "#########################################################################";
                   Seperator = "#";
                } {
                printf("%s\n",LINES);
                printf("%-71s %s\n",Seperator,Seperator);
                printf("%-4s Disclaimer: This Tool is for IBM support team diagnostics. %9s\n",Seperator,Seperator);
                printf("%-4s It is provided as is and is not supported as an IBM product %8s\n",Seperator,Seperator);
                printf("%-4s under any type of software maintenance agreement. %18s\n",Seperator,Seperator);
                printf("%s\n",LINES);

        }'

}

Usage () {
cat << EOF
    $0 
    -c searches for a clientid number
    -h searches for a passed in client hostname
    -N Only print the NPIV client data.
    -V prints version of the command
    -v prints out details about the specified vfchost.
    -s prints entries matching clients scsiid
    -S specify the location of the top level directory of the AIX SNAP
    -H prints usage
    -l run on a live system instead of a snap

If your running this command on an AIX SNAP you run it from the snap toplevel directory.
EOF
Disclaimer
exit
}
LIVE=0
DOCLIENT=0
NPIV_ONLY=0
DEBUG=0

while getopts "lc:Hh:Vs:dS:v:N" opt;do
    case "$opt" in
                V) echo "$0 Version $Version";exit;;
                c) clientid=$OPTARG;;
                v) vfchostid=$OPTARG;;
                h) hostid=$OPTARG;;
                s) scsiid=$OPTARG;;
                N) NPIV_ONLY=1;;
                l) LIVE=1;;
                C) DOCLIENT=1;;
                d) DEBUG=1;;
                S) SNAPDIR=$OPTARG;;
                H) Usage;;
   esac
done
shift $((OPTIND-1))
lvl=0
if [ ${DEBUG} -eq 1 ];then
    set -x
fi

if [ -n "${SNAPDIR}" ];then
    cd ${SNAPDIR} || Usage
    TOPLVL="`pwd`"
fi

# lets just check if this is a client or a vio server. This will
# make using the -C flag not required if running live.
if [ ${LIVE} -eq 1 ];then
    if [ -f /usr/lib/ras/snapscripts/svCollect ];then
        TOPLVL=/tmp/ibmsupt1
        DOCLIENT=0
    else
        DOCLIENT=1
    fi
elif [ ! -d ./svCollect ];then
        DOCLIENT=1
fi

if [ ${LIVE} -eq 0 ];then
       echo
       echo "                                             GETTING DATA FROM SNAP created on date: `head -n 1 general/general.snap`"
else
       lvl=`oslevel`
       if [ ${DOCLIENT} = 1 ];then
          TYPE="ON AN VIO CLIENT"
       else
          TYPE="ON AN VIO SERVER"
       fi
       echo "                                     GETTING DATA FROM LIVE SYSTEM `hostname` ${TYPE}"
fi
echo "                                                       Current Date:  `date`                         "

map_client() {
   if [ ${DEBUG} = 1 ];then
      set -x
   fi
   if [ ${LIVE} -eq 1 ];then
 
       export SNAPDIR=/tmp/ibmsupt1/svCollect/vfc_client_collect
       mkdir -p ${SNAPDIR} ||exit
       odmget CuAt > /tmp/ibmsupt1/general/CuAt.add
       rm -rf $SNAPDIR/*
       /usr/lib/ras/snapscripts/vfc_client_collect > /dev/null 2>&1
       cd /tmp/ibmsupt1/svCollect
       TOPLVL=/tmp/ibmsupt1
    fi
    BASE_DIR="$TOPLVL/svCollect/vscsi"
    BASE_DIR="$TOPLVL/svCollect/vfc_client_collect"
    if [ ! -d ${BASE_DIR} ];then
        BASE_DIR="$TOPLVL/vfc_client_collect"
    fi
    GEN_DIR="$TOPLVL/general"
    
    echo    
    cd "${BASE_DIR}" > /dev/null 2>&1
    ls *.state >/dev/null 2>&1 ;rc=$?
    if [ $rc -eq 0 ];then
        awk 'BEGIN {
                  printf("%85s\n","NPIV DETAILS");
                  printf("%114s %48s %26s\n","ADAPTER","COMMANDS","ERRORS"); 
                  printf("%-19s %-9s %-5s %-6s %-6s  %-17s %-6s %-16s %-8s %-6s %-4s %-6s %-10s %-6s %-6s %-7s %-7s %-7s\n","VIOS NAME","HOSTID","ADAP","NODEID","SCSI_ID"                       ,"WWN","VNUM", "PARTION_NAME","CMD_ELEMS","STATE","OPEN","FLAGS","XFER","ALLOW","ACTIVE","PENDING","HIACT","HIPEND"); } {
           if (/^adapter:/) {
               adap = $2; 
               apd[adap] = adap;
               partnum[adap] = $4;
               partname[adap] = $6;
               delete MissingVal[adapter];
           } else {
               if ( apd[adap] != adap ) {
		       # this means the name of the adapter is not in the KDB output and that means KDB failed to get any useful details. So now
		       # we flag this adapter as existing but we do not know what data is there.
		       split(FILENAME,dadap,".state");
		       adapter = dadap[1];
		       MissingVal[adapter] = adapter;
                }
           } if (/^num_cmd_elems:/) {
               cmds[adap] = $2;
               location[adap] = $4;
           } else if (/^state:/ ) {
               state[adap] = $2;
               open[adap] = $4;
               flags[adap] = $6;
           } else if (/^host_name:/) {
              host[adap] = $2;
              vfchost[adap] = $4;
           } else if (/^maxCmds/) {
               maxCmds[adap] = $2;
               DMA[adap] = $4;
               SCSI[adap] = $6;
           } else if (/^portName:/) {
               port[adap] = $2;
               node[adap] = $4;
               nodeid[adap] = $6;
           } else if (/^num_cmds_allowed:/) {
               cmd_allow[adap] = $2;
               cmd_active[adap] = $4;
               cmd_pending[adap] = $6;
           } else if (/^h_dropped/) {
                hdropped[adap] = $2;
                link_down_cnt[adap] = $4;
                num_frames[adap] = $6;
                tx_lock[adap] = $8;
           } else if (/^no_elem/) {
                no_elem[adap] = $2;
                no_dma[adap] = $4;
                no_sglist[adap] = $6;
                bad_mad[adap] = $8;
                qfull[adap] = $10;
           } else if (/^NAME/) {
               split(FILENAME,dadap,".state");
               adap = dadap[1];
               if ( apd[adap] == "")  {
                   defined_apd[adap] = adap": DEFINED";
               }
               break;
           } else  if (/^inp_bytes/) {
                 inp_bytes[adap] = $2;
                 out_bytes[adap] = $4;
                 npiv_logout_sent[adap] = $6;
                 npiv_logout_rcvd[adap] = $8;
                 act_hi_water[adap] = $10;
                 pend_hi_water[adap] = $12;
          }
       
           
        } END { 
        for (ad in apd) {
                if ( host[ad] != "" ) {
                    printf("%-18s %-10s %-5s %-6s %-8s %-17s %-6s %-16s %-9s %-6s %-4s %-6s 0x%-8s %-6s %-6s %-7s %-7s %-9s ",host[ad],  \
                                vfchost[ad],ad,nodeid[ad],SCSI[ad], port[ad],partnum[ad],  \
                    partname[ad],cmds[ad],state[ad],open[ad],flags[ad],DMA[ad],cmd_allow[ad],cmd_active[ad],cmd_pending[ad], \
                    act_hi_water[ad],pend_hi_water[ad]); 
                        if ((no_elem[ad] != "0x0" ) && (no_elem[ad] != ""))
                            printf("no_elem:%-6s ",no_elem[ad] );
                        if ((no_dma[ad] != "0x0" ) && (no_dma[ad] != ""))
                            printf("no_dma:%-6s ",no_dma[ad] );
                        if ((no_sglist[ad] != "0x0" ) && (no_sglist[ad] != ""))
                            printf("no_sglist:%-6s ",no_sglist[ad] );
                        if ((bad_mad[ad] != "0x0" ) && (bad_mad[ad] != ""))
                            printf("bad_mad:%-6s ",bad_mad[ad] );
                        if ((qfull[ad] != "0x0" ) && (qfull[ad] != ""))
                            printf("qfull:%-6s ",qfull[adap] );
                        if ((hdropped[ad] != "0x0" ) && (hdropped[ad] != ""))
                            printf("hdropped:%-6s ",hdropped[adap] );
                        if ((link_down_cnt[ad] != "0x0" ) && (link_down_cnt[ad] != ""))
                            printf("link_down_cnt:%-6s ",link_down_cnt[ad] );
                        if ((num_frames[ad] != "0x0" ) && (num_frames[ad] != ""))
                            printf("num_frames:%-6s ",num_frames[ad] );
                        if ((tx_lock[ad] != "0x0" ) && (tx_lock[ad] != ""))
                            printf("tx_lock:%-6s ",tx_lock[ad] );

                        printf("\n");
                    }
        }
        for (ad in defined_apd) {
            printf("%-18s\n",defined_apd[ad]); 
        }
        for (ad in MissingVal) {
            printf ("%18s: EXISTS but there is no KDB information\n", MissingVal[ad]);
        }
    }' *.state
    fi
}

# print out the lsnport data as well as the NPIV header
print_header ()
{
        if [ -z "${clientid}" ] && [ -z "${hostid}" ] && [ -z "$scsiid" ];then
            if [ -f lsnports.out ];then
                # use awk to make sure we only print the adapter info once.
                awk '{
                       if (/^name             physloc                        fabric tports aports swwpns  awwpns/) 
                             count++;
                       if (count > 1)
                          break;
                       if ($0 != "" ) {
                           printf("        ");
                           print;
                       }
                }' lsnports.out
            echo ""
            fi
        fi
        printf "Vios                Clnt    Client                                                 \n"
        printf "Phy                  id     Adapter  TGT                                           \n"
        printf "Adap   MAP                           Port  Client name       Scsi_ID Client wwn       Status    wwpn1  wwpn2  OS_TYPE MAX_TRANSFER\n"
        printf "====   =========     ===    ====     ====  ==============    ======= ===============  ======    =====  =====  ======= ============\n"
        printf "\n"
}
print_vscsi_header ()
{
    if [ $DOCLIENT = 0 ];then
         echo |awk '{printf("\n%80s","Getting VSCSI MAPPING");} '
    echo ""
        echo "" |awk '{
            printf("Vhost   Clntid     ");
            printf("%8s %35s %68s %7s %18s %36s \n","LUNID","BACKING","MIRROR","VTD","PVID","UUID");
        }'
        #printf "Vhost   Clntid                                    Mirrored  VTD           PVID                               UUID\n";
    fi
}
# get details on the vio server level and when the snap was created.
pull_info()
{

    lvl=`find "${TOPLVL}" -name VIOS.level`
    if [ -n "${lvl}" ];then
        OS_LEVEL=`grep VIOS ${lvl} | awk '{print $4}'`
    fi
    if [ -n "${lvl}" ];then
        echo "VIOS_LEVEL ${OS_LEVEL} $lvl"
        export VIOS_LEVEL="${OS_LEVEL}"
    fi
    if [[ -f ../general/general.snap ]]; then
        SNAP_TIME=`head -1 ../general/general.snap | awk '{print $1, $2, $3, $4, $5, $6}' `
    fi

    if [ -z "${clientid}" ] && [ -z "${hostid}" ] && [ -z "$scsiid" ];then
        if [ -n "${OS_LEVEL}" ] && [ -n "${SNAP_TIME}" ];then
            echo ""
                 
            echo "$OS_LEVEL / $SNAP_TIME"
        fi
    fi
}

Usage1 () {
if [ -n "$BASE_DIR" ];then
cat << EOF
     We could not find $BASE_DIR - This most not be a VIOS snap 
     This must be run from the toplevel directory of the snap
        
    
EOF
else
cat << EOF
     We could not find the svCollect directory in the snap - This may not be a snap 
     This must be run from the toplevel directory of the snap
    
        
EOF
fi    
#exit   
}

# This function gets all the NPIV client data from a vio server snap.
get_npiv () {
    awk 'BEGIN  { LG = 1;} 
    function get_vfcstate () {

        if (/clientName:/)  {
            CLINAME = $2;
        } else if (/node_name/) {
            N_NAME = $2;
            if ( ENVIRON["VIOS_LEVEL"] >= "3.1.1.10") {
                WWPN = $4;
                SCSI_ID = $8;
            } else {
                WWPN = $2;
                SCSI_ID = $4;
            }
        } else if (/osType/) {
            if ( ENVIRON["VIOS_LEVEL"] >= "3.1.1.10") {
               ost = $4;
            } else {
               ost = $2;
            }
            if (os == 1)
               OST= "i50S";
            else if (ost == 2)
               OST = "Linux";
            else if (ost == 3)
               OST = "AIX";
            else if (ost == 4)
               OST = "FIRMWARE";
            else
               OST = "UNKNOWN";
        } else if (/portResName/) {
            PORT = $2;
        } else if (/clientPartName/) {
            CLNT = $2;
        } else if (/client_part_num/) {
            CL_PRT_NUM = $2;
        } else if (/login_tcnt/) {
            LOGIN_CNT = $2;
            LG++;
        } else if (/link_status/) {
            LNK_STATUS = $2;
        } else if (/active_q/) {
            A_QUEUE = $2;
        } else if (/target_list/) {
            TARGET = $2;
        } else if (/fc_devno/) {
            FCDEV = $2;
        } else if (/fc_handle/) {
            FCFP = $2;
        } else if (/npiv_handle/) {
            NPIV_HAN = $2;
        } else if ((/^wwpn1/) && (!/nport_log/)) {
            if ( ENVIRON["VIOS_LEVEL"] >= "3.1.1.10") {
                WWPN1 =  substr( $4, length($4) - 4, length($4));
                WWPN2 =  substr( $8, length($8) - 4, length($8));
             } else {
                WWPN1 =  substr( $2, length($2) - 4, length($2));
                WWPN2 =  substr( $4, length($4) - 4, length($4));
             }
        } else if (/async_cmd/) {
            ASYNC_CMD = $2;
        } else if (/login_cmd/) {
            LOGIN_CMD = $2;
        } else if (/logout_cmd/) {
            LOGOUT_CMD = $2;
        } else if (/waiting_cmd/) {
            W_CMD =$2;
        } else if (/waiting_rsp/) {
            W_RSP = $4
        } else if (/npiv_query/) {
            QUERY = $2;
        } else if (/npiv_admin/) {
            ADMIN = $2;
        } else if (/npiv_scsi/) {
            SCSI = $4;
        } else if (/npiv_chba/) {
            CHBA = $4;
        } else if (/^fc_max_xfer_size:/) {
            fc_max_xfer_size = $2;
        } 
    }

    function get_vfcmap () {
        #Name          Physloc                            ClntID ClntName       ClntOS
        #------------- ---------------------------------- ------ -------------- -------
        #vfchost38     U8406.71Y.061363B-V1-C70                8 rn1228e        AIX

        #Status:LOGGED_IN
        #FC name:fcs2                    FC loc code:U78A5.001.WIHD8D1-P2-C20-T1
        #Ports logged in:3
        #Flags:a<LOGGED_IN,STRIP_MERGE>
        #VFC client name:fcs2            VFC client DRC:U8406.71Y.061363B-V8-C13
        if ( Found_Entry) {
                      exit;
                }

        if (/vfchost/) {
            i = 4;
            num = split($0,vfchost);
            while ( i <= num )       {
                if ((vfchost[i] ~/IBM/) || (vfchost[i] ~/AIX/)) {
                    break;
                }
                CLNTNAME = CLNTNAME" "vfchost[i];
                i++;
            }
        }
        if (/^vfchost/) {
            if ( Found_Entry) {
                            #printf("The snap was not cleared before it was run so we have more then one entry in the snap\n");
            }
            VHOST = $1;
            CLNT_ID = $3;
        }
        if (/VFC client name/) {
            split ($3,arr,":")
            split (arr[2],array);
            CLNT_ADAP =  array[1];
            if ( CLNT_ADAP == "")
                CLNT_ADAP = "----";
                if (CLNTNAME == "")
                    CLNTNAME = "------------------";
                        # this is the last entry and the map file is also last so we can print here. We
                        # have to reset and then print the next entry.
            if (((inputclid == "") && (inputhostid == "" ) && (inputscsiid == "") && (vfchostid == "")) || (CLNT_ID == inputclid) || (CLNTNAME == " "inputhostid) || (SCSI_ID == inputscsiid ) || (VHOST == vfchostid))
                printf("%-6s %-14s %-5s %-8s %-4s %-18s %-7s %-16s %-8s %-5s %-7s %-8s %-9s\n",SRVADP,VHOST,CLNT_ID,CLNT_ADAP,PORTS,CLNTNAME, SCSI_ID,WWPN, STATUS, WWPN1, WWPN2,OST,fc_max_xfer_size);
            CLNTNAME = "";
            Found_Entry = 1;
        }
        if ((/FC name/)  && (/fcs/)){
            split($0,arr,":");
            split(arr[2],array);
            SRVADP = array[1];
        }
        if (/Ports/) {
            if ($2 != "" ) {
            split($3,arr,":");
            PORTS = arr[2];
            } else {
            PORTS="--";
                }
        }
        if (/^Status/) {
            split ($1,arr,":")
            STATUS =  arr[2];
            if ( STATUS == "" )
                STATUS="---------";
            else if ( STATUS == "NOT_LOGGED_IN")
                STATUS="---------";
        }

    }

{ 
    if (FILENAME == VFC_STATE) {
        get_vfcstate();
    } else if (FILENAME == MAP_NAME) {
        get_vfcmap();
    }

    } END {    

    }' inputscsiid=${scsiid} vfchostid=${vfchostid} inputhostid=${hostid} inputclid=${clientid} VFC=${VFCHOST} VFC_STATE=${VFC_STATE} MAP_NAME=${MAP_NAME} ${VFC_STATE} ${MAP_NAME} 

}

# get each hdisk pvid and uniq id from either the live systems ODM or from the snap/general directory
get_pvid_uid() {
    if [ ${LIVE} = 1 ];then
        if [ ! -d /tmp/ibmsupt1/general ];then
            mkdir -p /tmp/ibmsupt1/general
        fi
        odmget CuAt > /tmp/ibmsupt1/general/CuAt.add
        cmd="cat /tmp/ibmsupt1/general/CuAt.add"
        diskoutput="/tmp/ibmsupt1/disk.data"
    else
        cmd="cat "${TOPLVL}"/general/CuAt.add"
        #cmd="cat ../general/CuAt.add"
        #diskoutput="${GEN_DIR}/../svCollect/disk.data"

        diskoutput="${TOPLVL}/general/disk.data"
        # grab the last commited level of the vio server from the VIOS.level file.
        # this is kind of ugly since there could be more then one entry. I am grabbing only
        # the last one.
        if [ -f "${TOPLVL}/svCollect/VIOS.level" ];then
            lvl=`awk '{if ($2 == "COMMIT") lvl = $1;} END {print lvl;}' "${TOPLVL}"//svCollect/VIOS.level`
        fi
    fi
  
    $cmd |awk '{
        gsub("\"","");
        if (/hdisk/) {
                hd = $3;
                getline;
                if(/pvid/) {
                      getline; 
                      gsub("0000000000000000","",$3);
                      pvid = $3;
                      pv[hd] = pvid;
                }
                if(/unique_id/) {
                      getline;
                      uid = $3;
                      uuid[hd] = uid;
                 }
         }
    } END {
        for (disk in pv) {
            printf("%s %s %s\n",disk, pv[disk],uuid[disk]);
        }

   }' > "$diskoutput"
}

# get the vscsi details from a vscsi client. This will include things like vio server used.
get_vscsi() {

  vhost=$1
  maplist=`ls *.map 2>/dev/null`
  for f in $maplist ;do
    awk 'BEGIN { FOUND = 1;} { 
       if (FILENAME == output) {
           uidarray[$1] = $2" "$3; 
       }

       if (/^vhost/) {
          name = $1;
          vhost[id] = name;
          clntid[name] = $3;
       }
       if (/^VTD/) {
           vg = $2;
           VTD[vg] = $2;
           getline;
           if (/^Status/)  {
              if (/Available/)
                  Status[vg] = "AVA";
              else
                  Status[vg] = "---";
              getline; 
           }
           if (/^LUN/) {
              id = $2
              LUN[id] = $2;
              Status[id] = Status[vg];
              VTD[id] = VTD[vg];
              getline;
              if (/^Backing device/)
                 Device[id] = $3;
              getline;
              if (/Physloc/)
                 Physloc[id] = $2;
              getline;
              if (/^Mirrored/) {
                 Mirrored[id] = $2;
              }
            }
       }

     }  END {
           if (name != "" ) 
               printf("%s %s \n",name,clntid[name]);
           for ( lunid in LUN ) {
               if ( LUN[lunid] != "" ) {
                   if (print_phys) {
                       if (LUN[lunid] != "")
                           printf("\t%-4s%-16s %-14s %s %s \n",Status[lunid],LUN[lunid],Device[lunid],Physloc[lunid],Mirrored[lunid]);
                   } else {
                       # we need to push the device id way over because some of the names are really long
                       if (LUN[lunid] != "")
                           printf("    %-17s %-17s %-84s %-8s %-15s %s\n",Status[n],LUN[lunid],Device[lunid],Mirrored[lunid],VTD[lunid],uidarray[Device[lunid]]);
                   }
               }
           }
     }' output=$diskoutput $diskoutput $f
done
}

# this function reads the state files created by the vio server.  These are slightly different then
# what you find in the vio client state files.
map_vscsi_server () {
    echo |awk '{
            printf("\n%78s\n","Getting VSCSI ADAPTER STATES");
            printf("%-7s %-8s %-22s %-5s %-10s %-5s %-10s %-5s %-7s %-3s %-3s %-5s %-17s\n","HOST","UNIT_ID","HOST_NAME","MAX_Q","#CMD_ELEM","FFAIL","MXFER","TPOPS","PART#","MAD","OS","TCNT","DEVNO");
    }'
    ls *.state >/dev/null 2>&1
    if [ $? -ne 2 ];then
    for state_file in `ls *.state |xargs`;do
        awk '{ 
            if (/Target vSCSI Adapter Structure/) {
              vhost = $5;
              vhostid[vhost] = vhost;
            }
            if(/client_data.partition_name:/) { 
               # Use an array so that we can handle names with spaces in them
               split($0,partition_nm,":");
               #partition[vhost] = $4;
               partition[vhost] = partition_nm[3];
            }
            if (/unit_id:/) {
               unit_id[vhost] = $2;
               vbus[vhost] = $4;
            }
            if (/max_q_elems:/) {
               max_q_elems[vhost] = $2;
               num_cmd_elems[vhost] = $4;
            }
            if (/^partition_num:/) {
               part_num[vhost] = $2;
               part_name[vhost] = $4;
            }
            if (/children:/) {
                children[vhost] = $4;
            }
            if (/fast fail:/) {
                fast_fail[vhost] = $5;
            }
            if (/max_xfer_size:/) {
                mxfersz[vhost] = $4;
            }
            if (/rsp_q_timer.timer_pops: /) {
                tpops[vhost] = $2;
            }
            if (/client_data.partition_number: /) {
                 cpart_num[vhost] = $2;
                 mad_version[vhost] = $4;
            }
            if (/client_data.os_type: /) {
               if ( $2 == 3) {
                   os_type[vhost] = "AIX";
               } else {
                   os_type[vhost] = $2;
               }
            }
            if (/login_tcnt: /) {
                 tcnt[vhost] = $2;
            }
            if (/^devno: /) {
               devno[vhost] = $2;
            }
        } END {
            for ( vhost in vhostid ) {
               printf("%-7s %-8s %-22s %-5s %-10s %-5s %-10s %-5s 0x%-5s %-3s %-3s %-5s %-17s\n",vhost,unit_id[vhost],partition[vhost],max_q_elems[vhost],num_cmd_elems[vhost],fast_fail[vhost],
                  mxfersz[vhost],tpops[vhost],cpart_num[vhost],mad_version[vhost],os_type[vhost],tcnt[vhost],devno[vhost] );
            }
        }' $state_file
    done
    fi
}

# this is the function that gets the client vscsi data from the actual
# client kdb data output.
map_vscsi_client() {
    if [ ${DEBUG} -eq 1 ];then
        set -x
    fi
    ls *.state > /dev/null 2>&1
    if [ $? -eq 2 ];then
        return
    fi
    echo |awk '{
          printf("%105s\n","VSCSI STATE DETAILS");
          printf("%87s %20s %180 %52s %35s\n","LAST","ADAPTER","COMMANDS","HEARTBEAT","ERRORS");
          printf("%-10s %-12s %-16s %-16s %-5s %-18s %-10s %6s %-4s %-4s %-8s %-8s %-6s   %-6s  %-6s %-6s %-7s %-8s: %-5s %-5s %-5s\n","ADAPTER","UNIT_ID","PARTITION","VIO_NAME","P#","HOSTNAME","LUNID:","PARTNM","OS","STATE","OPEN:","MAX_XFEr","STARTED","RW_TIME","ACTIVE","CREDIT","QSTATE","NUM_ACT_CMD","ENABLE","STIME","PTIME:");
    }'
    for f in `ls *.state |xargs`;do
    awk '{
        if(/^unit_id/) {
           id = $2;
           unit[id] = id;
           part_num[id] = $4;
           part_name[id] = $6;
           no_elem[adap] = "0x0";
           no_dma[id] = "0x0";
           no_sglist[id] = "0x0";
           bad_mad[id] = "0x0";
           qfull[id] = "0x0";
        }
        if (/^capability_level/) {
            caplvl[id] = $2;
        }
        if (/^priv_cap/) {
            privcap[id] = $2;
            host_cap[id] = $4;
            host_name[id] = $6;
        }
        if (/^heart_beat_enabled/) {
             hb[id] = $2;
             sample_time[id] = $4;
             ping_response_time[id] = $6;
        }
        if (/^rw_timeout/) {
              rw_time[id] = $2;
        }     
        if (/host part_number:/) {
            part_nm[id] = $3;
            if ($5 == "0x3") {
                os_type[id] = "AIX";
            } else {
                os_type[id] = $5;
            }
            vio_name[id] = $8;
            split($0,vname,":");
            vio_name[id] = vname[4];
        }
        if (/^srp_size/) {
            srp[id] = $2;
            cmdq_size[id] = $4;
            dma_size[id] = $6;
        }
        if (/^state:/) {
            state[id] = $2;
            open[id] = $4;
            pmig_cap[id] = $6;
            drv_cap[id] = $8;
        }
        if (/^effective_capable/) {
                eff_cap[id] = $2;
               comp_rcvd[id] = $4;
               flags[id] = $6;
               max_xfer[id] = $8;
        }
        if (/^credit_limit/) {
             crd_lim[id] = $2;
             cmds_active[id] = $4;
             dev_started[id] = $6;
        }
        # now fill in the errors if there are any.
        if (/^no_elem/) {
            no_elems[id] = $2;
            no_dma[id] = $4;
            bad_login[id] =$6;
        }
        if (/^bad_rej/) {
            bad_rej[id] = $2;
            bad_srp_iu[id] = $4;
            bad_mad[id] = $6;
        } 
        if (/^h_dropped:/) {
           h_dropped[id] = $2;
           ping_tmo[id] = $4;
        }
        # now get the commands outstanding
        if (/^qstate:/) {
            qstate[id] = $2;
            num_act_cmds[id] = $4;
        }
        if (/lun_id:/) {
            lun_id[id] = $4;
        }
        if (/for client adapter: /) {
             adapter[id] = $6;
        }

    } END {
        for ( id in unit ) {

           printf("%-10s %-12s %-16s %-16s %-5s %-10s %18s %-6s %-4s %-5s %-8s %-5s %-9s %-8s %-5s",adapter[id],unit[id],part_name[id],vio_name[id],part_num[id],host_name[id],lun_id[id],part_nm[id],os_type[id],state[id],open[id],max_xfer[id],dev_started[id],rw_time[id],cmds_active[id]);
           printf("  %-6s %-7s %-12s %-6s %-5s %-5s ",crd_lim[id],qstate[id], num_act_cmds[id],hb[id],sample_time[id],ping_response_time[id]  );

           if ((no_elems[id] != "0x0") && (no_elems[id] != "")) {
               printf("no_elems:%s ",no_elems[id]);
           }
           if ((no_dma[id] != "0x0") && (no_dma[id] != "")) {
               printf("no_dma:%s ",no_dma[id]);
           }
           if ((bad_login[id] != "0x0") && (bad_login[id] != "")) {
               printf("bad_login:%s ",bad_login[id]);
           }
           if ((bad_rej[id] != "0x0") && ( bad_rej[id] != "")) {
               printf("bad_rej:%s ",bad_rej[id]);
           }
           if ((bad_srp_iu[id] != "0x0") && (bad_srp_iu[id]  != "")) {
               printf("bad_srp_iu:%s ",bad_srp_iu[id]);
           }
           if ((bad_mad[id] != "0x0") && (bad_mad[id] != "")) {
               printf("bad_mad:%s ",bad_mad[id]);
           }
           if ((h_dropped[id] != "0x0") && (h_dropped[id] != "")) {
               printf("h_dropped:%s ",h_dropped[id]);
           }
           printf("\n");
        }

    }' $f
done

}

svCollect () {

     lsmap -all > /tmp/ibmsupt1/svCollect.out

}

# we requested to get the details from a client snap or live system.
if [ ${DOCLIENT} -eq 1 ];then
    map_client
else
    if [ ${LIVE} -eq 1 ];then
       export SNAPDIR=/tmp/ibmsupt1/svCollect/vscsi
       mkdir -p ${SNAPDIR} ||exit
       rm -rf $SNAPDIR/*
       if [ ! -d /tmp/ibmsupt1/general ];then
           mkdir -p /tmp/ibmsupt1/general
       fi
       odmget CuAt > /tmp/ibmsupt1/general/CuAt.add
       /usr/lib/ras/snapscripts/vscsiCollect all > /dev/null 2>&1

       if [ -f  ${SNAPDIR}/svCollect/vscsi/lsnports.out ];then
           mv ${SNAPDIR}/svCollect/vscsi/lsnports.out /tmp
       fi

       export SNAPDIR=/tmp/ibmsupt1/svCollect/svfc
       mkdir -p ${SNAPDIR} ||exit
       rm -f ${SNAPDIR}/lsnports.out
       rm -rf ${SNAPDIR}/*
       rm -f  ${SNAPDIR}/*.map  ${SNAPDIR}/*.state
       /usr/lib/ras/snapscripts/svfcCollect all > /dev/null 2>&1

       if [ ! -f ${SNAPDIR}/lsnports.out ];then
          mv /tmp/lsnports.out ${SNAPDIR}/lsnports.out
       else
          rm -f /tmp/lsnports
       fi

       export SNAPDIR=/tmp/ibmsupt1/svCollect/
       echo "Based on AIX, committed level follows" > $SNAPDIR/VIOS.level;
       /usr/bin/lslpp -h | grep -v "bos.rte." | grep -p "bos.rte" | grep -p COMMIT >>  $SNAPDIR/VIOS.level;

       export VIOS_LEVEL=`/usr/ios/cli/ioscli ioslevel`;
       echo "VIOS Level is $VIOS_LEVEL" >> $SNAPDIR/VIOS.level;

       cd ${SNAPDIR}/../ 
        
    fi
fi

#map_vscsi_client
pull_info


echo ""

if [ $DOCLIENT -ne 1 ];then
   if [ -d "$BASE_DIR" ]; then
        echo ""
        cd "$BASE_DIR"

        echo ""
   fi
fi

cd "$TOPLVL"
if [ -d svCollect/svfc ];then
    cd svCollect/svfc
elif [ -d svCollect ];then
    cd svCollect
fi

ls vfc*.map > /dev/null 2>&1
if [ $? -eq 0 ];then
    print_header
    for i in `ls vfc*.map`; do
        # now get the client map details
        VFCHOST=$i
        export MAP_NAME=$i
        export VFC_STATE=`echo $VFCHOST | sed -e 's/map/state/'`
        get_npiv
    done
    if [ -n "$scsiid" ] || [ -n "$hostid" ] || [ -n "$clientid" ] || [ -n "$vfchostid" ] || [ $NPIV_ONLY = 1 ];then
       Disclaimer
       exit
    fi
fi
cd - >/dev/null 2>&1

if [ ${LIVE} -eq 1 ];then
       export SNAPDIR=/tmp/ibmsupt1/svCollect/vscsi
       if [ ! -d ${SNAPDIR} ];then
           mkdir -p ${SNAPDIR} ||exit
       else
           rm -rf $SNAPDIR/*
       fi
       if [ ! -d ${SNAPDIR}/../general ];then
           mkdir -p ${SNAPDIR}/../general ||exit
       fi
       /usr/lib/ras/snapscripts/client_collect > /dev/null 2>&1
       /usr/lib/ras/snapscripts/vscsiCollect all > /dev/null 2>&1
       ls /tmp/ibmsupt1/svCollect/vscsi/*.state > /dev/null 2>&1
       cd /tmp/ibmsupt1/svCollect/vscsi
       ls *.state > /dev/null 2>&1
       if [ $? -eq 0 ];then
           print_vscsi_header
           get_pvid_uid
           cd /tmp/ibmsupt1/svCollect/vscsi
           get_vscsi
           if [ $DOCLIENT -eq 1 ];then
               map_vscsi_client
           else
               map_vscsi_server
           fi
           echo
           rm -f $diskoutput
       fi
else
       ls svCollect/vscsi/vhost*.map > /dev/null 2>&1
       if [ $? -eq 0 ];then
           print_vscsi_header
           get_pvid_uid
           cd svCollect/vscsi
           get_vscsi 
           echo
           rm -f $diskoutput

           lvl=`oslevel`
           if [ ${DOCLIENT} -eq 1 ];then
               export SNAPDIR=`pwd`/svCollect/vscsi
               map_vscsi_client
           else
               map_vscsi_server
           fi
       else
           ls svCollect//vhost*.map > /dev/null 2>&1
           print_vscsi_header
           get_pvid_uid
           if [ -d svCollect ];then
               cd svCollect
           fi
           get_vscsi 
           echo
           rm -f $diskoutput

           lvl=`oslevel`
           if [ ${DOCLIENT} -eq 1 ];then
               export SNAPDIR=`pwd`/svCollect
               if [ -d  $SNAPDIR ];then
                   map_vscsi_client
               fi
           else
               map_vscsi_server
           fi
       fi

       cd "${GEN_DIR}/../"
       if [ -d client_collect ];then
           cd client_collect
           export SNAPDIR=`pwd`
           map_vscsi_client
       fi
fi

Disclaimer
