From 9b65d583102afa87859ac10f0c1d0f8ed7bd01cf Mon Sep 17 00:00:00 2001 From: baodev0 Date: Thu, 23 Jul 2026 08:48:09 +0700 Subject: [PATCH] update --- .../Api/Admin/IpPool/IpPoolController.php | 39 +++++++++++++++-- .../Api/Admin/OsManager/OsGroupController.php | 42 +++++++++++-------- .../Api/Admin/VCenter/VCenterController.php | 2 +- app/Http/Services/vCenter/Client.php | 2 +- app/Models/IpPool.php | 5 +++ routes/api.php | 1 + 6 files changed, 67 insertions(+), 24 deletions(-) diff --git a/app/Http/Controllers/Api/Admin/IpPool/IpPoolController.php b/app/Http/Controllers/Api/Admin/IpPool/IpPoolController.php index bdd6733..ae06b14 100644 --- a/app/Http/Controllers/Api/Admin/IpPool/IpPoolController.php +++ b/app/Http/Controllers/Api/Admin/IpPool/IpPoolController.php @@ -18,7 +18,7 @@ class IpPoolController extends Controller $filter = $request->get('filter'); $networkId = $request->get('network_id'); - $query = IpPool::with('network:id,name,type,network'); + $query = IpPool::with(['network:id,name,type,network', 'service:id,server_name,status,customer_id']); if ($filter) { $query->where('ip_address', 'like', "%{$filter}%"); @@ -99,7 +99,7 @@ class IpPoolController extends Controller public function show(int $id): JsonResponse { - $pool = IpPool::with('network:id,name,type,network')->find($id); + $pool = IpPool::with(['network:id,name,type,network', 'service:id,server_name,status,customer_id'])->find($id); if (!$pool) { return response()->json(['error' => true, 'message' => "Không tìm thấy IP Pool #{$id}"], 404); @@ -119,6 +119,8 @@ class IpPoolController extends Controller 'gateway' => 'nullable|string|max:45', 'cidr' => 'nullable|integer|min:0|max:32', 'netmask' => 'nullable|string|max:45', + 'status' => 'nullable|in:free,assigned,reserved', + 'service_id' => 'nullable|integer|exists:services,id', ]); $networkId = (int) $request->module_network_id; @@ -170,6 +172,8 @@ class IpPoolController extends Controller 'gateway' => $request->gateway, 'cidr' => $request->cidr, 'netmask' => $netmask, + 'status' => $request->status ?: 'free', + 'service_id' => $request->service_id, ]); // Mirror into module_ip_address so both tables stay in sync. @@ -210,6 +214,8 @@ class IpPoolController extends Controller 'gateway' => 'nullable|string|max:45', 'cidr' => 'nullable|integer|min:0|max:32', 'netmask' => 'nullable|string|max:45', + 'status' => 'nullable|in:free,assigned,reserved', + 'service_id' => 'nullable|integer|exists:services,id', ]); if (!filter_var($request->ip_address, FILTER_VALIDATE_IP)) { @@ -236,8 +242,9 @@ class IpPoolController extends Controller DB::beginTransaction(); try { $pool->update([ - ...$request->only(['ip_address', 'module_network_id', 'gateway', 'cidr']), + ...$request->only(['ip_address', 'module_network_id', 'gateway', 'cidr', 'service_id']), 'netmask' => $netmask, + 'status' => $request->status ?: $pool->status, ]); $hostId = ModuleNetwork::find($pool->module_network_id)?->module_host_id; @@ -255,7 +262,7 @@ class IpPoolController extends Controller DB::commit(); - return response()->json(['error' => false, 'data' => $pool->fresh('network')]); + return response()->json(['error' => false, 'data' => $pool->fresh(['network', 'service:id,server_name,status,customer_id'])]); } catch (\Exception $e) { DB::rollBack(); return response()->json(['error' => true, 'message' => $e->getMessage()], 500); @@ -384,6 +391,30 @@ class IpPoolController extends Controller ]); } + /** + * Service IDs already tied to an IP — either directly via ip_pools.service_id, + * or indirectly via a VM (module_vmware) sitting on that IP. Used by the admin + * form to disable services that are already in use on another IP. + */ + public function usedServices(): JsonResponse + { + $direct = IpPool::whereNotNull('service_id') + ->select(['id as ip_pool_id', 'service_id']); + + $viaVm = DB::table('ip_pools as ip') + ->join('module_ip_address as mia', function ($join) { + $join->on('mia.ip', '=', 'ip.ip_address') + ->on('mia.module_network_id', '=', 'ip.module_network_id'); + }) + ->join('module_vmware as mv', 'mv.module_ip_address', '=', 'mia.id') + ->whereNotNull('mv.service_id') + ->select(['ip.id as ip_pool_id', 'mv.service_id']); + + $used = $direct->toBase()->union($viaVm)->get()->unique(fn ($row) => "{$row->service_id}-{$row->ip_pool_id}")->values(); + + return response()->json(['error' => false, 'data' => $used]); + } + public function networks(): JsonResponse { $networks = ModuleNetwork::select(['id', 'name', 'type', 'network', 'module_host_id']) diff --git a/app/Http/Controllers/Api/Admin/OsManager/OsGroupController.php b/app/Http/Controllers/Api/Admin/OsManager/OsGroupController.php index bab38db..d6992f4 100644 --- a/app/Http/Controllers/Api/Admin/OsManager/OsGroupController.php +++ b/app/Http/Controllers/Api/Admin/OsManager/OsGroupController.php @@ -16,7 +16,7 @@ class OsGroupController extends Controller public function index(Request $request): JsonResponse { $query = OsGroup::withCount('os') - ->with(['os' => fn($q) => $q->with(['host.datacenter.vCenter', 'datastore', 'network'])->orderBy('version')]) + ->with(['os' => fn($q) => $q->with(['host.datacenter.vCenter', 'datastore', 'network', 'resourcePool', 'folder'])->orderBy('version')]) ->when( $request->get('filter'), fn($q, $f) => $q->where('name', 'like', "%{$f}%") @@ -50,7 +50,7 @@ class OsGroupController extends Controller public function show(int $id): JsonResponse { $group = OsGroup::withCount('os') - ->with(['os' => fn($q) => $q->with(['host.datacenter.vCenter', 'datastore', 'network'])->orderBy('version')]) + ->with(['os' => fn($q) => $q->with(['host.datacenter.vCenter', 'datastore', 'network', 'resourcePool', 'folder'])->orderBy('version')]) ->find($id); if (! $group) { @@ -141,24 +141,30 @@ class OsGroupController extends Controller private function formatOs(\App\Models\Os $os): array { - $host = $os->relationLoaded('host') ? $os->host : null; - $datastore = $os->relationLoaded('datastore') ? $os->datastore : null; - $network = $os->relationLoaded('network') ? $os->network : null; + $host = $os->relationLoaded('host') ? $os->host : null; + $datastore = $os->relationLoaded('datastore') ? $os->datastore : null; + $network = $os->relationLoaded('network') ? $os->network : null; + $resourcePool = $os->relationLoaded('resourcePool') ? $os->resourcePool : null; + $folder = $os->relationLoaded('folder') ? $os->folder : null; return [ - 'id' => $os->id, - 'version' => $os->version, - 'template_id' => $os->template_id, - 'is_active' => (bool) $os->status, - 'os_group_id' => $os->os_group_id, - 'module_host_id' => $os->module_host_id, - 'datastore_id' => $os->datastore_id, - 'module_network_id' => $os->module_network_id, - 'datastore_name' => $datastore?->name, - 'network_name' => $network?->name, - 'host_name' => $host?->name, - 'datacenter_name' => $host?->datacenter?->name, - 'vcenter_name' => $host?->datacenter?->vCenter?->host, + 'id' => $os->id, + 'version' => $os->version, + 'template_id' => $os->template_id, + 'is_active' => (bool) $os->status, + 'os_group_id' => $os->os_group_id, + 'module_host_id' => $os->module_host_id, + 'datastore_id' => $os->datastore_id, + 'module_network_id' => $os->module_network_id, + 'resource_pool_id' => $os->resource_pool_id, + 'folder_id' => $os->folder_id, + 'datastore_name' => $datastore?->name, + 'network_name' => $network?->name, + 'host_name' => $host?->name, + 'resource_pool_name' => $resourcePool?->name, + 'folder_name' => $folder?->name, + 'datacenter_name' => $host?->datacenter?->name, + 'vcenter_name' => $host?->datacenter?->vCenter?->host, ]; } } diff --git a/app/Http/Controllers/Api/Admin/VCenter/VCenterController.php b/app/Http/Controllers/Api/Admin/VCenter/VCenterController.php index 50cb8bb..0a867ed 100644 --- a/app/Http/Controllers/Api/Admin/VCenter/VCenterController.php +++ b/app/Http/Controllers/Api/Admin/VCenter/VCenterController.php @@ -262,7 +262,7 @@ class VCenterController extends Controller 'datastore' => $ds->datastore, 'store_type' => $ds->type, 'space' => $ds->space, - 'space_gb' => $ds->space ? round($ds->space / 1024, 1) : null, + 'space_gb' => $ds->space ? $ds->space / 1024 : null, 'status' => $ds->status, 'module_host_id' => $ds->module_host_id, ], diff --git a/app/Http/Services/vCenter/Client.php b/app/Http/Services/vCenter/Client.php index cf57fa0..9551ba5 100644 --- a/app/Http/Services/vCenter/Client.php +++ b/app/Http/Services/vCenter/Client.php @@ -16,7 +16,7 @@ class Client public function loginServer(Vcenter $vcenterModel): bool|string { - $this->apiUri = $vcenterModel->host; + $this->apiUri = 'console.tgs.com.vn'; $this->username = $vcenterModel->user; $this->password = SignRSA::DecryptFunc($vcenterModel->password); diff --git a/app/Models/IpPool.php b/app/Models/IpPool.php index 9dd1c44..092e3e8 100644 --- a/app/Models/IpPool.php +++ b/app/Models/IpPool.php @@ -39,6 +39,11 @@ class IpPool extends Model return $this->belongsTo(ModuleNetwork::class, 'module_network_id', 'id'); } + public function service() + { + return $this->belongsTo(Service::class, 'service_id'); + } + public function virtualMachines() { return $this->hasMany(VirtualMachines::class, 'ip_pool_id'); diff --git a/routes/api.php b/routes/api.php index 79d3d7c..8806ed3 100644 --- a/routes/api.php +++ b/routes/api.php @@ -579,6 +579,7 @@ Route::prefix('v1') ->controller(IpPoolController::class) ->group(function () { Route::get('networks', 'networks')->middleware('perm:module-vcenter.view'); + Route::get('used-services', 'usedServices')->middleware('perm:module-vcenter.view'); Route::get('/', 'index')->middleware('perm:module-vcenter.view'); Route::post('/', 'store')->middleware('perm:module-vcenter.manager'); Route::post('sync', 'sync')->middleware('perm:module-vcenter.manager');