netgescon-master/_BACKUP_OLD_netgescon-laravel_INACTIVE/app/Services/DistributionService.php

359 lines
12 KiB
PHP

<?php
namespace App\Services;
use App\Models\Amministratore;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
/**
* Servizio per gestione distribuzione multi-server degli archivi amministratori
*/
class DistributionService
{
/**
* Migra un amministratore da un server all'altro
*/
public static function migrateAdministrator(Amministratore $amministratore, string $targetServerUrl): array
{
try {
Log::info("Inizio migrazione amministratore {$amministratore->codice_amministratore} verso {$targetServerUrl}");
// 1. Prepara archivio per migrazione
$migrationData = $amministratore->prepareForMigration();
if (!$migrationData['success']) {
throw new \Exception('Errore preparazione migrazione: ' . $migrationData['error']);
}
// 2. Verifica connettività server target
$targetHealth = static::checkServerHealth($targetServerUrl);
if (!$targetHealth['success']) {
throw new \Exception('Server target non raggiungibile: ' . $targetHealth['error']);
}
// 3. Trasferisce archivio al server target
$transferResult = static::transferArchive($migrationData['zip_file'], $targetServerUrl, $amministratore);
if (!$transferResult['success']) {
throw new \Exception('Errore trasferimento archivio: ' . $transferResult['error']);
}
// 4. Aggiorna configurazione amministratore
$amministratore->update([
'server_database' => parse_url($targetServerUrl, PHP_URL_HOST),
'server_port' => parse_url($targetServerUrl, PHP_URL_PORT) ?: 3306,
'url_accesso' => $targetServerUrl,
'stato_sincronizzazione' => 'migrazione',
'ultimo_backup' => now()
]);
// 5. Notifica server target per attivazione
$activationResult = static::activateOnTargetServer($targetServerUrl, $amministratore);
if ($activationResult['success']) {
$amministratore->update(['stato_sincronizzazione' => 'attivo']);
Log::info("Migrazione completata per amministratore {$amministratore->codice_amministratore}");
return [
'success' => true,
'message' => 'Migrazione completata con successo',
'new_url' => $targetServerUrl,
'transfer_id' => $transferResult['transfer_id'] ?? null
];
} else {
throw new \Exception('Errore attivazione su server target: ' . $activationResult['error']);
}
} catch (\Exception $e) {
Log::error("Errore migrazione amministratore {$amministratore->codice_amministratore}: " . $e->getMessage());
// Ripristina stato precedente
$amministratore->update(['stato_sincronizzazione' => 'errore']);
return [
'success' => false,
'error' => $e->getMessage()
];
}
}
/**
* Verifica salute e compatibilità di un server NetGesCon
*/
public static function checkServerHealth(string $serverUrl): array
{
try {
$response = Http::timeout(10)->get("{$serverUrl}/api/health");
if (!$response->successful()) {
throw new \Exception("Server risponde con codice {$response->status()}");
}
$data = $response->json();
// Verifica versione compatibile
$requiredVersion = config('app.min_version', '1.0.0');
if (version_compare($data['version'] ?? '0.0.0', $requiredVersion, '<')) {
throw new \Exception("Versione server incompatibile: {$data['version']} < {$requiredVersion}");
}
return [
'success' => true,
'server_info' => $data,
'compatible' => true
];
} catch (\Exception $e) {
return [
'success' => false,
'error' => $e->getMessage(),
'compatible' => false
];
}
}
/**
* Trasferisce archivio amministratore a server target
*/
private static function transferArchive(string $zipPath, string $targetServerUrl, Amministratore $amministratore): array
{
try {
$response = Http::timeout(300)
->attach('archive', file_get_contents($zipPath), basename($zipPath))
->post("{$targetServerUrl}/api/import-administrator", [
'codice_amministratore' => $amministratore->codice_amministratore,
'source_server' => config('app.url'),
'migration_token' => static::generateMigrationToken($amministratore)
]);
if (!$response->successful()) {
throw new \Exception("Errore HTTP {$response->status()}: " . $response->body());
}
return $response->json();
} catch (\Exception $e) {
return [
'success' => false,
'error' => $e->getMessage()
];
}
}
/**
* Attiva amministratore su server target
*/
private static function activateOnTargetServer(string $targetServerUrl, Amministratore $amministratore): array
{
try {
$response = Http::timeout(60)->post("{$targetServerUrl}/api/activate-administrator", [
'codice_amministratore' => $amministratore->codice_amministratore,
'activation_token' => static::generateMigrationToken($amministratore)
]);
if (!$response->successful()) {
throw new \Exception("Errore attivazione HTTP {$response->status()}: " . $response->body());
}
return $response->json();
} catch (\Exception $e) {
return [
'success' => false,
'error' => $e->getMessage()
];
}
}
/**
* Genera token sicuro per migrazione
*/
private static function generateMigrationToken(Amministratore $amministratore): string
{
return hash('sha256', $amministratore->codice_amministratore . $amministratore->created_at . config('app.key'));
}
/**
* Sincronizza dati tra server per amministratore distribuito
*/
public static function syncAdministratorData(Amministratore $amministratore): array
{
try {
if (!$amministratore->server_database) {
return ['success' => true, 'message' => 'Amministratore su server locale'];
}
$targetUrl = $amministratore->url_accesso;
if (!$targetUrl) {
throw new \Exception('URL server target non configurato');
}
// Verifica stato server target
$healthCheck = static::checkServerHealth($targetUrl);
if (!$healthCheck['success']) {
throw new \Exception('Server target non raggiungibile');
}
// Invia richiesta di sincronizzazione
$response = Http::timeout(30)->post("{$targetUrl}/api/sync-administrator", [
'codice_amministratore' => $amministratore->codice_amministratore,
'last_sync' => $amministratore->updated_at,
'sync_token' => static::generateMigrationToken($amministratore)
]);
if (!$response->successful()) {
throw new \Exception("Errore sincronizzazione: {$response->status()}");
}
$syncData = $response->json();
// Aggiorna timestamp ultima sincronizzazione
$amministratore->touch();
return [
'success' => true,
'synced_at' => now(),
'changes' => $syncData['changes'] ?? 0
];
} catch (\Exception $e) {
Log::error("Errore sincronizzazione amministratore {$amministratore->codice_amministratore}: " . $e->getMessage());
return [
'success' => false,
'error' => $e->getMessage()
];
}
}
/**
* Ottiene statistiche distribuzione server
*/
public static function getDistributionStats(): array
{
$stats = [
'total_administrators' => Amministratore::count(),
'local_administrators' => Amministratore::whereNull('server_database')->count(),
'distributed_administrators' => Amministratore::whereNotNull('server_database')->count(),
'servers' => [],
'status_distribution' => Amministratore::groupBy('stato_sincronizzazione')
->selectRaw('stato_sincronizzazione, count(*) as count')
->pluck('count', 'stato_sincronizzazione')
->toArray()
];
// Raggruppa per server
$serverGroups = Amministratore::whereNotNull('server_database')
->groupBy('server_database')
->selectRaw('server_database, count(*) as administrators_count')
->get();
foreach ($serverGroups as $group) {
$stats['servers'][] = [
'server' => $group->server_database,
'administrators_count' => $group->administrators_count,
'health' => 'unknown' // TODO: implementare controllo salute periodico
];
}
return $stats;
}
/**
* Routing DNS intelligente per amministratori distribuiti
*/
public static function getAdministratorAccessUrl(string $codiceAmministratore): array
{
$amministratore = Amministratore::where('codice_amministratore', $codiceAmministratore)->first();
if (!$amministratore) {
return [
'success' => false,
'error' => 'Amministratore non trovato'
];
}
// Se ha URL specifico, usalo
if ($amministratore->url_accesso) {
return [
'success' => true,
'url' => $amministratore->url_accesso,
'server_type' => 'distributed',
'server' => $amministratore->server_database
];
}
// Altrimenti è su server locale
return [
'success' => true,
'url' => config('app.url'),
'server_type' => 'local',
'server' => 'localhost'
];
}
/**
* Backup automatico distribuito
*/
public static function performDistributedBackup(Amministratore $amministratore): array
{
try {
// Backup locale
$localBackup = $amministratore->createDatabaseBackup();
if (!$localBackup['success']) {
throw new \Exception('Errore backup locale: ' . $localBackup['error']);
}
// Se distribuito, backup anche remoto
if ($amministratore->server_database && $amministratore->url_accesso) {
$remoteBackup = static::triggerRemoteBackup($amministratore);
return [
'success' => true,
'local_backup' => $localBackup,
'remote_backup' => $remoteBackup
];
}
return [
'success' => true,
'local_backup' => $localBackup,
'remote_backup' => null
];
} catch (\Exception $e) {
return [
'success' => false,
'error' => $e->getMessage()
];
}
}
/**
* Trigger backup remoto
*/
private static function triggerRemoteBackup(Amministratore $amministratore): array
{
try {
$response = Http::timeout(120)->post("{$amministratore->url_accesso}/api/backup-administrator", [
'codice_amministratore' => $amministratore->codice_amministratore,
'backup_token' => static::generateMigrationToken($amministratore)
]);
if (!$response->successful()) {
throw new \Exception("Errore backup remoto: {$response->status()}");
}
return $response->json();
} catch (\Exception $e) {
return [
'success' => false,
'error' => $e->getMessage()
];
}
}
}