maxBackupsForUser($user); $count = VmBackup::query() ->whereHas('vm', fn ($q) => $q->where('user_id', $user->id)) ->whereIn('status', ['running', 'completed']) ->count(); if ($count >= $max) { throw new ProvisioningException("Maximal {$max} Backups erlaubt.", step: 'backup_limit'); } $storage = config('hosting.backups.pbs_storage', 'inett-PBS'); $upid = $this->proxmox->startBackup((int) $vm->vmid, $storage); return VmBackup::query()->create([ 'customer_id' => $vm->id, 'user_id' => $user->id, 'storage' => $storage, 'volume_id' => $upid, 'status' => 'running', ]); } public function maxBackupsForUser(User $user): int { return (int) config('hosting.backups.max_per_customer', 4); } public function deleteAllForVm(Customer $vm): void { $backups = VmBackup::query()->where('customer_id', $vm->id)->get(); foreach ($backups as $backup) { Log::info('Backup record removed', ['id' => $backup->id, 'volume' => $backup->volume_id]); // PBS purge via API when credentials available $backup->delete(); } } public function enforceRetentionForUser(User $user): void { $max = $this->maxBackupsForUser($user); $backups = VmBackup::query() ->whereHas('vm', fn ($q) => $q->where('user_id', $user->id)) ->where('status', 'completed') ->orderByDesc('completed_at') ->get(); foreach ($backups->slice($max) as $old) { $old->delete(); } } }