1 | #!/usr/bin/perl -w
|
---|
2 | #
|
---|
3 | # Subroutines related to LVM brought by the MondoRescue project
|
---|
4 | #
|
---|
5 | # $Id$
|
---|
6 | #
|
---|
7 | # Copyright B. Cornec 2008-2014
|
---|
8 | # Provided under the GPL v2
|
---|
9 |
|
---|
10 | package MondoRescue::LVM;
|
---|
11 |
|
---|
12 | use strict 'vars';
|
---|
13 | use Data::Dumper;
|
---|
14 | use English;
|
---|
15 | use lib qw (lib);
|
---|
16 | use ProjectBuilder::Base;
|
---|
17 | use ProjectBuilder::Conf;
|
---|
18 | use MondoRescue::Base;
|
---|
19 |
|
---|
20 | # Inherit from the "Exporter" module which handles exporting functions.
|
---|
21 |
|
---|
22 | use Exporter;
|
---|
23 |
|
---|
24 | # Export, by default, all the functions into the namespace of
|
---|
25 | # any code which uses this module.
|
---|
26 |
|
---|
27 | our @ISA = qw(Exporter);
|
---|
28 | our @EXPORT = qw(mr_lvm_check mr_lvm_get_conf mr_lvm_read_conf mr_lvm_write_conf mr_lvm_edit_conf mr_lvm_apply_from_conf);
|
---|
29 |
|
---|
30 | =pod
|
---|
31 |
|
---|
32 | =head1 NAME
|
---|
33 |
|
---|
34 | MondoRescue::LVM, part of the mondorescue.org
|
---|
35 |
|
---|
36 | =head1 DESCRIPTION
|
---|
37 |
|
---|
38 | This modules provides low level functions for LVM support in the Mondorescue project
|
---|
39 |
|
---|
40 | =head1 USAGE
|
---|
41 |
|
---|
42 | =over 4
|
---|
43 |
|
---|
44 | =item B<mr_lvm_check>
|
---|
45 |
|
---|
46 | This function checks the usage of LVM and gets the version used
|
---|
47 | It returns 2 parameters, the LVM version, and the lvm command to use if needed
|
---|
48 | The LVM version could be undef, 0 (no LVM), 1 or 2 at the moment, or further not yet supported version
|
---|
49 | It potentially takes one parameter, the LVM version, already known, in which case it easily deduced the LVM command.
|
---|
50 | If LVM version is undefined then no LVM Handling should be done.
|
---|
51 | It has to run on on a system where LVM is activated to return useful results so typically on the system to backup
|
---|
52 |
|
---|
53 | =cut
|
---|
54 |
|
---|
55 | sub mr_lvm_check {
|
---|
56 |
|
---|
57 | my $lvmver = shift;
|
---|
58 |
|
---|
59 | # Get params from the conf file
|
---|
60 | my ($lvmds_t,$lvmproc_t,$lvmcmd_t,$lvmpath_t) = pb_conf_get("mr_cmd_lvmdiskscan","mr_proc_lvm","mr_cmd_lvm","mr_path_lvm");
|
---|
61 | my $lvmds = $lvmds_t->{$ENV{PBPROJ}};
|
---|
62 | my $lvmproc = $lvmproc_t->{$ENV{PBPROJ}};
|
---|
63 | my $lvmcmd = $lvmcmd_t->{$ENV{PBPROJ}};
|
---|
64 | my $lvmpath = $lvmpath_t->{$ENV{PBPROJ}};
|
---|
65 |
|
---|
66 | # That file is not mandatory anymore
|
---|
67 | if (not defined $lvmver) {
|
---|
68 | if (! -x $lvmproc) {
|
---|
69 | pb_log(1,"$lvmproc doesn't exist\n");
|
---|
70 | } else {
|
---|
71 | # Check LVM volumes presence
|
---|
72 | pb_log(2,"Checking with $lvmproc\n");
|
---|
73 | open(LVM,$lvmproc) || mr_exit(-1,"Unable to open $lvmproc");
|
---|
74 | while (<LVM>) {
|
---|
75 | if (/0 VGs 0 PVs 0 LVs/) {
|
---|
76 | pb_log(1,"No LVM volumes found in $lvmproc\n");
|
---|
77 | return(0,undef);
|
---|
78 | }
|
---|
79 | }
|
---|
80 | close(LVM);
|
---|
81 | }
|
---|
82 | }
|
---|
83 |
|
---|
84 | # Check LVM version
|
---|
85 | if (not defined $lvmver) {
|
---|
86 | pb_log(2,"LVM version value is not known\n");
|
---|
87 | if (-x $lvmds) {
|
---|
88 | pb_log(2,"Checking with $lvmds\n");
|
---|
89 | open(LVM,"$lvmds --help 2>&1 |") || mr_exit(-1,"Unable to execute $lvmds");
|
---|
90 | while (<LVM>) {
|
---|
91 | if (/Logical Volume Manager/ || /LVM version:/) {
|
---|
92 | $lvmver = $_;
|
---|
93 | chomp($lvmver);
|
---|
94 | $lvmver =~ s/:([0-9])\..*/$1/;
|
---|
95 | }
|
---|
96 | }
|
---|
97 | close(LVM);
|
---|
98 | pb_log(2,"Found a LVM version of $lvmver with $lvmds --help\n") if (defined $lvmver);
|
---|
99 | }
|
---|
100 | }
|
---|
101 |
|
---|
102 | if (not defined $lvmver) {
|
---|
103 | pb_log(2,"LVM version value is still not known\n");
|
---|
104 | if (-x $lvmcmd) {
|
---|
105 | pb_log(2,"Checking with $lvmcmd\n");
|
---|
106 | open(LVM,"$lvmcmd version |") || mr_exit(-1,"Unable to execute $lvmcmd");
|
---|
107 | while (<LVM>) {
|
---|
108 | if (/LVM version/) {
|
---|
109 | $lvmver = $_;
|
---|
110 | chomp($lvmver);
|
---|
111 | $lvmver =~ s/:([0-9])\..*/$1/;
|
---|
112 | $lvmver =~ s/[\s]*LVM version[:]*[\s]+([0-9])\..*/$1/;
|
---|
113 | }
|
---|
114 | }
|
---|
115 | close(LVM);
|
---|
116 | pb_log(2,"Found a LVM version of $lvmver with $lvmcmd version\n") if (defined $lvmver);
|
---|
117 | }
|
---|
118 | }
|
---|
119 |
|
---|
120 | if (not defined $lvmver) {
|
---|
121 | # Still not found
|
---|
122 | mr_log(0,"Unable to determine LVM version.\nIf you think this is wrong, please report to the dev team with the result of the commands:\n$lvmds --help and $lvmcmd version\n");
|
---|
123 | } elsif ($lvmver == 1) {
|
---|
124 | $lvmcmd = "$lvmpath";
|
---|
125 | } elsif ($lvmver == 2) {
|
---|
126 | $lvmcmd .= " ";
|
---|
127 | } else {
|
---|
128 | pb_log(0,"Unknown LVM version $lvmver\n");
|
---|
129 | }
|
---|
130 | # Here $lvmcmd contains a full path name
|
---|
131 | pb_log(1,"Found LVM version $lvmver\n");
|
---|
132 | return ($lvmver,$lvmcmd);
|
---|
133 |
|
---|
134 | }
|
---|
135 |
|
---|
136 | =over 4
|
---|
137 |
|
---|
138 | =item B<mr_lvm_get_conf>
|
---|
139 |
|
---|
140 | This function returns 1 parameters, the LVM structure or undef if no LVM
|
---|
141 | That LVM structure contains all the information related to the current LVM configuration
|
---|
142 |
|
---|
143 | =cut
|
---|
144 |
|
---|
145 | sub mr_lvm_get_conf {
|
---|
146 |
|
---|
147 | my $lvm = undef;
|
---|
148 |
|
---|
149 | my ($lvmver,$lvmcmd) = mr_lvm_check();
|
---|
150 | return(undef) if ((not defined $lvmver) || ($lvmver == 0));
|
---|
151 |
|
---|
152 | # Analyze the existing physical volumes
|
---|
153 | open(LVM,$lvmcmd."pvs --noheadings --nosuffix --units m --separator : -o pv_name,vg_name,pv_all,pv_fmt,pv_uuid,dev_size,pv_mda_free,pv_mda_size |") || mr_exit(-1,"Unable to execute ".$lvmcmd."pvs");
|
---|
154 | while (<LVM>) {
|
---|
155 | s/^[\s]*//;
|
---|
156 |
|
---|
157 | my ($pv_name,$vg_name,$pe_start,$pv_size,$pv_free,$pv_used,$pv_attr,$pv_pe_count,$pv_pe_alloc_count,$pv_tags,$pv_mda_count,$pv_uuid,$dev_size,$pv_mda_free,$pv_mda_size) = split(/:/);
|
---|
158 |
|
---|
159 | =pod
|
---|
160 |
|
---|
161 | The LVM hash is indexed by VGs, provided by the vg_name attribute of the pvs command
|
---|
162 | vg_name - Name of the volume group linked to this PV
|
---|
163 |
|
---|
164 | =cut
|
---|
165 |
|
---|
166 | $lvm->{$vg_name}->{'pvnum'}++;
|
---|
167 |
|
---|
168 | =pod
|
---|
169 |
|
---|
170 | The structure contains an array of PVs called pvs and starting at 1, containing the name of the PV as provided by the pv_name attribute of the pvs command
|
---|
171 | pv_name - Name of the physical volume PV
|
---|
172 |
|
---|
173 | =cut
|
---|
174 |
|
---|
175 | # Array of PVs for that VG
|
---|
176 | $lvm->{$vg_name}->{'pvs'}->[$lvm->{$vg_name}->{'pvnum'}] = $pv_name;
|
---|
177 |
|
---|
178 | =pod
|
---|
179 |
|
---|
180 | All the PV fields from the pvs command are gathered under their PV name (substructure)
|
---|
181 | The following names are used:
|
---|
182 |
|
---|
183 | From pvs -o help
|
---|
184 | pe_start - Offset to the start of data on the underlying device.
|
---|
185 | pv_size - Size of PV in current units.
|
---|
186 | pv_free - Total amount of unallocated space in current units.
|
---|
187 | pv_used - Total amount of allocated space in current units.
|
---|
188 | pv_attr - Various attributes - see man page.
|
---|
189 | pv_pe_count - Total number of Physical Extents.
|
---|
190 | pv_pe_alloc_count - Total number of allocated Physical Extents.
|
---|
191 | pv_tags - Tags, if any.
|
---|
192 | pv_mda_count - Number of metadata areas on this device.
|
---|
193 | pv_fmt - Type of metadata.
|
---|
194 | pv_uuid - Unique identifier.
|
---|
195 | dev_size - Size of underlying device in current units.
|
---|
196 | pv_mda_free - Free metadata area space on this device in current units.
|
---|
197 | pv_mda_size - Size of smallest metadata area on this device in current units.
|
---|
198 |
|
---|
199 | =cut
|
---|
200 |
|
---|
201 | $lvm->{$vg_name}->{$pv_name}->{'pe_start'} = $pe_start;
|
---|
202 | $lvm->{$vg_name}->{$pv_name}->{'pv_size'} = $pv_size;
|
---|
203 | $lvm->{$vg_name}->{$pv_name}->{'pv_free'} = $pv_free;
|
---|
204 | $lvm->{$vg_name}->{$pv_name}->{'pv_used'} = $pv_used;
|
---|
205 | $lvm->{$vg_name}->{$pv_name}->{'pv_attr'} = $pv_attr;
|
---|
206 | $lvm->{$vg_name}->{$pv_name}->{'pv_pe_count'} = $pv_pe_count;
|
---|
207 | $lvm->{$vg_name}->{$pv_name}->{'pv_pe_alloc_count'} = $pv_pe_alloc_count;
|
---|
208 | $lvm->{$vg_name}->{$pv_name}->{'pv_tags'} = $pv_tags;
|
---|
209 | $lvm->{$vg_name}->{$pv_name}->{'pv_mda_count'} = $pv_mda_count;
|
---|
210 | $lvm->{$vg_name}->{$pv_name}->{'pv_uuid'} = $pv_uuid;
|
---|
211 | $lvm->{$vg_name}->{$pv_name}->{'dev_size'} = $dev_size;
|
---|
212 | $lvm->{$vg_name}->{$pv_name}->{'pv_mda_free'} = $pv_mda_free;
|
---|
213 | $lvm->{$vg_name}->{$pv_name}->{'pv_mda_size'} = $pv_mda_size;
|
---|
214 | }
|
---|
215 | close(LVM);
|
---|
216 |
|
---|
217 | # Analyze the existing volume groups
|
---|
218 | #open(LVM,$lvmcmd."vgdisplay -c |") || mr_exit(-1,"Unable to execute ".$lvmcmd."vgdisplay -c");
|
---|
219 | open(LVM,$lvmcmd."vgs --noheadings --nosuffix --units m --separator : -o vg_all |") || mr_exit(-1,"Unable to execute ".$lvmcmd."vgs");
|
---|
220 | while (<LVM>) {
|
---|
221 |
|
---|
222 | =pod
|
---|
223 |
|
---|
224 | All the VG fields from the vgs command are gathered under the VG name
|
---|
225 | The following names are used:
|
---|
226 |
|
---|
227 | From vgs -o help
|
---|
228 | vg_fmt - Type of metadata.
|
---|
229 | vg_uuid - Unique identifier.
|
---|
230 | vg_attr - Various attributes - see man page.
|
---|
231 | vg_size - Total size of VG in current units.
|
---|
232 | vg_free - Total amount of free space in current units.
|
---|
233 | vg_sysid - System ID indicating when and where it was created.
|
---|
234 | vg_extent_size - Size of Physical Extents in current units.
|
---|
235 | vg_extent_count - Total number of Physical Extents.
|
---|
236 | vg_free_count - Total number of unallocated Physical Extents.
|
---|
237 | max_lv - Maximum number of LVs allowed in VG or 0 if unlimited.
|
---|
238 | max_pv - Maximum number of PVs allowed in VG or 0 if unlimited.
|
---|
239 | pv_count - Number of PVs.
|
---|
240 | lv_count - Number of LVs.
|
---|
241 | snap_count - Number of snapshots.
|
---|
242 | vg_seqno - Revision number of internal metadata. Incremented whenever it changes.
|
---|
243 | vg_tags - Tags, if any.
|
---|
244 | vg_mda_count - Number of metadata areas in use by this VG.
|
---|
245 | vg_mda_free - Free metadata area space for this VG in current units.
|
---|
246 | vg_mda_size - Size of smallest metadata area for this VG in current units.
|
---|
247 |
|
---|
248 | =cut
|
---|
249 | s/^[\s]*//;
|
---|
250 | my ($vg_fmt,$vg_uuid,$vg_name,$vg_attr,$vg_size,$vg_free,$vg_sysid,$vg_extend_size,$vg_extend_count,$vg_free_count,$max_lv,$max_pv,$pv_count,$lv_count,$snap_count,$vg_seqno,$vg_tags,$vg_mda_count,$vg_mda_free,$vg_mda_size) = split(/:/);
|
---|
251 | $lvm->{$vg_name}->{'vg_fmt'} = $vg_fmt;
|
---|
252 | $lvm->{$vg_name}->{'vg_uuid'} = $vg_uuid;
|
---|
253 | $lvm->{$vg_name}->{'vg_attr'} = $vg_attr;
|
---|
254 | $lvm->{$vg_name}->{'vg_size'} = $vg_size;
|
---|
255 | $lvm->{$vg_name}->{'vg_free'} = $vg_free;
|
---|
256 | $lvm->{$vg_name}->{'vg_sysid'} = $vg_sysid;
|
---|
257 | $lvm->{$vg_name}->{'vg_extend_size'} = $vg_extend_size;
|
---|
258 | $lvm->{$vg_name}->{'vg_extend_count'} = $vg_extend_count;
|
---|
259 | $lvm->{$vg_name}->{'vg_free_count'} = $vg_free_count;
|
---|
260 | $lvm->{$vg_name}->{'max_lv'} = $max_lv;
|
---|
261 | $lvm->{$vg_name}->{'max_pv'} = $max_pv;
|
---|
262 | $lvm->{$vg_name}->{'pv_count'} = $pv_count;
|
---|
263 | $lvm->{$vg_name}->{'lv_count'} = $lv_count;
|
---|
264 | $lvm->{$vg_name}->{'snap_count'} = $snap_count;
|
---|
265 | $lvm->{$vg_name}->{'vg_seqno'} = $vg_seqno;
|
---|
266 | $lvm->{$vg_name}->{'vg_tags'} = $vg_tags;
|
---|
267 | $lvm->{$vg_name}->{'vg_mda_count'} = $vg_mda_count;
|
---|
268 | $lvm->{$vg_name}->{'vg_mda_free'} = $vg_mda_free;
|
---|
269 | $lvm->{$vg_name}->{'vg_mda_size'} = $vg_mda_size;
|
---|
270 | }
|
---|
271 | close(LVM);
|
---|
272 |
|
---|
273 | # Analyze the existing logical volumes
|
---|
274 | #open(LVM,$lvmcmd."lvdisplay -c |") || mr_exit(-1,"Unable to execute ".$lvmcmd."lvdisplay -c");
|
---|
275 | open(LVM,$lvmcmd."lvs --noheadings --nosuffix --units m --separator : -o vg_name,lv_all|") || mr_exit(-1,"Unable to execute ".$lvmcmd."lvs");
|
---|
276 | while (<LVM>) {
|
---|
277 | s/^[\s]*//;
|
---|
278 |
|
---|
279 | =pod
|
---|
280 |
|
---|
281 | The structure contains an array of LVs called lvs and starting at 1, containing the name of the PV as provided by the pv_name attribute of the pvs command
|
---|
282 |
|
---|
283 | =cut
|
---|
284 |
|
---|
285 | my ($vg_name,$lv_uuid,$lv_name,$lv_attr,$lv_major,$lv_minor,$lv_read_ahead,$lv_kernel_major,$lv_kernel_minor,$lv_kernel_read_ahead,$lv_size,$seg_count,$origin,$origin_size,$snap_percent,$copy_percent,$move_pv,$convert_lv,$lv_tags,$mirror_log,$modules) = split(/:/);
|
---|
286 |
|
---|
287 | =pod
|
---|
288 |
|
---|
289 | All the PV fields from the pvs command are gathered under their PV name (substructure)
|
---|
290 | The following names are used:
|
---|
291 |
|
---|
292 |
|
---|
293 | # From lvs -o help
|
---|
294 |
|
---|
295 | #vg_name - Name of the related volume group
|
---|
296 | #lv_uuid - Unique identifier.
|
---|
297 | #lv_name - Name. LVs created for internal use are enclosed in brackets.
|
---|
298 | #lv_attr - Various attributes - see man page.
|
---|
299 | #lv_major - Persistent major number or -1 if not persistent.
|
---|
300 | #lv_minor - Persistent minor number or -1 if not persistent.
|
---|
301 | #lv_read_ahead - Read ahead setting in current units.
|
---|
302 | #lv_kernel_major - Currently assigned major number or -1 if LV is not active.
|
---|
303 | #lv_kernel_minor - Currently assigned minor number or -1 if LV is not active.
|
---|
304 | #lv_kernel_read_ahead - Currently-in-use read ahead setting in current units.
|
---|
305 | #lv_size - Size of LV in current units.
|
---|
306 | #seg_count - Number of segments in LV.
|
---|
307 | #origin - For snapshots, the origin device of this LV.
|
---|
308 | #origin_size - For snapshots, the size of the origin device of this LV.
|
---|
309 | #snap_percent - For snapshots, the percentage full if LV is active.
|
---|
310 | #copy_percent - For mirrors and pvmove, current percentage in-sync.
|
---|
311 | #move_pv - For pvmove, Source PV of temporary LV created by pvmove.
|
---|
312 | #convert_lv - For lvconvert, Name of temporary LV created by lvconvert.
|
---|
313 | #lv_tags - Tags, if any.
|
---|
314 | #mirror_log - For mirrors, the LV holding the synchronisation log.
|
---|
315 | #modules - Kernel device-mapper modules required for this LV.
|
---|
316 |
|
---|
317 | =cut
|
---|
318 |
|
---|
319 | # The LVM hash is indexed by VGs
|
---|
320 | $lvm->{$vg_name}->{'lvnum'}++;
|
---|
321 | # That array will start at 1 then
|
---|
322 | # Array of LVs for that VG
|
---|
323 | $lvm->{$vg_name}->{'lvs'}->[$lvm->{$vg_name}->{'lvnum'}] = $lv_name;
|
---|
324 | # All LV fields gathered under the LV name
|
---|
325 | $lvm->{$vg_name}->{$lv_name}->{'lv_uuid'} = $lv_uuid;
|
---|
326 | $lvm->{$vg_name}->{$lv_name}->{'lv_attr'} = $lv_attr;
|
---|
327 | $lvm->{$vg_name}->{$lv_name}->{'lv_major'} = $lv_major;
|
---|
328 | $lvm->{$vg_name}->{$lv_name}->{'lv_minor'} = $lv_minor;
|
---|
329 | $lvm->{$vg_name}->{$lv_name}->{'lv_read_ahead'} = $lv_read_ahead;
|
---|
330 | $lvm->{$vg_name}->{$lv_name}->{'lv_kernel_major'} = $lv_kernel_major;
|
---|
331 | $lvm->{$vg_name}->{$lv_name}->{'lv_kernel_minor'} = $lv_kernel_minor;
|
---|
332 | $lvm->{$vg_name}->{$lv_name}->{'lv_kernel_read_ahead'} = $lv_kernel_read_ahead;
|
---|
333 | $lvm->{$vg_name}->{$lv_name}->{'lv_size'} = $lv_size;
|
---|
334 | $lvm->{$vg_name}->{$lv_name}->{'origin'} = $origin;
|
---|
335 | $lvm->{$vg_name}->{$lv_name}->{'origin_size'} = $origin_size;
|
---|
336 | $lvm->{$vg_name}->{$lv_name}->{'snap_percent'} = $snap_percent;
|
---|
337 | $lvm->{$vg_name}->{$lv_name}->{'copy_percent'} = $copy_percent;
|
---|
338 | $lvm->{$vg_name}->{$lv_name}->{'move_pv'} = $move_pv;
|
---|
339 | $lvm->{$vg_name}->{$lv_name}->{'convert_lv'} = $convert_lv;
|
---|
340 | $lvm->{$vg_name}->{$lv_name}->{'lv_tags'} = $lv_tags;
|
---|
341 | $lvm->{$vg_name}->{$lv_name}->{'mirror_log'} = $mirror_log;
|
---|
342 | $lvm->{$vg_name}->{$lv_name}->{'modules'} = $modules;
|
---|
343 | }
|
---|
344 | close(LVM);
|
---|
345 | return($lvm);
|
---|
346 | }
|
---|
347 |
|
---|
348 | =item B<mr_lvm_analyze>
|
---|
349 |
|
---|
350 | This function outputs in a file descriptor the LVM analysis done
|
---|
351 | It returns 1 parameters, the LVM version or 0 if no LVM
|
---|
352 |
|
---|
353 | =cut
|
---|
354 |
|
---|
355 | sub mr_lvm_analyze {
|
---|
356 |
|
---|
357 | my $OUTPUT = shift;
|
---|
358 |
|
---|
359 | my ($lvmver,$lvmcmd) = mr_lvm_check();
|
---|
360 | my $lvm = mr_lvm_get_conf();
|
---|
361 | return(undef) if ($lvmver == 0);
|
---|
362 |
|
---|
363 | print $OUTPUT "LVM:$lvmver\n";
|
---|
364 |
|
---|
365 | # Analyze the existing physical volumes
|
---|
366 | #open(LVM,$lvmcmd."pvdisplay -c |") || mr_exit(-1,"Unable to execute ".$lvmcmd."pvdisplay -c");
|
---|
367 | open(LVM,$lvmcmd."pvs --noheadings --nosuffix --units m --separator : |") || mr_exit(-1,"Unable to execute ".$lvmcmd."pvs");
|
---|
368 | while (<LVM>) {
|
---|
369 | s/^[\s]*//;
|
---|
370 | my ($pv,$vg,$foo,$foo2,$size,$foo3) = split(/:/);
|
---|
371 | $lvm->{$vg}->{'pvnum'}++;
|
---|
372 | # that array will start at 1 then
|
---|
373 | $lvm->{$vg}->{'pv'}->[$lvm->{$vg}->{'pvnum'}] = $pv;
|
---|
374 | $lvm->{$vg}->{$pv}->{'size'} = $size;
|
---|
375 | print $OUTPUT "PV:$_";
|
---|
376 | }
|
---|
377 | close(LVM);
|
---|
378 |
|
---|
379 | # Analyze the existing volume groups
|
---|
380 | #open(LVM,$lvmcmd."vgdisplay -c |") || mr_exit(-1,"Unable to execute ".$lvmcmd."vgdisplay -c");
|
---|
381 | open(LVM,$lvmcmd."vgs --noheadings --nosuffix --units m --separator : |") || mr_exit(-1,"Unable to execute ".$lvmcmd."vgs");
|
---|
382 | while (<LVM>) {
|
---|
383 | s/^[\s]*//;
|
---|
384 | print $OUTPUT "VG:$_";
|
---|
385 | }
|
---|
386 | close(LVM);
|
---|
387 |
|
---|
388 | # Analyze the existing logical volumes
|
---|
389 | #open(LVM,$lvmcmd."lvdisplay -c |") || mr_exit(-1,"Unable to execute ".$lvmcmd."lvdisplay -c");
|
---|
390 | open(LVM,$lvmcmd."lvs --noheadings --nosuffix --units m --separator : |") || mr_exit(-1,"Unable to execute ".$lvmcmd."lvs");
|
---|
391 | while (<LVM>) {
|
---|
392 | s/^[\s]*//;
|
---|
393 | print $OUTPUT "LV:$_";
|
---|
394 | }
|
---|
395 | close(LVM);
|
---|
396 | return($lvm);
|
---|
397 | }
|
---|
398 |
|
---|
399 |
|
---|
400 | =over 4
|
---|
401 |
|
---|
402 | =item B<mr_lvm_prepare>
|
---|
403 |
|
---|
404 | This function outputs in a file descriptor the LVM setup needed to restore LVM conf
|
---|
405 | It returns 1 parameters, the LVM version or 0 if no LVM
|
---|
406 |
|
---|
407 | =cut
|
---|
408 |
|
---|
409 | sub mr_lvm_prepare {
|
---|
410 |
|
---|
411 | my $INPUT = shift;
|
---|
412 | my $OUTPUT = shift;
|
---|
413 | my $mrmult = shift;
|
---|
414 | my $lvmcmd;
|
---|
415 | my $lvmver;
|
---|
416 |
|
---|
417 | # Generate the startup scrit needed to restore LVM conf
|
---|
418 | # from what is given on input
|
---|
419 | # Multiply by the multiplier given in input or 1 of none
|
---|
420 |
|
---|
421 | my $firsttime = 0;
|
---|
422 | while (<$INPUT>) {
|
---|
423 | if (/^LVM:/) {
|
---|
424 | my $tag;
|
---|
425 | my $foo;
|
---|
426 | ($tag,$lvmver) = split(/:/);
|
---|
427 | ($foo,$lvmcmd) = mr_lvm_check($lvmver);
|
---|
428 |
|
---|
429 | print $OUTPUT "# Desactivate Volume Groups\n";
|
---|
430 | print $OUTPUT $lvmcmd."vgchange -an\n";
|
---|
431 | print $OUTPUT "\n";
|
---|
432 |
|
---|
433 | } elsif (/^PV:/) {
|
---|
434 | # This is for pvdisplay -c
|
---|
435 | #my ($tag,$pvname,$vgname,$pvsize,$ipvn,$pvstat,$pvna,$lvnum,$pesize,$petot,$pefree,$pelloc) = split(/:/);
|
---|
436 | my ($tag,$pvname,$vgname,$lvmv,$more,$pesize,$pefree) = split(/:/);
|
---|
437 | print $OUTPUT "# Creating Physical Volumes $pvname\n";
|
---|
438 | print $OUTPUT $lvmcmd."pvcreate -ff -y";
|
---|
439 | print $OUTPUT " -s ".$pesize*$mrmult if (defined $pesize);
|
---|
440 | print $OUTPUT " $pvname\n";
|
---|
441 | print $OUTPUT "\n";
|
---|
442 | } elsif (/^VG:/) {
|
---|
443 | # This if for vgdisplay -c
|
---|
444 | #my ($tag,$vgname,$vgaccess,$vgstat,$vgnum,$lvmaxnum,$lvnum,$ocalvinvg,$lvmaxsize,$pvmaxnum,$cnumpv,$anumpv,$vgsize,$pesize,$penum,$pealloc,$pefree,$uuid) = split(/:/);
|
---|
445 | my ($tag,$vgname,$pvnum,$lvnum,$attr,$vgsize,$vgfree) = split(/:/);
|
---|
446 | if ($lvmver < 2) {
|
---|
447 | print $OUTPUT "# Removing device first as LVM v1 doesn't do it\n";
|
---|
448 | print $OUTPUT "rm -Rf /dev/$vgname\n";
|
---|
449 | }
|
---|
450 | #$lvmaxnum = 255 if (($lvmaxnum > 256) or (not defined $lvmaxnum));
|
---|
451 | #$pvmaxnum = 255 if (($pvmaxnum > 256) or (not defined $pvmaxnum));
|
---|
452 | print $OUTPUT "# Create Volume Group $vgname\n";
|
---|
453 | # Pb sur pesize unite ?
|
---|
454 | print $OUTPUT $lvmcmd."vgcreate $vgname ";
|
---|
455 | #print $OUTPUT "-p $pvmaxnum -l $lvmaxnum";
|
---|
456 | #print $OUTPUT " -s ".$pesize."\n" if (defined $pesize);
|
---|
457 | print $OUTPUT "\n";
|
---|
458 |
|
---|
459 | } elsif (/^LV:/) {
|
---|
460 | if ($firsttime == 0) {
|
---|
461 | print $OUTPUT "\n";
|
---|
462 | print $OUTPUT "# Activate All Volume Groups\n";
|
---|
463 | print $OUTPUT $lvmcmd."vgchange -ay\n";
|
---|
464 | print $OUTPUT "\n";
|
---|
465 | $firsttime = 1;
|
---|
466 | }
|
---|
467 | my ($tag,$lvname,$vgname,$lvaccess,$lvstat,$lvnum,$oclv,$lvsize,$leinlv,$lealloc,$allocpol,$readahead,$major,$minor) = split(/:/);
|
---|
468 | print $OUTPUT "# Create Logical Volume $lvname\n";
|
---|
469 | print $OUTPUT $lvmcmd."lvcreate -n $lvname -L ".$lvsize*$mrmult;
|
---|
470 | print $OUTPUT " -r $readahead" if (defined $readahead);
|
---|
471 | print $OUTPUT " $vgname\n";
|
---|
472 | #[ "$stripes" ] && output="$output -i $stripes"
|
---|
473 | #[ "$stripesize" ] && output="$output -I $stripesize"
|
---|
474 | }
|
---|
475 | }
|
---|
476 |
|
---|
477 | print $OUTPUT "\n";
|
---|
478 | print $OUTPUT "# Scanning again Volume Groups\n";
|
---|
479 | print $OUTPUT $lvmcmd."vgscan\n";
|
---|
480 | print $OUTPUT "\n";
|
---|
481 |
|
---|
482 | }
|
---|
483 |
|
---|
484 | =back
|
---|
485 |
|
---|
486 | =head1 WEB SITES
|
---|
487 |
|
---|
488 | The main Web site of the project is available at L<http://www.mondorescue.org/>. Bug reports should be filled using the trac instance of the project at L<http://trac.mondorescue.org/>.
|
---|
489 |
|
---|
490 | =head1 USER MAILING LIST
|
---|
491 |
|
---|
492 | The mailing list of the project is available at L<mailto:mondo@lists.sf.net>
|
---|
493 |
|
---|
494 | =head1 AUTHORS
|
---|
495 |
|
---|
496 | The Mondorescue.org team L<http://www.mondorescue.org/> lead by Bruno Cornec L<mailto:bruno@mondorescue.org>.
|
---|
497 |
|
---|
498 | =head1 COPYRIGHT
|
---|
499 |
|
---|
500 | This module is distributed under the GPL v2.0 license
|
---|
501 | described in the file C<COPYING> included with the distribution.
|
---|
502 |
|
---|
503 |
|
---|
504 | =cut
|
---|
505 |
|
---|
506 | 1;
|
---|
507 |
|
---|