/// <exception cref="Org.Apache.Hadoop.Yarn.Exceptions.YarnException"/>
        /// <exception cref="System.IO.IOException"/>
        public virtual RegisterNodeManagerResponse RegisterNodeManager(RegisterNodeManagerRequest
                                                                       request)
        {
            NodeId   nodeId                      = request.GetNodeId();
            string   host                        = nodeId.GetHost();
            int      cmPort                      = nodeId.GetPort();
            int      httpPort                    = request.GetHttpPort();
            Resource capability                  = request.GetResource();
            string   nodeManagerVersion          = request.GetNMVersion();
            RegisterNodeManagerResponse response = recordFactory.NewRecordInstance <RegisterNodeManagerResponse
                                                                                    >();

            if (!minimumNodeManagerVersion.Equals("NONE"))
            {
                if (minimumNodeManagerVersion.Equals("EqualToRM"))
                {
                    minimumNodeManagerVersion = YarnVersionInfo.GetVersion();
                }
                if ((nodeManagerVersion == null) || (VersionUtil.CompareVersions(nodeManagerVersion
                                                                                 , minimumNodeManagerVersion)) < 0)
                {
                    string message = "Disallowed NodeManager Version " + nodeManagerVersion + ", is less than the minimum version "
                                     + minimumNodeManagerVersion + " sending SHUTDOWN signal to " + "NodeManager.";
                    Log.Info(message);
                    response.SetDiagnosticsMessage(message);
                    response.SetNodeAction(NodeAction.Shutdown);
                    return(response);
                }
            }
            // Check if this node is a 'valid' node
            if (!this.nodesListManager.IsValidNode(host))
            {
                string message = "Disallowed NodeManager from  " + host + ", Sending SHUTDOWN signal to the NodeManager.";
                Log.Info(message);
                response.SetDiagnosticsMessage(message);
                response.SetNodeAction(NodeAction.Shutdown);
                return(response);
            }
            // Check if this node has minimum allocations
            if (capability.GetMemory() < minAllocMb || capability.GetVirtualCores() < minAllocVcores)
            {
                string message = "NodeManager from  " + host + " doesn't satisfy minimum allocations, Sending SHUTDOWN"
                                 + " signal to the NodeManager.";
                Log.Info(message);
                response.SetDiagnosticsMessage(message);
                response.SetNodeAction(NodeAction.Shutdown);
                return(response);
            }
            response.SetContainerTokenMasterKey(containerTokenSecretManager.GetCurrentKey());
            response.SetNMTokenMasterKey(nmTokenSecretManager.GetCurrentKey());
            RMNode rmNode = new RMNodeImpl(nodeId, rmContext, host, cmPort, httpPort, Resolve
                                               (host), capability, nodeManagerVersion);
            RMNode oldNode = this.rmContext.GetRMNodes().PutIfAbsent(nodeId, rmNode);

            if (oldNode == null)
            {
                this.rmContext.GetDispatcher().GetEventHandler().Handle(new RMNodeStartedEvent(nodeId
                                                                                               , request.GetNMContainerStatuses(), request.GetRunningApplications()));
            }
            else
            {
                Log.Info("Reconnect from the node at: " + host);
                this.nmLivelinessMonitor.Unregister(nodeId);
                // Reset heartbeat ID since node just restarted.
                oldNode.ResetLastNodeHeartBeatResponse();
                this.rmContext.GetDispatcher().GetEventHandler().Handle(new RMNodeReconnectEvent(
                                                                            nodeId, rmNode, request.GetRunningApplications(), request.GetNMContainerStatuses
                                                                                ()));
            }
            // On every node manager register we will be clearing NMToken keys if
            // present for any running application.
            this.nmTokenSecretManager.RemoveNodeKey(nodeId);
            this.nmLivelinessMonitor.Register(nodeId);
            // Handle received container status, this should be processed after new
            // RMNode inserted
            if (!rmContext.IsWorkPreservingRecoveryEnabled())
            {
                if (!request.GetNMContainerStatuses().IsEmpty())
                {
                    Log.Info("received container statuses on node manager register :" + request.GetNMContainerStatuses
                                 ());
                    foreach (NMContainerStatus status in request.GetNMContainerStatuses())
                    {
                        HandleNMContainerStatus(status, nodeId);
                    }
                }
            }
            string message_1 = "NodeManager from node " + host + "(cmPort: " + cmPort + " httpPort: "
                               + httpPort + ") " + "registered with capability: " + capability + ", assigned nodeId "
                               + nodeId;

            Log.Info(message_1);
            response.SetNodeAction(NodeAction.Normal);
            response.SetRMIdentifier(ResourceManager.GetClusterTimeStamp());
            response.SetRMVersion(YarnVersionInfo.GetVersion());
            return(response);
        }