Advertisement
Guest User

Untitled

a guest
Feb 19th, 2019
95
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 23.08 KB | None | 0 0
  1. package host.batt.daemon;
  2.  
  3. import host.batt.daemon.ftp.*;
  4. import host.batt.daemon.console.commands.*;
  5. import host.batt.daemon.net.websocket.*;
  6. import host.batt.daemon.net.daemonsocket.*;
  7. import host.batt.daemon.tasks.*;
  8. import host.batt.daemon.migration.*;
  9. import org.apache.commons.io.FileUtils;
  10. import org.apache.commons.lang3.exception.*;
  11. import host.batt.daemon.console.*;
  12. import java.nio.charset.*;
  13. import host.batt.daemon.sql.*;
  14. import java.sql.*;
  15. import host.batt.daemon.adapter.*;
  16. import host.batt.daemon.processhooker.*;
  17. import java.io.*;
  18. import host.batt.daemon.config.*;
  19. import java.util.*;
  20. import java.util.Date;
  21. import java.util.concurrent.TimeUnit;
  22.  
  23. import host.batt.daemon.system.*;
  24.  
  25. public class MinecraftDaemon implements DaemonInfo, ManageableServer, ConsoleInput
  26. {
  27. public static String daemon_base_dir;
  28. public static String server_base_dir;
  29. public static String default_jars_dir;
  30. public static String process_hook_stream_dir;
  31. public static String update_dir;
  32. public static String migration_output_dir;
  33. public static String migration_input_dir;
  34. public static long version;
  35. public static String prefix;
  36. private boolean running;
  37. private boolean shuttingDown;
  38. private boolean outputServersConsole;
  39. private ConsoleBuffer consoleBuffer;
  40. private MysqlManager mysqlManager;
  41. private MysqlLogger mysqlLogger;
  42. private DaemonFtpServer ftpServer;
  43. private DaemonConfiguration daemonConfig;
  44. private CommandManager commandManager;
  45. private DaemonAdapter adapter;
  46. private ConsoleSocket consoleSocket;
  47. private DaemonSocket daemonSocket;
  48. public static ProcessWatcher processWatcher;
  49. private TaskManager taskManager;
  50. private MigrationManager migrationManager;
  51. private long startup;
  52. private long lastShutdownRequest;
  53. private Thread refreshThread;
  54. public List<MinecraftJavaServer> servers;
  55. private int lines = 1;
  56. public static MinecraftDaemon here;
  57.  
  58. public MinecraftDaemon() {
  59. this.running = true;
  60. this.shuttingDown = false;
  61. this.outputServersConsole = false;
  62. this.consoleBuffer = new ConsoleBuffer(this);
  63. this.processWatcher = new UnixProcessWatcher();
  64. this.taskManager = new TaskManager(this);
  65. this.servers = new ArrayList<MinecraftJavaServer>();
  66.  
  67. here = this;
  68. }
  69.  
  70. public long getVersion() {
  71. return MinecraftDaemon.version;
  72. }
  73.  
  74. public void log(final LogLevel level, final String line) {
  75. Date date = new Date();
  76. String info = date.getHours()+":"+date.getMinutes()+" - " + lines;
  77. switch (level) {
  78. case DAEMON_INFO: {
  79. this.consoleBuffer.outputLine("["+info+"] [INFO] " + line);
  80. break;
  81. }
  82. case DAEMON_ERROR: {
  83. this.consoleBuffer.outputLine("["+info+"] [Daemon Exception] " + line);
  84. break;
  85. }
  86. case CONSOLE_SOCKET: {
  87. this.consoleBuffer.outputLine("["+info+"] [Console Socket] " + line);
  88. break;
  89. }
  90. case DAEMON_SOCKET: {
  91. this.consoleBuffer.outputLine("["+info+"] [Daemon Socket] " + line);
  92. break;
  93. }
  94. case FTP: {
  95. this.consoleBuffer.outputLine("["+info+"] [FTP] ["+info+"] " + line);
  96. break;
  97. }
  98. case SQL: {
  99. this.consoleBuffer.outputLine("["+info+"] [SQL] ["+info+"] " + line);
  100. break;
  101. }
  102. case DOCKER_ERROR: {
  103. this.consoleBuffer.outputLine("["+info+"] [SQL] ["+info+"] " + line);
  104. break;
  105. }
  106. case SERVER: {
  107. if (this.outputServersConsole) {
  108. this.consoleBuffer.outputLine(line);
  109. break;
  110. }
  111. break;
  112. }
  113. case SERVER_ERROR: {
  114. this.consoleBuffer.outputLine(line);
  115. break;
  116. }
  117. }
  118. lines++;
  119. }
  120.  
  121. public void printDaemonException(final Throwable throwable) {
  122. this.log(LogLevel.DAEMON_ERROR, ExceptionUtils.getStackTrace(throwable));
  123. }
  124.  
  125. public static void sleep(final long millis) {
  126. try {
  127. Thread.sleep(millis);
  128. }
  129. catch (InterruptedException ex) {}
  130. }
  131.  
  132. public static void main(final String[] args) throws InterruptedException {
  133. installDocker();
  134. final MinecraftDaemon instance = new MinecraftDaemon();
  135. instance.getConsoleBuffer().hook(new ConsoleHook() {
  136. @Override
  137. public void onOutput(final String line) {
  138. System.out.println(line);
  139. }
  140. });
  141. instance.init();
  142. startCommandServer(instance);
  143. final BufferedReader stdInput = new BufferedReader(new InputStreamReader(System.in, StandardCharsets.UTF_8));
  144. try {
  145. while (instance.running) {
  146. final String l;
  147. if ((l = stdInput.readLine()) == null) {
  148. break;
  149. }
  150. instance.handleCommand(l);
  151. }
  152. }
  153. catch (Exception ex) {}
  154. }
  155.  
  156. public static void startCommandServer(MinecraftDaemon i){
  157.  
  158. //Vertx vertx = Vertx.vertx();
  159. //vertx.deployVerticle(new CmdServer(i));
  160. }
  161.  
  162.  
  163. public static File loadDefaultJar(final String fileName) {
  164. return new File(String.valueOf(MinecraftDaemon.default_jars_dir) + fileName);
  165. }
  166.  
  167. public void init() {
  168. this.startup = System.currentTimeMillis();
  169. try {
  170. this.loadConfig();
  171. }
  172. catch (Exception e) {
  173. e.printStackTrace();
  174. this.shutdown();
  175. return;
  176. }
  177. new Thread(getSizeUpdater()).start();
  178. this.log(LogLevel.DAEMON_INFO, "Using MYSQL database: " + MysqlConfig.getDefault().getHost());
  179. this.mysqlLogger = new MysqlLogger(this.mysqlManager, this.adapter.getDaemonUUID());
  180. this.migrationManager = new MigrationManager(this);
  181. (this.commandManager = new CommandManager(this)).registerDefaults();
  182. this.loadServers();
  183. (this.ftpServer = new DaemonFtpServer(this)).start();
  184. (this.consoleSocket = new ConsoleSocket(this)).listen(this.daemonConfig.getWebSocketPort());
  185. (this.daemonSocket = new DaemonSocket(this)).listen(8029);
  186. Runtime.getRuntime().addShutdownHook(new Thread() {
  187. @Override
  188. public void run() {
  189. MinecraftDaemon.this.kill();
  190. }
  191. });
  192. this.refreshThread = new Thread(new Runnable() {
  193. @Override
  194. public void run() {
  195. while (MinecraftDaemon.this.running) {
  196. try {
  197. if (MinecraftDaemon.this.getTimeTillNextRestart() == 0) {
  198. MinecraftDaemon.this.restart();
  199. }
  200. MinecraftDaemon.sleep(15000L);
  201. MinecraftDaemon.this.taskManager.refresh();
  202. MinecraftDaemon.this.migrationManager.refresh();
  203. MinecraftDaemon.this.startAll();
  204. MinecraftDaemon.this.loadServers();
  205. }
  206. catch (Exception e) {
  207. e.printStackTrace();
  208. }
  209. }
  210. }
  211. });
  212. new Thread(new Runnable() {
  213. @Override
  214. public void run() {
  215. MinecraftDaemon.this.clearCache();
  216. }
  217. }).start();
  218. this.refreshThread.start();
  219. this.startAll();
  220. this.mysqlLogger.logAsync("Daemon inicializado com sucesso.");
  221.  
  222. }
  223.  
  224. @Override
  225. public void kill() {
  226. for (final MinecraftJavaServer server : this.servers) {
  227. System.out.println("[Shutdown Handler] Sending kill signal to server " + server.getId());
  228. server.kill();
  229. }
  230. this.ftpServer.kill();
  231. this.consoleSocket.stop();
  232. this.daemonSocket.stop();
  233. this.mysqlManager.cancelTasks();
  234. this.refreshThread.stop();
  235. this.running = false;
  236. }
  237.  
  238. @Override
  239. public void restart() {
  240. this.shutdown(false);
  241. }
  242.  
  243. @Override
  244. public void shutdown() {
  245. this.shutdown(true);
  246. }
  247.  
  248. public int getTimeTillNextRestart() {
  249. return Math.max(0, 21600 - this.getOnlineTime());
  250. }
  251.  
  252. public void shutdown(final boolean stopServers) {
  253. if (this.shuttingDown && System.currentTimeMillis() - this.lastShutdownRequest < 120000L) {
  254. this.log(LogLevel.DAEMON_INFO, "Daemon is already in a shut down process.");
  255. return;
  256. }
  257. this.lastShutdownRequest = System.currentTimeMillis();
  258. this.shuttingDown = true;
  259. try {
  260. this.mysqlLogger.log("Processo de desligamento iniciado");
  261. }
  262. catch (SQLException ex) {}
  263. if (!stopServers) {
  264. this.servers.clear();
  265. }
  266. else {
  267. for (final MinecraftJavaServer server : this.servers) {
  268. server.shutdown();
  269. }
  270. }
  271. this.ftpServer.stop();
  272. this.consoleSocket.stop();
  273. this.daemonSocket.stop();
  274. this.mysqlManager.cancelTasks();
  275. int secs = 0;
  276. if (stopServers) {
  277. this.log(LogLevel.DAEMON_INFO, "Now waiting for all servers to shut down.");
  278. while (this.getRunningServerCount() > 0) {
  279. if (secs >= 30) {
  280. this.log(LogLevel.DAEMON_INFO, "Servers did not shutdown in 30 seconds, they will now be killed immediately.");
  281. for (final MinecraftJavaServer server2 : this.servers) {
  282. server2.kill();
  283. }
  284. break;
  285. }
  286. try {
  287. Thread.sleep(1000L);
  288. }
  289. catch (InterruptedException ex2) {}
  290. ++secs;
  291. }
  292. }
  293. this.running = false;
  294. if (!stopServers) {
  295. Runtime.getRuntime().halt(1);
  296. }
  297. else {
  298. System.exit(0);
  299. }
  300. }
  301.  
  302. private void loadConfig() throws Exception {
  303. final Properties pro = new Properties();
  304. pro.load(this.getClass().getResourceAsStream("/build.properties"));
  305. MinecraftDaemon.version = Long.valueOf(pro.getProperty("version").replaceAll("_", ""));
  306. this.daemonConfig = DaemonConfigurationLoader.loadConfig();
  307. this.mysqlManager = new MysqlManager(this.daemonConfig.getMysqlConfig());
  308. (this.adapter = new MysqlAdapter(this.mysqlManager, this)).loadConfig(this.daemonConfig);
  309. MinecraftDaemon.prefix = this.daemonConfig.getPrefix();
  310. MinecraftDaemon.daemon_base_dir = this.daemonConfig.getDaemonBaseDir();
  311. MinecraftDaemon.server_base_dir = String.valueOf(MinecraftDaemon.daemon_base_dir) + "servers" + File.separator;
  312. MinecraftDaemon.default_jars_dir = String.valueOf(MinecraftDaemon.daemon_base_dir) + "jars" + File.separator;
  313. MinecraftDaemon.process_hook_stream_dir = String.valueOf(MinecraftDaemon.daemon_base_dir) + "stream" + File.separator;
  314. MinecraftDaemon.update_dir = String.valueOf(MinecraftDaemon.daemon_base_dir) + "update" + File.separator;
  315. MinecraftDaemon.migration_output_dir = String.valueOf(MinecraftDaemon.daemon_base_dir) + "migration_out" + File.separator;
  316. MinecraftDaemon.migration_input_dir = String.valueOf(MinecraftDaemon.daemon_base_dir) + "migration_in" + File.separator;
  317. this.refreshHookperms();
  318. }
  319.  
  320. public void refreshHookperms() {
  321. try {
  322. processWatcher.runAndPrint("chmod", "-R", "777", MinecraftDaemon.process_hook_stream_dir);
  323. processWatcher.runAndPrint("chmod", "755", String.valueOf(MinecraftDaemon.daemon_base_dir) + "ProcessHooker.jar");
  324. }
  325. catch (Exception e) {
  326. e.printStackTrace();
  327. }
  328. }
  329.  
  330. public void clearCache() {
  331. try {
  332. this.log(LogLevel.DAEMON_INFO, "Limpando CACHE!");
  333. processWatcher.runAndPrint("echo", "3", ">", "/proc/sys/vm/drop_caches");
  334. processWatcher.runAndPrint("sysctl", "-w", "vm.drop_caches=3");
  335. }
  336. catch (Exception e) {
  337. e.printStackTrace();
  338. }
  339. }
  340.  
  341. private void loadServers() {
  342. final String[] servers = this.adapter.loadServers();
  343. String[] array;
  344. for (int length = (array = servers).length, i = 0; i < length; ++i) {
  345. final String id = array[i];
  346. MinecraftJavaServer server;
  347. if ((server = this.getServer(id)) == null) {
  348. this.addServer(server = new MinecraftJavaServer(id, this));
  349. }
  350. else {
  351. server.validate();
  352. }
  353. }
  354. for (final MinecraftJavaServer server2 : new HashSet<MinecraftJavaServer>(this.servers)) {
  355. boolean remove = true;
  356. String[] array2;
  357. for (int length2 = (array2 = servers).length, j = 0; j < length2; ++j) {
  358. final String id2 = array2[j];
  359. if (id2.equalsIgnoreCase(server2.getId())) {
  360. remove = false;
  361. break;
  362. }
  363. }
  364. if (remove) {
  365. server2.kill();
  366. this.servers.remove(server2);
  367. }
  368. }
  369. File[] listFiles;
  370. for (int length3 = (listFiles = new File(MinecraftDaemon.process_hook_stream_dir).listFiles()).length, k = 0; k < length3; ++k) {
  371. final File f = listFiles[k];
  372. if (f.getName().endsWith("in")) {
  373. final String[] a = f.getName().split(".");
  374. if (a.length != 0) {
  375. final String sid = a[0];
  376. boolean remove2 = true;
  377. String[] array3;
  378. for (int length4 = (array3 = servers).length, l = 0; l < length4; ++l) {
  379. final String id3 = array3[l];
  380. if (id3.equalsIgnoreCase(sid)) {
  381. remove2 = false;
  382. break;
  383. }
  384. }
  385. if (remove2) {
  386. new Thread(new Runnable() {
  387. @Override
  388. public void run() {
  389. try {
  390. final TailOutputStream out = new TailOutputStream(ProcessHooker.eof, new FileOutputStream(f));
  391. out.close();
  392. }
  393. catch (IOException ex) {}
  394. }
  395. }).start();
  396. }
  397. }
  398. }
  399. }
  400. File[] listFiles2;
  401. for (int length5 = (listFiles2 = new File(MinecraftDaemon.server_base_dir).listFiles()).length, n = 0; n < length5; ++n) {
  402. final File f = listFiles2[n];
  403. if (f.isDirectory() && f.exists()) {
  404. new Thread(new Runnable() {
  405. @Override
  406. public void run() {
  407. final ServerConfiguration config = MinecraftDaemon.this.adapter.loadServerConfig(f.getName());
  408. if (config != null && !config.getDaemon().equalsIgnoreCase(MinecraftDaemon.this.getUUID())) {
  409. MinecraftDaemon.this.moveToTrash("Server " + config.getId(), f);
  410. MinecraftDaemon.this.mysqlLogger.logAsync("Arquivos do servidor ID=" + config.getId() + " enviados para a lixeira. Motivo: este servidor n\u00e3o pertence mais a este daemon.");
  411. }
  412. }
  413. }).start();
  414. }
  415. }
  416. }
  417.  
  418. public MinecraftJavaServer getServer(final String serverID) {
  419. for (final MinecraftJavaServer server : this.servers) {
  420. if (server.getId().equalsIgnoreCase(serverID)) {
  421. return server;
  422. }
  423. }
  424. return null;
  425. }
  426.  
  427. public void addServer(final MinecraftJavaServer server) {
  428. this.servers.add(server);
  429. }
  430.  
  431. public void startAll() {
  432. for (final MinecraftJavaServer server : this.servers) {
  433. try {
  434. if (server.isRunning() || server.getShutdownRequested() != 0) {
  435. continue;
  436. }
  437. server.loadConfig();
  438. if (!server.getConfig().isAutoStart()) {
  439. continue;
  440. }
  441. this.startServer(server);
  442. }
  443. catch (Exception e) {
  444. this.log(LogLevel.DAEMON_ERROR, "ERROR WHILE AUTO-STARTING SERVER ID=" + server.getId());
  445. }
  446. }
  447. }
  448.  
  449. public void startServer(final MinecraftJavaServer server) {
  450. new Thread(new Runnable() {
  451. @Override
  452. public void run() {
  453. server.startServer();
  454. }
  455. }).start();
  456. }
  457.  
  458. public boolean moveToTrash(final String prefix, final File file) {
  459. final File trashf = new File(String.valueOf(MinecraftDaemon.daemon_base_dir) + "trash" + File.separator);
  460. if (!trashf.exists()) {
  461. trashf.mkdirs();
  462. }
  463. return file.renameTo(new File(trashf, String.valueOf(getDateFileNameWithPrefix(prefix)) + "_" + file.getName()));
  464. }
  465.  
  466. public static String getDateFileNameWithPrefix(final String prefix) {
  467. final GregorianCalendar c = new GregorianCalendar();
  468. return String.valueOf(prefix) + "_" + c.get(1) + "_" + (c.get(2) + 1) + "_" + c.get(5) + "_" + c.get(11) + "_" + c.get(12) + "_" + c.get(13);
  469. }
  470.  
  471. @Override
  472. public boolean onConsoleInput(final String line) {
  473. final String[] spl = line.split(" ");
  474. return this.commandManager.handleCommand(spl[0], Arrays.copyOfRange(spl, 1, spl.length));
  475. }
  476.  
  477. @Override
  478. public void handleCommand(final String line) {
  479. this.onConsoleInput(line);
  480. }
  481.  
  482. @Override
  483. public void start() {
  484. }
  485.  
  486. @Override
  487. public String getUUID() {
  488. return this.adapter.getDaemonUUID();
  489. }
  490.  
  491. @Override
  492. public int getReservedRam() {
  493. return this.daemonConfig.getMemory();
  494. }
  495.  
  496. @Override
  497. public int getAllocatedRam() {
  498. int r = 0;
  499. for (final MinecraftJavaServer s : this.servers) {
  500. r += s.getAllocatedRam();
  501. }
  502. return r;
  503. }
  504.  
  505. @Override
  506. public int getPlayerCount() {
  507. int r = 0;
  508. for (final MinecraftJavaServer s : this.servers) {
  509. if (s.isOnline()) {
  510. r += s.getPlayerCount();
  511. }
  512. }
  513. return r;
  514. }
  515.  
  516. @Override
  517. public int getServerCount() {
  518. return this.servers.size();
  519. }
  520.  
  521. @Override
  522. public int getRunningServerCount() {
  523. int r = 0;
  524. for (final MinecraftJavaServer server : this.servers) {
  525. if (server.isRunning()) {
  526. ++r;
  527. }
  528. }
  529. return r;
  530. }
  531.  
  532. @Override
  533. public int getOnlineServerCount() {
  534. int r = 0;
  535. for (final MinecraftJavaServer s : this.servers) {
  536. if (s.isOnline()) {
  537. ++r;
  538. }
  539. }
  540. return r;
  541. }
  542.  
  543. public static void installDocker(){
  544. Runtime runtime = Runtime.getRuntime();
  545.  
  546. try{
  547. runtime.exec("yum -y install docker-io");
  548. }catch (Exception e){
  549. here.log(LogLevel.DAEMON_ERROR, "Docker cannot be instaled: " + e.getLocalizedMessage());
  550. }
  551. }
  552.  
  553. public class SizeUpdate implements Runnable {
  554.  
  555. @Override
  556. public void run() {
  557. while (isRunning()){
  558. log(LogLevel.DAEMON_INFO, "Starting memory update and zip/unzip check");
  559. for (File sv : new File("/home/daemon/servers").listFiles()){
  560. update(sv);
  561. }
  562.  
  563. try{TimeUnit.MINUTES.sleep(5);}catch (Exception e){}
  564. }
  565.  
  566. }
  567.  
  568. public void update(File b){
  569. double size = ((FileUtils.sizeOfDirectory(b)/1024.0)/ 1024.0);
  570. try {
  571. int id = Integer.parseInt(b.getName());
  572. log(LogLevel.DAEMON_INFO, "Updating server " + id + " STORAGE_USAGE");
  573. getMysqlManager().executeUpdate("UPDATE servers SET STORAGE_USAGE = ? WHERE ID = ?", size, id);
  574. }
  575. catch (SQLException e) {
  576. log(LogLevel.DAEMON_ERROR, e.getMessage());
  577. }
  578. }
  579.  
  580. public void zipRequests(){
  581.  
  582. }
  583.  
  584. class zipRequest{
  585.  
  586. }
  587. }
  588.  
  589. public SizeUpdate getSizeUpdater(){
  590. return new SizeUpdate();
  591. }
  592.  
  593. @Override
  594. public int getOnlineTime() {
  595. return (int)((System.currentTimeMillis() - this.startup) / 1000L);
  596. }
  597.  
  598. public SystemInfo getSystemInfo() {
  599. return this.processWatcher;
  600. }
  601.  
  602. public static String getPrefix() {
  603. return MinecraftDaemon.prefix;
  604. }
  605.  
  606. public boolean isRunning() {
  607. return this.running;
  608. }
  609.  
  610. public boolean isShuttingDown() {
  611. return this.shuttingDown;
  612. }
  613.  
  614. public boolean isOutputServersConsole() {
  615. return this.outputServersConsole;
  616. }
  617.  
  618. public void setOutputServersConsole(final boolean outputServersConsole) {
  619. this.outputServersConsole = outputServersConsole;
  620. }
  621.  
  622. @Override
  623. public ConsoleBuffer getConsoleBuffer() {
  624. return this.consoleBuffer;
  625. }
  626.  
  627. public MysqlManager getMysqlManager() {
  628. return this.mysqlManager;
  629. }
  630.  
  631. public MysqlLogger getMysqlLogger() {
  632. return this.mysqlLogger;
  633. }
  634.  
  635. public DaemonFtpServer getFtpServer() {
  636. return this.ftpServer;
  637. }
  638.  
  639. public DaemonConfiguration getDaemonConfig() {
  640. return this.daemonConfig;
  641. }
  642.  
  643. public CommandManager getCommandManager() {
  644. return this.commandManager;
  645. }
  646.  
  647. public DaemonAdapter getAdapter() {
  648. return this.adapter;
  649. }
  650.  
  651. public ConsoleSocket getConsoleSocket() {
  652. return this.consoleSocket;
  653. }
  654.  
  655. public DaemonSocket getDaemonSocket() {
  656. return this.daemonSocket;
  657. }
  658.  
  659. public ProcessWatcher getProcessWatcher() {
  660. return this.processWatcher;
  661. }
  662.  
  663. public TaskManager getTaskManager() {
  664. return this.taskManager;
  665. }
  666.  
  667. public MigrationManager getMigrationManager() {
  668. return this.migrationManager;
  669. }
  670.  
  671. public long getStartup() {
  672. return this.startup;
  673. }
  674.  
  675. public long getLastShutdownRequest() {
  676. return this.lastShutdownRequest;
  677. }
  678. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement