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.apache.hadoop.hbase.HConstants.ZOOKEEPER_QUORUM;
021
022import java.io.IOException;
023import org.apache.hadoop.conf.Configuration;
024import org.apache.hadoop.hbase.Abortable;
025import org.apache.hadoop.hbase.HBaseClassTestRule;
026import org.apache.hadoop.hbase.HBaseTestingUtil;
027import org.apache.hadoop.hbase.HConstants;
028import org.apache.hadoop.hbase.Waiter;
029import org.apache.hadoop.hbase.ZooKeeperConnectionException;
030import org.apache.hadoop.hbase.testclassification.MasterTests;
031import org.apache.hadoop.hbase.testclassification.MediumTests;
032import org.apache.hadoop.hbase.util.CommonFSUtils;
033import org.apache.hadoop.hbase.util.Threads;
034import org.apache.hadoop.hbase.zookeeper.ZKUtil;
035import org.apache.hadoop.hbase.zookeeper.ZKWatcher;
036import org.apache.hadoop.metrics2.lib.DefaultMetricsSystem;
037import org.apache.zookeeper.KeeperException;
038import org.junit.After;
039import org.junit.AfterClass;
040import org.junit.Assert;
041import org.junit.BeforeClass;
042import org.junit.ClassRule;
043import org.junit.Rule;
044import org.junit.Test;
045import org.junit.experimental.categories.Category;
046import org.junit.rules.TestName;
047import org.slf4j.Logger;
048import org.slf4j.LoggerFactory;
049
050/**
051 * Standup the master and fake it to test various aspects of master function. Does NOT spin up a
052 * mini hbase nor mini dfs cluster testing master (it does put up a zk cluster but this is usually
053 * pretty fast compared). Also, should be possible to inject faults at points difficult to get at in
054 * cluster context. TODO: Speed up the zk connection by Master. It pauses 5 seconds establishing
055 * session.
056 */
057@Category({ MasterTests.class, MediumTests.class })
058public class TestMasterNoCluster {
059
060  @ClassRule
061  public static final HBaseClassTestRule CLASS_RULE =
062    HBaseClassTestRule.forClass(TestMasterNoCluster.class);
063
064  private static final Logger LOG = LoggerFactory.getLogger(TestMasterNoCluster.class);
065
066  private static final HBaseTestingUtil TESTUTIL = new HBaseTestingUtil();
067
068  @Rule
069  public TestName name = new TestName();
070
071  @BeforeClass
072  public static void setUpBeforeClass() throws Exception {
073    Configuration c = TESTUTIL.getConfiguration();
074    // We use local filesystem. Set it so it writes into the testdir.
075    CommonFSUtils.setRootDir(c, TESTUTIL.getDataTestDir());
076    DefaultMetricsSystem.setMiniClusterMode(true);
077    // Startup a mini zk cluster.
078    TESTUTIL.startMiniZKCluster();
079  }
080
081  @AfterClass
082  public static void tearDownAfterClass() throws Exception {
083    TESTUTIL.shutdownMiniZKCluster();
084  }
085
086  @After
087  public void tearDown() throws KeeperException, ZooKeeperConnectionException, IOException {
088    // Make sure zk is clean before we run the next test.
089    ZKWatcher zkw = new ZKWatcher(TESTUTIL.getConfiguration(), "@Before", new Abortable() {
090      @Override
091      public void abort(String why, Throwable e) {
092        throw new RuntimeException(why, e);
093      }
094
095      @Override
096      public boolean isAborted() {
097        return false;
098      }
099    });
100    // Before fails sometimes so retry.
101    try {
102      TESTUTIL.waitFor(10000, (Waiter.Predicate<Exception>) () -> {
103        try {
104          ZKUtil.deleteNodeRecursively(zkw, zkw.getZNodePaths().baseZNode);
105          return true;
106        } catch (KeeperException.NotEmptyException e) {
107          LOG.info("Failed delete, retrying", e);
108        }
109        return false;
110      });
111    } catch (Exception e) {
112      LOG.info("Failed zk clear", e);
113    }
114    zkw.close();
115  }
116
117  /**
118   * Test starting master then stopping it before its fully up.
119   */
120  @Test
121  public void testStopDuringStart() throws IOException, KeeperException, InterruptedException {
122    HMaster master = new HMaster(TESTUTIL.getConfiguration());
123    master.start();
124    // Immediately have it stop. We used hang in assigning meta.
125    master.stopMaster();
126    master.join();
127  }
128
129  @Test
130  public void testMasterInitWithSameClientServerZKQuorum() throws Exception {
131    Configuration conf = new Configuration(TESTUTIL.getConfiguration());
132    conf.set(HConstants.CLIENT_ZOOKEEPER_QUORUM, conf.get(ZOOKEEPER_QUORUM));
133    conf.setInt(HConstants.CLIENT_ZOOKEEPER_CLIENT_PORT, TESTUTIL.getZkCluster().getClientPort());
134    HMaster master = new HMaster(conf);
135    master.start();
136    // the master will abort due to IllegalArgumentException so we should finish within 60 seconds
137    master.join();
138  }
139
140  @Test
141  public void testMasterInitWithObserverModeClientZKQuorum() throws Exception {
142    Configuration conf = new Configuration(TESTUTIL.getConfiguration());
143    Assert.assertFalse(Boolean.getBoolean(HConstants.CLIENT_ZOOKEEPER_OBSERVER_MODE));
144    // set client ZK to some non-existing address and make sure server won't access client ZK
145    // (server start should not be affected)
146    conf.set(HConstants.CLIENT_ZOOKEEPER_QUORUM, HConstants.LOCALHOST);
147    conf.setInt(HConstants.CLIENT_ZOOKEEPER_CLIENT_PORT,
148      TESTUTIL.getZkCluster().getClientPort() + 1);
149    // need to enable maintenance mode so we will start master and an in process region server
150    conf.setBoolean(HMaster.MAINTENANCE_MODE, true);
151    // settings to allow us not to start additional RS
152    conf.setInt(ServerManager.WAIT_ON_REGIONSERVERS_MINTOSTART, 1);
153    // main setting for this test case
154    conf.setBoolean(HConstants.CLIENT_ZOOKEEPER_OBSERVER_MODE, true);
155    HMaster master = new HMaster(conf);
156    master.start();
157    while (!master.isInitialized()) {
158      Threads.sleep(200);
159    }
160    Assert.assertNull(master.getMetaLocationSyncer());
161    Assert.assertNull(master.masterAddressSyncer);
162    master.stopMaster();
163    master.join();
164  }
165}