2013-10-10 18:02:21 +02:00
|
|
|
package mineplex.servermonitor;
|
|
|
|
|
2014-02-18 09:40:41 +01:00
|
|
|
import java.io.BufferedReader;
|
2014-04-27 08:26:56 +02:00
|
|
|
import java.io.File;
|
2014-02-18 09:40:41 +01:00
|
|
|
import java.io.InputStreamReader;
|
2014-04-27 08:26:56 +02:00
|
|
|
import java.util.AbstractMap;
|
2013-11-05 19:19:04 +01:00
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.Collection;
|
2013-11-06 10:03:02 +01:00
|
|
|
import java.util.Collections;
|
2013-11-05 19:19:04 +01:00
|
|
|
import java.util.HashMap;
|
2014-01-08 21:18:52 +01:00
|
|
|
import java.util.HashSet;
|
|
|
|
import java.util.Iterator;
|
2013-11-02 08:56:31 +01:00
|
|
|
import java.util.List;
|
2014-04-27 08:26:56 +02:00
|
|
|
import java.util.Map.Entry;
|
2013-10-10 18:02:21 +02:00
|
|
|
|
|
|
|
public class ServerMonitor
|
|
|
|
{
|
2014-07-01 19:23:22 +02:00
|
|
|
private static boolean _us = true;
|
2013-10-10 18:02:21 +02:00
|
|
|
private static Repository _repository = new Repository();
|
2013-10-15 23:19:14 +02:00
|
|
|
private static int _count = 0;
|
2014-01-08 21:18:52 +01:00
|
|
|
private static HashSet<ProcessRunner> _processes = new HashSet<ProcessRunner>();
|
2014-02-18 09:40:41 +01:00
|
|
|
private static HashMap<String, Boolean> _badServers = new HashMap<String, Boolean>();
|
2013-10-10 18:02:21 +02:00
|
|
|
|
|
|
|
public static void main (String args[])
|
2014-04-27 08:26:56 +02:00
|
|
|
{
|
2014-07-01 19:23:22 +02:00
|
|
|
_us = !new File("eu.dat").exists();
|
2014-04-27 08:26:56 +02:00
|
|
|
|
2014-07-01 19:23:22 +02:00
|
|
|
_repository.initialize(_us);
|
2014-04-27 08:26:56 +02:00
|
|
|
HashMap<String, Entry<String, Long>> serverTracker = new HashMap<String, Entry<String, Long>>();
|
2013-10-10 18:02:21 +02:00
|
|
|
|
|
|
|
while (true)
|
2014-04-27 08:26:56 +02:00
|
|
|
{
|
|
|
|
Collection<ServerGroupData> serverGroups = _repository.retrieveServerGroups();
|
|
|
|
HashMap<String, GroupStatusData> groupStatusList = _repository.retrieveGroupStatusData();
|
|
|
|
|
2014-01-08 21:18:52 +01:00
|
|
|
for (ServerStatusData statusData : _repository.retrieveOldServerStatuses())
|
|
|
|
{
|
2014-07-01 19:23:22 +02:00
|
|
|
/*
|
2014-04-27 08:26:56 +02:00
|
|
|
if (us)
|
|
|
|
{
|
|
|
|
if (!serverTracker.containsKey(statusData.Name))
|
|
|
|
{
|
|
|
|
restartServer(statusData);
|
|
|
|
serverTracker.put(statusData.Name, new AbstractMap.SimpleEntry<String, Long>(statusData.Address, System.currentTimeMillis()));
|
|
|
|
}
|
|
|
|
else if (System.currentTimeMillis() - serverTracker.get(statusData.Name).getValue() > 15000)
|
2014-02-18 09:40:41 +01:00
|
|
|
{
|
2014-04-27 08:26:56 +02:00
|
|
|
serverTracker.remove(statusData.Name);
|
|
|
|
System.out.println("-=[SERVER RESTART TOO SLOW]=- " + statusData.Name + " (Putting back in restart queue)");
|
2014-02-18 09:40:41 +01:00
|
|
|
}
|
|
|
|
}
|
2014-04-27 08:26:56 +02:00
|
|
|
else
|
2014-07-01 19:23:22 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
killServer(statusData);
|
2014-02-18 09:40:41 +01:00
|
|
|
}
|
|
|
|
|
2014-07-01 19:23:22 +02:00
|
|
|
/*
|
2014-04-27 08:26:56 +02:00
|
|
|
if (us)
|
2014-02-18 09:40:41 +01:00
|
|
|
{
|
2014-04-27 08:26:56 +02:00
|
|
|
// Remove successfully restarted US servers
|
|
|
|
for (GroupStatusData groupStatus : groupStatusList.values())
|
2014-03-29 06:32:24 +01:00
|
|
|
{
|
2014-04-27 08:26:56 +02:00
|
|
|
for (ServerStatusData serverToKill : groupStatus.Servers.values())
|
|
|
|
{
|
|
|
|
if (serverTracker.containsKey(serverToKill.Name))
|
|
|
|
serverTracker.remove(serverToKill.Name);
|
|
|
|
}
|
2014-03-29 06:32:24 +01:00
|
|
|
}
|
|
|
|
}
|
2014-04-27 08:26:56 +02:00
|
|
|
else
|
2014-01-08 21:18:52 +01:00
|
|
|
{
|
2014-07-01 19:23:22 +02:00
|
|
|
*/
|
2014-04-27 08:26:56 +02:00
|
|
|
List<DynamicServerData> dynamicServers = new ArrayList<DynamicServerData>(_repository.retrieveDynamicServers());
|
|
|
|
|
|
|
|
if (_count % 15 == 0)
|
|
|
|
{
|
|
|
|
_badServers.clear();
|
|
|
|
|
|
|
|
for (DynamicServerData serverData : dynamicServers)
|
|
|
|
{
|
|
|
|
if (isServerOffline(serverData))
|
|
|
|
{
|
|
|
|
System.out.println("------=[OFFLINE]=------=[" + serverData.Name + ":" + serverData.Address + "]=------=[OFFLINE]=------");
|
|
|
|
_badServers.put(serverData.Name, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
System.out.println(_badServers.size() + " bad servers.");
|
2014-01-08 21:18:52 +01:00
|
|
|
}
|
|
|
|
|
2014-04-27 08:26:56 +02:00
|
|
|
for (Iterator<DynamicServerData> iterator = dynamicServers.iterator(); iterator.hasNext();)
|
2014-01-08 21:18:52 +01:00
|
|
|
{
|
2014-04-27 08:26:56 +02:00
|
|
|
DynamicServerData serverData = iterator.next();
|
2013-11-08 19:52:56 +01:00
|
|
|
|
2014-04-27 08:26:56 +02:00
|
|
|
if (_badServers.containsKey(serverData.Name))
|
|
|
|
iterator.remove();
|
|
|
|
}
|
|
|
|
|
|
|
|
for (GroupStatusData groupStatus : groupStatusList.values())
|
|
|
|
{
|
|
|
|
for (ServerStatusData serverToKill : groupStatus.KillServers)
|
2013-11-06 10:03:02 +01:00
|
|
|
{
|
2014-04-27 08:26:56 +02:00
|
|
|
System.out.println("----DUPLICATE SERVER----> " + serverToKill.Address + ", " + serverToKill.Name);
|
|
|
|
killServer(serverToKill);
|
2013-11-06 10:03:02 +01:00
|
|
|
}
|
2014-02-18 09:40:41 +01:00
|
|
|
|
2014-04-27 08:26:56 +02:00
|
|
|
for (ServerStatusData serverToKill : groupStatus.Servers.values())
|
|
|
|
{
|
|
|
|
if (serverTracker.containsKey(serverToKill.Name))
|
|
|
|
serverTracker.remove(serverToKill.Name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (Iterator<Entry<String, Entry<String, Long>>> iterator = serverTracker.entrySet().iterator(); iterator.hasNext();)
|
|
|
|
{
|
|
|
|
Entry<String, Entry<String, Long>> entry = iterator.next();
|
|
|
|
|
|
|
|
if (System.currentTimeMillis() - entry.getValue().getValue() > 15000)
|
|
|
|
{
|
|
|
|
System.out.println("-=[SERVER STARTUP TOO SLOW]=- " + entry.getKey());
|
|
|
|
|
|
|
|
ServerStatusData serverToKill = new ServerStatusData();
|
|
|
|
serverToKill.Name = entry.getKey();
|
|
|
|
serverToKill.Address = entry.getValue().getKey();
|
|
|
|
|
|
|
|
killServer(serverToKill);
|
|
|
|
iterator.remove();
|
|
|
|
}
|
2014-01-08 21:18:52 +01:00
|
|
|
}
|
|
|
|
|
2014-04-27 08:26:56 +02:00
|
|
|
for (ServerGroupData serverGroup : serverGroups)
|
2014-01-08 21:18:52 +01:00
|
|
|
{
|
2014-04-27 08:26:56 +02:00
|
|
|
if (!groupStatusList.containsKey(serverGroup.Name))
|
|
|
|
{
|
|
|
|
groupStatusList.put(serverGroup.Name, new GroupStatusData());
|
|
|
|
}
|
|
|
|
|
|
|
|
GroupStatusData groupStatus = groupStatusList.get(serverGroup.Name);
|
|
|
|
|
|
|
|
int serversToAdd = Math.max(serverGroup.RequiredTotalServers - groupStatus.getTotalServers(), serverGroup.RequiredJoinableServers - groupStatus.getJoinableCount());
|
|
|
|
int serversToKill = (groupStatus.getTotalServers() > serverGroup.RequiredTotalServers && groupStatus.getJoinableCount() > serverGroup.RequiredJoinableServers) ? Math.min(groupStatus.getJoinableCount() - serverGroup.RequiredJoinableServers, groupStatus.EmptyServers.size()) : 0;
|
|
|
|
|
|
|
|
while (serversToAdd > 0)
|
|
|
|
{
|
|
|
|
int serverNum = groupStatus.getNextServerNumber();
|
|
|
|
Collections.sort(dynamicServers, new DynamicServerSorter());
|
|
|
|
DynamicServerData bestServer = getBestDynamicServer(dynamicServers, serverGroup);
|
|
|
|
|
|
|
|
if (bestServer == null)
|
|
|
|
{
|
|
|
|
System.out.println("No best dynamic server available for group " + serverGroup.Name);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (serverTracker.containsKey(serverGroup.Prefix + "-" + serverNum))
|
|
|
|
System.out.println("[WAITING] On " + serverGroup.Prefix + "-" + serverNum + " to finish starting...");
|
|
|
|
else
|
|
|
|
{
|
|
|
|
startServer(bestServer, serverGroup, serverNum);
|
|
|
|
serverTracker.put(serverGroup.Prefix + "-" + serverNum, new AbstractMap.SimpleEntry<String, Long>(bestServer.Address, System.currentTimeMillis()));
|
|
|
|
}
|
|
|
|
|
|
|
|
serversToAdd--;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (serversToKill > 0)
|
|
|
|
{
|
|
|
|
System.out.println("[" + groupStatus.EmptyServers.get(0).Name + ":" + groupStatus.EmptyServers.get(0).Address + "] Killing " + serverGroup.Name + " Req Total: " + serverGroup.RequiredTotalServers + " Req Joinable: " + serverGroup.RequiredJoinableServers + " | Actual Total: " + groupStatus.getTotalServers() + " Actual Joinable: " + groupStatus.getJoinableCount());
|
|
|
|
killServer(groupStatus.EmptyServers.remove(0));
|
|
|
|
serversToKill--;
|
|
|
|
}
|
2013-11-06 10:03:02 +01:00
|
|
|
}
|
2014-07-01 19:23:22 +02:00
|
|
|
//}
|
2014-03-03 21:47:57 +01:00
|
|
|
|
2014-02-18 09:40:41 +01:00
|
|
|
int processWaits = 0;
|
|
|
|
|
2014-02-14 20:39:24 +01:00
|
|
|
while (_processes.size() > 0)
|
|
|
|
{
|
|
|
|
for (Iterator<ProcessRunner> iterator = _processes.iterator(); iterator.hasNext();)
|
|
|
|
{
|
|
|
|
ProcessRunner pr = iterator.next();
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
pr.join(100);
|
|
|
|
}
|
|
|
|
catch (InterruptedException e)
|
|
|
|
{
|
|
|
|
e.printStackTrace();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pr.isDone())
|
|
|
|
iterator.remove();
|
|
|
|
}
|
|
|
|
|
2014-02-18 09:40:41 +01:00
|
|
|
if (_processes.size() > 0)
|
2014-02-14 20:39:24 +01:00
|
|
|
{
|
2014-02-18 09:40:41 +01:00
|
|
|
try
|
|
|
|
{
|
|
|
|
System.out.println("Sleeping while processes run...");
|
|
|
|
Thread.sleep(6000);
|
|
|
|
}
|
|
|
|
catch (InterruptedException e)
|
|
|
|
{
|
|
|
|
e.printStackTrace();
|
|
|
|
}
|
2014-02-14 20:39:24 +01:00
|
|
|
}
|
|
|
|
|
2014-02-18 09:40:41 +01:00
|
|
|
if (processWaits >= 10)
|
2014-02-14 20:39:24 +01:00
|
|
|
{
|
|
|
|
System.out.println("Killing stale processes.");
|
|
|
|
|
|
|
|
for (Iterator<ProcessRunner> iterator = _processes.iterator(); iterator.hasNext();)
|
|
|
|
{
|
|
|
|
iterator.next().abort();
|
|
|
|
iterator.remove();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-18 09:40:41 +01:00
|
|
|
processWaits++;
|
2014-02-14 20:39:24 +01:00
|
|
|
}
|
2014-03-03 21:47:57 +01:00
|
|
|
|
2014-02-18 09:40:41 +01:00
|
|
|
processWaits = 0;
|
2014-02-14 20:39:24 +01:00
|
|
|
|
2013-10-10 18:02:21 +02:00
|
|
|
try
|
|
|
|
{
|
2014-01-08 21:18:52 +01:00
|
|
|
System.out.println("Natural sleep.");
|
2014-04-26 18:21:51 +02:00
|
|
|
Thread.sleep(10000);
|
2013-10-10 18:02:21 +02:00
|
|
|
}
|
|
|
|
catch (InterruptedException e)
|
|
|
|
{
|
|
|
|
e.printStackTrace();
|
|
|
|
}
|
2014-02-18 09:40:41 +01:00
|
|
|
|
|
|
|
_count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private static void killServer(final ServerStatusData serverToKill, final boolean announce)
|
|
|
|
{
|
|
|
|
String cmd = "/home/mineplex/easyRemoteKillServer.sh";
|
|
|
|
|
|
|
|
ProcessRunner pr = new ProcessRunner(new String[] {"/bin/sh", cmd, serverToKill.Address, serverToKill.Name});
|
|
|
|
pr.start(new GenericRunnable<Boolean>()
|
|
|
|
{
|
|
|
|
public void run(Boolean error)
|
|
|
|
{
|
|
|
|
if (!error)
|
|
|
|
_repository.removeServerRecord(serverToKill);
|
|
|
|
|
|
|
|
if (announce)
|
|
|
|
{
|
|
|
|
if (error)
|
|
|
|
System.out.println("[" + serverToKill.Name + ":" + serverToKill.Address + "] Kill errored.");
|
|
|
|
else
|
|
|
|
System.out.println("Sent kill command to " + serverToKill.Address + " for " + serverToKill.Name + " completed");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
pr.join(500);
|
|
|
|
}
|
|
|
|
catch (InterruptedException e1)
|
|
|
|
{
|
|
|
|
e1.printStackTrace();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!pr.isDone())
|
|
|
|
_processes.add(pr);
|
|
|
|
}
|
|
|
|
|
|
|
|
private static boolean isServerOffline(DynamicServerData serverData)
|
|
|
|
{
|
|
|
|
boolean success = false;
|
|
|
|
|
|
|
|
Process process = null;
|
|
|
|
String cmd = "/home/mineplex/isServerOnline.sh";
|
|
|
|
|
|
|
|
ProcessBuilder processBuilder = new ProcessBuilder(new String[] {"/bin/sh", cmd, serverData.Address});
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
process = processBuilder.start();
|
|
|
|
process.waitFor();
|
|
|
|
|
|
|
|
BufferedReader reader=new BufferedReader(new InputStreamReader(process.getInputStream()));
|
|
|
|
String line = reader.readLine();
|
|
|
|
|
|
|
|
while(line != null)
|
|
|
|
{
|
|
|
|
success = line.equals("Success");
|
|
|
|
|
|
|
|
line=reader.readLine();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (Exception e1)
|
|
|
|
{
|
|
|
|
e1.printStackTrace();
|
2013-10-10 18:02:21 +02:00
|
|
|
}
|
2014-02-18 09:40:41 +01:00
|
|
|
finally
|
|
|
|
{
|
|
|
|
process.destroy();
|
|
|
|
}
|
|
|
|
|
|
|
|
return !success;
|
2013-10-10 18:02:21 +02:00
|
|
|
}
|
2013-11-06 10:03:02 +01:00
|
|
|
|
|
|
|
private static DynamicServerData getBestDynamicServer(Collection<DynamicServerData> dynamicServers, ServerGroupData serverGroup)
|
|
|
|
{
|
|
|
|
DynamicServerData bestServer = null;
|
|
|
|
|
|
|
|
for (DynamicServerData serverData : dynamicServers)
|
|
|
|
{
|
|
|
|
if (serverData.AvailableRAM > serverGroup.RequiredRAM && serverData.AvailableCPU > serverGroup.RequiredCPU)
|
|
|
|
{
|
|
|
|
if (bestServer == null)
|
|
|
|
{
|
|
|
|
bestServer = serverData;
|
|
|
|
|
|
|
|
if (!serverData.ServerGroupCount.containsKey(serverGroup.Name))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if (serverData.ServerGroupCount.containsKey(serverGroup.Name))
|
|
|
|
{
|
|
|
|
if (serverData.ServerGroupCount.get(serverGroup.Name) < bestServer.ServerGroupCount.get(serverGroup.Name))
|
|
|
|
bestServer = serverData;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return bestServer;
|
|
|
|
}
|
2013-11-08 19:52:56 +01:00
|
|
|
|
2014-01-03 07:37:39 +01:00
|
|
|
private static void restartServer(final ServerStatusData serverToKill)
|
|
|
|
{
|
|
|
|
String cmd = "/home/mineplex/restartServer.sh";
|
|
|
|
|
2014-01-08 21:18:52 +01:00
|
|
|
ProcessRunner pr = new ProcessRunner(new String[] {"/bin/sh", cmd, serverToKill.Address, serverToKill.Name});
|
2014-02-18 09:40:41 +01:00
|
|
|
pr.start(new GenericRunnable<Boolean>()
|
2014-01-08 21:18:52 +01:00
|
|
|
{
|
2014-02-18 09:40:41 +01:00
|
|
|
public void run(Boolean error)
|
2014-01-08 21:18:52 +01:00
|
|
|
{
|
2014-02-18 09:40:41 +01:00
|
|
|
if (error)
|
|
|
|
System.out.println("Restart command to " + serverToKill.Address + " for " + serverToKill.Name + " failed");
|
|
|
|
else
|
|
|
|
System.out.println("Restart command to " + serverToKill.Address + " for " + serverToKill.Name + " completed");
|
2014-01-08 21:18:52 +01:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
pr.join(500);
|
|
|
|
}
|
|
|
|
catch (InterruptedException e1)
|
|
|
|
{
|
|
|
|
e1.printStackTrace();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!pr.isDone())
|
|
|
|
_processes.add(pr);
|
2014-01-03 07:37:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
private static void killServer(final ServerStatusData serverToKill)
|
2013-11-08 19:52:56 +01:00
|
|
|
{
|
2014-02-18 09:40:41 +01:00
|
|
|
killServer(serverToKill, true);
|
2013-11-08 19:52:56 +01:00
|
|
|
}
|
|
|
|
|
2014-01-03 07:37:39 +01:00
|
|
|
private static void startServer(final DynamicServerData serverSpace, final ServerGroupData serverGroup, final int serverNum)
|
2013-11-08 19:52:56 +01:00
|
|
|
{
|
|
|
|
String cmd = "/home/mineplex/easyRemoteStartServer.sh";
|
|
|
|
|
2014-01-08 21:18:52 +01:00
|
|
|
ProcessRunner pr = new ProcessRunner(new String[] {"/bin/sh", cmd, serverSpace.Address, serverSpace.PrivateAddress, serverGroup.ScriptName, serverGroup.Prefix + "-" + serverNum, "1", serverSpace.US ? "us" : "eu"});
|
2014-02-18 09:40:41 +01:00
|
|
|
pr.start(new GenericRunnable<Boolean>()
|
2014-01-08 21:18:52 +01:00
|
|
|
{
|
2014-02-18 09:40:41 +01:00
|
|
|
public void run(Boolean error)
|
2014-01-08 21:18:52 +01:00
|
|
|
{
|
2014-02-18 09:40:41 +01:00
|
|
|
if (error)
|
|
|
|
System.out.println("[" + serverSpace.Name + ":" + serverSpace.Address + "] Errored " + serverGroup.Name + "(" + serverGroup.Prefix + "-" + serverNum + ")");
|
|
|
|
else
|
|
|
|
System.out.println("[" + serverSpace.Name + ":" + serverSpace.Address + "] Added " + serverGroup.Name + "(" + serverGroup.Prefix + "-" + serverNum + ")");
|
2014-01-08 21:18:52 +01:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
pr.join(500);
|
|
|
|
}
|
|
|
|
catch (InterruptedException e1)
|
|
|
|
{
|
|
|
|
e1.printStackTrace();
|
|
|
|
}
|
|
|
|
|
2014-02-18 09:40:41 +01:00
|
|
|
serverSpace.setServerGroupCount(serverGroup, serverSpace.ServerGroupCount.containsKey(serverGroup.Name) ? (serverSpace.ServerGroupCount.get(serverGroup.Name) + 1) : 1);
|
2014-01-08 21:18:52 +01:00
|
|
|
|
|
|
|
if (!pr.isDone())
|
|
|
|
_processes.add(pr);
|
2013-11-08 19:52:56 +01:00
|
|
|
}
|
2013-10-10 18:02:21 +02:00
|
|
|
}
|