1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319
|
#!/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 init.pm
#
# @brief Initialize all variables and acquire the set of disks of the system.
#
# The layout of the data structures is documented in the wiki:
# https://wiki.fai-project.org/index.php/Setup-storage
#
# @author Christian Kern, Michael Tautschnig
#
################################################################################
package FAI;
# are we running an inital installation from nfsroot?
$FAI::do_init_tasks = $ENV{do_init_tasks} // 0;
################################################################################
#
# @brief Enable debugging by setting $debug to a value greater than 0
#
################################################################################
$FAI::debug = $ENV{debug} // 0;
################################################################################
#
# @brief Directory to store generated files such as fstab, crypttab
#
################################################################################
$FAI::DATADIR = $ENV{LOGDIR} // "/tmp/fai";
################################################################################
#
# @brief Write changes to disk only if set to
#
################################################################################
$FAI::no_dry_run = 0;
################################################################################
#
# @brief Perform syntactic checks only if set to 1
#
################################################################################
$FAI::check_only = 0;
################################################################################
#
# @brief The command to tell udev to settle (udevsettle or udevadm settle).
# Will be set in bin/setup-storage according to installed tool.
#
################################################################################
$FAI::udev_settle = undef;
################################################################################
#
# @brief The lists of disks of the system
#
################################################################################
@FAI::disks = ();
################################################################################
#
# @brief The variables later written to disk_var.sh
#
################################################################################
%FAI::disk_var = ();
$FAI::disk_var{SWAPLIST} = "";
$FAI::disk_var{BOOT_DEVICE} = "";
################################################################################
#
# @brief The contents later written to crypttab, if any
#
################################################################################
@FAI::crypttab = ();
################################################################################
#
# @brief A flag to tell our script that the system is not installed for the
# first time
#
################################################################################
$FAI::reinstall = 1;
$ENV{flag_initial} and $FAI::reinstall = 0;
################################################################################
#
# @brief The hash of all configurations specified in the disk_config file
#
################################################################################
%FAI::configs = ();
################################################################################
#
# @brief The current disk configuration
#
################################################################################
%FAI::current_config = ();
################################################################################
#
# @brief The current LVM configuration
#
################################################################################
%FAI::current_lvm_config = ();
$FAI::uses_lvm = 0;
################################################################################
#
# @brief The current RAID configuration
#
################################################################################
%FAI::current_raid_config = ();
$FAI::uses_raid = 0;
################################################################################
#
# @brief The commands to be executed
#
################################################################################
%FAI::commands = ();
################################################################################
#
# @brief Each command is associated with a unique id -- this one aids in
# counting (next_command_index)
#
################################################################################
$FAI::n_c_i = 1;
################################################################################
#
# @brief Map from devices to volumes stacked on top of them
#
################################################################################
%FAI::dev_children = ();
%FAI::current_dev_children = ();
################################################################################
#
# @brief Add command to hash. $pre and $post are never executed, they are just
# debug information showing the state of the program before and after the
# command has been executed.
#
# @param cmd Command
# @param pre Preconditions
# @param post Postconditions
#
################################################################################
sub push_command {
my ($cmd, $pre, $post) = @_;
$FAI::commands{$FAI::n_c_i} = {
cmd => $cmd,
pre => $pre,
post => $post
};
$FAI::n_c_i++;
}
################################################################################
#
# @brief Sort integer arrays
#
################################################################################
sub numsort { return sort { $a <=> $b } @_; }
################################################################################
#
# @brief Check, whether $dev is a physical device, and extract sub-parts
#
# @param $dev Device string
#
# @return 1, if it the matches the regexp, and disk device string, and
# partition number, if any, otherwise -1
#
################################################################################
sub phys_dev {
my ($dev) = @_;
if ($dev =~ m{^/dev/(i2o/hd[a-z]|sd[a-z]{1,2}|hd[a-z]|vd[a-z]|xvd[a-z]|fio[a-z])(\d+)?$})
{
defined($2) or return (1, "/dev/$1", -1);
return (1, "/dev/$1", $2);
}
elsif ($dev =~
m{^/dev/(loop\d+|cciss/c\d+d\d+|ida/c\d+d\d+|md\d{3,}|md/\w+\d*|rd/c\d+d\d+|ataraid/d\d+|etherd/e\d+\.\d+|nvme\d+n\d+|mmcblk\d+)(p(\d+))?$})
{
defined($2) or return (1, "/dev/$1", -1);
return (1, "/dev/$1", $3);
}
return (0, "", -2);
}
# used exclusively by enc_name() and mark_encrypted
my %dev_alias;
################################################################################
#
# @brief Compute the name of $dev considering possible encryption
#
# @param $dev Device string
#
# @return $dev iff $dev is not encrypted, otherwise /dev/mapper/<mangled name>
#
################################################################################
sub enc_name {
my ($dev) = @_;
return $dev_alias{$dev} if defined($dev_alias{$dev});
# handle old-style encryption entries
my ($i_p_d, $disk, $part_no) = &FAI::phys_dev($dev);
if ($i_p_d) {
defined ($FAI::configs{"PHY_$disk"}) or return $dev;
defined ($FAI::configs{"PHY_$disk"}{partitions}{$part_no}) or return $dev;
return $dev unless
($FAI::configs{"PHY_$disk"}{partitions}{$part_no}{encrypt});
} elsif ($dev =~ /^\/dev\/md(\d+)$/) {
defined ($FAI::configs{RAID}) or return $dev;
defined ($FAI::configs{RAID}{volumes}{$1}) or return $dev;
return $dev unless ($FAI::configs{RAID}{volumes}{$1}{encrypt});
} elsif ($dev =~ /^\/dev\/([^\/]+)\/([^\/]+)$/) {
defined ($FAI::configs{"VG_$1"}) or return $dev;
defined ($FAI::configs{"VG_$1"}{volumes}{$2}) or return $dev;
return $dev unless ($FAI::configs{"VG_$1"}{volumes}{$2}{encrypt});
} else {
return $dev;
}
&FAI::mark_encrypted($dev);
return $dev_alias{$dev};
}
################################################################################
#
# @brief Store mangled name for $dev
#
# @param $dev Device string
#
################################################################################
sub mark_encrypted {
my ($dev) = @_;
# encryption requested, rewrite the device name
my $enc_dev_name = $dev;
$enc_dev_name =~ s#/#_#g;
my $enc_dev_short_name = "crypt$enc_dev_name";
$enc_dev_name = "/dev/mapper/$enc_dev_short_name";
$dev_alias{$dev} = $enc_dev_name;
}
################################################################################
#
# @brief Convert a device name and a partition id to a proper device name,
# handling cciss and the like
#
# @param $dev Device name of disk
# @param $id Partition id
#
# @return Full device name
#
################################################################################
sub make_device_name {
my ($dev, $p) = @_;
$dev .= "p" if ($dev =~
m{^/dev/(loop\d+|cciss/c\d+d\d+|ida/c\d+d\d+|md\d{3,}|md/\w+\d*|rd/c\d+d\d+|ataraid/d\d+|etherd/e\d+\.\d+|nvme\d+n\d+|mmcblk\d+)$});
$dev .= $p;
internal_error("Invalid device $dev") unless (&FAI::phys_dev($dev))[0];
return $dev;
}
################################################################################
#
# @brief Report an error that is due to a bug in the implementation
#
# @param $error_msg Error message
#
################################################################################
sub internal_error {
my ($error_msg) = @_;
use Carp;
$Carp::CarpLevel = 1;
confess <<EOF;
INTERNAL ERROR in setup-storage:
$error_msg
Please report this error to the Debian Bug Tracking System.
EOF
}
1;
|