diff --git a/app/Http/Controllers/HostController.php b/app/Http/Controllers/HostController.php index 3bff2ef..4a640a9 100644 --- a/app/Http/Controllers/HostController.php +++ b/app/Http/Controllers/HostController.php @@ -2,10 +2,35 @@ namespace App\Http\Controllers; +use App\Models\Host; +use App\Services\ZabbixService; +use Carbon\Carbon; + class HostController extends BaseController { public function index() { return view('hosts.index'); } + + public function sync() + { + $zabbix = new ZabbixService("https://zabbix.itego.cz"); + $zabbix->connect("spaninger", "*"); + + foreach ( $zabbix->maintenances([ "selectTimeperiods" => "extend" ]) as $maintennace ) { + if(!Carbon::createFromTimestamp($maintennace['active_till'])->isPast()){ + dd(Carbon::createFromTimestamp($maintennace['active_till'])); + } + } + + foreach ($zabbix->hosts() as $host) { + Host::updateOrCreate([ + "hostname" => $host['host'], + ], [ + "display_name" => $host['name'], + ]); + } + return redirect()->back(); + } } diff --git a/app/Http/Controllers/MaintenanceController.php b/app/Http/Controllers/MaintenanceController.php index 6dd41da..304b9a8 100644 --- a/app/Http/Controllers/MaintenanceController.php +++ b/app/Http/Controllers/MaintenanceController.php @@ -3,6 +3,7 @@ namespace App\Http\Controllers; use App\Models\MaintenanceHistory; +use App\Services\ZabbixService; use Carbon\Carbon; use Illuminate\Http\Request; @@ -31,6 +32,7 @@ class MaintenanceController extends BaseController public function plannedDetailPut(Request $request, MaintenanceHistory $maintenance_history) { + if (!empty($maintenance_history->finished_at)) { abort(404); } diff --git a/app/Jobs/ScheduleNextMaintenance.php b/app/Jobs/ScheduleNextMaintenance.php index abf36b5..7f9b220 100644 --- a/app/Jobs/ScheduleNextMaintenance.php +++ b/app/Jobs/ScheduleNextMaintenance.php @@ -34,8 +34,14 @@ class ScheduleNextMaintenance implements ShouldQueue $maintenances = Maintenance::all(); foreach ($maintenances as $maintenance) { $cron = new CronCronExpression($maintenance->schedule); + $nextRunTime = Carbon::createFromTimestamp($cron->getNext()); + + if(MaintenanceHistory::where('hash', md5($maintenance->id . $nextRunTime))->first() === null){ + continue; + }; + $maintenancePlanned = $maintenance->history()->create([ - 'start_at' => Carbon::createFromTimestamp($cron->getNext()), + 'start_at' => $nextRunTime, 'guestor_id' => $maintenance->guestor_id, ]); $maintenancePlanned->refresh(); diff --git a/app/Livewire/Host/DataTable.php b/app/Livewire/Host/DataTable.php index 21cfdca..ce9020d 100644 --- a/app/Livewire/Host/DataTable.php +++ b/app/Livewire/Host/DataTable.php @@ -2,6 +2,7 @@ namespace App\Livewire\Host; use App\Models\Host; +use App\Services\ZabbixService; use SteelAnts\DataTable\Livewire\DataTableComponent; use Illuminate\Database\Eloquent\Builder; @@ -12,6 +13,9 @@ class DataTable extends DataTableComponent 'closeModal' => '$refresh', ]; + public bool $searchable = true; + public array $searchableColumns = ['display_name', 'hostname']; + public function query(): Builder { return Host::query(); @@ -20,6 +24,7 @@ class DataTable extends DataTableComponent public function headers(): array { return [ + 'display_name' => 'display_name', 'hostname' => 'hostname', ]; } diff --git a/app/Models/Host.php b/app/Models/Host.php index 0cc252c..ec3ea44 100644 --- a/app/Models/Host.php +++ b/app/Models/Host.php @@ -11,6 +11,7 @@ class Host extends Model protected $fillable = [ 'hostname', + 'display_name', ]; public function tasks() diff --git a/app/Models/MaintenanceHistory.php b/app/Models/MaintenanceHistory.php index 1f3e5bc..a756349 100644 --- a/app/Models/MaintenanceHistory.php +++ b/app/Models/MaintenanceHistory.php @@ -2,6 +2,7 @@ namespace App\Models; +use App\Observers\MaintenanceHistoryObserver; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; @@ -16,6 +17,12 @@ class MaintenanceHistory extends Model 'guestor_id', ]; + + protected static function booted() + { + MaintenanceHistory::observe(MaintenanceHistoryObserver::class); + } + public function maintenance() { return $this->BelongsTo(Maintenance::class); diff --git a/app/Observers/MaintenanceHistoryObserver.php b/app/Observers/MaintenanceHistoryObserver.php new file mode 100644 index 0000000..6d7a8a7 --- /dev/null +++ b/app/Observers/MaintenanceHistoryObserver.php @@ -0,0 +1,18 @@ +hash = md5($maintenanceHistory->maintenance_id . $maintenanceHistory->start_at); + } + + public function updating(MaintenanceHistory $maintenanceHistory): void + { + $maintenanceHistory->hash = md5($maintenanceHistory->maintenance_id . $maintenanceHistory->start_at); + } +} diff --git a/app/Services/ZabbixService.php b/app/Services/ZabbixService.php new file mode 100644 index 0000000..10ca353 --- /dev/null +++ b/app/Services/ZabbixService.php @@ -0,0 +1,130 @@ +url = $url; + } + + public function connect( $username, $password) + { + $response = Http::withoutVerifying()->post($this->url . "/api_jsonrpc.php", [ + "jsonrpc" => "2.0", + "method" => "user.login", + "params" => [ + "username" => $username, + "password" => $password, + ], + "id" => $this->id, + "auth" => null, + ]); + + if (!$response->successful()) { + throw new Exception("Unable To Authenticated", 1); + } + + $responseObject = $response->json(); + if (isset($responseObject['error'])) { + throw new Exception($responseObject['error']['data'], $responseObject['error']['code']); + } + + $this->token = $response['result']; + $this->id++; + } + + public function hosts($params = []) + { + if (empty($this->token)) { + throw new Exception("you need to connect first", 1); + } + + $response = Http::withoutVerifying()->post($this->url . "/api_jsonrpc.php", [ + "jsonrpc" => "2.0", + "method" => "host.get", + "params" => $params, + "id" => $this->id, + "auth" => $this->token, + ]); + + if (!$response->successful()) { + throw new Exception("Unable To Request", 1); + } + + $responseObject = $response->json(); + if (isset($responseObject['error'])) { + throw new Exception($responseObject['error']['data'], $responseObject['error']['code']); + } + + $this->id++; + return collect($responseObject["result"]); + } + + public function hostGroups($params = []) + { + if (empty($this->token)) { + throw new Exception("you need to connect first", 1); + } + + $response = Http::withoutVerifying()->post($this->url . "/api_jsonrpc.php", [ + "jsonrpc" => "2.0", + "method" => "hostgroup.get", + "params" => $params, + "id" => $this->id, + "auth" => $this->token, + ]); + + if (!$response->successful()) { + throw new Exception("Unable To Request", 1); + } + + $responseObject = $response->json(); + if (isset($responseObject['error'])) { + throw new Exception($responseObject['error']['data'], $responseObject['error']['code']); + } + + $this->id++; + return collect($responseObject["result"]); + } + + public function maintenances($params = []){ + return $this->request( [ + "jsonrpc" => "2.0", + "method" => "maintenance.get", + "params" => $params, + "id" => $this->id, + "auth" => $this->token, + ]); + } + + + /*Helpers*/ + + private function request($body = []){ + if (empty($this->token)) { + throw new Exception("you need to connect first", 1); + } + + $response = Http::withoutVerifying()->post($this->url . "/api_jsonrpc.php", $body); + + if (!$response->successful()) { + throw new Exception("Unable To Request", 1); + } + + $responseObject = $response->json(); + if (isset($responseObject['error'])) { + throw new Exception($responseObject['error']['data'], $responseObject['error']['code']); + } + + $this->id++; + return collect($responseObject["result"]); + } +} diff --git a/database/migrations/2024_08_16_150626_add_control_hash_to_maintenance_history_table.php b/database/migrations/2024_08_16_150626_add_control_hash_to_maintenance_history_table.php new file mode 100644 index 0000000..32ba382 --- /dev/null +++ b/database/migrations/2024_08_16_150626_add_control_hash_to_maintenance_history_table.php @@ -0,0 +1,25 @@ +string('hash'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + } +}; diff --git a/database/migrations/2024_08_16_154630_add_display_name_to_host_table.php b/database/migrations/2024_08_16_154630_add_display_name_to_host_table.php new file mode 100644 index 0000000..d835ae0 --- /dev/null +++ b/database/migrations/2024_08_16_154630_add_display_name_to_host_table.php @@ -0,0 +1,25 @@ +string('display_name')->nullable(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + } +}; diff --git a/resources/views/hosts/index.blade.php b/resources/views/hosts/index.blade.php index 99697d7..2bbc847 100644 --- a/resources/views/hosts/index.blade.php +++ b/resources/views/hosts/index.blade.php @@ -3,9 +3,16 @@ @livewire('host.data-table', [], key('data-table')) diff --git a/routes/web.php b/routes/web.php index 880473b..b1b376c 100644 --- a/routes/web.php +++ b/routes/web.php @@ -3,6 +3,9 @@ use Illuminate\Support\Facades\Route; Route::auth(); +Route::get('/', function () { + return redirect()->route('login'); +}); Route::get('/maintenance/planned', [App\Http\Controllers\MaintenanceController::class, 'planned'])->name('maintenance.planned'); Route::get('/maintenance/planned/{maintenance_history}', [App\Http\Controllers\MaintenanceController::class, 'plannedDetail'])->name('maintenance.planned.detail'); @@ -13,6 +16,9 @@ Route::get('/maintenance/history/{maintenance_history}', [App\Http\Controllers\M Route::get('/host', [App\Http\Controllers\HostController::class, 'index'])->name('host'); +Route::get('/host/sync', [App\Http\Controllers\HostController::class, 'sync'])->name('host.sync'); + + Route::get('/maintenance', [App\Http\Controllers\MaintenanceController::class, 'index'])->name('maintenance'); Route::get('/tasks', [App\Http\Controllers\TaskController::class, 'index'])->name('tasks'); diff --git a/storage/app/.gitignore b/storage/app/.gitignore deleted file mode 100644 index 8f4803c..0000000 --- a/storage/app/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -* -!public/ -!.gitignore diff --git a/storage/app/public/.gitignore b/storage/app/public/.gitignore deleted file mode 100644 index d6b7ef3..0000000 --- a/storage/app/public/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore diff --git a/storage/app/public/images/logo.png b/storage/app/public/images/logo.png new file mode 100644 index 0000000..6149f0d Binary files /dev/null and b/storage/app/public/images/logo.png differ