YARN-2414. RM web UI: app page will crash if app is failed before any attempt has been created. Contributed by Wangda Tan
This commit is contained in:
parent
bd8196e85e
commit
81c9d17af8
@ -99,6 +99,9 @@ Release 2.7.0 - UNRELEASED
|
|||||||
YARN-1703. Fixed ResourceManager web-proxy to close connections correctly.
|
YARN-1703. Fixed ResourceManager web-proxy to close connections correctly.
|
||||||
(Rohith Sharma via vinodkv)
|
(Rohith Sharma via vinodkv)
|
||||||
|
|
||||||
|
YARN-2414. RM web UI: app page will crash if app is failed before any
|
||||||
|
attempt has been created (Wangda Tan via jlowe)
|
||||||
|
|
||||||
Release 2.6.0 - 2014-11-18
|
Release 2.6.0 - 2014-11-18
|
||||||
|
|
||||||
INCOMPATIBLE CHANGES
|
INCOMPATIBLE CHANGES
|
||||||
|
@ -35,6 +35,8 @@
|
|||||||
import org.apache.hadoop.yarn.conf.YarnConfiguration;
|
import org.apache.hadoop.yarn.conf.YarnConfiguration;
|
||||||
import org.apache.hadoop.yarn.security.AdminACLsManager;
|
import org.apache.hadoop.yarn.security.AdminACLsManager;
|
||||||
|
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
|
||||||
@InterfaceAudience.Private
|
@InterfaceAudience.Private
|
||||||
public class ApplicationACLsManager {
|
public class ApplicationACLsManager {
|
||||||
|
|
||||||
@ -48,6 +50,11 @@ public class ApplicationACLsManager {
|
|||||||
private final ConcurrentMap<ApplicationId, Map<ApplicationAccessType, AccessControlList>> applicationACLS
|
private final ConcurrentMap<ApplicationId, Map<ApplicationAccessType, AccessControlList>> applicationACLS
|
||||||
= new ConcurrentHashMap<ApplicationId, Map<ApplicationAccessType, AccessControlList>>();
|
= new ConcurrentHashMap<ApplicationId, Map<ApplicationAccessType, AccessControlList>>();
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
public ApplicationACLsManager() {
|
||||||
|
this(new Configuration());
|
||||||
|
}
|
||||||
|
|
||||||
public ApplicationACLsManager(Configuration conf) {
|
public ApplicationACLsManager(Configuration conf) {
|
||||||
this.conf = conf;
|
this.conf = conf;
|
||||||
this.adminAclsManager = new AdminACLsManager(this.conf);
|
this.adminAclsManager = new AdminACLsManager(this.conf);
|
||||||
|
@ -24,9 +24,16 @@
|
|||||||
import org.apache.hadoop.yarn.conf.YarnConfiguration;
|
import org.apache.hadoop.yarn.conf.YarnConfiguration;
|
||||||
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.ResourceScheduler;
|
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.ResourceScheduler;
|
||||||
|
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
|
||||||
public class QueueACLsManager {
|
public class QueueACLsManager {
|
||||||
private ResourceScheduler scheduler;
|
private ResourceScheduler scheduler;
|
||||||
private boolean isACLsEnable;
|
private boolean isACLsEnable;
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
public QueueACLsManager() {
|
||||||
|
this(null, new Configuration());
|
||||||
|
}
|
||||||
|
|
||||||
public QueueACLsManager(ResourceScheduler scheduler, Configuration conf) {
|
public QueueACLsManager(ResourceScheduler scheduler, Configuration conf) {
|
||||||
this.scheduler = scheduler;
|
this.scheduler = scheduler;
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
import org.apache.hadoop.yarn.api.records.ApplicationAccessType;
|
import org.apache.hadoop.yarn.api.records.ApplicationAccessType;
|
||||||
import org.apache.hadoop.yarn.api.records.ApplicationId;
|
import org.apache.hadoop.yarn.api.records.ApplicationId;
|
||||||
import org.apache.hadoop.yarn.api.records.QueueACL;
|
import org.apache.hadoop.yarn.api.records.QueueACL;
|
||||||
|
import org.apache.hadoop.yarn.api.records.Resource;
|
||||||
import org.apache.hadoop.yarn.server.resourcemanager.RMContext;
|
import org.apache.hadoop.yarn.server.resourcemanager.RMContext;
|
||||||
import org.apache.hadoop.yarn.server.resourcemanager.ResourceManager;
|
import org.apache.hadoop.yarn.server.resourcemanager.ResourceManager;
|
||||||
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp;
|
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp;
|
||||||
@ -45,6 +46,7 @@
|
|||||||
import org.apache.hadoop.yarn.server.security.ApplicationACLsManager;
|
import org.apache.hadoop.yarn.server.security.ApplicationACLsManager;
|
||||||
import org.apache.hadoop.yarn.util.Apps;
|
import org.apache.hadoop.yarn.util.Apps;
|
||||||
import org.apache.hadoop.yarn.util.Times;
|
import org.apache.hadoop.yarn.util.Times;
|
||||||
|
import org.apache.hadoop.yarn.util.resource.Resources;
|
||||||
import org.apache.hadoop.yarn.webapp.hamlet.Hamlet;
|
import org.apache.hadoop.yarn.webapp.hamlet.Hamlet;
|
||||||
import org.apache.hadoop.yarn.webapp.hamlet.Hamlet.DIV;
|
import org.apache.hadoop.yarn.webapp.hamlet.Hamlet.DIV;
|
||||||
import org.apache.hadoop.yarn.webapp.hamlet.Hamlet.TABLE;
|
import org.apache.hadoop.yarn.webapp.hamlet.Hamlet.TABLE;
|
||||||
@ -113,8 +115,23 @@ protected void render(Block html) {
|
|||||||
setTitle(join("Application ", aid));
|
setTitle(join("Application ", aid));
|
||||||
|
|
||||||
RMAppMetrics appMerics = rmApp.getRMAppMetrics();
|
RMAppMetrics appMerics = rmApp.getRMAppMetrics();
|
||||||
RMAppAttemptMetrics attemptMetrics =
|
|
||||||
rmApp.getCurrentAppAttempt().getRMAppAttemptMetrics();
|
// Get attempt metrics and fields, it is possible currentAttempt of RMApp is
|
||||||
|
// null. In that case, we will assume resource preempted and number of Non
|
||||||
|
// AM container preempted on that attempt is 0
|
||||||
|
RMAppAttemptMetrics attemptMetrics;
|
||||||
|
if (null == rmApp.getCurrentAppAttempt()) {
|
||||||
|
attemptMetrics = null;
|
||||||
|
} else {
|
||||||
|
attemptMetrics = rmApp.getCurrentAppAttempt().getRMAppAttemptMetrics();
|
||||||
|
}
|
||||||
|
Resource attemptResourcePreempted =
|
||||||
|
attemptMetrics == null ? Resources.none() : attemptMetrics
|
||||||
|
.getResourcePreempted();
|
||||||
|
int attemptNumNonAMContainerPreempted =
|
||||||
|
attemptMetrics == null ? 0 : attemptMetrics
|
||||||
|
.getNumNonAMContainersPreempted();
|
||||||
|
|
||||||
info("Application Overview")
|
info("Application Overview")
|
||||||
._("User:", app.getUser())
|
._("User:", app.getUser())
|
||||||
._("Name:", app.getName())
|
._("Name:", app.getName())
|
||||||
@ -143,13 +160,12 @@ protected void render(Block html) {
|
|||||||
._("Total Number of AM Containers Preempted:",
|
._("Total Number of AM Containers Preempted:",
|
||||||
String.valueOf(appMerics.getNumAMContainersPreempted()))
|
String.valueOf(appMerics.getNumAMContainersPreempted()))
|
||||||
._("Resource Preempted from Current Attempt:",
|
._("Resource Preempted from Current Attempt:",
|
||||||
attemptMetrics.getResourcePreempted())
|
attemptResourcePreempted)
|
||||||
._("Number of Non-AM Containers Preempted from Current Attempt:",
|
._("Number of Non-AM Containers Preempted from Current Attempt:",
|
||||||
String.valueOf(attemptMetrics
|
attemptNumNonAMContainerPreempted)
|
||||||
.getNumNonAMContainersPreempted()))
|
|
||||||
._("Aggregate Resource Allocation:",
|
._("Aggregate Resource Allocation:",
|
||||||
String.format("%d MB-seconds, %d vcore-seconds",
|
String.format("%d MB-seconds, %d vcore-seconds",
|
||||||
appMerics.getMemorySeconds(), appMerics.getVcoreSeconds()));
|
appMerics.getMemorySeconds(), appMerics.getVcoreSeconds()));
|
||||||
pdiv._();
|
pdiv._();
|
||||||
|
|
||||||
Collection<RMAppAttempt> attempts = rmApp.getAppAttempts().values();
|
Collection<RMAppAttempt> attempts = rmApp.getAppAttempts().values();
|
||||||
|
@ -0,0 +1,90 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.hadoop.yarn.server.resourcemanager.webapp;
|
||||||
|
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.apache.hadoop.yarn.api.records.ApplicationId;
|
||||||
|
import org.apache.hadoop.yarn.api.records.FinalApplicationStatus;
|
||||||
|
import org.apache.hadoop.yarn.api.records.Resource;
|
||||||
|
import org.apache.hadoop.yarn.api.records.YarnApplicationState;
|
||||||
|
import org.apache.hadoop.yarn.server.resourcemanager.RMContext;
|
||||||
|
import org.apache.hadoop.yarn.server.resourcemanager.ResourceManager;
|
||||||
|
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp;
|
||||||
|
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMAppMetrics;
|
||||||
|
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMAppState;
|
||||||
|
import org.apache.hadoop.yarn.webapp.YarnWebParams;
|
||||||
|
import org.apache.hadoop.yarn.webapp.test.WebAppTests;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.google.inject.Binder;
|
||||||
|
import com.google.inject.Injector;
|
||||||
|
import com.google.inject.Module;
|
||||||
|
|
||||||
|
public class TestAppPage {
|
||||||
|
@Test
|
||||||
|
public void testAppBlockRenderWithNullCurrentAppAttempt() throws Exception {
|
||||||
|
final ApplicationId APP_ID = ApplicationId.newInstance(1234L, 0);
|
||||||
|
Injector injector;
|
||||||
|
|
||||||
|
// init app
|
||||||
|
RMApp app = mock(RMApp.class);
|
||||||
|
when(app.getTrackingUrl()).thenReturn("http://host:123");
|
||||||
|
when(app.getState()).thenReturn(RMAppState.FAILED);
|
||||||
|
when(app.getApplicationId()).thenReturn(APP_ID);
|
||||||
|
when(app.getApplicationType()).thenReturn("Type");
|
||||||
|
when(app.getUser()).thenReturn("user");
|
||||||
|
when(app.getName()).thenReturn("Name");
|
||||||
|
when(app.getQueue()).thenReturn("queue");
|
||||||
|
when(app.getDiagnostics()).thenReturn(new StringBuilder());
|
||||||
|
when(app.getFinalApplicationStatus()).thenReturn(FinalApplicationStatus.FAILED);
|
||||||
|
when(app.getFinalApplicationStatus()).thenReturn(FinalApplicationStatus.FAILED);
|
||||||
|
when(app.getStartTime()).thenReturn(0L);
|
||||||
|
when(app.getFinishTime()).thenReturn(0L);
|
||||||
|
when(app.createApplicationState()).thenReturn(YarnApplicationState.FAILED);
|
||||||
|
|
||||||
|
RMAppMetrics appMetrics = new RMAppMetrics(Resource.newInstance(0, 0), 0, 0, 0, 0);
|
||||||
|
when(app.getRMAppMetrics()).thenReturn(appMetrics);
|
||||||
|
|
||||||
|
// initialize RM Context, and create RMApp, without creating RMAppAttempt
|
||||||
|
final RMContext rmContext = TestRMWebApp.mockRMContext(15, 1, 2, 8);
|
||||||
|
rmContext.getRMApps().put(APP_ID, app);
|
||||||
|
|
||||||
|
injector =
|
||||||
|
WebAppTests.createMockInjector(RMContext.class, rmContext,
|
||||||
|
new Module() {
|
||||||
|
@Override
|
||||||
|
public void configure(Binder binder) {
|
||||||
|
try {
|
||||||
|
binder.bind(ResourceManager.class).toInstance(
|
||||||
|
TestRMWebApp.mockRm(rmContext));
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new IllegalStateException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
AppBlock instance = injector.getInstance(AppBlock.class);
|
||||||
|
instance.set(YarnWebParams.APPLICATION_ID, APP_ID.toString());
|
||||||
|
instance.render();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user