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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 package org
.apache
.hadoop
.hbase
;
20 import java
.io
.IOException
;
21 import java
.util
.EnumSet
;
22 import java
.util
.List
;
23 import java
.util
.Optional
;
24 import java
.util
.concurrent
.atomic
.AtomicInteger
;
25 import org
.apache
.hadoop
.conf
.Configuration
;
26 import org
.apache
.hadoop
.hbase
.ClusterMetrics
.Option
;
27 import org
.apache
.hadoop
.hbase
.Waiter
.Predicate
;
28 import org
.apache
.hadoop
.hbase
.client
.Admin
;
29 import org
.apache
.hadoop
.hbase
.coprocessor
.CoprocessorHost
;
30 import org
.apache
.hadoop
.hbase
.coprocessor
.MasterCoprocessor
;
31 import org
.apache
.hadoop
.hbase
.coprocessor
.MasterCoprocessorEnvironment
;
32 import org
.apache
.hadoop
.hbase
.coprocessor
.MasterObserver
;
33 import org
.apache
.hadoop
.hbase
.coprocessor
.ObserverContext
;
34 import org
.apache
.hadoop
.hbase
.master
.HMaster
;
35 import org
.apache
.hadoop
.hbase
.regionserver
.HRegionServer
;
36 import org
.apache
.hadoop
.hbase
.testclassification
.MediumTests
;
37 import org
.apache
.hadoop
.hbase
.util
.JVMClusterUtil
.MasterThread
;
38 import org
.apache
.hadoop
.hbase
.util
.JVMClusterUtil
.RegionServerThread
;
39 import org
.junit
.AfterClass
;
40 import org
.junit
.Assert
;
41 import org
.junit
.BeforeClass
;
42 import org
.junit
.ClassRule
;
43 import org
.junit
.Test
;
44 import org
.junit
.experimental
.categories
.Category
;
47 * Test the ClusterStatus.
49 @Category(MediumTests
.class)
50 public class TestClientClusterStatus
{
53 public static final HBaseClassTestRule CLASS_RULE
=
54 HBaseClassTestRule
.forClass(TestClientClusterStatus
.class);
56 private static HBaseTestingUtility UTIL
;
57 private static Admin ADMIN
;
58 private final static int SLAVES
= 5;
59 private final static int MASTERS
= 3;
60 private static MiniHBaseCluster CLUSTER
;
61 private static HRegionServer DEAD
;
64 public static void setUpBeforeClass() throws Exception
{
65 Configuration conf
= HBaseConfiguration
.create();
66 conf
.set(CoprocessorHost
.MASTER_COPROCESSOR_CONF_KEY
, MyObserver
.class.getName());
67 UTIL
= new HBaseTestingUtility(conf
);
68 StartMiniClusterOption option
= StartMiniClusterOption
.builder()
69 .numMasters(MASTERS
).numRegionServers(SLAVES
).numDataNodes(SLAVES
).build();
70 UTIL
.startMiniCluster(option
);
71 CLUSTER
= UTIL
.getHBaseCluster();
72 CLUSTER
.waitForActiveAndReadyMaster();
73 ADMIN
= UTIL
.getAdmin();
74 // Kill one region server
75 List
<RegionServerThread
> rsts
= CLUSTER
.getLiveRegionServerThreads();
76 RegionServerThread rst
= rsts
.get(rsts
.size() - 1);
77 DEAD
= rst
.getRegionServer();
78 DEAD
.stop("Test dead servers status");
79 while (rst
.isAlive()) {
85 public void testNone() throws Exception
{
86 ClusterMetrics status0
= ADMIN
.getClusterMetrics(EnumSet
.allOf(Option
.class));
87 ClusterMetrics status1
= ADMIN
.getClusterMetrics(EnumSet
.noneOf(Option
.class));
88 // Do a rough compare. More specific compares can fail because all regions not deployed yet
89 // or more requests than expected.
90 Assert
.assertEquals(status0
.getLiveServerMetrics().size(),
91 status1
.getLiveServerMetrics().size());
95 public void testLiveAndDeadServersStatus() throws Exception
{
96 // Count the number of live regionservers
97 List
<RegionServerThread
> regionserverThreads
= CLUSTER
.getLiveRegionServerThreads();
99 int len
= regionserverThreads
.size();
100 for (int i
= 0; i
< len
; i
++) {
101 if (regionserverThreads
.get(i
).isAlive()) {
105 // Depending on the (random) order of unit execution we may run this unit before the
106 // minicluster is fully up and recovered from the RS shutdown done during test init.
107 Waiter
.waitFor(CLUSTER
.getConfiguration(), 10 * 1000, 100, new Predicate
<Exception
>() {
109 public boolean evaluate() throws Exception
{
110 ClusterMetrics status
= ADMIN
.getClusterMetrics(EnumSet
.of(Option
.LIVE_SERVERS
));
111 Assert
.assertNotNull(status
);
112 return status
.getRegionCount() > 0;
115 // Retrieve live servers and dead servers info.
116 EnumSet
<Option
> options
=
117 EnumSet
.of(Option
.LIVE_SERVERS
, Option
.DEAD_SERVERS
, Option
.SERVERS_NAME
);
118 ClusterMetrics status
= ADMIN
.getClusterMetrics(options
);
119 Assert
.assertNotNull(status
);
120 Assert
.assertNotNull(status
.getLiveServerMetrics().keySet());
121 // exclude a dead region server
122 Assert
.assertEquals(SLAVES
-1, numRs
);
123 // live servers = nums of regionservers
124 // By default, HMaster don't carry any regions so it won't report its load.
125 // Hence, it won't be in the server list.
126 Assert
.assertEquals(status
.getLiveServerMetrics().keySet().size(), numRs
);
127 Assert
.assertTrue(status
.getRegionCount() > 0);
128 Assert
.assertNotNull(status
.getDeadServerNames());
129 Assert
.assertEquals(1, status
.getDeadServerNames().size());
130 ServerName deadServerName
= status
.getDeadServerNames().iterator().next();
131 Assert
.assertEquals(DEAD
.getServerName(), deadServerName
);
132 Assert
.assertNotNull(status
.getServersName());
133 Assert
.assertEquals(numRs
, status
.getServersName().size());
137 public void testMasterAndBackupMastersStatus() throws Exception
{
138 // get all the master threads
139 List
<MasterThread
> masterThreads
= CLUSTER
.getMasterThreads();
142 ServerName activeName
= null;
143 HMaster active
= null;
144 for (int i
= 0; i
< masterThreads
.size(); i
++) {
145 if (masterThreads
.get(i
).getMaster().isActiveMaster()) {
148 active
= masterThreads
.get(activeIndex
).getMaster();
149 activeName
= active
.getServerName();
152 Assert
.assertNotNull(active
);
153 Assert
.assertEquals(1, numActive
);
154 Assert
.assertEquals(MASTERS
, masterThreads
.size());
155 // Retrieve master and backup masters infos only.
156 EnumSet
<Option
> options
= EnumSet
.of(Option
.MASTER
, Option
.BACKUP_MASTERS
);
157 ClusterMetrics status
= ADMIN
.getClusterMetrics(options
);
158 Assert
.assertTrue(status
.getMasterName().equals(activeName
));
159 Assert
.assertEquals(MASTERS
- 1, status
.getBackupMasterNames().size());
163 public void testOtherStatusInfos() throws Exception
{
164 EnumSet
<Option
> options
=
165 EnumSet
.of(Option
.MASTER_COPROCESSORS
, Option
.HBASE_VERSION
,
166 Option
.CLUSTER_ID
, Option
.BALANCER_ON
);
167 ClusterMetrics status
= ADMIN
.getClusterMetrics(options
);
168 Assert
.assertTrue(status
.getMasterCoprocessorNames().size() == 1);
169 Assert
.assertNotNull(status
.getHBaseVersion());
170 Assert
.assertNotNull(status
.getClusterId());
171 Assert
.assertTrue(status
.getAverageLoad() == 0.0);
172 Assert
.assertNotNull(status
.getBalancerOn());
176 public static void tearDownAfterClass() throws Exception
{
177 if (ADMIN
!= null) ADMIN
.close();
178 UTIL
.shutdownMiniCluster();
182 public void testObserver() throws IOException
{
183 int preCount
= MyObserver
.PRE_COUNT
.get();
184 int postCount
= MyObserver
.POST_COUNT
.get();
185 Assert
.assertTrue(ADMIN
.getClusterMetrics().getMasterCoprocessorNames().stream()
186 .anyMatch(s
-> s
.equals(MyObserver
.class.getSimpleName())));
187 Assert
.assertEquals(preCount
+ 1, MyObserver
.PRE_COUNT
.get());
188 Assert
.assertEquals(postCount
+ 1, MyObserver
.POST_COUNT
.get());
191 public static class MyObserver
implements MasterCoprocessor
, MasterObserver
{
192 private static final AtomicInteger PRE_COUNT
= new AtomicInteger(0);
193 private static final AtomicInteger POST_COUNT
= new AtomicInteger(0);
195 @Override public Optional
<MasterObserver
> getMasterObserver() {
196 return Optional
.of(this);
199 @Override public void preGetClusterMetrics(ObserverContext
<MasterCoprocessorEnvironment
> ctx
)
201 PRE_COUNT
.incrementAndGet();
204 @Override public void postGetClusterMetrics(ObserverContext
<MasterCoprocessorEnvironment
> ctx
,
205 ClusterMetrics status
) throws IOException
{
206 POST_COUNT
.incrementAndGet();