package org.openslx.bwlp.sat; import java.io.IOException; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.sql.SQLException; import java.util.HashSet; import java.util.Set; import javax.net.ssl.SSLContext; import org.apache.log4j.BasicConfigurator; import org.apache.log4j.ConsoleAppender; import org.apache.log4j.Logger; import org.apache.log4j.PatternLayout; import org.apache.thrift.TException; import org.apache.thrift.transport.TTransportException; import org.openslx.bwlp.sat.database.Updater; import org.openslx.bwlp.sat.database.mappers.DbConfiguration; import org.openslx.bwlp.sat.database.mappers.DbUser; import org.openslx.bwlp.sat.fileserv.FileServer; import org.openslx.bwlp.sat.maintenance.DeleteOldImages; import org.openslx.bwlp.sat.maintenance.DeleteOldLectures; import org.openslx.bwlp.sat.maintenance.DeleteOldUsers; import org.openslx.bwlp.sat.maintenance.MailFlusher; import org.openslx.bwlp.sat.maintenance.SendExpireWarning; import org.openslx.bwlp.sat.thrift.BinaryListener; import org.openslx.bwlp.sat.thrift.cache.OperatingSystemList; import org.openslx.bwlp.sat.thrift.cache.OrganizationList; import org.openslx.bwlp.sat.thrift.cache.VirtualizerList; import org.openslx.bwlp.sat.util.Configuration; import org.openslx.bwlp.sat.util.Identity; import org.openslx.bwlp.sat.web.WebServer; import org.openslx.bwlp.thrift.iface.TInvalidTokenException; import org.openslx.sat.thrift.version.Version; import org.openslx.thrifthelper.ThriftManager; import org.openslx.thrifthelper.ThriftManager.ErrorCallback; import org.openslx.util.QuickTimer; public class App { private static Logger LOGGER = Logger.getLogger(App.class); public static boolean DEBUG = false; private static final Set failFastMethods = new HashSet<>(); public static void main(String[] args) throws TTransportException, NoSuchAlgorithmException, IOException, KeyManagementException { // get going and show basic information in log file // don't add date/time to log output - will be done by syslog ConsoleAppender appender = new ConsoleAppender(new PatternLayout("%-5p [%t] %C{1} - %m%n")); appender.setEncoding("UTF-8"); BasicConfigurator.configure(appender); if (args.length != 0 && args[0].equals("debug")) { DEBUG = true; } LOGGER.info("****************************************************************"); LOGGER.info("******************* Starting Application ***********************"); LOGGER.info("****************************************************************"); LOGGER.info("RPC version " + Version.VERSION); LOGGER.info("Features: " + SupportedFeatures.getFeatureString()); // get Configuration try { LOGGER.info("Loading configuration"); Configuration.load(); } catch (Exception e1) { LOGGER.fatal("Could not load configuration", e1); System.exit(1); } // Update database schema if applicable try { Updater.updateDatabase(); RuntimeConfig.get(); DbConfiguration.updateMailTemplates(false); } catch (SQLException e1) { LOGGER.fatal("Updating/checking the database layout failed."); return; } if (Identity.loadCertificate() == null) { LOGGER.error("Could not set up TLS/SSL requirements, exiting"); System.exit(1); } failFastMethods.add("getVirtualizers"); failFastMethods.add("getOperatingSystems"); failFastMethods.add("getOrganizations"); ThriftManager.setMasterErrorCallback(new ErrorCallback() { @Override public boolean thriftError(int failCount, String method, Throwable t) { if (failFastMethods.contains(method)) return false; if (failCount > 2 || t == null) { LOGGER.warn("Thrift Client error for " + method + ", FAIL."); return false; } if (t instanceof TInvalidTokenException) return false; if (((TException) t).getCause() == null) { LOGGER.info("Thrift error " + t.toString() + " for " + method + ", retrying..."); } else { LOGGER.info("Thrift error " + ((TException) t).getCause().toString() + " for " + method + ", retrying..."); } try { Thread.sleep(failCount * 250); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } return true; } }); SSLContext ctx = null; if (Configuration.getMasterServerSsl()) { ctx = Configuration.getMasterServerSslContext(); } ThriftManager.setMasterServerAddress(ctx, Configuration.getMasterServerAddress(), Configuration.getMasterServerPort(), 30000); // Load useful things from master server if (VirtualizerList.get() == null || VirtualizerList.get().isEmpty()) { LOGGER.fatal("Could not get initial virtualizer list from master server." + " Please make sure this server can connect to the internet."); return; } if (OrganizationList.get() == null || OrganizationList.get().isEmpty()) { LOGGER.fatal("Could not get initial organization list from master server." + " Please make sure this server can connect to the internet."); return; } if (OperatingSystemList.get() == null || OperatingSystemList.get().isEmpty()) { LOGGER.fatal("Could not get initial operating system list from master server." + " Please make sure this server can connect to the internet."); return; } // Start file transfer server if (!FileServer.instance().start()) { LOGGER.error("Could not start internal file server."); return; } // Start watch dog to ensure nobody else is messing with the vmstore QuickTimer.scheduleAtFixedDelay(new StorageUseCheck(), 10000, 60000); // Set a flag that we need to convert userids if applicable DbUser.checkIfLegacyUsersExist(); // Set up maintenance tasks DeleteOldImages.init(); SendExpireWarning.init(); MailFlusher.init(); DeleteOldLectures.init(); DeleteOldUsers.init(); // Start Thrift Server Thread t; // Plain t = new Thread(new BinaryListener(9090, false)); t.setDaemon(true); t.start(); // SSL t = new Thread(new BinaryListener(9091, true)); t.start(); // Start httpd t = new Thread(new WebServer(9080)); t.setDaemon(true); t.start(); Runtime.getRuntime().addShutdownHook(new Thread() { @Override public void run() { QuickTimer.cancel(); LOGGER.info("All services and workers shut down, exiting..."); } }); } }