in ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java [318:617]
public void run() throws Exception {
setupJulLogging();
performStaticInjection();
initDB();
// Client Jetty thread pool - widen the thread pool if needed !
Integer clientAcceptors = configs.getClientApiAcceptors() != null ? configs
.getClientApiAcceptors() : DEFAULT_ACCEPTORS_COUNT;
server = configureJettyThreadPool(clientAcceptors, CLIENT_THREAD_POOL_NAME,
configs.getClientThreadPoolSize());
final SessionIdManager sessionIdManager = new DefaultSessionIdManager(server);
sessionHandler.setSessionIdManager(sessionIdManager);
server.setSessionIdManager(sessionIdManager);
// Agent Jetty thread pool - widen the thread pool if needed !
Integer agentAcceptors = configs.getAgentApiAcceptors() != null ?
configs.getAgentApiAcceptors() : DEFAULT_ACCEPTORS_COUNT;
Server serverForAgent = configureJettyThreadPool(agentAcceptors * 2,
AGENT_THREAD_POOL_NAME, configs.getAgentThreadPoolSize());
setSystemProperties(configs);
runDatabaseConsistencyCheck();
try {
ClassPathXmlApplicationContext parentSpringAppContext =
new ClassPathXmlApplicationContext();
parentSpringAppContext.refresh();
ConfigurableListableBeanFactory factory = parentSpringAppContext.
getBeanFactory();
factory.registerSingleton("injector", injector);
//todo unable to register Users class as Spring @Bean since it tries to process @Inject annotations, investigate
factory.registerSingleton("ambariUsers", injector.getInstance(Users.class));
//create spring context for web api
AnnotationConfigWebApplicationContext apiContext = new AnnotationConfigWebApplicationContext();
apiContext.setParent(parentSpringAppContext);
apiContext.register(ApiSecurityConfig.class);
//refresh will be called in ContextLoaderListener
AnnotationConfigWebApplicationContext apiDispatcherContext = new AnnotationConfigWebApplicationContext();
apiDispatcherContext.register(ApiStompConfig.class);
DispatcherServlet apiDispatcherServlet = new DispatcherServlet(apiDispatcherContext);
AnnotationConfigWebApplicationContext agentDispatcherContext = new AnnotationConfigWebApplicationContext();
agentDispatcherContext.register(AgentStompConfig.class);
DispatcherServlet agentDispatcherServlet = new DispatcherServlet(agentDispatcherContext);
ServletContextHandler root = new ServletContextHandler(
ServletContextHandler.SECURITY | ServletContextHandler.SESSIONS);
configureRootHandler(root);
sessionHandlerConfigurer.configureSessionHandler(sessionHandler);
root.setSessionHandler(sessionHandler);
//ContextLoaderListener handles all work on registration in servlet container
root.addEventListener(new ContextLoaderListener(apiContext));
certMan.initRootCert();
// the agent communication (heartbeats, registration, etc) is stateless
// and does not use sessions.
ServletContextHandler agentroot = new ServletContextHandler(
serverForAgent, "/", ServletContextHandler.NO_SESSIONS);
AnnotationConfigWebApplicationContext agentApiContext = new AnnotationConfigWebApplicationContext();
agentApiContext.setParent(parentSpringAppContext);
if (configs.isAgentApiGzipped()) {
configureHandlerCompression(agentroot);
}
JettyWebSocketServletContainerInitializer initializerForAgentroot = new JettyWebSocketServletContainerInitializer((context, jettyContainer) -> {
jettyContainer.setMaxTextMessageSize(configs.getStompMaxIncomingMessageSize());
LOG.info("Configured WebSocket container max text message size: {}", configs.getStompMaxIncomingMessageSize());
});
agentroot.addEventListener(new ContextLoaderListener(agentApiContext));
agentroot.addEventListener(new WebSocketInitializerListener(initializerForAgentroot));
ServletHolder rootServlet = root.addServlet(DefaultServlet.class, "/");
rootServlet.setInitParameter("dirAllowed", "false");
rootServlet.setInitParameter("precompressed", "gzip=.gz");
rootServlet.setInitOrder(1);
/* Configure default servlet for agent server */
rootServlet = agentroot.addServlet(DefaultServlet.class, "/");
rootServlet.setInitOrder(1);
// Conditionally adds security-related headers to all HTTP responses.
root.addFilter(new FilterHolder(injector.getInstance(AmbariServerSecurityHeaderFilter.class)), "/*", DISPATCHER_TYPES);
// The security header filter - conditionally adds security-related headers to the HTTP response for Ambari Views
// requests.
root.addFilter(new FilterHolder(injector.getInstance(AmbariViewsSecurityHeaderFilter.class)), VIEWS_URL_PATTERN,
DISPATCHER_TYPES);
// since views share the REST API threadpool, a misbehaving view could
// consume all of the available threads and effectively cause a loss of
// service for Ambari
root.addFilter(new FilterHolder(injector.getInstance(ViewThrottleFilter.class)),
VIEWS_URL_PATTERN, DISPATCHER_TYPES);
// adds MDC info for views logging
root.addFilter(new FilterHolder(injector.getInstance(AmbariViewsMDCLoggingFilter.class)),
VIEWS_URL_PATTERN, DISPATCHER_TYPES);
// session-per-request strategy for api
root.addFilter(new FilterHolder(injector.getInstance(AmbariPersistFilter.class)), "/api/*", DISPATCHER_TYPES);
root.addFilter(new FilterHolder(new MethodOverrideFilter()), "/api/*", DISPATCHER_TYPES);
root.addFilter(new FilterHolder(new ContentTypeOverrideFilter()), "/api/*", DISPATCHER_TYPES);
JettyWebSocketServletContainerInitializer initializerForRoot = new JettyWebSocketServletContainerInitializer((context, jettyContainer) -> {
jettyContainer.setMaxTextMessageSize(configs.getStompMaxIncomingMessageSize());
LOG.info("Configured WebSocket container max text message size: {}", configs.getStompMaxIncomingMessageSize());
});
// register listener to capture request context
root.addEventListener(new RequestContextListener());
root.addEventListener(new WebSocketInitializerListener(initializerForRoot));
root.addFilter(new FilterHolder(springSecurityFilter), "/api/*", DISPATCHER_TYPES);
root.addFilter(new FilterHolder(new UserNameOverrideFilter()), "/api/v1/users/*", DISPATCHER_TYPES);
// session-per-request strategy for agents
agentroot.addFilter(new FilterHolder(injector.getInstance(AmbariPersistFilter.class)), "/agent/*", DISPATCHER_TYPES);
agentroot.addFilter(SecurityFilter.class, "/*", DISPATCHER_TYPES);
Map<String, String> configsMap = configs.getConfigsMap();
// Agents download cert on on-way connector but always communicate on
// two-way connector for server-agent communication
ServerConnector agentOneWayConnector = createSelectChannelConnectorForAgent(serverForAgent, configs.getOneWayAuthPort(), false, agentAcceptors);
ServerConnector agentTwoWayConnector = createSelectChannelConnectorForAgent(serverForAgent, configs.getTwoWayAuthPort(), configs.isTwoWaySsl(), agentAcceptors);
serverForAgent.addConnector(agentOneWayConnector);
serverForAgent.addConnector(agentTwoWayConnector);
ServletHolder sh = new ServletHolder(new ServletContainer(new ResourceConfig().packages(
"org.apache.ambari.server.api.rest",
"org.apache.ambari.server.api.services",
"org.apache.ambari.eventdb.webservice",
"org.apache.ambari.server.api").register(org.glassfish.jersey.jackson.JacksonFeature.class)));
root.addServlet(sh, "/api/v1/*");
sh.setInitOrder(2);
ServletHolder springDispatcherServlet = new ServletHolder("springDispatcherServlet", apiDispatcherServlet);
springDispatcherServlet.setInitOrder(3);
root.addServlet(springDispatcherServlet, "/api/stomp/*");
ServletHolder agentSpringDispatcherServlet =
new ServletHolder("agentSpringDispatcherServlet", agentDispatcherServlet);
agentSpringDispatcherServlet.setInitOrder(2);
agentroot.addServlet(agentSpringDispatcherServlet, "/agent/stomp/*");
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
viewRegistry.readViewArchives();
//Check and load requestlog handler.
loadRequestlogHandler(handlerList, serverForAgent, configsMap);
enableLog4jMonitor(configsMap);
if (configs.isGzipHandlerEnabledForJetty()) {
GzipHandler gzipHandler = new GzipHandler();
gzipHandler.setHandler(root);
//TODO minimal set, perhaps is needed to add some other mime types
gzipHandler.setIncludedMimeTypes("text/html", "text/plain", "text/xml", "text/css", "application/javascript",
"application/x-javascript", "application/xml", "application/x-www-form-urlencoded", "application/json");
handlerList.addHandler(gzipHandler);
} else {
handlerList.addHandler(root);
}
server.setHandler(handlerList);
ServletHolder agent = new ServletHolder(new ServletContainer(new ResourceConfig()
.packages("org.apache.ambari.server.agent.rest", "org.apache.ambari.server.api")
.register(org.glassfish.jersey.jackson.JacksonFeature.class)));
agentroot.addServlet(agent, "/agent/v1/*");
agent.setInitOrder(3);
injector.getInstance(HeartBeatHandler.class).start();
LOG.info("********** Started Heartbeat handler **********");
ServletHolder cert = new ServletHolder(new ServletContainer(new ResourceConfig()
.packages("org.apache.ambari.server.security.unsecured.rest", "org.apache.ambari.server.api")
.register(org.glassfish.jersey.jackson.JacksonFeature.class)));
agentroot.addServlet(cert, "/*");
cert.setInitOrder(4);
File resourcesDirectory = new File(configs.getResourceDirPath());
ServletHolder resources = new ServletHolder(DefaultServlet.class);
resources.setInitParameter("resourceBase", resourcesDirectory.getParent());
resources.setInitParameter("dirAllowed", "false");
root.addServlet(resources, "/resources/*");
resources.setInitOrder(5);
if (configs.csrfProtectionEnabled()) {
sh.setInitParameter("org.glassfish.jersey.server.ContainerRequestFilter",
"org.apache.ambari.server.api.AmbariCsrfProtectionFilter");
}
/* Configure the API server to use the NIO connectors */
ServerConnector apiConnector = createSelectChannelConnectorForClient(server, clientAcceptors);
server.addConnector(apiConnector);
server.setStopAtShutdown(true);
serverForAgent.setStopAtShutdown(true);
//todo remove springAppContext.start();
String osType = getServerOsType();
if (osType == null || osType.isEmpty()) {
throw new RuntimeException(Configuration.OS_VERSION.getKey() + " is not "
+ " set in the ambari.properties file");
}
//Start action scheduler
LOG.info("********* Initializing Clusters **********");
Clusters clusters = injector.getInstance(Clusters.class);
StringBuilder clusterDump = new StringBuilder();
//TODO temporally commented because takes a lot of time on 5k cluster
//clusters.debugDump(clusterDump);
LOG.info("********* Current Clusters State *********");
LOG.info(clusterDump.toString());
LOG.info("********* Reconciling Alert Definitions **********");
ambariMetaInfo.reconcileAlertDefinitions(clusters, false);
LOG.info("********* Initializing ActionManager **********");
ActionManager manager = injector.getInstance(ActionManager.class);
LOG.info("********* Initializing Controller **********");
AmbariManagementController controller = injector.getInstance(
AmbariManagementController.class);
LOG.info("********* Initializing Scheduled Request Manager **********");
ExecutionScheduleManager executionScheduleManager = injector
.getInstance(ExecutionScheduleManager.class);
MetricsService metricsService = injector.getInstance(
MetricsService.class);
clusterController = controller;
StateRecoveryManager recoveryManager = injector.getInstance(
StateRecoveryManager.class);
recoveryManager.doWork();
/*
* Start the server after controller state is recovered.
*/
server.start();
handlerList.shareSessionCacheToViews(sessionHandler.getSessionCache());
//views initialization will reset inactive interval with default value, so we should set it after
sessionHandlerConfigurer.configureMaxInactiveInterval(sessionHandler);
serverForAgent.start();
LOG.info("********* Started Server **********");
if( !configs.isViewDirectoryWatcherServiceDisabled()) {
LOG.info("Starting View Directory Watcher");
viewDirectoryWatcher.start();
}
manager.start();
LOG.info("********* Started ActionManager **********");
executionScheduleManager.start();
LOG.info("********* Started Scheduled Request Manager **********");
serviceManager.startAsync();
LOG.info("********* Started Services **********");
if (!configs.isMetricsServiceDisabled()) {
metricsService.start();
} else {
LOG.info("AmbariServer Metrics disabled.");
}
server.join();
LOG.info("Joined the Server");
} catch (BadPaddingException bpe) {
LOG.error("Bad keystore or private key password. " +
"HTTPS certificate re-importing may be required.");
throw bpe;
} catch (BindException bindException) {
LOG.error("Could not bind to server port - instance may already be running. " +
"Terminating this instance.", bindException);
throw bindException;
}
}