YARN-1145. Fixed a potential file-handle leak in the web interface for displaying aggregated logs. Contributed by Rohith Sharma.

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1551326 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Vinod Kumar Vavilapalli 2013-12-16 19:27:48 +00:00
parent d38fb71d00
commit 5a1b33507b
6 changed files with 109 additions and 102 deletions

View File

@ -249,6 +249,9 @@ Release 2.4.0 - UNRELEASED
YARN-1505. Fixed Webapplication proxy server to not hardcode its bind YARN-1505. Fixed Webapplication proxy server to not hardcode its bind
address. (Xuan Gong via vinodkv) address. (Xuan Gong via vinodkv)
YARN-1145. Fixed a potential file-handle leak in the web interface for
displaying aggregated logs. (Rohith Sharma via vinodkv)
Release 2.3.0 - UNRELEASED Release 2.3.0 - UNRELEASED
INCOMPATIBLE CHANGES INCOMPATIBLE CHANGES

View File

@ -53,6 +53,7 @@
import org.apache.hadoop.fs.Options; import org.apache.hadoop.fs.Options;
import org.apache.hadoop.fs.Path; import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.permission.FsPermission; import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.io.SecureIOUtils; import org.apache.hadoop.io.SecureIOUtils;
import org.apache.hadoop.io.Writable; import org.apache.hadoop.io.Writable;
import org.apache.hadoop.io.file.tfile.TFile; import org.apache.hadoop.io.file.tfile.TFile;
@ -294,7 +295,7 @@ public void append(LogKey logKey, LogValue logValue) throws IOException {
out.close(); out.close();
} }
public void closeWriter() { public void close() {
try { try {
this.writer.close(); this.writer.close();
} catch (IOException e) { } catch (IOException e) {
@ -569,9 +570,8 @@ public static void readAContainerLogsForALogType(
out.println(""); out.println("");
} }
public void close() throws IOException { public void close() {
this.scanner.close(); IOUtils.cleanup(LOG, scanner, reader, fsDataIStream);
this.fsDataIStream.close();
} }
} }

View File

@ -59,109 +59,113 @@ public class AggregatedLogsBlock extends HtmlBlock {
@Override @Override
protected void render(Block html) { protected void render(Block html) {
ContainerId containerId = verifyAndGetContainerId(html);
NodeId nodeId = verifyAndGetNodeId(html);
String appOwner = verifyAndGetAppOwner(html);
LogLimits logLimits = verifyAndGetLogLimits(html);
if (containerId == null || nodeId == null || appOwner == null
|| appOwner.isEmpty() || logLimits == null) {
return;
}
ApplicationId applicationId =
containerId.getApplicationAttemptId().getApplicationId();
String logEntity = $(ENTITY_STRING);
if (logEntity == null || logEntity.isEmpty()) {
logEntity = containerId.toString();
}
if (!conf.getBoolean(YarnConfiguration.LOG_AGGREGATION_ENABLED,
YarnConfiguration.DEFAULT_LOG_AGGREGATION_ENABLED)) {
html.h1()
._("Aggregation is not enabled. Try the nodemanager at " + nodeId)
._();
return;
}
Path remoteRootLogDir =
new Path(conf.get(YarnConfiguration.NM_REMOTE_APP_LOG_DIR,
YarnConfiguration.DEFAULT_NM_REMOTE_APP_LOG_DIR));
AggregatedLogFormat.LogReader reader = null; AggregatedLogFormat.LogReader reader = null;
try { try {
reader = ContainerId containerId = verifyAndGetContainerId(html);
new AggregatedLogFormat.LogReader(conf, NodeId nodeId = verifyAndGetNodeId(html);
LogAggregationUtils.getRemoteNodeLogFileForApp( String appOwner = verifyAndGetAppOwner(html);
remoteRootLogDir, applicationId, appOwner, nodeId, LogLimits logLimits = verifyAndGetLogLimits(html);
LogAggregationUtils.getRemoteNodeLogDirSuffix(conf))); if (containerId == null || nodeId == null || appOwner == null
} catch (FileNotFoundException e) { || appOwner.isEmpty() || logLimits == null) {
// ACLs not available till the log file is opened.
html.h1()
._("Logs not available for "
+ logEntity
+ ". Aggregation may not be complete, "
+ "Check back later or try the nodemanager at "
+ nodeId)._();
return;
} catch (IOException e) {
html.h1()._("Error getting logs for " + logEntity)._();
LOG.error("Error getting logs for " + logEntity, e);
return;
}
String owner = null;
Map<ApplicationAccessType, String> appAcls = null;
try {
owner = reader.getApplicationOwner();
appAcls = reader.getApplicationAcls();
} catch (IOException e) {
html.h1()._("Error getting logs for " + logEntity)._();
LOG.error("Error getting logs for " + logEntity, e);
return;
}
ApplicationACLsManager aclsManager = new ApplicationACLsManager(conf);
aclsManager.addApplication(applicationId, appAcls);
String remoteUser = request().getRemoteUser();
UserGroupInformation callerUGI = null;
if (remoteUser != null) {
callerUGI = UserGroupInformation.createRemoteUser(remoteUser);
}
if (callerUGI != null
&& !aclsManager.checkAccess(callerUGI, ApplicationAccessType.VIEW_APP,
owner, applicationId)) {
html.h1()
._("User [" + remoteUser
+ "] is not authorized to view the logs for " + logEntity)._();
return;
}
String desiredLogType = $(CONTAINER_LOG_TYPE);
try {
AggregatedLogFormat.ContainerLogsReader logReader =
reader.getContainerLogsReader(containerId);
if (logReader == null) {
html.h1()._(
"Logs not available for " + logEntity
+ ". Could be caused by the rentention policy")._();
return; return;
} }
boolean foundLog = readContainerLogs(html, logReader, logLimits, ApplicationId applicationId = containerId.getApplicationAttemptId()
desiredLogType); .getApplicationId();
String logEntity = $(ENTITY_STRING);
if (logEntity == null || logEntity.isEmpty()) {
logEntity = containerId.toString();
}
if (!foundLog) { if (!conf.getBoolean(YarnConfiguration.LOG_AGGREGATION_ENABLED,
if (desiredLogType.isEmpty()) { YarnConfiguration.DEFAULT_LOG_AGGREGATION_ENABLED)) {
html.h1("No logs available for container " + containerId.toString()); html.h1()
} else { ._("Aggregation is not enabled. Try the nodemanager at " + nodeId)
html.h1("Unable to locate '" + desiredLogType ._();
+ "' log for container " + containerId.toString()); return;
}
Path remoteRootLogDir = new Path(conf.get(
YarnConfiguration.NM_REMOTE_APP_LOG_DIR,
YarnConfiguration.DEFAULT_NM_REMOTE_APP_LOG_DIR));
try {
reader = new AggregatedLogFormat.LogReader(conf,
LogAggregationUtils.getRemoteNodeLogFileForApp(remoteRootLogDir,
applicationId, appOwner, nodeId,
LogAggregationUtils.getRemoteNodeLogDirSuffix(conf)));
} catch (FileNotFoundException e) {
// ACLs not available till the log file is opened.
html.h1()
._("Logs not available for " + logEntity
+ ". Aggregation may not be complete, "
+ "Check back later or try the nodemanager at " + nodeId)._();
return;
} catch (IOException e) {
html.h1()._("Error getting logs for " + logEntity)._();
LOG.error("Error getting logs for " + logEntity, e);
return;
}
String owner = null;
Map<ApplicationAccessType, String> appAcls = null;
try {
owner = reader.getApplicationOwner();
appAcls = reader.getApplicationAcls();
} catch (IOException e) {
html.h1()._("Error getting logs for " + logEntity)._();
LOG.error("Error getting logs for " + logEntity, e);
return;
}
ApplicationACLsManager aclsManager = new ApplicationACLsManager(conf);
aclsManager.addApplication(applicationId, appAcls);
String remoteUser = request().getRemoteUser();
UserGroupInformation callerUGI = null;
if (remoteUser != null) {
callerUGI = UserGroupInformation.createRemoteUser(remoteUser);
}
if (callerUGI != null
&& !aclsManager.checkAccess(callerUGI,
ApplicationAccessType.VIEW_APP, owner, applicationId)) {
html.h1()
._("User [" + remoteUser
+ "] is not authorized to view the logs for " + logEntity)._();
return;
}
String desiredLogType = $(CONTAINER_LOG_TYPE);
try {
AggregatedLogFormat.ContainerLogsReader logReader = reader
.getContainerLogsReader(containerId);
if (logReader == null) {
html.h1()
._("Logs not available for " + logEntity
+ ". Could be caused by the rentention policy")._();
return;
} }
boolean foundLog = readContainerLogs(html, logReader, logLimits,
desiredLogType);
if (!foundLog) {
if (desiredLogType.isEmpty()) {
html.h1("No logs available for container " + containerId.toString());
} else {
html.h1("Unable to locate '" + desiredLogType
+ "' log for container " + containerId.toString());
}
return;
}
} catch (IOException e) {
html.h1()._("Error getting logs for " + logEntity)._();
LOG.error("Error getting logs for " + logEntity, e);
return; return;
} }
} catch (IOException e) { } finally {
html.h1()._("Error getting logs for " + logEntity)._(); if (reader != null) {
LOG.error("Error getting logs for " + logEntity, e); reader.close();
return; }
} }
} }

View File

@ -114,7 +114,7 @@ public void testReadAcontainerLogs1() throws Exception {
testContainerId, ugi.getShortUserName()); testContainerId, ugi.getShortUserName());
logWriter.append(logKey, logValue); logWriter.append(logKey, logValue);
logWriter.closeWriter(); logWriter.close();
// make sure permission are correct on the file // make sure permission are correct on the file
FileStatus fsStatus = fs.getFileStatus(remoteAppLogFile); FileStatus fsStatus = fs.getFileStatus(remoteAppLogFile);
@ -194,7 +194,7 @@ public void testContainerLogsFileAccess() throws IOException {
ugi.getShortUserName()); ugi.getShortUserName());
logWriter.append(logKey, logValue); logWriter.append(logKey, logValue);
logWriter.closeWriter(); logWriter.close();
BufferedReader in = BufferedReader in =
new BufferedReader(new FileReader(new File(remoteAppLogFile new BufferedReader(new FileReader(new File(remoteAppLogFile

View File

@ -229,7 +229,7 @@ private void writeLog(Configuration configuration, String user)
writer.append(new AggregatedLogFormat.LogKey("container_0_0001_01_000001"), writer.append(new AggregatedLogFormat.LogKey("container_0_0001_01_000001"),
new AggregatedLogFormat.LogValue(rootLogDirs, containerId,UserGroupInformation.getCurrentUser().getShortUserName())); new AggregatedLogFormat.LogValue(rootLogDirs, containerId,UserGroupInformation.getCurrentUser().getShortUserName()));
writer.closeWriter(); writer.close();
} }
private void writeLogs(String dirName) throws Exception { private void writeLogs(String dirName) throws Exception {

View File

@ -178,7 +178,7 @@ private void doAppLogAggregation() {
localAppLogDirs); localAppLogDirs);
if (this.writer != null) { if (this.writer != null) {
this.writer.closeWriter(); this.writer.close();
LOG.info("Finished aggregate log-file for app " + this.applicationId); LOG.info("Finished aggregate log-file for app " + this.applicationId);
} }