#!/usr/bin/perl -w # @(#) create a report relating eva storage to Volume Groups #..# systems: #..# sites: #..# level: #..# publish: y #..# keys: #..# date: Fri Feb 3 08:50:08 GMT 2006 #..# vers: 1.6 04/Aug/2006-08:30 my $debug; my $verbose; my $this = $0; my $tag = $this; $tag =~ s!^.*/!!; my $hba; my $pref; my $status; my $dbf = 0; $netdata = "$home/netdata" if -d "$home/netdata/data/spmgr"; $netdata = "/var/adm/netdata" if -d "/var/adm/netdata/data/spmgr"; $netdata = $ENV{'NETDATA'} if defined($ENV{'NETDATA'}); $reportd = "/var/adm/EVAconfig" if -d "/var/adm/EVAconfig"; $evadmin = "/usr/local/bin/evadmin"; $usage = " Usage: $tag [-xl] [-d ] [ -o ] [-e ] "; $help = qq($tag combines data from an EVA disc array with the outputs of the pvdisplay and spmgr display commands run on the hosts to which EVA storage is presented into a report detailing the VG usage of each EVA vdisk. Other and intermediate information is also included. The output consists of columns detailing: the command-EVA folder the vdisk is found in: the name of the vdisk: the type of Raid: the size in GB: the data the vdisk was created: the wwid (7th group of 4 digits of the WWLunName - generally sufficient): the presentation host: the Lun of the presentation to that host: the first rscsi device listed by spmgr for that wwid: the hardware address of the fibre card the EVA is seen through on that host: the Target/Lun reported by spmgr on that host: the device in /dev/dsk on which spmgr makes the lun available: any VG that includes the above device: When a vdisk is presented to more than one host, the line is repeated with the apprpriate different data in the last 7 columns. -xl - causes the o/p to be tab delimited suitable for eXcel import. -d - $tag uses data from other hosts. It expects this data to be in a 'data' tree at . Do 'data -h' for details. This defaults to $netdata. -e - $tag uses the 'evadmin' script to extract the data from the EVA. If this is not at $evadmin then specify the path with -e. ); my $whenImplemented; $whenImplemented = qq( -o - If specified, o/p is to and .xls. ); sub vi() { qx(/usr/bin/ksh -c ". ~/.profile; \ lockvi $this" /dev/tty 2>&1); } sub dbg() { qx(/usr/bin/perl -d $this @ARGV /dev/tty 2>&1); } use Data::Dumper; if (defined $ENV{'home'}) { $home = $ENV{'home'} } elsif (defined $ENV{'HOME'}) { $home = $ENV{'HOME'} } $xl = 0; $fmt="%-14s %-21s %6s %3d %21s %-5s %-6s %3d %7s %1s/%1s %-13s %-7s %s\n"; $dbfmt="%-14s %-21s %6s %3d %-5s %-6s %3d %-7s %-8s %s\n"; $fulwwnfmt="%-14s %-21s %6s %3d %21s %-40s %-6s %3d %7s %1s/%1s %-13s %-7s %s\n"; while (defined($ARGV[0]) && ($_ = $ARGV[0], /^-/)) { shift; last if /^--$/; $debug = 1, next if /^-D(.*)/; vi, exit if /^-vi/; dbg, exit if /^-dbg/; if (/^-D(.*)/) { $debug = $1 } if (/^-v/) { $verbose++ } if (/^-h/) { print STDERR "$usage\n$help\n"; exit } if (/^-b/) { $fmt = $dbfmt; $dbf = 1 } if (/^-xl/i) { $xl = 1 } if (/^-w/) { $wwn = 1; $fmt = $fulwwnfmt; } if (/^-e/) { $evadmin = shift @ARGV or die "$usage\n"; -x $evadmin || die "$evadmin not found or not executable"; } if (/^-d/) { $netdata = shift @ARGV or die "$usage\n"; -d $netdata || die "$usage\n$netdata/ not found"; } if (/^-o/) { $reportd = shift @ARGV or die "$usage\n"; -d $reportd || die "$usage\n$reportd/ not found"; } if (/^-t/) { $fmt =~ s/([0-9]+)s/$1.$1s/g; $fmt =~ s/%([0-9]+)d/%-$1d/g; $m = '1234567890123456789012345678901234567890'; $tabs = sprintf($fmt, $m, $m, $m, 1, $m, $m, $m, 1, $m, $m, 2, $m, $m, $m, $m); my $tab = index($tabs, " 1", 1); print "$tab"; while ($tab >= 0) { $tab = index($tabs, " 1", $tab + 1); print ",$tab" if $tab > 0; } print "\n"; exit; } } $fmt =~ s/ /\t/g if $xl; -x $evadmin || die "$evadmin not found or not executable"; die "No value for 'netdata'" unless defined $netdata; -d $netdata || die "Directory for spmgr reports ($netdata) not found"; $pvd = $netdata . '/data/pvdisplay'; for $hostf (glob $pvd . '/*') { $host = $hostf; $host =~ s!.*/!!; next if $host eq 'core'; open(PV, "$hostf"); while () { chomp; next unless /^.. Name/; ($entry, undef, $value) = split; $value =~ s!.*/!!; $pv = $value, next if $entry eq 'PV'; $pvmap{$host}{$pv} = $value; } close(PV); } $bdf = $netdata . '/data/bdf'; for $hostf (glob $bdf . '/*') { $host = $hostf; $host =~ s!.*/!!; next if $host eq 'core'; open(BDF, "$hostf"); while () { chomp; next unless /^\//; @bdf = split; $device = shift @bdf; $device =~ s!.*/!!; $mp{$device} = pop @bdf; } close(BDF); } $spmgrd = $netdata . '/data/spmgr'; for $hostf (glob $spmgrd . '/*') { $host = $hostf; $host =~ s!.*/!!; next if $host eq 'core'; open(SPMGR, "$hostf"); $lu = -1; $sec = -1; while () { chomp; s/^\W*//; next if /^$/; next if /^Server:/; next if /^Command:/; next if /^Storage:/; next if /^Load Balance:/; next if /^Path Verify:/; next if /^HBAs:/; next if /^Devices:/; next if /^Controller/; next if /^[A-Z0-9]{14}/; $lu++, $sec = 0, next if m!TGT/LUN!; if (/([0-9A-F]{4}-){7}0000/) { ($tgt, $lun, $dev, $wwln, undef) = split; $lun{$host}[$lu]{'target'} = substr($tgt, 0, -1); $lun{$host}[$lu]{'lun'} = $lun; $lun{$host}[$lu]{'dev'} = $dev; $lun{$host}[$lu]{'wwln'} = $wwln; $wwid = lc(substr($wwln, 30, 4)); $lun{$host}[$lu]{'wwid'} = $wwid; $wwix{$host}{$wwid} = $lu; $sec++; next; } $lun{$host}[$lu]{'hwpath'} = $_, next if m!255/255/!; if (($sec > 0) && (/c[0-9]{1,2}t[0-9]{1,2}d[0-9]{1,2}/)) { ($rscsi, $hba, $pref, $status) = split; push @{$lun{$host}[$lu]{'rscsi'}}, $rscsi; $sec++; next } next if /^(c[0-9]{1,2}t[0-9]d[0-9] *)+$/; print "spmgr -> $_\n"; } close(SPMGR); } open(EVA, "$evadmin show vdisk |"); $vdisk = -1; while () { #print; chomp; s/^\W*//; next if $_ eq 'Attributes:'; next if $_ eq 'DR_Attributes:'; next if $_ eq 'Remote_VDisk:'; next if $_ eq 'Condition_State:'; next if $_ eq 'Date Time:'; next if $_ eq 'Vdisks available on this Cell:'; next if $_ =~ '^Virtual .* information:$'; $vdisk++, next if $_ eq 'Identification:'; ($item, $value) = split / : /; $incomment = 0 if defined $value; if ($item eq 'Name') { unless ($value =~ /ACTIVE$/) { $line = readline EVA; $line =~ s/^\s*/ /; $value .= $line; } $vdisk[$vdisk]{'fullname'} = $value; $value =~ s!^\\*[^\\]*\\*!!; $value =~ s!\\*ACTIVE!!; $vdisk[$vdisk]{'name'} = $value; next; } $vdisk[$vdisk]{'familyname'} = $value, next if $item eq 'Family_Name'; $vdisk[$vdisk]{'size'} = $value, next if $item eq 'Capacity_Req'; $vdisk[$vdisk]{'raid'} = $value, next if $item eq 'Redundancy'; $vdisk[$vdisk]{'id'} = $value, next if $item eq 'ID'; $vdisk[$vdisk]{'date'} = $value, next if $item eq 'Created'; if ($item eq 'World_Wide_Lun_Name') { $vdisk[$vdisk]{'wwn'} = $value; $vdisk[$vdisk]{'wwid'} = substr($value, 30, 4); next; } ($undef, $idx, $undef) = split(/[][]/, $item), next if $item =~ /^Presentation /; $vdisk[$vdisk]{'present'}[$idx]{'client'} = $value, next if $item eq "StorageClientName"; $vdisk[$vdisk]{'present'}[$idx]{'lun'} = $value, next if $item eq "Lun"; $incomment = 1, next if $item eq "Comments"; if (! defined $value && $incomment == 1) { next } print "evadmin -> $_\n" unless defined $value; } close(EVA); $dbs = $netdata . '/data/dbs'; for $hostf (glob $dbs . '/*') { $host = $hostf; $host =~ s!.*/!!; next if $host eq 'core'; open(DBS, "$hostf"); while () { #print; chomp; @dbs = split; $sid = shift @dbs; $vg = pop @dbs; @vgs = split(/,/, $vg); for $vg (@vgs) { next if $vg eq '-'; push @{$db{$host}{$vg}}, $sid unless defined($dbk{$host}{$vg}{$sid}); $dbk{$host}{$vg}{$sid} = 1; } #printf("%s\t%s\t%s\n", $host, $sid, $vg); } close(DBS); } ($hfmt = $fmt) =~ s/d/s/g; if ($dbf) { printf($hfmt, "EVA folder", "Name", "Raid", "GB", "ww id", "Pres", "Lun", "Device", "VG", "DBs"); } else { printf($hfmt, "EVA folder", "Name", "Raid", "GB", "Created", "ww id", "Pres", "Lun", "rscsi", "T", "L", "H/Waddr", "Device", "VG"); } for $disk (sort @vdisk) { $alloc = $disk->{'name'}; $alloc =~ s/\\+[^\\]+$//; $presnts = $disk->{'present'}; print STDERR "$disk->{'familyname'} $disk->{'name'} unused\n", next unless defined($presnts); for $pres (sort( @{ $presnts } )) { $host = $pres->{'client'}; $host =~ s/.*\\//; if (defined($lun{$host}) && defined($wwix{$host}) && defined($disk->{'wwid'})) { if (defined($wwix{$host}{$disk->{'wwid'}})) { $devx = $wwix{$host}{$disk->{'wwid'}}; if (defined($pvmap{$host}{$lun{$host}[$devx]->{'dev'}})) { $vg = $pvmap{$host}{$lun{$host}[$devx]->{'dev'}}; } elsif (defined($mp{$lun{$host}[$devx]->{'dev'}})) { $vg = $mp{$lun{$host}[$devx]->{'dev'}}; } } elsif ((-f "$netdata/data/lvmtab.strings/$host") && (qx(grep $lun{$host}[$devx]->{'dev'} $netdata/data/lvmtab.strings/$host))) { $vg = "?? error ??"; } else { $vg = "-X-"; } } elsif ((-f "$netdata/data/lvmtab.strings/$host") && (qx(grep $lun{$host}[$devx]->{'dev'} $netdata/data/lvmtab.strings/$host))) { $vg = "?? error ??"; } else { $vg = "-X-"; } if ($dbf) { printf($fmt, $alloc, $disk->{'familyname'}, $disk->{'raid'}, $disk->{'size'}, $disk->{'wwid'}, $host, $pres->{'lun'}, exists($lun{$host}[$devx]->{'dev'}) ? $lun{$host}[$devx]->{'dev'} : "", defined($vg) ? $vg : "", (defined($vg) && defined($db{$host}{$vg})) ? join(',', @{ $db{$host}{$vg} }) : "", ); } elsif ($wwn) { printf($fmt, $alloc, $disk->{'familyname'}, $disk->{'raid'}, $disk->{'size'}, $disk->{'date'}, $disk->{'wwn'}, $host, $pres->{'lun'}, exists($lun{$host}[$devx]->{'rscsi'}[0]) ? $lun{$host}[$devx]->{'rscsi'}[0] : "", exists($lun{$host}[$devx]->{'target'}) ? $lun{$host}[$devx]->{'target'} : "", exists($lun{$host}[$devx]->{'lun'}) ? $lun{$host}[$devx]->{'lun'} : "", exists($lun{$host}[$devx]->{'hwpath'}) ? $lun{$host}[$devx]->{'hwpath'} : "", exists($lun{$host}[$devx]->{'dev'}) ? $lun{$host}[$devx]->{'dev'} : "", defined($vg) ? $vg : "", ); } else { printf($fmt, $alloc, $disk->{'familyname'}, $disk->{'raid'}, $disk->{'size'}, $disk->{'date'}, $disk->{'wwid'}, $host, $pres->{'lun'}, exists($lun{$host}[$devx]->{'rscsi'}[0]) ? $lun{$host}[$devx]->{'rscsi'}[0] : "", exists($lun{$host}[$devx]->{'target'}) ? $lun{$host}[$devx]->{'target'} : "", exists($lun{$host}[$devx]->{'lun'}) ? $lun{$host}[$devx]->{'lun'} : "", exists($lun{$host}[$devx]->{'hwpath'}) ? $lun{$host}[$devx]->{'hwpath'} : "", exists($lun{$host}[$devx]->{'dev'}) ? $lun{$host}[$devx]->{'dev'} : "", defined($vg) ? $vg : "", ); } $vg = "?? error ??"; } } print Dumper(@vdisk) if $debug; print Dumper(%wwix) if $debug; print Dumper(%lun) if $debug; print Dumper(%pvmap) if $debug; print Dumper(%mp) if $debug;