File Coverage

blib/lib/StorageDisplay/Data/FS.pm
Criterion Covered Total %
statement 138 155 89.0
branch 15 26 57.6
condition 4 5 80.0
subroutine 35 36 97.2
pod 0 16 0.0
total 192 238 80.6


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   68 use strict;
  9         24  
  9         406  
10 9     9   54 use warnings;
  9         20  
  9         1518  
11              
12             package StorageDisplay::Data::FS;
13             # ABSTRACT: Handle filesystem data for StorageDisplay
14              
15             our $VERSION = '2.06'; # VERSION
16              
17 9     9   68 use Moose;
  9         25  
  9         77  
18 9     9   76832 use namespace::sweep;
  9         23  
  9         104  
19             extends 'StorageDisplay::Data::Elem';
20              
21             with (
22             'StorageDisplay::Role::Style::IsSubGraph',
23             'StorageDisplay::Role::Style::Grey',
24             );
25              
26             has '_swaps' => (
27             traits => [ 'Array' ],
28             is => 'ro',
29             isa => 'ArrayRef[StorageDisplay::Data::FS::SWAP::Elem]',
30             required => 1,
31             default => sub { return []; },
32             handles => {
33             '_add_swap' => 'push',
34             'all_swap' => 'elements',
35             'nb_swap' => 'count',
36             }
37             );
38              
39             around BUILDARGS => sub {
40             my $orig = shift;
41             my $class = shift;
42             my $st = shift;
43              
44             $st->log('Creating FS');
45             my $info = $st->get_info('fs')//{};
46              
47             return $class->$orig(
48             'ignore_name' => 1,
49             'consume' => [],
50             'st' => $st,
51             @_
52             );
53             };
54              
55             sub keep {
56 261     261 0 609 my $self = shift;
57 261         531 my $fs = shift;
58              
59 261         11016 return $fs->useblock;
60             }
61              
62             sub BUILD {
63 7     7 0 14657 my $self=shift;
64 7         23 my $args=shift;
65              
66 7         22 my $st = $args->{'st'};
67             # in case FS hierachy is not initialized
68             # and 'parent' not present (old versions of findmnt)
69 7         503 my $rootid = $st->fs_mountpoint_id('/');
70 7   50     49 my $allfs = $st->get_info('fs')//{};
71              
72 7         544 foreach my $mp (sort keys %{$allfs->{swap}}) {
  7         52  
73 5         19 my $fs = $allfs->{swap}->{$mp};
74 5 50       26 if ($fs->{'fstype'} eq 'partition') {
    0          
75             $self->_add_swap(
76             $self->newElem('FS::SWAP::Partition',
77 5         72 $fs->{filesystem}, $st, $fs),
78             );
79             } elsif ($fs->{'fstype'} eq 'file') {
80             $self->_add_swap(
81             $self->newElem('FS::SWAP::File',
82 0         0 $fs->{filesystem}, $st, $fs),
83             );
84             } else {
85 0         0 $self->error("Unknown swap type ".$fs->{'fstype'}." for ".$fs->{filesystem});
86             }
87             }
88 7 100       374 if ($self->nb_swap == 1) {
89 5         286 my $s = ($self->all_swap)[0];
90 5         47 $s->onlyoneswap;
91 5         53 $self->addChild($s);
92             } else {
93 2         90 $self->newChild('FS::SWAP', $st, [$self->all_swap()]);
94             }
95             #foreach my $mp (sort keys %{$allfs->{df}}) {
96             # my $fs = $allfs->{df}->{$mp};
97             # $self->newChild('FS::FS', $fs->{filesystem}, $st, $fs);
98             #}
99 7         37 my $fullfs = $allfs->{flatfull};
100 7         24 my $flat=0;
101 7 50       34 if ($flat) {
102 0         0 foreach my $id (keys %{$fullfs}) {
  0         0  
103 0         0 my $fs = $fullfs->{$id};
104 0         0 my $fs_elem = $self->newElem('FS::MP::FS', $st, $fs);
105 0 0       0 if ($self->keep($fs_elem)) {
106 0         0 $self->addChild($fs_elem);
107             }
108             }
109             } else {
110 7         56 while ($fullfs->{$rootid}->{parent} != 1) {
111 0         0 $rootid = $fullfs->{$rootid}->{parent};
112             }
113             #my $
114 7         42 $self->addChild($self->createFS($st, $fullfs, $rootid));
115             }
116             }
117              
118             sub createFS {
119 272     272 0 700 my $self = shift;
120 272         541 my $st = shift;
121 272         504 my $fullfs = shift;
122 272         814 my $id = shift;
123              
124 272         918 my $fs = $fullfs->{$id};
125 272         1368 my $fs_elem = $self->newElem('FS::MP::FS', $st, $fs);
126 272 100       5853 if (! exists($fs->{children})) {
127 210 100       1178 if ($self->keep($fs_elem)) {
128 27         101 return $fs_elem;
129             }
130 183         760 return;
131             }
132 62 50       333 if (exists($fs->{children})) {
133             my @fs_children = map
134             {
135 265         1275 my $fs = $self->createFS($st, $fullfs, $_);
136 265 100       2412 defined($fs) ? $fs : ()
137             }
138 62         132 @{$fs->{children}};
  62         227  
139              
140 62 100 100     438 if (scalar(@fs_children) == 0 && ! $self->keep($fs_elem)) {
141 50         185 return;
142             }
143 12         100 return $self->newElem('FS::MP',
144             'st' => $st,
145             'fs' => $fs,
146             'fs_elem' => $fs_elem,
147             'fs_children' => \@fs_children);
148             }
149             }
150              
151             sub dotLabel {
152 14     14 0 50 my $self = shift;
153 14         71 return "Mounted FS and swap";
154             }
155              
156             1;
157              
158             ##################################################################
159             package StorageDisplay::Data::FS::MP::FS;
160             # Basic FS info
161              
162 9     9   12215 use Moose;
  9         25  
  9         56  
163 9     9   76442 use namespace::sweep;
  9         33  
  9         65  
164             extends 'StorageDisplay::Data::Elem';
165              
166             with (
167             'StorageDisplay::Role::HasBlock',
168             'StorageDisplay::Role::Style::WithUsed',
169             );
170              
171             has 'mountpoint' => (
172             is => 'ro',
173             isa => 'Str',
174             required => 1,
175             );
176              
177             has 'fstype' => (
178             is => 'ro',
179             isa => 'Str',
180             required => 1,
181             );
182              
183             has 'sourcenames' => (
184             is => 'ro',
185             isa => 'Str',
186             required => 1,
187             );
188              
189             has 'special' => (
190             is => 'ro',
191             isa => 'Bool',
192             required => 1,
193             default => 0,
194             );
195              
196             has 'useblock' => (
197             is => 'ro',
198             isa => 'Bool',
199             required => 1,
200             default => 0,
201             );
202              
203             has 'fsroot' => (
204             is => 'ro',
205             isa => 'Str',
206             required => 1,
207             );
208              
209             has 'parentfsid' => (
210             is => 'ro',
211             isa => 'Num',
212             required => 1,
213             );
214              
215             has 'sd' => (
216             is => 'ro',
217             isa => 'StorageDisplay',
218             required => 1,
219             );
220              
221             around 'BUILDARGS' => sub {
222             my $orig = shift;
223             my $class = shift;
224             my $st = shift;
225             my $fs = shift;
226              
227             my @consume = ();
228             my $has_sources = exists($fs->{'sources'});
229             my @sources;
230             if ($has_sources) {
231             @sources = @{$fs->{'sources'}};
232             } else {
233             @sources = ($fs->{'source'});
234             }
235             my @sourcenames;
236             if (! defined($fs->{'fsroot'})) {
237 9     9   4131 use Data::Dumper;
  9         26  
  9         1077  
238 9     9   71 use Carp;
  9         40  
  9         12431  
239             print STDERR Dumper($fs), "\n";
240             confess "coucou\n";
241             }
242             my $use_block = 0;
243             my $special = 0;
244             for my $source (@sources) {
245             if (! $has_sources # old software, no 'sources' entry
246             && $fs->{'fsroot'} ne '/'
247             && $source =~ m,^(.*)\[$fs->{'fsroot'}\]$,) {
248             $source = $1; # only keep relevant part of 'source' entry
249             }
250             my $block;
251             if ($source =~ m,^/dev/,) {
252             $block = $st->block($source);
253             push @sourcenames, 'Device: '.$block->dname;
254             $use_block=1;
255             } elsif ($source =~ m,^/,) {
256             # TODO : wrong if $target is not a mountpoint
257             $block = $st->block($source);
258             push @sourcenames, 'Source: '.$source;
259             #$block = $st->block($st->fs_mountpoint_blockname($source));
260             } else {
261             push @sourcenames, 'Source: '.$source;
262             $block = $st->block($source);
263             $special = 1;
264             }
265             push @consume, $block;
266             }
267             if ($fs->{fsroot} ne '/') {
268             push @sourcenames, "Subdir: ".$fs->{fsroot};
269             }
270              
271             $st->log({level=>1}, $fs->{target});
272              
273             my $name = $st->fs_mountpoint_blockname_by_id($fs->{id}, $fs->{target});
274             if (not exists($fs->{free})) {
275             $fs->{free} = $fs->{avail};
276             }
277             if (exists($fs->{label})) {
278             delete $fs->{label};
279             }
280              
281             #if ($fs->{parent} != 1) {
282             # push @consume, $st->block($st->fs_mountpoint_blockname_by_id($fs->{parent}));
283             #}
284             my $block = $st->block($name);
285             return $class->$orig(
286             'name' => $name,
287             'consume' => \@consume,
288             'provide' => $block,
289             'sd' => $st,
290             'block' => $block,
291             'free' => $fs->{free},
292             'used' => $fs->{used},
293             'size' => $fs->{size},
294             'special' => $special,
295             'useblock' => $use_block,
296             'sourcenames' => join("\n", @sourcenames),
297             'fsroot' => $fs->{fsroot},
298             'fstype' => $fs->{fstype},
299             'mountpoint' => $fs->{target},
300             'parentfsid' => $fs->{parent},
301             #%{$fs},
302             @_
303             );
304             };
305              
306             sub BUILD {
307 272     272 0 895631 my $self=shift;
308 272         616 my $args=shift;
309 272         1974 $self->provideBlock($args->{provide});
310             }
311              
312             sub dotLabel {
313 78     78 0 186 my $self = shift;
314             #if ($self->size == 0 && $self->special) {
315 78 50       3409 if ($self->sourcenames eq 'Source: '.$self->{fstype}) {
316 0 0       0 if ($self->size == 0) {
317 0         0 return ($self->mountpoint.' ('.$self->fstype.')');
318             } else {
319             return (
320 0         0 $self->mountpoint,
321             $self->fstype,
322             );
323             }
324             }
325             return (
326 78         3001 $self->mountpoint,
327             $self->sourcenames,
328             $self->fstype,
329             );
330             }
331              
332             around 'sizeLabel' => sub {
333             my $orig = shift;
334             my $self = shift;
335              
336             if ($self->size == 0) {
337             return;
338             }
339             return $self->$orig(@_);
340             };
341              
342             around dotLinks => sub {
343             my $orig = shift;
344             my $self = shift;
345              
346             my @links = $self->$orig(@_);
347             if ($self->parentfsid != 1) {
348             push @links, $self->sd->block($self->sd->fs_mountpoint_blockname_by_id($self->parentfsid))->elem->linkname.' -> '.$self->linkname.' [style=invis]';
349             }
350             #if ($fs->{parent} != 1) {
351             # push @consume, $st->block($st->fs_mountpoint_blockname_by_id($fs->{parent}));
352             #}
353             return @links;
354             };
355              
356             1;
357              
358             ##################################################################
359             package StorageDisplay::Data::FS::MP;
360             # Container for FS that has children FS
361              
362 9     9   88 use Moose;
  9         36  
  9         111  
363 9     9   75304 use namespace::sweep;
  9         22  
  9         65  
364              
365             extends 'StorageDisplay::Data::Elem';
366              
367             with (
368             'StorageDisplay::Role::Style::IsSubGraph',
369             'StorageDisplay::Role::Style::Grey',
370             #'StorageDisplay::Role::Style::SubInternal',
371             );
372              
373             around 'BUILDARGS' => sub {
374             my $orig = shift;
375             my $class = shift;
376             #my $args = shift;
377             #for my $i (@_) {
378             # print STDERR "args=$i\n";
379             #}
380             my %args=(@_);
381             my $fs = $args{fs};
382              
383             return $class->$orig(
384             'name' => $fs->{id}.'@'.$fs->{target},
385             %args,
386             );
387             };
388              
389             sub BUILD {
390 12     12 0 20980 my $self=shift;
391 12         34 my $args=shift;
392              
393 12         116 $self->addChild($args->{fs_elem});
394 12         97 $self->newChild('FS::MP::C', $args);
395             }
396              
397             sub dotLabel {
398 24     24 0 102 return ();
399             }
400              
401             1;
402              
403             ##################################################################
404             package StorageDisplay::Data::FS::MP::C;
405             # Container for children FS
406              
407 9     9   6189 use Moose;
  9         26  
  9         53  
408 9     9   90537 use namespace::sweep;
  9         27  
  9         67  
409              
410             extends 'StorageDisplay::Data::Elem';
411              
412             with (
413             'StorageDisplay::Role::Style::IsSubGraph',
414             #'StorageDisplay::Role::Style::Grey',
415             'StorageDisplay::Role::Style::SubInternal',
416             #'StorageDisplay::Role::HasBlock',
417             #'StorageDisplay::Role::Style::WithUsed',
418             );
419              
420             sub BUILD {
421 12     12 0 22221 my $self=shift;
422 12         34 my $args=shift;
423              
424 12         40 my $st = $args->{st};
425 12         33 my $SDFS = $args->{SDFS};
426 12         32 my $fullfs = $args->{fullfs};
427 12         33 my $fs = $args->{fs};
428              
429 12         26 for my $child (@{$args->{fs_children}}) {
  12         52  
430 32         135 $self->addChild($child);
431             }
432             }
433              
434             sub dotLabel {
435 24     24 0 119 return ();
436             }
437              
438             1;
439              
440             ##################################################################
441             package StorageDisplay::Data::FS::SWAP;
442              
443 9     9   2822 use Moose;
  9         21  
  9         55  
444 9     9   92048 use namespace::sweep;
  9         25  
  9         89  
445             extends 'StorageDisplay::Data::Elem';
446              
447             with (
448             'StorageDisplay::Role::Style::IsSubGraph',
449             'StorageDisplay::Role::Style::WithUsed',
450             );
451              
452             has '_swaps' => (
453             traits => [ 'Array' ],
454             is => 'ro',
455             isa => 'ArrayRef[StorageDisplay::Data::FS::SWAP::Elem]',
456             required => 1,
457             handles => {
458             '_add_swap' => 'push',
459             'all_swap' => 'elements',
460             'nb_swap' => 'count',
461             }
462             );
463              
464             around BUILDARGS => sub {
465             my $orig = shift;
466             my $class = shift;
467             my $st = shift;
468             my $swaps = shift;
469              
470             $st->log({level=>1}, "SWAP");
471              
472             my $name = '@FS@SWAP';
473              
474             my ($size, $free, $used) = (0, 0, 0);
475             for my $s (@{$swaps}) {
476             $size += $s->size;
477             $free += $s->free;
478             $used += $s->used;
479             }
480              
481             return $class->$orig(
482             'name' => $name,
483             'st' => $st,
484             'free' => $free,
485             'size' => $size,
486             'used' => $used,
487             '_swaps' => $swaps,
488             @_
489             );
490             };
491              
492             sub BUILD {
493 2     2 0 4762 my $self=shift;
494 2         6 my $args=shift;
495              
496 2         128 for my $s ($self->all_swap) {
497 0         0 $self->addChild($s);
498             }
499             }
500              
501             sub dotLabel {
502 4     4 0 11 my $self = shift;
503 4         263 my $nb_swap = $self->nb_swap;
504             return (
505 4         87 "SWAP",
506             );
507             }
508              
509             sub dotStyle2 {
510 0     0 0 0 my $orig = shift;
511 0         0 my $self = shift;
512              
513             return (
514 0         0 "style=filled;",
515             "color=lightgrey;",
516             "fillcolor=lightgrey;",
517             "node [style=filled,color=lightgrey,fillcolor=lightgrey,shape=rectangle];",
518             );
519             };
520              
521             around 'dotStyle' => sub {
522             my $orig = shift;
523             my $self = shift;
524              
525             my @config = (map {
526             my $val = $_;
527             $val =~ s/^color=.*;/color=white/;
528             $val =~ s/,color=[^,]*,/,color=white,/;
529             $val;
530             } ($self->$orig(@_)));
531             return @config;
532             };
533              
534             1;
535              
536             ##################################################################
537             package StorageDisplay::Data::FS::SWAP::Elem;
538              
539 9     9   6267 use Moose;
  9         21  
  9         60  
540 9     9   88834 use namespace::sweep;
  9         29  
  9         70  
541             extends 'StorageDisplay::Data::Elem';
542              
543             with (
544             'StorageDisplay::Role::HasBlock',
545             'StorageDisplay::Role::Style::WithUsed',
546             );
547              
548             has 'fstype' => (
549             is => 'ro',
550             isa => 'Str',
551             );
552              
553             has 'standalone' => (
554             is => 'ro',
555             isa => 'Bool',
556             default => 0,
557             required => 1,
558             writer => '_standalone'
559             );
560              
561             sub onlyoneswap {
562 5     5 0 15 my $self = shift;
563 5         264 return $self->_standalone(1);
564             }
565              
566             sub BUILD {
567 5     5 0 12774 my $self=shift;
568 5         15 my $args=shift;
569 5         65 $self->provideBlock($args->{'provide'});
570             }
571              
572             sub dotLabel {
573 10     10 0 22 my $self = shift;
574 10 50       435 if ($self->standalone) {
575             return (
576 10         434 'SWAP',
577             'Device: '.$self->block->dname,
578             );
579             }
580             return (
581 0           $self->block->dname,
582             );
583             }
584              
585             1;
586              
587             ##################################################################
588             package StorageDisplay::Data::FS::SWAP::Partition;
589              
590 9     9   4595 use Moose;
  9         26  
  9         62  
591 9     9   88159 use namespace::sweep;
  9         23  
  9         65  
592             extends 'StorageDisplay::Data::FS::SWAP::Elem';
593              
594             around BUILDARGS => sub {
595             my $orig = shift;
596             my $class = shift;
597             my $dev = shift;
598             my $st = shift;
599             my $fs = shift;
600              
601             my $block = $st->block($dev);
602             $st->log({level=>1}, "SWAP@".$dev);
603              
604             my $name = $block->name;
605              
606             return $class->$orig(
607             'name' => $name,
608             'consume' => [$block],
609             'provide' => $st->block($st->fs_swap_blockname($name)),
610             'st' => $st,
611             'block' => $block,
612             %{$fs},
613             @_
614             );
615             };
616              
617             1;
618              
619             ##################################################################
620             package StorageDisplay::Data::FS::SWAP::File;
621              
622 9     9   2863 use Moose;
  9         25  
  9         84  
623 9     9   89496 use namespace::sweep;
  9         23  
  9         73  
624             extends 'StorageDisplay::Data::FS::SWAP::Elem';
625              
626             around BUILDARGS => sub {
627             my $orig = shift;
628             my $class = shift;
629             my $file = shift;
630             my $st = shift;
631             my $fs = shift;
632              
633             my $block = $st->block($file);
634             $st->log({level=>1}, "SWAP@".$file);
635              
636             my $name = $file;
637             my $fblock = $st->block($st->fs_mountpoint_blockname($fs->{'file-mountpoint'} // '@none@'));
638             if (defined($fs->{'file-size'})) {
639             $fblock->size($fs->{'file-size'});
640             }
641              
642             return $class->$orig(
643             'name' => $name,
644             'consume' => [$fblock],
645             'provide' => $st->block($st->fs_swap_blockname($file)),
646             'st' => $st,
647             'block' => $block,
648             %{$fs},
649             @_
650             );
651             };
652              
653             1;
654              
655             __END__
656              
657             =pod
658              
659             =encoding UTF-8
660              
661             =head1 NAME
662              
663             StorageDisplay::Data::FS - Handle filesystem data for StorageDisplay
664              
665             =head1 VERSION
666              
667             version 2.06
668              
669             =head1 AUTHOR
670              
671             Vincent Danjean <Vincent.Danjean@ens-lyon.org>
672              
673             =head1 COPYRIGHT AND LICENSE
674              
675             This software is copyright (c) 2014-2023 by Vincent Danjean.
676              
677             This is free software; you can redistribute it and/or modify it under
678             the same terms as the Perl 5 programming language system itself.
679              
680             =cut