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.assertEquals;
021import static org.junit.Assert.assertNotNull;
022import static org.junit.Assert.assertTrue;
023
024import java.util.List;
025import org.apache.hadoop.conf.Configuration;
026import org.apache.hadoop.hbase.ClusterMetrics;
027import org.apache.hadoop.hbase.HBaseClassTestRule;
028import org.apache.hadoop.hbase.HBaseConfiguration;
029import org.apache.hadoop.hbase.HBaseTestingUtility;
030import org.apache.hadoop.hbase.LocalHBaseCluster;
031import org.apache.hadoop.hbase.MiniHBaseCluster;
032import org.apache.hadoop.hbase.StartMiniClusterOption;
033import org.apache.hadoop.hbase.client.Admin;
034import org.apache.hadoop.hbase.client.Connection;
035import org.apache.hadoop.hbase.client.ConnectionFactory;
036import org.apache.hadoop.hbase.testclassification.LargeTests;
037import org.apache.hadoop.hbase.testclassification.MasterTests;
038import org.apache.hadoop.hbase.util.JVMClusterUtil.MasterThread;
039import org.junit.ClassRule;
040import org.junit.Test;
041import org.junit.experimental.categories.Category;
042import org.slf4j.Logger;
043import org.slf4j.LoggerFactory;
044
045@Category({MasterTests.class, LargeTests.class})
046public class TestMasterShutdown {
047
048  @ClassRule
049  public static final HBaseClassTestRule CLASS_RULE =
050      HBaseClassTestRule.forClass(TestMasterShutdown.class);
051
052  private static final Logger LOG = LoggerFactory.getLogger(TestMasterShutdown.class);
053
054  /**
055   * Simple test of shutdown.
056   * <p>
057   * Starts with three masters.  Tells the active master to shutdown the cluster.
058   * Verifies that all masters are properly shutdown.
059   */
060  @Test
061  public void testMasterShutdown() throws Exception {
062    final int NUM_MASTERS = 3;
063    final int NUM_RS = 3;
064
065    // Create config to use for this cluster
066    Configuration conf = HBaseConfiguration.create();
067
068    // Start the cluster
069    HBaseTestingUtility htu = new HBaseTestingUtility(conf);
070    StartMiniClusterOption option = StartMiniClusterOption.builder()
071        .numMasters(NUM_MASTERS).numRegionServers(NUM_RS).numDataNodes(NUM_RS).build();
072    htu.startMiniCluster(option);
073    MiniHBaseCluster cluster = htu.getHBaseCluster();
074
075    // get all the master threads
076    List<MasterThread> masterThreads = cluster.getMasterThreads();
077
078    // wait for each to come online
079    for (MasterThread mt : masterThreads) {
080      assertTrue(mt.isAlive());
081    }
082
083    // find the active master
084    HMaster active = null;
085    for (int i = 0; i < masterThreads.size(); i++) {
086      if (masterThreads.get(i).getMaster().isActiveMaster()) {
087        active = masterThreads.get(i).getMaster();
088        break;
089      }
090    }
091    assertNotNull(active);
092    // make sure the other two are backup masters
093    ClusterMetrics status = active.getClusterMetrics();
094    assertEquals(2, status.getBackupMasterNames().size());
095
096    // tell the active master to shutdown the cluster
097    active.shutdown();
098
099    for (int i = NUM_MASTERS - 1; i >= 0 ;--i) {
100      cluster.waitOnMaster(i);
101    }
102    // make sure all the masters properly shutdown
103    assertEquals(0, masterThreads.size());
104
105    htu.shutdownMiniCluster();
106  }
107
108  @Test
109  public void testMasterShutdownBeforeStartingAnyRegionServer() throws Exception {
110    final int NUM_MASTERS = 1;
111    final int NUM_RS = 0;
112
113    // Create config to use for this cluster
114    Configuration conf = HBaseConfiguration.create();
115    conf.setInt("hbase.ipc.client.failed.servers.expiry", 200);
116    conf.setInt(ServerManager.WAIT_ON_REGIONSERVERS_MINTOSTART, 1);
117
118    // Start the cluster
119    final HBaseTestingUtility util = new HBaseTestingUtility(conf);
120    util.startMiniDFSCluster(3);
121    util.startMiniZKCluster();
122    util.createRootDir();
123    final LocalHBaseCluster cluster =
124        new LocalHBaseCluster(conf, NUM_MASTERS, NUM_RS, HMaster.class,
125            MiniHBaseCluster.MiniHBaseClusterRegionServer.class);
126    final int MASTER_INDEX = 0;
127    final MasterThread master = cluster.getMasters().get(MASTER_INDEX);
128    master.start();
129    LOG.info("Called master start on " + master.getName());
130    Thread shutdownThread = new Thread("Shutdown-Thread") {
131      @Override
132      public void run() {
133        LOG.info("Before call to shutdown master");
134        try {
135          try (
136            Connection connection = ConnectionFactory.createConnection(util.getConfiguration())) {
137            try (Admin admin = connection.getAdmin()) {
138              admin.shutdown();
139            }
140          }
141        } catch (Exception e) {
142          LOG.info("Error while calling Admin.shutdown, which is expected: " + e.getMessage());
143        }
144        LOG.info("After call to shutdown master");
145        cluster.waitOnMaster(MASTER_INDEX);
146      }
147    };
148    shutdownThread.start();
149    LOG.info("Called master join on " + master.getName());
150    master.join();
151    shutdownThread.join();
152
153    List<MasterThread> masterThreads = cluster.getMasters();
154    // make sure all the masters properly shutdown
155    assertEquals(0, masterThreads.size());
156
157    util.shutdownMiniZKCluster();
158    util.shutdownMiniDFSCluster();
159    util.cleanupTestDir();
160  }
161}