YARN-10723. Change CS nodes page in UI to support custom resource. Contributed by Qi Zhu

This commit is contained in:
Eric Badger 2021-04-20 17:34:49 +00:00
parent 2dd1e04010
commit 6cb90005a7
2 changed files with 69 additions and 22 deletions

View File

@ -39,6 +39,7 @@
import org.apache.hadoop.yarn.webapp.view.HtmlBlock; import org.apache.hadoop.yarn.webapp.view.HtmlBlock;
import java.util.Collection; import java.util.Collection;
import java.util.Map;
import static org.apache.hadoop.yarn.webapp.YarnWebParams.NODE_LABEL; import static org.apache.hadoop.yarn.webapp.YarnWebParams.NODE_LABEL;
import static org.apache.hadoop.yarn.webapp.YarnWebParams.NODE_STATE; import static org.apache.hadoop.yarn.webapp.YarnWebParams.NODE_STATE;
@ -90,9 +91,7 @@ protected void render(Block html) {
.th(".mem", "Phys Mem Used %") .th(".mem", "Phys Mem Used %")
.th(".vcores", "VCores Used") .th(".vcores", "VCores Used")
.th(".vcores", "VCores Avail") .th(".vcores", "VCores Avail")
.th(".vcores", "Phys VCores Used %") .th(".vcores", "Phys VCores Used %");
.th(".gpus", "GPUs Used")
.th(".gpus", "GPUs Avail");
} else { } else {
trbody.th(".containers", "Running Containers (G)") trbody.th(".containers", "Running Containers (G)")
.th(".allocationTags", "Allocation Tags") .th(".allocationTags", "Allocation Tags")
@ -102,14 +101,26 @@ protected void render(Block html) {
.th(".vcores", "VCores Used (G)") .th(".vcores", "VCores Used (G)")
.th(".vcores", "VCores Avail (G)") .th(".vcores", "VCores Avail (G)")
.th(".vcores", "Phys VCores Used %") .th(".vcores", "Phys VCores Used %")
.th(".gpus", "GPUs Used (G)")
.th(".gpus", "GPUs Avail (G)")
.th(".containers", "Running Containers (O)") .th(".containers", "Running Containers (O)")
.th(".mem", "Mem Used (O)") .th(".mem", "Mem Used (O)")
.th(".vcores", "VCores Used (O)") .th(".vcores", "VCores Used (O)")
.th(".containers", "Queued Containers"); .th(".containers", "Queued Containers");
} }
for (Map.Entry<String, Integer> integerEntry :
ResourceUtils.getResourceTypeIndex().entrySet()) {
if (integerEntry.getKey().equals(ResourceInformation.MEMORY_URI)
|| integerEntry.getKey().equals(ResourceInformation.VCORES_URI)) {
continue;
}
trbody.th("." + integerEntry.getKey(),
integerEntry.getKey() + " " + "Used");
trbody.th("." + integerEntry.getKey(),
integerEntry.getKey() + " " + "Avail");
}
TBODY<TABLE<Hamlet>> tbody = TBODY<TABLE<Hamlet>> tbody =
trbody.th(".nodeManagerVersion", "Version").__().__().tbody(); trbody.th(".nodeManagerVersion", "Version").__().__().tbody();
@ -175,17 +186,7 @@ protected void render(Block html) {
nodeTableData.append("\",\"<a ").append("href='" + "//" + httpAddress) nodeTableData.append("\",\"<a ").append("href='" + "//" + httpAddress)
.append("'>").append(httpAddress).append("</a>\",").append("\""); .append("'>").append(httpAddress).append("</a>\",").append("\"");
} }
Integer gpuIndex = ResourceUtils.getResourceTypeIndex()
.get(ResourceInformation.GPU_URI);
long usedGPUs = 0;
long availableGPUs = 0;
if (gpuIndex != null && info.getUsedResource() != null
&& info.getAvailableResource() != null) {
usedGPUs = info.getUsedResource().getResource()
.getResourceValue(ResourceInformation.GPU_URI);
availableGPUs = info.getAvailableResource().getResource()
.getResourceValue(ResourceInformation.GPU_URI);
}
nodeTableData.append("<br title='") nodeTableData.append("<br title='")
.append(String.valueOf(info.getLastHealthUpdate())).append("'>") .append(String.valueOf(info.getLastHealthUpdate())).append("'>")
.append(Times.format(info.getLastHealthUpdate())).append("\",\"") .append(Times.format(info.getLastHealthUpdate())).append("\",\"")
@ -205,10 +206,6 @@ protected void render(Block html) {
.append(String.valueOf(info.getAvailableVirtualCores())) .append(String.valueOf(info.getAvailableVirtualCores()))
.append("\",\"") .append("\",\"")
.append(String.valueOf((int) info.getVcoreUtilization())) .append(String.valueOf((int) info.getVcoreUtilization()))
.append("\",\"")
.append(String.valueOf(usedGPUs))
.append("\",\"")
.append(String.valueOf(availableGPUs))
.append("\",\""); .append("\",\"");
// If opportunistic containers are enabled, add extra fields. // If opportunistic containers are enabled, add extra fields.
@ -226,6 +223,34 @@ protected void render(Block html) {
.append("\",\""); .append("\",\"");
} }
for (Map.Entry<String, Integer> integerEntry :
ResourceUtils.getResourceTypeIndex().entrySet()) {
if (integerEntry.getKey().equals(ResourceInformation.MEMORY_URI)
|| integerEntry.getKey().equals(ResourceInformation.VCORES_URI)) {
continue;
}
long usedCustomResource = 0;
long availableCustomResource = 0;
String resourceName = integerEntry.getKey();
Integer index = integerEntry.getValue();
if (index != null && info.getUsedResource() != null
&& info.getAvailableResource() != null) {
usedCustomResource = info.getUsedResource().getResource()
.getResourceValue(resourceName);
availableCustomResource = info.getAvailableResource().getResource()
.getResourceValue(resourceName);
nodeTableData
.append(usedCustomResource)
.append("\",\"")
.append(availableCustomResource)
.append("\",\"");
}
}
nodeTableData.append(ni.getNodeManagerVersion()) nodeTableData.append(ni.getNodeManagerVersion())
.append("\"],\n"); .append("\"],\n");
} }

View File

@ -53,7 +53,7 @@ public class TestNodesPage {
// Number of Actual Table Headers for NodesPage.NodesBlock might change in // Number of Actual Table Headers for NodesPage.NodesBlock might change in
// future. In that case this value should be adjusted to the new value. // future. In that case this value should be adjusted to the new value.
private final int numberOfThInMetricsTable = 23; private final int numberOfThInMetricsTable = 23;
private final int numberOfActualTableHeaders = 18; private final int numberOfActualTableHeaders = 16;
private final int numberOfThForOpportunisticContainers = 4; private final int numberOfThForOpportunisticContainers = 4;
private Injector injector; private Injector injector;
@ -119,12 +119,34 @@ public void testNodesBlockRenderForLostNodesWithGPUResources()
initResourceTypes(ResourceInformation.GPU_URI); initResourceTypes(ResourceInformation.GPU_URI);
this.setUpInternal(true); this.setUpInternal(true);
try { try {
this.testNodesBlockRenderForLostNodes(); // Test gpu as a custom resource.
//<th class="yarn io/gpu">
// yarn.io/gpu Used
//</th>
//<th class="yarn io/gpu">
// yarn.io/gpu Avail
//</th>
this.testNodesBlockRenderForLostNodesWithGPU();
} finally { } finally {
ResourceUtils.initializeResourcesFromResourceInformationMap(oldRtMap); ResourceUtils.initializeResourcesFromResourceInformationMap(oldRtMap);
} }
} }
public void testNodesBlockRenderForLostNodesWithGPU() {
NodesBlock nodesBlock = injector.getInstance(NodesBlock.class);
nodesBlock.set("node.state", "lost");
nodesBlock.render();
PrintWriter writer = injector.getInstance(PrintWriter.class);
WebAppTests.flushOutput(injector);
Mockito.verify(writer,
Mockito.times(numberOfActualTableHeaders
+ numberOfThInMetricsTable + 2))
.print("<th");
Mockito.verify(writer, Mockito.times(numberOfThInMetricsTable))
.print("<td");
}
@Test @Test
public void testNodesBlockRenderForNodeLabelFilterWithNonEmptyLabel() { public void testNodesBlockRenderForNodeLabelFilterWithNonEmptyLabel() {
NodesBlock nodesBlock = injector.getInstance(NodesBlock.class); NodesBlock nodesBlock = injector.getInstance(NodesBlock.class);