mar 18 2011

Obtenir une vision synthétique du stockage sous Linux avec une baie XP (HP).

Tag: ScriptsUggla @ 15 h 11 min

Un script perl qui combine les sorties de différents outils (xpinfo, multipath, mount) pour produire une vue complète du stockage disque.

Ce script fonctionne sur une machine Linux (RHEL5.5) avec une baie XP (HP).

Note : Ce script fonctionne mais peut probablement être grandement amélioré


#!/usr/bin/perl
# --------------------------------------------------------------------------------
# Script :   map.pl
# Revision : 1.1
# Author :   Rene Ribaud
# Description :
# --------------------------------------------------------------------------------
use strict;
use warnings;
#use diagnostics;   # Only use it for debugging purpose.

# --------------------------------------------------------------------------------
# Global variables
# --------------------------------------------------------------------------------
# Time
my ($sec,$min,$hour,$day,$month,$year,$wday,$yday,$isdst);
my $timestamp;

# Data
# Define a full structure
#my %mpaths =(
#        name =>{
#               size => undef,
#               uuid => undef,
#               dm => undef,
#               fs => undef,
#               disk =>         {
#                               diskname =>     {
#                                               port => undef,
#                                               lunid => undef,
#                                               sfnum => undef,
#                                               ldev => undef,
#                                               type => undef,
#                                               xp => undef,
#                                               },
#                               },
#               },
#        );

my %mpaths;

# --------------------------------------------------------------------------------
# Functions
# --------------------------------------------------------------------------------

# --------------------------------------------------------------------------------
# Main
# --------------------------------------------------------------------------------

# Get variable from command line

# Get timestamp
($sec,$min,$hour,$day,$month,$year,$wday,$yday,$isdst)=localtime();
$timestamp=sprintf("%4d%02d%02d-%02d:%02d:%02d",($year+1900),($month+1),$day,$hour,$min,$sec);

# Slurp tools data into arrays in memory
my @xpinfo=`xpinfo -i`;
my @multipath=`multipath -ll`;
my @mounts=`mount`;

for (my $line=0; $line<scalar(@multipath); $line++){
if ($multipath[$line] =~ /^mpath/){   # Check & parse line : mpath23 (360060e8015276a000001276a0000d0fc) dm-8 HP,OPEN-V
        (my $mpath, my $uuid, my $dm, my $type) = split ('\s+',$multipath[$line]);
        $uuid=~s/\(//g;
        $uuid=~s/\)//g;
        $mpaths{$mpath}->{"dm"}=$dm;
        $mpaths{$mpath}->{"uuid"}=$uuid;
        $mpaths{$mpath}->{"type"}=$type;
        # Crosscheck into mount to get the fs name
        # /dev/mapper/mpath14 on /oradata/crs/voting1 type ocfs2 (rw,_netdev,datavolume,nointr,heartbeat=local)
        my $fs;
        my @mount = grep(/$mpath\s/,@mounts);
        if (scalar(@mount==0)){
                $fs="N/A";
                }
                else
                {
                (undef,undef,$fs) = split('\s+',$mount[0]);
                }
        $mpaths{$mpath}->{"fs"}=$fs;

        # Next line to parse : [size=36G][features=1 queue_if_no_path][hwhandler=0][rw]
        $line++;
        if ($multipath[$line] =~ /^\[size=/){
                (my $size) = $multipath[$line] =~ /\[size=([0-9]+\w)/;
                $mpaths{$mpath}->{"size"}=$size;

                # Next line to parse : \_ round-robin 0 [prio=0][active]
                $line++;
                if ($multipath[$line] =~ /^\\_/){
                        # Next line to parse :  \_ 0:0:4:13 sdad 65:208 [active][ready]
                        $line++;
                        if ($multipath[$line] =~ /^ \\_/){
                                my $no_more_device=0;
                                do{
                                        (undef,undef,undef,my $disk, my $sf, undef) = split ('\s+',$multipath[$line]);
                                        $mpaths{$mpath}->{"disk"}->{$disk}->{"sfnum"}=$sf;
                                        # Crosscheck into xpinfo
                                        my @device = grep(/$disk\s/,@xpinfo);

                                        # Handle the case where device was not unmapped correctly
                                        # Unmapped from XP and not remoove from multipath.
                                        if (scalar(@device) == 0){
                                                $mpaths{$mpath}->{"disk"}->{$disk}->{"port"} = "Not found";
                                                $mpaths{$mpath}->{"disk"}->{$disk}->{"lunid"}= "N/A";
                                                $mpaths{$mpath}->{"disk"}->{$disk}->{"ldev"}= "N/A";
                                                $mpaths{$mpath}->{"disk"}->{$disk}->{"type"}= "N/A";
                                                $mpaths{$mpath}->{"disk"}->{$disk}->{"xp"}= "N/A";
                                        }
                                        else{
                                                #/dev/sdu                     76  04  02  CL2H  d0:f1  OPEN-V           00075626
                                                (undef,undef,undef, my $lunid, my $port, my $ldev, my $type, my $xp) = split('\s+',$device[0]);
                                                $mpaths{$mpath}->{"disk"}->{$disk}->{"port"}=$port;
                                                $mpaths{$mpath}->{"disk"}->{$disk}->{"lunid"}=$lunid;
                                                $mpaths{$mpath}->{"disk"}->{$disk}->{"ldev"}=$ldev;
                                                $mpaths{$mpath}->{"disk"}->{$disk}->{"type"}=$type;
                                                $mpaths{$mpath}->{"disk"}->{$disk}->{"xp"}=$xp;
                                        }
                                        if ((defined($multipath[$line+1])) && ($multipath[$line+1] =~ /^ \\_/)){
                                                $line++;
                                                }
                                                else {
                                                $no_more_device=1;
                                                }
                                        } while ($no_more_device==0);
                                }
                        }
                }
        }
}

# Print mapping
printf("%-34s %-9s %-7s %-6s %-6s %-8s %-6s %-6s %s\n","UUID","xp","type","size","dm","mapth","lunid","ldev","fs");
foreach my $mpath (sort(keys(%mpaths))){
        my @first_disk=keys(%{$mpaths{$mpath}->{"disk"}});
        # Check to report disk not unmapped correctly
        printf("%-34s %-9s %-7s %-6s %-6s %-8s %-6s %-6s %s\n"  ,$mpaths{$mpath}->{"uuid"}
                                                                ,$mpaths{$mpath}->{"disk"}->{$first_disk[0]}->{"xp"}
                                                                ,$mpaths{$mpath}->{"disk"}->{$first_disk[0]}->{"type"}
                                                                ,$mpaths{$mpath}->{"size"}
                                                                ,$mpaths{$mpath}->{"dm"}
                                                                ,$mpath
                                                                ,$mpaths{$mpath}->{"disk"}->{$first_disk[0]}->{"lunid"}
                                                                ,$mpaths{$mpath}->{"disk"}->{$first_disk[0]}->{"ldev"}
                                                                ,$mpaths{$mpath}->{"fs"}
                                                                );
        my $notfoundcount=0;
        foreach my $disk (keys(%{$mpaths{$mpath}->{"disk"}})){
                printf("%-6s %-8s %-4s\n",$disk,$mpaths{$mpath}->{"disk"}->{$disk}->{"sfnum"},$mpaths{$mpath}->{"disk"}->{$disk}->{"port"});

                if ($mpaths{$mpath}->{"disk"}->{$disk}->{"port"} eq "Not found"){
                        $notfoundcount++;
                        }

                if ($notfoundcount == scalar(keys(%{$mpaths{$mpath}->{"disk"}}))){
                        printf("This device was found in multipath but not reported by xpinfo.\n");
                        printf("Multipath device was probably not flushed after unmapping the device.\n");
                        printf("Try to run multipath -f %s.\n",$mpath);
                        }

                }

print "\n";
}

Output result :

UUID                               xp        type    size   dm     mapth    lunid  ldev   fs
360060e8015276a000001276a0000d0f1  00075626  OPEN-V  201M   dm-13  mpath14  02     d0:f1  /oradata/crs/voting1
sdai   66:32    CL1F
sdc    8:32     CL2F
sday   67:32    CL1H
sds    65:32    CL2H

360060e8015276a000001276a0000d0f2  00075626  OPEN-V  201M   dm-14  mpath15  03     d0:f2  /oradata/crs/voting2
sdd    8:48     CL2F
sdaz   67:48    CL1H
sdaj   66:48    CL1F
sdt    65:48    CL2H

360060e8015276a000001276a0000d0f3  00075626  OPEN-V  201M   dm-15  mpath16  04     d0:f3  /oradata/crs/voting3
sde    8:64     CL2F
sdu    65:64    CL2H
sdba   67:64    CL1H
sdak   66:64    CL1F

360060e8015276a000001276a0000d0f4  00075626  OPEN-V  201M   dm-16  mpath17  05     d0:f4  /oradata/GFSTEUR1/pfile
sdal   66:80    CL1F
sdv    65:80    CL2H
sdbb   67:80    CL1H
sdf    8:80     CL2F

360060e8015276a000001276a0000d0f5  00075626  OPEN-V  36G    dm-17  mpath18  06     d0:f5  /oradata/GFSTEUR1/undo
sdg    8:96     CL2F
sdbc   67:96    CL1H
sdw    65:96    CL2H
sdam   66:96    CL1F

360060e8015276a000001276a0000d0f8  00075626  OPEN-V  99G    dm-18  mpath19  09     d0:f8  /oradata/RMAN/rman01
sdh    8:112    CL2F
sdan   66:112   CL1F
sdbd   67:112   CL1H
sdx    65:112   CL2H
...