|
28 | 28 | import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_RPC_BIND_HOST_KEY; |
29 | 29 | import static org.junit.Assert.assertEquals; |
30 | 30 | import static org.junit.Assert.assertNotEquals; |
| 31 | +import static org.junit.Assert.assertNotNull; |
31 | 32 |
|
32 | 33 | import java.io.IOException; |
33 | 34 | import java.nio.charset.StandardCharsets; |
| 35 | +import java.security.PrivilegedExceptionAction; |
34 | 36 |
|
35 | 37 | import org.apache.hadoop.conf.Configuration; |
36 | 38 | import org.apache.hadoop.fs.FSDataOutputStream; |
| 39 | +import org.apache.hadoop.fs.FileSystem; |
37 | 40 | import org.apache.hadoop.fs.Path; |
| 41 | +import org.apache.hadoop.fs.permission.FsPermission; |
38 | 42 | import org.apache.hadoop.hdfs.DFSTestUtil; |
39 | 43 | import org.apache.hadoop.hdfs.DistributedFileSystem; |
40 | 44 | import org.apache.hadoop.hdfs.HdfsConfiguration; |
41 | 45 | import org.apache.hadoop.hdfs.MiniDFSCluster; |
42 | 46 |
|
43 | 47 | import org.apache.hadoop.hdfs.protocol.LocatedBlocks; |
| 48 | +import org.apache.hadoop.hdfs.qjournal.MiniQJMHACluster; |
44 | 49 | import org.apache.hadoop.ipc.CallerContext; |
45 | 50 | import org.apache.hadoop.security.UserGroupInformation; |
| 51 | +import org.apache.hadoop.test.GenericTestUtils; |
46 | 52 | import org.junit.Test; |
| 53 | +import org.junit.jupiter.api.Timeout; |
47 | 54 |
|
48 | 55 | public class TestNameNodeRpcServer { |
49 | 56 |
|
@@ -91,6 +98,66 @@ private static String getPreferredLocation(DistributedFileSystem fs, |
91 | 98 | // trials. 1/3^20=3e-10, so that should be good enough. |
92 | 99 | static final int ITERATIONS_TO_USE = 20; |
93 | 100 |
|
| 101 | + @Test |
| 102 | + @Timeout(30000) |
| 103 | + public void testNamenodeRpcClientIpProxyWithFailBack() throws Exception { |
| 104 | + // Make 3 nodes & racks so that we have a decent shot of detecting when |
| 105 | + // our change overrides the random choice of datanode. |
| 106 | + Configuration conf = new HdfsConfiguration(); |
| 107 | + conf.set(DFS_NAMENODE_IP_PROXY_USERS, "fake_joe"); |
| 108 | + final CallerContext original = CallerContext.getCurrent(); |
| 109 | + |
| 110 | + MiniQJMHACluster qjmhaCluster = null; |
| 111 | + try { |
| 112 | + String baseDir = GenericTestUtils.getRandomizedTempPath(); |
| 113 | + MiniQJMHACluster.Builder builder = new MiniQJMHACluster.Builder(conf); |
| 114 | + builder.getDfsBuilder().numDataNodes(3); |
| 115 | + qjmhaCluster = builder.baseDir(baseDir).build(); |
| 116 | + MiniDFSCluster dfsCluster = qjmhaCluster.getDfsCluster(); |
| 117 | + dfsCluster.waitActive(); |
| 118 | + dfsCluster.transitionToActive(0); |
| 119 | + |
| 120 | + // Set the caller context to set the ip address |
| 121 | + CallerContext.setCurrent( |
| 122 | + new CallerContext.Builder("test", conf) |
| 123 | + .build()); |
| 124 | + |
| 125 | + dfsCluster.getFileSystem(0).setPermission( |
| 126 | + new Path("/"), FsPermission.getDirDefault()); |
| 127 | + |
| 128 | + // Run as fake joe to authorize the test |
| 129 | + UserGroupInformation joe = |
| 130 | + UserGroupInformation.createUserForTesting("fake_joe", |
| 131 | + new String[]{"fake_group"}); |
| 132 | + |
| 133 | + FileSystem joeFs = joe.doAs((PrivilegedExceptionAction<FileSystem>) () -> |
| 134 | + FileSystem.get(dfsCluster.getURI(0), conf)); |
| 135 | + |
| 136 | + Path testPath = new Path("/foo"); |
| 137 | + // Write a sample file |
| 138 | + FSDataOutputStream stream = joeFs.create(testPath); |
| 139 | + stream.write("Hello world!\n".getBytes(StandardCharsets.UTF_8)); |
| 140 | + stream.close(); |
| 141 | + |
| 142 | + qjmhaCluster.getDfsCluster().transitionToStandby(0); |
| 143 | + qjmhaCluster.getDfsCluster().transitionToActive(1); |
| 144 | + |
| 145 | + DistributedFileSystem nn1 = dfsCluster.getFileSystem(1); |
| 146 | + assertNotNull(nn1.getFileStatus(testPath)); |
| 147 | + } finally { |
| 148 | + CallerContext.setCurrent(original); |
| 149 | + if (qjmhaCluster != null) { |
| 150 | + try { |
| 151 | + qjmhaCluster.shutdown(); |
| 152 | + } catch (IOException e) { |
| 153 | + e.printStackTrace(); |
| 154 | + } |
| 155 | + } |
| 156 | + // Reset the config |
| 157 | + conf.unset(DFS_NAMENODE_IP_PROXY_USERS); |
| 158 | + } |
| 159 | + } |
| 160 | + |
94 | 161 | /** |
95 | 162 | * A test to make sure that if an authorized user adds "clientIp:" to their |
96 | 163 | * caller context, it will be used to make locality decisions on the NN. |
|
0 commit comments