Subversion Repositories camp_sysinfo_client_3

Rev

Rev 157 | Rev 169 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
152 rodolico 1
#!/usr/bin/env perl
2
use warnings;
165 rodolico 3
use strict;
4
use Data::Dumper;
152 rodolico 5
 
6
# Description: Use smartctl to get disk information
7
 
165 rodolico 8
our $VERSION = '2.0';
152 rodolico 9
 
10
# R. W. Rodolico
11
# grabs smart readings from all drives in system
157 rodolico 12
# note that in the case of some hardware RAID controller, will list the components of a "drive" and the drive itself,
13
# so you may have up to twice the number of entries than you have physical drives, for example, if you have a megaraid
14
# controller where each physical drive is also a single logical drive.
152 rodolico 15
 
165 rodolico 16
# find our location and use it for searching for libraries
152 rodolico 17
BEGIN {
165 rodolico 18
   use FindBin;
19
   use File::Spec;
20
   use lib File::Spec->catdir($FindBin::Bin);
21
   use library;
152 rodolico 22
}
23
 
165 rodolico 24
exit 0 unless checkDate( 'm' ); # run this only on first of month
152 rodolico 25
 
165 rodolico 26
my %ignoreDriveTypes = ( # a list of drive "types" used by virtuals that we just ignore.
27
         'VBOX HARDDISK' => 1,
28
         );
152 rodolico 29
 
30
 
165 rodolico 31
sub getSmartInformationReport {
157 rodolico 32
   my ($drive, $type) = @_;
165 rodolico 33
   $type = '' if ( $type =~ m/scsi/ );
34
   my @report = `smartctl -i $drive $type`;
157 rodolico 35
   chomp @report;
165 rodolico 36
   my %reportHash;
37
   for ( my $i = 0; $i < @report; $i++ ) {
38
      if ( $report[$i] =~ m/^(.*):(.*)$/ ) {
39
         $reportHash{$1} = trim($2);
40
      }
41
   }
42
   return \%reportHash;
43
} # getSmartInformationReport
44
 
45
sub getSmartAttributeReport {
46
   my ($drive, $type) = @_;
47
   $type = '' if ( $type =~ m/scsi/ );
48
   my @report = `smartctl -A $drive $type`;
49
   chomp @report;
50
   my %reportHash;
51
   my %headers;
52
   # bypass all the header information
53
   my $i;
54
   for ( $i = 0; $i < @report && $report[$i] !~ m/^ID#/; $i++ ) {}
55
   if ( $i < @report ) { # did we get an actual report? some drives will not give us one
56
      my $char = 0;
57
      while ( $char < length($report[$i]) ) {
58
         substr( $report[$i],$char ) =~ m/^([^ ]+\s*)/;
59
         my $header = $1;
60
         my $start = $char;
61
         my $length = length($header);
62
         if ( $header = &trim( $header ) ) {
63
            $headers{$header}{'start'} = $start;
64
            $headers{$header}{'length'} = $length-1;
65
         }
66
         $char += $length;
67
      }
68
      while ( ++$i < @report ) {
69
         last unless $report[$i];
70
         my $id = &trim(substr( $report[$i], $headers{'ID#'}{'start'}, $headers{'ID#'}{'length'} ));
71
         my $name = &trim(substr( $report[$i], $headers{'ATTRIBUTE_NAME'}{'start'}, $headers{'ATTRIBUTE_NAME'}{'length'} ));
72
         my $value = &trim(substr( $report[$i], $headers{'RAW_VALUE'}{'start'} ));
73
         $reportHash{$id}{'value'} = $value;
74
         $reportHash{$id}{'name'} = $name;
75
      }
76
   }
77
   #print Dumper( \%reportHash ); die;
78
   return \%reportHash;
152 rodolico 79
}
80
 
81
 
165 rodolico 82
sub getAttributes {
83
   my ($report,$sectorSize) = @_;
84
   my %reportHash;
85
   # first let's get total disk writes
86
   if ( defined( $report->{'241'} ) ) {
87
      $sectorSize =~ m/^(\d+)/;
88
      $reportHash{'writes'} = $report->{'241'} * $sectorSize;
89
   }
90
   # find total uptime
91
   if ( defined( $report->{'9'} ) ) {
92
      $report->{'9'}->{'value'} =~ m/^(\d+)/;
93
      $reportHash{'uptime'} = $1;
94
   }
95
   return \%reportHash;
152 rodolico 96
}
97
 
98
sub getInformation {
165 rodolico 99
   my $report = shift;
152 rodolico 100
   my %info;
101
   my %keys = ( 
165 rodolico 102
                  'Model Family'  => { 
152 rodolico 103
                                          'tag' => 'Make',
104
                                          'regex' => '(.*)'
105
                                      },
165 rodolico 106
                  'Device Model'  => { 
152 rodolico 107
                                          'tag' => 'Model',
108
                                          'regex' => '(.*)'
109
                                      },
165 rodolico 110
                  'Serial number' => { 
157 rodolico 111
                                          'tag' => 'Serial',
112
                                          'regex' => '(.*)'
113
                                      },
165 rodolico 114
                  'Serial Number' => { 
152 rodolico 115
                                          'tag' => 'Serial',
116
                                          'regex' => '(.*)'
117
                                      },
165 rodolico 118
                  'User Capacity' => { 
152 rodolico 119
                                          'tag' => 'Capacity',
120
                                          'regex' => '([0-9,]+)'
121
                                      },
165 rodolico 122
                  'Logical block size' =>{ 
157 rodolico 123
                                          'tag' => 'Sector Size',
124
                                          'regex' => '(\d+)'
125
                                      },
165 rodolico 126
                  'Sector Size'   => { 
152 rodolico 127
                                          'tag' => 'Sector Size',
128
                                          'regex' => '(\d+)'
129
                                      },
165 rodolico 130
                  'Rotation Rate' => { 
152 rodolico 131
                                          'tag' => 'Rotation',
132
                                          'regex' => '(.*)'
165 rodolico 133
                                      },
152 rodolico 134
               );
135
   foreach my $key ( keys %keys ) {
165 rodolico 136
      if ( defined( $report->{$key} ) && $report->{$key} =~ m/$keys{$key}->{'regex'}/ ) {
152 rodolico 137
         $info{$keys{$key}->{'tag'}} = $1;
138
      }
139
   }
140
   # remove comma's from capacity
141
   $info{'Capacity'} =~ s/,//g if $info{'Capacity'};
142
   return \%info;
143
}
144
 
145
 
146
 
147
# category we will use for all values found
148
# see sysinfo for a list of valid categories
157 rodolico 149
my $CATEGORY = 'attributes';
152 rodolico 150
 
151
# run the commands necessary to do whatever you want to do
152
# The library entered above has some helper routines
153
# validCommandOnSystem -- passed a name, returns the fully qualified path or '' if it does not exist
154
# cleanUp - passed a delimiter and a string, does the following (delimiter can be '')
155
#           chomps the string (removes trailing newlines)
156
#           removes all text BEFORE the delimiter, the delimiter, and any whitespace
157
#           thus, the string 'xxI Am x  a weird string' with a newline will become
158
#           'a weird string' with no newline
159
 
160
# now, return the tab delimited output (to STDOUT). $CATEGORY is the first
161
# item, name as recognized by sysinfo is the second and the value is
162
# the last one. For multiple entries, place on separate lines (ie, newline separated)
163
 
164
# check for commands we want to run
165
my %commands = ( 
166
                  'smartctl' => '',
167
               );
168
 
169
# check the commands for validity
170
foreach my $command ( keys %commands ) {
171
   $commands{$command} = &validCommandOnSystem( $command );
172
}
173
 
174
# bail if we don't have the commands we need
157 rodolico 175
exit 1 unless $commands{'smartctl'};
152 rodolico 176
 
177
# Get all the drives on the system
157 rodolico 178
my %allDrives = map { $_ =~ '(^[a-z0-9/]+)\s+(.*)\#'; ($1,$2) } `smartctl --scan`;
152 rodolico 179
 
157 rodolico 180
#foreach my $key ( keys %allDrives ) { print "$key\t$allDrives{$key}\n"; } die;
152 rodolico 181
 
182
# output the drives and information as tab delimited,
183
foreach my $thisDrive ( sort keys %allDrives ) {
153 rodolico 184
 #print "$thisDrive\n";
157 rodolico 185
 print "$CATEGORY\t$thisDrive Type\t$allDrives{$thisDrive}\n";
165 rodolico 186
 my $informationReport = &getSmartInformationReport( $thisDrive, $allDrives{$thisDrive} );
187
 my $info = &getInformation( $informationReport );
188
 # if this is not a virtual device, get smart attributes also
189
 if ( ! defined( $ignoreDriveTypes{ $info->{'Model'} } ) ) {
190
    #print Dumper( $info ); die;
191
    my $attributesReport = &getSmartAttributeReport( $thisDrive, $allDrives{$thisDrive} );
192
    my $attributes = &getAttributes( $attributesReport, $info->{'Sector Size'} );
193
    #print Dumper( $attributes ); die;
194
    $info = { %$info, %$attributes };
195
    #print Dumper( $info ); die;
196
 }
152 rodolico 197
 foreach my $key ( keys %$info ) {
198
    print "$CATEGORY\t$thisDrive $key\t" . $info->{$key} . "\n";
199
 }
200
}
201
 
202
exit 0;