1 /*******************************************************************************
\r
2 * ============LICENSE_START==================================================
\r
4 * * ===========================================================================
\r
5 * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
\r
6 * * ===========================================================================
\r
7 * * Licensed under the Apache License, Version 2.0 (the "License");
\r
8 * * you may not use this file except in compliance with the License.
\r
9 * * You may obtain a copy of the License at
\r
11 * * http://www.apache.org/licenses/LICENSE-2.0
\r
13 * * Unless required by applicable law or agreed to in writing, software
\r
14 * * distributed under the License is distributed on an "AS IS" BASIS,
\r
15 * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
16 * * See the License for the specific language governing permissions and
\r
17 * * limitations under the License.
\r
18 * * ============LICENSE_END====================================================
\r
20 * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
\r
22 ******************************************************************************/
\r
25 package com.att.research.datarouter.provisioning;
\r
27 import java.security.Security;
\r
28 import java.util.Properties;
\r
29 import java.util.Timer;
\r
31 import org.apache.log4j.Logger;
\r
32 import org.eclipse.jetty.server.Connector;
\r
33 import org.eclipse.jetty.server.Handler;
\r
34 import org.eclipse.jetty.server.NCSARequestLog;
\r
35 import org.eclipse.jetty.server.Server;
\r
36 import org.eclipse.jetty.server.handler.ContextHandlerCollection;
\r
37 import org.eclipse.jetty.server.handler.DefaultHandler;
\r
38 import org.eclipse.jetty.server.handler.HandlerCollection;
\r
39 import org.eclipse.jetty.server.handler.RequestLogHandler;
\r
40 import org.eclipse.jetty.server.nio.SelectChannelConnector;
\r
41 import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
\r
42 import org.eclipse.jetty.servlet.FilterHolder;
\r
43 import org.eclipse.jetty.servlet.FilterMapping;
\r
44 import org.eclipse.jetty.servlet.ServletContextHandler;
\r
45 import org.eclipse.jetty.servlet.ServletHolder;
\r
46 import org.eclipse.jetty.util.ssl.SslContextFactory;
\r
47 import org.eclipse.jetty.util.thread.QueuedThreadPool;
\r
49 import com.att.research.datarouter.provisioning.utils.DB;
\r
50 import com.att.research.datarouter.provisioning.utils.LogfileLoader;
\r
51 import com.att.research.datarouter.provisioning.utils.PurgeLogDirTask;
\r
52 import com.att.research.datarouter.provisioning.utils.ThrottleFilter;
\r
56 * A main class which may be used to start the provisioning server with an "embedded" Jetty server.
\r
57 * Configuration is done via the properties file <i>provserver.properties</i>, which should be in the CLASSPATH.
\r
58 * The provisioning server may also be packaged with a web.xml and started as a traditional webapp.
\r
61 * Most of the work of the provisioning server is carried out within the eight servlets (configured below)
\r
62 * that are used to handle each of the eight types of requests the server may receive.
\r
63 * In addition, there are background threads started to perform other tasks:
\r
66 * <li>One background Thread runs the {@link LogfileLoader} in order to process incoming logfiles.
\r
67 * This Thread is created as a side effect of the first successful POST to the /internal/logs/ servlet.</li>
\r
68 * <li>One background Thread runs the {@link SynchronizerTask} which is used to periodically
\r
69 * synchronize the database between active and standby servers.</li>
\r
70 * <li>One background Thread runs the {@link Poker} which is used to notify the nodes whenever
\r
71 * provisioning data changes.</li>
\r
72 * <li>One task is run once a day to run {@link PurgeLogDirTask} which purges older logs from the
\r
73 * /opt/app/datartr/logs directory.</li>
\r
76 * The provisioning server is stopped by issuing a GET to the URL http://127.0.0.1/internal/halt
\r
77 * using <i>curl</i> or some other such tool.
\r
80 * @author Robert Eby
\r
81 * @version $Id: Main.java,v 1.12 2014/03/12 19:45:41 eby Exp $
\r
84 /** The truststore to use if none is specified */
\r
85 public static final String DEFAULT_TRUSTSTORE = "/opt/java/jdk/jdk180/jre/lib/security/cacerts";
\r
86 public static final String KEYSTORE_TYPE_PROPERTY = "com.att.research.datarouter.provserver.keystore.type";
\r
87 public static final String KEYSTORE_PATH_PROPERTY = "com.att.research.datarouter.provserver.keystore.path";
\r
88 public static final String KEYSTORE_PASSWORD_PROPERTY = "com.att.research.datarouter.provserver.keystore.password";
\r
89 public static final String TRUSTSTORE_PATH_PROPERTY = "com.att.research.datarouter.provserver.truststore.path";
\r
90 public static final String TRUSTSTORE_PASSWORD_PROPERTY = "com.att.research.datarouter.provserver.truststore.password";
\r
92 /** The one and only {@link Server} instance in this JVM */
\r
93 private static Server server;
\r
96 * Starts the Data Router Provisioning server.
\r
97 * @param args not used
\r
98 * @throws Exception if Jetty has a problem starting
\r
100 public static void main(String[] args) throws Exception {
\r
101 Security.setProperty("networkaddress.cache.ttl", "4");
\r
102 Logger logger = Logger.getLogger("com.att.research.datarouter.provisioning.internal");
\r
104 // Check DB is accessible and contains the expected tables
\r
105 if (! checkDatabase(logger))
\r
108 logger.info("PROV0000 **** AT&T Data Router Provisioning Server starting....");
\r
111 Properties p = (new DB()).getProperties();
\r
112 int http_port = Integer.parseInt(p.getProperty("com.att.research.datarouter.provserver.http.port", "8080"));
\r
113 int https_port = Integer.parseInt(p.getProperty("com.att.research.datarouter.provserver.https.port", "8443"));
\r
116 SelectChannelConnector http = new SelectChannelConnector();
\r
117 http.setPort(http_port);
\r
118 http.setMaxIdleTime(300000);
\r
119 http.setRequestHeaderSize(2048);
\r
120 http.setAcceptors(2);
\r
121 http.setConfidentialPort(https_port);
\r
122 http.setLowResourcesConnections(20000);
\r
125 SslSelectChannelConnector https = new SslSelectChannelConnector();
\r
126 https.setPort(https_port);
\r
127 https.setMaxIdleTime(30000);
\r
128 https.setRequestHeaderSize(8192);
\r
129 https.setAcceptors(2);
\r
132 SslContextFactory cf = https.getSslContextFactory();
\r
134 /**Skip SSLv3 Fixes*/
\r
135 cf.addExcludeProtocols("SSLv3");
\r
136 logger.info("Excluded protocols prov-"+cf.getExcludeProtocols());
\r
137 /**End of SSLv3 Fixes*/
\r
139 cf.setKeyStoreType(p.getProperty(KEYSTORE_TYPE_PROPERTY, "jks"));
\r
140 cf.setKeyStorePath(p.getProperty(KEYSTORE_PATH_PROPERTY));
\r
141 cf.setKeyStorePassword(p.getProperty(KEYSTORE_PASSWORD_PROPERTY));
\r
142 cf.setKeyManagerPassword(p.getProperty("com.att.research.datarouter.provserver.keymanager.password"));
\r
143 String ts = p.getProperty(TRUSTSTORE_PATH_PROPERTY);
\r
144 if (ts != null && ts.length() > 0) {
\r
145 System.out.println("@@ TS -> "+ts);
\r
146 cf.setTrustStore(ts);
\r
147 cf.setTrustStorePassword(p.getProperty(TRUSTSTORE_PASSWORD_PROPERTY));
\r
149 cf.setTrustStore(DEFAULT_TRUSTSTORE);
\r
150 cf.setTrustStorePassword("changeit");
\r
152 cf.setTrustStore("/opt/app/datartr/self_signed/cacerts.jks");
\r
153 cf.setTrustStorePassword("changeit");
\r
154 cf.setWantClientAuth(true);
\r
156 // Servlet and Filter configuration
\r
157 ServletContextHandler ctxt = new ServletContextHandler(0);
\r
158 ctxt.setContextPath("/");
\r
159 ctxt.addServlet(new ServletHolder(new FeedServlet()), "/feed/*");
\r
160 ctxt.addServlet(new ServletHolder(new FeedLogServlet()), "/feedlog/*");
\r
161 ctxt.addServlet(new ServletHolder(new PublishServlet()), "/publish/*");
\r
162 ctxt.addServlet(new ServletHolder(new SubscribeServlet()), "/subscribe/*");
\r
163 ctxt.addServlet(new ServletHolder(new StatisticsServlet()), "/statistics/*");
\r
164 ctxt.addServlet(new ServletHolder(new SubLogServlet()), "/sublog/*");
\r
165 ctxt.addServlet(new ServletHolder(new GroupServlet()), "/group/*"); //Provision groups - Rally US708115 -1610
\r
166 ctxt.addServlet(new ServletHolder(new SubscriptionServlet()), "/subs/*");
\r
167 ctxt.addServlet(new ServletHolder(new InternalServlet()), "/internal/*");
\r
168 ctxt.addServlet(new ServletHolder(new RouteServlet()), "/internal/route/*");
\r
169 ctxt.addServlet(new ServletHolder(new DRFeedsServlet()), "/");
\r
170 ctxt.addFilter (new FilterHolder (new ThrottleFilter()), "/publish/*", FilterMapping.REQUEST);
\r
172 ContextHandlerCollection contexts = new ContextHandlerCollection();
\r
173 contexts.addHandler(ctxt);
\r
175 // Request log configuration
\r
176 NCSARequestLog nrl = new NCSARequestLog();
\r
177 nrl.setFilename(p.getProperty("com.att.research.datarouter.provserver.accesslog.dir") + "/request.log.yyyy_mm_dd");
\r
178 nrl.setFilenameDateFormat("yyyyMMdd");
\r
179 nrl.setRetainDays(90);
\r
180 nrl.setAppend(true);
\r
181 nrl.setExtended(false);
\r
182 nrl.setLogCookies(false);
\r
183 nrl.setLogTimeZone("GMT");
\r
185 RequestLogHandler reqlog = new RequestLogHandler();
\r
186 reqlog.setRequestLog(nrl);
\r
188 // Server's Handler collection
\r
189 HandlerCollection hc = new HandlerCollection();
\r
190 hc.setHandlers(new Handler[] { contexts, new DefaultHandler() });
\r
191 hc.addHandler(reqlog);
\r
193 // Server's thread pool
\r
194 QueuedThreadPool pool = new QueuedThreadPool();
\r
195 pool.setMinThreads(10);
\r
196 pool.setMaxThreads(200);
\r
197 pool.setDetailedDump(false);
\r
199 // Daemon to clean up the log directory on a daily basis
\r
200 Timer rolex = new Timer();
\r
201 rolex.scheduleAtFixedRate(new PurgeLogDirTask(), 0, 86400000L); // run once per day
\r
203 // Start LogfileLoader
\r
204 LogfileLoader.getLoader();
\r
206 // The server itself
\r
207 server = new Server();
\r
208 server.setThreadPool(pool);
\r
209 server.setConnectors(new Connector[] { http, https });
\r
210 server.setHandler(hc);
\r
211 server.setStopAtShutdown(true);
\r
212 server.setSendServerVersion(true);
\r
213 server.setSendDateHeader(true);
\r
214 server.setGracefulShutdown(5000); // allow 5 seconds for servlets to wrap up
\r
215 server.setDumpAfterStart(false);
\r
216 server.setDumpBeforeStop(false);
\r
220 logger.info("PROV0001 **** AT&T Data Router Provisioning Server halted.");
\r
223 private static boolean checkDatabase(Logger logger) {
\r
225 return db.runRetroFits();
\r
229 * Stop the Jetty server.
\r
231 public static void shutdown() {
\r
234 public void run() {
\r
237 Thread.sleep(5000L);
\r
239 } catch (Exception e) {
\r