diff --git a/html/skins/alteeve/pxe.txt b/html/skins/alteeve/pxe.txt
index dd45d572..f1cbaf21 100644
--- a/html/skins/alteeve/pxe.txt
+++ b/html/skins/alteeve/pxe.txt
@@ -44,7 +44,7 @@ eula --agreed
firstboot --disable
# Reboot when the install is done.
-reboot
+#reboot
# Install from the source Striker
url --url=#!variable!url!#
@@ -128,7 +128,7 @@ rsync -av /var/log /mnt/sysimage/root/install_logs/var/
# 1 - Target type not specified.
# 2 - Failed to find a drive to install on.
#
-# NOTE: This is restricted to what is available during an anaconda install session. That is to same, bare
+# NOTE: This is restricted to what is available during an anaconda install session. That is to say, bare
# minimum.
# TODO: If multiple matching drives are found (same medium and size, build an appropriate RAID array.
# TODO: in pre, wipefs on all disks to clear old LVM and DRBD data
@@ -140,32 +140,42 @@ use warnings;
# Set to '1' for verbose output
my $debug = #!variable!debug!#;
-### NOTE: This must be set to 'striker', 'node' or 'dr' when incorporated into a kickstart %pre script!
+### NOTE: This must be set to 'striker', 'node' or 'dr'! Wither set '$type' or use the appropriate argument.
my $type = "#!variable!type!#";
+if ((defined $ARGV[0]) && ((lc($ARGV[0]) eq "striker") or (lc($ARGV[0]) eq "node") or (lc($ARGV[0]) eq "dr")))
+{
+ $type = $ARGV[0];
+}
if ($type =~ /striker/i)
{
- print "#!string!message_0103!#\n";
+ print "-=] Finding install drive(s) for a Striker dashboard.\n";
$type = "striker";
}
elsif ($type =~ /node/i)
{
- print "#!string!message_0104!#\n";
+ print "-=] Finding install drive(s) for an Anvil! node.\n";
$type = "node";
}
elsif ($type =~ /dr/i)
{
- print "#!string!message_0105!#\n";
+ print "-=] Finding install drive(s) for a DR (disaster recovery) host.\n";
$type = "dr";
}
else
{
- print "#!string!message_0106!#\n";
+ print "
+[ Error ] - Target type not specified!
+
+Usage: ".$0." {striker,node,dr}
+
+";
exit(1);
}
my $device = {};
# We might want to add HCTL (Host:Channel:Target:Lun for SCSI) and/or SUBSYSTEMS later
+my $drives = {};
my $target = "";
my $lsblk = system_call("/bin/lsblk --bytes --paths --pairs --output NAME,RM,HOTPLUG,TYPE,SIZE,TRAN,ROTA");
foreach my $line (split/\n/, $lsblk)
@@ -186,14 +196,30 @@ foreach my $line (split/\n/, $lsblk)
transport => $transport,
rotational => $rotational,
};
+ my $hr_size = hr_size($device->{$path}{size});
+ $device->{$path}{hr_size} = $hr_size;
+
if ($device->{$path}{rotational})
{
- print "#!string!message_0107!#\n";
+ if (not $device->{$path}{transport})
+ {
+ print "Analyzing platter or virtual drive: [".$path."] of the size: [".$device->{$path}{size}." (".$device->{$path}{hr_size}.")]\n";
+ }
+ else
+ {
+ print "Analyzing platter drive: [".$path."], using the transport: [".$device->{$path}{transport}."], of the size: [".$device->{$path}{size}." (".$device->{$path}{hr_size}.")]\n";
+ }
}
else
{
- print "#!string!message_0108!#\n";
+ print "Analyzing solid-state drive: [".$path."], using the transport: [".$device->{$path}{transport}."], of the size: [".$device->{$path}{size}." (".$device->{$path}{hr_size}.")]\n";
+ }
+
+ if (not exists $drives->{by_hr_size}{$hr_size})
+ {
+ $drives->{by_hr_size}{$hr_size} = [];
}
+ push @{$drives->{by_hr_size}{$hr_size}}, $path;
}
### Usage selection priority
@@ -215,7 +241,7 @@ if ($type eq "striker")
}
if ($use_drive)
{
- print "#!string!message_0109!#\n";
+ print "Selected the largest disk: [".$use_drive."], which has a capacity of: [".hr_size($device->{$use_drive}{size})."]\n";
}
}
else
@@ -281,11 +307,11 @@ else
{
if ($selected_is_platter)
{
- print "#!string!message_0110!#\n";
+ print "Selected the smallest platter drive: [".$use_drive."], which has a capacity of: [".hr_size($device->{$use_drive}{size})."]\n";
}
else
{
- print "#!string!message_0111!#\n";
+ print "Selected the smallest solid-state drive: [".$use_drive."], which has a capacity of: [".hr_size($device->{$use_drive}{size})."] (no platter drives found)\n";
}
}
}
@@ -293,7 +319,7 @@ else
# Did we find a disk to use?
if (not $use_drive)
{
- print "#!string!message_0112!#\n";
+ print "[ Error ] - Failed to find any fixed drives (platter or USB, not removable) to install onto. Unable to proceed.\n";
exit(2);
}
@@ -322,29 +348,194 @@ if ((-e "/sys/class/dmi/id/product_uuid") && (-r "/sys/class/dmi/id/product_uuid
}
}
-# Finally, we've got our output.
-my $say_grow = $type eq "striker" ? "--grow " : "";
-my $vg_name = $type."_".$id;
+### NOTE: RAID 0 is not RAID (literally or in this case). So '0' means 'no raid'
+# If I have 2+ drives of the same size as 'use_drive', I will create a RAID array.
+my $raid_level = 0;
+my $hr_size = $device->{$use_drive}{hr_size};
+my $count = @{$drives->{by_hr_size}{$hr_size}};
+print __LINE__."; [ Debug ] - Drives of size: [".$hr_size."]: [".$count."].\n" if $debug;
+if ($count == 0)
+{
+ $raid_level = 0;
+}
+elsif ($count == 2)
+{
+ $raid_level = 1;
+}
+elsif ($count == 4)
+{
+ $raid_level = 10;
+}
+elsif (($count == 3) or ($count == 5))
+{
+ $raid_level = 5;
+}
+elsif ($count > 5)
+{
+ $raid_level = 6;
+}
+
+my $say_use_drive = $use_drive;
+if (not $raid_level)
+{
+ print "Building a standard partition layout for: [".$use_drive."] which is: [".$hr_size."]\n";
+}
+else
+{
+ print "Building a software RAID level: [".$raid_level."] array using the: [".$count."x] [".$hr_size."] drives;\n";
+ $say_use_drive = "";
+ foreach my $path (sort {$a cmp $b} @{$drives->{by_hr_size}{$hr_size}})
+ {
+ print "- ".$path."\n";
+ $say_use_drive .= $path.",";
+ }
+ $say_use_drive =~ s/,$//;
+}
+
+### NOTE: kickstart sizes are in MiB
+# Prepare some variables
+my $swap_size = 8192;
+my $root_size = 0;
+my $vg_name = $type."_".$id;
+
+# If this machine has a small size, we'll cut back the swap and root sizes.
+my $per_disk_space = sprintf("%.2f", ($device->{$use_drive}{size} /= (2 ** 20)));
+my $available_space = $per_disk_space;
+print __LINE__."; [ Debug ] - per_disk_space: [".$per_disk_space." (".hr_size($per_disk_space * (2**20)).")], available_space: [".$available_space." (".hr_size($available_space * (2**20)).")]\n" if $debug;
+if ($raid_level == 10)
+{
+ # Total == 2 x single disk
+ $available_space *= 2;
+ print __LINE__."; [ Debug ] - available_space: [".$available_space."]\n" if $debug;
+}
+elsif ($raid_level == 5)
+{
+ # Total == count x Disks - 1
+ $available_space = ($per_disk_space * $count) - $per_disk_space;
+ print __LINE__."; [ Debug ] - available_space: [".$available_space."]\n" if $debug;
+}
+elsif ($raid_level == 6)
+{
+ # Total == count x Disks - 2
+ $available_space = ($per_disk_space * $count) - ($per_disk_space * 2);
+ print __LINE__."; [ Debug ] - available_space: [".$available_space."]\n" if $debug;
+}
+
+# Now, how much space is available after taking some for BIOSBOOT and /boot ?
+$available_space -= 2;
+print __LINE__."; [ Debug ] - available_space: [".$available_space." (".hr_size($available_space * (2**20)).")]\n" if $debug;
+if ($available_space < 40960)
+{
+ # Not enough space for the standard layout.
+ $swap_size = 4096;
+ print __LINE__."; [ Debug ] - swap_size: [".$swap_size."]\n" if $debug;
+}
+
+# The left over space is for '/' (we'll shorten this up to 40GiB for nodes and DR hosts next)
+$root_size = $available_space - $swap_size;
+print __LINE__."; [ Debug ] - root_size: [".$root_size."]\n" if $debug;
+
+print __LINE__."; [ Debug ] - type: [".$type."], root_size: [".$root_size."]\n" if $debug;
+if (($type ne "striker") && ($root_size > 40960))
+{
+ $root_size = 40960;
+ print __LINE__."; [ Debug ] - root_size: [".$root_size."]\n" if $debug;
+}
+
+# Round down to an event integer.
+$root_size =~ s/\.\d+$//;
+print __LINE__."; Assigning: [".hr_size($swap_size * (2**20))." (".$swap_size." MiB)], root_size: [".hr_size($root_size * (2**20))." (".$root_size.") MiB]\n" if $debug;
+
+# Build the partition file.
my $partition_file = "/tmp/plan_partitions.out";
-my $partition_body = "zerombr
-clearpart --all --drives=".$use_drive."
-ignoredisk --only-use=".$use_drive."
-bootloader --location=mbr --driveorder=".$use_drive." --boot-drive=".$use_drive."
+my $partition_body = "
+clearpart --all --drives=".$say_use_drive."
+ignoredisk --only-use=".$say_use_drive."
+bootloader --location=mbr --driveorder=".$say_use_drive." --boot-drive=".$use_drive;
+if (not $raid_level)
+{
+ # Finally, we've got our output.
+ $partition_body .= "
# Partitions
-part biosboot --fstype=biosboot --size=1
-part /boot --fstype=ext4 --size=1024 --asprimary --ondisk=".$use_drive."
-part pv.01 --fstype=lvmpv --size=100 --asprimary --ondisk=".$use_drive." --grow
+part biosboot --fstype=biosboot --size=2
+part pv.01 --fstype=lvmpv --size=100 --ondisk=".$use_drive." --grow
# LVM Volume groups
volgroup ".$vg_name." --pesize=4096 pv.01
# LVM logical volumes
-logvol swap --fstype=swap --size=8188 --name=lv_swap --vgname=".$vg_name."
-logvol / --fstype=xfs --size=40960 --name=lv_root --vgname=".$vg_name." ".$say_grow."
+logvol swap --fstype=swap --size=".$swap_size." --name=lv_swap --vgname=".$vg_name."
+logvol / --fstype=xfs --size=".$root_size." --name=lv_root --vgname=".$vg_name."
+";
+}
+else
+{
+ $partition_body .= "
+# LVM PV
+";
+ my $say_raid = "";
+ for (my $i = 0; $i < $count; $i++)
+ {
+ my $disk_number = $i + 1;
+ $partition_body .= "part raid.1".$disk_number." --size 100 --grow --ondisk=".$drives->{by_hr_size}{$hr_size}->[$i]."\n";
+ $say_raid .= "raid.1".$disk_number." ";
+ }
+ $partition_body .= "raid pv.01 --fstype=xfs --device=pv.01 --level=RAID".$raid_level." ".$say_raid."
+
+# LVM Volume groups
+volgroup ".$vg_name." pv.01
+
+# LVM logical volumes
+logvol swap --fstype=swap --size=".$swap_size." --name=lv_swap --vgname=".$vg_name."
+logvol / --fstype=xfs --size=".$root_size." --name=lv_root --vgname=".$vg_name."
";
-print __LINE__."; [ Debug ] - partition_body: [".$partition_body."]\n" if $debug;
-print "#!string!message_0113!#\n";
+}
+
+=cut
+# Wipe out the start of each disk and make it a GPT labelled disk.
+# See: https://access.redhat.com/solutions/55652
+foreach my $path (split/,/, $say_use_drive)
+{
+ print "[ NOTE ] - Wiping the boot sector of: [".$path."] and configuring it for a GPT label.\n";
+ my $dd_out = system_call("/bin/dd bs=5120 count=1 if=/dev/zero of=".$path." oflag=dsync");
+ print __LINE__."; [ Debug ] - dd output:
+================================================================================
+".$dd_out."
+================================================================================\n" if $debug;
+ my $parted_out1 = system_call("/sbin/parted --script ".$path." mklabel gpt");
+ print __LINE__."; [ Debug ] - parted mklabel output
+================================================================================
+".$parted_out1."
+================================================================================\n" if $debug;
+ my $parted_out2 = system_call("/sbin/parted --script ".$path." print free");
+ print __LINE__."; [ Debug ] - parted print output showing new layout.
+================================================================================
+".$parted_out2."
+================================================================================\n" if $debug;
+ my $partprobe_out = system_call("/sbin/partprobe --summary ".$path);
+ print __LINE__."; [ Debug ] - partprobe summary.
+================================================================================
+".$partprobe_out."
+================================================================================\n" if $debug;
+ my $partx_out = system_call("/sbin/partx --update --verbose ".$path);
+ print __LINE__."; [ Debug ] - parted print output showing new layout.
+================================================================================
+".$partx_out."
+================================================================================\n" if $debug;
+}
+# Flush things out. The article says to blindly sleep 30, but it says to do so to make sure udev, partx and
+# others have updated. We're forcing the issue, which should be faster and safer.
+system_call("/sbin/udevadm settle");
+system_call("/bin/sync");
+=cut
+
+# Write out the file.
+print __LINE__."; [ Debug ] - partition_body:
+================================================================================
+".$partition_body."
+================================================================================\n";
+print "Writing out the partition plan to: [".$partition_file."]\n";
# Write it to the temp file that the kickstart's %include will look for.
my $shell_call = $partition_file;
@@ -352,7 +543,7 @@ print __LINE__."; [ Debug ] - shell_call: [".$shell_call."]\n" if $debug;
open (my $file_handle, ">", $shell_call) or die "Failed to write: [".$shell_call."], the error was: ".$!."\n";
print $file_handle $partition_body;
close $file_handle;
-print "#!string!message_0114!#\n";
+print "Completed successfully, exiting.\n";
# We're done.
exit(0);
@@ -489,7 +680,7 @@ TEXT HELP
ENDTEXT
kernel fedora28/vmlinuz
# NOTE: add ' rd.debug' below for debugging
-append initrd=fedora28/initrd.img root=live:#!variable!base_url!#/os/images/install.img inst.stage2=#!variable!base_url!#/os/ ip=dhcp inst.ks=#!variable!base_url!#/kickstart/striker.ks inst.sshd
+append initrd=fedora28/initrd.img root=live:#!variable!base_url!#/os/images/install.img inst.stage2=#!variable!base_url!#/os/ ip=dhcp inst.ks=#!variable!base_url!#/kickstart/striker.ks inst.gpt inst.sshd
label node
menu label #!string!message_0086!#
@@ -497,7 +688,7 @@ TEXT HELP
#!string!message_0087!#
ENDTEXT
kernel fedora28/vmlinuz
-append initrd=fedora28/initrd.img root=live:#!variable!base_url!#/os/images/install.img inst.stage2=#!variable!base_url!#/os/ ip=dhcp inst.ks=#!variable!base_url!#/kickstart/node.ks inst.sshd
+append initrd=fedora28/initrd.img root=live:#!variable!base_url!#/os/images/install.img inst.stage2=#!variable!base_url!#/os/ ip=dhcp inst.ks=#!variable!base_url!#/kickstart/node.ks inst.gpt inst.sshd
label node
menu label #!string!message_0088!#
@@ -505,7 +696,7 @@ TEXT HELP
#!string!message_0089!#
ENDTEXT
kernel fedora28/vmlinuz
-append initrd=fedora28/initrd.img root=live:#!variable!base_url!#/os/images/install.img inst.stage2=#!variable!base_url!#/os/ ip=dhcp inst.ks=#!variable!base_url!#/kickstart/dr.ks inst.sshd
+append initrd=fedora28/initrd.img root=live:#!variable!base_url!#/os/images/install.img inst.stage2=#!variable!base_url!#/os/ ip=dhcp inst.ks=#!variable!base_url!#/kickstart/dr.ks inst.gpt inst.sshd
label rescue
menu label #!string!message_0090!#
@@ -513,7 +704,7 @@ TEXT HELP
#!string!message_0091!#
ENDTEXT
kernel fedora28/vmlinuz
-append initrd=fedora28initrd.img ip=dhcp root=live:#!variable!base_url!#/os/LiveOS/squashfs.img rescue
+append initrd=fedora28/initrd.img ip=dhcp root=live:#!variable!base_url!#/os/LiveOS/squashfs.img rescue inst.repo=#!variable!base_url!#/os/ ip=dhcp inst.sshd
label fedora
menu label #!string!message_0092!#
@@ -521,7 +712,7 @@ TEXT HELP
#!string!message_0093!#
ENDTEXT
kernel fedora28/vmlinuz
-append initrd=fedora28/initrd.img root=live:#!variable!base_url!#/os/images/install.img
+append initrd=fedora28/initrd.img root=live:#!variable!base_url!#/os/images/install.img inst.repo=#!variable!base_url!#/os/ ip=dhcp inst.gpt inst.sshd
label next
menu default
diff --git a/notes b/notes
index b0f1c2c4..80aef190 100644
--- a/notes
+++ b/notes
@@ -56,6 +56,9 @@ firewall-cmd --zone=BCN1 --change-interface=bcn1_bond1
# Set the IFN as the default zone (as that is what will most likely be edited by a user)
firewall-cmd --set-default-zone=IFN1
+# Allow tftpd
+firewall-cmd --zone=BCN1 --add-service=tftp --permanent
+
# Allow routing/masq'ing through the IFN1 (provide net access to the BCN)
firewall-cmd --zone=IFN1 --add-masquerade
@@ -76,6 +79,8 @@ firewall-cmd --permanent --add-service=postgresql
firewall-cmd --reload
firewall-cmd --state [running (rc: 0),not running (rc:252)]
+firewall-cmd --zone=BCN1 --add-service=tftp
+
Ports we care about
diff --git a/scripts/plan_partitions b/scripts/plan_partitions
index 5efda293..c635c44b 100755
--- a/scripts/plan_partitions
+++ b/scripts/plan_partitions
@@ -8,7 +8,7 @@
# 1 - Target type not specified.
# 2 - Failed to find a drive to install on.
#
-# NOTE: This is restricted to what is available during an anaconda install session. That is to same, bare
+# NOTE: This is restricted to what is available during an anaconda install session. That is to say, bare
# minimum.
# TODO: If multiple matching drives are found (same medium and size, build an appropriate RAID array.
# TODO: in pre, wipefs on all disks to clear old LVM and DRBD data
@@ -20,29 +20,34 @@ use warnings;
# Set to '1' for verbose output
my $debug = 0;
-### NOTE: This must be set to 'striker', 'node' or 'dr' when incorporated into a kickstart %pre script!
+### NOTE: This must be set to 'striker', 'node' or 'dr'! Wither set '$type' or use the appropriate argument.
my $type = "";
+if ((defined $ARGV[0]) && ((lc($ARGV[0]) eq "striker") or (lc($ARGV[0]) eq "node") or (lc($ARGV[0]) eq "dr")))
+{
+ $type = $ARGV[0];
+}
if ($type =~ /striker/i)
{
- print "Finding install drive for a Striker dashboard.\n";
+ print "-=] Finding install drive(s) for a Striker dashboard.\n";
$type = "striker";
}
elsif ($type =~ /node/i)
{
- print "Finding install drive for an Anvil! node.\n";
+ print "-=] Finding install drive(s) for an Anvil! node.\n";
$type = "node";
}
elsif ($type =~ /dr/i)
{
- print "Finding install drive for a DR (disaster recovery) host.\n";
+ print "-=] Finding install drive(s) for a DR (disaster recovery) host.\n";
$type = "dr";
}
else
{
print "
-Error: Target type not specified.
-Be sure that '\$type' is set to 'striker', 'node' or 'dr' in the \%pre section
-of the kickstart script
+[ Error ] - Target type not specified!
+
+Usage: ".$0." {striker,node,dr}
+
";
exit(1);
}
@@ -50,6 +55,7 @@ of the kickstart script
my $device = {};
# We might want to add HCTL (Host:Channel:Target:Lun for SCSI) and/or SUBSYSTEMS later
+my $drives = {};
my $target = "";
my $lsblk = system_call("/bin/lsblk --bytes --paths --pairs --output NAME,RM,HOTPLUG,TYPE,SIZE,TRAN,ROTA");
foreach my $line (split/\n/, $lsblk)
@@ -70,14 +76,30 @@ foreach my $line (split/\n/, $lsblk)
transport => $transport,
rotational => $rotational,
};
+ my $hr_size = hr_size($device->{$path}{size});
+ $device->{$path}{hr_size} = $hr_size;
+
if ($device->{$path}{rotational})
{
- print "Analyzing platter drive: [".$path."], using the transport: [".$device->{$path}{transport}."], of the size: [".$device->{$path}{size}." (".hr_size($device->{$path}{size}).")]\n";
+ if (not $device->{$path}{transport})
+ {
+ print "Analyzing platter or virtual drive: [".$path."] of the size: [".$device->{$path}{size}." (".$device->{$path}{hr_size}.")]\n";
+ }
+ else
+ {
+ print "Analyzing platter drive: [".$path."], using the transport: [".$device->{$path}{transport}."], of the size: [".$device->{$path}{size}." (".$device->{$path}{hr_size}.")]\n";
+ }
}
else
{
- print "Analyzing solid-state drive: [".$path."], using the transport: [".$device->{$path}{transport}."], of the size: [".$device->{$path}{size}." (".hr_size($device->{$path}{size}).")]\n";
+ print "Analyzing solid-state drive: [".$path."], using the transport: [".$device->{$path}{transport}."], of the size: [".$device->{$path}{size}." (".$device->{$path}{hr_size}.")]\n";
}
+
+ if (not exists $drives->{by_hr_size}{$hr_size})
+ {
+ $drives->{by_hr_size}{$hr_size} = [];
+ }
+ push @{$drives->{by_hr_size}{$hr_size}}, $path;
}
### Usage selection priority
@@ -206,28 +228,202 @@ if ((-e "/sys/class/dmi/id/product_uuid") && (-r "/sys/class/dmi/id/product_uuid
}
}
-# Finally, we've got our output.
-my $say_grow = $type eq "striker" ? "--grow " : "";
-my $vg_name = $type."_".$id;
+### NOTE: RAID 0 is not RAID (literally or in this case). So '0' means 'no raid'
+# If I have 2+ drives of the same size as 'use_drive', I will create a RAID array.
+my $raid_level = 0;
+my $hr_size = $device->{$use_drive}{hr_size};
+my $count = @{$drives->{by_hr_size}{$hr_size}};
+print __LINE__."; [ Debug ] - Drives of size: [".$hr_size."]: [".$count."].\n" if $debug;
+if ($count == 0)
+{
+ $raid_level = 0;
+}
+elsif ($count == 2)
+{
+ $raid_level = 1;
+}
+elsif ($count == 4)
+{
+ $raid_level = 10;
+}
+elsif (($count == 3) or ($count == 5))
+{
+ $raid_level = 5;
+}
+elsif ($count > 5)
+{
+ $raid_level = 6;
+}
+
+my $say_use_drive = $use_drive;
+if (not $raid_level)
+{
+ print "Building a standard partition layout for: [".$use_drive."] which is: [".$hr_size."]\n";
+}
+else
+{
+ print "Building a software RAID level: [".$raid_level."] array using the: [".$count."x] [".$hr_size."] drives;\n";
+ $say_use_drive = "";
+ foreach my $path (sort {$a cmp $b} @{$drives->{by_hr_size}{$hr_size}})
+ {
+ print "- ".$path."\n";
+ $say_use_drive .= $path.",";
+ }
+ $say_use_drive =~ s/,$//;
+}
+
+### NOTE: kickstart sizes are in MiB
+# Prepare some variables
+my $swap_size = 8192;
+my $root_size = 0;
+my $vg_name = $type."_".$id;
+
+# If this machine has a small size, we'll cut back the swap and root sizes.
+my $per_disk_space = sprintf("%.2f", ($device->{$use_drive}{size} /= (2 ** 20)));
+my $available_space = $per_disk_space;
+print __LINE__."; [ Debug ] - per_disk_space: [".$per_disk_space." (".hr_size($per_disk_space * (2**20)).")], available_space: [".$available_space." (".hr_size($available_space * (2**20)).")]\n" if $debug;
+if ($raid_level == 10)
+{
+ # Total == 2 x single disk
+ $available_space *= 2;
+ print __LINE__."; [ Debug ] - available_space: [".$available_space."]\n" if $debug;
+}
+elsif ($raid_level == 5)
+{
+ # Total == count x Disks - 1
+ $available_space = ($per_disk_space * $count) - $per_disk_space;
+ print __LINE__."; [ Debug ] - available_space: [".$available_space."]\n" if $debug;
+}
+elsif ($raid_level == 6)
+{
+ # Total == count x Disks - 2
+ $available_space = ($per_disk_space * $count) - ($per_disk_space * 2);
+ print __LINE__."; [ Debug ] - available_space: [".$available_space."]\n" if $debug;
+}
+
+# Now, how much space is available after taking some for BIOSBOOT and /boot ?
+$available_space -= 2;
+print __LINE__."; [ Debug ] - available_space: [".$available_space." (".hr_size($available_space * (2**20)).")]\n" if $debug;
+if ($available_space < 40960)
+{
+ # Not enough space for the standard layout.
+ $swap_size = 4096;
+ print __LINE__."; [ Debug ] - swap_size: [".$swap_size."]\n" if $debug;
+}
+
+# The left over space is for '/' (we'll shorten this up to 40GiB for nodes and DR hosts next)
+$root_size = $available_space - $swap_size;
+print __LINE__."; [ Debug ] - root_size: [".$root_size."]\n" if $debug;
+
+print __LINE__."; [ Debug ] - type: [".$type."], root_size: [".$root_size."]\n" if $debug;
+if (($type ne "striker") && ($root_size > 40960))
+{
+ $root_size = 40960;
+ print __LINE__."; [ Debug ] - root_size: [".$root_size."]\n" if $debug;
+}
+
+# Round down to an event integer.
+$root_size =~ s/\.\d+$//;
+print __LINE__."; Assigning: [".hr_size($swap_size * (2**20))." (".$swap_size." MiB)], root_size: [".hr_size($root_size * (2**20))." (".$root_size.") MiB]\n" if $debug;
+
+# Build the partition file.
my $partition_file = "/tmp/plan_partitions.out";
my $partition_body = "zerombr
-clearpart --all --drives=".$use_drive."
-ignoredisk --only-use=".$use_drive."
-bootloader --location=mbr --driveorder=".$use_drive." --boot-drive=".$use_drive."
+clearpart --all --drives=".$say_use_drive."
+ignoredisk --only-use=".$say_use_drive."
+bootloader --location=mbr --driveorder=".$say_use_drive." --boot-drive=".$use_drive;
+if (not $raid_level)
+{
+ # Finally, we've got our output.
+ $partition_body .= "
# Partitions
-part biosboot --fstype=biosboot --size=1
-part /boot --fstype=ext4 --size=1024 --asprimary --ondisk=".$use_drive."
-part pv.01 --fstype=lvmpv --size=100 --asprimary --ondisk=".$use_drive." --grow
+part biosboot --fstype=biosboot --size=2
+part pv.01 --fstype=lvmpv --size=100 --ondisk=".$use_drive." --grow
# LVM Volume groups
volgroup ".$vg_name." --pesize=4096 pv.01
# LVM logical volumes
-logvol swap --fstype=swap --size=8188 --name=lv_swap --vgname=".$vg_name."
-logvol / --fstype=xfs --size=40960 --name=lv_root --vgname=".$vg_name." ".$say_grow."
+logvol swap --fstype=swap --size=".$swap_size." --name=lv_swap --vgname=".$vg_name."
+logvol / --fstype=xfs --size=".$root_size." --name=lv_root --vgname=".$vg_name."
+";
+}
+else
+{
+ $partition_body .= "
+# biosboot
";
-print __LINE__."; [ Debug ] - partition_body: [".$partition_body."]\n" if $debug;
+
+ for (my $i = 0; $i < $count; $i++)
+ {
+ $partition_body .= "part biosboot --fstype=biosboot --size=2 --ondisk=".$drives->{by_hr_size}{$hr_size}->[$i]."\n";
+ }
+
+ $partition_body .= "
+# LVM PV
+";
+ my $say_raid = "";
+ for (my $i = 0; $i < $count; $i++)
+ {
+ my $disk_number = $i + 1;
+ $partition_body .= "part raid.1".$disk_number." --size 100 --grow --ondisk=".$drives->{by_hr_size}{$hr_size}->[$i]."\n";
+ $say_raid .= "raid.1".$disk_number." ";
+ }
+ $partition_body .= "raid pv.01 --fstype=xfs --device=pv.01 --level=RAID".$raid_level." ".$say_raid."
+
+# LVM Volume groups
+volgroup ".$vg_name." pv.01
+
+# LVM logical volumes
+logvol swap --fstype=swap --size=".$swap_size." --name=lv_swap --vgname=".$vg_name."
+logvol / --fstype=xfs --size=".$root_size." --name=lv_root --vgname=".$vg_name."
+";
+}
+
+=cut
+# Wipe out the start of each disk and make it a GPT labelled disk.
+# See: https://access.redhat.com/solutions/55652
+foreach my $path (split/,/, $say_use_drive)
+{
+ print "[ NOTE ] - Wiping the boot sector of: [".$path."] and configuring it for a GPT label.\n";
+ my $dd_out = system_call("/bin/dd bs=5120 count=1 if=/dev/zero of=".$path." oflag=dsync");
+ print __LINE__."; [ Debug ] - dd output:
+================================================================================
+".$dd_out."
+================================================================================\n" if $debug;
+ my $parted_out1 = system_call("/sbin/parted --script ".$path." mklabel gpt");
+ print __LINE__."; [ Debug ] - parted mklabel output
+================================================================================
+".$parted_out1."
+================================================================================\n" if $debug;
+ my $parted_out2 = system_call("/sbin/parted --script ".$path." print free");
+ print __LINE__."; [ Debug ] - parted print output showing new layout.
+================================================================================
+".$parted_out2."
+================================================================================\n" if $debug;
+ my $partprobe_out = system_call("/sbin/partprobe --summary ".$path);
+ print __LINE__."; [ Debug ] - partprobe summary.
+================================================================================
+".$partprobe_out."
+================================================================================\n" if $debug;
+ my $partx_out = system_call("/sbin/partx --update --verbose ".$path);
+ print __LINE__."; [ Debug ] - parted print output showing new layout.
+================================================================================
+".$partx_out."
+================================================================================\n" if $debug;
+}
+# Flush things out. The article says to blindly sleep 30, but it says to do so to make sure udev, partx and
+# others have updated. We're forcing the issue, which should be faster and safer.
+system_call("/sbin/udevadm settle");
+system_call("/bin/sync");
+=cut
+
+# Write out the file.
+print __LINE__."; [ Debug ] - partition_body:
+================================================================================
+".$partition_body."
+================================================================================\n";
print "Writing out the partition plan to: [".$partition_file."]\n";
# Write it to the temp file that the kickstart's %include will look for.
diff --git a/share/words.xml b/share/words.xml
index 80954213..f06e2788 100644
--- a/share/words.xml
+++ b/share/words.xml
@@ -222,7 +222,10 @@ NOTE: Please be patient!
About to try to download aproximately: [#!variable!packages!#] packages needed to:
- [#!variable!directory!#].
-
+ Successfully enabled the Install Target function.
+ Successfully disabled the Install Target function.
+ The Install Target function is enabled.
+ The Install Target function is disabled.
Starting: [#!variable!program!#].
@@ -498,6 +501,7 @@ The body of the file: [#!variable!file!#] does not match the new body. The file
There was a problem updating file: [#!variable!file!#], expected the write to return '0' but got: [#!variable!return!#]. Please check the logs for details.
Failed to backup the file: [#!variable!source!#] to: [#!variable!destination!#]. Details may be found in the logs above.
Not updating the local repository on this run. Use '#!variable!program!# --refresh' to force a refresh of the local repository.
+ Skipping the RPM repository refresh. The next scheduled refresh will be done in: [#!variable!next_refresh!#] second(s). Use '#!variable!program!# --refresh' to force an immediate refresh.
Test
@@ -727,6 +731,8 @@ The update appears to have not completed successfully. The output was:
====
This Striker system is not configured yet. This tool will not be available until it is.
+ Failed to start the Install Target feature. Got a non-zero return code when starting: [#!data!sys::daemon::dhcpd!#] (got: [#!variable!rc!#]).
+ Failed to stop the Install Target feature. Got a non-zero return code when starting: [#!data!sys::daemon::dhcpd!#] (got: [#!variable!rc!#]).
Yes
diff --git a/tools/anvil-manage-install-target b/tools/anvil-manage-install-target
index 0faa8d32..9a3a215d 100755
--- a/tools/anvil-manage-install-target
+++ b/tools/anvil-manage-install-target
@@ -13,16 +13,18 @@
# - Call with '--refresh' to check for updates from upstream repositories.
#
# Exit codes;
-# 0 = Normal exit.
-# 1 = Alteeve repo not installed and not installable.
-# 2 = BCN IP not found, unable to configure yet.
-# 3 = Failed to write or update a configuration file.
-# 4 = Not a striker dashboard (or isn't yet).
-# 5 = Not running as the 'root' user.
-# 6 = The 'comps,xml' file provided by anvil-striker-extra was not found.
-# 7 = A package failed to download to our repo
-# 8 = No database connection available.
-# 9 = The system isn't configured yet.
+# 0 = Normal exit.
+# 1 = Alteeve repo not installed and not installable.
+# 2 = BCN IP not found, unable to configure yet.
+# 3 = Failed to write or update a configuration file.
+# 4 = Not a striker dashboard (or isn't yet).
+# 5 = Not running as the 'root' user.
+# 6 = The 'comps,xml' file provided by anvil-striker-extra was not found.
+# 7 = A package failed to download to our repo
+# 8 = No database connection available.
+# 9 = The system isn't configured yet.
+# 10 = Failed to start dhcpd.
+# 11 = Failed to stop dhcpd.
#
# TODO:
# - Support building the install target by mounting the ISO and checking /mnt/shared/incoming for needed
@@ -63,6 +65,45 @@ if (($< != 0) && ($> != 0))
$anvil->nice_exit({code => 5});
}
+# If the user just wants a status, check and exit.
+if ($anvil->data->{switches}{status})
+{
+ my $dhcpd_running = $anvil->System->check_daemon({daemon => $anvil->data->{sys}{daemon}{dhcpd}});
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { dhcpd_running => $dhcpd_running }});
+ if ($dhcpd_running)
+ {
+ print $anvil->Words->string({key => "message_0123"})."\n";
+ $anvil->nice_exit({code => 0});
+ }
+ else
+ {
+ print $anvil->Words->string({key => "message_0124"})."\n";
+ $anvil->nice_exit({code => 0});
+ }
+}
+
+### NOTE: Enabling is handled at the end, after checks/updates are applied
+# If we're being asked to disable, just do so and exit.
+if ($anvil->data->{switches}{disable})
+{
+ my $return_code = $anvil->System->stop_daemon({daemon => $anvil->data->{sys}{daemon}{dhcpd}});
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { return_code => $return_code }});
+ if ($return_code)
+ {
+ # non-0 means something went wrong.
+ print $anvil->Words->string({key => "error_0047", variables => { rc => $return_code }})."\n";
+ $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, secure => 0, key => "error_0048", variables => { rc => $return_code }});
+ $anvil->nice_exit({exit_code => 8});
+ }
+ else
+ {
+ # Success!
+ print $anvil->Words->string({key => "message_0122"})."\n";
+ $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, secure => 0, key => "message_0122"});
+ $anvil->nice_exit({code => 0});
+ }
+}
+
# Connect to the database(s).
$anvil->Database->connect;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 3, secure => 0, key => "log_0132"});
@@ -112,6 +153,26 @@ setup_boot_environment($anvil);
# Store the RPMs in repo directory.
update_install_source($anvil);
+# If we've been asked to enable or disable the install target, do so now.
+if ($anvil->data->{switches}{enable})
+{
+ my $return_code = $anvil->System->start_daemon({daemon => $anvil->data->{sys}{daemon}{dhcpd}});
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { return_code => $return_code }});
+ if ($return_code)
+ {
+ # non-0 means something went wrong.
+ print $anvil->Words->string({key => "error_0047", variables => { rc => $return_code }})."\n";
+ $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, secure => 0, key => "error_0047", variables => { rc => $return_code }});
+ $anvil->nice_exit({exit_code => 8});
+ }
+ else
+ {
+ # Success!
+ print $anvil->Words->string({key => "message_0121"})."\n";
+ $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, secure => 0, key => "message_0121"});
+ }
+}
+
# We're done
$anvil->nice_exit({exit_code => 0});
@@ -156,6 +217,15 @@ sub check_refresh
return(0);
}
+ # If the user has asked to enable or disable, skip.
+ $anvil->data->{switches}{enable} = "" if not defined $anvil->data->{switches}{enable};
+ $anvil->data->{switches}{disable} = "" if not defined $anvil->data->{switches}{disable};
+ if (($anvil->data->{switches}{enable}) or ($anvil->data->{switches}{disable}))
+ {
+ # Skip.
+ return(0);
+ }
+
# See when the last time we refreshed the local package cache
my ($unixtime, $variable_uuid, $modified_date) = $anvil->Database->read_variable({
variable_name => "install-target::refreshed",
@@ -168,6 +238,12 @@ sub check_refresh
modified_date => $modified_date,
}});
+ if (($unixtime eq "") or ($unixtime =~ /\D/))
+ {
+ $unixtime = 0;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { unixtime => $unixtime }});
+ }
+
### TODO: Allow the user to set a "refresh time" that will wait until the local time is after a
### certain time before refreshing. Also, allow the user to disable auto-refresh entirely.
# If the database variable 'install-target::refresh' is not set, or is more than 24 hours old,
@@ -184,18 +260,25 @@ sub check_refresh
'install-manifest::refresh-period' => $anvil->data->{'install-manifest'}{'refresh-period'},
}});
}
- my $time_now = time;
- my $next_scan = $unixtime + $anvil->data->{'install-manifest'}{'refresh-period'};
+ my $time_now = time;
+ my $next_scan = $unixtime + $anvil->data->{'install-manifest'}{'refresh-period'};
+ my $difference = ($next_scan - $time_now);
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
- 's1:time_now' => $time_now,
- 's2:next_scan' => $next_scan,
+ 's1:time_now' => $time_now,
+ 's2:next_scan' => $next_scan,
+ 's3:difference' => $difference,
}});
- if ((not $variable_uuid) or ($unixtime =~ /^\d+/) or ($time_now > $next_scan))
+ if ((not $variable_uuid) or ($unixtime =~ /^\d+/) or ($difference < 0))
{
$anvil->data->{switches}{refresh} = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "switches::refresh" => $anvil->data->{switches}{refresh} }});
return(0);
}
+ elsif ($difference > 0)
+ {
+ # Log when the next scan will happen
+ $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0236", variables => { next_refresh => $anvil->Convert->add_commas({number => $difference}) }});
+ }
# If the refresh fails, we'll update the last unixtime to be 24 hours from now, so that we can try
# again. We intentionally ignore 'install-manifest::refresh-period', that's only used when the
@@ -355,7 +438,7 @@ sub setup_boot_environment
### Generate kickstart files.
foreach my $type ("striker", "node", "dr")
{
- $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { type => $type }});
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { type => $type }});
my $say_type = "#!string!message_0115!#";
if ($type eq "node")
{
@@ -377,7 +460,7 @@ sub setup_boot_environment
password => $anvil->data->{kickstart}{password} ? $anvil->data->{kickstart}{password} : $anvil->data->{defaults}{kickstart}{password},
debug => 0, # This isn't the same as the rest of our code, just '1' or '0'.
}});
- $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { kickstart_body => $kickstart_body }});
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { kickstart_body => $kickstart_body }});
# Return code if '1' means the file was changed, '2' indicates it didn't change. '0' means
# something went wrong.
@@ -386,14 +469,14 @@ sub setup_boot_environment
body => $kickstart_body,
file => $kickstart_file,
});
- $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { kickstart_success => $kickstart_success }});
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { kickstart_success => $kickstart_success }});
if (not $kickstart_success)
{
# Failed.
print $anvil->Words->string({key => "error_0043", variables => { file => $kickstart_file }})."\n";
$anvil->nice_exit({code => 3});
}
- elsif ($dhcpd_conf_success eq "1")
+ elsif ($kickstart_success eq "1")
{
# Updated
$anvil->Storage->change_mode({target => $kickstart_file, mode => "0664"});
@@ -401,7 +484,7 @@ sub setup_boot_environment
print $anvil->Words->string({key => "message_0097", variables => { file => $kickstart_file }})."\n";
}
- elsif ($dhcpd_conf_success eq "2")
+ elsif ($kickstart_success eq "2")
{
# Update not needed.
print $anvil->Words->string({key => "message_0096", variables => { file => $kickstart_file }})."\n";
@@ -808,6 +891,7 @@ sub update_install_source
# Update the refresh time to now.
$anvil->Database->insert_or_update_variables({
+ debug => 2,
variable_name => "install-target::refreshed",
variable_value => time,
variable_default => "",