PageRenderTime 28ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/SystemImager/Server.pm

https://bitbucket.org/gvallee/systemimager-4.1.6-ubuntuprecise
Perl | 2366 lines | 1578 code | 338 blank | 450 comment | 171 complexity | 726ed874d42e3fcc6c393f5fc9a91f75 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. #
  2. # "SystemImager"
  3. #
  4. # Copyright (C) 1999-2006 Brian Elliott Finley
  5. #
  6. # $Id: Server.pm 4426 2008-03-11 15:05:17Z arighi $
  7. #
  8. package SystemImager::Server;
  9. use lib "USR_PREFIX/lib/systemimager/perl";
  10. use Carp;
  11. use strict;
  12. use File::Copy;
  13. use File::Path;
  14. use XML::Simple;
  15. use SystemImager::Config qw($config);
  16. use vars qw($VERSION @mount_points %device_by_mount_point %filesystem_type_by_mount_point $disk_no %dev2disk $bootdev $rootdev);
  17. $VERSION="SYSTEMIMAGER_VERSION_STRING";
  18. ################################################################################
  19. #
  20. # Subroutines in this module include:
  21. #
  22. # _mount_proc_in_image_on_client
  23. # _get_array_of_disks
  24. # _imageexists
  25. # _in_script_add_standard_header_stuff
  26. # _read_partition_info_and_prepare_parted_commands
  27. # _read_partition_info_and_prepare_soft_raid_devs -AR-
  28. # _read_partition_info_and_prepare_pvcreate_commands -AR-
  29. # _write_lvm_groups_commands -AR-
  30. # _write_lvm_volumes_commands -AR-
  31. # _write_boel_devstyle_entry
  32. # _write_elilo_conf
  33. # _write_out_mkfs_commands
  34. # _write_out_new_fstab_file
  35. # _write_out_umount_commands
  36. # add2rsyncd
  37. # copy_boot_files_from_image_to_shared_dir
  38. # copy_boot_files_to_boot_media
  39. # create_autoinstall_script
  40. # create_image_stub
  41. # gen_rsyncd_conf
  42. # get_image_path
  43. # numerically
  44. # record_image_retrieval_time
  45. # record_image_retrieved_from
  46. # remove_boot_file
  47. # remove_image_stub
  48. # upgrade_partition_schemes_to_generic_style
  49. # validate_auto_install_script_conf
  50. # validate_ip_assignment_option
  51. # validate_post_install_option
  52. #
  53. ################################################################################
  54. sub copy_boot_files_from_image_to_shared_dir {
  55. use File::Copy;
  56. use File::Path;
  57. shift;
  58. my $image = shift;
  59. my $image_dir = shift;
  60. my $rsync_stub_dir = shift;
  61. my $autoinstall_boot_dir = shift;
  62. my $kernel = $image_dir . "/etc/systemimager/boot/kernel";
  63. my $initrd = $image_dir . "/etc/systemimager/boot/initrd.img";
  64. my $file = $image_dir . "/etc/systemimager/boot/ARCH";
  65. unless ((-e $kernel) && (-e $initrd) && (-e $file)) {
  66. return -1;
  67. }
  68. open(FILE,"<$file") or die("Couldn't open $file for reading $!");
  69. my $arch = (<FILE>)[0];
  70. close(FILE);
  71. chomp $arch;
  72. my $dir = "$autoinstall_boot_dir/$arch/$image";
  73. eval { mkpath($dir, 0, 0755) };
  74. if ($@) { print "Couldn’t create $dir: $@"; }
  75. copy("$kernel","$dir") or die "Copy failed: $!";
  76. copy("$initrd","$dir") or die "Copy failed: $!";
  77. return 1;
  78. }
  79. sub record_image_retrieved_from {
  80. shift;
  81. my $image_dir = shift @_;
  82. my $golden_client = shift @_;
  83. my $file = $image_dir . "/etc/systemimager/IMAGE_RETRIEVED_FROM";
  84. local *FILE;
  85. open(FILE,">$file") or die("Couldn't open $file for writing!");
  86. print FILE "$golden_client\n";
  87. close(FILE);
  88. return 1;
  89. }
  90. sub record_image_retrieval_time {
  91. shift;
  92. my $image_dir = shift @_;
  93. my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
  94. $year += 1900;
  95. $mon += 1;
  96. my $file = $image_dir . "/etc/systemimager/IMAGE_RETRIEVAL_TIME";
  97. local *FILE;
  98. open(FILE,">$file") or die("Couldn't open $file for writing!");
  99. printf(FILE "%04d.%02d.%02d %02d:%02d\n", $year,$mon,$mday,$hour,$min);
  100. close(FILE);
  101. return 1;
  102. }
  103. sub create_image_stub {
  104. my ($class, $stub_dir, $imagename, $image_dir) = @_;
  105. open(OUT,">$stub_dir/40$imagename") or return undef;
  106. print OUT "[$imagename]\n\tpath=$image_dir\n\n";
  107. close OUT;
  108. }
  109. sub remove_image_stub {
  110. my ($class, $stub_dir, $imagename) = @_;
  111. unlink "$stub_dir/40$imagename" or return undef;
  112. }
  113. sub gen_rsyncd_conf {
  114. my ($class, $stub_dir, $rsyncconf) = @_;
  115. opendir STUBDIR, $stub_dir or return undef;
  116. my @stubfiles = readdir STUBDIR;
  117. closedir STUBDIR;
  118. #
  119. # For a stub file to be used, that stub file's name must:
  120. # o start with one or more digits
  121. # o have one or more letters and or underscores
  122. # o have no other characters
  123. #
  124. # -BEF-
  125. #
  126. @stubfiles = grep (/^\d+/, @stubfiles); # Must start with a digit
  127. @stubfiles = grep (!/~$/, @stubfiles); # Can't end with a tilde (~)
  128. @stubfiles = grep (!/\.bak$/, @stubfiles); # Can't end with .bak
  129. @stubfiles = sort @stubfiles;
  130. open(RSYNC_CONF, ">$rsyncconf") or return undef;
  131. foreach my $stub_file (@stubfiles) {
  132. my $file = "$stub_dir/$stub_file";
  133. if ( -f $file ) {
  134. open(STUBFILE, "<$file") or return undef;
  135. while (<STUBFILE>) {
  136. print RSYNC_CONF;
  137. }
  138. close STUBFILE;
  139. }
  140. }
  141. close RSYNC_CONF;
  142. }
  143. sub add2rsyncd {
  144. my ($class, $rsyncconf, $imagename, $image_dir) = @_;
  145. if(!_imageexists($rsyncconf, $imagename)) {
  146. open(OUT,">>$rsyncconf") or return undef;
  147. print OUT "[$imagename]\n\tpath=$image_dir\n\n";
  148. close OUT;
  149. return 1;
  150. }
  151. return 1;
  152. }
  153. sub _imageexists {
  154. my ($rsyncconf, $imagename) = @_;
  155. open(IN,"<$rsyncconf") or return undef;
  156. if(grep(/\[$imagename\]/, <IN>)) {
  157. close(IN);
  158. return 1;
  159. }
  160. return undef;
  161. }
  162. sub validate_post_install_option {
  163. my $post_install=$_[1];
  164. unless(($post_install eq "beep") or ($post_install eq "reboot") or ($post_install eq "shutdown") or ($post_install eq "kexec")) {
  165. die qq(\nERROR: -post-install must be beep, reboot, shutdown, or kexec.\n\n Try "-help" for more options.\n);
  166. }
  167. return 0;
  168. }
  169. sub validate_ip_assignment_option {
  170. my $ip_assignment_method=$_[1];
  171. $ip_assignment_method = lc $ip_assignment_method;
  172. unless(
  173. ($ip_assignment_method eq "")
  174. or ($ip_assignment_method eq "dhcp")
  175. or ($ip_assignment_method eq "static")
  176. or ($ip_assignment_method eq "replicant")
  177. ) { die qq(\nERROR: -ip-assignment must be dhcp, static, or replicant.\n\n Try "-help" for more options.\n); }
  178. return 0;
  179. }
  180. #
  181. # Usage: my $path = get_image_path( $stub_dir, $imagename );
  182. #
  183. sub get_image_path {
  184. my $class = shift;
  185. my $stub_dir = shift;
  186. my $imagename = shift;
  187. open (FILE, "<$stub_dir/40$imagename") or return undef;
  188. while (<FILE>) {
  189. if (/^\s*path\s*=\s*(\S+)\s$/) {
  190. close FILE;
  191. return $1;
  192. }
  193. }
  194. close FILE;
  195. return undef;
  196. }
  197. # Usage:
  198. # my $path = SystemImager::Server->get_image_path( $rsync_stub_dir, $image ); #XXX
  199. sub get_full_path_to_image_from_rsyncd_conf {
  200. print "FATAL: get_full_path_to_image_from_rsyncd_conf is depricated.\n";
  201. print "Please tell this tool to call the following subroutine instead:\n";
  202. print 'SystemImager::Server->get_image_path( $rsync_stub_dir, $image );' . "\n";
  203. die;
  204. }
  205. # Description:
  206. # Given a disk name, and a partition number, return the appropriate
  207. # filename for the partition.
  208. #
  209. # Usage:
  210. # get_part_name($disk, $num);
  211. #
  212. sub get_part_name {
  213. my ($disk, $num) = @_;
  214. if ($disk =~ /^\/dev\/.*\/c\d+d\d+$/) {
  215. return $disk . "p" . $num;
  216. }
  217. return $disk . $num;
  218. }
  219. # Description:
  220. # Returns a list of all devices (disks & partitions) from a given
  221. # autoinstallscript.conf file.
  222. #
  223. # Usage:
  224. # get_all_devices($file)
  225. #
  226. sub get_all_devices($) {
  227. my ($file) = @_;
  228. my @dev_list = ();
  229. my $part_config = XMLin($file, keyattr => { fsinfo => "+line" }, forcearray => 1 );
  230. foreach my $line (keys %{$part_config->{fsinfo}}) {
  231. if ($part_config->{fsinfo}->{$line}->{comment}) {
  232. next;
  233. }
  234. if ($part_config->{fsinfo}->{$line}->{real_dev}) {
  235. push @dev_list, $part_config->{fsinfo}->{$line}->{real_dev};
  236. }
  237. }
  238. my $fs_config = XMLin($file, keyattr => { disk => "+dev", part => "+num" }, forcearray => 1 );
  239. foreach my $key (keys %{$fs_config->{disk}}) {
  240. push @dev_list, $key;
  241. }
  242. return @dev_list;
  243. }
  244. # Description:
  245. # Returns a list of all disks from a given autoinstallscript.conf
  246. # file.
  247. #
  248. # Usage:
  249. # get_all_disks($file)
  250. #
  251. sub get_all_disks($) {
  252. my ($file) = @_;
  253. my @dev_list = ();
  254. my $fs_config = XMLin($file, keyattr => { disk => "+dev", part => "+num" }, forcearray => 1 );
  255. foreach my $key (keys %{$fs_config->{disk}}) {
  256. push @dev_list, $key;
  257. }
  258. return @dev_list;
  259. }
  260. # Description:
  261. # Convert standard /dev names to the corresponding devfs names.
  262. # In most cases this is not needed. However, there are a few cases
  263. # in which using devfsd symbolic links is not possible.
  264. #
  265. # An example of a case where this is necessary is the cpqarray driver.
  266. # The standard /dev file name includes /dev/ida/c0d0 for the disk,
  267. # while the devfs name it exports is /dev/ida/c0d0/disc. The overlapping
  268. # use of the /dev/ida/c0d0 name (in one case a file, and in another a
  269. # directory), makes it impossible for both sets of names to exist in the
  270. # same namespace.
  271. #
  272. # Usage:
  273. # dev_to_devfs( @disk_and_partition_list );
  274. #
  275. # returns a mapping of [standard /dev name] -> [devfs name] in a hash
  276. sub dev_to_devfs {
  277. my @devices = @_;
  278. my %table = ();
  279. foreach my $dev (@devices) {
  280. $table{$dev} = $dev;
  281. }
  282. return %table;
  283. }
  284. # Usage:
  285. # _read_partition_info_and_prepare_parted_commands( $out, $image_dir, $auto_install_script_conf );
  286. sub _read_partition_info_and_prepare_parted_commands {
  287. my ($out, $image_dir, $file) = @_;
  288. my $xml_config = XMLin($file, keyattr => { disk => "+dev", part => "+num" }, forcearray => 1 );
  289. my @all_devices = get_all_devices($file);
  290. my %devfs_map = dev_to_devfs(@all_devices) or return undef;
  291. #
  292. # Diagnostic output. -BEF-
  293. #
  294. #foreach my $dev (sort (keys ( %{$xml_config->{disk}} ))) {
  295. # print "Found disk: $dev.\n";
  296. #}
  297. #
  298. # Ok. Now that we've read all of the partition scheme info into hashes, let's do stuff with it. -BEF-
  299. #
  300. foreach my $dev (sort (keys ( %{$xml_config->{disk}} ))) {
  301. my $label_type = $xml_config->{disk}->{$dev}->{label_type};
  302. my (
  303. $highest_part_num,
  304. $highest_p_or_e_part_num,
  305. $m,
  306. $cmd,
  307. $part,
  308. $empty_partition_count,
  309. $remaining_empty_partitions,
  310. $MB_from_end_of_disk
  311. );
  312. my $devfs_dev = $devfs_map{$dev};
  313. $dev2disk{$devfs_dev} = "DISK".$disk_no++;
  314. print $out "if [ -z \$DISKORDER ] ; then\n";
  315. print $out " $dev2disk{$devfs_dev}=$devfs_dev\n";
  316. print $out "elif [ -z \$$dev2disk{$devfs_dev} ] ; then\n";
  317. print $out qq( echo "Undefined: $dev2disk{$devfs_dev}"\n);
  318. print $out " shellout\n";
  319. print $out "fi\n";
  320. $devfs_dev = '$'.$dev2disk{$devfs_dev};
  321. print $out "### BEGIN partition $devfs_dev ###\n";
  322. print $out qq(logmsg "Partitioning $devfs_dev..."\n);
  323. print $out qq(logmsg "Old partition table for $devfs_dev:"\n);
  324. print $out "parted -s -- $devfs_dev print\n\n";
  325. print $out "# Wipe the MBR (Master Boot Record) clean.\n";
  326. $cmd = "dd if=/dev/zero of=$devfs_dev bs=512 count=1 || shellout";
  327. print $out qq(logmsg "$cmd"\n);
  328. print $out "$cmd\n\n";
  329. print $out "# Re-read the disk label.\n";
  330. $cmd = "blockdev --rereadpt $devfs_dev";
  331. print $out qq(logmsg "$cmd"\n);
  332. print $out "$cmd\n\n";
  333. print $out "# Create disk label. This ensures that all remnants of the old label, whatever\n";
  334. print $out "# type it was, are removed and that we're starting with a clean label.\n";
  335. $cmd = "parted -s -- $devfs_dev mklabel $label_type || shellout";
  336. print $out qq(logmsg "$cmd"\n);
  337. print $out "$cmd\n\n";
  338. print $out "# Get the size of the destination disk so that we can make the partitions fit properly.\n";
  339. print $out qq(DISK_SIZE=`parted -s $devfs_dev unit MB print | grep 'Disk ' | sed 's/^.*\: //' | sed 's/MB//' `) . qq(\n);
  340. print $out q([ -z $DISK_SIZE ] && shellout) . qq(\n);
  341. print $out q(if [ "$ARCH" = "alpha" ]; then) . qq(\n);
  342. print $out q( END_OF_LAST_PRIMARY=1) . qq(\n);
  343. print $out q(else) . qq(\n);
  344. print $out q( END_OF_LAST_PRIMARY=0) . qq(\n);
  345. print $out q(fi) . qq(\n\n);
  346. ### BEGIN Populate the simple hashes. -BEF- ###
  347. my (
  348. %end_of_disk,
  349. %flags,
  350. %id,
  351. %p_type,
  352. %p_name,
  353. %size,
  354. %startMB,
  355. %endMB
  356. );
  357. my $unit_of_measurement = lc $xml_config->{disk}->{$dev}->{unit_of_measurement};
  358. ########################################################################
  359. #
  360. # Make sure the user specified 100% or less of the disk (if used). -BEF-
  361. # (may want to functionize these at some point)
  362. #
  363. ########################################################################
  364. if (("$unit_of_measurement" eq "%")
  365. or ("$unit_of_measurement" eq "percent")
  366. or ("$unit_of_measurement" eq "percentage")
  367. or ("$unit_of_measurement" eq "percentages")) {
  368. #
  369. # Primary partitions. -BEF-
  370. #
  371. my $p_sum = 0;
  372. foreach my $m (sort (keys ( %{$xml_config->{disk}->{$dev}->{part}} ))) {
  373. #
  374. # Skip over logical partitions. -BEF-
  375. #
  376. $_ = $xml_config->{disk}->{$dev}->{part}{$m}->{p_type};
  377. if ( $_ ne "primary" ) { next; }
  378. #
  379. # Skip over if size is end_of_disk (*) -- we can't measure that without the disk. -BEF-
  380. #
  381. $_ = $xml_config->{disk}->{$dev}->{part}{$m}->{size};
  382. if ( $_ eq "*" ) { next; }
  383. if (/[[:alpha:]]/) {
  384. print qq(FATAL: autoinstallscript.conf cannot contain "$_" as a percentage.\n);
  385. print qq( Disk: $dev, partition: $m\n);
  386. exit 1;
  387. }
  388. $p_sum += $_;
  389. }
  390. #
  391. # Extended partition. -BEF-
  392. #
  393. my $e_sum = 0;
  394. foreach my $m (sort (keys ( %{$xml_config->{disk}->{$dev}->{part}} ))) {
  395. $_ = $xml_config->{disk}->{$dev}->{part}{$m}->{p_type};
  396. if ( $_ ne "extended" ) { next; }
  397. #
  398. # Skip over if size is end_of_disk (we can't measure that without the disk.) -BEF-
  399. #
  400. $_ = $xml_config->{disk}->{$dev}->{part}{$m}->{size};
  401. if ( $_ eq "*" ) { next; }
  402. if (/[[:alpha:]]/) {
  403. print qq(FATAL: autoinstallscript.conf cannot contain "$_" as a percentage.\n);
  404. print qq( Disk: $dev, partition: $m\n);
  405. exit 1;
  406. }
  407. $e_sum += $_;
  408. }
  409. #
  410. # Logical partitions must not exceed percentage size of the extended partition. But
  411. # we only need to process this loop if an extended partition exists. -BEF-
  412. #
  413. my $l_sum = 0;
  414. if ($e_sum > 0) {
  415. foreach my $m (sort (keys ( %{$xml_config->{disk}->{$dev}->{part}} ))) {
  416. #
  417. # Skip over primary and extended partitions. -BEF-
  418. #
  419. $_ = $xml_config->{disk}->{$dev}->{part}{$m}->{p_type};
  420. unless ( $_ eq "logical" ) { next; }
  421. #
  422. # Skip over if size is end_of_disk (we can't measure that without the disk.) -BEF-
  423. #
  424. $_ = $xml_config->{disk}->{$dev}->{part}{$m}->{size};
  425. if ( $_ eq "*" ) { next; }
  426. if (/[[:alpha:]]/) {
  427. print qq(FATAL: autoinstallscript.conf cannot contain "$_" as a percentage.\n);
  428. print qq( Disk: $dev, partition: $m\n);
  429. exit 1;
  430. }
  431. $l_sum += $_;
  432. }
  433. }
  434. #
  435. # Produce error message if necessary. -BEF-
  436. #
  437. my $p_e_sum = $p_sum + $e_sum;
  438. if ($p_e_sum > 100) {
  439. print qq(FATAL: Your autoinstallscript.conf file specifies that "${p_e_sum}%" of your disk\n);
  440. print " should be partitioned. Ummm, I don't think you have that much disk. ;-)\n";
  441. exit 1;
  442. } elsif ($l_sum > 100) {
  443. print qq(FATAL: Your autoinstallscript.conf file specifies that "${l_sum}%" of your disk\n);
  444. print " should be partitioned. Ummm, I don't think you have that much disk. ;-)\n";
  445. exit 1;
  446. } elsif ($l_sum > $e_sum) {
  447. print qq(FATAL: Your autoinstallscript.conf file specifies that the sum of your logical\n);
  448. print qq(partitions should take up "${l_sum}%" of your disk but the extended partition,\n);
  449. print qq(in which the logical partitions must fit, is specified as only "${e_sum}%" of\n);
  450. print qq(your disk. Please modify and try again.\n);
  451. exit 1;
  452. }
  453. }
  454. ########################################################################
  455. #
  456. # Continue processing. -BEF-
  457. #
  458. ########################################################################
  459. my $end_of_last_primary = 0;
  460. my $end_of_last_logical;
  461. foreach my $m (sort (keys ( %{$xml_config->{disk}->{$dev}->{part}} ))) {
  462. $flags{$m} = $xml_config->{disk}->{$dev}->{part}{$m}->{flags};
  463. $id{$m} = $xml_config->{disk}->{$dev}->{part}{$m}->{id};
  464. $p_name{$m} = $xml_config->{disk}->{$dev}->{part}{$m}->{p_name};
  465. $p_type{$m} = $xml_config->{disk}->{$dev}->{part}{$m}->{p_type};
  466. $size{$m} = $xml_config->{disk}->{$dev}->{part}{$m}->{size};
  467. # Calculate $startMB and $endMB. -BEF-
  468. if ("$p_type{$m}" eq "primary") {
  469. $startMB{$m} = q($END_OF_LAST_PRIMARY);
  470. } elsif ("$p_type{$m}" eq "extended") {
  471. $startMB{$m} = q($END_OF_LAST_PRIMARY);
  472. } elsif ("$p_type{$m}" eq "logical") {
  473. $startMB{$m} = q($END_OF_LAST_LOGICAL);
  474. }
  475. if (("$unit_of_measurement" eq "mb")
  476. or ("$unit_of_measurement" eq "megabytes")) {
  477. $endMB{$m} = q#$(echo "scale=3; ($START_MB + # . qq#$size{$m})" | bc)#;
  478. } elsif (("$unit_of_measurement" eq "%")
  479. or ("$unit_of_measurement" eq "percent")
  480. or ("$unit_of_measurement" eq "percentage")
  481. or ("$unit_of_measurement" eq "percentages")) {
  482. $endMB{$m} = q#$(echo "scale=3; (# . qq#$startMB{$m}# . q# + ($DISK_SIZE * # . qq#$size{$m} / 100))" | bc)#;
  483. }
  484. }
  485. ### END Populate the simple hashes. -BEF- ###
  486. # Figure out what the highest partition number is. -BEF-
  487. foreach (sort { $a <=> $b } (keys ( %{$xml_config->{disk}->{$dev}->{part}} ))) {
  488. $highest_part_num = $_;
  489. }
  490. # Find out what the highest primary or extended partition number is.
  491. # This will help us prevent from creating unnecessary bogus partitions.
  492. # -BEF-
  493. #
  494. foreach my $m (sort (keys ( %{$xml_config->{disk}->{$dev}->{part}} ))) {
  495. unless (($p_type{$m} eq "primary") or ($p_type{$m} eq "extended")) { next; }
  496. $highest_p_or_e_part_num = $m;
  497. }
  498. ### BEGIN For empty partitions, change $endMB appropriately. -BEF- ###
  499. #
  500. $m = $highest_p_or_e_part_num;
  501. $empty_partition_count = 0;
  502. $MB_from_end_of_disk = 0;
  503. my %minors_to_remove;
  504. until ($m == 0) {
  505. unless ($endMB{$m}) {
  506. $empty_partition_count++;
  507. $endMB{$m} = '$(( $DISK_SIZE - ' . "$MB_from_end_of_disk" . ' ))';
  508. $MB_from_end_of_disk++;
  509. $startMB{$m} = '$(( $DISK_SIZE - ' . "$MB_from_end_of_disk" . ' ))';
  510. $MB_from_end_of_disk++;
  511. $p_type{$m} = "primary";
  512. $p_name{$m} = "-";
  513. $flags{$m} = "-";
  514. $minors_to_remove{$m} = 1; # This could be any value. -BEF-
  515. }
  516. $m--;
  517. }
  518. # For partitions that go to the end of the disk, tell $endMB to grow to end of disk. -BEF-
  519. foreach $m (keys %endMB) {
  520. if (($size{$m}) and ( $size{$m} eq "*" )) {
  521. $endMB{$m} = '$(( $DISK_SIZE - ' . "$MB_from_end_of_disk" . ' ))';
  522. }
  523. }
  524. ### END For empty partitions, change $endMB appropriately. -BEF- ###
  525. # Start out with a minor of 1. We iterate through all minors from one
  526. # to $highest_part_num, and fool parted by creating bogus partitions
  527. # where there are gaps in the partition numbers, then later removing them. -BEF-
  528. #
  529. $m = "0";
  530. until ($m > $highest_part_num) {
  531. $m++;
  532. # Skip over partitions we don't have data for. This is most likely to
  533. # occur in the case of an msdos disk label, with empty partitions
  534. # after an extended partition, but before logical partitions. -BEF-
  535. #
  536. unless ($endMB{$m}) { next; }
  537. ### Print partitioning commands. -BEF-
  538. print $out "\n";
  539. $part = &get_part_name($dev, $m);
  540. $part =~ /^(.*?)(p?\d+)$/;
  541. $part = "\${".$dev2disk{$1}."}".$2;
  542. $cmd = "Creating partition $part.";
  543. print $out qq(logmsg "$cmd"\n);
  544. print $out qq(START_MB=$startMB{$m}\n);
  545. print $out qq(END_MB=$endMB{$m}\n);
  546. my $swap = '';
  547. if ($flags{$m}) {
  548. if ($flags{$m} =~ /swap/) {
  549. $swap = 'linux-swap ';
  550. }
  551. }
  552. if($p_type{$m} eq "extended") {
  553. # When using parted, we end up with a Win95 extended type of
  554. # partition, which creates problems with some big HDD. So using
  555. # fdisk instead
  556. #$cmd = qq(parted -s -- $devfs_dev mkpart $p_type{$m} $swap) . q($START_MB $END_MB) . qq( || shellout);
  557. $cmd = "echo \"n\n" .
  558. "e\n" .
  559. "2\n" .
  560. "\n" .
  561. "\n" .
  562. "w\" | fdisk $devfs_dev";
  563. } else {
  564. #
  565. # parted *always* (except for extended partitions) requires that you
  566. # specify a filesystem type, even though it does nothing with it
  567. # with the "mkpart" command. -BEF-
  568. #
  569. $cmd = qq(parted -s -- $devfs_dev mkpart $p_type{$m} $swap) . q($START_MB $END_MB) . qq( || shellout);
  570. }
  571. #print $out qq(logmsg "$cmd"\n);
  572. print $out "$cmd\n";
  573. # Leave info behind for the next partition. -BEF-
  574. if ("$p_type{$m}" eq "primary") {
  575. print $out q(END_OF_LAST_PRIMARY=$END_MB) . qq(\n);
  576. } elsif ("$p_type{$m}" eq "extended") {
  577. print $out q(END_OF_LAST_PRIMARY=$END_MB) . qq(\n);
  578. print $out q(END_OF_LAST_LOGICAL=$START_MB) . qq(\n);
  579. } elsif ("$p_type{$m}" eq "logical") {
  580. print $out q(END_OF_LAST_LOGICAL=$END_MB) . qq(\n);
  581. }
  582. #
  583. # If $id is set for a partition, we invoke sfdisk to tag the partition
  584. # id appropriately. parted is lame (in the true sense of the word) in
  585. # this regard and is incapable of # adding an arbitrary id to a
  586. # partition. -BEF-
  587. #
  588. if ($id{$m}) {
  589. print $out qq(# Use sfdisk to change the partition id. parted is\n);
  590. print $out qq(# incapable of this particular operation.\n);
  591. print $out qq(sfdisk --change-id $devfs_dev $m $id{$m} \n);
  592. }
  593. # Name any partitions that need that kinda treatment.
  594. #
  595. # XXX Currently, we are assuming that no one is using a rediculously long name.
  596. # parted's output doesn't make it easy for us, and it is currently possible for
  597. # a long name to get truncated, and the rest would be considered flags.
  598. # Consider submitting a patch to parted that would print easily parsable output
  599. # with n/a values "-" and no spaces in the flags. -BEF-
  600. #
  601. if (
  602. ($label_type eq "gpt")
  603. and ($p_name{$m})
  604. and ($p_name{$m} ne "-")
  605. ) { # We're kinda assuming no one names their partitions "-". -BEF-
  606. $cmd = "parted -s -- $devfs_dev name $m $p_name{$m} || shellout\n";
  607. print $out "logmsg $cmd";
  608. print $out "$cmd";
  609. }
  610. ### Deal with flags for each partition. -BEF-
  611. if(($flags{$m}) and ($flags{$m} ne "-")) {
  612. # $flags{$m} will look something like "boot,lba,raid" or "boot" at this point.
  613. my @flags = split (/,/, $flags{$m});
  614. foreach my $flag (@flags) {
  615. # Parted 1.6.0 doesn't seem to want to tag gpt partitions with lba. Hmmm. -BEF-
  616. if (($flag eq "lba") and ($label_type eq "gpt")) { next; }
  617. # Ignore custom flag 'swap'. -AR-
  618. if ($flag eq "swap") { next; }
  619. $cmd = "parted -s -- $devfs_dev set $m $flag on || shellout\n";
  620. print $out "logmsg $cmd";
  621. print $out "$cmd";
  622. }
  623. }
  624. }
  625. # Kick the minors out. (remove temporary partitions) -BEF-
  626. foreach $m (keys %minors_to_remove) {
  627. print $out "\n# Gotta lose this one (${dev}${m}) to make the disk look right.\n";
  628. $cmd = "parted -s -- $devfs_dev rm $m || shellout";
  629. print $out qq(logmsg "$cmd"\n);
  630. print $out "$cmd\n";
  631. }
  632. print $out "\n";
  633. print $out qq(logmsg "New partition table for $devfs_dev:"\n);
  634. $cmd = "parted -s -- $devfs_dev print";
  635. print $out qq(logmsg "$cmd"\n);
  636. print $out "$cmd\n";
  637. print $out "### END partition $devfs_dev ###\n";
  638. print $out "\n";
  639. print $out "\n";
  640. }
  641. }
  642. # Usage:
  643. #
  644. # _read_partition_info_and_prepare_soft_raid_devs( $out, $image_dir, $auto_install_script_conf );
  645. #
  646. sub _read_partition_info_and_prepare_soft_raid_devs {
  647. my ($out, $image_dir, $file) = @_;
  648. # Load RAID modules.
  649. print $out qq(logmsg "Load software RAID modules."\n);
  650. print $out qq(modprobe linear\n);
  651. print $out qq(modprobe raid0\n);
  652. print $out qq(modprobe raid1\n);
  653. print $out qq(modprobe raid5\n);
  654. print $out qq(modprobe raid6\n);
  655. print $out qq(modprobe raid10\n);
  656. print $out qq(modprobe raid456\n);
  657. my $xml = XMLin($file, keyattr => { raid => "+name" }, forcearray => 1 );
  658. my @all_disks = reverse(get_all_disks($file));
  659. #
  660. # Create a lookup hash. Contents are like:
  661. # /dev/sda => DISK0
  662. #
  663. my %DISK_by_disk;
  664. my $i = 0;
  665. foreach my $disk (sort @all_disks) {
  666. $DISK_by_disk{$disk} = "DISK$i";
  667. $i++;
  668. }
  669. foreach my $md ( sort (keys %{$xml->{raid}}) ) {
  670. my @md_devices = split(/ /, $xml->{raid}->{$md}->{devices});
  671. my $devices;
  672. # Translate partitions in disk variables (disk autodetection compliant).
  673. foreach (@md_devices) {
  674. m/^(.*)(p?\d+)$/;
  675. my $disk = $1;
  676. my $part_no = $2;
  677. $devices .= '${' . $DISK_by_disk{$disk} . '}' . $part_no . ' ';
  678. }
  679. # yes | mdadm --create $name \
  680. # --chunk $chunk_size \
  681. # --level $raid_level \
  682. # --raid-devices $raid_devices \
  683. # --spare-devices ($total_devices - $raid_devices) \
  684. # $devices
  685. my $cmd = qq(yes | mdadm --create $md \\\n);
  686. $cmd .= qq( --auto yes \\\n);
  687. $cmd .= qq( --level $xml->{raid}->{$md}->{raid_level} \\\n) if($xml->{raid}->{$md}->{raid_level});
  688. $cmd .= qq( --raid-devices $xml->{raid}->{$md}->{raid_devices} \\\n) if($xml->{raid}->{$md}->{raid_devices});
  689. $cmd .= qq( --spare-devices $xml->{raid}->{$md}->{spare_devices} \\\n) if($xml->{raid}->{$md}->{spare_devices});
  690. if($xml->{raid}->{$md}->{rounding}) {
  691. $xml->{raid}->{$md}->{rounding} =~ s/K$//;
  692. $cmd .= qq( --rounding $xml->{raid}->{$md}->{rounding} \\\n);
  693. }
  694. $cmd .= qq( --layout $xml->{raid}->{$md}->{layout} \\\n) if($xml->{raid}->{$md}->{layout});
  695. if($xml->{raid}->{$md}->{chunk_size}) {
  696. $xml->{raid}->{$md}->{chunk_size} =~ s/K$//;
  697. $cmd .= qq( --chunk $xml->{raid}->{$md}->{chunk_size} \\\n);
  698. }
  699. $cmd .= qq( $devices\n);
  700. print $out "\nlogmsg \"$cmd\"";
  701. print $out "\n$cmd\n";
  702. }
  703. #XXX Do we want to
  704. # - re-create UUIDs?
  705. # - store partition vs.
  706. #
  707. # This is where we should create the /etc/mdadm/mdadm.conf file.
  708. #
  709. #XXX
  710. # - for DEVICE, we can literally list every device involved. Ie:
  711. # DEVICE /dev/sda1 /dev/sdb1 /dev/sdc1 etc...
  712. return 1;
  713. }
  714. # Usage:
  715. # _read_partition_info_and_prepare_pvcreate_commands( $out, $image_dir, $auto_install_script_conf );
  716. sub _read_partition_info_and_prepare_pvcreate_commands {
  717. my ($out, $image_dir, $file) = @_;
  718. my $xml_config = XMLin($file, keyattr => { disk => "+dev", part => "+num" }, forcearray => 1 );
  719. my @all_devices = get_all_devices($file);
  720. my %devfs_map = dev_to_devfs(@all_devices) or return undef;
  721. my $cmd;
  722. foreach my $dev (sort (keys ( %{$xml_config->{disk}} ))) {
  723. my (
  724. $highest_part_num,
  725. $m,
  726. $part,
  727. );
  728. my $devfs_dev = '$' . $dev2disk{$devfs_map{$dev}};
  729. ### BEGIN Populate the simple hashes. -BEF- ###
  730. my (
  731. %flags,
  732. %p_type,
  733. %p_name,
  734. );
  735. foreach my $m (sort (keys ( %{$xml_config->{disk}->{$dev}->{part}} ))) {
  736. $flags{$m} = $xml_config->{disk}->{$dev}->{part}{$m}->{flags};
  737. $p_name{$m} = $xml_config->{disk}->{$dev}->{part}{$m}->{p_name};
  738. $p_type{$m} = $xml_config->{disk}->{$dev}->{part}{$m}->{p_type};
  739. }
  740. # Figure out what the highest partition number is. -BEF-
  741. foreach (sort { $a <=> $b } (keys ( %{$xml_config->{disk}->{$dev}->{part}} ))) {
  742. $highest_part_num = $_;
  743. }
  744. $m = "0";
  745. until ($m >= $highest_part_num) {
  746. $m++;
  747. unless (defined($p_type{$m})) { next; }
  748. $part = &get_part_name($dev, $m);
  749. $part =~ /^(.*?)(p?\d+)$/;
  750. $part = "\${".$dev2disk{$1}."}".$2;
  751. # Extended partitions can't be used by LVM. -AR-
  752. if ("$p_type{$m}" eq "extended") { next; }
  753. ### Deal with LVM flag for each partition. -AR-
  754. if (($flags{$m}) and ($flags{$m} ne "-")) {
  755. my @flags = split (/,/, $flags{$m});
  756. foreach my $flag (@flags) {
  757. if ("$flag" eq "lvm") {
  758. # Get volume group for this patition -AR-
  759. my $vg_name = $xml_config->{disk}->{$dev}->{part}->{$m}->{lvm_group};
  760. unless (defined($vg_name)) {
  761. print "WARNING: LVM partition \"${dev}${m}\" is not assigned to any group!\n";
  762. next;
  763. }
  764. # Get the version of the LVM metadata to use -AR-
  765. foreach my $lvm (@{$xml_config->{lvm}}) {
  766. my $version = $lvm->{version};
  767. unless (defined($version)) {
  768. # Default => get LVM2 metadata type.
  769. $version = 2;
  770. }
  771. foreach my $lvm_group_name (@{$lvm->{lvm_group}}) {
  772. if ($lvm_group_name->{name} eq $vg_name) {
  773. $cmd = "Initializing partition $part for use by LVM.";
  774. print $out qq(logmsg "$cmd"\n);
  775. $cmd = "pvcreate -M${version} -ff -y $part || shellout";
  776. print $out qq(logmsg "$cmd"\n);
  777. print $out "$cmd\n";
  778. goto part_done;
  779. }
  780. }
  781. }
  782. }
  783. }
  784. part_done:
  785. }
  786. }
  787. }
  788. # Initialize software RAID volumes used for LVM (if present).
  789. my $xml = XMLin($file, keyattr => { raid => "+name" }, forcearray => 1 );
  790. foreach my $md ( sort (keys %{$xml->{raid}}) ) {
  791. my $vg_name = $xml->{raid}->{$md}->{lvm_group};
  792. unless ($vg_name) {
  793. next;
  794. }
  795. # Get the version of the LVM metadata to use.
  796. foreach my $lvm (@{$xml_config->{lvm}}) {
  797. my $version = $lvm->{version};
  798. unless (defined($version)) {
  799. # Default => get LVM2 metadata type.
  800. $version = 2;
  801. }
  802. foreach my $lvm_group_name (@{$lvm->{lvm_group}}) {
  803. if ($lvm_group_name->{name} eq $vg_name) {
  804. $cmd = "pvcreate -M${version} -ff -y $md || shellout";
  805. print $out qq(logmsg "$cmd"\n);
  806. print $out "$cmd\n";
  807. }
  808. }
  809. }
  810. }
  811. }
  812. # Usage:
  813. # write_lvm_groups_commands( $out, $image_dir, $auto_install_script_conf );
  814. sub write_lvm_groups_commands {
  815. my ($out, $image_dir, $file) = @_;
  816. my $xml_config = XMLin($file, keyattr => { lvm_group => "+name" }, forcearray => 1 );
  817. my $cmd;
  818. # Get all LVM blocks.
  819. foreach my $lvm (@{$xml_config->{lvm}}) {
  820. my @all_devices = get_all_devices($file);
  821. my %devfs_map = dev_to_devfs(@all_devices) or return undef;
  822. my $version = $lvm->{version};
  823. unless (defined($version)) {
  824. # Default => get LVM2 metadata type.
  825. $version = 2;
  826. }
  827. # Find the partitions assigned to each LVM group. -AR-
  828. foreach my $group_name (sort (keys ( %{$lvm->{lvm_group}} ))) {
  829. my $part_list = "";
  830. foreach my $disk (@{$xml_config->{disk}}) {
  831. my $dev = $disk->{dev};
  832. # Figure out what the highest partition number is. -AR-
  833. my $highest_part_num = 0;
  834. foreach my $part ( @{$disk->{part}} ) {
  835. my $num = $part->{num};
  836. if ($num > $highest_part_num) {
  837. $highest_part_num = $num;
  838. }
  839. }
  840. # Evaluate the partition list for the current LVM group -AR-
  841. my $m = "0";
  842. foreach my $part (@{$disk->{part}}) {
  843. $m++;
  844. unless (defined($part->{lvm_group})) { next; }
  845. if ($part->{lvm_group} eq $group_name) {
  846. if (defined($part->{num})) {
  847. $m = $part->{num};
  848. }
  849. my $part_name = &get_part_name($dev, $m);
  850. if ($part_name =~ /^(.*?)(p?\d+)$/) {
  851. $part_name = "\${".$dev2disk{$1}."}".$2;
  852. }
  853. $part_list .= " $part_name";
  854. }
  855. }
  856. }
  857. # Find RAID disks assigned to the volume group.
  858. my $xml = XMLin($file, keyattr => { raid => "+name" }, forcearray => 1 );
  859. foreach my $md ( sort (keys %{$xml->{raid}}) ) {
  860. my $vg_name = $xml->{raid}->{$md}->{lvm_group};
  861. unless ($vg_name) {
  862. next;
  863. }
  864. unless ($vg_name eq $group_name) {
  865. next;
  866. }
  867. $part_list .= " $md";
  868. }
  869. if ($part_list ne "") {
  870. # Evaluate the volume group options -AR-
  871. my $vg_max_log_vols = $lvm->{lvm_group}->{$group_name}->{max_log_vols};
  872. if (defined($vg_max_log_vols)) {
  873. $vg_max_log_vols = "-l $vg_max_log_vols ";
  874. } else {
  875. $vg_max_log_vols = "";
  876. }
  877. my $vg_max_phys_vols = $lvm->{lvm_group}->{$group_name}->{max_phys_vols};
  878. if (defined($vg_max_phys_vols)) {
  879. $vg_max_phys_vols = "-p $vg_max_phys_vols ";
  880. } else {
  881. $vg_max_phys_vols = "";
  882. }
  883. my $vg_phys_extent_size = $lvm->{lvm_group}->{$group_name}->{phys_extent_size};
  884. if (defined($vg_phys_extent_size)) {
  885. $vg_phys_extent_size = "-s $vg_phys_extent_size ";
  886. } else {
  887. $vg_phys_extent_size = "";
  888. }
  889. # Remove previous volume groups with $group_name if already present.
  890. $cmd = "lvremove -f /dev/${group_name} >/dev/null 2>&1 && vgremove $group_name >/dev/null 2>&1";
  891. print $out qq(logmsg "$cmd"\n);
  892. print $out "$cmd\n";
  893. # Write the command to create the volume group -AR-
  894. $cmd = "vgcreate -M${version} ${vg_max_log_vols}${vg_max_phys_vols}${vg_phys_extent_size}${group_name}${part_list} || shellout";
  895. print $out qq(logmsg "$cmd"\n);
  896. print $out "$cmd\n";
  897. } else {
  898. print "WARNING: LVM group \"$group_name\" doesn't have partitions!\n";
  899. }
  900. }
  901. }
  902. }
  903. # Usage:
  904. # write_lvm_volumes_commands( $out, $image_dir, $auto_install_script_conf );
  905. sub write_lvm_volumes_commands {
  906. my ($out, $image_dir, $file) = @_;
  907. my $xml_config = XMLin($file, keyattr => { lvm_group => "+name" }, forcearray => 1 );
  908. my $lvm = @{$xml_config->{lvm}}[0];
  909. unless (defined($lvm)) {
  910. return;
  911. }
  912. foreach my $group_name (sort (keys ( %{$lvm->{lvm_group}} ))) {
  913. foreach my $lv (@{$lvm->{lvm_group}->{$group_name}->{lv}}) {
  914. my $cmd;
  915. # Get logical volume name -AR-
  916. my $lv_name = $lv->{name};
  917. unless (defined($lv_name)) {
  918. print "WARNING: undefined logical volume name! skipping volume creation.\n";
  919. next;
  920. }
  921. # Get logical volume size -AR-
  922. my $lv_size = $lv->{size};
  923. unless (defined($lv_size)) {
  924. print "WARNING: undefined logical volume size! skipping volume creation.\n";
  925. next;
  926. }
  927. if ($lv_size eq '*') {
  928. $lv_size = '-l100%FREE';
  929. } else {
  930. $lv_size = '-L' . $lv_size;
  931. }
  932. # Get additional options (expressed in lvcreate format) -AR-
  933. my $lv_options = $lv->{lv_options};
  934. unless (defined($lv_options)) {
  935. $lv_options = "";
  936. }
  937. # Create the logical volume -AR-
  938. $cmd = "lvcreate $lv_options $lv_size -n $lv_name $group_name || shellout";
  939. print $out qq(logmsg "$cmd"\n);
  940. print $out "$cmd\n";
  941. # Enable the logical volume -AR-
  942. $cmd = "lvscan > /dev/null; lvchange -a y /dev/$group_name/$lv_name || shellout";
  943. print $out qq(logmsg "$cmd"\n);
  944. print $out "$cmd\n";
  945. }
  946. }
  947. }
  948. # Usage:
  949. # upgrade_partition_schemes_to_generic_style($image_dir, $config_dir);
  950. sub upgrade_partition_schemes_to_generic_style {
  951. my ($module, $image_dir, $config_dir) = @_;
  952. my $partition_dir = "$config_dir/partitionschemes";
  953. # Disk types ide and scsi are pretty self explanatory. Here are
  954. # some others: -BEF-
  955. # o rd is a dac960 device (mylex extremeraid is an example)
  956. # o ida is a compaq smartscsi device
  957. # o cciss is a compaq smartscsi device
  958. #
  959. my @disk_types = qw( . rd ida cciss ); # The . is for ide and scsi disks. -BEF-
  960. foreach my $type (@disk_types) {
  961. my $dir;
  962. if ($type eq ".") {
  963. $dir = $image_dir . "/" . $partition_dir;
  964. } else {
  965. $dir = $image_dir . "/" . $partition_dir . "/" . $type;
  966. }
  967. if(-d $dir) {
  968. opendir(DIR, $dir) || die "Can't read the $dir directory.";
  969. while(my $device = readdir(DIR)) {
  970. # Skip over any "dot" files. -BEF-
  971. #
  972. if ($device =~ /^\./) { next; }
  973. my $file = "$dir/$device";
  974. if (-f $file) {
  975. my $autoinstall_script_conf_file = $image_dir . "/" . $config_dir . "/autoinstallscript.conf";
  976. SystemImager::Common->save_partition_information($file, "old_sfdisk_file", $autoinstall_script_conf_file);
  977. }
  978. }
  979. close(DIR);
  980. }
  981. }
  982. }
  983. sub _get_array_of_disks {
  984. my ($image_dir, $config_dir) = @_;
  985. my @disks;
  986. # Disk types ide and scsi are pretty self explanatory. Here are
  987. # some others: -BEF-
  988. # o rd is a dac960 device (mylex extremeraid is an example)
  989. # o ida is a compaq smartscsi device
  990. # o cciss is a compaq smartscsi device
  991. #
  992. my @disk_types = qw(ide scsi rd ida cciss);
  993. my $partition_dir = "$config_dir/partitionschemes";
  994. foreach my $type (@disk_types) {
  995. my $dir = $image_dir . $partition_dir . "/" . $type;
  996. if(-d $dir) {
  997. opendir(DIR, $dir) || die "Can't read the $dir directory.";
  998. while(my $device = readdir(DIR)) {
  999. # Skip over any "dot" files. -BEF-
  1000. if ($device =~ /^\./) { next; }
  1001. # Only process regular files.
  1002. if (-f "$dir/$device") {
  1003. # Keep the device name and directory.
  1004. push @disks, "$type/$device";
  1005. }
  1006. }
  1007. close(DIR);
  1008. }
  1009. }
  1010. return @disks;
  1011. }
  1012. # Description:
  1013. # Read configuration information from /etc/systemimager/autoinstallscript.conf
  1014. # and write filesystem creation commands to the autoinstall script. -BEF-
  1015. #
  1016. # Usage:
  1017. # _write_out_mkfs_commands( $out, $image_dir,
  1018. # $auto_install_script_conf, $raid);
  1019. #
  1020. sub _write_out_mkfs_commands {
  1021. my ($out, $image_dir, $file) = @_;
  1022. my $xml_config = XMLin($file, keyattr => { fsinfo => "+line" }, forcearray => 1 );
  1023. my @all_devices = get_all_devices($file);
  1024. my %devfs_map = dev_to_devfs(@all_devices) or return undef;
  1025. my @d2dkeys = reverse sort keys %dev2disk;
  1026. # Figure out if software RAID is in use. -BEF-
  1027. #
  1028. my $software_raid;
  1029. foreach my $line (sort numerically (keys ( %{$xml_config->{fsinfo}} ))) {
  1030. # If this line is a comment, skip over. -BEF-
  1031. if ( $xml_config->{fsinfo}->{$line}->{comment} ) { next; }
  1032. # If real_dev isn't set, move on. -BEF-
  1033. unless ($xml_config->{fsinfo}->{$line}->{real_dev}) { next; }
  1034. my $real_dev = $xml_config->{fsinfo}->{$line}->{real_dev};
  1035. if ($real_dev =~ /\/dev\/md/) {
  1036. $software_raid = "true";
  1037. }
  1038. }
  1039. # The $part_type here is used to find and create all the swap partitions
  1040. # before the other filesystems. This reduces the probability to have a OOM
  1041. # condition during the filesystem creation.
  1042. foreach my $part_type (0, 1) {
  1043. foreach my $line (sort numerically (keys (%{$xml_config->{fsinfo}}))) {
  1044. my $cmd = "";
  1045. # If this line is a comment, skip over. -BEF-
  1046. if ( $xml_config->{fsinfo}->{$line}->{comment} ) { next; }
  1047. # If real_dev isn't set, move on. -BEF-
  1048. unless ($xml_config->{fsinfo}->{$line}->{real_dev}) { next; }
  1049. # If format="no" is set, then skip over this one. -BEF-
  1050. my $format = $xml_config->{fsinfo}->{$line}->{format};
  1051. if (($format) and ( "$format" eq "no")) { next; }
  1052. # mount_dev should contain fs LABEL or UUID information. -BEF-
  1053. my $mount_dev = $xml_config->{fsinfo}->{$line}->{mount_dev};
  1054. my $real_dev = $devfs_map{$xml_config->{fsinfo}->{$line}->{real_dev}};
  1055. my $mp = $xml_config->{fsinfo}->{$line}->{mp};
  1056. my $fs = $xml_config->{fsinfo}->{$line}->{fs};
  1057. my $options = $xml_config->{fsinfo}->{$line}->{options};
  1058. my $mkfs_opts = $xml_config->{fsinfo}->{$line}->{mkfs_opts};
  1059. unless ($mkfs_opts) { $mkfs_opts = ""; }
  1060. # Remove options that may cause problems and are unnecessary during
  1061. # the install.
  1062. $options = _remove_mount_option($options, "errors=remount-ro");
  1063. # Deal with filesystems to be mounted read only (ro) after install.
  1064. # We still need to write to them to install them. ;)
  1065. $options =~ s/\bro\b/rw/g;
  1066. $options =~ s/\bnoauto\b/defaults/g;
  1067. # software RAID devices (/dev/md*)
  1068. if ($real_dev =~ /\/dev\/md/) {
  1069. print $out qq(mkraid --really-force $real_dev || shellout\n)
  1070. unless (defined($xml_config->{raid}));
  1071. } elsif( $real_dev =~ /^(.*?)(p?\d+)$/ ) {
  1072. if ($dev2disk{$1}) {
  1073. $real_dev = "\${".$dev2disk{$1}."}".$2;
  1074. }
  1075. }
  1076. # First of all look for swap partitions only.
  1077. if ($part_type == 0) {
  1078. # swap
  1079. if ( $xml_config->{fsinfo}->{$line}->{fs} eq "swap" ) {
  1080. # create swap
  1081. # FIXME!!! mkswap is creating problems at the moment (do not know why)
  1082. $cmd = "# mkswap -v1 $real_dev";
  1083. # add swap label if necessary
  1084. if ($mount_dev) {
  1085. if( $mount_dev =~ /^LABEL=(.*)/ ){
  1086. $cmd .= " -L $1";
  1087. }
  1088. }
  1089. $cmd .= " || shellout";
  1090. print $out qq(logmsg "$cmd"\n);
  1091. print $out "$cmd\n";
  1092. # swapon
  1093. # FIXME!!! Since mkswap is not executed, we do not execute swapon
  1094. $cmd = "# swapon $real_dev || shellout";
  1095. print $out qq(logmsg "$cmd"\n);
  1096. print $out "$cmd\n";
  1097. print $out "\n";
  1098. }
  1099. next;
  1100. }
  1101. # OK, now that swap partitions commands have been written to the
  1102. # autoinstall script, proceed with the other filesystems.
  1103. # msdos or vfat
  1104. if (($xml_config->{fsinfo}->{$line}->{fs} eq "vfat") or
  1105. ($xml_config->{fsinfo}->{$line}->{fs} eq "msdos")) {
  1106. # create fs
  1107. $cmd = "mkdosfs $mkfs_opts -v $real_dev || shellout";
  1108. print $out qq(logmsg "$cmd"\n);
  1109. print $out "$cmd\n";
  1110. # mkdir
  1111. $cmd = "mkdir -p /a$mp || shellout";
  1112. print $out qq(logmsg "$cmd"\n);
  1113. print $out "$cmd\n";
  1114. # mount
  1115. $cmd = "mount $real_dev /a$mp -t $fs || shellout";
  1116. print $out qq(logmsg "$cmd"\n);
  1117. print $out "$cmd\n";
  1118. print $out "\n";
  1119. # ext2
  1120. } elsif ( $xml_config->{fsinfo}->{$line}->{fs} eq "ext2" ) {
  1121. # create fs
  1122. $cmd = "mke2fs -q $real_dev || shellout";
  1123. print $out qq(logmsg "$cmd"\n);
  1124. print $out "$cmd\n";
  1125. if ($mount_dev) {
  1126. # add LABEL if necessary
  1127. if ($mount_dev =~ /LABEL=/) {
  1128. my $label = $mount_dev;
  1129. $label =~ s/LABEL=//;
  1130. $cmd = "tune2fs -L $label $real_dev";
  1131. print $out qq(logmsg "$cmd"\n);
  1132. print $out "$cmd\n";
  1133. }
  1134. # add UUID if necessary
  1135. if ($mount_dev =~ /UUID=/) {
  1136. my $uuid = $mount_dev;
  1137. $uuid =~ s/UUID=//;
  1138. $cmd = "tune2fs -U $uuid $real_dev";
  1139. print $out qq(logmsg "$cmd"\n);
  1140. print $out "$cmd\n";
  1141. }
  1142. }
  1143. # mkdir
  1144. $cmd = "mkdir -p /a$mp || shellout";
  1145. print $out qq(logmsg "$cmd"\n);
  1146. print $out "$cmd\n";
  1147. # mount
  1148. # FIXME!!! we explicitely remove the mount options because it
  1149. # includes an invalid option (new version of mount), and
  1150. # cannot figure out how to do this properly
  1151. #$cmd = "mount $real_dev /a$mp -t $fs -o $options || shellout";
  1152. $cmd = "mount $real_dev /a$mp -t $fs || shellout";
  1153. print $out qq(logmsg "$cm…

Large files files are truncated, but you can click here to view the full file