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.UnknownHostException;
021import java.util.Arrays;
022import java.util.Collection;
023import org.apache.hadoop.conf.Configuration;
024import org.apache.hadoop.hbase.AuthUtil;
025import org.apache.hadoop.hbase.ChoreService;
026import org.apache.hadoop.hbase.HBaseConfiguration;
027import org.apache.hadoop.hbase.ScheduledChore;
028import org.apache.hadoop.util.GenericOptionsParser;
029import org.apache.yetus.audience.InterfaceAudience;
030import org.slf4j.Logger;
031import org.slf4j.LoggerFactory;
032
033import org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLine;
034import org.apache.hbase.thirdparty.org.apache.commons.cli.GnuParser;
035import org.apache.hbase.thirdparty.org.apache.commons.cli.Option;
036import org.apache.hbase.thirdparty.org.apache.commons.cli.Options;
037
038/**
039 * Class used to start/stop Chaos related services (currently chaosagent)
040 */
041@InterfaceAudience.Private
042public class ChaosService {
043
044  private static final Logger LOG = LoggerFactory.getLogger(ChaosService.class.getName());
045
046  public static void execute(String[] args, Configuration conf) {
047    LOG.info("arguments : " + Arrays.toString(args));
048
049    try {
050      CommandLine cmdline = new GnuParser().parse(getOptions(), args);
051      if (cmdline.hasOption(ChaosServiceName.CHAOSAGENT.toString().toLowerCase())) {
052        String actionStr =
053          cmdline.getOptionValue(ChaosServiceName.CHAOSAGENT.toString().toLowerCase());
054        try {
055          ExecutorAction action = ExecutorAction.valueOf(actionStr.toUpperCase());
056          if (action == ExecutorAction.START) {
057            ChaosServiceStart(conf, ChaosServiceName.CHAOSAGENT);
058          } else if (action == ExecutorAction.STOP) {
059            ChaosServiceStop();
060          }
061        } catch (IllegalArgumentException e) {
062          LOG.error("action passed: {} Unexpected action. Please provide only start/stop.",
063            actionStr, e);
064          throw new RuntimeException(e);
065        }
066      } else {
067        LOG.error("Invalid Options");
068      }
069    } catch (Exception e) {
070      LOG.error("Error while starting ChaosService : ", e);
071    }
072  }
073
074  private static void ChaosServiceStart(Configuration conf, ChaosServiceName serviceName) {
075    switch (serviceName) {
076      case CHAOSAGENT:
077        ChaosAgent.stopChaosAgent.set(false);
078        try {
079          Thread t = new Thread(
080            new ChaosAgent(conf, ChaosUtils.getZKQuorum(conf), ChaosUtils.getHostName()));
081          t.start();
082          t.join();
083        } catch (InterruptedException | UnknownHostException e) {
084          LOG.error("Failed while executing next task execution of ChaosAgent on : {}", serviceName,
085            e);
086        }
087        break;
088      default:
089        LOG.error("Service Name not known : " + serviceName.toString());
090    }
091  }
092
093  private static void ChaosServiceStop() {
094    ChaosAgent.stopChaosAgent.set(true);
095  }
096
097  private static Options getOptions() {
098    Options options = new Options();
099    options.addOption(new Option("c", ChaosServiceName.CHAOSAGENT.toString().toLowerCase(), true,
100      "expecting a start/stop argument"));
101    options
102      .addOption(new Option("D", ChaosServiceName.GENERIC.toString(), true, "generic D param"));
103    LOG.info(Arrays.toString(new Collection[] { options.getOptions() }));
104    return options;
105  }
106
107  public static void main(String[] args) throws Exception {
108    Configuration conf = HBaseConfiguration.create();
109    new GenericOptionsParser(conf, args);
110
111    ChoreService choreChaosService = null;
112    ScheduledChore authChore = AuthUtil.getAuthChore(conf);
113
114    try {
115      if (authChore != null) {
116        choreChaosService = new ChoreService(ChaosConstants.CHORE_SERVICE_PREFIX);
117        choreChaosService.scheduleChore(authChore);
118      }
119
120      execute(args, conf);
121    } finally {
122      if (authChore != null) choreChaosService.shutdown();
123    }
124  }
125
126  enum ChaosServiceName {
127    CHAOSAGENT,
128    GENERIC
129  }
130
131  enum ExecutorAction {
132    START,
133    STOP
134  }
135}