Added 302 and 307 code handlers on initial API connection and various

other changes.

- Add logic to freenas_api_connect to handle a '302 Found' which seems
to mean it does not handle v1.0 API's. Fixes #60.
- Add logic to freenas_api_connect to handle a '307 Temporary Redirect'
which is when the redirect http to https box is checked. Fixes #59.
- Redesign the RegEx that validates and pulls the version information
from the API system/version call. This is due to a format like
TrueNAS-12.0-BETA instead of [FreeNAS|TrueNAS]-12.0-U1.1. Also make sure
empty RegEx return variables are zero (0) so the version number that is
formulated is correct (e.g. 12000000, 11030302). Fixes #60.
- During testing needed to add a check due to the
api/v2.0/system/version returning a quoted string where
api/v1.0/system/version returned a JSON-format data.
- Tested against baremetal FreeNAS 11.3-U3.2 and virtual TrueNAS
12.0-BETA machines.
This commit is contained in:
Kevin Scott Adams 2020-07-07 11:14:30 -04:00
parent aa11d596bd
commit ac1c31f2d0
1 changed files with 35 additions and 6 deletions

View File

@ -6,6 +6,8 @@ use Data::Dumper;
use PVE::SafeSyslog;
use IO::Socket::SSL;
use LWP::UserAgent;
use HTTP::Request;
use REST::Client;
use MIME::Base64;
use JSON;
@ -16,6 +18,8 @@ my $freenas_rest_connection = undef;
my $freenas_global_config = undef;
my $dev_prefix = "";
my $product_name = undef;
my $apiping = '/api/v1.0/system/version/';
my $runawayprevent = 0;
# FreeNAS API Definitions
my $freenas_api_version = "v1.0"; # Default to v1.0 of the API's
@ -332,9 +336,10 @@ sub freenas_api_connect {
my $scheme = $scfg->{freenas_use_ssl} ? "https" : "http";
my $apihost = defined($scfg->{freenas_apiv4_host}) ? $scfg->{freenas_apiv4_host} : $scfg->{portal};
my $apiping = '/api/v1.0/system/version/';
$freenas_rest_connection = REST::Client->new();
if (! defined $freenas_rest_connection) {
$freenas_rest_connection = REST::Client->new();
}
$freenas_rest_connection->setHost($scheme . '://' . $apihost);
$freenas_rest_connection->addHeader('Content-Type', 'application/json');
$freenas_rest_connection->addHeader('Authorization', 'Basic ' . encode_base64($scfg->{freenas_user} . ':' . $scfg->{freenas_password}));
@ -345,10 +350,27 @@ sub freenas_api_connect {
}
# Check if the APIs are accessable via the selected host and scheme
my $code = $freenas_rest_connection->request('GET', $apiping)->responseCode();
if ($code != 200) {
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.
freenas_api_log_error($freenas_rest_connection, "freenas_api_call");
die "Loop recursion prevention";
} elsif ($code == 302) { # A 302 from FreeNAS means it doesn't like v1.0 APIs.
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.
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.
freenas_api_log_error($freenas_rest_connection, "freenas_api_call");
die "Unable to connect to the FreeNAS API service at '" . $apihost . "' using the '" . $scheme . "' protocol";
}
return;
}
#
@ -357,15 +379,22 @@ sub freenas_api_connect {
#
sub freenas_api_check {
my ($scfg, $timeout) = @_;
my $result = {};
syslog("info", (caller(0))[3] . " : called");
if (! defined $freenas_rest_connection) {
freenas_api_connect($scfg);
my $result = decode_json($freenas_rest_connection->responseContent());
eval {
$result = decode_json($freenas_rest_connection->responseContent());
};
if ($@) {
$result->{'fullversion'} = $freenas_rest_connection->responseContent();
$result->{'fullversion'} =~ s/^"//g;
}
syslog("info", (caller(0))[3] . " : successful : Server version: " . $result->{'fullversion'});
$result->{'fullversion'} =~ s/^(\w+)\-(\d+)\.(\d+)\-U(\d+)\.?(\d?)//;
my $freenas_version = sprintf("%02d%02d%02d%02d", $2, $3, $4, $5);
$result->{'fullversion'} =~ s/^(\w+)\-(\d+)\.(\d+)\-(?:U|BETA)(\d?)\.?(\d?)//;
my $freenas_version = sprintf("%02d%02d%02d%02d", $2, $3 || 0, $4 || 0, $5 || 0);
$product_name = $1;
syslog("info", (caller(0))[3] . " : ". $product_name . " Unformatted Version: " . $freenas_version);
if ($freenas_version >= 11030100) {