/// <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); }
/// <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); }
/// <summary> /// Gets the state of Windows Update operation using the state stored in RepairTask /// </summary> /// <param name="nodeName">Name of current Service Fabric node</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"/></returns> public async Task <NodeAgentSfUtilityExitCodes> GetWuOperationStateAsync(String nodeName, TimeSpan timeout, CancellationToken cancellationToken) { RepairTask repairTask; try { repairTask = await RepairManagerHelper.GetRepairTaskForNode( this.fabricClient, nodeName, timeout, cancellationToken); } catch (Exception e) { ServiceEventSource.Current.ErrorMessage( String.Format("RepairManagerHelper.GetRepairTaskForNode failed. Exception details {0}", e)); if (e is FabricTransientException) { return(NodeAgentSfUtilityExitCodes.RetryableException); } else { return(NodeAgentSfUtilityExitCodes.Failure); } } if (null == repairTask) { ServiceEventSource.Current.VerboseMessage(String.Format("No repair task found for this node, Operation State = {0}", NodeAgentSfUtilityExitCodes.None)); return(NodeAgentSfUtilityExitCodes.None); } NodeAgentSfUtilityExitCodes resultState; ExecutorDataForRmTask executorData = SerializationUtility.Deserialize <ExecutorDataForRmTask>(repairTask.ExecutorData); ExecutorDataForNtService executorDataForNtService = new ExecutorDataForNtService() { ApprovedDateTime = repairTask.ApprovedTimestamp, ExecutorTimeoutInMinutes = executorData.ExecutorTimeoutInMinutes }; string workFolder = Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location); string executorDataForNtServiceFilePath = Path.Combine(workFolder, ExecutorDataForNtServiceFileName); SerializationUtility.Serialize(executorDataForNtServiceFilePath, executorDataForNtService); switch (repairTask.State) { case RepairTaskState.Claimed: case RepairTaskState.Preparing: resultState = NodeAgentSfUtilityExitCodes.DownloadCompleted; break; case RepairTaskState.Approved: resultState = NodeAgentSfUtilityExitCodes.InstallationApproved; break; case RepairTaskState.Executing: { resultState = executorData.ExecutorSubState; if (resultState == NodeAgentSfUtilityExitCodes.RestartRequested) { if (this.GetRestartStatus(executorData.RestartRequestedTime)) { string resultDetails = "Installation of the updates completed, Restart post installation completed successfully"; resultState = await RepairManagerHelper.UpdateRepairTask(this.fabricClient, nodeName, RepairTaskState.Executing, RepairTaskResult.Pending, resultDetails, NodeAgentSfUtilityExitCodes.RestartCompleted, timeout, cancellationToken); if (resultState == NodeAgentSfUtilityExitCodes.Success) { resultState = NodeAgentSfUtilityExitCodes.RestartCompleted; } else { ServiceEventSource.Current.ErrorMessage( String.Format("Post restart, update of Repair task failed with {0}", resultState)); resultState = NodeAgentSfUtilityExitCodes.RetryableException; } } } break; } case RepairTaskState.Completed: case RepairTaskState.Restoring: { resultState = NodeAgentSfUtilityExitCodes.OperationCompleted; break; } default: { ServiceEventSource.Current.ErrorMessage(String.Format("Repair task for current node in unexpected state {0}", repairTask.State)); resultState = NodeAgentSfUtilityExitCodes.RepairTaskInvalidState; break; } } ServiceEventSource.Current.InfoMessage("GetWuOperationStateAsync returned {0}", resultState); return(resultState); }