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:
parent
d38fb71d00
commit
5a1b33507b
@ -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
|
||||||
|
@ -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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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 {
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user