Пример #1
0
        public void DeploymentManagerTest_GoalStateDefaults()
        {
            // Create empty package in goal state to test default values
            string         emptyPackageDefaults = "{\"packages\": [{}]}";
            GoalStateModel model = JsonConvert.DeserializeObject <GoalStateModel>(emptyPackageDefaults, new JsonSerializerSettings()
            {
                DefaultValueHandling = DefaultValueHandling.Populate
            });
            PackageDetails pd = model.Packages.First();

            Assert.IsTrue(pd.IsUpgradeDisabled == false, "IsUpgradeDisabled should be defaulted to false.");
            Assert.IsTrue(pd.IsDowngradeDisabled == false, "IsDowngradeDisabled should be defaulted to false.");
            Assert.IsTrue(pd.IsGoalPackage == false, "IsGoalPackage should be defaulted to false.");
        }
Пример #2
0
        private async Task PollGoalStateForCodePackagesAsync(CancellationToken cancellationToken)
        {
            var fabricClient = new FabricClient();

            //// region: Initialization Parameters

            FabricUpgradeProgress upgradeProgress;

            try
            {
                upgradeProgress = await FabricClientRetryHelper.ExecuteFabricActionWithRetryAsync <FabricUpgradeProgress>(
                    () =>
                    fabricClient.ClusterManager.GetFabricUpgradeProgressAsync(TimeSpan.FromMinutes(DMConstants.FabricOperationTimeoutInMinutes), cancellationToken),
                    TimeSpan.FromMinutes(DMConstants.FabricOperationTimeoutInMinutes),
                    cancellationToken).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                this.traceSource.WriteError(TraceType, "GetFabricUpgradeProgressAsync threw: {0}", ex.ToString());
                this.timerInterval = TimeSpan.FromMinutes(DMConstants.FabricUpgradeStatePollIntervalInMinutes);
                return;
            }

            if (!FabricClientWrapper.IsUpgradeCompleted(upgradeProgress.UpgradeState))
            {
                this.timerInterval = TimeSpan.FromMinutes(DMConstants.FabricUpgradeStatePollIntervalInMinutes);
                this.traceSource.WriteInfo(TraceType, "Cannot retrieve cluster version; FabricUpgradeState is currently: {0}. Will retry in {1}.", upgradeProgress.UpgradeState.ToString(), this.timerInterval.ToString());
                return;
            }

            string            currentVersionStr = upgradeProgress.TargetCodeVersion;
            Version           currentVersion    = Version.Parse(currentVersionStr);
            string            packageDropDir    = System.Fabric.Common.Helpers.GetNewTempPath();
            NativeConfigStore configStore       = NativeConfigStore.FabricGetConfigStore();
            string            goalStateUriStr   = configStore.ReadUnencryptedString(DMConstants.UpgradeOrchestrationServiceConfigSectionName, DMConstants.GoalStateFileUrlName);

            if (string.IsNullOrEmpty(goalStateUriStr))
            {
                goalStateUriStr = DMConstants.DefaultGoalStateFileUrl;
            }

            //// endregion

            this.traceSource.WriteInfo(TraceType, "PollCodePackagesFromGoalState currentVersion: {0}, packageDropDir: {1} goalStateUri: {2}", currentVersionStr, packageDropDir, goalStateUriStr);
            try
            {
                Uri    goalStateUri  = null;
                string goalStateJson = null;
                if (!Uri.TryCreate(goalStateUriStr, UriKind.Absolute, out goalStateUri))
                {
                    string errorMessage = string.Format("Cannot parse GoalStateUri: {0}", goalStateUriStr);
                    this.traceSource.WriteError(TraceType, errorMessage);
                    ReleaseAssert.Fail(errorMessage);
                    return;
                }

                if (!(await StandaloneUtility.IsUriReachableAsync(goalStateUri).ConfigureAwait(false)))
                {
                    this.timerInterval = TimeSpan.FromMinutes(DMConstants.FabricGoalStateReachablePollIntervalInMinutes);
                    this.traceSource.WriteWarning(TraceType, "Cannot reach download uri for goal state file: {0}. Will retry in {1}.", goalStateUri.AbsoluteUri, this.timerInterval.ToString());
                    this.EmitGoalStateReachableHealth(fabricClient, false);
                    return;
                }
                else
                {
                    this.EmitGoalStateReachableHealth(fabricClient, true);
                }

                goalStateJson = await GoalStateModel.GetGoalStateFileJsonAsync(goalStateUri).ConfigureAwait(false);

                if (string.IsNullOrEmpty(goalStateJson))
                {
                    this.traceSource.WriteWarning(TraceType, "Loaded goal state JSON is empty.");
                    return;
                }

                GoalStateModel model = GoalStateModel.GetGoalStateModelFromJson(goalStateJson);
                if (model == null || model.Packages == null)
                {
                    this.traceSource.WriteWarning(TraceType, "Goal state JSON could not be deserialized:\n{0}", goalStateJson);
                    return;
                }

                string availableGoalStateVersions = string.Format("Available versions in goal state file: {0}", model.ToString());
                this.traceSource.WriteInfo(TraceType, availableGoalStateVersions);

                IEnumerable <PackageDetails> candidatePackages = model.Packages.Where(
                    package => currentVersion < Version.Parse(package.Version));

                if (candidatePackages.Count() == 0)
                {
                    this.traceSource.WriteInfo(TraceType, "No upgrades available.");
                }

                string         versionCurrentStr = currentVersionStr;
                Version        versionCurrent    = currentVersion;
                PackageDetails targetPackage     = null;
                for (IEnumerable <PackageDetails> availableCandidatePackages = candidatePackages.Where(
                         package => (package.MinVersion == null || Version.Parse(package.MinVersion) <= versionCurrent));
                     availableCandidatePackages.Count() > 0;
                     versionCurrentStr = targetPackage.Version,
                     versionCurrent = Version.Parse(versionCurrentStr),
                     availableCandidatePackages = candidatePackages.Where(
                         package => (versionCurrent < Version.Parse(package.Version) &&
                                     (package.MinVersion == null || Version.Parse(package.MinVersion) <= versionCurrent))))
                {
                    if (!IsVersionUpgradeable(versionCurrentStr, model))
                    {
                        this.traceSource.WriteInfo(TraceType, "Version {0} is not upgradeable.", versionCurrentStr);
                        break;
                    }

                    int numPackages = availableCandidatePackages.Count();
                    if (numPackages == 0)
                    {
                        this.traceSource.WriteInfo(TraceType, "No upgrade available.");
                        return;
                    }
                    else if (numPackages == 1)
                    {
                        targetPackage = availableCandidatePackages.First();
                    }
                    else
                    {
                        Version maxVersion = StandaloneGoalStateProvisioner.ZeroVersion;
                        foreach (PackageDetails package in availableCandidatePackages)
                        {
                            Version targetVersion;
                            if (!Version.TryParse(package.Version, out targetVersion))
                            {
                                this.traceSource.WriteWarning(TraceType, "Package {0} version could not be parsed. Trying another one.", package.Version);
                                continue;
                            }

                            if (targetVersion > maxVersion)
                            {
                                targetPackage = package;
                                maxVersion    = targetVersion;
                            }
                        }
                    }

                    try
                    {
                        if (await this.IsPackageProvisionedAsync(targetPackage.Version, fabricClient, cancellationToken).ConfigureAwait(false))
                        {
                            this.traceSource.WriteInfo(TraceType, "Package {0} is already provisioned.", targetPackage.Version);
                            continue;
                        }
                    }
                    catch (Exception ex)
                    {
                        this.traceSource.WriteError(TraceType, "PackageIsProvisioned for {0} threw: {1}", targetPackage.Version, ex.ToString());
                    }

                    string packageLocalDownloadPath = Path.Combine(packageDropDir, string.Format(DMConstants.SFPackageDropNameFormat, targetPackage.Version));
                    if (await StandaloneUtility.DownloadPackageAsync(targetPackage.Version, targetPackage.TargetPackageLocation, packageLocalDownloadPath).ConfigureAwait(false))
                    {
                        try
                        {
                            this.traceSource.WriteInfo(TraceType, "Copying and provisioning version {0} from {1}.", targetPackage.Version, packageLocalDownloadPath);
                            await ProvisionPackageAsync(targetPackage.Version, packageLocalDownloadPath, cancellationToken).ConfigureAwait(false);
                        }
                        catch (Exception ex)
                        {
                            this.traceSource.WriteError(TraceType, "ProvisionPackageAsync for {0}, package {1} threw: {2}", targetPackage.Version, packageLocalDownloadPath, ex.ToString());
                        }
                    }
                }

                // Determine if current version is latest/doesn't have expiry date. If package expiring, post cluster health warning.
                PackageDetails currentPackage = model.Packages.Where(package => package.Version == currentVersionStr).FirstOrDefault();
                if (currentPackage != null && currentPackage.SupportExpiryDate != null && !currentPackage.IsGoalPackage && !this.IsAutoupgradeInstallEnabled() && this.IsPackageNearExpiry(currentPackage))
                {
                    this.traceSource.WriteWarning(TraceType, "Current version {0} expires {1}; emitting cluster warning.", currentVersionStr, currentPackage.SupportExpiryDate);
                    this.EmitClusterVersionSupportedHealth(fabricClient, false, currentVersionStr, currentPackage.SupportExpiryDate);
                }
                else
                {
                    this.traceSource.WriteInfo(TraceType, "Current version {0} is supported. Cluster health OK.", currentVersionStr);
                    this.EmitClusterVersionSupportedHealth(fabricClient, true, null, null);
                }

                if (targetPackage != null &&
                    !string.IsNullOrEmpty(targetPackage.Version) &&
                    this.IsAutoupgradeInstallEnabled())
                {
                    try
                    {
                        // fire off an upgrade.
                        this.StartCodeUpgrade(targetPackage.Version, fabricClient);
                    }
                    catch (Exception ex)
                    {
                        this.traceSource.WriteError(TraceType, "StartCodeUpgrade for version {0} threw: {1}", targetPackage.Version, ex.ToString());
                    }
                }
            }
            finally
            {
                if (Directory.Exists(packageDropDir))
                {
                    try
                    {
                        FabricDirectory.Delete(packageDropDir, true, true);
                    }
                    catch
                    {
                    }
                }
            }
        }
Пример #3
0
        private static bool IsVersionUpgradeable(string version, GoalStateModel model)
        {
            PackageDetails package = model.Packages.Find(p => p.Version == version);

            return(package == null || !package.IsUpgradeDisabled);
        }
Пример #4
0
        public void DeploymentManagerTest_ProductionGoalState()
        {
            Console.WriteLine("test begins: {0}", DateTime.UtcNow);

            string goalStateFilepath = Path.Combine(BaseDir, GoalStateFilename);

            Assert.IsTrue(File.Exists(goalStateFilepath), string.Format("GoalStateFile {0} did not exist.", goalStateFilepath));
            string         goalStateJson = File.ReadAllText(goalStateFilepath);
            GoalStateModel model         = GoalStateModel.GetGoalStateModelFromJson(goalStateJson);

            Assert.IsTrue(model != null, "Goal state JSON could not be deserialized.");
            Assert.IsTrue(model.Packages != null, "Goal state model must have a packages element.");

            if (model.Packages.Count() == 0)
            {
                return;
            }

            // There can only be one goal package
            int countGoalpackages = model.Packages.Where(package => package.IsGoalPackage).Count();

            Assert.IsTrue(countGoalpackages == 1, "Exactly one goal package may be marked as IsGoalPackage in the goal state file.");

            // Validate each package link is reachable
            string errorMessage = string.Empty;

            foreach (PackageDetails package in model.Packages)
            {
                Uri packageUri;
                if (!Uri.TryCreate(package.TargetPackageLocation, UriKind.Absolute, out packageUri))
                {
                    errorMessage = string.Format("Cannot parse packageUri: {0}", package.TargetPackageLocation);
                    Assert.Fail(errorMessage);
                }

                if (!StandaloneUtility.IsUriReachable(packageUri))
                {
                    errorMessage = string.Format("Package uri is not reachable: {0}", packageUri.AbsoluteUri);
                }
            }

            if (!string.IsNullOrEmpty(errorMessage))
            {
                Assert.Fail(errorMessage);
            }

            // Validate that goal state downloaded package is the correct version
            string         packageDropDir = System.Fabric.Common.Helpers.GetNewTempPath();
            PackageDetails goalPackage    = model.Packages.First(package => package.IsGoalPackage);

            Assert.IsTrue(goalPackage != null, "goalPackage null");

            // Validate package downloadable
            Console.WriteLine("download begins for {0}: {1}", goalPackage.Version, DateTime.UtcNow);
            string packageLocalDownloadPath = Path.Combine(packageDropDir, string.Format(Microsoft.ServiceFabric.DeploymentManager.Constants.SFPackageDropNameFormat, goalPackage.Version));
            bool   packageDownloaded        = StandaloneUtility.DownloadPackageAsync(goalPackage.Version, goalPackage.TargetPackageLocation, packageLocalDownloadPath).Result;

            Assert.IsTrue(packageDownloaded, string.Format("Package {0} failed to download from {1}.", goalPackage.Version, goalPackage.TargetPackageLocation));

            // Validate downloaded package matches version of version in goal state file
            string cabVersion = CabFileOperations.GetCabVersion(packageLocalDownloadPath);

            Assert.IsTrue(goalPackage.Version == cabVersion, string.Format("Goal state package version {0} doesn't match downloaded package version {1}.", goalPackage.Version, cabVersion));

            if (Directory.Exists(packageDropDir))
            {
                try
                {
                    FabricDirectory.Delete(packageDropDir, true, true);
                }
                catch { }
            }

            Console.WriteLine("test ends: {0}", DateTime.UtcNow);
        }