File Coverage

blib/lib/FusionInventory/Agent/Task/Inventory/Linux/Drives.pm
Criterion Covered Total %
statement 12 85 14.1
branch 0 50 0.0
condition 0 12 0.0
subroutine 4 9 44.4
pod 0 2 0.0
total 16 158 10.1


line stmt bran cond sub pod time code
1             package FusionInventory::Agent::Task::Inventory::Linux::Drives;
2              
3 1     1   31749749 use strict;
  1         8  
  1         70  
4 1     1   10 use warnings;
  1         1  
  1         58  
5              
6 1     1   469 use FusionInventory::Agent::Tools;
  1         2  
  1         140  
7 1     1   498 use FusionInventory::Agent::Tools::Unix;
  1         3  
  1         1036  
8              
9             sub isEnabled {
10 0     0 0   my (%params) = @_;
11 0 0         return 0 if $params{no_category}->{drive};
12             return
13 0   0       canRun('df') ||
14             canRun('lshal');
15             }
16              
17             sub doInventory {
18 0     0 0   my (%params) = @_;
19              
20 0           my $inventory = $params{inventory};
21 0           my $logger = $params{logger};
22              
23 0           foreach my $filesystem (_getFilesystems($logger)) {
24 0           $inventory->addEntry(
25             section => 'DRIVES',
26             entry => $filesystem
27             );
28             }
29             }
30              
31             sub _getFilesystems {
32 0     0     my ($logger) = @_;
33              
34             # get filesystems list
35 0           my @filesystems =
36             # exclude virtual file systems
37 0           grep { $_->{FILESYSTEM} !~ /^(tmpfs|usbfs|proc|devpts|devshm|udev)$/ }
38             # get all file systems
39             getFilesystemsFromDf(logger => $logger, command => 'df -P -T -k');
40              
41             # get additional informations
42 0 0         if (canRun('blkid')) {
43             # use blkid if available, as it is filesystem-independent
44 0           foreach my $filesystem (@filesystems) {
45 0           $filesystem->{SERIAL} = getFirstMatch(
46             logger => $logger,
47             command => "blkid -w /dev/null $filesystem->{VOLUMN}",
48             pattern => qr/\sUUID="(\S*)"\s/
49             );
50             }
51             } else {
52             # otherwise fallback to filesystem-dependant utilities
53 0           my $has_dumpe2fs = canRun('dumpe2fs');
54 0           my $has_xfs_db = canRun('xfs_db');
55 0           my $has_dosfslabel = canRun('dosfslabel');
56 0           my %months = (
57             Jan => 1,
58             Feb => 2,
59             Mar => 3,
60             Apr => 4,
61             May => 5,
62             Jun => 6,
63             Jul => 7,
64             Aug => 8,
65             Sep => 9,
66             Oct => 10,
67             Nov => 11,
68             Dec => 12,
69             );
70              
71 0           foreach my $filesystem (@filesystems) {
72 0 0 0       if ($filesystem->{FILESYSTEM} =~ /^ext(2|3|4|4dev)/ && $has_dumpe2fs) {
73 0           my $handle = getFileHandle(
74             logger => $logger,
75             command => "dumpe2fs -h $filesystem->{VOLUMN}"
76             );
77 0 0         next unless $handle;
78 0           while (my $line = <$handle>) {
79 0 0         if ($line =~ /Filesystem UUID:\s+(\S+)/) {
    0          
    0          
80 0           $filesystem->{SERIAL} = $1;
81             } elsif ($line =~ /Filesystem created:\s+\w+\s+(\w+)\s+(\d+)\s+([\d:]+)\s+(\d{4})$/) {
82 0           $filesystem->{CREATEDATE} = "$4/$months{$1}/$2 $3";
83             } elsif ($line =~ /Filesystem volume name:\s*(\S.*)/) {
84 0 0         $filesystem->{LABEL} = $1 unless $1 eq '';
85             }
86             }
87 0           close $handle;
88 0           next;
89             }
90              
91 0 0 0       if ($filesystem->{FILESYSTEM} eq 'xfs' && $has_xfs_db) {
92 0           $filesystem->{SERIAL} = getFirstMatch(
93             logger => $logger,
94             command => "xfs_db -r -c uuid $filesystem->{VOLUMN}",
95             pattern => qr/^UUID =\s+(\S+)/
96             );
97 0           $filesystem->{LABEL} = getFirstMatch(
98             logger => $logger,
99             command => "xfs_db -r -c label $filesystem->{VOLUMN}",
100             pattern => qr/^label =\s+"(\S+)"/
101             );
102 0           next;
103             }
104              
105 0 0 0       if ($filesystem->{FILESYSTEM} eq 'vfat' && $has_dosfslabel) {
106 0           $filesystem->{LABEL} = getFirstLine(
107             logger => $logger,
108             command => "dosfslabel $filesystem->{VOLUMN}"
109             );
110 0           next;
111             }
112             }
113             }
114              
115             # complete with hal if available
116 0 0         if (canRun('lshal')) {
117 0           my @hal_filesystems = _getFilesystemsFromHal();
118 0           my %hal_filesystems = map { $_->{VOLUMN} => $_ } @hal_filesystems;
  0            
119              
120 0           foreach my $filesystem (@filesystems) {
121             # retrieve hal informations for this drive
122 0           my $hal_filesystem = $hal_filesystems{$filesystem->{VOLUMN}};
123 0 0         next unless $hal_filesystem;
124              
125             # take hal information if it doesn't exist already
126 0           foreach my $key (keys %$hal_filesystem) {
127 0 0         $filesystem->{$key} = $hal_filesystem->{$key}
128             if !$filesystem->{$key};
129             }
130             }
131             }
132              
133 0           return @filesystems;
134             }
135              
136             sub _getFilesystemsFromHal {
137 0     0     my $devices = _parseLshal(command => 'lshal');
138 0           return @$devices;
139             }
140              
141             sub _parseLshal {
142 0     0     my $handle = getFileHandle(@_);
143 0 0         return unless $handle;
144              
145 0           my $devices = [];
146 0           my $device = {};
147              
148 0           while (my $line = <$handle>) {
149 0           chomp $line;
150 0 0         if ($line =~ m{^udi = '/org/freedesktop/Hal/devices/(volume|block).*}) {
151 0           $device = {};
152 0           next;
153             }
154              
155 0 0         next unless defined $device;
156              
157 0 0         if ($line =~ /^$/) {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
158 0 0         if ($device->{ISVOLUME}) {
159 0           delete($device->{ISVOLUME});
160 0           push(@$devices, $device);
161             }
162 0           undef $device;
163             } elsif ($line =~ /^\s+ block.device \s = \s '([^']+)'/x) {
164 0           $device->{VOLUMN} = $1;
165             } elsif ($line =~ /^\s+ volume.fstype \s = \s '([^']+)'/x) {
166 0           $device->{FILESYSTEM} = $1;
167             } elsif ($line =~ /^\s+ volume.label \s = \s '([^']+)'/x) {
168 0           $device->{LABEL} = $1;
169             } elsif ($line =~ /^\s+ volume.uuid \s = \s '([^']+)'/x) {
170 0           $device->{SERIAL} = $1;
171             } elsif ($line =~ /^\s+ storage.model \s = \s '([^']+)'/x) {
172 0           $device->{TYPE} = $1;
173             } elsif ($line =~ /^\s+ volume.size \s = \s (\S+)/x) {
174 0           my $value = $1;
175 0           $device->{TOTAL} = int($value/(1024*1024) + 0.5);
176             } elsif ($line =~ /block.is_volume\s*=\s*true/i) {
177 0           $device->{ISVOLUME} = 1;
178             }
179             }
180 0           close $handle;
181              
182 0           return $devices;
183             }
184              
185             1;