/* * 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.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.net.URL; import java.util.List; import java.util.Map; import org.apache.commons.io.FileUtils; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.yarn.api.ApplicationConstants.Environment; import org.apache.hadoop.yarn.conf.YarnConfiguration; import org.apache.hadoop.yarn.server.MiniYARNCluster; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import backtype.storm.generated.ClusterSummary; import backtype.storm.generated.Nimbus; import backtype.storm.generated.TopologySummary; import backtype.storm.utils.NimbusClient; import backtype.storm.utils.Utils; import com.google.common.base.Joiner; public class TestIntegration { private static final Logger LOG = LoggerFactory.getLogger(TestIntegration.class); private static final String STORM_YARN_CMD = "bin"+File.separator+"storm-yarn"; private static MiniYARNCluster yarnCluster = null; private static String appId; private static EmbeddedZKServer zkServer; private static File storm_conf_file; private static File yarn_site_xml; private static String storm_home; private static TestConfig testConf = new TestConfig(); @SuppressWarnings({ "rawtypes", "unchecked" }) @BeforeClass public static void setup() { try { zkServer = new EmbeddedZKServer(); zkServer.start(); LOG.info("Starting up MiniYARN cluster"); if (yarnCluster == null) { yarnCluster = new MiniYARNCluster(TestIntegration.class.getName(), 2, 1, 1); Configuration conf = new YarnConfiguration(); conf.setInt(YarnConfiguration.RM_SCHEDULER_MINIMUM_ALLOCATION_MB, 512); conf.setInt(YarnConfiguration.RM_SCHEDULER_MAXIMUM_ALLOCATION_MB, 2*1024); yarnCluster.init(conf); yarnCluster.start(); } sleep(2000); Configuration miniyarn_conf = yarnCluster.getConfig(); yarn_site_xml = testConf.createYarnSiteConfig(miniyarn_conf); storm_home = testConf.stormHomePath(); LOG.info("Will be using storm found on PATH at "+storm_home); //create a storm configuration file with zkport final Map storm_conf = Config.readStormConfig(); storm_conf.put(backtype.storm.Config.STORM_ZOOKEEPER_PORT, zkServer.port()); storm_conf_file = testConf.createConfigFile(storm_conf); List<String> cmd = java.util.Arrays.asList("bin/storm-yarn", "launch", storm_conf_file.toString(), "--stormZip", "lib/storm.zip", "--appname", "storm-on-yarn-test", "--output", "target/appId.txt"); execute(cmd); //wait for Storm cluster to be fully luanched sleep(15000); BufferedReader reader = new BufferedReader(new FileReader ("target/appId.txt")); appId = reader.readLine(); reader.close(); if (appId!=null) appId = appId.trim(); LOG.info("application ID:"+appId); } catch (Exception ex) { LOG.error("setup failure", ex); Assert.assertEquals(null, ex); } } private static void sleep(int i) { try { Thread.sleep(i); } catch (InterruptedException e) { LOG.info("setup thread sleep interrupted. message=" + e.getMessage()); } } @Test public void performActions() throws Exception { try { List<String> cmd = java.util.Arrays.asList(STORM_YARN_CMD, "getStormConfig", storm_conf_file.toString(), "--appId", appId, "--output", storm_home+"/storm.yaml"); execute(cmd); sleep(1000); cmd = java.util.Arrays.asList(storm_home+"/bin/storm", "jar", "lib/storm-starter-0.0.1-SNAPSHOT.jar", "storm.starter.ExclamationTopology", "exclamation-topology"); execute(cmd); sleep(30000); if (new File(storm_home+"/storm.yaml").exists()) { Map storm_conf = Config.readStormConfig(storm_home+"/storm.yaml"); Nimbus.Client nimbus_client = NimbusClient.getConfiguredClient(storm_conf).getClient(); ClusterSummary cluster_summary = nimbus_client.getClusterInfo(); TopologySummary topology_summary = cluster_summary.get_topologies().get(0); Assert.assertEquals("ACTIVE", topology_summary.get_status()); } cmd = java.util.Arrays.asList(storm_home+"/bin/storm", "kill", "exclamation-topology"); execute(cmd); sleep(1000); cmd = java.util.Arrays.asList(STORM_YARN_CMD, "stopNimbus", storm_conf_file.toString(), "--appId", appId); execute(cmd); sleep(1000); cmd = java.util.Arrays.asList(STORM_YARN_CMD, "startNimbus", storm_conf_file.toString(), "--appId", appId); execute(cmd); sleep(1000); cmd = java.util.Arrays.asList(STORM_YARN_CMD, "stopUI", storm_conf_file.toString(), "--appId", appId); execute(cmd); sleep(1000); cmd = java.util.Arrays.asList(STORM_YARN_CMD, "startUI", storm_conf_file.toString(), "--appId", appId); execute(cmd); sleep(1000); } catch (Exception ex) { LOG.warn("Exception in Integration Test", ex); Assert.assertEquals(null, ex); } } @AfterClass public static void tearDown() { try { //shutdown Storm Cluster List<String> cmd = java.util.Arrays.asList(STORM_YARN_CMD, "shutdown", storm_conf_file.toString(), "--appId", appId); execute(cmd); sleep(1000); } catch (Exception ex) { LOG.info(ex.toString()); } //shutdown Zookeeper server if (zkServer != null) { zkServer.stop(); zkServer = null; } //shutdown YARN cluster if (yarnCluster != null) { LOG.info("shutdown MiniYarn cluster"); yarnCluster.stop(); yarnCluster = null; } sleep(1000); //remove configuration file testConf.cleanup(); } @SuppressWarnings({ "rawtypes", "unchecked" }) private static int execute(List<String> cmd) throws InterruptedException, IOException { LOG.info(Joiner.on(" ").join(cmd)); ProcessBuilder pb = new ProcessBuilder(cmd); Map env = pb.environment(); env.putAll(System.getenv()); env.put(Environment.PATH.name(), "bin:"+storm_home+File.separator+"bin:"+env.get(Environment.PATH.name())); String yarn_conf_dir = yarn_site_xml.getParent().toString(); env.put("STORM_YARN_CONF_DIR", yarn_conf_dir); List<URL> logback_xmls = Utils.findResources("logback.xml"); if (logback_xmls != null && logback_xmls.size()>=1) { String logback_xml = logback_xmls.get(0).getFile(); LOG.debug("logback_xml:"+yarn_conf_dir+File.separator+"logback.xml"); FileUtils.copyFile(new File(logback_xml), new File(yarn_conf_dir+File.separator+"logback.xml")); } List<URL> log4j_properties = Utils.findResources("log4j.properties"); if (log4j_properties != null && log4j_properties.size()>=1) { String log4j_properties_file = log4j_properties.get(0).getFile(); LOG.debug("log4j_properties_file:"+yarn_conf_dir+File.separator+"log4j.properties"); FileUtils.copyFile(new File(log4j_properties_file), new File(yarn_conf_dir+File.separator+"log4j.properties")); } Process proc = pb.start(); Util.redirectStreamAsync(proc.getInputStream(), System.out); Util.redirectStreamAsync(proc.getErrorStream(), System.err); int status = proc.waitFor(); return status; } }