[!
use strict;
use Socket;
use PVE::pvecfg;
use PVE::I18N;
use PVE::ConfigServer;
use PVE::HTMLTable;
use PVE::HTMLDropDown;
use PVE::HTMLForm;
use PVE::HTMLGrid;
use PVE::HTMLUtils;
!]
[-
use strict;
my $cinfo = $fdat{__cinfo};
my $out = '';
my $form = PVE::HTMLForm->new (\%fdat);
my $conn = PVE::ConfigClient::connect ($udat{auth_cookie});
my $titles_add = {
dir => __("Add Directory"),
lvm => __("Add LVM Group"),
nfs => __("Add NFS Share"),
iscsi => __("Add ISCSI Target"),
};
my $titles_edit = {
dir => __("Edit Directory"),
lvm => __("Edit LVM Group"),
nfs => __("Edit NFS Share"),
iscsi => __("Edit ISCSI Target"),
};
my $typenames = {
dir => 'Directory',
nfs => 'NFS',
iscsi => 'ISCSI',
lvm => 'LVM',
};
my $fnames = {
storeid => __("Storage Name"),
path => __("Directory"),
basestore => __("Base Storage"),
base => __("Base Volume"),
server => __("Server"),
portal => __("Portal"),
target => __("Target"),
export => __("Export"),
vgname => __("Volume Group Name"),
enable => __("Enable"),
shared => __("Shared"),
content => __("Content"),
};
if ($udat{action}) {
my ($storeid, $digest) = split (/:/, $fdat{aa});
eval {
check_write_mode ($udat{AM});
if ($udat{action} eq 'delete') {
$conn->storage_remove ($storeid, $digest);
} elsif ($udat{action} eq 'enable') {
$conn->storage_enable ($storeid, $digest);
} elsif ($udat{action} eq 'disable') {
$conn->storage_disable ($storeid, $digest);
}
};
if ($@) {
$udat{popup_error} = $@;
$udat{redirect} = $fdat{__uri};
return;
}
}
if ($form->action eq 'scan') {
eval {
if ($fdat{type} eq 'nfs') {
check_field ($fnames->{server}, $fdat{server}, 'NOTEMPTY', 'SERVER');
if (my $res = $conn->storage_scan_nfs($fdat{server})->result) {
$fdat{scandata} = join (" ", sort keys %$res);
} else {
$udat{popup_info} = __("Found no exports");
}
} elsif ($fdat{type} eq 'iscsi') {
check_field ($fnames->{portal}, $fdat{portal}, 'NOTEMPTY', 'PORTAL');
if (my $res = $conn->storage_scan_iscsi($fdat{portal}, 1)->result) {
$fdat{scandata} = join (" ", sort keys %$res);
} else {
$udat{popup_info} = __("Found no unused targets");
}
}
};
$udat{popup_error} = $@ if $@;
} elsif ($form->action eq 'save') {
eval {
check_write_mode ($udat{AM});
if ($fdat{type} eq 'iscsi') {
$fdat{content} = $fdat{usedev} ? 'images' : 'none';
}
if ($fdat{edit} == 2) {
my $storeid = $fdat{storeid};
my $type = $fdat{type};
check_field ($fnames->{storeid}, $storeid, 'NOTEMPTY');
die "unable to use reserved storage ID '$storeid'\n" if $storeid eq 'local';
PVE::Storage::parse_storage_id ($storeid);
my $param = [];
if ($fdat{type} eq 'dir') {
push @$param, "--path", $fdat{path};
} elsif ($fdat{type} eq 'nfs') {
my $server = check_field ($fnames->{server}, $fdat{server}, 'NOTEMPTY', 'SERVER');
check_field ($fnames->{export}, $fdat{export}, 'NOTEMPTY');
push @$param, "--server", $server;
push @$param, "--export", $fdat{export};
} elsif ($fdat{type} eq 'lvm') {
check_field ($fnames->{vgname}, $fdat{vgname}, 'NOTEMPTY');
push @$param, "--vgname", $fdat{vgname};
push @$param, "--base", $fdat{base} if $fdat{base};
} elsif ($fdat{type} eq 'iscsi') {
my $portal = check_field ($fnames->{portal}, $fdat{portal}, 'NOTEMPTY', 'PORTAL');
check_field ($fnames->{target}, $fdat{target}, 'NOTEMPTY');
push @$param, "--portal", $portal;
push @$param, "--target", $fdat{target};
}
push @$param, "--disable", 1 if !$fdat{enable};
push @$param, "--shared", 1 if $fdat{shared};
push @$param, "--content", $fdat{content} || 'none';
$conn->storage_add ($storeid, $type, $param);
} else {
my ($storeid, $digest) = split (/:/, $fdat{aa});
my $param = [];
push @$param, "--disable", $fdat{enable} ? 0 : 1 if defined ($fdat{enable});
push @$param, "--shared", $fdat{shared} ? 1 : 0 if defined ($fdat{shared});
push @$param, "--content", $fdat{content} || 'none';
if (scalar (@$param)) {
$conn->storage_set ($storeid, $param, $digest);
}
}
};
if ($@) {
$udat{popup_error} = $@;
} else {
$fdat{edit} = undef;
}
}
my $ststat = $conn->get_storage_status ()->result;
my $stcfg = $ststat->{cfg};
my @sids = PVE::Storage::storage_ids ($stcfg);
my $iscsi_ids;
foreach my $storeid (@sids) {
my $scfg = PVE::Storage::storage_config ($stcfg, $storeid);
if ($scfg->{type} eq 'iscsi') {
push @$iscsi_ids, $storeid;
}
}
if ($fdat{edit}) {
my $fw3 = PVE::HTMLGrid::get_width ('fw3') - 80;
my $grid = PVE::HTMLGrid->new ('fw1', 'fw2', 80, "${fw3}:right", 'fw4');
my $d;
my ($storeid, $digest) = split (/:/, $fdat{aa});
my $edit = 0;
if ($fdat{edit} == 2) {
$d = {
type => $fdat{type},
shared => 0,
disable => 0,
content => { 'images' => 1 },
};
} else {
$edit = 1;
$d = PVE::Storage::storage_config ($stcfg, $storeid);
}
my $is_shared = $d->{type} eq 'nfs' || $d->{type} eq 'iscsi';
my $islocal = $storeid && $storeid eq 'local';
$out .= $form->create_header($fdat{__uri});
if (!defined ($fdat{enable})) {
$fdat{enable} = !$d->{disable};
};
foreach my $key (qw (shared path vgname server export portal target base)) {
if (!defined ($fdat{$key})) {
$fdat{$key} = $d->{$key};
};
}
if (!defined ($fdat{content})) {
my @ca = keys %{$d->{content}};
if ($islocal) {
$fdat{content} = join (' ', @ca);
} else {
$fdat{content} = $ca[0] || 'none';
}
};
if (!defined ($fdat{usedev})) {
$fdat{usedev} = defined ($d->{content}->{images});
}
my $clist = [];
my $valid_ctypes = PVE::Storage::valid_content_types ($d->{type});
push @$clist, [ 'images', __("Virtual Disks") ] if $valid_ctypes->{images};
push @$clist, [ 'iso', __("ISO Images") ] if $valid_ctypes->{iso};
push @$clist, [ 'rootdir', __("OpenVZ Containers") ] if $islocal && $valid_ctypes->{rootdir};
push @$clist, [ 'vztmpl', __("OpenVZ Templates") ] if $islocal && $valid_ctypes->{vztmpl};
push @$clist, [ 'backup', __("VZDump Backups") ] if !$islocal && $valid_ctypes->{backup};
my $csel;
if ($islocal) {
$csel = $form->create_element ('content', 'checkbox', $fdat{content},
[ 1, $clist]);
} else {
$csel = $form->create_element ('content', 'dropdown', $fdat{content}, $clist);
}
my @ca;
my $el;
if ($edit) {
$el = $form->create_element ('storeid', 'rotext', $storeid);
} else {
$el = $form->create_element ('storeid', 'text', $fdat{storeid});
}
$ca[0][0] = [ $fnames->{storeid} . ':', $el ];
if ($d->{type} eq 'dir') {
my $el = $form->create_element ('path', $edit ? 'rotext' : 'text', $fdat{path});
$ca[1][0] = [ $fnames->{path} . ':', $el ];
} elsif ($d->{type} eq 'lvm') {
my $ind = 1;
my $el;
if (!$edit) {
my $bida = [ ['', "Existing volume groups"] ];
if ($iscsi_ids) {
foreach my $sid (@$iscsi_ids) {
push @$bida, [ $sid, "$sid ($typenames->{iscsi})" ];
}
}
$el = $form->create_element ('basestore', 'dynamicdropdown',
$fdat{basestore}, $bida);
$ca[$ind++][0] = [ $fnames->{basestore} . ':', $el ];
if ($fdat{basestore}) {
my $tmp = $conn->storage_list_volumes ($fdat{basestore})->result;
my $imagelist = PVE::HTMLUtils::storage_format_volume_list_iscsi ($stcfg, $tmp);
$el = $form->create_element ('base', 'dropdown', $fdat{base}, $imagelist);
$ca[$ind++][0] = [ $fnames->{base} . ':', $el ];
}
} else {
if ($fdat{base}) {
$el = $form->create_element ('base', 'rotext', $fdat{base});
$ca[$ind++][0] = [ $fnames->{base} . ':', $el ];
}
}
if ($edit) {
$el = $form->create_element ('vgname', 'rotext', $fdat{vgname});
} else {
if ($fdat{basestore}) {
$el = $form->create_element ('vgname', 'text', $fdat{vgname});
} else {
my $tmp = $conn->storage_list_vgs ()->result;
my $vglist = PVE::HTMLUtils::storage_format_vgs_list ($stcfg, $tmp);
$el = $form->create_element ('vgname', 'dropdown', $fdat{vgname}, $vglist);
}
}
$ca[$ind++][0] = [ $fnames->{vgname} . ':', $el ];
} elsif ($d->{type} eq 'nfs') {
my $el = $form->create_element ('server', $edit ? 'rotext' : 'text', $fdat{server});
$ca[1][0] = [ $fnames->{server} . ':', $el ];
$ca[1][1] = $form->create_cmdbutton ('scan') if !$edit;
if (!$edit && $fdat{scandata}) {
$el = $form->create_element ('export', $edit ? 'rotext' : 'dropdown', $fdat{export},
[ split (/\s/, $fdat{scandata}) ]);
} else {
$el = $form->create_element ('export', $edit ? 'rotext' : 'text', $fdat{export});
}
$ca[2][0] = [ $fnames->{export} . ':', $el ];
} elsif ($d->{type} eq 'iscsi') {
my $el = $form->create_element ('portal', $edit ? 'rotext' : 'text', $fdat{portal});
$ca[1][0] = [ $fnames->{portal} . ':', $el ];
$ca[1][1] = $form->create_cmdbutton ('scan') if !$edit;
if (!$edit && $fdat{scandata}) {
$el = $form->create_element ('target', $edit ? 'rotext' : 'dropdown', $fdat{target},
[ split (/\s/, $fdat{scandata}) ]);
} else {
$el = $form->create_element ('target', $edit ? 'rotext' : 'text', $fdat{target});
}
$ca[2][0] = [ $fnames->{target} . ':', $el ];
} else {
die "unknown storage type '$d->{type}' $fdat{edit}";
}
# common settings for all storage types
my $ind = 0;
$ca[$ind++][2] = [ $fnames->{enable} . ':',
$form->create_element ('enable', $islocal ? 'robool' : 'bool', $fdat{enable}) ];
if (!$is_shared) {
$ca[$ind++][2] = [ $fnames->{shared} . ':',
$form->create_element ('shared',$islocal ? 'robool' : 'bool', $fdat{shared}) ];
}
if ($d->{type} eq 'iscsi') {
$el = $form->create_element ('usedev', 'bool', $fdat{usedev});
$ca[$ind++][2] = [ __("Use LUNs directly") . ':', $el ];
} else {
$ca[$ind++][2] = [ $fnames->{content} . ':', $csel ];
}
foreach my $row (@ca) {
my @ea = @$row;
$grid->add_row ($ea[0][0], $ea[0][1], $ea[1], $ea[2][0], $ea[2][1]);
}
my $html = $grid->html();
$html .= $form->create_element("edit", "hidden", $fdat{edit});
$html .= $form->create_element("type", "hidden", $d->{type});
$html .= $form->create_element("aa", "hidden", $fdat{aa});
$html .= $form->create_element("scandata", "hidden", $fdat{scandata});
$html .= "
";
$html .= $form->create_cmdbutton ('save');
my $title = $edit ? $titles_edit->{$d->{type}} : $titles_add->{$d->{type}};
$out .= PVE::HTMLUtils::create_statusframe (undef, $title, undef, $html);
$out .= $form->create_footer();
print OUT $out;
return;
}
if ($fdat{browse}) {
my ($storeid, $digest) = split (/:/, $fdat{aa});
my $scfg = PVE::Storage::storage_config ($stcfg, $storeid, 1);
if (!$scfg) {
$udat{popup_error} = __("No such Storage ID '$storeid'");
} elsif ($scfg->{disable}) {
$udat{popup_error} = __("Storage '$storeid' is disabled");
} else {
print OUT sprintf '