Run a command on a list of Fibre-Channel switches (fc-switch-commands.pl)

Up till now, we did have a bunch of shell and perl scripts doing this work. Today, as I was looking for some stuff to do, I found them and decided rewriting it, so you wouldn’t need a shell script to call the perl worker script … This is pretty much the result!

#!/usr/bin/perl

# This script runs a batch of commands on a list of FC-switches. For example:
# fc-switch-commands.pl statsclear | configupload | supportsave

use strict;
use warnings;
use Net::Telnet;

our( @san_fabric1_core, @san_fabric1_edge_1, @san_fabric1_edge_2 );
our( @san_fabric2_core, @san_fabric2_edge_1, @san_fabric2_edge_2 );
our( @switches );
our( $ftp_host, $ftp_username, $ftp_password );
our( $telnet );
our( $i, $version, @debug );

@san_fabric1_core = ( "10.144.20.50", "admin", "JuNxJFSAS!", 'san_fabric1_core' );
@san_fabric1_edge_1 = ( "10.144.20.51", "admin", "JuNxJFSAS!", 'san_fabric1_edge_1' );
@san_fabric1_edge_2 = ( "10.144.20.52", "admin", "JuNxJFSAS!", 'san_fabric1_edge_2' );
@san_fabric2_core = ( "10.144.20.60", "admin", "JuNxJFSAS!", 'san_fabric2_core' );
@san_fabric2_edge_1 = ( "10.144.20.61", "admin", "JuNxJFSAS!", 'san_fabric2_edge_1' );
@san_fabric2_edge_2 = ( "10.144.20.62", "admin", "JuNxJFSAS!", 'san_fabric2_edge_2' );

$ftp_host = '10.144.20.45';
$ftp_username = 'brocade_cfg';
$ftp_password = 'JuNxJPFC!';

@switches = ( \@san_fabric1_core, \@san_fabric2_core,
              \@san_fabric1_edge_1, \@san_fabric1_edge_2,
              \@san_fabric2_edge_1, \@san_fabric2_edge_2 );

@debug = ( Dump_Log => 'dump.log', Output_Log => 'out.log', Input_Log => 'in.log' );

$telnet = new Net::Telnet(Timeout=>240, Errmode=>'die',
                          Prompt => '/.*\:admin> $/is', @debug);

for ($i = 0; $i < $#switches + 1; $i++) {
  $telnet->open($switches[$i][0]);
  $telnet->login($switches[$i][1], $switches[$i][2]);

  if ( $ARGV[0] eq "statsclear" ) {
    $telnet->cmd("statsclear");
  } elsif ( $ARGV[0] eq "configupload" ) {
    # Check the FabricOS version, as Brocade decided to break compatiblity with
    # earlier firmware versions w/ v6 (at least configupload)
    $telnet->cmd("firmwareshow");
    $version = $telnet->lastline;
    $version =~ s/\s+|\s+$//g;

    if ( $version =~ "v6" ) {
      $telnet->cmd("configupload -all -ftp \"$ftp_host\",\"$ftp_username\",\"$switches[$i][3].cfg\",\"$ftp_password\"");
    } else {
      $telnet->cmd("configupload \"$ftp_host\",\"$ftp_username\",\"$switches[$i][3].cfg\",\"$ftp_password\"");
    }
  } elsif ( $ARGV[0] eq "supportsave" ) {
    $telnet->cmd("supportsave -n -u \"$ftp_username\" -p \"$ftp_password\" -h \"$ftp_host\" -d \"supportsave/$switches[$i][3]\" -l ftp");
  }

  $telnet->close();
}

SAN reporting

We do have some customers, who get charged on a monthly basis for their SAN usage. We already had “reporting” in place, but that wasn’t very flexible. So I went ahead and rewrote the current reporting script from scratch, and this is what I’ve come up with:

#/bin/bash

svc_sshkey="~/.ssh/svc-id_dsa"
svc_addr="10.144.0.150"
svc_user="admin"

if [ -z $1 ] ; then
  echo "Please rerun this script with some kind of filter value"
  echo "(for example '$0 NAS')"
  exit 1
else
  filter=$1
fi

IFS="
"

DISK="$( ssh -i $svc_sshkey -l $svc_user $svc_addr svcinfo lsvdisk -nohdr -bytes -delim : \
          | egrep -i "V.*$filter" | cut -d: -f2,8 | sort )"

# Get a unique list of systems
SYSTEMS="$( echo $DISK | sed "s, ,\n,g" | cut -d\  -f1 | sed 's,^V,,' | cut -d_ -f1 | sort -u )"

for system in $SYSTEMS ; do
  VDISKS="$( echo $DISK | sed "s, ,\n,g" | grep $system | sed "s,:,: ," )"
  SYSTEM_TOTAL="$( echo $DISK | sed "s, ,\n,g" | grep $system | cut -d: -f2 | awk '{SUM += $1} END { printf "%.2f", SUM }' )"
  for vdisk in $VDISKS ; do
    NAME="$( echo $vdisk | cut -d: -f1 )"
    SIZE="$( echo $vdisk | cut -d: -f2 | sed "s,^ ,," )"
    GB_SIZE="$( echo "$SIZE / 1024 / 1024 / 1024" | bc )"
    if [ $GB_SIZE -eq 0 ] ; then
      GB_SIZE="$( echo "scale=2; $SIZE / 1024 / 1024 / 1024" | bc )"
      GB_SIZE="${GB_SIZE/./0.}"
    fi
    echo "$NAME: ${GB_SIZE/./,} GB"
  done
  SUB_TOTAL_SYSTEM="$( echo "scale=2; $SYSTEM_TOTAL / 1024 / 1024 / 1024" | bc )"
  echo "SUB TOTAL: ${SUB_TOTAL_SYSTEM/./,} GB"
  echo
done

TOTAL="$( echo $DISK | sed "s, ,\n,g" | cut -d: -f2  | awk '{SUM += $1} END { printf "%.2f", SUM }' )"
TOTAL="$( echo "scale=2; $TOTAL / 1024 / 1024 / 1024" | bc ) GB"

echo "------------------------------------------------"
echo $TOTAL

exit 0

I gotta say, once again I learned a lot … two new things about awk!

I know the report itself doesn’t look *that* pretty, but it serves a purpose!