/** * Licensed to Cloudera, Inc. under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. Cloudera, Inc. licenses this file * to you 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. */ package com.cloudera.flume.master.logical; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertTrue; import java.io.IOException; import java.util.Arrays; import java.util.Collections; import org.antlr.runtime.RecognitionException; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.junit.Before; import org.junit.Test; import com.cloudera.flume.conf.FlumeConfiguration; import com.cloudera.flume.conf.FlumeSpecException; import com.cloudera.flume.conf.PatternMatch; import com.cloudera.flume.conf.FlumeConfigData; import com.cloudera.flume.master.ConfigManager; import com.cloudera.flume.master.ConfigurationManager; import com.cloudera.flume.master.StatusManager; import com.cloudera.flume.master.StatusManager.NodeState; import com.cloudera.flume.master.availability.ConsistentHashFailoverChainManager; import com.cloudera.flume.master.availability.FailoverChainManager; import com.cloudera.flume.master.failover.FailoverConfigurationManager; import com.cloudera.util.Clock; import com.cloudera.util.NetUtils; /** * This test the logical configuration manager, and the logical configuration * manager in conjunction with the failover configuration manager. */ public class TestLogicalConfigManager { public static Logger LOG = Logger.getLogger(TestLogicalConfigManager.class); public String DEFAULTFLOW = "default-flow"; @Before public void setDebugLevel() { Logger.getRootLogger().setLevel(Level.DEBUG); Logger.getLogger(PatternMatch.class).setLevel(Level.INFO); } ConfigurationManager logical; ConfigurationManager trans; ConfigurationManager failover; StatusManager statman; /** * Instantiate and expose managers */ void setupNewManagers() { ConfigurationManager parent = new ConfigManager(); ConfigurationManager self = new ConfigManager(); FailoverChainManager fcMan = new ConsistentHashFailoverChainManager(3); ConfigurationManager self2 = new ConfigManager(); failover = new FailoverConfigurationManager(parent, self2, fcMan); statman = new StatusManager(); logical = new LogicalConfigurationManager(failover, self, statman); trans = logical; } void setupCollectorAgentConfigs() throws IOException, FlumeSpecException { // 3 collectors, one auto chain trans.setConfig("foo", DEFAULTFLOW, "autoCollectorSource", "null"); trans.setConfig("foo2", DEFAULTFLOW, "autoCollectorSource", "null"); trans.setConfig("foo3", DEFAULTFLOW, "autoCollectorSource", "null"); trans.setConfig("bar", DEFAULTFLOW, "null", "autoBEChain"); } // make it so that the local host info is present void setupHeartbeats() { String host = NetUtils.localhost(); statman.updateHeartbeatStatus(host, "physnode", "foo", NodeState.HELLO, Clock.unixTime()); statman.updateHeartbeatStatus(host, "physnode", "foo2", NodeState.HELLO, Clock.unixTime()); statman.updateHeartbeatStatus(host, "physnode", "foo3", NodeState.HELLO, Clock.unixTime()); statman.updateHeartbeatStatus(host, "physnode", "bar", NodeState.HELLO, Clock.unixTime()); } // Next mapped logical node to a physical void setupLogicalMapping() { String host = NetUtils.localhost(); trans.addLogicalNode(host, "foo"); trans.addLogicalNode(host, "foo2"); trans.addLogicalNode(host, "foo3"); trans.addLogicalNode(host, "bar"); } /** * Test the core of the LogicalConfigManager */ @Test public void testLogicalTrans() throws IOException, FlumeSpecException { ConfigurationManager parent = new ConfigManager(); ConfigurationManager self = new ConfigManager(); StatusManager statman = new StatusManager(); ConfigurationManager trans = new LogicalConfigurationManager(parent, self, statman); // make it so that the local host info is present statman.updateHeartbeatStatus("foo", "foo", "foo", NodeState.HELLO, Clock .unixTime()); statman.updateHeartbeatStatus("bar", "bar", "bar", NodeState.HELLO, Clock .unixTime()); // Next spawn so that all are mapped onto a node and now gets a physical trans.addLogicalNode("foo", "foo"); trans.addLogicalNode("bar", "bar"); // now set configs trans.setConfig("foo", DEFAULTFLOW, "logicalSource", "null"); trans.setConfig("bar", DEFAULTFLOW, "null", "logicalSink(\"foo\")"); // update the configurations trans.updateAll(); int port = FlumeConfiguration.get().getCollectorPort(); // check if translated FlumeConfigData transData = trans.getConfig("bar"); assertEquals("null", transData.getSourceConfig()); assertEquals("rpcSink( \"foo\", " + port + " )", transData.getSinkConfig()); FlumeConfigData transData2 = trans.getConfig("foo"); assertEquals("rpcSource( " + port + " )", transData2.getSourceConfig()); assertEquals("null", transData2.getSinkConfig()); // self is same as translated FlumeConfigData selfData = self.getConfig("bar"); assertEquals("null", selfData.getSourceConfig()); assertEquals("rpcSink( \"foo\", " + port + " )", selfData.getSinkConfig()); FlumeConfigData selfData2 = self.getConfig("foo"); assertEquals("rpcSource( " + port + " )", selfData2.getSourceConfig()); assertEquals("null", selfData2.getSinkConfig()); // original is the user entered values FlumeConfigData origData = parent.getConfig("bar"); assertEquals("null", origData.getSourceConfig()); assertEquals("logicalSink(\"foo\")", origData.getSinkConfig()); FlumeConfigData origData2 = parent.getConfig("foo"); assertEquals("logicalSource", origData2.getSourceConfig()); assertEquals("null", origData2.getSinkConfig()); } /** * Test interaction between LogicalConfigManager and FailoverConfigManager */ @Test public void testFailoverLogicalTrans() throws IOException, FlumeSpecException { setupNewManagers(); setupHeartbeats(); setupLogicalMapping(); setupCollectorAgentConfigs(); // update the configurations trans.updateAll(); LOG.info("Full Translation: " + trans); LOG.info("logical Translation: " + logical); LOG.info("failover Translation: " + failover); // check the interesting configurations FlumeConfigData transData = trans.getConfig("bar"); assertEquals("null", transData.getSourceConfig()); String lh = NetUtils.localhost(); String translated = "< { lazyOpen => rpcSink( \"" + lh + "\", 35853 ) } ? " + "< { lazyOpen => rpcSink( \"" + lh + "\", 35855 ) } ? " + "< { lazyOpen => rpcSink( \"" + lh + "\", 35854 ) } ? null > > >"; assertEquals(translated, transData.getSinkConfig()); FlumeConfigData transCollData = trans.getConfig("foo"); assertEquals("rpcSource( 35853 )", transCollData.getSourceConfig()); assertEquals("null", transCollData.getSinkConfig()); // intermediate data FlumeConfigData failData = failover.getConfig("bar"); assertEquals("null", failData.getSourceConfig()); String failTranslated = "< { lazyOpen => logicalSink( \"foo\" ) } ? " + "< { lazyOpen => logicalSink( \"foo3\" ) } ? " + "< { lazyOpen => logicalSink( \"foo2\" ) } ? null > > >"; assertEquals(failTranslated, failData.getSinkConfig()); } /** * This method allows tests to be setup with a arrays of strings, and then * auto checks the configurations. * * Here is the format of the data: * * { logical node name, logical source, logical sink, expected source, * substring expected in sink } **/ void manyMappingHarness(String[][] lists) throws IOException, FlumeSpecException, RecognitionException { setupNewManagers(); String host = NetUtils.localhost(); // setup nodes for (String[] objs : lists) { // register nodes in the status manager statman.updateHeartbeatStatus(host, "physnode", objs[0], NodeState.HELLO, Clock.unixTime()); // Next spawn so that all are mapped onto a node and now gets a physical trans.addLogicalNode(host, objs[0]); // set some configs trans.setConfig(objs[0], DEFAULTFLOW, objs[1], objs[2]); } // refresh all the configs so that the logical translations kick in. trans.updateAll(); // check to see physical translations. for (String[] objs : lists) { FlumeConfigData fcd = trans.getConfig(objs[0]); LOG.info(objs[0] + " " + fcd); assertEquals(objs[3], fcd.getSourceConfig()); LOG.info(fcd + " contains " + objs[4] + "?"); assertTrue(fcd.getSinkConfig().contains(objs[4])); LOG.info(fcd + " does not contain logicalSink?"); assertFalse(fcd.getSinkConfig().contains("logicalSink")); } } /** * This tests many buried logical sinks going to a single source */ @Test public void testSingleSource() throws IOException, FlumeSpecException, RecognitionException { int port = FlumeConfiguration.get().getCollectorPort(); String host = NetUtils.localhost(); String[][] lists = { { "foo", "logicalSource", "null", "rpcSource( " + port + " )", "null" }, { "bar", "null", "logicalSink(\"foo\")", "null", "rpcSink( \"" + host + "\", " + port + " )" }, { "baz", "null", "{ nullDeco => logicalSink(\"foo\") }", "null", "rpcSink( \"" + host + "\", " + port + " )" }, { "baz2", "null", "[ { nullDeco => logicalSink(\"foo\") }, console ]", "null", "rpcSink( \"" + host + "\", " + port + " )" }, { "baz3", "null", "{ nullDeco => < logicalSink(\"foo\") ? null > }", "null", "rpcSink( \"" + host + "\", " + port + " )" } }; manyMappingHarness(lists); } /** * This tests many mappings going to many other sources. Note that foo1 and * foo2 are on the same physical node, and have different auto chosen ports. */ @Test public void testManySources() throws IOException, FlumeSpecException, RecognitionException { int foo1port = FlumeConfiguration.get().getCollectorPort(); int foo2port = foo1port + 1; String host = NetUtils.localhost(); String[][] lists = { { "foo1", "logicalSource", "null", "rpcSource( " + foo1port + " )", "null" }, { "foo2", "logicalSource", "null", "rpcSource( " + foo2port + " )", "null" }, { "bar0", "null", "logicalSink(\"foo1\")", "null", "rpcSink( \"" + host + "\", " + foo1port + " )" }, { "bar1", "null", "logicalSink(\"foo2\")", "null", "rpcSink( \"" + host + "\", " + foo2port + " )" }, { "bar2", "null", "[ { nullDeco => logicalSink(\"foo1\") }, console ]", "null", "rpcSink( \"" + host + "\", " + foo1port + " )" }, { "bar3", "null", "{ nullDeco => < logicalSink(\"foo2\") ? null > }", "null", "rpcSink( \"" + host + "\", " + foo2port + " " } }; manyMappingHarness(lists); } /** * This tests many logical nodes on a single logical node. */ @Test public void testMultiSink() throws IOException, FlumeSpecException, RecognitionException { int foo1port = FlumeConfiguration.get().getCollectorPort(); int foo2port = foo1port + 1; String host = NetUtils.localhost(); String[][] lists = { { "foo1", "logicalSource", "null", "rpcSource( " + foo1port + " )", "null" }, { "foo2", "logicalSource", "null", "rpcSource( " + foo2port + " )", "null" }, { "bar0", "null", "logicalSink(\"foo1\")", "null", "rpcSink( \"" + host + "\", " + foo1port + " )" }, { "bar1", "null", "logicalSink(\"foo2\")", "null", "rpcSink( \"" + host + "\", " + foo2port + " )" }, { "bar2", "null", "[ logicalSink(\"foo1\"), logicalSink(\"foo2\"), logicalSink(\"foo1\"), logicalSink(\"foo2\"), console ]", "null", "rpcSink( \"" + host + "\", " + foo1port + " )" }, { "bar3", "null", "< logicalSink(\"foo2\") ? <logicalSink(\"foo1\") ? logicalSink(\"foo1\") > > ", "null", "rpcSink( \"" + host + "\", " + foo2port + " " } }; manyMappingHarness(lists); } /** * Test to ensure attempts to map a single logical node to multiple physicals * is discarded with a warning. This may be exception worthy. */ @Test public void testDuplicateAssignment() { ConfigurationManager parent = new ConfigManager(); ConfigurationManager self = new ConfigManager(); StatusManager statman = new StatusManager(); ConfigurationManager trans = new LogicalConfigurationManager(parent, self, statman); trans.addLogicalNode("hostA", "foo"); assertEquals(1, trans.getLogicalNodeMap().size()); trans.addLogicalNode("hostB", "foo"); assertEquals(1, trans.getLogicalNodeMap().size()); assertEquals(Arrays.asList("foo"), trans.getLogicalNode("hostA")); assertEquals(Collections.EMPTY_LIST, trans.getLogicalNode("hostB")); } /** * This tests many logical nodes on a single logical node going through a * roller */ @Test public void testRollSink() throws IOException, FlumeSpecException, RecognitionException { int foo1port = FlumeConfiguration.get().getCollectorPort(); int foo2port = foo1port + 1; String host = NetUtils.localhost(); String[][] lists = { { "foo1", "logicalSource", "null", "rpcSource( " + foo1port + " )", "null" }, { "foo2", "logicalSource", "null", "rpcSource( " + foo2port + " )", "null" }, { "bar0", "null", "logicalSink(\"foo1\")", "null", "rpcSink( \"" + host + "\", " + foo1port + " )" }, { "bar1", "null", "logicalSink(\"foo2\")", "null", "rpcSink( \"" + host + "\", " + foo2port + " )" }, { "bar2", "null", "roll(200) { < logicalSink(\"foo1\") ? logicalSink(\"foo2\") > }", "null", "rpcSink( \"" + host + "\", " + foo1port + " )" }, }; manyMappingHarness(lists); } /** * This tests interaction between LogicalConfigManager and * FailoverConfigManager. This verifies that auto*Chains eventually and get * translated to physical sinks/sources */ @Test public void testAutoChainSink() throws IOException, FlumeSpecException, RecognitionException { int foo1port = FlumeConfiguration.get().getCollectorPort(); int foo2port = foo1port + 1; String host = NetUtils.localhost(); String[][] lists = { { "foo1", "autoCollectorSource", "null", "rpcSource( 35853 )", "null" }, { "foo2", "autoCollectorSource", "null", "rpcSource( 35854 )", "null" }, { "bar0", "null", "autoBEChain", "null", "rpcSink( \"" + host + "\", " + foo1port + " )" }, { "bar1", "null", "autoDFOChain", "null", "rpcSink( \"" + host + "\", " + foo2port + " )" }, { "bar2", "null", "autoE2EChain", "null", "rpcSink( \"" + host + "\", " + foo1port + " )" }, }; manyMappingHarness(lists); } /** * Test interaction between LogicalConfigManager and FailoverConfigManager */ @Test public void testMultipleRefreshes() throws IOException, FlumeSpecException { setupNewManagers(); setupHeartbeats(); setupLogicalMapping(); setupCollectorAgentConfigs(); // update the configurations trans.updateAll(); FlumeConfigData transData0 = trans.getConfig("bar"); assertEquals("null", transData0.getSourceConfig()); String lh = NetUtils.localhost(); String translated = "< { lazyOpen => rpcSink( \"" + lh + "\", 35853 ) } ? " + "< { lazyOpen => rpcSink( \"" + lh + "\", 35855 ) } ? " + "< { lazyOpen => rpcSink( \"" + lh + "\", 35854 ) } ? null > > >"; assertEquals(translated, transData0.getSinkConfig()); trans.updateAll(); FlumeConfigData transData = trans.getConfig("bar"); assertEquals("null", transData.getSourceConfig()); assertEquals(translated, transData.getSinkConfig()); FlumeConfigData transCollData = trans.getConfig("foo"); assertEquals("rpcSource( 35853 )", transCollData.getSourceConfig()); assertEquals("null", transCollData.getSinkConfig()); trans.updateAll(); transData = trans.getConfig("bar"); assertEquals("null", transData.getSourceConfig()); assertEquals(translated, transData.getSinkConfig()); transCollData = trans.getConfig("foo"); assertEquals("rpcSource( 35853 )", transCollData.getSourceConfig()); assertEquals("null", transCollData.getSinkConfig()); trans.updateAll(); LOG.info("Full Translation: " + trans); LOG.info("logical Translation: " + logical); LOG.info("failover Translation: " + failover); transData = trans.getConfig("bar"); assertEquals("null", transData.getSourceConfig()); assertEquals(translated, transData.getSinkConfig()); transCollData = trans.getConfig("foo"); assertEquals("rpcSource( 35853 )", transCollData.getSourceConfig()); assertEquals("null", transCollData.getSinkConfig()); // intermediate data FlumeConfigData failData = failover.getConfig("bar"); assertEquals("null", failData.getSourceConfig()); String failTranslated = "< { lazyOpen => logicalSink( \"foo\" ) } ? " + "< { lazyOpen => logicalSink( \"foo3\" ) } ? " + "< { lazyOpen => logicalSink( \"foo2\" ) } ? null > > >"; assertEquals(failTranslated, failData.getSinkConfig()); } /** * Test incremental version stamp updating with no changes. */ @Test public void testMultipleUpdates() throws IOException, FlumeSpecException { setupNewManagers(); setupHeartbeats(); setupLogicalMapping(); setupCollectorAgentConfigs(); // update the configurations trans.updateAll(); LOG.info("Full Translation: " + trans); LOG.info("logical Translation: " + logical); LOG.info("failover Translation: " + failover); FlumeConfigData transData0 = trans.getConfig("bar"); assertEquals("null", transData0.getSourceConfig()); String lh = NetUtils.localhost(); String translated = "< { lazyOpen => rpcSink( \"" + lh + "\", 35853 ) } ? " + "< { lazyOpen => rpcSink( \"" + lh + "\", 35855 ) } ? " + "< { lazyOpen => rpcSink( \"" + lh + "\", 35854 ) } ? null > > >"; assertEquals(translated, transData0.getSinkConfig()); trans.updateAll(); FlumeConfigData transData = trans.getConfig("bar"); long barVer = transData.getTimestamp(); assertEquals("null", transData.getSourceConfig()); assertEquals(translated, transData.getSinkConfig()); FlumeConfigData transCollData = trans.getConfig("foo"); long fooVer = transCollData.getTimestamp(); assertEquals("rpcSource( 35853 )", transCollData.getSourceConfig()); assertEquals("null", transCollData.getSinkConfig()); trans.updateAll(); transData = trans.getConfig("bar"); assertEquals(barVer, transData.getTimestamp()); assertEquals("null", transData.getSourceConfig()); assertEquals(translated, transData.getSinkConfig()); transCollData = trans.getConfig("foo"); assertEquals(fooVer, transCollData.getTimestamp()); assertEquals("rpcSource( 35853 )", transCollData.getSourceConfig()); assertEquals("null", transCollData.getSinkConfig()); trans.updateAll(); // TODO (jon) Ideally, this shouldn't be necessary LOG.info("Full Translation: " + trans); LOG.info("Logical Translation: " + logical); LOG.info("Failover Translation: " + failover); transData = trans.getConfig("bar"); assertEquals(barVer, transData.getTimestamp()); assertEquals("null", transData.getSourceConfig()); assertEquals(translated, transData.getSinkConfig()); transCollData = trans.getConfig("foo"); assertEquals(fooVer, transCollData.getTimestamp()); assertEquals("rpcSource( 35853 )", transCollData.getSourceConfig()); assertEquals("null", transCollData.getSinkConfig()); // intermediate data FlumeConfigData failData = failover.getConfig("bar"); assertEquals("null", failData.getSourceConfig()); String failTranslated = "< { lazyOpen => logicalSink( \"foo\" ) } ? " + "< { lazyOpen => logicalSink( \"foo3\" ) } ? " + "< { lazyOpen => logicalSink( \"foo2\" ) } ? null > > >"; assertEquals(failTranslated, failData.getSinkConfig()); } /** * Test changes to configuration and incremental version stamp changes. */ @Test public void testUnconfigures() throws IOException, FlumeSpecException { setupNewManagers(); setupHeartbeats(); setupLogicalMapping(); setupCollectorAgentConfigs(); // Look, no explicit update to the configurations! // foo3 is no longer a collector long fooVer = trans.getConfig("foo").getTimestamp(); long foo2Ver = trans.getConfig("foo2").getTimestamp(); long foo3Ver = trans.getConfig("foo3").getTimestamp(); long barVer = trans.getConfig("bar").getTimestamp(); trans.setConfig("foo3", DEFAULTFLOW, "null", "null"); // Look, no explicit update to the configurations! LOG.info("Full Translation: " + trans); LOG.info("logical Translation: " + logical); LOG.info("failover Translation: " + failover); FlumeConfigData transData = trans.getConfig("bar"); assertEquals("null", transData.getSourceConfig()); String lh = NetUtils.localhost(); String translated = "< { lazyOpen => rpcSink( \"" + lh + "\", 35853 ) } ? " + "< { lazyOpen => rpcSink( \"" + lh + "\", 35854 ) } ? null > >"; assertEquals(translated, transData.getSinkConfig()); FlumeConfigData transCollData = trans.getConfig("foo"); assertEquals("rpcSource( 35853 )", transCollData.getSourceConfig()); assertEquals("null", transCollData.getSinkConfig()); assertEquals(fooVer, trans.getConfig("foo").getTimestamp()); assertEquals(foo2Ver, trans.getConfig("foo2").getTimestamp()); assertNotSame(foo3Ver, trans.getConfig("foo3").getTimestamp()); foo3Ver = trans.getConfig("foo3").getTimestamp(); assertNotSame(barVer, trans.getConfig("bar").getTimestamp()); barVer = trans.getConfig("bar").getTimestamp(); // intermediate data FlumeConfigData failData = failover.getConfig("bar"); assertEquals("null", failData.getSourceConfig()); String failTranslated = "< { lazyOpen => logicalSink( \"foo\" ) } ? " + "< { lazyOpen => logicalSink( \"foo2\" ) } ? null > >"; assertEquals(failTranslated, failData.getSinkConfig()); assertEquals(fooVer, trans.getConfig("foo").getTimestamp()); assertEquals(foo2Ver, trans.getConfig("foo2").getTimestamp()); assertEquals(foo3Ver, trans.getConfig("foo3").getTimestamp()); assertEquals(barVer, trans.getConfig("bar").getTimestamp()); } /** * This initially has many logical nodes, that are not mapped to a physical * node (never heartbeated). We then "trigger" a heart beat adding one at a * time and watch the translated configuration change. * * Any failed translations are wrapped with a 'fail' sink which just throws * exceptions. These are still valid configurations, and will just failover if * in a failover configuration. */ @Test public void testNoPhysicalNode() throws IOException, FlumeSpecException { setupNewManagers(); // NO local host information present to make physical node! setupLogicalMapping(); setupCollectorAgentConfigs(); // update the configurations trans.updateAll(); FlumeConfigData transData0 = trans.getConfig("bar"); assertEquals("null", transData0.getSourceConfig()); String lh = NetUtils.localhost(); String first = "< { lazyOpen => fail( \"logicalSink( \\\"foo\\\" )\" ) } ? " + "< { lazyOpen => fail( \"logicalSink( \\\"foo3\\\" )\" ) } ? " + "< { lazyOpen => fail( \"logicalSink( \\\"foo2\\\" )\" ) } ? null > > >"; assertEquals(first, transData0.getSinkConfig()); // update one at a time and check config statman.updateHeartbeatStatus(NetUtils.localhost(), "physnode", "foo", NodeState.HELLO, Clock.unixTime()); trans.updateAll(); // TODO remove String second = "< { lazyOpen => rpcSink( \"" + lh + "\", 35853 ) } ? " + "< { lazyOpen => fail( \"logicalSink( \\\"foo3\\\" )\" ) } ? " + "< { lazyOpen => fail( \"logicalSink( \\\"foo2\\\" )\" ) } ? null > > >"; FlumeConfigData transData = trans.getConfig("bar"); assertEquals("null", transData.getSourceConfig()); assertEquals(second, transData.getSinkConfig()); FlumeConfigData transCollData = trans.getConfig("foo"); assertEquals("rpcSource( 35853 )", transCollData.getSourceConfig()); assertEquals("null", transCollData.getSinkConfig()); // update one at a time and check config statman.updateHeartbeatStatus(NetUtils.localhost(), "physnode", "foo2", NodeState.HELLO, Clock.unixTime()); trans.updateAll(); String third = "< { lazyOpen => rpcSink( \"" + lh + "\", 35853 ) } ? " + "< { lazyOpen => fail( \"logicalSink( \\\"foo3\\\" )\" ) } ? " + "< { lazyOpen => rpcSink( \"" + lh + "\", 35854 ) } ? null > > >"; transData = trans.getConfig("bar"); assertEquals("null", transData.getSourceConfig()); assertEquals(third, transData.getSinkConfig()); String translated = "< { lazyOpen => rpcSink( \"" + lh + "\", 35853 ) } ? " + "< { lazyOpen => rpcSink( \"" + lh + "\", 35855 ) } ? " + "< { lazyOpen => rpcSink( \"" + lh + "\", 35854 ) } ? null > > >"; transCollData = trans.getConfig("foo"); assertEquals("rpcSource( 35853 )", transCollData.getSourceConfig()); assertEquals("null", transCollData.getSinkConfig()); statman.updateHeartbeatStatus(NetUtils.localhost(), "physnode", "foo3", NodeState.HELLO, Clock.unixTime()); trans.updateAll(); LOG.info("Full Translation: " + trans); LOG.info("logical Translation: " + logical); LOG.info("failover Translation: " + failover); transData = trans.getConfig("bar"); assertEquals("null", transData.getSourceConfig()); assertEquals(translated, transData.getSinkConfig()); transCollData = trans.getConfig("foo"); assertEquals("rpcSource( 35853 )", transCollData.getSourceConfig()); assertEquals("null", transCollData.getSinkConfig()); // intermediate data FlumeConfigData failData = failover.getConfig("bar"); assertEquals("null", failData.getSourceConfig()); String failTranslated = "< { lazyOpen => logicalSink( \"foo\" ) } ? " + "< { lazyOpen => logicalSink( \"foo3\" ) } ? " + "< { lazyOpen => logicalSink( \"foo2\" ) } ? null > > >"; assertEquals(failTranslated, failData.getSinkConfig()); } /** * We knock out a node. What is the right behavior? Use old information. */ @Test public void testPhysicalNodeLost() throws IOException, FlumeSpecException { setupNewManagers(); setupLogicalMapping(); // No local host information present to make physical node! setupCollectorAgentConfigs(); // update the configurations trans.updateAll(); FlumeConfigData transData0 = trans.getConfig("bar"); assertEquals("null", transData0.getSourceConfig()); String lh = NetUtils.localhost(); String first = "< { lazyOpen => fail( \"logicalSink( \\\"foo\\\" )\" ) } ? " + "< { lazyOpen => fail( \"logicalSink( \\\"foo3\\\" )\" ) } ? " + "< { lazyOpen => fail( \"logicalSink( \\\"foo2\\\" )\" ) } ? null > > >"; assertEquals(first, transData0.getSinkConfig()); // update one at a time and check config statman.updateHeartbeatStatus(NetUtils.localhost(), "physnode", "foo", NodeState.HELLO, Clock.unixTime()); trans.updateAll(); // TODO remove String second = "< { lazyOpen => rpcSink( \"" + lh + "\", 35853 ) } ? " + "< { lazyOpen => fail( \"logicalSink( \\\"foo3\\\" )\" ) } ? " + "< { lazyOpen => fail( \"logicalSink( \\\"foo2\\\" )\" ) } ? null > > >"; FlumeConfigData transData = trans.getConfig("bar"); assertEquals("null", transData.getSourceConfig()); assertEquals(second, transData.getSinkConfig()); FlumeConfigData transCollData = trans.getConfig("foo"); assertEquals("rpcSource( 35853 )", transCollData.getSourceConfig()); assertEquals("null", transCollData.getSinkConfig()); // We knock out a node. What is the right behavior? Use old information. statman.updateHeartbeatStatus(NetUtils.localhost(), "physnode", "foo", NodeState.LOST, Clock.unixTime()); trans.updateAll(); // TODO remove String third = "< { lazyOpen => rpcSink( \"" + lh + "\", 35853 ) } ? " + "< { lazyOpen => fail( \"logicalSink( \\\"foo3\\\" )\" ) } ? " + "< { lazyOpen => fail( \"logicalSink( \\\"foo2\\\" )\" ) } ? null > > >"; transData = trans.getConfig("bar"); assertEquals("null", transData.getSourceConfig()); assertEquals(third, transData.getSinkConfig()); transCollData = trans.getConfig("foo"); assertEquals("rpcSource( 35853 )", transCollData.getSourceConfig()); assertEquals("null", transCollData.getSinkConfig()); } /** * An unmap command should force the logical sources/sinks to revert to failed * state. */ @Test public void testUpdateAfterUnmapAll() throws IOException, FlumeSpecException { setupNewManagers(); setupHeartbeats(); setupLogicalMapping(); setupCollectorAgentConfigs(); // update the configurations trans.updateAll(); String lh = NetUtils.localhost(); String translated = "< { lazyOpen => rpcSink( \"" + lh + "\", 35853 ) } ? " + "< { lazyOpen => rpcSink( \"" + lh + "\", 35855 ) } ? " + "< { lazyOpen => rpcSink( \"" + lh + "\", 35854 ) } ? null > > >"; FlumeConfigData transCollData = trans.getConfig("foo"); assertEquals("rpcSource( 35853 )", transCollData.getSourceConfig()); assertEquals("null", transCollData.getSinkConfig()); statman.updateHeartbeatStatus(NetUtils.localhost(), "physnode", "foo3", NodeState.HELLO, Clock.unixTime()); trans.updateAll(); LOG.info("Full Translation: " + trans); LOG.info("logical Translation: " + logical); LOG.info("failover Translation: " + failover); FlumeConfigData transData = trans.getConfig("bar"); assertEquals("null", transData.getSourceConfig()); assertEquals(translated, transData.getSinkConfig()); transCollData = trans.getConfig("foo"); assertEquals("rpcSource( 35853 )", transCollData.getSourceConfig()); assertEquals("null", transCollData.getSinkConfig()); // // // Unmap all the nodes. // // trans.unmapAllLogicalNodes(); // This should go back to the failed state FlumeConfigData transData0 = trans.getConfig("bar"); assertEquals("null", transData0.getSourceConfig()); String first = "< { lazyOpen => fail( \"logicalSink( \\\"foo\\\" )\" ) } ? " + "< { lazyOpen => fail( \"logicalSink( \\\"foo3\\\" )\" ) } ? " + "< { lazyOpen => fail( \"logicalSink( \\\"foo2\\\" )\" ) } ? null > > >"; assertEquals(first, transData0.getSinkConfig()); } }