festbench-web/app/Console/Commands/Gpus.php

107 lines
3 KiB
PHP

<?php
namespace App\Console\Commands;
use App\Models\Gpu;
use Illuminate\Console\Command;
use Symfony\Component\Console\Attribute\AsCommand;
#[AsCommand(name: 'festbench:gpus', description: 'Manage the canonical GPU catalog')]
class Gpus extends Command
{
protected $signature = 'festbench:gpus
{action : list|add|deactivate}
{--name= : GPU name (add/deactivate)}
{--vendor= : amd|nvidia|intel|other (add)}';
public function handle(): int
{
return match ($this->argument('action')) {
'list' => $this->listGpus(),
'add' => $this->addGpu(),
'deactivate' => $this->deactivateGpu(),
default => (function () {
$this->error('Unknown action. Use list, add or deactivate.');
return self::FAILURE;
})(),
};
}
private function listGpus(): int
{
$this->table(
['id', 'name', 'vendor', 'active'],
Gpu::orderBy('vendor')->orderBy('name')->get(['id', 'name', 'vendor', 'active'])
->map(fn ($g) => [$g->id, $g->name, $g->vendor, $g->active ? 'yes' : 'no'])->all()
);
return self::SUCCESS;
}
private function addGpu(): int
{
$name = $this->option('name');
if ($name === null) {
$this->error('--name is required.');
return self::FAILURE;
}
$vendor = $this->option('vendor') ?? $this->guessVendor($name);
if (! in_array($vendor, ['amd', 'nvidia', 'intel', 'cloud', 'other'], true)) {
$this->error('--vendor must be amd, nvidia, intel, cloud or other.');
return self::FAILURE;
}
$gpu = Gpu::updateOrCreate(
['name' => trim($name)],
['vendor' => $vendor, 'active' => true]
);
$this->info($gpu->wasRecentlyCreated
? "GPU {$gpu->name} ({$gpu->vendor}) added."
: "GPU {$gpu->name} ({$gpu->vendor}) updated.");
return self::SUCCESS;
}
private function deactivateGpu(): int
{
$name = $this->option('name');
if ($name === null) {
$this->error('--name is required.');
return self::FAILURE;
}
$gpu = Gpu::match($name);
if ($gpu === null) {
$this->error("GPU {$name} not found.");
return self::FAILURE;
}
$gpu->update(['active' => false]);
$this->info("GPU {$gpu->name} deactivated (historical runs keep their links).");
return self::SUCCESS;
}
private function guessVendor(string $name): string
{
$lower = strtolower($name);
return match (true) {
str_contains($lower, 'radeon') || str_contains($lower, 'amd') || str_contains($lower, 'instinct') => 'amd',
str_contains($lower, 'nvidia') || str_contains($lower, 'geforce') || str_contains($lower, 'rtx') || str_contains($lower, 'gtx') => 'nvidia',
str_contains($lower, 'intel') || str_contains($lower, 'arc') => 'intel',
default => 'other',
};
}
}