/*
* Copyright (c) 2013 Yahoo! Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License. See accompanying LICENSE file.
*/
package com.yahoo.storm.yarn;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Map;
import junit.framework.Assert;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.mockito.Mockito.mock;
import com.yahoo.storm.yarn.generated.StormMaster;
public class TestStormCluster {
static final Logger LOG = LoggerFactory.getLogger(TestStormCluster.class);
private static EmbeddedZKServer zkServer;
private static MasterServer server = null;
private static MasterClient client = null;
private static File storm_conf_file = null;
private static TestConfig testConf = new TestConfig();
@SuppressWarnings({ "unchecked", "rawtypes" })
@BeforeClass
public static void setup() throws InterruptedException, IOException {
//start embedded ZK server
zkServer = new EmbeddedZKServer();
zkServer.start();
String storm_home = testConf.stormHomePath();
if (storm_home == null) {
throw new RuntimeException("Storm home was not found."
+ " Make sure to include storm in the PATH.");
}
LOG.info("Will be using storm found on PATH at "+storm_home);
//simple configuration
final Map storm_conf = Config.readStormConfig("src/main/resources/master_defaults.yaml");
storm_conf.put(backtype.storm.Config.STORM_ZOOKEEPER_PORT, zkServer.port());
storm_conf_file = testConf.createConfigFile(storm_conf);
confirmNothingIsRunning(storm_conf);
StormAMRMClient mockClient = mock(StormAMRMClient.class);
server = new MasterServer(storm_conf, mockClient);
//launch server
new Thread(new Runnable() {
@Override
public void run() {
try {
server.serve();
} catch (Exception ex) {
tearDown();
}
}
}).start();
LOG.info("Sleep to wait for the server to startup");
final int timeoutSecs = 40;
for (int elapsedSecs=0; elapsedSecs < timeoutSecs; elapsedSecs++) {
Thread.sleep(1000);
LOG.info("Slept " + elapsedSecs + " of " + timeoutSecs + "s.");
try {
checkZkConnection(storm_conf);
} catch (IOException e) {
LOG.warn("Could not connect to zookeeper server");
continue;
}
try {
checkNimbusConnection(storm_conf);
} catch (IOException e) {
LOG.warn("Still cannot connect to nimbus server.");
continue;
}
try {
checkUiConnection(storm_conf);
} catch (IOException e) {
LOG.warn("Still cannot connect to UI server.");
continue;
}
// The server appears to be up. Launch the client.
client = MasterClient.getConfiguredClient(storm_conf);
LOG.info("Connected to master to get client");
return;
}
throw new RuntimeException("Failed to connect to nimbus server in "
+ timeoutSecs + "seconds.");
}
private static void checkNimbusConnection(
@SuppressWarnings("rawtypes") final Map storm_conf)
throws IOException, UnknownHostException {
// Try to open a TCP connection to the nimbus port.
new Socket((String) storm_conf.get(Config.MASTER_HOST),
(Integer) storm_conf
.get(backtype.storm.Config.NIMBUS_THRIFT_PORT))
.close();
}
private static void checkZkConnection(
@SuppressWarnings("rawtypes") final Map storm_conf)
throws IOException, UnknownHostException {
// Try to open a TCP connection to the zookeeper ports
new Socket("localhost",
(Integer) storm_conf
.get(backtype.storm.Config.STORM_ZOOKEEPER_PORT))
.close();
}
private static void checkUiConnection(Map<?, ?> storm_conf)
throws IOException, UnknownHostException {
// Try to open a TCP connection to the UI port.
new Socket((String) storm_conf.get(Config.MASTER_HOST),
(Integer) storm_conf
.get(backtype.storm.Config.UI_PORT))
.close();
}
private static void confirmNothingIsRunning(Map<?, ?> storm_conf) {
try {
checkNimbusConnection(storm_conf);
throw new RuntimeException("Nimbus server already running.");
} catch (IOException e) {
LOG.info("OK: Nimbus does not seem to be running.");
}
try {
checkUiConnection(storm_conf);
throw new RuntimeException("UI server already running.");
} catch (IOException e) {
LOG.info("OK: UI does not seem to be running.");
}
}
@AfterClass
public static void tearDown() {
//stop client
if (client != null) {
StormMaster.Client master_client = client.getClient();
try {
master_client.stopSupervisors();
master_client.stopNimbus();
master_client.stopUI();
} catch (Exception e) {
LOG.info("failure in tearn down:"+e.toString());
}
client.close();
client = null;
}
//stop server
if (server != null) {
server.stop();
server = null;
}
//remove configuration file
testConf.cleanup();
//shutdown Zookeeper server
if (zkServer != null) {
zkServer.stop();
zkServer = null;
}
}
@Test
public void testUI() throws Exception {
LOG.info("Testing UI");
@SuppressWarnings("rawtypes")
final Map storm_conf = Config.readStormConfig(storm_conf_file.toString());
LOG.info("Testing connection to UI ...");
String host = (String) storm_conf.get("ui.host");
if (host==null) host = "localhost";
URL url = new URL("http://"+host+":"+storm_conf.get("ui.port")+"/");
LOG.info("UI URL:"+url);
URLConnection con = url.openConnection();
Assert.assertNotNull(con);
Assert.assertNotNull(con.getContent());
}
}