Example #1
0
            /// <exception cref="Org.Apache.Hadoop.Yarn.Exceptions.YarnException"/>
            protected internal override void SubmitApplication(ApplicationSubmissionContext submissionContext
                                                               , long submitTime, string user)
            {
                //Do nothing, just add the application to RMContext
                RMAppImpl application = new RMAppImpl(submissionContext.GetApplicationId(), this.
                                                      rmContext, this.conf, submissionContext.GetApplicationName(), user, submissionContext
                                                      .GetQueue(), submissionContext, this.rmContext.GetScheduler(), this.rmContext.GetApplicationMasterService
                                                          (), submitTime, submissionContext.GetApplicationType(), submissionContext.GetApplicationTags
                                                          (), null);

                this.rmContext.GetRMApps()[submissionContext.GetApplicationId()] = application;
            }
Example #2
0
        /// <exception cref="Org.Apache.Hadoop.Yarn.Exceptions.YarnException"/>
        private RMAppImpl CreateAndPopulateNewRMApp(ApplicationSubmissionContext submissionContext
                                                    , long submitTime, string user, bool isRecovery)
        {
            ApplicationId   applicationId = submissionContext.GetApplicationId();
            ResourceRequest amReq         = ValidateAndCreateResourceRequest(submissionContext, isRecovery
                                                                             );
            // Create RMApp
            RMAppImpl application = new RMAppImpl(applicationId, rmContext, this.conf, submissionContext
                                                  .GetApplicationName(), user, submissionContext.GetQueue(), submissionContext, this
                                                  .scheduler, this.masterService, submitTime, submissionContext.GetApplicationType
                                                      (), submissionContext.GetApplicationTags(), amReq);

            // Concurrent app submissions with same applicationId will fail here
            // Concurrent app submissions with different applicationIds will not
            // influence each other
            if (rmContext.GetRMApps().PutIfAbsent(applicationId, application) != null)
            {
                string message = "Application with id " + applicationId + " is already present! Cannot add a duplicate!";
                Log.Warn(message);
                throw new YarnException(message);
            }
            // Inform the ACLs Manager
            this.applicationACLsManager.AddApplication(applicationId, submissionContext.GetAMContainerSpec
                                                           ().GetApplicationACLs());
            string appViewACLs = submissionContext.GetAMContainerSpec().GetApplicationACLs()[
                ApplicationAccessType.ViewApp];

            rmContext.GetSystemMetricsPublisher().AppACLsUpdated(application, appViewACLs, Runtime
                                                                 .CurrentTimeMillis());
            return(application);
        }
Example #3
0
        /// <exception cref="System.Exception"/>
        protected internal virtual void RecoverApplication(ApplicationStateData appState,
                                                           RMStateStore.RMState rmState)
        {
            ApplicationSubmissionContext appContext = appState.GetApplicationSubmissionContext
                                                          ();
            ApplicationId appId = appContext.GetApplicationId();
            // create and recover app.
            RMAppImpl application = CreateAndPopulateNewRMApp(appContext, appState.GetSubmitTime
                                                                  (), appState.GetUser(), true);

            application.Handle(new RMAppRecoverEvent(appId, rmState));
        }
Example #4
0
        /// <exception cref="Org.Apache.Hadoop.Yarn.Exceptions.YarnException"/>
        protected internal virtual void SubmitApplication(ApplicationSubmissionContext submissionContext
                                                          , long submitTime, string user)
        {
            ApplicationId applicationId = submissionContext.GetApplicationId();
            RMAppImpl     application   = CreateAndPopulateNewRMApp(submissionContext, submitTime,
                                                                    user, false);
            ApplicationId appId = submissionContext.GetApplicationId();

            if (UserGroupInformation.IsSecurityEnabled())
            {
                try
                {
                    this.rmContext.GetDelegationTokenRenewer().AddApplicationAsync(appId, ParseCredentials
                                                                                       (submissionContext), submissionContext.GetCancelTokensWhenComplete(), application
                                                                                   .GetUser());
                }
                catch (Exception e)
                {
                    Log.Warn("Unable to parse credentials.", e);
                    // Sending APP_REJECTED is fine, since we assume that the
                    // RMApp is in NEW state and thus we haven't yet informed the
                    // scheduler about the existence of the application
                    System.Diagnostics.Debug.Assert(application.GetState() == RMAppState.New);
                    this.rmContext.GetDispatcher().GetEventHandler().Handle(new RMAppEvent(applicationId
                                                                                           , RMAppEventType.AppRejected, e.Message));
                    throw RPCUtil.GetRemoteException(e);
                }
            }
            else
            {
                // Dispatcher is not yet started at this time, so these START events
                // enqueued should be guaranteed to be first processed when dispatcher
                // gets started.
                this.rmContext.GetDispatcher().GetEventHandler().Handle(new RMAppEvent(applicationId
                                                                                       , RMAppEventType.Start));
            }
        }
Example #5
0
 /// <exception cref="Org.Apache.Hadoop.Yarn.Exceptions.InvalidResourceRequestException
 ///     "/>
 private ResourceRequest ValidateAndCreateResourceRequest(ApplicationSubmissionContext
                                                          submissionContext, bool isRecovery)
 {
     // Validation of the ApplicationSubmissionContext needs to be completed
     // here. Only those fields that are dependent on RM's configuration are
     // checked here as they have to be validated whether they are part of new
     // submission or just being recovered.
     // Check whether AM resource requirements are within required limits
     if (!submissionContext.GetUnmanagedAM())
     {
         ResourceRequest amReq = submissionContext.GetAMContainerResourceRequest();
         if (amReq == null)
         {
             amReq = BuilderUtils.NewResourceRequest(RMAppAttemptImpl.AmContainerPriority, ResourceRequest
                                                     .Any, submissionContext.GetResource(), 1);
         }
         // set label expression for AM container
         if (null == amReq.GetNodeLabelExpression())
         {
             amReq.SetNodeLabelExpression(submissionContext.GetNodeLabelExpression());
         }
         try
         {
             SchedulerUtils.NormalizeAndValidateRequest(amReq, scheduler.GetMaximumResourceCapability
                                                            (), submissionContext.GetQueue(), scheduler, isRecovery, rmContext);
         }
         catch (InvalidResourceRequestException e)
         {
             Log.Warn("RM app submission failed in validating AM resource request" + " for application "
                      + submissionContext.GetApplicationId(), e);
             throw;
         }
         SchedulerUtils.NormalizeRequest(amReq, scheduler.GetResourceCalculator(), scheduler
                                         .GetClusterResource(), scheduler.GetMinimumResourceCapability(), scheduler.GetMaximumResourceCapability
                                             (), scheduler.GetMinimumResourceCapability());
         return(amReq);
     }
     return(null);
 }
Example #6
0
        public virtual void Setup()
        {
            // start minicluster
            conf        = new YarnConfiguration();
            yarnCluster = new MiniYARNCluster(typeof(TestAMRMClient).FullName, nodeCount, 1,
                                              1);
            yarnCluster.Init(conf);
            yarnCluster.Start();
            NUnit.Framework.Assert.IsNotNull(yarnCluster);
            NUnit.Framework.Assert.AreEqual(Service.STATE.Started, yarnCluster.GetServiceState
                                                ());
            // start rm client
            yarnClient = (YarnClientImpl)YarnClient.CreateYarnClient();
            yarnClient.Init(conf);
            yarnClient.Start();
            NUnit.Framework.Assert.IsNotNull(yarnClient);
            NUnit.Framework.Assert.AreEqual(Service.STATE.Started, yarnClient.GetServiceState
                                                ());
            // get node info
            nodeReports = yarnClient.GetNodeReports(NodeState.Running);
            // submit new app
            ApplicationSubmissionContext appContext = yarnClient.CreateApplication().GetApplicationSubmissionContext
                                                          ();
            ApplicationId appId = appContext.GetApplicationId();

            // set the application name
            appContext.SetApplicationName("Test");
            // Set the priority for the application master
            Priority pri = Priority.NewInstance(0);

            appContext.SetPriority(pri);
            // Set the queue to which this application is to be submitted in the RM
            appContext.SetQueue("default");
            // Set up the container launch context for the application master
            ContainerLaunchContext amContainer = Org.Apache.Hadoop.Yarn.Util.Records.NewRecord
                                                 <ContainerLaunchContext>();

            appContext.SetAMContainerSpec(amContainer);
            // unmanaged AM
            appContext.SetUnmanagedAM(true);
            // Create the request to send to the applications manager
            SubmitApplicationRequest appRequest = Org.Apache.Hadoop.Yarn.Util.Records.NewRecord
                                                  <SubmitApplicationRequest>();

            appRequest.SetApplicationSubmissionContext(appContext);
            // Submit the application to the applications manager
            yarnClient.SubmitApplication(appContext);
            // wait for app to start
            int          iterationsLeft = 30;
            RMAppAttempt appAttempt     = null;

            while (iterationsLeft > 0)
            {
                ApplicationReport appReport = yarnClient.GetApplicationReport(appId);
                if (appReport.GetYarnApplicationState() == YarnApplicationState.Accepted)
                {
                    attemptId  = appReport.GetCurrentApplicationAttemptId();
                    appAttempt = yarnCluster.GetResourceManager().GetRMContext().GetRMApps()[attemptId
                                                                                             .GetApplicationId()].GetCurrentAppAttempt();
                    while (true)
                    {
                        if (appAttempt.GetAppAttemptState() == RMAppAttemptState.Launched)
                        {
                            break;
                        }
                    }
                    break;
                }
                Sleep(1000);
                --iterationsLeft;
            }
            if (iterationsLeft == 0)
            {
                NUnit.Framework.Assert.Fail("Application hasn't bee started");
            }
            // Just dig into the ResourceManager and get the AMRMToken just for the sake
            // of testing.
            UserGroupInformation.SetLoginUser(UserGroupInformation.CreateRemoteUser(UserGroupInformation
                                                                                    .GetCurrentUser().GetUserName()));
            UserGroupInformation.GetCurrentUser().AddToken(appAttempt.GetAMRMToken());
            //creating an instance NMTokenCase
            nmTokenCache = new NMTokenCache();
            // start am rm client
            rmClient = (AMRMClientImpl <AMRMClient.ContainerRequest>)AMRMClient.CreateAMRMClient
                       <AMRMClient.ContainerRequest>();
            //setting an instance NMTokenCase
            rmClient.SetNMTokenCache(nmTokenCache);
            rmClient.Init(conf);
            rmClient.Start();
            NUnit.Framework.Assert.IsNotNull(rmClient);
            NUnit.Framework.Assert.AreEqual(Service.STATE.Started, rmClient.GetServiceState()
                                            );
            // start am nm client
            nmClient = (NMClientImpl)NMClient.CreateNMClient();
            //propagating the AMRMClient NMTokenCache instance
            nmClient.SetNMTokenCache(rmClient.GetNMTokenCache());
            nmClient.Init(conf);
            nmClient.Start();
            NUnit.Framework.Assert.IsNotNull(nmClient);
            NUnit.Framework.Assert.AreEqual(Service.STATE.Started, nmClient.GetServiceState()
                                            );
        }
Example #7
0
 /// <exception cref="System.IO.IOException"/>
 /// <exception cref="Org.Apache.Hadoop.Yarn.Exceptions.YarnException"/>
 public virtual bool Run()
 {
     Log.Info("Starting Client");
     // Connect to ResourceManager
     rmClient.Start();
     try
     {
         // Create launch context for app master
         Log.Info("Setting up application submission context for ASM");
         ApplicationSubmissionContext appContext = rmClient.CreateApplication().GetApplicationSubmissionContext
                                                       ();
         ApplicationId appId = appContext.GetApplicationId();
         // set the application name
         appContext.SetApplicationName(appName);
         // Set the priority for the application master
         Priority pri = Org.Apache.Hadoop.Yarn.Util.Records.NewRecord <Priority>();
         pri.SetPriority(amPriority);
         appContext.SetPriority(pri);
         // Set the queue to which this application is to be submitted in the RM
         appContext.SetQueue(amQueue);
         // Set up the container launch context for the application master
         ContainerLaunchContext amContainer = Org.Apache.Hadoop.Yarn.Util.Records.NewRecord
                                              <ContainerLaunchContext>();
         appContext.SetAMContainerSpec(amContainer);
         // unmanaged AM
         appContext.SetUnmanagedAM(true);
         Log.Info("Setting unmanaged AM");
         // Submit the application to the applications manager
         Log.Info("Submitting application to ASM");
         rmClient.SubmitApplication(appContext);
         ApplicationReport appReport = MonitorApplication(appId, EnumSet.Of(YarnApplicationState
                                                                            .Accepted, YarnApplicationState.Killed, YarnApplicationState.Failed, YarnApplicationState
                                                                            .Finished));
         if (appReport.GetYarnApplicationState() == YarnApplicationState.Accepted)
         {
             // Monitor the application attempt to wait for launch state
             ApplicationAttemptReport attemptReport = MonitorCurrentAppAttempt(appId, YarnApplicationAttemptState
                                                                               .Launched);
             ApplicationAttemptId attemptId = attemptReport.GetApplicationAttemptId();
             Log.Info("Launching AM with application attempt id " + attemptId);
             // launch AM
             LaunchAM(attemptId);
             // Monitor the application for end state
             appReport = MonitorApplication(appId, EnumSet.Of(YarnApplicationState.Killed, YarnApplicationState
                                                              .Failed, YarnApplicationState.Finished));
         }
         YarnApplicationState   appState  = appReport.GetYarnApplicationState();
         FinalApplicationStatus appStatus = appReport.GetFinalApplicationStatus();
         Log.Info("App ended with state: " + appReport.GetYarnApplicationState() + " and status: "
                  + appStatus);
         bool success;
         if (YarnApplicationState.Finished == appState && FinalApplicationStatus.Succeeded
             == appStatus)
         {
             Log.Info("Application has completed successfully.");
             success = true;
         }
         else
         {
             Log.Info("Application did finished unsuccessfully." + " YarnState=" + appState.ToString
                          () + ", FinalStatus=" + appStatus.ToString());
             success = false;
         }
         return(success);
     }
     finally
     {
         rmClient.Stop();
     }
 }
Example #8
0
        /// <exception cref="Org.Apache.Hadoop.Yarn.Exceptions.YarnException"/>
        /// <exception cref="System.IO.IOException"/>
        public override ApplicationId SubmitApplication(ApplicationSubmissionContext appContext
                                                        )
        {
            ApplicationId applicationId = appContext.GetApplicationId();

            if (applicationId == null)
            {
                throw new ApplicationIdNotProvidedException("ApplicationId is not provided in ApplicationSubmissionContext"
                                                            );
            }
            SubmitApplicationRequest request = Org.Apache.Hadoop.Yarn.Util.Records.NewRecord <
                SubmitApplicationRequest>();

            request.SetApplicationSubmissionContext(appContext);
            // Automatically add the timeline DT into the CLC
            // Only when the security and the timeline service are both enabled
            if (IsSecurityEnabled() && timelineServiceEnabled)
            {
                AddTimelineDelegationToken(appContext.GetAMContainerSpec());
            }
            //TODO: YARN-1763:Handle RM failovers during the submitApplication call.
            rmClient.SubmitApplication(request);
            int  pollCount = 0;
            long startTime = Runtime.CurrentTimeMillis();
            EnumSet <YarnApplicationState> waitingStates = EnumSet.Of(YarnApplicationState.New
                                                                      , YarnApplicationState.NewSaving, YarnApplicationState.Submitted);
            EnumSet <YarnApplicationState> failToSubmitStates = EnumSet.Of(YarnApplicationState
                                                                           .Failed, YarnApplicationState.Killed);

            while (true)
            {
                try
                {
                    ApplicationReport    appReport = GetApplicationReport(applicationId);
                    YarnApplicationState state     = appReport.GetYarnApplicationState();
                    if (!waitingStates.Contains(state))
                    {
                        if (failToSubmitStates.Contains(state))
                        {
                            throw new YarnException("Failed to submit " + applicationId + " to YARN : " + appReport
                                                    .GetDiagnostics());
                        }
                        Log.Info("Submitted application " + applicationId);
                        break;
                    }
                    long elapsedMillis = Runtime.CurrentTimeMillis() - startTime;
                    if (EnforceAsyncAPITimeout() && elapsedMillis >= asyncApiPollTimeoutMillis)
                    {
                        throw new YarnException("Timed out while waiting for application " + applicationId
                                                + " to be submitted successfully");
                    }
                    // Notify the client through the log every 10 poll, in case the client
                    // is blocked here too long.
                    if (++pollCount % 10 == 0)
                    {
                        Log.Info("Application submission is not finished, " + "submitted application " +
                                 applicationId + " is still in " + state);
                    }
                    try
                    {
                        Sharpen.Thread.Sleep(submitPollIntervalMillis);
                    }
                    catch (Exception)
                    {
                        Log.Error("Interrupted while waiting for application " + applicationId + " to be successfully submitted."
                                  );
                    }
                }
                catch (ApplicationNotFoundException)
                {
                    // FailOver or RM restart happens before RMStateStore saves
                    // ApplicationState
                    Log.Info("Re-submit application " + applicationId + "with the " + "same ApplicationSubmissionContext"
                             );
                    rmClient.SubmitApplication(request);
                }
            }
            return(applicationId);
        }
Example #9
0
        /// <summary>Main run function for the client</summary>
        /// <returns>true if application completed successfully</returns>
        /// <exception cref="System.IO.IOException"/>
        /// <exception cref="Org.Apache.Hadoop.Yarn.Exceptions.YarnException"/>
        public virtual bool Run()
        {
            Log.Info("Running Client");
            yarnClient.Start();
            YarnClusterMetrics clusterMetrics = yarnClient.GetYarnClusterMetrics();

            Log.Info("Got Cluster metric info from ASM" + ", numNodeManagers=" + clusterMetrics
                     .GetNumNodeManagers());
            IList <NodeReport> clusterNodeReports = yarnClient.GetNodeReports(NodeState.Running
                                                                              );

            Log.Info("Got Cluster node info from ASM");
            foreach (NodeReport node in clusterNodeReports)
            {
                Log.Info("Got node report from ASM for" + ", nodeId=" + node.GetNodeId() + ", nodeAddress"
                         + node.GetHttpAddress() + ", nodeRackName" + node.GetRackName() + ", nodeNumContainers"
                         + node.GetNumContainers());
            }
            QueueInfo queueInfo = yarnClient.GetQueueInfo(this.amQueue);

            Log.Info("Queue info" + ", queueName=" + queueInfo.GetQueueName() + ", queueCurrentCapacity="
                     + queueInfo.GetCurrentCapacity() + ", queueMaxCapacity=" + queueInfo.GetMaximumCapacity
                         () + ", queueApplicationCount=" + queueInfo.GetApplications().Count + ", queueChildQueueCount="
                     + queueInfo.GetChildQueues().Count);
            IList <QueueUserACLInfo> listAclInfo = yarnClient.GetQueueAclsInfo();

            foreach (QueueUserACLInfo aclInfo in listAclInfo)
            {
                foreach (QueueACL userAcl in aclInfo.GetUserAcls())
                {
                    Log.Info("User ACL Info for Queue" + ", queueName=" + aclInfo.GetQueueName() + ", userAcl="
                             + userAcl.ToString());
                }
            }
            if (domainId != null && domainId.Length > 0 && toCreateDomain)
            {
                PrepareTimelineDomain();
            }
            // Get a new application id
            YarnClientApplication     app         = yarnClient.CreateApplication();
            GetNewApplicationResponse appResponse = app.GetNewApplicationResponse();
            // TODO get min/max resource capabilities from RM and change memory ask if needed
            // If we do not have min/max, we may not be able to correctly request
            // the required resources from the RM for the app master
            // Memory ask has to be a multiple of min and less than max.
            // Dump out information about cluster capability as seen by the resource manager
            int maxMem = appResponse.GetMaximumResourceCapability().GetMemory();

            Log.Info("Max mem capabililty of resources in this cluster " + maxMem);
            // A resource ask cannot exceed the max.
            if (amMemory > maxMem)
            {
                Log.Info("AM memory specified above max threshold of cluster. Using max value." +
                         ", specified=" + amMemory + ", max=" + maxMem);
                amMemory = maxMem;
            }
            int maxVCores = appResponse.GetMaximumResourceCapability().GetVirtualCores();

            Log.Info("Max virtual cores capabililty of resources in this cluster " + maxVCores
                     );
            if (amVCores > maxVCores)
            {
                Log.Info("AM virtual cores specified above max threshold of cluster. " + "Using max value."
                         + ", specified=" + amVCores + ", max=" + maxVCores);
                amVCores = maxVCores;
            }
            // set the application name
            ApplicationSubmissionContext appContext = app.GetApplicationSubmissionContext();
            ApplicationId appId = appContext.GetApplicationId();

            appContext.SetKeepContainersAcrossApplicationAttempts(keepContainers);
            appContext.SetApplicationName(appName);
            if (attemptFailuresValidityInterval >= 0)
            {
                appContext.SetAttemptFailuresValidityInterval(attemptFailuresValidityInterval);
            }
            // set local resources for the application master
            // local files or archives as needed
            // In this scenario, the jar file for the application master is part of the local resources
            IDictionary <string, LocalResource> localResources = new Dictionary <string, LocalResource
                                                                                 >();

            Log.Info("Copy App Master jar from local filesystem and add to local environment"
                     );
            // Copy the application master jar to the filesystem
            // Create a local resource to point to the destination jar path
            FileSystem fs = FileSystem.Get(conf);

            AddToLocalResources(fs, appMasterJar, appMasterJarPath, appId.ToString(), localResources
                                , null);
            // Set the log4j properties if needed
            if (!log4jPropFile.IsEmpty())
            {
                AddToLocalResources(fs, log4jPropFile, log4jPath, appId.ToString(), localResources
                                    , null);
            }
            // The shell script has to be made available on the final container(s)
            // where it will be executed.
            // To do this, we need to first copy into the filesystem that is visible
            // to the yarn framework.
            // We do not need to set this as a local resource for the application
            // master as the application master does not need it.
            string hdfsShellScriptLocation  = string.Empty;
            long   hdfsShellScriptLen       = 0;
            long   hdfsShellScriptTimestamp = 0;

            if (!shellScriptPath.IsEmpty())
            {
                Path   shellSrc        = new Path(shellScriptPath);
                string shellPathSuffix = appName + "/" + appId.ToString() + "/" + ScriptPath;
                Path   shellDst        = new Path(fs.GetHomeDirectory(), shellPathSuffix);
                fs.CopyFromLocalFile(false, true, shellSrc, shellDst);
                hdfsShellScriptLocation = shellDst.ToUri().ToString();
                FileStatus shellFileStatus = fs.GetFileStatus(shellDst);
                hdfsShellScriptLen       = shellFileStatus.GetLen();
                hdfsShellScriptTimestamp = shellFileStatus.GetModificationTime();
            }
            if (!shellCommand.IsEmpty())
            {
                AddToLocalResources(fs, null, shellCommandPath, appId.ToString(), localResources,
                                    shellCommand);
            }
            if (shellArgs.Length > 0)
            {
                AddToLocalResources(fs, null, shellArgsPath, appId.ToString(), localResources, StringUtils
                                    .Join(shellArgs, " "));
            }
            // Set the necessary security tokens as needed
            //amContainer.setContainerTokens(containerToken);
            // Set the env variables to be setup in the env where the application master will be run
            Log.Info("Set the environment for the application master");
            IDictionary <string, string> env = new Dictionary <string, string>();

            // put location of shell script into env
            // using the env info, the application master will create the correct local resource for the
            // eventual containers that will be launched to execute the shell scripts
            env[DSConstants.Distributedshellscriptlocation]  = hdfsShellScriptLocation;
            env[DSConstants.Distributedshellscripttimestamp] = System.Convert.ToString(hdfsShellScriptTimestamp
                                                                                       );
            env[DSConstants.Distributedshellscriptlen] = System.Convert.ToString(hdfsShellScriptLen
                                                                                 );
            if (domainId != null && domainId.Length > 0)
            {
                env[DSConstants.Distributedshelltimelinedomain] = domainId;
            }
            // Add AppMaster.jar location to classpath
            // At some point we should not be required to add
            // the hadoop specific classpaths to the env.
            // It should be provided out of the box.
            // For now setting all required classpaths including
            // the classpath to "." for the application jar
            StringBuilder classPathEnv = new StringBuilder(ApplicationConstants.Environment.Classpath
                                                           .$$()).Append(ApplicationConstants.ClassPathSeparator).Append("./*");

            foreach (string c in conf.GetStrings(YarnConfiguration.YarnApplicationClasspath,
                                                 YarnConfiguration.DefaultYarnCrossPlatformApplicationClasspath))
            {
                classPathEnv.Append(ApplicationConstants.ClassPathSeparator);
                classPathEnv.Append(c.Trim());
            }
            classPathEnv.Append(ApplicationConstants.ClassPathSeparator).Append("./log4j.properties"
                                                                                );
            // add the runtime classpath needed for tests to work
            if (conf.GetBoolean(YarnConfiguration.IsMiniYarnCluster, false))
            {
                classPathEnv.Append(':');
                classPathEnv.Append(Runtime.GetProperty("java.class.path"));
            }
            env["CLASSPATH"] = classPathEnv.ToString();
            // Set the necessary command to execute the application master
            Vector <CharSequence> vargs = new Vector <CharSequence>(30);

            // Set java executable command
            Log.Info("Setting up app master command");
            vargs.AddItem(ApplicationConstants.Environment.JavaHome.$$() + "/bin/java");
            // Set Xmx based on am memory size
            vargs.AddItem("-Xmx" + amMemory + "m");
            // Set class name
            vargs.AddItem(appMasterMainClass);
            // Set params for Application Master
            vargs.AddItem("--container_memory " + containerMemory.ToString());
            vargs.AddItem("--container_vcores " + containerVirtualCores.ToString());
            vargs.AddItem("--num_containers " + numContainers.ToString());
            if (null != nodeLabelExpression)
            {
                appContext.SetNodeLabelExpression(nodeLabelExpression);
            }
            vargs.AddItem("--priority " + shellCmdPriority.ToString());
            foreach (KeyValuePair <string, string> entry in shellEnv)
            {
                vargs.AddItem("--shell_env " + entry.Key + "=" + entry.Value);
            }
            if (debugFlag)
            {
                vargs.AddItem("--debug");
            }
            vargs.AddItem("1>" + ApplicationConstants.LogDirExpansionVar + "/AppMaster.stdout"
                          );
            vargs.AddItem("2>" + ApplicationConstants.LogDirExpansionVar + "/AppMaster.stderr"
                          );
            // Get final commmand
            StringBuilder command = new StringBuilder();

            foreach (CharSequence str in vargs)
            {
                command.Append(str).Append(" ");
            }
            Log.Info("Completed setting up app master command " + command.ToString());
            IList <string> commands = new AList <string>();

            commands.AddItem(command.ToString());
            // Set up the container launch context for the application master
            ContainerLaunchContext amContainer = ContainerLaunchContext.NewInstance(localResources
                                                                                    , env, commands, null, null, null);
            // Set up resource type requirements
            // For now, both memory and vcores are supported, so we set memory and
            // vcores requirements
            Resource capability = Resource.NewInstance(amMemory, amVCores);

            appContext.SetResource(capability);
            // Service data is a binary blob that can be passed to the application
            // Not needed in this scenario
            // amContainer.setServiceData(serviceData);
            // Setup security tokens
            if (UserGroupInformation.IsSecurityEnabled())
            {
                // Note: Credentials class is marked as LimitedPrivate for HDFS and MapReduce
                Credentials credentials  = new Credentials();
                string      tokenRenewer = conf.Get(YarnConfiguration.RmPrincipal);
                if (tokenRenewer == null || tokenRenewer.Length == 0)
                {
                    throw new IOException("Can't get Master Kerberos principal for the RM to use as renewer"
                                          );
                }
                // For now, only getting tokens for the default file-system.
                Org.Apache.Hadoop.Security.Token.Token <object>[] tokens = fs.AddDelegationTokens(
                    tokenRenewer, credentials);
                if (tokens != null)
                {
                    foreach (Org.Apache.Hadoop.Security.Token.Token <object> token in tokens)
                    {
                        Log.Info("Got dt for " + fs.GetUri() + "; " + token);
                    }
                }
                DataOutputBuffer dob = new DataOutputBuffer();
                credentials.WriteTokenStorageToStream(dob);
                ByteBuffer fsTokens = ByteBuffer.Wrap(dob.GetData(), 0, dob.GetLength());
                amContainer.SetTokens(fsTokens);
            }
            appContext.SetAMContainerSpec(amContainer);
            // Set the priority for the application master
            // TODO - what is the range for priority? how to decide?
            Priority pri = Priority.NewInstance(amPriority);

            appContext.SetPriority(pri);
            // Set the queue to which this application is to be submitted in the RM
            appContext.SetQueue(amQueue);
            // Submit the application to the applications manager
            // SubmitApplicationResponse submitResp = applicationsManager.submitApplication(appRequest);
            // Ignore the response as either a valid response object is returned on success
            // or an exception thrown to denote some form of a failure
            Log.Info("Submitting application to ASM");
            yarnClient.SubmitApplication(appContext);
            // TODO
            // Try submitting the same request again
            // app submission failure?
            // Monitor the application
            return(MonitorApplication(appId));
        }