| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF 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 org.apache.hadoop.hbase; |
| |
| import java.io.IOException; |
| import java.util.ArrayList; |
| |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| import org.apache.hadoop.util.Shell.ExitCodeException; |
| import org.apache.hadoop.util.Shell.ShellCommandExecutor; |
| |
| /** |
| * A utility for executing an external script that checks the health of |
| * the node. An example script can be found at |
| * <tt>src/main/sh/healthcheck/healthcheck.sh</tt> in the |
| * <tt>hbase-examples</tt> module. |
| */ |
| class HealthChecker { |
| |
| private static final Log LOG = LogFactory.getLog(HealthChecker.class); |
| private ShellCommandExecutor shexec = null; |
| private String exceptionStackTrace; |
| |
| /** Pattern used for searching in the output of the node health script */ |
| static private final String ERROR_PATTERN = "ERROR"; |
| |
| private String healthCheckScript; |
| private long scriptTimeout; |
| |
| enum HealthCheckerExitStatus { |
| SUCCESS, |
| TIMED_OUT, |
| FAILED_WITH_EXIT_CODE, |
| FAILED_WITH_EXCEPTION, |
| FAILED |
| } |
| |
| /** |
| * Initialize. |
| * |
| * @param configuration |
| */ |
| public void init(String location, long timeout) { |
| this.healthCheckScript = location; |
| this.scriptTimeout = timeout; |
| ArrayList<String> execScript = new ArrayList<String>(); |
| execScript.add(healthCheckScript); |
| this.shexec = new ShellCommandExecutor(execScript.toArray(new String[execScript.size()]), null, |
| null, scriptTimeout); |
| LOG.info("HealthChecker initialized with script at " + this.healthCheckScript + |
| ", timeout=" + timeout); |
| } |
| |
| public HealthReport checkHealth() { |
| HealthCheckerExitStatus status = HealthCheckerExitStatus.SUCCESS; |
| try { |
| // Calling this execute leaves around running executor threads. |
| shexec.execute(); |
| } catch (ExitCodeException e) { |
| // ignore the exit code of the script |
| LOG.warn("Caught exception : " + e + ",exit code:" + e.getExitCode()); |
| status = HealthCheckerExitStatus.FAILED_WITH_EXIT_CODE; |
| } catch (IOException e) { |
| LOG.warn("Caught exception : " + e); |
| status = HealthCheckerExitStatus.FAILED_WITH_EXCEPTION; |
| exceptionStackTrace = org.apache.hadoop.util.StringUtils.stringifyException(e); |
| } finally { |
| if (shexec.isTimedOut()) { |
| status = HealthCheckerExitStatus.TIMED_OUT; |
| } |
| if (status == HealthCheckerExitStatus.SUCCESS) { |
| if (hasErrors(shexec.getOutput())) { |
| status = HealthCheckerExitStatus.FAILED; |
| } |
| } |
| } |
| return new HealthReport(status, getHealthReport(status)); |
| } |
| |
| private boolean hasErrors(String output) { |
| String[] splits = output.split("\n"); |
| for (String split : splits) { |
| if (split.startsWith(ERROR_PATTERN)) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| private String getHealthReport(HealthCheckerExitStatus status){ |
| String healthReport = null; |
| switch (status) { |
| case SUCCESS: |
| healthReport = "Server is healthy."; |
| break; |
| case TIMED_OUT: |
| healthReport = "Health script timed out"; |
| break; |
| case FAILED_WITH_EXCEPTION: |
| healthReport = exceptionStackTrace; |
| break; |
| case FAILED_WITH_EXIT_CODE: |
| healthReport = "Health script failed with exit code."; |
| break; |
| case FAILED: |
| healthReport = shexec.getOutput(); |
| break; |
| } |
| return healthReport; |
| } |
| } |