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

(cherry picked from commit 6cb90005a7)
This commit is contained in:
Eric Badger 2021-04-20 17:54:20 +00:00
parent 3991139b0f
commit b36810ee3f
2 changed files with 69 additions and 22 deletions

View File

@ -39,6 +39,7 @@ import org.apache.hadoop.yarn.webapp.hamlet2.Hamlet.TBODY;
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 @@ class NodesPage extends RmView {
.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 @@ class NodesPage extends RmView {
.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 @@ class NodesPage extends RmView {
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 @@ class NodesPage extends RmView {
.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 @@ class NodesPage extends RmView {
.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;
@ -118,12 +118,34 @@ public class TestNodesPage {
TestResourceUtils.addNewTypesToResources(ResourceInformation.GPU_URI); TestResourceUtils.addNewTypesToResources(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);