154 lines
5.8 KiB
PHP
154 lines
5.8 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Services\vCenter;
|
|
|
|
use App\Support\TlsHttpClientFactory;
|
|
use Illuminate\Support\Facades\Log;
|
|
use App\Http\Services\Discord;
|
|
use App\Services\VirtualMachine\VmProviderSettingsService;
|
|
use Exception;
|
|
use App\Http\Services\vCenter\Concerns\ReadsVirtualMachineInfo;
|
|
use App\Http\Services\vCenter\Concerns\UpgradesVirtualMachine;
|
|
|
|
class VirtualMachineService
|
|
{
|
|
use ReadsVirtualMachineInfo;
|
|
use UpgradesVirtualMachine;
|
|
|
|
protected Client $client;
|
|
protected PowerShellService $powerShellService;
|
|
|
|
public function __construct(Client $client, PowerShellService $powerShellService)
|
|
{
|
|
$this->client = $client;
|
|
$this->powerShellService = $powerShellService;
|
|
}
|
|
|
|
public function CreateVirtualMachine($product_data): array|string
|
|
{
|
|
$vcenterModel = $product_data['vcenter'];
|
|
Log::info('Vcenter Info', ['data' => $vcenterModel]);
|
|
|
|
if (!$this->client->loginServer($vcenterModel)) {
|
|
Log::error('Failed to create VM: API check failed, requires login.');
|
|
return 'Login_Again';
|
|
}
|
|
|
|
$userName = customer()?->email;
|
|
|
|
$item = $product_data['item'];
|
|
$product = $product_data['product'] ?? null;
|
|
$host = $product_data['host'];
|
|
$datacenter = $product_data['datacenter'];
|
|
$template = $product_data['template'];
|
|
|
|
$addon = $product_data['addon'] ?? ['cpu' => 0, 'ram' => 0, 'disk' => 0];
|
|
|
|
$base_cpu = $product->cpu ?? ($host->cpu ?? 1);
|
|
$base_ram = $product->ram ?? ($host->ram ?? 1);
|
|
$base_disk = $product->disk ?? ($host->disk ?? 20);
|
|
|
|
$base_cpu = max(1, (int) $base_cpu);
|
|
$base_ram = max(1, (int) $base_ram);
|
|
$base_disk = max(20, (int) $base_disk);
|
|
|
|
Log::info("Cấu hình cơ bản", [
|
|
'base_cpu' => $base_cpu,
|
|
'base_ram' => $base_ram,
|
|
'base_disk' => $base_disk,
|
|
'addon' => $addon
|
|
]);
|
|
|
|
/** @var VmProviderSettingsService $providerSettings */
|
|
$providerSettings = app(VmProviderSettingsService::class);
|
|
|
|
$datastore = $product_data['datastore'] ?? null;
|
|
if (!$datastore) {
|
|
throw new Exception("Host id={$host->id} chưa có datastore active để tạo VM.");
|
|
}
|
|
$datastoreId = $datastore->datastore;
|
|
|
|
$body = [
|
|
'spec' => [
|
|
'name' => $item->server_name ?? ($userName . '-vm-' . $item->id),
|
|
'source' => $template,
|
|
'placement' => [
|
|
'datacenter' => $datacenter->datacenter_id,
|
|
'folder' => $product_data['folder'] ?? $providerSettings->defaultFolder(),
|
|
'host' => $host->host_id,
|
|
'resource_pool' => $product_data['resource_pool'] ?? $providerSettings->defaultResourcePool(),
|
|
'datastore' => $datastoreId,
|
|
],
|
|
'power_on' => false,
|
|
'fallback_to_datastore_default_policy' => true,
|
|
],
|
|
];
|
|
|
|
Log::info('Data payload', ['data' => $body]);
|
|
|
|
try {
|
|
Log::info('Bắt đầu clone VM với timeout 300 giây', ['template' => $template, 'target_name' => $body['spec']['name']]);
|
|
|
|
$response = TlsHttpClientFactory::vCenter()
|
|
->timeout(300)
|
|
->connectTimeout(30)
|
|
->withHeaders([
|
|
'vmware-api-session-id' => $this->client->token,
|
|
'Content-Type' => 'application/json',
|
|
])
|
|
->post("https://{$this->client->apiUri}/rest/vcenter/vm?action=clone", $body);
|
|
|
|
$responseData = $response->json();
|
|
|
|
if ($response->successful() && !isset($responseData['type'])) {
|
|
$vmId = $responseData['value'] ?? 'UNKNOWN';
|
|
|
|
Log::info("VM clone thành công, VM ID: {$vmId}", [
|
|
'addon_data' => $addon,
|
|
'base_cpu' => $base_cpu,
|
|
'base_ram' => $base_ram,
|
|
'has_cpu_addon' => $addon['cpu'] > 0,
|
|
'has_ram_addon' => $addon['ram'] > 0,
|
|
'has_disk_addon' => $addon['disk'] > 0
|
|
]);
|
|
|
|
if ($vmId !== 'UNKNOWN' && ($addon['cpu'] > 0 || $addon['ram'] > 0 || $addon['disk'] > 0)) {
|
|
Log::info("Bắt đầu cập nhật addon cho VM {$vmId}");
|
|
$this->updateVMHardware($vmId, $addon, $base_cpu, $base_ram);
|
|
} else {
|
|
Log::info("Không có addon nào cần cập nhật cho VM {$vmId}");
|
|
}
|
|
|
|
$discord = app(Discord::class);
|
|
|
|
$addonMsg = '';
|
|
if (!empty($addon)) {
|
|
$addonMsg = "\n**Addon:** " .
|
|
($addon['cpu'] ? "CPU +{$addon['cpu']} " : "") .
|
|
($addon['ram'] ? "RAM +{$addon['ram']}GB " : "") .
|
|
($addon['disk'] ? "Disk +{$addon['disk']}GB " : "");
|
|
}
|
|
|
|
$discord->SendMessage(
|
|
message: "**User:** {$item->server_name}\n**VM ID:** `{$vmId}`{$addonMsg}\n**Thời gian:** " . now()->format('d/m/Y H:i:s'),
|
|
color: Discord::COLOR_SUCCESS,
|
|
title: '🎉 Tạo máy ảo thành công'
|
|
);
|
|
|
|
return ['error' => false, 'data' => $vmId];
|
|
}
|
|
|
|
Log::error('VM clone failed on vCenter', [
|
|
'status' => $response->status(),
|
|
'request' => $body,
|
|
'response' => $responseData ?? $response->body(),
|
|
]);
|
|
|
|
return ['error' => true, 'data' => $responseData['value'] ?? $response->body()];
|
|
} catch (Exception $e) {
|
|
Log::error('Exception when creating VM', ['message' => $e->getMessage()]);
|
|
return ['error' => true, 'data' => $e->getMessage()];
|
|
}
|
|
}
|
|
}
|