/// <summary>
        /// Get the progress of the current upgrade
        /// </summary>
        /// <param name="timeout"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task <FabricOrchestrationUpgradeProgress> ProcessGetClusterConfigurationUpgradeProgressAsync(TimeSpan timeout, CancellationToken cancellationToken)
        {
            UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "Entering ProcessGetUpgradeProgressAsync.");
            FabricOrchestrationUpgradeProgress upgradeProgress = null;

            try
            {
                string configVersion = await this.GetCurrentJsonConfigVersionAsync(this.cancellationToken).ConfigureAwait(false);

                FabricUpgradeProgress fabricUpgradeProgress = await FabricClientRetryHelper.ExecuteFabricActionWithRetryAsync(
                    () =>
                    this.fabricClient.ClusterManager.GetFabricUpgradeProgressAsync(Constants.UpgradeServiceMaxOperationTimeout, this.cancellationToken),
                    Constants.UpgradeServiceMaxOperationTimeout,
                    this.cancellationToken).ConfigureAwait(false);

                ConfigUpgradeErrorDetail errorDetails = await this.storeManager.GetConfigUpgradeErrorDetailsAsync(Constants.ConfigUpgradeErrorDetails, cancellationToken);

                uint manifestVersion;
                upgradeProgress = new FabricOrchestrationUpgradeProgress()
                {
                    UpgradeState   = fabricUpgradeProgress.UpgradeState,
                    ProgressStatus = uint.TryParse(fabricUpgradeProgress.TargetConfigVersion, out manifestVersion) ? manifestVersion : 0,
                    ConfigVersion  = configVersion,
                    Details        = (errorDetails != null) ? errorDetails.ToString() : null
                };
            }
            catch (Exception e)
            {
                UpgradeOrchestrationTrace.TraceSource.WriteWarning(TraceType, "ProcessGetUpgradeProgressAsync exception: {0}", e);
                throw;
            }

            UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "Exiting ProcessGetUpgradeProgressAsync.");
            return(upgradeProgress);
        }
        private async Task ProcessClusterUpgradeAsync(
            PaasClusterUpgradeDescription upgradeDesc,
            CancellationToken token)
        {
            var upgradeProgressTask    = this.fabricClientWrapper.GetFabricUpgradeProgressAsync(Constants.MaxOperationTimeout, token);
            var clusterHealthQueryTask = this.fabricClientWrapper.GetClusterHealthAsync(Constants.MaxOperationTimeout, token);

            await Task.WhenAll(
                upgradeProgressTask,
                clusterHealthQueryTask);

            FabricUpgradeProgress currentUpgradeProgress = GetResultFromTask(upgradeProgressTask);
            ClusterHealth         currentClusterHealth   = GetResultFromTask(clusterHealthQueryTask);

            ClusterUpgradeCommandParameter upgradeCommandParameter = null;

            try
            {
                upgradeCommandParameter = await this.commandParameterGenerator.GetCommandParameterAsync(
                    currentUpgradeProgress,
                    currentClusterHealth,
                    upgradeDesc,
                    token);

                await UpgradeClusterAsync(upgradeCommandParameter, token);
            }
            finally
            {
                Cleanup(upgradeCommandParameter);
            }
        }
        protected FabricUpgradeProgress GetClusterUpgradeProgress()
        {
            var clusterConnection = this.GetClusterConnection();

            FabricUpgradeProgress currentProgress = null;

            try
            {
                currentProgress =
                    clusterConnection.GetFabricUpgradeProgressAsync(
                        this.GetTimeout(),
                        this.GetCancellationToken()).Result;
            }
            catch (AggregateException aggregateException)
            {
                aggregateException.Handle((ae) =>
                {
                    this.ThrowTerminatingError(
                        ae,
                        Constants.GetClusterUpgradeProgressErrorId,
                        clusterConnection);
                    return(true);
                });
            }

            return(currentProgress);
        }
Example #4
0
        /// <summary>
        /// Returns a task which will complete when underlying upgrade completes.
        /// </summary>
        /// <param name="timeout"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task <FabricUpgradeProgress> GetCurrentRunningUpgradeTaskAsync(
            TimeSpan timeout,
            CancellationToken cancellationToken)
        {
            FabricUpgradeProgress fabricUpgradeProgress = null;
            var timeoutHelper = new TimeoutHelper(timeout, Constants.MaxOperationTimeout);

            while (true)
            {
                fabricUpgradeProgress = await this.fabricClient.ClusterManager.GetFabricUpgradeProgressAsync(
                    timeoutHelper.GetOperationTimeout(),
                    cancellationToken);

                Trace.WriteInfo(TraceType, "Current status: {0}", fabricUpgradeProgress.UpgradeState);
                if (IsUpgradeCompleted(fabricUpgradeProgress.UpgradeState))
                {
                    break;
                }

                if (IsUpgradeInUnSupportedState(fabricUpgradeProgress.UpgradeState))
                {
                    throw new NotSupportedException(string.Format("Cluster Fabric upgrade is in state {0}", fabricUpgradeProgress.UpgradeState));
                }

                var delayTime = timeoutHelper.GetRemainingTime();
                if (delayTime.CompareTo(TimeSpan.FromSeconds(DelayTimeoutInSeconds)) > 0)
                {
                    delayTime = TimeSpan.FromSeconds(DelayTimeoutInSeconds);
                }

                await Task.Delay(delayTime, cancellationToken);
            }

            return(fabricUpgradeProgress);
        }
Example #5
0
        internal static async Task <string> GetCurrentCodeVersion()
        {
            FabricUpgradeProgress fabricUpgradeProgress = await FabricClientRetryHelper.ExecuteFabricActionWithRetryAsync(
                () =>
                new FabricClient().ClusterManager.GetFabricUpgradeProgressAsync()).ConfigureAwait(false);

            return(fabricUpgradeProgress.TargetCodeVersion);
        }
        internal async Task <bool> IsInterruptibleAsync(ClusterUpgradeStateBase clusterUpgradeState)
        {
            if (!clusterUpgradeState.CanInterruptUpgrade())
            {
                return(false);
            }

            FabricUpgradeProgress fabricUpgradeProgress = await FabricClientRetryHelper.ExecuteFabricActionWithRetryAsync(
                () =>
                this.fabricClient.ClusterManager.GetFabricUpgradeProgressAsync(Constants.UpgradeServiceMaxOperationTimeout, this.cancellationToken),
                Constants.UpgradeServiceMaxOperationTimeout,
                this.cancellationToken).ConfigureAwait(false);

            return(fabricUpgradeProgress.UpgradeState != FabricUpgradeState.RollingBackInProgress);
        }
        private async Task UpdateReplicaStoreAfterUpgradeStartAsync(
            FabricUpgradeProgress upgradeProgress,
            CancellationToken token)
        {
            try
            {
                await this.WaitForPartitionReadyAsync(token);

                using (var tx = await this.store.CreateTransactionWithRetryAsync(this.exceptionPolicy, token))
                {
                    KeyValueStoreItem         storeItem         = null;
                    CurrentUpgradeInformation updateInformation = null;
                    if (this.store.Contains(tx, CurrentUpgradeKey))
                    {
                        try
                        {
                            storeItem         = this.store.Get(tx, CurrentUpgradeKey);
                            updateInformation = CurrentUpgradeInformation.Deserialize(storeItem.Value);
                            if (!updateInformation.UpgradeStarted)
                            {
                                updateInformation.UpgradeStarted = true;
                            }
                        }
                        catch (Exception ex)
                        {
                            Trace.WriteError(TraceType, "Update state deserialize failed with exception {0}", ex);
                            updateInformation = null;
                        }
                    }

                    if (updateInformation != null &&
                        !updateInformation.UpgradeStarted &&
                        updateInformation.TargetCodeVersion == upgradeProgress.TargetCodeVersion &&
                        (updateInformation.TargetConfigVersion == null ||
                         updateInformation.TargetConfigVersion == upgradeProgress.TargetConfigVersion))
                    {
                        updateInformation.UpgradeStarted = true;
                        this.store.Update(tx, CurrentUpgradeKey, updateInformation.Serialize(),
                                          storeItem.Metadata.SequenceNumber);
                        await tx.CommitAsync();
                    }
                }
            }
            catch (Exception ex)
            {
                Trace.WriteError(TraceType, "UpdateReplicaStoreAfterUpgradeStartAsync: Error : {0}", ex);
            }
        }
        private async Task <TimeSpan> GetWaitDurationAndUpdateHealth(FabricUpgradeProgress upgradeProgress, CancellationToken token)
        {
            TimeSpan waitDuration = TimeSpan.MinValue;

            using (var tx = await this.store.CreateTransactionWithRetryAsync(this.exceptionPolicy, token))
            {
                KeyValueStoreItem         storeItem         = null;
                CurrentUpgradeInformation updateInformation = null;
                if (this.store.Contains(tx, this.CurrentUpgradeKey))
                {
                    try
                    {
                        storeItem         = this.store.Get(tx, this.CurrentUpgradeKey);
                        updateInformation = CurrentUpgradeInformation.Deserialize(storeItem.Value);
                    }
                    catch (Exception ex)
                    {
                        Trace.WriteError(TraceType, "Update state deserialize failed with exception {0}", ex);
                        updateInformation = null;
                    }
                }

                if (updateInformation != null &&
                    (upgradeProgress.UpgradeState == FabricUpgradeState.Failed ||
                     upgradeProgress.UpgradeState == FabricUpgradeState.RollingBackCompleted))
                {
                    if (updateInformation.CurrentCodeVersion == upgradeProgress.TargetCodeVersion &&
                        updateInformation.CurrentConfigVersion == upgradeProgress.TargetConfigVersion)
                    {
                        // Error so report Warning health for the service
                        var description = string.Format(
                            CultureInfo.InvariantCulture,
                            "Upgrade failed for Update Id:{0} Target code version: {1}",
                            updateInformation.UpdateId,
                            updateInformation.TargetCodeVersion);
                        this.ReportHealthEvent(description, HealthState.Warning);
                        waitDuration = this.waitTimeBeforePolling;
                    }
                }
                else
                {
                    this.ReportHealthEvent("Health", HealthState.Ok);
                }
            }

            return(waitDuration);
        }
        private async Task CheckClusterManifestVersion(string clusterManifestVersion, CancellationToken cancellationToken)
        {
            // If an upgrade is still in progress, don't do anything
            FabricUpgradeProgress upgradeProgress = await FabricClientRetryHelper.ExecuteFabricActionWithRetryAsync <FabricUpgradeProgress>(
                () =>
                this.fabricClient.ClusterManager.GetFabricUpgradeProgressAsync(FabricClient.DefaultTimeout, cancellationToken)).ConfigureAwait(false);

            if (upgradeProgress == null || !FabricClientWrapper.IsUpgradeCompleted(upgradeProgress.UpgradeState))
            {
                return;
            }

            string clusterManifestContent = await FabricClientRetryHelper.ExecuteFabricActionWithRetryAsync(
                () => this.fabricClient.ClusterManager.GetClusterManifestAsync(FabricClient.DefaultTimeout, cancellationToken)).ConfigureAwait(false);

            var clusterManifest       = XMLHelper.ReadClusterManifestFromContent(clusterManifestContent);
            var actualManifestVersion = clusterManifest.Version;

            if (!actualManifestVersion.Equals(clusterManifestVersion, StringComparison.OrdinalIgnoreCase))
            {
                this.fabricClient.HealthManager.ReportHealth(new ClusterHealthReport(new HealthInformation(
                                                                                         Constants.UpgradeOrchestrationHealthSourceId,
                                                                                         Constants.ManifestVersionMismatchHealthProperty,
                                                                                         HealthState.Warning)
                {
                    Description = string.Format(
                        StringResources.WarningHealth_ClusterManifestVersionMismatch, actualManifestVersion, clusterManifestVersion),
                    TimeToLive        = TimeSpan.FromHours(48),
                    RemoveWhenExpired = true
                }));
            }
            else
            {
                this.fabricClient.HealthManager.ReportHealth(new ClusterHealthReport(new HealthInformation(
                                                                                         Constants.UpgradeOrchestrationHealthSourceId,
                                                                                         Constants.ManifestVersionMismatchHealthProperty,
                                                                                         HealthState.Ok)
                {
                    TimeToLive        = TimeSpan.FromMilliseconds(1),
                    RemoveWhenExpired = true
                }));
            }
        }
Example #10
0
        public Task <ClusterUpgradeCommandParameter> GetUpgradeCommandParamterAsync(
            FabricUpgradeProgress currentUpgradeProgress,
            TimeSpan timeout,
            CancellationToken token)
        {
            Trace.ConsoleWriteLine(TraceType, "In Test");
            ClusterUpgradeCommandParameter parameter = null;
            var tcs = new TaskCompletionSource <ClusterUpgradeCommandParameter>();

            if (Directory.Exists(@"c:\TempTest"))
            {
                parameter = new ClusterUpgradeCommandParameter();
                if (File.Exists(@"c:\TempTest\ClusterManifest.xml"))
                {
                    parameter.ConfigFilePath = @"c:\TempTest\ClusterManifest.xml";
                }

                var files = Directory.EnumerateFiles(@"c:\TempTest", "WindowsFabric.*.msi").ToArray();
                if (files.Count() == 1)
                {
                    var msi     = Path.GetFileName(files[0]);
                    var name    = Path.GetFileNameWithoutExtension(msi);
                    var version = name.Substring(14);
                    parameter.CodeFilePath = files[0];
                    parameter.CodeVersion  = version;
                }

                if (currentUpgradeProgress.TargetCodeVersion == parameter.CodeVersion ||
                    (string.IsNullOrWhiteSpace(parameter.CodeFilePath) && string.IsNullOrWhiteSpace(parameter.ConfigFilePath)))
                {
                    parameter = null;
                }
            }

            if (parameter != null)
            {
                Trace.ConsoleWriteLine(TraceType, "codepath:{0} configPath:{1}", parameter.CodeFilePath, parameter.ConfigFilePath);
            }

            tcs.SetResult(parameter);
            return(tcs.Task);
        }
        public async Task <ClusterUpgradeCommandParameter> GetCommandParameterAsync(
            FabricUpgradeProgress currentUpgradeProgress,
            ClusterHealth currentClusterHealth,
            PaasClusterUpgradeDescription response,
            CancellationToken token)
        {
            if (response == null ||
                (response.TargetClusterManifestBase64 == null && response.TargetMsiUri == null))
            {
                Trace.WriteInfo(TraceType, "GetCommandParameterAsync: Null response");
                return(null);
            }

            if (currentClusterHealth == null)
            {
                Trace.WriteWarning(TraceType, "currentClusterHealth is null. ContinousNullClusterHealthCount = {0}", this.continousNullClusterHealthCount);
                if (++continousNullClusterHealthCount < 5)
                {
                    Trace.WriteWarning(TraceType, "Returning null since upgrade will not be initiated");
                    return(null);
                }

                Trace.WriteWarning(TraceType, "Upgrading even though currentClusterHealth is null.");
            }
            else
            {
                this.continousNullClusterHealthCount = 0;
            }

            Trace.WriteInfo(TraceType, "GetCommandParameterAsync: Processing WRP response");
            ClusterManifestType targetClusterManifest = FromBase64ClusterManifest(response.TargetClusterManifestBase64);

            Trace.WriteInfo(TraceType, "GetCommandParameterAsync: response.TargetMsiVersion = {0}, currentUpgradeProgress.TargetCodeVersion = {1}, targetClusterManifest.Version = {2}, currentUpgradeProgress.UpgradeState = {3}",
                            response.TargetMsiVersion,
                            currentUpgradeProgress != null ? currentUpgradeProgress.TargetCodeVersion : "NA",
                            targetClusterManifest != null ? targetClusterManifest.Version : "NA",
                            currentUpgradeProgress != null ? currentUpgradeProgress.UpgradeState.ToString() : "NA");

            string currentCodeVersion   = string.Empty;
            string currentConfigVersion = string.Empty;
            bool   isUpgradeStateFailed = false;

            if (currentUpgradeProgress != null)
            {
                currentCodeVersion   = currentUpgradeProgress.TargetCodeVersion;
                currentConfigVersion = currentUpgradeProgress.TargetConfigVersion;
                isUpgradeStateFailed = currentUpgradeProgress.UpgradeState == FabricUpgradeState.Failed;
            }

            if (response.TargetMsiVersion == currentCodeVersion &&
                (targetClusterManifest != null && targetClusterManifest.Version == currentConfigVersion) &&
                !isUpgradeStateFailed)
            {
                return(null);
            }

            string clusterConfigFilePath = null;
            string clusterMsiPath        = null;
            string clusterConfigVersion  = null;
            var    info     = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()));
            var    tempPath = info.FullName;

            if (isUpgradeStateFailed || (targetClusterManifest != null && targetClusterManifest.Version != currentConfigVersion))
            {
                clusterConfigFilePath = Path.Combine(tempPath, "ClusterManifest.xml");
                using (var fs = new FileStream(clusterConfigFilePath, FileMode.Create))
                {
                    using (TextWriter writer = new StreamWriter(fs, new UTF8Encoding()))
                    {
                        // Serialize using the XmlTextWriter.
                        this.clusterManifestSerializer.Serialize(writer, targetClusterManifest);
                    }
                }

                clusterConfigVersion = targetClusterManifest.Version;
            }

            if (isUpgradeStateFailed || (response.TargetMsiUri != null && response.TargetMsiVersion != currentCodeVersion))
            {
                clusterMsiPath = await DownloadMsiAsync(response.TargetMsiUri, response.TargetMsiVersion, tempPath);
            }

            Trace.WriteInfo(TraceType, "ClusterConfigFile {0}, ClusterMsiFile {1}", clusterConfigFilePath, clusterMsiPath);
            var parameter = new ClusterUpgradeCommandParameter()
            {
                CodeVersion    = response.TargetMsiVersion,
                CodeFilePath   = clusterMsiPath,
                ConfigFilePath = clusterConfigFilePath,
                ConfigVersion  = clusterConfigVersion
            };

            parameter.UpgradeDescription = await this.GetClusterUpgradeDescriptionAsync(response.UpgradePolicy, currentClusterHealth, token);

            return(parameter);
        }
        private async Task <IOperationStatus> BuildStatusAsync(ClusterOperationDescription description, IOperationContext context, ClusterErrorDetails errorDetails)
        {
            var upgradeProgressTask = this.fabricClientWrapper.GetFabricUpgradeProgressAsync(Constants.MaxOperationTimeout, context.CancellationToken);

            var nodeListQueryTask = this.fabricClientWrapper.GetNodeListAsync(Constants.MaxOperationTimeout, context.CancellationToken);

            // Only query for system services when WRP needs to adjust the replica set size
            Task <Dictionary <string, ServiceRuntimeDescription> > systemServiceSizeQueryTask = null;

            if (description != null &&
                description.SystemServiceDescriptionsToSet != null &&
                description.SystemServiceDescriptionsToSet.Any())
            {
                systemServiceSizeQueryTask =
                    this.fabricClientWrapper.GetSystemServiceRuntimeDescriptionsAsync(Constants.MaxOperationTimeout, context.CancellationToken);
            }

            await Task.WhenAll(
                nodeListQueryTask,
                upgradeProgressTask,
                systemServiceSizeQueryTask ?? Task.FromResult <Dictionary <string, ServiceRuntimeDescription> >(null));

            FabricUpgradeProgress currentUpgradeProgress = GetResultFromTask(upgradeProgressTask);
            NodeList nodeList = FilterPrimaryNodeTypesStatus(GetResultFromTask(nodeListQueryTask), description?.PrimaryNodeTypes);
            Dictionary <string, ServiceRuntimeDescription> systemServicesRuntimeDescriptions = GetResultFromTask(systemServiceSizeQueryTask);

            List <PaasNodeStatusInfo> nodesDisabled = null;
            List <PaasNodeStatusInfo> nodesEnabled  = null;

            if (description != null &&
                nodeList != null)
            {
                Trace.WriteNoise(TraceType, "BuildStatusAsync: Begin this.nodeStatusManager.ProcessNodeQuery.");
                await this.nodeStatusManager.ProcessNodeQuery(nodeList, Constants.KvsCommitTimeout, context.CancellationToken);

                Trace.WriteNoise(TraceType, "BuildStatusAsync: End this.nodeStatusManager.ProcessNodeQuery.");

                // Send back the list of nodes that are disabled
                if (description.NodesToDisabled != null)
                {
                    nodesDisabled = new List <PaasNodeStatusInfo>();

                    // Send back the Instance# for the requested disabled nodes
                    foreach (var nodeToDisable in description.NodesToDisabled)
                    {
                        var matchingNodeStatus =
                            nodeList.FirstOrDefault(
                                node =>
                                string.Equals(node.NodeName, nodeToDisable.NodeName,
                                              StringComparison.OrdinalIgnoreCase));
                        if (matchingNodeStatus != null && matchingNodeStatus.NodeStatus == NodeStatus.Disabled)
                        {
                            var nodeDisabled = new PaasNodeStatusInfo(nodeToDisable)
                            {
                                NodeState = NodeState.Disabled
                            };

                            nodesDisabled.Add(nodeDisabled);

                            Trace.WriteInfo(TraceType, "BuildStatusAsync: Node has been successfully disabled. {0}", nodeDisabled);
                        }
                    }
                }

                // Send back the list of nodes that are Enabled
                if (description.NodesToEnabled != null)
                {
                    nodesEnabled = new List <PaasNodeStatusInfo>();

                    // Send back the Instance# for the requested up nodes
                    foreach (var nodeToEnable in description.NodesToEnabled)
                    {
                        var matchingNodeStatus =
                            nodeList.FirstOrDefault(
                                node =>
                                string.Equals(node.NodeName, nodeToEnable.NodeName,
                                              StringComparison.OrdinalIgnoreCase));

                        // Since a node can be enabled and can still be down, we infer enabled status instead.
                        if (matchingNodeStatus != null &&
                            (matchingNodeStatus.NodeStatus != NodeStatus.Disabling) &&
                            (matchingNodeStatus.NodeStatus != NodeStatus.Disabled) &&
                            (matchingNodeStatus.NodeStatus != NodeStatus.Enabling))
                        {
                            var nodeEnabled = new PaasNodeStatusInfo(nodeToEnable);
                            nodeEnabled.NodeState = NodeState.Enabled;

                            nodesEnabled.Add(nodeEnabled);

                            Trace.WriteInfo(TraceType, "BuildStatusAsync: Node has been successfully enabled. {0}", nodeEnabled);
                        }
                    }
                }
            }

            Trace.WriteNoise(TraceType, "BuildStatusAsync: Begin this.nodeStatusManager.GetNodeStates.");
            var nodesStatus = await this.nodeStatusManager.GetNodeStates(Constants.KvsCommitTimeout, context.CancellationToken);

            Trace.WriteNoise(TraceType, "BuildStatusAsync: End this.nodeStatusManager.GetNodeStates.");

            var status = new ClusterOperationStatus(description)
            {
                DisabledNodes             = nodesDisabled,
                EnabledNodes              = nodesEnabled,
                NodesStatus               = nodesStatus,
                SystemServiceDescriptions = systemServicesRuntimeDescriptions,
            };

            if (currentUpgradeProgress != null)
            {
                status.Progress = JObject.FromObject(currentUpgradeProgress, this.serializer);
            }

            if (errorDetails != null)
            {
                status.ErrorDetails = JObject.FromObject(errorDetails, this.serializer);
            }

            return(status);
        }
Example #13
0
            internal static FabricUpgradeProgress CreateFromNative(NativeClient.IFabricUpgradeProgressResult3 nativeResult)
            {
                if (nativeResult == null)
                {
                    return(null);
                }

                var progress = new FabricUpgradeProgress(nativeResult);

                progress.TargetCodeVersion   = NativeTypes.FromNativeString(nativeResult.get_TargetCodeVersion());
                progress.TargetConfigVersion = NativeTypes.FromNativeString(nativeResult.get_TargetConfigVersion());

                switch (nativeResult.get_UpgradeState())
                {
                case NativeTypes.FABRIC_UPGRADE_STATE.FABRIC_UPGRADE_STATE_ROLLBACK_IN_PROGRESS:
                case NativeTypes.FABRIC_UPGRADE_STATE.FABRIC_UPGRADE_STATE_ROLLBACK_COMPLETED:
                case NativeTypes.FABRIC_UPGRADE_STATE.FABRIC_UPGRADE_STATE_ROLLBACK_PENDING:
                case NativeTypes.FABRIC_UPGRADE_STATE.FABRIC_UPGRADE_STATE_ROLLFORWARD_PENDING:
                case NativeTypes.FABRIC_UPGRADE_STATE.FABRIC_UPGRADE_STATE_ROLLFORWARD_IN_PROGRESS:
                case NativeTypes.FABRIC_UPGRADE_STATE.FABRIC_UPGRADE_STATE_ROLLFORWARD_COMPLETED:
                case NativeTypes.FABRIC_UPGRADE_STATE.FABRIC_UPGRADE_STATE_FAILED:
                    progress.UpgradeState = (FabricUpgradeState)nativeResult.get_UpgradeState();
                    break;

                default:
                    progress.UpgradeState = FabricUpgradeState.Invalid;
                    break;
                }

                uint   count   = 0;
                IntPtr pointer = nativeResult.GetUpgradeDomains(out count);

                progress.UpgradeDomains = UpgradeDomainHelper.CreateUpgradeDomainsFromNative(count, pointer);

                switch (nativeResult.get_RollingUpgradeMode())
                {
                case NativeTypes.FABRIC_ROLLING_UPGRADE_MODE.FABRIC_ROLLING_UPGRADE_MODE_UNMONITORED_AUTO:
                case NativeTypes.FABRIC_ROLLING_UPGRADE_MODE.FABRIC_ROLLING_UPGRADE_MODE_UNMONITORED_MANUAL:
                case NativeTypes.FABRIC_ROLLING_UPGRADE_MODE.FABRIC_ROLLING_UPGRADE_MODE_MONITORED:
                    progress.RollingUpgradeMode = (RollingUpgradeMode)nativeResult.get_RollingUpgradeMode();
                    break;

                default:
                    progress.RollingUpgradeMode = RollingUpgradeMode.Invalid;
                    break;
                }

                progress.NextUpgradeDomain = NativeTypes.FromNativeString(nativeResult.get_NextUpgradeDomain());

                IntPtr upgradeProgressPtr = nativeResult.get_UpgradeProgress();

                if (upgradeProgressPtr != IntPtr.Zero)
                {
                    unsafe
                    {
                        var castedProgressPtr = (NativeTypes.FABRIC_UPGRADE_PROGRESS *)upgradeProgressPtr;
                        progress.UpgradeDescription           = FabricUpgradeDescription.FromNative(castedProgressPtr->UpgradeDescription);
                        progress.UpgradeDuration              = TimeSpan.FromSeconds(castedProgressPtr->UpgradeDurationInSeconds);
                        progress.CurrentUpgradeDomainDuration = TimeSpan.FromSeconds(castedProgressPtr->CurrentUpgradeDomainDurationInSeconds);
                        progress.UnhealthyEvaluations         = HealthEvaluation.FromNativeList(castedProgressPtr->UnhealthyEvaluations);
                        progress.CurrentUpgradeDomainProgress = UpgradeDomainProgress.FromNative(castedProgressPtr->CurrentUpgradeDomainProgress);

                        if (castedProgressPtr->Reserved != IntPtr.Zero)
                        {
                            var castedProgressEx1Ptr = (NativeTypes.FABRIC_UPGRADE_PROGRESS_EX1 *)castedProgressPtr->Reserved;
                            progress.StartTimestampUtc   = NativeTypes.FromNullableNativeFILETIME(castedProgressEx1Ptr->StartTimestampUtc);
                            progress.FailureTimestampUtc = NativeTypes.FromNullableNativeFILETIME(castedProgressEx1Ptr->FailureTimestampUtc);

                            if (progress.FailureTimestampUtc.HasValue)
                            {
                                switch (castedProgressEx1Ptr->FailureReason)
                                {
                                case NativeTypes.FABRIC_UPGRADE_FAILURE_REASON.FABRIC_UPGRADE_FAILURE_REASON_INTERRUPTED:
                                case NativeTypes.FABRIC_UPGRADE_FAILURE_REASON.FABRIC_UPGRADE_FAILURE_REASON_HEALTH_CHECK:
                                case NativeTypes.FABRIC_UPGRADE_FAILURE_REASON.FABRIC_UPGRADE_FAILURE_REASON_UPGRADE_DOMAIN_TIMEOUT:
                                case NativeTypes.FABRIC_UPGRADE_FAILURE_REASON.FABRIC_UPGRADE_FAILURE_REASON_OVERALL_UPGRADE_TIMEOUT:
                                case NativeTypes.FABRIC_UPGRADE_FAILURE_REASON.FABRIC_UPGRADE_FAILURE_REASON_PROCESSING_FAILURE:
                                    progress.FailureReason = (UpgradeFailureReason)castedProgressEx1Ptr->FailureReason;
                                    break;

                                default:
                                    progress.FailureReason = UpgradeFailureReason.None;
                                    break;
                                }

                                progress.UpgradeDomainProgressAtFailure = UpgradeDomainProgress.FromNative(
                                    castedProgressEx1Ptr->UpgradeDomainProgressAtFailure);
                            }
                        }
                    }
                }

                GC.KeepAlive(nativeResult);
                return(progress);
            }
        private async Task <ClusterUpgradeCommandParameter> UpdateReplicaStoreBeforeUpgradeStartAsync(
            ClusterUpgradeCommandParameter commandParameter,
            FabricUpgradeProgress upgradeProgress,
            string updateId,
            CancellationToken token)
        {
            try
            {
                await this.WaitForPartitionReadyAsync(token);

                Trace.WriteInfo(TraceType, "UpdateReplicaStoreBeforeUpgradeStartAsync: Update replica store.");
                KeyValueStoreItem storeItem = null;
                using (var tx = await this.store.CreateTransactionWithRetryAsync(this.exceptionPolicy, token))
                {
                    CurrentUpgradeInformation updateInformation = null;
                    if (this.store.Contains(tx, CurrentUpgradeKey))
                    {
                        storeItem = this.store.Get(tx, CurrentUpgradeKey);
                        try
                        {
                            updateInformation = CurrentUpgradeInformation.Deserialize(storeItem.Value);
                            if (updateInformation.UpgradeStarted && updateId == updateInformation.UpdateId)
                            {
                                updateInformation.Retry++;
                                updateInformation.UpgradeStarted = false;
                            }
                        }
                        catch (Exception ex)
                        {
                            Trace.WriteError(TraceType, "Deserialize failed with exception {0}", ex);
                            updateInformation = null;
                        }
                    }

                    if (updateInformation == null || updateId != updateInformation.UpdateId)
                    {
                        updateInformation = new CurrentUpgradeInformation
                        {
                            Retry                = 0,
                            TargetCodeVersion    = commandParameter.CodeVersion,
                            TargetConfigVersion  = commandParameter.ConfigVersion,
                            CurrentCodeVersion   = upgradeProgress.TargetCodeVersion,
                            CurrentConfigVersion = upgradeProgress.TargetConfigVersion,
                            UpdateId             = updateId,
                            UpgradeStarted       = false
                        };
                    }

                    Trace.WriteInfo(TraceType, "Updating store for update Id: {0}, Retry: {1} ", updateId, updateInformation.Retry);
                    if (storeItem != null)
                    {
                        this.store.Update(tx, CurrentUpgradeKey, updateInformation.Serialize(), storeItem.Metadata.SequenceNumber);
                    }
                    else
                    {
                        this.store.Add(tx, CurrentUpgradeKey, updateInformation.Serialize());
                    }

                    await tx.CommitAsync();

                    Trace.WriteInfo(TraceType, "UpdateReplicaStoreBeforeUpgradeStartAsync: replica store updated");
                }
            }
            catch (Exception ex)
            {
                Trace.WriteError(TraceType, "UpdateReplicaStoreBeforeUpgradeStartAsync: Error : {0}", ex);
                commandParameter = null;
            }

            if (commandParameter != null)
            {
                if (commandParameter.UpgradeDescription == null)
                {
                    commandParameter.UpgradeDescription = new CommandProcessorClusterUpgradeDescription();
                }

                commandParameter.UpgradeDescription.ForceRestart = true;
            }

            return(commandParameter);
        }
        // Return true if upgrade started other wise false
        private async Task <bool> OnGettingUpdateCollectionAsync(
            NativeMethods.IUpdateCollection updateCollection,
            FabricUpgradeProgress upgradeProgress,
            CancellationToken token)
        {
            ClusterUpgradeCommandParameter commandParameter = null;
            string updateId = string.Empty;

            if (updateCollection != null)
            {
                NativeMethods.IUpdate updateToDownload = this.GetUpdateToDownload(updateCollection);
                if (updateToDownload != null)
                {
                    Trace.WriteInfo(TraceType, "OnGettingUpdateCollectionAsync: Update to download: {0}", updateToDownload.Identity.UpdateID);
                    commandParameter = await this.packageRetriever.DownloadWindowsUpdate(updateToDownload, this.windowsUpdateApiTimeout, token);

                    updateId = updateToDownload.Identity.UpdateID;
                }
                else
                {
                    Trace.WriteInfo(TraceType, "OnGettingUpdateCollectionAsync: No update found.");
                }
            }
            else
            {
                Trace.WriteInfo(TraceType, "OnGettingUpdateCollectionAsync: update collection is null.");
                if (this.testMode && Directory.Exists(this.testSrcDir))
                {
                    var srcCabFile = Directory.GetFiles(this.testSrcDir, "*.cab", SearchOption.TopDirectoryOnly).FirstOrDefault();
                    if (!string.IsNullOrWhiteSpace(srcCabFile))
                    {
                        Trace.WriteWarning(TraceType, "OnGettingUpdateCollectionAsync: Test cab file {0}", srcCabFile);
                        var dir  = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
                        var info = new DirectoryInfo(dir);
                        if (!info.Exists)
                        {
                            info.Create();
                        }

                        updateId = Guid.NewGuid().ToString();
                        var destCabFile = Path.Combine(dir, "test.cab");
                        File.Copy(srcCabFile, destCabFile);
                        Trace.WriteWarning(TraceType, "OnGettingUpdateCollectionAsync: Test dest file {0}", destCabFile);
                        var cabVersion = CabFileOperations.GetCabVersion(destCabFile);
                        Trace.WriteWarning(TraceType, "OnGettingUpdateCollectionAsync: Cab version {0}", cabVersion);
                        commandParameter = new ClusterUpgradeCommandParameter()
                        {
                            CodeFilePath = destCabFile,
                            CodeVersion  = cabVersion
                        };
                    }
                }
            }

            if (commandParameter == null)
            {
                return(false);
            }

            var updatedCommandParameter = await this.UpdateReplicaStoreBeforeUpgradeStartAsync(
                commandParameter,
                upgradeProgress,
                updateId,
                token);

            var upgradeTask = await this.commandProcessor.ClusterUpgradeAsync(updatedCommandParameter, TimeSpan.MaxValue, token).ContinueWith(
                (task) =>
            {
                if (commandParameter != null)
                {
                    DeleteFileDirectory(commandParameter.CodeFilePath);
                    DeleteFileDirectory(commandParameter.ConfigFilePath);
                }

                return(task);
            });

            await upgradeTask;

            return(true);
        }