report md devices and zfs spare cache and log drives
[sysadmin-cookbook] / recepies / zfs / disks.pl
1 #!/usr/bin/perl
2 use warnings;
3 use strict;
4 use autodie;
5 use Data::Dump qw(dump);
6
7 my ($before, $delimiter, $after) = ( ''=>' | '=> "\n" ); # double space for display
8    ($before, $delimiter, $after) = ( '"'=>'","'=> '"'."\n" ) if @ARGV;
9
10 my $zfs;
11 open(my $zpool, '-|', 'zpool status');
12 my $name = 'zfs';
13 my $vdev = '';
14 while(<$zpool>) {
15         chomp;
16         $name = $1 if /^\s+pool:\s(\S+)/;
17         $vdev = $1 if /^\s+(raid\S+|spare|log|cache)/;
18         $zfs->{$1} = join(' ', $name, $vdev) if /^\s+(sd\S+)/;
19 }
20 warn "# zfs ",dump($zfs);
21
22 my $md;
23 open(my $mdstat, '<', '/proc/mdstat');
24 while(<$mdstat>) {
25         chomp;
26         if ( m/(md\d+)\s+:\s+active\s+(\S+)\s+(.+)/ ) {
27                 my ( $nr, $raid ) = ( $1, $2 );
28                 foreach my $dev ( split(/\s+/, $3) ) {
29                         my $d = $1 if $dev =~ m{(sd\w+)\d+};
30                         $md->{$d} = "$nr $raid $dev";
31                 }
32         }
33 }
34 warn "# md ",dump($md);
35
36 open(my $lsscsi, '-|', 'lsscsi --size -v');
37
38 print $before, join($delimiter, qw(id type name dev size pert_of path) ), $after;
39
40 while(my $line = <$lsscsi>) {
41         chomp($line);
42 #       warn "## $line\n";
43
44         my @l = $line =~ m{(^\S+)\s+(\S+)\s+(.+)\s+(\S+)\s+(\S+)};
45
46         my $dev = $l[3];
47         $dev =~ s{/dev/}{};
48         warn "# dev $dev\n";
49
50         push @l,
51                 exists $zfs->{$dev} ? $zfs->{$dev} :
52                 exists $md->{$dev} ? $md->{$dev} :
53                 '-';
54
55         my $v = <$lsscsi>;
56         chomp($v);
57         push @l, $1 if $v =~ m/\[(.+)\]/;
58         print $before,join($delimiter,@l),$after;
59 };