public async Task <string> ProcessSetUpgradeOrchestrationServiceStateAsync(string inputBlob, TimeSpan timeout, CancellationToken cancellationToken)
        {
            UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "Entering ProcessSetUpgradeOrchestrationServiceStateAsync.");
            try
            {
                // data validation
                StandAloneCluster cluster = null;
                if (!string.IsNullOrWhiteSpace(inputBlob))
                {
                    JsonSerializerSettings settings = StandaloneUtility.GetStandAloneClusterDeserializerSettings();

                    cluster = JsonConvert.DeserializeObject <StandAloneCluster>(
                        inputBlob,
                        settings);
                }

                await this.storeManager.SetStorageObjectAsync(Constants.ClusterReliableDictionaryKey, inputBlob, this.cancellationToken).ConfigureAwait(false);

                FabricUpgradeOrchestrationServiceState result = UpgradeOrchestrationMessageProcessor.ConstructServiceStateFromCluster(cluster);

                return(JsonConvert.SerializeObject(
                           result,
                           new JsonSerializerSettings
                {
                    ReferenceLoopHandling = ReferenceLoopHandling.Serialize,
                    NullValueHandling = NullValueHandling.Ignore,
                }));
            }
            catch (Exception e)
            {
                UpgradeOrchestrationTrace.TraceSource.WriteWarning(TraceType, "ProcessSetUpgradeOrchestrationServiceStateAsync exception: {0}", e);
                throw UpgradeOrchestrationMessageProcessor.ConvertToComException(e);
            }
        }
        public async Task <string> CallSystemService(string action, string inputBlob, TimeSpan timeout, CancellationToken cancellationToken)
        {
            string outputBlob = null;

            try
            {
                UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "Enter CallSystemService for {0}.", action);

                if (this.actionMapping.ContainsKey(action))
                {
                    outputBlob = await this.actionMapping[action](inputBlob, timeout, cancellationToken).ConfigureAwait(false);
                }
                else
                {
                    throw UpgradeOrchestrationMessageProcessor.ConvertToComException(new NotImplementedException(action + "is not implemented"));
                }
            }
            catch (Exception e)
            {
                UpgradeOrchestrationTrace.TraceSource.WriteWarning(TraceType, "CallSystemService error: {0}", e);
                throw;
            }

            UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "Exit CallSystemService for {0}.", action);
            return(outputBlob);
        }
        internal FabricUpgradeOrchestrationService(StatefulServiceContext serviceContext, string endpoint, bool enableEndpointV2)
            : base(
                serviceContext,
                new ReliableStateManager(
                    serviceContext,
                    new ReliableStateManagerConfiguration(
                        GetReplicatorSettings(endpoint, enableEndpointV2))))
        {
            this.endpoint         = endpoint;
            this.enableEndpointV2 = enableEndpointV2;
            this.fabricClient     = new FabricClient();
            this.storeManager     = new StoreManager(this.StateManager);
            this.Orchestrator     = new UpgradeOrchestrator(this.storeManager, this, this.fabricClient);

            this.messageProcessor = new UpgradeOrchestrationMessageProcessor(
                this.storeManager,
                this.fabricClient,
                this.Orchestrator,
                new CancellationToken(canceled: false));

            UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "FabricUpgradeOrchestrationService constructor: enableEndpointV2 is {0}", this.enableEndpointV2);

            if (this.enableEndpointV2)
            {
                this.clusterEndpointSecuritySettingsChangeNotifier = new ClusterEndpointSecuritySettingsChangeNotifier(this.endpoint, this.UpdateReplicatorSettings);
            }

            AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(OnResolveAssemblyFailed);
        }
        public async Task <string> ProcessGetClusterConfigurationAsync(string apiVersion, TimeSpan timeout, CancellationToken cancellationToken)
        {
            UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "Entering ProcessGetClusterConfigurationAsync.");
            try
            {
                UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "Retrieve current cluster resource from StoreManager.");
                StandAloneCluster cluster = await this.storeManager.GetClusterResourceAsync(
                    Constants.ClusterReliableDictionaryKey, this.cancellationToken).ConfigureAwait(false);

                if (cluster == null || cluster.Current == null)
                {
                    // read from fabric data root
                    string fabricDataRoot = FabricEnvironment.GetDataRoot();
                    string jsonConfigPath = Path.Combine(fabricDataRoot, System.Fabric.FabricDeployer.Constants.FileNames.BaselineJsonClusterConfig); // TODO: Needs to come from image store
                    return(File.ReadAllText(jsonConfigPath));
                }
                else
                {
                    var      nodesFromFM = new Dictionary <string, NodeDescription>();
                    NodeList nodes       = await StandaloneUtility.GetNodesFromFMAsync(this.fabricClient, this.cancellationToken).ConfigureAwait(false);

                    for (int i = 0; i < nodes.Count; ++i)
                    {
                        if (nodes[i].NodeStatus != System.Fabric.Query.NodeStatus.Invalid && !UpgradeOrchestrationMessageProcessor.IsGhostNode(nodes[i]))
                        {
                            NodeDescription nodeDesc = new NodeDescription()
                            {
                                FaultDomain   = nodes[i].FaultDomain.ToString(),
                                UpgradeDomain = nodes[i].UpgradeDomain,
                                IPAddress     = nodes[i].IpAddressOrFQDN,
                                NodeTypeRef   = nodes[i].NodeType,
                                NodeName      = nodes[i].NodeName
                            };
                            nodesFromFM.Add(nodes[i].NodeName, nodeDesc);
                        }
                    }

                    cluster.Topology.Nodes = nodesFromFM;

                    UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "Construct StandAloneJsonModel from current cluster resource.");
                    var jsonModel = StandAloneInstallerJsonModelBase.ConstructByApiVersion(cluster.Current.CSMConfig, cluster.Topology, cluster.Current.CSMConfig.Version.Version, apiVersion);
                    UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "Serializing current json model.");
                    var serializerSettings = new JsonSerializerSettings
                    {
                        Formatting                 = Formatting.Indented,
                        NullValueHandling          = NullValueHandling.Ignore,
                        PreserveReferencesHandling = PreserveReferencesHandling.None
                    };
                    serializerSettings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());
                    return(JsonConvert.SerializeObject(jsonModel, serializerSettings));
                }
            }
            catch (Exception e)
            {
                UpgradeOrchestrationTrace.TraceSource.WriteWarning(TraceType, "ProcessStartUpgradeAsync exception: {0}", e);
                throw UpgradeOrchestrationMessageProcessor.ConvertToComException(e);
            }
        }
 public async Task <string> ProcessGetUpgradeOrchestrationServiceStateAsync(string inputBlob, TimeSpan timeout, CancellationToken cancellationToken)
 {
     UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "Entering ProcessGetUpgradeOrchestrationServiceStateAsync.");
     try
     {
         UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "Retrieve current cluster resource object from StoreManager.");
         return(await this.storeManager.GetStorageObjectAsync(
                    Constants.ClusterReliableDictionaryKey, this.cancellationToken).ConfigureAwait(false));
     }
     catch (Exception e)
     {
         UpgradeOrchestrationTrace.TraceSource.WriteWarning(TraceType, "ProcessGetUpgradeOrchestrationServiceStateAsync exception: {0}", e);
         throw UpgradeOrchestrationMessageProcessor.ConvertToComException(e);
     }
 }
        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.");
        }
 public UpgradeOrchestrationServiceImpl(UpgradeOrchestrationMessageProcessor messageProcessor)
 {
     this.MessageProcessor = messageProcessor;
     this.LoadActionMapping();
 }