File Coverage

blib/lib/FusionInventory/Agent/Task/Inventory/Linux/Drives.pm
Criterion Covered Total %
statement 37 85 43.5
branch 23 50 46.0
condition 0 12 0.0
subroutine 5 9 55.5
pod 0 2 0.0
total 65 158 41.1


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