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  package org.apache.hadoop.hbase.chaos.util;
19  
20  import java.io.IOException;
21  import java.util.Properties;
22  import java.util.Set;
23  
24  import org.apache.commons.cli.CommandLine;
25  import org.apache.commons.lang.StringUtils;
26  import org.apache.commons.logging.Log;
27  import org.apache.commons.logging.LogFactory;
28  import org.apache.hadoop.conf.Configuration;
29  import org.apache.hadoop.hbase.HBaseConfiguration;
30  import org.apache.hadoop.hbase.HConstants;
31  import org.apache.hadoop.hbase.IntegrationTestingUtility;
32  import org.apache.hadoop.hbase.TableName;
33  import org.apache.hadoop.hbase.chaos.factories.MonkeyFactory;
34  import org.apache.hadoop.hbase.chaos.monkies.ChaosMonkey;
35  import org.apache.hadoop.hbase.util.AbstractHBaseTool;
36  import org.apache.hadoop.util.ToolRunner;
37  
38  import com.google.common.collect.Sets;
39  
40  public class ChaosMonkeyRunner extends AbstractHBaseTool {
41    private static final Log LOG = LogFactory.getLog(ChaosMonkeyRunner.class);
42  
43    public static final String MONKEY_LONG_OPT = "monkey";
44    public static final String CHAOS_MONKEY_PROPS = "monkeyProps";
45    public static final String TABLE_NAME_OPT = "tableName";
46    public static final String FAMILY_NAME_OPT = "familyName";
47  
48    protected IntegrationTestingUtility util;
49    protected ChaosMonkey monkey;
50    protected String monkeyToUse;
51    protected Properties monkeyProps;
52    protected boolean noClusterCleanUp = false;
53    private String tableName = "ChaosMonkeyRunner.tableName";
54    private String familyName = "ChaosMonkeyRunner.familyName";
55  
56    @Override
57    public void addOptions() {
58      addOptWithArg("m", MONKEY_LONG_OPT, "Which chaos monkey to run");
59      addOptWithArg(CHAOS_MONKEY_PROPS, "The properties file for specifying chaos "
60          + "monkey properties.");
61      addOptWithArg(TABLE_NAME_OPT, "Table name in the test to run chaos monkey against");
62      addOptWithArg(FAMILY_NAME_OPT, "Family name in the test to run chaos monkey against");
63    }
64  
65    @Override
66    protected void processOptions(CommandLine cmd) {
67      if (cmd.hasOption(MONKEY_LONG_OPT)) {
68        monkeyToUse = cmd.getOptionValue(MONKEY_LONG_OPT);
69      }
70      monkeyProps = new Properties();
71      if (cmd.hasOption(CHAOS_MONKEY_PROPS)) {
72        String chaosMonkeyPropsFile = cmd.getOptionValue(CHAOS_MONKEY_PROPS);
73        if (StringUtils.isNotEmpty(chaosMonkeyPropsFile)) {
74          try {
75            monkeyProps.load(this.getClass().getClassLoader()
76                .getResourceAsStream(chaosMonkeyPropsFile));
77          } catch (IOException e) {
78            LOG.warn(e);
79            System.exit(EXIT_FAILURE);
80          }
81        }
82      }
83      if (cmd.hasOption(TABLE_NAME_OPT)) {
84        this.tableName = cmd.getOptionValue(TABLE_NAME_OPT);
85      }
86      if (cmd.hasOption(FAMILY_NAME_OPT)) {
87        this.familyName = cmd.getOptionValue(FAMILY_NAME_OPT);
88      }
89    }
90  
91    @Override
92    protected int doWork() throws Exception {
93      setUpCluster();
94      getAndStartMonkey();
95      while (!monkey.isStopped()) {
96        // loop here until got killed
97        try{
98          Thread.sleep(5000);
99        } catch (InterruptedException ite) {
100         // Chaos monkeys got interrupted.
101         // It is ok to stop monkeys and exit.
102         monkey.stop("Interruption occurred.");
103         break;
104       }
105     }
106     monkey.waitForStop();
107     return 0;
108   }
109 
110 
111   public void stopRunner() {
112     if (monkey != null) {
113       monkey.stop("Program Control");
114     }
115   }
116 
117   public void setUpCluster() throws Exception {
118     util = getTestingUtil(getConf());
119     boolean isDistributed = isDistributedCluster(getConf());
120     if (isDistributed) {
121       util.createDistributedHBaseCluster();
122       util.checkNodeCount(1);// make sure there's at least 1 alive rs
123     } else {
124       throw new RuntimeException("ChaosMonkeyRunner must run against a distributed cluster,"
125           + " please check and point to the right configuration dir");
126     }
127     this.setConf(util.getConfiguration());
128   }
129 
130   private boolean isDistributedCluster(Configuration conf) {
131     return conf.getBoolean(HConstants.CLUSTER_DISTRIBUTED, false);
132   }
133 
134   public void getAndStartMonkey() throws Exception {
135     util = getTestingUtil(getConf());
136     MonkeyFactory fact = MonkeyFactory.getFactory(monkeyToUse);
137     if (fact == null) {
138       fact = getDefaultMonkeyFactory();
139     }
140     monkey =
141         fact.setUtil(util).setTableName(getTablename()).setProperties(monkeyProps)
142             .setColumnFamilies(getColumnFamilies()).build();
143     monkey.start();
144   }
145 
146   protected IntegrationTestingUtility getTestingUtil(Configuration conf) {
147     if (this.util == null) {
148       if (conf == null) {
149         this.util = new IntegrationTestingUtility();
150         this.setConf(util.getConfiguration());
151       } else {
152         this.util = new IntegrationTestingUtility(conf);
153       }
154     }
155     return util;
156   }
157 
158   protected MonkeyFactory getDefaultMonkeyFactory() {
159     // Run with slow deterministic monkey by default
160     return MonkeyFactory.getFactory(MonkeyFactory.SLOW_DETERMINISTIC);
161   }
162 
163   public TableName getTablename() {
164     return TableName.valueOf(tableName);
165   }
166 
167   protected Set<String> getColumnFamilies() {
168     return Sets.newHashSet(familyName);
169   }
170 
171   public static void main(String[] args) throws Exception {
172     Configuration conf = HBaseConfiguration.create();
173     IntegrationTestingUtility.setUseDistributedCluster(conf);
174     int ret = ToolRunner.run(conf, new ChaosMonkeyRunner(), args);
175     System.exit(ret);
176   }
177 
178 }