/**
 * 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.hadoop.mapred;

import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.mapred.Queue.QueueState;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.security.authorize.AccessControlList;
import org.apache.hadoop.util.StringUtils;

/**
 * Class that exposes information about queues maintained by the Hadoop
 * Map/Reduce framework.
 * 
 * The Map/Reduce framework can be configured with one or more queues,
 * depending on the scheduler it is configured with. While some 
 * schedulers work only with one queue, some schedulers support multiple 
 * queues.
 *  
 * Queues can be configured with various properties. Some of these
 * properties are common to all schedulers, and those are handled by this
 * class. Schedulers might also associate several custom properties with 
 * queues. Where such a case exists, the queue name must be used to link 
 * the common properties with the scheduler specific ones.  
 */
class QueueManager {
  
  private static final Log LOG = LogFactory.getLog(QueueManager.class);
  
  static final String QUEUE_STATE_SUFFIX = "state";
  /** Prefix in configuration for queue related keys */
  static final String QUEUE_CONF_PROPERTY_NAME_PREFIX = "mapred.queue.";

  // Continue to add this resource, to avoid incompatible change
  static final String QUEUE_ACLS_FILE_NAME = "mapred-queue-acls.xml";

  /** Whether ACLs are enabled in the system or not. */
  private boolean aclsEnabled;
  /** Map of a queue name and Queue object */
  final HashMap<String,Queue> queues = new HashMap<String,Queue>();
  
  /**
   * Enum representing an AccessControlList that drives set of operations that
   * can be performed on a queue.
   */
  static enum QueueACL {
    SUBMIT_JOB ("acl-submit-job"),
    ADMINISTER_JOBS ("acl-administer-jobs");
    // Currently this ACL acl-administer-jobs is checked for the operations
    // FAIL_TASK, KILL_TASK, KILL_JOB, SET_JOB_PRIORITY and VIEW_JOB.

    // TODO: Add ACL for LIST_JOBS when we have ability to authenticate 
    //       users in UI
    // TODO: Add ACL for CHANGE_ACL when we have an admin tool for 
    //       configuring queues.
    
    private final String aclName;
    
    QueueACL(String aclName) {
      this.aclName = aclName;
    }

    final String getAclName() {
      return aclName;
    }
    
  }
  
  /**
   * Construct a new QueueManager using configuration specified in the passed
   * in {@link org.apache.hadoop.conf.Configuration} object.
   * 
   * @param conf Configuration object where queue configuration is specified.
   */
  public QueueManager(Configuration conf) {
    checkDeprecation(conf);
    conf.addResource(QUEUE_ACLS_FILE_NAME);
    
    // Get configured ACLs and state for each queue
    aclsEnabled = conf.getBoolean("mapred.acls.enabled", false);

    queues.putAll(parseQueues(conf)); 
  }
  
  synchronized private Map<String, Queue> parseQueues(Configuration conf) {
    Map<String, Queue> queues = new HashMap<String, Queue>();
    // First get the queue names
    String[] queueNameValues = conf.getStrings("mapred.queue.names",
        new String[]{JobConf.DEFAULT_QUEUE_NAME});
    for (String name : queueNameValues) {
      Map queueACLs = getQueueAcls(name, conf);
      if (queueACLs == null) {
        LOG.error("The queue, " + name + " does not have a configured ACL list");
      }
      queues.put(name, new Queue(name, getQueueAcls(name, conf),
          getQueueState(name, conf), QueueMetrics.create(name, conf)));
    }
    
    return queues;
  }
  
  /**
   * Return the set of queues configured in the system.
   * 
   * The number of queues configured should be dependent on the Scheduler 
   * configured. Note that some schedulers work with only one queue, whereas
   * others can support multiple queues.
   *  
   * @return Set of queue names.
   */
  public synchronized Set<String> getQueues() {
    return queues.keySet();
  }

  /**
   * Return a specific queue configured in the system.
   * 
   * @param queueName Name of the queue requested
   * @return Queue object corresponding to queueName
   */
  public synchronized Queue getQueue(String queueName) {
    return queues.get(queueName);
  }

  /**
   * Return true if the given user is part of the ACL for the given
   * {@link QueueACL} name for the given queue.
   * 
   * An operation is allowed if all users are provided access for this
   * operation, or if either the user or any of the groups specified is
   * provided access.
   * 
   * @param queueName Queue on which the operation needs to be performed. 
   * @param qACL The queue ACL name to be checked
   * @param ugi The user and groups who wish to perform the operation.
   * 
   * @return true if the operation is allowed, false otherwise.
   */
  public synchronized boolean hasAccess(String queueName, QueueACL qACL,
      UserGroupInformation ugi) {
    if (!aclsEnabled) {
      return true;
    }
    final Queue q = queues.get(queueName);
    if (null == q) {
      LOG.info("Queue " + queueName + " is not present");
      return false;
    }
    
    if (LOG.isDebugEnabled()) {
      LOG.debug("checking access for : " +
          toFullPropertyName(queueName, qACL.getAclName()));
    }

    AccessControlList acl =
      q.getAcls().get(toFullPropertyName(queueName, qACL.getAclName()));

    // Check if user is part of the ACL
    return acl != null && acl.isUserAllowed(ugi);
  }

  /**
   * Checks whether the given queue is running or not.
   * @param queueName name of the queue
   * @return true, if the queue is running.
   */
  synchronized boolean isRunning(String queueName) {
    Queue q = queues.get(queueName);
    return q != null && Queue.QueueState.RUNNING.equals(q.getState());
  }

  /**
   * Set a generic Object that represents scheduling information relevant
   * to a queue.
   * 
   * A string representation of this Object will be used by the framework
   * to display in user facing applications like the JobTracker web UI and
   * the hadoop CLI.
   * 
   * @param queueName queue for which the scheduling information is to be set. 
   * @param queueInfo scheduling information for this queue.
   */
  public synchronized void setSchedulerInfo(String queueName, 
                                              Object queueInfo) {
    Queue q = queues.get(queueName);
    if (q != null) {
      q.setSchedulingInfo(queueInfo);
    }
  }
  
  /**
   * Return the scheduler information configured for this queue.
   * 
   * @param queueName queue for which the scheduling information is required.
   * @return The scheduling information for this queue.
   * 
   * @see #setSchedulerInfo(String, Object)
   */
  public synchronized Object getSchedulerInfo(String queueName) {
    Queue q = queues.get(queueName);
    return (q != null)
      ? q.getSchedulingInfo()
      : null;
  }
  
  /**
   * Refresh the acls for the configured queues in the system by reading
   * it from mapred-queue-acls.xml.
   * 
   * The previous acls are removed. Previously configured queues and
   * if or not acl is disabled is retained.
   * 
   * @throws IOException when queue ACL configuration file is invalid.
   */
  synchronized void refreshQueues(Configuration conf) throws IOException {
    
    // First check if things are configured in mapred-site.xml,
    // so we can print out a deprecation warning.
    // This check is needed only until we support the configuration
    // in mapred-site.xml
    checkDeprecation(conf);

    // Add the queue configuration file. Values from mapred-site.xml
    // will be overridden.
    conf.addResource(QUEUE_ACLS_FILE_NAME);

    // Now parse the queues and check to ensure no queue has been deleted
    Map<String, Queue> newQueues = parseQueues(conf);
    checkQueuesForDeletion(queues, newQueues);

    // Now we refresh the properties of the queues. Note that we
    // do *not* refresh the queue names or the acls flag. Instead
    // we use the older values configured for them.
    queues.clear();
    queues.putAll(newQueues);
    LOG.info("Queues acls, state and configs refreshed: " + 
        queues.size() + " queues present now.");
  }

  private void checkQueuesForDeletion(Map<String, Queue> currentQueues,
      Map<String, Queue> newQueues) {
    for (String queue : currentQueues.keySet()) {
      if (!newQueues.containsKey(queue)) {
        throw new IllegalArgumentException("Couldn't find queue '" + queue + 
            "' during refresh!");
      }
    }
    
    // Mark new queues as STOPPED
    for (String queue : newQueues.keySet()) {
      if (!currentQueues.containsKey(queue)) {
        newQueues.get(queue).setState(QueueState.STOPPED);
      }
    }
  }
  
  private void checkDeprecation(Configuration conf) {
    // check if queues are defined.
    String[] queues = conf.getStrings("mapred.queue.names");
    // check if acls are defined
    if (queues != null) {
      for (String queue : queues) {
        for (QueueACL oper : QueueACL.values()) {
          String aclString =
            conf.get(toFullPropertyName(queue, oper.getAclName()));
          if (aclString != null) {
            LOG.warn("Configuring queue ACLs in mapred-site.xml or " +
                "hadoop-site.xml is deprecated. Configure queue ACLs in " +
                QUEUE_ACLS_FILE_NAME);
            // even if one string is configured, it is enough for printing
            // the warning. so we can return from here.
            return;
          }
        }
      }
    }
  }

  /** Parse ACLs for the queue from the configuration. */
  HashMap<String, AccessControlList> getQueueAcls(
      String name, Configuration conf) {
    HashMap<String,AccessControlList> map =
      new HashMap<String,AccessControlList>();
    for (QueueACL oper : QueueACL.values()) {
      String aclKey = toFullPropertyName(name, oper.getAclName());
      map.put(aclKey, new AccessControlList(conf.get(aclKey, "*")));
    }
    return map;
  }

  /** Parse state of the queue from the configuration. */
  Queue.QueueState getQueueState(String name, Configuration conf) {
    return conf.getEnum(
        toFullPropertyName(name, QueueManager.QUEUE_STATE_SUFFIX),
        Queue.QueueState.RUNNING);
  }

  static final String toFullPropertyName(String queue, String property) {
    return QUEUE_CONF_PROPERTY_NAME_PREFIX + queue + "." + property;
  }
  
  synchronized JobQueueInfo getJobQueueInfo(String queue) {
    Queue q = queues.get(queue);
    if (q != null) {
      JobQueueInfo qInfo = new JobQueueInfo();
      qInfo.setQueueName(q.getName());
      qInfo.setQueueState(q.getState().getStateName());
      Object schedInfo = q.getSchedulingInfo();
      qInfo.setSchedulingInfo(schedInfo == null ? null : schedInfo.toString());
      return qInfo;
    }
    return null;
  }

  synchronized JobQueueInfo[] getJobQueueInfos() {
    ArrayList<JobQueueInfo> ret = new ArrayList<JobQueueInfo>();
    for (String qName : getQueues()) {
      ret.add(getJobQueueInfo(qName));
    }
    return (JobQueueInfo[]) ret.toArray(new JobQueueInfo[ret.size()]);
  }

  /**
   * Generates the array of QueueAclsInfo object. The array consists of only those queues
   * for which user <ugi.getShortUserName()> has acls
   *
   * @return QueueAclsInfo[]
   * @throws java.io.IOException
   */
  synchronized QueueAclsInfo[] getQueueAcls(UserGroupInformation ugi)
      throws IOException {
    //List of all QueueAclsInfo objects , this list is returned
    ArrayList<QueueAclsInfo> queueAclsInfolist = new ArrayList<QueueAclsInfo>();
    QueueACL[] acls = QueueACL.values();
    for (String queueName : getQueues()) {
      QueueAclsInfo queueAclsInfo = null;
      ArrayList<String> operationsAllowed = null;
      for (QueueACL qACL : acls) {
        if (hasAccess(queueName, qACL, ugi)) {
          if (operationsAllowed == null) {
            operationsAllowed = new ArrayList<String>();
          }
          operationsAllowed.add(qACL.getAclName());
        }
      }
      if (operationsAllowed != null) {
        //There is atleast 1 operation supported for queue <queueName>
        //, hence initialize queueAclsInfo
        queueAclsInfo = new QueueAclsInfo(queueName, operationsAllowed.toArray(
              new String[operationsAllowed.size()]));
        queueAclsInfolist.add(queueAclsInfo);
      }
    }
    return
      queueAclsInfolist.toArray(new QueueAclsInfo[queueAclsInfolist.size()]);
  }

  /**
   * Returns the specific queue ACL for the given queue.
   * Returns null if the given queue does not exist or the acl is not
   * configured for that queue.
   * If acls are disabled(mapred.acls.enabled set to false), returns ACL with
   * all users.
   */
  synchronized AccessControlList getQueueACL(String queueName, QueueACL qACL) {
    if (aclsEnabled) {
      Queue q = queues.get(queueName);
      if (q == null) {
        throw new IllegalArgumentException(
            "There is no queue named " + queueName);
      }
      Map<String, AccessControlList> acls = q.getAcls();
      if (acls == null) {
        throw new IllegalArgumentException("The queue named " + queueName +
            " is misconfigured: its access control lists are undefined.");
      }
      return acls.get(toFullPropertyName(queueName, qACL.getAclName()));
    }
    return new AccessControlList("*");
  }

  /**
   * prints the configuration of QueueManager in Json format.
   * The method should be modified accordingly whenever
   * QueueManager(Configuration) constructor is modified.
   * @param writer {@link}Writer object to which the configuration properties 
   * are printed in json format
   * @throws IOException
   */
  static void dumpConfiguration(Writer writer) throws IOException {
    Configuration conf = new Configuration(false);
    conf.addResource(QUEUE_ACLS_FILE_NAME);
    Configuration.dumpConfiguration(conf, writer);
  }

}
