HDFS-14887. RBF: In Router Web UI, Observer Namenode Information displaying as Unavailable. Contributed by hemanthboyina.

This commit is contained in:
Inigo Goiri 2019-10-19 13:24:58 -07:00
parent 2ae4b33d48
commit e6f95eb0f7
6 changed files with 88 additions and 3 deletions

View File

@ -25,6 +25,7 @@
*/ */
public enum FederationNamenodeServiceState { public enum FederationNamenodeServiceState {
ACTIVE, // HAServiceState.ACTIVE or operational. ACTIVE, // HAServiceState.ACTIVE or operational.
OBSERVER, // HAServiceState.OBSERVER.
STANDBY, // HAServiceState.STANDBY. STANDBY, // HAServiceState.STANDBY.
UNAVAILABLE, // When the namenode cannot be reached. UNAVAILABLE, // When the namenode cannot be reached.
EXPIRED, // When the last update is too old. EXPIRED, // When the last update is too old.
@ -34,10 +35,9 @@ public static FederationNamenodeServiceState getState(HAServiceState state) {
switch(state) { switch(state) {
case ACTIVE: case ACTIVE:
return FederationNamenodeServiceState.ACTIVE; return FederationNamenodeServiceState.ACTIVE;
case STANDBY:
// TODO: we should probably have a separate state OBSERVER for RBF and
// treat it differently.
case OBSERVER: case OBSERVER:
return FederationNamenodeServiceState.OBSERVER;
case STANDBY:
return FederationNamenodeServiceState.STANDBY; return FederationNamenodeServiceState.STANDBY;
case INITIALIZING: case INITIALIZING:
return FederationNamenodeServiceState.UNAVAILABLE; return FederationNamenodeServiceState.UNAVAILABLE;

View File

@ -129,6 +129,7 @@
<div> <div>
<ul class="federationhealth-namenode-legend"> <ul class="federationhealth-namenode-legend">
<li class="federationhealth-namenode-icon federationhealth-namenode-active">Active</li> <li class="federationhealth-namenode-icon federationhealth-namenode-active">Active</li>
<li class="federationhealth-namenode-icon federationhealth-namenode-observer">Observer</li>
<li class="federationhealth-namenode-icon federationhealth-namenode-standby">Standby</li> <li class="federationhealth-namenode-icon federationhealth-namenode-standby">Standby</li>
<li class="federationhealth-namenode-icon federationhealth-namenode-safemode">Safe mode</li> <li class="federationhealth-namenode-icon federationhealth-namenode-safemode">Safe mode</li>
<li class="federationhealth-namenode-icon federationhealth-namenode-disabled">Disabled</li> <li class="federationhealth-namenode-icon federationhealth-namenode-disabled">Disabled</li>
@ -196,6 +197,7 @@
<div> <div>
<ul class="federationhealth-namenode-legend"> <ul class="federationhealth-namenode-legend">
<li class="federationhealth-namenode-icon federationhealth-namenode-active">Active</li> <li class="federationhealth-namenode-icon federationhealth-namenode-active">Active</li>
<li class="federationhealth-namenode-icon federationhealth-namenode-observer">Observer</li>
<li class="federationhealth-namenode-icon federationhealth-namenode-standby">Standby</li> <li class="federationhealth-namenode-icon federationhealth-namenode-standby">Standby</li>
<li class="federationhealth-namenode-icon federationhealth-namenode-safemode">Safe mode</li> <li class="federationhealth-namenode-icon federationhealth-namenode-safemode">Safe mode</li>
<li class="federationhealth-namenode-icon federationhealth-namenode-unavailable">Unavailable</li> <li class="federationhealth-namenode-icon federationhealth-namenode-unavailable">Unavailable</li>

View File

@ -123,6 +123,9 @@
} else if (n.state === "ACTIVE") { } else if (n.state === "ACTIVE") {
n.title = capitalise(n.state); n.title = capitalise(n.state);
n.iconState = "active"; n.iconState = "active";
} else if (nodes[i].state === "OBSERVER") {
n.title = capitalise(n.state);
n.iconState = "observer";
} else if (nodes[i].state === "STANDBY") { } else if (nodes[i].state === "STANDBY") {
n.title = capitalise(n.state); n.title = capitalise(n.state);
n.iconState = "standby"; n.iconState = "standby";

View File

@ -38,6 +38,11 @@
content: "\e013"; content: "\e013";
} }
.federationhealth-namenode-observer:before {
color: #CCCC00;
content: "\e013";
}
.federationhealth-namenode-unavailable:before { .federationhealth-namenode-unavailable:before {
color: #c7254e; color: #c7254e;
content: "\e101"; content: "\e101";

View File

@ -19,20 +19,26 @@
import static org.apache.hadoop.hdfs.server.federation.FederationTestUtils.NAMENODES; import static org.apache.hadoop.hdfs.server.federation.FederationTestUtils.NAMENODES;
import static org.apache.hadoop.hdfs.server.federation.FederationTestUtils.NAMESERVICES; import static org.apache.hadoop.hdfs.server.federation.FederationTestUtils.NAMESERVICES;
import static org.apache.hadoop.hdfs.server.federation.FederationTestUtils.ROUTERS;
import static org.apache.hadoop.hdfs.server.federation.store.FederationStateStoreTestUtils.clearAllRecords; import static org.apache.hadoop.hdfs.server.federation.store.FederationStateStoreTestUtils.clearAllRecords;
import static org.apache.hadoop.hdfs.server.federation.store.FederationStateStoreTestUtils.createMockMountTable; import static org.apache.hadoop.hdfs.server.federation.store.FederationStateStoreTestUtils.createMockMountTable;
import static org.apache.hadoop.hdfs.server.federation.store.FederationStateStoreTestUtils.createMockRegistrationForNamenode; import static org.apache.hadoop.hdfs.server.federation.store.FederationStateStoreTestUtils.createMockRegistrationForNamenode;
import static org.apache.hadoop.hdfs.server.federation.store.FederationStateStoreTestUtils.synchronizeRecords; import static org.apache.hadoop.hdfs.server.federation.store.FederationStateStoreTestUtils.synchronizeRecords;
import static org.apache.hadoop.hdfs.server.federation.store.FederationStateStoreTestUtils.waitStateStore; import static org.apache.hadoop.hdfs.server.federation.store.FederationStateStoreTestUtils.waitStateStore;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hdfs.server.federation.RouterConfigBuilder; import org.apache.hadoop.hdfs.server.federation.RouterConfigBuilder;
import org.apache.hadoop.hdfs.server.federation.resolver.FederationNamenodeServiceState; import org.apache.hadoop.hdfs.server.federation.resolver.FederationNamenodeServiceState;
import org.apache.hadoop.hdfs.server.federation.resolver.MembershipNamenodeResolver;
import org.apache.hadoop.hdfs.server.federation.router.Router; import org.apache.hadoop.hdfs.server.federation.router.Router;
import org.apache.hadoop.hdfs.server.federation.router.RouterServiceState; import org.apache.hadoop.hdfs.server.federation.router.RouterServiceState;
import org.apache.hadoop.hdfs.server.federation.store.MembershipStore; import org.apache.hadoop.hdfs.server.federation.store.MembershipStore;
@ -41,14 +47,18 @@
import org.apache.hadoop.hdfs.server.federation.store.protocol.GetRouterRegistrationRequest; import org.apache.hadoop.hdfs.server.federation.store.protocol.GetRouterRegistrationRequest;
import org.apache.hadoop.hdfs.server.federation.store.protocol.GetRouterRegistrationResponse; import org.apache.hadoop.hdfs.server.federation.store.protocol.GetRouterRegistrationResponse;
import org.apache.hadoop.hdfs.server.federation.store.protocol.NamenodeHeartbeatRequest; import org.apache.hadoop.hdfs.server.federation.store.protocol.NamenodeHeartbeatRequest;
import org.apache.hadoop.hdfs.server.federation.store.protocol.NamenodeHeartbeatResponse;
import org.apache.hadoop.hdfs.server.federation.store.protocol.RouterHeartbeatRequest; import org.apache.hadoop.hdfs.server.federation.store.protocol.RouterHeartbeatRequest;
import org.apache.hadoop.hdfs.server.federation.store.records.MembershipState; import org.apache.hadoop.hdfs.server.federation.store.records.MembershipState;
import org.apache.hadoop.hdfs.server.federation.store.records.MountTable; import org.apache.hadoop.hdfs.server.federation.store.records.MountTable;
import org.apache.hadoop.hdfs.server.federation.store.records.RouterState; import org.apache.hadoop.hdfs.server.federation.store.records.RouterState;
import org.apache.hadoop.hdfs.server.federation.store.records.StateStoreVersion; import org.apache.hadoop.hdfs.server.federation.store.records.StateStoreVersion;
import org.apache.hadoop.util.Time; import org.apache.hadoop.util.Time;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test;
/** /**
* Test the basic metrics functionality. * Test the basic metrics functionality.
@ -193,4 +203,59 @@ protected List<RouterState> getMockRouters() {
protected StateStoreService getStateStore() { protected StateStoreService getStateStore() {
return stateStore; return stateStore;
} }
@Test
public void testObserverMetrics() throws Exception {
mockObserver();
RBFMetrics metrics = router.getMetrics();
String jsonString = metrics.getNameservices();
JSONObject jsonObject = new JSONObject(jsonString);
Map<String, String> map = getNameserviceStateMap(jsonObject);
assertTrue("Cannot find ns0 in: " + jsonString, map.containsKey("ns0"));
assertEquals("OBSERVER", map.get("ns0"));
}
public static Map<String, String> getNameserviceStateMap(
JSONObject jsonObject) throws JSONException {
Map<String, String> map = new TreeMap<>();
Iterator<?> keys = jsonObject.keys();
while (keys.hasNext()) {
String key = (String) keys.next();
JSONObject json = jsonObject.getJSONObject(key);
String nsId = json.getString("nameserviceId");
String state = json.getString("state");
map.put(nsId, state);
}
return map;
}
private void mockObserver() throws IOException {
String ns = "ns0";
String nn = "nn0";
createRegistration(ns, nn, ROUTERS[1],
FederationNamenodeServiceState.OBSERVER);
// Load data into cache and calculate quorum
assertTrue(stateStore.loadCache(MembershipStore.class, true));
membershipStore.loadCache(true);
MembershipNamenodeResolver resolver =
(MembershipNamenodeResolver) router.getNamenodeResolver();
resolver.loadCache(true);
}
private MembershipState createRegistration(String ns, String nn,
String routerId, FederationNamenodeServiceState state)
throws IOException {
MembershipState record =
MembershipState.newInstance(routerId, ns, nn, "testcluster",
"testblock-" + ns, "testrpc-" + ns + nn, "testservice-" + ns + nn,
"testlifeline-" + ns + nn, "testweb-" + ns + nn, state, false);
NamenodeHeartbeatRequest request =
NamenodeHeartbeatRequest.newInstance(record);
NamenodeHeartbeatResponse response =
membershipStore.namenodeHeartbeat(request);
assertTrue(response.getResult());
return record;
}
} }

View File

@ -104,6 +104,16 @@ public void testNamenodeStateOverride() throws Exception {
MembershipState newState = getNamenodeRegistration(ns, nn); MembershipState newState = getNamenodeRegistration(ns, nn);
assertEquals(FederationNamenodeServiceState.ACTIVE, newState.getState()); assertEquals(FederationNamenodeServiceState.ACTIVE, newState.getState());
// Override cache
UpdateNamenodeRegistrationRequest request1 =
UpdateNamenodeRegistrationRequest.newInstance(ns, nn,
FederationNamenodeServiceState.OBSERVER);
assertTrue(
membershipStore.updateNamenodeRegistration(request1).getResult());
MembershipState newState1 = getNamenodeRegistration(ns, nn);
assertEquals(FederationNamenodeServiceState.OBSERVER, newState1.getState());
} }
@Test @Test