Enhance VM provisioning logging by integrating VmProvisionLogger into CreateVirtualMachineJob and AssignIpToGuestJob; update composer dependencies for Plesk integration
This commit is contained in:
@@ -58,6 +58,8 @@ class CreateVirtualMachineJob implements ShouldQueue
|
||||
$ipPoolId = null;
|
||||
$lock = null;
|
||||
|
||||
$vmLogger->for('CreateVirtualMachineJob');
|
||||
|
||||
try {
|
||||
$customerId = $this->item->order->customer_id;
|
||||
$lock = VmProvisionLock::updateOrCreate(
|
||||
|
||||
@@ -13,6 +13,7 @@ use App\Models\Service;
|
||||
use App\Models\VirtualMachines;
|
||||
use App\Http\Services\vCenter as vCenterService;
|
||||
use App\Models\vCenter;
|
||||
use App\Services\VirtualMachine\VmProvisionLogger;
|
||||
use App\Services\VmProvisionService;
|
||||
use App\Services\VsphereHostSshService;
|
||||
use Illuminate\Bus\Queueable;
|
||||
@@ -64,9 +65,11 @@ class AssignIpToGuestJob implements ShouldQueue
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
|
||||
public function handle(VsphereHostSshService $ssh, vCenterService $vCenterService): void
|
||||
public function handle(VsphereHostSshService $ssh, vCenterService $vCenterService, VmProvisionLogger $logger): void
|
||||
{
|
||||
Log::info('AssignIpToGuestJob: start', [
|
||||
$logger->for('AssignIpToGuestJob');
|
||||
|
||||
$logger->step('start', [
|
||||
'module_vmware_id' => $this->moduleVmwareId,
|
||||
'vm_id' => $this->vmId,
|
||||
'os_family' => $this->osFamily,
|
||||
@@ -79,7 +82,7 @@ class AssignIpToGuestJob implements ShouldQueue
|
||||
])->find($this->moduleVmwareId);
|
||||
|
||||
if (!$moduleVmware) {
|
||||
Log::error('AssignIpToGuestJob: ModuleVmware not found', [
|
||||
$logger->error('ModuleVmware not found', [
|
||||
'module_vmware_id' => $this->moduleVmwareId,
|
||||
]);
|
||||
return;
|
||||
@@ -110,7 +113,7 @@ class AssignIpToGuestJob implements ShouldQueue
|
||||
$maxAttempts = $this->reservationId ? 1 : self::MAX_ATTEMPTS;
|
||||
|
||||
for ($attempt = 1; $attempt <= $maxAttempts; $attempt++) {
|
||||
Log::info('AssignIpToGuestJob: attempt', [
|
||||
$logger->step('attempt', [
|
||||
'attempt' => $attempt,
|
||||
'module_vmware_id' => $this->moduleVmwareId,
|
||||
'network_id' => $networkId,
|
||||
@@ -119,15 +122,15 @@ class AssignIpToGuestJob implements ShouldQueue
|
||||
|
||||
// [3] Use upstream reservation if provided, else reserve a fresh IP.
|
||||
$picked = $this->reservationId
|
||||
? $this->loadReservation($this->reservationId, $this->reservedIpPoolId)
|
||||
? $this->loadReservation($this->reservationId, $this->reservedIpPoolId, $logger)
|
||||
: $this->reserveIp($networkId, $hostId, $dns);
|
||||
|
||||
if (!$picked) {
|
||||
Log::error('AssignIpToGuestJob: no free IPs in pool', [
|
||||
$logger->error('no free IPs in pool', [
|
||||
'network_id' => $networkId,
|
||||
'attempt' => $attempt,
|
||||
]);
|
||||
break; // No point retrying — no IPs available
|
||||
break;
|
||||
}
|
||||
|
||||
$reservation = $picked['reservation'];
|
||||
@@ -153,19 +156,19 @@ class AssignIpToGuestJob implements ShouldQueue
|
||||
|
||||
// [5] If assign failed → release and try next IP
|
||||
if (!$this->isSuccess($assignOutput)) {
|
||||
Log::warning('AssignIpToGuestJob: assignIp FAIL', [
|
||||
$logger->warning('assignIp FAIL', [
|
||||
'ip' => $ip,
|
||||
'attempt' => $attempt,
|
||||
'output' => trim($assignOutput),
|
||||
]);
|
||||
$this->releaseIp($reservation, $ipPoolId);
|
||||
$this->releaseIp($reservation, $ipPoolId, $logger);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strtoupper($this->osFamily) === VmProvisionService::OS_WINDOWS) {
|
||||
$this->persistIp($reservation, $moduleVmware, $ipPoolId, $serviceId);
|
||||
|
||||
Log::info('AssignIpToGuestJob: Windows IP assigned', [
|
||||
$logger->success('Windows IP assigned', [
|
||||
'module_vmware_id' => $this->moduleVmwareId,
|
||||
'vm_id' => $this->vmId,
|
||||
'ip' => $ip,
|
||||
@@ -195,19 +198,19 @@ class AssignIpToGuestJob implements ShouldQueue
|
||||
|
||||
// [7] If verification failed → release and try next IP
|
||||
if (!$this->isSuccess($verifyOutput)) {
|
||||
Log::warning('AssignIpToGuestJob: verifyIpInGuest FAIL', [
|
||||
$logger->warning('verifyIpInGuest FAIL', [
|
||||
'ip' => $ip,
|
||||
'attempt' => $attempt,
|
||||
'output' => trim($verifyOutput),
|
||||
]);
|
||||
$this->releaseIp($reservation, $ipPoolId);
|
||||
$this->releaseIp($reservation, $ipPoolId, $logger);
|
||||
continue;
|
||||
}
|
||||
|
||||
// [8] SUCCESS — persist confirmed IP to module_vmware + virtual_machines + ip_pools
|
||||
$this->persistIp($reservation, $moduleVmware, $ipPoolId, $serviceId);
|
||||
|
||||
Log::info('AssignIpToGuestJob: IP assigned and verified', [
|
||||
$logger->success('IP assigned and verified', [
|
||||
'module_vmware_id' => $this->moduleVmwareId,
|
||||
'vm_id' => $this->vmId,
|
||||
'ip' => $ip,
|
||||
@@ -225,7 +228,7 @@ class AssignIpToGuestJob implements ShouldQueue
|
||||
}
|
||||
|
||||
// [9] All attempts exhausted
|
||||
Log::error('AssignIpToGuestJob: all attempts failed — marking VM inactive', [
|
||||
$logger->error('all attempts failed — marking VM inactive', [
|
||||
'module_vmware_id' => $this->moduleVmwareId,
|
||||
'vm_id' => $this->vmId,
|
||||
'attempts' => $maxAttempts,
|
||||
@@ -246,7 +249,7 @@ class AssignIpToGuestJob implements ShouldQueue
|
||||
$guestIp = $guestInfo['data']['ip_address'] ?? null;
|
||||
if ($guestIp) {
|
||||
$moduleVmware->update(['ip' => $guestIp, 'status' => 1]);
|
||||
Log::info('AssignIpToGuestJob: recovered IP from guest identity', [
|
||||
$logger->step('recovered IP from guest identity', [
|
||||
'module_vmware_id' => $this->moduleVmwareId,
|
||||
'ip' => $guestIp,
|
||||
]);
|
||||
@@ -255,7 +258,7 @@ class AssignIpToGuestJob implements ShouldQueue
|
||||
}
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('AssignIpToGuestJob: failed to recover IP after exhausted attempts', [
|
||||
$logger->error('failed to recover IP after exhausted attempts', [
|
||||
'module_vmware_id' => $this->moduleVmwareId,
|
||||
'error' => $e->getMessage(),
|
||||
]);
|
||||
@@ -348,11 +351,11 @@ class AssignIpToGuestJob implements ShouldQueue
|
||||
*
|
||||
* @return array{reservation:ModuleIpAddress,ip_pool_id:int,gateway:string,cidr:int}|null
|
||||
*/
|
||||
private function loadReservation(int $reservationId, ?int $ipPoolId): ?array
|
||||
private function loadReservation(int $reservationId, ?int $ipPoolId, VmProvisionLogger $logger): ?array
|
||||
{
|
||||
$reservation = ModuleIpAddress::find($reservationId);
|
||||
if (!$reservation) {
|
||||
Log::error('AssignIpToGuestJob: upstream reservation missing', [
|
||||
$logger->error('upstream reservation missing', [
|
||||
'reservation_id' => $reservationId,
|
||||
]);
|
||||
return null;
|
||||
@@ -374,16 +377,16 @@ class AssignIpToGuestJob implements ShouldQueue
|
||||
* Release a failed reservation by deleting the pending ModuleIpAddress row.
|
||||
* This returns the IP to the available pool.
|
||||
*/
|
||||
private function releaseIp(ModuleIpAddress $reservation, ?int $ipPoolId): void
|
||||
private function releaseIp(ModuleIpAddress $reservation, ?int $ipPoolId, VmProvisionLogger $logger): void
|
||||
{
|
||||
try {
|
||||
$reservation->delete();
|
||||
if ($ipPoolId) {
|
||||
IpPool::where('id', $ipPoolId)->update(['status' => 'free']);
|
||||
}
|
||||
Log::info('AssignIpToGuestJob: IP reservation released', ['ip' => $reservation->ip]);
|
||||
$logger->step('IP reservation released', ['ip' => $reservation->ip]);
|
||||
} catch (\Throwable $e) {
|
||||
Log::warning('AssignIpToGuestJob: could not release IP reservation', [
|
||||
$logger->warning('could not release IP reservation', [
|
||||
'ip' => $reservation->ip,
|
||||
'error' => $e->getMessage(),
|
||||
]);
|
||||
@@ -462,13 +465,4 @@ class AssignIpToGuestJob implements ShouldQueue
|
||||
return is_array($data) && ($data['status'] ?? '') === 'ok';
|
||||
}
|
||||
|
||||
/** Convert dotted-decimal netmask to CIDR prefix length (e.g. 255.255.255.0 → 24). */
|
||||
private function netmaskToCidr(string $netmask): int
|
||||
{
|
||||
$bits = 0;
|
||||
foreach (explode('.', $netmask) as $octet) {
|
||||
$bits += substr_count(decbin((int) $octet), '1');
|
||||
}
|
||||
return $bits;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ use Throwable;
|
||||
|
||||
class VmProvisionLogger
|
||||
{
|
||||
private const JOB_NAME = 'CreateVirtualMachineJob';
|
||||
private string $jobName = 'System';
|
||||
|
||||
private const REDACTED_KEYS = [
|
||||
'password',
|
||||
@@ -29,6 +29,12 @@ class VmProvisionLogger
|
||||
{
|
||||
}
|
||||
|
||||
public function for(string $jobName): static
|
||||
{
|
||||
$this->jobName = $jobName;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function step(string $title, array $context = []): void
|
||||
{
|
||||
$safe = $this->redact($context);
|
||||
@@ -90,7 +96,7 @@ class VmProvisionLogger
|
||||
|
||||
private function jobLabel(): string
|
||||
{
|
||||
return self::JOB_NAME;
|
||||
return $this->jobName;
|
||||
}
|
||||
|
||||
private function redact(array $context): array
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
"nwidart/laravel-modules": "^10.0",
|
||||
"opcodesio/log-viewer": "^3.18",
|
||||
"phpseclib/phpseclib": "*",
|
||||
"plesk/ext-laravel-integration": "^7.0",
|
||||
"predis/predis": "^2.2",
|
||||
"pusher/pusher-php-server": "^7.2",
|
||||
"spatie/laravel-permission": "^6.3",
|
||||
|
||||
Generated
+48
-1
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "cfc535c27971a90c45e31a2ddd47afe3",
|
||||
"content-hash": "4996106ea97079078f843b42993edb6f",
|
||||
"packages": [
|
||||
{
|
||||
"name": "barryvdh/laravel-dompdf",
|
||||
@@ -4181,6 +4181,53 @@
|
||||
],
|
||||
"time": "2026-06-14T23:24:10+00:00"
|
||||
},
|
||||
{
|
||||
"name": "plesk/ext-laravel-integration",
|
||||
"version": "7.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/plesk/ext-laravel-integration.git",
|
||||
"reference": "73dc4ea3f99e033396497f147aa033eb0602f943"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/plesk/ext-laravel-integration/zipball/73dc4ea3f99e033396497f147aa033eb0602f943",
|
||||
"reference": "73dc4ea3f99e033396497f147aa033eb0602f943",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"laravel/framework": ">=7.0.0",
|
||||
"php": ">=7.4"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"PleskExtLaravel\\Providers\\ConsoleServiceProvider"
|
||||
]
|
||||
},
|
||||
"component": "package"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"PleskExtLaravel\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"Apache-2.0"
|
||||
],
|
||||
"description": "Plesk Laravel Toolkit integration with Laravel applications.",
|
||||
"keywords": [
|
||||
"laravel",
|
||||
"plesk"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/plesk/ext-laravel-integration/issues",
|
||||
"source": "https://github.com/plesk/ext-laravel-integration/tree/7.0.0"
|
||||
},
|
||||
"time": "2023-01-20T09:40:57+00:00"
|
||||
},
|
||||
{
|
||||
"name": "predis/predis",
|
||||
"version": "v2.4.1",
|
||||
|
||||
Reference in New Issue
Block a user