extrahd.cgi: Add support for LVM and MDADM devices

This commit adds support for using LVM and mdadm based RAID devices
for the CGI page.

In case one or more drives/partitions are used by such a "grouped"
volume they still will displayed on the page, but can not be
configured/used. Instead the "master" volume of which the
drive/partition is part of is shown in the "mountpoint" input box.

Signed-off-by: Stefan Schantl <stefan.schantl@ipfire.org>
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
This commit is contained in:
Stefan Schantl
2023-09-23 12:54:55 +02:00
committed by Michael Tremer
parent 3a7b9b7a2e
commit 15d9c996f9

View File

@@ -51,6 +51,12 @@ my @devices = &get_block_devices();
# Grab all known UUID's.
my %uuids = &get_uuids();
# Detect device mapper devices.
my %device_mapper = &get_device_mapper();
# Grab members of group devices (RAID, LVM)
my %grouped_devices = &collect_grouped_devices();
# Grab all mountpoints.
my %mountpoints = &get_mountpoints();
@@ -236,7 +242,39 @@ END
# Grab the known partitions of the current block device.
my @partitions = &get_device_partitions($device);
# Check if the block device has any partitions for display.
if (@partitions) {
# Loop through the partitions.
foreach my $partition (@partitions) {
# Call function to display the row in the WUI.
&print_row($partition);
}
}
# Also print rows for devices with an UUID.
&print_row($device) if($uuids{$device});
}
print <<END
<tr><td align="center" colspan="5">&nbsp;</td></tr>
<tr><td align="center" colspan="5">&nbsp;</td></tr>
<tr><td align="center" colspan="5">$Lang::tr{'extrahd install or load driver'}</td></tr>
</table>
END
;
&Header::closebox();
&Header::closebigbox();
&Header::closepage();
#
# Function to print a table row with device data on the WUI.
#
sub print_row ($) {
my ($partition) = @_;
my $disabled;
# Omit the partition size.
@@ -251,6 +289,18 @@ END
# Get the mountpoint.
my $mountpoint = $mountpoints{$partition};
# Generate partition string.
my $partition_string = "/dev/$partition";
# Check if the given partition is managed by device mapper.
if (exists($device_mapper{$partition})) {
# Alter the partition string to used one by the device mapper.
$partition_string = "$device_mapper{$partition}";
}
# Check if the device is part of a group.
my $grouped_device = &is_grouped_member($partition);
# If no mountpoint could be determined try to grab from
# configured drives.
unless($mountpoint) {
@@ -276,19 +326,30 @@ END
$disabled = "disabled";
$mountpoint = "swap";
$fs = "swap";
# Check if the device is part of a group.
} elsif ($grouped_device) {
$disabled = "disabled";
$mountpoint = "/dev/$grouped_device";
$mountpoint = $device_mapper{$grouped_device} if (exists($device_mapper{$grouped_device}));
}
print "<form method='post' action='$ENV{'SCRIPT_NAME'}'>\n";
# Only display UUID details if an UUID could be obtained.
if ( $uuids{$partition} ) {
print "<tr><td align='left' colspan=5><strong>UUID=$uuids{$partition}</strong></td></tr>\n";
}
print <<END
<form method='post' action='$ENV{'SCRIPT_NAME'}'>
<tr><td align="left" colspan=5><strong>UUID=$uuids{$partition}</strong></td></tr>
<tr>
<td align="list">/dev/$partition</td>
<td align="list">$partition_string</td>
<td align="center">$Lang::tr{'size'} $size</td>
<td align="center">$fs</td>
<td align="center"><input type='text' name='PATH' value='$mountpoint' $disabled></td>
<td align="center">
<input type='hidden' name='DEVICE' value='/dev/$partition' />
<input type='hidden' name='DEVICE' value='$partition_string' />
<input type='hidden' name='UUID' value='$uuids{$partition}' />
END
;
@@ -317,21 +378,8 @@ END
print <<END
</form></td></tr>
END
; }
}
print <<END
<tr><td align="center" colspan="5">&nbsp;</td></tr>
<tr><td align="center" colspan="5">&nbsp;</td></tr>
<tr><td align="center" colspan="5">$Lang::tr{'extrahd install or load driver'}</td></tr>
</table>
END
;
&Header::closebox();
&Header::closebigbox();
&Header::closepage();
}
#
## Function which return an array with all available block devices.
@@ -486,6 +534,86 @@ sub get_device_size ($) {
return $size;
}
#
## Function which tries to detect if a block device is a device mapper device and returns the alias a
## a hash. Example: "dm-0" -> "/dev/mapper/GROUP-DEVICE"
#
sub get_device_mapper () {
my %mapper_devices = ();
# Loop through all known block devices.
foreach my $block_device (@devices) {
# Generate device directory.
my $device_dir = "$sysfs_block_dir/$block_device";
# Skip the device if it is not managed by device mapper
# In this case the "bd" is not present.
next unless (-e "$device_dir/dm");
# Grab the group and volume name.
open(NAME, "$device_dir/dm/name") if (-e "$device_dir/dm/name");
my $name = <NAME>;
close(NAME);
# Skip device if no name could be determined.
next unless($name);
# Remove any newlines from the name string.
chomp($name);
# Generate path to the dev node in devfs.
my $dev_path = "/dev/mapper/$name";
# Store the device and the omited mapper name in the hash.
$mapper_devices{$block_device} = $dev_path;
}
# Return the hash of omited device mapper devices.
return %mapper_devices;
}
#
## Function which will collect grouped devices and their members as array in a hash and returns them.
## For example: "sda1" -> "dm-0" in case /dev/sda1 is assigned to a device mapper group.
#
sub collect_grouped_devices () {
my %grouped_devices = ();
# Loop through the array of known block devices.
foreach my $device (@devices) {
# Generate device directory.
my $device_dir = "$sysfs_block_dir/$device";
# Skip device if it has no members.
# In this case the "slaves" directory does not exist.
next unless (-e "$device_dir/slaves");
# Tempoarary array to store the members of a group.
my @members = ();
# Grab all members.
opendir(MEMBERS, "$device_dir/slaves");
while(readdir(MEMBERS)) {
next if($_ eq ".");
next if($_ eq "..");
# Add the found member to the array of members.
push(@members, $_);
}
closedir(MEMBERS);
# Skip the device if no members could be grabbed.
next unless (@members);
# Add the array of found members as value to the hash of grouped devices.
$grouped_devices{$device} = [ @members ];
}
# Return the hash of found grouped devices and their members.
return %grouped_devices;
}
#
## Function which returns all currently mounted devices as a hash.
## example: "sda1" -> "/boot"
@@ -708,3 +836,22 @@ sub is_configured ($) {
return 1 if($configured_drives{$uuid} eq "$path");
}
}
#
## Retruns the device name of the grouped device,if a given device is a group member.
#
sub is_grouped_member ($) {
my ($device) = @_;
# Loop through the hash of found grouped devices.
foreach my $grouped_device(keys %grouped_devices) {
# The found members are stored as arrays.
my @members = @{ $grouped_devices{$grouped_device} };
# Loop through array of members and check if the given
# device is part of it.
foreach my $member (@members) {
return $grouped_device if ($member eq $device);
}
}
}