File Coverage

blib/lib/StorageDisplay/Data/RAID.pm
Criterion Covered Total %
statement 292 345 84.6
branch 29 54 53.7
condition 10 19 52.6
subroutine 69 78 88.4
pod 0 28 0.0
total 400 524 76.3


line stmt bran cond sub pod time code
1             #
2             # This file is part of StorageDisplay
3             #
4             # This software is copyright (c) 2014-2023 by Vincent Danjean.
5             #
6             # This is free software; you can redistribute it and/or modify it under
7             # the same terms as the Perl 5 programming language system itself.
8             #
9 9     9   97 use strict;
  9         31  
  9         533  
10 9     9   54 use warnings;
  9         19  
  9         1007  
11              
12             package StorageDisplay::Data::RAID;
13             # ABSTRACT: Handle RAID data for StorageDisplay
14              
15             our $VERSION = '2.06'; # VERSION
16              
17 9     9   82 use Moose;
  9         60  
  9         104  
18 9     9   69042 use namespace::sweep;
  9         23  
  9         110  
19             extends 'StorageDisplay::Data::Elem';
20              
21             with (
22             'StorageDisplay::Role::Style::IsSubGraph',
23             'StorageDisplay::Role::Style::Grey',
24             );
25              
26             has '_devices' => (
27             traits => [ 'Array' ],
28             is => 'ro',
29             isa => 'ArrayRef[StorageDisplay::Data::RAID::Device]',
30             required => 1,
31             default => sub { return []; },
32             handles => {
33             '_add_device' => 'push',
34             'devices' => 'elements',
35             }
36             );
37              
38             has 'raid-devices' => (
39             traits => [ 'Array' ],
40             is => 'ro',
41             isa => 'ArrayRef[StorageDisplay::Data::RAID::RaidDevice]',
42             required => 1,
43             default => sub { return []; },
44             handles => {
45             '_add_raid_device' => 'push',
46             'raid_devices' => 'elements',
47             }
48             );
49              
50             around '_add_raid_device' => sub {
51             my $orig = shift;
52             my $self = shift;
53             my $raid_device = shift;
54             my $state = shift;
55             die "Invalid state" if $state->raid_device != $raid_device;
56             $raid_device->_state($state);
57             $self->addChild($state);
58             return $self->$orig($raid_device);
59             };
60              
61             1;
62              
63             ##################################################################
64             package StorageDisplay::Data::RAID::Container;
65 9     9   3099 use Moose;
  9         25  
  9         90  
66 9     9   69853 use namespace::sweep;
  9         26  
  9         71  
67             extends 'StorageDisplay::Data::RAID';
68              
69             has 'container-devices' => (
70             traits => [ 'Array' ],
71             is => 'ro',
72             isa => 'ArrayRef[StorageDisplay::Data::RAID::ContainerDevice]',
73             required => 1,
74             default => sub { return []; },
75             handles => {
76             '_add_container_device' => 'push',
77             'container_devices' => 'elements',
78             }
79             );
80              
81             sub _add_raid_device {
82 0     0   0 die "Internal error";
83             }
84              
85             around '_add_container_device' => sub {
86             my $orig = shift;
87             my $self = shift;
88             my $container_device = shift;
89             $self->addChild($container_device);
90             return $self->$orig($container_device);
91             };
92              
93             1;
94              
95             ###########################################################################
96             package StorageDisplay::Data::RAID::Elem;
97              
98 9     9   2579 use Moose;
  9         18  
  9         65  
99 9     9   69161 use namespace::sweep;
  9         22  
  9         67  
100             extends 'StorageDisplay::Data::Elem';
101              
102             has 'raid' => (
103             is => 'ro',
104             isa => 'StorageDisplay::Data::RAID',
105             required => 1,
106             );
107              
108             around BUILDARGS => sub {
109             my $orig = shift;
110             my $class = shift;
111             my $raid = shift;
112             my $st = shift;
113              
114             return $class->$orig(
115             'raid' => $raid,
116             'st' => $st,
117             @_
118             );
119             };
120              
121             1;
122              
123             ###########################################################################
124             package StorageDisplay::Data::RAID::State;
125              
126 9     9   1912 use Moose;
  9         19  
  9         75  
127 9     9   68032 use namespace::sweep;
  9         19  
  9         77  
128             extends 'StorageDisplay::Data::RAID::Elem';
129              
130             with (
131             'StorageDisplay::Role::Style::Plain',
132             'StorageDisplay::Role::Style::IsSubGraph',
133             );
134              
135             has 'state' => (
136             is => 'ro',
137             isa => 'Str',
138             required => 1,
139             );
140              
141             has 'extra-info' => (
142             is => 'ro',
143             isa => 'Str',
144             required => 0,
145             predicate => 'has_extra_info',
146             reader => 'extra_info',
147             );
148              
149             has 'raid_device' => (
150             is => 'ro',
151             isa => 'StorageDisplay::Data::RAID::RaidDevice',
152             required => 1,
153             );
154              
155             around BUILDARGS => sub {
156             my $orig = shift;
157             my $class = shift;
158             my $raid_device = shift;
159             my $st = shift;
160              
161             return $class->$orig(
162             $raid_device->raid, $st,
163             'consume' => [],
164             'raid_device' => $raid_device,
165             @_
166             );
167             };
168              
169             sub dotStyleNode {
170 24     24 0 54 my $self = shift;
171 24         51 my $color = 'special';
172 24         1040 my $state = $self->state;
173              
174 24 50       416 if ($state =~ /degraded|DGD/i) {
    50          
    50          
175 0         0 $color = 'warning';
176             } elsif ($state =~ /failed|offline/i) {
177 0         0 $color = 'error';
178             } elsif ($state =~ /clean|active|active-idle|optimal|OKY/i) {
179 24         56 $color = 'ok';
180             }
181              
182             return (
183 24         167 "shape=oval",
184             "fillcolor=".$self->statecolor($color),
185             );
186             }
187              
188             sub dotLabel {
189 24     24 0 59 my $self = shift;
190 24         1198 my @label=('state: '.$self->state);
191 24 50       1160 if ($self->has_extra_info) {
192 0         0 push @label, $self->extra_info;
193             }
194              
195 24         156 return @label;
196             }
197              
198             1;
199              
200             ###########################################################################
201             package StorageDisplay::Data::RAID::ContainerDevice;
202              
203 9     9   7259 use Moose;
  9         19  
  9         57  
204 9     9   69070 use namespace::sweep;
  9         52  
  9         69  
205             extends 'StorageDisplay::Data::RAID::Elem';
206              
207             with (
208             'StorageDisplay::Role::HasBlock',
209             #'StorageDisplay::Role::Style::Plain',
210             );
211              
212             has 'container-type' => (
213             is => 'ro',
214             isa => 'Str',
215             reader => 'container_type',
216             required => 1,
217             );
218              
219             around BUILDARGS => sub {
220             my $orig = shift;
221             my $class = shift;
222             my $raid = shift;
223             my $st = shift;
224             my $block = shift;
225              
226             return $class->$orig(
227             $raid, $st,
228             'block' => $block,
229             'name' => $block->name,
230             'consume' => [],
231             @_
232             );
233             };
234              
235             sub BUILD {
236 0     0 0 0 my $self = shift;
237 0         0 my $args = shift;
238              
239             #print STDERR "container device ", $self->name, " with providing block ", $self->block->dname,"\n";
240 0         0 $self->block->providedBy($self);
241             }
242              
243             sub dotLabel {
244 0     0 0 0 my $self = shift;
245              
246             return (
247 0         0 $self->block->dname,
248             #$self->container_type,
249             );
250             }
251              
252             sub dotStyleNode {
253 0     0 0 0 my $self = shift;
254             return (
255 0         0 "shape=oval;",
256             "fillcolor=".$self->statecolor('special').";",
257             );
258             };
259              
260             1;
261              
262             ###########################################################################
263             package StorageDisplay::Data::RAID::RaidDevice;
264              
265 9     9   3624 use Moose;
  9         23  
  9         420  
266 9     9   64064 use namespace::sweep;
  9         21  
  9         251  
267             extends 'StorageDisplay::Data::RAID::Elem';
268              
269             with (
270             'StorageDisplay::Role::HasBlock',
271             'StorageDisplay::Role::Style::FromBlockState',
272             'StorageDisplay::Role::Style::WithSize',
273             );
274              
275             has 'state' => (
276             is => 'ro',
277             isa => 'StorageDisplay::Data::RAID::State',
278             writer => '_state',
279             required => 0,
280             );
281              
282             has 'raid-level' => (
283             is => 'ro',
284             isa => 'Str',
285             reader => 'raid_level',
286             required => 1,
287             );
288              
289             around '_state' => sub {
290             my $orig = shift;
291             my $self = shift;
292             my $ret = $self->$orig(@_);
293             $self->state->addChild($self);
294             return $ret;
295             };
296              
297             around BUILDARGS => sub {
298             my $orig = shift;
299             my $class = shift;
300             my $raid = shift;
301             my $st = shift;
302             my $block = shift;
303              
304             return $class->$orig(
305             $raid, $st,
306             'block' => $block,
307             'name' => $block->name,
308             'consume' => [],
309             @_
310             );
311             };
312              
313             sub BUILD {
314 12     12 0 33439 my $self = shift;
315 12         34 my $args = shift;
316              
317 12         710 $self->block->providedBy($self);
318             }
319              
320             sub dotLabel {
321 24     24 0 50 my $self = shift;
322              
323             return (
324 24         1095 $self->block->dname,
325             $self->raid_level,
326             );
327             }
328              
329             1;
330              
331             ###########################################################################
332             package StorageDisplay::Data::RAID::Device;
333              
334 9     9   3307 use Moose;
  9         24  
  9         145  
335 9     9   62222 use namespace::sweep;
  9         21  
  9         64  
336             extends 'StorageDisplay::Data::RAID::Elem';
337              
338             with (
339             'StorageDisplay::Role::HasBlock',
340             'StorageDisplay::Role::Style::Plain',
341             );
342              
343             has 'state' => (
344             is => 'ro',
345             isa => 'Maybe[Str]',
346             required => 0,
347             );
348              
349             has 'raiddevice' => (
350             is => 'ro',
351             isa => 'Str',
352             required => 1,
353             );
354              
355             around BUILDARGS => sub {
356             my $orig = shift;
357             my $class = shift;
358             my $raid = shift;
359             my $st = shift;
360             my $devname = shift;
361             my $info = shift;
362             my $args = { @_ };
363             my $container_block = $args->{'container-block'};
364              
365             my $block = $st->block($devname);
366              
367             #print STDERR "RAID::Device ", $block->dname, " container ", ($container_block // $block)->dname, "\n";
368              
369             return $class->$orig(
370             $raid, $st,
371             'block' => $block,
372             'name' => $block->name,
373             'consume' => [$container_block // $block],
374             'state' => $info->{state},
375             'raiddevice' => $info->{raiddevice},
376             @_
377             );
378             };
379              
380             around 'dotStyleNode' => sub {
381             my $orig = shift;
382             my $self = shift;
383             my @text = $self->$orig(@_);
384              
385             my $state = $self->state;
386             my $s;
387              
388             if (not defined($state)) {
389             # devices in RAID containers
390             $s = 'used';
391             } elsif ($state =~ /active|Online, Spun Up|OPT|RDY/i) {
392             $s = 'used';
393             } elsif ($state =~ /rebuild|RBLD/i) {
394             $s = 'warning';
395             } elsif ($state =~ /spare|HSP/i) {
396             $s = 'free';
397             } elsif ($state =~ /faulty|error|FLD|MIS|bad|offline/i) {
398             $s = 'error';
399             } elsif ($state =~ /Unconfigured.*good|AVL/i) {
400             $s = 'unused';
401             } elsif ($state =~ /JBOD/i) {
402             $s = $self->block->state;
403             } else {
404             $s = 'warning';
405             }
406             my $color = $self->statecolor($s);
407              
408             push @text, "fillcolor=$color";
409             return @text;
410             };
411              
412             sub dotLabel {
413 46     46 0 72 my $self = shift;
414 46         1639 my @label = ($self->raiddevice.': '.$self->block->dname);
415 46 50       4548 if (defined($self->state)) {
416 46         1360 push @label, $self->state;
417             }
418 46         187 return @label;
419             }
420              
421             1;
422              
423             ###########################################################################
424             package StorageDisplay::Data::RAID::RawDevice;
425              
426 9     9   9199 use Moose;
  9         24  
  9         52  
427 9     9   63994 use namespace::sweep;
  9         19  
  9         208  
428             extends 'StorageDisplay::Data::RAID::Device';
429             with(
430             'StorageDisplay::Role::Style::WithSize',
431             );
432              
433             has 'model' => (
434             is => 'ro',
435             isa => 'Str',
436             required => 1,
437             );
438              
439             has 'slot' => (
440             is => 'ro',
441             isa => 'Str',
442             required => 1,
443             );
444              
445             sub dotLabel {
446 28     28 0 63 my $self = shift;
447              
448             return (
449 28         1528 $self->model,
450             $self->raiddevice.': slot '.$self->slot,
451             $self->state,
452             );
453             }
454              
455             1;
456              
457             ##################################################################
458             package StorageDisplay::Data::RAID::MD::Container;
459              
460 9     9   1930 use Moose;
  9         20  
  9         53  
461 9     9   67141 use namespace::sweep;
  9         18  
  9         71  
462             extends 'StorageDisplay::Data::RAID::Container';
463              
464             with(
465             'StorageDisplay::Role::HasBlock',
466             );
467              
468             around BUILDARGS => sub {
469             my $orig = shift;
470             my $class = shift;
471             my $devname = shift;
472             my $st = shift;
473              
474             #$st->get_infos
475             $st->log({level=>1}, 'MD Container managed by '.$devname);
476              
477             my $info = $st->get_info('md', $devname);
478             my $block = $st->block($devname);
479             #print STDERR "MD::Container $devname -> ", $block->dname, "\n";
480              
481             return $class->$orig(
482             'name' => $block->name,
483             'block' => $block,
484             'consume' => [],
485             'st' => $st,
486             'raid-name' => '', # in case $info has no name
487             %{$info},
488             @_
489             );
490             };
491              
492             sub BUILD {
493 0     0 0 0 my $self=shift;
494 0         0 my $args=shift;
495 0         0 my $st = $args->{st};
496              
497             my $container_device = StorageDisplay::Data::RAID::ContainerDevice->new(
498             $self, $st,
499             $self->block,
500 0         0 'container-type' => $args->{'raid-version'},
501             );
502 0         0 $self->_add_container_device($container_device);
503              
504 0         0 foreach my $dev (sort keys %{$args->{'devices'}}) {
  0         0  
505 0         0 my $d = StorageDisplay::Data::RAID::Device->new($self, $st, $dev, $args->{'devices'}->{$dev});
506 0         0 $self->_add_device($d);
507 0         0 $self->addChild($d);
508             }
509              
510 0         0 return $self;
511             };
512              
513             has 'raid-version' => (
514             is => 'ro',
515             isa => 'Str',
516             required => 1,
517             reader => 'container_type',
518             );
519              
520             sub dname {
521 0     0 0 0 my $self=shift;
522 0         0 return 'MD: '.$self->block->dname;
523             }
524              
525             sub dotLabel {
526 0     0 0 0 my $self = shift;
527             return (
528 0         0 'Software RAID container',
529             'Type: '.$self->container_type,
530             #$self->disp_size($self->used_dev_size).' used per device',
531             );
532             }
533              
534             sub dotLinks {
535 0     0 0 0 my $self = shift;
536             # Always one container device for MD RAID
537 0         0 my $raidlinkname = ($self->container_devices)[0]->linkname;
538             return (
539             map {
540 0         0 $_->linkname.' -> '.$raidlinkname
  0         0  
541             } $self->devices
542             );
543             }
544              
545             1;
546              
547             ##################################################################
548             package StorageDisplay::Data::RAID::MD;
549              
550 9     9   5980 use Moose;
  9         20  
  9         55  
551 9     9   70562 use namespace::sweep;
  9         48  
  9         77  
552             extends 'StorageDisplay::Data::RAID';
553              
554             with(
555             'StorageDisplay::Role::HasBlock',
556             );
557              
558             around BUILDARGS => sub {
559             my $orig = shift;
560             my $class = shift;
561             my $devname = shift;
562             my $st = shift;
563              
564             #$st->get_infos
565             $st->log({level=>1}, 'MD Raid for device '.$devname);
566              
567             my $info = $st->get_info('md', $devname);
568             my $block = $st->block($devname);
569              
570             return $class->$orig(
571             'name' => $block->name,
572             'block' => $block,
573             'consume' => [],
574             'st' => $st,
575             'raid-name' => '', # in case $info has no name
576             %{$info},
577             @_
578             );
579             };
580              
581             sub BUILD {
582 8     8 0 19985 my $self=shift;
583 8         23 my $args=shift;
584 8         23 my $st = $args->{st};
585              
586             my $raid_device = $self->newElem(
587             'RAID::MD::State::RaidDevice', $self, $st, $self->block,
588             'raid-level' => $args->{'raid-level'},
589 8         558 'size' => $args->{'array-size'});
590             my $state = $self->newElem(
591             'RAID::MD::State', $raid_device, $st,
592 8         169 'state' => $args->{'raid-state'},
593             'ignore_name' => 1,
594             );
595 8         17922 $self->_add_raid_device($raid_device, $state);
596              
597 8         23 my $container_device_block = undef;
598 8 50       35 if (exists($args->{'raid-container-device'})) {
599 0         0 $container_device_block = $st->block($args->{'raid-container-device'});
600             #print STDERR "RAID::MD Container ", $args->{'raid-container-device'}, " -> ",
601             # $container_device_block->dname, "\n";
602             }
603              
604 8         18 foreach my $dev (sort keys %{$args->{'devices'}}) {
  8         74  
605             my $d = $self->newChild(
606             'RAID::MD::Device',
607 23         168 $self, $st, $dev, $args->{'devices'}->{$dev},
608             'container-block' => $container_device_block);
609 23         1399 $self->_add_device($d);
610             }
611              
612 8         70 return $self;
613             };
614              
615             has 'used-dev-size' => (
616             is => 'ro',
617             isa => 'Int',
618             required => 0, # not present with RAID0
619             predicate => 'has_used_dev_size',
620             reader => 'used_dev_size',
621             );
622              
623             has 'raid-name' => (
624             is => 'ro',
625             isa => 'Str',
626             required => 1,
627             reader => 'raid_name',
628             );
629              
630             sub dname {
631 16     16 0 39 my $self=shift;
632 16         800 return 'MD: '.$self->block->dname;
633             }
634              
635             sub dotLabel {
636 16     16 0 33 my $self = shift;
637 16         718 my @label = ($self->raid_name);
638 16 100       721 if ($self->has_used_dev_size) {
639 14         586 push @label, $self->disp_size($self->used_dev_size).' used per device';
640             }
641 16         631 return @label;
642             }
643              
644             sub dotLinks {
645 8     8 0 20 my $self = shift;
646             # Always one raid device for MD RAID
647 8         721 my $raidlinkname = ($self->raid_devices)[0]->linkname;
648             return (
649             map {
650 8         508 $_->linkname.' -> '.$raidlinkname
  23         83  
651             } $self->devices
652             );
653             }
654              
655             1;
656              
657             ##################################################################
658             package StorageDisplay::Data::RAID::MD::State;
659              
660 9     9   7396 use Moose;
  9         21  
  9         51  
661 9     9   70460 use namespace::sweep;
  9         21  
  9         86  
662             extends 'StorageDisplay::Data::RAID::State';
663              
664             1;
665              
666             ##################################################################
667             package StorageDisplay::Data::RAID::MD::State::RaidDevice;
668              
669 9     9   1044 use Moose;
  9         22  
  9         70  
670 9     9   70274 use namespace::sweep;
  9         23  
  9         68  
671             extends 'StorageDisplay::Data::RAID::RaidDevice';
672              
673             1;
674              
675             ##################################################################
676             package StorageDisplay::Data::RAID::MD::Device;
677              
678 9     9   923 use Moose;
  9         23  
  9         47  
679 9     9   67142 use namespace::sweep;
  9         23  
  9         91  
680             extends 'StorageDisplay::Data::RAID::Device';
681              
682             1;
683              
684             ##################################################################
685             package StorageDisplay::Data::RAID::LSI::Megacli;
686              
687 9     9   1205 use Moose;
  9         22  
  9         66  
688 9     9   74236 use namespace::sweep;
  9         22  
  9         67  
689             extends 'StorageDisplay::Data::RAID';
690              
691             has 'controller' => (
692             is => 'ro',
693             isa => 'Num',
694             required => 1,
695             );
696              
697             has 'hw_model' => (
698             is => 'ro',
699             isa => 'Str',
700             init_arg => 'H/W Model',
701             required => 1,
702             );
703              
704             has 'ID' => (
705             is => 'ro',
706             isa => 'Str',
707             required => 1,
708             );
709              
710             has 'named-raid-devices' => (
711             traits => [ 'Hash' ],
712             is => 'ro',
713             isa => 'HashRef[StorageDisplay::Data::RAID::RaidDevice]',
714             required => 1,
715             default => sub { return {}; },
716             handles => {
717             '_add_named_raid_device' => 'set',
718             'raid_device' => 'get',
719             }
720             );
721              
722             around BUILDARGS => sub {
723             my $orig = shift;
724             my $class = shift;
725             my $controller = shift;
726             my $st = shift;
727              
728             #$st->get_infos
729             $st->log({level=>1}, 'Megacli Raid controller '.$controller);
730              
731             my $info = $st->get_info('lsi-megacli', $controller);
732              
733             return $class->$orig(
734             'name' => $controller,
735             'controller' => $controller,
736             'consume' => [],
737             'st' => $st,
738             %{$info->{'Controller'}->{'c'.$controller}},
739             %{$info},
740             @_
741             );
742             };
743              
744             sub hwsize {
745 0     0 0 0 my $self = shift;
746 0         0 my $hwsize = shift;
747              
748 0 0       0 if ($hwsize =~ /^[0-9]+$/) {
    0          
749 0         0 return $hwsize;
750             } elsif ($hwsize =~ /^([0-9]+)([BKMGTP])$/) {
751 0         0 my %pow = (
752             'B' => 0,
753             'K' => 1,
754             'M' => 2,
755             'G' => 3,
756             'T' => 4,
757             'P' => 5,
758             );
759 0         0 return $1 * (1024 ** $pow{$2});
760             } else {
761 0         0 print STDERR "Warning: cannot interpret size $hwsize, using -1\n";
762 0         0 return -1;
763             }
764             }
765              
766             sub BUILD {
767 1     1 0 2984 my $self=shift;
768 1         2 my $args=shift;
769 1         5 my $st = $args->{st};
770              
771             #my $state = StorageDisplay::Data::RAID::State->new($self, $st,
772             # 'state' => $args->{'raid-state'});
773             #$self->addChild($state);
774              
775             #$self->_add_raid_device(StorageDisplay::Data::RAID::RaidDevice->new($self, $st,
776             # $self->block,
777             # $state,
778             # 'size' => $args->{'array-size'}));
779 1         62 my $cid = $self->controller;
780              
781             #use Data::Dumper;
782             #print STDERR Dumper($st);
783             $self->newChild('RAID::LSI::Megacli::BBU::Status',
784 1         13 $self, $st, 'status' => $args->{'BBU'});
785              
786 9     9   14079 use bignum qw/hex/;
  9         42478  
  9         50  
787 1         3 foreach my $dev (sort { $a->{'LSI ID'} <=> $b->{'LSI ID'} }
  23         54  
788 1         9 (values %{$args->{'Disk'}})) {
789 10   100     64 my $devname = $dev->{'Path'} // '';
790 10         46 my $devpath = 'LSI@'.$dev->{'Slot ID'};
791 10 100       56 if ($dev->{'ID'} !~ /^c[0-9]+uXpY$/) {
792 9         33 $devpath = 'LSI@'.$dev->{'ID'};
793             }
794 10         25 my $block;
795             my @block;
796 10 50 66     47 if ($devname ne '' && $devname ne 'N/A') {
797 0         0 $block = $st->block($devname);
798 0         0 @block = ('block' => $block);
799             }
800             my $d = $self->newChild(
801             'RAID::LSI::Megacli::RawDevice',
802             $self, $st, $devpath, $dev,
803             'raiddevice' => $dev->{'ID'},
804             'state' => $dev->{'Status'},
805             'model' => $dev->{'Drive Model'},
806             'slot' => $dev->{'Slot ID'},
807 10   50     343 'size' => (hex($dev->{'# sectors'}) * ($dev->{'sector size'} // 512))->numify(),
808             @block,
809             );
810 10         740 $self->_add_device($d);
811 10 50       51 if ($block) {
812 0         0 $d->provideBlock($block);
813             }
814             }
815 1         4 foreach my $dev (sort { $a->{'ID'} cmp $b->{'ID'} }
  2         11  
816 1         11 (values %{$args->{'Array'}})) {
817             #print STDERR Dumper($dev);
818 3         14 my $devname = $dev->{'OS Path'};
819 3         29 my $block = $st->block($devname);
820             #print STDERR Dumper($block->blk_info("SIZE")//$self->hwsize($dev->{'Size'}));
821             my $raid_device = $self->newElem(
822             'RAID::LSI::Megacli::State::RaidDevice',
823             $self, $st, $block,
824             # If the disk is not attached to linux (or have been 'deleted')
825             # the SIZE would be unknown from blk
826             'size' => $block->blk_info("SIZE")//$self->hwsize($dev->{'Size'}),
827             'raid-level' => $dev->{'Type'},
828 3   33     217 %{$dev},
  3         36  
829             );
830 3         66 my %inprogress=();
831 3 50       18 if ($dev->{'InProgress'} ne 'None') {
832 0         0 %inprogress=('extra-info' => $dev->{'InProgress'});
833             }
834             my $state = $self->newElem(
835             'RAID::LSI::Megacli::State', $raid_device, $st,
836 3         156 'state' => $dev->{'Status'},
837             'name' => $raid_device->block->name,
838             %inprogress);
839              
840 3         11324 $self->_add_raid_device($raid_device, $state);
841 3         282 $self->_add_named_raid_device($dev->{'ID'}, $raid_device);
842             }
843              
844 1         9 return $self;
845             };
846              
847             sub dname {
848 2     2 0 4 my $self=shift;
849 2         75 return 'MegaCli: Controller '.$self->ID;
850             }
851              
852             sub dotLabel {
853 2     2 0 6 my $self = shift;
854             return (
855 2         114 $self->hw_model,
856             "Controller: ".$self->ID,
857             #$self->raid_level.': '.$self->raid_name,
858             #$self->disp_size($self->used_dev_size).' used per device',
859             );
860             }
861              
862             sub dotLinks {
863 1     1 0 4 my $self = shift;
864             return (
865             map {
866 1 100       78 if ($_->raiddevice =~ /^(c[0-9]+u[0-9]+)p([0-9]+|Y)$/) {
  10         343  
867 9         425 my $raid_device = $self->raid_device($1);
868 9         30 $_->linkname.' -> '.$raid_device->linkname;
869             }
870             } $self->devices
871             );
872             }
873              
874             1;
875              
876             ##################################################################
877             package StorageDisplay::Data::RAID::LSI::Megacli::BBU::Status;
878              
879 9     9   21166 use Moose;
  9         30  
  9         87  
880 9     9   80240 use namespace::sweep;
  9         31  
  9         128  
881             extends 'StorageDisplay::Data::RAID::Elem';
882              
883             has 'status' => (
884             is => 'ro',
885             isa => 'Str',
886             required => 1,
887             );
888              
889             around BUILDARGS => sub {
890             my $orig = shift;
891             my $class = shift;
892             my $raid = shift;
893             my $st = shift;
894              
895             return $class->$orig(
896             $raid, $st,
897             'ignore_name' => 1,
898             'consume' => [],
899             @_
900             );
901             };
902              
903             sub dotStyleNode {
904 2     2 0 30 my $self = shift;
905 2         7 my $color = 'special';
906 2         103 my $status = $self->status;
907              
908 2 50 33     39 if ($status =~ /REPL|error/i) {
    50          
    50          
    50          
909 0         0 $color = 'red';
910             } elsif ($status =~ /missing/i || $status eq '') {
911 0         0 $color = 'warning';
912             } elsif ($status =~ /absent/i) {
913 0         0 $color = 'unused';
914             } elsif ($status =~ /good/i) {
915 2         24 $color = 'ok';
916             }
917              
918             return (
919 2         33 "shape=oval",
920             "fillcolor=".$self->statecolor($color),
921             );
922             }
923              
924             sub dotLabel {
925 2     2 0 5 my $self = shift;
926              
927             return (
928 2         115 'BBU Status: '.$self->status,
929             );
930             }
931              
932             1;
933              
934             ##################################################################
935             package StorageDisplay::Data::RAID::LSI::Megacli::State;
936              
937 9     9   4862 use Moose;
  9         22  
  9         94  
938 9     9   74945 use namespace::sweep;
  9         26  
  9         73  
939             extends 'StorageDisplay::Data::RAID::State';
940              
941             1;
942              
943             ##################################################################
944             package StorageDisplay::Data::RAID::LSI::Megacli::RawDevice;
945              
946 9     9   1028 use Moose;
  9         26  
  9         51  
947 9     9   75316 use namespace::sweep;
  9         31  
  9         70  
948             extends 'StorageDisplay::Data::RAID::RawDevice';
949              
950             1;
951              
952             ##################################################################
953             package StorageDisplay::Data::RAID::LSI::Megacli::State::RaidDevice;
954              
955 9     9   997 use Moose;
  9         23  
  9         53  
956 9     9   72301 use namespace::sweep;
  9         25  
  9         70  
957             extends 'StorageDisplay::Data::RAID::RaidDevice';
958              
959             has 'lsi-id' => (
960             is => 'ro',
961             isa => 'Str',
962             init_arg => 'ID',
963             reader=> 'lsi_id',
964             required => 1,
965             );
966              
967             around 'dotLabel' => sub {
968             my $orig = shift;
969             my $self = shift;
970             my @ret = $self->$orig(@_);
971             $ret[0] .= " (".$self->lsi_id.")";
972             return @ret;
973             };
974              
975             1;
976              
977             ##################################################################
978             package StorageDisplay::Data::RAID::LSI::SASIrcu;
979              
980 9     9   2406 use Moose;
  9         24  
  9         64  
981 9     9   70196 use namespace::sweep;
  9         22  
  9         105  
982             extends 'StorageDisplay::Data::RAID';
983              
984             my $missing_count=0;
985              
986             has 'controller' => (
987             is => 'ro',
988             isa => 'Num',
989             init_arg => 'controllerID',
990             required => 1,
991             );
992              
993             has 'hw_model' => (
994             is => 'ro',
995             isa => 'Str',
996             init_arg => 'controller-type',
997             required => 1,
998             );
999              
1000             has 'named-raw-devices' => (
1001             traits => [ 'Hash' ],
1002             is => 'ro',
1003             isa => 'HashRef[StorageDisplay::Data::RAID::RawDevice]',
1004             required => 1,
1005             default => sub { return {}; },
1006             handles => {
1007             '_add_named_raw_device' => 'set',
1008             'raw_device' => 'get',
1009             }
1010             );
1011              
1012             around BUILDARGS => sub {
1013             my $orig = shift;
1014             my $class = shift;
1015             my $controller = shift;
1016             my $st = shift;
1017              
1018             #$st->get_infos
1019             $st->log({level=>1}, 'LSI Raid controller (SAS2Ircu) '.$controller);
1020              
1021             my $info = $st->get_info('lsi-sas-ircu', $controller);
1022              
1023             return $class->$orig(
1024             'name' => $controller,
1025             'controllerID' => $controller,
1026             'consume' => [],
1027             'st' => $st,
1028             %{$info->{'controller'}},
1029             %{$info},
1030             @_
1031             );
1032             };
1033              
1034             sub BUILD {
1035 1     1 0 1173 my $self=shift;
1036 1         3 my $args=shift;
1037 1         4 my $st = $args->{st};
1038              
1039 1         32 my $cid = $self->controller;
1040 1         3 my $cur_missing_count = $missing_count;
1041 1         2 foreach my $dev (sort { $a->{'enclosure'} <=> $b->{'enclosure'}
1042 4 0       19 or $a->{'slot'} <=> $b->{'slot'}
1043             }
1044 1         7 @{$args->{'devices'}}) {
1045 4         14 my ($id,$d);
1046 4 50       25 if ($dev->{'state'} =~ /MIS/) {
1047             # disk missing
1048 0         0 $id = $dev->{'enclosure'}.":".$dev->{'slot'}." (".($missing_count++).")";
1049 0         0 my $devpath = 'LSISASIrcu@'.$id;
1050             $d = $self->newChild(
1051             'RAID::LSI::SASIrcu::MissingRawDevice',
1052             $self, $st, $devpath, $dev,
1053             'raiddevice' => $id,
1054 0         0 'state' => $dev->{'state'},
1055             'model' => 'Disk missing',
1056             'size' => 0,
1057             'slot' => 'none',
1058             );
1059             } else {
1060 4         14 $id=$dev->{'enclosure'}.":".$dev->{'slot'};
1061 4 50       13 if ($id eq '0:0') { # can be the case of FLD drives
1062 0         0 $id .= ' ('.($cur_missing_count++).')';
1063             }
1064             #print STDERR "Adding $id\n";
1065 4         12 my $devpath = 'LSISASIrcu@'.$id;
1066 4         7 my $block;
1067             {
1068 4   50     7 my $serial = $dev->{'serial-no'}//'';
  4         20  
1069 4 50       12 if ($serial ne '') {
1070             #print STDERR "Serial for $id is $serial\n";
1071 4         36 $block = $st->blockBySerial($serial);
1072             }# else { # GUID/WWN is not always unique
1073             # $serial = $dev->{'guid'}//'';
1074             # if ($serial ne '') {
1075             # print STDERR "Guid for $id is $serial\n";
1076             # $block = $st->blockBySerial($serial);
1077             # }
1078             #}
1079             }
1080             $d = $self->newChild(
1081             'RAID::LSI::SASIrcu::RawDevice',
1082             $self, $st, $devpath, $dev,
1083             'raiddevice' => $id,
1084             'state' => $dev->{'state'},
1085             'model' => join(' ', $dev->{'manufacturer'}, $dev->{'model-number'}, $dev->{'serial-no'}),
1086 4   50     81 'size' => $dev->{'size'}//'0', # No size on some FLD devices
1087             'slot' => $id,
1088             );
1089 4 100       24 if (defined($block)) {
1090             #print STDERR "$id provide ", $block->name,"\n";
1091 2         23 $d->provideBlock($block);
1092             }
1093             }
1094 4         135 $self->_add_device($d);
1095 4         164 $self->_add_named_raw_device($id, $d);
1096             }
1097 1         2 my $defined_missing_count = $cur_missing_count;
1098 1         4 $cur_missing_count = $missing_count;
1099 1         3 foreach my $dev (sort { $a->{'id'} cmp $b->{'id'} }
  0         0  
1100 1         4 @{$args->{'volumes'}}) {
1101 1         5 my $devname = $args->{'wwid'}->{$dev->{'wwid'}};
1102 1         10 my $block = $st->block($devname);
1103             my $raid_device = $self->newElem(
1104             'RAID::LSI::SASIrcu::State::RaidDevice',
1105             $self, $st, $block,
1106             'size' => $block->blk_info("SIZE"),
1107             'raid-level' => $dev->{'Type'},
1108 1         33 %{$dev},
  1         13  
1109             );
1110             my $state = $self->newElem(
1111             'RAID::LSI::SASIrcu::State', $raid_device, $st,
1112 1         37 'state' => $dev->{'status'},
1113             'name' => $raid_device->block->name
1114             );
1115              
1116 1         1566 $self->_add_raid_device($raid_device, $state);
1117 1   50     3 foreach my $phyid (keys %{$dev->{'PHY'} // {}}) {
  1         8  
1118 2         6 my $phy = $dev->{'PHY'}->{$phyid};
1119 2         9 my $id = $phy->{'enclosure'}.":".$phy->{'slot'};
1120 2 50       7 if ($id eq '0:0') {
1121 0         0 $id .= ' ('.($cur_missing_count++).')';
1122             }
1123             #print STDERR "Getting $id\n";
1124 2         84 my $rdsk = $self->raw_device($id);
1125 2         54 $rdsk->volume($raid_device);
1126 2         61 $rdsk->phyid($phyid);
1127             }
1128             }
1129 1 50       5 if ($cur_missing_count != $defined_missing_count) {
1130 0         0 print STDERR "Internal warning: wrong total of missing drives: $cur_missing_count != $defined_missing_count\n";
1131             }
1132 1 50       4 $missing_count = ($cur_missing_count > $defined_missing_count)?$cur_missing_count:$defined_missing_count;
1133 1         8 return $self;
1134             };
1135              
1136             sub dname {
1137 2     2 0 7 my $self=shift;
1138 2         105 return 'MegaCli: Controller '.$self->controller;
1139             }
1140              
1141             sub dotLabel {
1142 2     2 0 5 my $self = shift;
1143             return (
1144 2         90 $self->hw_model,
1145             #$self->ID,
1146             #$self->raid_level.': '.$self->raid_name,
1147             #$self->disp_size($self->used_dev_size).' used per device',
1148             );
1149             }
1150              
1151             sub dotLinks {
1152 1     1 0 4 my $self = shift;
1153             return (
1154             map {
1155 1 100       77 if ($_->has_volume) {
  4         215  
1156 2         9 $_->linkname.' -> '.$_->volume->linkname;
1157             }
1158             } $self->devices
1159             );
1160             }
1161              
1162             1;
1163              
1164             ##################################################################
1165             package StorageDisplay::Data::RAID::LSI::SASIrcu::MissingRawDevice;
1166              
1167 9     9   14333 use Moose;
  9         26  
  9         73  
1168 9     9   71675 use namespace::sweep;
  9         25  
  9         68  
1169             extends 'StorageDisplay::Data::RAID::RawDevice';
1170              
1171             #with (
1172             # 'StorageDisplay::Role::Style::WithSize',
1173             # );
1174              
1175             has 'volume' => (
1176             is => 'rw',
1177             isa => 'StorageDisplay::Data::RAID::RaidDevice',
1178             required => 0,
1179             predicate => 'has_volume',
1180             );
1181              
1182             has 'phyid' => (
1183             is => 'rw',
1184             isa => 'Num',
1185             required => 0,
1186             predicate => 'has_phyid',
1187             );
1188              
1189             around 'dotLabel' => sub {
1190             my $orig = shift;
1191             my $self = shift;
1192             my @ret = $self->$orig(@_);
1193             if ($self->has_phyid) {
1194             $ret[1] = $self->phyid.": enc/slot: ".$self->slot;
1195             } else {
1196             $ret[1] = "enc/slot: ".$self->slot;
1197             }
1198             return @ret;
1199             };
1200              
1201             1;
1202              
1203             ##################################################################
1204             package StorageDisplay::Data::RAID::LSI::SASIrcu::RawDevice;
1205              
1206 9     9   2728 use Moose;
  9         18  
  9         58  
1207 9     9   70947 use namespace::sweep;
  9         27  
  9         65  
1208             extends 'StorageDisplay::Data::RAID::RawDevice';
1209              
1210             has 'volume' => (
1211             is => 'rw',
1212             isa => 'StorageDisplay::Data::RAID::RaidDevice',
1213             required => 0,
1214             predicate => 'has_volume',
1215             );
1216              
1217             has 'phyid' => (
1218             is => 'rw',
1219             isa => 'Num',
1220             required => 0,
1221             predicate => 'has_phyid',
1222             );
1223              
1224             around 'dotLabel' => sub {
1225             my $orig = shift;
1226             my $self = shift;
1227             my @ret = $self->$orig(@_);
1228             if ($self->has_phyid) {
1229             $ret[1] = $self->phyid.": enc/slot: ".$self->slot;
1230             } else {
1231             $ret[1] = "enc/slot: ".$self->slot;
1232             }
1233             return @ret;
1234             };
1235              
1236             1;
1237              
1238             ##################################################################
1239             package StorageDisplay::Data::RAID::LSI::SASIrcu::State;
1240              
1241 9     9   2670 use Moose;
  9         26  
  9         58  
1242 9     9   70369 use namespace::sweep;
  9         25  
  9         63  
1243             extends 'StorageDisplay::Data::RAID::State';
1244              
1245             1;
1246              
1247             ##################################################################
1248             package StorageDisplay::Data::RAID::LSI::SASIrcu::State::RaidDevice;
1249              
1250 9     9   976 use Moose;
  9         22  
  9         53  
1251 9     9   72346 use namespace::sweep;
  9         25  
  9         69  
1252             extends 'StorageDisplay::Data::RAID::RaidDevice';
1253              
1254             1;
1255              
1256             __END__
1257              
1258             =pod
1259              
1260             =encoding UTF-8
1261              
1262             =head1 NAME
1263              
1264             StorageDisplay::Data::RAID - Handle RAID data for StorageDisplay
1265              
1266             =head1 VERSION
1267              
1268             version 2.06
1269              
1270             =head1 AUTHOR
1271              
1272             Vincent Danjean <Vincent.Danjean@ens-lyon.org>
1273              
1274             =head1 COPYRIGHT AND LICENSE
1275              
1276             This software is copyright (c) 2014-2023 by Vincent Danjean.
1277              
1278             This is free software; you can redistribute it and/or modify it under
1279             the same terms as the Perl 5 programming language system itself.
1280              
1281             =cut