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.nodemanager;
20 
21 import java.io.File;
22 import java.io.IOException;
23 import java.util.List;
24 import java.util.ListIterator;
25 
26 import org.apache.hadoop.conf.Configuration;
27 import org.apache.hadoop.fs.CommonConfigurationKeys;
28 import org.apache.hadoop.fs.FileContext;
29 import org.apache.hadoop.fs.FileStatus;
30 import org.apache.hadoop.fs.FileUtil;
31 import org.apache.hadoop.fs.Path;
32 import org.apache.hadoop.fs.permission.FsPermission;
33 import org.apache.hadoop.yarn.conf.YarnConfiguration;
34 import org.junit.After;
35 import org.junit.Assert;
36 import org.junit.Before;
37 import org.junit.BeforeClass;
38 import org.junit.Before;
39 import org.junit.Test;
40 
41 public class TestDirectoryCollection {
42 
43   private static final File testDir = new File("target",
44       TestDirectoryCollection.class.getName()).getAbsoluteFile();
45   private static final File testFile = new File(testDir, "testfile");
46 
47   private Configuration conf;
48   private FileContext localFs;
49 
50   @Before
setupForTests()51   public void setupForTests() throws IOException {
52     conf = new Configuration();
53     localFs = FileContext.getLocalFSFileContext(conf);
54     testDir.mkdirs();
55     testFile.createNewFile();
56   }
57 
58   @After
teardown()59   public void teardown() {
60     FileUtil.fullyDelete(testDir);
61   }
62 
63   @Test
testConcurrentAccess()64   public void testConcurrentAccess() throws IOException {
65     // Initialize DirectoryCollection with a file instead of a directory
66 
67     String[] dirs = {testFile.getPath()};
68     DirectoryCollection dc =
69         new DirectoryCollection(dirs, conf.getFloat(
70           YarnConfiguration.NM_MAX_PER_DISK_UTILIZATION_PERCENTAGE,
71           YarnConfiguration.DEFAULT_NM_MAX_PER_DISK_UTILIZATION_PERCENTAGE));
72 
73     // Create an iterator before checkDirs is called to reliable test case
74     List<String> list = dc.getGoodDirs();
75     ListIterator<String> li = list.listIterator();
76 
77     // DiskErrorException will invalidate iterator of non-concurrent
78     // collections. ConcurrentModificationException will be thrown upon next
79     // use of the iterator.
80     Assert.assertTrue("checkDirs did not remove test file from directory list",
81         dc.checkDirs());
82 
83     // Verify no ConcurrentModification is thrown
84     li.next();
85   }
86 
87   @Test
testCreateDirectories()88   public void testCreateDirectories() throws IOException {
89 
90     conf.set(CommonConfigurationKeys.FS_PERMISSIONS_UMASK_KEY, "077");
91 
92     String dirA = new File(testDir, "dirA").getPath();
93     String dirB = new File(dirA, "dirB").getPath();
94     String dirC = new File(testDir, "dirC").getPath();
95     Path pathC = new Path(dirC);
96     FsPermission permDirC = new FsPermission((short)0710);
97 
98     localFs.mkdir(pathC, null, true);
99     localFs.setPermission(pathC, permDirC);
100 
101     String[] dirs = { dirA, dirB, dirC };
102     DirectoryCollection dc =
103         new DirectoryCollection(dirs, conf.getFloat(
104           YarnConfiguration.NM_MAX_PER_DISK_UTILIZATION_PERCENTAGE,
105           YarnConfiguration.DEFAULT_NM_MAX_PER_DISK_UTILIZATION_PERCENTAGE));
106     FsPermission defaultPerm = FsPermission.getDefault()
107         .applyUMask(new FsPermission((short)FsPermission.DEFAULT_UMASK));
108     boolean createResult = dc.createNonExistentDirs(localFs, defaultPerm);
109     Assert.assertTrue(createResult);
110 
111     FileStatus status = localFs.getFileStatus(new Path(dirA));
112     Assert.assertEquals("local dir parent not created with proper permissions",
113         defaultPerm, status.getPermission());
114     status = localFs.getFileStatus(new Path(dirB));
115     Assert.assertEquals("local dir not created with proper permissions",
116         defaultPerm, status.getPermission());
117     status = localFs.getFileStatus(pathC);
118     Assert.assertEquals("existing local directory permissions modified",
119         permDirC, status.getPermission());
120   }
121 
122   @Test
testDiskSpaceUtilizationLimit()123   public void testDiskSpaceUtilizationLimit() throws IOException {
124 
125     String dirA = new File(testDir, "dirA").getPath();
126     String[] dirs = { dirA };
127     DirectoryCollection dc = new DirectoryCollection(dirs, 0.0F);
128     dc.checkDirs();
129     Assert.assertEquals(0, dc.getGoodDirs().size());
130     Assert.assertEquals(1, dc.getFailedDirs().size());
131     Assert.assertEquals(1, dc.getFullDirs().size());
132 
133     dc = new DirectoryCollection(dirs, 100.0F);
134     dc.checkDirs();
135     Assert.assertEquals(1, dc.getGoodDirs().size());
136     Assert.assertEquals(0, dc.getFailedDirs().size());
137     Assert.assertEquals(0, dc.getFullDirs().size());
138 
139     dc = new DirectoryCollection(dirs, testDir.getTotalSpace() / (1024 * 1024));
140     dc.checkDirs();
141     Assert.assertEquals(0, dc.getGoodDirs().size());
142     Assert.assertEquals(1, dc.getFailedDirs().size());
143     Assert.assertEquals(1, dc.getFullDirs().size());
144 
145     dc = new DirectoryCollection(dirs, 100.0F, 0);
146     dc.checkDirs();
147     Assert.assertEquals(1, dc.getGoodDirs().size());
148     Assert.assertEquals(0, dc.getFailedDirs().size());
149     Assert.assertEquals(0, dc.getFullDirs().size());
150   }
151 
152   @Test
testDiskLimitsCutoffSetters()153   public void testDiskLimitsCutoffSetters() throws IOException {
154 
155     String[] dirs = { "dir" };
156     DirectoryCollection dc = new DirectoryCollection(dirs, 0.0F, 100);
157     float testValue = 57.5F;
158     float delta = 0.1F;
159     dc.setDiskUtilizationPercentageCutoff(testValue);
160     Assert.assertEquals(testValue, dc.getDiskUtilizationPercentageCutoff(),
161       delta);
162     testValue = -57.5F;
163     dc.setDiskUtilizationPercentageCutoff(testValue);
164     Assert.assertEquals(0.0F, dc.getDiskUtilizationPercentageCutoff(), delta);
165     testValue = 157.5F;
166     dc.setDiskUtilizationPercentageCutoff(testValue);
167     Assert.assertEquals(100.0F, dc.getDiskUtilizationPercentageCutoff(), delta);
168 
169     long spaceValue = 57;
170     dc.setDiskUtilizationSpaceCutoff(spaceValue);
171     Assert.assertEquals(spaceValue, dc.getDiskUtilizationSpaceCutoff());
172     spaceValue = -57;
173     dc.setDiskUtilizationSpaceCutoff(spaceValue);
174     Assert.assertEquals(0, dc.getDiskUtilizationSpaceCutoff());
175   }
176 
177   @Test
testFailedDisksBecomingGoodAgain()178   public void testFailedDisksBecomingGoodAgain() throws Exception {
179 
180     String dirA = new File(testDir, "dirA").getPath();
181     String[] dirs = { dirA };
182     DirectoryCollection dc = new DirectoryCollection(dirs, 0.0F);
183     dc.checkDirs();
184     Assert.assertEquals(0, dc.getGoodDirs().size());
185     Assert.assertEquals(1, dc.getFailedDirs().size());
186     Assert.assertEquals(1, dc.getFullDirs().size());
187 
188     dc.setDiskUtilizationPercentageCutoff(100.0F);
189     dc.checkDirs();
190     Assert.assertEquals(1, dc.getGoodDirs().size());
191     Assert.assertEquals(0, dc.getFailedDirs().size());
192     Assert.assertEquals(0, dc.getFullDirs().size());
193 
194     conf.set(CommonConfigurationKeys.FS_PERMISSIONS_UMASK_KEY, "077");
195 
196     String dirB = new File(testDir, "dirB").getPath();
197     Path pathB = new Path(dirB);
198     FsPermission permDirB = new FsPermission((short) 0400);
199 
200     localFs.mkdir(pathB, null, true);
201     localFs.setPermission(pathB, permDirB);
202 
203     String[] dirs2 = { dirB };
204 
205     dc = new DirectoryCollection(dirs2, 100.0F);
206     dc.checkDirs();
207     Assert.assertEquals(0, dc.getGoodDirs().size());
208     Assert.assertEquals(1, dc.getFailedDirs().size());
209     Assert.assertEquals(0, dc.getFullDirs().size());
210     permDirB = new FsPermission((short) 0700);
211     localFs.setPermission(pathB, permDirB);
212     dc.checkDirs();
213     Assert.assertEquals(1, dc.getGoodDirs().size());
214     Assert.assertEquals(0, dc.getFailedDirs().size());
215     Assert.assertEquals(0, dc.getFullDirs().size());
216   }
217 
218   @Test
testConstructors()219   public void testConstructors() {
220 
221     String[] dirs = { "dir" };
222     float delta = 0.1F;
223     DirectoryCollection dc = new DirectoryCollection(dirs);
224     Assert.assertEquals(100.0F, dc.getDiskUtilizationPercentageCutoff(), delta);
225     Assert.assertEquals(0, dc.getDiskUtilizationSpaceCutoff());
226 
227     dc = new DirectoryCollection(dirs, 57.5F);
228     Assert.assertEquals(57.5F, dc.getDiskUtilizationPercentageCutoff(), delta);
229     Assert.assertEquals(0, dc.getDiskUtilizationSpaceCutoff());
230 
231     dc = new DirectoryCollection(dirs, 57);
232     Assert.assertEquals(100.0F, dc.getDiskUtilizationPercentageCutoff(), delta);
233     Assert.assertEquals(57, dc.getDiskUtilizationSpaceCutoff());
234 
235     dc = new DirectoryCollection(dirs, 57.5F, 67);
236     Assert.assertEquals(57.5F, dc.getDiskUtilizationPercentageCutoff(), delta);
237     Assert.assertEquals(67, dc.getDiskUtilizationSpaceCutoff());
238 
239     dc = new DirectoryCollection(dirs, -57.5F, -67);
240     Assert.assertEquals(0.0F, dc.getDiskUtilizationPercentageCutoff(), delta);
241     Assert.assertEquals(0, dc.getDiskUtilizationSpaceCutoff());
242 
243     dc = new DirectoryCollection(dirs, 157.5F, -67);
244     Assert.assertEquals(100.0F, dc.getDiskUtilizationPercentageCutoff(), delta);
245     Assert.assertEquals(0, dc.getDiskUtilizationSpaceCutoff());
246   }
247 }
248