diff --git a/.github/stale.yml b/.github/stale.yml new file mode 100644 index 0000000..dc90e5a --- /dev/null +++ b/.github/stale.yml @@ -0,0 +1,17 @@ +# Number of days of inactivity before an issue becomes stale +daysUntilStale: 60 +# Number of days of inactivity before a stale issue is closed +daysUntilClose: 7 +# Issues with these labels will never be considered stale +exemptLabels: + - pinned + - security +# Label to use when marking an issue as stale +staleLabel: wontfix +# Comment to post when marking an issue as stale. Set to `false` to disable +markComment: > + This issue has been automatically marked as stale because it has not had + recent activity. It will be closed if no further activity occurs. Thank you + for your contributions. +# Comment to post when closing a stale issue. Set to `false` to disable +closeComment: false diff --git a/README.md b/README.md index 5b0d190..f940668 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,17 @@ # FreeNAS ZFS over iSCSI interface [![Donate](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=TCLNEMBUYQUXN&source=url) -## Thank you for all that have donated to the project +## Currently trying JFrog for the repo. Just changing the Automation and making sure all works.
I am currently testing an should have at least the repos up for production and testing. You will need to update your repos with the new location and gpg. I will have instructions on this page. + +## Also currently developing for TrueNAS-Core 13 to provide fixes to support all the [Free|True]NAS family. + +## Thank you for all that have recently donated to the project. + Daniel Most + Maksym Vasylenko + Alexander Finkhäuser - Reoccuring + Bjarte Kvamme - Reoccuring + Jonathan Schober - Reoccuring + +## And thanks to all that have donated to the project in the past. Clevvi Technology Mark Elkins - Reoccuring Marc Hodler @@ -29,6 +40,11 @@ On Proxmox 6 apt reinstall pve-manager pve-docs libpve-storage-perl ``` +On Proxmox 7 +```bash +apt reinstall pve-manager pve-docs libpve-storage-perl +``` +## Changing in the near future. Issue the following to install the repo and get your Proxmox VE updating the FreeNAS patches automatically: ```bash wget http://repo.ksatechnologies.com/debian/pve/ksatechnologies-release.gpg -O /etc/apt/trusted.gpg.d/ksatechnologies-repo.gpg @@ -71,7 +87,7 @@ This will place you back to a normal and unpatched Proxmox VE install. Please be aware that this plugin uses the FreeNAS APIs and NOT the ssh/scp interface like the other plugins use, but... -You will still need to configure the SSH connector for listing the ZFS Pools because this is currently being done in a Proxmox module (ZFSPoolPlugin.pm). To configure this please follow the steps at https://pve.proxmox.com/wiki/Storage:_ZFS_over_iSCSI that have to do with SSH between Proxmox VE and FreeNAS. The code segment should start out �mkdir /etc/pve/priv/zfs�. +You will still need to configure the SSH connector for listing the ZFS Pools because this is currently being done in a Proxmox module (ZFSPoolPlugin.pm). To configure this please follow the steps at https://pve.proxmox.com/wiki/Storage:_ZFS_over_iSCSI that have to do with SSH between Proxmox VE and FreeNAS. The code segment should start out `mkdir /etc/pve/priv/zfs`. 1. Remember to follow the instructions mentioned above for the SSH keys. diff --git a/perl5/PVE/Storage/LunCmd/FreeNAS.pm b/perl5/PVE/Storage/LunCmd/FreeNAS.pm index 1bc0198..1bb75c6 100644 --- a/perl5/PVE/Storage/LunCmd/FreeNAS.pm +++ b/perl5/PVE/Storage/LunCmd/FreeNAS.pm @@ -27,6 +27,8 @@ my $runawayprevent = 0; # Recursion prevention variable my $freenas_api_version = "v1.0"; # Default to v1.0 of the API's my $freenas_api_methods = undef; # API Methods Nested HASH Ref my $freenas_api_variables = undef; # API Variable Nested HASH Ref +my $truenas_version = undef; +my $truenas_release_type = "Production"; # FreeNAS/TrueNAS (CORE) API Versioning HashRef Matrix my $freenas_api_version_matrix = { @@ -197,52 +199,45 @@ sub run_list_view { # # -# +# Optimized sub run_list_lu { my ($scfg, $timeout, $method, $result_value_type, @params) = @_; my $object = $params[0]; - syslog("info", (caller(0))[3] . " : called with (method=$method; result_value_type=$result_value_type; object=$object)"); - my $result = undef; my $luns = freenas_list_lu($scfg); - foreach my $lun (@$luns) { - syslog("info", (caller(0))[3] . " : Verifing '$lun->{$freenas_api_variables->{'extentpath'}}' and '$object'"); - if ($dev_prefix . $lun->{$freenas_api_variables->{'extentpath'}} eq $object) { - $result = $result_value_type eq "lun-id" ? $lun->{$freenas_api_variables->{'lunid'}} : $dev_prefix . $lun->{$freenas_api_variables->{'extentpath'}}; - syslog("info",(caller(0))[3] . "($object) '$result_value_type' found $result"); - last; - } - } - if(!defined($result)) { - syslog("info", (caller(0))[3] . "($object) : $result_value_type : lun not found"); - } + syslog("info", (caller(0))[3] . " : called with (method: '$method'; result_value_type: '$result_value_type'; param[0]: '$object')"); + $object =~ s/^\Q$dev_prefix//; + syslog("info", (caller(0))[3] . " : TrueNAS object to find: '$object'"); + if (defined($luns->{$object})) { + my $lu_object = $luns->{$object}; + $result = $result_value_type eq "lun-id" ? $lu_object->{$freenas_api_variables->{'lunid'}} : $dev_prefix . $lu_object->{$freenas_api_variables->{'extentpath'}}; + syslog("info",(caller(0))[3] . " '$object' with key '$result_value_type' found with value: '$result'"); + } else { + syslog("info", (caller(0))[3] . " '$object' with key '$result_value_type' was not found"); + } return $result; } # # -# +# Optimzed sub run_list_extent { my ($scfg, $timeout, $method, @params) = @_; my $object = $params[0]; - - syslog("info", (caller(0))[3] . " : called with (method=$method; object=$object)"); - + syslog("info", (caller(0))[3] . " : called with (method: '$method'; params[0]: '$object')"); my $result = undef; my $luns = freenas_list_lu($scfg); - foreach my $lun (@$luns) { - syslog("info", (caller(0))[3] . " : Verifing '$lun->{$freenas_api_variables->{'extentpath'}}' and '$object'"); - if ($dev_prefix . $lun->{$freenas_api_variables->{'extentpath'}} eq $object) { - $result = $lun->{$freenas_api_variables->{'extentnaa'}}; - syslog("info","FreeNAS::list_extent($object): naa found $result"); - last; - } - } - if (!defined($result)) { - syslog("info","FreeNAS::list_extent($object): naa not found"); - } + $object =~ s/^\Q$dev_prefix//; + syslog("info", (caller(0))[3] . " TrueNAS object to find: '$object'"); + if (defined($luns->{$object})) { + my $lu_object = $luns->{$object}; + $result = $lu_object->{$freenas_api_variables->{'extentnaa'}}; + syslog("info",(caller(0))[3] . " '$object' wtih key '$freenas_api_variables->{'extentnaa'}' found with value: '$result'"); + } else { + syslog("info",(caller(0))[3] . " '$object' with key '$freenas_api_variables->{'extentnaa'}' was not found"); + } return $result; } @@ -280,24 +275,24 @@ sub run_create_lu { # # -# +# Optimzied sub run_delete_lu { my ($scfg, $timeout, $method, @params) = @_; my $lun_path = $params[0]; - syslog("info", (caller(0))[3] . " : called with (method=$method; param[0]=$lun_path)"); + syslog("info", (caller(0))[3] . " : called with (method: '$method'; param[0]: '$lun_path')"); my $luns = freenas_list_lu($scfg); my $lun = undef; my $link = undef; - foreach my $item (@$luns) { - if($dev_prefix . $item->{ $freenas_api_variables->{'extentpath'}} eq $lun_path) { - $lun = $item; - last; - } - } + $lun_path =~ s/^\Q$dev_prefix//; - die "Unable to find the lun $lun_path for $scfg->{target}" if !defined($lun); + if (defined($luns->{$lun_path})) { + $lun = $luns->{$lun_path}; + syslog("info",(caller(0))[3] . " lun: '$lun_path' found"); + } else { + die "Unable to find the lun $lun_path for $scfg->{target}"; + } my $target_id = freenas_get_targetid($scfg); die "Unable to find the target id for $scfg->{target}" if !defined($target_id); @@ -353,24 +348,34 @@ sub freenas_api_connect { $freenas_server_list->{$apihost}->getUseragent()->ssl_opts(SSL_verify_mode => SSL_VERIFY_NONE); } # Check if the APIs are accessable via the selected host and scheme - my $code = $freenas_server_list->{$apihost}->request('GET', $apiping)->responseCode(); - if ($code == 200) { # Successful connection - syslog("info", (caller(0))[3] . " : REST connection successful to '" . $apihost . "' using the '" . $scheme . "' protocol"); - $runawayprevent = 0; - } elsif ($runawayprevent > 1) { # Make sure we are not recursion calling. + my $api_response = $freenas_server_list->{$apihost}->request('GET', $apiping); + my $code = $api_response->responseCode(); + my $type = $api_response->responseHeader('Content-Type'); + syslog("info", (caller(0))[3] . " : REST connection header Content-Type:'" . $type . "'"); + + # Make sure we are not recursion calling. + if ($runawayprevent > 1) { freenas_api_log_error($freenas_server_list->{$apihost}); die "Loop recursion prevention"; - } elsif ($code == 302) { # A 302 from FreeNAS means it doesn't like v1.0 APIs. + # Successful connection + } elsif ($code == 200 && ($type =~ /^text\/plain/ || $type =~ /^application\/json/)) { + syslog("info", (caller(0))[3] . " : REST connection successful to '" . $apihost . "' using the '" . $scheme . "' protocol"); + $runawayprevent = 0; + # A 302 or 200 with Content-Type not 'text/plain' from {True|Free}NAS means it doesn't like v1.0 APIs. + # So change to v2.0 APIs. + } elsif ($code == 302 || ($code == 200 && $type !~ /^text\/plain/)) { syslog("info", (caller(0))[3] . " : Changing to v2.0 API's"); $runawayprevent++; $apiping =~ s/v1\.0/v2\.0/; freenas_api_connect($scfg); - } elsif ($code == 307) { # A 307 from FreeNAS means rediect http to https. + # A 307 from FreeNAS means rediect http to https. + } elsif ($code == 307) { syslog("info", (caller(0))[3] . " : Redirecting to HTTPS protocol"); $runawayprevent++; $scfg->{freenas_use_ssl} = 1; freenas_api_connect($scfg); - } else { # For now, any other code we fail. + # For now, any other code we fail. + } else { freenas_api_log_error($freenas_server_list->{$apihost}); die "Unable to connect to the FreeNAS API service at '" . $apihost . "' using the '" . $scheme . "' protocol"; } @@ -395,18 +400,36 @@ sub freenas_api_check { $result = decode_json($freenas_rest_connection->responseContent()); }; if ($@) { - $result->{'fullversion'} = $freenas_rest_connection->responseContent(); - $result->{'fullversion'} =~ s/^"//g; + $result = $freenas_rest_connection->responseContent(); + } else { + $result = $freenas_rest_connection->responseContent(); } - syslog("info", (caller(0))[3] . " : successful : Server version: " . $result->{'fullversion'}); - $result->{'fullversion'} =~ s/^((?!\-\d).*)\-(\d+)\.(\d+)\-([A-Za-z]*)(?(?=\-)\-(\d*)\-(\d*)|(\d?)\.?(\d?))//; - $product_name = $1; - my $freenas_version = sprintf("%02d%02d%02d%02d", $2, $3 || 0, $7 || 0, $8 || 0); - syslog("info", (caller(0))[3] . " : ". $product_name . " Unformatted Version: " . $freenas_version); - if ($freenas_version >= 11030100) { + $result =~ s/"//g; + syslog("info", (caller(0))[3] . " : successful : Server version: " . $result); + if ($result =~ /^(TrueNAS|FreeNAS)-(\d+)\.(\d+)\-U(\d+)(?(?=\.)\.(\d+))$/) { + $product_name = $1; + $truenas_version = sprintf("%02d%02d%02d%02d", $2, $3 || 0, $4 || 0, $5 || 0); + } elsif ($result =~ /^(TrueNAS)-(\d+)\.(\d+)(?(?=\-U\d+)-U(\d+)|-\w+)(?(?=\.).(\d+))$/) { + $product_name = $1; + $truenas_version = sprintf("%02d%02d%02d%02d", $2, $3 || 0, $4 || 0, $6 || 0); + $truenas_release_type = $5 || "Production"; + } elsif ($result =~ /^(TrueNAS-SCALE)-(\d+)\.(\d+)(?(?=\-)-(\w+))\.(\d+)(?(?=\.)\.(\d+))(?(?=\-)-(\d+))$/) { + $product_name = $1; + $truenas_version = sprintf("%02d%02d%02d%02d", $2, $3 || 0, $5 || 0, $7 || 0); + $truenas_release_type = $4 || "Production"; + } else { + $product_name = "Unknown"; + $truenas_release_type = "Unknown"; + syslog("error", (caller(0))[3] . " : Could not parse the version of TrueNAS."); + } + syslog("info", (caller(0))[3] . " : ". $product_name . " Unformatted Version: " . $truenas_version); + if ($truenas_version >= 11030100) { $freenas_api_version = "v2.0"; $dev_prefix = "/dev/"; } + if ($truenas_release_type ne "Production") { + syslog("warn", (caller(0))[3] . " : The '" . $product_name . "' release type of '" . $truenas_release_type . "' may not worked due to unsupported changes."); + } } else { syslog("info", (caller(0))[3] . " : REST Client already initialized"); } @@ -510,7 +533,11 @@ sub freenas_iscsi_create_extent { my $name = $lun_path; $name =~ s/^.*\///; # all from last / - $name = $scfg->{'pool'} . ($product_name eq "TrueNAS-SCALE" ? '-' : '/') . $name; + my $pool = $scfg->{'pool'}; + if ($product_name eq "TrueNAS-SCALE") { + $pool =~ s/\//-/g; + } + $name = $pool . ($product_name eq "TrueNAS-SCALE" ? '-' : '/') . $name; my $device = $lun_path; $device =~ s/^\/dev\///; # strip /dev/ @@ -677,7 +704,7 @@ sub freenas_list_lu { my $targets = freenas_iscsi_get_target($scfg); my $target_id = freenas_get_targetid($scfg); - my @luns = (); + my %lun_hash; my $iscsi_lunid = undef; if(defined($target_id)) { @@ -689,21 +716,21 @@ sub freenas_list_lu { foreach my $node (@$extents) { if($node->{'id'} == $item->{$freenas_api_variables->{'extentid'}}) { if ($item->{$freenas_api_variables->{'lunid'}} =~ /(\d+)/) { - $iscsi_lunid = "$1"; + if (defined($node)) { + $node->{$freenas_api_variables->{'lunid'}} .= "$1"; + $lun_hash{$node->{$freenas_api_variables->{'extentpath'}}} = $node; + } + last; } else { - syslog("info", (caller(0))[3] . " : iscsi_lunid did not pass tainted testing"); - next; + syslog("warn", (caller(0))[3] . " : iscsi_lunid did not pass tainted testing"); } - $node->{$freenas_api_variables->{'lunid'}} .= $iscsi_lunid; - push(@luns , $node); - last; } } } } } syslog("info", (caller(0))[3] . " : successful"); - return \@luns; + return \%lun_hash; } # diff --git a/perl5/PVE/Storage/ZFSPlugin-7.1-1_1.pm.patch b/perl5/PVE/Storage/ZFSPlugin-7.1-1_1.pm.patch new file mode 100644 index 0000000..d791749 --- /dev/null +++ b/perl5/PVE/Storage/ZFSPlugin-7.1-1_1.pm.patch @@ -0,0 +1,147 @@ +--- ZFSPlugin.pm.orig 2022-02-04 12:08:01.000000000 -0500 ++++ ZFSPlugin.pm 2022-03-26 13:51:40.660068908 -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') { +@@ -166,6 +172,15 @@ + die "lun_number for guid $guid is not a number"; + } + ++# 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 { +@@ -184,6 +199,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 +@@ -211,14 +244,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 }, +@@ -243,6 +280,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 = `/usr/sbin/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/perl5/PVE/Storage/ZFSPlugin.pm.patch b/perl5/PVE/Storage/ZFSPlugin.pm.patch index 8fadf60..d791749 100644 --- a/perl5/PVE/Storage/ZFSPlugin.pm.patch +++ b/perl5/PVE/Storage/ZFSPlugin.pm.patch @@ -1,10 +1,5 @@ -<<<<<<< HEAD ---- ZFSPlugin.pm.orig 2019-09-23 12:17:37.000000000 -0400 -+++ ZFSPlugin.pm 2019-10-13 09:31:58.780554103 -0400 -======= ---- ZFSPlugin.pm.orig 2019-09-03 04:24:37.000000000 -0400 -+++ ZFSPlugin.pm 2019-09-22 13:54:51.570048336 -0400 ->>>>>>> branch 'master' of https://github.com/TheGrandWazoo/freenas-proxmox.git +--- ZFSPlugin.pm.orig 2022-02-04 12:08:01.000000000 -0500 ++++ ZFSPlugin.pm 2022-03-26 13:51:40.660068908 -0400 @@ -10,6 +10,7 @@ use base qw(PVE::Storage::ZFSPoolPlugin); @@ -47,8 +42,8 @@ } elsif ($scfg->{iscsiprovider} eq 'istgt') { $msg = PVE::Storage::LunCmd::Istgt::run_lun_command($scfg, $timeout, $method, @params); } elsif ($scfg->{iscsiprovider} eq 'iet') { -@@ -162,6 +168,15 @@ - return $class->zfs_request($scfg, undef, 'list_view', $guid); +@@ -166,6 +172,15 @@ + die "lun_number for guid $guid is not a number"; } +# Part of the multipath enhancement @@ -63,7 +58,7 @@ # Configuration sub type { -@@ -180,6 +195,24 @@ +@@ -184,6 +199,24 @@ description => "iscsi provider", type => 'string', }, @@ -88,7 +83,7 @@ # 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 -@@ -207,14 +240,18 @@ +@@ -211,14 +244,18 @@ nodes => { optional => 1 }, disable => { optional => 1 }, portal => { fixed => 1 }, @@ -109,7 +104,7 @@ lio_tpg => { optional => 1 }, content => { optional => 1 }, bwlimit => { optional => 1 }, -@@ -239,6 +276,40 @@ +@@ -243,6 +280,40 @@ my $path = "iscsi://$portal/$target/$lun"; diff --git a/pve-docs/api-viewer/apidoc-7.1-2_1.js.patch b/pve-docs/api-viewer/apidoc-7.1-2_1.js.patch new file mode 100644 index 0000000..477f9f4 --- /dev/null +++ b/pve-docs/api-viewer/apidoc-7.1-2_1.js.patch @@ -0,0 +1,79 @@ +--- apidoc.js.orig 2021-11-15 10:07:34.000000000 -0500 ++++ apidoc.js 2021-12-06 08:04:01.648822707 -0500 +@@ -44064,6 +44064,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, +@@ -44275,6 +44300,12 @@ + "type" : "boolean", + "typetext" : "" + }, ++ "target" : { ++ "description" : "iSCSI target.", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, + "transport" : { + "description" : "Gluster transport: tcp or rdma", + "enum" : [ +@@ -44547,6 +44578,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/pve-docs/api-viewer/apidoc.js.patch b/pve-docs/api-viewer/apidoc.js.patch index 3bc6dd7..477f9f4 100644 --- a/pve-docs/api-viewer/apidoc.js.patch +++ b/pve-docs/api-viewer/apidoc.js.patch @@ -1,6 +1,6 @@ ---- 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 @@ +--- apidoc.js.orig 2021-11-15 10:07:34.000000000 -0500 ++++ apidoc.js 2021-12-06 08:04:01.648822707 -0500 +@@ -44064,6 +44064,31 @@ "type" : "string", "typetext" : "" }, @@ -32,7 +32,7 @@ "fuse" : { "description" : "Mount CephFS through FUSE.", "optional" : 1, -@@ -35157,6 +35182,12 @@ +@@ -44275,6 +44300,12 @@ "type" : "boolean", "typetext" : "" }, @@ -45,7 +45,7 @@ "transport" : { "description" : "Gluster transport: tcp or rdma", "enum" : [ -@@ -35362,6 +35393,31 @@ +@@ -44547,6 +44578,31 @@ "optional" : 1, "type" : "string", "typetext" : "" diff --git a/pve-manager/js/pvemanagerlib-6.3-6_1.js.patch b/pve-manager/js/pvemanagerlib-6.3-6_1.js.patch new file mode 100644 index 0000000..12dc4a5 --- /dev/null +++ b/pve-manager/js/pvemanagerlib-6.3-6_1.js.patch @@ -0,0 +1,189 @@ +--- pvemanagerlib.js.orig 2021-03-09 02:22:47.000000000 -0500 ++++ pvemanagerlib.js 2021-03-20 11:52:39.694828636 -0400 +@@ -7849,6 +7849,7 @@ + alias: ['widget.pveiScsiProviderSelector'], + comboItems: [ + ['comstar', 'Comstar'], ++ ['freenas', 'FreeNAS-API'], + ['istgt', 'istgt'], + ['iet', 'IET'], + ['LIO', 'LIO'], +@@ -46874,6 +46875,7 @@ + data: { + isLIO: false, + isComstar: true, ++ isFreeNAS: false, + hasWriteCacheOption: true, + }, + }, +@@ -46886,10 +46888,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; ++ } + }, + }, + +@@ -46907,6 +46925,7 @@ + }, + + setValues: function diff(values) { ++ values.freenas_confirmpw = values.freenas_password; + values.writecache = values.nowritecache ? 0 : 1; + this.callParent([values]); + }, +@@ -46923,7 +46942,7 @@ + allowBlank: false, + }, + { +- xtype: me.isCreate ? 'textfield' : 'displayfield', ++ xtype: 'textfield', + name: 'pool', + value: '', + fieldLabel: gettext('Pool'), +@@ -46933,11 +46952,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'), +@@ -46948,9 +46967,34 @@ + 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}' ++ }, ++ }, + ]; + + me.column2 = [ +@@ -46980,7 +47024,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, + }, +@@ -46988,9 +47034,62 @@ + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'lio_tpg', + value: '', +- bind: me.isCreate ? { disabled: '{!isLIO}' } : { hidden: '{!isLIO}' }, +- allowBlank: false, ++ 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/pve-manager/js/pvemanagerlib-6.4-8_1.js.patch b/pve-manager/js/pvemanagerlib-6.4-8_1.js.patch new file mode 100644 index 0000000..90e9098 --- /dev/null +++ b/pve-manager/js/pvemanagerlib-6.4-8_1.js.patch @@ -0,0 +1,189 @@ +--- pvemanagerlib.js.orig 2021-05-27 08:28:35.000000000 -0400 ++++ pvemanagerlib.js 2021-06-10 11:03:15.380175988 -0400 +@@ -7900,6 +7900,7 @@ + alias: ['widget.pveiScsiProviderSelector'], + comboItems: [ + ['comstar', 'Comstar'], ++ ['freenas', 'FreeNAS-API'], + ['istgt', 'istgt'], + ['iet', 'IET'], + ['LIO', 'LIO'], +@@ -47367,6 +47368,7 @@ + data: { + isLIO: false, + isComstar: true, ++ isFreeNAS: false, + hasWriteCacheOption: true, + }, + }, +@@ -47379,10 +47381,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; ++ } + }, + }, + +@@ -47400,6 +47418,7 @@ + }, + + setValues: function(values) { ++ values.freenas_confirmpw = values.freenas_password; + values.writecache = values.nowritecache ? 0 : 1; + this.callParent([values]); + }, +@@ -47416,7 +47435,7 @@ + allowBlank: false, + }, + { +- xtype: me.isCreate ? 'textfield' : 'displayfield', ++ xtype: 'textfield', + name: 'pool', + value: '', + fieldLabel: gettext('Pool'), +@@ -47426,11 +47445,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'), +@@ -47441,9 +47460,34 @@ + 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}' ++ }, ++ }, + ]; + + me.column2 = [ +@@ -47473,7 +47517,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, + }, +@@ -47481,9 +47527,62 @@ + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'lio_tpg', + value: '', +- bind: me.isCreate ? { disabled: '{!isLIO}' } : { hidden: '{!isLIO}' }, +- allowBlank: false, ++ 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/pve-manager/js/pvemanagerlib-7.1-11_1.js.patch b/pve-manager/js/pvemanagerlib-7.1-11_1.js.patch new file mode 100644 index 0000000..52019ab --- /dev/null +++ b/pve-manager/js/pvemanagerlib-7.1-11_1.js.patch @@ -0,0 +1,189 @@ +--- pvemanagerlib.js.orig 2022-03-17 09:08:40.000000000 -0400 ++++ pvemanagerlib.js 2022-04-03 08:54:10.229689187 -0400 +@@ -8068,6 +8068,7 @@ + alias: ['widget.pveiScsiProviderSelector'], + comboItems: [ + ['comstar', 'Comstar'], ++ ['freenas', 'FreeNAS-API'], + ['istgt', 'istgt'], + ['iet', 'IET'], + ['LIO', 'LIO'], +@@ -49636,6 +49637,7 @@ + data: { + isLIO: false, + isComstar: true, ++ isFreeNAS: false, + hasWriteCacheOption: true, + }, + }, +@@ -49648,10 +49650,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; ++ } + }, + }, + +@@ -49669,6 +49687,7 @@ + }, + + setValues: function(values) { ++ values.freenas_confirmpw = values.freenas_password; + values.writecache = values.nowritecache ? 0 : 1; + this.callParent([values]); + }, +@@ -49685,7 +49704,7 @@ + allowBlank: false, + }, + { +- xtype: me.isCreate ? 'textfield' : 'displayfield', ++ xtype: 'textfield', + name: 'pool', + value: '', + fieldLabel: gettext('Pool'), +@@ -49695,11 +49714,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'), +@@ -49710,9 +49729,34 @@ + 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}' ++ }, ++ }, + ]; + + me.column2 = [ +@@ -49742,7 +49786,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, + }, +@@ -49750,9 +49796,62 @@ + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'lio_tpg', + value: '', +- bind: me.isCreate ? { disabled: '{!isLIO}' } : { hidden: '{!isLIO}' }, +- allowBlank: false, ++ 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/pve-manager/js/pvemanagerlib.js.patch b/pve-manager/js/pvemanagerlib.js.patch index b4da53d..52019ab 100644 --- a/pve-manager/js/pvemanagerlib.js.patch +++ b/pve-manager/js/pvemanagerlib.js.patch @@ -1,23 +1,23 @@ ---- pvemanagerlib.js.orig 2019-09-03 04:31:21.000000000 -0400 -+++ pvemanagerlib.js 2019-09-22 13:54:51.602048049 -0400 -@@ -6183,6 +6183,7 @@ +--- pvemanagerlib.js.orig 2022-03-17 09:08:40.000000000 -0400 ++++ pvemanagerlib.js 2022-04-03 08:54:10.229689187 -0400 +@@ -8068,6 +8068,7 @@ alias: ['widget.pveiScsiProviderSelector'], comboItems: [ ['comstar', 'Comstar'], + ['freenas', 'FreeNAS-API'], - [ 'istgt', 'istgt'], - [ 'iet', 'IET'], - [ 'LIO', 'LIO'] -@@ -32992,6 +32993,7 @@ + ['istgt', 'istgt'], + ['iet', 'IET'], + ['LIO', 'LIO'], +@@ -49636,6 +49637,7 @@ data: { isLIO: false, isComstar: true, -+ isFreeNAS: false, - hasWriteCacheOption: true - } ++ isFreeNAS: false, + hasWriteCacheOption: true, + }, }, -@@ -33004,10 +33006,26 @@ - } +@@ -49648,10 +49650,26 @@ + }, }, changeISCSIProvider: function(f, newVal, oldVal) { + var me = this; @@ -41,19 +41,19 @@ + me.lookupReference('freenas_password_field').allowBlank = false; + me.lookupReference('freenas_confirmpw_field').allowBlank = false; + } - } + }, }, -@@ -33025,6 +33043,7 @@ +@@ -49669,6 +49687,7 @@ }, - setValues: function diff(values) { -+ values.freenas_confirmpw = values.freenas_password; + setValues: function(values) { ++ values.freenas_confirmpw = values.freenas_password; values.writecache = values.nowritecache ? 0 : 1; this.callParent([values]); }, -@@ -33041,7 +33060,7 @@ - allowBlank: false +@@ -49685,7 +49704,7 @@ + allowBlank: false, }, { - xtype: me.isCreate ? 'textfield' : 'displayfield', @@ -61,13 +61,13 @@ name: 'pool', value: '', fieldLabel: gettext('Pool'), -@@ -33051,11 +33070,11 @@ +@@ -49695,11 +49714,11 @@ xtype: me.isCreate ? 'textfield' : 'displayfield', name: 'blocksize', value: '4k', - fieldLabel: gettext('Block Size'), + fieldLabel: gettext('ZFS Block Size'), - allowBlank: false + allowBlank: false, }, { - xtype: me.isCreate ? 'textfield' : 'displayfield', @@ -75,7 +75,7 @@ name: 'target', value: '', fieldLabel: gettext('Target'), -@@ -33066,8 +33085,33 @@ +@@ -49710,9 +49729,34 @@ name: 'comstar_tg', value: '', fieldLabel: gettext('Target group'), @@ -83,8 +83,8 @@ + bind: { + hidden: '{!isComstar}' + }, - allowBlank: true -+ }, + allowBlank: true, + }, + { + xtype: 'proxmoxcheckbox', + name: 'freenas_use_ssl', @@ -95,7 +95,7 @@ + hidden: '{!isFreeNAS}' + }, + uncheckedValue: 0, -+ fieldLabel: gettext('API use SSL') ++ fieldLabel: gettext('API use SSL'), + }, + { + xtype: 'textfield', @@ -106,11 +106,12 @@ + fieldLabel: gettext('API Username'), + bind: { + hidden: '{!isFreeNAS}' -+ } - } ++ }, ++ }, ]; -@@ -33098,7 +33142,9 @@ + me.column2 = [ +@@ -49742,7 +49786,9 @@ xtype: me.isCreate ? 'textfield' : 'displayfield', name: 'comstar_hg', value: '', @@ -119,19 +120,18 @@ + hidden: '{!isComstar}' + }, fieldLabel: gettext('Host group'), - allowBlank: true + allowBlank: true, }, -@@ -33106,9 +33152,62 @@ +@@ -49750,9 +49796,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'), + fieldLabel: gettext('Target portal group'), + allowBlank: true + }, + { @@ -162,7 +162,7 @@ + if (f.rendered) { + f.up().down('field[name=freenas_confirmpw]').validate(); + } -+ } ++ }, + }, + { + xtype: 'proxmoxtextfield', @@ -183,7 +183,7 @@ + return "Passwords do not match!"; + } + return true; -+ } - } ++ }, + }, ]; diff --git a/stable-7/perl5/PVE/Storage/ZFSPlugin-7.1-1_1.pm.patch b/stable-7/perl5/PVE/Storage/ZFSPlugin-7.1-1_1.pm.patch new file mode 100644 index 0000000..d791749 --- /dev/null +++ b/stable-7/perl5/PVE/Storage/ZFSPlugin-7.1-1_1.pm.patch @@ -0,0 +1,147 @@ +--- ZFSPlugin.pm.orig 2022-02-04 12:08:01.000000000 -0500 ++++ ZFSPlugin.pm 2022-03-26 13:51:40.660068908 -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') { +@@ -166,6 +172,15 @@ + die "lun_number for guid $guid is not a number"; + } + ++# 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 { +@@ -184,6 +199,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 +@@ -211,14 +244,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 }, +@@ -243,6 +280,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 = `/usr/sbin/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-7/perl5/PVE/Storage/ZFSPlugin.pm.patch b/stable-7/perl5/PVE/Storage/ZFSPlugin.pm.patch new file mode 100644 index 0000000..d791749 --- /dev/null +++ b/stable-7/perl5/PVE/Storage/ZFSPlugin.pm.patch @@ -0,0 +1,147 @@ +--- ZFSPlugin.pm.orig 2022-02-04 12:08:01.000000000 -0500 ++++ ZFSPlugin.pm 2022-03-26 13:51:40.660068908 -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') { +@@ -166,6 +172,15 @@ + die "lun_number for guid $guid is not a number"; + } + ++# 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 { +@@ -184,6 +199,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 +@@ -211,14 +244,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 }, +@@ -243,6 +280,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 = `/usr/sbin/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-7/pve-docs/api-viewer/apidoc-7.1-2_1.js.patch b/stable-7/pve-docs/api-viewer/apidoc-7.1-2_1.js.patch new file mode 100644 index 0000000..477f9f4 --- /dev/null +++ b/stable-7/pve-docs/api-viewer/apidoc-7.1-2_1.js.patch @@ -0,0 +1,79 @@ +--- apidoc.js.orig 2021-11-15 10:07:34.000000000 -0500 ++++ apidoc.js 2021-12-06 08:04:01.648822707 -0500 +@@ -44064,6 +44064,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, +@@ -44275,6 +44300,12 @@ + "type" : "boolean", + "typetext" : "" + }, ++ "target" : { ++ "description" : "iSCSI target.", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, + "transport" : { + "description" : "Gluster transport: tcp or rdma", + "enum" : [ +@@ -44547,6 +44578,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-7/pve-docs/api-viewer/apidoc.js.patch b/stable-7/pve-docs/api-viewer/apidoc.js.patch new file mode 100644 index 0000000..477f9f4 --- /dev/null +++ b/stable-7/pve-docs/api-viewer/apidoc.js.patch @@ -0,0 +1,79 @@ +--- apidoc.js.orig 2021-11-15 10:07:34.000000000 -0500 ++++ apidoc.js 2021-12-06 08:04:01.648822707 -0500 +@@ -44064,6 +44064,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, +@@ -44275,6 +44300,12 @@ + "type" : "boolean", + "typetext" : "" + }, ++ "target" : { ++ "description" : "iSCSI target.", ++ "optional" : 1, ++ "type" : "string", ++ "typetext" : "" ++ }, + "transport" : { + "description" : "Gluster transport: tcp or rdma", + "enum" : [ +@@ -44547,6 +44578,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-7/pve-manager/js/pvemanagerlib-7.1-11_1.js.patch b/stable-7/pve-manager/js/pvemanagerlib-7.1-11_1.js.patch new file mode 100644 index 0000000..52019ab --- /dev/null +++ b/stable-7/pve-manager/js/pvemanagerlib-7.1-11_1.js.patch @@ -0,0 +1,189 @@ +--- pvemanagerlib.js.orig 2022-03-17 09:08:40.000000000 -0400 ++++ pvemanagerlib.js 2022-04-03 08:54:10.229689187 -0400 +@@ -8068,6 +8068,7 @@ + alias: ['widget.pveiScsiProviderSelector'], + comboItems: [ + ['comstar', 'Comstar'], ++ ['freenas', 'FreeNAS-API'], + ['istgt', 'istgt'], + ['iet', 'IET'], + ['LIO', 'LIO'], +@@ -49636,6 +49637,7 @@ + data: { + isLIO: false, + isComstar: true, ++ isFreeNAS: false, + hasWriteCacheOption: true, + }, + }, +@@ -49648,10 +49650,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; ++ } + }, + }, + +@@ -49669,6 +49687,7 @@ + }, + + setValues: function(values) { ++ values.freenas_confirmpw = values.freenas_password; + values.writecache = values.nowritecache ? 0 : 1; + this.callParent([values]); + }, +@@ -49685,7 +49704,7 @@ + allowBlank: false, + }, + { +- xtype: me.isCreate ? 'textfield' : 'displayfield', ++ xtype: 'textfield', + name: 'pool', + value: '', + fieldLabel: gettext('Pool'), +@@ -49695,11 +49714,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'), +@@ -49710,9 +49729,34 @@ + 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}' ++ }, ++ }, + ]; + + me.column2 = [ +@@ -49742,7 +49786,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, + }, +@@ -49750,9 +49796,62 @@ + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'lio_tpg', + value: '', +- bind: me.isCreate ? { disabled: '{!isLIO}' } : { hidden: '{!isLIO}' }, +- allowBlank: false, ++ 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-7/pve-manager/js/pvemanagerlib.js.patch b/stable-7/pve-manager/js/pvemanagerlib.js.patch new file mode 100644 index 0000000..52019ab --- /dev/null +++ b/stable-7/pve-manager/js/pvemanagerlib.js.patch @@ -0,0 +1,189 @@ +--- pvemanagerlib.js.orig 2022-03-17 09:08:40.000000000 -0400 ++++ pvemanagerlib.js 2022-04-03 08:54:10.229689187 -0400 +@@ -8068,6 +8068,7 @@ + alias: ['widget.pveiScsiProviderSelector'], + comboItems: [ + ['comstar', 'Comstar'], ++ ['freenas', 'FreeNAS-API'], + ['istgt', 'istgt'], + ['iet', 'IET'], + ['LIO', 'LIO'], +@@ -49636,6 +49637,7 @@ + data: { + isLIO: false, + isComstar: true, ++ isFreeNAS: false, + hasWriteCacheOption: true, + }, + }, +@@ -49648,10 +49650,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; ++ } + }, + }, + +@@ -49669,6 +49687,7 @@ + }, + + setValues: function(values) { ++ values.freenas_confirmpw = values.freenas_password; + values.writecache = values.nowritecache ? 0 : 1; + this.callParent([values]); + }, +@@ -49685,7 +49704,7 @@ + allowBlank: false, + }, + { +- xtype: me.isCreate ? 'textfield' : 'displayfield', ++ xtype: 'textfield', + name: 'pool', + value: '', + fieldLabel: gettext('Pool'), +@@ -49695,11 +49714,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'), +@@ -49710,9 +49729,34 @@ + 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}' ++ }, ++ }, + ]; + + me.column2 = [ +@@ -49742,7 +49786,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, + }, +@@ -49750,9 +49796,62 @@ + xtype: me.isCreate ? 'textfield' : 'displayfield', + name: 'lio_tpg', + value: '', +- bind: me.isCreate ? { disabled: '{!isLIO}' } : { hidden: '{!isLIO}' }, +- allowBlank: false, ++ 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; ++ }, + }, + ]; +