Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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<String> getConfigurationResourceFiles() {
List<String> 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[] {
Expand All @@ -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);
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,35 @@

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;
import javax.servlet.ServletException;
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.
Expand Down Expand Up @@ -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<String, Properties> propMap = new HashMap<>();

Map<String, String> descriptionMap = buildDescriptionMap(config);
Map<String, Map<String, OzoneConfiguration.Property>> propMap = new HashMap<>();

for (String tag : tags.split(",")) {
if (config.isPropertyTag(tag)) {
Properties properties = config.getAllPropertiesByTag(tag);
propMap.put(tag, properties);
Map<String, OzoneConfiguration.Property> 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));
Expand All @@ -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<String, String> buildDescriptionMap(OzoneConfiguration config) {
Map<String, String> 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<String, String> 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;
}
Expand Down
10 changes: 6 additions & 4 deletions hadoop-hdds/framework/src/main/resources/webapps/static/ozone.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -392,4 +394,4 @@
}
});

})();
})();
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@
<tbody>
<tr
ng-repeat="config in $ctrl.configs | filter:search | orderBy:$ctrl.propertyName:$ctrl.reverse">
<td style="word-wrap: break-word;">{{config.name}}</td>
<td style="word-wrap: break-word;">{{config.value}}</td>
<td style="word-wrap: break-word; font-family: monospace;">{{config.name}}</td>
<td style="word-wrap: break-word; font-family: monospace;">{{config.value}}</td>
<td style="word-wrap: break-word;">{{config.description}}</td>
</tr>
</tbody>
Expand Down