Enhance VM provisioning logging by integrating VmProvisionLogger into CreateVirtualMachineJob and AssignIpToGuestJob; update composer dependencies for Plesk integration

This commit is contained in:
baodev0
2026-07-13 13:45:22 +07:00
parent fdb5714e93
commit d283a2c694
5 changed files with 83 additions and 33 deletions
@@ -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;
}
}