diff --git a/lvm/index.cgi b/lvm/index.cgi index cc938adaf..cbab6c3de 100755 --- a/lvm/index.cgi +++ b/lvm/index.cgi @@ -160,6 +160,8 @@ if (@vgs) { "thin_form.cgi?vg=".&urlize($v->{'name'}), &text('index_addlv3', $v->{'name'}))); } + push(@links, &ui_link("raid_form.cgi?vg=".&urlize($v->{'name'}), + &text('index_addlv4', $v->{'name'}))); } if (!@alllvs) { # None yet diff --git a/lvm/lang/en b/lvm/lang/en index 82e27257d..dd8acb41e 100644 --- a/lvm/lang/en +++ b/lvm/lang/en @@ -13,6 +13,7 @@ index_addpv2=Add a physical volume to $1. index_addlv2=Create a logical volume in $1. index_addlv2s=Create a snapshot in $1. index_addlv3=Create a thin pool in $1. +index_addlv4=Create a RAID volume in $1. index_addlv=Create a new logical volume. index_addsnap=Create a new snapshot. index_return=volume groups @@ -213,6 +214,26 @@ thin_esame=Both selected LVs are the same thin_edata=The selected data LV is already in use thin_emetadata=The selected metadata LV is already in use +raid_title=Create RAID Volume +raid_desc=A RAID volume is an LV that spreads data across multiple physical volumes to increase performance, add redudancy to protect against disk failures, or both. +raid_header=New RAID volume details +raid_type=RAID volume type +raid_mode0=RAID0 (striped) across PVs +raid_mode1=RAID1 (mirrored) across PVs +raid_mode4=RAID4 (single-drive parity) across PVs +raid_mode5=RAID5 (multi-drive parity) across PVs +raid_mode6=RAID6 (multi-drive parity) across PVs +raid_mode10=RAID10 (multi-drive parity) across PVs +raid_ok=Create RAID volume +raid_err=Failed to create RAID volume +raid_estripe0=Number of PVs to stripe across must be at least 2 +raid_emirror1=Number of PVs to mirror across must be at least 2 +raid_estripe4=Number of PVs in a parity volume must be at least 3 +raid_estripe5=Number of PVs in a multi-drive parity volume must be at least 3 +raid_estripe6=Number of PVs in a multi-drive parity volume must be at least 3 +raid_estripe10=Number of PVs in a multi-drive parity volume must be at least 3 +raid_eeither=Missing either mirrors or stripes! + log_create_vg=Created volume group $1 log_modify_vg=Modified volume group $1 log_delete_vg=Deleted volume group $1 diff --git a/lvm/lvm-lib.pl b/lvm/lvm-lib.pl index 6d2a29827..c735d7097 100755 --- a/lvm/lvm-lib.pl +++ b/lvm/lvm-lib.pl @@ -969,7 +969,7 @@ sub create_raid_volume local ($lv) = @_; local $cmd = "lvcreate -y -n".quotemeta($lv->{'name'})." "; $cmd .= " --type ".quotemeta($lv->{'raid'}); -if ($rv->{'raid'} eq 'raid1') { +if ($lv->{'raid'} eq 'raid1') { $cmd .= " --mirrors ".$lv->{'mirrors'}; } else { @@ -978,14 +978,14 @@ else { local $suffix; if ($lv->{'size_of'} eq 'VG' || $lv->{'size_of'} eq 'FREE' || $lv->{'size_of'} eq 'ORIGIN') { - $cmd .= "-l ".quotemeta("$lv->{'size'}%$lv->{'size_of'}"); + $cmd .= " -l ".quotemeta("$lv->{'size'}%$lv->{'size_of'}"); } elsif ($lv->{'size_of'}) { - $cmd .= "-l $lv->{'size'}%PVS"; + $cmd .= " -l $lv->{'size'}%PVS"; $suffix = " ".quotemeta("/dev/".$lv->{'size_of'}); } else { - $cmd .= "-L".$lv->{'size'}."k"; + $cmd .= " -L".$lv->{'size'}."k"; } $cmd .= " -p ".quotemeta($lv->{'perm'}); $cmd .= " -r ".quotemeta($lv->{'readahead'}) @@ -998,7 +998,6 @@ $cmd .= " ".quotemeta($lv->{'vg'}); $cmd .= $suffix; local $out = &backquote_logged("$cmd 2>&1 {'name'} eq $in{'vg'} } &list_volume_groups(); +$vg || &error($text{'vg_egone'}); + +# Parse and validate inputs +&error_setup($text{'raid_err'}); +$in{'name'} =~ /^[A-Za-z0-9\.\-\_]+$/ || &error($text{'lv_ename'}); +($same) = grep { $_->{'name'} eq $in{'name'} } + &list_logical_volumes($in{'vg'}); +$same && &error($text{'lv_esame'}); +if ($in{'size_mode'} == 0) { + # Absolute size + $in{'size'} =~ /^\d+$/ || &error($text{'lv_esize'}); + $size = $in{'size'}; + if (defined($in{'size_units'})) { + # Convert selected units to kB + $size *= $in{'size_units'}/1024; + } + $sizeof = undef; + } +elsif ($in{'size_mode'} == 1) { + # Size of VG + $in{'vgsize'} =~ /^\d+$/ && + $in{'vgsize'} > 0 && + $in{'vgsize'} <= 100 || &error($text{'lv_evgsize'}); + $size = $in{'vgsize'}; + $sizeof = 'VG'; + } +elsif ($in{'size_mode'} == 2) { + # Size of free space + if (!$in{'lv'}) { + $in{'freesize'} =~ /^\d+$/ && + $in{'freesize'} > 0 && + $in{'freesize'} <= 100 || &error($text{'lv_efreesize'}); + } + $size = $in{'freesize'}; + $sizeof = 'FREE'; + } +elsif ($in{'size_mode'} == 3) { + # Size of some PV + $in{'pvsize'} =~ /^\d+$/ && + $in{'pvsize'} > 0 && + $in{'pvsize'} <= 100 || &error($text{'lv_epvsize'}); + $size = $in{'pvsize'}; + $sizeof = $in{'pvof'}; + } +if ($in{'raid_mode'} eq 'raid0') { + $in{'raid_stripe0'} =~ /^\d+$/ && $in{'raid_stripe0'} >= 2 || + &error($text{'raid_estripe0'}); + $stripes = $in{'raid_stripe0'}; + } +elsif ($in{'raid_mode'} eq 'raid1') { + $in{'raid_mirror1'} =~ /^\d+$/ && $in{'raid_mirror1'} >= 2 || + &error($text{'raid_emirror1'}); + $mirrors = $in{'raid_mirror1'}; + } +elsif ($in{'raid_mode'} eq 'raid4') { + $in{'raid_stripe4'} =~ /^\d+$/ && $in{'raid_stripe4'} >= 3 || + &error($text{'raid_estripe4'}); + $stripes = $in{'raid_stripe4'}; + } +elsif ($in{'raid_mode'} eq 'raid5') { + $in{'raid_stripe5'} =~ /^\d+$/ && $in{'raid_stripe5'} >= 3 || + &error($text{'raid_estripe5'}); + $stripes = $in{'raid_stripe5'}; + } +elsif ($in{'raid_mode'} eq 'raid6') { + $in{'raid_stripe6'} =~ /^\d+$/ && $in{'raid_stripe6'} >= 3 || + &error($text{'raid_estripe6'}); + $stripes = $in{'raid_stripe6'}; + } +elsif ($in{'raid_mode'} eq 'raid10') { + $in{'raid_stripe10'} =~ /^\d+$/ && $in{'raid_stripe10'} >= 3 || + &error($text{'raid_estripe10'}); + $stripes = $in{'raid_stripe10'}; + } +$mirrors || $stripes || &error($text{'raid_eeither'}); + +# Create the LV +$lv = { }; +$lv->{'vg'} = $in{'vg'}; +$lv->{'name'} = $in{'name'}; +$lv->{'size'} = $size; +$lv->{'size_of'} = $sizeof; +$lv->{'raid'} = $in{'raid_mode'}; +$lv->{'mirrors'} = $mirrors; +$lv->{'stripes'} = $stripes; +$lv->{'perm'} = $in{'perm'}; +$lv->{'alloc'} = $in{'alloc'}; +$lv->{'readahead'} = $in{'readahead'}; +$err = &create_raid_volume($lv); +&error($err) if ($err); + +&webmin_log("raid", "lv", $in{'name'}, $lv); +&redirect("index.cgi?mode=lvs"); diff --git a/lvm/raid_form.cgi b/lvm/raid_form.cgi new file mode 100755 index 000000000..762c4caae --- /dev/null +++ b/lvm/raid_form.cgi @@ -0,0 +1,77 @@ +#!/usr/local/bin/perl +# Display a form for creating a new RAID logical volume + +require './lvm-lib.pl'; +&ReadParse(); +($vg) = grep { $_->{'name'} eq $in{'vg'} } &list_volume_groups(); +$vg || &error($text{'vg_egone'}); + +$vgdesc = &text('lv_vg', $vg->{'name'}); +&ui_print_header($vgdesc, $text{'raid_title'}, ""); + +print $text{'raid_desc'},"
\n"; + +print &ui_form_start("raid_create.cgi", "post"); +print &ui_hidden("vg", $in{'vg'}); +print &ui_table_start($text{'raid_header'}, undef, 2); + +# LV name +print &ui_table_row($text{'lv_name'}, + &ui_textbox("name", $lv->{'name'}, 30)); + +# LV size +@pvopts = map { $_->{'name'} } + &list_physical_volumes($in{'vg'}); +print &ui_table_row($text{'lv_size'}, + &ui_radio_table("size_mode", 0, + [ [ 0, $text{'lv_size0'}, + &ui_bytesbox("size", $show_size * 1024, 8) ], + [ 1, $text{'lv_size1'}, + &ui_textbox("vgsize", undef, 4)."%" ], + [ 2, $text{'lv_size2'}, + &ui_textbox("freesize", undef, 4)."%" ], + [ 3, $text{'lv_size3'}, + &text('lv_size3a', + &ui_textbox("pvsize", undef, 4)."%", + &ui_select("pvof", undef, \@pvopts)) ], + ]), 3); + +# RAID type +print &ui_table_row($text{'raid_type'}, + &ui_radio_table("raid_mode", 'raid0', + [ [ 'raid0', $text{'raid_mode0'}, + &ui_textbox('raid_stripe0', 2, 5) ], + [ 'raid1', $text{'raid_mode1'}, + &ui_textbox('raid_mirror1', 2, 5) ], + [ 'raid4', $text{'raid_mode4'}, + &ui_textbox('raid_stripe4', 3, 5) ], + [ 'raid5', $text{'raid_mode5'}, + &ui_textbox('raid_stripe5', 3, 5) ], + [ 'raid6', $text{'raid_mode6'}, + &ui_textbox('raid_stripe6', 3, 5) ], + [ 'raid10', $text{'raid_mode10'}, + &ui_textbox('raid_stripe10', 3, 5) ] ])); + +# Permissions +print &ui_table_row($text{'lv_perm'}, + &ui_radio("perm", 'rw', + [ [ 'rw', $text{'lv_permrw'} ], + [ 'r', $text{'lv_permr'} ] ])); + +# Allocation method +print &ui_table_row($text{'lv_alloc'}, + &ui_radio("alloc", 'n', + [ [ 'y', $text{'lv_allocy'} ], + [ 'n', $text{'lv_allocn'} ] ])); + +# Readahead sectors +print &ui_table_row($text{'lv_readahead'}, + &ui_select("readahead", $lv->{'readahead'}, + [ [ "auto", "Auto" ], [ 0, "None" ], + map { [ $_, $_."" ] } + map { 2**$_ } ( 7 .. 16) ])); + +print &ui_table_end(); +print &ui_form_end([ [ undef, $text{'raid_ok'} ] ]); + +&ui_print_footer("index.cgi?mode=lvs", $text{'index_return'});