210 lines
7.2 KiB
JavaScript
210 lines
7.2 KiB
JavaScript
const axios = require('axios');
|
|
const { getConfig } = require('./database');
|
|
|
|
let isMonitoring = false;
|
|
let checkInterval = null;
|
|
let isRebooting = false;
|
|
let reconnectCallback = null; // Callback pour resync le WebSocket
|
|
|
|
const CHECK_INTERVAL_MS = 60 * 1000; // Vérifier toutes les 60 secondes
|
|
|
|
/**
|
|
* Vérifie l'utilisation actuelle de la RAM du serveur
|
|
*/
|
|
const checkRAMUsage = async () => {
|
|
try {
|
|
const response = await axios.get(
|
|
`${process.env.PTERODACTYL_API_URL}/api/client/servers/${process.env.PTERODACTYL_SERVER_ID}/resources`,
|
|
{
|
|
headers: {
|
|
'Accept': 'application/json',
|
|
'Content-Type': 'application/json',
|
|
'Authorization': `Bearer ${process.env.PTERODACTYL_API_TOKEN}`
|
|
}
|
|
}
|
|
);
|
|
|
|
const resources = response.data.attributes.resources;
|
|
const ramUsedMB = resources.memory_bytes / (1024 * 1024); // Convertir en MB
|
|
const ramUsedGB = (ramUsedMB / 1024).toFixed(2); // Convertir en GB pour l'affichage
|
|
const currentState = response.data.attributes.current_state;
|
|
|
|
console.log(`🔍 [RAM Monitor] Utilisation RAM: ${ramUsedGB} Go / État: ${currentState}`);
|
|
|
|
// Récupérer la configuration depuis la base de données
|
|
const autoRebootEnabled = (await getConfig('auto_reboot_enabled')) === 'true';
|
|
const ramThresholdGB = parseInt(await getConfig('ram_threshold_gb')) || 19;
|
|
const RAM_THRESHOLD_MB = ramThresholdGB * 1024;
|
|
|
|
// Vérifier si on dépasse le seuil ET que le serveur est en cours d'exécution ET que l'auto-reboot est activé
|
|
if (autoRebootEnabled && ramUsedMB > RAM_THRESHOLD_MB && currentState === 'running' && !isRebooting) {
|
|
console.log(`⚠️ [RAM Monitor] SEUIL DÉPASSÉ ! ${ramUsedGB} Go > ${ramThresholdGB} Go`);
|
|
console.log(`🔄 [RAM Monitor] Déclenchement du redémarrage automatique...`);
|
|
|
|
await rebootServer();
|
|
} else if (!autoRebootEnabled && ramUsedMB > RAM_THRESHOLD_MB) {
|
|
console.log(`⚠️ [RAM Monitor] Seuil dépassé mais auto-reboot désactivé (${ramUsedGB} Go > ${ramThresholdGB} Go)`);
|
|
}
|
|
|
|
return { ramUsedMB, ramUsedGB, currentState };
|
|
} catch (error) {
|
|
console.error('❌ [RAM Monitor] Erreur lors de la vérification RAM:', error.message);
|
|
return null;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Redémarre le serveur automatiquement
|
|
*/
|
|
const rebootServer = async () => {
|
|
if (isRebooting) {
|
|
console.log('⚠️ [RAM Monitor] Redémarrage déjà en cours, annulation...');
|
|
return;
|
|
}
|
|
|
|
isRebooting = true;
|
|
|
|
try {
|
|
const headers = {
|
|
'Accept': 'application/json',
|
|
'Content-Type': 'application/json',
|
|
'Authorization': `Bearer ${process.env.PTERODACTYL_API_TOKEN}`
|
|
};
|
|
|
|
const serverUrl = `${process.env.PTERODACTYL_API_URL}/api/client/servers/${process.env.PTERODACTYL_SERVER_ID}`;
|
|
|
|
console.log('💾 [RAM Monitor] Sauvegarde du serveur...');
|
|
await axios.post(`${serverUrl}/command`, {
|
|
command: 'save'
|
|
}, { headers });
|
|
|
|
// Annoncer le redémarrage aux joueurs
|
|
console.log('📢 [RAM Monitor] Annonce du redémarrage...');
|
|
await axios.post(`${serverUrl}/command`, {
|
|
command: "broadcast 'Redémarrage automatique (RAM élevée - 60 secondes)'"
|
|
}, { headers });
|
|
|
|
// Attendre la sauvegarde
|
|
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
|
|
console.log('⏹️ [RAM Monitor] Arrêt du serveur...');
|
|
await axios.post(`${serverUrl}/power`, {
|
|
signal: 'stop'
|
|
}, { headers });
|
|
|
|
// Attendre 60 secondes
|
|
console.log('⏳ [RAM Monitor] Attente de 60 secondes...');
|
|
await new Promise(resolve => setTimeout(resolve, 60000));
|
|
|
|
console.log('🚀 [RAM Monitor] Redémarrage du serveur...');
|
|
await axios.post(`${serverUrl}/power`, {
|
|
signal: 'start'
|
|
}, { headers });
|
|
|
|
// Attendre que le serveur soit opérationnel
|
|
let isRunning = false;
|
|
let attempts = 0;
|
|
const maxAttempts = 30; // 30 tentatives * 5 secondes = 2.5 minutes max
|
|
|
|
while (!isRunning && attempts < maxAttempts) {
|
|
attempts++;
|
|
await new Promise(resolve => setTimeout(resolve, 5000));
|
|
|
|
try {
|
|
const checkResponse = await axios.get(`${serverUrl}/resources`, { headers });
|
|
const state = checkResponse.data.attributes.current_state;
|
|
|
|
if (state === 'running') {
|
|
isRunning = true;
|
|
console.log('✅ [RAM Monitor] Serveur redémarré avec succès !');
|
|
|
|
// Resynchroniser le WebSocket si un callback est défini
|
|
if (reconnectCallback) {
|
|
console.log('🔄 [RAM Monitor] Resynchronisation du WebSocket...');
|
|
await new Promise(resolve => setTimeout(resolve, 5000)); // Attendre 5s de plus
|
|
reconnectCallback();
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error(`❌ [RAM Monitor] Tentative ${attempts}/${maxAttempts} échouée:`, error.message);
|
|
}
|
|
}
|
|
|
|
if (!isRunning) {
|
|
console.error('❌ [RAM Monitor] Le serveur n\'a pas redémarré après le délai maximum');
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error('❌ [RAM Monitor] Erreur lors du redémarrage:', error.message);
|
|
} finally {
|
|
isRebooting = false;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Démarre la surveillance de la RAM
|
|
*/
|
|
const startRAMMonitoring = async (websocketReconnectCallback = null) => {
|
|
if (isMonitoring) {
|
|
console.log('⚠️ [RAM Monitor] Surveillance déjà active');
|
|
return;
|
|
}
|
|
|
|
reconnectCallback = websocketReconnectCallback;
|
|
|
|
const ramThresholdGB = parseInt(await getConfig('ram_threshold_gb')) || 19;
|
|
|
|
console.log(`🚀 [RAM Monitor] Démarrage de la surveillance RAM (seuil: ${ramThresholdGB} Go)`);
|
|
console.log(`⏱️ [RAM Monitor] Intervalle de vérification: ${CHECK_INTERVAL_MS / 1000}s`);
|
|
|
|
isMonitoring = true;
|
|
|
|
// Première vérification immédiate
|
|
checkRAMUsage();
|
|
|
|
// Vérifications périodiques
|
|
checkInterval = setInterval(async () => {
|
|
if (!isRebooting) {
|
|
await checkRAMUsage();
|
|
}
|
|
}, CHECK_INTERVAL_MS);
|
|
};
|
|
|
|
/**
|
|
* Arrête la surveillance de la RAM
|
|
*/
|
|
const stopRAMMonitoring = () => {
|
|
if (!isMonitoring) {
|
|
console.log('⚠️ [RAM Monitor] Surveillance déjà inactive');
|
|
return;
|
|
}
|
|
|
|
console.log('⏹️ [RAM Monitor] Arrêt de la surveillance RAM');
|
|
isMonitoring = false;
|
|
|
|
if (checkInterval) {
|
|
clearInterval(checkInterval);
|
|
checkInterval = null;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Obtenir le statut de la surveillance
|
|
*/
|
|
const getMonitoringStatus = async () => {
|
|
const ramThresholdGB = parseInt(await getConfig('ram_threshold_gb')) || 19;
|
|
return {
|
|
isMonitoring,
|
|
isRebooting,
|
|
threshold: ramThresholdGB * 1024, // En MB
|
|
checkInterval: CHECK_INTERVAL_MS
|
|
};
|
|
};
|
|
|
|
module.exports = {
|
|
startRAMMonitoring,
|
|
stopRAMMonitoring,
|
|
checkRAMUsage,
|
|
getMonitoringStatus
|
|
};
|