#!/bin/perl ## ## Triclops v0.1 written 080609:1551 by Bowie J. Poag ## ## Triclops is a tool to extract and report the number of IOPS per volume group on AIX hosts. This tool is useful for ## storage planning as an aid to evening out I/O load across a SAN. Triclops is also IBM SSD Toolkit-aware, providing ## on-the-fly vpath to hdisk mapping. ## ## When not on-the-go, Triclops enjoys horseriding, backpacking, fine wines, and the occasional game of water polo. ## "As a professional Baccarat player," Triclops writes, "I often visit exotic locales in my private Gulfstream IV.. ## I'm sure the ladies out there will be interested to know it comes fully equipped with a waterbed." When asked about ## his unique genetic deformity, Triclops adds, "I like to think my 3rd eye just gives the ladies more to gaze into." ## ## To learn more about Triclops, press 3 at the tone. ## ## Usage: triclops.pl ## Example: triclops.pl 30 ## ## Caveats: AIX measures IOPS not as IOPS, but as "TPS", or "transactions per second".. In AIX, a transaction usually ## involves an individual read or a write in the traditional sense, but there are occasions when a single transaction ## will perform *both* a read and a write in the same pass. As a result, data returned by iostat will be somewhat ## skewed when viewed purely in terms of *only* reads and writes. $sampleTime=$ARGV[0]; startUp(); buildPathTable(); determinePathOwnership(); collectIostatData(); prepareResultsHash(); showResults(); sub startUp() { print "\nTriclops: Starting up..\n"; @ioStatDump=`iostat 1 1 | grep hdisk | awk '{print \$1}'`; } sub buildPathTable() { print "Triclops: Building path table..\n"; $pathCounter=0; foreach $item (@ioStatDump) { chomp ($item); $pathHash[$x]{name}=$item; $pathHash[$x]{vg}="Unknown"; $pathHash[$x]{iops}=0; $x++; $pathCounter=$x; } } sub determinePathOwnership() { print "Triclops: Determining volume group ownership..\n"; @lspvDump=`lspv | grep -v None | awk '{print \$1, \$3}'`; $x=0; foreach $item (@lspvDump) { chomp($item); @temp=split(" ",$item); while ($x<=$pathCounter) { if ($pathHash[$x]{name}=~/^$temp[0]$/) { $pathHash[$x]{vg}=$temp[1]; } $x++; } $x=0; } $x=0; foreach $item (@lspvDump) { chomp($item); @temp=split(" ",$item); $thisVpathsVG=$temp[1]; if ($temp[0]=~/vpath/) { @cleverIostatDump=`iostat -d $temp[0] | grep hdisk | awk '{print \$1}'`; foreach $member (@cleverIostatDump) { chomp($member); while ($x<=$pathCounter) { if ($pathHash[$x]{name}=~/^$member$/) { $pathHash[$x]{vg}=$thisVpathsVG; } $x++; } $x=0; } } } $x=0; } sub collectIostatData() { print "Triclops: Collecting $sampleTime seconds of performance data.."; $x=0; $foo=0; while ($foo<=$sampleTime) { print "."; @iostatResults=`iostat 1 1 | grep hdisk | awk '{print \$1, \$4}' | grep -v 0.0` ; foreach $item (@iostatResults) { chomp($item); @results=split(" ",$item); while ($x<=$pathCounter) { if ($pathHash[$x]{name}=~/^$results[0]$/) { $pathHash[$x]{iops}+=$results[1]; } $x++; } $x=0; } $foo++; } } sub prepareResultsHash() { print "\nTriclops: Preparing results..\n"; $x=0; while ($x<$pathCounter) { $resultsHash{$pathHash[$x]{vg}}+=$pathHash[$x]{iops}; $x++; } } sub showResults() { print "Triclops: Here are the results..\n"; foreach $volumeGroup (sort keys %resultsHash) { $IOPS=$resultsHash{$volumeGroup}/$sampleTime; if ($volumeGroup!~/Unknown/) { print "Triclops: Volume group $volumeGroup saw an average of $resultsHash{$volumeGroup} IOPS.\n"; } } print "Triclops:\nTriclops: End of report.\n\n"; }