blob: 7da51c104dd11db7c3abde576d499da23337a81f [file] [log] [blame]
/*
* 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.slider.other
import groovy.io.FileType
import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
import org.apache.hadoop.conf.Configuration
import org.apache.hadoop.fs.AbstractFileSystem
import org.apache.hadoop.fs.FileContext
import org.apache.hadoop.fs.FileStatus
import org.apache.hadoop.fs.FileUtil
import org.apache.hadoop.fs.LocalFileSystem
import org.apache.hadoop.fs.Path
import org.apache.hadoop.fs.local.LocalFs
import org.apache.hadoop.fs.permission.FsPermission
import org.apache.hadoop.util.DiskChecker
import org.apache.hadoop.yarn.exceptions.YarnRuntimeException
import org.apache.hadoop.yarn.server.nodemanager.containermanager.localizer.ContainerLocalizer
import org.apache.hadoop.yarn.server.nodemanager.containermanager.localizer.ResourceLocalizationService
import org.apache.slider.test.YarnMiniClusterTestBase
import org.junit.After
import org.junit.Test
import org.slf4j.Logger
import org.slf4j.LoggerFactory
/**
* This test class exists to look at permissions of the filesystem, especially
* that created by Mini YARN clusters. On some windows jenkins machines,
* YARN actions were failing as the directories had the wrong permissions
* (i.e. too lax)
*/
@CompileStatic
@Slf4j
class TestFilesystemPermissions extends YarnMiniClusterTestBase {
static final Logger LOG = LoggerFactory.getLogger(TestFilesystemPermissions);
List<File> filesToDelete = []
@After
public void deleteFiles() {
filesToDelete.each { File f ->
FileUtil.fullyDelete(f, true)
}
}
@Test
public void testJavaFSOperations() throws Throwable {
assertNativeLibrariesPresent();
File subdir = testDir()
subdir.mkdir()
assert subdir.isDirectory()
assert FileUtil.canRead(subdir)
assert FileUtil.canWrite(subdir)
assert FileUtil.canExecute(subdir)
}
@Test
public void testDiskCheckerOperations() throws Throwable {
assertNativeLibrariesPresent();
File subdir = testDir()
subdir.mkdir()
DiskChecker checker = new DiskChecker()
checker.checkDir(subdir)
}
@Test
public void testDiskCheckerMkdir() throws Throwable {
assertNativeLibrariesPresent();
File subdir = testDir()
subdir.mkdirs()
DiskChecker checker = new DiskChecker()
checker.checkDir(subdir)
}
/**
* Get a test dir for this method; one that will be deleted on teardown
* @return a filename unique to this test method
*/
File testDir() {
File parent = new File("target/testfspermissions")
parent.mkdir()
File testdir = new File(parent, methodName.methodName)
filesToDelete << testdir
return testdir;
}
@Test
public void testPermsMap() throws Throwable {
def dir = testDir()
def diruri = dir.toURI().toString()
def lfs = createLocalFS(dir, configuration)
getLocalDirsPathPermissionsMap(lfs, diruri)
}
@Test
public void testInitLocaldir() throws Throwable {
def dir = testDir()
def diruri = dir.toURI().toString()
def lfs = createLocalFS(dir, configuration)
initializeLocalDir(lfs, diruri)
def localDirs = getInitializedLocalDirs(lfs, [diruri])
assert localDirs.size() ==1
}
@Test
public void testValidateMiniclusterPerms() throws Throwable {
def numLocal = 1
def cluster = createMiniCluster("", configuration, 1, numLocal, 1, false)
def workDir = miniCluster.getTestWorkDir()
List<File> localdirs = [];
workDir.eachDir { File file ->
if (file.absolutePath.contains("-local")) {
// local dir
localdirs << file
}
}
assert localdirs.size() == numLocal
def lfs = createLocalFS(workDir, configuration)
localdirs.each { File file ->
checkLocalDir(lfs, file.toURI().toString())
}
}
FileContext createLocalFS(File dir, Configuration conf) {
return FileContext.getFileContext(dir.toURI(), conf)
}
/**
* extracted from ResourceLocalizationService
* @param lfs
* @param localDir
* @return perms map
* @see ResourceLocalizationService
*/
private Map<Path, FsPermission> getLocalDirsPathPermissionsMap(
FileContext lfs,
String localDir) {
Map<Path, FsPermission> localDirPathFsPermissionsMap = new HashMap<Path, FsPermission>();
FsPermission defaultPermission =
FsPermission.getDirDefault().applyUMask(lfs.getUMask());
FsPermission nmPrivatePermission =
ResourceLocalizationService.NM_PRIVATE_PERM.applyUMask(lfs.getUMask());
Path userDir = new Path(localDir, ContainerLocalizer.USERCACHE);
Path fileDir = new Path(localDir, ContainerLocalizer.FILECACHE);
Path sysDir = new Path(
localDir,
ResourceLocalizationService.NM_PRIVATE_DIR);
localDirPathFsPermissionsMap.put(userDir, defaultPermission);
localDirPathFsPermissionsMap.put(fileDir, defaultPermission);
localDirPathFsPermissionsMap.put(sysDir, nmPrivatePermission);
return localDirPathFsPermissionsMap;
}
private boolean checkLocalDir(FileContext lfs, String localDir) {
Map<Path, FsPermission> pathPermissionMap =
getLocalDirsPathPermissionsMap(lfs, localDir);
for (Map.Entry<Path, FsPermission> entry : pathPermissionMap.entrySet()) {
FileStatus status;
status = lfs.getFileStatus(entry.getKey());
if (!status.getPermission().equals(entry.getValue())) {
String msg =
"Permissions incorrectly set for dir " + entry.getKey() +
", should be " + entry.getValue() + ", actual value = " +
status.getPermission();
throw new YarnRuntimeException(msg);
}
}
return true;
}
private void initializeLocalDir(FileContext lfs, String localDir) {
Map<Path, FsPermission> pathPermissionMap =
getLocalDirsPathPermissionsMap(lfs, localDir);
for (Map.Entry<Path, FsPermission> entry : pathPermissionMap.entrySet()) {
FileStatus status;
try {
status = lfs.getFileStatus(entry.getKey());
}
catch (FileNotFoundException fs) {
status = null;
}
if (status == null) {
lfs.mkdir(entry.getKey(), entry.getValue(), true);
status = lfs.getFileStatus(entry.getKey());
}
FsPermission perms = status.getPermission();
if (!perms.equals(entry.getValue())) {
lfs.setPermission(entry.getKey(), entry.getValue());
}
}
}
synchronized private List<String> getInitializedLocalDirs(FileContext lfs,
List<String> dirs) {
List<String> checkFailedDirs = new ArrayList<String>();
for (String dir : dirs) {
try {
checkLocalDir(lfs, dir);
} catch (YarnRuntimeException e) {
checkFailedDirs.add(dir);
}
}
for (String dir : checkFailedDirs) {
LOG.info("Attempting to initialize " + dir);
initializeLocalDir(lfs, dir);
checkLocalDir(lfs, dir);
}
return dirs;
}
private void createDir(FileContext localFs, Path dir, FsPermission perm)
throws IOException {
if (dir == null) {
return;
}
try {
localFs.getFileStatus(dir);
} catch (FileNotFoundException e) {
createDir(localFs, dir.getParent(), perm);
localFs.mkdir(dir, perm, false);
if (!perm.equals(perm.applyUMask(localFs.getUMask()))) {
localFs.setPermission(dir, perm);
}
}
}
}