View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  package org.apache.hadoop.hbase;
20  
21  import java.io.IOException;
22  import java.util.Properties;
23  import java.util.Set;
24  
25  import org.apache.commons.cli.CommandLine;
26  import org.apache.commons.lang.StringUtils;
27  import org.apache.commons.logging.Log;
28  import org.apache.commons.logging.LogFactory;
29  import org.apache.hadoop.conf.Configuration;
30  import org.apache.hadoop.hbase.chaos.factories.MonkeyFactory;
31  import org.apache.hadoop.hbase.chaos.monkies.ChaosMonkey;
32  import org.apache.hadoop.hbase.util.AbstractHBaseTool;
33  import org.junit.After;
34  import org.junit.Before;
35  
36  /**
37   * Base class for HBase integration tests that want to use the Chaos Monkey.
38   * Usage: bin/hbase <sub_class_of_IntegrationTestBase> <options>
39   * Options: -h,--help Show usage
40   *          -m,--monkey <arg> Which chaos monkey to run
41   *          -monkeyProps <arg> The properties file for specifying chaos monkey properties.
42   *          -ncc Option to not clean up the cluster at the end.
43   */
44  public abstract class IntegrationTestBase extends AbstractHBaseTool {
45    public static final String LONG_OPT = "monkey";
46    public static final String CHAOS_MONKEY_PROPS = "monkeyProps";
47    private static final Log LOG = LogFactory.getLog(IntegrationTestBase.class);
48  
49    protected IntegrationTestingUtility util;
50    protected ChaosMonkey monkey;
51    protected String monkeyToUse;
52    protected Properties monkeyProps;
53  
54    public IntegrationTestBase() {
55      this(null);
56    }
57  
58    public IntegrationTestBase(String monkeyToUse) {
59      this.monkeyToUse = monkeyToUse;
60    }
61  
62    @Override
63    protected void addOptions() {
64      addOptWithArg("m", LONG_OPT, "Which chaos monkey to run");
65      addOptWithArg(CHAOS_MONKEY_PROPS, "The properties file for specifying chaos "
66          + "monkey properties.");
67    }
68  
69    @Override
70    protected void processOptions(CommandLine cmd) {
71      if (cmd.hasOption(LONG_OPT)) {
72        monkeyToUse = cmd.getOptionValue(LONG_OPT);
73      }
74      monkeyProps = new Properties();
75      if (cmd.hasOption(CHAOS_MONKEY_PROPS)) {
76        String chaosMonkeyPropsFile = cmd.getOptionValue(CHAOS_MONKEY_PROPS);
77        if (StringUtils.isNotEmpty(chaosMonkeyPropsFile)) {
78          try {
79            monkeyProps.load(this.getClass().getClassLoader()
80                .getResourceAsStream(chaosMonkeyPropsFile));
81          } catch (IOException e) {
82            LOG.warn(e);
83            System.exit(EXIT_FAILURE);
84          }
85        }
86      }
87    }
88  
89    @Override
90    public Configuration getConf() {
91      Configuration c = super.getConf();
92      if (c == null && util != null) {
93        conf = util.getConfiguration();
94        c = conf;
95      }
96      return c;
97    }
98  
99    @Override
100   protected int doWork() throws Exception {
101     setUp();
102     int result = -1;
103     try {
104       result = runTestFromCommandLine();
105     } finally {
106       cleanUp();
107     }
108 
109     return result;
110   }
111 
112   @Before
113   public void setUp() throws Exception {
114     setUpCluster();
115     setUpMonkey();
116   }
117 
118   @After
119   public void cleanUp() throws Exception {
120     cleanUpMonkey();
121     cleanUpCluster();
122   }
123 
124   public void setUpMonkey() throws Exception {
125     util = getTestingUtil(getConf());
126     MonkeyFactory fact = MonkeyFactory.getFactory(monkeyToUse);
127     if (fact == null) {
128       fact = getDefaultMonkeyFactory();
129     }
130     monkey = fact.setUtil(util)
131                  .setTableName(getTablename())
132                  .setProperties(monkeyProps)
133                  .setColumnFamilies(getColumnFamilies()).build();
134     startMonkey();
135   }
136 
137   protected void startMonkey() throws Exception {
138     monkey.start();
139   }
140 
141   public void cleanUpMonkey() throws Exception {
142     cleanUpMonkey("Ending test");
143   }
144 
145   protected void cleanUpMonkey(String why) throws Exception {
146     if (monkey != null && !monkey.isStopped()) {
147       monkey.stop(why);
148       monkey.waitForStop();
149     }
150   }
151 
152   protected IntegrationTestingUtility getTestingUtil(Configuration conf) {
153     if (this.util == null) {
154       if (conf == null) {
155         this.util = new IntegrationTestingUtility();
156         this.setConf(util.getConfiguration());
157       } else {
158         this.util = new IntegrationTestingUtility(conf);
159       }
160     }
161     return util;
162   }
163   
164   protected MonkeyFactory getDefaultMonkeyFactory() {
165     return MonkeyFactory.getFactory(
166         util.isDistributedCluster() ? MonkeyFactory.CALM : MonkeyFactory.SLOW_DETERMINISTIC);
167   }
168 
169   public abstract void setUpCluster() throws Exception;
170 
171   public void cleanUpCluster() throws Exception {
172     if (!util.isDistributedCluster() ||  (monkey != null && monkey.isDestructive())) {
173       LOG.debug("Restoring the cluster");
174       util.restoreCluster();
175       LOG.debug("Done restoring the cluster");
176     }
177   }
178 
179   public abstract int runTestFromCommandLine() throws Exception;
180 
181   public abstract String getTablename();
182 
183   protected abstract Set<String> getColumnFamilies();
184 }