Beispiel #1
0
        public ConfigurationUpgradeFabricRequest(IFabricClient fabricClient, ConfigurationUpgradeDescription upgradeDescription, TimeSpan timeout)
            : base(fabricClient, timeout)
        {
            ThrowIf.Null(upgradeDescription, "upgradeDescription");

            this.UpgradeDescription = upgradeDescription;
            this.ConfigureErrorCodes();
        }
Beispiel #2
0
        public void ConfigurationUpgradeDescription_ParseTest()
        {
            ConfigurationUpgradeDescription expected = HelperInstance.CreateDefaultDescription();

            using (var pc = new PinCollection())
            {
                IntPtr native = expected.ToNative(pc);

                ConfigurationUpgradeDescription actual = ConfigurationUpgradeDescription.CreateFromNative(native);

                HelperInstance.Compare(expected, actual);
            }
        }
        public NativeCommon.IFabricAsyncOperationContext BeginUpgradeConfiguration(IntPtr startUpgradeDescription, uint timeoutMilliseconds, NativeCommon.IFabricAsyncOperationCallback callback)
        {
            var managedStartUpgradeDescription = ConfigurationUpgradeDescription.CreateFromNative(startUpgradeDescription);

            TimeSpan managedTimeout = TimeSpan.FromMilliseconds(timeoutMilliseconds);

            return(Utility.WrapNativeAsyncMethodImplementation(
                       (cancellationToken) =>
                       this.StartClusterConfigurationUpgradeAsync(
                           managedStartUpgradeDescription,
                           managedTimeout,
                           cancellationToken),
                       callback,
                       "UpgradeOrchestrationServiceBroker.StartClusterConfigurationUpgrade",
                       ThreadErrorMessageSetter));
        }
Beispiel #4
0
        public void ConfigUpgradeDescConstructorTest()
        {
            ConfigurationUpgradeDescription desc = new ConfigurationUpgradeDescription();

            Assert.AreEqual(null, desc.ClusterConfiguration);
            Assert.AreEqual(TimeSpan.FromSeconds(600), desc.HealthCheckRetryTimeout);
            Assert.AreEqual(TimeSpan.Zero, desc.HealthCheckStableDuration);
            Assert.AreEqual(TimeSpan.Zero, desc.HealthCheckWaitDuration);
            Assert.AreEqual(0, desc.MaxPercentDeltaUnhealthyNodes);
            Assert.AreEqual(0, desc.MaxPercentUnhealthyApplications);
            Assert.AreEqual(0, desc.MaxPercentUnhealthyNodes);
            Assert.AreEqual(0, desc.MaxPercentUpgradeDomainDeltaUnhealthyNodes);
            Assert.AreEqual(TimeSpan.MaxValue, desc.UpgradeDomainTimeout);
            Assert.AreEqual(TimeSpan.MaxValue, desc.UpgradeTimeout);

            Console.WriteLine(desc.ToStringDescription());
        }
        public async Task StartClusterConfigurationUpgrade(
            ConfigurationUpgradeDescription configurationUpgradeDescription,
            TimeSpan timeout,
            CancellationToken cancellationToken)
        {
            UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "Enter StartClusterConfigurationUpgrade.");
            UpgradeOrchestrationTrace.TraceSource.WriteInfo(
                TraceType,
                "startUpgradeDescription: {0}",
                configurationUpgradeDescription.ClusterConfiguration);

            try
            {
                await this.MessageProcessor.ProcessStartClusterConfigurationUpgradeAsync(configurationUpgradeDescription, timeout, cancellationToken);
            }
            catch (Exception e)
            {
                UpgradeOrchestrationTrace.TraceSource.WriteWarning(TraceType, "{0} - Exception occurred", e);
                throw;
            }

            UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "Exit StartClusterConfigurationUpgrade.");
        }
 private Task StartClusterConfigurationUpgradeAsync(ConfigurationUpgradeDescription startUpgradeDescription, TimeSpan timeout, CancellationToken cancellationToken)
 {
     return(this.service.StartClusterConfigurationUpgrade(startUpgradeDescription, timeout, cancellationToken));
 }
        public async Task ProcessStartClusterConfigurationUpgradeAsync(ConfigurationUpgradeDescription configUpgradeDesc, TimeSpan timeout, CancellationToken cancellationToken)
        {
            /* The cancellation token passed in this API call is not used (by design). This token corresponds to the client side call.
             * The global this.cancellationToken is initialised in RunAsync() and is honored in every API call. */

            UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "Entering ProcessStartUpgradeAsync.");
            try
            {
                UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "Deserializing input json config string.");
                StandAloneInstallerJsonModelBase targetJsonConfig = StandAloneInstallerJsonModelBase.GetJsonConfigFromString(configUpgradeDesc.ClusterConfiguration);
                if (targetJsonConfig == null)
                {
                    throw new ArgumentException("The input cluster configuration is not in a valid json format or supported apiVersion.");
                }

                UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "Retrieve current cluster resource from StoreManager.");
                StandAloneCluster cluster = await this.storeManager.GetClusterResourceAsync(
                    Constants.ClusterReliableDictionaryKey, this.cancellationToken).ConfigureAwait(false);

                bool isInDataLossState = await DatalossHelper.IsInDatalossStateAsync(this.cancellationToken).ConfigureAwait(false);

                if (!isInDataLossState)
                {
                    if (cluster == null || cluster.Current == null)
                    {
                        UpgradeOrchestrationTrace.TraceSource.WriteWarning(TraceType, "Persisted cluster resource is not ready: {0}", cluster == null ? "null" : "current = null");
                        throw new FabricException("UpgradeOrchestrationService is not ready.");
                    }

                    UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "Setting target config and topology based on new input json config.");

                    if (cluster.Pending != null && !this.IsInterruptibleAsync(cluster.Pending).Result)
                    {
                        throw new FabricException(string.Format("Cluster configuration upgrade of type {0} is already in progress and cannot be interrupted.", cluster.Pending.GetType().Name));
                    }

                    StandaloneSettingsValidator validator = new StandaloneSettingsValidator(targetJsonConfig);

                    await UpgradeOrchestrationMessageProcessor.ValidateModel(targetJsonConfig, validator, cluster, true).ConfigureAwait(false);

                    var removedNodes = validator.GetRemovedNodes(cluster.Topology);
                    var addedNodes   = validator.GetAddedNodes(cluster.Topology);

                    if (addedNodes.Any() && StandaloneUtility.CheckFabricRunningAsGMSA(cluster.Current.CSMConfig))
                    {
                        /* Need to resolve assembly so that FabricDeployer can load the right binaries from FabricCodePath since not all binaries required by FabricDeployer are present in UOS.Current folder.*/
                        AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(this.LoadFromFabricCodePath);
                        try
                        {
                            await this.PerformAddNodeOperationGMSAAsync(addedNodes, this.fabricClient, validator.ClusterProperties.NodeTypes).ConfigureAwait(false);
                        }
                        catch (AggregateException ex)
                        {
                            UpgradeOrchestrationTrace.TraceSource.WriteError(TraceType, "Adding nodes for GMSA scenario failed with exception: {0}", ex);
                            throw;
                        }
                        finally
                        {
                            AppDomain.CurrentDomain.AssemblyResolve -= new ResolveEventHandler(this.LoadFromFabricCodePath);
                        }
                    }

                    if (addedNodes.Any())
                    {
                        cluster.TargetNodeConfig = GetTargetNodeConfigAddNode(validator.Topology, cluster.Current.NodeConfig.Version);
                    }

                    if (removedNodes.Any())
                    {
                        cluster.TargetNodeConfig = GetTargetNodeConfigRemoveNode(cluster.Topology, removedNodes, cluster.Current.NodeConfig.Version);
                    }
                    else
                    {
                        cluster.Topology = validator.Topology;
                    }

                    cluster.TargetCsmConfig = validator.ClusterProperties;

                    // Cluster is updated above so persist it.
                    await this.storeManager.PersistClusterResourceAsync(Constants.ClusterReliableDictionaryKey, cluster, cancellationToken).ConfigureAwait(false);

                    await this.UpdatePersistedCodeUpgradePackage(validator).ConfigureAwait(false);

                    UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "Invoking Orchestrator");

                    await this.orchestrator.StartUpgradeAsync(cluster, this.cancellationToken, configUpgradeDesc).ContinueWith(t =>
                    {
                        if (t.Exception != null)
                        {
                            UpgradeOrchestrationTrace.TraceSource.WriteWarning(TraceType, "Orchestrator completed with status: {0} exception: {1}", t.Status, t.Exception);
                        }
                        else
                        {
                            UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "Orchestrator completed with status: {0}", t.Status);
                        }
                    });
                }
                else
                {
                    StandaloneSettingsValidator validator = new StandaloneSettingsValidator(targetJsonConfig);
                    await UpgradeOrchestrationMessageProcessor.ValidateModel(targetJsonConfig, validator, cluster, false).ConfigureAwait(false);

                    cluster = FabricUpgradeOrchestrationService.ConstructClusterFromJson(targetJsonConfig, FabricNativeConfigStore.FabricGetConfigStore());

                    DatalossHelper.DryRunConfigUpgrade(cluster);
                    await this.storeManager.PersistClusterResourceAsync(Constants.ClusterReliableDictionaryKey, cluster, this.cancellationToken);

                    await DatalossHelper.UpdateHeathStateAsync(isHealthy : true).ConfigureAwait(false);
                }
            }
            catch (Exception e)
            {
                UpgradeOrchestrationTrace.TraceSource.WriteWarning(TraceType, "ProcessStartUpgradeAsync exception: {0}", e);
                throw UpgradeOrchestrationMessageProcessor.ConvertToComException(e);
            }

            UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "Exiting ProcessStartUpgradeAsync.");
        }
        protected override void ProcessRecord()
        {
            var clusterConnection = this.GetClusterConnection();

            try
            {
                string clusterConfigAbsolutePath = GetAbsolutePath(this.ClusterConfigPath);
                string jsonConfigString          = File.ReadAllText(clusterConfigAbsolutePath);
                var    description = new ConfigurationUpgradeDescription
                {
                    ClusterConfiguration = jsonConfigString
                };

                if (this.HealthCheckRetryTimeoutSec.HasValue)
                {
                    description.HealthCheckRetryTimeout = TimeSpan.FromSeconds(this.HealthCheckRetryTimeoutSec.Value);
                }

                if (this.HealthCheckWaitDurationSec.HasValue)
                {
                    description.HealthCheckWaitDuration = TimeSpan.FromSeconds(this.HealthCheckWaitDurationSec.Value);
                }

                if (this.HealthCheckStableDurationSec.HasValue)
                {
                    description.HealthCheckStableDuration = TimeSpan.FromSeconds(this.HealthCheckStableDurationSec.Value);
                }

                if (this.UpgradeDomainTimeoutSec.HasValue)
                {
                    description.UpgradeDomainTimeout = TimeSpan.FromSeconds(this.UpgradeDomainTimeoutSec.Value);
                }

                if (this.UpgradeTimeoutSec.HasValue)
                {
                    description.UpgradeTimeout = TimeSpan.FromSeconds(this.UpgradeTimeoutSec.Value);
                }

                description.MaxPercentUnhealthyApplications =
                    this.MaxPercentUnhealthyApplications ?? description.MaxPercentUnhealthyApplications;

                description.MaxPercentUnhealthyNodes =
                    this.MaxPercentUnhealthyNodes ?? description.MaxPercentUnhealthyNodes;

                description.MaxPercentDeltaUnhealthyNodes =
                    this.MaxPercentDeltaUnhealthyNodes ?? description.MaxPercentDeltaUnhealthyNodes;

                description.MaxPercentUpgradeDomainDeltaUnhealthyNodes =
                    this.MaxPercentUpgradeDomainDeltaUnhealthyNodes ?? description.MaxPercentUpgradeDomainDeltaUnhealthyNodes;

                if (this.ApplicationHealthPolicies != null)
                {
                    foreach (var entry in this.ApplicationHealthPolicies)
                    {
                        description.ApplicationHealthPolicies.Add(entry.Key, entry.Value);
                    }
                }

                clusterConnection.StartClusterConfigurationUpgradeAsync(
                    description,
                    this.GetTimeout(),
                    this.GetCancellationToken()).Wait();
            }
            catch (AggregateException aggregateException)
            {
                aggregateException.Handle((ae) =>
                {
                    this.ThrowTerminatingError(
                        ae,
                        Constants.StartClusterConfigurationUpgradeErrorId,
                        clusterConnection);
                    return(true);
                });
            }
        }