YARN-288. Fair scheduler queue doesn't accept any jobs when ACLs are configured. Contributed by Sandy Ryza.

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1428362 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Thomas White 2013-01-03 14:32:01 +00:00
parent ba90c9c867
commit 19a291a0d6
6 changed files with 62 additions and 28 deletions

View File

@ -158,6 +158,9 @@ Release 2.0.3-alpha - Unreleased
YARN-192. Node update causes NPE in the fair scheduler. YARN-192. Node update causes NPE in the fair scheduler.
(Sandy Ryza via tomwhite) (Sandy Ryza via tomwhite)
YARN-288. Fair scheduler queue doesn't accept any jobs when ACLs are
configured. (Sandy Ryza via tomwhite)
Release 2.0.2-alpha - 2012-09-07 Release 2.0.2-alpha - 2012-09-07
INCOMPATIBLE CHANGES INCOMPATIBLE CHANGES

View File

@ -99,20 +99,6 @@ public class FSParentQueue extends FSQueue {
} }
} }
public boolean hasAccess(QueueACL acl, UserGroupInformation user) {
synchronized (this) {
if (getQueueAcls().get(acl).isUserAllowed(user)) {
return true;
}
}
if (parent != null) {
return parent.hasAccess(acl, user);
}
return false;
}
private synchronized QueueUserACLInfo getUserAclInfo( private synchronized QueueUserACLInfo getUserAclInfo(
UserGroupInformation user) { UserGroupInformation user) {
QueueUserACLInfo userAclInfo = QueueUserACLInfo userAclInfo =

View File

@ -23,6 +23,7 @@ import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.security.authorize.AccessControlList; import org.apache.hadoop.security.authorize.AccessControlList;
import org.apache.hadoop.yarn.api.records.Priority; import org.apache.hadoop.yarn.api.records.Priority;
import org.apache.hadoop.yarn.api.records.QueueACL; import org.apache.hadoop.yarn.api.records.QueueACL;
@ -118,6 +119,16 @@ public abstract class FSQueue extends Schedulable implements Queue {
return metrics; return metrics;
} }
public boolean hasAccess(QueueACL acl, UserGroupInformation user) {
// Check if the leaf-queue allows access
if (queueMgr.getQueueAcls(getName()).get(acl).isUserAllowed(user)) {
return true;
}
// Check if parent-queue allows access
return parent != null && parent.hasAccess(acl, user);
}
/** /**
* Recomputes the fair shares for all queues and applications * Recomputes the fair shares for all queues and applications
* under this queue. * under this queue.

View File

@ -33,6 +33,7 @@ import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.classification.InterfaceAudience.LimitedPrivate; import org.apache.hadoop.classification.InterfaceAudience.LimitedPrivate;
import org.apache.hadoop.classification.InterfaceStability.Unstable; import org.apache.hadoop.classification.InterfaceStability.Unstable;
import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.security.AccessControlException;
import org.apache.hadoop.security.UserGroupInformation; import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.yarn.Clock; import org.apache.hadoop.yarn.Clock;
import org.apache.hadoop.yarn.SystemClock; import org.apache.hadoop.yarn.SystemClock;
@ -494,24 +495,15 @@ public class FairScheduler implements ResourceScheduler {
new FSSchedulerApp(applicationAttemptId, user, new FSSchedulerApp(applicationAttemptId, user,
queue, new ActiveUsersManager(getRootQueueMetrics()), queue, new ActiveUsersManager(getRootQueueMetrics()),
rmContext); rmContext);
// Enforce ACLs // Enforce ACLs
UserGroupInformation userUgi; UserGroupInformation userUgi = UserGroupInformation.createRemoteUser(user);
try { if (!queue.hasAccess(QueueACL.SUBMIT_APPLICATIONS, userUgi)) {
userUgi = UserGroupInformation.getCurrentUser();
} catch (IOException ioe) {
LOG.info("Failed to get current user information");
return;
}
// Always a singleton list
List<QueueUserACLInfo> info = queue.getQueueUserAclInfo(userUgi);
if (!info.get(0).getUserAcls().contains(QueueACL.SUBMIT_APPLICATIONS)) {
LOG.info("User " + userUgi.getUserName() + LOG.info("User " + userUgi.getUserName() +
" cannot submit" + " applications to queue " + queue.getName()); " cannot submit applications to queue " + queue.getName());
return; return;
} }
queue.addApp(schedulerApp); queue.addApp(schedulerApp);
queue.getMetrics().submitApp(user, applicationAttemptId.getAttemptId()); queue.getMetrics().submitApp(user, applicationAttemptId.getAttemptId());

View File

@ -387,6 +387,16 @@ public class QueueManager {
queueMaxApps, userMaxApps, queueWeights, userMaxAppsDefault, queueMaxApps, userMaxApps, queueWeights, userMaxAppsDefault,
queueMaxAppsDefault, defaultSchedulingMode, minSharePreemptionTimeouts, queueMaxAppsDefault, defaultSchedulingMode, minSharePreemptionTimeouts,
queueAcls, fairSharePreemptionTimeout, defaultMinSharePreemptionTimeout); queueAcls, fairSharePreemptionTimeout, defaultMinSharePreemptionTimeout);
// Root queue should have empty ACLs. As a queue's ACL is the union of
// its ACL and all its parents' ACLs, setting the roots' to empty will
// neither allow nor prohibit more access to its children.
Map<QueueACL, AccessControlList> rootAcls =
new HashMap<QueueACL, AccessControlList>();
rootAcls.put(QueueACL.SUBMIT_APPLICATIONS, new AccessControlList(" "));
rootAcls.put(QueueACL.ADMINISTER_QUEUE, new AccessControlList(" "));
queueAcls.put(ROOT_QUEUE, rootAcls);
for (String name: queueNamesInAllocFile) { for (String name: queueNamesInAllocFile) {
FSLeafQueue queue = getLeafQueue(name); FSLeafQueue queue = getLeafQueue(name);
if (queueModes.containsKey(name)) { if (queueModes.containsKey(name)) {

View File

@ -19,6 +19,8 @@
package org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair; package org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import java.io.File; import java.io.File;
@ -1243,4 +1245,34 @@ public class TestFairScheduler {
Assert.assertEquals(2, liveContainer.getContainer().getPriority().getPriority()); Assert.assertEquals(2, liveContainer.getContainer().getPriority().getPriority());
} }
} }
@Test
public void testAclSubmitApplication() throws Exception {
// Set acl's
Configuration conf = createConfiguration();
conf.set(FairSchedulerConfiguration.ALLOCATION_FILE, ALLOC_FILE);
scheduler.reinitialize(conf, resourceManager.getRMContext());
PrintWriter out = new PrintWriter(new FileWriter(ALLOC_FILE));
out.println("<?xml version=\"1.0\"?>");
out.println("<allocations>");
out.println("<queue name=\"queue1\">");
out.println("<aclSubmitApps>norealuserhasthisname</aclSubmitApps>");
out.println("</queue>");
out.println("</allocations>");
out.close();
QueueManager queueManager = scheduler.getQueueManager();
queueManager.initialize();
ApplicationAttemptId attId1 = createSchedulingRequest(1024, "queue1",
"norealuserhasthisname", 1);
ApplicationAttemptId attId2 = createSchedulingRequest(1024, "queue1",
"norealuserhasthisname2", 1);
FSSchedulerApp app1 = scheduler.applications.get(attId1);
assertNotNull("The application was not allowed", app1);
FSSchedulerApp app2 = scheduler.applications.get(attId2);
assertNull("The application was allowed", app2);
}
} }