Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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 @@ -19,7 +19,9 @@

import com.google.common.annotations.VisibleForTesting;
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;
Expand All @@ -28,10 +30,20 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.core.HttpHeaders;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.apache.commons.lang3.StringUtils;
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.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 All @@ -41,13 +53,53 @@
public class HddsConfServlet extends HttpServlet {

private static final long serialVersionUID = 1L;
private static final Logger LOG = LoggerFactory.getLogger(HddsConfServlet.class);

protected static final String FORMAT_JSON = "json";
protected static final String FORMAT_XML = "xml";
private static final String COMMAND = "cmd";
private static final OzoneConfiguration OZONE_CONFIG =
new OzoneConfiguration();

/**
* Represents metadata for a configuration property, including its name, value and description.
*/
public static class PropertyMetadata {
Comment thread
ptlrs marked this conversation as resolved.
Outdated
private String name;
private String value;
private String description;

public PropertyMetadata(String name, String value, String description) {
this.name = name;
this.value = value;
this.description = description;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getValue() {
return value;
}

public void setValue(String value) {
this.value = value;
}

public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}
}

/**
* Return the Configuration of the daemon hosting this servlet.
* This is populated when the HttpServer starts.
Expand Down Expand Up @@ -149,12 +201,21 @@ private void processConfigTagRequest(HttpServletRequest request, String cmd,
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, PropertyMetadata>> propMap = new HashMap<>();

for (String tag : tags.split(",")) {
if (config.isPropertyTag(tag)) {
Properties properties = config.getAllPropertiesByTag(tag);
propMap.put(tag, properties);
Map<String, PropertyMetadata> metadataMap = new HashMap<>();

for (String propName : properties.stringPropertyNames()) {
String value = properties.getProperty(propName);
String description = descriptionMap.getOrDefault(propName, "");
metadataMap.put(propName, new PropertyMetadata(propName, value, description));
}
propMap.put(tag, metadataMap);
}
}
out.write(JsonUtils.toJsonString(propMap));
Expand All @@ -165,6 +226,92 @@ private void processConfigTagRequest(HttpServletRequest request, String cmd,

}

/**
* 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<>();

// List of configuration resource names to check
String[] configResources = new String[] {
"core-default.xml",
"core-site.xml",
"hdfs-default.xml",
"hdfs-site.xml",
"hdds-common-default.xml",
"hdds-client-default.xml",
"hdds-container-service-default.xml",
"hdds-server-framework-default.xml",
"hdds-server-scm-default.xml",
"ozone-common-default.xml",
"ozone-csi-default.xml",
"ozone-manager-default.xml",
"ozone-recon-default.xml",
"ozone-default.xml",
"ozone-site.xml"
};
Comment thread
ptlrs marked this conversation as resolved.
Outdated

for (String resourceName : configResources) {
try {
URL resourceUrl = config.getResource(resourceName);
if (resourceUrl != null) {
parseXmlDescriptions(resourceUrl, descriptionMap);
}
} catch (Exception e) {
LOG.error("Could not read descriptions from resource: {}", resourceName, e);
}
}

return descriptionMap;
}

/**
* Parse XML configuration file and extract property descriptions using DOM parser.
* @param resourceUrl URL of the XML resource to parse
* @param descriptionMap map to populate with property name -> description mappings
*/
private void parseXmlDescriptions(URL resourceUrl, Map<String, String> descriptionMap) {
try (InputStream inputStream = resourceUrl.openStream()) {
DocumentBuilderFactory factory = XMLUtils.newSecureDocumentBuilderFactory();
DocumentBuilder builder = factory.newDocumentBuilder();
Comment thread
ptlrs marked this conversation as resolved.
Outdated
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