[Fai-commit] r4955 - people/michael/features/setup_harddisks_2/implementation/lib trunk/lib/setup-storage
lange at alioth.debian.org
lange at alioth.debian.org
Thu Jun 12 11:37:54 UTC 2008
Author: lange
Date: 2008-06-12 11:37:53 +0000 (Thu, 12 Jun 2008)
New Revision: 4955
Added:
trunk/lib/setup-storage/Volumes.pm
Removed:
people/michael/features/setup_harddisks_2/implementation/lib/volumes.pm
Log:
moving setup-storage to trunk
Deleted: people/michael/features/setup_harddisks_2/implementation/lib/volumes.pm
===================================================================
--- people/michael/features/setup_harddisks_2/implementation/lib/volumes.pm 2008-06-12 11:37:51 UTC (rev 4954)
+++ people/michael/features/setup_harddisks_2/implementation/lib/volumes.pm 2008-06-12 11:37:53 UTC (rev 4955)
@@ -1,437 +0,0 @@
-#!/usr/bin/perl -w
-
-#*********************************************************************
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# A copy of the GNU General Public License is available as
-# `/usr/share/common-licences/GPL' in the Debian GNU/Linux distribution
-# or on the World Wide Web at http://www.gnu.org/copyleft/gpl.html. You
-# can also obtain it by writing to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
-#*********************************************************************
-
-use strict;
-
-################################################################################
-#
-# @file volumes.pm
-#
-# @brief Parse the current partition table and LVM/RAID configurations
-#
-# $Id$
-#
-# @author Christian Kern, Michael Tautschnig
-# @date Sun Jul 23 16:09:36 CEST 2006
-#
-################################################################################
-
-package FAI;
-
-################################################################################
-#
-# @brief Collect the current partition information from all disks listed both
-# in $FAI::disks and $FAI::configs{PHY_<disk>}
-#
-################################################################################
-sub get_current_disks {
-
- # obtain the current state of all disks
- foreach my $disk (@FAI::disks) {
-
- # create full paths
- ($disk =~ m{^/}) or $disk = "/dev/$disk";
-
- # make sure, $disk is a proper block device
- (-b $disk) or die "$disk is not a block special device!\n";
- &FAI::push_command( "true", "", "exist_$disk" );
-
- # initialise the hash
- $FAI::current_config{$disk}{partitions} = {};
-
- # the list to hold the output of parted commands as parsed below
- my @parted_print = ();
-
- # try to obtain the partition table for $disk
- # it might fail with parted_2 in case the disk has no partition table
- my $error =
- &FAI::execute_ro_command("parted -s $disk unit TiB print", \@parted_print, 0);
-
- # parted_2 happens when the disk has no disk label, because parted then
- # provides no information about the disk
- if ($error eq "parted_2") {
- $FAI::no_dry_run or die
- "Can't run on test-only mode on this system because there is no disklabel on $disk\n";
-
- # if there is no disk configuration, write an msdos disklabel
- if (!defined ($FAI::configs{"PHY_$disk"}{disklabel})) {
-
- # write the disk label as configured
- $error = &FAI::execute_command("parted -s $disk mklabel msdos");
- } else {
-
- # write the disk label as configured
- $error = &FAI::execute_command("parted -s $disk mklabel "
- . $FAI::configs{"PHY_$disk"}{disklabel});
- }
- # retry partition-table print
- $error =
- &FAI::execute_ro_command("parted -s $disk unit TiB print", \@parted_print, 0);
- }
-
- ($error eq "") or die "Failed to read the partition table from $disk\n";
-
-# the following code parses the output of parted print, using various units
-# (TiB, B, chs)
-# the parser is capable of reading the output of parted version 1.7.1, which
-# looks like
-#
-# $ /sbin/parted -s /dev/hda unit B print
-# WARNING: You are not superuser. Watch out for permissions.
-#
-# Disk /dev/hda: 80026361855B
-# Sector size (logical/physical): 512B/512B
-# Partition Table: mac
-#
-# Number Start End Size File system Name Flags
-# 1 512B 32767B 32256B primary
-# 5 32768B 1033215B 1000448B hfs primary boot
-# 3 134250496B 32212287487B 32078036992B hfs+ primary
-# 6 32212287488B 46212287487B 14000000000B ext3 primary
-# 2 46212287488B 47212287999B 1000000512B linux-swap primary swap
-# 4 47212288000B 80026361855B 32814073856B ext3 primary
-#
-# Note that the output contains an additional column on msdos, indicating,
-# whether the type of a partition is primary, logical or extended.
-#
-# $ parted -s /dev/hda unit B print
-#
-# Disk /dev/hda: 82348277759B
-# Sector size (logical/physical): 512B/512B
-# Partition Table: msdos
-#
-# Number Start End Size Type File system Flags
-# 1 32256B 24675839B 24643584B primary ext3
-# 2 24675840B 1077511679B 1052835840B primary linux-swap
-# 3 1077511680B 13662190079B 12584678400B primary ext3 boot
-# 4 13662190080B 82343278079B 68681088000B extended
-# 5 13662222336B 14715025919B 1052803584B logical ext3
-# 14715058176B 30449986559B 15734928384B
-# 7 30450018816B 32547432959B 2097414144B logical ext3
-# 8 32547465216B 82343278079B 49795812864B logical ext3
-#
-
- # As shown above, some entries may be blank. Thus the exact column starts
- # and lengths must be parsed from the header line. This is stored in the
- # following hash
- my %cols = ();
-
- # Parse the output line by line
- foreach my $line (@parted_print) {
-
- # now we test line by line - some of them may be ignored
- next if ($line =~ /^Disk / || $line =~ /^\s*$/
- || $line =~ /^WARNING: You are not superuser/);
-
- # determine the logical sector size
- if ($line =~ /^Sector size \(logical\/physical\): (\d+)B\/\d+B$/) {
- $FAI::current_config{$disk}{sector_size} = $1;
- }
-
- # read and store the current disk label
- elsif ($line =~ /^Partition Table: (.+)$/) {
- $FAI::current_config{$disk}{disklabel} = $1;
- }
-
- # the line containing the table headers
- elsif ($line =~ /^(Number\s+)(\S+\s+)+/) {
- my $col_start = 0;
-
- # check the length of each heading; note that they might contain spaces
- while ($line =~ /^(\S+( [a-z]\S+)?\s*)([A-Z].*)?$/) {
- my $heading = $1;
-
- # set the line to the remainder
- $line = "";
- $line = $3 if defined ($3);
-
- # the width of the column includes any whitespace
- my $col_width = length ($heading);
- $heading =~ s/(\S+)\s*$/$1/;
-
- # build the hash entry
- # this start counter starts at 0, which is useful below
- $cols{$heading} = {
- "start" => $col_start,
- "length" => $col_width
- };
- $col_start += $col_width;
- }
- } else { # one of the partitions
-
- # we must have seen the header, otherwise probably the format has
- # changed
- defined ($cols{"File system"}{"start"})
- or &FAI::internal_error("Table header not seen yet");
-
- # the info for the partition number
- my $num_cols_before = $cols{"Number"}{"start"};
- my $num_col_width = $cols{"Number"}{"length"};
-
- # the info for the file system column
- my $fs_cols_before = $cols{"File system"}{"start"};
- my $fs_col_width = $cols{"File system"}{"length"};
-
- # get the partition number, if any
- $line =~ /^.{$num_cols_before}(.{$num_col_width})/;
- my $id = $1;
- $id =~ s/\s*//g;
-
- # if there is no partition number, then it must be free space, so no
- # file system either
- next if ($id eq "");
-
- # extract the set of characters
- $line =~ /^.{$fs_cols_before}(.{$fs_col_width})/;
- my $fs = $1;
-
- # remove any trailing space
- $fs =~ s/\s*$//g;
-
- # store the information in the hash
- $FAI::current_config{$disk}{partitions}{$id}{filesystem} = $fs;
- }
- }
-
- # reset the output list
- @parted_print = ();
-
- # obtain the partition table using bytes as units
- $error =
- &FAI::execute_ro_command("parted -s $disk unit B print free", \@parted_print, 0);
-
- # Parse the output of the byte-wise partition table
- foreach my $line (@parted_print) {
-
- # the disk size line (Disk /dev/hda: 82348277759B)
- if ($line =~ /Disk \Q$disk\E: (\d+)B$/) {
- $FAI::current_config{$disk}{begin_byte} = 0;
- $FAI::current_config{$disk}{end_byte} = $1 - 1;
- $FAI::current_config{$disk}{size} = $1;
-
- # nothing else to be done
- next;
- }
-
- # One of the partition lines, see above example
- next unless ($line =~
- /^\s*(\d+)\s+(\d+)B\s+(\d+)B\s+(\d+)B(\s+(primary|logical|extended))?/i);
-
- # mark the bounds of existing partitions
- $FAI::current_config{$disk}{partitions}{$1}{begin_byte} = $2;
- $FAI::current_config{$disk}{partitions}{$1}{end_byte} = $3;
- $FAI::current_config{$disk}{partitions}{$1}{count_byte} = $4;
-
- # is_extended defaults to false/0
- $FAI::current_config{$disk}{partitions}{$1}{is_extended} = 0;
-
- # but may be true/1 on msdos disk labels
- ( ( $FAI::current_config{$disk}{disklabel} eq "msdos" )
- && ( $6 eq "extended" ) )
- and $FAI::current_config{$disk}{partitions}{$1}{is_extended} = 1;
- }
-
- # reset the output list
- @parted_print = ();
-
- # obtain the partition table using bytes as units
- $error =
- &FAI::execute_ro_command(
- "parted -s $disk unit chs print free", \@parted_print, 0);
-
- # Parse the output of the CHS partition table
- foreach my $line (@parted_print) {
-
- # find the BIOS geometry that looks like this:
- # BIOS cylinder,head,sector geometry: 10011,255,63. Each cylinder is 8225kB.
- if ($line =~
- /^BIOS cylinder,head,sector geometry:\s*(\d+),(\d+),(\d+)\.\s*Each cylinder is \d+kB\.$/) {
- $FAI::current_config{$disk}{bios_cylinders} = $1;
- $FAI::current_config{$disk}{bios_heads} = $2;
- $FAI::current_config{$disk}{bios_sectors_per_track} = $3;
- }
- }
-
- # make sure we have determined all the necessary information
- ($FAI::current_config{$disk}{begin_byte} == 0)
- or die "Invalid start byte\n";
- ($FAI::current_config{$disk}{end_byte} > 0) or die "Invalid end byte\n";
- defined ($FAI::current_config{$disk}{size})
- or die "Failed to determine disk size\n";
- defined ($FAI::current_config{$disk}{sector_size})
- or die "Failed to determine sector size\n";
- defined ($FAI::current_config{$disk}{bios_sectors_per_track})
- or die "Failed to determine the number of sectors per track\n";
-
- }
-}
-
-################################################################################
-#
-# @brief Collect the current LVM configuration
-#
-################################################################################
-sub get_current_lvm {
-
- use Linux::LVM;
-
- # get the existing volume groups
- foreach my $vg (get_volume_group_list()) {
- # initialise the hash entry
- $FAI::current_lvm_config{$vg}{physical_volumes} = ();
- &FAI::push_command( "true", "", "vg_created_$vg" );
-
- # store the vg size in MB
- my %vg_info = get_volume_group_information($vg);
- $FAI::current_lvm_config{$vg}{size} =
- &FAI::convert_unit( $vg_info{alloc_pe_size} .
- $vg_info{alloc_pe_size_unit} );
-
- # store the logical volumes and their sizes
- my %lv_info = get_logical_volume_information($vg);
- foreach my $lv_name (sort keys %lv_info) {
- my $short_name = $lv_name;
- $short_name =~ "s{/dev/\Q$vg\E/}{}";
- $FAI::current_lvm_config{$vg}{volumes}{$short_name}{size} =
- &FAI::convert_unit($lv_info{$lv_name}->{lv_size} .
- $lv_info{$lv_name}->{lv_size_unit});
- &FAI::push_command( "true", "", "exist_/dev/$vg/$short_name" );
- }
-
- # store the physical volumes
- my %pv_info = get_physical_volume_information($vg);
- @{ $FAI::current_lvm_config{$vg}{physical_volumes} } =
- sort keys %{ get_physical_volume_information($vg) };
- }
-
-}
-
-################################################################################
-#
-# @brief Collect the current RAID device information from all partitions
-# currently active in the system
-#
-################################################################################
-sub get_current_raid {
-
- # the list to hold the output of mdadm commands as parsed below
- my @mdadm_print = ();
-
- # try to obtain the list of existing RAID arrays
- my $error =
- &FAI::execute_ro_command("mdadm --detail --scan --verbose -c partitions",
- \@mdadm_print, 0);
-
-# the expected output is as follows
-# $ mdadm --detail --scan --verbose -c partitions
-# ARRAY /dev/md0 level=linear num-devices=2 UUID=7e11efd6:93e977fd:b110d941:ce79a4f6
-# devices=/dev/hda1,/dev/hda2
-# ARRAY /dev/md1 level=raid0 num-devices=2 UUID=50d7a6ec:4207f0db:b110d941:ce79a4f6
-# devices=/dev/md0,/dev/hda3
-
- # the id of the RAID
- my $id;
-
- # parse the output line by line
- foreach my $line (@mdadm_print) {
- if ($line =~ /^ARRAY \/dev\/md(\d+) level=(\S+) num-devices=\d+ UUID=/) {
- $id = $1;
- $FAI::current_raid_config{$id}{mode} = $2;
- &FAI::push_command( "true", "", "exist_/dev/md$id" );
- } elsif ($line =~ /^\s*devices=(\S+)$/) {
- @{ $FAI::current_raid_config{$id}{devices} } = split (",", $1);
- }
- }
-}
-
-
-################################################################################
-#
-# @brief Set the appropriate preserve flag for $device_name
-#
-# @param device_name Full device path
-#
-################################################################################
-sub mark_preserve {
- my ($device_name) = @_;
- my ($i_p_d, $disk, $part_no) = &FAI::phys_dev($device_name);
-
- if (1 == $i_p_d && defined($FAI::configs{"PHY_$disk"}{partitions}{$part_no})) {
- $FAI::configs{"PHY_$disk"}{partitions}{$part_no}{size}{preserve} = 1;
- } elsif ($device_name =~ m{^/dev/md(\d+)$}) {
- my $vol = $1;
- if (defined($FAI::configs{RAID}{volumes}{$vol}) &&
- $FAI::configs{RAID}{volumes}{$vol}{preserve} != 1) {
- $FAI::configs{RAID}{volumes}{$vol}{preserve} = 1;
- &FAI::mark_preserve($_) foreach (keys %{ $FAI::configs{RAID}{volumes}{$vol}{devices} });
- }
- } elsif ($device_name =~ m{^/dev/([^/\s]+)/([^/\s]+)$}) {
- my $vg = $1;
- my $lv = $2;
- if (defined($FAI::configs{"VG_$vg"}{volumes}{$lv}) &&
- $FAI::configs{"VG_$vg"}{volumes}{$lv}{size}{preserve} != 1) {
- $FAI::configs{"VG_$vg"}{volumes}{$lv}{size}{preserve} = 1;
- &FAI::mark_preserve($_) foreach (keys %{ $FAI::configs{"VG_$vg"}{devices} });
- }
- } else {
- warn "Don't know how to mark $device_name for preserve\n";
- }
-}
-
-
-################################################################################
-#
-# @brief Mark devices as preserve, in case an LVM volume or RAID device shall be
-# preserved
-#
-################################################################################
-sub propagate_preserve {
-
- # loop through all configs
- foreach my $config (keys %FAI::configs) {
-
- # no physical devices here
- next if ($config =~ /^PHY_./);
-
- if ($config =~ /^VG_(.+)$/) {
- next if ($1 eq "--ANY--");
- # check for logical volumes that need to be preserved and preserve the
- # underlying devices recursively
- foreach my $l (keys %{ $FAI::configs{$config}{volumes} }) {
- next unless ($FAI::configs{$config}{volumes}{$l}{size}{preserve} == 1);
- &FAI::mark_preserve($_) foreach (keys %{ $FAI::configs{$config}{devices} });
- last;
- }
- } elsif ($config eq "RAID") {
- # check for volumes that need to be preserved and preserve the underlying
- # devices recursively
- foreach my $r (keys %{ $FAI::configs{$config}{volumes} }) {
- next unless ($FAI::configs{$config}{volumes}{$r}{preserve} == 1);
- &FAI::mark_preserve($_) foreach (keys %{ $FAI::configs{$config}{volumes}{$r}{devices} });
- }
- } else {
- &FAI::internal_error("Unexpected key $config");
- }
- }
-}
-
-
-1;
-
Copied: trunk/lib/setup-storage/Volumes.pm (from rev 4954, people/michael/features/setup_harddisks_2/implementation/lib/volumes.pm)
===================================================================
--- trunk/lib/setup-storage/Volumes.pm (rev 0)
+++ trunk/lib/setup-storage/Volumes.pm 2008-06-12 11:37:53 UTC (rev 4955)
@@ -0,0 +1,437 @@
+#!/usr/bin/perl -w
+
+#*********************************************************************
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# A copy of the GNU General Public License is available as
+# `/usr/share/common-licences/GPL' in the Debian GNU/Linux distribution
+# or on the World Wide Web at http://www.gnu.org/copyleft/gpl.html. You
+# can also obtain it by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+#*********************************************************************
+
+use strict;
+
+################################################################################
+#
+# @file volumes.pm
+#
+# @brief Parse the current partition table and LVM/RAID configurations
+#
+# $Id$
+#
+# @author Christian Kern, Michael Tautschnig
+# @date Sun Jul 23 16:09:36 CEST 2006
+#
+################################################################################
+
+package FAI;
+
+################################################################################
+#
+# @brief Collect the current partition information from all disks listed both
+# in $FAI::disks and $FAI::configs{PHY_<disk>}
+#
+################################################################################
+sub get_current_disks {
+
+ # obtain the current state of all disks
+ foreach my $disk (@FAI::disks) {
+
+ # create full paths
+ ($disk =~ m{^/}) or $disk = "/dev/$disk";
+
+ # make sure, $disk is a proper block device
+ (-b $disk) or die "$disk is not a block special device!\n";
+ &FAI::push_command( "true", "", "exist_$disk" );
+
+ # initialise the hash
+ $FAI::current_config{$disk}{partitions} = {};
+
+ # the list to hold the output of parted commands as parsed below
+ my @parted_print = ();
+
+ # try to obtain the partition table for $disk
+ # it might fail with parted_2 in case the disk has no partition table
+ my $error =
+ &FAI::execute_ro_command("parted -s $disk unit TiB print", \@parted_print, 0);
+
+ # parted_2 happens when the disk has no disk label, because parted then
+ # provides no information about the disk
+ if ($error eq "parted_2") {
+ $FAI::no_dry_run or die
+ "Can't run on test-only mode on this system because there is no disklabel on $disk\n";
+
+ # if there is no disk configuration, write an msdos disklabel
+ if (!defined ($FAI::configs{"PHY_$disk"}{disklabel})) {
+
+ # write the disk label as configured
+ $error = &FAI::execute_command("parted -s $disk mklabel msdos");
+ } else {
+
+ # write the disk label as configured
+ $error = &FAI::execute_command("parted -s $disk mklabel "
+ . $FAI::configs{"PHY_$disk"}{disklabel});
+ }
+ # retry partition-table print
+ $error =
+ &FAI::execute_ro_command("parted -s $disk unit TiB print", \@parted_print, 0);
+ }
+
+ ($error eq "") or die "Failed to read the partition table from $disk\n";
+
+# the following code parses the output of parted print, using various units
+# (TiB, B, chs)
+# the parser is capable of reading the output of parted version 1.7.1, which
+# looks like
+#
+# $ /sbin/parted -s /dev/hda unit B print
+# WARNING: You are not superuser. Watch out for permissions.
+#
+# Disk /dev/hda: 80026361855B
+# Sector size (logical/physical): 512B/512B
+# Partition Table: mac
+#
+# Number Start End Size File system Name Flags
+# 1 512B 32767B 32256B primary
+# 5 32768B 1033215B 1000448B hfs primary boot
+# 3 134250496B 32212287487B 32078036992B hfs+ primary
+# 6 32212287488B 46212287487B 14000000000B ext3 primary
+# 2 46212287488B 47212287999B 1000000512B linux-swap primary swap
+# 4 47212288000B 80026361855B 32814073856B ext3 primary
+#
+# Note that the output contains an additional column on msdos, indicating,
+# whether the type of a partition is primary, logical or extended.
+#
+# $ parted -s /dev/hda unit B print
+#
+# Disk /dev/hda: 82348277759B
+# Sector size (logical/physical): 512B/512B
+# Partition Table: msdos
+#
+# Number Start End Size Type File system Flags
+# 1 32256B 24675839B 24643584B primary ext3
+# 2 24675840B 1077511679B 1052835840B primary linux-swap
+# 3 1077511680B 13662190079B 12584678400B primary ext3 boot
+# 4 13662190080B 82343278079B 68681088000B extended
+# 5 13662222336B 14715025919B 1052803584B logical ext3
+# 14715058176B 30449986559B 15734928384B
+# 7 30450018816B 32547432959B 2097414144B logical ext3
+# 8 32547465216B 82343278079B 49795812864B logical ext3
+#
+
+ # As shown above, some entries may be blank. Thus the exact column starts
+ # and lengths must be parsed from the header line. This is stored in the
+ # following hash
+ my %cols = ();
+
+ # Parse the output line by line
+ foreach my $line (@parted_print) {
+
+ # now we test line by line - some of them may be ignored
+ next if ($line =~ /^Disk / || $line =~ /^\s*$/
+ || $line =~ /^WARNING: You are not superuser/);
+
+ # determine the logical sector size
+ if ($line =~ /^Sector size \(logical\/physical\): (\d+)B\/\d+B$/) {
+ $FAI::current_config{$disk}{sector_size} = $1;
+ }
+
+ # read and store the current disk label
+ elsif ($line =~ /^Partition Table: (.+)$/) {
+ $FAI::current_config{$disk}{disklabel} = $1;
+ }
+
+ # the line containing the table headers
+ elsif ($line =~ /^(Number\s+)(\S+\s+)+/) {
+ my $col_start = 0;
+
+ # check the length of each heading; note that they might contain spaces
+ while ($line =~ /^(\S+( [a-z]\S+)?\s*)([A-Z].*)?$/) {
+ my $heading = $1;
+
+ # set the line to the remainder
+ $line = "";
+ $line = $3 if defined ($3);
+
+ # the width of the column includes any whitespace
+ my $col_width = length ($heading);
+ $heading =~ s/(\S+)\s*$/$1/;
+
+ # build the hash entry
+ # this start counter starts at 0, which is useful below
+ $cols{$heading} = {
+ "start" => $col_start,
+ "length" => $col_width
+ };
+ $col_start += $col_width;
+ }
+ } else { # one of the partitions
+
+ # we must have seen the header, otherwise probably the format has
+ # changed
+ defined ($cols{"File system"}{"start"})
+ or &FAI::internal_error("Table header not seen yet");
+
+ # the info for the partition number
+ my $num_cols_before = $cols{"Number"}{"start"};
+ my $num_col_width = $cols{"Number"}{"length"};
+
+ # the info for the file system column
+ my $fs_cols_before = $cols{"File system"}{"start"};
+ my $fs_col_width = $cols{"File system"}{"length"};
+
+ # get the partition number, if any
+ $line =~ /^.{$num_cols_before}(.{$num_col_width})/;
+ my $id = $1;
+ $id =~ s/\s*//g;
+
+ # if there is no partition number, then it must be free space, so no
+ # file system either
+ next if ($id eq "");
+
+ # extract the set of characters
+ $line =~ /^.{$fs_cols_before}(.{$fs_col_width})/;
+ my $fs = $1;
+
+ # remove any trailing space
+ $fs =~ s/\s*$//g;
+
+ # store the information in the hash
+ $FAI::current_config{$disk}{partitions}{$id}{filesystem} = $fs;
+ }
+ }
+
+ # reset the output list
+ @parted_print = ();
+
+ # obtain the partition table using bytes as units
+ $error =
+ &FAI::execute_ro_command("parted -s $disk unit B print free", \@parted_print, 0);
+
+ # Parse the output of the byte-wise partition table
+ foreach my $line (@parted_print) {
+
+ # the disk size line (Disk /dev/hda: 82348277759B)
+ if ($line =~ /Disk \Q$disk\E: (\d+)B$/) {
+ $FAI::current_config{$disk}{begin_byte} = 0;
+ $FAI::current_config{$disk}{end_byte} = $1 - 1;
+ $FAI::current_config{$disk}{size} = $1;
+
+ # nothing else to be done
+ next;
+ }
+
+ # One of the partition lines, see above example
+ next unless ($line =~
+ /^\s*(\d+)\s+(\d+)B\s+(\d+)B\s+(\d+)B(\s+(primary|logical|extended))?/i);
+
+ # mark the bounds of existing partitions
+ $FAI::current_config{$disk}{partitions}{$1}{begin_byte} = $2;
+ $FAI::current_config{$disk}{partitions}{$1}{end_byte} = $3;
+ $FAI::current_config{$disk}{partitions}{$1}{count_byte} = $4;
+
+ # is_extended defaults to false/0
+ $FAI::current_config{$disk}{partitions}{$1}{is_extended} = 0;
+
+ # but may be true/1 on msdos disk labels
+ ( ( $FAI::current_config{$disk}{disklabel} eq "msdos" )
+ && ( $6 eq "extended" ) )
+ and $FAI::current_config{$disk}{partitions}{$1}{is_extended} = 1;
+ }
+
+ # reset the output list
+ @parted_print = ();
+
+ # obtain the partition table using bytes as units
+ $error =
+ &FAI::execute_ro_command(
+ "parted -s $disk unit chs print free", \@parted_print, 0);
+
+ # Parse the output of the CHS partition table
+ foreach my $line (@parted_print) {
+
+ # find the BIOS geometry that looks like this:
+ # BIOS cylinder,head,sector geometry: 10011,255,63. Each cylinder is 8225kB.
+ if ($line =~
+ /^BIOS cylinder,head,sector geometry:\s*(\d+),(\d+),(\d+)\.\s*Each cylinder is \d+kB\.$/) {
+ $FAI::current_config{$disk}{bios_cylinders} = $1;
+ $FAI::current_config{$disk}{bios_heads} = $2;
+ $FAI::current_config{$disk}{bios_sectors_per_track} = $3;
+ }
+ }
+
+ # make sure we have determined all the necessary information
+ ($FAI::current_config{$disk}{begin_byte} == 0)
+ or die "Invalid start byte\n";
+ ($FAI::current_config{$disk}{end_byte} > 0) or die "Invalid end byte\n";
+ defined ($FAI::current_config{$disk}{size})
+ or die "Failed to determine disk size\n";
+ defined ($FAI::current_config{$disk}{sector_size})
+ or die "Failed to determine sector size\n";
+ defined ($FAI::current_config{$disk}{bios_sectors_per_track})
+ or die "Failed to determine the number of sectors per track\n";
+
+ }
+}
+
+################################################################################
+#
+# @brief Collect the current LVM configuration
+#
+################################################################################
+sub get_current_lvm {
+
+ use Linux::LVM;
+
+ # get the existing volume groups
+ foreach my $vg (get_volume_group_list()) {
+ # initialise the hash entry
+ $FAI::current_lvm_config{$vg}{physical_volumes} = ();
+ &FAI::push_command( "true", "", "vg_created_$vg" );
+
+ # store the vg size in MB
+ my %vg_info = get_volume_group_information($vg);
+ $FAI::current_lvm_config{$vg}{size} =
+ &FAI::convert_unit( $vg_info{alloc_pe_size} .
+ $vg_info{alloc_pe_size_unit} );
+
+ # store the logical volumes and their sizes
+ my %lv_info = get_logical_volume_information($vg);
+ foreach my $lv_name (sort keys %lv_info) {
+ my $short_name = $lv_name;
+ $short_name =~ "s{/dev/\Q$vg\E/}{}";
+ $FAI::current_lvm_config{$vg}{volumes}{$short_name}{size} =
+ &FAI::convert_unit($lv_info{$lv_name}->{lv_size} .
+ $lv_info{$lv_name}->{lv_size_unit});
+ &FAI::push_command( "true", "", "exist_/dev/$vg/$short_name" );
+ }
+
+ # store the physical volumes
+ my %pv_info = get_physical_volume_information($vg);
+ @{ $FAI::current_lvm_config{$vg}{physical_volumes} } =
+ sort keys %{ get_physical_volume_information($vg) };
+ }
+
+}
+
+################################################################################
+#
+# @brief Collect the current RAID device information from all partitions
+# currently active in the system
+#
+################################################################################
+sub get_current_raid {
+
+ # the list to hold the output of mdadm commands as parsed below
+ my @mdadm_print = ();
+
+ # try to obtain the list of existing RAID arrays
+ my $error =
+ &FAI::execute_ro_command("mdadm --detail --scan --verbose -c partitions",
+ \@mdadm_print, 0);
+
+# the expected output is as follows
+# $ mdadm --detail --scan --verbose -c partitions
+# ARRAY /dev/md0 level=linear num-devices=2 UUID=7e11efd6:93e977fd:b110d941:ce79a4f6
+# devices=/dev/hda1,/dev/hda2
+# ARRAY /dev/md1 level=raid0 num-devices=2 UUID=50d7a6ec:4207f0db:b110d941:ce79a4f6
+# devices=/dev/md0,/dev/hda3
+
+ # the id of the RAID
+ my $id;
+
+ # parse the output line by line
+ foreach my $line (@mdadm_print) {
+ if ($line =~ /^ARRAY \/dev\/md(\d+) level=(\S+) num-devices=\d+ UUID=/) {
+ $id = $1;
+ $FAI::current_raid_config{$id}{mode} = $2;
+ &FAI::push_command( "true", "", "exist_/dev/md$id" );
+ } elsif ($line =~ /^\s*devices=(\S+)$/) {
+ @{ $FAI::current_raid_config{$id}{devices} } = split (",", $1);
+ }
+ }
+}
+
+
+################################################################################
+#
+# @brief Set the appropriate preserve flag for $device_name
+#
+# @param device_name Full device path
+#
+################################################################################
+sub mark_preserve {
+ my ($device_name) = @_;
+ my ($i_p_d, $disk, $part_no) = &FAI::phys_dev($device_name);
+
+ if (1 == $i_p_d && defined($FAI::configs{"PHY_$disk"}{partitions}{$part_no})) {
+ $FAI::configs{"PHY_$disk"}{partitions}{$part_no}{size}{preserve} = 1;
+ } elsif ($device_name =~ m{^/dev/md(\d+)$}) {
+ my $vol = $1;
+ if (defined($FAI::configs{RAID}{volumes}{$vol}) &&
+ $FAI::configs{RAID}{volumes}{$vol}{preserve} != 1) {
+ $FAI::configs{RAID}{volumes}{$vol}{preserve} = 1;
+ &FAI::mark_preserve($_) foreach (keys %{ $FAI::configs{RAID}{volumes}{$vol}{devices} });
+ }
+ } elsif ($device_name =~ m{^/dev/([^/\s]+)/([^/\s]+)$}) {
+ my $vg = $1;
+ my $lv = $2;
+ if (defined($FAI::configs{"VG_$vg"}{volumes}{$lv}) &&
+ $FAI::configs{"VG_$vg"}{volumes}{$lv}{size}{preserve} != 1) {
+ $FAI::configs{"VG_$vg"}{volumes}{$lv}{size}{preserve} = 1;
+ &FAI::mark_preserve($_) foreach (keys %{ $FAI::configs{"VG_$vg"}{devices} });
+ }
+ } else {
+ warn "Don't know how to mark $device_name for preserve\n";
+ }
+}
+
+
+################################################################################
+#
+# @brief Mark devices as preserve, in case an LVM volume or RAID device shall be
+# preserved
+#
+################################################################################
+sub propagate_preserve {
+
+ # loop through all configs
+ foreach my $config (keys %FAI::configs) {
+
+ # no physical devices here
+ next if ($config =~ /^PHY_./);
+
+ if ($config =~ /^VG_(.+)$/) {
+ next if ($1 eq "--ANY--");
+ # check for logical volumes that need to be preserved and preserve the
+ # underlying devices recursively
+ foreach my $l (keys %{ $FAI::configs{$config}{volumes} }) {
+ next unless ($FAI::configs{$config}{volumes}{$l}{size}{preserve} == 1);
+ &FAI::mark_preserve($_) foreach (keys %{ $FAI::configs{$config}{devices} });
+ last;
+ }
+ } elsif ($config eq "RAID") {
+ # check for volumes that need to be preserved and preserve the underlying
+ # devices recursively
+ foreach my $r (keys %{ $FAI::configs{$config}{volumes} }) {
+ next unless ($FAI::configs{$config}{volumes}{$r}{preserve} == 1);
+ &FAI::mark_preserve($_) foreach (keys %{ $FAI::configs{$config}{volumes}{$r}{devices} });
+ }
+ } else {
+ &FAI::internal_error("Unexpected key $config");
+ }
+ }
+}
+
+
+1;
+
More information about the Fai-commit
mailing list