All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.hadoop.hdfs.server.namenode.ClusterJspHelper Maven / Gradle / Ivy

There is a newer version: 3.2.0-9
Show newest version
/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.hadoop.hdfs.server.namenode;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.management.MalformedObjectNameException;

import io.prestosql.hadoop.$internal.org.apache.commons.logging.Log;
import io.prestosql.hadoop.$internal.org.apache.commons.logging.LogFactory;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hdfs.DFSConfigKeys;
import org.apache.hadoop.hdfs.DFSUtil;
import org.apache.hadoop.hdfs.DFSUtil.ConfiguredNNAddress;
import org.apache.hadoop.hdfs.protocol.DatanodeInfo.AdminStates;
import org.apache.hadoop.util.StringUtils;
import io.prestosql.hadoop.$internal.org.codehaus.jackson.JsonNode;
import io.prestosql.hadoop.$internal.org.codehaus.jackson.map.ObjectMapper;
import io.prestosql.hadoop.$internal.org.codehaus.jackson.type.TypeReference;
import org.znerd.xmlenc.XMLOutputter;

import io.prestosql.hadoop.$internal.com.google.common.base.Charsets;

/**
 * This class generates the data that is needed to be displayed on cluster web 
 * console.
 */
@InterfaceAudience.Private
class ClusterJspHelper {
  private static final Log LOG = LogFactory.getLog(ClusterJspHelper.class);
  public static final String OVERALL_STATUS = "overall-status";
  public static final String DEAD = "Dead";
  private static final String JMX_QRY = 
    "/jmx?qry=Hadoop:service=NameNode,name=NameNodeInfo";
  
  /**
   * JSP helper function that generates cluster health report.  When 
   * encountering exception while getting Namenode status, the exception will 
   * be listed on the page with corresponding stack trace.
   */
  ClusterStatus generateClusterHealthReport() {
    ClusterStatus cs = new ClusterStatus();
    Configuration conf = new Configuration();
    List nns = null;
    try {
      nns = DFSUtil.flattenAddressMap(
          DFSUtil.getNNServiceRpcAddresses(conf));
    } catch (Exception e) {
      // Could not build cluster status
      cs.setError(e);
      return cs;
    }
    
    // Process each namenode and add it to ClusterStatus
    for (ConfiguredNNAddress cnn : nns) {
      InetSocketAddress isa = cnn.getAddress();
      NamenodeMXBeanHelper nnHelper = null;
      try {
        nnHelper = new NamenodeMXBeanHelper(isa, conf);
        String mbeanProps= queryMbean(nnHelper.httpAddress, conf);
        NamenodeStatus nn = nnHelper.getNamenodeStatus(mbeanProps);
        if (cs.clusterid.isEmpty() || cs.clusterid.equals("")) { // Set clusterid only once
          cs.clusterid = nnHelper.getClusterId(mbeanProps);
        }
        cs.addNamenodeStatus(nn);
      } catch ( Exception e ) {
        // track exceptions encountered when connecting to namenodes
        cs.addException(isa.getHostName(), e);
        continue;
      } 
    }
    return cs;
  }

  /**
   * Helper function that generates the decommissioning report.  Connect to each
   * Namenode over http via JmxJsonServlet to collect the data nodes status.
   */
  DecommissionStatus generateDecommissioningReport() {
    String clusterid = "";
    Configuration conf = new Configuration();
    List cnns = null;
    try {
      cnns = DFSUtil.flattenAddressMap(
          DFSUtil.getNNServiceRpcAddresses(conf));
    } catch (Exception e) {
      // catch any exception encountered other than connecting to namenodes
      DecommissionStatus dInfo = new DecommissionStatus(clusterid, e);
      return dInfo;
    }
    
    // Outer map key is datanode. Inner map key is namenode and the value is 
    // decom status of the datanode for the corresponding namenode
    Map> statusMap = 
      new HashMap>();
    
    // Map of exceptions encountered when connecting to namenode
    // key is namenode and value is exception
    Map decommissionExceptions = 
      new HashMap();
    
    List unreportedNamenode = new ArrayList();
    for (ConfiguredNNAddress cnn : cnns) {
      InetSocketAddress isa = cnn.getAddress();
      NamenodeMXBeanHelper nnHelper = null;
      try {
        nnHelper = new NamenodeMXBeanHelper(isa, conf);
        String mbeanProps= queryMbean(nnHelper.httpAddress, conf);
        if (clusterid.equals("")) {
          clusterid = nnHelper.getClusterId(mbeanProps);
        }
        nnHelper.getDecomNodeInfoForReport(statusMap, mbeanProps);
      } catch (Exception e) {
        // catch exceptions encountered while connecting to namenodes
        String nnHost = isa.getHostName();
        decommissionExceptions.put(nnHost, e);
        unreportedNamenode.add(nnHost);
        continue;
      } 
    }
    updateUnknownStatus(statusMap, unreportedNamenode);
    getDecommissionNodeClusterState(statusMap);
    return new DecommissionStatus(statusMap, clusterid,
        getDatanodeHttpPort(conf), decommissionExceptions);
  }
  
  /**
   * Based on the state of the datanode at each namenode, marks the overall
   * state of the datanode across all the namenodes, to one of the following:
   * 
    *
  1. {@link DecommissionStates#DECOMMISSIONED}
  2. *
  3. {@link DecommissionStates#DECOMMISSION_INPROGRESS}
  4. *
  5. {@link DecommissionStates#PARTIALLY_DECOMMISSIONED}
  6. *
  7. {@link DecommissionStates#UNKNOWN}
  8. *
* * @param statusMap * map whose key is datanode, value is an inner map with key being * namenode, value being decommission state. */ private void getDecommissionNodeClusterState( Map> statusMap) { if (statusMap == null || statusMap.isEmpty()) { return; } // For each datanodes Iterator>> it = statusMap.entrySet().iterator(); while (it.hasNext()) { // Map entry for a datanode: // key is namenode, value is datanode status at the namenode Entry> entry = it.next(); Map nnStatus = entry.getValue(); if (nnStatus == null || nnStatus.isEmpty()) { continue; } boolean isUnknown = false; int unknown = 0; int decommissioned = 0; int decomInProg = 0; int inservice = 0; int dead = 0; DecommissionStates overallState = DecommissionStates.UNKNOWN; // Process a datanode state from each namenode for (Map.Entry m : nnStatus.entrySet()) { String status = m.getValue(); if (status.equals(DecommissionStates.UNKNOWN.toString())) { isUnknown = true; unknown++; } else if (status.equals(AdminStates.DECOMMISSION_INPROGRESS.toString())) { decomInProg++; } else if (status.equals(AdminStates.DECOMMISSIONED.toString())) { decommissioned++; } else if (status.equals(AdminStates.NORMAL.toString())) { inservice++; } else if (status.equals(DEAD)) { // dead dead++; } } // Consolidate all the states from namenode in to overall state int nns = nnStatus.keySet().size(); if ((inservice + dead + unknown) == nns) { // Do not display this data node. Remove this entry from status map. it.remove(); } else if (isUnknown) { overallState = DecommissionStates.UNKNOWN; } else if (decommissioned == nns) { overallState = DecommissionStates.DECOMMISSIONED; } else if ((decommissioned + decomInProg) == nns) { overallState = DecommissionStates.DECOMMISSION_INPROGRESS; } else if ((decommissioned + decomInProg < nns) && (decommissioned + decomInProg > 0)){ overallState = DecommissionStates.PARTIALLY_DECOMMISSIONED; } else { LOG.warn("Cluster console encounters a not handled situtation."); } // insert overall state nnStatus.put(OVERALL_STATUS, overallState.toString()); } } /** * update unknown status in datanode status map for every unreported namenode */ private void updateUnknownStatus(Map> statusMap, List unreportedNn) { if (unreportedNn == null || unreportedNn.isEmpty()) { // no unreported namenodes return; } for (Map.Entry> entry : statusMap.entrySet()) { String dn = entry.getKey(); Map nnStatus = entry.getValue(); for (String nn : unreportedNn) { nnStatus.put(nn, DecommissionStates.UNKNOWN.toString()); } statusMap.put(dn, nnStatus); } } /** * Get datanode http port from configration */ private int getDatanodeHttpPort(Configuration conf) { String address = conf.get(DFSConfigKeys.DFS_DATANODE_HTTP_ADDRESS_KEY, ""); if (address.equals("")) { return -1; } return Integer.parseInt(address.split(":")[1]); } /** * Class for connecting to Namenode over http via JmxJsonServlet * to get JMX attributes exposed by the MXBean. */ static class NamenodeMXBeanHelper { private static final ObjectMapper mapper = new ObjectMapper(); private final String host; private final URI httpAddress; NamenodeMXBeanHelper(InetSocketAddress addr, Configuration conf) throws IOException, MalformedObjectNameException { this.host = addr.getHostName(); this.httpAddress = DFSUtil.getInfoServer(addr, conf, DFSUtil.getHttpClientScheme(conf)); } /** Get the map corresponding to the JSON string */ private static Map> getNodeMap(String json) throws IOException { TypeReference>> type = new TypeReference>>() { }; return mapper.readValue(json, type); } /** * Get the number of live datanodes. * * @param json JSON string that contains live node status. * @param nn namenode status to return information in */ private static void getLiveNodeCount(String json, NamenodeStatus nn) throws IOException { // Map of datanode host to (map of attribute name to value) Map> nodeMap = getNodeMap(json); if (nodeMap == null || nodeMap.isEmpty()) { return; } nn.liveDatanodeCount = nodeMap.size(); for (Entry> entry : nodeMap.entrySet()) { // Inner map of attribute name to value Map innerMap = entry.getValue(); if (innerMap != null) { if (innerMap.get("adminState") .equals(AdminStates.DECOMMISSIONED.toString())) { nn.liveDecomCount++; } } } } /** * Count the number of dead datanode. * * @param nn namenode * @param json JSON string */ private static void getDeadNodeCount(String json, NamenodeStatus nn) throws IOException { Map> nodeMap = getNodeMap(json); if (nodeMap == null || nodeMap.isEmpty()) { return; } nn.deadDatanodeCount = nodeMap.size(); for (Entry> entry : nodeMap.entrySet()) { Map innerMap = entry.getValue(); if (innerMap != null && !innerMap.isEmpty()) { if (((Boolean) innerMap.get("decommissioned")) .booleanValue() == true) { nn.deadDecomCount++; } } } } public String getClusterId(String props) throws IOException { return getProperty(props, "ClusterId").getTextValue(); } public NamenodeStatus getNamenodeStatus(String props) throws IOException, MalformedObjectNameException, NumberFormatException { NamenodeStatus nn = new NamenodeStatus(); nn.host = host; nn.filesAndDirectories = getProperty(props, "TotalFiles").getLongValue(); nn.capacity = getProperty(props, "Total").getLongValue(); nn.free = getProperty(props, "Free").getLongValue(); nn.bpUsed = getProperty(props, "BlockPoolUsedSpace").getLongValue(); nn.nonDfsUsed = getProperty(props, "NonDfsUsedSpace").getLongValue(); nn.blocksCount = getProperty(props, "TotalBlocks").getLongValue(); nn.missingBlocksCount = getProperty(props, "NumberOfMissingBlocks") .getLongValue(); nn.httpAddress = httpAddress.toURL(); getLiveNodeCount(getProperty(props, "LiveNodes").asText(), nn); getDeadNodeCount(getProperty(props, "DeadNodes").asText(), nn); nn.softwareVersion = getProperty(props, "SoftwareVersion").getTextValue(); return nn; } /** * Get the decommission node information. * @param statusMap data node status map * @param props string */ private void getDecomNodeInfoForReport( Map> statusMap, String props) throws IOException, MalformedObjectNameException { getLiveNodeStatus(statusMap, host, getProperty(props, "LiveNodes") .asText()); getDeadNodeStatus(statusMap, host, getProperty(props, "DeadNodes") .asText()); getDecommissionNodeStatus(statusMap, host, getProperty(props, "DecomNodes").asText()); } /** * Store the live datanode status information into datanode status map and * DecommissionNode. * * @param statusMap Map of datanode status. Key is datanode, value * is an inner map whose key is namenode, value is datanode status. * reported by each namenode. * @param namenodeHost host name of the namenode * @param json JSON string contains datanode status * @throws IOException */ private static void getLiveNodeStatus( Map> statusMap, String namenodeHost, String json) throws IOException { Map> nodeMap = getNodeMap(json); if (nodeMap != null && !nodeMap.isEmpty()) { List liveDecommed = new ArrayList(); for (Map.Entry> entry: nodeMap.entrySet()) { Map innerMap = entry.getValue(); String dn = entry.getKey(); if (innerMap != null) { if (innerMap.get("adminState").equals( AdminStates.DECOMMISSIONED.toString())) { liveDecommed.add(dn); } // the inner map key is namenode, value is datanode status. Map nnStatus = statusMap.get(dn); if (nnStatus == null) { nnStatus = new HashMap(); } nnStatus.put(namenodeHost, (String) innerMap.get("adminState")); // map whose key is datanode, value is the inner map. statusMap.put(dn, nnStatus); } } } } /** * Store the dead datanode information into datanode status map and * DecommissionNode. * * @param statusMap map with key being datanode, value being an * inner map (key:namenode, value:decommisionning state). * @param host datanode hostname * @param json String * @throws IOException */ private static void getDeadNodeStatus( Map> statusMap, String host, String json) throws IOException { Map> nodeMap = getNodeMap(json); if (nodeMap == null || nodeMap.isEmpty()) { return; } List deadDn = new ArrayList(); List deadDecommed = new ArrayList(); for (Entry> entry : nodeMap.entrySet()) { deadDn.add(entry.getKey()); Map deadNodeDetailMap = entry.getValue(); String dn = entry.getKey(); if (deadNodeDetailMap != null && !deadNodeDetailMap.isEmpty()) { // NN - status Map nnStatus = statusMap.get(dn); if (nnStatus == null) { nnStatus = new HashMap(); } if (((Boolean) deadNodeDetailMap.get("decommissioned")) .booleanValue() == true) { deadDecommed.add(dn); nnStatus.put(host, AdminStates.DECOMMISSIONED.toString()); } else { nnStatus.put(host, DEAD); } // dn-nn-status statusMap.put(dn, nnStatus); } } } /** * Get the decommisioning datanode information. * * @param dataNodeStatusMap map with key being datanode, value being an * inner map (key:namenode, value:decommisionning state). * @param host datanode * @param json String */ private static void getDecommissionNodeStatus( Map> dataNodeStatusMap, String host, String json) throws IOException { Map> nodeMap = getNodeMap(json); if (nodeMap == null || nodeMap.isEmpty()) { return; } List decomming = new ArrayList(); for (Entry> entry : nodeMap.entrySet()) { String dn = entry.getKey(); decomming.add(dn); // nn-status Map nnStatus = new HashMap(); if (dataNodeStatusMap.containsKey(dn)) { nnStatus = dataNodeStatusMap.get(dn); } nnStatus.put(host, AdminStates.DECOMMISSION_INPROGRESS.toString()); // dn-nn-status dataNodeStatusMap.put(dn, nnStatus); } } } /** * This class contains cluster statistics. */ static class ClusterStatus { /** Exception indicates failure to get cluster status */ Exception error = null; /** Cluster status information */ String clusterid = ""; long total_sum = 0; long free_sum = 0; long clusterDfsUsed = 0; long nonDfsUsed_sum = 0; long totalFilesAndDirectories = 0; /** List of namenodes in the cluster */ final List nnList = new ArrayList(); /** Map of namenode host and exception encountered when getting status */ final Map nnExceptions = new HashMap(); public void setError(Exception e) { error = e; } public void addNamenodeStatus(NamenodeStatus nn) { nnList.add(nn); // Add namenode status to cluster status totalFilesAndDirectories += nn.filesAndDirectories; total_sum += nn.capacity; free_sum += nn.free; clusterDfsUsed += nn.bpUsed; nonDfsUsed_sum += nn.nonDfsUsed; } public void addException(String host, Exception e) { nnExceptions.put(host, e); } public void toXML(XMLOutputter doc) throws IOException { if (error != null) { // general exception, only print exception message onto web page. createGeneralException(doc, clusterid, StringUtils.stringifyException(error)); doc.getWriter().flush(); return; } int size = nnList.size(); long total = 0L, free = 0L, nonDfsUsed = 0l; float dfsUsedPercent = 0.0f, dfsRemainingPercent = 0.0f; if (size > 0) { total = total_sum / size; free = free_sum / size; nonDfsUsed = nonDfsUsed_sum / size; dfsUsedPercent = DFSUtil.getPercentUsed(clusterDfsUsed, total); dfsRemainingPercent = DFSUtil.getPercentRemaining(free, total); } doc.startTag("cluster"); doc.attribute("clusterId", clusterid); doc.startTag("storage"); toXmlItemBlock(doc, "Total Files And Directories", Long.toString(totalFilesAndDirectories)); toXmlItemBlock(doc, "Configured Capacity", StringUtils.byteDesc(total)); toXmlItemBlock(doc, "DFS Used", StringUtils.byteDesc(clusterDfsUsed)); toXmlItemBlock(doc, "Non DFS Used", StringUtils.byteDesc(nonDfsUsed)); toXmlItemBlock(doc, "DFS Remaining", StringUtils.byteDesc(free)); // dfsUsedPercent toXmlItemBlock(doc, "DFS Used%", DFSUtil.percent2String(dfsUsedPercent)); // dfsRemainingPercent toXmlItemBlock(doc, "DFS Remaining%", DFSUtil.percent2String(dfsRemainingPercent)); doc.endTag(); // storage doc.startTag("namenodes"); // number of namenodes toXmlItemBlock(doc, "NamenodesCount", Integer.toString(size)); for (NamenodeStatus nn : nnList) { doc.startTag("node"); toXmlItemBlockWithLink(doc, nn.host, nn.httpAddress, "NameNode"); toXmlItemBlock(doc, "Blockpool Used", StringUtils.byteDesc(nn.bpUsed)); toXmlItemBlock(doc, "Blockpool Used%", DFSUtil.percent2String(DFSUtil.getPercentUsed(nn.bpUsed, total))); toXmlItemBlock(doc, "Files And Directories", Long.toString(nn.filesAndDirectories)); toXmlItemBlock(doc, "Blocks", Long.toString(nn.blocksCount)); toXmlItemBlock(doc, "Missing Blocks", Long.toString(nn.missingBlocksCount)); toXmlItemBlockWithLink(doc, nn.liveDatanodeCount + " (" + nn.liveDecomCount + ")", new URL(nn.httpAddress, "/dfsnodelist.jsp?whatNodes=LIVE"), "Live Datanode (Decommissioned)"); toXmlItemBlockWithLink(doc, nn.deadDatanodeCount + " (" + nn.deadDecomCount + ")", new URL(nn.httpAddress, "/dfsnodelist.jsp?whatNodes=DEAD"), "Dead Datanode (Decommissioned)"); toXmlItemBlock(doc, "Software Version", nn.softwareVersion); doc.endTag(); // node } doc.endTag(); // namenodes createNamenodeExceptionMsg(doc, nnExceptions); doc.endTag(); // cluster doc.getWriter().flush(); } } /** * This class stores namenode statistics to be used to generate cluster * web console report. */ static class NamenodeStatus { String host = ""; long capacity = 0L; long free = 0L; long bpUsed = 0L; long nonDfsUsed = 0L; long filesAndDirectories = 0L; long blocksCount = 0L; long missingBlocksCount = 0L; int liveDatanodeCount = 0; int liveDecomCount = 0; int deadDatanodeCount = 0; int deadDecomCount = 0; URL httpAddress = null; String softwareVersion = ""; } /** * cluster-wide decommission state of a datanode */ public enum DecommissionStates { /* * If datanode state is decommissioning at one or more namenodes and * decommissioned at the rest of the namenodes. */ DECOMMISSION_INPROGRESS("Decommission In Progress"), /* If datanode state at all the namenodes is decommissioned */ DECOMMISSIONED("Decommissioned"), /* * If datanode state is not decommissioning at one or more namenodes and * decommissioned/decommissioning at the rest of the namenodes. */ PARTIALLY_DECOMMISSIONED("Partially Decommissioning"), /* * If datanode state is not known at a namenode, due to problems in getting * the datanode state from the namenode. */ UNKNOWN("Unknown"); final String value; DecommissionStates(final String v) { this.value = v; } @Override public String toString() { return value; } } /** * This class consolidates the decommissioning datanodes information in the * cluster and generates decommissioning reports in XML. */ static class DecommissionStatus { /** Error when set indicates failure to get decomission status*/ final Exception error; /** Map of dn host <-> (Map of NN host <-> decommissioning state) */ final Map> statusMap; final String clusterid; final int httpPort; int decommissioned = 0; // total number of decommissioned nodes int decommissioning = 0; // total number of decommissioning datanodes int partial = 0; // total number of partially decommissioned nodes /** Map of namenode and exception encountered when getting decom status */ Map exceptions = new HashMap(); private DecommissionStatus(Map> statusMap, String cid, int httpPort, Map exceptions) { this(statusMap, cid, httpPort, exceptions, null); } public DecommissionStatus(String cid, Exception e) { this(null, cid, -1, null, e); } private DecommissionStatus(Map> statusMap, String cid, int httpPort, Map exceptions, Exception error) { this.statusMap = statusMap; this.clusterid = cid; this.httpPort = httpPort; this.exceptions = exceptions; this.error = error; } /** * Generate decommissioning datanode report in XML format * * @param doc * , xmloutputter * @throws IOException */ public void toXML(XMLOutputter doc) throws IOException { if (error != null) { createGeneralException(doc, clusterid, StringUtils.stringifyException(error)); doc.getWriter().flush(); return; } if (statusMap == null || statusMap.isEmpty()) { // none of the namenodes has reported, print exceptions from each nn. doc.startTag("cluster"); createNamenodeExceptionMsg(doc, exceptions); doc.endTag(); doc.getWriter().flush(); return; } doc.startTag("cluster"); doc.attribute("clusterId", clusterid); doc.startTag("decommissioningReport"); countDecommissionDatanodes(); toXmlItemBlock(doc, DecommissionStates.DECOMMISSIONED.toString(), Integer.toString(decommissioned)); toXmlItemBlock(doc, DecommissionStates.DECOMMISSION_INPROGRESS.toString(), Integer.toString(decommissioning)); toXmlItemBlock(doc, DecommissionStates.PARTIALLY_DECOMMISSIONED.toString(), Integer.toString(partial)); doc.endTag(); // decommissioningReport doc.startTag("datanodes"); Set dnSet = statusMap.keySet(); for (String dnhost : dnSet) { Map nnStatus = statusMap.get(dnhost); if (nnStatus == null || nnStatus.isEmpty()) { continue; } String overallStatus = nnStatus.get(OVERALL_STATUS); // check if datanode is in decommission states if (overallStatus != null && (overallStatus.equals(AdminStates.DECOMMISSION_INPROGRESS .toString()) || overallStatus.equals(AdminStates.DECOMMISSIONED.toString()) || overallStatus .equals(DecommissionStates.PARTIALLY_DECOMMISSIONED .toString()) || overallStatus .equals(DecommissionStates.UNKNOWN.toString()))) { doc.startTag("node"); // dn toXmlItemBlockWithLink(doc, dnhost, new URL("http", dnhost, httpPort, ""), "DataNode"); // overall status first toXmlItemBlock(doc, OVERALL_STATUS, overallStatus); for (Map.Entry m : nnStatus.entrySet()) { String nn = m.getKey(); if (nn.equals(OVERALL_STATUS)) { continue; } // xml toXmlItemBlock(doc, nn, nnStatus.get(nn)); } doc.endTag(); // node } } doc.endTag(); // datanodes createNamenodeExceptionMsg(doc, exceptions); doc.endTag();// cluster } // toXML /** * Count the total number of decommissioned/decommission_inprogress/ * partially decommissioned datanodes. */ private void countDecommissionDatanodes() { for (String dn : statusMap.keySet()) { Map nnStatus = statusMap.get(dn); String status = nnStatus.get(OVERALL_STATUS); if (status.equals(DecommissionStates.DECOMMISSIONED.toString())) { decommissioned++; } else if (status.equals(DecommissionStates.DECOMMISSION_INPROGRESS .toString())) { decommissioning++; } else if (status.equals(DecommissionStates.PARTIALLY_DECOMMISSIONED .toString())) { partial++; } } } } /** * Generate a XML block as such, */ private static void toXmlItemBlock(XMLOutputter doc, String key, String value) throws IOException { doc.startTag("item"); doc.attribute("label", key); doc.attribute("value", value); doc.endTag(); } /** * Generate a XML block as such, */ private static void toXmlItemBlockWithLink(XMLOutputter doc, String value, URL url, String label) throws IOException { doc.startTag("item"); doc.attribute("label", label); doc.attribute("value", value); doc.attribute("link", url.toString()); doc.endTag(); // item } /** * create the XML for exceptions that we encountered when connecting to * namenode. */ private static void createNamenodeExceptionMsg(XMLOutputter doc, Map exceptionMsg) throws IOException { if (exceptionMsg.size() > 0) { doc.startTag("unreportedNamenodes"); for (Map.Entry m : exceptionMsg.entrySet()) { doc.startTag("node"); doc.attribute("name", m.getKey()); doc.attribute("exception", StringUtils.stringifyException(m.getValue())); doc.endTag();// node } doc.endTag(); // unreportedNamnodes } } /** * create XML block from general exception. */ private static void createGeneralException(XMLOutputter doc, String clusterid, String eMsg) throws IOException { doc.startTag("cluster"); doc.attribute("clusterId", clusterid); doc.startTag("message"); doc.startTag("item"); doc.attribute("msg", eMsg); doc.endTag(); // item doc.endTag(); // message doc.endTag(); // cluster } /** * Read in the content from a URL * @param url URL To read * @return the text from the output * @throws IOException if something went wrong */ private static String readOutput(URL url) throws IOException { StringBuilder out = new StringBuilder(); URLConnection connection = url.openConnection(); BufferedReader in = new BufferedReader( new InputStreamReader( connection.getInputStream(), Charsets.UTF_8)); String inputLine; while ((inputLine = in.readLine()) != null) { out.append(inputLine); } in.close(); return out.toString(); } private static String queryMbean(URI httpAddress, Configuration conf) throws IOException { /** * Although the other namenode might support HTTPS, it is fundamentally * broken to get the JMX via an HTTPS connection inside the namenode, * because in HTTPS set up the principal of the client and the one of * the namenode differs. Therefore, there is no guarantees that the * HTTPS connection can be set up. * * As a result, we just hard code the connection as an HTTP connection. */ URL url = new URL(httpAddress.toURL(), JMX_QRY); return readOutput(url); } /** * In order to query a namenode mxbean, a http connection in the form of * "http://hostname/jmx?qry=Hadoop:service=NameNode,name=NameNodeInfo" * is sent to namenode. JMX attributes are exposed via JmxJsonServelet on * the namenode side. */ private static JsonNode getProperty(String props, String propertyname) throws IOException { if (props == null || props.equals("") || propertyname == null || propertyname.equals("")) { return null; } ObjectMapper m = new ObjectMapper(); JsonNode rootNode = m.readValue(props, JsonNode.class); JsonNode jn = rootNode.get("beans").get(0).get(propertyname); return jn; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy