/[smeserver]/rpms/e-smith-base/sme10/e-smith-base-5.8.0-rewrite_manageraid.patch
ViewVC logotype

Contents of /rpms/e-smith-base/sme10/e-smith-base-5.8.0-rewrite_manageraid.patch

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.3 - (show annotations) (download)
Sun Jun 6 20:38:52 2021 UTC (3 years, 5 months ago) by jpp
Branch: MAIN
CVS Tags: HEAD
Changes since 1.2: +0 -0 lines
FILE REMOVED
5.8.1

1 diff -urN e-smith-base-5.8.0.old/root/sbin/e-smith/add_drive_to_raid e-smith-base-5.8.0/root/sbin/e-smith/add_drive_to_raid
2 --- e-smith-base-5.8.0.old/root/sbin/e-smith/add_drive_to_raid 2008-03-26 16:49:00.000000000 +0000
3 +++ e-smith-base-5.8.0/root/sbin/e-smith/add_drive_to_raid 2020-12-23 17:45:39.455641041 +0000
4 @@ -31,133 +31,96 @@
5 GetOptions(\%options, 'f', 'force');
6
7 my $force = $options{f} || $options{force};
8 -
9 my $newdev = $ARGV[0] || die "usage:\n\n\tadd_drive_to_raid [-f] dev\n\n";
10 -
11 +my $target_drive = "/dev/$newdev";
12 my $raid = require "/sbin/e-smith/console-menu-items/manageRAID.pl";
13
14 +# Log STDOUT from this point on and return STDERR back to the console
15 +my $pid = open(STDOUT, "|-");
16 +die gettext("Can't fork"), ": $!\n" unless defined $pid;
17 +
18 +unless ($pid)
19 +{
20 + exec qw(/usr/bin/logger -p local1.info -t add_drive_to_raid);
21 +}
22 +
23 +# Get dictionary of active md devices and sort by size
24 my %devices = $raid->get_raid_details();
25 my @devices = sort { $devices{$a}{DeviceSize} <=> $devices{$b}{DeviceSize} } keys %devices;
26
27 die "There are no RAID devices configured\n" unless $#devices >= 0;
28
29 +# Get dictionary of all partitions from /proc/partitions
30 my %partitions = $raid->get_partitions();
31 my @partitions;
32
33 -my $minsize = 0;
34 -
35 -die "/dev/$newdev is not a block special device\n" unless -b "/dev/$newdev";
36 +die "$target_drive is not a block special device\n" unless -b $target_drive;
37
38 +# Calculate min size of new disk to accomodate active md devices
39 +my $minsize = 0;
40 for my $dev (@devices)
41 {
42 - die "/dev/$newdev is already in use\n" if grep m#^$newdev$#, @{$devices{$dev}{UsedDisks}};
43 + die "$target_drive is already in use\n" if grep m#^$newdev$#, @{$devices{$dev}{UsedDisks}};
44 $minsize += $devices{$dev}{DeviceSize} + 65;
45 }
46
47 -die "/dev/$newdev is not large enough\n" unless $partitions{$newdev}{blocks} >= $minsize;
48 -
49 -die "/dev/$newdev already contains partitions\n" unless $force or ! grep m#^$newdev.+$#, keys %partitions;
50 +die "$target_drive is not large enough\n" unless $partitions{$newdev}{blocks} >= $minsize;
51 +die "$target_drive already contains partitions\n" unless $force or ! grep m#^$newdev.+$#, keys %partitions;
52
53 -my $pid = open(STDERR, "|-");
54 -die gettext("Can't fork"), ": $!\n" unless defined $pid;
55 -
56 -unless ($pid)
57 -{
58 - exec qw(/usr/bin/logger -p local1.info -t add_drive_to_raid);
59 +# Find a healthy drive hosting our /boot partition to use as our template
60 +my @srcdrives = qx(df /boot --output=source | grep /dev/ | xargs -r lsblk -lnsp | grep disk);
61 +die "Unable to identify existing boot device - manual intervention required\n" unless (scalar @srcdrives) >= 1;
62 +my ($source_drive) = $srcdrives[0] =~ /(\S+)/;
63 +print "Using $source_drive as source partition template.\n";
64 +
65 +# Check if it's MBR or GPT
66 +my $pttype = qx(blkid -o value -s PTTYPE $source_drive);
67 +chomp $pttype;
68 +die "Unable to identify source partition table type for $source_drive\n" unless $pttype;
69 +print "$source_drive partition table type is $pttype\n";
70 +
71 +# Clear disk in preparation
72 +print "Wiping $target_drive...\n";
73 +system("wipefs", "-a", $target_drive) == 0
74 + or die "Error clearing existing partition table on $target_drive\n";
75 +
76 +# Copy new partition layout
77 +print "Copying partition table from $source_drive to $target_drive...\n";
78 +if ($pttype eq 'dos') {
79 + system("sfdisk -d $source_drive | sfdisk -qf --no-reread $target_drive") == 0
80 + or die "Error copying MBR partition table to $target_drive\n";
81 +} elsif ($pttype eq 'gpt') {
82 + system("sgdisk", "-R", $target_drive, $source_drive) == 0
83 + or die "Error copying GPT partition table to $target_drive\n";
84 + system("sgdisk", "-G", $target_drive) == 0
85 + or die "Error randomising GUID on $target_drive\n";
86 +} else {
87 + die "Couldn't interpret partition table type '$pttype' on $source_drive\n";
88 }
89
90 -unless (open(OUTPUT, "-|"))
91 -{
92 - my $boot = "*";
93 - my $pid = open(SFDISK, "|-");
94 - if ($pid)
95 - {
96 - # parent
97 - for my $dev (@devices)
98 - {
99 - unless ($dev eq $devices[$#devices])
100 - {
101 - print SFDISK ",", $devices{$dev}{DeviceSize} + 65, ",fd,$boot\n";
102 - }
103 - else
104 - {
105 - print SFDISK ",,fd,$boot\n";
106 - }
107 - $boot = "-";
108 - }
109 - print SFDISK ",0\n" for (1..4);
110 - close(SFDISK) || die "SFDISK kid exited $?\n";
111 - }
112 - else
113 - {
114 - # child
115 - exec("/sbin/sfdisk", "-uB", "--no-reread", "--force", "/dev/$newdev")
116 - or die "can't exec program: $!\n";
117 - # NOTREACHED
118 - }
119 -
120 - print "\nChecking partitions on /dev/$newdev...\n";
121 - sleep(3);
122 - my $good;
123 - my $cnt = 0;
124 - do {
125 - $cnt++;
126 - $good = 1;
127 - sleep(1);
128 -
129 - %partitions = $raid->get_partitions();
130 - @partitions = sort grep m#^$newdev.+$#, keys %partitions;
131 - if ( $#devices == $#partitions ) {
132 - foreach my $part ( 0..($#devices-1) ) {
133 - $good &= $partitions{$partitions[$part]}{blocks} >= $devices{$devices[$part]}{DeviceSize} + 64;
134 - $good &= $partitions{$partitions[$part]}{blocks} <= $devices{$devices[$part]}{DeviceSize} + 68;
135 - $good &= -b "/dev/$partitions[$part]" || 0;
136 - }
137 - $good &= $partitions{$partitions[$#devices]}{blocks} >= $devices{$devices[$#devices]}{DeviceSize} + 64;
138 - $good &= -b "/dev/$partitions[$#devices]" || 0;
139 - } else {
140 - $good = 0;
141 - }
142 - } until ( $good || $cnt > 60 );
143 - print "\n";
144 -
145 - die "\nPartitions on /dev/$newdev aren't correct. Reboot may be necessary.\n" unless $good;
146 -
147 - sleep(3);
148 - foreach my $part (0..$#devices)
149 - {
150 - print "Going to add /dev/$partitions[$part] to $devices[$part]\n";
151 - system("/sbin/mdadm", $devices[$part], "--add", "/dev/$partitions[$part]");
152 - sleep(2);
153 - }
154 -
155 - print "\nWaiting for boot partition to sync before installing grub...\n";
156 - sleep(15);
157 -
158 - $pid = open(GRUB, "|-");
159 - if ($pid)
160 - {
161 - # parent
162 - print GRUB "device (hd0) /dev/$newdev\n";
163 - print GRUB "root (hd0,0)\n";
164 - print GRUB "setup (hd0)\n";
165 - print GRUB "quit\n";
166 - close(GRUB) || die "GRUB kid exited $?\n";
167 - exit(0);
168 - }
169 - else
170 - {
171 - # child
172 - exec("/sbin/grub", "--no-floppy", "--batch")
173 - or die "can't exec program: $!\n";
174 - # NOTREACHED
175 - }
176 -}
177 -while(<OUTPUT>)
178 +# Pause to sync
179 +sleep(3);
180 +
181 +# Install GRUB
182 +print "Installing GRUB on $target_drive...\n";
183 +system("grub2-install", "--recheck", $target_drive) == 0
184 + or warn "Warning - error installing GRUB to $target_drive\n";
185 +
186 +# Loop through RAID devices and add the corresponding new partitions
187 +my @srcparts;
188 +my $srcpart;
189 +my $tgtpart;
190 +foreach my $part (0..$#devices)
191 {
192 - print "$_";
193 - next unless $_;
194 - warn "$_";
195 + # Find the matching source drive partition and substitute the name
196 + @srcparts = qx(mdadm -v --detail --scan $devices[$part]);
197 + foreach my $s (@srcparts) {($srcpart) = $s =~ /devices=(\Q$source_drive\E\d+)/};
198 + $tgtpart = $srcpart =~ s/\Q$source_drive/$target_drive/r;
199 +
200 + print "Adding $tgtpart to $devices[$part]\n";
201 + system("/sbin/mdadm", $devices[$part], "--add", $tgtpart) == 0
202 + or die "Error adding $tgtpart to $devices[$part]";
203 }
204 -close(OUTPUT) or die "Closing stdin pipe reported: $!\n";
205
206 +# Finished
207 +print "Successfully added $target_drive to RAID!\n";
208 \ No newline at end of file
209 diff -urN e-smith-base-5.8.0.old/root/sbin/e-smith/console-menu-items/manageRAID.pl e-smith-base-5.8.0/root/sbin/e-smith/console-menu-items/manageRAID.pl
210 --- e-smith-base-5.8.0.old/root/sbin/e-smith/console-menu-items/manageRAID.pl 2020-12-23 17:42:19.991247057 +0000
211 +++ e-smith-base-5.8.0/root/sbin/e-smith/console-menu-items/manageRAID.pl 2020-12-23 17:46:12.587310812 +0000
212 @@ -3,10 +3,11 @@
213 use warnings;
214 use esmith::console;
215 use Locale::gettext;
216 +use Taint::Util;
217
218 use Data::Dumper;
219
220 -use constant DEBUG_MANAGE_RAID => 1;
221 +use constant DEBUG_MANAGE_RAID => 0;
222
223 sub new
224 {
225 @@ -35,11 +36,12 @@
226 my ($rc, $choice);
227
228 use POSIX qw(strftime);
229 +
230 + SCAN:
231 my $today = strftime "%A %B %e, %Y %H:%M:%S", localtime;
232 my $title = gettext("Disk redundancy status as of") . " " . $today,
233 my $text = gettext("Current RAID status:") . "\n\n" .
234 join("", get_raid_status()) . "\n\n";
235 -
236 my %devices = get_raid_details();
237
238 warn $text if DEBUG_MANAGE_RAID;
239 @@ -52,31 +54,40 @@
240 return;
241 }
242
243 + # Determine the status of each array
244 my @unclean = ();
245 my @recovering = ();
246 + my @failed = ();
247 my %used_disks = ();
248
249 for my $dev (keys %devices)
250 {
251 - $used_disks{$_}++ for (@{$devices{$dev}{UsedDisks}});
252 + $used_disks{$_}++ for (@{$devices{$dev}{UsedDisks}});
253
254 - if ($devices{$dev}{State} =~ /recovering|resync/)
255 - {
256 + if ($devices{$dev}{FailedDevices} > 0) {
257 + push @failed, "$dev => " . $devices{$dev}{FailedDevices};
258 + }
259 +
260 + if ($devices{$dev}{State} =~ /recovering|resync/) {
261 push @recovering, "$dev => " . $devices{$dev}{State};
262 next;
263 }
264
265 next if ($devices{$dev}{State} =~ /^(clean|active)\s*$/);
266 -
267 push @unclean, "$dev => " . $devices{$dev}{State};
268 }
269
270 - warn "used_disks: " . Dumper(\%used_disks) . "\n" if DEBUG_MANAGE_RAID;
271 -
272 warn "unclean: @unclean\n" if DEBUG_MANAGE_RAID;
273 -
274 warn "recovering: @recovering\n" if DEBUG_MANAGE_RAID;
275 + warn "failed: @failed\n" if DEBUG_MANAGE_RAID;
276 + warn "used_disks: " . Dumper(\%used_disks) . "\n" if DEBUG_MANAGE_RAID;
277
278 + # Check for any spare disks we could add
279 + my %free_disks = map {$_ => 1} get_disks();
280 + delete $free_disks{$_} for keys %used_disks;
281 + warn "free_disks: " . Dumper(\%free_disks) . "\n" if DEBUG_MANAGE_RAID;
282 +
283 + # Report status and return if recovering
284 if (scalar @recovering)
285 {
286 $text .= gettext("A RAID resynchronization is in progress.");
287 @@ -84,29 +95,33 @@
288 return;
289 }
290
291 - unless (scalar @unclean)
292 + # Report status and return if arrays are inconsistent
293 + if ((scalar @unclean && scalar @unclean != scalar keys %devices) || (scalar @failed && scalar @failed != scalar keys %devices))
294 {
295 - $text .= gettext("All RAID devices are in clean state");
296 + $text .= gettext("Only some of the RAID devices are unclean or contain failed disks.") .
297 + "\n\n" .
298 + gettext("Manual intervention may be required.") . "\n\n";
299 +
300 ($rc, $choice) = $console->message_page(title => $title, text => $text);
301 return;
302 }
303
304 - unless (scalar @unclean == scalar keys %devices)
305 + # Report status if arrays are clean and continue if a spare disk is available or there's only one disk in the system
306 + unless (scalar @unclean || scalar @failed)
307 {
308 - $text .= gettext("Only some of the RAID devices are unclean.") .
309 - "\n\n" .
310 - gettext("Manual intervention may be required.") . "\n\n";
311 -
312 + $text .= gettext("All RAID devices are in a clean state.");
313 + ($rc, $choice) = $console->message_page(title => $title, text => $text);
314 + return unless scalar keys %free_disks > 0 || scalar keys %used_disks == 1;
315 + }
316 +
317 + # Report status if all arrays are dirty and continue
318 + if ((scalar @unclean && scalar @unclean == scalar keys %devices) || (scalar @failed && scalar @failed == scalar keys %devices))
319 + {
320 + $text .= gettext("All RAID devices are in an unclean state or contain failed disks.");
321 ($rc, $choice) = $console->message_page(title => $title, text => $text);
322 - return;
323 }
324
325 - my %free_disks = map {$_ => 1} get_disks();
326 -
327 - delete $free_disks{$_} for keys %used_disks;
328 -
329 - warn "free_disks: " . Dumper(\%free_disks) . "\n" if DEBUG_MANAGE_RAID;
330 -
331 + # Summarise disk assignments
332 my $disk_status = gettext("Current disk status:") . "\n\n";
333 $disk_status .= gettext("Installed disks") . ": " .
334 join(" ", get_disks()) . "\n";
335 @@ -115,50 +130,64 @@
336 $disk_status .= gettext("Free disks") . ": " .
337 join(" ", keys %free_disks) . "\n";
338
339 - if (scalar keys %used_disks == 1 and scalar keys %free_disks == 0)
340 + # Spare disk scenarios
341 + # Scenario 1 - single disk or degraded array with no spare - warn
342 + if ((scalar @unclean || scalar @failed || scalar keys %used_disks == 1) && scalar keys %free_disks == 0)
343 {
344 - $text .= gettext("Your system only has a single disk drive installed or is using hardware mirroring. If you would like to enable software mirroring, please shut down, install a second disk drive (of the same capacity) and then return to this screen.");
345 + $text = $disk_status .
346 + "\n\n" .
347 + gettext("To ensure continued redundancy, please shut down, install another drive of the same capacity and then return to this screen.");
348
349 ($rc, $choice) = $console->message_page(title => $title, text => $text);
350 return;
351 }
352
353 - unless (scalar keys %used_disks == 1 and
354 - scalar keys %free_disks == scalar keys %used_disks)
355 + # Scenario 2 - no spares and not degraded so something has gone wrong
356 + if (scalar keys %free_disks == 0)
357 {
358 - $text .= gettext("The free and used disk count must equal one.") .
359 - "\n\n" .
360 - gettext("Manual intervention may be required.") . "\n\n" .
361 - $disk_status;
362 + $text = $disk_status .
363 + "\n\n" .
364 + gettext("Your RAID devices are in an inconsistent state, and no spare drives were detected. You may need to manually remove a failed drive from your arrays using mdadm.");
365
366 ($rc, $choice) = $console->message_page(title => $title, text => $text);
367 return;
368 }
369
370 - my @cmd = ("/sbin/e-smith/add_drive_to_raid", "-f", join("", keys %free_disks));
371 + # Scenario 3 - multiple spares
372 + if (scalar keys %free_disks > 1)
373 + {
374 + $text = $disk_status .
375 + "\n\n" .
376 + gettext("Multiple spare drives have been detected. This utility can only add one drive at a time. Please either shut down and remove all but one of your spare drives, or configure your array manually.");
377
378 + ($rc, $choice) = $console->message_page(title => $title, text => $text);
379 + return;
380 + }
381 +
382 + # Scenario 4 - single spare ready to add
383 $text = $disk_status .
384 "\n\n" .
385 gettext("There is an unused disk drive in your system. Do you want to add it to the existing RAID array(s)?") .
386 - "\n\n" .
387 - gettext("WARNING: ALL DATA ON THE NEW DISK WILL BE DESTROYED!") .
388 - "\n"
389 - ;
390 + "\n\n" .
391 + gettext("WARNING: ALL DATA ON THE NEW DISK WILL BE DESTROYED!") .
392 + "\n";
393
394 ($rc, $choice) = $console->yesno_page(title => $title, text => $text, defaultno => 1);
395 return unless ($rc == 0);
396
397 + my @cmd = ("/sbin/e-smith/add_drive_to_raid", "-f", join("", keys %free_disks));
398 my $cmd_out = qx( @cmd 2>&1 );
399 - unless ($? == 0)
400 - {
401 - $text = gettext("The command failed:") . " @cmd" .
402 - "\n\n" . $cmd_out . "\n\n" .
403 - gettext("This configuration is not yet fully supported in these screens.");
404 + untaint $cmd_out;
405
406 - ($rc, $choice) = $console->message_page(title => $title, text => $text);
407 - return;
408 + if ($? == 0) {
409 + $text = "\nSuccessfully added /dev/" . join("", keys %free_disks) . " to RAID!";
410 + } else {
411 + $text = gettext("The command failed:") . " @cmd" .
412 + "\n\n" . $cmd_out . "\n\n";
413 }
414 -
415 +
416 + ($rc, $choice) = $console->message_page(title => $title, text => $text);
417 + goto SCAN;
418 }
419
420 sub get_raid_status
421 @@ -185,7 +214,7 @@
422
423 while (<MDADM>)
424 {
425 - push @devices, $1 if ( m:ARRAY (/dev/md/\d+): )
426 + push @devices, $1 if ( m:ARRAY (/dev/md/\w+): )
427 }
428 close MDADM;
429
430 @@ -203,7 +232,7 @@
431 my ($key, $value) = ($1, $2);
432 $key =~ s/\s//g;
433
434 - # Allow for different mdadm output formats for DeviceSize
435 + # Allow for different mdadm output formats for DeviceSize
436 $key =~ s/UsedDevSize/DeviceSize/;
437
438 $devices{$dev}{$key} = $value;

admin@koozali.org
ViewVC Help
Powered by ViewVC 1.2.1 RSS 2.0 feed