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;
19  
20  import static org.junit.Assert.assertFalse;
21  import static org.junit.Assert.assertTrue;
22  import static org.junit.Assert.assertEquals;
23  
24  import java.io.File;
25  import java.io.FileOutputStream;
26  import java.io.IOException;
27  import java.io.PrintWriter;
28  
29  import org.apache.commons.logging.Log;
30  import org.apache.commons.logging.LogFactory;
31  import org.apache.hadoop.conf.Configuration;
32  import org.apache.hadoop.hbase.HBaseTestingUtility;
33  import org.apache.hadoop.hbase.HConstants;
34  import org.apache.hadoop.hbase.SmallTests;
35  import org.apache.hadoop.hbase.Stoppable;
36  import org.apache.hadoop.hbase.HealthChecker.HealthCheckerExitStatus;
37  import org.junit.After;
38  import org.junit.Test;
39  import org.junit.experimental.categories.Category;
40  
41  @Category(SmallTests.class)
42  public class TestNodeHealthCheckChore {
43  
44    private static final Log LOG = LogFactory.getLog(TestNodeHealthCheckChore.class);
45    private static final HBaseTestingUtility UTIL = new HBaseTestingUtility();
46    private File healthScriptFile;
47  
48  
49    @After
50    public void cleanUp() throws IOException {
51      UTIL.cleanupTestDir();
52    }
53  
54    @Test
55    public void testHealthChecker() throws Exception {
56      Configuration config = getConfForNodeHealthScript();
57      config.addResource(healthScriptFile.getName());
58      String location = healthScriptFile.getAbsolutePath();
59      long timeout = config.getLong(HConstants.HEALTH_SCRIPT_TIMEOUT, 200);
60  
61      HealthChecker checker = new HealthChecker();
62      checker.init(location, timeout);
63  
64      String normalScript = "echo \"I am all fine\"";
65      createScript(normalScript, true);
66      HealthReport report = checker.checkHealth();
67      assertEquals(HealthCheckerExitStatus.SUCCESS, report.getStatus());
68  
69      LOG.info("Health Status:" + checker);
70  
71      String errorScript = "echo ERROR\n echo \"Node not healthy\"";
72      createScript(errorScript, true);
73      report = checker.checkHealth();
74      assertEquals(HealthCheckerExitStatus.FAILED, report.getStatus());
75      LOG.info("Health Status:" + report.getHealthReport());
76  
77      String timeOutScript = "sleep 4\n echo\"I am fine\"";
78      createScript(timeOutScript, true);
79      report = checker.checkHealth();
80      assertEquals(HealthCheckerExitStatus.TIMED_OUT, report.getStatus());
81      LOG.info("Health Status:" + report.getHealthReport());
82  
83      healthScriptFile.delete();
84    }
85  
86    @Test
87    public void testNodeHealthChore() throws Exception{
88      Stoppable stop = new StoppableImplementation();
89      Configuration conf = getConfForNodeHealthScript();
90      String errorScript = "echo ERROR\n echo \"Node not healthy\"";
91      createScript(errorScript, true);
92      HealthCheckChore rsChore = new HealthCheckChore(100, stop, conf);
93      //Default threshold is three.
94      rsChore.chore();
95      rsChore.chore();
96      assertFalse("Stoppable must not be stopped.", stop.isStopped());
97      rsChore.chore();
98      assertTrue("Stoppable must have been stopped.", stop.isStopped());
99    }
100 
101   private void createScript(String scriptStr, boolean setExecutable)
102       throws Exception {
103     healthScriptFile.createNewFile();
104     PrintWriter pw = new PrintWriter(new FileOutputStream(healthScriptFile));
105     pw.println(scriptStr);
106     pw.flush();
107     pw.close();
108     healthScriptFile.setExecutable(setExecutable);
109   }
110 
111   private Configuration getConfForNodeHealthScript() {
112     Configuration conf = UTIL.getConfiguration();
113     File tempDir = new File(UTIL.getDataTestDir().toString());
114     tempDir.mkdirs();
115     healthScriptFile = new File(tempDir.getAbsolutePath(), "HealthScript.sh");
116     conf.set(HConstants.HEALTH_SCRIPT_LOC,
117       healthScriptFile.getAbsolutePath());
118     conf.setLong(HConstants.HEALTH_FAILURE_THRESHOLD, 3);
119     conf.setLong(HConstants.HEALTH_SCRIPT_TIMEOUT, 200);
120     return conf;
121   }
122 
123   /**
124    * Simple helper class that just keeps track of whether or not its stopped.
125    */
126   private static class StoppableImplementation implements Stoppable {
127     private volatile boolean stop = false;
128 
129     @Override
130     public void stop(String why) {
131       this.stop = true;
132     }
133 
134     @Override
135     public boolean isStopped() {
136       return this.stop;
137     }
138 
139   }
140 }