/**
 * 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 static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.IOException;
import java.net.URI;
import java.security.PrivilegedExceptionAction;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hdfs.MiniDFSCluster;
import org.apache.hadoop.hdfs.protocol.HdfsFileStatus;
import org.apache.hadoop.hdfs.server.namenode.NameNode;
import org.apache.hadoop.ipc.RPC;
import org.apache.hadoop.ipc.RemoteException;
import org.apache.hadoop.mapreduce.MRConfig;
import org.apache.hadoop.mapreduce.SleepJob;
import org.apache.hadoop.mapreduce.protocol.ClientProtocol;
import org.apache.hadoop.mapreduce.server.jobtracker.JTConfig;
import org.apache.hadoop.net.NetUtils;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.util.ToolRunner;
import org.junit.Test;

/**
 * Test job submission. This test checks if 
 *   - basic   : job submission via jobclient
 *   - cleanup : job client crashes while submitting
 *   - invalid job config
 *     - invalid memory config
 *   
 */
public class TestSubmitJob {
  static final Log LOG = LogFactory.getLog(TestSubmitJob.class);
  
  private static Path TEST_DIR = 
    new Path(System.getProperty("test.build.data","/tmp"), 
             "job-submission-testing");

  /**
   * Test to verify that jobs with invalid memory requirements are killed at the
   * JT.
   * 
   * @throws Exception
   */
  @SuppressWarnings("deprecation")
  @Test
  public void testJobWithInvalidMemoryReqs() throws Exception {
    MiniMRCluster mrCluster = null;
    try {
      JobConf jtConf = new JobConf();
      jtConf.setLong(MRConfig.MAPMEMORY_MB, 1 * 1024L);
      jtConf.setLong(MRConfig.REDUCEMEMORY_MB, 2 * 1024L);
      jtConf.setLong(JTConfig.JT_MAX_MAPMEMORY_MB, 3 * 1024L);
      jtConf.setLong(JTConfig.JT_MAX_REDUCEMEMORY_MB, 4 * 1024L);

      mrCluster = new MiniMRCluster(0, "file:///", 0, null, null, jtConf);

      JobConf clusterConf = mrCluster.createJobConf();

      // No map-memory configuration
      JobConf jobConf = new JobConf(clusterConf);
      jobConf.setMemoryForReduceTask(1 * 1024L);
      runJobAndVerifyFailure(jobConf, JobConf.DISABLED_MEMORY_LIMIT, 1 * 1024L,
          "Invalid job requirements.");

      // No reduce-memory configuration
      jobConf = new JobConf(clusterConf);
      jobConf.setMemoryForMapTask(1 * 1024L);
      runJobAndVerifyFailure(jobConf, 1 * 1024L, JobConf.DISABLED_MEMORY_LIMIT,
          "Invalid job requirements.");

      // Invalid map-memory configuration
      jobConf = new JobConf(clusterConf);
      jobConf.setMemoryForMapTask(4 * 1024L);
      jobConf.setMemoryForReduceTask(1 * 1024L);
      runJobAndVerifyFailure(jobConf, 4 * 1024L, 1 * 1024L,
          "Exceeds the cluster's max-memory-limit.");

      // No reduce-memory configuration
      jobConf = new JobConf(clusterConf);
      jobConf.setMemoryForMapTask(1 * 1024L);
      jobConf.setMemoryForReduceTask(5 * 1024L);
      runJobAndVerifyFailure(jobConf, 1 * 1024L, 5 * 1024L,
          "Exceeds the cluster's max-memory-limit.");
    } finally {
      if (mrCluster != null) {
        mrCluster.shutdown();
      }
    }
  }
  
  @SuppressWarnings("deprecation")
  private void runJobAndVerifyFailure(JobConf jobConf, long memForMapTasks,
      long memForReduceTasks, String expectedMsg)
      throws Exception,
      IOException {
    String[] args = { "-m", "0", "-r", "0", "-mt", "0", "-rt", "0" };
    boolean throwsException = false;
    String msg = null;
    try {
      ToolRunner.run(jobConf, new SleepJob(), args);
    } catch (RemoteException re) {
      throwsException = true;
      msg = re.unwrapRemoteException().getMessage();
    }
    assertTrue(throwsException);
    assertNotNull(msg);

    String overallExpectedMsg =
        "(" + memForMapTasks + " memForMapTasks " + memForReduceTasks
            + " memForReduceTasks): " + expectedMsg;
    assertTrue("Observed message - " + msg
        + " - doesn't contain expected message - " + overallExpectedMsg, msg
        .contains(overallExpectedMsg));
  }
  
  @SuppressWarnings("deprecation")
  static ClientProtocol getJobSubmitClient(JobConf conf, 
                                           UserGroupInformation ugi) 
  throws IOException {
    return (ClientProtocol) RPC.getProxy(ClientProtocol.class, 
        ClientProtocol.versionID, JobTracker.getAddress(conf), ugi, 
        conf, NetUtils.getSocketFactory(conf, ClientProtocol.class));
  }

  static org.apache.hadoop.hdfs.protocol.ClientProtocol getDFSClient(
      Configuration conf, UserGroupInformation ugi) 
  throws IOException {
    return (org.apache.hadoop.hdfs.protocol.ClientProtocol) 
      RPC.getProxy(org.apache.hadoop.hdfs.protocol.ClientProtocol.class, 
        org.apache.hadoop.hdfs.protocol.ClientProtocol.versionID, 
        NameNode.getAddress(conf), ugi, 
        conf, 
        NetUtils.getSocketFactory(conf, 
            org.apache.hadoop.hdfs.protocol.ClientProtocol.class));
  }
  
  /**
   * Submit a job and check if the files are accessible to other users.
   */
  @SuppressWarnings("deprecation")
  @Test
  public void testSecureJobExecution() throws Exception {
    LOG.info("Testing secure job submission/execution");
    MiniMRCluster mr = null;
    Configuration conf = new Configuration();
    final MiniDFSCluster dfs = new MiniDFSCluster(conf, 1, true, null);
    try {
      FileSystem fs = 
        TestMiniMRWithDFSWithDistinctUsers.DFS_UGI.doAs(new PrivilegedExceptionAction<FileSystem>() {
          public FileSystem run() throws IOException {
            return dfs.getFileSystem();
          }
        });
      TestMiniMRWithDFSWithDistinctUsers.mkdir(fs, "/user", "mapred", "mapred", (short)01777);
      TestMiniMRWithDFSWithDistinctUsers.mkdir(fs, "/mapred", "mapred", "mapred", (short)01777);
      TestMiniMRWithDFSWithDistinctUsers.mkdir(fs, conf.get(JTConfig.JT_STAGING_AREA_ROOT),
                                               "mapred", "mapred", (short)01777);

      UserGroupInformation MR_UGI = UserGroupInformation.getLoginUser();
      mr = new MiniMRCluster(0, 0, 1, dfs.getFileSystem().getUri().toString(),
                             1, null, null, MR_UGI);
      JobTracker jt = mr.getJobTrackerRunner().getJobTracker();

      // cleanup
      dfs.getFileSystem().delete(TEST_DIR, true);

      final Path mapSignalFile = new Path(TEST_DIR, "map-signal");
      final Path reduceSignalFile = new Path(TEST_DIR, "reduce-signal");
      
      // create a ugi for user 1
      UserGroupInformation user1 = 
        TestMiniMRWithDFSWithDistinctUsers.createUGI("user1", false);
      Path inDir = new Path("/user/input");
      Path outDir = new Path("/user/output");
      final JobConf job = mr.createJobConf();

      UtilsForTests.configureWaitingJobConf(job, inDir, outDir, 2, 0, 
        "test-submit-job", mapSignalFile.toString(), 
        reduceSignalFile.toString());
      job.set(UtilsForTests.getTaskSignalParameter(true), 
      mapSignalFile.toString());
      job.set(UtilsForTests.getTaskSignalParameter(false), 
      reduceSignalFile.toString());
      LOG.info("Submit job as the actual user (" + user1.getUserName() + ")");
      final JobClient jClient = 
        user1.doAs(new PrivilegedExceptionAction<JobClient>() {
          public JobClient run() throws IOException {
            return new JobClient(job);
          }
        });
      RunningJob rJob = user1.doAs(new PrivilegedExceptionAction<RunningJob>() {
        public RunningJob run() throws IOException {
          return jClient.submitJob(job);
        }
      });
      JobID id = rJob.getID();
      LOG.info("Running job " + id);

      // create user2
      UserGroupInformation user2 = 
        TestMiniMRWithDFSWithDistinctUsers.createUGI("user2", false);
      JobConf conf_other = mr.createJobConf();
      org.apache.hadoop.hdfs.protocol.ClientProtocol client = 
        getDFSClient(conf_other, user2);

      // try accessing mapred.system.dir/jobid/*
      try {
        String path = new URI(jt.getSystemDir()).getPath();
        LOG.info("Try listing the mapred-system-dir as the user (" 
                 + user2.getUserName() + ")");
        client.getListing(path, HdfsFileStatus.EMPTY_NAME, false);
        fail("JobTracker system dir is accessible to others");
      } catch (IOException ioe) {
        assertTrue(ioe.toString(),
          ioe.toString().contains("Permission denied"));
      }
      // try accessing ~/.staging/jobid/*
      JobInProgress jip = jt.getJob(id);
      Path jobSubmitDirpath = 
        new Path(jip.getJobConf().get("mapreduce.job.dir"));
      try {
        LOG.info("Try accessing the job folder for job " + id + " as the user (" 
                 + user2.getUserName() + ")");
        client.getListing(jobSubmitDirpath.toUri().getPath(),
          HdfsFileStatus.EMPTY_NAME, false);
        fail("User's staging folder is accessible to others");
      } catch (IOException ioe) {
        assertTrue(ioe.toString(),
          ioe.toString().contains("Permission denied"));
      }
      UtilsForTests.signalTasks(dfs, fs, true, mapSignalFile.toString(), 
      reduceSignalFile.toString());
      // wait for job to be done
      UtilsForTests.waitTillDone(jClient);

      // check if the staging area is cleaned up
      LOG.info("Check if job submit dir is cleanup or not");
      assertFalse(fs.exists(jobSubmitDirpath));
    } finally {
      if (mr != null) {
        mr.shutdown();
      }
      if (dfs != null) {
        dfs.shutdown();
      }
    }
  }
}
