# raid-lib.pl # Functions for managing RAID do '../web-lib.pl'; &init_config(); %container = ( 'raiddev', 1, 'device', 1 ); # get_raidtab() # Parse the raid config file into a list of devices sub get_raidtab { local ($raiddev, $device, %mdstat); return \@get_raidtab_cache if (defined(@get_raidtab_cache)); # Read the mdstat file open(MDSTAT, $config{'mdstat'}); while() { if (/^(md\d+)\s*:\s+(\S+)\s+(\S+)\s+(.*)\s+(\d+)\s+blocks.*resync=(\d+)/) { $mdstat{"/dev/$1"} = [ $2, $3, $4, $5, $6 ]; } elsif (/^(md\d+)\s*:\s+(\S+)\s+(\S+)\s+(.*)\s+(\d+)\s+blocks/) { $mdstat{"/dev/$1"} = [ $2, $3, $4, $5 ]; } elsif (/^(md\d+)\s*:\s+(\S+)\s+(\S+)\s+(.*)/) { $mdstat{"/dev/$1"} = [ $2, $3, $4 ]; $_ = ; if (/\s+(\d+)\s+blocks.*resync=(\d+)/) { $mdstat{"/dev/$1"}->[3] = $1; $mdstat{"/dev/$1"}->[4] = $2; } elsif (/\s+(\d+)\s+blocks/) { $mdstat{"/dev/$1"}->[3] = $1; } } } close(MDSTAT); # Read the raidtab file local $lnum = 0; open(RAID, $config{'raidtab'}); while() { s/\r|\n//g; s/#.*$//; if (/^\s*(\S+)\s+(\S+)/) { local $dir = { 'name' => lc($1), 'value' => $2, 'line' => $lnum, 'eline' => $lnum }; if ($dir->{'name'} =~ /^(raid|spare|parity|failed)-disk$/) { push(@{$device->{'members'}}, $dir); $device->{'eline'} = $lnum; $raiddev->{'eline'} = $lnum; } elsif ($dir->{'name'} eq 'raiddev') { $dir->{'index'} = scalar(@get_raidtab_cache); push(@get_raidtab_cache, $dir); } else { push(@{$raiddev->{'members'}}, $dir); $raiddev->{'eline'} = $lnum; } if ($dir->{'name'} eq 'device') { $device = $dir; } elsif ($dir->{'name'} eq 'raiddev') { $raiddev = $dir; local $m = $mdstat{$dir->{'value'}}; $dir->{'active'} = $m->[0] eq 'active'; $dir->{'level'} = $m->[1] =~ /raid(\d+)/ ? $1 : $m->[1]; $dir->{'devices'} = [ map { /(\S+)\[\d+\]/; "/dev/$1" } split(/\s+/, $m->[2]) ]; $dir->{'size'} = $m->[3]; $dir->{'resync'} = $m->[4]; $dir->{'recovery'} = $m->[5]; } } $lnum++; } close(RAID); return \@get_raidtab_cache; } # create_raid(&raid) # Create a new raid set sub create_raid { $lref = &read_file_lines($config{'raidtab'}); $_[0]->{'line'} = @$lref; push(@$lref, &directive_lines($_[0])); $_[0]->{'eline'} = @$lref - 1; &flush_file_lines(); } # delete_raid(&raid) # Delete a raid set from the config file sub delete_raid { $lref = &read_file_lines($config{'raidtab'}); splice(@$lref, $_[0]->{'line'}, $_[0]->{'eline'} - $_[0]->{'line'} + 1); &flush_file_lines(); } # make_raid(&raid, force) # Call mkraid to make a raid set sub make_raid { local $f = $_[1] ? "--really-force" : ""; local $out = &backquote_logged("mkraid $f $_[0]->{'value'} 2>&1 $out") : undef; } # activate_raid(&raid) # Activate a raid set sub activate_raid { local $out = &backquote_logged("raidstart $_[0]->{'value'} 2>&1"); &error(&text('eraidstart', "$out")) if ($?); } # activate_raid(&raid) # Deactivate a raid set sub deactivate_raid { local $out = &backquote_logged("raidstop $_[0]->{'value'} 2>&1"); &error(&text('eraidstop', "$out")) if ($?); } # directive_lines(&directive, indent) sub directive_lines { local @rv = ( "$_[1]$_[0]->{'name'}\t$_[0]->{'value'}" ); foreach $m (@{$_[0]->{'members'}}) { push(@rv, &directive_lines($m, $_[1]."\t")); } return @rv; } # find(name, &array) sub find { local($c, @rv); foreach $c (@{$_[1]}) { if ($c->{'name'} eq $_[0]) { push(@rv, $c); } } return @rv ? wantarray ? @rv : $rv[0] : wantarray ? () : undef; } # find_value(name, &array) sub find_value { local(@v); @v = &find($_[0], $_[1]); if (!@v) { return undef; } elsif (wantarray) { return map { $_->{'value'} } @v; } else { return $v[0]->{'value'}; } } # device_status(device) # Returns an array of directory, type, mounted sub device_status { @mounted = &foreign_call("mount", "list_mounted") if (!@mounted); @mounts = &foreign_call("mount", "list_mounts") if (!@mounts); local $label = `e2label $_[0] 2>/dev/null`; chop($label); local ($mounted) = grep { &same_file($_->[1], $_[0]) || $_->[1] eq "LABEL=$label" } @mounted; local ($mount) = grep { &same_file($_->[1], $_[0]) || $_->[1] eq "LABEL=$label" } @mounts; if ($mounted) { return ($mounted->[0], $mounted->[2], 1, &indexof($mount, @mounts), &indexof($mounted, @mounted)); } elsif ($mount) { return ($mount->[0], $mount->[2], 0, &indexof($mount, @mounts)); } if (!defined(@physical_volumes)) { @physical_volumes = (); foreach $vg (&foreign_call("lvm", "list_volume_groups")) { push(@physical_volumes, &foreign_call("lvm", "list_physical_volumes", $vg->{'name'})); } } foreach $pv (@physical_volumes) { return ( $pv->{'vg'}, "lvm", 1) if ($pv->{'device'} eq $_[0]); } return (); } 1;