/**
* 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.mapreduce.v2;

import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceStability;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.CommonConfigurationKeys;
import org.apache.hadoop.fs.FileContext;
import org.apache.hadoop.fs.LocalFileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.http.HttpConfig;
import org.apache.hadoop.mapred.LocalContainerLauncher;
import org.apache.hadoop.mapred.ShuffleHandler;
import org.apache.hadoop.mapreduce.MRConfig;
import org.apache.hadoop.mapreduce.MRJobConfig;
import org.apache.hadoop.mapreduce.v2.hs.JobHistoryServer;
import org.apache.hadoop.mapreduce.v2.jobhistory.JHAdminConfig;
import org.apache.hadoop.mapreduce.v2.jobhistory.JobHistoryUtils;
import org.apache.hadoop.mapreduce.v2.util.MRWebAppUtil;
import org.apache.hadoop.net.NetUtils;
import org.apache.hadoop.service.AbstractService;
import org.apache.hadoop.service.Service;
import org.apache.hadoop.util.JarFinder;
import org.apache.hadoop.yarn.conf.YarnConfiguration;
import org.apache.hadoop.yarn.exceptions.YarnRuntimeException;
import org.apache.hadoop.yarn.server.MiniYARNCluster;
import org.apache.hadoop.yarn.server.nodemanager.ContainerExecutor;
import org.apache.hadoop.yarn.server.nodemanager.DefaultContainerExecutor;
import org.apache.hadoop.yarn.webapp.util.WebAppUtils;

/**
 * Configures and starts the MR-specific components in the YARN cluster.
 *
 */
@InterfaceAudience.Public
@InterfaceStability.Evolving
public class MiniMRYarnCluster extends MiniYARNCluster {

  public static final String APPJAR = JarFinder.getJar(LocalContainerLauncher.class);

  private static final Log LOG = LogFactory.getLog(MiniMRYarnCluster.class);
  private JobHistoryServer historyServer;
  private JobHistoryServerWrapper historyServerWrapper;
  private static final String TIMELINE_AUX_SERVICE_NAME = "timeline_collector";

  public MiniMRYarnCluster(String testName) {
    this(testName, 1);
  }

  public MiniMRYarnCluster(String testName, int noOfNMs) {
    this(testName, noOfNMs, false);
  }
  @Deprecated
  public MiniMRYarnCluster(String testName, int noOfNMs, boolean enableAHS) {
    super(testName, 1, noOfNMs, 4, 4, enableAHS);
    historyServerWrapper = new JobHistoryServerWrapper();
    addService(historyServerWrapper);
  }

  public static String getResolvedMRHistoryWebAppURLWithoutScheme(
      Configuration conf, boolean isSSLEnabled) {
    InetSocketAddress address = null;
    if (isSSLEnabled) {
      address =
          conf.getSocketAddr(JHAdminConfig.MR_HISTORY_WEBAPP_HTTPS_ADDRESS,
              JHAdminConfig.DEFAULT_MR_HISTORY_WEBAPP_HTTPS_ADDRESS,
              JHAdminConfig.DEFAULT_MR_HISTORY_WEBAPP_HTTPS_PORT);
    } else {
      address =
          conf.getSocketAddr(JHAdminConfig.MR_HISTORY_WEBAPP_ADDRESS,
              JHAdminConfig.DEFAULT_MR_HISTORY_WEBAPP_ADDRESS,
              JHAdminConfig.DEFAULT_MR_HISTORY_WEBAPP_PORT);    }
    address = NetUtils.getConnectAddress(address);
    StringBuffer sb = new StringBuffer();
    InetAddress resolved = address.getAddress();
    if (resolved == null || resolved.isAnyLocalAddress() || 
        resolved.isLoopbackAddress()) {
      String lh = address.getHostName();
      try {
        lh = InetAddress.getLocalHost().getCanonicalHostName();
      } catch (UnknownHostException e) {
        //Ignore and fallback.
      }
      sb.append(lh);
    } else {
      sb.append(address.getHostName());
    }
    sb.append(":").append(address.getPort());
    return sb.toString();
  }

  @Override
  public void serviceInit(Configuration conf) throws Exception {
    conf.set(MRConfig.FRAMEWORK_NAME, MRConfig.YARN_FRAMEWORK_NAME);
    if (conf.get(MRJobConfig.MR_AM_STAGING_DIR) == null) {
      conf.set(MRJobConfig.MR_AM_STAGING_DIR, new File(getTestWorkDir(),
          "apps_staging_dir/").getAbsolutePath());
    }

    // By default, VMEM monitoring disabled, PMEM monitoring enabled.
    if (!conf.getBoolean(
        MRConfig.MAPREDUCE_MINICLUSTER_CONTROL_RESOURCE_MONITORING,
        MRConfig.DEFAULT_MAPREDUCE_MINICLUSTER_CONTROL_RESOURCE_MONITORING)) {
      conf.setBoolean(YarnConfiguration.NM_PMEM_CHECK_ENABLED, false);
      conf.setBoolean(YarnConfiguration.NM_VMEM_CHECK_ENABLED, false);
    }

    conf.set(CommonConfigurationKeys.FS_PERMISSIONS_UMASK_KEY,  "000");

    try {
      Path stagingPath = FileContext.getFileContext(conf).makeQualified(
          new Path(conf.get(MRJobConfig.MR_AM_STAGING_DIR)));
      /*
       * Re-configure the staging path on Windows if the file system is localFs.
       * We need to use a absolute path that contains the drive letter. The unit
       * test could run on a different drive than the AM. We can run into the
       * issue that job files are localized to the drive where the test runs on,
       * while the AM starts on a different drive and fails to find the job
       * metafiles. Using absolute path can avoid this ambiguity.
       */
      if (Path.WINDOWS) {
        if (LocalFileSystem.class.isInstance(stagingPath.getFileSystem(conf))) {
          conf.set(MRJobConfig.MR_AM_STAGING_DIR,
              new File(conf.get(MRJobConfig.MR_AM_STAGING_DIR))
                  .getAbsolutePath());
        }
      }
      FileContext fc=FileContext.getFileContext(stagingPath.toUri(), conf);
      if (fc.util().exists(stagingPath)) {
        LOG.info(stagingPath + " exists! deleting...");
        fc.delete(stagingPath, true);
      }
      LOG.info("mkdir: " + stagingPath);
      //mkdir the staging directory so that right permissions are set while running as proxy user
      fc.mkdir(stagingPath, null, true);
      //mkdir done directory as well 
      String doneDir = JobHistoryUtils.getConfiguredHistoryServerDoneDirPrefix(conf);
      Path doneDirPath = fc.makeQualified(new Path(doneDir));
      fc.mkdir(doneDirPath, null, true);
    } catch (IOException e) {
      throw new YarnRuntimeException("Could not create staging directory. ", e);
    }
    conf.set(MRConfig.MASTER_ADDRESS, "test"); // The default is local because of
                                             // which shuffle doesn't happen
    //configure the shuffle service in NM
    String[] nmAuxServices = conf.getStrings(YarnConfiguration.NM_AUX_SERVICES);
    // if need to enable TIMELINE_AUX_SERVICE_NAME
    boolean enableTimelineAuxService = false;
    if (nmAuxServices != null) {
      for (String nmAuxService: nmAuxServices) {
        if (nmAuxService.equals(TIMELINE_AUX_SERVICE_NAME)) {
          enableTimelineAuxService = true;
          break;
        }
      }
    }
    if (enableTimelineAuxService) {
      conf.setStrings(YarnConfiguration.NM_AUX_SERVICES,
          new String[] {ShuffleHandler.MAPREDUCE_SHUFFLE_SERVICEID,
              TIMELINE_AUX_SERVICE_NAME});
    } else {
      conf.setStrings(YarnConfiguration.NM_AUX_SERVICES,
          new String[] {ShuffleHandler.MAPREDUCE_SHUFFLE_SERVICEID});
    }
    conf.setClass(String.format(YarnConfiguration.NM_AUX_SERVICE_FMT,
        ShuffleHandler.MAPREDUCE_SHUFFLE_SERVICEID), ShuffleHandler.class,
        Service.class);

    // Non-standard shuffle port
    conf.setInt(ShuffleHandler.SHUFFLE_PORT_CONFIG_KEY, 0);

    conf.setClass(YarnConfiguration.NM_CONTAINER_EXECUTOR,
        DefaultContainerExecutor.class, ContainerExecutor.class);

    // TestMRJobs is for testing non-uberized operation only; see TestUberAM
    // for corresponding uberized tests.
    conf.setBoolean(MRJobConfig.JOB_UBERTASK_ENABLE, false);

    super.serviceInit(conf);
  }

  @Override
  protected void serviceStart() throws Exception {
    super.serviceStart();

    //need to do this because historyServer.init creates a new Configuration
    getConfig().set(JHAdminConfig.MR_HISTORY_ADDRESS,
                    historyServer.getConfig().get(JHAdminConfig.MR_HISTORY_ADDRESS));
    MRWebAppUtil.setJHSWebappURLWithoutScheme(getConfig(),
        MRWebAppUtil.getJHSWebappURLWithoutScheme(historyServer.getConfig()));

    LOG.info("MiniMRYARN ResourceManager address: " +
        getConfig().get(YarnConfiguration.RM_ADDRESS));
    LOG.info("MiniMRYARN ResourceManager web address: " +
        WebAppUtils.getRMWebAppURLWithoutScheme(getConfig()));
    LOG.info("MiniMRYARN HistoryServer address: " +
        getConfig().get(JHAdminConfig.MR_HISTORY_ADDRESS));
    LOG.info("MiniMRYARN HistoryServer web address: " +
        getResolvedMRHistoryWebAppURLWithoutScheme(getConfig(),
            MRWebAppUtil.getJHSHttpPolicy() == HttpConfig.Policy.HTTPS_ONLY));
  }

  private class JobHistoryServerWrapper extends AbstractService {
    public JobHistoryServerWrapper() {
      super(JobHistoryServerWrapper.class.getName());
    }
    private volatile boolean jhsStarted = false;

    @Override
    public synchronized void serviceStart() throws Exception {
      try {
        if (!getConfig().getBoolean(
            JHAdminConfig.MR_HISTORY_MINICLUSTER_FIXED_PORTS,
            JHAdminConfig.DEFAULT_MR_HISTORY_MINICLUSTER_FIXED_PORTS)) {
          String hostname = MiniYARNCluster.getHostname();
          // pick free random ports.
          getConfig().set(JHAdminConfig.MR_HISTORY_ADDRESS,
            hostname + ":0");
          MRWebAppUtil.setJHSWebappURLWithoutScheme(getConfig(), hostname
              + ":0");
          getConfig().set(JHAdminConfig.JHS_ADMIN_ADDRESS,
            hostname + ":0");
        }
        historyServer = new JobHistoryServer();
        historyServer.init(getConfig());
        new Thread() {
          public void run() {
            historyServer.start();
            jhsStarted = true;
          };
        }.start();

        while (!jhsStarted) {
          LOG.info("Waiting for HistoryServer to start...");
          Thread.sleep(1500);
        }
        //TODO Add a timeout. State.STOPPED check ?
        if (historyServer.getServiceState() != STATE.STARTED) {
          throw new IOException("HistoryServer failed to start");
        }
        super.serviceStart();
      } catch (Throwable t) {
        throw new YarnRuntimeException(t);
      }
    }

    @Override
    public synchronized void serviceStop() throws Exception {
      if (historyServer != null) {
        historyServer.stop();
      }
      super.serviceStop();
    }
  }

  public JobHistoryServer getHistoryServer() {
    return this.historyServer;
  }
}
