commit
927e51a524
|
|
@ -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
|
||||||
105
README.md
105
README.md
|
|
@ -1,63 +1,66 @@
|
||||||
# FreeNAS ZFS over iSCSI interface [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=TCLNEMBUYQUXN&source=url)
|
# TrueNAS ZFS over iSCSI interface [](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
|
### Updates 2023-02-12<br/> - Added `systemctl restart pvescheduler.service` command to the package.
|
||||||
|
#### Roadmap
|
||||||
|
* Fix automated builds.
|
||||||
|
* Production - 'main' repo component.
|
||||||
|
* Package the patches with the deb package.
|
||||||
|
* Remove the need for the git dependency.
|
||||||
|
* Change to LWP::UserAgent
|
||||||
|
* Remove depenancy of the REST::Client because LWP::UserAgent is already installed and used by Proxmox VE.
|
||||||
|
* Change from FreeNAS to TrueNAS.
|
||||||
|
* Cleanup the FreeNAS repo and name everything to TrueNAS to be inline with the product.
|
||||||
|
* Add API key for direct TrueNAS services.
|
||||||
|
* Will be a new enable field and API key and will only be used by the plugin.
|
||||||
|
* You will still need the SSH keys, username, and password because of Proxmox VE using `iscsiadm` to get the list of disks.
|
||||||
|
* This is tricky because the format needs to be that of the output of 'zfs list' which is not part of the LunCmd but that of the backend Proxmox VE system and the API's do a bunch of JSON stuff.
|
||||||
|
|
||||||
|
## Thank you for all that have recently donated to the project - Updated 2022-06-04
|
||||||
|
Alexander Finkhäuser - Recurring
|
||||||
|
Bjarte Kvamme - Recurring
|
||||||
|
Jonathan Schober - Recurring
|
||||||
|
Frederic Silvi
|
||||||
|
Security Camera
|
||||||
|
Vincent Cui
|
||||||
|
Jakub Jochec
|
||||||
|
|
||||||
|
Mark Komarinski
|
||||||
|
Jesse Bryan
|
||||||
|
Maksym Vasylenko
|
||||||
|
Daniel Most
|
||||||
|
Velocity Host
|
||||||
|
Robert Hancock
|
||||||
Clevvi Technology
|
Clevvi Technology
|
||||||
Mark Elkins - Reoccuring
|
Mark Elkins
|
||||||
Marc Hodler
|
Marc Hodler
|
||||||
Martin Gonzalez
|
Martin Gonzalez
|
||||||
|
|
||||||
|
### 'main' repo (Follows a release branch - Current 2.x) Currently unavailable.
|
||||||
|
Will be production ready code that has been tested (as best as possible) from the 'testing' repo.
|
||||||
|
|
||||||
I have created a debian repo that holds a package to install scripts into the Proxmox VE system that will automatically do all the necessary patching when one or any combo of the following files are changed in the Proxmox VE stream:
|
### 'testing' repo (Follows the master branch)
|
||||||
```
|
Will be 'beta' code for features, bugs, and updates.
|
||||||
/usr/share/pve-manager/js/pvemanagerlib.js <- From package pve-manager
|
|
||||||
/usr/share/pve-docs/api-viewer/apidoc.js <- From package pve-docs
|
|
||||||
/usr/share/perl5/PVE/Storage/ZFSPlugin.pm <- From package libpve-storage-perl
|
|
||||||
```
|
|
||||||
It will also install the /usr/share/perl5/PVE/Storage/LunCmd/FreeNAS.pm (The FreeNAS API plugin), git and librest-client-perl
|
|
||||||
|
|
||||||
If you wish, you may remove the directory 'freenas-proxmox' where your system is currently
|
## New Installs.
|
||||||
housing the repo and then issue the following to have a clean system before installing the
|
Issue the following from a command line:
|
||||||
package.
|
|
||||||
|
|
||||||
On Proxmox 5
|
|
||||||
```bash
|
```bash
|
||||||
apt install --reinstall pve-manager pve-docs libpve-storage-perl
|
curl https://ksatechnologies.jfrog.io/artifactory/ksa-repo-gpg/ksatechnologies-release.gpg -o /etc/apt/trusted.gpg.d/ksatechnologies-release.gpg
|
||||||
```
|
curl https://ksatechnologies.jfrog.io/artifactory/ksa-repo-gpg/ksatechnologies-repo.list -o /etc/apt/sources.list.d/ksatechnologies-repo.list
|
||||||
|
|
||||||
On Proxmox 6
|
|
||||||
```bash
|
|
||||||
apt reinstall pve-manager pve-docs libpve-storage-perl
|
|
||||||
```
|
|
||||||
|
|
||||||
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
|
|
||||||
echo "deb http://repo.ksatechnologies.com/debian/pve stable freenas-proxmox" > /etc/apt/sources.list.d/ksatechnologies-repo.list
|
|
||||||
```
|
|
||||||
|
|
||||||
### I will be using a 'testing' repo to develop the new phase of the Proxmox VE FreeNAS plugin.
|
|
||||||
#### This next phase will introduce the following...
|
|
||||||
* Auto detection of the Proxmox VE version
|
|
||||||
* Auto detection of the FreeNAS version so it will use the V1 or V2 API's or you can select it manually via the Proxmox VE FreeNAS modal
|
|
||||||
* Remove the need for SSH keys and use the API
|
|
||||||
* This is tricky because the format needs to be that of the output of'zfs list' which is not part of the LunCmd but that of the backend Proxmox VE system and the API's do a bunch of JSON stuff.
|
|
||||||
|
|
||||||
#### If you'd like, you may also issue the following commands now or later to use the 'testing' repo.
|
|
||||||
#### Just comment the 'stable' line and uncomment the 'testing' line in
|
|
||||||
#### /etc/apt/sources.list.d/ksatechnologies-repo.list to use. 'testing' is disabled be default.
|
|
||||||
```bash
|
|
||||||
echo "" >> /etc/apt/sources.list.d/ksatechnologies-repo.list
|
|
||||||
echo "# deb http://repo.ksatechnologies.com/debian/pve testing freenas-proxmox" >> /etc/apt/sources.list.d/ksatechnologies-repo.list
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Then issue the following to install the package
|
Then issue the following to install the package
|
||||||
```
|
```bash
|
||||||
apt update
|
apt update
|
||||||
apt install freenas-proxmox
|
apt install freenas-proxmox
|
||||||
```
|
```
|
||||||
|
|
||||||
Then just do your regular upgrade via apt to your system; the package will automatically
|
Before freenas-proxmox-2.2.0-0-beta8 please issue the following:
|
||||||
issue all commands to patch the files.
|
```
|
||||||
|
systemctl restart pvescheduler.service
|
||||||
|
```
|
||||||
|
due to this post https://github.com/TheGrandWazoo/freenas-proxmox/issues/109#issuecomment-1367527917
|
||||||
|
|
||||||
|
Then just do your regular upgrade via apt at the command line or the Proxmox Update subsystem; the package will automatically issue all commands to patch the files.
|
||||||
```bash
|
```bash
|
||||||
apt update
|
apt update
|
||||||
apt [full|dist]-upgrade
|
apt [full|dist]-upgrade
|
||||||
|
|
@ -67,16 +70,16 @@ If you wish not to use the package you may remove it at anytime with
|
||||||
```
|
```
|
||||||
apt [remove|purge] freenas-proxmox
|
apt [remove|purge] freenas-proxmox
|
||||||
```
|
```
|
||||||
This will place you back to a normal and unpatched Proxmox VE install.
|
This will place you back to a normal and non-patched 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...
|
#### NOTE: Please be aware that this plugin uses the TrueNAS APIs but still uses SSH keys due to the underlying Proxmox VE perl modules that use the ```iscsiadm``` command.
|
||||||
|
|
||||||
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 TrueNAS. The code segment should start out `mkdir /etc/pve/priv/zfs`.
|
||||||
|
|
||||||
1. Remember to follow the instructions mentioned above for the SSH keys.
|
1. Remember to follow the instructions mentioned above for the SSH keys.
|
||||||
|
|
||||||
1. Refresh the Proxmox GUI in your browser to load the new Javascript code.
|
2. Refresh the Proxmox GUI in your browser to load the new Javascript code.
|
||||||
|
|
||||||
1. Add your new FreeNAS ZFS-over-iSCSI storage using the FreeNAS-API.
|
3. Add your new TrueNAS ZFS-over-iSCSI storage using the TrueNAS-API.
|
||||||
|
|
||||||
1. Thanks for your support.
|
4. Thanks for your support.
|
||||||
|
|
|
||||||
|
|
@ -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_version = "v1.0"; # Default to v1.0 of the API's
|
||||||
my $freenas_api_methods = undef; # API Methods Nested HASH Ref
|
my $freenas_api_methods = undef; # API Methods Nested HASH Ref
|
||||||
my $freenas_api_variables = undef; # API Variable 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
|
# FreeNAS/TrueNAS (CORE) API Versioning HashRef Matrix
|
||||||
my $freenas_api_version_matrix = {
|
my $freenas_api_version_matrix = {
|
||||||
|
|
@ -197,52 +199,45 @@ sub run_list_view {
|
||||||
|
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
#
|
# Optimized
|
||||||
sub run_list_lu {
|
sub run_list_lu {
|
||||||
my ($scfg, $timeout, $method, $result_value_type, @params) = @_;
|
my ($scfg, $timeout, $method, $result_value_type, @params) = @_;
|
||||||
my $object = $params[0];
|
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 $result = undef;
|
||||||
my $luns = freenas_list_lu($scfg);
|
my $luns = freenas_list_lu($scfg);
|
||||||
foreach my $lun (@$luns) {
|
syslog("info", (caller(0))[3] . " : called with (method: '$method'; result_value_type: '$result_value_type'; param[0]: '$object')");
|
||||||
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");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
$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;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
#
|
# Optimzed
|
||||||
sub run_list_extent {
|
sub run_list_extent {
|
||||||
my ($scfg, $timeout, $method, @params) = @_;
|
my ($scfg, $timeout, $method, @params) = @_;
|
||||||
my $object = $params[0];
|
my $object = $params[0];
|
||||||
|
syslog("info", (caller(0))[3] . " : called with (method: '$method'; params[0]: '$object')");
|
||||||
syslog("info", (caller(0))[3] . " : called with (method=$method; object=$object)");
|
|
||||||
|
|
||||||
my $result = undef;
|
my $result = undef;
|
||||||
my $luns = freenas_list_lu($scfg);
|
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;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -280,24 +275,24 @@ sub run_create_lu {
|
||||||
|
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
#
|
# Optimzied
|
||||||
sub run_delete_lu {
|
sub run_delete_lu {
|
||||||
my ($scfg, $timeout, $method, @params) = @_;
|
my ($scfg, $timeout, $method, @params) = @_;
|
||||||
my $lun_path = $params[0];
|
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 $luns = freenas_list_lu($scfg);
|
||||||
my $lun = undef;
|
my $lun = undef;
|
||||||
my $link = undef;
|
my $link = undef;
|
||||||
foreach my $item (@$luns) {
|
$lun_path =~ s/^\Q$dev_prefix//;
|
||||||
if($dev_prefix . $item->{ $freenas_api_variables->{'extentpath'}} eq $lun_path) {
|
|
||||||
$lun = $item;
|
|
||||||
last;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
my $target_id = freenas_get_targetid($scfg);
|
||||||
die "Unable to find the target id for $scfg->{target}" if !defined($target_id);
|
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);
|
$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
|
# Check if the APIs are accessable via the selected host and scheme
|
||||||
my $code = $freenas_server_list->{$apihost}->request('GET', $apiping)->responseCode();
|
my $api_response = $freenas_server_list->{$apihost}->request('GET', $apiping);
|
||||||
if ($code == 200) { # Successful connection
|
my $code = $api_response->responseCode();
|
||||||
syslog("info", (caller(0))[3] . " : REST connection successful to '" . $apihost . "' using the '" . $scheme . "' protocol");
|
my $type = $api_response->responseHeader('Content-Type');
|
||||||
$runawayprevent = 0;
|
syslog("info", (caller(0))[3] . " : REST connection header Content-Type:'" . $type . "'");
|
||||||
} elsif ($runawayprevent > 1) { # Make sure we are not recursion calling.
|
|
||||||
|
# Make sure we are not recursion calling.
|
||||||
|
if ($runawayprevent > 2) {
|
||||||
freenas_api_log_error($freenas_server_list->{$apihost});
|
freenas_api_log_error($freenas_server_list->{$apihost});
|
||||||
die "Loop recursion prevention";
|
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 (We already check for the correct 'type' above with a 200 so why add additional conditionals).
|
||||||
|
# So change to v2.0 APIs.
|
||||||
|
} elsif ($code == 302 || $code == 200) {
|
||||||
syslog("info", (caller(0))[3] . " : Changing to v2.0 API's");
|
syslog("info", (caller(0))[3] . " : Changing to v2.0 API's");
|
||||||
$runawayprevent++;
|
$runawayprevent++;
|
||||||
$apiping =~ s/v1\.0/v2\.0/;
|
$apiping =~ s/v1\.0/v2\.0/;
|
||||||
freenas_api_connect($scfg);
|
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");
|
syslog("info", (caller(0))[3] . " : Redirecting to HTTPS protocol");
|
||||||
$runawayprevent++;
|
$runawayprevent++;
|
||||||
$scfg->{freenas_use_ssl} = 1;
|
$scfg->{freenas_use_ssl} = 1;
|
||||||
freenas_api_connect($scfg);
|
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});
|
freenas_api_log_error($freenas_server_list->{$apihost});
|
||||||
die "Unable to connect to the FreeNAS API service at '" . $apihost . "' using the '" . $scheme . "' protocol";
|
die "Unable to connect to the FreeNAS API service at '" . $apihost . "' using the '" . $scheme . "' protocol";
|
||||||
}
|
}
|
||||||
|
|
@ -399,16 +404,32 @@ sub freenas_api_check {
|
||||||
} else {
|
} else {
|
||||||
$result = $freenas_rest_connection->responseContent();
|
$result = $freenas_rest_connection->responseContent();
|
||||||
}
|
}
|
||||||
$result =~ s/^"//g;
|
$result =~ s/"//g;
|
||||||
syslog("info", (caller(0))[3] . " : successful : Server version: " . $result);
|
syslog("info", (caller(0))[3] . " : successful : Server version: " . $result);
|
||||||
$result =~ s/^((?!\-\d).*)\-(\d+)\.(\d+)\-([A-Za-z]*)(?(?=\-)\-(\d*)\-(\d*)|(\d?)\.?(\d?))//;
|
if ($result =~ /^(TrueNAS|FreeNAS)-(\d+)\.(\d+)\-U(\d+)(?(?=\.)\.(\d+))$/) {
|
||||||
$product_name = $1;
|
$product_name = $1;
|
||||||
my $freenas_version = sprintf("%02d%02d%02d%02d", $2, $3 || 0, $7 || 0, $8 || 0);
|
$truenas_version = sprintf("%02d%02d%02d%02d", $2, $3 || 0, $4 || 0, $5 || 0);
|
||||||
syslog("info", (caller(0))[3] . " : ". $product_name . " Unformatted Version: " . $freenas_version);
|
} elsif ($result =~ /^(TrueNAS)-(\d+)\.(\d+)(?(?=\-U\d+)-U(\d+)|-\w+)(?(?=\.).(\d+))$/) {
|
||||||
if ($freenas_version >= 11030100) {
|
$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";
|
$freenas_api_version = "v2.0";
|
||||||
$dev_prefix = "/dev/";
|
$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 {
|
} else {
|
||||||
syslog("info", (caller(0))[3] . " : REST Client already initialized");
|
syslog("info", (caller(0))[3] . " : REST Client already initialized");
|
||||||
}
|
}
|
||||||
|
|
@ -512,10 +533,15 @@ sub freenas_iscsi_create_extent {
|
||||||
|
|
||||||
my $name = $lun_path;
|
my $name = $lun_path;
|
||||||
$name =~ s/^.*\///; # all from last /
|
$name =~ s/^.*\///; # all from last /
|
||||||
|
|
||||||
|
my $pool = $scfg->{'pool'};
|
||||||
|
# If TrueNAS-SCALE the slashes (/) need to be converted to dashes (-)
|
||||||
if ($product_name eq "TrueNAS-SCALE") {
|
if ($product_name eq "TrueNAS-SCALE") {
|
||||||
$scfg->{'pool'} =~ s/\//-/;
|
$pool =~ s/\//-/g;
|
||||||
|
syslog("info", (caller(0))[3] . " : TrueNAS-SCALE slash to dash conversion '" . $pool ."'");
|
||||||
}
|
}
|
||||||
$name = $scfg->{'pool'} . ($product_name eq "TrueNAS-SCALE" ? '-' : '/') . $name;
|
$name = $pool . ($product_name eq "TrueNAS-SCALE" ? '-' : '/') . $name;
|
||||||
|
syslog("info", (caller(0))[3] . " : " . $product_name . " extent '". $name . "'");
|
||||||
|
|
||||||
my $device = $lun_path;
|
my $device = $lun_path;
|
||||||
$device =~ s/^\/dev\///; # strip /dev/
|
$device =~ s/^\/dev\///; # strip /dev/
|
||||||
|
|
@ -682,7 +708,7 @@ sub freenas_list_lu {
|
||||||
my $targets = freenas_iscsi_get_target($scfg);
|
my $targets = freenas_iscsi_get_target($scfg);
|
||||||
my $target_id = freenas_get_targetid($scfg);
|
my $target_id = freenas_get_targetid($scfg);
|
||||||
|
|
||||||
my @luns = ();
|
my %lun_hash;
|
||||||
my $iscsi_lunid = undef;
|
my $iscsi_lunid = undef;
|
||||||
|
|
||||||
if(defined($target_id)) {
|
if(defined($target_id)) {
|
||||||
|
|
@ -694,21 +720,21 @@ sub freenas_list_lu {
|
||||||
foreach my $node (@$extents) {
|
foreach my $node (@$extents) {
|
||||||
if($node->{'id'} == $item->{$freenas_api_variables->{'extentid'}}) {
|
if($node->{'id'} == $item->{$freenas_api_variables->{'extentid'}}) {
|
||||||
if ($item->{$freenas_api_variables->{'lunid'}} =~ /(\d+)/) {
|
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 {
|
} else {
|
||||||
syslog("info", (caller(0))[3] . " : iscsi_lunid did not pass tainted testing");
|
syslog("warn", (caller(0))[3] . " : iscsi_lunid did not pass tainted testing");
|
||||||
next;
|
|
||||||
}
|
}
|
||||||
$node->{$freenas_api_variables->{'lunid'}} .= $iscsi_lunid;
|
|
||||||
push(@luns , $node);
|
|
||||||
last;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
syslog("info", (caller(0))[3] . " : successful");
|
syslog("info", (caller(0))[3] . " : successful");
|
||||||
return \@luns;
|
return \%lun_hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1,10 +1,5 @@
|
||||||
<<<<<<< HEAD
|
--- ZFSPlugin.pm.orig 2022-02-04 12:08:01.000000000 -0500
|
||||||
--- ZFSPlugin.pm.orig 2019-09-23 12:17:37.000000000 -0400
|
+++ ZFSPlugin.pm 2022-03-26 13:51:40.660068908 -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
|
|
||||||
@@ -10,6 +10,7 @@
|
@@ -10,6 +10,7 @@
|
||||||
|
|
||||||
use base qw(PVE::Storage::ZFSPoolPlugin);
|
use base qw(PVE::Storage::ZFSPoolPlugin);
|
||||||
|
|
@ -47,8 +42,8 @@
|
||||||
} elsif ($scfg->{iscsiprovider} eq 'istgt') {
|
} elsif ($scfg->{iscsiprovider} eq 'istgt') {
|
||||||
$msg = PVE::Storage::LunCmd::Istgt::run_lun_command($scfg, $timeout, $method, @params);
|
$msg = PVE::Storage::LunCmd::Istgt::run_lun_command($scfg, $timeout, $method, @params);
|
||||||
} elsif ($scfg->{iscsiprovider} eq 'iet') {
|
} elsif ($scfg->{iscsiprovider} eq 'iet') {
|
||||||
@@ -162,6 +168,15 @@
|
@@ -166,6 +172,15 @@
|
||||||
return $class->zfs_request($scfg, undef, 'list_view', $guid);
|
die "lun_number for guid $guid is not a number";
|
||||||
}
|
}
|
||||||
|
|
||||||
+# Part of the multipath enhancement
|
+# Part of the multipath enhancement
|
||||||
|
|
@ -63,7 +58,7 @@
|
||||||
# Configuration
|
# Configuration
|
||||||
|
|
||||||
sub type {
|
sub type {
|
||||||
@@ -180,6 +195,24 @@
|
@@ -184,6 +199,24 @@
|
||||||
description => "iscsi provider",
|
description => "iscsi provider",
|
||||||
type => 'string',
|
type => 'string',
|
||||||
},
|
},
|
||||||
|
|
@ -88,7 +83,7 @@
|
||||||
# this will disable write caching on comstar and istgt.
|
# this will disable write caching on comstar and istgt.
|
||||||
# it is not implemented for iet. iet blockio always operates with
|
# it is not implemented for iet. iet blockio always operates with
|
||||||
# writethrough caching when not in readonly mode
|
# writethrough caching when not in readonly mode
|
||||||
@@ -207,14 +240,18 @@
|
@@ -211,14 +244,18 @@
|
||||||
nodes => { optional => 1 },
|
nodes => { optional => 1 },
|
||||||
disable => { optional => 1 },
|
disable => { optional => 1 },
|
||||||
portal => { fixed => 1 },
|
portal => { fixed => 1 },
|
||||||
|
|
@ -109,7 +104,7 @@
|
||||||
lio_tpg => { optional => 1 },
|
lio_tpg => { optional => 1 },
|
||||||
content => { optional => 1 },
|
content => { optional => 1 },
|
||||||
bwlimit => { optional => 1 },
|
bwlimit => { optional => 1 },
|
||||||
@@ -239,6 +276,40 @@
|
@@ -243,6 +280,40 @@
|
||||||
|
|
||||||
my $path = "iscsi://$portal/$target/$lun";
|
my $path = "iscsi://$portal/$target/$lun";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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" : "<string>"
|
||||||
|
},
|
||||||
|
+ "freenas_user" : {
|
||||||
|
+ "description" : "FreeNAS user for API access",
|
||||||
|
+ "optional" : 1,
|
||||||
|
+ "type" : "string",
|
||||||
|
+ "typetext" : "<string>"
|
||||||
|
+ },
|
||||||
|
+ "freenas_password" : {
|
||||||
|
+ "description" : "FreeNAS password for API access",
|
||||||
|
+ "optional" : 1,
|
||||||
|
+ "type" : "string",
|
||||||
|
+ "typetext" : "<string>"
|
||||||
|
+ },
|
||||||
|
+ "freenas_use_ssl" : {
|
||||||
|
+ "description" : "FreeNAS API access via SSL",
|
||||||
|
+ "optional" : 1,
|
||||||
|
+ "type" : "boolean",
|
||||||
|
+ "typetext" : "<boolean>"
|
||||||
|
+ },
|
||||||
|
+ "freenas_apiv4_host" : {
|
||||||
|
+ "description" : "FreeNAS API Host via IPv4",
|
||||||
|
+ "format" : "address",
|
||||||
|
+ "optional" : 1,
|
||||||
|
+ "type" : "string",
|
||||||
|
+ "typetext" : "<string>"
|
||||||
|
+ },
|
||||||
|
"fuse" : {
|
||||||
|
"description" : "Mount CephFS through FUSE.",
|
||||||
|
"optional" : 1,
|
||||||
|
@@ -44275,6 +44300,12 @@
|
||||||
|
"type" : "boolean",
|
||||||
|
"typetext" : "<boolean>"
|
||||||
|
},
|
||||||
|
+ "target" : {
|
||||||
|
+ "description" : "iSCSI target.",
|
||||||
|
+ "optional" : 1,
|
||||||
|
+ "type" : "string",
|
||||||
|
+ "typetext" : "<string>"
|
||||||
|
+ },
|
||||||
|
"transport" : {
|
||||||
|
"description" : "Gluster transport: tcp or rdma",
|
||||||
|
"enum" : [
|
||||||
|
@@ -44547,6 +44578,31 @@
|
||||||
|
"optional" : 1,
|
||||||
|
"type" : "string",
|
||||||
|
"typetext" : "<string>"
|
||||||
|
+ },
|
||||||
|
+ "freenas_user" : {
|
||||||
|
+ "description" : "FreeNAS user for API access",
|
||||||
|
+ "optional" : 1,
|
||||||
|
+ "type" : "string",
|
||||||
|
+ "typetext" : "<string>"
|
||||||
|
+ },
|
||||||
|
+ "freenas_password" : {
|
||||||
|
+ "description" : "FreeNAS password for API access",
|
||||||
|
+ "optional" : 1,
|
||||||
|
+ "type" : "string",
|
||||||
|
+ "typetext" : "<string>"
|
||||||
|
+ },
|
||||||
|
+ "freenas_use_ssl" : {
|
||||||
|
+ "description" : "FreeNAS API access via SSL",
|
||||||
|
+ "optional" : 1,
|
||||||
|
+ "type" : "boolean",
|
||||||
|
+ "typetext" : "<boolean>"
|
||||||
|
+ },
|
||||||
|
+ "freenas_apiv4_host" : {
|
||||||
|
+ "description" : "FreeNAS API Host via IPv4",
|
||||||
|
+ "format" : "address",
|
||||||
|
+ "optional" : 1,
|
||||||
|
+ "type" : "string",
|
||||||
|
+ "typetext" : "<string>"
|
||||||
|
},
|
||||||
|
"fuse" : {
|
||||||
|
"description" : "Mount CephFS through FUSE.",
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
--- apidoc.js.orig 2019-07-15 15:45:00.000000000 -0400
|
--- apidoc.js.orig 2021-11-15 10:07:34.000000000 -0500
|
||||||
+++ apidoc.js 2019-08-07 13:28:29.292382229 -0400
|
+++ apidoc.js 2021-12-06 08:04:01.648822707 -0500
|
||||||
@@ -35001,6 +35001,31 @@
|
@@ -44064,6 +44064,31 @@
|
||||||
"type" : "string",
|
"type" : "string",
|
||||||
"typetext" : "<string>"
|
"typetext" : "<string>"
|
||||||
},
|
},
|
||||||
|
|
@ -32,7 +32,7 @@
|
||||||
"fuse" : {
|
"fuse" : {
|
||||||
"description" : "Mount CephFS through FUSE.",
|
"description" : "Mount CephFS through FUSE.",
|
||||||
"optional" : 1,
|
"optional" : 1,
|
||||||
@@ -35157,6 +35182,12 @@
|
@@ -44275,6 +44300,12 @@
|
||||||
"type" : "boolean",
|
"type" : "boolean",
|
||||||
"typetext" : "<boolean>"
|
"typetext" : "<boolean>"
|
||||||
},
|
},
|
||||||
|
|
@ -45,7 +45,7 @@
|
||||||
"transport" : {
|
"transport" : {
|
||||||
"description" : "Gluster transport: tcp or rdma",
|
"description" : "Gluster transport: tcp or rdma",
|
||||||
"enum" : [
|
"enum" : [
|
||||||
@@ -35362,6 +35393,31 @@
|
@@ -44547,6 +44578,31 @@
|
||||||
"optional" : 1,
|
"optional" : 1,
|
||||||
"type" : "string",
|
"type" : "string",
|
||||||
"typetext" : "<string>"
|
"typetext" : "<string>"
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
+ },
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
--- pvemanagerlib.js.orig 2021-05-27 08:28:35.000000000 -0400
|
--- pvemanagerlib.js.orig 2022-03-17 09:08:40.000000000 -0400
|
||||||
+++ pvemanagerlib.js 2021-06-10 11:03:15.380175988 -0400
|
+++ pvemanagerlib.js 2022-04-03 08:54:10.229689187 -0400
|
||||||
@@ -7900,6 +7900,7 @@
|
@@ -8068,6 +8068,7 @@
|
||||||
alias: ['widget.pveiScsiProviderSelector'],
|
alias: ['widget.pveiScsiProviderSelector'],
|
||||||
comboItems: [
|
comboItems: [
|
||||||
['comstar', 'Comstar'],
|
['comstar', 'Comstar'],
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
['istgt', 'istgt'],
|
['istgt', 'istgt'],
|
||||||
['iet', 'IET'],
|
['iet', 'IET'],
|
||||||
['LIO', 'LIO'],
|
['LIO', 'LIO'],
|
||||||
@@ -47367,6 +47368,7 @@
|
@@ -49636,6 +49637,7 @@
|
||||||
data: {
|
data: {
|
||||||
isLIO: false,
|
isLIO: false,
|
||||||
isComstar: true,
|
isComstar: true,
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
hasWriteCacheOption: true,
|
hasWriteCacheOption: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -47379,10 +47381,26 @@
|
@@ -49648,10 +49650,26 @@
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
changeISCSIProvider: function(f, newVal, oldVal) {
|
changeISCSIProvider: function(f, newVal, oldVal) {
|
||||||
|
|
@ -44,7 +44,7 @@
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -47400,6 +47418,7 @@
|
@@ -49669,6 +49687,7 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
setValues: function(values) {
|
setValues: function(values) {
|
||||||
|
|
@ -52,7 +52,7 @@
|
||||||
values.writecache = values.nowritecache ? 0 : 1;
|
values.writecache = values.nowritecache ? 0 : 1;
|
||||||
this.callParent([values]);
|
this.callParent([values]);
|
||||||
},
|
},
|
||||||
@@ -47416,7 +47435,7 @@
|
@@ -49685,7 +49704,7 @@
|
||||||
allowBlank: false,
|
allowBlank: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -61,7 +61,7 @@
|
||||||
name: 'pool',
|
name: 'pool',
|
||||||
value: '',
|
value: '',
|
||||||
fieldLabel: gettext('Pool'),
|
fieldLabel: gettext('Pool'),
|
||||||
@@ -47426,11 +47445,11 @@
|
@@ -49695,11 +49714,11 @@
|
||||||
xtype: me.isCreate ? 'textfield' : 'displayfield',
|
xtype: me.isCreate ? 'textfield' : 'displayfield',
|
||||||
name: 'blocksize',
|
name: 'blocksize',
|
||||||
value: '4k',
|
value: '4k',
|
||||||
|
|
@ -75,7 +75,7 @@
|
||||||
name: 'target',
|
name: 'target',
|
||||||
value: '',
|
value: '',
|
||||||
fieldLabel: gettext('Target'),
|
fieldLabel: gettext('Target'),
|
||||||
@@ -47441,9 +47460,34 @@
|
@@ -49710,9 +49729,34 @@
|
||||||
name: 'comstar_tg',
|
name: 'comstar_tg',
|
||||||
value: '',
|
value: '',
|
||||||
fieldLabel: gettext('Target group'),
|
fieldLabel: gettext('Target group'),
|
||||||
|
|
@ -111,7 +111,7 @@
|
||||||
];
|
];
|
||||||
|
|
||||||
me.column2 = [
|
me.column2 = [
|
||||||
@@ -47473,7 +47517,9 @@
|
@@ -49742,7 +49786,9 @@
|
||||||
xtype: me.isCreate ? 'textfield' : 'displayfield',
|
xtype: me.isCreate ? 'textfield' : 'displayfield',
|
||||||
name: 'comstar_hg',
|
name: 'comstar_hg',
|
||||||
value: '',
|
value: '',
|
||||||
|
|
@ -122,7 +122,7 @@
|
||||||
fieldLabel: gettext('Host group'),
|
fieldLabel: gettext('Host group'),
|
||||||
allowBlank: true,
|
allowBlank: true,
|
||||||
},
|
},
|
||||||
@@ -47481,9 +47527,62 @@
|
@@ -49750,9 +49796,62 @@
|
||||||
xtype: me.isCreate ? 'textfield' : 'displayfield',
|
xtype: me.isCreate ? 'textfield' : 'displayfield',
|
||||||
name: 'lio_tpg',
|
name: 'lio_tpg',
|
||||||
value: '',
|
value: '',
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -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" : "<string>"
|
||||||
|
},
|
||||||
|
+ "freenas_user" : {
|
||||||
|
+ "description" : "FreeNAS user for API access",
|
||||||
|
+ "optional" : 1,
|
||||||
|
+ "type" : "string",
|
||||||
|
+ "typetext" : "<string>"
|
||||||
|
+ },
|
||||||
|
+ "freenas_password" : {
|
||||||
|
+ "description" : "FreeNAS password for API access",
|
||||||
|
+ "optional" : 1,
|
||||||
|
+ "type" : "string",
|
||||||
|
+ "typetext" : "<string>"
|
||||||
|
+ },
|
||||||
|
+ "freenas_use_ssl" : {
|
||||||
|
+ "description" : "FreeNAS API access via SSL",
|
||||||
|
+ "optional" : 1,
|
||||||
|
+ "type" : "boolean",
|
||||||
|
+ "typetext" : "<boolean>"
|
||||||
|
+ },
|
||||||
|
+ "freenas_apiv4_host" : {
|
||||||
|
+ "description" : "FreeNAS API Host via IPv4",
|
||||||
|
+ "format" : "address",
|
||||||
|
+ "optional" : 1,
|
||||||
|
+ "type" : "string",
|
||||||
|
+ "typetext" : "<string>"
|
||||||
|
+ },
|
||||||
|
"fuse" : {
|
||||||
|
"description" : "Mount CephFS through FUSE.",
|
||||||
|
"optional" : 1,
|
||||||
|
@@ -44275,6 +44300,12 @@
|
||||||
|
"type" : "boolean",
|
||||||
|
"typetext" : "<boolean>"
|
||||||
|
},
|
||||||
|
+ "target" : {
|
||||||
|
+ "description" : "iSCSI target.",
|
||||||
|
+ "optional" : 1,
|
||||||
|
+ "type" : "string",
|
||||||
|
+ "typetext" : "<string>"
|
||||||
|
+ },
|
||||||
|
"transport" : {
|
||||||
|
"description" : "Gluster transport: tcp or rdma",
|
||||||
|
"enum" : [
|
||||||
|
@@ -44547,6 +44578,31 @@
|
||||||
|
"optional" : 1,
|
||||||
|
"type" : "string",
|
||||||
|
"typetext" : "<string>"
|
||||||
|
+ },
|
||||||
|
+ "freenas_user" : {
|
||||||
|
+ "description" : "FreeNAS user for API access",
|
||||||
|
+ "optional" : 1,
|
||||||
|
+ "type" : "string",
|
||||||
|
+ "typetext" : "<string>"
|
||||||
|
+ },
|
||||||
|
+ "freenas_password" : {
|
||||||
|
+ "description" : "FreeNAS password for API access",
|
||||||
|
+ "optional" : 1,
|
||||||
|
+ "type" : "string",
|
||||||
|
+ "typetext" : "<string>"
|
||||||
|
+ },
|
||||||
|
+ "freenas_use_ssl" : {
|
||||||
|
+ "description" : "FreeNAS API access via SSL",
|
||||||
|
+ "optional" : 1,
|
||||||
|
+ "type" : "boolean",
|
||||||
|
+ "typetext" : "<boolean>"
|
||||||
|
+ },
|
||||||
|
+ "freenas_apiv4_host" : {
|
||||||
|
+ "description" : "FreeNAS API Host via IPv4",
|
||||||
|
+ "format" : "address",
|
||||||
|
+ "optional" : 1,
|
||||||
|
+ "type" : "string",
|
||||||
|
+ "typetext" : "<string>"
|
||||||
|
},
|
||||||
|
"fuse" : {
|
||||||
|
"description" : "Mount CephFS through FUSE.",
|
||||||
|
|
@ -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" : "<string>"
|
||||||
|
},
|
||||||
|
+ "freenas_user" : {
|
||||||
|
+ "description" : "FreeNAS user for API access",
|
||||||
|
+ "optional" : 1,
|
||||||
|
+ "type" : "string",
|
||||||
|
+ "typetext" : "<string>"
|
||||||
|
+ },
|
||||||
|
+ "freenas_password" : {
|
||||||
|
+ "description" : "FreeNAS password for API access",
|
||||||
|
+ "optional" : 1,
|
||||||
|
+ "type" : "string",
|
||||||
|
+ "typetext" : "<string>"
|
||||||
|
+ },
|
||||||
|
+ "freenas_use_ssl" : {
|
||||||
|
+ "description" : "FreeNAS API access via SSL",
|
||||||
|
+ "optional" : 1,
|
||||||
|
+ "type" : "boolean",
|
||||||
|
+ "typetext" : "<boolean>"
|
||||||
|
+ },
|
||||||
|
+ "freenas_apiv4_host" : {
|
||||||
|
+ "description" : "FreeNAS API Host via IPv4",
|
||||||
|
+ "format" : "address",
|
||||||
|
+ "optional" : 1,
|
||||||
|
+ "type" : "string",
|
||||||
|
+ "typetext" : "<string>"
|
||||||
|
+ },
|
||||||
|
"fuse" : {
|
||||||
|
"description" : "Mount CephFS through FUSE.",
|
||||||
|
"optional" : 1,
|
||||||
|
@@ -44275,6 +44300,12 @@
|
||||||
|
"type" : "boolean",
|
||||||
|
"typetext" : "<boolean>"
|
||||||
|
},
|
||||||
|
+ "target" : {
|
||||||
|
+ "description" : "iSCSI target.",
|
||||||
|
+ "optional" : 1,
|
||||||
|
+ "type" : "string",
|
||||||
|
+ "typetext" : "<string>"
|
||||||
|
+ },
|
||||||
|
"transport" : {
|
||||||
|
"description" : "Gluster transport: tcp or rdma",
|
||||||
|
"enum" : [
|
||||||
|
@@ -44547,6 +44578,31 @@
|
||||||
|
"optional" : 1,
|
||||||
|
"type" : "string",
|
||||||
|
"typetext" : "<string>"
|
||||||
|
+ },
|
||||||
|
+ "freenas_user" : {
|
||||||
|
+ "description" : "FreeNAS user for API access",
|
||||||
|
+ "optional" : 1,
|
||||||
|
+ "type" : "string",
|
||||||
|
+ "typetext" : "<string>"
|
||||||
|
+ },
|
||||||
|
+ "freenas_password" : {
|
||||||
|
+ "description" : "FreeNAS password for API access",
|
||||||
|
+ "optional" : 1,
|
||||||
|
+ "type" : "string",
|
||||||
|
+ "typetext" : "<string>"
|
||||||
|
+ },
|
||||||
|
+ "freenas_use_ssl" : {
|
||||||
|
+ "description" : "FreeNAS API access via SSL",
|
||||||
|
+ "optional" : 1,
|
||||||
|
+ "type" : "boolean",
|
||||||
|
+ "typetext" : "<boolean>"
|
||||||
|
+ },
|
||||||
|
+ "freenas_apiv4_host" : {
|
||||||
|
+ "description" : "FreeNAS API Host via IPv4",
|
||||||
|
+ "format" : "address",
|
||||||
|
+ "optional" : 1,
|
||||||
|
+ "type" : "string",
|
||||||
|
+ "typetext" : "<string>"
|
||||||
|
},
|
||||||
|
"fuse" : {
|
||||||
|
"description" : "Mount CephFS through FUSE.",
|
||||||
|
|
@ -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;
|
||||||
|
+ },
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
|
@ -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;
|
||||||
|
+ },
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
Loading…
Reference in New Issue