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.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.core.config.Configurator; import org.apache.logging.log4j.core.config.DefaultConfiguration; 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.AppUtil; import org.openslx.util.QuickTimer; public class App { private static Logger LOGGER = LogManager.getLogger(App.class); private static final String NAME = "bwLehrpool-Server"; private static final Set failFastMethods = new HashSet<>(); public static void main(String[] args) throws TTransportException, NoSuchAlgorithmException, IOException, KeyManagementException { System.setProperty("mariadb.logging.disable", "true"); // setup basic logging appender to log output on console if no external appender (log4j.properties) is configured if (org.apache.logging.log4j.core.Logger.class.cast(LogManager.getRootLogger()).getAppenders().isEmpty()) { Configurator.initialize(new DefaultConfiguration()); } // get Configuration try { LOGGER.info("Loading configuration"); Configuration.load(); } catch (Exception e1) { LOGGER.fatal("Could not load configuration", e1); System.exit(1); } AppUtil.logHeader(LOGGER, App.NAME, App.class.getPackage().getImplementationVersion()); AppUtil.logProperty(LOGGER, "rpc.version", Long.toString(Version.VERSION)); AppUtil.logProperty(LOGGER, "server.features", SupportedFeatures.getFeatureString()); // 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..."); } }); } }