File Coverage

blib/lib/Linux/LVM2/Utils.pm
Criterion Covered Total %
statement 25 83 30.1
branch 0 28 0.0
condition 0 7 0.0
subroutine 9 13 69.2
pod 4 4 100.0
total 38 135 28.1


line stmt bran cond sub pod time code
1             package Linux::LVM2::Utils;
2             {
3             $Linux::LVM2::Utils::VERSION = '0.14';
4             }
5             BEGIN {
6 1     1   1760 $Linux::LVM2::Utils::AUTHORITY = 'cpan:TEX';
7             }
8             # ABSTRACT: Linux LVM2 helper
9              
10 1     1   22 use 5.010_000;
  1         5  
  1         47  
11 1     1   6 use mro 'c3';
  1         2  
  1         7  
12 1     1   31 use feature ':5.10';
  1         3  
  1         108  
13              
14 1     1   7 use strict;
  1         2  
  1         54  
15 1     1   6 use warnings;
  1         1  
  1         36  
16              
17             # use IO::Handle;
18             # use autodie;
19              
20 1     1   6 use Carp;
  1         2  
  1         97  
21 1     1   8 use File::Basename;
  1         1  
  1         95  
22 1     1   1206 use POSIX qw();
  1         12685  
  1         1009  
23              
24             # translate_devmapper_name
25             # inspired by translate_devicemapper_name from the munin diskstats plugin
26             # which was written by Michael Renner <michael.renner@amd.co.at>
27             sub translate_devmapper_name {
28 0     0 1   my $device = shift;
29              
30 0           my $want_minor;
31              
32 0 0         if($device =~ m/^dm-(\d+)$/) {
33 0           $want_minor = $1;
34             }
35              
36 0 0         if(!$want_minor) {
37 0           carp "No devicemapper id found\n";
38 0           return;
39             }
40              
41 0           my $dm_major = find_dm_major();
42              
43 0 0         if(!$dm_major) {
44 0           carp "No devicemapper major id found\n";
45 0           return;
46             }
47              
48 0           foreach my $dirent ( glob('/dev/mapper/*')) {
49 0           my $rdev = (stat($dirent))[6];
50 0           my $major = POSIX::floor($rdev / 256 );
51 0           my $minor = $rdev % 256;
52              
53 0 0 0       if( $major == $dm_major && $minor == $want_minor) {
54 0           my $display_name = translate_lvm_name($dirent);
55 0           $dirent =~ s#/dev/##;
56              
57 0 0         if(defined($display_name)) {
58 0           return $display_name;
59             } else {
60 0           return $dirent;
61             }
62             }
63             }
64              
65             # fallback in case our search was fruitless
66 0           return $device;
67             }
68              
69             # translate_lvm_name
70             # inspired by translate_lvm_name from the munin diskstats plugin
71             # which was written by Michael Renner <michael.renner@amd.co.at>
72             sub translate_lvm_name {
73 0     0 1   my $device = shift;
74 0   0       my $no_stat = shift || 0;
75              
76 0           my $device_name = File::Basename::basename($device);
77              
78             # search for single dashes as this suggests for a lvm devmapper dev
79 0 0         if ( $device_name =~ m/(?<!-)-(?!-)/ ) {
80             # split into vg and lv parts
81 0           my ( $vg, $lv ) = split /(?<!-)-(?!-)/, $device_name, 2;
82              
83             # remove superflous dashes from vg and lv names
84 0           $vg =~ s/--/-/g;
85 0           $lv =~ s/--/-/g;
86              
87 0           $device_name = '/dev/'.$vg.'/'.$lv;
88              
89             # assert that the assembled device name actually exists
90 0 0         if($no_stat) {
    0          
91 0           return $device_name;
92             }
93             elsif( stat($device_name)) {
94 0           return $device_name;
95             }
96             }
97              
98 0           return;
99             }
100              
101             # translate_mapper_name
102             sub translate_mapper_name {
103 0     0 1   my $entry = shift;
104 0   0       my $no_stat = shift || 0;
105              
106 0 0         if ( $entry =~ m#^/dev/([^/]+)/(.*)$# ) {
107 0           my $vg = $1;
108 0           my $lv = $2;
109              
110             # add extraneous dashes to vg and lv names
111 0           $vg =~ s/-/--/g;
112 0           $lv =~ s/-/--/g;
113              
114 0           my $device_name = '/dev/mapper/'.$vg.'-'.$lv;
115              
116             # Sanity check - does the constructed device name exist?
117             # Breaks unless we are root.
118 0 0         if( $no_stat) {
    0          
119 0           return $device_name;
120             }
121             elsif ( stat($device_name) ) {
122 0           return $device_name;
123             }
124             }
125              
126 0           return $entry;
127             }
128              
129             # find_devicemapper_major
130             # inspired by find_devicemapper_major from the munin diskstats plugin
131             # which was written by Michael Renner <michael.renner@amd.co.at>
132             sub find_devicemapper_major {
133 0     0 1   my $dm_major;
134              
135 0 0         if(open(my $fh, '<', '/proc/devices')) {
136 0           my @lines = <$fh>;
137             ## no critic (RequireCheckedClose)
138 0           close($fh);
139             ## use critic
140 0           chomp(@lines);
141 0           foreach my $line ( @lines ) {
142              
143 0           my ($major, $name ) = split /\s+/, $line, 2;
144              
145 0 0         next unless defined $name;
146              
147 0 0         if ( $name eq 'device-mapper' ) {
148 0           $dm_major = $major;
149 0           last;
150             }
151             }
152             }
153              
154 0           return $dm_major;
155             }
156              
157             1;
158              
159             __END__
160              
161             =pod
162              
163             =encoding utf-8
164              
165             =head1 NAME
166              
167             Linux::LVM2::Utils - Linux LVM2 helper
168              
169             =head1 SYNOPSIS
170              
171             use Linux::LVM2::Utils
172              
173             =head1 DESCRIPTION
174              
175             This class provides some helper methods that aid in handling of Linux LVM2 devices.
176              
177             =head1 FUNCTIONS
178              
179             =head2 find_devicemapper_major
180              
181             Searches for the major number of the devicemapper device
182              
183             =head2 translate_devmapper_name
184              
185             This method tries to find a device mapper name based on the dm minor number.
186              
187             It will return either the resolved device mapper name or the original device.
188              
189             =head2 translate_lvm_name
190              
191             This method tries to translate an dev-mapper device name to
192             its LVM counterpart, e.g. /dev/mapper/vg-lv -> /dev/vg/lv
193              
194             =head2 translate_mapper_name
195              
196             Translates LVM names to their ugly devicemapper names
197             e.g. /dev/VGfoo/LVbar -> /dev/mapper/VGfoo-LVbar
198              
199             =head1 NAME
200              
201             Linux::LVM2::Utils - LVM2 helper methods.
202              
203             =head1 AUTHOR
204              
205             Dominik Schulz <dominik.schulz@gauner.org>
206              
207             =head1 COPYRIGHT AND LICENSE
208              
209             This software is copyright (c) 2012 by Dominik Schulz.
210              
211             This is free software; you can redistribute it and/or modify it under
212             the same terms as the Perl 5 programming language system itself.
213              
214             =cut