From 36d98324fa689bcca711eb80b2dcb38f85845966 Mon Sep 17 00:00:00 2001 From: snags141 Date: Thu, 9 Dec 2021 15:51:11 +0000 Subject: [PATCH 01/20] Added the base code multi-port allocations. --- wisp/wisp.php | 208 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 204 insertions(+), 4 deletions(-) diff --git a/wisp/wisp.php b/wisp/wisp.php index 878da43..309ce61 100644 --- a/wisp/wisp.php +++ b/wisp/wisp.php @@ -169,6 +169,22 @@ function wisp_ConfigOptions() { "Description" => "Port ranges seperated by comma to assign to the server (Example: 25565-25570,25580-25590) (optional)", "Type" => "text", "Size" => 25, + ], + "additional_ports" => [ + "FriendlyName" => "Additional Ports", + "Description" => "Additional ports as an offset from the first allocation - seperated by comma. Example: if the first assigned port is 25565 and you enter '1,2,4' then you'll get three additional ports 25565+1 (25566) 25565+2 (25567) and 25565+4 (25569) (optional)", + "Type" => "text", + "Size" => 25, + ], + "additional_port_fail_mode" => [ + "FriendlyName" => "Additional Port Failure Mode", + "Type" => "dropdown", + "Options" => [ + 'stop' => 'Stop', + 'continue' => 'Continue', + ], + "Description" => "Determines whether server creation will continue if none of your nodes are able to satisfy the additional port allocation", + "Default" => "stop", ], "startup" => [ "FriendlyName" => "Startup", @@ -274,10 +290,14 @@ function wisp_GetOption(array $params, $id, $default = NULL) { } function wisp_CreateAccount(array $params) { + logActivity('Doing wisp_CreateAccount'); try { + + // Checking if the server ID already exists $serverId = wisp_GetServerID($params); if(isset($serverId)) throw new Exception('Failed to create server because it is already created.'); - + + // Create or fetch the user account $userResult = wisp_API($params, 'users/external/' . $params['clientsdetails']['uuid']); if($userResult['status_code'] === 404) { $userResult = wisp_API($params, 'users?search=' . urlencode($params['clientsdetails']['email'])); @@ -303,8 +323,9 @@ function wisp_CreateAccount(array $params) { $userId = $userResult['attributes']['id']; } else { throw new Exception('Failed to create user, received error code: ' . $userResult['status_code'] . '. Enable module debug log for more info.'); - } + } + // Get egg data $nestId = wisp_GetOption($params, 'nest_id'); $eggId = wisp_GetOption($params, 'egg_id'); @@ -324,7 +345,8 @@ function wisp_CreateAccount(array $params) { else $environment[$var] = $default; } - $name = wisp_GetOption($params, 'server_name', 'My Server'); + // Fetch given server parameters + $name = wisp_GetOption($params, 'server_name', 'My Server'); $memory = wisp_GetOption($params, 'memory'); $swap = wisp_GetOption($params, 'swap'); $io = wisp_GetOption($params, 'io'); @@ -333,7 +355,9 @@ function wisp_CreateAccount(array $params) { $pack_id = wisp_GetOption($params, 'pack_id'); $location_id = wisp_GetOption($params, 'location_id'); $dedicated_ip = wisp_GetOption($params, 'dedicated_ip') ? true : false; - $port_range = wisp_GetOption($params, 'port_range'); + $port_range = wisp_GetOption($params, 'port_range'); + $additional_ports = wisp_GetOption($params, 'additional_ports'); + $additional_port_fail_mode = wisp_GetOption($params, 'additional_port_fail_mode'); $port_range = isset($port_range) ? explode(',', $port_range) : []; $image = wisp_GetOption($params, 'image', $eggData['attributes']['docker_image']); $startup = wisp_GetOption($params, 'startup', $eggData['attributes']['startup']); @@ -372,6 +396,39 @@ function wisp_CreateAccount(array $params) { ]; if(isset($pack_id)) $serverData['pack'] = (int) $pack_id; + // Check if additional ports have been set + if(isset($additional_ports) && $additional_ports != '') { + // Query all nodes for the given location until we find an available set of ports + // Get the list of additional ports to add + $additional_port_list = explode(",", $additional_ports); + + // Get the server nodes for the specified location_id + $nodes = getNodes($params, $location_id); + // Get the port allocations for each node at this location and check if there's space for the additional ports + if(isset($nodes)) { + foreach($nodes as $key => $node_id) { + logActivity("Checking allocations for node ".$node_id); + $available_allocations = getAllocations($params,$node_id); + + $final_allocations = findFreePorts($available_allocations, $additional_port_list); + + if($final_allocations['status'] == true) { + logActivity("Successfully found an allocation. Setting primary allocation to ID " . $final_allocations['main_allocation_id']); + $serverData['allocation']['default'] = intval($final_allocations['main_allocation_id']); + } else { + logActivity("Failed to find an available allocation."); + } + // update serverData + } + } else { + logActivity("Unable to find any nodes at location ID ".$loc_id); + } + } else { + // Continue with normal deployment + $serverData['deploy']['port_range'] = $port_range; + } + + // Create the game server $server = wisp_API($params, 'servers', $serverData, 'POST'); if($server['status_code'] === 400) throw new Exception('Couldn\'t find any nodes satisfying the request.'); @@ -597,3 +654,146 @@ function wisp_ClientArea(array $params) { // Ignore } } + + +/* Utility Functions */ +function getNodes(array $params, int $loc_id) { + /* + Fetches and returns all nodes with a specific location_id + */ + $filteredNodes = array(); + $nodes = wisp_API($params, 'nodes/'); + foreach($nodes['data'] as $key => $value) { + $node_id = $value['attributes']['id']; + if($value['attributes']['location_id'] == $loc_id) { + array_push($filteredNodes, $node_id); + } + } + return $filteredNodes; +} + +function getAllocations(array $params, int $node_id){ + /* + Gets the available allocations for a specific node_id + and returns them in a format that can be more easily parsed. + + Output: + Returns the available allocations in + a more usable format for filtering + Format: + [ + [] => { + [] => { + ['id'] = 1234; + } + }, + ['192.168.1.123'] => { + ['1234'] => { + ['id'] = 1234; + } + }, + ] + */ + echo "Getting Allocations \n"; + $available_allocations = array(); + $allocations = getPaginatedData($params,'nodes/'.$node_id.'/allocations'); + foreach($allocations as $key => $allocation) { + $ip = $allocation['attributes']['ip']; + $port = $allocation['attributes']['port']; + if ($allocation['attributes']['assigned']!=true) { + $available_allocations[$ip][$port]['id'] = $allocation['attributes']['id']; + } + } + return $available_allocations; +} + +function getPaginatedData($params,$url) { + /* + Makes a paginated API request and returns the response. + */ + + $results = array(); + logActivity("API: Fetching page: ".$ports[$next_port]['id']); + $response = wisp_API($params, $url); + //array_push($results, $response['data']); + foreach($response['data'] as $key => $value) { + array_push($results, $value); + } + $current_page = $response['meta']['pagination']['current_page']; + $total_pages = $response['meta']['pagination']['total_pages']; + while ($total_pages > $current_page) { + $next_page = intval($current_page)+1; + logActivity("API: Fetching page: ".$next_page); + $response = wisp_API($params, $url.'?page='.$next_page); + foreach($response['data'] as $key => $value) { + array_push($results, $value); + } + $current_page = $response['meta']['pagination']['current_page']; + $total_pages = $response['meta']['pagination']['total_pages']; + } + return $results; +} + +function findFreePorts(array $available_allocations, array $port_offsets) { + /* + This is the main logic that takes a list of available allocations + and the required offsets and then finds the first available set. + e.g. if port offsets +1 +2 and +4 are requested (format: 1,2,4) + we take each port one by one and check if + 1, + + 2 and + 4 are available. + If all requested port allocations are available, they are returned. + + Inputs: + $available_allocations This is the first port in the range to test. + All other ports will be checked based on the + required offset from the first. + + $port_offsets The list of offsets from the first port that + are required for the server. + + Outputs: + $ports_found The array of ports that were found available, based on the offsets + the additional ports required. + */ + // Iterate over available IP's + foreach($available_allocations as $ip_addr => $ports) { + $result = Array(); + $result['status'] = false; + $main_allocation_id = ""; + $additional_allocation_ids = Array(); + + // Iterate over Ports + logActivity("Checking IP: ".$ip_addr); + //echo "Key: ".key($ports); + foreach($ports as $port => $portDetails) { + $main_allocation_id = $port; + $found_all = true; + foreach($port_offsets as $key => $port_offset) { + // check if port + $next_port = intval($port) + intval($port_offset); + if(!isset($ports[$next_port])) { + // Port is not available + $found_all = false; + } else { + logActivity("Stashing available port: ".$ports[$next_port]['id']); + array_push($additional_allocation_ids, $ports[$next_port]['id']); + } + } + if($found_all == true) { + logActivity("Found an available set of ports!"); + logActivity("Main port allocation ID: ". $main_allocation_id); + logActivity("Additional port allocation ID's: ". print_r($additional_allocation_ids, true)); + $result['main_allocation_id'] = $main_allocation_id; + $result['additional_allocation_ids'] = $additional_allocation_ids; + $result['status'] = true; + return $result; + } else { + // Reset values in array for next run + $additional_ports = array(); + } + } + // Raise an exception + logActivity("Failed to find available ports!"); + return false; + } +} From 8109275adeaff3b778b25e59e2d8c83bee241591 Mon Sep 17 00:00:00 2001 From: snags141 Date: Thu, 9 Dec 2021 15:57:56 +0000 Subject: [PATCH 02/20] Updated readme FAQ for multiple port allocations --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5bc15f6..d2b034d 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,12 @@ This can be caused from any of the following: Wrong location, not enough disk sp The customer gets an email from the panel to setup their account (incl. password) if they didn't have an account before. Otherwise they should be able to use their existing credentials. ## My game requires multiple ports allocated. -Currently, this isn't possible with this module but is planned. +Configure the "Additional Ports" option in the module settings. +It expects a comma-separated list of ports as a numeric offset from the first available allocation. +E.g: If you enter `1,2,4` and the first available port happens to be 25565, you'll get as additional allocations: (If they're available) +* 25566 (First Port + 1) +* 25567 (First Port +2) +* 25569 (First Port +4) ## How to enable module debug log 1. In WHMCS 7 or below navigate to Utilities > Logs > Module Log. For WHMCS 8.x navigate to System Logs > Module Log in the left sidebar. From d2faa67b4a9a4d08f33d99b4d28270ed6aff8655 Mon Sep 17 00:00:00 2001 From: snags141 Date: Fri, 10 Dec 2021 00:17:46 +0800 Subject: [PATCH 03/20] Added the patch call to add additional allocations --- wisp/wisp.php | 85 ++++++++++++++++++++++++++++----------------------- 1 file changed, 47 insertions(+), 38 deletions(-) diff --git a/wisp/wisp.php b/wisp/wisp.php index 309ce61..45474ce 100644 --- a/wisp/wisp.php +++ b/wisp/wisp.php @@ -293,11 +293,11 @@ function wisp_CreateAccount(array $params) { logActivity('Doing wisp_CreateAccount'); try { - // Checking if the server ID already exists + // Checking if the server ID already exists $serverId = wisp_GetServerID($params); if(isset($serverId)) throw new Exception('Failed to create server because it is already created.'); - // Create or fetch the user account + // Create or fetch the user account $userResult = wisp_API($params, 'users/external/' . $params['clientsdetails']['uuid']); if($userResult['status_code'] === 404) { $userResult = wisp_API($params, 'users?search=' . urlencode($params['clientsdetails']['email'])); @@ -325,7 +325,7 @@ function wisp_CreateAccount(array $params) { throw new Exception('Failed to create user, received error code: ' . $userResult['status_code'] . '. Enable module debug log for more info.'); } - // Get egg data + // Get egg data $nestId = wisp_GetOption($params, 'nest_id'); $eggId = wisp_GetOption($params, 'egg_id'); @@ -345,8 +345,8 @@ function wisp_CreateAccount(array $params) { else $environment[$var] = $default; } - // Fetch given server parameters - $name = wisp_GetOption($params, 'server_name', 'My Server'); + // Fetch given server parameters + $name = wisp_GetOption($params, 'server_name', 'My Server'); $memory = wisp_GetOption($params, 'memory'); $swap = wisp_GetOption($params, 'swap'); $io = wisp_GetOption($params, 'io'); @@ -355,9 +355,9 @@ function wisp_CreateAccount(array $params) { $pack_id = wisp_GetOption($params, 'pack_id'); $location_id = wisp_GetOption($params, 'location_id'); $dedicated_ip = wisp_GetOption($params, 'dedicated_ip') ? true : false; - $port_range = wisp_GetOption($params, 'port_range'); - $additional_ports = wisp_GetOption($params, 'additional_ports'); - $additional_port_fail_mode = wisp_GetOption($params, 'additional_port_fail_mode'); + $port_range = wisp_GetOption($params, 'port_range'); + $additional_ports = wisp_GetOption($params, 'additional_ports'); + $additional_port_fail_mode = wisp_GetOption($params, 'additional_port_fail_mode'); $port_range = isset($port_range) ? explode(',', $port_range) : []; $image = wisp_GetOption($params, 'image', $eggData['attributes']['docker_image']); $startup = wisp_GetOption($params, 'startup', $eggData['attributes']['startup']); @@ -400,45 +400,54 @@ function wisp_CreateAccount(array $params) { if(isset($additional_ports) && $additional_ports != '') { // Query all nodes for the given location until we find an available set of ports // Get the list of additional ports to add - $additional_port_list = explode(",", $additional_ports); - - // Get the server nodes for the specified location_id - $nodes = getNodes($params, $location_id); - // Get the port allocations for each node at this location and check if there's space for the additional ports - if(isset($nodes)) { - foreach($nodes as $key => $node_id) { - logActivity("Checking allocations for node ".$node_id); - $available_allocations = getAllocations($params,$node_id); + $additional_port_list = explode(",", $additional_ports); + + // Get the server nodes for the specified location_id + $nodes = getNodes($params, $location_id); + // Get the port allocations for each node at this location and check if there's space for the additional ports + if(isset($nodes)) { + foreach($nodes as $key => $node_id) { + logActivity("Checking allocations for node ".$node_id); + $available_allocations = getAllocations($params,$node_id); - $final_allocations = findFreePorts($available_allocations, $additional_port_list); - - if($final_allocations['status'] == true) { - logActivity("Successfully found an allocation. Setting primary allocation to ID " . $final_allocations['main_allocation_id']); - $serverData['allocation']['default'] = intval($final_allocations['main_allocation_id']); - } else { - logActivity("Failed to find an available allocation."); - } - // update serverData - } - } else { - logActivity("Unable to find any nodes at location ID ".$loc_id); - } + $final_allocations = findFreePorts($available_allocations, $additional_port_list); + + if($final_allocations['status'] == true) { + logActivity("Successfully found an allocation. Setting primary allocation to ID " . $final_allocations['main_allocation_id']); + $serverData['allocation']['default'] = intval($final_allocations['main_allocation_id']); + } else { + logActivity("Failed to find an available allocation."); + } + } + } else { + logActivity("Unable to find any nodes at location ID ".$loc_id); + } } else { // Continue with normal deployment $serverData['deploy']['port_range'] = $port_range; } // Create the game server - $server = wisp_API($params, 'servers', $serverData, 'POST'); + $server = wisp_API($params, 'servers', $serverData, 'POST'); - if($server['status_code'] === 400) throw new Exception('Couldn\'t find any nodes satisfying the request.'); - if($server['status_code'] !== 201) throw new Exception('Failed to create the server, received the error code: ' . $server['status_code'] . '. Enable module debug log for more info.'); + if($final_allocations['status'] == true) { + + $patchData = [ + 'add_allocations' => $final_allocations['additional_allocation_ids'], + ] + logActivity("Adding additional allocations to server. "); + $server = wisp_API($params, 'servers/' . $serverId . "/build", $patchData, 'PATCH'); + } + - unset($params['password']); - Capsule::table('tblhosting')->where('id', $params['serviceid'])->update([ - 'username' => '', - 'password' => '', - ]); + if($server['status_code'] === 400) throw new Exception('Couldn\'t find any nodes satisfying the request.'); + if($server['status_code'] !== 201) throw new Exception('Failed to create the server, received the error code: ' . $server['status_code'] . '. Enable module debug log for more info.'); + + unset($params['password']); + Capsule::table('tblhosting')->where('id', $params['serviceid'])->update([ + 'username' => '', + 'password' => '', + ]); } catch(Exception $err) { return $err->getMessage(); } From 07b08a8b31b0cd97209321dae2a5f9859e1aae70 Mon Sep 17 00:00:00 2001 From: snags141 Date: Fri, 10 Dec 2021 00:30:11 +0800 Subject: [PATCH 04/20] Fixed missing ; and added additional call to get server ID --- wisp/wisp.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wisp/wisp.php b/wisp/wisp.php index 45474ce..eb1accc 100644 --- a/wisp/wisp.php +++ b/wisp/wisp.php @@ -434,8 +434,9 @@ function wisp_CreateAccount(array $params) { $patchData = [ 'add_allocations' => $final_allocations['additional_allocation_ids'], - ] + ]; logActivity("Adding additional allocations to server. "); + $serverId = wisp_GetServerID($params); $server = wisp_API($params, 'servers/' . $serverId . "/build", $patchData, 'PATCH'); } From 4663e7a3a5914e90405fff1fa5a8b876830876d5 Mon Sep 17 00:00:00 2001 From: snags141 Date: Mon, 13 Dec 2021 01:37:14 +0800 Subject: [PATCH 05/20] Mostly finished general implementation and tested in dev --- wisp/wisp.php | 129 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 84 insertions(+), 45 deletions(-) diff --git a/wisp/wisp.php b/wisp/wisp.php index eb1accc..5c8914b 100644 --- a/wisp/wisp.php +++ b/wisp/wisp.php @@ -78,7 +78,7 @@ function wisp_API(array $params, $endpoint, array $data = [], $method = "GET", $ $response = curl_exec($curl); $responseData = json_decode($response, true); $responseData['status_code'] = curl_getinfo($curl, CURLINFO_HTTP_CODE); - + if($responseData['status_code'] === 0 && !$dontLog) logModuleCall("WISP-WHMCS", "CURL ERROR", curl_error($curl), ""); curl_close($curl); @@ -169,14 +169,14 @@ function wisp_ConfigOptions() { "Description" => "Port ranges seperated by comma to assign to the server (Example: 25565-25570,25580-25590) (optional)", "Type" => "text", "Size" => 25, - ], - "additional_ports" => [ + ], + "additional_ports" => [ "FriendlyName" => "Additional Ports", "Description" => "Additional ports as an offset from the first allocation - seperated by comma. Example: if the first assigned port is 25565 and you enter '1,2,4' then you'll get three additional ports 25565+1 (25566) 25565+2 (25567) and 25565+4 (25569) (optional)", "Type" => "text", "Size" => 25, - ], - "additional_port_fail_mode" => [ + ], + "additional_port_fail_mode" => [ "FriendlyName" => "Additional Port Failure Mode", "Type" => "dropdown", "Options" => [ @@ -204,7 +204,7 @@ function wisp_ConfigOptions() { "Type" => "text", "Size" => 10, ], - "server_name" => [ + "server_name" => [ "FriendlyName" => "Server Name", "Description" => "The name of the server as shown on the panel (optional)", "Type" => "text", @@ -293,11 +293,11 @@ function wisp_CreateAccount(array $params) { logActivity('Doing wisp_CreateAccount'); try { - // Checking if the server ID already exists + // Checking if the server ID already exists $serverId = wisp_GetServerID($params); if(isset($serverId)) throw new Exception('Failed to create server because it is already created.'); - - // Create or fetch the user account + + // Create or fetch the user account $userResult = wisp_API($params, 'users/external/' . $params['clientsdetails']['uuid']); if($userResult['status_code'] === 404) { $userResult = wisp_API($params, 'users?search=' . urlencode($params['clientsdetails']['email'])); @@ -323,9 +323,9 @@ function wisp_CreateAccount(array $params) { $userId = $userResult['attributes']['id']; } else { throw new Exception('Failed to create user, received error code: ' . $userResult['status_code'] . '. Enable module debug log for more info.'); - } + } - // Get egg data + // Get egg data $nestId = wisp_GetOption($params, 'nest_id'); $eggId = wisp_GetOption($params, 'egg_id'); @@ -345,8 +345,8 @@ function wisp_CreateAccount(array $params) { else $environment[$var] = $default; } - // Fetch given server parameters - $name = wisp_GetOption($params, 'server_name', 'My Server'); + // Fetch given server parameters + $name = wisp_GetOption($params, 'server_name', 'My Server'); $memory = wisp_GetOption($params, 'memory'); $swap = wisp_GetOption($params, 'swap'); $io = wisp_GetOption($params, 'io'); @@ -355,9 +355,9 @@ function wisp_CreateAccount(array $params) { $pack_id = wisp_GetOption($params, 'pack_id'); $location_id = wisp_GetOption($params, 'location_id'); $dedicated_ip = wisp_GetOption($params, 'dedicated_ip') ? true : false; - $port_range = wisp_GetOption($params, 'port_range'); - $additional_ports = wisp_GetOption($params, 'additional_ports'); - $additional_port_fail_mode = wisp_GetOption($params, 'additional_port_fail_mode'); + $port_range = wisp_GetOption($params, 'port_range'); + $additional_ports = wisp_GetOption($params, 'additional_ports'); + $additional_port_fail_mode = wisp_GetOption($params, 'additional_port_fail_mode'); $port_range = isset($port_range) ? explode(',', $port_range) : []; $image = wisp_GetOption($params, 'image', $eggData['attributes']['docker_image']); $startup = wisp_GetOption($params, 'startup', $eggData['attributes']['startup']); @@ -396,10 +396,10 @@ function wisp_CreateAccount(array $params) { ]; if(isset($pack_id)) $serverData['pack'] = (int) $pack_id; - // Check if additional ports have been set - if(isset($additional_ports) && $additional_ports != '') { - // Query all nodes for the given location until we find an available set of ports - // Get the list of additional ports to add + // Check if additional ports have been set + if(isset($additional_ports) && $additional_ports != '') { + // Query all nodes for the given location until we find an available set of ports + // Get the list of additional ports to add $additional_port_list = explode(",", $additional_ports); // Get the server nodes for the specified location_id @@ -409,7 +409,7 @@ function wisp_CreateAccount(array $params) { foreach($nodes as $key => $node_id) { logActivity("Checking allocations for node ".$node_id); $available_allocations = getAllocations($params,$node_id); - + $final_allocations = findFreePorts($available_allocations, $additional_port_list); if($final_allocations['status'] == true) { @@ -422,27 +422,63 @@ function wisp_CreateAccount(array $params) { } else { logActivity("Unable to find any nodes at location ID ".$loc_id); } - } else { - // Continue with normal deployment - $serverData['deploy']['port_range'] = $port_range; - } + } else { + // Continue with normal deployment + $serverData['deploy']['port_range'] = $port_range; + } + + // Create the game server + $server = wisp_API($params, 'servers', $serverData, 'POST'); + if($server['status_code'] === 400) throw new Exception('Couldn\'t find any nodes satisfying the request.'); + if($server['status_code'] !== 201) throw new Exception('Failed to create the server, received the error code: ' . $server['status_code'] . '. Enable module debug log for more info.'); + + // Get server ID + $serverId = wisp_GetServerID($params); + logActivity("Server ID is " . $serverId); + // Check the server status + $serverIsInstalled = false; + $timeoutCounter = 0; + logActivity('Logging install status next'); + logActivity($serverStatus['attributes']['container']['installed']); + while($serverIsInstalled != true && $timeoutCounter <= 30) { // Hard coded timeout, can be tweaked here if more time is required due to slow internet connection etc.. + logActivity('Container isn\'t installed yet. Waiting... x'.strval($timeoutCounter)); + sleep(3); + $serverStatus = wisp_API($params, 'servers/' . $serverId); + $serverIsInstalled = $serverStatus['attributes']['container']['installed']; + $timeoutCounter ++; + } + $timeoutCounter = 0; - // Create the game server - $server = wisp_API($params, 'servers', $serverData, 'POST'); + if($final_allocations['status'] == true) { - if($final_allocations['status'] == true) { - $patchData = [ 'add_allocations' => $final_allocations['additional_allocation_ids'], + 'allocation' => intval($final_allocations['main_allocation_id']), + 'memory' => intval($server['attributes']['limits']['memory']), + 'swap' => intval($server['attributes']['limits']['swap']), + 'io' => intval($server['attributes']['limits']['io']), + 'cpu' => intval($server['attributes']['limits']['cpu']), + 'disk' => intval($server['attributes']['limits']['disk']), + 'feature_limits' => [ + 'databases' => $databases ? (int) $databases : null, + 'allocations' => intval($server['attributes']['feature_limits']['allocations']), + //'allocations' => 3, + ] + ]; logActivity("Adding additional allocations to server. "); - $serverId = wisp_GetServerID($params); $server = wisp_API($params, 'servers/' . $serverId . "/build", $patchData, 'PATCH'); } - + // Due to some edge cases where the container dies immediately after creation and is re-started, + // may need to try again a couple of times before the daemon will finally accept the request. + while(($server['status_code'] !== 201 && $server['status_code'] !== 200) && $timeoutCounter < 5 ) { + $server = wisp_API($params, 'servers/' . $serverId . "/build", $patchData, 'PATCH'); + $timeoutCounter ++; + } + if($server['status_code'] === 400) throw new Exception('Couldn\'t find any nodes satisfying the request.'); - if($server['status_code'] !== 201) throw new Exception('Failed to create the server, received the error code: ' . $server['status_code'] . '. Enable module debug log for more info.'); + if($server['status_code'] !== 201 && $server['status_code'] !== 200) throw new Exception('Failed to create the server, received the error code: ' . $server['status_code'] . '. Enable module debug log for more info.'); unset($params['password']); Capsule::table('tblhosting')->where('id', $params['serviceid'])->update([ @@ -767,16 +803,18 @@ function findFreePorts(array $available_allocations, array $port_offsets) { */ // Iterate over available IP's foreach($available_allocations as $ip_addr => $ports) { - $result = Array(); - $result['status'] = false; + $result = Array(); + $result['status'] = false; $main_allocation_id = ""; - $additional_allocation_ids = Array(); + $main_allocation_port = ""; + $additional_allocation_ids = Array(); // Iterate over Ports logActivity("Checking IP: ".$ip_addr); //echo "Key: ".key($ports); foreach($ports as $port => $portDetails) { - $main_allocation_id = $port; + $main_allocation_id = $portDetails['id']; + $mail_allocation_port = $port; $found_all = true; foreach($port_offsets as $key => $port_offset) { // check if port @@ -786,24 +824,25 @@ function findFreePorts(array $available_allocations, array $port_offsets) { $found_all = false; } else { logActivity("Stashing available port: ".$ports[$next_port]['id']); - array_push($additional_allocation_ids, $ports[$next_port]['id']); + array_push($additional_allocation_ids, strval($ports[$next_port]['id'])); } } if($found_all == true) { logActivity("Found an available set of ports!"); logActivity("Main port allocation ID: ". $main_allocation_id); - logActivity("Additional port allocation ID's: ". print_r($additional_allocation_ids, true)); - $result['main_allocation_id'] = $main_allocation_id; - $result['additional_allocation_ids'] = $additional_allocation_ids; - $result['status'] = true; + logActivity("Additional port allocation ID's: ". print_r($additional_allocation_ids, true)); + $result['main_allocation_id'] = $main_allocation_id; + $result['main_allocatiion_port'] = $mail_allocation_port; + $result['additional_allocation_ids'] = $additional_allocation_ids; + $result['status'] = true; return $result; } else { // Reset values in array for next run - $additional_ports = array(); + $additional_allocation_ids = array(); } } // Raise an exception - logActivity("Failed to find available ports!"); - return false; + logActivity("Failed to find available ports!"); + return false; } -} +} \ No newline at end of file From 8632739725944ddbce255b7cae9de60ff1f32a6a Mon Sep 17 00:00:00 2001 From: snags141 Date: Mon, 3 Jan 2022 19:56:34 +0800 Subject: [PATCH 06/20] Updated to new method - assigns additional allocs at server create --- wisp/wisp.php | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/wisp/wisp.php b/wisp/wisp.php index 5c8914b..3a600b5 100644 --- a/wisp/wisp.php +++ b/wisp/wisp.php @@ -385,6 +385,10 @@ function wisp_CreateAccount(array $params) { 'allocations' => (int) $allocations, 'backup_megabytes_limit' => (int) $backup_megabytes_limit, ], + /*'allocation' => [ + 'default' => $final_allocations['main_allocation_id'], + 'additional' => $final_allocations['additional_allocation_ids'], + ],*/ 'deploy' => [ 'locations' => [(int) $location_id], 'dedicated_ip' => $dedicated_ip, @@ -414,7 +418,12 @@ function wisp_CreateAccount(array $params) { if($final_allocations['status'] == true) { logActivity("Successfully found an allocation. Setting primary allocation to ID " . $final_allocations['main_allocation_id']); + logActivity("Successfully found additional allocations: " . $final_allocations['additional_allocation_ids']); + foreach($final_allocations['additional_allocation_ids'] as $alloc_key => $alloc_id) { + logActivity("Got additional alloc: " . $alloc_id); + } $serverData['allocation']['default'] = intval($final_allocations['main_allocation_id']); + $serverData['allocation']['additional'] = $final_allocations['additional_allocation_ids']; } else { logActivity("Failed to find an available allocation."); } @@ -428,6 +437,7 @@ function wisp_CreateAccount(array $params) { } // Create the game server + logActivity("Creating the server "); $server = wisp_API($params, 'servers', $serverData, 'POST'); if($server['status_code'] === 400) throw new Exception('Couldn\'t find any nodes satisfying the request.'); if($server['status_code'] !== 201) throw new Exception('Failed to create the server, received the error code: ' . $server['status_code'] . '. Enable module debug log for more info.'); @@ -436,18 +446,18 @@ function wisp_CreateAccount(array $params) { $serverId = wisp_GetServerID($params); logActivity("Server ID is " . $serverId); // Check the server status - $serverIsInstalled = false; - $timeoutCounter = 0; + //$serverIsInstalled = false; + //$timeoutCounter = 0; logActivity('Logging install status next'); logActivity($serverStatus['attributes']['container']['installed']); - while($serverIsInstalled != true && $timeoutCounter <= 30) { // Hard coded timeout, can be tweaked here if more time is required due to slow internet connection etc.. + /*while($serverIsInstalled != true && $timeoutCounter <= 30) { // Hard coded timeout, can be tweaked here if more time is required due to slow internet connection etc.. logActivity('Container isn\'t installed yet. Waiting... x'.strval($timeoutCounter)); sleep(3); $serverStatus = wisp_API($params, 'servers/' . $serverId); $serverIsInstalled = $serverStatus['attributes']['container']['installed']; $timeoutCounter ++; } - $timeoutCounter = 0; + $timeoutCounter = 0;*/ if($final_allocations['status'] == true) { @@ -466,15 +476,15 @@ function wisp_CreateAccount(array $params) { ] ]; - logActivity("Adding additional allocations to server. "); - $server = wisp_API($params, 'servers/' . $serverId . "/build", $patchData, 'PATCH'); + //logActivity("Adding additional allocations to server. "); + //$server = wisp_API($params, 'servers/' . $serverId . "/build", $patchData, 'PATCH'); } // Due to some edge cases where the container dies immediately after creation and is re-started, // may need to try again a couple of times before the daemon will finally accept the request. - while(($server['status_code'] !== 201 && $server['status_code'] !== 200) && $timeoutCounter < 5 ) { + /*while(($server['status_code'] !== 201 && $server['status_code'] !== 200) && $timeoutCounter < 5 ) { $server = wisp_API($params, 'servers/' . $serverId . "/build", $patchData, 'PATCH'); $timeoutCounter ++; - } + }*/ if($server['status_code'] === 400) throw new Exception('Couldn\'t find any nodes satisfying the request.'); From 490b7cb0a115daf47ea3a3649c60cbce5579d843 Mon Sep 17 00:00:00 2001 From: snags141 Date: Mon, 3 Jan 2022 20:38:33 +0800 Subject: [PATCH 07/20] Updated readme FAQ section for multi-allocations, updated permissions screenshot and cleaned up code --- README.md | 7 ++- wisp/wisp.php | 163 +++++++++++++++++++------------------------------- 2 files changed, 68 insertions(+), 102 deletions(-) diff --git a/README.md b/README.md index d2b034d..89879de 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Please use the [WISP Discord](https://wisp.gg/discord) for configuration related 1. Download/Git clone this repository. 2. Move the ``wisp/`` folder into ``/modules/servers/``. -3. Create API Credentials with these permissions: ![Image](https://owo.whats-th.is/fa1eee.png) +3. Create API Credentials with these permissions: ![Image](https://i.imgur.com/nzo0u8C.png) 4. In WHMCS navigate to Setup > Products/Services > Servers 5. Create new server, fill the name with anything you want, hostname as the url to the panel. For example: ``my-panel.panel.gg`` 6. Change Server Type to WISP, leave username empty, fill the password field with your generated API Key. @@ -59,6 +59,11 @@ E.g: If you enter `1,2,4` and the first available port happens to be 25565, you' * 25567 (First Port +2) * 25569 (First Port +4) +You'll also want to configure "Additional Port Failure Mode". +This determines what the module should do if there are no allocations available on any of the defined nodes. +* "Continue" - Continues creating the server but only with one allocation, whatever is available at the time. You'll need to manually go in after the server gets created to assign additional ports as required. +* "Stop" - Stops the server creation and raises an error. + ## How to enable module debug log 1. In WHMCS 7 or below navigate to Utilities > Logs > Module Log. For WHMCS 8.x navigate to System Logs > Module Log in the left sidebar. 2. Click the Enable Debug Logging button. diff --git a/wisp/wisp.php b/wisp/wisp.php index 3a600b5..98ba73b 100644 --- a/wisp/wisp.php +++ b/wisp/wisp.php @@ -180,11 +180,11 @@ function wisp_ConfigOptions() { "FriendlyName" => "Additional Port Failure Mode", "Type" => "dropdown", "Options" => [ - 'stop' => 'Stop', 'continue' => 'Continue', + 'stop' => 'Stop', ], "Description" => "Determines whether server creation will continue if none of your nodes are able to satisfy the additional port allocation", - "Default" => "stop", + "Default" => "continue", ], "startup" => [ "FriendlyName" => "Startup", @@ -292,12 +292,11 @@ function wisp_GetOption(array $params, $id, $default = NULL) { function wisp_CreateAccount(array $params) { logActivity('Doing wisp_CreateAccount'); try { - - // Checking if the server ID already exists + // Checking if the server ID already exists $serverId = wisp_GetServerID($params); if(isset($serverId)) throw new Exception('Failed to create server because it is already created.'); - // Create or fetch the user account + // Create or fetch the user account $userResult = wisp_API($params, 'users/external/' . $params['clientsdetails']['uuid']); if($userResult['status_code'] === 404) { $userResult = wisp_API($params, 'users?search=' . urlencode($params['clientsdetails']['email'])); @@ -325,7 +324,7 @@ function wisp_CreateAccount(array $params) { throw new Exception('Failed to create user, received error code: ' . $userResult['status_code'] . '. Enable module debug log for more info.'); } - // Get egg data + // Get egg data $nestId = wisp_GetOption($params, 'nest_id'); $eggId = wisp_GetOption($params, 'egg_id'); @@ -345,8 +344,8 @@ function wisp_CreateAccount(array $params) { else $environment[$var] = $default; } - // Fetch given server parameters - $name = wisp_GetOption($params, 'server_name', 'My Server'); + // Fetch given server parameters + $name = wisp_GetOption($params, 'server_name', 'My Server'); $memory = wisp_GetOption($params, 'memory'); $swap = wisp_GetOption($params, 'swap'); $io = wisp_GetOption($params, 'io'); @@ -355,9 +354,9 @@ function wisp_CreateAccount(array $params) { $pack_id = wisp_GetOption($params, 'pack_id'); $location_id = wisp_GetOption($params, 'location_id'); $dedicated_ip = wisp_GetOption($params, 'dedicated_ip') ? true : false; - $port_range = wisp_GetOption($params, 'port_range'); - $additional_ports = wisp_GetOption($params, 'additional_ports'); - $additional_port_fail_mode = wisp_GetOption($params, 'additional_port_fail_mode'); + $port_range = wisp_GetOption($params, 'port_range'); + $additional_ports = wisp_GetOption($params, 'additional_ports'); + $additional_port_fail_mode = wisp_GetOption($params, 'additional_port_fail_mode'); $port_range = isset($port_range) ? explode(',', $port_range) : []; $image = wisp_GetOption($params, 'image', $eggData['attributes']['docker_image']); $startup = wisp_GetOption($params, 'startup', $eggData['attributes']['startup']); @@ -385,10 +384,6 @@ function wisp_CreateAccount(array $params) { 'allocations' => (int) $allocations, 'backup_megabytes_limit' => (int) $backup_megabytes_limit, ], - /*'allocation' => [ - 'default' => $final_allocations['main_allocation_id'], - 'additional' => $final_allocations['additional_allocation_ids'], - ],*/ 'deploy' => [ 'locations' => [(int) $location_id], 'dedicated_ip' => $dedicated_ip, @@ -402,35 +397,45 @@ function wisp_CreateAccount(array $params) { // Check if additional ports have been set if(isset($additional_ports) && $additional_ports != '') { + // Query all nodes for the given location until we find an available set of ports // Get the list of additional ports to add - $additional_port_list = explode(",", $additional_ports); - - // Get the server nodes for the specified location_id - $nodes = getNodes($params, $location_id); - // Get the port allocations for each node at this location and check if there's space for the additional ports - if(isset($nodes)) { - foreach($nodes as $key => $node_id) { - logActivity("Checking allocations for node ".$node_id); - $available_allocations = getAllocations($params,$node_id); - - $final_allocations = findFreePorts($available_allocations, $additional_port_list); - - if($final_allocations['status'] == true) { - logActivity("Successfully found an allocation. Setting primary allocation to ID " . $final_allocations['main_allocation_id']); - logActivity("Successfully found additional allocations: " . $final_allocations['additional_allocation_ids']); - foreach($final_allocations['additional_allocation_ids'] as $alloc_key => $alloc_id) { - logActivity("Got additional alloc: " . $alloc_id); + $additional_port_list = explode(",", $additional_ports); + + // Get the server nodes for the specified location_id + $nodes = getNodes($params, $location_id); + + // Get the port allocations for each node at this location and check if there's space for the additional ports + if(isset($nodes)) { + foreach($nodes as $key => $node_id) { + logActivity("Checking allocations for node ".$node_id); + $available_allocations = getAllocations($params,$node_id); + + $final_allocations = findFreePorts($available_allocations, $additional_port_list); + + if($final_allocations != false && $final_allocations['status'] == true) { + logActivity("Successfully found an allocation. Setting primary allocation to ID " . $final_allocations['main_allocation_id']); + logActivity("Successfully found additional allocations: " . $final_allocations['additional_allocation_ids']); + foreach($final_allocations['additional_allocation_ids'] as $alloc_key => $alloc_id) { + logActivity("Got additional alloc: " . $alloc_id); + } + $serverData['allocation']['default'] = intval($final_allocations['main_allocation_id']); + $serverData['allocation']['additional'] = $final_allocations['additional_allocation_ids']; + } else { + logActivity("Failed to find an available allocation."); + // Failure handling logic + if($additional_port_fail_mode = "Stop") { + throw new Exception('Couldn\'t find any available allocations to satisfy the request on node: ' . $node_id); + } else { + // Continue with normal deployment + $serverData['deploy']['port_range'] = $port_range; + } } - $serverData['allocation']['default'] = intval($final_allocations['main_allocation_id']); - $serverData['allocation']['additional'] = $final_allocations['additional_allocation_ids']; - } else { - logActivity("Failed to find an available allocation."); } + } else { + logActivity("Unable to find any nodes at location ID ".$loc_id); + throw new Exception('Couldn\'t find any nodes satisfying the request at location: ' . $loc_id); } - } else { - logActivity("Unable to find any nodes at location ID ".$loc_id); - } } else { // Continue with normal deployment $serverData['deploy']['port_range'] = $port_range; @@ -442,59 +447,15 @@ function wisp_CreateAccount(array $params) { if($server['status_code'] === 400) throw new Exception('Couldn\'t find any nodes satisfying the request.'); if($server['status_code'] !== 201) throw new Exception('Failed to create the server, received the error code: ' . $server['status_code'] . '. Enable module debug log for more info.'); - // Get server ID - $serverId = wisp_GetServerID($params); - logActivity("Server ID is " . $serverId); - // Check the server status - //$serverIsInstalled = false; - //$timeoutCounter = 0; - logActivity('Logging install status next'); - logActivity($serverStatus['attributes']['container']['installed']); - /*while($serverIsInstalled != true && $timeoutCounter <= 30) { // Hard coded timeout, can be tweaked here if more time is required due to slow internet connection etc.. - logActivity('Container isn\'t installed yet. Waiting... x'.strval($timeoutCounter)); - sleep(3); - $serverStatus = wisp_API($params, 'servers/' . $serverId); - $serverIsInstalled = $serverStatus['attributes']['container']['installed']; - $timeoutCounter ++; - } - $timeoutCounter = 0;*/ - - if($final_allocations['status'] == true) { - - $patchData = [ - 'add_allocations' => $final_allocations['additional_allocation_ids'], - 'allocation' => intval($final_allocations['main_allocation_id']), - 'memory' => intval($server['attributes']['limits']['memory']), - 'swap' => intval($server['attributes']['limits']['swap']), - 'io' => intval($server['attributes']['limits']['io']), - 'cpu' => intval($server['attributes']['limits']['cpu']), - 'disk' => intval($server['attributes']['limits']['disk']), - 'feature_limits' => [ - 'databases' => $databases ? (int) $databases : null, - 'allocations' => intval($server['attributes']['feature_limits']['allocations']), - //'allocations' => 3, - ] + // Catch API errors + if($server['status_code'] === 400) throw new Exception('Couldn\'t find any nodes satisfying the request.'); + if($server['status_code'] !== 201 && $server['status_code'] !== 200) throw new Exception('Failed to create the server, received the error code: ' . $server['status_code'] . '. Enable module debug log for more info.'); - ]; - //logActivity("Adding additional allocations to server. "); - //$server = wisp_API($params, 'servers/' . $serverId . "/build", $patchData, 'PATCH'); - } - // Due to some edge cases where the container dies immediately after creation and is re-started, - // may need to try again a couple of times before the daemon will finally accept the request. - /*while(($server['status_code'] !== 201 && $server['status_code'] !== 200) && $timeoutCounter < 5 ) { - $server = wisp_API($params, 'servers/' . $serverId . "/build", $patchData, 'PATCH'); - $timeoutCounter ++; - }*/ - - - if($server['status_code'] === 400) throw new Exception('Couldn\'t find any nodes satisfying the request.'); - if($server['status_code'] !== 201 && $server['status_code'] !== 200) throw new Exception('Failed to create the server, received the error code: ' . $server['status_code'] . '. Enable module debug log for more info.'); - - unset($params['password']); - Capsule::table('tblhosting')->where('id', $params['serviceid'])->update([ - 'username' => '', - 'password' => '', - ]); + unset($params['password']); + Capsule::table('tblhosting')->where('id', $params['serviceid'])->update([ + 'username' => '', + 'password' => '', + ]); } catch(Exception $err) { return $err->getMessage(); } @@ -721,7 +682,9 @@ function getNodes(array $params, int $loc_id) { $nodes = wisp_API($params, 'nodes/'); foreach($nodes['data'] as $key => $value) { $node_id = $value['attributes']['id']; - if($value['attributes']['location_id'] == $loc_id) { + if(!isset($loc_id) || $value['attributes']['location_id'] == $loc_id) { + array_push($filteredNodes, $node_id); + } else { array_push($filteredNodes, $node_id); } } @@ -769,17 +732,16 @@ function getPaginatedData($params,$url) { */ $results = array(); - logActivity("API: Fetching page: ".$ports[$next_port]['id']); + // Fetch and parse first page of data $response = wisp_API($params, $url); - //array_push($results, $response['data']); foreach($response['data'] as $key => $value) { array_push($results, $value); } $current_page = $response['meta']['pagination']['current_page']; $total_pages = $response['meta']['pagination']['total_pages']; + // Fetch and parse any remaining pages while ($total_pages > $current_page) { $next_page = intval($current_page)+1; - logActivity("API: Fetching page: ".$next_page); $response = wisp_API($params, $url.'?page='.$next_page); foreach($response['data'] as $key => $value) { array_push($results, $value); @@ -821,19 +783,17 @@ function findFreePorts(array $available_allocations, array $port_offsets) { // Iterate over Ports logActivity("Checking IP: ".$ip_addr); - //echo "Key: ".key($ports); foreach($ports as $port => $portDetails) { - $main_allocation_id = $portDetails['id']; - $mail_allocation_port = $port; + $main_allocation_id = $portDetails['id']; + $mail_allocation_port = $port; $found_all = true; foreach($port_offsets as $key => $port_offset) { - // check if port $next_port = intval($port) + intval($port_offset); if(!isset($ports[$next_port])) { // Port is not available $found_all = false; } else { - logActivity("Stashing available port: ".$ports[$next_port]['id']); + // Port is available, add it to the array array_push($additional_allocation_ids, strval($ports[$next_port]['id'])); } } @@ -851,7 +811,8 @@ function findFreePorts(array $available_allocations, array $port_offsets) { $additional_allocation_ids = array(); } } - // Raise an exception + + // Failed to find available set of ports based on requirements logActivity("Failed to find available ports!"); return false; } From fd5f94263cac9a029301143ca343ebecb212e472 Mon Sep 17 00:00:00 2001 From: snags141 Date: Tue, 4 Jan 2022 23:20:34 +0800 Subject: [PATCH 08/20] Removed unecessary log and comments --- wisp/wisp.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/wisp/wisp.php b/wisp/wisp.php index 98ba73b..3d944f2 100644 --- a/wisp/wisp.php +++ b/wisp/wisp.php @@ -290,7 +290,6 @@ function wisp_GetOption(array $params, $id, $default = NULL) { } function wisp_CreateAccount(array $params) { - logActivity('Doing wisp_CreateAccount'); try { // Checking if the server ID already exists $serverId = wisp_GetServerID($params); @@ -672,7 +671,6 @@ function wisp_ClientArea(array $params) { } } - /* Utility Functions */ function getNodes(array $params, int $loc_id) { /* @@ -709,11 +707,10 @@ function getAllocations(array $params, int $node_id){ ['192.168.1.123'] => { ['1234'] => { ['id'] = 1234; - } + }z }, ] */ - echo "Getting Allocations \n"; $available_allocations = array(); $allocations = getPaginatedData($params,'nodes/'.$node_id.'/allocations'); foreach($allocations as $key => $allocation) { From fd8447b5b8303863d579ac32c8b1052f19a3b878 Mon Sep 17 00:00:00 2001 From: snags141 Date: Tue, 4 Jan 2022 23:25:52 +0800 Subject: [PATCH 09/20] Final readme update --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 89879de..1a1d9b0 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ Please use the [WISP Discord](https://wisp.gg/discord) for configuration related ## Credits [Dane](https://github.com/DaneEveritt) and [everyone else](https://github.com/Pterodactyl/Panel/graphs/contributors) involved in development of the Pterodactyl Panel. [death-droid](https://github.com/death-droid) for the original WHMCS module. +[snags141](https://github.com/snags141/) for additional allocation support. # FAQ @@ -40,7 +41,7 @@ Valid options: ``server_name, memory, swap, io, cpu, disk, nest_id, egg_id, pack This also works for any name of environment variable: Player Slots => Will overwrite the environment variable named "Player Slots" to its value. -Useful trick: You can use the | seperator to change the display name of the variable like this: +Useful trick: You can use the | separator to change the display name of the variable like this: dedicated_ip|Dedicated IP => Will be displayed as "Dedicated IP" but will work correctly. [Sample configuration for configurable memory](https://owo.whats-th.is/85JwhVX.png) From f5622b0874824db34cc81c33cbdf968c24dc1c08 Mon Sep 17 00:00:00 2001 From: snags141 Date: Wed, 5 Jan 2022 00:31:14 +0800 Subject: [PATCH 10/20] Fixed a logic issue when multiple nodes are present at a location. Minor readme update. --- README.md | 2 ++ wisp/wisp.php | 32 +++++++++++++++++++------------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 1a1d9b0..b6bf68c 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,8 @@ E.g: If you enter `1,2,4` and the first available port happens to be 25565, you' * 25567 (First Port +2) * 25569 (First Port +4) +Note: Currently if this option is set, will override anything specified under "port_range" - Use one or the other. + You'll also want to configure "Additional Port Failure Mode". This determines what the module should do if there are no allocations available on any of the defined nodes. * "Continue" - Continues creating the server but only with one allocation, whatever is available at the time. You'll need to manually go in after the server gets created to assign additional ports as required. diff --git a/wisp/wisp.php b/wisp/wisp.php index 3d944f2..c02f65f 100644 --- a/wisp/wisp.php +++ b/wisp/wisp.php @@ -172,7 +172,7 @@ function wisp_ConfigOptions() { ], "additional_ports" => [ "FriendlyName" => "Additional Ports", - "Description" => "Additional ports as an offset from the first allocation - seperated by comma. Example: if the first assigned port is 25565 and you enter '1,2,4' then you'll get three additional ports 25565+1 (25566) 25565+2 (25567) and 25565+4 (25569) (optional)", + "Description" => "Additional ports as an offset from the first allocation - seperated by comma. Example: if the first assigned port is 25565 and you enter '1,2,4' then you'll get three additional ports 25565+1 (25566) 25565+2 (25567) and 25565+4 (25569). Note: Setting this will overwrite the port_range setting. (optional)", "Type" => "text", "Size" => 25, ], @@ -406,29 +406,35 @@ function wisp_CreateAccount(array $params) { // Get the port allocations for each node at this location and check if there's space for the additional ports if(isset($nodes)) { + $alloc_success = false; foreach($nodes as $key => $node_id) { logActivity("Checking allocations for node ".$node_id); + + // Get all the available allocations for this node $available_allocations = getAllocations($params,$node_id); - + + // Taking our additional allocation requirements and available node allocations, find a combination of available ports. $final_allocations = findFreePorts($available_allocations, $additional_port_list); if($final_allocations != false && $final_allocations['status'] == true) { + $alloc_success = true; logActivity("Successfully found an allocation. Setting primary allocation to ID " . $final_allocations['main_allocation_id']); logActivity("Successfully found additional allocations: " . $final_allocations['additional_allocation_ids']); - foreach($final_allocations['additional_allocation_ids'] as $alloc_key => $alloc_id) { - logActivity("Got additional alloc: " . $alloc_id); - } + $serverData['allocation']['default'] = intval($final_allocations['main_allocation_id']); $serverData['allocation']['additional'] = $final_allocations['additional_allocation_ids']; + // We successfully found an available allocation, break and check no more nodes. + break; + } + logActivity("Failed to find an available allocation on node: " . $node_id); + } + if(!$alloc_success) { + // Failure handling logic + if($additional_port_fail_mode = "Stop") { + throw new Exception('Couldn\'t find any nodes to satisfy the requested allocations.'); } else { - logActivity("Failed to find an available allocation."); - // Failure handling logic - if($additional_port_fail_mode = "Stop") { - throw new Exception('Couldn\'t find any available allocations to satisfy the request on node: ' . $node_id); - } else { - // Continue with normal deployment - $serverData['deploy']['port_range'] = $port_range; - } + // Continue with normal deployment + $serverData['deploy']['port_range'] = $port_range; } } } else { From e5bb7b45b330edb7eb6fb8fc51f30b75eda29933 Mon Sep 17 00:00:00 2001 From: snags141 Date: Wed, 5 Jan 2022 00:41:19 +0800 Subject: [PATCH 11/20] Minor wording change to reduce confusion --- wisp/wisp.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wisp/wisp.php b/wisp/wisp.php index c02f65f..11540b7 100644 --- a/wisp/wisp.php +++ b/wisp/wisp.php @@ -172,7 +172,7 @@ function wisp_ConfigOptions() { ], "additional_ports" => [ "FriendlyName" => "Additional Ports", - "Description" => "Additional ports as an offset from the first allocation - seperated by comma. Example: if the first assigned port is 25565 and you enter '1,2,4' then you'll get three additional ports 25565+1 (25566) 25565+2 (25567) and 25565+4 (25569). Note: Setting this will overwrite the port_range setting. (optional)", + "Description" => "Additional ports as an offset from the first allocation - seperated by comma. Example: if the first assigned port is 25565 and you enter '1,2,4' then you'll get three additional ports 25565+1 (25566) 25565+2 (25567) and 25565+4 (25569). Note: Setting this will ignore the port_range setting. (optional)", "Type" => "text", "Size" => 25, ], From 98cde615941b6c78a128656cedb9a1c1ce227483 Mon Sep 17 00:00:00 2001 From: snags141 Date: Wed, 5 Jan 2022 11:33:16 +0800 Subject: [PATCH 12/20] initial --- wisp/wisp.php | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/wisp/wisp.php b/wisp/wisp.php index 11540b7..7e8b674 100644 --- a/wisp/wisp.php +++ b/wisp/wisp.php @@ -423,6 +423,20 @@ function wisp_CreateAccount(array $params) { $serverData['allocation']['default'] = intval($final_allocations['main_allocation_id']); $serverData['allocation']['additional'] = $final_allocations['additional_allocation_ids']; + + // Update the start command - game port + logActivity("Starting to update command: ".$startup); + $startup = str_replace("{{game_port}}", $final_allocations['main_allocation_port'], $startup); + logActivity("Replacing game_port with ". $final_allocations['main_allocation_port']); + $idx = 1; + // Update the start command - additional allocations + foreach($final_allocations['additional_allocation_ports'] as $key => $port) { + logActivity("Replacing additional_port_".$idx." with ". $port); + $startup = str_replace("{{additional_port_".$idx."}}", $port, $startup); + $idx++; + } + logActivity("The final startup command is: " . $startup); + $serverData['startup'] = $startup; // We successfully found an available allocation, break and check no more nodes. break; } @@ -788,7 +802,7 @@ function findFreePorts(array $available_allocations, array $port_offsets) { logActivity("Checking IP: ".$ip_addr); foreach($ports as $port => $portDetails) { $main_allocation_id = $portDetails['id']; - $mail_allocation_port = $port; + $main_allocation_port = $port; $found_all = true; foreach($port_offsets as $key => $port_offset) { $next_port = intval($port) + intval($port_offset); @@ -805,7 +819,7 @@ function findFreePorts(array $available_allocations, array $port_offsets) { logActivity("Main port allocation ID: ". $main_allocation_id); logActivity("Additional port allocation ID's: ". print_r($additional_allocation_ids, true)); $result['main_allocation_id'] = $main_allocation_id; - $result['main_allocatiion_port'] = $mail_allocation_port; + $result['main_allocation_port'] = $main_allocation_port; $result['additional_allocation_ids'] = $additional_allocation_ids; $result['status'] = true; return $result; @@ -819,4 +833,5 @@ function findFreePorts(array $available_allocations, array $port_offsets) { logActivity("Failed to find available ports!"); return false; } -} \ No newline at end of file +} + From f98eec8c2b051c9ece98a3ff141981f9805047c3 Mon Sep 17 00:00:00 2001 From: Daniel Date: Wed, 5 Jan 2022 12:34:17 +0800 Subject: [PATCH 13/20] changed logActivity calls to module log and added port array --- wisp/wisp.php | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/wisp/wisp.php b/wisp/wisp.php index 7e8b674..fd5e9f5 100644 --- a/wisp/wisp.php +++ b/wisp/wisp.php @@ -408,7 +408,7 @@ function wisp_CreateAccount(array $params) { if(isset($nodes)) { $alloc_success = false; foreach($nodes as $key => $node_id) { - logActivity("Checking allocations for node ".$node_id); + logModuleCall("WISP-WHMCS", "Checking allocations for node: ".$node_id, "", ""); // Get all the available allocations for this node $available_allocations = getAllocations($params,$node_id); @@ -418,8 +418,7 @@ function wisp_CreateAccount(array $params) { if($final_allocations != false && $final_allocations['status'] == true) { $alloc_success = true; - logActivity("Successfully found an allocation. Setting primary allocation to ID " . $final_allocations['main_allocation_id']); - logActivity("Successfully found additional allocations: " . $final_allocations['additional_allocation_ids']); + logModuleCall("WISP-WHMCS", "Successfully found an allocation. Setting primary allocation to ID " . $final_allocations['main_allocation_id'], "", ""); $serverData['allocation']['default'] = intval($final_allocations['main_allocation_id']); $serverData['allocation']['additional'] = $final_allocations['additional_allocation_ids']; @@ -440,7 +439,7 @@ function wisp_CreateAccount(array $params) { // We successfully found an available allocation, break and check no more nodes. break; } - logActivity("Failed to find an available allocation on node: " . $node_id); + logModuleCall("WISP-WHMCS", "Failed to find an available allocation on node: ".$node_id, "", ""); } if(!$alloc_success) { // Failure handling logic @@ -452,7 +451,7 @@ function wisp_CreateAccount(array $params) { } } } else { - logActivity("Unable to find any nodes at location ID ".$loc_id); + logModuleCall("WISP-WHMCS", "Unable to find any nodes at location ID: ".$loc_id, "", ""); throw new Exception('Couldn\'t find any nodes satisfying the request at location: ' . $loc_id); } } else { @@ -461,7 +460,6 @@ function wisp_CreateAccount(array $params) { } // Create the game server - logActivity("Creating the server "); $server = wisp_API($params, 'servers', $serverData, 'POST'); if($server['status_code'] === 400) throw new Exception('Couldn\'t find any nodes satisfying the request.'); if($server['status_code'] !== 201) throw new Exception('Failed to create the server, received the error code: ' . $server['status_code'] . '. Enable module debug log for more info.'); @@ -797,9 +795,10 @@ function findFreePorts(array $available_allocations, array $port_offsets) { $main_allocation_id = ""; $main_allocation_port = ""; $additional_allocation_ids = Array(); + $additional_allocation_ports = Array(); // Iterate over Ports - logActivity("Checking IP: ".$ip_addr); + logModuleCall("WISP-WHMCS", "Checking IP: ".$ip_addr, "", ""); foreach($ports as $port => $portDetails) { $main_allocation_id = $portDetails['id']; $main_allocation_port = $port; @@ -812,25 +811,27 @@ function findFreePorts(array $available_allocations, array $port_offsets) { } else { // Port is available, add it to the array array_push($additional_allocation_ids, strval($ports[$next_port]['id'])); + array_push($additional_allocation_ports, strval($ports[$next_port])); } } if($found_all == true) { - logActivity("Found an available set of ports!"); - logActivity("Main port allocation ID: ". $main_allocation_id); - logActivity("Additional port allocation ID's: ". print_r($additional_allocation_ids, true)); + logModuleCall("WISP-WHMCS", "Found a game port allocation ID: ".$main_allocation_id, "", ""); + logModuleCall("WISP-WHMCS", "Found additional allocation ID's: ".print_r($additional_allocation_ids, true), "", ""); $result['main_allocation_id'] = $main_allocation_id; $result['main_allocation_port'] = $main_allocation_port; $result['additional_allocation_ids'] = $additional_allocation_ids; + $result['additional_allocation_ports'] = $additional_allocation_ports; $result['status'] = true; return $result; } else { // Reset values in array for next run - $additional_allocation_ids = array(); + $additional_allocation_ids = Array(); + $additional_allocation_ports = Array(); } } // Failed to find available set of ports based on requirements - logActivity("Failed to find available ports!"); + logModuleCall("WISP-WHMCS", "Failed to find available ports!", "", ""); return false; } } From 21e4c5292696b977c878ce1392012f70db1ff8b5 Mon Sep 17 00:00:00 2001 From: snags141 Date: Wed, 5 Jan 2022 23:05:37 +0800 Subject: [PATCH 14/20] Updated logic to use new json method of additional port assignments. Added support for setting environment parameters --- README.md | 25 ++++++++++++++++++++----- wisp/wisp.php | 49 ++++++++++++++++++++++++++++++------------------- 2 files changed, 50 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index b6bf68c..89a349e 100644 --- a/README.md +++ b/README.md @@ -53,20 +53,35 @@ This can be caused from any of the following: Wrong location, not enough disk sp The customer gets an email from the panel to setup their account (incl. password) if they didn't have an account before. Otherwise they should be able to use their existing credentials. ## My game requires multiple ports allocated. -Configure the "Additional Ports" option in the module settings. -It expects a comma-separated list of ports as a numeric offset from the first available allocation. -E.g: If you enter `1,2,4` and the first available port happens to be 25565, you'll get as additional allocations: (If they're available) +Configure the "**Additional Ports**" option in the module settings. +It expects a valid JSON string consisting of the parameter name or NONE, and a number representing a port as a numeric offset from the first available allocation. +E.g: If you enter `{"NONE":1, "NONE":2, "NONE":4}` and the first available port happens to be 25565, you'll get as additional allocations: * 25566 (First Port + 1) * 25567 (First Port +2) * 25569 (First Port +4) -Note: Currently if this option is set, will override anything specified under "port_range" - Use one or the other. +(If they're available) -You'll also want to configure "Additional Port Failure Mode". +Note: I this option is set, it will override anything specified under "port_range" - Use one or the other, not both. + +You'll also want to configure "**Additional Port Failure Mode**". This determines what the module should do if there are no allocations available on any of the defined nodes. * "Continue" - Continues creating the server but only with one allocation, whatever is available at the time. You'll need to manually go in after the server gets created to assign additional ports as required. * "Stop" - Stops the server creation and raises an error. +## How to assign additional allocations to server parameters like RCON_PORT +See the table below for "Additional Ports" example values. +*These examples assume your WISP node has allocations available from 1000-2000.* + +| Game | Required Ports |Additional Ports Example | Ports Assigned | +| ------------ | ------------ | ------------ | +| Rust | Game port and RCON port | `{"RCON_PORT":1}` | Game Port: 1000, RCON_PORT: 1001| +| Arma 3 | Game port, Game port +1 for Steam Query, Game port + 2 for Steam Port, and Game port +4 for BattleEye | `{"NONE":1, "NONE":2, "NONE":4}` | Game Port: 1000, Additional Ports: 1001, 1002, 1004 | +| Unturned | Game port, Game port +1 and Game port +2 | `{"NONE":1, "NONE":2}` | Game Port: 1000, Additional Ports: 1001, 1002 | +| Project Zomboid | Game Port, Steam port and an additional port for every player. Let's say we want 10 additional ports for 10 players. | `{"STEAM_PORT": 1, "NONE": 2, "NONE": 3, "NONE": 4, "NONE": 5, "NONE": 6, "NONE": 7, "NONE": 8, "NONE": 9, "NONE": 10, "NONE":11}` | Game Port: 1000, Steam Port: 1001, Additional Ports: 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011| +**What does "NONE" mean?** +"NONE" means you want to assign the additional port to the server, but it doesn't need to be assigned to a server parameter. If instead you want to add a +1 allocation and assign it to the parameter "RCON_PORT then you'd use `{"RCON_PORT":1}` for example. + ## How to enable module debug log 1. In WHMCS 7 or below navigate to Utilities > Logs > Module Log. For WHMCS 8.x navigate to System Logs > Module Log in the left sidebar. 2. Click the Enable Debug Logging button. diff --git a/wisp/wisp.php b/wisp/wisp.php index fd5e9f5..25f7bc8 100644 --- a/wisp/wisp.php +++ b/wisp/wisp.php @@ -399,8 +399,8 @@ function wisp_CreateAccount(array $params) { // Query all nodes for the given location until we find an available set of ports // Get the list of additional ports to add - $additional_port_list = explode(",", $additional_ports); - + //$additional_port_list = explode(",", $additional_ports); + $additional_port_list = $additional_ports; // Get the server nodes for the specified location_id $nodes = getNodes($params, $location_id); @@ -422,21 +422,15 @@ function wisp_CreateAccount(array $params) { $serverData['allocation']['default'] = intval($final_allocations['main_allocation_id']); $serverData['allocation']['additional'] = $final_allocations['additional_allocation_ids']; - - // Update the start command - game port - logActivity("Starting to update command: ".$startup); - $startup = str_replace("{{game_port}}", $final_allocations['main_allocation_port'], $startup); - logActivity("Replacing game_port with ". $final_allocations['main_allocation_port']); - $idx = 1; - // Update the start command - additional allocations + + // Update the environment parameters - additional allocations foreach($final_allocations['additional_allocation_ports'] as $key => $port) { - logActivity("Replacing additional_port_".$idx." with ". $port); - $startup = str_replace("{{additional_port_".$idx."}}", $port, $startup); - $idx++; + // If the key given in the config had a value of NONE, don't worry about adding it to the environment parameters. + if(substr( $key, 0, 5 ) !== "NONE_") { + $serverData['environment'][$key] = $port; + } } - logActivity("The final startup command is: " . $startup); - $serverData['startup'] = $startup; - // We successfully found an available allocation, break and check no more nodes. + // We successfully found and assigned an available allocation, break and check no more nodes. break; } logModuleCall("WISP-WHMCS", "Failed to find an available allocation on node: ".$node_id, "", ""); @@ -767,7 +761,7 @@ function getPaginatedData($params,$url) { return $results; } -function findFreePorts(array $available_allocations, array $port_offsets) { +function findFreePorts(array $available_allocations, string $port_offsets) { /* This is the main logic that takes a list of available allocations and the required offsets and then finds the first available set. @@ -781,7 +775,7 @@ function findFreePorts(array $available_allocations, array $port_offsets) { All other ports will be checked based on the required offset from the first. - $port_offsets The list of offsets from the first port that + $port_offsets The json string of offsets from the first port that are required for the server. Outputs: @@ -789,6 +783,20 @@ function findFreePorts(array $available_allocations, array $port_offsets) { the additional ports required. */ // Iterate over available IP's + + // Decode json string of port offsets + $none_string = "\"NONE\""; + $pos_idx = 1; + $pos = strpos($port_offsets, $none_string); + while($pos != false) { + // Rename any "NONE" keys as we can't decode duplicates + $port_offsets = substr_replace($port_offsets, "\"NONE_".$pos_idx."\"", $pos, strlen($none_string)); + $pos = strpos($port_offsets, $none_string); + $pos_idx ++; + } + + $port_offsets_array = json_decode($port_offsets, true); + foreach($available_allocations as $ip_addr => $ports) { $result = Array(); $result['status'] = false; @@ -803,7 +811,7 @@ function findFreePorts(array $available_allocations, array $port_offsets) { $main_allocation_id = $portDetails['id']; $main_allocation_port = $port; $found_all = true; - foreach($port_offsets as $key => $port_offset) { + foreach($port_offsets_array as $key => $port_offset) { $next_port = intval($port) + intval($port_offset); if(!isset($ports[$next_port])) { // Port is not available @@ -811,12 +819,15 @@ function findFreePorts(array $available_allocations, array $port_offsets) { } else { // Port is available, add it to the array array_push($additional_allocation_ids, strval($ports[$next_port]['id'])); - array_push($additional_allocation_ports, strval($ports[$next_port])); + //array_push($additional_allocation_ports, strval($next_port)); + + $additional_allocation_ports[$key] = $next_port; } } if($found_all == true) { logModuleCall("WISP-WHMCS", "Found a game port allocation ID: ".$main_allocation_id, "", ""); logModuleCall("WISP-WHMCS", "Found additional allocation ID's: ".print_r($additional_allocation_ids, true), "", ""); + logModuleCall("WISP-WHMCS", "Found additional allocation Keys: ".print_r($additional_allocation_keys, true), "", ""); $result['main_allocation_id'] = $main_allocation_id; $result['main_allocation_port'] = $main_allocation_port; $result['additional_allocation_ids'] = $additional_allocation_ids; From e1678245d008dab198fbad26f7a03ac4e87a59cb Mon Sep 17 00:00:00 2001 From: snags141 Date: Wed, 5 Jan 2022 23:17:39 +0800 Subject: [PATCH 15/20] Updated the description for additional_ports config option --- wisp/wisp.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wisp/wisp.php b/wisp/wisp.php index 25f7bc8..7ebe3b1 100644 --- a/wisp/wisp.php +++ b/wisp/wisp.php @@ -172,7 +172,7 @@ function wisp_ConfigOptions() { ], "additional_ports" => [ "FriendlyName" => "Additional Ports", - "Description" => "Additional ports as an offset from the first allocation - seperated by comma. Example: if the first assigned port is 25565 and you enter '1,2,4' then you'll get three additional ports 25565+1 (25566) 25565+2 (25567) and 25565+4 (25569). Note: Setting this will ignore the port_range setting. (optional)", + "Description" => "Additional ports in a JSON string, each must have a key of either "NONE" or an egg parameter name to set. E.g. If you want a game port, game port+1 and RCON_PORT assigned to game port +4 then use: {\"NONE\":1, \"RCON_PORT\":4} (optional)", "Type" => "text", "Size" => 25, ], @@ -794,7 +794,7 @@ function findFreePorts(array $available_allocations, string $port_offsets) { $pos = strpos($port_offsets, $none_string); $pos_idx ++; } - + $port_offsets_array = json_decode($port_offsets, true); foreach($available_allocations as $ip_addr => $ports) { From 1a42e04b055afad66788414ebe333001118e8068 Mon Sep 17 00:00:00 2001 From: snags141 Date: Thu, 6 Jan 2022 01:00:48 +0800 Subject: [PATCH 16/20] Updated json format and added links to readme in whmcs config options regarding allocations --- wisp/wisp.php | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/wisp/wisp.php b/wisp/wisp.php index 7ebe3b1..e414440 100644 --- a/wisp/wisp.php +++ b/wisp/wisp.php @@ -172,7 +172,7 @@ function wisp_ConfigOptions() { ], "additional_ports" => [ "FriendlyName" => "Additional Ports", - "Description" => "Additional ports in a JSON string, each must have a key of either "NONE" or an egg parameter name to set. E.g. If you want a game port, game port+1 and RCON_PORT assigned to game port +4 then use: {\"NONE\":1, \"RCON_PORT\":4} (optional)", + "Description" => "Additional ports to assign to the server. See the module readme for instructions: View Readme (optional)", "Type" => "text", "Size" => 25, ], @@ -183,7 +183,7 @@ function wisp_ConfigOptions() { 'continue' => 'Continue', 'stop' => 'Stop', ], - "Description" => "Determines whether server creation will continue if none of your nodes are able to satisfy the additional port allocation", + "Description" => "Determines whether server creation will continue if none of your nodes are able to satisfy the additional port allocation. See the module readme for more information: View Readme", "Default" => "continue", ], "startup" => [ @@ -437,7 +437,7 @@ function wisp_CreateAccount(array $params) { } if(!$alloc_success) { // Failure handling logic - if($additional_port_fail_mode = "Stop") { + if($additional_port_fail_mode == "stop") { throw new Exception('Couldn\'t find any nodes to satisfy the requested allocations.'); } else { // Continue with normal deployment @@ -782,21 +782,10 @@ function findFreePorts(array $available_allocations, string $port_offsets) { $ports_found The array of ports that were found available, based on the offsets the additional ports required. */ - // Iterate over available IP's - - // Decode json string of port offsets - $none_string = "\"NONE\""; - $pos_idx = 1; - $pos = strpos($port_offsets, $none_string); - while($pos != false) { - // Rename any "NONE" keys as we can't decode duplicates - $port_offsets = substr_replace($port_offsets, "\"NONE_".$pos_idx."\"", $pos, strlen($none_string)); - $pos = strpos($port_offsets, $none_string); - $pos_idx ++; - } - + $port_offsets_array = json_decode($port_offsets, true); + // Iterate over available IP's foreach($available_allocations as $ip_addr => $ports) { $result = Array(); $result['status'] = false; @@ -827,7 +816,7 @@ function findFreePorts(array $available_allocations, string $port_offsets) { if($found_all == true) { logModuleCall("WISP-WHMCS", "Found a game port allocation ID: ".$main_allocation_id, "", ""); logModuleCall("WISP-WHMCS", "Found additional allocation ID's: ".print_r($additional_allocation_ids, true), "", ""); - logModuleCall("WISP-WHMCS", "Found additional allocation Keys: ".print_r($additional_allocation_keys, true), "", ""); + logModuleCall("WISP-WHMCS", "Found additional allocation Ports: ".print_r($additional_allocation_ports, true), "", ""); $result['main_allocation_id'] = $main_allocation_id; $result['main_allocation_port'] = $main_allocation_port; $result['additional_allocation_ids'] = $additional_allocation_ids; From 77507502d8e170c25c42144782a3212a4d19696f Mon Sep 17 00:00:00 2001 From: snags141 Date: Thu, 6 Jan 2022 01:03:48 +0800 Subject: [PATCH 17/20] Moved new whmcs config options to the bottom of the list to maintain backwards compatibility --- wisp/wisp.php | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/wisp/wisp.php b/wisp/wisp.php index e414440..8b9f916 100644 --- a/wisp/wisp.php +++ b/wisp/wisp.php @@ -170,22 +170,6 @@ function wisp_ConfigOptions() { "Type" => "text", "Size" => 25, ], - "additional_ports" => [ - "FriendlyName" => "Additional Ports", - "Description" => "Additional ports to assign to the server. See the module readme for instructions: View Readme (optional)", - "Type" => "text", - "Size" => 25, - ], - "additional_port_fail_mode" => [ - "FriendlyName" => "Additional Port Failure Mode", - "Type" => "dropdown", - "Options" => [ - 'continue' => 'Continue', - 'stop' => 'Stop', - ], - "Description" => "Determines whether server creation will continue if none of your nodes are able to satisfy the additional port allocation. See the module readme for more information: View Readme", - "Default" => "continue", - ], "startup" => [ "FriendlyName" => "Startup", "Description" => "Custom startup command to assign to the created server (optional)", @@ -221,6 +205,22 @@ function wisp_ConfigOptions() { "Type" => "text", "Size" => 25, ], + "additional_ports" => [ + "FriendlyName" => "Additional Ports", + "Description" => "Additional ports to assign to the server. See the module readme for instructions: View Readme (optional)", + "Type" => "text", + "Size" => 25, + ], + "additional_port_fail_mode" => [ + "FriendlyName" => "Additional Port Failure Mode", + "Type" => "dropdown", + "Options" => [ + 'continue' => 'Continue', + 'stop' => 'Stop', + ], + "Description" => "Determines whether server creation will continue if none of your nodes are able to satisfy the additional port allocation. See the module readme for more information: View Readme", + "Default" => "continue", + ], ]; } From e039d022bbd916080dd62cba54a7bd6f1a46c1a6 Mon Sep 17 00:00:00 2001 From: snags141 Date: Thu, 6 Jan 2022 01:11:00 +0800 Subject: [PATCH 18/20] Removed two duplicate lines of API error handling --- wisp/wisp.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/wisp/wisp.php b/wisp/wisp.php index 8b9f916..1beb209 100644 --- a/wisp/wisp.php +++ b/wisp/wisp.php @@ -455,8 +455,6 @@ function wisp_CreateAccount(array $params) { // Create the game server $server = wisp_API($params, 'servers', $serverData, 'POST'); - if($server['status_code'] === 400) throw new Exception('Couldn\'t find any nodes satisfying the request.'); - if($server['status_code'] !== 201) throw new Exception('Failed to create the server, received the error code: ' . $server['status_code'] . '. Enable module debug log for more info.'); // Catch API errors if($server['status_code'] === 400) throw new Exception('Couldn\'t find any nodes satisfying the request.'); From ef75fb2280b6c396e17f9d98eb61ab13c0df5669 Mon Sep 17 00:00:00 2001 From: snags141 Date: Thu, 6 Jan 2022 01:22:32 +0800 Subject: [PATCH 19/20] Removed redundant test from getNodes() --- wisp/wisp.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/wisp/wisp.php b/wisp/wisp.php index 1beb209..c332317 100644 --- a/wisp/wisp.php +++ b/wisp/wisp.php @@ -686,13 +686,11 @@ function getNodes(array $params, int $loc_id) { /* Fetches and returns all nodes with a specific location_id */ - $filteredNodes = array(); + $filteredNodes = Array(); $nodes = wisp_API($params, 'nodes/'); foreach($nodes['data'] as $key => $value) { $node_id = $value['attributes']['id']; - if(!isset($loc_id) || $value['attributes']['location_id'] == $loc_id) { - array_push($filteredNodes, $node_id); - } else { + if($value['attributes']['location_id'] == $loc_id) { array_push($filteredNodes, $node_id); } } From 58bdf2557bdb9d8fff39c145c1dc71eea8d4955b Mon Sep 17 00:00:00 2001 From: snags141 Date: Thu, 6 Jan 2022 14:11:59 +0800 Subject: [PATCH 20/20] Updated readme with new json format. --- README.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 89a349e..98caf48 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ The customer gets an email from the panel to setup their account (incl. password ## My game requires multiple ports allocated. Configure the "**Additional Ports**" option in the module settings. It expects a valid JSON string consisting of the parameter name or NONE, and a number representing a port as a numeric offset from the first available allocation. -E.g: If you enter `{"NONE":1, "NONE":2, "NONE":4}` and the first available port happens to be 25565, you'll get as additional allocations: +E.g: If you enter `{1:"NONE", 2:"NONE", 4:"NONE"}` and the first available port happens to be 25565, you'll get as additional allocations: * 25566 (First Port + 1) * 25567 (First Port +2) * 25569 (First Port +4) @@ -74,16 +74,17 @@ See the table below for "Additional Ports" example values. *These examples assume your WISP node has allocations available from 1000-2000.* | Game | Required Ports |Additional Ports Example | Ports Assigned | -| ------------ | ------------ | ------------ | -| Rust | Game port and RCON port | `{"RCON_PORT":1}` | Game Port: 1000, RCON_PORT: 1001| -| Arma 3 | Game port, Game port +1 for Steam Query, Game port + 2 for Steam Port, and Game port +4 for BattleEye | `{"NONE":1, "NONE":2, "NONE":4}` | Game Port: 1000, Additional Ports: 1001, 1002, 1004 | -| Unturned | Game port, Game port +1 and Game port +2 | `{"NONE":1, "NONE":2}` | Game Port: 1000, Additional Ports: 1001, 1002 | -| Project Zomboid | Game Port, Steam port and an additional port for every player. Let's say we want 10 additional ports for 10 players. | `{"STEAM_PORT": 1, "NONE": 2, "NONE": 3, "NONE": 4, "NONE": 5, "NONE": 6, "NONE": 7, "NONE": 8, "NONE": 9, "NONE": 10, "NONE":11}` | Game Port: 1000, Steam Port: 1001, Additional Ports: 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011| +| ------------ | ------------ | ------------ | ------------ | +| Rust | Game port and RCON port | `{1:"RCON_PORT"}` | Game Port: 1000, RCON_PORT: 1001| +| Arma 3 | Game port, Game port +1 for Steam Query, Game port + 2 for Steam Port, and Game port +4 for BattleEye | `{1:"NONE", 2:"NONE", 4:"NONE"}` | Game Port: 1000, Additional Ports: 1001, 1002, 1004 | +| Unturned | Game port, Game port +1 and Game port +2 | `{1:"NONE", 2:"NONE"}` | Game Port: 1000, Additional Ports: 1001, 1002 | +| Project Zomboid | Game Port, Steam port and an additional port for every player. Let's say we want 10 additional ports for 10 players. | `{1:"STEAM_PORT", 2:"NONE", 3:"NONE", 4:"NONE", 5:"NONE", 6:"NONE", 7:"NONE", 8:"NONE", 9:"NONE", 10:"NONE", 11:"NONE"}` | Game Port: 1000, Steam Port: 1001, Additional Ports: 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011| + **What does "NONE" mean?** -"NONE" means you want to assign the additional port to the server, but it doesn't need to be assigned to a server parameter. If instead you want to add a +1 allocation and assign it to the parameter "RCON_PORT then you'd use `{"RCON_PORT":1}` for example. +"NONE" means you want to assign the additional port to the server, but it doesn't need to be assigned to a server parameter. If instead you want to add a +1 port and assign it to the parameter "RCON_PORT" then you'd use `{1:"RCON_PORT"}` for example. ## How to enable module debug log 1. In WHMCS 7 or below navigate to Utilities > Logs > Module Log. For WHMCS 8.x navigate to System Logs > Module Log in the left sidebar. 2. Click the Enable Debug Logging button. 3. Do the action that failed again and you will have required logs to debug the issue. All 404 errors can be ignored. -4. Remember to Disable Debug Logging if you are using this in production, as it's not recommended to have it enabled. +4. Remember to Disable Debug Logging if you are using this in production, as it's not recommended to have it enabled. \ No newline at end of file