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);
            }
        }
        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);
        }