133 lines
4.8 KiB
PHP
133 lines
4.8 KiB
PHP
<?php
|
||
|
||
namespace App\Console\Commands;
|
||
|
||
use App\Models\NetworkDevice;
|
||
use App\Models\NetworkHost;
|
||
use Illuminate\Console\Command;
|
||
|
||
class NetworkBackfillDevicesCommand extends Command
|
||
{
|
||
protected $signature = 'network:backfill-devices
|
||
{--dry-run : Nur anzeigen, was gemacht würde, ohne zu schreiben}';
|
||
|
||
protected $description = 'Erstellt NetworkDevice-Einträge für bestehende network_hosts ohne device_id';
|
||
|
||
public function handle(): int
|
||
{
|
||
$dryRun = $this->option('dry-run');
|
||
|
||
// Alle Hosts ohne device_id, neueste zuerst (für korrekte last_seen_at)
|
||
$hosts = NetworkHost::query()
|
||
->join('network_scans', 'network_scans.id', '=', 'network_hosts.scan_id')
|
||
->whereNull('network_hosts.device_id')
|
||
->select([
|
||
'network_hosts.*',
|
||
'network_scans.created_at as scan_time',
|
||
])
|
||
->orderByDesc('network_scans.created_at')
|
||
->get();
|
||
|
||
$this->info("Gefunden: {$hosts->count()} Hosts ohne device_id");
|
||
|
||
if ($hosts->isEmpty()) {
|
||
$this->info('Nichts zu tun.');
|
||
return Command::SUCCESS;
|
||
}
|
||
|
||
$created = 0;
|
||
$linked = 0;
|
||
|
||
foreach ($hosts as $host) {
|
||
$device = null;
|
||
|
||
// 1. Per MAC suchen/erstellen
|
||
if (!empty($host->mac_address)) {
|
||
$device = NetworkDevice::where('mac_address', $host->mac_address)->first();
|
||
|
||
if (!$device) {
|
||
if (!$dryRun) {
|
||
$device = NetworkDevice::create([
|
||
'mac_address' => $host->mac_address,
|
||
'current_ip' => $host->ip_address,
|
||
'hostname' => $host->hostname,
|
||
'mac_vendor' => $host->mac_vendor,
|
||
'status' => $host->status,
|
||
'first_seen_at' => $host->scan_time,
|
||
'last_seen_at' => $host->scan_time,
|
||
]);
|
||
$created++;
|
||
}
|
||
$this->line(" + Gerät (MAC) {$host->mac_address} / {$host->ip_address}");
|
||
}
|
||
}
|
||
|
||
// 2. Per Hostname suchen/erstellen (kein MAC)
|
||
elseif (!empty($host->hostname)) {
|
||
$device = NetworkDevice::whereNull('mac_address')
|
||
->where('hostname', $host->hostname)
|
||
->first();
|
||
|
||
if (!$device) {
|
||
if (!$dryRun) {
|
||
$device = NetworkDevice::create([
|
||
'mac_address' => null,
|
||
'current_ip' => $host->ip_address,
|
||
'hostname' => $host->hostname,
|
||
'mac_vendor' => null,
|
||
'status' => $host->status,
|
||
'first_seen_at' => $host->scan_time,
|
||
'last_seen_at' => $host->scan_time,
|
||
]);
|
||
$created++;
|
||
}
|
||
$this->line(" + Gerät (Hostname) {$host->hostname} / {$host->ip_address}");
|
||
}
|
||
}
|
||
|
||
// 3. Per IP suchen/erstellen (weder MAC noch Hostname)
|
||
else {
|
||
$device = NetworkDevice::whereNull('mac_address')
|
||
->where('current_ip', $host->ip_address)
|
||
->first();
|
||
|
||
if (!$device) {
|
||
if (!$dryRun) {
|
||
$device = NetworkDevice::create([
|
||
'mac_address' => null,
|
||
'current_ip' => $host->ip_address,
|
||
'hostname' => null,
|
||
'mac_vendor' => null,
|
||
'status' => $host->status,
|
||
'first_seen_at' => $host->scan_time,
|
||
'last_seen_at' => $host->scan_time,
|
||
]);
|
||
$created++;
|
||
}
|
||
$this->line(" + Gerät (IP) {$host->ip_address}");
|
||
}
|
||
}
|
||
|
||
// Host mit Gerät verknüpfen
|
||
if ($device && !$dryRun) {
|
||
$host->update(['device_id' => $device->id]);
|
||
|
||
// Älteste first_seen_at beibehalten
|
||
if ($host->scan_time < $device->first_seen_at) {
|
||
$device->update(['first_seen_at' => $host->scan_time]);
|
||
}
|
||
|
||
$linked++;
|
||
}
|
||
}
|
||
|
||
if ($dryRun) {
|
||
$this->warn('Dry-Run – keine Änderungen geschrieben.');
|
||
} else {
|
||
$this->info("✓ Fertig: {$created} Geräte neu erstellt, {$linked} Hosts verknüpft.");
|
||
}
|
||
|
||
return Command::SUCCESS;
|
||
}
|
||
}
|