/// <summary>UpdateInstallationStatus
        /// Restart System if after installation restart is required.
        /// </summary>
        public void HandleRestart()
        {
            TimeSpan utilityTaskTimeOut = TimeSpan.FromMinutes(this._serviceSettings.OperationTimeOutInMinutes);

            NodeAgentSfUtilityExitCodes wuOperationState = this._nodeAgentSfUtility.GetWuOperationState(utilityTaskTimeOut);

            _eventSource.InfoMessage("Handling restart. Current WU Operation State : {0}.", wuOperationState);

            switch (wuOperationState)
            {
            case NodeAgentSfUtilityExitCodes.InstallationCompleted:
                this._nodeAgentSfUtility.UpdateInstallationStatus(NodeAgentSfUtilityExitCodes.RestartRequested, null, utilityTaskTimeOut);
                this.RestartSystem();
                break;

            case NodeAgentSfUtilityExitCodes.RestartRequested:
                this.RestartSystem();
                break;

            case NodeAgentSfUtilityExitCodes.OperationCompleted:
                break;

            default:
                _eventSource.ErrorMessage("Invalid state : {0}", wuOperationState);
                break;
            }
        }
        /// <summary>
        /// Changes the state machine state to Completed.
        /// </summary>
        public void CompleteWUOperations()
        {
            TimeSpan utilityTaskTimeOut = TimeSpan.FromMinutes(this._serviceSettings.OperationTimeOutInMinutes);
            NodeAgentSfUtilityExitCodes wuOperationState = this._nodeAgentSfUtility.GetWuOperationState(utilityTaskTimeOut);

            _eventSource.InfoMessage("Completing Wu Operation. Current state: {0}", wuOperationState);

            switch (wuOperationState)
            {
            case NodeAgentSfUtilityExitCodes.InstallationCompleted:
            case NodeAgentSfUtilityExitCodes.RestartNotNeeded:
            case NodeAgentSfUtilityExitCodes.RestartCompleted:
                this._nodeAgentSfUtility.UpdateInstallationStatus(
                    NodeAgentSfUtilityExitCodes.OperationCompleted,
                    null,
                    utilityTaskTimeOut);
                break;

            case NodeAgentSfUtilityExitCodes.OperationCompleted:
                break;

            default:
                _eventSource.WarningMessage("Invalid WU state : " + wuOperationState);
                break;
            }
        }
        /// <summary>UpdateInstallationStatus
        /// Restart System if after installation restart is required.
        /// </summary>
        public void HandleRestart()
        {
            TimeSpan utilityTaskTimeOut = TimeSpan.FromMinutes(this._serviceSettings.OperationTimeOutInMinutes);

            NodeAgentSfUtilityExitCodes wuOperationState = this._nodeAgentSfUtility.GetWuOperationState(utilityTaskTimeOut);

            _eventSource.InfoMessage("Handling restart. Current WU Operation State : {0}.", wuOperationState);
            string systemRestartDescription = "Installation attempted, now trying to restart the node.";

            switch (wuOperationState)
            {
            case NodeAgentSfUtilityExitCodes.InstallationCompleted:
                this._nodeAgentSfUtility.UpdateInstallationStatus(NodeAgentSfUtilityExitCodes.RestartRequested, null, utilityTaskTimeOut);
                this._nodeAgentSfUtility.ReportHealth(WUOperationStatus, systemRestartDescription, HealthState.Ok, -1, TimeSpan.FromMinutes(this._serviceSettings.OperationTimeOutInMinutes));
                this.RestartSystem();
                break;

            case NodeAgentSfUtilityExitCodes.RestartRequested:
                this._nodeAgentSfUtility.ReportHealth(WUOperationStatus, systemRestartDescription, HealthState.Ok, -1, TimeSpan.FromMinutes(this._serviceSettings.OperationTimeOutInMinutes));
                this.RestartSystem();
                break;

            case NodeAgentSfUtilityExitCodes.OperationCompleted:
                break;

            default:
                _eventSource.ErrorMessage("Invalid state : {0}", wuOperationState);
                break;
            }
        }
        /// <summary>
        /// Resets the state machine.
        /// </summary>
        /// <returns></returns>
        public bool ResetStateMachine()
        {
            _eventSource.InfoMessage("Resetting State Machine.");
            TimeSpan utilityTaskTimeOut = TimeSpan.FromMinutes(this._serviceSettings.OperationTimeOutInMinutes);

            try
            {
                NodeAgentSfUtilityExitCodes wuOperationState =
                    this._nodeAgentSfUtility.GetWuOperationState(utilityTaskTimeOut);
                switch (wuOperationState)
                {
                case NodeAgentSfUtilityExitCodes.None:
                    break;

                case NodeAgentSfUtilityExitCodes.DownloadCompleted:
                    this._nodeAgentSfUtility.UpdateSearchAndDownloadStatus(NodeAgentSfUtilityExitCodes.OperationAborted, null, utilityTaskTimeOut);
                    break;

                default:
                    this._nodeAgentSfUtility.UpdateInstallationStatus(NodeAgentSfUtilityExitCodes.OperationCompleted, null, utilityTaskTimeOut);
                    break;
                }
                return(true);
            }
            catch (Exception e)
            {
                _eventSource.ErrorMessage("Not able to reset state machine. exception : {0}", e);
                return(false);
            }
        }
        /// <summary>
        /// Utility to Report health for the NodeAgentService. Typical usecases are as below
        /// If windows update operation is not successful after exhausting all reties, user can post warning level health report
        /// If windows update operation is successfull, user can post Ok level health report.
        /// </summary>
        /// <param name="applicationName">Application name for constructing the servicename</param>
        /// <param name="healthProperty">Title for health report. Once the health report is set, any future updates should be done using same healthProperty.</param>
        /// <param name="healthDescription">Description of the health. In case of failure a good description is very helpful for quick mitigation.</param>
        /// <param name="healthState"><see cref="HealthState"/>Indicating the severity of the health report</param>
        /// <param name="timeToLiveInMinutes">Time to live for health report in the health manager in minutes. Default value is -1 indicating infinite time to live, any positive value indicates </param>
        /// <param name="timeout">Timeout for the async operation</param>
        /// <param name="cancellationToken">Cancellation token to cancel this async operation</param>
        /// <returns>Operation result in <see cref="NodeAgentSfUtilityExitCodes"/></returns>
        public NodeAgentSfUtilityExitCodes ReportHealth(Uri applicationName, String healthProperty, String healthDescription, HealthState healthState,
                                                        long timeToLiveInMinutes, TimeSpan timeout, CancellationToken cancellationToken)
        {
            NodeAgentSfUtilityExitCodes result = HealthManagerHelper.PostServiceHealthReport(this.fabricClient, applicationName, ServiceNameSuffix, healthProperty, healthDescription, (System.Fabric.Health.HealthState)healthState, timeout, timeToLiveInMinutes);

            ServiceEventSource.Current.InfoMessage("CommandProcessor.ReportHealth returned {0}", result);
            return(result);
        }
        public ExecutorDataForNtService GetExecutorDataForNtService()
        {
            string executorDataForNtServiceFilePath = Path.Combine(this._settingsManager.WorkFolder, ExecutorDataForNtServiceFileName);

            _eventSource.InfoMessage("Retrieving Executor data from {0}", executorDataForNtServiceFilePath);

            NodeAgentSfUtilityExitCodes exitCode = GetWuOperationState(TimeSpan.FromMinutes(this._serviceSettings.OperationTimeOutInMinutes));

            return(SerializationUtility.DeserializeFromFile <ExecutorDataForNtService>(executorDataForNtServiceFilePath));
        }
        /// <summary>
        /// Gets the application status of a deployed application
        /// </summary>
        /// <param name="applicationName">Uri of the application to be queried.</param>
        /// <param name="timeout">Timeout for the async operation</param>
        /// <param name="cancellationToken">The cancellation token to cancel the async operation</param>
        /// <returns>A Task representing the asnyc operation, result of the task would be
        ///  <see cref="NodeAgentSfUtilityExitCodes.Success"/> in case applicaiton exists,
        ///  <see cref="NodeAgentSfUtilityExitCodes.ApplicationNotFound"/> in case applicaiton doesn't exists
        /// </returns>
        public async Task <NodeAgentSfUtilityExitCodes> GetApplicationDeployedStatusAsync(Uri applicationName,
                                                                                          TimeSpan timeout, CancellationToken cancellationToken)
        {
            NodeAgentSfUtilityExitCodes result = await
                                                 CoordinatorServiceHelper.GetApplicationDeployedStatusAsync(this.fabricClient, applicationName,
                                                                                                            timeout, cancellationToken);

            ServiceEventSource.Current.InfoMessage("CommandProcessor.GetApplicationDeployedStatusAsync returned {0}", result);
            return(result);
        }
Exemple #8
0
        /// <summary>
        /// Update the status of Search and Download operation
        /// </summary>
        /// <param name="nodeName">name of service fabric node</param>
        /// <param name="updateState">State of Wu operation, possible values are InstallationInProgress, InstallationCompleted, RestartRequested, RestartNotNeeded, OperationCompleted</param>
        /// <param name="operationResult">result of the install operation, can be null in case no results are there to be updated</param>
        /// <returns>true if operation is success else false.</returns>
        public bool UpdateSearchAndDownloadStatus(NodeAgentSfUtilityExitCodes updateState, WindowsUpdateOperationResult operationResult = null, TimeSpan timeout = default(TimeSpan))
        {
            _eventSource.InfoMessage("Updating search and download  status : updateState : {0}, operationResult : {1}, timeout : {2}", updateState, operationResult, timeout);
            this.ReportCurrentNodeStatus(operationResult);
            string filePath = Path.Combine(this._settingsManager.TempFolder, OperationResultFileName);

            string[] arguments;

            if (operationResult != null)
            {
                operationResult.Serialize(filePath);
                arguments = new string[]
                { "UpdateSearchAndDownloadStatus", this._nodeName, this._applicationUri.ToString(), updateState.ToString(), this._serviceSettings.WUOperationTimeOutInMinutes.ToString(), timeout.TotalSeconds.ToString(), filePath };
            }
            else
            {
                arguments = new string[]
                { "UpdateSearchAndDownloadStatus", this._nodeName, this._applicationUri.ToString(), updateState.ToString(), this._serviceSettings.WUOperationTimeOutInMinutes.ToString(), timeout.TotalSeconds.ToString() };
            }

            ProcessExecutor processExecutor = new ProcessExecutor(SfUtilityFileName, CreateProcessArgument(arguments));

            long retries = 0;

            while (!this._cancellationToken.IsCancellationRequested)
            {
                if (processExecutor.Execute() == 0)
                {
                    return(true);
                }
                if (retries >= this._serviceSettings.WUOperationRetryCount || this._cancellationToken.IsCancellationRequested)
                {
                    break;
                }

                TimeSpan retryDelayTime = TimeSpan.FromMinutes(this._serviceSettings.WUDelayBetweenRetriesInMinutes);
                this._helper.WaitOnTask(Task.Delay(retryDelayTime), this._cancellationToken);
                retries++;
            }
            throw new Exception("Not able to update Search/download status.");
        }
        private NodeAgentSfUtilityExitCodes WaitForInstallationApproval(CancellationToken cancellationToken)
        {
            _eventSource.InfoMessage("Waiting for Installation approval.");
            while (!cancellationToken.IsCancellationRequested)
            {
                NodeAgentSfUtilityExitCodes wuOperationState = this._nodeAgentSfUtility.GetWuOperationState(TimeSpan.FromMinutes(this._serviceSettings.OperationTimeOutInMinutes));

                if (wuOperationState.Equals(NodeAgentSfUtilityExitCodes.InstallationApproved))
                {
                    _eventSource.InfoMessage("Installation Approved.");
                    return(wuOperationState);
                }
                else if (wuOperationState.Equals(NodeAgentSfUtilityExitCodes.OperationCompleted) || wuOperationState.Equals(NodeAgentSfUtilityExitCodes.None))
                {
                    _eventSource.InfoMessage("Installation Approval failed.");
                    return(NodeAgentSfUtilityExitCodes.Failure);
                }
                this._helper.WaitOnTask(Task.Delay(TimeSpan.FromMinutes(this._serviceSettings.WUDelayBetweenRetriesInMinutes)), cancellationToken);
            }
            _eventSource.InfoMessage("Installation Approval failed.");
            return(NodeAgentSfUtilityExitCodes.Failure);
        }
        /// <summary>
        /// Updates the status of search and download operation in CoordinatorService's repliable store
        /// And updates the RepairTask with appropriate state as per the updateState provided
        /// </summary>
        /// <param name="nodeName">Name of current service fabric node</param>
        /// <param name="applicationName">Uri of the Patch Orchestration Application.</param>
        /// <param name="updateState">State of Wu operation, possible values are DownloadAvailable, DownloadCompleted, OperationCompleted</param>
        /// <param name="operationResult">result of the search and download operation, cannot be null</param>
        /// <param name="installationTimeout">Amount of time a node can undergo installation, during installation node would be in disabled state</param>
        /// <param name="timeout">Timeout for the async operation</param>
        /// <param name="cancellationToken">The cancellation token to cancel the async operation</param>
        /// <returns>Task containing result of operation, true for success, false for failure</returns>
        /// <returns>
        /// A Task representing the asnyc operation, result of the task would be <see cref="NodeAgentSfUtilityExitCodes.Success"/> in case of success
        /// Any other <see cref="NodeAgentSfUtilityExitCodes"/> in case of failure
        /// </returns>
        public async Task <NodeAgentSfUtilityExitCodes> UpdateSearchAndDownloadStatusAsync(String nodeName, Uri applicationName,
                                                                                           NodeAgentSfUtilityExitCodes updateState, WindowsUpdateOperationResult operationResult, int installationTimeout, TimeSpan timeout, CancellationToken cancellationToken)
        {
            String taskDescription = null;
            String resultDetails   = null;
            NodeAgentSfUtilityExitCodes result;
            ExecutorDataForRmTask       executorData = new ExecutorDataForRmTask()
            {
                ExecutorSubState         = updateState,
                ExecutorTimeoutInMinutes = installationTimeout
            };

            if (null != operationResult)
            {
                int succeededOperations;
                int abortedOperations;
                int totalOperations;

                this.GetWuOperationResultCount(operationResult, out totalOperations, out abortedOperations,
                                               out succeededOperations);

                result = await
                         CoordinatorServiceHelper.UpdateWuOperationResult(
                    this.fabricClient,
                    applicationName,
                    operationResult,
                    timeout,
                    cancellationToken);

                if (result != NodeAgentSfUtilityExitCodes.Success)
                {
                    return(result);
                }

                taskDescription =
                    String.Format(
                        "{0} updates successfully downloaded on {1}. Creating this repair task to install the downloaded updates",
                        succeededOperations, operationResult.OperationTime);
                resultDetails =
                    String.Format("{0} updates searched. {1} downloaded successfully, {2} downloads were aborted",
                                  operationResult.UpdateDetails.Count, succeededOperations, abortedOperations);
            }

            switch (updateState)
            {
            case NodeAgentSfUtilityExitCodes.DownloadCompleted:
            {
                result = await
                         RepairManagerHelper.CreateRepairTaskForNode(
                    this.fabricClient,
                    nodeName,
                    taskDescription,
                    resultDetails,
                    executorData,
                    timeout,
                    cancellationToken);

                break;
            }

            case NodeAgentSfUtilityExitCodes.OperationCompleted:
            {
                result = NodeAgentSfUtilityExitCodes.Success;
                break;
            }

            case NodeAgentSfUtilityExitCodes.OperationAborted:
            {
                ServiceEventSource.Current.InfoMessage(String.Format("Operation aborted for a claimed task"));
                result = await RepairManagerHelper.UpdateRepairTask(this.fabricClient, nodeName,
                                                                    RepairTaskState.Completed, RepairTaskResult.Failed,
                                                                    "Aborting the operation", updateState, timeout, cancellationToken);

                break;
            }

            default:
            {
                ServiceEventSource.Current.ErrorMessage(
                    String.Format("UpdateSearchAndDownloadStatusAsync called with invalid state {0}", updateState));
                result = NodeAgentSfUtilityExitCodes.InvalidArgument;
                break;
            }
            }

            ServiceEventSource.Current.InfoMessage("UpdateSearchAndDownloadStatusAsync result = {0}", result);
            return(result);
        }
Exemple #11
0
        /// <summary>
        /// Updates the repair task for current node
        /// </summary>
        /// <param name="fc">Fabric client object used for carrying out service fabric client requests</param>
        /// <param name="nodeName">Nodename against which repair task needs to be updated</param>
        /// <param name="taskState">State of the repair task <see cref="RepairTaskState"/></param>
        /// <param name="taskResultStatus">Result status for last completed operation by RE</param>
        /// <param name="resultDetails">Result details for last completed operation by RE</param>
        /// <param name="executorState">Substate of repair executor</param>
        /// <param name="timeout">Timeout for the async operation</param>
        /// <param name="cancellationToken">The cancellation token to cancel the async operation</param>
        /// <param name="restartRequesteDateTime">Timestamp at which restart was requested</param>
        /// <returns>A Task representing the asnyc operation</returns>
        internal static async Task <NodeAgentSfUtilityExitCodes> UpdateRepairTask(FabricClient fc, string nodeName,
                                                                                  RepairTaskState taskState,
                                                                                  RepairTaskResult taskResultStatus, string resultDetails, NodeAgentSfUtilityExitCodes executorState,
                                                                                  TimeSpan timeout,
                                                                                  CancellationToken cancellationToken, DateTime?restartRequesteDateTime)
        {
            try
            {
                var repairTask = await GetRepairTaskForNode(fc, nodeName, timeout, cancellationToken);

                if (null != repairTask)
                {
                    await
                    UpdateRepairTask(fc, repairTask, taskState, taskResultStatus, resultDetails, executorState,
                                     timeout,
                                     cancellationToken, restartRequesteDateTime);

                    return(NodeAgentSfUtilityExitCodes.Success);
                }
                else
                {
                    // If repair task does not exist we're in a unknown state.
                    ServiceEventSource.Current.ErrorMessage(
                        String.Format("RepairManagerHelper.UpdateRepairTask failed. No repair task found for this node"));
                    return(NodeAgentSfUtilityExitCodes.RepairTaskInvalidState);
                }
            }
            catch (Exception e)
            {
                ServiceEventSource.Current.ErrorMessage(
                    String.Format("RepairManagerHelper.UpdateRepairTask failed. Exception details {0}", e));
                if (e is FabricTransientException)
                {
                    return(NodeAgentSfUtilityExitCodes.RetryableException);
                }
                else
                {
                    return(NodeAgentSfUtilityExitCodes.Failure);
                }
            }
        }
Exemple #12
0
 /// <summary>
 /// Updates the repair task for current node
 /// </summary>
 /// <param name="fc">Fabric client object used for carrying out service fabric client requests</param>
 /// <param name="nodeName">Nodename against which repair task needs to be updated</param>
 /// <param name="taskState">State of the repair task <see cref="RepairTaskState"/></param>
 /// <param name="taskResultStatus">Result status for last completed operation by RE</param>
 /// <param name="resultDetails">Result details for last completed operation by RE</param>
 /// <param name="executorState">Substate of repair executor</param>
 /// <param name="timeout">Timeout for the async operation</param>
 /// <param name="cancellationToken">The cancellation token to cancel the async operation</param>
 /// <returns>A Task representing the asnyc operation</returns>
 internal static async Task <NodeAgentSfUtilityExitCodes> UpdateRepairTask(FabricClient fc, string nodeName,
                                                                           RepairTaskState taskState,
                                                                           RepairTaskResult taskResultStatus, string resultDetails, NodeAgentSfUtilityExitCodes executorState,
                                                                           TimeSpan timeout,
                                                                           CancellationToken cancellationToken)
 {
     return(await
            UpdateRepairTask(fc, nodeName, taskState, taskResultStatus, resultDetails, executorState,
                             timeout,
                             cancellationToken, null));
 }
Exemple #13
0
        /// <summary>
        /// Updates the repair task for current node
        /// </summary>
        /// <param name="fc">Fabric client object used for carrying out service fabric client requests</param>
        /// <param name="task">Repair task which needs to be updated</param>
        /// <param name="taskState">State of the repair task <see cref="RepairTaskState"/></param>
        /// <param name="taskResultStatus">Result status for last completed operation by RE</param>
        /// <param name="resultDetails">Result details for last completed operation by RE</param>
        /// <param name="executorState">Substate of repair executor</param>
        /// <param name="timeout">Timeout for the async operation</param>
        /// <param name="cancellationToken">The cancellation token to cancel the async operation</param>
        /// <returns>A Task representing the asnyc operation</returns>
        private static async Task UpdateRepairTask(FabricClient fc, RepairTask task, RepairTaskState taskState,
                                                   RepairTaskResult taskResultStatus, string resultDetails, NodeAgentSfUtilityExitCodes executorState, TimeSpan timeout,
                                                   CancellationToken cancellationToken, DateTime?restartRequesteDateTime)
        {
            // Do the actual work before mark the task as Executing.
            task.State         = taskState;
            task.ResultStatus  = taskResultStatus;
            task.ResultDetails = resultDetails;
            ExecutorDataForRmTask executorData =
                SerializationUtility.Deserialize <ExecutorDataForRmTask>(task.ExecutorData);

            executorData.ExecutorSubState = executorState;
            if (restartRequesteDateTime.HasValue)
            {
                executorData.RestartRequestedTime = restartRequesteDateTime.Value;
            }

            task.ExecutorData = SerializationUtility.Serialize(executorData);
            await fc.RepairManager.UpdateRepairExecutionStateAsync(task, timeout, cancellationToken);
        }
        /// <summary>
        /// Update the status of installation operation in Coordinator Service's Relaible store
        /// Also update the status of repair task as per the updateState provided
        /// </summary>
        /// <param name="nodeName">Name of the service fabric node</param>
        /// <param name="applicationName">Uri of the Patch Orchestration Application.</param>
        /// <param name="updateState">State of Wu operation, possible values are InstallationInProgress, InstallationCompleted, RestartRequested, RestartNotNeeded, OperationCompleted</param>
        /// <param name="operationResult">result of the install operation, can be null in case no results are there to be updated</param>
        /// <param name="timeout">Timeout for the async operation</param>
        /// <param name="cancellationToken">The cancellation token to cancel the async operation</param>
        /// <returns>
        /// A Task representing the asnyc operation, result of the task would be <see cref="NodeAgentSfUtilityExitCodes.Success"/> in case of success
        /// Any other <see cref="NodeAgentSfUtilityExitCodes"/> in case of failure
        /// </returns>
        public async Task <NodeAgentSfUtilityExitCodes> UpdateInstallationStatusAsync(String nodeName, Uri applicationName,
                                                                                      NodeAgentSfUtilityExitCodes updateState, WindowsUpdateOperationResult operationResult,
                                                                                      TimeSpan timeout, CancellationToken cancellationToken)
        {
            NodeAgentSfUtilityExitCodes result;
            String resultDetails = null;

            if (operationResult != null)
            {
                int succeededOperations;
                int abortedOperations;
                int totalOperations;
                this.GetWuOperationResultCount(operationResult, out totalOperations, out abortedOperations, out succeededOperations);

                result =
                    await
                    CoordinatorServiceHelper.UpdateWuOperationResult(
                        this.fabricClient,
                        applicationName,
                        operationResult,
                        timeout,
                        cancellationToken);

                if (result != NodeAgentSfUtilityExitCodes.Success)
                {
                    return(result);
                }

                resultDetails =
                    String.Format(
                        "{0} out of {1} updates were installed successfully, {2} were aborted",
                        succeededOperations,
                        operationResult.UpdateDetails.Count,
                        abortedOperations);
            }

            switch (updateState)
            {
            case NodeAgentSfUtilityExitCodes.InstallationCompleted:
            {
                result =
                    await
                    RepairManagerHelper.UpdateRepairTask(
                        this.fabricClient,
                        nodeName,
                        RepairTaskState.Executing,
                        RepairTaskResult.Pending,
                        resultDetails,
                        NodeAgentSfUtilityExitCodes.InstallationCompleted,
                        timeout,
                        cancellationToken);

                break;
            }

            case NodeAgentSfUtilityExitCodes.InstallationInProgress:
            {
                result = await
                         RepairManagerHelper.UpdateRepairTask(this.fabricClient, nodeName,
                                                              RepairTaskState.Executing, RepairTaskResult.Pending, resultDetails, NodeAgentSfUtilityExitCodes.InstallationInProgress, timeout,
                                                              cancellationToken);

                break;
            }

            case NodeAgentSfUtilityExitCodes.RestartRequested:
            {
                resultDetails = "Installation of the updates completed, Restart pending";
                result        = await RepairManagerHelper.UpdateRepairTask(this.fabricClient, nodeName,
                                                                           RepairTaskState.Executing, RepairTaskResult.Pending,
                                                                           resultDetails, NodeAgentSfUtilityExitCodes.RestartRequested, timeout, cancellationToken, DateTime.UtcNow);

                break;
            }

            case NodeAgentSfUtilityExitCodes.RestartNotNeeded:
            {
                resultDetails = "Installation of the updates completed, Restart not needed";
                result        = await RepairManagerHelper.UpdateRepairTask(this.fabricClient, nodeName,
                                                                           RepairTaskState.Executing, RepairTaskResult.Pending,
                                                                           resultDetails, NodeAgentSfUtilityExitCodes.RestartNotNeeded, timeout, cancellationToken);

                break;
            }

            case NodeAgentSfUtilityExitCodes.RestartCompleted:
            {
                resultDetails = "Installation of the updates completed, Restart post installation completed successfully";
                result        = await RepairManagerHelper.UpdateRepairTask(this.fabricClient, nodeName,
                                                                           RepairTaskState.Executing, RepairTaskResult.Pending,
                                                                           resultDetails, NodeAgentSfUtilityExitCodes.RestartCompleted, timeout, cancellationToken);

                break;
            }

            case NodeAgentSfUtilityExitCodes.OperationCompleted:
            {
                ServiceEventSource.Current.InfoMessage(String.Format("Mark the operation as completed"));
                result = await RepairManagerHelper.UpdateRepairTask(this.fabricClient, nodeName,
                                                                    RepairTaskState.Restoring, RepairTaskResult.Succeeded,
                                                                    resultDetails, NodeAgentSfUtilityExitCodes.OperationCompleted, timeout, cancellationToken);

                break;
            }

            default:
            {
                ServiceEventSource.Current.ErrorMessage(String.Format("UpdateInstallationStatusAsync called with invalid state {0}", updateState));
                result = NodeAgentSfUtilityExitCodes.InvalidArgument;
                break;
            }
            }

            ServiceEventSource.Current.InfoMessage("UpdateInstallationStatusAsync result = {0}", result);
            return(result);
        }
        private bool HandleWUOperationStates(CancellationToken cancellationToken)
        {
            TimeSpan utilityTaskTimeOut = TimeSpan.FromMinutes(this._serviceSettings.OperationTimeOutInMinutes);
            NodeAgentSfUtilityExitCodes wuOperationState = this._nodeAgentSfUtility.GetWuOperationState(utilityTaskTimeOut);

            _eventSource.InfoMessage("Current WU Operation State : {0}", wuOperationState);

            bool reschedule = false;

            switch (wuOperationState)
            {
            case NodeAgentSfUtilityExitCodes.None:
            case NodeAgentSfUtilityExitCodes.OperationCompleted:
            {
                OperationResultCode searchResult = SearchUpdates(cancellationToken);
                reschedule = (searchResult != OperationResultCode.orcSucceeded ? true : reschedule);

                if (this._wuCollectionWrapper != null)
                {
                    if (this._wuCollectionWrapper.Collection.Count == 0)
                    {
                        _eventSource.InfoMessage("No Windows Update available. Completing the operation.");
                        //Complete operation.
                        this._nodeAgentSfUtility.UpdateSearchAndDownloadStatus(
                            NodeAgentSfUtilityExitCodes.OperationCompleted,
                            this._operationResultFormatter.CreateSearchAndDownloadDummyResult(),
                            utilityTaskTimeOut
                            );

                        break;
                    }

                    OperationResultCode downloadResult = DownloadUpdates(cancellationToken);
                    reschedule = (downloadResult != OperationResultCode.orcSucceeded ? true : reschedule);

                    WindowsUpdateOperationResult searchAndDownloadResult = this._operationResultFormatter.FormatSearchAndDownloadResult(downloadResult, this._wuCollectionWrapper);
                    _eventSource.InfoMessage("Search and download result: {0}", searchAndDownloadResult);

                    this._nodeAgentSfUtility.UpdateSearchAndDownloadStatus(NodeAgentSfUtilityExitCodes.DownloadCompleted, searchAndDownloadResult, utilityTaskTimeOut);

                    NodeAgentSfUtilityExitCodes exitCodes = this.WaitForInstallationApproval(cancellationToken);
                    if (exitCodes.Equals(NodeAgentSfUtilityExitCodes.Failure))
                    {
                        _eventSource.ErrorMessage("Not able to move from DownloadCompleted state to InstallationApproved state.");
                        reschedule = true;
                        break;
                    }

                    this._nodeAgentSfUtility.UpdateInstallationStatus(NodeAgentSfUtilityExitCodes.InstallationInProgress, null, utilityTaskTimeOut);

                    OperationResultCode installResult = InstallUpdates(cancellationToken);
                    reschedule = (installResult != OperationResultCode.orcSucceeded ? true : reschedule);

                    WindowsUpdateOperationResult installationResult = this._operationResultFormatter.FormatInstallationResult(installResult, this._wuCollectionWrapper);
                    _eventSource.InfoMessage("Installation result: {0}", installationResult);

                    this._nodeAgentSfUtility.UpdateInstallationStatus(NodeAgentSfUtilityExitCodes.InstallationCompleted, installationResult, utilityTaskTimeOut);
                }

                break;
            }

            case NodeAgentSfUtilityExitCodes.DownloadCompleted:
            case NodeAgentSfUtilityExitCodes.InstallationApproved:
            {
                NodeAgentSfUtilityExitCodes exitCodes = this.WaitForInstallationApproval(cancellationToken);
                if (exitCodes.Equals(NodeAgentSfUtilityExitCodes.Failure))
                {
                    _eventSource.ErrorMessage("Not able to move from DownloadCompleted state to InstallationApproved state.");
                    reschedule = true;
                    break;
                }

                OperationResultCode searchResult = SearchUpdates(cancellationToken);
                reschedule = (searchResult != OperationResultCode.orcSucceeded ? true : reschedule);

                if (this._wuCollectionWrapper != null)
                {
                    if (this._wuCollectionWrapper.Collection.Count == 0)
                    {
                        string msg =
                            "Current Operation state : InstallationApproved but no updates found to install. Completing the operation.";
                        this._nodeAgentSfUtility.ReportHealth("WindowsUpdateOperationResult", msg, HealthState.Warning, -1, TimeSpan.FromMinutes(this._serviceSettings.OperationTimeOutInMinutes));
                        _eventSource.WarningMessage(msg);
                        //Complete operation.
                        this._nodeAgentSfUtility.UpdateInstallationStatus(
                            NodeAgentSfUtilityExitCodes.OperationCompleted,
                            this._operationResultFormatter.CreateInstallationDummyResult(),
                            utilityTaskTimeOut
                            );
                        break;
                    }

                    this._nodeAgentSfUtility.UpdateInstallationStatus(NodeAgentSfUtilityExitCodes.InstallationInProgress, null, utilityTaskTimeOut);

                    OperationResultCode installResult = InstallUpdates(cancellationToken);
                    reschedule = (installResult != OperationResultCode.orcSucceeded ? true : reschedule);

                    WindowsUpdateOperationResult installationResult = this._operationResultFormatter.FormatInstallationResult(installResult, this._wuCollectionWrapper);
                    _eventSource.InfoMessage("Installation result: {0}", installationResult);

                    this._nodeAgentSfUtility.UpdateInstallationStatus(NodeAgentSfUtilityExitCodes.InstallationCompleted, installationResult, utilityTaskTimeOut);
                }
                break;
            }

            case NodeAgentSfUtilityExitCodes.InstallationInProgress:
            {
                OperationResultCode searchResult = SearchUpdates(cancellationToken);
                reschedule = (searchResult != OperationResultCode.orcSucceeded ? true : reschedule);

                if (this._wuCollectionWrapper != null)
                {
                    if (this._wuCollectionWrapper.Collection.Count == 0)
                    {
                        //this is possible when installation is completed but NT service is killed before updating "InstallationCompleted" status.
                        break;
                    }

                    OperationResultCode installResult = InstallUpdates(cancellationToken);
                    reschedule = (installResult != OperationResultCode.orcSucceeded ? true : reschedule);

                    WindowsUpdateOperationResult installationResult = this._operationResultFormatter.FormatInstallationResult(installResult, this._wuCollectionWrapper);
                    _eventSource.InfoMessage("Installation result: {0}", installationResult);

                    this._nodeAgentSfUtility.UpdateInstallationStatus(NodeAgentSfUtilityExitCodes.InstallationCompleted, installationResult, utilityTaskTimeOut);
                }
                break;
            }

            default:
                break;
            }
            return(reschedule);
        }
        // polls every 5 minutes, execute the callback if the date-time is according to frequency mentioned in Settings.xml.
        private void ScheduleTimer()
        {
            try
            {
                if (!this.CheckApplicationExists())
                {
                    _eventSource.InfoMessage("Application deleted. Removing NT service...");
                    this._windowsUpdateManager.ResetStateMachine();
                    this.RemoveSelf();
                    return;
                }

                // If cancellation token is canceled or application is not found
                if (this._cancellationToken.IsCancellationRequested)
                {
                    _eventSource.InfoMessage("Canceled timer.");
                    return;
                }

                NodeAgentSfUtilityExitCodes exitCode = this._nodeAgentSfUtility.GetWuOperationState(
                    TimeSpan.FromMinutes(this._serviceSettings.OperationTimeOutInMinutes));
                _eventSource.InfoMessage("Current Wu state: {0}", exitCode);
                if (exitCode == NodeAgentSfUtilityExitCodes.RestartRequested)
                {
                    _eventSource.ErrorMessage("Not able to restart system.");

                    //wait for sometime before retrying. This delay is recommended if posting health reports.
                    if (this._helper.WaitOnTask(Task.Delay(TimeSpan.FromMinutes(WaitTimeInMinutes)),
                                                this._cancellationToken))
                    {
                        this.ScheduleWindowsUpdates();
                        this.ScheduleTimer();
                    }
                    return;
                }
                else if (exitCode == NodeAgentSfUtilityExitCodes.RestartCompleted)
                {
                    this.ScheduleWindowsUpdates();

                    this.CreateNewCheckpointFile();

                    this.ScheduleTimer();
                    return;
                }

                CheckpointFileData fileData = this.ReadCheckpointFile();

                if (fileData.rescheduleNeeded)
                {
                    // If total retries are exhausted, schedule the call back for next interval mentioned in Settings.xml.
                    if (this.IncrementRetryCount() == false)
                    {
                        if (this._windowsUpdateManager.ResetStateMachine())
                        {
                            this.UpdateSettingsAndCreateCheckpoint();
                            this.CreateNewCheckpointFile();
                        }
                        else
                        {
                            if (this._helper.WaitOnTask(Task.Delay(TimeSpan.FromMinutes(WaitTimeInMinutes)),
                                                        this._cancellationToken))
                            {
                                this.ScheduleTimer();
                            }
                            return;
                        }
                    }
                }
                else
                {
                    // Do not update the lastAttemptedTime.
                    this.UpdateSettingsAndCreateCheckpoint(false);
                }

                // read checkpoint file after modifications.
                fileData = this.ReadCheckpointFile();

                // Execute call back
                if (this.ScheduleWindowsUpdatesFlag(fileData))
                {
                    bool retryNeeded = this.ScheduleWindowsUpdates();

                    if (retryNeeded)
                    {
                        fileData.rescheduleNeeded = true;
                        this.WriteCheckpointFile(fileData);
                    }
                    else
                    {
                        this.CreateNewCheckpointFile();
                    }

                    this.ScheduleTimer();
                    return;
                }
            }
            catch (Exception e)
            {
                _eventSource.ErrorMessage("ScheduleTimer ended with exception : {0}", e);
            }
            TimeSpan operationTimeSpan = TimeSpan.FromMinutes(WaitTimeInMinutes);

            if (this._helper.WaitOnTask(Task.Delay(operationTimeSpan), this._cancellationToken))
            {
                this.ScheduleTimer();
            }
        }
 public Task <NodeAgentSfUtilityExitCodes> UpdateInstallationStatusAsync(string nodeName, Uri applicationName, NodeAgentSfUtilityExitCodes updateState,
                                                                         WindowsUpdateOperationResult operationResult, TimeSpan timeout, CancellationToken cancellationToken)
 {
     throw new NotImplementedException();
 }