Proxxgers + ZBX hosts Sync

This commit is contained in:
JonatanRek 2024-08-16 18:20:45 +02:00
parent 84ef42382a
commit 2f4f917032
15 changed files with 261 additions and 9 deletions

View File

@ -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();
}
}

View File

@ -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);
}

View File

@ -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();

View File

@ -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',
];
}

View File

@ -11,6 +11,7 @@ class Host extends Model
protected $fillable = [
'hostname',
'display_name',
];
public function tasks()

View File

@ -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);

View File

@ -0,0 +1,18 @@
<?php
namespace App\Observers;
use App\Models\MaintenanceHistory;
class MaintenanceHistoryObserver
{
public function creating(MaintenanceHistory $maintenanceHistory): void
{
$maintenanceHistory->hash = md5($maintenanceHistory->maintenance_id . $maintenanceHistory->start_at);
}
public function updating(MaintenanceHistory $maintenanceHistory): void
{
$maintenanceHistory->hash = md5($maintenanceHistory->maintenance_id . $maintenanceHistory->start_at);
}
}

View File

@ -0,0 +1,130 @@
<?php
namespace App\Services;
use Exception;
use Illuminate\Support\Facades\Http;
class ZabbixService
{
public string $token = "";
public string $url = "";
public int $id = 1;
function __construct($url) {
$this->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"]);
}
}

View File

@ -0,0 +1,25 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('maintenance_histories', function (Blueprint $table) {
$table->string('hash');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
}
};

View File

@ -0,0 +1,25 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('hosts', function (Blueprint $table) {
$table->string('display_name')->nullable();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
}
};

View File

@ -3,9 +3,16 @@
<div class="page-header">
<h1>{{ __('boilerplate::hosts.title') }}</h1>
<button class="btn btn-primary" onclick="Livewire.dispatch('openModal', {livewireComponents: 'host.form', title: '{{ __('boilerplate::host.create') }}'})">
<i class="me-2 fas fa-plus"></i><span>{{ __('boilerplate::ui.add') }}</span>
</button>
<div>
<a class="btn btn-primary" href="{{ route('host.sync') }}">
<i class="me-2 fas fa-sync-alt"></i><span>{{ __('boilerplate::ui.sync') }}</span>
</a>
<button class="btn btn-primary"
onclick="Livewire.dispatch('openModal', {livewireComponents: 'host.form', title: '{{ __('boilerplate::host.create') }}'})">
<i class="me-2 fas fa-plus"></i><span>{{ __('boilerplate::ui.add') }}</span>
</button>
</div>
</div>
@livewire('host.data-table', [], key('data-table'))

View File

@ -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');

View File

@ -1,3 +0,0 @@
*
!public/
!.gitignore

View File

@ -1,2 +0,0 @@
*
!.gitignore

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB