diff --git a/stable-5/perl5/PVE/Storage/.gitignore b/stable-5/perl5/PVE/Storage/.gitignore new file mode 100644 index 0000000..5eba4e6 --- /dev/null +++ b/stable-5/perl5/PVE/Storage/.gitignore @@ -0,0 +1,4 @@ +/ZFSPlugin.pm +/ZFSPoolPlugin.pm +/ZFSPlugin-new.pm +/ZFSPlugin-newver.patch diff --git a/stable-5/perl5/PVE/Storage/LunCmd/FreeNAS.pm b/stable-5/perl5/PVE/Storage/LunCmd/FreeNAS.pm new file mode 100644 index 0000000..71d24ec --- /dev/null +++ b/stable-5/perl5/PVE/Storage/LunCmd/FreeNAS.pm @@ -0,0 +1,546 @@ +package PVE::Storage::LunCmd::FreeNAS; + +use strict; +use warnings; +use Data::Dumper; +use PVE::SafeSyslog; +use IO::Socket::SSL; + +use REST::Client; +use MIME::Base64; +use JSON; + +# Max LUNS per target on the iSCSI server +my $MAX_LUNS = 255; + +# +# +# +sub get_base { + return '/dev/zvol'; +} + +# +# +# +sub run_lun_command { + my ($scfg, $timeout, $method, @params) = @_; + + if(!defined($scfg->{'freenas_user'}) || !defined($scfg->{'freenas_password'})) { + die "Undefined freenas_user and/or freenas_password."; + } + + syslog("info","FreeNAS::lun_command : $method(@params)"); + + if($method eq "create_lu") { + return run_create_lu($scfg, $timeout, $method, @params); + } + if($method eq "delete_lu") { + return run_delete_lu($scfg, $timeout, $method, @params); + } + if($method eq "import_lu") { + return run_create_lu($scfg, $timeout, $method, @params); + } + if($method eq "modify_lu") { + return run_modify_lu($scfg, $timeout, $method, @params); + } + if($method eq "add_view") { + return run_add_view($scfg, $timeout, $method, @params); + } + if($method eq "list_view") { + return run_list_view($scfg, $timeout, $method, @params); + } + if($method eq "list_extent") { + return run_list_extent($scfg, $timeout, $method, @params); + } + if($method eq "list_lu") { + return run_list_lu($scfg, $timeout, $method, "name", @params); + } + + syslog("error","FreeNAS::lun_command : unknown method $method"); + return undef; +} + +# +# +# +sub run_add_view { + return ''; +} + +# +# a modify_lu occur by example on a zvol resize. we just need to destroy and recreate the lun with the same zvol. +# Be careful, the first param is the new size of the zvol, we must shift params +# +sub run_modify_lu { + my ($scfg, $timeout, $method, @params) = @_; + shift(@params); + run_delete_lu($scfg, $timeout, $method, @params); + return run_create_lu($scfg, $timeout, $method, @params); +} + +# +# +# +sub run_list_view { + my ($scfg, $timeout, $method, @params) = @_; + return run_list_lu($scfg, $timeout, $method, "lun-id", @params); +} + +# +# +# +sub run_list_lu { + my ($scfg, $timeout, $method, $result_value_type, @params) = @_; + my $object = $params[0]; + my $result = undef; + + my $luns = freenas_list_lu($scfg); + foreach my $lun (@$luns) { + if ($lun->{'iscsi_target_extent_path'} =~ /^$object$/) { + $result = $result_value_type eq "lun-id" ? $lun->{'iscsi_lunid'} : $lun->{'iscsi_target_extent_path'}; + syslog("info","FreeNAS::list_lu($object):$result_value_type : lun found $result"); + last; + } + } + if(!defined($result)) { + syslog("info","FreeNAS::list_lu($object):$result_value_type : lun not found"); + } + + return $result; +} + +# +# +# +sub run_list_extent { + my ($scfg, $timeout, $method, @params) = @_; + my $object = $params[0]; + my $result = undef; + + my $luns = freenas_list_lu($scfg); + foreach my $lun (@$luns) { + if ($lun->{'iscsi_target_extent_path'} =~ /^$object$/) { + $result = $lun->{'iscsi_target_extent_naa'}; + syslog("info","FreeNAS::list_extent($object): naa found $result"); + last; + } + } + if (!defined($result)) { + syslog("info","FreeNAS::list_extent($object): naa not found"); + } + + return $result; +} + +# +# +# +sub run_create_lu { + my ($scfg, $timeout, $method, @params) = @_; + + my $lun_path = $params[0]; + my $lun_id = freenas_get_first_available_lunid($scfg); + + die "Maximum number of LUNs per target is $MAX_LUNS" if scalar $lun_id >= $MAX_LUNS; + die "$params[0]: LUN $lun_path exists" if defined(run_list_lu($scfg, $timeout, $method, "name", @params)); + + my $target_id = freenas_get_targetid($scfg); + die "Unable to find the target id for $scfg->{target}" if !defined($target_id); + + # Create the extent + my $extent = freenas_iscsi_create_extent($scfg, $lun_path); + + # Associate the new extent to the target + my $link = freenas_iscsi_create_target_to_extent($scfg, $target_id, $extent->{'id'}, $lun_id); + + if (defined($link)) { + syslog("info","FreeNAS::create_lu(lun_path=$lun_path, lun_id=$lun_id) : sucessfull"); + } else { + die "Unable to create lun $lun_path"; + } + + return ""; +} + +# +# +# +sub run_delete_lu { + my ($scfg, $timeout, $method, @params) = @_; + + my $lun_path = $params[0]; + my $luns = freenas_list_lu($scfg); + my $lun = undef; + my $link = undef; + + foreach my $item (@$luns) { + if($item->{'iscsi_target_extent_path'} =~ /^$lun_path$/) { + $lun = $item; + last; + } + } + + die "Unable to find the lun $lun_path for $scfg->{target}" if !defined($lun); + + my $target_id = freenas_get_targetid($scfg); + die "Unable to find the target id for $scfg->{target}" if !defined($target_id); + + # find the target to extent + my $target2extents = freenas_iscsi_get_target_to_extent($scfg); + + foreach my $item (@$target2extents) { + if($item->{'iscsi_target'} == $target_id && + $item->{'iscsi_lunid'} == $lun->{'iscsi_lunid'} && + $item->{'iscsi_extent'} == $lun->{'id'}) { + + $link = $item; + last; + } + } + die "Unable to find the link for the lun $lun_path for $scfg->{target}" if !defined($link); + + # Remove the link + my $remove_link = freenas_iscsi_remove_target_to_extent($scfg, $link->{'id'}); + + # Remove the extent + my $remove_extent = freenas_iscsi_remove_extent($scfg, $lun->{'id'}); + + if($remove_link == 1 && $remove_extent == 1) { + syslog("info","FreeNAS::delete_lu(lun_path=$lun_path) : sucessfull"); + } else { + die "Unable to delete lun $lun_path"; + } + + return ""; +} + +# +### FREENAS API CALLING ### +# +sub freenas_api_call { + my ($scfg, $method, $path, $data) = @_; + my $client = undef; + my $scheme = $scfg->{freenas_use_ssl} ? "https" : "http"; + my $apihost = defined($scfg->{freenas_apiv4_host}) ? $scfg->{freenas_apiv4_host} : $scfg->{portal}; + my $apiping = '/api/v1.0/system/version/'; + + $client = REST::Client->new(); + $client->setHost($scheme . '://' . $apihost); + $client->addHeader('Content-Type' , 'application/json'); + $client->addHeader('Authorization' , 'Basic ' . encode_base64($scfg->{freenas_user} . ':' . $scfg->{freenas_password})); + # If using SSL, don't verify SSL certs + if ($scfg->{freenas_use_ssl}) { + $client->getUseragent()->ssl_opts(verify_hostname => 0); + $client->getUseragent()->ssl_opts(SSL_verify_mode => SSL_VERIFY_NONE); + } + # Check if the APIs are accessable via the selected host and scheme + my $code = $client->request('GET', $apiping)->responseCode(); + if ($code != 200) { + freenas_api_log_error($client, "freenas_api_call"); + die "Unable to connect to the FreeNAS API service at '" . $apihost . "' using the '" . $scheme . "' protocol"; + } + syslog("info","FreeNAS::api_call : setup : sucessfull"); + if ($method eq 'GET') { + $client->GET($path); + } + if ($method eq 'DELETE') { + $client->DELETE($path); + } + if ($method eq 'POST') { + $client->POST($path, encode_json($data)); + } + + return $client +} + +# +# Writes the Response and Content to SysLog +# +sub freenas_api_log_error { + my ($client, $method) = @_; + syslog("info","[ERROR]FreeNAS::API::" . $method . " : Response code: " . $client->responseCode()); + syslog("info","[ERROR]FreeNAS::API::" . $method . " : Response content: " . $client->responseContent()); + return 1; +} + +# +# +# +sub freenas_iscsi_get_globalconfiguration { + my ($scfg) = @_; + my $client = freenas_api_call($scfg, 'GET', "/api/v1.0/services/iscsi/globalconfiguration/", undef); + my $code = $client->responseCode(); + + if ($code == 200) { + my $result = decode_json($client->responseContent()); + syslog("info","FreeNAS::API::get_globalconfig : target_basename=" . $result->{'iscsi_basename'}); + return $result; + } else { + freenas_api_log_error($client, "get_globalconfig"); + return undef; + } +} + +# +# Returns a list of all extents. +# http://api.freenas.org/resources/iscsi/index.html#get--api-v1.0-services-iscsi-extent- +# +sub freenas_iscsi_get_extent { + my ($scfg) = @_; + my $client = freenas_api_call($scfg, 'GET', "/api/v1.0/services/iscsi/extent/?limit=0", undef); + + my $code = $client->responseCode(); + if ($code == 200) { + my $result = decode_json($client->responseContent()); + syslog("info","FreeNAS::API::get_extent : sucessfull"); + return $result; + } else { + freenas_api_log_error($client, "get_extent"); + return undef; + } +} + +# +# Create an extent on FreeNas +# http://api.freenas.org/resources/iscsi/index.html#create-resource +# Parameters: +# - target config (scfg) +# - lun_path +# +sub freenas_iscsi_create_extent { + my ($scfg, $lun_path) = @_; + + my $name = $lun_path; + $name =~ s/^.*\///; # all from last / + $name = $scfg->{'pool'} . '/' . $name; + + my $device = $lun_path; + $device =~ s/^\/dev\///; # strip /dev/ + + my $request = { + "iscsi_target_extent_type" => "Disk", + "iscsi_target_extent_name" => $name, + "iscsi_target_extent_disk" => $device, + }; + + my $client = freenas_api_call($scfg, 'POST', "/api/v1.0/services/iscsi/extent/", $request); + my $code = $client->responseCode(); + if ($code == 201) { + my $result = decode_json($client->responseContent()); + syslog("info", "FreeNAS::API::create_extent(lun_path=" . $result->{'iscsi_target_extent_path'} . ") : sucessfull"); + return $result; + } else { + freenas_api_log_error($client, "create_extent"); + return undef; + } +} + +# +# Remove an extent by it's id +# http://api.freenas.org/resources/iscsi/index.html#delete-resource +# Parameters: +# - scfg +# - extent_id +# +sub freenas_iscsi_remove_extent { + my ($scfg, $extent_id) = @_; + + my $client = freenas_api_call($scfg, 'DELETE', "/api/v1.0/services/iscsi/extent/$extent_id/", undef); + my $code = $client->responseCode(); + if ($code == 204) { + syslog("info","FreeNAS::API::remove_extent(extent_id=$extent_id) : sucessfull"); + return 1; + } else { + freenas_api_log_error($client, "remove_extent"); + return 0; + } +} + +# +# Returns a list of all targets +# http://api.freenas.org/resources/iscsi/index.html#get--api-v1.0-services-iscsi-target- +# +sub freenas_iscsi_get_target { + my ($scfg) = @_; + + my $client = freenas_api_call($scfg, 'GET', "/api/v1.0/services/iscsi/target/?limit=0", undef); + my $code = $client->responseCode(); + if ($code == 200) { + my $result = decode_json($client->responseContent()); + syslog("info","FreeNAS::API::get_target() : sucessfull"); + return $result; + } else { + freenas_api_log_error($client, "get_target"); + return undef; + } +} + +# +# Returns a list of associated extents to targets +# http://api.freenas.org/resources/iscsi/index.html#get--api-v1.0-services-iscsi-targettoextent- +# +sub freenas_iscsi_get_target_to_extent { + my ($scfg) = @_; + + my $client = freenas_api_call($scfg, 'GET', "/api/v1.0/services/iscsi/targettoextent/?limit=0", undef); + my $code = $client->responseCode(); + if ($code == 200) { + my $result = decode_json($client->responseContent()); + syslog("info","FreeNAS::API::get_target_to_extent() : sucessfull"); + # If 'iscsi_lunid' is undef then it is set to 'Auto' in FreeNAS + # which should be '0' in our eyes. + # This gave Proxmox 5.x and FreeNAS 11.1 a few issues. + foreach my $item (@$result) { + if (!defined($item->{'iscsi_lunid'})) { + $item->{'iscsi_lunid'} = 0; + syslog("info", "FreeNAS::API::get_target_to_extent() : change undef iscsi_lunid to 0"); + } + } + return $result; + } else { + freenas_api_log_error($client, "get_target_to_extent"); + return undef; + } +} + +# +# Associate a FreeNas extent to a FreeNas Target +# http://api.freenas.org/resources/iscsi/index.html#post--api-v1.0-services-iscsi-targettoextent- +# Parameters: +# - target config (scfg) +# - FreeNas Target ID +# - FreeNas Extent ID +# - Lun ID +# +sub freenas_iscsi_create_target_to_extent { + my ($scfg, $target_id, $extent_id, $lun_id) = @_; + + my $request = { + "iscsi_target" => $target_id, + "iscsi_extent" => $extent_id, + "iscsi_lunid" => $lun_id + }; + + my $client = freenas_api_call($scfg, 'POST', "/api/v1.0/services/iscsi/targettoextent/", $request); + my $code = $client->responseCode(); + if ($code == 201) { + my $result = decode_json($client->responseContent()); + syslog("info","FreeNAS::API::create_target_to_extent(target_id=$target_id, extent_id=$extent_id, lun_id=$lun_id) : sucessfull"); + return $result; + } else { + freenas_api_log_error($client, "create_target_to_extent"); + return undef; + } +} + +# +# Remove a Target to extent by it's id +# http://api.freenas.org/resources/iscsi/index.html#delete--api-v1.0-services-iscsi-targettoextent-(int-id)- +# Parameters: +# - scfg +# - link_id +# +sub freenas_iscsi_remove_target_to_extent { + my ($scfg, $link_id) = @_; + + my $client = freenas_api_call($scfg, 'DELETE', "/api/v1.0/services/iscsi/targettoextent/$link_id/", undef); + my $code = $client->responseCode(); + if ($code == 204) { + syslog("info","FreeNAS::API::remove_target_to_extent(link_id=$link_id) : sucessfull"); + return 1; + } else { + freenas_api_log_error($client, "remove_target_to_extent"); + return 0; + } +} + +# +# Returns all luns associated to the current target defined by $scfg->{target} +# This method returns an array reference like "freenas_iscsi_get_extent" do +# but with an additionnal hash entry "iscsi_lunid" retrieved from "freenas_iscsi_get_target_to_extent" +# +sub freenas_list_lu { + my ($scfg) = @_; + + my $targets = freenas_iscsi_get_target($scfg); + my $target_id = freenas_get_targetid($scfg); + + my @luns = (); + my $iscsi_lunid = undef; + + if(defined($target_id)) { + my $target2extents = freenas_iscsi_get_target_to_extent($scfg); + my $extents = freenas_iscsi_get_extent($scfg); + + foreach my $item (@$target2extents) { + if($item->{'iscsi_target'} == $target_id) { + foreach my $node (@$extents) { + if($node->{'id'} == $item->{'iscsi_extent'}) { + if ($item->{'iscsi_lunid'} =~ /(\d+)/) { + $iscsi_lunid = "$1"; + } else { + syslog("info", "FreeNAS::API::freenas_list_lu : iscsi_lunid did not pass tainted testing"); + next; + } + $node->{'iscsi_lunid'} .= $iscsi_lunid; + push(@luns , $node); + } + } + } + } + } + syslog("info", "FreeNAS::API::freenas_list_lu : sucessfull"); + return \@luns; +} + +# +# Returns the first available "lunid" (in all targets namespaces) +# +sub freenas_get_first_available_lunid { + my ($scfg) = @_; + + my $target_id = freenas_get_targetid($scfg); + my $target2extents = freenas_iscsi_get_target_to_extent($scfg); + my @luns = (); + + foreach my $item (@$target2extents) { + push(@luns, $item->{'iscsi_lunid'}) if ($item->{'iscsi_target'} == $target_id); + } + + my @sorted_luns = sort {$a <=> $b} @luns; + my $lun_id = 0; + + # find the first hole, if not, give the +1 of the last lun + foreach my $lun (@sorted_luns) { + last if $lun != $lun_id; + $lun_id = $lun_id + 1; + } + + syslog("info", "FreeNAS::API::freenas_get_first_available_lunid : return $lun_id"); + return $lun_id; +} + +# +# Returns the target id on FreeNas of the currently configured target of this PVE storage +# +sub freenas_get_targetid { + my ($scfg) = @_; + + my $global = freenas_iscsi_get_globalconfiguration($scfg); + my $targets = freenas_iscsi_get_target($scfg); + my $target_id = undef; + + foreach my $target (@$targets) { + my $iqn = $global->{'iscsi_basename'} . ':' . $target->{'iscsi_target_name'}; + if($iqn eq $scfg->{target}) { + $target_id = $target->{'id'}; + last; + } + } + + return $target_id; +} + + +1; diff --git a/stable-5/perl5/PVE/Storage/ZFSPlugin-5.0-30.pm.patch b/stable-5/perl5/PVE/Storage/ZFSPlugin-5.0-30.pm.patch new file mode 100644 index 0000000..0a1c8a4 --- /dev/null +++ b/stable-5/perl5/PVE/Storage/ZFSPlugin-5.0-30.pm.patch @@ -0,0 +1,140 @@ +--- ZFSPlugin.pm.orig 2018-10-03 11:02:46.000000000 -0400 ++++ ZFSPlugin.pm 2018-10-28 21:27:44.794732848 -0400 +@@ -10,6 +10,7 @@ + + use base qw(PVE::Storage::ZFSPoolPlugin); + use PVE::Storage::LunCmd::Comstar; ++use PVE::Storage::LunCmd::FreeNAS; + use PVE::Storage::LunCmd::Istgt; + use PVE::Storage::LunCmd::Iet; + use PVE::Storage::LunCmd::LIO; +@@ -32,7 +33,7 @@ + my $zfs_unknown_scsi_provider = sub { + my ($provider) = @_; + +- die "$provider: unknown iscsi provider. Available [comstar, istgt, iet, LIO]"; ++ die "$provider: unknown iscsi provider. Available [comstar, freenas, istgt, iet, LIO]"; + }; + + my $zfs_get_base = sub { +@@ -40,6 +41,8 @@ + + if ($scfg->{iscsiprovider} eq 'comstar') { + return PVE::Storage::LunCmd::Comstar::get_base; ++ } elsif ($scfg->{iscsiprovider} eq 'freenas') { ++ return PVE::Storage::LunCmd::FreeNAS::get_base; + } elsif ($scfg->{iscsiprovider} eq 'istgt') { + return PVE::Storage::LunCmd::Istgt::get_base; + } elsif ($scfg->{iscsiprovider} eq 'iet') { +@@ -62,6 +65,8 @@ + if ($lun_cmds->{$method}) { + if ($scfg->{iscsiprovider} eq 'comstar') { + $msg = PVE::Storage::LunCmd::Comstar::run_lun_command($scfg, $timeout, $method, @params); ++ } elsif ($scfg->{iscsiprovider} eq 'freenas') { ++ $msg = PVE::Storage::LunCmd::FreeNAS::run_lun_command($scfg, $timeout, $method, @params); + } elsif ($scfg->{iscsiprovider} eq 'istgt') { + $msg = PVE::Storage::LunCmd::Istgt::run_lun_command($scfg, $timeout, $method, @params); + } elsif ($scfg->{iscsiprovider} eq 'iet') { +@@ -160,6 +165,15 @@ + return $class->zfs_request($scfg, undef, 'list_view', $guid); + } + ++# Part of the multipath enhancement ++sub zfs_get_wwid_number { ++ my ($class, $scfg, $guid) = @_; ++ ++ die "could not find lun_number for guid $guid" if !$guid; ++ ++ return $class->zfs_request($scfg, undef, 'list_extent', $guid); ++} ++ + # Configuration + + sub type { +@@ -178,6 +192,24 @@ + description => "iscsi provider", + type => 'string', + }, ++ # This is for FreeNAS iscsi and API intergration ++ # And some enhancements asked by the community ++ freenas_user => { ++ description => "FreeNAS API Username", ++ type => 'string', ++ }, ++ freenas_password => { ++ description => "FreeNAS API Password", ++ type => 'string', ++ }, ++ freenas_use_ssl => { ++ description => "FreeNAS API access via SSL", ++ type => 'boolean', ++ }, ++ freenas_apiv4_host => { ++ description => "FreeNAS API Host", ++ type => 'string', ++ }, + # this will disable write caching on comstar and istgt. + # it is not implemented for iet. iet blockio always operates with + # writethrough caching when not in readonly mode +@@ -205,14 +237,18 @@ + nodes => { optional => 1 }, + disable => { optional => 1 }, + portal => { fixed => 1 }, +- target => { fixed => 1 }, +- pool => { fixed => 1 }, ++ target => { fixed => 0 }, ++ pool => { fixed => 0 }, + blocksize => { fixed => 1 }, + iscsiprovider => { fixed => 1 }, + nowritecache => { optional => 1 }, + sparse => { optional => 1 }, + comstar_hg => { optional => 1 }, + comstar_tg => { optional => 1 }, ++ freenas_user => { optional => 1 }, ++ freenas_password => { optional => 1 }, ++ freenas_use_ssl => { optional => 1 }, ++ freenas_apiv4_host => { optional => 1 }, + lio_tpg => { optional => 1 }, + content => { optional => 1 }, + bwlimit => { optional => 1 }, +@@ -237,6 +273,40 @@ + + my $path = "iscsi://$portal/$target/$lun"; + ++ # Multipath enhancement ++ eval { ++ my $wwid = $class->zfs_get_wwid_number($scfg, $guid); ++# syslog(info,"JD: path get_lun_number guid $guid"); ++ ++ if ($wwid =~ /^([-\@\w.]+)$/) { ++ $wwid = $1; # $data now untainted ++ } else { ++ die "Bad data in '$wwid'"; # log this somewhere ++ } ++ my $wwid_end = substr $wwid, 16; ++ ++ my $mapper = ''; ++ sleep 3; ++ run_command("iscsiadm -m session --rescan"); ++ sleep 3; ++ my $line = `multipath -ll | grep \"$wwid_end\"`; ++ my ($mapper_device) = split(' ', $line); ++ $mapper_device = "" unless $mapper_device; ++ $mapper .= $mapper_device; ++ ++ if ($mapper =~ /^([-\@\w.]+)$/) { ++ $mapper = $1; # $data now untainted ++ } else { ++ $mapper = ''; ++ } ++ ++# syslog(info,"Multipath mapper found: $mapper\n"); ++ if ($mapper ne "") { ++ $path = "/dev/mapper/$mapper"; ++ sleep 5; ++ } ++ }; ++ + return ($path, $vmid, $vtype); + } + diff --git a/stable-5/perl5/PVE/Storage/ZFSPlugin-5.0-33_1.pm.hotfix.patch b/stable-5/perl5/PVE/Storage/ZFSPlugin-5.0-33_1.pm.hotfix.patch new file mode 100644 index 0000000..c8c7180 --- /dev/null +++ b/stable-5/perl5/PVE/Storage/ZFSPlugin-5.0-33_1.pm.hotfix.patch @@ -0,0 +1,10 @@ +--- ZFSPlugin-5.0-33.pm 2018-12-15 09:29:56.586101170 -0500 ++++ ZFSPlugin.pm 2018-12-15 09:24:08.393984276 -0500 +@@ -27,6 +27,7 @@ + modify_lu => 1, + add_view => 1, + list_view => 1, ++ list_extent => 1, + list_lu => 1, + }; + diff --git a/stable-5/perl5/PVE/Storage/ZFSPlugin-5.0-33_1.pm.patch b/stable-5/perl5/PVE/Storage/ZFSPlugin-5.0-33_1.pm.patch new file mode 100644 index 0000000..cb29033 --- /dev/null +++ b/stable-5/perl5/PVE/Storage/ZFSPlugin-5.0-33_1.pm.patch @@ -0,0 +1,147 @@ +--- ZFSPlugin.pm.orig 2018-11-27 07:23:15.000000000 -0500 ++++ ZFSPlugin.pm 2018-12-15 09:24:08.393984276 -0500 +@@ -10,6 +10,7 @@ + + use base qw(PVE::Storage::ZFSPoolPlugin); + use PVE::Storage::LunCmd::Comstar; ++use PVE::Storage::LunCmd::FreeNAS; + use PVE::Storage::LunCmd::Istgt; + use PVE::Storage::LunCmd::Iet; + use PVE::Storage::LunCmd::LIO; +@@ -26,13 +27,14 @@ + modify_lu => 1, + add_view => 1, + list_view => 1, ++ list_extent => 1, + list_lu => 1, + }; + + my $zfs_unknown_scsi_provider = sub { + my ($provider) = @_; + +- die "$provider: unknown iscsi provider. Available [comstar, istgt, iet, LIO]"; ++ die "$provider: unknown iscsi provider. Available [comstar, freenas, istgt, iet, LIO]"; + }; + + my $zfs_get_base = sub { +@@ -40,6 +42,8 @@ + + if ($scfg->{iscsiprovider} eq 'comstar') { + return PVE::Storage::LunCmd::Comstar::get_base; ++ } elsif ($scfg->{iscsiprovider} eq 'freenas') { ++ return PVE::Storage::LunCmd::FreeNAS::get_base; + } elsif ($scfg->{iscsiprovider} eq 'istgt') { + return PVE::Storage::LunCmd::Istgt::get_base; + } elsif ($scfg->{iscsiprovider} eq 'iet') { +@@ -62,6 +66,8 @@ + if ($lun_cmds->{$method}) { + if ($scfg->{iscsiprovider} eq 'comstar') { + $msg = PVE::Storage::LunCmd::Comstar::run_lun_command($scfg, $timeout, $method, @params); ++ } elsif ($scfg->{iscsiprovider} eq 'freenas') { ++ $msg = PVE::Storage::LunCmd::FreeNAS::run_lun_command($scfg, $timeout, $method, @params); + } elsif ($scfg->{iscsiprovider} eq 'istgt') { + $msg = PVE::Storage::LunCmd::Istgt::run_lun_command($scfg, $timeout, $method, @params); + } elsif ($scfg->{iscsiprovider} eq 'iet') { +@@ -160,6 +166,15 @@ + return $class->zfs_request($scfg, undef, 'list_view', $guid); + } + ++# Part of the multipath enhancement ++sub zfs_get_wwid_number { ++ my ($class, $scfg, $guid) = @_; ++ ++ die "could not find lun_number for guid $guid" if !$guid; ++ ++ return $class->zfs_request($scfg, undef, 'list_extent', $guid); ++} ++ + # Configuration + + sub type { +@@ -178,6 +193,24 @@ + description => "iscsi provider", + type => 'string', + }, ++ # This is for FreeNAS iscsi and API intergration ++ # And some enhancements asked by the community ++ freenas_user => { ++ description => "FreeNAS API Username", ++ type => 'string', ++ }, ++ freenas_password => { ++ description => "FreeNAS API Password", ++ type => 'string', ++ }, ++ freenas_use_ssl => { ++ description => "FreeNAS API access via SSL", ++ type => 'boolean', ++ }, ++ freenas_apiv4_host => { ++ description => "FreeNAS API Host", ++ type => 'string', ++ }, + # this will disable write caching on comstar and istgt. + # it is not implemented for iet. iet blockio always operates with + # writethrough caching when not in readonly mode +@@ -205,14 +238,18 @@ + nodes => { optional => 1 }, + disable => { optional => 1 }, + portal => { fixed => 1 }, +- target => { fixed => 1 }, +- pool => { fixed => 1 }, ++ target => { fixed => 0 }, ++ pool => { fixed => 0 }, + blocksize => { fixed => 1 }, + iscsiprovider => { fixed => 1 }, + nowritecache => { optional => 1 }, + sparse => { optional => 1 }, + comstar_hg => { optional => 1 }, + comstar_tg => { optional => 1 }, ++ freenas_user => { optional => 1 }, ++ freenas_password => { optional => 1 }, ++ freenas_use_ssl => { optional => 1 }, ++ freenas_apiv4_host => { optional => 1 }, + lio_tpg => { optional => 1 }, + content => { optional => 1 }, + bwlimit => { optional => 1 }, +@@ -237,6 +274,40 @@ + + my $path = "iscsi://$portal/$target/$lun"; + ++ # Multipath enhancement ++ eval { ++ my $wwid = $class->zfs_get_wwid_number($scfg, $guid); ++# syslog(info,"JD: path get_lun_number guid $guid"); ++ ++ if ($wwid =~ /^([-\@\w.]+)$/) { ++ $wwid = $1; # $data now untainted ++ } else { ++ die "Bad data in '$wwid'"; # log this somewhere ++ } ++ my $wwid_end = substr $wwid, 16; ++ ++ my $mapper = ''; ++ sleep 3; ++ run_command("iscsiadm -m session --rescan"); ++ sleep 3; ++ my $line = `multipath -ll | grep \"$wwid_end\"`; ++ my ($mapper_device) = split(' ', $line); ++ $mapper_device = "" unless $mapper_device; ++ $mapper .= $mapper_device; ++ ++ if ($mapper =~ /^([-\@\w.]+)$/) { ++ $mapper = $1; # $data now untainted ++ } else { ++ $mapper = ''; ++ } ++ ++# syslog(info,"Multipath mapper found: $mapper\n"); ++ if ($mapper ne "") { ++ $path = "/dev/mapper/$mapper"; ++ sleep 5; ++ } ++ }; ++ + return ($path, $vmid, $vtype); + } + diff --git a/stable-5/perl5/PVE/Storage/ZFSPlugin-5.0-34_1.pm.patch b/stable-5/perl5/PVE/Storage/ZFSPlugin-5.0-34_1.pm.patch new file mode 100644 index 0000000..b16823d --- /dev/null +++ b/stable-5/perl5/PVE/Storage/ZFSPlugin-5.0-34_1.pm.patch @@ -0,0 +1,147 @@ +--- ZFSPlugin-5.0-34.pm 2018-12-21 12:52:21.764194866 -0500 ++++ ZFSPlugin.pm 2018-12-21 12:53:08.663665081 -0500 +@@ -10,6 +10,7 @@ + + use base qw(PVE::Storage::ZFSPoolPlugin); + use PVE::Storage::LunCmd::Comstar; ++use PVE::Storage::LunCmd::FreeNAS; + use PVE::Storage::LunCmd::Istgt; + use PVE::Storage::LunCmd::Iet; + use PVE::Storage::LunCmd::LIO; +@@ -26,13 +27,14 @@ + modify_lu => 1, + add_view => 1, + list_view => 1, ++ list_extent => 1, + list_lu => 1, + }; + + my $zfs_unknown_scsi_provider = sub { + my ($provider) = @_; + +- die "$provider: unknown iscsi provider. Available [comstar, istgt, iet, LIO]"; ++ die "$provider: unknown iscsi provider. Available [comstar, freenas, istgt, iet, LIO]"; + }; + + my $zfs_get_base = sub { +@@ -40,6 +42,8 @@ + + if ($scfg->{iscsiprovider} eq 'comstar') { + return PVE::Storage::LunCmd::Comstar::get_base; ++ } elsif ($scfg->{iscsiprovider} eq 'freenas') { ++ return PVE::Storage::LunCmd::FreeNAS::get_base; + } elsif ($scfg->{iscsiprovider} eq 'istgt') { + return PVE::Storage::LunCmd::Istgt::get_base; + } elsif ($scfg->{iscsiprovider} eq 'iet') { +@@ -62,6 +66,8 @@ + if ($lun_cmds->{$method}) { + if ($scfg->{iscsiprovider} eq 'comstar') { + $msg = PVE::Storage::LunCmd::Comstar::run_lun_command($scfg, $timeout, $method, @params); ++ } elsif ($scfg->{iscsiprovider} eq 'freenas') { ++ $msg = PVE::Storage::LunCmd::FreeNAS::run_lun_command($scfg, $timeout, $method, @params); + } elsif ($scfg->{iscsiprovider} eq 'istgt') { + $msg = PVE::Storage::LunCmd::Istgt::run_lun_command($scfg, $timeout, $method, @params); + } elsif ($scfg->{iscsiprovider} eq 'iet') { +@@ -160,6 +166,15 @@ + return $class->zfs_request($scfg, undef, 'list_view', $guid); + } + ++# Part of the multipath enhancement ++sub zfs_get_wwid_number { ++ my ($class, $scfg, $guid) = @_; ++ ++ die "could not find lun_number for guid $guid" if !$guid; ++ ++ return $class->zfs_request($scfg, undef, 'list_extent', $guid); ++} ++ + # Configuration + + sub type { +@@ -178,6 +193,24 @@ + description => "iscsi provider", + type => 'string', + }, ++ # This is for FreeNAS iscsi and API intergration ++ # And some enhancements asked by the community ++ freenas_user => { ++ description => "FreeNAS API Username", ++ type => 'string', ++ }, ++ freenas_password => { ++ description => "FreeNAS API Password", ++ type => 'string', ++ }, ++ freenas_use_ssl => { ++ description => "FreeNAS API access via SSL", ++ type => 'boolean', ++ }, ++ freenas_apiv4_host => { ++ description => "FreeNAS API Host", ++ type => 'string', ++ }, + # this will disable write caching on comstar and istgt. + # it is not implemented for iet. iet blockio always operates with + # writethrough caching when not in readonly mode +@@ -205,14 +238,18 @@ + nodes => { optional => 1 }, + disable => { optional => 1 }, + portal => { fixed => 1 }, +- target => { fixed => 1 }, +- pool => { fixed => 1 }, ++ target => { fixed => 0 }, ++ pool => { fixed => 0 }, + blocksize => { fixed => 1 }, + iscsiprovider => { fixed => 1 }, + nowritecache => { optional => 1 }, + sparse => { optional => 1 }, + comstar_hg => { optional => 1 }, + comstar_tg => { optional => 1 }, ++ freenas_user => { optional => 1 }, ++ freenas_password => { optional => 1 }, ++ freenas_use_ssl => { optional => 1 }, ++ freenas_apiv4_host => { optional => 1 }, + lio_tpg => { optional => 1 }, + content => { optional => 1 }, + bwlimit => { optional => 1 }, +@@ -237,6 +274,40 @@ + + my $path = "iscsi://$portal/$target/$lun"; + ++ # Multipath enhancement ++ eval { ++ my $wwid = $class->zfs_get_wwid_number($scfg, $guid); ++# syslog(info,"JD: path get_lun_number guid $guid"); ++ ++ if ($wwid =~ /^([-\@\w.]+)$/) { ++ $wwid = $1; # $data now untainted ++ } else { ++ die "Bad data in '$wwid'"; # log this somewhere ++ } ++ my $wwid_end = substr $wwid, 16; ++ ++ my $mapper = ''; ++ sleep 3; ++ run_command("iscsiadm -m session --rescan"); ++ sleep 3; ++ my $line = `multipath -ll | grep \"$wwid_end\"`; ++ my ($mapper_device) = split(' ', $line); ++ $mapper_device = "" unless $mapper_device; ++ $mapper .= $mapper_device; ++ ++ if ($mapper =~ /^([-\@\w.]+)$/) { ++ $mapper = $1; # $data now untainted ++ } else { ++ $mapper = ''; ++ } ++ ++# syslog(info,"Multipath mapper found: $mapper\n"); ++ if ($mapper ne "") { ++ $path = "/dev/mapper/$mapper"; ++ sleep 5; ++ } ++ }; ++ + return ($path, $vmid, $vtype); + } + diff --git a/stable-5/perl5/PVE/Storage/ZFSPlugin-5.0-38_1.pm.patch b/stable-5/perl5/PVE/Storage/ZFSPlugin-5.0-38_1.pm.patch new file mode 100644 index 0000000..fa40368 --- /dev/null +++ b/stable-5/perl5/PVE/Storage/ZFSPlugin-5.0-38_1.pm.patch @@ -0,0 +1,147 @@ +--- ZFSPlugin.pm.orig 2019-02-07 09:14:12.000000000 -0500 ++++ ZFSPlugin.pm 2019-02-26 20:53:29.096598801 -0500 +@@ -10,6 +10,7 @@ + + use base qw(PVE::Storage::ZFSPoolPlugin); + use PVE::Storage::LunCmd::Comstar; ++use PVE::Storage::LunCmd::FreeNAS; + use PVE::Storage::LunCmd::Istgt; + use PVE::Storage::LunCmd::Iet; + use PVE::Storage::LunCmd::LIO; +@@ -26,13 +27,14 @@ + modify_lu => 1, + add_view => 1, + list_view => 1, ++ list_extent => 1, + list_lu => 1, + }; + + my $zfs_unknown_scsi_provider = sub { + my ($provider) = @_; + +- die "$provider: unknown iscsi provider. Available [comstar, istgt, iet, LIO]"; ++ die "$provider: unknown iscsi provider. Available [comstar, freenas, istgt, iet, LIO]"; + }; + + my $zfs_get_base = sub { +@@ -40,6 +42,8 @@ + + if ($scfg->{iscsiprovider} eq 'comstar') { + return PVE::Storage::LunCmd::Comstar::get_base; ++ } elsif ($scfg->{iscsiprovider} eq 'freenas') { ++ return PVE::Storage::LunCmd::FreeNAS::get_base; + } elsif ($scfg->{iscsiprovider} eq 'istgt') { + return PVE::Storage::LunCmd::Istgt::get_base; + } elsif ($scfg->{iscsiprovider} eq 'iet') { +@@ -62,6 +66,8 @@ + if ($lun_cmds->{$method}) { + if ($scfg->{iscsiprovider} eq 'comstar') { + $msg = PVE::Storage::LunCmd::Comstar::run_lun_command($scfg, $timeout, $method, @params); ++ } elsif ($scfg->{iscsiprovider} eq 'freenas') { ++ $msg = PVE::Storage::LunCmd::FreeNAS::run_lun_command($scfg, $timeout, $method, @params); + } elsif ($scfg->{iscsiprovider} eq 'istgt') { + $msg = PVE::Storage::LunCmd::Istgt::run_lun_command($scfg, $timeout, $method, @params); + } elsif ($scfg->{iscsiprovider} eq 'iet') { +@@ -160,6 +166,15 @@ + return $class->zfs_request($scfg, undef, 'list_view', $guid); + } + ++# Part of the multipath enhancement ++sub zfs_get_wwid_number { ++ my ($class, $scfg, $guid) = @_; ++ ++ die "could not find lun_number for guid $guid" if !$guid; ++ ++ return $class->zfs_request($scfg, undef, 'list_extent', $guid); ++} ++ + # Configuration + + sub type { +@@ -178,6 +193,24 @@ + description => "iscsi provider", + type => 'string', + }, ++ # This is for FreeNAS iscsi and API intergration ++ # And some enhancements asked by the community ++ freenas_user => { ++ description => "FreeNAS API Username", ++ type => 'string', ++ }, ++ freenas_password => { ++ description => "FreeNAS API Password", ++ type => 'string', ++ }, ++ freenas_use_ssl => { ++ description => "FreeNAS API access via SSL", ++ type => 'boolean', ++ }, ++ freenas_apiv4_host => { ++ description => "FreeNAS API Host", ++ type => 'string', ++ }, + # this will disable write caching on comstar and istgt. + # it is not implemented for iet. iet blockio always operates with + # writethrough caching when not in readonly mode +@@ -205,14 +238,18 @@ + nodes => { optional => 1 }, + disable => { optional => 1 }, + portal => { fixed => 1 }, +- target => { fixed => 1 }, +- pool => { fixed => 1 }, ++ target => { fixed => 0 }, ++ pool => { fixed => 0 }, + blocksize => { fixed => 1 }, + iscsiprovider => { fixed => 1 }, + nowritecache => { optional => 1 }, + sparse => { optional => 1 }, + comstar_hg => { optional => 1 }, + comstar_tg => { optional => 1 }, ++ freenas_user => { optional => 1 }, ++ freenas_password => { optional => 1 }, ++ freenas_use_ssl => { optional => 1 }, ++ freenas_apiv4_host => { optional => 1 }, + lio_tpg => { optional => 1 }, + content => { optional => 1 }, + bwlimit => { optional => 1 }, +@@ -237,6 +274,40 @@ + + my $path = "iscsi://$portal/$target/$lun"; + ++ # Multipath enhancement ++ eval { ++ my $wwid = $class->zfs_get_wwid_number($scfg, $guid); ++# syslog(info,"JD: path get_lun_number guid $guid"); ++ ++ if ($wwid =~ /^([-\@\w.]+)$/) { ++ $wwid = $1; # $data now untainted ++ } else { ++ die "Bad data in '$wwid'"; # log this somewhere ++ } ++ my $wwid_end = substr $wwid, 16; ++ ++ my $mapper = ''; ++ sleep 3; ++ run_command("iscsiadm -m session --rescan"); ++ sleep 3; ++ my $line = `multipath -ll | grep \"$wwid_end\"`; ++ my ($mapper_device) = split(' ', $line); ++ $mapper_device = "" unless $mapper_device; ++ $mapper .= $mapper_device; ++ ++ if ($mapper =~ /^([-\@\w.]+)$/) { ++ $mapper = $1; # $data now untainted ++ } else { ++ $mapper = ''; ++ } ++ ++# syslog(info,"Multipath mapper found: $mapper\n"); ++ if ($mapper ne "") { ++ $path = "/dev/mapper/$mapper"; ++ sleep 5; ++ } ++ }; ++ + return ($path, $vmid, $vtype); + } + diff --git a/stable-5/perl5/PVE/Storage/ZFSPlugin-5.0-42_1.pm.patch b/stable-5/perl5/PVE/Storage/ZFSPlugin-5.0-42_1.pm.patch new file mode 100644 index 0000000..5bb7925 --- /dev/null +++ b/stable-5/perl5/PVE/Storage/ZFSPlugin-5.0-42_1.pm.patch @@ -0,0 +1,147 @@ +--- ZFSPlugin.pm.orig 2019-04-30 09:54:55.000000000 -0400 ++++ ZFSPlugin.pm 2019-05-11 10:32:36.326734352 -0400 +@@ -10,6 +10,7 @@ + + use base qw(PVE::Storage::ZFSPoolPlugin); + use PVE::Storage::LunCmd::Comstar; ++use PVE::Storage::LunCmd::FreeNAS; + use PVE::Storage::LunCmd::Istgt; + use PVE::Storage::LunCmd::Iet; + use PVE::Storage::LunCmd::LIO; +@@ -26,13 +27,14 @@ + modify_lu => 1, + add_view => 1, + list_view => 1, ++ list_extent => 1, + list_lu => 1, + }; + + my $zfs_unknown_scsi_provider = sub { + my ($provider) = @_; + +- die "$provider: unknown iscsi provider. Available [comstar, istgt, iet, LIO]"; ++ die "$provider: unknown iscsi provider. Available [comstar, freenas, istgt, iet, LIO]"; + }; + + my $zfs_get_base = sub { +@@ -40,6 +42,8 @@ + + if ($scfg->{iscsiprovider} eq 'comstar') { + return PVE::Storage::LunCmd::Comstar::get_base; ++ } elsif ($scfg->{iscsiprovider} eq 'freenas') { ++ return PVE::Storage::LunCmd::FreeNAS::get_base; + } elsif ($scfg->{iscsiprovider} eq 'istgt') { + return PVE::Storage::LunCmd::Istgt::get_base; + } elsif ($scfg->{iscsiprovider} eq 'iet') { +@@ -62,6 +66,8 @@ + if ($lun_cmds->{$method}) { + if ($scfg->{iscsiprovider} eq 'comstar') { + $msg = PVE::Storage::LunCmd::Comstar::run_lun_command($scfg, $timeout, $method, @params); ++ } elsif ($scfg->{iscsiprovider} eq 'freenas') { ++ $msg = PVE::Storage::LunCmd::FreeNAS::run_lun_command($scfg, $timeout, $method, @params); + } elsif ($scfg->{iscsiprovider} eq 'istgt') { + $msg = PVE::Storage::LunCmd::Istgt::run_lun_command($scfg, $timeout, $method, @params); + } elsif ($scfg->{iscsiprovider} eq 'iet') { +@@ -160,6 +166,15 @@ + return $class->zfs_request($scfg, undef, 'list_view', $guid); + } + ++# Part of the multipath enhancement ++sub zfs_get_wwid_number { ++ my ($class, $scfg, $guid) = @_; ++ ++ die "could not find lun_number for guid $guid" if !$guid; ++ ++ return $class->zfs_request($scfg, undef, 'list_extent', $guid); ++} ++ + # Configuration + + sub type { +@@ -178,6 +193,24 @@ + description => "iscsi provider", + type => 'string', + }, ++ # This is for FreeNAS iscsi and API intergration ++ # And some enhancements asked by the community ++ freenas_user => { ++ description => "FreeNAS API Username", ++ type => 'string', ++ }, ++ freenas_password => { ++ description => "FreeNAS API Password", ++ type => 'string', ++ }, ++ freenas_use_ssl => { ++ description => "FreeNAS API access via SSL", ++ type => 'boolean', ++ }, ++ freenas_apiv4_host => { ++ description => "FreeNAS API Host", ++ type => 'string', ++ }, + # this will disable write caching on comstar and istgt. + # it is not implemented for iet. iet blockio always operates with + # writethrough caching when not in readonly mode +@@ -205,14 +238,18 @@ + nodes => { optional => 1 }, + disable => { optional => 1 }, + portal => { fixed => 1 }, +- target => { fixed => 1 }, +- pool => { fixed => 1 }, ++ target => { fixed => 0 }, ++ pool => { fixed => 0 }, + blocksize => { fixed => 1 }, + iscsiprovider => { fixed => 1 }, + nowritecache => { optional => 1 }, + sparse => { optional => 1 }, + comstar_hg => { optional => 1 }, + comstar_tg => { optional => 1 }, ++ freenas_user => { optional => 1 }, ++ freenas_password => { optional => 1 }, ++ freenas_use_ssl => { optional => 1 }, ++ freenas_apiv4_host => { optional => 1 }, + lio_tpg => { optional => 1 }, + content => { optional => 1 }, + bwlimit => { optional => 1 }, +@@ -237,6 +274,40 @@ + + my $path = "iscsi://$portal/$target/$lun"; + ++ # Multipath enhancement ++ eval { ++ my $wwid = $class->zfs_get_wwid_number($scfg, $guid); ++# syslog(info,"JD: path get_lun_number guid $guid"); ++ ++ if ($wwid =~ /^([-\@\w.]+)$/) { ++ $wwid = $1; # $data now untainted ++ } else { ++ die "Bad data in '$wwid'"; # log this somewhere ++ } ++ my $wwid_end = substr $wwid, 16; ++ ++ my $mapper = ''; ++ sleep 3; ++ run_command("iscsiadm -m session --rescan"); ++ sleep 3; ++ my $line = `multipath -ll | grep \"$wwid_end\"`; ++ my ($mapper_device) = split(' ', $line); ++ $mapper_device = "" unless $mapper_device; ++ $mapper .= $mapper_device; ++ ++ if ($mapper =~ /^([-\@\w.]+)$/) { ++ $mapper = $1; # $data now untainted ++ } else { ++ $mapper = ''; ++ } ++ ++# syslog(info,"Multipath mapper found: $mapper\n"); ++ if ($mapper ne "") { ++ $path = "/dev/mapper/$mapper"; ++ sleep 5; ++ } ++ }; ++ + return ($path, $vmid, $vtype); + } + diff --git a/stable-5/perl5/PVE/Storage/ZFSPlugin-5.0-44_1.pm.patch b/stable-5/perl5/PVE/Storage/ZFSPlugin-5.0-44_1.pm.patch new file mode 100644 index 0000000..adb1b63 --- /dev/null +++ b/stable-5/perl5/PVE/Storage/ZFSPlugin-5.0-44_1.pm.patch @@ -0,0 +1,147 @@ +--- ZFSPlugin.pm.orig 2019-06-25 06:54:50.000000000 -0400 ++++ ZFSPlugin.pm 2019-07-16 13:36:48.817831174 -0400 +@@ -10,6 +10,7 @@ + + use base qw(PVE::Storage::ZFSPoolPlugin); + use PVE::Storage::LunCmd::Comstar; ++use PVE::Storage::LunCmd::FreeNAS; + use PVE::Storage::LunCmd::Istgt; + use PVE::Storage::LunCmd::Iet; + use PVE::Storage::LunCmd::LIO; +@@ -26,13 +27,14 @@ + modify_lu => 1, + add_view => 1, + list_view => 1, ++ list_extent => 1, + list_lu => 1, + }; + + my $zfs_unknown_scsi_provider = sub { + my ($provider) = @_; + +- die "$provider: unknown iscsi provider. Available [comstar, istgt, iet, LIO]"; ++ die "$provider: unknown iscsi provider. Available [comstar, freenas, istgt, iet, LIO]"; + }; + + my $zfs_get_base = sub { +@@ -40,6 +42,8 @@ + + if ($scfg->{iscsiprovider} eq 'comstar') { + return PVE::Storage::LunCmd::Comstar::get_base; ++ } elsif ($scfg->{iscsiprovider} eq 'freenas') { ++ return PVE::Storage::LunCmd::FreeNAS::get_base; + } elsif ($scfg->{iscsiprovider} eq 'istgt') { + return PVE::Storage::LunCmd::Istgt::get_base; + } elsif ($scfg->{iscsiprovider} eq 'iet') { +@@ -62,6 +66,8 @@ + if ($lun_cmds->{$method}) { + if ($scfg->{iscsiprovider} eq 'comstar') { + $msg = PVE::Storage::LunCmd::Comstar::run_lun_command($scfg, $timeout, $method, @params); ++ } elsif ($scfg->{iscsiprovider} eq 'freenas') { ++ $msg = PVE::Storage::LunCmd::FreeNAS::run_lun_command($scfg, $timeout, $method, @params); + } elsif ($scfg->{iscsiprovider} eq 'istgt') { + $msg = PVE::Storage::LunCmd::Istgt::run_lun_command($scfg, $timeout, $method, @params); + } elsif ($scfg->{iscsiprovider} eq 'iet') { +@@ -160,6 +166,15 @@ + return $class->zfs_request($scfg, undef, 'list_view', $guid); + } + ++# Part of the multipath enhancement ++sub zfs_get_wwid_number { ++ my ($class, $scfg, $guid) = @_; ++ ++ die "could not find lun_number for guid $guid" if !$guid; ++ ++ return $class->zfs_request($scfg, undef, 'list_extent', $guid); ++} ++ + # Configuration + + sub type { +@@ -178,6 +193,24 @@ + description => "iscsi provider", + type => 'string', + }, ++ # This is for FreeNAS iscsi and API intergration ++ # And some enhancements asked by the community ++ freenas_user => { ++ description => "FreeNAS API Username", ++ type => 'string', ++ }, ++ freenas_password => { ++ description => "FreeNAS API Password", ++ type => 'string', ++ }, ++ freenas_use_ssl => { ++ description => "FreeNAS API access via SSL", ++ type => 'boolean', ++ }, ++ freenas_apiv4_host => { ++ description => "FreeNAS API Host", ++ type => 'string', ++ }, + # this will disable write caching on comstar and istgt. + # it is not implemented for iet. iet blockio always operates with + # writethrough caching when not in readonly mode +@@ -205,14 +238,18 @@ + nodes => { optional => 1 }, + disable => { optional => 1 }, + portal => { fixed => 1 }, +- target => { fixed => 1 }, +- pool => { fixed => 1 }, ++ target => { fixed => 0 }, ++ pool => { fixed => 0 }, + blocksize => { fixed => 1 }, + iscsiprovider => { fixed => 1 }, + nowritecache => { optional => 1 }, + sparse => { optional => 1 }, + comstar_hg => { optional => 1 }, + comstar_tg => { optional => 1 }, ++ freenas_user => { optional => 1 }, ++ freenas_password => { optional => 1 }, ++ freenas_use_ssl => { optional => 1 }, ++ freenas_apiv4_host => { optional => 1 }, + lio_tpg => { optional => 1 }, + content => { optional => 1 }, + bwlimit => { optional => 1 }, +@@ -237,6 +274,40 @@ + + my $path = "iscsi://$portal/$target/$lun"; + ++ # Multipath enhancement ++ eval { ++ my $wwid = $class->zfs_get_wwid_number($scfg, $guid); ++# syslog(info,"JD: path get_lun_number guid $guid"); ++ ++ if ($wwid =~ /^([-\@\w.]+)$/) { ++ $wwid = $1; # $data now untainted ++ } else { ++ die "Bad data in '$wwid'"; # log this somewhere ++ } ++ my $wwid_end = substr $wwid, 16; ++ ++ my $mapper = ''; ++ sleep 3; ++ run_command("iscsiadm -m session --rescan"); ++ sleep 3; ++ my $line = `multipath -ll | grep \"$wwid_end\"`; ++ my ($mapper_device) = split(' ', $line); ++ $mapper_device = "" unless $mapper_device; ++ $mapper .= $mapper_device; ++ ++ if ($mapper =~ /^([-\@\w.]+)$/) { ++ $mapper = $1; # $data now untainted ++ } else { ++ $mapper = ''; ++ } ++ ++# syslog(info,"Multipath mapper found: $mapper\n"); ++ if ($mapper ne "") { ++ $path = "/dev/mapper/$mapper"; ++ sleep 5; ++ } ++ }; ++ + return ($path, $vmid, $vtype); + } + diff --git a/stable-5/pve-docs/api-viewer/.gitignore b/stable-5/pve-docs/api-viewer/.gitignore new file mode 100644 index 0000000..71df65e --- /dev/null +++ b/stable-5/pve-docs/api-viewer/.gitignore @@ -0,0 +1 @@ +/apidoc.js diff --git a/stable-5/pve-docs/api-viewer/apidoc-5.2-8.js.patch b/stable-5/pve-docs/api-viewer/apidoc-5.2-8.js.patch new file mode 100644 index 0000000..af861f2 --- /dev/null +++ b/stable-5/pve-docs/api-viewer/apidoc-5.2-8.js.patch @@ -0,0 +1,66 @@ +--- apidoc.js.orig 2018-08-19 10:18:11.715767285 -0400 ++++ apidoc.js.new 2018-08-19 10:17:09.364282178 -0400 +@@ -27584,6 +27584,31 @@ + "type" : "string", + "typetext" : "" + }, ++ "freenas_user" : { ++ "description" : "FreeNAS user for API access", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, ++ "freenas_password" : { ++ "description" : "FreeNAS password for API access", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, ++ "freenas_use_ssl" : { ++ "description" : "FreeNAS API access via SSL", ++ "optional" : 1, ++ "type" : "boolean", ++ "typetext" : "" ++ }, ++ "freenas_apiv4_host" : { ++ "description" : "FreeNAS API Host via IPv4", ++ "format" : "address", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, + "content" : { + "description" : "Allowed content types.\n\nNOTE: the value 'rootdir' is used for Containers, and value 'images' for VMs.\n", + "format" : "pve-storage-content-list", +@@ -27948,6 +27973,31 @@ + "optional" : 1, + "type" : "string", + "typetext" : "" ++ }, ++ "freenas_user" : { ++ "description" : "FreeNAS user for API access", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, ++ "freenas_password" : { ++ "description" : "FreeNAS password for API access", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, ++ "freenas_use_ssl" : { ++ "description" : "FreeNAS API access via SSL", ++ "optional" : 1, ++ "type" : "boolean", ++ "typetext" : "" ++ }, ++ "freenas_apiv4_host" : { ++ "description" : "FreeNAS API Host via IPv4", ++ "format" : "address", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" + }, + "content" : { + "description" : "Allowed content types.\n\nNOTE: the value 'rootdir' is used for Containers, and value 'images' for VMs.\n", diff --git a/stable-5/pve-docs/api-viewer/apidoc-5.2-9.js.patch b/stable-5/pve-docs/api-viewer/apidoc-5.2-9.js.patch new file mode 100644 index 0000000..f726c6b --- /dev/null +++ b/stable-5/pve-docs/api-viewer/apidoc-5.2-9.js.patch @@ -0,0 +1,79 @@ +--- apidoc-5.2-9.js 2018-11-10 14:28:44.022355849 -0500 ++++ apidoc.js 2018-11-10 15:49:38.873720011 -0500 +@@ -32448,6 +32448,31 @@ + "type" : "string", + "typetext" : "" + }, ++ "freenas_user" : { ++ "description" : "FreeNAS user for API access", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, ++ "freenas_password" : { ++ "description" : "FreeNAS password for API access", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, ++ "freenas_use_ssl" : { ++ "description" : "FreeNAS API access via SSL", ++ "optional" : 1, ++ "type" : "boolean", ++ "typetext" : "" ++ }, ++ "freenas_apiv4_host" : { ++ "description" : "FreeNAS API Host via IPv4", ++ "format" : "address", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, + "fuse" : { + "description" : "Mount CephFS through FUSE.", + "optional" : 1, +@@ -32604,6 +32629,12 @@ + "type" : "boolean", + "typetext" : "" + }, ++ "target" : { ++ "description" : "iSCSI target.", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, + "transport" : { + "description" : "Gluster transport: tcp or rdma", + "enum" : [ +@@ -32810,6 +32841,31 @@ + "optional" : 1, + "type" : "string", + "typetext" : "" ++ }, ++ "freenas_user" : { ++ "description" : "FreeNAS user for API access", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, ++ "freenas_password" : { ++ "description" : "FreeNAS password for API access", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, ++ "freenas_use_ssl" : { ++ "description" : "FreeNAS API access via SSL", ++ "optional" : 1, ++ "type" : "boolean", ++ "typetext" : "" ++ }, ++ "freenas_apiv4_host" : { ++ "description" : "FreeNAS API Host via IPv4", ++ "format" : "address", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" + }, + "fuse" : { + "description" : "Mount CephFS through FUSE.", diff --git a/stable-5/pve-docs/api-viewer/apidoc-5.3-1_1.js.patch b/stable-5/pve-docs/api-viewer/apidoc-5.3-1_1.js.patch new file mode 100644 index 0000000..47bdbd2 --- /dev/null +++ b/stable-5/pve-docs/api-viewer/apidoc-5.3-1_1.js.patch @@ -0,0 +1,79 @@ +--- apidoc-5.3-1.js 2018-12-21 12:46:55.459865478 -0500 ++++ apidoc.js 2018-12-06 15:50:21.487987807 -0500 +@@ -33477,6 +33477,31 @@ + "type" : "string", + "typetext" : "" + }, ++ "freenas_user" : { ++ "description" : "FreeNAS user for API access", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, ++ "freenas_password" : { ++ "description" : "FreeNAS password for API access", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, ++ "freenas_use_ssl" : { ++ "description" : "FreeNAS API access via SSL", ++ "optional" : 1, ++ "type" : "boolean", ++ "typetext" : "" ++ }, ++ "freenas_apiv4_host" : { ++ "description" : "FreeNAS API Host via IPv4", ++ "format" : "address", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, + "fuse" : { + "description" : "Mount CephFS through FUSE.", + "optional" : 1, +@@ -33633,6 +33658,12 @@ + "type" : "boolean", + "typetext" : "" + }, ++ "target" : { ++ "description" : "iSCSI target.", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, + "transport" : { + "description" : "Gluster transport: tcp or rdma", + "enum" : [ +@@ -33840,6 +33871,31 @@ + "optional" : 1, + "type" : "string", + "typetext" : "" ++ }, ++ "freenas_user" : { ++ "description" : "FreeNAS user for API access", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, ++ "freenas_password" : { ++ "description" : "FreeNAS password for API access", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, ++ "freenas_use_ssl" : { ++ "description" : "FreeNAS API access via SSL", ++ "optional" : 1, ++ "type" : "boolean", ++ "typetext" : "" ++ }, ++ "freenas_apiv4_host" : { ++ "description" : "FreeNAS API Host via IPv4", ++ "format" : "address", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" + }, + "fuse" : { + "description" : "Mount CephFS through FUSE.", diff --git a/stable-5/pve-docs/api-viewer/apidoc-5.3-3_1.js.patch b/stable-5/pve-docs/api-viewer/apidoc-5.3-3_1.js.patch new file mode 100644 index 0000000..ff25121 --- /dev/null +++ b/stable-5/pve-docs/api-viewer/apidoc-5.3-3_1.js.patch @@ -0,0 +1,79 @@ +--- apidoc.js.orig 2019-02-20 06:20:05.000000000 -0500 ++++ apidoc.js 2019-02-26 20:51:26.857204965 -0500 +@@ -33709,6 +33709,31 @@ + "type" : "string", + "typetext" : "" + }, ++ "freenas_user" : { ++ "description" : "FreeNAS user for API access", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, ++ "freenas_password" : { ++ "description" : "FreeNAS password for API access", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, ++ "freenas_use_ssl" : { ++ "description" : "FreeNAS API access via SSL", ++ "optional" : 1, ++ "type" : "boolean", ++ "typetext" : "" ++ }, ++ "freenas_apiv4_host" : { ++ "description" : "FreeNAS API Host via IPv4", ++ "format" : "address", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, + "fuse" : { + "description" : "Mount CephFS through FUSE.", + "optional" : 1, +@@ -33865,6 +33890,12 @@ + "type" : "boolean", + "typetext" : "" + }, ++ "target" : { ++ "description" : "iSCSI target.", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, + "transport" : { + "description" : "Gluster transport: tcp or rdma", + "enum" : [ +@@ -34071,6 +34102,31 @@ + "optional" : 1, + "type" : "string", + "typetext" : "" ++ }, ++ "freenas_user" : { ++ "description" : "FreeNAS user for API access", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, ++ "freenas_password" : { ++ "description" : "FreeNAS password for API access", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, ++ "freenas_use_ssl" : { ++ "description" : "FreeNAS API access via SSL", ++ "optional" : 1, ++ "type" : "boolean", ++ "typetext" : "" ++ }, ++ "freenas_apiv4_host" : { ++ "description" : "FreeNAS API Host via IPv4", ++ "format" : "address", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" + }, + "fuse" : { + "description" : "Mount CephFS through FUSE.", diff --git a/stable-5/pve-docs/api-viewer/apidoc-5.4-2_1.js.patch b/stable-5/pve-docs/api-viewer/apidoc-5.4-2_1.js.patch new file mode 100644 index 0000000..a054d90 --- /dev/null +++ b/stable-5/pve-docs/api-viewer/apidoc-5.4-2_1.js.patch @@ -0,0 +1,79 @@ +--- apidoc.js.orig 2019-04-08 02:02:09.000000000 -0400 ++++ apidoc.js 2019-05-11 10:34:28.305764709 -0400 +@@ -34385,6 +34385,31 @@ + "type" : "string", + "typetext" : "" + }, ++ "freenas_user" : { ++ "description" : "FreeNAS user for API access", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, ++ "freenas_password" : { ++ "description" : "FreeNAS password for API access", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, ++ "freenas_use_ssl" : { ++ "description" : "FreeNAS API access via SSL", ++ "optional" : 1, ++ "type" : "boolean", ++ "typetext" : "" ++ }, ++ "freenas_apiv4_host" : { ++ "description" : "FreeNAS API Host via IPv4", ++ "format" : "address", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, + "fuse" : { + "description" : "Mount CephFS through FUSE.", + "optional" : 1, +@@ -34541,6 +34566,12 @@ + "type" : "boolean", + "typetext" : "" + }, ++ "target" : { ++ "description" : "iSCSI target.", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, + "transport" : { + "description" : "Gluster transport: tcp or rdma", + "enum" : [ +@@ -34748,6 +34779,31 @@ + "optional" : 1, + "type" : "string", + "typetext" : "" ++ }, ++ "freenas_user" : { ++ "description" : "FreeNAS user for API access", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, ++ "freenas_password" : { ++ "description" : "FreeNAS password for API access", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, ++ "freenas_use_ssl" : { ++ "description" : "FreeNAS API access via SSL", ++ "optional" : 1, ++ "type" : "boolean", ++ "typetext" : "" ++ }, ++ "freenas_apiv4_host" : { ++ "description" : "FreeNAS API Host via IPv4", ++ "format" : "address", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" + }, + "fuse" : { + "description" : "Mount CephFS through FUSE.", diff --git a/stable-5/pve-manager/js/.gitignore b/stable-5/pve-manager/js/.gitignore new file mode 100644 index 0000000..7ad0727 --- /dev/null +++ b/stable-5/pve-manager/js/.gitignore @@ -0,0 +1 @@ +/pvemanagerlib.js diff --git a/stable-5/pve-manager/js/pvemanagerlib-5.2-10.js.patch b/stable-5/pve-manager/js/pvemanagerlib-5.2-10.js.patch new file mode 100644 index 0000000..ce35642 --- /dev/null +++ b/stable-5/pve-manager/js/pvemanagerlib-5.2-10.js.patch @@ -0,0 +1,167 @@ +--- pvemanagerlib-5.2-10.js 2018-10-23 07:18:18.058603386 -0400 ++++ pvemanagerlib.js 2018-10-23 15:29:52.573563883 -0400 +@@ -5597,6 +5597,7 @@ + alias: ['widget.pveiScsiProviderSelector'], + comboItems: [ + ['comstar', 'Comstar'], ++ ['freenas', 'FreeNAS-API'], + [ 'istgt', 'istgt'], + [ 'iet', 'IET'], + [ 'LIO', 'LIO'] +@@ -28583,6 +28584,7 @@ + data: { + isLIO: false, + isComstar: true, ++ isFreeNAS: false, + hasWriteCacheOption: true + } + }, +@@ -28595,10 +28597,19 @@ + } + }, + changeISCSIProvider: function(f, newVal, oldVal) { ++ var me = this; + var vm = this.getViewModel(); + vm.set('isLIO', newVal === 'LIO'); + vm.set('isComstar', newVal === 'comstar'); +- vm.set('hasWriteCacheOption', newVal === 'comstar' || newVal === 'istgt'); ++ vm.set('isFreeNAS', newVal === 'freenas'); ++ vm.set('hasWriteCacheOption', newVal === 'comstar' || newVal === 'freenas' || newVal === 'istgt'); ++ if (newVal !== 'freenas') { ++ me.lookupReference('freenas_use_ssl_field').setValue(false); ++ me.lookupReference('freenas_apiv4_host_field').setValue(''); ++ me.lookupReference('freenas_user_field').setValue(''); ++ me.lookupReference('freenas_password_field').setValue(''); ++ me.lookupReference('freenas_confirmpw_field').setValue(''); ++ } + } + }, + +@@ -28616,6 +28627,7 @@ + }, + + setValues: function diff(values) { ++ values.freenas_confirmpw = values.freenas_password; + values.writecache = values.nowritecache ? 0 : 1; + this.callParent([values]); + }, +@@ -28632,7 +28644,7 @@ + allowBlank: false + }, + { +- xtype: me.isCreate ? 'textfield' : 'displayfield', ++ xtype: 'textfield', + name: 'pool', + value: '', + fieldLabel: gettext('Pool'), +@@ -28646,7 +28658,7 @@ + allowBlank: false + }, + { +- xtype: me.isCreate ? 'textfield' : 'displayfield', ++ xtype: 'textfield', + name: 'target', + value: '', + fieldLabel: gettext('Target'), +@@ -28657,8 +28669,28 @@ + name: 'comstar_tg', + value: '', + fieldLabel: gettext('Target group'), +- bind: me.isCreate ? { disabled: '{!isComstar}' } : { hidden: '{!isComstar}' }, ++ bind: { hidden: '{!isComstar}' }, + allowBlank: true ++ }, ++ { ++ xtype: 'proxmoxcheckbox', ++ name: 'freenas_use_ssl', ++ reference: 'freenas_use_ssl_field', ++ inputId: 'freenas_use_ssl_field', ++ checked: false, ++ bind: { hidden: '{!isFreeNAS}' }, ++ uncheckedValue: 0, ++ fieldLabel: gettext('API use SSL') ++ }, ++ { ++ xtype: 'textfield', ++ name: 'freenas_user', ++ reference: 'freenas_user_field', ++ inputId: 'freenas_user_field', ++ value: '', ++ allowBlank: false, ++ fieldLabel: gettext('API Username'), ++ bind: { hidden: '{!isFreeNAS}' }, + } + ]; + +@@ -28689,7 +28721,7 @@ + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'comstar_hg', + value: '', +- bind: me.isCreate ? { disabled: '{!isComstar}' } : { hidden: '{!isComstar}' }, ++ bind: { hidden: '{!isComstar}' }, + fieldLabel: gettext('Host group'), + allowBlank: true + }, +@@ -28697,9 +28729,60 @@ + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'lio_tpg', + value: '', +- bind: me.isCreate ? { disabled: '{!isLIO}' } : { hidden: '{!isLIO}' }, ++ bind: { hidden: '{!isLIO}' }, ++ fieldLabel: gettext('Target portal group'), ++ allowBlank: true ++ }, ++ { ++ xtype: 'proxmoxtextfield', ++ name: 'freenas_apiv4_host', ++ reference: 'freenas_apiv4_host_field', ++ value: '', ++ editable: true, ++ allowBlank: true, ++ emptyText: Proxmox.Utils.noneText, ++ bind: { hidden: '{!isFreeNAS}' }, ++ fieldLabel: gettext('API IPv4 Host'), ++ allowBlank: true ++ }, ++ { ++ xtype: 'proxmoxtextfield', ++ name: 'freenas_password', ++ reference: 'freenas_password_field', ++ inputType: me.isCreate ? '' : 'password', ++ value: '', ++ editable: true, ++ deleteEmpty: true, ++ allowBlank: false, ++ emptyText: Proxmox.Utils.noneText, ++ bind: { hidden: '{!isFreeNAS}' }, ++ fieldLabel: gettext('API Password'), ++ change: function(f, value) { ++ if (f.rendered) { ++ f.up().down('field[name=freenas_confirmpw]').validate(); ++ } ++ } ++ }, ++ { ++ xtype: 'proxmoxtextfield', ++ name: 'freenas_confirmpw', ++ reference: 'freenas_confirmpw_field', ++ inputType: me.isCreate ? '' : 'password', ++ value: '', ++ editable: true, ++ deleteEmpty: true, + allowBlank: false, +- fieldLabel: gettext('Target portal group') ++ submitValue: false, ++ emptyText: Proxmox.Utils.noneText, ++ bind: { hidden: '{!isFreeNAS}' }, ++ fieldLabel: gettext('Confirm Password'), ++ validator: function(value) { ++ var pw = this.up().down('field[name=freenas_password]').getValue(); ++ if (pw !== value) { ++ return "Passwords do not match!"; ++ } ++ return true; ++ } + } + ]; + diff --git a/stable-5/pve-manager/js/pvemanagerlib-5.2-6.js.patch b/stable-5/pve-manager/js/pvemanagerlib-5.2-6.js.patch new file mode 100644 index 0000000..5bd8066 --- /dev/null +++ b/stable-5/pve-manager/js/pvemanagerlib-5.2-6.js.patch @@ -0,0 +1,86 @@ +--- pvemanagerlib.js.orig 2018-07-30 23:13:28.045035059 -0400 ++++ pvemanagerlib.js.new 2018-08-19 10:42:58.494724196 -0400 +@@ -5379,6 +5379,7 @@ + alias: ['widget.pveiScsiProviderSelector'], + comboItems: [ + ['comstar', 'Comstar'], ++ ['freenas', 'FreeNAS-API'], + [ 'istgt', 'istgt'], + [ 'iet', 'IET'] + ] +@@ -27361,7 +27362,23 @@ + value: '', + fieldLabel: gettext('Target group'), + allowBlank: true +- } ++ }, ++ { ++ xtype: 'proxmoxcheckbox', ++ name: 'freenas_use_ssl', ++ checked: false, ++ uncheckedValue: 0, ++ hidden: me.iscsiprovider !== "freenas", ++ fieldLabel: gettext('FreeNAS API use SSL') ++ }, ++ { ++ xtype: me.isCreate ? 'textfield' : 'displayfield', ++ name: 'freenas_user', ++ value: '', ++ hidden: me.iscsiprovider !== "freenas", ++ fieldLabel: gettext('FreeNAS User'), ++ allowBlank: true ++ }, + ]; + + me.column2 = [ +@@ -27370,7 +27387,26 @@ + name: 'iscsiprovider', + value: 'comstar', + fieldLabel: gettext('iSCSI Provider'), +- allowBlank: false ++ allowBlank: false, ++ listeners: { ++ change: function(f, value) { ++ if (value === "freenas") { ++ me.down('field[name=freenas_use_ssl]').setHidden(false); ++ me.down('field[name=freenas_apiv4_host]').setHidden(false); ++ me.down('field[name=freenas_user]').setHidden(false); ++ me.down('field[name=freenas_password]').setHidden(false); ++ } else { ++ me.down('field[name=freenas_use_ssl]').setHidden(true); ++ me.down('field[name=freenas_use_ssl]').setValue(false); ++ me.down('field[name=freenas_apiv4_host]').setHidden(true); ++ me.down('field[name=freenas_apiv4_host]').setValue(false); ++ me.down('field[name=freenas_user]').setHidden(true); ++ me.down('field[name=freenas_user]').setValue(''); ++ me.down('field[name=freenas_password]').setHidden(true); ++ me.down('field[name=freenas_password]').setValue(''); ++ } ++ } ++ } + }, + { + xtype: 'proxmoxcheckbox', +@@ -27392,6 +27428,22 @@ + value: '', + fieldLabel: gettext('Host group'), + allowBlank: true ++ }, ++ { ++ xtype: me.isCreate ? 'textfield' : 'displayfield', ++ name: 'freenas_apiv4_host', ++ value: '', ++ hidden: me.iscsiprovider !== "freenas", ++ fieldLabel: gettext('API IPv4 Host'), ++ allowBlank: true ++ }, ++ { ++ xtype: me.isCreate ? 'textfield' : 'displayfield', ++ name: 'freenas_password', ++ value: '', ++ hidden: me.iscsiprovider !== "freenas", ++ fieldLabel: gettext('FreeNAS Password'), ++ allowBlank: true + } + ]; + diff --git a/stable-5/pve-manager/js/pvemanagerlib-5.2-8.js.patch b/stable-5/pve-manager/js/pvemanagerlib-5.2-8.js.patch new file mode 100644 index 0000000..7490e05 --- /dev/null +++ b/stable-5/pve-manager/js/pvemanagerlib-5.2-8.js.patch @@ -0,0 +1,102 @@ +--- pvemanagerlib.js.5.2-8.js 2018-08-30 20:10:52.957313992 -0400 ++++ pvemanagerlib.js.new 2018-09-01 16:20:05.131908768 -0400 +@@ -28578,6 +28578,7 @@ + data: { + isLIO: false, + isComstar: true, ++ isFreeNAS: false, + hasWriteCacheOption: true + } + }, +@@ -28590,11 +28591,18 @@ + } + }, + changeISCSIProvider: function(f, newVal, oldVal) { ++ var me = this; + var vm = this.getViewModel(); + vm.set('isLIO', newVal === 'LIO'); + vm.set('isComstar', newVal === 'comstar'); + vm.set('isFreeNAS', newVal === 'freenas'); +- vm.set('hasWriteCacheOption', newVal === 'comstar' || newVal === 'istgt'); ++ vm.set('hasWriteCacheOption', newVal === 'comstar' || newVal === 'freenas' || newVal === 'istgt'); ++ if (newVal !== 'freenas') { ++ me.lookupReference('freenas_use_ssl_field').setValue(false); ++ me.lookupReference('freenas_apiv4_host_field').setValue(''); ++ me.lookupReference('freenas_user_field').setValue(''); ++ me.lookupReference('freenas_password_field').setValue(''); ++ } + } + }, + +@@ -28653,16 +28661,28 @@ + name: 'comstar_tg', + value: '', + fieldLabel: gettext('Target group'), +- bind: me.isCreate ? { disabled: '{!isComstar}' } : { hidden: '{!isComstar}' }, ++ bind: me.isCreate ? { hidden: '{!isComstar}' } : { hidden: '{!isComstar}' }, + allowBlank: true + }, + { ++ xtype: 'proxmoxcheckbox', ++ name: 'freenas_use_ssl', ++ reference: 'freenas_use_ssl_field', ++ inputId: 'freenas_use_ssl_field', ++ checked: false, ++ bind: me.isCreate ? { hidden: '{!isFreeNAS}' } : { hidden: '{!isFreeNAS}' }, ++ uncheckedValue: 0, ++ fieldLabel: gettext('API use SSL') ++ }, ++ { + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'freenas_user', ++ reference: 'freenas_user_field', ++ inputId: 'freenas_user_field', + value: '', +- fieldLabel: gettext('FreeNAS User'), ++ fieldLabel: gettext('API Username'), + bind: me.isCreate ? { hidden: '{!isFreeNAS}' } : { hidden: '{!isFreeNAS}' }, +- allowBlank: true ++ allowBlank: me.isFreeNAS ? false : true + } + ]; + +@@ -28693,7 +28713,7 @@ + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'comstar_hg', + value: '', +- bind: me.isCreate ? { disabled: '{!isComstar}' } : { hidden: '{!isComstar}' }, ++ bind: me.isCreate ? { hidden: '{!isComstar}' } : { hidden: '{!isComstar}' }, + fieldLabel: gettext('Host group'), + allowBlank: true + }, +@@ -28701,9 +28721,27 @@ + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'lio_tpg', + value: '', +- bind: me.isCreate ? { disabled: '{!isLIO}' } : { hidden: '{!isLIO}' }, +- allowBlank: false, +- fieldLabel: gettext('Target portal group') ++ bind: me.isCreate ? { hidden: '{!isLIO}' } : { hidden: '{!isLIO}' }, ++ fieldLabel: gettext('Target portal group'), ++ allowBlank: true ++ }, ++ { ++ xtype: me.isCreate ? 'textfield' : 'displayfield', ++ name: 'freenas_apiv4_host', ++ reference: 'freenas_apiv4_host_field', ++ value: '', ++ bind: me.isCreate ? { hidden: '{!isFreeNAS}' } : { hidden: '{!isFreeNAS}' }, ++ fieldLabel: gettext('API IPv4 Host'), ++ allowBlank: true ++ }, ++ { ++ xtype: me.isCreate ? 'textfield' : 'displayfield', ++ name: 'freenas_password', ++ reference: 'freenas_password_field', ++ value: '', ++ bind: me.isCreate ? { hidden: '{!isFreeNAS}' } : { hidden: '{!isFreeNAS}' }, ++ fieldLabel: gettext('API Password'), ++ allowBlank: true + } + ]; + diff --git a/stable-5/pve-manager/js/pvemanagerlib-5.2-9_2.js.patch b/stable-5/pve-manager/js/pvemanagerlib-5.2-9_2.js.patch new file mode 100644 index 0000000..f6c5657 --- /dev/null +++ b/stable-5/pve-manager/js/pvemanagerlib-5.2-9_2.js.patch @@ -0,0 +1,169 @@ +--- pvemanagerlib-5.2-9.js 2018-10-16 07:17:21.915593478 -0400 ++++ pvemanagerlib.js 2018-10-21 21:52:20.781740237 -0400 +@@ -5597,6 +5597,7 @@ + alias: ['widget.pveiScsiProviderSelector'], + comboItems: [ + ['comstar', 'Comstar'], ++ ['freenas', 'FreeNAS-API'], + [ 'istgt', 'istgt'], + [ 'iet', 'IET'], + [ 'LIO', 'LIO'] +@@ -28574,6 +28575,7 @@ + data: { + isLIO: false, + isComstar: true, ++ isFreeNAS: false, + hasWriteCacheOption: true + } + }, +@@ -28586,10 +28588,19 @@ + } + }, + changeISCSIProvider: function(f, newVal, oldVal) { ++ var me = this; + var vm = this.getViewModel(); + vm.set('isLIO', newVal === 'LIO'); + vm.set('isComstar', newVal === 'comstar'); +- vm.set('hasWriteCacheOption', newVal === 'comstar' || newVal === 'istgt'); ++ vm.set('isFreeNAS', newVal === 'freenas'); ++ vm.set('hasWriteCacheOption', newVal === 'comstar' || newVal === 'freenas' || newVal === 'istgt'); ++ if (newVal !== 'freenas') { ++ me.lookupReference('freenas_use_ssl_field').setValue(false); ++ me.lookupReference('freenas_apiv4_host_field').setValue(''); ++ me.lookupReference('freenas_user_field').setValue(''); ++ me.lookupReference('freenas_password_field').setValue(''); ++ me.lookupReference('freenas_confirmpw_field').setValue(''); ++ } + } + }, + +@@ -28607,6 +28618,7 @@ + }, + + setValues: function diff(values) { ++ values.freenas_confirmpw = values.freenas_password; + values.writecache = values.nowritecache ? 0 : 1; + this.callParent([values]); + }, +@@ -28623,7 +28635,7 @@ + allowBlank: false + }, + { +- xtype: me.isCreate ? 'textfield' : 'displayfield', ++ xtype: 'textfield', + name: 'pool', + value: '', + fieldLabel: gettext('Pool'), +@@ -28637,7 +28649,7 @@ + allowBlank: false + }, + { +- xtype: me.isCreate ? 'textfield' : 'displayfield', ++ xtype: 'textfield', + name: 'target', + value: '', + fieldLabel: gettext('Target'), +@@ -28648,8 +28660,28 @@ + name: 'comstar_tg', + value: '', + fieldLabel: gettext('Target group'), +- bind: me.isCreate ? { disabled: '{!isComstar}' } : { hidden: '{!isComstar}' }, ++ bind: { hidden: '{!isComstar}' }, + allowBlank: true ++ }, ++ { ++ xtype: 'proxmoxcheckbox', ++ name: 'freenas_use_ssl', ++ reference: 'freenas_use_ssl_field', ++ inputId: 'freenas_use_ssl_field', ++ checked: false, ++ bind: { hidden: '{!isFreeNAS}' }, ++ uncheckedValue: 0, ++ fieldLabel: gettext('API use SSL') ++ }, ++ { ++ xtype: 'textfield', ++ name: 'freenas_user', ++ reference: 'freenas_user_field', ++ inputId: 'freenas_user_field', ++ value: '', ++ allowBlank: false, ++ fieldLabel: gettext('API Username'), ++ bind: { hidden: '{!isFreeNAS}' }, + } + ]; + +@@ -28680,7 +28712,7 @@ + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'comstar_hg', + value: '', +- bind: me.isCreate ? { disabled: '{!isComstar}' } : { hidden: '{!isComstar}' }, ++ bind: { hidden: '{!isComstar}' }, + fieldLabel: gettext('Host group'), + allowBlank: true + }, +@@ -28688,9 +28720,61 @@ + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'lio_tpg', + value: '', +- bind: me.isCreate ? { disabled: '{!isLIO}' } : { hidden: '{!isLIO}' }, +- allowBlank: false, +- fieldLabel: gettext('Target portal group') ++ bind: { hidden: '{!isLIO}' }, ++ fieldLabel: gettext('Target portal group'), ++ allowBlank: true ++ }, ++ { ++ xtype: 'proxmoxtextfield', ++ name: 'freenas_apiv4_host', ++ reference: 'freenas_apiv4_host_field', ++ value: '', ++ editable: true, ++ deleteEmpty: true, ++ allowBlank: true, ++ emptyText: Proxmox.Utils.noneText, ++ bind: { hidden: '{!isFreeNAS}' }, ++ fieldLabel: gettext('API IPv4 Host'), ++ allowBlank: true ++ }, ++ { ++ xtype: 'proxmoxtextfield', ++ name: 'freenas_password', ++ reference: 'freenas_password_field', ++ inputType: me.isCreate ? '' : 'password', ++ value: '', ++ editable: true, ++ deleteEmpty: true, ++ allowBlank: false, ++ emptyText: Proxmox.Utils.noneText, ++ bind: { hidden: '{!isFreeNAS}' }, ++ fieldLabel: gettext('API Password'), ++ change: function(f, value) { ++ if (f.rendered) { ++ f.up().down('field[name=freenas_confirmpw]').validate(); ++ } ++ } ++ }, ++ { ++ xtype: 'proxmoxtextfield', ++ name: 'freenas_confirmpw', ++ reference: 'freenas_confirmpw_field', ++ inputType: me.isCreate ? '' : 'password', ++ value: '', ++ editable: true, ++ deleteEmpty: true, ++ allowBlank: false, ++ submitValue: false, ++ emptyText: Proxmox.Utils.noneText, ++ bind: { hidden: '{!isFreeNAS}' }, ++ fieldLabel: gettext('Confirm Password'), ++ validator: function(value) { ++ var pw = this.up().down('field[name=freenas_password]').getValue(); ++ if (pw !== value) { ++ return "Passwords do not match!"; ++ } ++ return true; ++ } + } + ]; + diff --git a/stable-5/pve-manager/js/pvemanagerlib-5.3-11_1.js.patch b/stable-5/pve-manager/js/pvemanagerlib-5.3-11_1.js.patch new file mode 100644 index 0000000..cfb2f99 --- /dev/null +++ b/stable-5/pve-manager/js/pvemanagerlib-5.3-11_1.js.patch @@ -0,0 +1,189 @@ +--- pvemanagerlib.js.orig 2019-02-20 13:40:43.000000000 -0500 ++++ pvemanagerlib.js 2019-02-26 20:49:41.032327478 -0500 +@@ -5920,6 +5920,7 @@ + alias: ['widget.pveiScsiProviderSelector'], + comboItems: [ + ['comstar', 'Comstar'], ++ ['freenas', 'FreeNAS-API'], + [ 'istgt', 'istgt'], + [ 'iet', 'IET'], + [ 'LIO', 'LIO'] +@@ -30182,6 +30183,7 @@ + data: { + isLIO: false, + isComstar: true, ++ isFreeNAS: false, + hasWriteCacheOption: true + } + }, +@@ -30194,10 +30196,26 @@ + } + }, + changeISCSIProvider: function(f, newVal, oldVal) { ++ var me = this; + var vm = this.getViewModel(); + vm.set('isLIO', newVal === 'LIO'); + vm.set('isComstar', newVal === 'comstar'); +- vm.set('hasWriteCacheOption', newVal === 'comstar' || newVal === 'istgt'); ++ vm.set('isFreeNAS', newVal === 'freenas'); ++ vm.set('hasWriteCacheOption', newVal === 'comstar' || newVal === 'freenas' || newVal === 'istgt'); ++ if (newVal !== 'freenas') { ++ me.lookupReference('freenas_use_ssl_field').setValue(false); ++ me.lookupReference('freenas_apiv4_host_field').setValue(''); ++ me.lookupReference('freenas_user_field').setValue(''); ++ me.lookupReference('freenas_user_field').allowBlank = true; ++ me.lookupReference('freenas_password_field').setValue(''); ++ me.lookupReference('freenas_password_field').allowBlank = true; ++ me.lookupReference('freenas_confirmpw_field').setValue(''); ++ me.lookupReference('freenas_confirmpw_field').allowBlank = true; ++ } else { ++ me.lookupReference('freenas_user_field').allowBlank = false; ++ me.lookupReference('freenas_password_field').allowBlank = false; ++ me.lookupReference('freenas_confirmpw_field').allowBlank = false; ++ } + } + }, + +@@ -30215,6 +30233,7 @@ + }, + + setValues: function diff(values) { ++ values.freenas_confirmpw = values.freenas_password; + values.writecache = values.nowritecache ? 0 : 1; + this.callParent([values]); + }, +@@ -30231,7 +30250,7 @@ + allowBlank: false + }, + { +- xtype: me.isCreate ? 'textfield' : 'displayfield', ++ xtype: 'textfield', + name: 'pool', + value: '', + fieldLabel: gettext('Pool'), +@@ -30241,11 +30260,11 @@ + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'blocksize', + value: '4k', +- fieldLabel: gettext('Block Size'), ++ fieldLabel: gettext('ZFS Block Size'), + allowBlank: false + }, + { +- xtype: me.isCreate ? 'textfield' : 'displayfield', ++ xtype: 'textfield', + name: 'target', + value: '', + fieldLabel: gettext('Target'), +@@ -30256,8 +30275,33 @@ + name: 'comstar_tg', + value: '', + fieldLabel: gettext('Target group'), +- bind: me.isCreate ? { disabled: '{!isComstar}' } : { hidden: '{!isComstar}' }, ++ bind: { ++ hidden: '{!isComstar}' ++ }, + allowBlank: true ++ }, ++ { ++ xtype: 'proxmoxcheckbox', ++ name: 'freenas_use_ssl', ++ reference: 'freenas_use_ssl_field', ++ inputId: 'freenas_use_ssl_field', ++ checked: false, ++ bind: { ++ hidden: '{!isFreeNAS}' ++ }, ++ uncheckedValue: 0, ++ fieldLabel: gettext('API use SSL') ++ }, ++ { ++ xtype: 'textfield', ++ name: 'freenas_user', ++ reference: 'freenas_user_field', ++ inputId: 'freenas_user_field', ++ value: '', ++ fieldLabel: gettext('API Username'), ++ bind: { ++ hidden: '{!isFreeNAS}' ++ } + } + ]; + +@@ -30288,7 +30332,9 @@ + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'comstar_hg', + value: '', +- bind: me.isCreate ? { disabled: '{!isComstar}' } : { hidden: '{!isComstar}' }, ++ bind: { ++ hidden: '{!isComstar}' ++ }, + fieldLabel: gettext('Host group'), + allowBlank: true + }, +@@ -30296,9 +30342,62 @@ + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'lio_tpg', + value: '', +- bind: me.isCreate ? { disabled: '{!isLIO}' } : { hidden: '{!isLIO}' }, +- allowBlank: false, +- fieldLabel: gettext('Target portal group') ++ bind: { ++ hidden: '{!isLIO}' ++ }, ++ fieldLabel: gettext('Target portal group'), ++ allowBlank: true ++ }, ++ { ++ xtype: 'proxmoxtextfield', ++ name: 'freenas_apiv4_host', ++ reference: 'freenas_apiv4_host_field', ++ value: '', ++ editable: true, ++ emptyText: Proxmox.Utils.noneText, ++ bind: { ++ hidden: '{!isFreeNAS}' ++ }, ++ fieldLabel: gettext('API IPv4 Host'), ++ }, ++ { ++ xtype: 'proxmoxtextfield', ++ name: 'freenas_password', ++ reference: 'freenas_password_field', ++ inputType: me.isCreate ? '' : 'password', ++ value: '', ++ editable: true, ++ emptyText: Proxmox.Utils.noneText, ++ bind: { ++ hidden: '{!isFreeNAS}' ++ }, ++ fieldLabel: gettext('API Password'), ++ change: function(f, value) { ++ if (f.rendered) { ++ f.up().down('field[name=freenas_confirmpw]').validate(); ++ } ++ } ++ }, ++ { ++ xtype: 'proxmoxtextfield', ++ name: 'freenas_confirmpw', ++ reference: 'freenas_confirmpw_field', ++ inputType: me.isCreate ? '' : 'password', ++ value: '', ++ editable: true, ++ submitValue: false, ++ emptyText: Proxmox.Utils.noneText, ++ bind: { ++ hidden: '{!isFreeNAS}' ++ }, ++ fieldLabel: gettext('Confirm Password'), ++ validator: function(value) { ++ var pw = this.up().down('field[name=freenas_password]').getValue(); ++ if (pw !== value) { ++ return "Passwords do not match!"; ++ } ++ return true; ++ } + } + ]; + diff --git a/stable-5/pve-manager/js/pvemanagerlib-5.3-5_3.js.patch b/stable-5/pve-manager/js/pvemanagerlib-5.3-5_3.js.patch new file mode 100644 index 0000000..07b399f --- /dev/null +++ b/stable-5/pve-manager/js/pvemanagerlib-5.3-5_3.js.patch @@ -0,0 +1,172 @@ +--- pvemanagerlib-5.3-5.js 2018-12-21 12:34:35.727962756 -0500 ++++ pvemanagerlib.js 2018-12-21 12:43:02.370462786 -0500 +@@ -5854,6 +5854,7 @@ + alias: ['widget.pveiScsiProviderSelector'], + comboItems: [ + ['comstar', 'Comstar'], ++ ['freenas', 'FreeNAS-API'], + [ 'istgt', 'istgt'], + [ 'iet', 'IET'], + [ 'LIO', 'LIO'] +@@ -29983,6 +29984,7 @@ + data: { + isLIO: false, + isComstar: true, ++ isFreeNAS: false, + hasWriteCacheOption: true + } + }, +@@ -29995,10 +29997,19 @@ + } + }, + changeISCSIProvider: function(f, newVal, oldVal) { ++ var me = this; + var vm = this.getViewModel(); + vm.set('isLIO', newVal === 'LIO'); + vm.set('isComstar', newVal === 'comstar'); +- vm.set('hasWriteCacheOption', newVal === 'comstar' || newVal === 'istgt'); ++ vm.set('isFreeNAS', newVal === 'freenas'); ++ vm.set('hasWriteCacheOption', newVal === 'comstar' || newVal === 'freenas' || newVal === 'istgt'); ++ if (newVal !== 'freenas') { ++ me.lookupReference('freenas_use_ssl_field').setValue(false); ++ me.lookupReference('freenas_apiv4_host_field').setValue(''); ++ me.lookupReference('freenas_user_field').setValue(''); ++ me.lookupReference('freenas_password_field').setValue(''); ++ me.lookupReference('freenas_confirmpw_field').setValue(''); ++ } + } + }, + +@@ -30016,6 +30027,7 @@ + }, + + setValues: function diff(values) { ++ values.freenas_confirmpw = values.freenas_password; + values.writecache = values.nowritecache ? 0 : 1; + this.callParent([values]); + }, +@@ -30032,7 +30044,7 @@ + allowBlank: false + }, + { +- xtype: me.isCreate ? 'textfield' : 'displayfield', ++ xtype: 'textfield', + name: 'pool', + value: '', + fieldLabel: gettext('Pool'), +@@ -30042,11 +30054,11 @@ + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'blocksize', + value: '4k', +- fieldLabel: gettext('Block Size'), ++ fieldLabel: gettext('ZFS Block Size'), + allowBlank: false + }, + { +- xtype: me.isCreate ? 'textfield' : 'displayfield', ++ xtype: 'textfield', + name: 'target', + value: '', + fieldLabel: gettext('Target'), +@@ -30057,8 +30069,28 @@ + name: 'comstar_tg', + value: '', + fieldLabel: gettext('Target group'), +- bind: me.isCreate ? { disabled: '{!isComstar}' } : { hidden: '{!isComstar}' }, ++ bind: { hidden: '{!isComstar}' }, + allowBlank: true ++ }, ++ { ++ xtype: 'proxmoxcheckbox', ++ name: 'freenas_use_ssl', ++ reference: 'freenas_use_ssl_field', ++ inputId: 'freenas_use_ssl_field', ++ checked: false, ++ bind: { hidden: '{!isFreeNAS}' }, ++ uncheckedValue: 0, ++ fieldLabel: gettext('API use SSL') ++ }, ++ { ++ xtype: 'textfield', ++ name: 'freenas_user', ++ reference: 'freenas_user_field', ++ inputId: 'freenas_user_field', ++ value: '', ++ allowBlank: false, ++ fieldLabel: gettext('API Username'), ++ bind: { hidden: '{!isFreeNAS}' }, + } + ]; + +@@ -30089,7 +30121,7 @@ + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'comstar_hg', + value: '', +- bind: me.isCreate ? { disabled: '{!isComstar}' } : { hidden: '{!isComstar}' }, ++ bind: { hidden: '{!isComstar}' }, + fieldLabel: gettext('Host group'), + allowBlank: true + }, +@@ -30097,9 +30129,60 @@ + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'lio_tpg', + value: '', +- bind: me.isCreate ? { disabled: '{!isLIO}' } : { hidden: '{!isLIO}' }, ++ bind: { hidden: '{!isLIO}' }, ++ fieldLabel: gettext('Target portal group'), ++ allowBlank: true ++ }, ++ { ++ xtype: 'proxmoxtextfield', ++ name: 'freenas_apiv4_host', ++ reference: 'freenas_apiv4_host_field', ++ value: '', ++ editable: true, ++ allowBlank: true, ++ emptyText: Proxmox.Utils.noneText, ++ bind: { hidden: '{!isFreeNAS}' }, ++ fieldLabel: gettext('API IPv4 Host'), ++ allowBlank: true ++ }, ++ { ++ xtype: 'proxmoxtextfield', ++ name: 'freenas_password', ++ reference: 'freenas_password_field', ++ inputType: me.isCreate ? '' : 'password', ++ value: '', ++ editable: true, ++ deleteEmpty: true, ++ allowBlank: false, ++ emptyText: Proxmox.Utils.noneText, ++ bind: { hidden: '{!isFreeNAS}' }, ++ fieldLabel: gettext('API Password'), ++ change: function(f, value) { ++ if (f.rendered) { ++ f.up().down('field[name=freenas_confirmpw]').validate(); ++ } ++ } ++ }, ++ { ++ xtype: 'proxmoxtextfield', ++ name: 'freenas_confirmpw', ++ reference: 'freenas_confirmpw_field', ++ inputType: me.isCreate ? '' : 'password', ++ value: '', ++ editable: true, ++ deleteEmpty: true, + allowBlank: false, +- fieldLabel: gettext('Target portal group') ++ submitValue: false, ++ emptyText: Proxmox.Utils.noneText, ++ bind: { hidden: '{!isFreeNAS}' }, ++ fieldLabel: gettext('Confirm Password'), ++ validator: function(value) { ++ var pw = this.up().down('field[name=freenas_password]').getValue(); ++ if (pw !== value) { ++ return "Passwords do not match!"; ++ } ++ return true; ++ } + } + ]; + diff --git a/stable-5/pve-manager/js/pvemanagerlib-5.3-6_2.js.patch b/stable-5/pve-manager/js/pvemanagerlib-5.3-6_2.js.patch new file mode 100644 index 0000000..d0e07e7 --- /dev/null +++ b/stable-5/pve-manager/js/pvemanagerlib-5.3-6_2.js.patch @@ -0,0 +1,191 @@ +--- pvemanagerlib-5.3-6.js 2018-12-21 12:54:58.650421078 -0500 ++++ pvemanagerlib.js 2019-02-01 13:52:17.906074280 -0500 +@@ -5894,6 +5894,7 @@ + alias: ['widget.pveiScsiProviderSelector'], + comboItems: [ + ['comstar', 'Comstar'], ++ ['freenas', 'FreeNAS-API'], + [ 'istgt', 'istgt'], + [ 'iet', 'IET'], + [ 'LIO', 'LIO'] +@@ -30085,6 +30086,7 @@ + data: { + isLIO: false, + isComstar: true, ++ isFreeNAS: false, + hasWriteCacheOption: true + } + }, +@@ -30097,10 +30099,26 @@ + } + }, + changeISCSIProvider: function(f, newVal, oldVal) { ++ var me = this; + var vm = this.getViewModel(); + vm.set('isLIO', newVal === 'LIO'); + vm.set('isComstar', newVal === 'comstar'); +- vm.set('hasWriteCacheOption', newVal === 'comstar' || newVal === 'istgt'); ++ vm.set('isFreeNAS', newVal === 'freenas'); ++ vm.set('hasWriteCacheOption', newVal === 'comstar' || newVal === 'freenas' || newVal === 'istgt'); ++ if (newVal !== 'freenas') { ++ me.lookupReference('freenas_use_ssl_field').setValue(false); ++ me.lookupReference('freenas_apiv4_host_field').setValue(''); ++ me.lookupReference('freenas_user_field').setValue(''); ++ me.lookupReference('freenas_user_field').allowBlank = true; ++ me.lookupReference('freenas_password_field').setValue(''); ++ me.lookupReference('freenas_password_field').allowBlank = true; ++ me.lookupReference('freenas_confirmpw_field').setValue(''); ++ me.lookupReference('freenas_confirmpw_field').allowBlank = true; ++ } else { ++ me.lookupReference('freenas_user_field').allowBlank = false; ++ me.lookupReference('freenas_password_field').allowBlank = false; ++ me.lookupReference('freenas_confirmpw_field').allowBlank = false; ++ } + } + }, + +@@ -30118,6 +30136,7 @@ + }, + + setValues: function diff(values) { ++ values.freenas_confirmpw = values.freenas_password; + values.writecache = values.nowritecache ? 0 : 1; + this.callParent([values]); + }, +@@ -30134,7 +30153,7 @@ + allowBlank: false + }, + { +- xtype: me.isCreate ? 'textfield' : 'displayfield', ++ xtype: 'textfield', + name: 'pool', + value: '', + fieldLabel: gettext('Pool'), +@@ -30144,11 +30163,11 @@ + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'blocksize', + value: '4k', +- fieldLabel: gettext('Block Size'), ++ fieldLabel: gettext('ZFS Block Size'), + allowBlank: false + }, + { +- xtype: me.isCreate ? 'textfield' : 'displayfield', ++ xtype: 'textfield', + name: 'target', + value: '', + fieldLabel: gettext('Target'), +@@ -30159,8 +30178,33 @@ + name: 'comstar_tg', + value: '', + fieldLabel: gettext('Target group'), +- bind: me.isCreate ? { disabled: '{!isComstar}' } : { hidden: '{!isComstar}' }, ++ bind: { ++ hidden: '{!isComstar}' ++ }, + allowBlank: true ++ }, ++ { ++ xtype: 'proxmoxcheckbox', ++ name: 'freenas_use_ssl', ++ reference: 'freenas_use_ssl_field', ++ inputId: 'freenas_use_ssl_field', ++ checked: false, ++ bind: { ++ hidden: '{!isFreeNAS}' ++ }, ++ uncheckedValue: 0, ++ fieldLabel: gettext('API use SSL') ++ }, ++ { ++ xtype: 'textfield', ++ name: 'freenas_user', ++ reference: 'freenas_user_field', ++ inputId: 'freenas_user_field', ++ value: '', ++ fieldLabel: gettext('API Username'), ++ bind: { ++ hidden: '{!isFreeNAS}' ++ } + } + ]; + +@@ -30191,7 +30235,9 @@ + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'comstar_hg', + value: '', +- bind: me.isCreate ? { disabled: '{!isComstar}' } : { hidden: '{!isComstar}' }, ++ bind: { ++ hidden: '{!isComstar}' ++ }, + fieldLabel: gettext('Host group'), + allowBlank: true + }, +@@ -30199,9 +30245,64 @@ + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'lio_tpg', + value: '', +- bind: me.isCreate ? { disabled: '{!isLIO}' } : { hidden: '{!isLIO}' }, +- allowBlank: false, +- fieldLabel: gettext('Target portal group') ++ bind: { ++ hidden: '{!isLIO}' ++ }, ++ fieldLabel: gettext('Target portal group'), ++ allowBlank: true ++ }, ++ { ++ xtype: 'proxmoxtextfield', ++ name: 'freenas_apiv4_host', ++ reference: 'freenas_apiv4_host_field', ++ value: '', ++ editable: true, ++ emptyText: Proxmox.Utils.noneText, ++ bind: { ++ hidden: '{!isFreeNAS}' ++ }, ++ fieldLabel: gettext('API IPv4 Host'), ++ }, ++ { ++ xtype: 'proxmoxtextfield', ++ name: 'freenas_password', ++ reference: 'freenas_password_field', ++ inputType: me.isCreate ? '' : 'password', ++ value: '', ++ editable: true, ++ deleteEmpty: true, ++ emptyText: Proxmox.Utils.noneText, ++ bind: { ++ hidden: '{!isFreeNAS}' ++ }, ++ fieldLabel: gettext('API Password'), ++ change: function(f, value) { ++ if (f.rendered) { ++ f.up().down('field[name=freenas_confirmpw]').validate(); ++ } ++ } ++ }, ++ { ++ xtype: 'proxmoxtextfield', ++ name: 'freenas_confirmpw', ++ reference: 'freenas_confirmpw_field', ++ inputType: me.isCreate ? '' : 'password', ++ value: '', ++ editable: true, ++ submitValue: false, ++ deleteEmpty: true, ++ emptyText: Proxmox.Utils.noneText, ++ bind: { ++ hidden: '{!isFreeNAS}' ++ }, ++ fieldLabel: gettext('Confirm Password'), ++ validator: function(value) { ++ var pw = this.up().down('field[name=freenas_password]').getValue(); ++ if (pw !== value) { ++ return "Passwords do not match!"; ++ } ++ return true; ++ } + } + ]; + diff --git a/stable-5/pve-manager/js/pvemanagerlib-5.3-8_1.js.patch b/stable-5/pve-manager/js/pvemanagerlib-5.3-8_1.js.patch new file mode 100644 index 0000000..9c25bc6 --- /dev/null +++ b/stable-5/pve-manager/js/pvemanagerlib-5.3-8_1.js.patch @@ -0,0 +1,189 @@ +--- pvemanagerlib.js.orig 2019-01-11 04:23:42.000000000 -0500 ++++ pvemanagerlib.js 2019-02-05 07:30:18.168655803 -0500 +@@ -5894,6 +5894,7 @@ + alias: ['widget.pveiScsiProviderSelector'], + comboItems: [ + ['comstar', 'Comstar'], ++ ['freenas', 'FreeNAS-API'], + [ 'istgt', 'istgt'], + [ 'iet', 'IET'], + [ 'LIO', 'LIO'] +@@ -30085,6 +30086,7 @@ + data: { + isLIO: false, + isComstar: true, ++ isFreeNAS: false, + hasWriteCacheOption: true + } + }, +@@ -30097,10 +30099,26 @@ + } + }, + changeISCSIProvider: function(f, newVal, oldVal) { ++ var me = this; + var vm = this.getViewModel(); + vm.set('isLIO', newVal === 'LIO'); + vm.set('isComstar', newVal === 'comstar'); +- vm.set('hasWriteCacheOption', newVal === 'comstar' || newVal === 'istgt'); ++ vm.set('isFreeNAS', newVal === 'freenas'); ++ vm.set('hasWriteCacheOption', newVal === 'comstar' || newVal === 'freenas' || newVal === 'istgt'); ++ if (newVal !== 'freenas') { ++ me.lookupReference('freenas_use_ssl_field').setValue(false); ++ me.lookupReference('freenas_apiv4_host_field').setValue(''); ++ me.lookupReference('freenas_user_field').setValue(''); ++ me.lookupReference('freenas_user_field').allowBlank = true; ++ me.lookupReference('freenas_password_field').setValue(''); ++ me.lookupReference('freenas_password_field').allowBlank = true; ++ me.lookupReference('freenas_confirmpw_field').setValue(''); ++ me.lookupReference('freenas_confirmpw_field').allowBlank = true; ++ } else { ++ me.lookupReference('freenas_user_field').allowBlank = false; ++ me.lookupReference('freenas_password_field').allowBlank = false; ++ me.lookupReference('freenas_confirmpw_field').allowBlank = false; ++ } + } + }, + +@@ -30118,6 +30136,7 @@ + }, + + setValues: function diff(values) { ++ values.freenas_confirmpw = values.freenas_password; + values.writecache = values.nowritecache ? 0 : 1; + this.callParent([values]); + }, +@@ -30134,7 +30153,7 @@ + allowBlank: false + }, + { +- xtype: me.isCreate ? 'textfield' : 'displayfield', ++ xtype: 'textfield', + name: 'pool', + value: '', + fieldLabel: gettext('Pool'), +@@ -30144,11 +30163,11 @@ + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'blocksize', + value: '4k', +- fieldLabel: gettext('Block Size'), ++ fieldLabel: gettext('ZFS Block Size'), + allowBlank: false + }, + { +- xtype: me.isCreate ? 'textfield' : 'displayfield', ++ xtype: 'textfield', + name: 'target', + value: '', + fieldLabel: gettext('Target'), +@@ -30159,8 +30178,33 @@ + name: 'comstar_tg', + value: '', + fieldLabel: gettext('Target group'), +- bind: me.isCreate ? { disabled: '{!isComstar}' } : { hidden: '{!isComstar}' }, ++ bind: { ++ hidden: '{!isComstar}' ++ }, + allowBlank: true ++ }, ++ { ++ xtype: 'proxmoxcheckbox', ++ name: 'freenas_use_ssl', ++ reference: 'freenas_use_ssl_field', ++ inputId: 'freenas_use_ssl_field', ++ checked: false, ++ bind: { ++ hidden: '{!isFreeNAS}' ++ }, ++ uncheckedValue: 0, ++ fieldLabel: gettext('API use SSL') ++ }, ++ { ++ xtype: 'textfield', ++ name: 'freenas_user', ++ reference: 'freenas_user_field', ++ inputId: 'freenas_user_field', ++ value: '', ++ fieldLabel: gettext('API Username'), ++ bind: { ++ hidden: '{!isFreeNAS}' ++ } + } + ]; + +@@ -30191,7 +30235,9 @@ + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'comstar_hg', + value: '', +- bind: me.isCreate ? { disabled: '{!isComstar}' } : { hidden: '{!isComstar}' }, ++ bind: { ++ hidden: '{!isComstar}' ++ }, + fieldLabel: gettext('Host group'), + allowBlank: true + }, +@@ -30199,9 +30245,62 @@ + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'lio_tpg', + value: '', +- bind: me.isCreate ? { disabled: '{!isLIO}' } : { hidden: '{!isLIO}' }, +- allowBlank: false, +- fieldLabel: gettext('Target portal group') ++ bind: { ++ hidden: '{!isLIO}' ++ }, ++ fieldLabel: gettext('Target portal group'), ++ allowBlank: true ++ }, ++ { ++ xtype: 'proxmoxtextfield', ++ name: 'freenas_apiv4_host', ++ reference: 'freenas_apiv4_host_field', ++ value: '', ++ editable: true, ++ emptyText: Proxmox.Utils.noneText, ++ bind: { ++ hidden: '{!isFreeNAS}' ++ }, ++ fieldLabel: gettext('API IPv4 Host'), ++ }, ++ { ++ xtype: 'proxmoxtextfield', ++ name: 'freenas_password', ++ reference: 'freenas_password_field', ++ inputType: me.isCreate ? '' : 'password', ++ value: '', ++ editable: true, ++ emptyText: Proxmox.Utils.noneText, ++ bind: { ++ hidden: '{!isFreeNAS}' ++ }, ++ fieldLabel: gettext('API Password'), ++ change: function(f, value) { ++ if (f.rendered) { ++ f.up().down('field[name=freenas_confirmpw]').validate(); ++ } ++ } ++ }, ++ { ++ xtype: 'proxmoxtextfield', ++ name: 'freenas_confirmpw', ++ reference: 'freenas_confirmpw_field', ++ inputType: me.isCreate ? '' : 'password', ++ value: '', ++ editable: true, ++ submitValue: false, ++ emptyText: Proxmox.Utils.noneText, ++ bind: { ++ hidden: '{!isFreeNAS}' ++ }, ++ fieldLabel: gettext('Confirm Password'), ++ validator: function(value) { ++ var pw = this.up().down('field[name=freenas_password]').getValue(); ++ if (pw !== value) { ++ return "Passwords do not match!"; ++ } ++ return true; ++ } + } + ]; + diff --git a/stable-5/pve-manager/js/pvemanagerlib-5.4-11_1.js.patch b/stable-5/pve-manager/js/pvemanagerlib-5.4-11_1.js.patch new file mode 100644 index 0000000..d774f7c --- /dev/null +++ b/stable-5/pve-manager/js/pvemanagerlib-5.4-11_1.js.patch @@ -0,0 +1,189 @@ +--- pvemanagerlib.js.orig 2019-07-09 03:52:19.000000000 -0400 ++++ pvemanagerlib.js 2019-07-16 13:59:37.658409977 -0400 +@@ -6094,6 +6094,7 @@ + alias: ['widget.pveiScsiProviderSelector'], + comboItems: [ + ['comstar', 'Comstar'], ++ ['freenas', 'FreeNAS-API'], + [ 'istgt', 'istgt'], + [ 'iet', 'IET'], + [ 'LIO', 'LIO'] +@@ -31700,6 +31701,7 @@ + data: { + isLIO: false, + isComstar: true, ++ isFreeNAS: false, + hasWriteCacheOption: true + } + }, +@@ -31712,10 +31714,26 @@ + } + }, + changeISCSIProvider: function(f, newVal, oldVal) { ++ var me = this; + var vm = this.getViewModel(); + vm.set('isLIO', newVal === 'LIO'); + vm.set('isComstar', newVal === 'comstar'); +- vm.set('hasWriteCacheOption', newVal === 'comstar' || newVal === 'istgt'); ++ vm.set('isFreeNAS', newVal === 'freenas'); ++ vm.set('hasWriteCacheOption', newVal === 'comstar' || newVal === 'freenas' || newVal === 'istgt'); ++ if (newVal !== 'freenas') { ++ me.lookupReference('freenas_use_ssl_field').setValue(false); ++ me.lookupReference('freenas_apiv4_host_field').setValue(''); ++ me.lookupReference('freenas_user_field').setValue(''); ++ me.lookupReference('freenas_user_field').allowBlank = true; ++ me.lookupReference('freenas_password_field').setValue(''); ++ me.lookupReference('freenas_password_field').allowBlank = true; ++ me.lookupReference('freenas_confirmpw_field').setValue(''); ++ me.lookupReference('freenas_confirmpw_field').allowBlank = true; ++ } else { ++ me.lookupReference('freenas_user_field').allowBlank = false; ++ me.lookupReference('freenas_password_field').allowBlank = false; ++ me.lookupReference('freenas_confirmpw_field').allowBlank = false; ++ } + } + }, + +@@ -31733,6 +31751,7 @@ + }, + + setValues: function diff(values) { ++ values.freenas_confirmpw = values.freenas_password; + values.writecache = values.nowritecache ? 0 : 1; + this.callParent([values]); + }, +@@ -31749,7 +31768,7 @@ + allowBlank: false + }, + { +- xtype: me.isCreate ? 'textfield' : 'displayfield', ++ xtype: 'textfield', + name: 'pool', + value: '', + fieldLabel: gettext('Pool'), +@@ -31759,11 +31778,11 @@ + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'blocksize', + value: '4k', +- fieldLabel: gettext('Block Size'), ++ fieldLabel: gettext('ZFS Block Size'), + allowBlank: false + }, + { +- xtype: me.isCreate ? 'textfield' : 'displayfield', ++ xtype: 'textfield', + name: 'target', + value: '', + fieldLabel: gettext('Target'), +@@ -31774,8 +31793,33 @@ + name: 'comstar_tg', + value: '', + fieldLabel: gettext('Target group'), +- bind: me.isCreate ? { disabled: '{!isComstar}' } : { hidden: '{!isComstar}' }, ++ bind: { ++ hidden: '{!isComstar}' ++ }, + allowBlank: true ++ }, ++ { ++ xtype: 'proxmoxcheckbox', ++ name: 'freenas_use_ssl', ++ reference: 'freenas_use_ssl_field', ++ inputId: 'freenas_use_ssl_field', ++ checked: false, ++ bind: { ++ hidden: '{!isFreeNAS}' ++ }, ++ uncheckedValue: 0, ++ fieldLabel: gettext('API use SSL') ++ }, ++ { ++ xtype: 'textfield', ++ name: 'freenas_user', ++ reference: 'freenas_user_field', ++ inputId: 'freenas_user_field', ++ value: '', ++ fieldLabel: gettext('API Username'), ++ bind: { ++ hidden: '{!isFreeNAS}' ++ } + } + ]; + +@@ -31806,7 +31850,9 @@ + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'comstar_hg', + value: '', +- bind: me.isCreate ? { disabled: '{!isComstar}' } : { hidden: '{!isComstar}' }, ++ bind: { ++ hidden: '{!isComstar}' ++ }, + fieldLabel: gettext('Host group'), + allowBlank: true + }, +@@ -31814,9 +31860,62 @@ + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'lio_tpg', + value: '', +- bind: me.isCreate ? { disabled: '{!isLIO}' } : { hidden: '{!isLIO}' }, +- allowBlank: false, +- fieldLabel: gettext('Target portal group') ++ bind: { ++ hidden: '{!isLIO}' ++ }, ++ fieldLabel: gettext('Target portal group'), ++ allowBlank: true ++ }, ++ { ++ xtype: 'proxmoxtextfield', ++ name: 'freenas_apiv4_host', ++ reference: 'freenas_apiv4_host_field', ++ value: '', ++ editable: true, ++ emptyText: Proxmox.Utils.noneText, ++ bind: { ++ hidden: '{!isFreeNAS}' ++ }, ++ fieldLabel: gettext('API IPv4 Host'), ++ }, ++ { ++ xtype: 'proxmoxtextfield', ++ name: 'freenas_password', ++ reference: 'freenas_password_field', ++ inputType: me.isCreate ? '' : 'password', ++ value: '', ++ editable: true, ++ emptyText: Proxmox.Utils.noneText, ++ bind: { ++ hidden: '{!isFreeNAS}' ++ }, ++ fieldLabel: gettext('API Password'), ++ change: function(f, value) { ++ if (f.rendered) { ++ f.up().down('field[name=freenas_confirmpw]').validate(); ++ } ++ } ++ }, ++ { ++ xtype: 'proxmoxtextfield', ++ name: 'freenas_confirmpw', ++ reference: 'freenas_confirmpw_field', ++ inputType: me.isCreate ? '' : 'password', ++ value: '', ++ editable: true, ++ submitValue: false, ++ emptyText: Proxmox.Utils.noneText, ++ bind: { ++ hidden: '{!isFreeNAS}' ++ }, ++ fieldLabel: gettext('Confirm Password'), ++ validator: function(value) { ++ var pw = this.up().down('field[name=freenas_password]').getValue(); ++ if (pw !== value) { ++ return "Passwords do not match!"; ++ } ++ return true; ++ } + } + ]; + diff --git a/stable-5/pve-manager/js/pvemanagerlib-5.4-13_1.js.patch b/stable-5/pve-manager/js/pvemanagerlib-5.4-13_1.js.patch new file mode 100644 index 0000000..ac83610 --- /dev/null +++ b/stable-5/pve-manager/js/pvemanagerlib-5.4-13_1.js.patch @@ -0,0 +1,189 @@ +--- pvemanagerlib.js.orig 2019-07-26 04:14:56.000000000 -0400 ++++ pvemanagerlib.js 2019-08-05 16:02:38.484913553 -0400 +@@ -6094,6 +6094,7 @@ + alias: ['widget.pveiScsiProviderSelector'], + comboItems: [ + ['comstar', 'Comstar'], ++ ['freenas', 'FreeNAS-API'], + [ 'istgt', 'istgt'], + [ 'iet', 'IET'], + [ 'LIO', 'LIO'] +@@ -31722,6 +31723,7 @@ + data: { + isLIO: false, + isComstar: true, ++ isFreeNAS: false, + hasWriteCacheOption: true + } + }, +@@ -31734,10 +31736,26 @@ + } + }, + changeISCSIProvider: function(f, newVal, oldVal) { ++ var me = this; + var vm = this.getViewModel(); + vm.set('isLIO', newVal === 'LIO'); + vm.set('isComstar', newVal === 'comstar'); +- vm.set('hasWriteCacheOption', newVal === 'comstar' || newVal === 'istgt'); ++ vm.set('isFreeNAS', newVal === 'freenas'); ++ vm.set('hasWriteCacheOption', newVal === 'comstar' || newVal === 'freenas' || newVal === 'istgt'); ++ if (newVal !== 'freenas') { ++ me.lookupReference('freenas_use_ssl_field').setValue(false); ++ me.lookupReference('freenas_apiv4_host_field').setValue(''); ++ me.lookupReference('freenas_user_field').setValue(''); ++ me.lookupReference('freenas_user_field').allowBlank = true; ++ me.lookupReference('freenas_password_field').setValue(''); ++ me.lookupReference('freenas_password_field').allowBlank = true; ++ me.lookupReference('freenas_confirmpw_field').setValue(''); ++ me.lookupReference('freenas_confirmpw_field').allowBlank = true; ++ } else { ++ me.lookupReference('freenas_user_field').allowBlank = false; ++ me.lookupReference('freenas_password_field').allowBlank = false; ++ me.lookupReference('freenas_confirmpw_field').allowBlank = false; ++ } + } + }, + +@@ -31755,6 +31773,7 @@ + }, + + setValues: function diff(values) { ++ values.freenas_confirmpw = values.freenas_password; + values.writecache = values.nowritecache ? 0 : 1; + this.callParent([values]); + }, +@@ -31771,7 +31790,7 @@ + allowBlank: false + }, + { +- xtype: me.isCreate ? 'textfield' : 'displayfield', ++ xtype: 'textfield', + name: 'pool', + value: '', + fieldLabel: gettext('Pool'), +@@ -31781,11 +31800,11 @@ + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'blocksize', + value: '4k', +- fieldLabel: gettext('Block Size'), ++ fieldLabel: gettext('ZFS Block Size'), + allowBlank: false + }, + { +- xtype: me.isCreate ? 'textfield' : 'displayfield', ++ xtype: 'textfield', + name: 'target', + value: '', + fieldLabel: gettext('Target'), +@@ -31796,8 +31815,33 @@ + name: 'comstar_tg', + value: '', + fieldLabel: gettext('Target group'), +- bind: me.isCreate ? { disabled: '{!isComstar}' } : { hidden: '{!isComstar}' }, ++ bind: { ++ hidden: '{!isComstar}' ++ }, + allowBlank: true ++ }, ++ { ++ xtype: 'proxmoxcheckbox', ++ name: 'freenas_use_ssl', ++ reference: 'freenas_use_ssl_field', ++ inputId: 'freenas_use_ssl_field', ++ checked: false, ++ bind: { ++ hidden: '{!isFreeNAS}' ++ }, ++ uncheckedValue: 0, ++ fieldLabel: gettext('API use SSL') ++ }, ++ { ++ xtype: 'textfield', ++ name: 'freenas_user', ++ reference: 'freenas_user_field', ++ inputId: 'freenas_user_field', ++ value: '', ++ fieldLabel: gettext('API Username'), ++ bind: { ++ hidden: '{!isFreeNAS}' ++ } + } + ]; + +@@ -31828,7 +31872,9 @@ + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'comstar_hg', + value: '', +- bind: me.isCreate ? { disabled: '{!isComstar}' } : { hidden: '{!isComstar}' }, ++ bind: { ++ hidden: '{!isComstar}' ++ }, + fieldLabel: gettext('Host group'), + allowBlank: true + }, +@@ -31836,9 +31882,62 @@ + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'lio_tpg', + value: '', +- bind: me.isCreate ? { disabled: '{!isLIO}' } : { hidden: '{!isLIO}' }, +- allowBlank: false, +- fieldLabel: gettext('Target portal group') ++ bind: { ++ hidden: '{!isLIO}' ++ }, ++ fieldLabel: gettext('Target portal group'), ++ allowBlank: true ++ }, ++ { ++ xtype: 'proxmoxtextfield', ++ name: 'freenas_apiv4_host', ++ reference: 'freenas_apiv4_host_field', ++ value: '', ++ editable: true, ++ emptyText: Proxmox.Utils.noneText, ++ bind: { ++ hidden: '{!isFreeNAS}' ++ }, ++ fieldLabel: gettext('API IPv4 Host'), ++ }, ++ { ++ xtype: 'proxmoxtextfield', ++ name: 'freenas_password', ++ reference: 'freenas_password_field', ++ inputType: me.isCreate ? '' : 'password', ++ value: '', ++ editable: true, ++ emptyText: Proxmox.Utils.noneText, ++ bind: { ++ hidden: '{!isFreeNAS}' ++ }, ++ fieldLabel: gettext('API Password'), ++ change: function(f, value) { ++ if (f.rendered) { ++ f.up().down('field[name=freenas_confirmpw]').validate(); ++ } ++ } ++ }, ++ { ++ xtype: 'proxmoxtextfield', ++ name: 'freenas_confirmpw', ++ reference: 'freenas_confirmpw_field', ++ inputType: me.isCreate ? '' : 'password', ++ value: '', ++ editable: true, ++ submitValue: false, ++ emptyText: Proxmox.Utils.noneText, ++ bind: { ++ hidden: '{!isFreeNAS}' ++ }, ++ fieldLabel: gettext('Confirm Password'), ++ validator: function(value) { ++ var pw = this.up().down('field[name=freenas_password]').getValue(); ++ if (pw !== value) { ++ return "Passwords do not match!"; ++ } ++ return true; ++ } + } + ]; + diff --git a/stable-5/pve-manager/js/pvemanagerlib-5.4-5_1.js.patch b/stable-5/pve-manager/js/pvemanagerlib-5.4-5_1.js.patch new file mode 100644 index 0000000..32a982a --- /dev/null +++ b/stable-5/pve-manager/js/pvemanagerlib-5.4-5_1.js.patch @@ -0,0 +1,189 @@ +--- pvemanagerlib.js.orig 2019-04-24 07:28:11.000000000 -0400 ++++ pvemanagerlib.js 2019-05-11 10:33:38.130198999 -0400 +@@ -6094,6 +6094,7 @@ + alias: ['widget.pveiScsiProviderSelector'], + comboItems: [ + ['comstar', 'Comstar'], ++ ['freenas', 'FreeNAS-API'], + [ 'istgt', 'istgt'], + [ 'iet', 'IET'], + [ 'LIO', 'LIO'] +@@ -31483,6 +31484,7 @@ + data: { + isLIO: false, + isComstar: true, ++ isFreeNAS: false, + hasWriteCacheOption: true + } + }, +@@ -31495,10 +31497,26 @@ + } + }, + changeISCSIProvider: function(f, newVal, oldVal) { ++ var me = this; + var vm = this.getViewModel(); + vm.set('isLIO', newVal === 'LIO'); + vm.set('isComstar', newVal === 'comstar'); +- vm.set('hasWriteCacheOption', newVal === 'comstar' || newVal === 'istgt'); ++ vm.set('isFreeNAS', newVal === 'freenas'); ++ vm.set('hasWriteCacheOption', newVal === 'comstar' || newVal === 'freenas' || newVal === 'istgt'); ++ if (newVal !== 'freenas') { ++ me.lookupReference('freenas_use_ssl_field').setValue(false); ++ me.lookupReference('freenas_apiv4_host_field').setValue(''); ++ me.lookupReference('freenas_user_field').setValue(''); ++ me.lookupReference('freenas_user_field').allowBlank = true; ++ me.lookupReference('freenas_password_field').setValue(''); ++ me.lookupReference('freenas_password_field').allowBlank = true; ++ me.lookupReference('freenas_confirmpw_field').setValue(''); ++ me.lookupReference('freenas_confirmpw_field').allowBlank = true; ++ } else { ++ me.lookupReference('freenas_user_field').allowBlank = false; ++ me.lookupReference('freenas_password_field').allowBlank = false; ++ me.lookupReference('freenas_confirmpw_field').allowBlank = false; ++ } + } + }, + +@@ -31516,6 +31534,7 @@ + }, + + setValues: function diff(values) { ++ values.freenas_confirmpw = values.freenas_password; + values.writecache = values.nowritecache ? 0 : 1; + this.callParent([values]); + }, +@@ -31532,7 +31551,7 @@ + allowBlank: false + }, + { +- xtype: me.isCreate ? 'textfield' : 'displayfield', ++ xtype: 'textfield', + name: 'pool', + value: '', + fieldLabel: gettext('Pool'), +@@ -31542,11 +31561,11 @@ + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'blocksize', + value: '4k', +- fieldLabel: gettext('Block Size'), ++ fieldLabel: gettext('ZFS Block Size'), + allowBlank: false + }, + { +- xtype: me.isCreate ? 'textfield' : 'displayfield', ++ xtype: 'textfield', + name: 'target', + value: '', + fieldLabel: gettext('Target'), +@@ -31557,8 +31576,33 @@ + name: 'comstar_tg', + value: '', + fieldLabel: gettext('Target group'), +- bind: me.isCreate ? { disabled: '{!isComstar}' } : { hidden: '{!isComstar}' }, ++ bind: { ++ hidden: '{!isComstar}' ++ }, + allowBlank: true ++ }, ++ { ++ xtype: 'proxmoxcheckbox', ++ name: 'freenas_use_ssl', ++ reference: 'freenas_use_ssl_field', ++ inputId: 'freenas_use_ssl_field', ++ checked: false, ++ bind: { ++ hidden: '{!isFreeNAS}' ++ }, ++ uncheckedValue: 0, ++ fieldLabel: gettext('API use SSL') ++ }, ++ { ++ xtype: 'textfield', ++ name: 'freenas_user', ++ reference: 'freenas_user_field', ++ inputId: 'freenas_user_field', ++ value: '', ++ fieldLabel: gettext('API Username'), ++ bind: { ++ hidden: '{!isFreeNAS}' ++ } + } + ]; + +@@ -31589,7 +31633,9 @@ + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'comstar_hg', + value: '', +- bind: me.isCreate ? { disabled: '{!isComstar}' } : { hidden: '{!isComstar}' }, ++ bind: { ++ hidden: '{!isComstar}' ++ }, + fieldLabel: gettext('Host group'), + allowBlank: true + }, +@@ -31597,9 +31643,62 @@ + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'lio_tpg', + value: '', +- bind: me.isCreate ? { disabled: '{!isLIO}' } : { hidden: '{!isLIO}' }, +- allowBlank: false, +- fieldLabel: gettext('Target portal group') ++ bind: { ++ hidden: '{!isLIO}' ++ }, ++ fieldLabel: gettext('Target portal group'), ++ allowBlank: true ++ }, ++ { ++ xtype: 'proxmoxtextfield', ++ name: 'freenas_apiv4_host', ++ reference: 'freenas_apiv4_host_field', ++ value: '', ++ editable: true, ++ emptyText: Proxmox.Utils.noneText, ++ bind: { ++ hidden: '{!isFreeNAS}' ++ }, ++ fieldLabel: gettext('API IPv4 Host'), ++ }, ++ { ++ xtype: 'proxmoxtextfield', ++ name: 'freenas_password', ++ reference: 'freenas_password_field', ++ inputType: me.isCreate ? '' : 'password', ++ value: '', ++ editable: true, ++ emptyText: Proxmox.Utils.noneText, ++ bind: { ++ hidden: '{!isFreeNAS}' ++ }, ++ fieldLabel: gettext('API Password'), ++ change: function(f, value) { ++ if (f.rendered) { ++ f.up().down('field[name=freenas_confirmpw]').validate(); ++ } ++ } ++ }, ++ { ++ xtype: 'proxmoxtextfield', ++ name: 'freenas_confirmpw', ++ reference: 'freenas_confirmpw_field', ++ inputType: me.isCreate ? '' : 'password', ++ value: '', ++ editable: true, ++ submitValue: false, ++ emptyText: Proxmox.Utils.noneText, ++ bind: { ++ hidden: '{!isFreeNAS}' ++ }, ++ fieldLabel: gettext('Confirm Password'), ++ validator: function(value) { ++ var pw = this.up().down('field[name=freenas_password]').getValue(); ++ if (pw !== value) { ++ return "Passwords do not match!"; ++ } ++ return true; ++ } + } + ]; + diff --git a/stable-6/perl5/PVE/Storage/ZFSPlugin-6.0-6_1.pm.patch b/stable-6/perl5/PVE/Storage/ZFSPlugin-6.0-6_1.pm.patch new file mode 100644 index 0000000..4ec36bd --- /dev/null +++ b/stable-6/perl5/PVE/Storage/ZFSPlugin-6.0-6_1.pm.patch @@ -0,0 +1,147 @@ +--- ZFSPlugin.pm.orig 2019-07-25 07:34:52.000000000 -0400 ++++ ZFSPlugin.pm 2019-08-07 13:28:29.268383007 -0400 +@@ -10,6 +10,7 @@ + + use base qw(PVE::Storage::ZFSPoolPlugin); + use PVE::Storage::LunCmd::Comstar; ++use PVE::Storage::LunCmd::FreeNAS; + use PVE::Storage::LunCmd::Istgt; + use PVE::Storage::LunCmd::Iet; + use PVE::Storage::LunCmd::LIO; +@@ -26,13 +27,14 @@ + modify_lu => 1, + add_view => 1, + list_view => 1, ++ list_extent => 1, + list_lu => 1, + }; + + my $zfs_unknown_scsi_provider = sub { + my ($provider) = @_; + +- die "$provider: unknown iscsi provider. Available [comstar, istgt, iet, LIO]"; ++ die "$provider: unknown iscsi provider. Available [comstar, freenas, istgt, iet, LIO]"; + }; + + my $zfs_get_base = sub { +@@ -40,6 +42,8 @@ + + if ($scfg->{iscsiprovider} eq 'comstar') { + return PVE::Storage::LunCmd::Comstar::get_base; ++ } elsif ($scfg->{iscsiprovider} eq 'freenas') { ++ return PVE::Storage::LunCmd::FreeNAS::get_base; + } elsif ($scfg->{iscsiprovider} eq 'istgt') { + return PVE::Storage::LunCmd::Istgt::get_base; + } elsif ($scfg->{iscsiprovider} eq 'iet') { +@@ -62,6 +66,8 @@ + if ($lun_cmds->{$method}) { + if ($scfg->{iscsiprovider} eq 'comstar') { + $msg = PVE::Storage::LunCmd::Comstar::run_lun_command($scfg, $timeout, $method, @params); ++ } elsif ($scfg->{iscsiprovider} eq 'freenas') { ++ $msg = PVE::Storage::LunCmd::FreeNAS::run_lun_command($scfg, $timeout, $method, @params); + } elsif ($scfg->{iscsiprovider} eq 'istgt') { + $msg = PVE::Storage::LunCmd::Istgt::run_lun_command($scfg, $timeout, $method, @params); + } elsif ($scfg->{iscsiprovider} eq 'iet') { +@@ -160,6 +166,15 @@ + return $class->zfs_request($scfg, undef, 'list_view', $guid); + } + ++# Part of the multipath enhancement ++sub zfs_get_wwid_number { ++ my ($class, $scfg, $guid) = @_; ++ ++ die "could not find lun_number for guid $guid" if !$guid; ++ ++ return $class->zfs_request($scfg, undef, 'list_extent', $guid); ++} ++ + # Configuration + + sub type { +@@ -178,6 +193,24 @@ + description => "iscsi provider", + type => 'string', + }, ++ # This is for FreeNAS iscsi and API intergration ++ # And some enhancements asked by the community ++ freenas_user => { ++ description => "FreeNAS API Username", ++ type => 'string', ++ }, ++ freenas_password => { ++ description => "FreeNAS API Password", ++ type => 'string', ++ }, ++ freenas_use_ssl => { ++ description => "FreeNAS API access via SSL", ++ type => 'boolean', ++ }, ++ freenas_apiv4_host => { ++ description => "FreeNAS API Host", ++ type => 'string', ++ }, + # this will disable write caching on comstar and istgt. + # it is not implemented for iet. iet blockio always operates with + # writethrough caching when not in readonly mode +@@ -205,14 +238,18 @@ + nodes => { optional => 1 }, + disable => { optional => 1 }, + portal => { fixed => 1 }, +- target => { fixed => 1 }, +- pool => { fixed => 1 }, ++ target => { fixed => 0 }, ++ pool => { fixed => 0 }, + blocksize => { fixed => 1 }, + iscsiprovider => { fixed => 1 }, + nowritecache => { optional => 1 }, + sparse => { optional => 1 }, + comstar_hg => { optional => 1 }, + comstar_tg => { optional => 1 }, ++ freenas_user => { optional => 1 }, ++ freenas_password => { optional => 1 }, ++ freenas_use_ssl => { optional => 1 }, ++ freenas_apiv4_host => { optional => 1 }, + lio_tpg => { optional => 1 }, + content => { optional => 1 }, + bwlimit => { optional => 1 }, +@@ -237,6 +274,40 @@ + + my $path = "iscsi://$portal/$target/$lun"; + ++ # Multipath enhancement ++ eval { ++ my $wwid = $class->zfs_get_wwid_number($scfg, $guid); ++# syslog(info,"JD: path get_lun_number guid $guid"); ++ ++ if ($wwid =~ /^([-\@\w.]+)$/) { ++ $wwid = $1; # $data now untainted ++ } else { ++ die "Bad data in '$wwid'"; # log this somewhere ++ } ++ my $wwid_end = substr $wwid, 16; ++ ++ my $mapper = ''; ++ sleep 3; ++ run_command("iscsiadm -m session --rescan"); ++ sleep 3; ++ my $line = `multipath -ll | grep \"$wwid_end\"`; ++ my ($mapper_device) = split(' ', $line); ++ $mapper_device = "" unless $mapper_device; ++ $mapper .= $mapper_device; ++ ++ if ($mapper =~ /^([-\@\w.]+)$/) { ++ $mapper = $1; # $data now untainted ++ } else { ++ $mapper = ''; ++ } ++ ++# syslog(info,"Multipath mapper found: $mapper\n"); ++ if ($mapper ne "") { ++ $path = "/dev/mapper/$mapper"; ++ sleep 5; ++ } ++ }; ++ + return ($path, $vmid, $vtype); + } + diff --git a/stable-6/perl5/PVE/Storage/ZFSPlugin.pm.patch b/stable-6/perl5/PVE/Storage/ZFSPlugin.pm.patch new file mode 100644 index 0000000..4ec36bd --- /dev/null +++ b/stable-6/perl5/PVE/Storage/ZFSPlugin.pm.patch @@ -0,0 +1,147 @@ +--- ZFSPlugin.pm.orig 2019-07-25 07:34:52.000000000 -0400 ++++ ZFSPlugin.pm 2019-08-07 13:28:29.268383007 -0400 +@@ -10,6 +10,7 @@ + + use base qw(PVE::Storage::ZFSPoolPlugin); + use PVE::Storage::LunCmd::Comstar; ++use PVE::Storage::LunCmd::FreeNAS; + use PVE::Storage::LunCmd::Istgt; + use PVE::Storage::LunCmd::Iet; + use PVE::Storage::LunCmd::LIO; +@@ -26,13 +27,14 @@ + modify_lu => 1, + add_view => 1, + list_view => 1, ++ list_extent => 1, + list_lu => 1, + }; + + my $zfs_unknown_scsi_provider = sub { + my ($provider) = @_; + +- die "$provider: unknown iscsi provider. Available [comstar, istgt, iet, LIO]"; ++ die "$provider: unknown iscsi provider. Available [comstar, freenas, istgt, iet, LIO]"; + }; + + my $zfs_get_base = sub { +@@ -40,6 +42,8 @@ + + if ($scfg->{iscsiprovider} eq 'comstar') { + return PVE::Storage::LunCmd::Comstar::get_base; ++ } elsif ($scfg->{iscsiprovider} eq 'freenas') { ++ return PVE::Storage::LunCmd::FreeNAS::get_base; + } elsif ($scfg->{iscsiprovider} eq 'istgt') { + return PVE::Storage::LunCmd::Istgt::get_base; + } elsif ($scfg->{iscsiprovider} eq 'iet') { +@@ -62,6 +66,8 @@ + if ($lun_cmds->{$method}) { + if ($scfg->{iscsiprovider} eq 'comstar') { + $msg = PVE::Storage::LunCmd::Comstar::run_lun_command($scfg, $timeout, $method, @params); ++ } elsif ($scfg->{iscsiprovider} eq 'freenas') { ++ $msg = PVE::Storage::LunCmd::FreeNAS::run_lun_command($scfg, $timeout, $method, @params); + } elsif ($scfg->{iscsiprovider} eq 'istgt') { + $msg = PVE::Storage::LunCmd::Istgt::run_lun_command($scfg, $timeout, $method, @params); + } elsif ($scfg->{iscsiprovider} eq 'iet') { +@@ -160,6 +166,15 @@ + return $class->zfs_request($scfg, undef, 'list_view', $guid); + } + ++# Part of the multipath enhancement ++sub zfs_get_wwid_number { ++ my ($class, $scfg, $guid) = @_; ++ ++ die "could not find lun_number for guid $guid" if !$guid; ++ ++ return $class->zfs_request($scfg, undef, 'list_extent', $guid); ++} ++ + # Configuration + + sub type { +@@ -178,6 +193,24 @@ + description => "iscsi provider", + type => 'string', + }, ++ # This is for FreeNAS iscsi and API intergration ++ # And some enhancements asked by the community ++ freenas_user => { ++ description => "FreeNAS API Username", ++ type => 'string', ++ }, ++ freenas_password => { ++ description => "FreeNAS API Password", ++ type => 'string', ++ }, ++ freenas_use_ssl => { ++ description => "FreeNAS API access via SSL", ++ type => 'boolean', ++ }, ++ freenas_apiv4_host => { ++ description => "FreeNAS API Host", ++ type => 'string', ++ }, + # this will disable write caching on comstar and istgt. + # it is not implemented for iet. iet blockio always operates with + # writethrough caching when not in readonly mode +@@ -205,14 +238,18 @@ + nodes => { optional => 1 }, + disable => { optional => 1 }, + portal => { fixed => 1 }, +- target => { fixed => 1 }, +- pool => { fixed => 1 }, ++ target => { fixed => 0 }, ++ pool => { fixed => 0 }, + blocksize => { fixed => 1 }, + iscsiprovider => { fixed => 1 }, + nowritecache => { optional => 1 }, + sparse => { optional => 1 }, + comstar_hg => { optional => 1 }, + comstar_tg => { optional => 1 }, ++ freenas_user => { optional => 1 }, ++ freenas_password => { optional => 1 }, ++ freenas_use_ssl => { optional => 1 }, ++ freenas_apiv4_host => { optional => 1 }, + lio_tpg => { optional => 1 }, + content => { optional => 1 }, + bwlimit => { optional => 1 }, +@@ -237,6 +274,40 @@ + + my $path = "iscsi://$portal/$target/$lun"; + ++ # Multipath enhancement ++ eval { ++ my $wwid = $class->zfs_get_wwid_number($scfg, $guid); ++# syslog(info,"JD: path get_lun_number guid $guid"); ++ ++ if ($wwid =~ /^([-\@\w.]+)$/) { ++ $wwid = $1; # $data now untainted ++ } else { ++ die "Bad data in '$wwid'"; # log this somewhere ++ } ++ my $wwid_end = substr $wwid, 16; ++ ++ my $mapper = ''; ++ sleep 3; ++ run_command("iscsiadm -m session --rescan"); ++ sleep 3; ++ my $line = `multipath -ll | grep \"$wwid_end\"`; ++ my ($mapper_device) = split(' ', $line); ++ $mapper_device = "" unless $mapper_device; ++ $mapper .= $mapper_device; ++ ++ if ($mapper =~ /^([-\@\w.]+)$/) { ++ $mapper = $1; # $data now untainted ++ } else { ++ $mapper = ''; ++ } ++ ++# syslog(info,"Multipath mapper found: $mapper\n"); ++ if ($mapper ne "") { ++ $path = "/dev/mapper/$mapper"; ++ sleep 5; ++ } ++ }; ++ + return ($path, $vmid, $vtype); + } + diff --git a/stable-6/pve-docs/api-viewer/apidoc-6.0-4_1.js.patch b/stable-6/pve-docs/api-viewer/apidoc-6.0-4_1.js.patch new file mode 100644 index 0000000..3bc6dd7 --- /dev/null +++ b/stable-6/pve-docs/api-viewer/apidoc-6.0-4_1.js.patch @@ -0,0 +1,79 @@ +--- apidoc.js.orig 2019-07-15 15:45:00.000000000 -0400 ++++ apidoc.js 2019-08-07 13:28:29.292382229 -0400 +@@ -35001,6 +35001,31 @@ + "type" : "string", + "typetext" : "" + }, ++ "freenas_user" : { ++ "description" : "FreeNAS user for API access", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, ++ "freenas_password" : { ++ "description" : "FreeNAS password for API access", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, ++ "freenas_use_ssl" : { ++ "description" : "FreeNAS API access via SSL", ++ "optional" : 1, ++ "type" : "boolean", ++ "typetext" : "" ++ }, ++ "freenas_apiv4_host" : { ++ "description" : "FreeNAS API Host via IPv4", ++ "format" : "address", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, + "fuse" : { + "description" : "Mount CephFS through FUSE.", + "optional" : 1, +@@ -35157,6 +35182,12 @@ + "type" : "boolean", + "typetext" : "" + }, ++ "target" : { ++ "description" : "iSCSI target.", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, + "transport" : { + "description" : "Gluster transport: tcp or rdma", + "enum" : [ +@@ -35362,6 +35393,31 @@ + "optional" : 1, + "type" : "string", + "typetext" : "" ++ }, ++ "freenas_user" : { ++ "description" : "FreeNAS user for API access", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, ++ "freenas_password" : { ++ "description" : "FreeNAS password for API access", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, ++ "freenas_use_ssl" : { ++ "description" : "FreeNAS API access via SSL", ++ "optional" : 1, ++ "type" : "boolean", ++ "typetext" : "" ++ }, ++ "freenas_apiv4_host" : { ++ "description" : "FreeNAS API Host via IPv4", ++ "format" : "address", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" + }, + "fuse" : { + "description" : "Mount CephFS through FUSE.", diff --git a/stable-6/pve-docs/api-viewer/apidoc.js.patch b/stable-6/pve-docs/api-viewer/apidoc.js.patch new file mode 100644 index 0000000..3bc6dd7 --- /dev/null +++ b/stable-6/pve-docs/api-viewer/apidoc.js.patch @@ -0,0 +1,79 @@ +--- apidoc.js.orig 2019-07-15 15:45:00.000000000 -0400 ++++ apidoc.js 2019-08-07 13:28:29.292382229 -0400 +@@ -35001,6 +35001,31 @@ + "type" : "string", + "typetext" : "" + }, ++ "freenas_user" : { ++ "description" : "FreeNAS user for API access", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, ++ "freenas_password" : { ++ "description" : "FreeNAS password for API access", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, ++ "freenas_use_ssl" : { ++ "description" : "FreeNAS API access via SSL", ++ "optional" : 1, ++ "type" : "boolean", ++ "typetext" : "" ++ }, ++ "freenas_apiv4_host" : { ++ "description" : "FreeNAS API Host via IPv4", ++ "format" : "address", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, + "fuse" : { + "description" : "Mount CephFS through FUSE.", + "optional" : 1, +@@ -35157,6 +35182,12 @@ + "type" : "boolean", + "typetext" : "" + }, ++ "target" : { ++ "description" : "iSCSI target.", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, + "transport" : { + "description" : "Gluster transport: tcp or rdma", + "enum" : [ +@@ -35362,6 +35393,31 @@ + "optional" : 1, + "type" : "string", + "typetext" : "" ++ }, ++ "freenas_user" : { ++ "description" : "FreeNAS user for API access", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, ++ "freenas_password" : { ++ "description" : "FreeNAS password for API access", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, ++ "freenas_use_ssl" : { ++ "description" : "FreeNAS API access via SSL", ++ "optional" : 1, ++ "type" : "boolean", ++ "typetext" : "" ++ }, ++ "freenas_apiv4_host" : { ++ "description" : "FreeNAS API Host via IPv4", ++ "format" : "address", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" + }, + "fuse" : { + "description" : "Mount CephFS through FUSE.", diff --git a/stable-6/pve-manager/js/pvemanagerlib-6.0-5_1.js.patch b/stable-6/pve-manager/js/pvemanagerlib-6.0-5_1.js.patch new file mode 100644 index 0000000..12603e4 --- /dev/null +++ b/stable-6/pve-manager/js/pvemanagerlib-6.0-5_1.js.patch @@ -0,0 +1,189 @@ +--- pvemanagerlib.js.orig 2019-07-23 13:21:08.000000000 -0400 ++++ pvemanagerlib.js 2019-08-07 13:28:29.304381840 -0400 +@@ -6182,6 +6182,7 @@ + alias: ['widget.pveiScsiProviderSelector'], + comboItems: [ + ['comstar', 'Comstar'], ++ ['freenas', 'FreeNAS-API'], + [ 'istgt', 'istgt'], + [ 'iet', 'IET'], + [ 'LIO', 'LIO'] +@@ -32977,6 +32978,7 @@ + data: { + isLIO: false, + isComstar: true, ++ isFreeNAS: false, + hasWriteCacheOption: true + } + }, +@@ -32989,10 +32991,26 @@ + } + }, + changeISCSIProvider: function(f, newVal, oldVal) { ++ var me = this; + var vm = this.getViewModel(); + vm.set('isLIO', newVal === 'LIO'); + vm.set('isComstar', newVal === 'comstar'); +- vm.set('hasWriteCacheOption', newVal === 'comstar' || newVal === 'istgt'); ++ vm.set('isFreeNAS', newVal === 'freenas'); ++ vm.set('hasWriteCacheOption', newVal === 'comstar' || newVal === 'freenas' || newVal === 'istgt'); ++ if (newVal !== 'freenas') { ++ me.lookupReference('freenas_use_ssl_field').setValue(false); ++ me.lookupReference('freenas_apiv4_host_field').setValue(''); ++ me.lookupReference('freenas_user_field').setValue(''); ++ me.lookupReference('freenas_user_field').allowBlank = true; ++ me.lookupReference('freenas_password_field').setValue(''); ++ me.lookupReference('freenas_password_field').allowBlank = true; ++ me.lookupReference('freenas_confirmpw_field').setValue(''); ++ me.lookupReference('freenas_confirmpw_field').allowBlank = true; ++ } else { ++ me.lookupReference('freenas_user_field').allowBlank = false; ++ me.lookupReference('freenas_password_field').allowBlank = false; ++ me.lookupReference('freenas_confirmpw_field').allowBlank = false; ++ } + } + }, + +@@ -33010,6 +33028,7 @@ + }, + + setValues: function diff(values) { ++ values.freenas_confirmpw = values.freenas_password; + values.writecache = values.nowritecache ? 0 : 1; + this.callParent([values]); + }, +@@ -33026,7 +33045,7 @@ + allowBlank: false + }, + { +- xtype: me.isCreate ? 'textfield' : 'displayfield', ++ xtype: 'textfield', + name: 'pool', + value: '', + fieldLabel: gettext('Pool'), +@@ -33036,11 +33055,11 @@ + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'blocksize', + value: '4k', +- fieldLabel: gettext('Block Size'), ++ fieldLabel: gettext('ZFS Block Size'), + allowBlank: false + }, + { +- xtype: me.isCreate ? 'textfield' : 'displayfield', ++ xtype: 'textfield', + name: 'target', + value: '', + fieldLabel: gettext('Target'), +@@ -33051,8 +33070,33 @@ + name: 'comstar_tg', + value: '', + fieldLabel: gettext('Target group'), +- bind: me.isCreate ? { disabled: '{!isComstar}' } : { hidden: '{!isComstar}' }, ++ bind: { ++ hidden: '{!isComstar}' ++ }, + allowBlank: true ++ }, ++ { ++ xtype: 'proxmoxcheckbox', ++ name: 'freenas_use_ssl', ++ reference: 'freenas_use_ssl_field', ++ inputId: 'freenas_use_ssl_field', ++ checked: false, ++ bind: { ++ hidden: '{!isFreeNAS}' ++ }, ++ uncheckedValue: 0, ++ fieldLabel: gettext('API use SSL') ++ }, ++ { ++ xtype: 'textfield', ++ name: 'freenas_user', ++ reference: 'freenas_user_field', ++ inputId: 'freenas_user_field', ++ value: '', ++ fieldLabel: gettext('API Username'), ++ bind: { ++ hidden: '{!isFreeNAS}' ++ } + } + ]; + +@@ -33083,7 +33127,9 @@ + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'comstar_hg', + value: '', +- bind: me.isCreate ? { disabled: '{!isComstar}' } : { hidden: '{!isComstar}' }, ++ bind: { ++ hidden: '{!isComstar}' ++ }, + fieldLabel: gettext('Host group'), + allowBlank: true + }, +@@ -33091,9 +33137,62 @@ + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'lio_tpg', + value: '', +- bind: me.isCreate ? { disabled: '{!isLIO}' } : { hidden: '{!isLIO}' }, +- allowBlank: false, +- fieldLabel: gettext('Target portal group') ++ bind: { ++ hidden: '{!isLIO}' ++ }, ++ fieldLabel: gettext('Target portal group'), ++ allowBlank: true ++ }, ++ { ++ xtype: 'proxmoxtextfield', ++ name: 'freenas_apiv4_host', ++ reference: 'freenas_apiv4_host_field', ++ value: '', ++ editable: true, ++ emptyText: Proxmox.Utils.noneText, ++ bind: { ++ hidden: '{!isFreeNAS}' ++ }, ++ fieldLabel: gettext('API IPv4 Host'), ++ }, ++ { ++ xtype: 'proxmoxtextfield', ++ name: 'freenas_password', ++ reference: 'freenas_password_field', ++ inputType: me.isCreate ? '' : 'password', ++ value: '', ++ editable: true, ++ emptyText: Proxmox.Utils.noneText, ++ bind: { ++ hidden: '{!isFreeNAS}' ++ }, ++ fieldLabel: gettext('API Password'), ++ change: function(f, value) { ++ if (f.rendered) { ++ f.up().down('field[name=freenas_confirmpw]').validate(); ++ } ++ } ++ }, ++ { ++ xtype: 'proxmoxtextfield', ++ name: 'freenas_confirmpw', ++ reference: 'freenas_confirmpw_field', ++ inputType: me.isCreate ? '' : 'password', ++ value: '', ++ editable: true, ++ submitValue: false, ++ emptyText: Proxmox.Utils.noneText, ++ bind: { ++ hidden: '{!isFreeNAS}' ++ }, ++ fieldLabel: gettext('Confirm Password'), ++ validator: function(value) { ++ var pw = this.up().down('field[name=freenas_password]').getValue(); ++ if (pw !== value) { ++ return "Passwords do not match!"; ++ } ++ return true; ++ } + } + ]; + diff --git a/stable-6/pve-manager/js/pvemanagerlib.js.patch b/stable-6/pve-manager/js/pvemanagerlib.js.patch new file mode 100644 index 0000000..12603e4 --- /dev/null +++ b/stable-6/pve-manager/js/pvemanagerlib.js.patch @@ -0,0 +1,189 @@ +--- pvemanagerlib.js.orig 2019-07-23 13:21:08.000000000 -0400 ++++ pvemanagerlib.js 2019-08-07 13:28:29.304381840 -0400 +@@ -6182,6 +6182,7 @@ + alias: ['widget.pveiScsiProviderSelector'], + comboItems: [ + ['comstar', 'Comstar'], ++ ['freenas', 'FreeNAS-API'], + [ 'istgt', 'istgt'], + [ 'iet', 'IET'], + [ 'LIO', 'LIO'] +@@ -32977,6 +32978,7 @@ + data: { + isLIO: false, + isComstar: true, ++ isFreeNAS: false, + hasWriteCacheOption: true + } + }, +@@ -32989,10 +32991,26 @@ + } + }, + changeISCSIProvider: function(f, newVal, oldVal) { ++ var me = this; + var vm = this.getViewModel(); + vm.set('isLIO', newVal === 'LIO'); + vm.set('isComstar', newVal === 'comstar'); +- vm.set('hasWriteCacheOption', newVal === 'comstar' || newVal === 'istgt'); ++ vm.set('isFreeNAS', newVal === 'freenas'); ++ vm.set('hasWriteCacheOption', newVal === 'comstar' || newVal === 'freenas' || newVal === 'istgt'); ++ if (newVal !== 'freenas') { ++ me.lookupReference('freenas_use_ssl_field').setValue(false); ++ me.lookupReference('freenas_apiv4_host_field').setValue(''); ++ me.lookupReference('freenas_user_field').setValue(''); ++ me.lookupReference('freenas_user_field').allowBlank = true; ++ me.lookupReference('freenas_password_field').setValue(''); ++ me.lookupReference('freenas_password_field').allowBlank = true; ++ me.lookupReference('freenas_confirmpw_field').setValue(''); ++ me.lookupReference('freenas_confirmpw_field').allowBlank = true; ++ } else { ++ me.lookupReference('freenas_user_field').allowBlank = false; ++ me.lookupReference('freenas_password_field').allowBlank = false; ++ me.lookupReference('freenas_confirmpw_field').allowBlank = false; ++ } + } + }, + +@@ -33010,6 +33028,7 @@ + }, + + setValues: function diff(values) { ++ values.freenas_confirmpw = values.freenas_password; + values.writecache = values.nowritecache ? 0 : 1; + this.callParent([values]); + }, +@@ -33026,7 +33045,7 @@ + allowBlank: false + }, + { +- xtype: me.isCreate ? 'textfield' : 'displayfield', ++ xtype: 'textfield', + name: 'pool', + value: '', + fieldLabel: gettext('Pool'), +@@ -33036,11 +33055,11 @@ + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'blocksize', + value: '4k', +- fieldLabel: gettext('Block Size'), ++ fieldLabel: gettext('ZFS Block Size'), + allowBlank: false + }, + { +- xtype: me.isCreate ? 'textfield' : 'displayfield', ++ xtype: 'textfield', + name: 'target', + value: '', + fieldLabel: gettext('Target'), +@@ -33051,8 +33070,33 @@ + name: 'comstar_tg', + value: '', + fieldLabel: gettext('Target group'), +- bind: me.isCreate ? { disabled: '{!isComstar}' } : { hidden: '{!isComstar}' }, ++ bind: { ++ hidden: '{!isComstar}' ++ }, + allowBlank: true ++ }, ++ { ++ xtype: 'proxmoxcheckbox', ++ name: 'freenas_use_ssl', ++ reference: 'freenas_use_ssl_field', ++ inputId: 'freenas_use_ssl_field', ++ checked: false, ++ bind: { ++ hidden: '{!isFreeNAS}' ++ }, ++ uncheckedValue: 0, ++ fieldLabel: gettext('API use SSL') ++ }, ++ { ++ xtype: 'textfield', ++ name: 'freenas_user', ++ reference: 'freenas_user_field', ++ inputId: 'freenas_user_field', ++ value: '', ++ fieldLabel: gettext('API Username'), ++ bind: { ++ hidden: '{!isFreeNAS}' ++ } + } + ]; + +@@ -33083,7 +33127,9 @@ + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'comstar_hg', + value: '', +- bind: me.isCreate ? { disabled: '{!isComstar}' } : { hidden: '{!isComstar}' }, ++ bind: { ++ hidden: '{!isComstar}' ++ }, + fieldLabel: gettext('Host group'), + allowBlank: true + }, +@@ -33091,9 +33137,62 @@ + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'lio_tpg', + value: '', +- bind: me.isCreate ? { disabled: '{!isLIO}' } : { hidden: '{!isLIO}' }, +- allowBlank: false, +- fieldLabel: gettext('Target portal group') ++ bind: { ++ hidden: '{!isLIO}' ++ }, ++ fieldLabel: gettext('Target portal group'), ++ allowBlank: true ++ }, ++ { ++ xtype: 'proxmoxtextfield', ++ name: 'freenas_apiv4_host', ++ reference: 'freenas_apiv4_host_field', ++ value: '', ++ editable: true, ++ emptyText: Proxmox.Utils.noneText, ++ bind: { ++ hidden: '{!isFreeNAS}' ++ }, ++ fieldLabel: gettext('API IPv4 Host'), ++ }, ++ { ++ xtype: 'proxmoxtextfield', ++ name: 'freenas_password', ++ reference: 'freenas_password_field', ++ inputType: me.isCreate ? '' : 'password', ++ value: '', ++ editable: true, ++ emptyText: Proxmox.Utils.noneText, ++ bind: { ++ hidden: '{!isFreeNAS}' ++ }, ++ fieldLabel: gettext('API Password'), ++ change: function(f, value) { ++ if (f.rendered) { ++ f.up().down('field[name=freenas_confirmpw]').validate(); ++ } ++ } ++ }, ++ { ++ xtype: 'proxmoxtextfield', ++ name: 'freenas_confirmpw', ++ reference: 'freenas_confirmpw_field', ++ inputType: me.isCreate ? '' : 'password', ++ value: '', ++ editable: true, ++ submitValue: false, ++ emptyText: Proxmox.Utils.noneText, ++ bind: { ++ hidden: '{!isFreeNAS}' ++ }, ++ fieldLabel: gettext('Confirm Password'), ++ validator: function(value) { ++ var pw = this.up().down('field[name=freenas_password]').getValue(); ++ if (pw !== value) { ++ return "Passwords do not match!"; ++ } ++ return true; ++ } + } + ]; +