Subversion Repositories camp_sysinfo_client_3

Rev

Rev 165 | Rev 170 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 165 Rev 169
Line 1... Line 1...
1
#!/usr/bin/env perl
1
#!/usr/bin/env perl
2
use warnings;
2
use warnings;
3
use strict;
3
use strict;
4
use Data::Dumper;
4
use Data::Dumper;
5
 
5
 
6
# Description: Use smartctl to get disk information
6
# Description: Use smartctl, lsblk and geom to get disk information
-
 
7
# will decode lsblk first. Then use geom to get information on BSD systems
-
 
8
# finally, smartctl will be used to gather additional information.
7
 
9
 
-
 
10
# 20200224 RWR v2.1
-
 
11
# large re-organization of code and inclusion to get basic information from lsblk if it is on the system
-
 
12
 
8
our $VERSION = '2.0';
13
our $VERSION = '2.1';
9
 
14
 
10
# R. W. Rodolico
15
# R. W. Rodolico
11
# grabs smart readings from all drives in system
16
# grabs smart readings from all drives in system
12
# note that in the case of some hardware RAID controller, will list the components of a "drive" and the drive itself,
17
# 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
18
# so you may have up to twice the number of entries than you have physical drives, for example, if you have a megaraid
Line 21... Line 26...
21
   use library;
26
   use library;
22
}
27
}
23
 
28
 
24
exit 0 unless checkDate( 'm' ); # run this only on first of month
29
exit 0 unless checkDate( 'm' ); # run this only on first of month
25
 
30
 
-
 
31
my %driveDefinitions; # this will be a global that everything will put info into
-
 
32
 
26
my %ignoreDriveTypes = ( # a list of drive "types" used by virtuals that we just ignore.
33
my %ignoreDriveTypes = ( # a list of drive "types" used by virtuals that we just ignore.
27
         'VBOX HARDDISK' => 1,
34
         'VBOX HARDDISK' => 1,
28
         );
35
         );
29
 
36
 
30
 
37
 
-
 
38
# acquires information using lsblk, if it is available
-
 
39
# uses global %driveDefinitions to store the results
-
 
40
 
-
 
41
sub lsblk {
-
 
42
   eval ( 'use JSON qw( decode_json );' );
-
 
43
   if ( $@ ) {
-
 
44
      warn "Could not load JSON library\n";    
-
 
45
      return;
-
 
46
   }
-
 
47
   
-
 
48
   my $output = qx'lsblk -bdJO 2>/dev/null';
-
 
49
   # older versions do not have the O option, so we'll run it without
-
 
50
   $output = qx'lsblk -bdJ 2>/dev/null' if $?;
-
 
51
   my $drives = decode_json( join( '', $output ) );
-
 
52
   $drives = $drives->{'blockdevices'};
-
 
53
   while ( my $thisDrive = shift @{$drives} ) {
-
 
54
      if ( $thisDrive->{'type'} eq 'disk' ) {
-
 
55
         my $key = '/dev/' . $thisDrive->{'name'};
-
 
56
         $driveDefinitions{$key}{'Capacity'} = $thisDrive->{'size'};
-
 
57
         $driveDefinitions{$key}{'Model'} = $thisDrive->{'model'} if defined $thisDrive->{'model'};
-
 
58
         $driveDefinitions{$key}{'Serial'} = $thisDrive->{'serial'} if defined $thisDrive->{'serial'};
-
 
59
      }
-
 
60
   }
-
 
61
}
-
 
62
 
-
 
63
 
31
sub getSmartInformationReport {
64
sub getSmartInformationReport {
32
   my ($drive, $type) = @_;
65
   my ($drive, $type) = @_;
33
   $type = '' if ( $type =~ m/scsi/ );
66
   $type = '' if ( $type =~ m/scsi/ );
34
   my @report = `smartctl -i $drive $type`;
67
   my @report = `smartctl -i $drive $type`;
35
   chomp @report;
68
   chomp @report;
Line 78... Line 111...
78
   return \%reportHash;
111
   return \%reportHash;
79
}
112
}
80
 
113
 
81
 
114
 
82
sub getAttributes {
115
sub getAttributes {
83
   my ($report,$sectorSize) = @_;
116
   my ($drive,$type,$sectorSize) = @_;
-
 
117
 
84
   my %reportHash;
118
   my $report = &getSmartAttributeReport( $drive, $type );
-
 
119
 
85
   # first let's get total disk writes
120
   # first let's get total disk writes
86
   if ( defined( $report->{'241'} ) ) {
121
   if ( defined( $report->{'241'} ) ) {
87
      $sectorSize =~ m/^(\d+)/;
122
      $sectorSize =~ m/^(\d+)/;
88
      $reportHash{'writes'} = $report->{'241'} * $sectorSize;
123
      $driveDefinitions{$drive}{'writes'} = $report->{'241'} * $sectorSize;
89
   }
124
   }
90
   # find total uptime
125
   # find total uptime
91
   if ( defined( $report->{'9'} ) ) {
126
   if ( defined( $report->{'9'} ) ) {
92
      $report->{'9'}->{'value'} =~ m/^(\d+)/;
127
      $report->{'9'}->{'value'} =~ m/^(\d+)/;
93
      $reportHash{'uptime'} = $1;
128
      $driveDefinitions{$drive}{'uptime'} = $1;
94
   }
129
   }
95
   return \%reportHash;
-
 
96
}
130
}
97
 
131
 
98
sub getInformation {
132
sub getInformation {
99
   my $report = shift;
133
   my ($drive, $type) = @_;
-
 
134
 
-
 
135
   my $report = &getSmartInformationReport( $drive, $type );
-
 
136
 
100
   my %info;
137
   my %info;
101
   my %keys = ( 
138
   my %keys = ( 
102
                  'Model Family'  => { 
139
                  'Model Family'  => { 
103
                                          'tag' => 'Make',
140
                                          'tag' => 'Make',
104
                                          'regex' => '(.*)'
141
                                          'regex' => '(.*)'
Line 132... Line 169...
132
                                          'regex' => '(.*)'
169
                                          'regex' => '(.*)'
133
                                      },
170
                                      },
134
               );
171
               );
135
   foreach my $key ( keys %keys ) {
172
   foreach my $key ( keys %keys ) {
136
      if ( defined( $report->{$key} ) && $report->{$key} =~ m/$keys{$key}->{'regex'}/ ) {
173
      if ( defined( $report->{$key} ) && $report->{$key} =~ m/$keys{$key}->{'regex'}/ ) {
137
         $info{$keys{$key}->{'tag'}} = $1;
174
         $driveDefinitions{$drive}{$keys{$key}->{'tag'}} = $1;
138
      }
175
      }
139
   }
176
   }
-
 
177
}
-
 
178
 
-
 
179
sub smartctl {
140
   # remove comma's from capacity
180
   # Get all the drives on the system
-
 
181
   my %allDrives = map { $_ =~ '(^[a-z0-9/]+)\s+(.*)\#'; ($1,$2) } `smartctl --scan`;
-
 
182
 
141
   $info{'Capacity'} =~ s/,//g if $info{'Capacity'};
183
   # output the drives and information as tab delimited,
-
 
184
   foreach my $thisDrive ( sort keys %allDrives ) {
-
 
185
      $driveDefinitions{$thisDrive}{'type'} = $allDrives{$thisDrive};
-
 
186
      &getInformation( $thisDrive, $allDrives{$thisDrive} );
-
 
187
      #print Dumper( $info ); die;
-
 
188
      my $attributes = &getAttributes( $thisDrive, $allDrives{$thisDrive}, $driveDefinitions{$thisDrive}{'Sector Size'} );
-
 
189
      #print Dumper( $attributes ); die;
142
   return \%info;
190
      #print Dumper( $info ); die;
-
 
191
   }
-
 
192
   
143
}
193
}
144
 
194
 
145
 
195
 
146
 
196
 
147
# category we will use for all values found
197
# category we will use for all values found
Line 162... Line 212...
162
# the last one. For multiple entries, place on separate lines (ie, newline separated)
212
# the last one. For multiple entries, place on separate lines (ie, newline separated)
163
 
213
 
164
# check for commands we want to run
214
# check for commands we want to run
165
my %commands = ( 
215
my %commands = ( 
166
                  'smartctl' => '',
216
                  'smartctl' => '',
-
 
217
                  'lsblk' => '',
-
 
218
                  'geom' => '',
167
               );
219
               );
168
 
220
 
169
# check the commands for validity
221
# check the commands for validity
170
foreach my $command ( keys %commands ) {
222
foreach my $command ( keys %commands ) {
171
   $commands{$command} = &validCommandOnSystem( $command );
223
   $commands{$command} = &validCommandOnSystem( $command );
172
}
224
}
173
 
225
 
174
# bail if we don't have the commands we need
226
# bail if we don't have the commands we need
175
exit 1 unless $commands{'smartctl'};
227
exit 1 unless $commands{'smartctl'} || $commands{'lsblk'} || $commands{'geom'};
176
 
-
 
177
# Get all the drives on the system
-
 
178
my %allDrives = map { $_ =~ '(^[a-z0-9/]+)\s+(.*)\#'; ($1,$2) } `smartctl --scan`;
-
 
179
 
-
 
180
#foreach my $key ( keys %allDrives ) { print "$key\t$allDrives{$key}\n"; } die;
-
 
181
 
228
 
182
# output the drives and information as tab delimited,
229
# first, get basic information using lsblk for linux systems
183
foreach my $thisDrive ( sort keys %allDrives ) {
230
&lsblk() if $commands{'lsblk'};
184
 #print "$thisDrive\n";
231
# now, try geom for bsd systems
185
 print "$CATEGORY\t$thisDrive Type\t$allDrives{$thisDrive}\n";
232
#&geom() if $commands{'geom'};
186
 my $informationReport = &getSmartInformationReport( $thisDrive, $allDrives{$thisDrive} );
233
# finally, populate whatever using smartctl if it is on system.
187
 my $info = &getInformation( $informationReport );
234
&smartctl() if $commands{'smartctl'};
188
 # if this is not a virtual device, get smart attributes also
-
 
-
 
235
 
189
 if ( ! defined( $ignoreDriveTypes{ $info->{'Model'} } ) ) {
236
for my $drive ( sort keys %driveDefinitions ) {
190
    #print Dumper( $info ); die;
237
   # don't print iSCSI definitions
191
    my $attributesReport = &getSmartAttributeReport( $thisDrive, $allDrives{$thisDrive} );
238
   next if defined( $driveDefinitions{$drive}{'Transport protocol'} ) && $driveDefinitions{$drive}{'Transport protocol'} eq 'ISCSI';
192
    my $attributes = &getAttributes( $attributesReport, $info->{'Sector Size'} );
-
 
193
    #print Dumper( $attributes ); die;
239
   #also, blow off our ignored types
194
    $info = { %$info, %$attributes };
240
   next if ( defined( $driveDefinitions{$drive}{'Model'} ) && defined( $ignoreDriveTypes{ $driveDefinitions{$drive}{'Model'} }  ) );
195
    #print Dumper( $info ); die;
-
 
196
 }
241
   
-
 
242
   # remove comma's from capacity
-
 
243
   $driveDefinitions{$drive}{'Capacity'} =~ s/,//g if $driveDefinitions{$drive}{'Capacity'};
197
 foreach my $key ( keys %$info ) {
244
   foreach my $key ( sort keys %{$driveDefinitions{$drive}} ) {
198
    print "$CATEGORY\t$thisDrive $key\t" . $info->{$key} . "\n";
245
      print "$CATEGORY\t$drive $key\t$driveDefinitions{$drive}{$key}\n";
199
 }
246
   }
200
}
247
}
201
 
248
 
-
 
249
 
202
exit 0;
250
exit 0;