[3219] | 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);
|
---|
[3475] | 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 mr_lvm_analyze mr_lvm_prepare);
|
---|
[3219] | 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
|
---|
[3432] | 162 |
|
---|
[3219] | 163 | vg_name - Name of the volume group linked to this PV
|
---|
| 164 |
|
---|
| 165 | =cut
|
---|
| 166 |
|
---|
| 167 | $lvm->{$vg_name}->{'pvnum'}++;
|
---|
| 168 |
|
---|
| 169 | =pod
|
---|
| 170 |
|
---|
| 171 | 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
|
---|
[3432] | 172 |
|
---|
[3219] | 173 | pv_name - Name of the physical volume PV
|
---|
| 174 |
|
---|
| 175 | =cut
|
---|
| 176 |
|
---|
| 177 | # Array of PVs for that VG
|
---|
| 178 | $lvm->{$vg_name}->{'pvs'}->[$lvm->{$vg_name}->{'pvnum'}] = $pv_name;
|
---|
| 179 |
|
---|
| 180 | =pod
|
---|
| 181 |
|
---|
| 182 | All the PV fields from the pvs command are gathered under their PV name (substructure)
|
---|
| 183 | The following names are used:
|
---|
| 184 |
|
---|
| 185 | From pvs -o help
|
---|
| 186 | pe_start - Offset to the start of data on the underlying device.
|
---|
| 187 | pv_size - Size of PV in current units.
|
---|
| 188 | pv_free - Total amount of unallocated space in current units.
|
---|
| 189 | pv_used - Total amount of allocated space in current units.
|
---|
| 190 | pv_attr - Various attributes - see man page.
|
---|
| 191 | pv_pe_count - Total number of Physical Extents.
|
---|
| 192 | pv_pe_alloc_count - Total number of allocated Physical Extents.
|
---|
| 193 | pv_tags - Tags, if any.
|
---|
| 194 | pv_mda_count - Number of metadata areas on this device.
|
---|
| 195 | pv_fmt - Type of metadata.
|
---|
| 196 | pv_uuid - Unique identifier.
|
---|
| 197 | dev_size - Size of underlying device in current units.
|
---|
| 198 | pv_mda_free - Free metadata area space on this device in current units.
|
---|
| 199 | pv_mda_size - Size of smallest metadata area on this device in current units.
|
---|
| 200 |
|
---|
| 201 | =cut
|
---|
| 202 |
|
---|
| 203 | $lvm->{$vg_name}->{$pv_name}->{'pe_start'} = $pe_start;
|
---|
| 204 | $lvm->{$vg_name}->{$pv_name}->{'pv_size'} = $pv_size;
|
---|
| 205 | $lvm->{$vg_name}->{$pv_name}->{'pv_free'} = $pv_free;
|
---|
| 206 | $lvm->{$vg_name}->{$pv_name}->{'pv_used'} = $pv_used;
|
---|
| 207 | $lvm->{$vg_name}->{$pv_name}->{'pv_attr'} = $pv_attr;
|
---|
| 208 | $lvm->{$vg_name}->{$pv_name}->{'pv_pe_count'} = $pv_pe_count;
|
---|
| 209 | $lvm->{$vg_name}->{$pv_name}->{'pv_pe_alloc_count'} = $pv_pe_alloc_count;
|
---|
| 210 | $lvm->{$vg_name}->{$pv_name}->{'pv_tags'} = $pv_tags;
|
---|
| 211 | $lvm->{$vg_name}->{$pv_name}->{'pv_mda_count'} = $pv_mda_count;
|
---|
| 212 | $lvm->{$vg_name}->{$pv_name}->{'pv_uuid'} = $pv_uuid;
|
---|
| 213 | $lvm->{$vg_name}->{$pv_name}->{'dev_size'} = $dev_size;
|
---|
| 214 | $lvm->{$vg_name}->{$pv_name}->{'pv_mda_free'} = $pv_mda_free;
|
---|
| 215 | $lvm->{$vg_name}->{$pv_name}->{'pv_mda_size'} = $pv_mda_size;
|
---|
| 216 | }
|
---|
| 217 | close(LVM);
|
---|
| 218 |
|
---|
| 219 | # Analyze the existing volume groups
|
---|
| 220 | #open(LVM,$lvmcmd."vgdisplay -c |") || mr_exit(-1,"Unable to execute ".$lvmcmd."vgdisplay -c");
|
---|
| 221 | open(LVM,$lvmcmd."vgs --noheadings --nosuffix --units m --separator : -o vg_all |") || mr_exit(-1,"Unable to execute ".$lvmcmd."vgs");
|
---|
| 222 | while (<LVM>) {
|
---|
| 223 |
|
---|
| 224 | =pod
|
---|
| 225 |
|
---|
| 226 | All the VG fields from the vgs command are gathered under the VG name
|
---|
| 227 | The following names are used:
|
---|
| 228 |
|
---|
| 229 | From vgs -o help
|
---|
| 230 | vg_fmt - Type of metadata.
|
---|
| 231 | vg_uuid - Unique identifier.
|
---|
| 232 | vg_attr - Various attributes - see man page.
|
---|
| 233 | vg_size - Total size of VG in current units.
|
---|
| 234 | vg_free - Total amount of free space in current units.
|
---|
| 235 | vg_sysid - System ID indicating when and where it was created.
|
---|
| 236 | vg_extent_size - Size of Physical Extents in current units.
|
---|
| 237 | vg_extent_count - Total number of Physical Extents.
|
---|
| 238 | vg_free_count - Total number of unallocated Physical Extents.
|
---|
| 239 | max_lv - Maximum number of LVs allowed in VG or 0 if unlimited.
|
---|
| 240 | max_pv - Maximum number of PVs allowed in VG or 0 if unlimited.
|
---|
| 241 | pv_count - Number of PVs.
|
---|
| 242 | lv_count - Number of LVs.
|
---|
| 243 | snap_count - Number of snapshots.
|
---|
| 244 | vg_seqno - Revision number of internal metadata. Incremented whenever it changes.
|
---|
| 245 | vg_tags - Tags, if any.
|
---|
| 246 | vg_mda_count - Number of metadata areas in use by this VG.
|
---|
| 247 | vg_mda_free - Free metadata area space for this VG in current units.
|
---|
| 248 | vg_mda_size - Size of smallest metadata area for this VG in current units.
|
---|
| 249 |
|
---|
| 250 | =cut
|
---|
| 251 | s/^[\s]*//;
|
---|
| 252 | 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(/:/);
|
---|
| 253 | $lvm->{$vg_name}->{'vg_fmt'} = $vg_fmt;
|
---|
| 254 | $lvm->{$vg_name}->{'vg_uuid'} = $vg_uuid;
|
---|
| 255 | $lvm->{$vg_name}->{'vg_attr'} = $vg_attr;
|
---|
| 256 | $lvm->{$vg_name}->{'vg_size'} = $vg_size;
|
---|
| 257 | $lvm->{$vg_name}->{'vg_free'} = $vg_free;
|
---|
| 258 | $lvm->{$vg_name}->{'vg_sysid'} = $vg_sysid;
|
---|
| 259 | $lvm->{$vg_name}->{'vg_extend_size'} = $vg_extend_size;
|
---|
| 260 | $lvm->{$vg_name}->{'vg_extend_count'} = $vg_extend_count;
|
---|
| 261 | $lvm->{$vg_name}->{'vg_free_count'} = $vg_free_count;
|
---|
| 262 | $lvm->{$vg_name}->{'max_lv'} = $max_lv;
|
---|
| 263 | $lvm->{$vg_name}->{'max_pv'} = $max_pv;
|
---|
| 264 | $lvm->{$vg_name}->{'pv_count'} = $pv_count;
|
---|
| 265 | $lvm->{$vg_name}->{'lv_count'} = $lv_count;
|
---|
| 266 | $lvm->{$vg_name}->{'snap_count'} = $snap_count;
|
---|
| 267 | $lvm->{$vg_name}->{'vg_seqno'} = $vg_seqno;
|
---|
| 268 | $lvm->{$vg_name}->{'vg_tags'} = $vg_tags;
|
---|
| 269 | $lvm->{$vg_name}->{'vg_mda_count'} = $vg_mda_count;
|
---|
| 270 | $lvm->{$vg_name}->{'vg_mda_free'} = $vg_mda_free;
|
---|
| 271 | $lvm->{$vg_name}->{'vg_mda_size'} = $vg_mda_size;
|
---|
| 272 | }
|
---|
| 273 | close(LVM);
|
---|
| 274 |
|
---|
| 275 | # Analyze the existing logical volumes
|
---|
| 276 | #open(LVM,$lvmcmd."lvdisplay -c |") || mr_exit(-1,"Unable to execute ".$lvmcmd."lvdisplay -c");
|
---|
| 277 | open(LVM,$lvmcmd."lvs --noheadings --nosuffix --units m --separator : -o vg_name,lv_all|") || mr_exit(-1,"Unable to execute ".$lvmcmd."lvs");
|
---|
| 278 | while (<LVM>) {
|
---|
| 279 | s/^[\s]*//;
|
---|
| 280 |
|
---|
| 281 | =pod
|
---|
| 282 |
|
---|
| 283 | 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
|
---|
| 284 |
|
---|
| 285 | =cut
|
---|
| 286 |
|
---|
| 287 | 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(/:/);
|
---|
| 288 |
|
---|
| 289 | =pod
|
---|
| 290 |
|
---|
| 291 | All the PV fields from the pvs command are gathered under their PV name (substructure)
|
---|
| 292 | The following names are used:
|
---|
| 293 |
|
---|
| 294 |
|
---|
| 295 | # From lvs -o help
|
---|
| 296 |
|
---|
| 297 | #vg_name - Name of the related volume group
|
---|
| 298 | #lv_uuid - Unique identifier.
|
---|
| 299 | #lv_name - Name. LVs created for internal use are enclosed in brackets.
|
---|
| 300 | #lv_attr - Various attributes - see man page.
|
---|
| 301 | #lv_major - Persistent major number or -1 if not persistent.
|
---|
| 302 | #lv_minor - Persistent minor number or -1 if not persistent.
|
---|
| 303 | #lv_read_ahead - Read ahead setting in current units.
|
---|
| 304 | #lv_kernel_major - Currently assigned major number or -1 if LV is not active.
|
---|
| 305 | #lv_kernel_minor - Currently assigned minor number or -1 if LV is not active.
|
---|
| 306 | #lv_kernel_read_ahead - Currently-in-use read ahead setting in current units.
|
---|
| 307 | #lv_size - Size of LV in current units.
|
---|
| 308 | #seg_count - Number of segments in LV.
|
---|
| 309 | #origin - For snapshots, the origin device of this LV.
|
---|
| 310 | #origin_size - For snapshots, the size of the origin device of this LV.
|
---|
| 311 | #snap_percent - For snapshots, the percentage full if LV is active.
|
---|
| 312 | #copy_percent - For mirrors and pvmove, current percentage in-sync.
|
---|
| 313 | #move_pv - For pvmove, Source PV of temporary LV created by pvmove.
|
---|
| 314 | #convert_lv - For lvconvert, Name of temporary LV created by lvconvert.
|
---|
| 315 | #lv_tags - Tags, if any.
|
---|
| 316 | #mirror_log - For mirrors, the LV holding the synchronisation log.
|
---|
| 317 | #modules - Kernel device-mapper modules required for this LV.
|
---|
| 318 |
|
---|
| 319 | =cut
|
---|
| 320 |
|
---|
| 321 | # The LVM hash is indexed by VGs
|
---|
| 322 | $lvm->{$vg_name}->{'lvnum'}++;
|
---|
| 323 | # That array will start at 1 then
|
---|
| 324 | # Array of LVs for that VG
|
---|
| 325 | $lvm->{$vg_name}->{'lvs'}->[$lvm->{$vg_name}->{'lvnum'}] = $lv_name;
|
---|
| 326 | # All LV fields gathered under the LV name
|
---|
| 327 | $lvm->{$vg_name}->{$lv_name}->{'lv_uuid'} = $lv_uuid;
|
---|
| 328 | $lvm->{$vg_name}->{$lv_name}->{'lv_attr'} = $lv_attr;
|
---|
| 329 | $lvm->{$vg_name}->{$lv_name}->{'lv_major'} = $lv_major;
|
---|
| 330 | $lvm->{$vg_name}->{$lv_name}->{'lv_minor'} = $lv_minor;
|
---|
| 331 | $lvm->{$vg_name}->{$lv_name}->{'lv_read_ahead'} = $lv_read_ahead;
|
---|
| 332 | $lvm->{$vg_name}->{$lv_name}->{'lv_kernel_major'} = $lv_kernel_major;
|
---|
| 333 | $lvm->{$vg_name}->{$lv_name}->{'lv_kernel_minor'} = $lv_kernel_minor;
|
---|
| 334 | $lvm->{$vg_name}->{$lv_name}->{'lv_kernel_read_ahead'} = $lv_kernel_read_ahead;
|
---|
| 335 | $lvm->{$vg_name}->{$lv_name}->{'lv_size'} = $lv_size;
|
---|
| 336 | $lvm->{$vg_name}->{$lv_name}->{'origin'} = $origin;
|
---|
| 337 | $lvm->{$vg_name}->{$lv_name}->{'origin_size'} = $origin_size;
|
---|
| 338 | $lvm->{$vg_name}->{$lv_name}->{'snap_percent'} = $snap_percent;
|
---|
| 339 | $lvm->{$vg_name}->{$lv_name}->{'copy_percent'} = $copy_percent;
|
---|
| 340 | $lvm->{$vg_name}->{$lv_name}->{'move_pv'} = $move_pv;
|
---|
| 341 | $lvm->{$vg_name}->{$lv_name}->{'convert_lv'} = $convert_lv;
|
---|
| 342 | $lvm->{$vg_name}->{$lv_name}->{'lv_tags'} = $lv_tags;
|
---|
| 343 | $lvm->{$vg_name}->{$lv_name}->{'mirror_log'} = $mirror_log;
|
---|
| 344 | $lvm->{$vg_name}->{$lv_name}->{'modules'} = $modules;
|
---|
| 345 | }
|
---|
| 346 | close(LVM);
|
---|
| 347 | return($lvm);
|
---|
| 348 | }
|
---|
| 349 |
|
---|
| 350 | =item B<mr_lvm_analyze>
|
---|
| 351 |
|
---|
| 352 | This function outputs in a file descriptor the LVM analysis done
|
---|
| 353 | It returns 1 parameters, the LVM version or 0 if no LVM
|
---|
| 354 |
|
---|
| 355 | =cut
|
---|
| 356 |
|
---|
| 357 | sub mr_lvm_analyze {
|
---|
| 358 |
|
---|
| 359 | my $OUTPUT = shift;
|
---|
| 360 |
|
---|
| 361 | my ($lvmver,$lvmcmd) = mr_lvm_check();
|
---|
| 362 | my $lvm = mr_lvm_get_conf();
|
---|
| 363 | return(undef) if ($lvmver == 0);
|
---|
| 364 |
|
---|
| 365 | print $OUTPUT "LVM:$lvmver\n";
|
---|
| 366 |
|
---|
| 367 | # Analyze the existing physical volumes
|
---|
| 368 | #open(LVM,$lvmcmd."pvdisplay -c |") || mr_exit(-1,"Unable to execute ".$lvmcmd."pvdisplay -c");
|
---|
| 369 | open(LVM,$lvmcmd."pvs --noheadings --nosuffix --units m --separator : |") || mr_exit(-1,"Unable to execute ".$lvmcmd."pvs");
|
---|
| 370 | while (<LVM>) {
|
---|
| 371 | s/^[\s]*//;
|
---|
| 372 | my ($pv,$vg,$foo,$foo2,$size,$foo3) = split(/:/);
|
---|
| 373 | $lvm->{$vg}->{'pvnum'}++;
|
---|
| 374 | # that array will start at 1 then
|
---|
| 375 | $lvm->{$vg}->{'pv'}->[$lvm->{$vg}->{'pvnum'}] = $pv;
|
---|
| 376 | $lvm->{$vg}->{$pv}->{'size'} = $size;
|
---|
| 377 | print $OUTPUT "PV:$_";
|
---|
| 378 | }
|
---|
| 379 | close(LVM);
|
---|
| 380 |
|
---|
| 381 | # Analyze the existing volume groups
|
---|
| 382 | #open(LVM,$lvmcmd."vgdisplay -c |") || mr_exit(-1,"Unable to execute ".$lvmcmd."vgdisplay -c");
|
---|
| 383 | open(LVM,$lvmcmd."vgs --noheadings --nosuffix --units m --separator : |") || mr_exit(-1,"Unable to execute ".$lvmcmd."vgs");
|
---|
| 384 | while (<LVM>) {
|
---|
| 385 | s/^[\s]*//;
|
---|
| 386 | print $OUTPUT "VG:$_";
|
---|
| 387 | }
|
---|
| 388 | close(LVM);
|
---|
| 389 |
|
---|
| 390 | # Analyze the existing logical volumes
|
---|
| 391 | #open(LVM,$lvmcmd."lvdisplay -c |") || mr_exit(-1,"Unable to execute ".$lvmcmd."lvdisplay -c");
|
---|
| 392 | open(LVM,$lvmcmd."lvs --noheadings --nosuffix --units m --separator : |") || mr_exit(-1,"Unable to execute ".$lvmcmd."lvs");
|
---|
| 393 | while (<LVM>) {
|
---|
| 394 | s/^[\s]*//;
|
---|
| 395 | print $OUTPUT "LV:$_";
|
---|
| 396 | }
|
---|
| 397 | close(LVM);
|
---|
| 398 | return($lvm);
|
---|
| 399 | }
|
---|
| 400 |
|
---|
| 401 |
|
---|
| 402 | =over 4
|
---|
| 403 |
|
---|
| 404 | =item B<mr_lvm_prepare>
|
---|
| 405 |
|
---|
| 406 | This function outputs in a file descriptor the LVM setup needed to restore LVM conf
|
---|
| 407 | It returns 1 parameters, the LVM version or 0 if no LVM
|
---|
| 408 |
|
---|
| 409 | =cut
|
---|
| 410 |
|
---|
| 411 | sub mr_lvm_prepare {
|
---|
| 412 |
|
---|
| 413 | my $INPUT = shift;
|
---|
| 414 | my $OUTPUT = shift;
|
---|
| 415 | my $mrmult = shift;
|
---|
| 416 | my $lvmcmd;
|
---|
| 417 | my $lvmver;
|
---|
| 418 |
|
---|
| 419 | # Generate the startup scrit needed to restore LVM conf
|
---|
| 420 | # from what is given on input
|
---|
| 421 | # Multiply by the multiplier given in input or 1 of none
|
---|
| 422 |
|
---|
| 423 | my $firsttime = 0;
|
---|
| 424 | while (<$INPUT>) {
|
---|
| 425 | if (/^LVM:/) {
|
---|
| 426 | my $tag;
|
---|
| 427 | my $foo;
|
---|
| 428 | ($tag,$lvmver) = split(/:/);
|
---|
| 429 | ($foo,$lvmcmd) = mr_lvm_check($lvmver);
|
---|
| 430 |
|
---|
| 431 | print $OUTPUT "# Desactivate Volume Groups\n";
|
---|
| 432 | print $OUTPUT $lvmcmd."vgchange -an\n";
|
---|
| 433 | print $OUTPUT "\n";
|
---|
| 434 |
|
---|
| 435 | } elsif (/^PV:/) {
|
---|
| 436 | # This is for pvdisplay -c
|
---|
| 437 | #my ($tag,$pvname,$vgname,$pvsize,$ipvn,$pvstat,$pvna,$lvnum,$pesize,$petot,$pefree,$pelloc) = split(/:/);
|
---|
| 438 | my ($tag,$pvname,$vgname,$lvmv,$more,$pesize,$pefree) = split(/:/);
|
---|
| 439 | print $OUTPUT "# Creating Physical Volumes $pvname\n";
|
---|
| 440 | print $OUTPUT $lvmcmd."pvcreate -ff -y";
|
---|
| 441 | print $OUTPUT " -s ".$pesize*$mrmult if (defined $pesize);
|
---|
| 442 | print $OUTPUT " $pvname\n";
|
---|
| 443 | print $OUTPUT "\n";
|
---|
| 444 | } elsif (/^VG:/) {
|
---|
| 445 | # This if for vgdisplay -c
|
---|
| 446 | #my ($tag,$vgname,$vgaccess,$vgstat,$vgnum,$lvmaxnum,$lvnum,$ocalvinvg,$lvmaxsize,$pvmaxnum,$cnumpv,$anumpv,$vgsize,$pesize,$penum,$pealloc,$pefree,$uuid) = split(/:/);
|
---|
| 447 | my ($tag,$vgname,$pvnum,$lvnum,$attr,$vgsize,$vgfree) = split(/:/);
|
---|
| 448 | if ($lvmver < 2) {
|
---|
| 449 | print $OUTPUT "# Removing device first as LVM v1 doesn't do it\n";
|
---|
| 450 | print $OUTPUT "rm -Rf /dev/$vgname\n";
|
---|
| 451 | }
|
---|
| 452 | #$lvmaxnum = 255 if (($lvmaxnum > 256) or (not defined $lvmaxnum));
|
---|
| 453 | #$pvmaxnum = 255 if (($pvmaxnum > 256) or (not defined $pvmaxnum));
|
---|
| 454 | print $OUTPUT "# Create Volume Group $vgname\n";
|
---|
| 455 | # Pb sur pesize unite ?
|
---|
| 456 | print $OUTPUT $lvmcmd."vgcreate $vgname ";
|
---|
| 457 | #print $OUTPUT "-p $pvmaxnum -l $lvmaxnum";
|
---|
| 458 | #print $OUTPUT " -s ".$pesize."\n" if (defined $pesize);
|
---|
| 459 | print $OUTPUT "\n";
|
---|
| 460 |
|
---|
| 461 | } elsif (/^LV:/) {
|
---|
| 462 | if ($firsttime == 0) {
|
---|
| 463 | print $OUTPUT "\n";
|
---|
| 464 | print $OUTPUT "# Activate All Volume Groups\n";
|
---|
| 465 | print $OUTPUT $lvmcmd."vgchange -ay\n";
|
---|
| 466 | print $OUTPUT "\n";
|
---|
| 467 | $firsttime = 1;
|
---|
| 468 | }
|
---|
| 469 | my ($tag,$lvname,$vgname,$lvaccess,$lvstat,$lvnum,$oclv,$lvsize,$leinlv,$lealloc,$allocpol,$readahead,$major,$minor) = split(/:/);
|
---|
| 470 | print $OUTPUT "# Create Logical Volume $lvname\n";
|
---|
[3475] | 471 | # TODO: We should use % here as well
|
---|
[3312] | 472 | print $OUTPUT $lvmcmd."echo y | lvcreate -n $lvname -L ".$lvsize*$mrmult;
|
---|
[3219] | 473 | print $OUTPUT " -r $readahead" if (defined $readahead);
|
---|
| 474 | print $OUTPUT " $vgname\n";
|
---|
| 475 | #[ "$stripes" ] && output="$output -i $stripes"
|
---|
| 476 | #[ "$stripesize" ] && output="$output -I $stripesize"
|
---|
| 477 | }
|
---|
| 478 | }
|
---|
| 479 |
|
---|
| 480 | print $OUTPUT "\n";
|
---|
| 481 | print $OUTPUT "# Scanning again Volume Groups\n";
|
---|
| 482 | print $OUTPUT $lvmcmd."vgscan\n";
|
---|
| 483 | print $OUTPUT "\n";
|
---|
| 484 |
|
---|
| 485 | }
|
---|
| 486 |
|
---|
| 487 | =back
|
---|
| 488 |
|
---|
| 489 | =head1 WEB SITES
|
---|
| 490 |
|
---|
| 491 | 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/>.
|
---|
| 492 |
|
---|
| 493 | =head1 USER MAILING LIST
|
---|
| 494 |
|
---|
| 495 | The mailing list of the project is available at L<mailto:mondo@lists.sf.net>
|
---|
| 496 |
|
---|
| 497 | =head1 AUTHORS
|
---|
| 498 |
|
---|
| 499 | The Mondorescue.org team L<http://www.mondorescue.org/> lead by Bruno Cornec L<mailto:bruno@mondorescue.org>.
|
---|
| 500 |
|
---|
| 501 | =head1 COPYRIGHT
|
---|
| 502 |
|
---|
| 503 | This module is distributed under the GPL v2.0 license
|
---|
| 504 | described in the file C<COPYING> included with the distribution.
|
---|
| 505 |
|
---|
| 506 |
|
---|
| 507 | =cut
|
---|
| 508 |
|
---|
| 509 | 1;
|
---|
| 510 |
|
---|