diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/conf/OzoneConfiguration.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/conf/OzoneConfiguration.java index f863f3a303e3..fc09a5a59337 100644 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/conf/OzoneConfiguration.java +++ b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/conf/OzoneConfiguration.java @@ -209,11 +209,16 @@ public boolean equals(Object obj) { } } - /** Add default resources. */ - public static void activate() { - // core-default and core-site are added by parent class - addDefaultResource("hdfs-default.xml"); - addDefaultResource("hdfs-site.xml"); + public static List getConfigurationResourceFiles() { + List resourceFiles = new ArrayList<>(); + + // even though core-default and core-site are added by the parent Configuration class, + // we add it here for them to be a part of the resourceFiles list. + // addDefaultResource is idempotent so any duplicate items in this list will be handled accordingly + resourceFiles.add("hdfs-default.xml"); + resourceFiles.add("hdfs-site.xml"); + resourceFiles.add("core-default.xml"); + resourceFiles.add("core-site.xml"); // Modules with @Config annotations. If new one is introduced, add it to this list. String[] modules = new String[] { @@ -228,12 +233,21 @@ public static void activate() { "ozone-recon", }; for (String module : modules) { - addDefaultResource(module + "-default.xml"); + resourceFiles.add(module + "-default.xml"); } // Non-generated configs - addDefaultResource("ozone-default.xml"); - addDefaultResource("ozone-site.xml"); + resourceFiles.add("ozone-default.xml"); + resourceFiles.add("ozone-site.xml"); + + return resourceFiles; + } + + /** Add default resources. */ + public static void activate() { + for (String resourceFile : getConfigurationResourceFiles()) { + addDefaultResource(resourceFile); + } } /** diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/conf/HddsConfServlet.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/conf/HddsConfServlet.java index 066735a02582..719ce0522763 100644 --- a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/conf/HddsConfServlet.java +++ b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/conf/HddsConfServlet.java @@ -17,8 +17,12 @@ package org.apache.hadoop.hdds.conf; +import static org.apache.hadoop.hdds.conf.OzoneConfiguration.getConfigurationResourceFiles; + import java.io.IOException; +import java.io.InputStream; import java.io.Writer; +import java.net.URL; import java.util.HashMap; import java.util.Map; import java.util.Properties; @@ -26,14 +30,22 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import org.apache.commons.lang3.StringUtils; import org.apache.hadoop.conf.ConfServlet.BadFormatException; import org.apache.hadoop.hdds.annotation.InterfaceAudience; import org.apache.hadoop.hdds.annotation.InterfaceStability; import org.apache.hadoop.hdds.server.JsonUtils; import org.apache.hadoop.hdds.server.http.HttpServer2; import org.apache.hadoop.hdds.utils.HttpServletUtils; +import org.apache.hadoop.util.XMLUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; /** * A servlet to print out the running configuration data. @@ -123,12 +135,25 @@ private void processConfigTagRequest(HttpServletRequest request, String cmd, Htt throw new IllegalArgumentException("The tags parameter should be set" + " when using the getPropertyByTag command."); } - Map propMap = new HashMap<>(); + + Map descriptionMap = buildDescriptionMap(config); + Map> propMap = new HashMap<>(); for (String tag : tags.split(",")) { if (config.isPropertyTag(tag)) { Properties properties = config.getAllPropertiesByTag(tag); - propMap.put(tag, properties); + Map metadataMap = new HashMap<>(); + + for (String propName : properties.stringPropertyNames()) { + String value = properties.getProperty(propName); + String description = descriptionMap.getOrDefault(propName, ""); + OzoneConfiguration.Property property = new OzoneConfiguration.Property(); + property.setName(propName); + property.setValue(value); + property.setDescription(description); + metadataMap.put(propName, property); + } + propMap.put(tag, metadataMap); } } out.write(JsonUtils.toJsonString(propMap)); @@ -138,6 +163,75 @@ private void processConfigTagRequest(HttpServletRequest request, String cmd, Htt } } + /** + * Build a map of property names to descriptions by reading from configuration resources. + * @param config the OzoneConfiguration to extract descriptions from + * @return map of property name to description + */ + private Map buildDescriptionMap(OzoneConfiguration config) { + Map descriptionMap = new HashMap<>(); + + try { + DocumentBuilderFactory factory = XMLUtils.newSecureDocumentBuilderFactory(); + DocumentBuilder builder = factory.newDocumentBuilder(); + + for (String resourceName : getConfigurationResourceFiles()) { + URL resourceUrl = config.getResource(resourceName); + if (resourceUrl != null) { + parseXmlDescriptions(builder, resourceUrl, descriptionMap); + } + } + } catch (Exception e) { + LOG.error("Failed to parse XML resource files", e); + } + + return descriptionMap; + } + + /** + * Parse XML configuration file and extract property descriptions using DOM parser. + * @param builder The XML parser + * @param resourceUrl URL of the XML resource to parse + * @param descriptionMap map to populate with property name -> description mappings + */ + private void parseXmlDescriptions(DocumentBuilder builder, URL resourceUrl, Map descriptionMap) { + try (InputStream inputStream = resourceUrl.openStream()) { + Document doc = builder.parse(inputStream); + NodeList propertyNodes = doc.getElementsByTagName("property"); + + for (int i = 0; i < propertyNodes.getLength(); i++) { + Node propertyNode = propertyNodes.item(i); + if (propertyNode.getNodeType() == Node.ELEMENT_NODE) { + Element propertyElement = (Element) propertyNode; + + String name = getTextContent(propertyElement, "name"); + String description = getTextContent(propertyElement, "description"); + + if (name != null && !StringUtils.isBlank(description)) { + descriptionMap.put(name, description.trim()); + } + } + } + } catch (Exception e) { + LOG.error("Failed to parse XML from resource: {}", resourceUrl, e); + } + } + + /** + * Get text content of a child element by tag name. + * @param parent parent element + * @param tagName tag name of child element + * @return text content of the child element, or null if not found + */ + private String getTextContent(Element parent, String tagName) { + NodeList nodeList = parent.getElementsByTagName(tagName); + if (nodeList.getLength() > 0) { + Node node = nodeList.item(0); + return node.getTextContent(); + } + return null; + } + private static OzoneConfiguration getOzoneConfig() { return OZONE_CONFIG; } diff --git a/hadoop-hdds/framework/src/main/resources/webapps/static/ozone.js b/hadoop-hdds/framework/src/main/resources/webapps/static/ozone.js index 7bb93106284f..aac641e625e1 100644 --- a/hadoop-hdds/framework/src/main/resources/webapps/static/ozone.js +++ b/hadoop-hdds/framework/src/main/resources/webapps/static/ozone.js @@ -296,13 +296,15 @@ for (var idx in srcObj) { //console.log("Adding keys for "+idx) for (var key in srcObj[idx]) { - + var propMetadata = srcObj[idx][key]; + if (ctrl.keyTagMap.hasOwnProperty(key)) { ctrl.keyTagMap[key]['tag'].push(idx); } else { var newProp = {}; - newProp['name'] = key; - newProp['value'] = srcObj[idx][key]; + newProp['name'] = propMetadata.name || key; + newProp['value'] = propMetadata.value; + newProp['description'] = propMetadata.description || ''; newProp['tag'] = []; newProp['tag'].push(idx); ctrl.keyTagMap[key] = newProp; @@ -392,4 +394,4 @@ } }); -})(); \ No newline at end of file +})(); diff --git a/hadoop-hdds/framework/src/main/resources/webapps/static/templates/config.html b/hadoop-hdds/framework/src/main/resources/webapps/static/templates/config.html index b52f6533fc90..9d3bc90915d4 100644 --- a/hadoop-hdds/framework/src/main/resources/webapps/static/templates/config.html +++ b/hadoop-hdds/framework/src/main/resources/webapps/static/templates/config.html @@ -81,8 +81,8 @@ - {{config.name}} - {{config.value}} + {{config.name}} + {{config.value}} {{config.description}}