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.master;
019
020import static org.junit.Assert.assertFalse;
021import static org.junit.Assert.assertTrue;
022
023import java.io.IOException;
024import java.util.List;
025import org.apache.hadoop.hbase.ClusterMetrics;
026import org.apache.hadoop.hbase.HBaseClassTestRule;
027import org.apache.hadoop.hbase.HBaseTestingUtility;
028import org.apache.hadoop.hbase.MasterNotRunningException;
029import org.apache.hadoop.hbase.MiniHBaseCluster;
030import org.apache.hadoop.hbase.testclassification.LargeTests;
031import org.apache.hadoop.hbase.testclassification.MasterTests;
032import org.apache.hadoop.hbase.util.JVMClusterUtil;
033import org.junit.ClassRule;
034import org.junit.Test;
035import org.junit.experimental.categories.Category;
036
037@Category({MasterTests.class, LargeTests.class})
038public class TestMasterFailoverBalancerPersistence {
039
040  @ClassRule
041  public static final HBaseClassTestRule CLASS_RULE =
042      HBaseClassTestRule.forClass(TestMasterFailoverBalancerPersistence.class);
043
044  /**
045   * Test that if the master fails, the load balancer maintains its
046   * state (running or not) when the next master takes over
047   *
048   * @throws Exception
049   */
050  @Test
051  public void testMasterFailoverBalancerPersistence() throws Exception {
052    final int NUM_MASTERS = 3;
053    final int NUM_RS = 1;
054
055    // Start the cluster
056    HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
057
058    TEST_UTIL.startMiniCluster(NUM_MASTERS, NUM_RS);
059    MiniHBaseCluster cluster = TEST_UTIL.getHBaseCluster();
060
061    assertTrue(cluster.waitForActiveAndReadyMaster());
062    HMaster active = cluster.getMaster();
063    // check that the balancer is on by default for the active master
064    ClusterMetrics clusterStatus = active.getClusterMetrics();
065    assertTrue(clusterStatus.getBalancerOn());
066
067    active = killActiveAndWaitForNewActive(cluster);
068
069    // ensure the load balancer is still running on new master
070    clusterStatus = active.getClusterMetrics();
071    assertTrue(clusterStatus.getBalancerOn());
072
073    // turn off the load balancer
074    active.balanceSwitch(false);
075
076    // once more, kill active master and wait for new active master to show up
077    active = killActiveAndWaitForNewActive(cluster);
078
079    // ensure the load balancer is not running on the new master
080    clusterStatus = active.getClusterMetrics();
081    assertFalse(clusterStatus.getBalancerOn());
082
083    // Stop the cluster
084    TEST_UTIL.shutdownMiniCluster();
085  }
086
087  /**
088   * Kill the master and wait for a new active master to show up
089   *
090   * @param cluster
091   * @return the new active master
092   * @throws InterruptedException
093   * @throws java.io.IOException
094   */
095  private HMaster killActiveAndWaitForNewActive(MiniHBaseCluster cluster)
096      throws InterruptedException, IOException {
097    int activeIndex = getActiveMasterIndex(cluster);
098    HMaster active = cluster.getMaster();
099    cluster.stopMaster(activeIndex);
100    cluster.waitOnMaster(activeIndex);
101    assertTrue(cluster.waitForActiveAndReadyMaster());
102    // double check this is actually a new master
103    HMaster newActive = cluster.getMaster();
104    assertFalse(active == newActive);
105    return newActive;
106  }
107
108  /**
109   * return the index of the active master in the cluster
110   *
111   * @throws org.apache.hadoop.hbase.MasterNotRunningException
112   *          if no active master found
113   */
114  private int getActiveMasterIndex(MiniHBaseCluster cluster) throws MasterNotRunningException {
115    // get all the master threads
116    List<JVMClusterUtil.MasterThread> masterThreads = cluster.getMasterThreads();
117
118    for (int i = 0; i < masterThreads.size(); i++) {
119      if (masterThreads.get(i).getMaster().isActiveMaster()) {
120        return i;
121      }
122    }
123    throw new MasterNotRunningException();
124  }
125
126}