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}