|
@@ -18,21 +18,21 @@
|
|
|
|
|
|
package org.apache.ambari.server.stack;
|
|
|
|
|
|
-import com.google.common.reflect.TypeToken;
|
|
|
-import org.apache.ambari.server.state.Cluster;
|
|
|
-import org.apache.ambari.server.utils.HTTPUtils;
|
|
|
-
|
|
|
import java.lang.reflect.Type;
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.HashMap;
|
|
|
-import java.util.Iterator;
|
|
|
+import java.util.LinkedHashSet;
|
|
|
import java.util.Map;
|
|
|
import java.util.Set;
|
|
|
|
|
|
+import org.apache.ambari.server.state.Cluster;
|
|
|
+import org.apache.ambari.server.utils.HTTPUtils;
|
|
|
import org.apache.ambari.server.utils.StageUtils;
|
|
|
import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
|
|
+import com.google.common.reflect.TypeToken;
|
|
|
+
|
|
|
|
|
|
public class MasterHostResolver {
|
|
|
|
|
@@ -42,7 +42,8 @@ public class MasterHostResolver {
|
|
|
|
|
|
enum Service {
|
|
|
HDFS,
|
|
|
- HBASE
|
|
|
+ HBASE,
|
|
|
+ YARN
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -53,10 +54,6 @@ public class MasterHostResolver {
|
|
|
STANDBY
|
|
|
}
|
|
|
|
|
|
- public MasterHostResolver() {
|
|
|
- ;
|
|
|
- }
|
|
|
-
|
|
|
public MasterHostResolver(Cluster cluster) {
|
|
|
this.cluster = cluster;
|
|
|
}
|
|
@@ -74,15 +71,21 @@ public class MasterHostResolver {
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
- Service s = Service.valueOf(serviceName.toUpperCase());
|
|
|
-
|
|
|
Set<String> componentHosts = cluster.getHosts(serviceName, componentName);
|
|
|
if (0 == componentHosts.size()) {
|
|
|
return null;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
hostsType.hosts = componentHosts;
|
|
|
|
|
|
+ Service s = null;
|
|
|
+ try {
|
|
|
+ s = Service.valueOf(serviceName.toUpperCase());
|
|
|
+ } catch (Exception e) {
|
|
|
+ // !!! nothing to do
|
|
|
+ return hostsType;
|
|
|
+ }
|
|
|
+
|
|
|
switch (s) {
|
|
|
case HDFS:
|
|
|
if (componentName.equalsIgnoreCase("NAMENODE")) {
|
|
@@ -90,13 +93,19 @@ public class MasterHostResolver {
|
|
|
if (pair != null) {
|
|
|
hostsType.master = pair.containsKey(Status.ACTIVE) ? pair.get(Status.ACTIVE) : null;
|
|
|
hostsType.secondary = pair.containsKey(Status.STANDBY) ? pair.get(Status.STANDBY) : null;
|
|
|
+ } else {
|
|
|
+ hostsType.master = componentHosts.iterator().next();
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
+ case YARN:
|
|
|
+ if (componentName.equalsIgnoreCase("RESOURCEMANAGER")) {
|
|
|
+ resolveResourceManagers(hostsType);
|
|
|
+ }
|
|
|
+ break;
|
|
|
case HBASE:
|
|
|
- if (componentName.equalsIgnoreCase("HBASE_REGIONSERVER")) {
|
|
|
- // TODO Rolling Upgrade, fill for this Component.
|
|
|
- ;
|
|
|
+ if (componentName.equalsIgnoreCase("HBASE_MASTER")) {
|
|
|
+ resolveHBaseMasters(hostsType);
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
@@ -110,42 +119,20 @@ public class MasterHostResolver {
|
|
|
*/
|
|
|
private Map<Status, String> getNameNodePair(Set<String> hosts) {
|
|
|
Map<Status, String> stateToHost = new HashMap<Status, String>();
|
|
|
+
|
|
|
if (hosts != null && hosts.size() == 2) {
|
|
|
- Iterator iter = hosts.iterator();
|
|
|
-
|
|
|
- while(iter.hasNext()) {
|
|
|
- String hostname = (String) iter.next();
|
|
|
- try {
|
|
|
- // TODO Rolling Upgrade, don't hardcode jmx port number
|
|
|
- // E.g.,
|
|
|
- // dfs.namenode.http-address.dev.nn1 : c6401.ambari.apache.org:50070
|
|
|
- // dfs.namenode.http-address.dev.nn2 : c6402.ambari.apache.org:50070
|
|
|
- String endpoint = "http://" + hostname + ":50070/jmx?qry=Hadoop:service=NameNode,name=NameNodeStatus";
|
|
|
- String response = HTTPUtils.requestURL(endpoint);
|
|
|
-
|
|
|
- if (response != null && !response.isEmpty()) {
|
|
|
- Map<String, ArrayList<HashMap<String, String>>> nameNodeInfo = new HashMap<String, ArrayList<HashMap<String, String>>>();
|
|
|
- Type type = new TypeToken<Map<String, ArrayList<HashMap<String, String>>>>() {}.getType();
|
|
|
- nameNodeInfo = StageUtils.getGson().fromJson(response, type);
|
|
|
-
|
|
|
- try {
|
|
|
- String state = nameNodeInfo.get("beans").get(0).get("State");
|
|
|
-
|
|
|
- if (state.equalsIgnoreCase(Status.ACTIVE.toString()) || state.equalsIgnoreCase(Status.STANDBY.toString())) {
|
|
|
- Status status = Status.valueOf(state.toUpperCase());
|
|
|
- stateToHost.put(status, hostname);
|
|
|
- }
|
|
|
- } catch (Exception e) {
|
|
|
- throw new Exception("Response from endpoint " + endpoint + " was not formatted correctly. Value: " + response);
|
|
|
- }
|
|
|
- } else {
|
|
|
- throw new Exception("Response from endpoint " + endpoint + " was empty.");
|
|
|
+ for (String hostname : hosts) {
|
|
|
+ String state = queryJmxBeanValue(hostname, 50070,
|
|
|
+ "Hadoop:service=NameNode,name=NameNodeStatus", "State", true);
|
|
|
+
|
|
|
+ if (null != state &&
|
|
|
+ (state.equalsIgnoreCase(Status.ACTIVE.toString()) ||
|
|
|
+ state.equalsIgnoreCase(Status.STANDBY.toString()))) {
|
|
|
+ Status status = Status.valueOf(state.toUpperCase());
|
|
|
+ stateToHost.put(status, hostname);
|
|
|
}
|
|
|
- } catch (Exception e) {
|
|
|
- LOG.warn("Failed to parse namenode jmx endpoint to get state for host " + hostname + ". Error: " + e.getMessage());
|
|
|
}
|
|
|
- }
|
|
|
-
|
|
|
+
|
|
|
if (stateToHost.containsKey(Status.ACTIVE) && stateToHost.containsKey(Status.STANDBY) && !stateToHost.get(Status.ACTIVE).equalsIgnoreCase(stateToHost.get(Status.STANDBY))) {
|
|
|
return stateToHost;
|
|
|
}
|
|
@@ -153,4 +140,75 @@ public class MasterHostResolver {
|
|
|
|
|
|
return null;
|
|
|
}
|
|
|
+
|
|
|
+ private void resolveResourceManagers(HostsType hostType) {
|
|
|
+ // !!! for RM, only the master returns jmx
|
|
|
+ Set<String> orderedHosts = new LinkedHashSet<String>(hostType.hosts);
|
|
|
+
|
|
|
+ for (String hostname : hostType.hosts) {
|
|
|
+
|
|
|
+ String value = queryJmxBeanValue(hostname, 8088,
|
|
|
+ "Hadoop:service=ResourceManager,name=RMNMInfo", "modelerType", true);
|
|
|
+
|
|
|
+ if (null != value) {
|
|
|
+ if (null == hostType.master) {
|
|
|
+ hostType.master = hostname;
|
|
|
+ }
|
|
|
+
|
|
|
+ // !!! quick and dirty to make sure the master is last in the list
|
|
|
+ orderedHosts.remove(hostname);
|
|
|
+ orderedHosts.add(hostname);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ hostType.hosts = orderedHosts;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void resolveHBaseMasters(HostsType hostsType) {
|
|
|
+
|
|
|
+ for (String hostname : hostsType.hosts) {
|
|
|
+
|
|
|
+ String value = queryJmxBeanValue(hostname, 60010,
|
|
|
+ "Hadoop:service=HBase,name=Master,sub=Server", "tag.isActiveMaster", false);
|
|
|
+
|
|
|
+ if (null != value) {
|
|
|
+ Boolean bool = Boolean.valueOf(value);
|
|
|
+ if (bool.booleanValue()) {
|
|
|
+ hostsType.master = hostname;
|
|
|
+ } else {
|
|
|
+ hostsType.secondary = hostname;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private String queryJmxBeanValue(String hostname, int port, String beanName, String attributeName,
|
|
|
+ boolean asQuery) {
|
|
|
+
|
|
|
+ String endPoint = asQuery ?
|
|
|
+ String.format("http://%s:%s/jmx?qry=%s", hostname, port, beanName) :
|
|
|
+ String.format("http://%s:%s/jmx?get=%s::%s", hostname, port, beanName, attributeName);
|
|
|
+
|
|
|
+ String response = HTTPUtils.requestURL(endPoint);
|
|
|
+
|
|
|
+ if (null == response || response.isEmpty()) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ Type type = new TypeToken<Map<String, ArrayList<HashMap<String, String>>>>() {}.getType();
|
|
|
+
|
|
|
+ try {
|
|
|
+ Map<String, ArrayList<HashMap<String, String>>> jmxBeans =
|
|
|
+ StageUtils.getGson().fromJson(response, type);
|
|
|
+
|
|
|
+ return jmxBeans.get("beans").get(0).get(attributeName);
|
|
|
+ } catch (Exception e) {
|
|
|
+ LOG.info("Could not load JMX from {}/{} from {}", beanName, attributeName, hostname, e);
|
|
|
+ }
|
|
|
+
|
|
|
+ return null;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
}
|