diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/federation/metrics/FederationMBean.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/federation/metrics/FederationMBean.java index 8abfc6e594..79fb3e4326 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/federation/metrics/FederationMBean.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/federation/metrics/FederationMBean.java @@ -46,6 +46,12 @@ public interface FederationMBean { */ String getMountTable(); + /** + * Get the latest state of all routers. + * @return JSON with all of the known routers or null if failure. + */ + String getRouters(); + /** * Get the total capacity of the federated cluster. * @return Total capacity of the federated cluster. diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/federation/metrics/FederationMetrics.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/federation/metrics/FederationMetrics.java index 45828252ab..a80c3be2e0 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/federation/metrics/FederationMetrics.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/federation/metrics/FederationMetrics.java @@ -57,6 +57,7 @@ import org.apache.hadoop.hdfs.server.federation.router.RouterRpcServer; import org.apache.hadoop.hdfs.server.federation.store.MembershipStore; import org.apache.hadoop.hdfs.server.federation.store.MountTableStore; +import org.apache.hadoop.hdfs.server.federation.store.RouterStore; import org.apache.hadoop.hdfs.server.federation.store.StateStoreService; import org.apache.hadoop.hdfs.server.federation.store.protocol.GetMountTableEntriesRequest; import org.apache.hadoop.hdfs.server.federation.store.protocol.GetMountTableEntriesResponse; @@ -64,10 +65,14 @@ import org.apache.hadoop.hdfs.server.federation.store.protocol.GetNamenodeRegistrationsResponse; import org.apache.hadoop.hdfs.server.federation.store.protocol.GetNamespaceInfoRequest; import org.apache.hadoop.hdfs.server.federation.store.protocol.GetNamespaceInfoResponse; +import org.apache.hadoop.hdfs.server.federation.store.protocol.GetRouterRegistrationsRequest; +import org.apache.hadoop.hdfs.server.federation.store.protocol.GetRouterRegistrationsResponse; import org.apache.hadoop.hdfs.server.federation.store.records.BaseRecord; import org.apache.hadoop.hdfs.server.federation.store.records.MembershipState; import org.apache.hadoop.hdfs.server.federation.store.records.MembershipStats; 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.metrics2.util.MBeans; import org.apache.hadoop.util.StringUtils; import org.apache.hadoop.util.VersionInfo; @@ -76,6 +81,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.common.annotations.VisibleForTesting; + /** * Implementation of the Router metrics collector. */ @@ -106,6 +113,8 @@ public class FederationMetrics implements FederationMBean { private MembershipStore membershipStore; /** Mount table store. */ private MountTableStore mountTableStore; + /** Router state store. */ + private RouterStore routerStore; public FederationMetrics(Router router) throws IOException { @@ -131,6 +140,8 @@ public FederationMetrics(Router router) throws IOException { MembershipStore.class); this.mountTableStore = stateStore.getRegisteredRecordStore( MountTableStore.class); + this.routerStore = stateStore.getRegisteredRecordStore( + RouterStore.class); } } @@ -261,6 +272,63 @@ public String getMountTable() { return JSON.toString(info); } + @Override + public String getRouters() { + final Map> info = new LinkedHashMap<>(); + try { + // Get all the routers in order + GetRouterRegistrationsRequest request = + GetRouterRegistrationsRequest.newInstance(); + GetRouterRegistrationsResponse response = + routerStore.getRouterRegistrations(request); + final List routers = response.getRouters(); + List routersOrder = new ArrayList<>(routers); + Collections.sort(routersOrder); + + // Dump router information into JSON + for (RouterState record : routersOrder) { + Map innerInfo = new HashMap<>(); + Map map = getJson(record); + innerInfo.putAll(map); + long dateModified = record.getDateModified(); + long lastHeartbeat = getSecondsSince(dateModified); + innerInfo.put("lastHeartbeat", lastHeartbeat); + + StateStoreVersion stateStoreVersion = record.getStateStoreVersion(); + if (stateStoreVersion == null) { + LOG.error("Cannot get State Store versions"); + } else { + setStateStoreVersions(innerInfo, stateStoreVersion); + } + + info.put(record.getPrimaryKey(), + Collections.unmodifiableMap(innerInfo)); + } + } catch (IOException e) { + LOG.error("Cannot get Routers JSON from the State Store", e); + return "{}"; + } + return JSON.toString(info); + } + + /** + * Populate the map with the State Store versions. + * + * @param innerInfo Map with the information. + * @param version State Store versions. + */ + private static void setStateStoreVersions( + Map map, StateStoreVersion version) { + + long membershipVersion = version.getMembershipVersion(); + String lastMembershipUpdate = getDateString(membershipVersion); + map.put("lastMembershipUpdate", lastMembershipUpdate); + + long mountTableVersion = version.getMountTableVersion(); + String lastMountTableDate = getDateString(mountTableVersion); + map.put("lastMountTableUpdate", lastMountTableDate); + } + @Override public long getTotalCapacity() { return getNameserviceAggregatedLong(MembershipStats::getTotalSpace); @@ -587,7 +655,8 @@ private List getActiveNamenodeRegistrations() * @param time Seconds since 1970. * @return String representing the date. */ - private static String getDateString(long time) { + @VisibleForTesting + static String getDateString(long time) { if (time <= 0) { return "-"; } diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/federation/router/FederationUtil.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/federation/router/FederationUtil.java index 3f736d45d2..8d631e99ee 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/federation/router/FederationUtil.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/federation/router/FederationUtil.java @@ -107,12 +107,12 @@ public static JSONArray getJmx(String beanQuery, String webAddress) { } /** - * Fetch the compile timestamp for this jar. + * Fetch the Hadoop version string for this jar. * - * @return Date compiled. + * @return Hadoop version string, e.g., 3.0.1. */ - public static String getBuildVersion() { - return VersionInfo.getBuildVersion(); + public static String getVersion() { + return VersionInfo.getVersion(); } /** diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/federation/store/records/RouterState.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/federation/store/records/RouterState.java index ccdd392681..d727395b86 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/federation/store/records/RouterState.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/federation/store/records/RouterState.java @@ -60,7 +60,7 @@ public static RouterState newInstance(String addr, long startTime, record.setAddress(addr); record.setStatus(status); record.setCompileInfo(FederationUtil.getCompileInfo()); - record.setBuildVersion(FederationUtil.getBuildVersion()); + record.setVersion(FederationUtil.getVersion()); return record; } @@ -78,9 +78,9 @@ public static RouterState newInstance(String addr, long startTime, public abstract void setStatus(RouterServiceState newStatus); - public abstract String getBuildVersion(); + public abstract String getVersion(); - public abstract void setBuildVersion(String version); + public abstract void setVersion(String version); public abstract String getCompileInfo(); @@ -116,7 +116,7 @@ public boolean like(BaseRecord o) { @Override public String toString() { - return getAddress() + " -> " + getStatus() + "," + getBuildVersion(); + return getAddress() + " -> " + getStatus() + "," + getVersion(); } @Override diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/federation/store/records/impl/pb/RouterStatePBImpl.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/federation/store/records/impl/pb/RouterStatePBImpl.java index aebc7a81f5..23a61f92b7 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/federation/store/records/impl/pb/RouterStatePBImpl.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/federation/store/records/impl/pb/RouterStatePBImpl.java @@ -133,21 +133,21 @@ public void setStatus(RouterServiceState newStatus) { } @Override - public String getBuildVersion() { + public String getVersion() { RouterRecordProtoOrBuilder proto = this.translator.getProtoOrBuilder(); - if (!proto.hasBuildVersion()) { + if (!proto.hasVersion()) { return null; } - return proto.getBuildVersion(); + return proto.getVersion(); } @Override - public void setBuildVersion(String version) { + public void setVersion(String version) { RouterRecordProto.Builder builder = this.translator.getBuilder(); if (version == null) { - builder.clearBuildVersion(); + builder.clearVersion(); } else { - builder.setBuildVersion(version); + builder.setVersion(version); } } diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/proto/FederationProtocol.proto b/hadoop-hdfs-project/hadoop-hdfs/src/main/proto/FederationProtocol.proto index f98d0ad7f2..58d05fc771 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/proto/FederationProtocol.proto +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/proto/FederationProtocol.proto @@ -188,7 +188,7 @@ message RouterRecordProto { optional string address = 3; optional string status = 4; optional StateStoreVersionRecordProto stateStoreVersion = 5; - optional string buildVersion = 6; + optional string version = 6; optional string compileInfo = 7; optional uint64 dateStarted = 8; } diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/router/federationhealth.html b/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/router/federationhealth.html index ac5bb49812..b89e5aa420 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/router/federationhealth.html +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/router/federationhealth.html @@ -245,6 +245,47 @@ + +
+
    +
  • Active
  • +
  • Safe mode
  • +
  • Unavailable
  • +
+
+ + + + + + + + + + + + + + + + + + + {#Routers} + + + + + + + + + + {/Routers} + +
Last update
AddressStatusHeartbeatMembershipMount tableVersion
{address}{status}{lastHeartbeat} sec ago{lastMembershipUpdate}{lastMountTableUpdate}{version}
+ +