Browse Source

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

Inigo Goiri 5 years ago
parent
commit
e6f95eb0f7

+ 3 - 3
hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/resolver/FederationNamenodeServiceState.java

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

+ 2 - 0
hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/webapps/router/federationhealth.html

@@ -129,6 +129,7 @@
 <div>
   <ul class="federationhealth-namenode-legend">
     <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-safemode">Safe mode</li>
     <li class="federationhealth-namenode-icon federationhealth-namenode-disabled">Disabled</li>
@@ -196,6 +197,7 @@
 <div>
   <ul class="federationhealth-namenode-legend">
     <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-safemode">Safe mode</li>
     <li class="federationhealth-namenode-icon federationhealth-namenode-unavailable">Unavailable</li>

+ 3 - 0
hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/webapps/router/federationhealth.js

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

+ 5 - 0
hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/webapps/static/rbf.css

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

+ 65 - 0
hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/metrics/TestMetricsBase.java

@@ -19,20 +19,26 @@ package org.apache.hadoop.hdfs.server.federation.metrics;
 
 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.ROUTERS;
 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.createMockRegistrationForNamenode;
 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.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
 
 import org.apache.hadoop.conf.Configuration;
 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.MembershipNamenodeResolver;
 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.store.MembershipStore;
@@ -41,14 +47,18 @@ import org.apache.hadoop.hdfs.server.federation.store.StateStoreService;
 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.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.records.MembershipState;
 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.StateStoreVersion;
 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.Before;
+import org.junit.Test;
 
 /**
  * Test the basic metrics functionality.
@@ -193,4 +203,59 @@ public class TestMetricsBase {
   protected StateStoreService getStateStore() {
     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;
+  }
 }

+ 10 - 0
hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/store/TestStateStoreMembershipState.java

@@ -104,6 +104,16 @@ public class TestStateStoreMembershipState extends TestStateStoreBase {
 
     MembershipState newState = getNamenodeRegistration(ns, nn);
     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