001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.chaos;
019
020import java.net.InetAddress;
021import java.net.UnknownHostException;
022import java.util.Arrays;
023import java.util.Collection;
024import org.apache.hadoop.conf.Configuration;
025import org.apache.hadoop.hbase.AuthUtil;
026import org.apache.hadoop.hbase.ChoreService;
027import org.apache.hadoop.hbase.HBaseConfiguration;
028import org.apache.hadoop.hbase.ScheduledChore;
029import org.apache.hadoop.hbase.zookeeper.ZKConfig;
030import org.apache.hadoop.util.GenericOptionsParser;
031import org.apache.yetus.audience.InterfaceAudience;
032import org.slf4j.Logger;
033import org.slf4j.LoggerFactory;
034
035import org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLine;
036import org.apache.hbase.thirdparty.org.apache.commons.cli.GnuParser;
037import org.apache.hbase.thirdparty.org.apache.commons.cli.Option;
038import org.apache.hbase.thirdparty.org.apache.commons.cli.Options;
039
040/**
041 * Class used to start/stop Chaos related services (currently chaosagent)
042 */
043@InterfaceAudience.Private
044public class ChaosService {
045
046  private static final Logger LOG = LoggerFactory.getLogger(ChaosService.class.getName());
047
048  public static void execute(String[] args, Configuration conf) {
049    LOG.info("arguments : " + Arrays.toString(args));
050
051    try {
052      CommandLine cmdline = new GnuParser().parse(getOptions(), args);
053      if (cmdline.hasOption(ChaosServiceName.CHAOSAGENT.toString().toLowerCase())) {
054        String actionStr =
055          cmdline.getOptionValue(ChaosServiceName.CHAOSAGENT.toString().toLowerCase());
056        try {
057          ExecutorAction action = ExecutorAction.valueOf(actionStr.toUpperCase());
058          if (action == ExecutorAction.START) {
059            ChaosServiceStart(conf, ChaosServiceName.CHAOSAGENT);
060          } else if (action == ExecutorAction.STOP) {
061            ChaosServiceStop();
062          }
063        } catch (IllegalArgumentException e) {
064          LOG.error("action passed: {} Unexpected action. Please provide only start/stop.",
065            actionStr, e);
066          throw new RuntimeException(e);
067        }
068      } else {
069        LOG.error("Invalid Options");
070      }
071    } catch (Exception e) {
072      LOG.error("Error while starting ChaosService : ", e);
073    }
074  }
075
076  private static void ChaosServiceStart(Configuration conf, ChaosServiceName serviceName) {
077    switch (serviceName) {
078      case CHAOSAGENT:
079        ChaosAgent.stopChaosAgent.set(false);
080        try {
081          String hostname = InetAddress.getLocalHost().getHostName();
082          String quorum = ZKConfig.getZKQuorumServersString(conf);
083          LOG.info("Starting the ChaosAgent with hostname: {}, quorum: {}", hostname, quorum);
084
085          Thread t = new Thread(new ChaosAgent(conf, quorum, hostname));
086          t.start();
087          t.join();
088        } catch (InterruptedException | UnknownHostException e) {
089          LOG.error("Failed while executing next task execution of ChaosAgent on : {}", serviceName,
090            e);
091        }
092        break;
093      default:
094        LOG.error("Service Name not known : " + serviceName.toString());
095    }
096  }
097
098  private static void ChaosServiceStop() {
099    ChaosAgent.stopChaosAgent.set(true);
100  }
101
102  private static Options getOptions() {
103    Options options = new Options();
104    options.addOption(new Option("c", ChaosServiceName.CHAOSAGENT.toString().toLowerCase(), true,
105      "expecting a start/stop argument"));
106    options
107      .addOption(new Option("D", ChaosServiceName.GENERIC.toString(), true, "generic D param"));
108    LOG.info(Arrays.toString(new Collection[] { options.getOptions() }));
109    return options;
110  }
111
112  public static void main(String[] args) throws Exception {
113    Configuration conf = HBaseConfiguration.create();
114    new GenericOptionsParser(conf, args);
115
116    ChoreService choreChaosService = null;
117    ScheduledChore authChore = AuthUtil.getAuthChore(conf);
118
119    try {
120      if (authChore != null) {
121        choreChaosService = new ChoreService(ChaosConstants.CHORE_SERVICE_PREFIX);
122        choreChaosService.scheduleChore(authChore);
123      }
124
125      execute(args, conf);
126    } finally {
127      if (authChore != null) choreChaosService.shutdown();
128    }
129  }
130
131  enum ChaosServiceName {
132    CHAOSAGENT,
133    GENERIC
134  }
135
136  enum ExecutorAction {
137    START,
138    STOP
139  }
140}