mirror of
https://gitlab.com/ArkHost/WHMCS-ArkHost-HetznerVPS.git
synced 2026-07-23 23:36:04 +02:00
update v1.2.5
This commit is contained in:
@@ -59,7 +59,7 @@ WHMCS server module for Hetzner Cloud VPS management.
|
||||
|
||||
- Server Type: `cx23`, `cx33`, `cx43`, `cx53` (Cost-Optimized), `cpx11`, `cpx21`, `cax11`, `ccx13`, etc.
|
||||
- Operating System: `ubuntu-22.04`, `debian-11`, `rocky-9`, etc.
|
||||
- Datacenter: `fsn1`, `nbg1`, `hel1`, `ash`, `hil`, `sin`
|
||||
- Location: `fsn1`, `nbg1`, `hel1`, `ash`, `hil`, `sin`
|
||||
- Backups: On/Off
|
||||
- Create Floating IP: On/Off
|
||||
- Cloud-Init YAML: Optional custom cloud-init configuration
|
||||
@@ -84,17 +84,19 @@ Create in Setup → Products/Services → Configurable Options:
|
||||
- `No|None`
|
||||
- `Yes|1 Floating IP`
|
||||
|
||||
**2\. Datacenter Selection**
|
||||
**2\. Location Selection**
|
||||
|
||||
- Option Name: `datacenter`
|
||||
- Option Name: `Location`
|
||||
- Option Type: `Dropdown`
|
||||
- Options:
|
||||
- `fsn1-dc14|Falkenstein, Germany`
|
||||
- `nbg1-dc3|Nuremberg, Germany`
|
||||
- `hel1-dc2|Helsinki, Finland`
|
||||
- `ash-dc1|Ashburn, USA`
|
||||
- `hil-dc1|Hillsboro, USA`
|
||||
- `sin-dc1|Singapore, Singapore`
|
||||
- `fsn1|Falkenstein, Germany`
|
||||
- `nbg1|Nuremberg, Germany`
|
||||
- `hel1|Helsinki, Finland`
|
||||
- `ash|Ashburn, USA`
|
||||
- `hil|Hillsboro, USA`
|
||||
- `sin|Singapore, Singapore`
|
||||
|
||||
Existing configurable options named `datacenter` remain supported. Legacy values such as `fsn1-dc14` are automatically converted to their corresponding location (`fsn1`) when provisioning.
|
||||
|
||||
**3\. Server Type**
|
||||
|
||||
@@ -329,6 +331,13 @@ Check out our other WHMCS modules at [arkhost.com/whmcs-modules.php](https://ar
|
||||
|
||||
## Changelog
|
||||
|
||||
### v1.2.5
|
||||
**Fixed:**
|
||||
- Restored server provisioning after Hetzner removed the deprecated `datacenter` request property on July 1, 2026
|
||||
- Replaced datacenter discovery with the Hetzner Locations API
|
||||
- Updated client-area location display for the current server response format
|
||||
- Added automatic conversion of legacy datacenter values such as `fsn1-dc14` to `fsn1`
|
||||
|
||||
### v1.2.4
|
||||
**Fixed:**
|
||||
- IP address now stored on the service at provisioning (and backfilled for existing services) so it displays in WHMCS instead of showing blank
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* WHMCS Server Module - Hetzner VPS
|
||||
*
|
||||
* @package WHMCS
|
||||
* @version 1.2.4
|
||||
* @version 1.2.5
|
||||
* @copyright Copyright (c) ArkHost 2025
|
||||
* @author ArkHost <support@arkhost.com>
|
||||
* @link https://arkhost.com
|
||||
@@ -104,6 +104,57 @@ function ArkHostHetznerVPS_GetConfigurableOption(array $params, $optionName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a legacy Hetzner datacenter name (for example fsn1-dc14) to the
|
||||
* corresponding location name (fsn1). Location names are normalized to
|
||||
* lowercase, while numeric IDs remain unchanged.
|
||||
*/
|
||||
function ArkHostHetznerVPS_NormalizeLocation($location) {
|
||||
if (!is_scalar($location)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$location = trim((string)$location);
|
||||
if ($location === '') {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (preg_match('/^([a-z0-9]+)-dc[0-9]+$/i', $location, $matches)) {
|
||||
return strtolower($matches[1]);
|
||||
}
|
||||
|
||||
return strtolower($location);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the server location while remaining compatible with configurable
|
||||
* options named either "Location" or the former "Datacenter".
|
||||
*/
|
||||
function ArkHostHetznerVPS_GetLocationOption(array $params, $default = NULL) {
|
||||
foreach (array('configoptions', 'customfields') as $collection) {
|
||||
if (!isset($params[$collection]) || !is_array($params[$collection])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Prefer the current option name if both current and legacy options
|
||||
// happen to exist on the same product.
|
||||
foreach (array('location', 'datacenter') as $optionName) {
|
||||
foreach ($params[$collection] as $name => $value) {
|
||||
$normalizedName = strtolower(trim((string)$name));
|
||||
if ($normalizedName === $optionName && $value !== '') {
|
||||
return ArkHostHetznerVPS_NormalizeLocation($value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Keep using the original module setting key so existing WHMCS products
|
||||
// retain their configoption3 value after upgrading.
|
||||
return ArkHostHetznerVPS_NormalizeLocation(
|
||||
ArkHostHetznerVPS_GetOption($params, 'datacenter', $default)
|
||||
);
|
||||
}
|
||||
|
||||
function ArkHostHetznerVPS_API(array $params) {
|
||||
$url = 'https://api.hetzner.cloud/v1/';
|
||||
$data = [];
|
||||
@@ -125,8 +176,8 @@ function ArkHostHetznerVPS_API(array $params) {
|
||||
$method = 'GET';
|
||||
break;
|
||||
|
||||
case 'Datacenters':
|
||||
$url .= 'datacenters';
|
||||
case 'Locations':
|
||||
$url .= 'locations?per_page=50';
|
||||
$method = 'GET';
|
||||
break;
|
||||
|
||||
@@ -160,10 +211,11 @@ function ArkHostHetznerVPS_API(array $params) {
|
||||
)
|
||||
);
|
||||
|
||||
// Add datacenter if specified
|
||||
$datacenter = ArkHostHetznerVPS_GetOption($params, 'datacenter');
|
||||
if ($datacenter) {
|
||||
$data['datacenter'] = $datacenter;
|
||||
// Hetzner removed the datacenter request property on 1 July 2026.
|
||||
// Normalize legacy values such as fsn1-dc14 before sending location.
|
||||
$location = ArkHostHetznerVPS_GetLocationOption($params);
|
||||
if ($location) {
|
||||
$data['location'] = $location;
|
||||
}
|
||||
|
||||
// Handle backups
|
||||
@@ -975,9 +1027,11 @@ function ArkHostHetznerVPS_ConfigOptions() {
|
||||
'Type' => 'dropdown',
|
||||
'Options' => array(),
|
||||
),
|
||||
// Keep the original array key and position for existing WHMCS product
|
||||
// settings. Only the Hetzner-facing value and admin label have changed.
|
||||
'datacenter' => array(
|
||||
'FriendlyName' => 'Datacenter',
|
||||
'Description' => 'The datacenter location for the server.',
|
||||
'FriendlyName' => 'Location',
|
||||
'Description' => 'The Hetzner location for the server (Configurable option: Location or legacy datacenter).',
|
||||
'Type' => 'dropdown',
|
||||
'Options' => array(),
|
||||
),
|
||||
@@ -993,7 +1047,7 @@ function ArkHostHetznerVPS_ConfigOptions() {
|
||||
),
|
||||
'floating_ip_location' => array(
|
||||
'FriendlyName' => 'Floating IP Location',
|
||||
'Description' => 'Location for floating IPs (same as datacenter)',
|
||||
'Description' => 'Location for floating IPs (normally the same as the server location).',
|
||||
'Type' => 'dropdown',
|
||||
'Options' => array(),
|
||||
),
|
||||
@@ -1082,19 +1136,31 @@ function ArkHostHetznerVPS_ConfigOptions() {
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch datacenters
|
||||
$params['action'] = 'Datacenters';
|
||||
$datacenters = ArkHostHetznerVPS_API($params);
|
||||
// Fetch locations. Hetzner's datacenter endpoints are deprecated
|
||||
// and are scheduled for removal after 1 October 2026.
|
||||
$params['action'] = 'Locations';
|
||||
$locations = ArkHostHetznerVPS_API($params);
|
||||
|
||||
if (isset($datacenters['datacenters'])) {
|
||||
foreach ($datacenters['datacenters'] as $datacenter) {
|
||||
$array['datacenter']['Options'] += array(
|
||||
$datacenter['name'] => $datacenter['description'] . ' (' . $datacenter['location']['city'] . ')'
|
||||
);
|
||||
// Also populate floating IP locations
|
||||
$array['floating_ip_location']['Options'] += array(
|
||||
$datacenter['location']['name'] => $datacenter['location']['city'] . ', ' . $datacenter['location']['country']
|
||||
);
|
||||
if (isset($locations['locations'])) {
|
||||
foreach ($locations['locations'] as $location) {
|
||||
if (empty($location['name'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$place = array_filter(array(
|
||||
$location['city'] ?? '',
|
||||
$location['country'] ?? ''
|
||||
));
|
||||
$description = !empty($location['description'])
|
||||
? $location['description']
|
||||
: $location['name'];
|
||||
$label = $description;
|
||||
if (!empty($place)) {
|
||||
$label .= ' (' . implode(', ', $place) . ')';
|
||||
}
|
||||
|
||||
$array['datacenter']['Options'][$location['name']] = $label;
|
||||
$array['floating_ip_location']['Options'][$location['name']] = $label;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1218,7 +1284,9 @@ function ArkHostHetznerVPS_CreateAccount(array $params) {
|
||||
$floatingIpParams = $params;
|
||||
$floatingIpParams['action'] = 'Create Floating IP';
|
||||
$floatingIpParams['ip_type'] = $ipType;
|
||||
$floatingIpParams['location'] = ArkHostHetznerVPS_GetOption($params, 'floating_ip_location');
|
||||
$floatingIpParams['location'] = ArkHostHetznerVPS_NormalizeLocation(
|
||||
ArkHostHetznerVPS_GetOption($params, 'floating_ip_location')
|
||||
);
|
||||
$floatingIpParams['description'] = 'Server ID: ' . $create['server']['id'];
|
||||
$floatingIpParams['assign_to_server'] = true;
|
||||
|
||||
@@ -1691,8 +1759,9 @@ function ArkHostHetznerVPS_ClientAreaAPI(array $params) {
|
||||
$createParams = $params;
|
||||
$createParams['action'] = 'Create Floating IP';
|
||||
$createParams['ip_type'] = 'ipv4';
|
||||
$createParams['location'] = ArkHostHetznerVPS_GetOption($params, 'floating_ip_location') ?:
|
||||
ArkHostHetznerVPS_GetOption($params, 'datacenter');
|
||||
$createParams['location'] = ArkHostHetznerVPS_NormalizeLocation(
|
||||
ArkHostHetznerVPS_GetOption($params, 'floating_ip_location')
|
||||
) ?: ArkHostHetznerVPS_GetLocationOption($params);
|
||||
$createParams['description'] = 'WHMCS Service ID: ' . $params['serviceid'];
|
||||
$createParams['assign_to_server'] = true;
|
||||
|
||||
@@ -2485,21 +2554,31 @@ function ArkHostHetznerVPS_ClientArea(array $params) {
|
||||
$serverInfo['bandwidth'] = 20480; // 20TB in GB (20 * 1024)
|
||||
$serverInfo['bandwidth_used'] = 0; // Not available via API
|
||||
|
||||
// Add datacenter info - format as "City, Country"
|
||||
$city = isset($serverInfo['datacenter']['location']['city']) ? $serverInfo['datacenter']['location']['city'] : '';
|
||||
$country = isset($serverInfo['datacenter']['location']['country']) ? $serverInfo['datacenter']['location']['country'] : '';
|
||||
|
||||
if ($city && $country) {
|
||||
$serverInfo['datacenter'] = $city . ', ' . $country;
|
||||
} elseif ($city) {
|
||||
$serverInfo['datacenter'] = $city;
|
||||
} elseif ($country) {
|
||||
$serverInfo['datacenter'] = $country;
|
||||
} else {
|
||||
$serverInfo['datacenter'] = 'N/A';
|
||||
// Hetzner now returns location directly on the server. Retain a fallback
|
||||
// for cached/older responses that still contain datacenter.location.
|
||||
$locationInfo = array();
|
||||
if (isset($serverInfo['location']) && is_array($serverInfo['location'])) {
|
||||
$locationInfo = $serverInfo['location'];
|
||||
} elseif (isset($serverInfo['datacenter']['location']) && is_array($serverInfo['datacenter']['location'])) {
|
||||
$locationInfo = $serverInfo['datacenter']['location'];
|
||||
}
|
||||
|
||||
$serverInfo['location'] = $city ?: 'N/A';
|
||||
$city = $locationInfo['city'] ?? '';
|
||||
$country = $locationInfo['country'] ?? '';
|
||||
|
||||
if ($city && $country) {
|
||||
$locationDisplay = $city . ', ' . $country;
|
||||
} elseif ($city) {
|
||||
$locationDisplay = $city;
|
||||
} elseif ($country) {
|
||||
$locationDisplay = $country;
|
||||
} else {
|
||||
$locationDisplay = 'N/A';
|
||||
}
|
||||
|
||||
$serverInfo['location_display'] = $locationDisplay;
|
||||
// Preserve the former display key for third-party/custom templates.
|
||||
$serverInfo['datacenter'] = $locationDisplay;
|
||||
|
||||
// Get root password with expiration check (72 hours)
|
||||
$passwordSetTime = $params['model']->serviceProperties->get('ArkHostHetznerVPS|Password Set Time');
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* WHMCS Server Module - Hetzner VPS Hooks
|
||||
*
|
||||
* @package WHMCS
|
||||
* @version 1.2.4
|
||||
* @version 1.2.5
|
||||
* @copyright Copyright (c) ArkHost 2025
|
||||
* @author ArkHost <support@arkhost.com>
|
||||
* @link https://arkhost.com
|
||||
@@ -70,4 +70,3 @@ add_hook('ClientAreaHeadOutput', 1, function($vars) {
|
||||
</style>
|
||||
HTML;
|
||||
});
|
||||
|
||||
|
||||
@@ -207,7 +207,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-muted">{$ADDONLANG.Overview.Location}:</td>
|
||||
<td><i class="fa fa-map-marker-alt mr-1"></i>{$serverInfo['datacenter']}</td>
|
||||
<td><i class="fa fa-map-marker-alt mr-1"></i>{$serverInfo['location_display']}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-muted">{$ADDONLANG.Overview.ServerType}:</td>
|
||||
|
||||
Reference in New Issue
Block a user