Skip to content

Commit 0df4777

Browse files
committed
Merge pull request #61 from childsb/super_user
multi-user/multi-tenancy support for hadoop on glusterfs
2 parents 4d76213 + a6286a9 commit 0df4777

File tree

4 files changed

+115
-5
lines changed

4 files changed

+115
-5
lines changed

conf/core-site.xml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,12 @@
2424
<value>glusterfs://ambari-3.abrv8.com:gv0<</value>
2525
</property>
2626

27-
27+
<!-- a super user that the hadoop daemons run under. required for multi-user secure clusters -->
28+
<property>
29+
<name>gluster.daemon.user</name>
30+
<value>hadoop</value>
31+
</property>
32+
2833
<!-- this is the default glusterfs hook with no additional integrity checking on files -->
2934
<property>
3035
<name>fs.AbstractFileSystem.glusterfs.impl</name>

conf/mapred-site.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,16 @@
1616
<name>mapred.system.dir</name>
1717
<value>glusterfs:///mapred/system</value>
1818
</property>
19+
<property>
20+
<name>mapreduce.jobhistory.done-dir</name>
21+
<value>glusterfs:///job-history/done</value>
22+
</property>
23+
24+
<property>
25+
<name>mapreduce.jobhistory.intermediate-done-dir</name>
26+
<value>glusterfs:///job-history/intermediate-done</value>
27+
</property>
28+
1929
<property>
2030
<name>mapreduce.jobtracker.staging.root.dir</name>
2131
<value>glusterfs:///user</value>
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package org.apache.hadoop.fs.glusterfs;
2+
3+
import java.io.IOException;
4+
import java.util.ListIterator;
5+
import java.util.Vector;
6+
import org.apache.hadoop.conf.Configuration;
7+
import org.apache.hadoop.fs.Path;
8+
import org.apache.hadoop.security.UserGroupInformation;
9+
10+
11+
public class AclPathFilter {
12+
13+
Vector<String> paths = null;
14+
15+
public AclPathFilter(){
16+
paths = new Vector<String>();
17+
}
18+
/* generates a white list of ACL path regular expressions */
19+
public AclPathFilter(Configuration conf){
20+
this();
21+
UserGroupInformation ugi = null;
22+
try {
23+
ugi = UserGroupInformation.getCurrentUser();
24+
} catch (IOException e) {
25+
26+
}
27+
String stagingRootDir = new Path(conf.get("yarn.app.mapreduce.am.staging-dir",conf.get("mapreduce.jobtracker.staging.root.dir", "/tmp/hadoop/mapred/staging"))).toString();
28+
String user;
29+
String randid = "\\d*";
30+
if (ugi != null) {
31+
user = ugi.getShortUserName();
32+
} else {
33+
user = "dummy";
34+
}
35+
paths.add("^" + new Path(stagingRootDir, user + randid +"/.staging").toString() + ".*");
36+
paths.add("^" + (new Path(stagingRootDir, user + randid +"/.staging")).toUri().getPath() + ".*");
37+
stagingRootDir = new Path(conf.get("mapreduce.jobtracker.staging.root.dir","/tmp/hadoop/mapred/staging")).toString();
38+
paths.add("^" + new Path(stagingRootDir, user+"/.staging").toString() + ".*");
39+
paths.add("^" + (new Path(stagingRootDir, user+"/.staging")).toUri().getPath() + ".*");
40+
41+
}
42+
43+
public boolean matches(String path){
44+
45+
boolean needsAcl = false;
46+
ListIterator<String> list = paths.listIterator();
47+
String filterPath = null;
48+
while(list.hasNext() && !needsAcl){
49+
filterPath = list.next();
50+
if(path.matches(filterPath)){
51+
needsAcl = true;
52+
}
53+
}
54+
return needsAcl;
55+
}
56+
public boolean matches(Path path){
57+
return matches(path.toString());
58+
}
59+
}

src/main/java/org/apache/hadoop/fs/glusterfs/GlusterVolume.java

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import org.apache.hadoop.fs.RawLocalFileSystem;
3636
import org.slf4j.Logger;
3737
import org.slf4j.LoggerFactory;
38+
import org.apache.hadoop.fs.permission.FsPermission;
3839

3940
public class GlusterVolume extends RawLocalFileSystem{
4041

@@ -43,6 +44,8 @@ public class GlusterVolume extends RawLocalFileSystem{
4344
public static final URI NAME = URI.create("glusterfs:///");
4445

4546
protected String root=null;
47+
protected String superUser=null;
48+
protected AclPathFilter aclFilter = null;
4649

4750
protected static GlusterFSXattr attr = null;
4851

@@ -81,6 +84,10 @@ public void setConf(Configuration conf){
8184
mkdirs(mapredSysDirectory);
8285
}
8386

87+
superUser = conf.get("gluster.daemon.user", null);
88+
89+
aclFilter = new AclPathFilter(conf);
90+
8491
/* ensure the initial working directory exists */
8592
Path workingDirectory = getInitialWorkingDirectory();
8693
mkdirs(workingDirectory);
@@ -104,7 +111,7 @@ public File pathToFile(Path path) {
104111
}
105112

106113
@Override
107-
protected Path getInitialWorkingDirectory() {
114+
protected Path getInitialWorkingDirectory() {
108115
/* apache's unit tests use a default working direcotry like this: */
109116
return new Path(this.NAME + "user/" + System.getProperty("user.name"));
110117
/* The super impl returns the users home directory in unix */
@@ -113,9 +120,9 @@ protected Path getInitialWorkingDirectory() {
113120

114121
public Path fileToPath(File path) {
115122
return new Path(NAME.toString() + path.toURI().getRawPath().substring(root.length()));
116-
}
123+
}
117124

118-
public boolean rename(Path src, Path dst) throws IOException {
125+
public boolean rename(Path src, Path dst) throws IOException {
119126
File dest = pathToFile(dst);
120127

121128
/* two HCFS semantics java.io.File doesn't honor */
@@ -200,7 +207,36 @@ public long getBlockSize(Path path) throws IOException{
200207

201208
return blkSz;
202209
}
203-
210+
/*
211+
* ensures the 'super user' is given read/write access.
212+
* the ACL drops off after a chmod or chown.
213+
*/
214+
215+
private void updateAcl(Path p){
216+
if(superUser!=null && aclFilter.matches(p) ){
217+
File f = pathToFile(p);
218+
String path = f.getAbsolutePath();
219+
String command = "setfacl -m u:" + superUser + ":rwx " + path;
220+
try{
221+
Runtime.getRuntime().exec(command);
222+
}catch(IOException ex){
223+
throw new RuntimeException(ex);
224+
}
225+
}
226+
}
227+
228+
public void setOwner(Path p, String username, String groupname)
229+
throws IOException {
230+
super.setOwner(p,username,groupname);
231+
updateAcl(p);
232+
233+
}
234+
235+
public void setPermission(Path p, FsPermission permission)
236+
throws IOException {
237+
super.setPermission(p,permission);
238+
updateAcl(p);
239+
}
204240
public BlockLocation[] getFileBlockLocations(FileStatus file,long start,long len) throws IOException{
205241
File f=pathToFile(file.getPath());
206242
BlockLocation[] result=null;

0 commit comments

Comments
 (0)