FreeNAS API v2.0 features
- Allows the use of FreeNAS API v2.0 so we can finally remove a VM drive from the Proxmox VE GUI. - Created a Frankenstein of out of FreeNAS.pm to allow 'one module to rule them all' for v1.0 and v2.0 API's to FreeNAS. - librest-client-perl changes so the call can have a <body/> to it on GET and DELETE methods. - Some spelling mistakes. - Better syslog entries. - More debbugging for testing purposes to the syslog.
This commit is contained in:
		
							parent
							
								
									006dacc479
								
							
						
					
					
						commit
						977b00a178
					
				|  | @ -13,6 +13,65 @@ use JSON; | ||||||
| # Max LUNS per target on the iSCSI server | # Max LUNS per target on the iSCSI server | ||||||
| my $MAX_LUNS = 255; | my $MAX_LUNS = 255; | ||||||
| 
 | 
 | ||||||
|  | # FreeNAS API Definitions | ||||||
|  | my $freenas_api_version = "v1.0"; | ||||||
|  | my $freenas_api_methods = undef; | ||||||
|  | my $freenas_api_variables = undef; | ||||||
|  | my $freenas_api_version_methods = { | ||||||
|  |     "v1.0" => { | ||||||
|  |         "config"       => "/api/v1.0/services/iscsi/globalconfiguration/", | ||||||
|  |         "target"       => "/api/v1.0/services/iscsi/target/", | ||||||
|  |         "extent"       => "/api/v1.0/services/iscsi/extent/", | ||||||
|  |         "targetextent" => "/api/v1.0/services/iscsi/targettoextent/", | ||||||
|  |     }, | ||||||
|  |     "v2.0" => { | ||||||
|  |         "config"       => "/api/v2.0/iscsi/global", | ||||||
|  |         "target"       => "/api/v2.0/iscsi/target/", | ||||||
|  |         "extent"       => "/api/v2.0/iscsi/extent/", | ||||||
|  |         "targetextent" => "/api/v2.0/iscsi/targetextent/", | ||||||
|  |     }, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | # | ||||||
|  | # | ||||||
|  | # | ||||||
|  | my $freenas_api_version_variables = { | ||||||
|  |     "v1.0" => { | ||||||
|  |         "basename"   => "iscsi_basename", | ||||||
|  |         "lunid"      => "iscsi_lunid", | ||||||
|  |         "extentid"   => "iscsi_extentid", | ||||||
|  |         "targetid"   => "iscsi_targetid", | ||||||
|  |         "extentpath" => "iscsi_target_extent_path", | ||||||
|  |         "extentnaa"  => "iscsi_target_extent_naa", | ||||||
|  |         "targetname" => "iscsi_target_name", | ||||||
|  |     }, | ||||||
|  |     "v2.0" => { | ||||||
|  |         "basename"   => "basename", | ||||||
|  |         "lunid"      => "lunid", | ||||||
|  |         "extentid"   => "extent", | ||||||
|  |         "targetid"   => "target", | ||||||
|  |         "extentpath" => "path", | ||||||
|  |         "extentnaa"  => "naa", | ||||||
|  |         "targetname" => "name", | ||||||
|  |     }, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | # | ||||||
|  | # | ||||||
|  | # | ||||||
|  | my $freenas_apiv2_parameters = { | ||||||
|  |     "target" => { | ||||||
|  |         "none" => undef, | ||||||
|  |     }, | ||||||
|  |     "extent" => { | ||||||
|  |         "force" => "true", | ||||||
|  |     }, | ||||||
|  |     "targetextent" => { | ||||||
|  |         "remove" => "true", | ||||||
|  |         "force" => "true", | ||||||
|  |     }, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| # | # | ||||||
| # | # | ||||||
| # | # | ||||||
|  | @ -26,11 +85,13 @@ sub get_base { | ||||||
| sub run_lun_command { | sub run_lun_command { | ||||||
|     my ($scfg, $timeout, $method, @params) = @_; |     my ($scfg, $timeout, $method, @params) = @_; | ||||||
| 
 | 
 | ||||||
|  |     syslog("info",(caller(0))[3] . " : $method(@params)"); | ||||||
|  | 
 | ||||||
|     if(!defined($scfg->{'freenas_user'}) || !defined($scfg->{'freenas_password'})) { |     if(!defined($scfg->{'freenas_user'}) || !defined($scfg->{'freenas_password'})) { | ||||||
|         die "Undefined freenas_user and/or freenas_password."; |         die "Undefined freenas_user and/or freenas_password."; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     syslog("info","FreeNAS::lun_command : $method(@params)"); |     freenas_api_check($scfg, $timeout); | ||||||
| 
 | 
 | ||||||
|     if($method eq "create_lu") { |     if($method eq "create_lu") { | ||||||
|         return run_create_lu($scfg, $timeout, $method, @params); |         return run_create_lu($scfg, $timeout, $method, @params); | ||||||
|  | @ -57,7 +118,7 @@ sub run_lun_command { | ||||||
|         return run_list_lu($scfg, $timeout, $method, "name", @params); |         return run_list_lu($scfg, $timeout, $method, "name", @params); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     syslog("error","FreeNAS::lun_command : unknown method $method"); |     syslog("error",(caller(0))[3] . " : unknown method $method"); | ||||||
|     return undef; |     return undef; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -74,6 +135,9 @@ sub run_add_view { | ||||||
| # | # | ||||||
| sub run_modify_lu { | sub run_modify_lu { | ||||||
|     my ($scfg, $timeout, $method, @params) = @_; |     my ($scfg, $timeout, $method, @params) = @_; | ||||||
|  | 
 | ||||||
|  |     syslog("info", (caller(0))[3] . " : called"); | ||||||
|  | 
 | ||||||
|     shift(@params); |     shift(@params); | ||||||
|     run_delete_lu($scfg, $timeout, $method, @params); |     run_delete_lu($scfg, $timeout, $method, @params); | ||||||
|     return run_create_lu($scfg, $timeout, $method, @params); |     return run_create_lu($scfg, $timeout, $method, @params); | ||||||
|  | @ -84,6 +148,9 @@ sub run_modify_lu { | ||||||
| # | # | ||||||
| sub run_list_view { | sub run_list_view { | ||||||
|     my ($scfg, $timeout, $method, @params) = @_; |     my ($scfg, $timeout, $method, @params) = @_; | ||||||
|  | 
 | ||||||
|  |     syslog("info", (caller(0))[3] . " : called"); | ||||||
|  | 
 | ||||||
|     return run_list_lu($scfg, $timeout, $method, "lun-id", @params); |     return run_list_lu($scfg, $timeout, $method, "lun-id", @params); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -93,18 +160,21 @@ sub run_list_view { | ||||||
| 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]; | ||||||
|     my $result = undef; |     syslog("info", (caller(0))[3] . " : called with (method=$method; result_value_type=$result_value_type; object=$object)"); | ||||||
| 
 | 
 | ||||||
|  |     my $adddev    = ($freenas_api_version eq "v2.0") ? "/dev/" : ""; | ||||||
|  |     my $result = undef; | ||||||
|     my $luns = freenas_list_lu($scfg); |     my $luns = freenas_list_lu($scfg); | ||||||
|     foreach my $lun (@$luns) { |     foreach my $lun (@$luns) { | ||||||
|         if ($lun->{'iscsi_target_extent_path'} =~ /^$object$/) { |         syslog("info", (caller(0))[3] . " : Verifing '$lun->{$freenas_api_variables->{'extentpath'}}' and '$object'"); | ||||||
|             $result = $result_value_type eq "lun-id" ? $lun->{'iscsi_lunid'} : $lun->{'iscsi_target_extent_path'}; |         if ($adddev . $lun->{$freenas_api_variables->{'extentpath'}} eq $object) { | ||||||
|             syslog("info","FreeNAS::list_lu($object):$result_value_type : lun found $result"); |             $result = $result_value_type eq "lun-id" ? $lun->{$freenas_api_variables->{'lunid'}} : $adddev . $lun->{$freenas_api_variables->{'extentpath'}}; | ||||||
|  |             syslog("info",(caller(0))[3] . "($object) '$result_value_type' found $result"); | ||||||
|             last; |             last; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     if(!defined($result)) { |     if(!defined($result)) { | ||||||
|         syslog("info","FreeNAS::list_lu($object):$result_value_type : lun not found"); |         syslog("info", (caller(0))[3] . "($object) : $result_value_type : lun not found"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return $result; |     return $result; | ||||||
|  | @ -116,12 +186,16 @@ sub run_list_lu { | ||||||
| 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]; | ||||||
|     my $result = undef; |  | ||||||
| 
 | 
 | ||||||
|  |     syslog("info", (caller(0))[3] . " : called with (method=$method; object=$object)"); | ||||||
|  | 
 | ||||||
|  |     my $adddev    = ($freenas_api_version eq "v2.0") ? "/dev/" : ""; | ||||||
|  |     my $result = undef; | ||||||
|     my $luns = freenas_list_lu($scfg); |     my $luns = freenas_list_lu($scfg); | ||||||
|     foreach my $lun (@$luns) { |     foreach my $lun (@$luns) { | ||||||
|         if ($lun->{'iscsi_target_extent_path'} =~ /^$object$/) { |         syslog("info", (caller(0))[3] . " : Verifing '$lun->{$freenas_api_variables->{'extentpath'}}' and '$object'"); | ||||||
|             $result = $lun->{'iscsi_target_extent_naa'}; |         if ($adddev . $lun->{$freenas_api_variables->{'extentpath'}} eq $object) { | ||||||
|  |             $result = $lun->{$freenas_api_variables->{'extentnaa'}}; | ||||||
|             syslog("info","FreeNAS::list_extent($object): naa found $result"); |             syslog("info","FreeNAS::list_extent($object): naa found $result"); | ||||||
|             last; |             last; | ||||||
|         } |         } | ||||||
|  | @ -138,8 +212,10 @@ sub run_list_extent { | ||||||
| # | # | ||||||
| sub run_create_lu { | sub run_create_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)"); | ||||||
|  | 
 | ||||||
|     my $lun_id    = freenas_get_first_available_lunid($scfg); |     my $lun_id    = freenas_get_first_available_lunid($scfg); | ||||||
| 
 | 
 | ||||||
|     die "Maximum number of LUNs per target is $MAX_LUNS" if scalar $lun_id >= $MAX_LUNS; |     die "Maximum number of LUNs per target is $MAX_LUNS" if scalar $lun_id >= $MAX_LUNS; | ||||||
|  | @ -155,7 +231,7 @@ sub run_create_lu { | ||||||
|     my $link = freenas_iscsi_create_target_to_extent($scfg, $target_id, $extent->{'id'}, $lun_id); |     my $link = freenas_iscsi_create_target_to_extent($scfg, $target_id, $extent->{'id'}, $lun_id); | ||||||
| 
 | 
 | ||||||
|     if (defined($link)) { |     if (defined($link)) { | ||||||
|        syslog("info","FreeNAS::create_lu(lun_path=$lun_path, lun_id=$lun_id) : sucessfull"); |        syslog("info","FreeNAS::create_lu(lun_path=$lun_path, lun_id=$lun_id) : successful"); | ||||||
|     } else { |     } else { | ||||||
|        die "Unable to create lun $lun_path"; |        die "Unable to create lun $lun_path"; | ||||||
|     } |     } | ||||||
|  | @ -168,14 +244,16 @@ sub run_create_lu { | ||||||
| # | # | ||||||
| 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)"); | ||||||
|  | 
 | ||||||
|  |     my $adddev    = ($freenas_api_version eq "v2.0") ? "/dev/" : ""; | ||||||
|     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) { |     foreach my $item (@$luns) { | ||||||
|        if($item->{'iscsi_target_extent_path'} =~ /^$lun_path$/) { |        if($adddev . $item->{ $freenas_api_variables->{'extentpath'}} eq $lun_path) { | ||||||
|            $lun = $item; |            $lun = $item; | ||||||
|            last; |            last; | ||||||
|        } |        } | ||||||
|  | @ -189,25 +267,26 @@ sub run_delete_lu { | ||||||
|     # find the target to extent |     # find the target to extent | ||||||
|     my $target2extents = freenas_iscsi_get_target_to_extent($scfg); |     my $target2extents = freenas_iscsi_get_target_to_extent($scfg); | ||||||
| 
 | 
 | ||||||
|  |     syslog("info", (caller(0))[3] . " : searching for 'targetextent' with (target_id=$target_id; lun_id=$lun->{$freenas_api_variables->{'lunid'}}; extent_id=$lun->{id})"); | ||||||
|     foreach my $item (@$target2extents) { |     foreach my $item (@$target2extents) { | ||||||
|         if($item->{'iscsi_target'} == $target_id && |         if($item->{$freenas_api_variables->{'targetid'}} == $target_id && | ||||||
|            $item->{'iscsi_lunid'} == $lun->{'iscsi_lunid'} && |            $item->{$freenas_api_variables->{'lunid'}} == $lun->{$freenas_api_variables->{'lunid'}} && | ||||||
|            $item->{'iscsi_extent'} == $lun->{'id'}) { |            $item->{$freenas_api_variables->{'extentid'}} == $lun->{'id'}) { | ||||||
| 
 |  | ||||||
|             $link = $item; |             $link = $item; | ||||||
|  |             syslog("info", (caller(0))[3] . " : found 'targetextent'(target_id=$item->{$freenas_api_variables->{'targetid'}}; lun_id=$item->{$freenas_api_variables->{'lunid'}}; extent_id=$item->{$freenas_api_variables->{'extentid'}})"); | ||||||
|             last; |             last; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     die "Unable to find the link for the lun $lun_path for $scfg->{target}" if !defined($link); |     die "Unable to find the link for the lun $lun_path for $scfg->{target}" if !defined($link); | ||||||
| 
 | 
 | ||||||
|     # Remove the link |  | ||||||
|     my $remove_link = freenas_iscsi_remove_target_to_extent($scfg, $link->{'id'}); |  | ||||||
| 
 |  | ||||||
|     # Remove the extent |     # Remove the extent | ||||||
|     my $remove_extent = freenas_iscsi_remove_extent($scfg, $lun->{'id'}); |     my $remove_extent = freenas_iscsi_remove_extent($scfg, $lun->{'id'}); | ||||||
| 
 | 
 | ||||||
|  |     # Remove the link | ||||||
|  |     my $remove_link = freenas_iscsi_remove_target_to_extent($scfg, $link->{'id'}); | ||||||
|  | 
 | ||||||
|     if($remove_link == 1 && $remove_extent == 1) { |     if($remove_link == 1 && $remove_extent == 1) { | ||||||
|         syslog("info","FreeNAS::delete_lu(lun_path=$lun_path) : sucessfull"); |         syslog("info", (caller(0))[3] . "(lun_path=$lun_path) : successful"); | ||||||
|     } else { |     } else { | ||||||
|         die "Unable to delete lun $lun_path"; |         die "Unable to delete lun $lun_path"; | ||||||
|     } |     } | ||||||
|  | @ -216,10 +295,14 @@ sub run_delete_lu { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| # | # | ||||||
| ### FREENAS API CALLING ### | # Check to see what FreeNAS version we are running and set | ||||||
|  | # the FreeNAS.pm to use the correct API version of FreeNAS | ||||||
| # | # | ||||||
| sub freenas_api_call { | sub freenas_api_check { | ||||||
|     my ($scfg, $method, $path, $data) = @_; |     my ($scfg, $timeout) = @_; | ||||||
|  | 
 | ||||||
|  |     syslog("info", (caller(0))[3] . " : called"); | ||||||
|  | 
 | ||||||
|     my $client = undef; |     my $client = undef; | ||||||
|     my $scheme = $scfg->{freenas_use_ssl} ? "https" : "http"; |     my $scheme = $scfg->{freenas_use_ssl} ? "https" : "http"; | ||||||
|     my $apihost = defined($scfg->{freenas_apiv4_host}) ? $scfg->{freenas_apiv4_host} : $scfg->{portal}; |     my $apihost = defined($scfg->{freenas_apiv4_host}) ? $scfg->{freenas_apiv4_host} : $scfg->{portal}; | ||||||
|  | @ -227,8 +310,8 @@ sub freenas_api_call { | ||||||
| 
 | 
 | ||||||
|     $client = REST::Client->new(); |     $client = REST::Client->new(); | ||||||
|     $client->setHost($scheme . '://' . $apihost); |     $client->setHost($scheme . '://' . $apihost); | ||||||
|     $client->addHeader('Content-Type'  , 'application/json'); |     $client->addHeader('Content-Type', 'application/json'); | ||||||
|     $client->addHeader('Authorization' , 'Basic ' . encode_base64($scfg->{freenas_user} . ':' . $scfg->{freenas_password})); |     $client->addHeader('Authorization', 'Basic ' . encode_base64($scfg->{freenas_user} . ':' . $scfg->{freenas_password})); | ||||||
|     # If using SSL, don't verify SSL certs |     # If using SSL, don't verify SSL certs | ||||||
|     if ($scfg->{freenas_use_ssl}) { |     if ($scfg->{freenas_use_ssl}) { | ||||||
|         $client->getUseragent()->ssl_opts(verify_hostname => 0); |         $client->getUseragent()->ssl_opts(verify_hostname => 0); | ||||||
|  | @ -240,16 +323,48 @@ sub freenas_api_call { | ||||||
|         freenas_api_log_error($client, "freenas_api_call"); |         freenas_api_log_error($client, "freenas_api_call"); | ||||||
|         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"; | ||||||
|     } |     } | ||||||
|     syslog("info","FreeNAS::api_call : setup : sucessfull"); |     my $result = decode_json($client->responseContent()); | ||||||
|  |     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); | ||||||
|  |     syslog("info", (caller(0))[3] . " : ". $1 . " Unformatted Version: " . $freenas_version); | ||||||
|  |     if ($freenas_version >= 11030100) { | ||||||
|  |         $freenas_api_version = "v2.0"; | ||||||
|  |     } | ||||||
|  |     syslog("info", (caller(0))[3] . " : Using " . $1 ." API version " . $freenas_api_version); | ||||||
|  |     $freenas_api_methods   = $freenas_api_version_methods->{$freenas_api_version}; | ||||||
|  |     $freenas_api_variables = $freenas_api_version_variables->{$freenas_api_version}; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | # | ||||||
|  | ### FREENAS API CALLING ### | ||||||
|  | # | ||||||
|  | sub freenas_api_call { | ||||||
|  |     my ($scfg, $method, $path, $data) = @_; | ||||||
|  |     my $client = undef; | ||||||
|  |     my $scheme = $scfg->{freenas_use_ssl} ? "https" : "http"; | ||||||
|  |     my $apihost = defined($scfg->{freenas_apiv4_host}) ? $scfg->{freenas_apiv4_host} : $scfg->{portal}; | ||||||
|  | 
 | ||||||
|  |     $client = REST::Client->new(); | ||||||
|  |     $client->setHost($scheme . '://' . $apihost); | ||||||
|  |     $client->addHeader('Content-Type'  , 'application/json'); | ||||||
|  |     $client->addHeader('Authorization' , 'Basic ' . encode_base64($scfg->{freenas_user} . ':' . $scfg->{freenas_password})); | ||||||
|  |     # If using SSL, don't verify SSL certs | ||||||
|  |     if ($scfg->{freenas_use_ssl}) { | ||||||
|  |         $client->getUseragent()->ssl_opts(verify_hostname => 0); | ||||||
|  |         $client->getUseragent()->ssl_opts(SSL_verify_mode => SSL_VERIFY_NONE); | ||||||
|  |     } | ||||||
|  |     my $json_data = (defined $data) ? encode_json($data) : undef; | ||||||
|     if ($method eq 'GET') { |     if ($method eq 'GET') { | ||||||
|         $client->GET($path); |         $client->GET($path, $json_data); | ||||||
|     } |     } | ||||||
|     if ($method eq 'DELETE') { |     if ($method eq 'DELETE') { | ||||||
|         $client->DELETE($path); |         $client->DELETE($path, $json_data); | ||||||
|     } |     } | ||||||
|     if ($method eq 'POST') { |     if ($method eq 'POST') { | ||||||
|         $client->POST($path, encode_json($data)); |         $client->POST($path, $json_data); | ||||||
|     } |     } | ||||||
|  |     syslog("info", (caller(0))[3] . " : successful"); | ||||||
| 
 | 
 | ||||||
|     return $client |     return $client | ||||||
| } | } | ||||||
|  | @ -269,12 +384,13 @@ sub freenas_api_log_error { | ||||||
| # | # | ||||||
| sub freenas_iscsi_get_globalconfiguration { | sub freenas_iscsi_get_globalconfiguration { | ||||||
|     my ($scfg) = @_; |     my ($scfg) = @_; | ||||||
|     my $client = freenas_api_call($scfg, 'GET', "/api/v1.0/services/iscsi/globalconfiguration/", undef); |     syslog("info", (caller(0))[3] . " : called"); | ||||||
|  |     my $client = freenas_api_call($scfg, 'GET', "$freenas_api_methods->{'config'}", undef); | ||||||
|     my $code = $client->responseCode(); |     my $code = $client->responseCode(); | ||||||
| 
 | 
 | ||||||
|     if ($code == 200) { |     if ($code == 200) { | ||||||
|         my $result = decode_json($client->responseContent()); |         my $result = decode_json($client->responseContent()); | ||||||
|         syslog("info","FreeNAS::API::get_globalconfig : target_basename=" . $result->{'iscsi_basename'}); |         syslog("info", (caller(0))[3] . " : target_basename=" . $result->{$freenas_api_variables->{'basename'}}); | ||||||
|         return $result; |         return $result; | ||||||
|     } else { |     } else { | ||||||
|         freenas_api_log_error($client, "get_globalconfig"); |         freenas_api_log_error($client, "get_globalconfig"); | ||||||
|  | @ -288,12 +404,14 @@ sub freenas_iscsi_get_globalconfiguration { | ||||||
| # | # | ||||||
| sub freenas_iscsi_get_extent { | sub freenas_iscsi_get_extent { | ||||||
|     my ($scfg) = @_; |     my ($scfg) = @_; | ||||||
|     my $client = freenas_api_call($scfg, 'GET', "/api/v1.0/services/iscsi/extent/?limit=0", undef); |  | ||||||
| 
 | 
 | ||||||
|  |     syslog("info", (caller(0))[3] . " : called"); | ||||||
|  | 
 | ||||||
|  |     my $client = freenas_api_call($scfg, 'GET', $freenas_api_methods->{'extent'} . "?limit=0", undef); | ||||||
|     my $code = $client->responseCode(); |     my $code = $client->responseCode(); | ||||||
|     if ($code == 200) { |     if ($code == 200) { | ||||||
|         my $result = decode_json($client->responseContent()); |         my $result = decode_json($client->responseContent()); | ||||||
|         syslog("info","FreeNAS::API::get_extent : sucessfull"); |         syslog("info", (caller(0))[3] . " : successful"); | ||||||
|         return $result; |         return $result; | ||||||
|     } else { |     } else { | ||||||
|         freenas_api_log_error($client, "get_extent"); |         freenas_api_log_error($client, "get_extent"); | ||||||
|  | @ -311,6 +429,8 @@ sub freenas_iscsi_get_extent { | ||||||
| sub freenas_iscsi_create_extent { | sub freenas_iscsi_create_extent { | ||||||
|     my ($scfg, $lun_path) = @_; |     my ($scfg, $lun_path) = @_; | ||||||
| 
 | 
 | ||||||
|  |     syslog("info", (caller(0))[3] . " : called with (lun_path=$lun_path)"); | ||||||
|  | 
 | ||||||
|     my $name = $lun_path; |     my $name = $lun_path; | ||||||
|     $name  =~ s/^.*\///; # all from last / |     $name  =~ s/^.*\///; # all from last / | ||||||
|     $name  = $scfg->{'pool'} . '/' . $name; |     $name  = $scfg->{'pool'} . '/' . $name; | ||||||
|  | @ -319,16 +439,23 @@ sub freenas_iscsi_create_extent { | ||||||
|     $device =~ s/^\/dev\///; # strip /dev/ |     $device =~ s/^\/dev\///; # strip /dev/ | ||||||
| 
 | 
 | ||||||
|     my $request = { |     my $request = { | ||||||
|  |         "v1.0" => { | ||||||
|             "iscsi_target_extent_type"      => "Disk", |             "iscsi_target_extent_type"      => "Disk", | ||||||
|             "iscsi_target_extent_name"      => $name, |             "iscsi_target_extent_name"      => $name, | ||||||
|             "iscsi_target_extent_disk"      => $device, |             "iscsi_target_extent_disk"      => $device, | ||||||
|  |         }, | ||||||
|  |         "v2.0" => { | ||||||
|  |             "type"      => "DISK", | ||||||
|  |             "name"      => $name, | ||||||
|  |             "disk"      => $device, | ||||||
|  |         }, | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     my $client = freenas_api_call($scfg, 'POST', "/api/v1.0/services/iscsi/extent/", $request); |     my $client = freenas_api_call($scfg, 'POST', $freenas_api_methods->{'extent'}, $request->{$freenas_api_version}); | ||||||
|     my $code = $client->responseCode(); |     my $code = $client->responseCode(); | ||||||
|     if ($code == 201) { |     if ($code == 200 || $code == 201) { | ||||||
|         my $result = decode_json($client->responseContent()); |         my $result = decode_json($client->responseContent()); | ||||||
|         syslog("info", "FreeNAS::API::create_extent(lun_path=" . $result->{'iscsi_target_extent_path'} . ") : sucessfull"); |         syslog("info", "FreeNAS::API::create_extent(lun_path=" . $result->{$freenas_api_variables->{'extentpath'}} . ") : successful"); | ||||||
|         return $result; |         return $result; | ||||||
|     } else { |     } else { | ||||||
|         freenas_api_log_error($client, "create_extent"); |         freenas_api_log_error($client, "create_extent"); | ||||||
|  | @ -345,11 +472,18 @@ sub freenas_iscsi_create_extent { | ||||||
| # | # | ||||||
| sub freenas_iscsi_remove_extent { | sub freenas_iscsi_remove_extent { | ||||||
|     my ($scfg, $extent_id) = @_; |     my ($scfg, $extent_id) = @_; | ||||||
|  |     my $request = { | ||||||
|  |         "v2.0" => { | ||||||
|  |             "remove" => \1, | ||||||
|  |             "force"  => \1, | ||||||
|  |         }, | ||||||
|  |     }; | ||||||
| 
 | 
 | ||||||
|     my $client = freenas_api_call($scfg, 'DELETE', "/api/v1.0/services/iscsi/extent/$extent_id/", undef); |     syslog("info", (caller(0))[3] . " : called with (extent_id=$extent_id)"); | ||||||
|  |     my $client = freenas_api_call($scfg, 'DELETE', $freenas_api_methods->{'extent'} . (($freenas_api_version eq "v2.0") ? "id/" : "") . "$extent_id/", $request->{$freenas_api_version}); | ||||||
|     my $code = $client->responseCode(); |     my $code = $client->responseCode(); | ||||||
|     if ($code == 204) { |     if ($code == 200 || $code == 204) { | ||||||
|         syslog("info","FreeNAS::API::remove_extent(extent_id=$extent_id) : sucessfull"); |         syslog("info", (caller(0))[3] . "(extent_id=$extent_id) : successful"); | ||||||
|         return 1; |         return 1; | ||||||
|     } else { |     } else { | ||||||
|         freenas_api_log_error($client, "remove_extent"); |         freenas_api_log_error($client, "remove_extent"); | ||||||
|  | @ -364,11 +498,13 @@ sub freenas_iscsi_remove_extent { | ||||||
| sub freenas_iscsi_get_target { | sub freenas_iscsi_get_target { | ||||||
|     my ($scfg) = @_; |     my ($scfg) = @_; | ||||||
| 
 | 
 | ||||||
|     my $client = freenas_api_call($scfg, 'GET', "/api/v1.0/services/iscsi/target/?limit=0", undef); |     syslog("info", (caller(0))[3] . " : called"); | ||||||
|  | 
 | ||||||
|  |     my $client = freenas_api_call($scfg, 'GET', $freenas_api_methods->{'target'} . "?limit=0", undef); | ||||||
|     my $code = $client->responseCode(); |     my $code = $client->responseCode(); | ||||||
|     if ($code == 200) { |     if ($code == 200) { | ||||||
|         my $result = decode_json($client->responseContent()); |         my $result = decode_json($client->responseContent()); | ||||||
|         syslog("info","FreeNAS::API::get_target() : sucessfull"); |         syslog("info", (caller(0))[3] . " : successful"); | ||||||
|         return $result; |         return $result; | ||||||
|     } else { |     } else { | ||||||
|         freenas_api_log_error($client, "get_target"); |         freenas_api_log_error($client, "get_target"); | ||||||
|  | @ -383,18 +519,20 @@ sub freenas_iscsi_get_target { | ||||||
| sub freenas_iscsi_get_target_to_extent { | sub freenas_iscsi_get_target_to_extent { | ||||||
|     my ($scfg) = @_; |     my ($scfg) = @_; | ||||||
| 
 | 
 | ||||||
|     my $client = freenas_api_call($scfg, 'GET', "/api/v1.0/services/iscsi/targettoextent/?limit=0", undef); |     syslog("info", (caller(0))[3] . " : called"); | ||||||
|  | 
 | ||||||
|  |     my $client = freenas_api_call($scfg, 'GET', $freenas_api_methods->{'targetextent'} . "?limit=0", undef); | ||||||
|     my $code = $client->responseCode(); |     my $code = $client->responseCode(); | ||||||
|     if ($code == 200) { |     if ($code == 200) { | ||||||
|         my $result = decode_json($client->responseContent()); |         my $result = decode_json($client->responseContent()); | ||||||
|         syslog("info","FreeNAS::API::get_target_to_extent() : sucessfull"); |         syslog("info", (caller(0))[3] . " : successful"); | ||||||
|         # If 'iscsi_lunid' is undef then it is set to 'Auto' in FreeNAS |         # If 'iscsi_lunid' is undef then it is set to 'Auto' in FreeNAS | ||||||
|         # which should be '0' in our eyes. |         # which should be '0' in our eyes. | ||||||
|         # This gave Proxmox 5.x and FreeNAS 11.1 a few issues. |         # This gave Proxmox 5.x and FreeNAS 11.1 a few issues. | ||||||
|         foreach my $item (@$result) { |         foreach my $item (@$result) { | ||||||
|             if (!defined($item->{'iscsi_lunid'})) { |             if (!defined($item->{$freenas_api_variables->{'lunid'}})) { | ||||||
|                 $item->{'iscsi_lunid'} = 0; |                 $item->{$freenas_api_variables->{'lunid'}} = 0; | ||||||
|                 syslog("info", "FreeNAS::API::get_target_to_extent() : change undef iscsi_lunid to 0"); |                 syslog("info", (caller(0))[3] . " : change undef iscsi_lunid to 0"); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         return $result; |         return $result; | ||||||
|  | @ -416,17 +554,26 @@ sub freenas_iscsi_get_target_to_extent { | ||||||
| sub freenas_iscsi_create_target_to_extent { | sub freenas_iscsi_create_target_to_extent { | ||||||
|     my ($scfg, $target_id, $extent_id, $lun_id) = @_; |     my ($scfg, $target_id, $extent_id, $lun_id) = @_; | ||||||
| 
 | 
 | ||||||
|  |     syslog("info", (caller(0))[3] . " : called with (target_id=$target_id, extent_id=$extent_id, lun_id=$lun_id)"); | ||||||
|  | 
 | ||||||
|     my $request = { |     my $request = { | ||||||
|  |         "v1.0" => { | ||||||
|             "iscsi_target"  => $target_id, |             "iscsi_target"  => $target_id, | ||||||
|             "iscsi_extent"  => $extent_id, |             "iscsi_extent"  => $extent_id, | ||||||
|         "iscsi_lunid"   => $lun_id |             "iscsi_lunid"   => $lun_id, | ||||||
|  |         }, | ||||||
|  |         "v2.0" => { | ||||||
|  |             "target"  => $target_id, | ||||||
|  |             "extent"  => $extent_id, | ||||||
|  |             "lunid"   => $lun_id, | ||||||
|  |         }, | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     my $client = freenas_api_call($scfg, 'POST', "/api/v1.0/services/iscsi/targettoextent/", $request); |     my $client = freenas_api_call($scfg, 'POST', $freenas_api_methods->{'targetextent'}, $request->{$freenas_api_version}); | ||||||
|     my $code = $client->responseCode(); |     my $code = $client->responseCode(); | ||||||
|     if ($code == 201) { |     if ($code == 200 || $code == 201) { | ||||||
|         my $result = decode_json($client->responseContent()); |         my $result = decode_json($client->responseContent()); | ||||||
|         syslog("info","FreeNAS::API::create_target_to_extent(target_id=$target_id, extent_id=$extent_id, lun_id=$lun_id) : sucessfull"); |         syslog("info", (caller(0))[3] . "(target_id=$target_id, extent_id=$extent_id, lun_id=$lun_id) : successful"); | ||||||
|         return $result; |         return $result; | ||||||
|     } else { |     } else { | ||||||
|         freenas_api_log_error($client, "create_target_to_extent"); |         freenas_api_log_error($client, "create_target_to_extent"); | ||||||
|  | @ -444,10 +591,17 @@ sub freenas_iscsi_create_target_to_extent { | ||||||
| sub freenas_iscsi_remove_target_to_extent { | sub freenas_iscsi_remove_target_to_extent { | ||||||
|     my ($scfg, $link_id) = @_; |     my ($scfg, $link_id) = @_; | ||||||
| 
 | 
 | ||||||
|     my $client = freenas_api_call($scfg, 'DELETE', "/api/v1.0/services/iscsi/targettoextent/$link_id/", undef); |     syslog("info", (caller(0))[3] . " : called with (link_id=$link_id)"); | ||||||
|  | 
 | ||||||
|  |     if ($freenas_api_version eq "v2.0") { | ||||||
|  |         syslog("info", (caller(0))[3] . "(link_id=$link_id) : V2.0 API's so NOT Needed...successful"); | ||||||
|  |         return 1; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     my $client = freenas_api_call($scfg, 'DELETE', $freenas_api_methods->{'targetextent'} . (($freenas_api_version eq "v2.0") ? "id/" : "") . "$link_id/", undef); | ||||||
|     my $code = $client->responseCode(); |     my $code = $client->responseCode(); | ||||||
|     if ($code == 204) { |     if ($code == 200 || $code == 204) { | ||||||
|         syslog("info","FreeNAS::API::remove_target_to_extent(link_id=$link_id) : sucessfull"); |         syslog("info", (caller(0))[3] . "(link_id=$link_id) : successful"); | ||||||
|         return 1; |         return 1; | ||||||
|     } else { |     } else { | ||||||
|         freenas_api_log_error($client, "remove_target_to_extent"); |         freenas_api_log_error($client, "remove_target_to_extent"); | ||||||
|  | @ -463,6 +617,8 @@ sub freenas_iscsi_remove_target_to_extent { | ||||||
| sub freenas_list_lu { | sub freenas_list_lu { | ||||||
|     my ($scfg) = @_; |     my ($scfg) = @_; | ||||||
| 
 | 
 | ||||||
|  |     syslog("info", (caller(0))[3] . " : called"); | ||||||
|  | 
 | ||||||
|     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); | ||||||
| 
 | 
 | ||||||
|  | @ -474,23 +630,23 @@ sub freenas_list_lu { | ||||||
|         my $extents        = freenas_iscsi_get_extent($scfg); |         my $extents        = freenas_iscsi_get_extent($scfg); | ||||||
| 
 | 
 | ||||||
|         foreach my $item (@$target2extents) { |         foreach my $item (@$target2extents) { | ||||||
|             if($item->{'iscsi_target'} == $target_id) { |             if($item->{$freenas_api_variables->{'targetid'}} == $target_id) { | ||||||
|                 foreach my $node (@$extents) { |                 foreach my $node (@$extents) { | ||||||
|                     if($node->{'id'} == $item->{'iscsi_extent'}) { |                     if($node->{'id'} == $item->{$freenas_api_variables->{'extentid'}}) { | ||||||
|                         if ($item->{'iscsi_lunid'} =~ /(\d+)/) { |                         if ($item->{$freenas_api_variables->{'lunid'}} =~ /(\d+)/) { | ||||||
|                             $iscsi_lunid = "$1"; |                             $iscsi_lunid = "$1"; | ||||||
|                         } else { |                         } else { | ||||||
|                             syslog("info", "FreeNAS::API::freenas_list_lu : iscsi_lunid did not pass tainted testing"); |                             syslog("info", (caller(0))[3] . " : iscsi_lunid did not pass tainted testing"); | ||||||
|                             next; |                             next; | ||||||
|                         } |                         } | ||||||
|                         $node->{'iscsi_lunid'} .= $iscsi_lunid; |                         $node->{$freenas_api_variables->{'lunid'}} .= $iscsi_lunid; | ||||||
|                         push(@luns , $node); |                         push(@luns , $node); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     syslog("info", "FreeNAS::API::freenas_list_lu : sucessfull"); |     syslog("info", (caller(0))[3] . " : successful"); | ||||||
|     return \@luns; |     return \@luns; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -500,12 +656,14 @@ sub freenas_list_lu { | ||||||
| sub freenas_get_first_available_lunid { | sub freenas_get_first_available_lunid { | ||||||
|     my ($scfg) = @_; |     my ($scfg) = @_; | ||||||
| 
 | 
 | ||||||
|  |     syslog("info", (caller(0))[3] . " : called"); | ||||||
|  | 
 | ||||||
|     my $target_id      = freenas_get_targetid($scfg); |     my $target_id      = freenas_get_targetid($scfg); | ||||||
|     my $target2extents = freenas_iscsi_get_target_to_extent($scfg); |     my $target2extents = freenas_iscsi_get_target_to_extent($scfg); | ||||||
|     my @luns           = (); |     my @luns           = (); | ||||||
| 
 | 
 | ||||||
|     foreach my $item (@$target2extents) { |     foreach my $item (@$target2extents) { | ||||||
|         push(@luns, $item->{'iscsi_lunid'}) if ($item->{'iscsi_target'} == $target_id); |         push(@luns, $item->{$freenas_api_variables->{'lunid'}}) if ($item->{$freenas_api_variables->{'targetid'}} == $target_id); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     my @sorted_luns =  sort {$a <=> $b} @luns; |     my @sorted_luns =  sort {$a <=> $b} @luns; | ||||||
|  | @ -517,7 +675,7 @@ sub freenas_get_first_available_lunid { | ||||||
|         $lun_id = $lun_id + 1; |         $lun_id = $lun_id + 1; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     syslog("info", "FreeNAS::API::freenas_get_first_available_lunid : return $lun_id"); |     syslog("info", (caller(0))[3] . " : $lun_id"); | ||||||
|     return $lun_id; |     return $lun_id; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -527,18 +685,20 @@ sub freenas_get_first_available_lunid { | ||||||
| sub freenas_get_targetid { | sub freenas_get_targetid { | ||||||
|     my ($scfg) = @_; |     my ($scfg) = @_; | ||||||
| 
 | 
 | ||||||
|  |     syslog("info", (caller(0))[3] . " : called"); | ||||||
|  | 
 | ||||||
|     my $global    = freenas_iscsi_get_globalconfiguration($scfg); |     my $global    = freenas_iscsi_get_globalconfiguration($scfg); | ||||||
|     my $targets   = freenas_iscsi_get_target($scfg); |     my $targets   = freenas_iscsi_get_target($scfg); | ||||||
|     my $target_id = undef; |     my $target_id = undef; | ||||||
| 
 | 
 | ||||||
|     foreach my $target (@$targets) { |     foreach my $target (@$targets) { | ||||||
|         my $iqn = $global->{'iscsi_basename'} . ':' . $target->{'iscsi_target_name'}; |         my $iqn = $global->{$freenas_api_variables->{'basename'}} . ':' . $target->{$freenas_api_variables->{'targetname'}}; | ||||||
|         if($iqn eq $scfg->{target}) { |         if($iqn eq $scfg->{target}) { | ||||||
|             $target_id = $target->{'id'}; |             $target_id = $target->{'id'}; | ||||||
|             last; |             last; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 |     syslog("info", (caller(0))[3] . " : successful : $target_id"); | ||||||
|     return $target_id; |     return $target_id; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -233,9 +233,7 @@ Preform an HTTP GET to the resource specified. Takes an optional hashref of cust | ||||||
| 
 | 
 | ||||||
| sub GET { | sub GET { | ||||||
|     my $self = shift; |     my $self = shift; | ||||||
|     my $url = shift; |     return $self->request('GET', @_); | ||||||
|     my $headers = shift; |  | ||||||
|     return $self->request('GET', $url, undef, $headers); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| =head3 PUT ($url, [$body_content, %$headers] ) | =head3 PUT ($url, [$body_content, %$headers] ) | ||||||
|  | @ -279,9 +277,7 @@ Preform an HTTP DELETE to the resource specified. Takes an optional hashref of c | ||||||
| 
 | 
 | ||||||
| sub DELETE { | sub DELETE { | ||||||
|     my $self = shift; |     my $self = shift; | ||||||
|     my $url = shift; |     return $self->request('DELETE', @_); | ||||||
|     my $headers = shift; |  | ||||||
|     return $self->request('DELETE', $url, undef, $headers); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| =head3 OPTIONS ( $url, [%$headers] ) | =head3 OPTIONS ( $url, [%$headers] ) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue