1 /** 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 package org.apache.hadoop.yarn.server.resourcemanager.webapp; 20 21 import static org.apache.hadoop.yarn.webapp.view.JQueryUI._EVEN; 22 import static org.apache.hadoop.yarn.webapp.view.JQueryUI._INFO_WRAP; 23 import static org.apache.hadoop.yarn.webapp.view.JQueryUI._ODD; 24 import static org.apache.hadoop.yarn.webapp.view.JQueryUI._TH; 25 26 import org.apache.commons.lang.StringUtils; 27 import org.apache.hadoop.conf.Configuration; 28 import org.apache.hadoop.yarn.api.records.ApplicationAttemptId; 29 import org.apache.hadoop.yarn.api.records.ApplicationAttemptReport; 30 import org.apache.hadoop.yarn.api.records.ApplicationId; 31 import org.apache.hadoop.yarn.api.records.ContainerReport; 32 import org.apache.hadoop.yarn.api.records.Resource; 33 import org.apache.hadoop.yarn.api.records.ResourceRequest; 34 import org.apache.hadoop.yarn.api.records.YarnApplicationAttemptState; 35 import org.apache.hadoop.yarn.server.resourcemanager.ResourceManager; 36 import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp; 37 import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.RMAppAttempt; 38 import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.RMAppAttemptMetrics; 39 import org.apache.hadoop.yarn.server.resourcemanager.scheduler.AbstractYarnScheduler; 40 import org.apache.hadoop.yarn.server.resourcemanager.scheduler.SchedulerApplicationAttempt; 41 import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.AppInfo; 42 import org.apache.hadoop.yarn.server.webapp.AppAttemptBlock; 43 import org.apache.hadoop.yarn.server.webapp.dao.AppAttemptInfo; 44 import org.apache.hadoop.yarn.util.resource.Resources; 45 import org.apache.hadoop.yarn.webapp.hamlet.Hamlet; 46 import org.apache.hadoop.yarn.webapp.hamlet.Hamlet.DIV; 47 import org.apache.hadoop.yarn.webapp.hamlet.Hamlet.TABLE; 48 import org.apache.hadoop.yarn.webapp.util.WebAppUtils; 49 import org.apache.hadoop.yarn.webapp.view.InfoBlock; 50 import com.google.inject.Inject; 51 import java.util.List; 52 53 import java.util.Collection; 54 import java.util.Set; 55 56 public class RMAppAttemptBlock extends AppAttemptBlock{ 57 58 private final ResourceManager rm; 59 protected Configuration conf; 60 61 @Inject RMAppAttemptBlock(ViewContext ctx, ResourceManager rm, Configuration conf)62 RMAppAttemptBlock(ViewContext ctx, ResourceManager rm, Configuration conf) { 63 super(rm.getClientRMService(), ctx); 64 this.rm = rm; 65 this.conf = conf; 66 } 67 createResourceRequestsTable(Block html)68 private void createResourceRequestsTable(Block html) { 69 AppInfo app = 70 new AppInfo(rm, rm.getRMContext().getRMApps() 71 .get(this.appAttemptId.getApplicationId()), true, 72 WebAppUtils.getHttpSchemePrefix(conf)); 73 74 List<ResourceRequest> resourceRequests = app.getResourceRequests(); 75 if (resourceRequests == null || resourceRequests.isEmpty()) { 76 return; 77 } 78 79 DIV<Hamlet> div = html.div(_INFO_WRAP); 80 TABLE<DIV<Hamlet>> table = 81 div.h3("Total Outstanding Resource Requests: " 82 + getTotalResource(resourceRequests)).table( 83 "#ResourceRequests"); 84 85 table.tr(). 86 th(_TH, "Priority"). 87 th(_TH, "ResourceName"). 88 th(_TH, "Capability"). 89 th(_TH, "NumContainers"). 90 th(_TH, "RelaxLocality"). 91 th(_TH, "NodeLabelExpression"). 92 _(); 93 94 boolean odd = false; 95 for (ResourceRequest request : resourceRequests) { 96 if (request.getNumContainers() == 0) { 97 continue; 98 } 99 table.tr((odd = !odd) ? _ODD : _EVEN) 100 .td(String.valueOf(request.getPriority())) 101 .td(request.getResourceName()) 102 .td(String.valueOf(request.getCapability())) 103 .td(String.valueOf(request.getNumContainers())) 104 .td(String.valueOf(request.getRelaxLocality())) 105 .td(request.getNodeLabelExpression() == null ? "N/A" : request 106 .getNodeLabelExpression())._(); 107 } 108 table._(); 109 div._(); 110 } 111 getTotalResource(List<ResourceRequest> requests)112 private Resource getTotalResource(List<ResourceRequest> requests) { 113 Resource totalResource = Resource.newInstance(0, 0); 114 if (requests == null) { 115 return totalResource; 116 } 117 for (ResourceRequest request : requests) { 118 if (request.getNumContainers() == 0) { 119 continue; 120 } 121 if (request.getResourceName().equals(ResourceRequest.ANY)) { 122 Resources.addTo( 123 totalResource, 124 Resources.multiply(request.getCapability(), 125 request.getNumContainers())); 126 } 127 } 128 return totalResource; 129 } 130 createContainerLocalityTable(Block html)131 private void createContainerLocalityTable(Block html) { 132 RMAppAttemptMetrics attemptMetrics = null; 133 RMAppAttempt attempt = getRMAppAttempt(); 134 if (attempt != null) { 135 attemptMetrics = attempt.getRMAppAttemptMetrics(); 136 } 137 138 if (attemptMetrics == null) { 139 return; 140 } 141 142 DIV<Hamlet> div = html.div(_INFO_WRAP); 143 TABLE<DIV<Hamlet>> table = 144 div.h3( 145 "Total Allocated Containers: " 146 + attemptMetrics.getTotalAllocatedContainers()).h3("Each table cell" 147 + " represents the number of NodeLocal/RackLocal/OffSwitch containers" 148 + " satisfied by NodeLocal/RackLocal/OffSwitch resource requests.").table( 149 "#containerLocality"); 150 table. 151 tr(). 152 th(_TH, ""). 153 th(_TH, "Node Local Request"). 154 th(_TH, "Rack Local Request"). 155 th(_TH, "Off Switch Request"). 156 _(); 157 158 String[] containersType = 159 { "Num Node Local Containers (satisfied by)", "Num Rack Local Containers (satisfied by)", 160 "Num Off Switch Containers (satisfied by)" }; 161 boolean odd = false; 162 for (int i = 0; i < attemptMetrics.getLocalityStatistics().length; i++) { 163 table.tr((odd = !odd) ? _ODD : _EVEN).td(containersType[i]) 164 .td(String.valueOf(attemptMetrics.getLocalityStatistics()[i][0])) 165 .td(i == 0 ? "" : String.valueOf(attemptMetrics.getLocalityStatistics()[i][1])) 166 .td(i <= 1 ? "" : String.valueOf(attemptMetrics.getLocalityStatistics()[i][2]))._(); 167 } 168 table._(); 169 div._(); 170 } 171 isApplicationInFinalState(YarnApplicationAttemptState state)172 private boolean isApplicationInFinalState(YarnApplicationAttemptState state) { 173 return state == YarnApplicationAttemptState.FINISHED 174 || state == YarnApplicationAttemptState.FAILED 175 || state == YarnApplicationAttemptState.KILLED; 176 } 177 178 @Override createAttemptHeadRoomTable(Block html)179 protected void createAttemptHeadRoomTable(Block html) { 180 RMAppAttempt attempt = getRMAppAttempt(); 181 if (attempt != null) { 182 if (!isApplicationInFinalState(YarnApplicationAttemptState 183 .valueOf(attempt.getAppAttemptState().toString()))) { 184 RMAppAttemptMetrics metrics = attempt.getRMAppAttemptMetrics(); 185 DIV<Hamlet> pdiv = html._(InfoBlock.class).div(_INFO_WRAP); 186 info("Application Attempt Overview").clear(); 187 info("Application Attempt Metrics")._( 188 "Application Attempt Headroom : ", metrics == null ? "N/A" : 189 metrics.getApplicationAttemptHeadroom()); 190 pdiv._(); 191 } 192 } 193 } 194 getRMAppAttempt()195 private RMAppAttempt getRMAppAttempt() { 196 ApplicationId appId = this.appAttemptId.getApplicationId(); 197 RMAppAttempt attempt = null; 198 RMApp rmApp = rm.getRMContext().getRMApps().get(appId); 199 if (rmApp != null) { 200 attempt = rmApp.getAppAttempts().get(appAttemptId); 201 } 202 return attempt; 203 } 204 205 @Override createTablesForAttemptMetrics(Block html)206 protected void createTablesForAttemptMetrics(Block html) { 207 createContainerLocalityTable(html); 208 createResourceRequestsTable(html); 209 } 210 generateOverview(ApplicationAttemptReport appAttemptReport, Collection<ContainerReport> containers, AppAttemptInfo appAttempt, String node)211 protected void generateOverview(ApplicationAttemptReport appAttemptReport, 212 Collection<ContainerReport> containers, AppAttemptInfo appAttempt, 213 String node) { 214 215 String blacklistedNodes = "-"; 216 Set<String> nodes = 217 getBlacklistedNodes(rm, getRMAppAttempt().getAppAttemptId()); 218 if (nodes != null) { 219 if (!nodes.isEmpty()) { 220 blacklistedNodes = StringUtils.join(nodes, ", "); 221 } 222 } 223 224 info("Application Attempt Overview") 225 ._( 226 "Application Attempt State:", 227 appAttempt.getAppAttemptState() == null ? UNAVAILABLE : appAttempt 228 .getAppAttemptState()) 229 ._( 230 "AM Container:", 231 appAttempt.getAmContainerId() == null || containers == null 232 || !hasAMContainer(appAttemptReport.getAMContainerId(), containers) 233 ? null : root_url("container", appAttempt.getAmContainerId()), 234 String.valueOf(appAttempt.getAmContainerId())) 235 ._("Node:", node) 236 ._( 237 "Tracking URL:", 238 appAttempt.getTrackingUrl() == null 239 || appAttempt.getTrackingUrl().equals(UNAVAILABLE) ? null 240 : root_url(appAttempt.getTrackingUrl()), 241 appAttempt.getTrackingUrl() == null 242 || appAttempt.getTrackingUrl().equals(UNAVAILABLE) 243 ? "Unassigned" 244 : appAttempt.getAppAttemptState() == YarnApplicationAttemptState.FINISHED 245 || appAttempt.getAppAttemptState() == YarnApplicationAttemptState.FAILED 246 || appAttempt.getAppAttemptState() == YarnApplicationAttemptState.KILLED 247 ? "History" : "ApplicationMaster") 248 ._( 249 "Diagnostics Info:", 250 appAttempt.getDiagnosticsInfo() == null ? "" : appAttempt 251 .getDiagnosticsInfo())._("Blacklisted Nodes:", blacklistedNodes); 252 } 253 getBlacklistedNodes(ResourceManager rm, ApplicationAttemptId appid)254 public static Set<String> getBlacklistedNodes(ResourceManager rm, 255 ApplicationAttemptId appid) { 256 if (rm.getResourceScheduler() instanceof AbstractYarnScheduler) { 257 AbstractYarnScheduler ayScheduler = 258 (AbstractYarnScheduler) rm.getResourceScheduler(); 259 SchedulerApplicationAttempt attempt = 260 ayScheduler.getApplicationAttempt(appid); 261 if (attempt != null) { 262 return attempt.getBlacklistedNodes(); 263 } 264 } 265 return null; 266 } 267 } 268