public override ServiceGroupDescription Build()
            {
                this.ServiceGroupDescription = new ServiceGroupDescription();
                var statefulServiceDescription = new StatefulServiceDescription
                {
                    HasPersistedState    = this.HasPersistentState,
                    TargetReplicaSetSize = this.TargetReplicaSetSize,
                    MinReplicaSetSize    = this.MinReplicaSetSize
                };

                if (this.ReplicaRestartWaitDuration.HasValue)
                {
                    statefulServiceDescription.ReplicaRestartWaitDuration = this.ReplicaRestartWaitDuration.Value;
                }

                if (this.QuorumLossWaitDuration.HasValue)
                {
                    statefulServiceDescription.QuorumLossWaitDuration = this.QuorumLossWaitDuration.Value;
                }

                this.ServiceGroupDescription.ServiceDescription = statefulServiceDescription;

                if (this.Metrics != null)
                {
                    foreach (var str in this.Metrics)
                    {
                        this.ServiceGroupDescription.ServiceDescription.Metrics.Add(ServiceCmdletBase.ParseStatefulMetric(str));
                    }
                }

                return(base.Build());
            }
Пример #2
0
        /// <summary>
        /// Provisions a new backend and name it uniquely according to the name in param
        /// </summary>
        /// <param name="backendName"></param>
        /// <returns></returns>
        public async Task ProvisionNewBackend(string backendName)
        {
            Uri serviceName     = new Uri($"{m_appName}/{backendName}");
            var applicationName = new Uri(m_appName);
            var payload         = backendName;
            StatefulServiceDescription serviceDescription = new StatefulServiceDescription()
            {
                ApplicationName              = applicationName,
                ServiceTypeName              = "LogicEngineType",
                ServiceName                  = serviceName,
                PartitionSchemeDescription   = new UniformInt64RangePartitionSchemeDescription(3, 0, 2),//TODO read from config
                ServicePackageActivationMode = ServicePackageActivationMode.ExclusiveProcess,
                HasPersistedState            = true,
                MinReplicaSetSize            = 1,
                TargetReplicaSetSize         = 1
            };

            //launch service
            try
            {
                using (var fabricClient = new FabricClient())
                {
                    await fabricClient.ServiceManager.CreateServiceAsync(serviceDescription);
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }
Пример #3
0
        public async Task WaitForStatefulService(Uri serviceInstanceUri)
        {
            StatefulServiceDescription description =
                await this.Client.ServiceManager.GetServiceDescriptionAsync(serviceInstanceUri) as StatefulServiceDescription;

            int targetTotalReplicas = description.TargetReplicaSetSize;

            if (description.PartitionSchemeDescription is UniformInt64RangePartitionSchemeDescription)
            {
                targetTotalReplicas *= ((UniformInt64RangePartitionSchemeDescription)description.PartitionSchemeDescription).PartitionCount;
            }

            ServicePartitionList partitions = await this.Client.QueryManager.GetPartitionListAsync(serviceInstanceUri);

            int replicaTotal = 0;

            while (replicaTotal < targetTotalReplicas)
            {
                await Task.Delay(this.interval);

                //ServiceEventSource.Current.ServiceMessage(this, "CountyService waiting for National Service to come up.");

                replicaTotal = 0;
                foreach (Partition partition in partitions)
                {
                    ServiceReplicaList replicaList = await this.Client.QueryManager.GetReplicaListAsync(partition.PartitionInformation.Id);

                    replicaTotal += replicaList.Count(x => x.ReplicaStatus == System.Fabric.Query.ServiceReplicaStatus.Ready);
                }
            }
        }
Пример #4
0
        public async Task <IActionResult> Put(string name)
        {
            StatefulServiceDescription serviceDescription = new StatefulServiceDescription()
            {
                ApplicationName            = new Uri(this.applicationName),
                MinReplicaSetSize          = 3,
                TargetReplicaSetSize       = 3,
                PartitionSchemeDescription = new SingletonPartitionSchemeDescription(),
                HasPersistedState          = true,
                ServiceTypeName            = Constants.TOPIC_SERVICE_TYPE_NAME,
                ServiceName = this.serviceContext.CreateTopicUri(name)
            };

            try
            {
                await fabric.ServiceManager.CreateServiceAsync(serviceDescription);
            }
            catch (FabricElementAlreadyExistsException)
            {
                //idempotent so return 200
                return(Ok());
            }

            return(Ok());
        }
Пример #5
0
        public Task Post(string jobName, string parameters)
        {
            string applicationName = this.context.CodePackageActivationContext.ApplicationName;


            StatefulServiceDescription serviceDescription = new StatefulServiceDescription()
            {
                ApplicationName            = new Uri(applicationName),
                MinReplicaSetSize          = 3,
                TargetReplicaSetSize       = 3,
                PartitionSchemeDescription = new UniformInt64RangePartitionSchemeDescription()
                {
                    LowKey         = 0,
                    HighKey        = 10,
                    PartitionCount = 1
                },
                HasPersistedState  = true,
                InitializationData = Encoding.UTF8.GetBytes(parameters),
                ServiceTypeName    = "JobServiceType",
                ServiceName        = new Uri($"{applicationName}/jobs/{jobName}")
            };

            //try
            //{
            return(fabricClient.ServiceManager.CreateServiceAsync(serviceDescription));
            //    return Task.FromResult(true);
            //}
            //catch(Exception e)
            //{
            //return Task.FromResult(false);

            //}
        }
        protected override void ProcessRecord()
        {
            PartitionSchemeDescription partitionSchemeDescription;
            ServiceDescription         serviceDescription;
            var client = new ServiceFabricClientBuilder().ConnectAsync(ClusterEndPoint, ThumbPrint).Result;

            if (PartitionSchemeUniformInt64)
            {
                partitionSchemeDescription = new UniformInt64RangePartitionSchemeDescription(PartitionCount, LowKey.ToString(), HighKey.ToString());
            }
            else if (PartitionSchemeNamed)
            {
                partitionSchemeDescription = new NamedPartitionSchemeDescription(PartitionCount, PartitionNames);
            }
            else
            {
                partitionSchemeDescription = new SingletonPartitionSchemeDescription();
            }

            if (Stateless.IsPresent)
            {
                serviceDescription = new StatelessServiceDescription(new ServiceName(ServiceName), ServiceType, partitionSchemeDescription, InstanceCount, initializationData: InitializationData);
            }
            else
            {
                serviceDescription = new StatefulServiceDescription(new ServiceName(ServiceName), ServiceType, partitionSchemeDescription, TargetReplicaSetSize, MinReplicaSetSize, PersistedState, initializationData: InitializationData);
            }

            client.Services.CreateServiceAsync(ApplicationId, serviceDescription).Wait();
        }
Пример #7
0
        /// <summary>
        /// Provisions a new backend and name it uniquely according to the name in param
        /// </summary>
        /// <param name="backendName"></param>
        /// <returns></returns>
        public async Task ProvisionNewBackend(string backendName)
        {
            Uri serviceName     = new Uri($"{m_appName}/{backendName}");
            var applicationName = new Uri(m_appName);
            StatefulServiceDescription serviceDescription = new StatefulServiceDescription()
            {
                ApplicationName              = applicationName,
                ServiceTypeName              = "Stateful.BackendType",
                ServiceName                  = serviceName,
                PartitionSchemeDescription   = new SingletonPartitionSchemeDescription(),
                HasPersistedState            = true,
                MinReplicaSetSize            = 3,
                TargetReplicaSetSize         = 3,
                ServicePackageActivationMode = ServicePackageActivationMode.ExclusiveProcess
            };

            //launch service
            try
            {
                using (var fabricClient = new FabricClient())
                {
                    await fabricClient.ServiceManager.CreateServiceAsync(serviceDescription);
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }
        public async Task <IActionResult> Post(string reportName)
        {
            // Now create the data service in the new application instance.
            StatefulServiceDescription dataServiceDescription = new StatefulServiceDescription()
            {
                ApplicationName            = new Uri(this.serviceContext.CodePackageActivationContext.ApplicationName),
                HasPersistedState          = true,
                MinReplicaSetSize          = 3,
                TargetReplicaSetSize       = 3,
                PartitionSchemeDescription = new SingletonPartitionSchemeDescription(),
                ServiceName     = this.GetServiceName(reportName),
                ServiceTypeName = ReportProcessingServiceTypeName,
                ServicePackageActivationMode = ServicePackageActivationMode.ExclusiveProcess
            };

            try
            {
                await this.fabricClient.ServiceManager.CreateServiceAsync(dataServiceDescription, this.operationTimeout, this.appLifetime.ApplicationStopping);

                return(this.Ok());
            }
            catch (FabricElementAlreadyExistsException)
            {
                return(new ContentResult()
                {
                    StatusCode = 400, Content = $"Service for report '{reportName}' already exists."
                });
            }
        }
Пример #9
0
        internal StatefulServiceDescription GetStatefulDescription(Job j)
        {
            var ser = JsonSerializer.Create();

            var sw = new StringWriter();

            ser.Serialize(sw, j);

            var desc = new StatefulServiceDescription()
            {
                ApplicationName            = new Uri("fabric:/Compute2"),
                DefaultMoveCost            = MoveCost.High,
                ServiceName                = new Uri(string.Format("fabric:/Compute2/ComputeInstance{0}", System.DateTime.Now.Ticks)),
                ServiceTypeName            = "StatefulComputeServiceType",
                HasPersistedState          = true,
                PartitionSchemeDescription = new SingletonPartitionSchemeDescription(),
                TargetReplicaSetSize       = 3,
                MinReplicaSetSize          = 2,
                InitializationData         = Encoding.UTF8.GetBytes(sw.ToString())
            };

            var metric = new StatefulServiceLoadMetricDescription()
            {
                PrimaryDefaultLoad   = 1,
                SecondaryDefaultLoad = 0,
                Name   = "TCU",
                Weight = ServiceLoadMetricWeight.Medium
            };

            desc.Metrics.Add(metric);

            return(desc);
        }
Пример #10
0
        public async Task <IActionResult> Post(string reportName)
        {
            int power      = this.random.Next(2, 7);
            int multiplier = (int)Math.Pow(2, power);

            // Now create the data service in the new application instance.
            StatefulServiceDescription dataServiceDescription = new StatefulServiceDescription()
            {
                ApplicationName            = new Uri(this.serviceContext.CodePackageActivationContext.ApplicationName),
                HasPersistedState          = true,
                MinReplicaSetSize          = 3,
                TargetReplicaSetSize       = 3,
                PartitionSchemeDescription = new SingletonPartitionSchemeDescription(),
                ServiceName     = this.GetServiceName(reportName),
                ServiceTypeName = ReportProcessingServiceTypeName,
                ServicePackageActivationMode = ServicePackageActivationMode.ExclusiveProcess,
                InitializationData           = BitConverter.GetBytes(multiplier)
            };

            dataServiceDescription.Metrics.Add(new StatefulServiceLoadMetricDescription()
            {
                Name = "ProcessingCapacity",
                PrimaryDefaultLoad   = multiplier,
                SecondaryDefaultLoad = multiplier,
                Weight = ServiceLoadMetricWeight.High
            });

            dataServiceDescription.Metrics.Add(new StatefulServiceLoadMetricDescription()
            {
                Name = "CPU",
                PrimaryDefaultLoad   = 0,
                SecondaryDefaultLoad = 0,
                Weight = ServiceLoadMetricWeight.Medium
            });

            dataServiceDescription.Metrics.Add(new StatefulServiceLoadMetricDescription()
            {
                Name = "MemoryMB",
                PrimaryDefaultLoad   = multiplier,
                SecondaryDefaultLoad = multiplier,
                Weight = ServiceLoadMetricWeight.Medium
            });

            try
            {
                await this.fabricClient.ServiceManager.CreateServiceAsync(dataServiceDescription, this.operationTimeout, this.appLifetime.ApplicationStopping);

                return(this.Ok());
            }
            catch (FabricElementAlreadyExistsException)
            {
                return(new ContentResult()
                {
                    StatusCode = 400, Content = $"Service for report '{reportName}' already exists."
                });
            }
        }
        public async Task <IActionResult> Post([FromRoute] string name, [FromBody] EventsProcessorApplicationParams parameters)
        {
            // Determine the number of IoT Hub partitions.
            // The events processing service will be created with the same number of partitions.
            EventHubClient             eventHubClient = EventHubClient.CreateFromConnectionString(parameters.IotHubConnectionString, "messages/events");
            EventHubRuntimeInformation eventHubInfo   = await eventHubClient.GetRuntimeInformationAsync();

            // Application parameters are passed to the Events Processing application instance.
            NameValueCollection appInstanceParameters = new NameValueCollection();

            appInstanceParameters["IotHubConnectionString"]        = parameters.IotHubConnectionString;
            appInstanceParameters["IotHubProcessOnlyFutureEvents"] = parameters.IotHubProcessOnlyFutureEvents;
            appInstanceParameters["PublishDataServiceURLs"]        = parameters.PublishDataServiceURLs;

            ApplicationDescription application = new ApplicationDescription(
                new Uri($"{Names.EventsProcessorApplicationPrefix}/{name}"),
                Names.EventsProcessorApplicationTypeName,
                parameters.Version,
                appInstanceParameters);

            // Create a named application instance
            await this.fabricClient.ApplicationManager.CreateApplicationAsync(application, this.operationTimeout, this.appLifetime.ApplicationStopping);

            // Next, create named instances of the services that run in the application.
            ServiceUriBuilder serviceNameUriBuilder = new ServiceUriBuilder(application.ApplicationName.ToString(), Names.EventsProcessorRouterServiceName);

            StatefulServiceDescription service = new StatefulServiceDescription()
            {
                ApplicationName            = application.ApplicationName,
                HasPersistedState          = true,
                MinReplicaSetSize          = 3,
                TargetReplicaSetSize       = 3,
                PartitionSchemeDescription = new UniformInt64RangePartitionSchemeDescription(eventHubInfo.PartitionCount, 0, eventHubInfo.PartitionCount - 1),
                ServiceName     = serviceNameUriBuilder.Build(),
                ServiceTypeName = Names.EventsProcessorRouterServiceTypeName
            };

            await this.fabricClient.ServiceManager.CreateServiceAsync(service, this.operationTimeout, this.appLifetime.ApplicationStopping);

            if (parameters.PublishDataServiceURLs != null && parameters.PublishDataServiceURLs.Length > 0)
            {
                // Next, create named instances of the services that run in the application.
                serviceNameUriBuilder = new ServiceUriBuilder(application.ApplicationName.ToString(), Names.EventsProcessorExtenderServiceName);

                StatelessServiceDescription extenderService = new StatelessServiceDescription()
                {
                    ApplicationName            = application.ApplicationName,
                    InstanceCount              = 1,
                    PartitionSchemeDescription = new SingletonPartitionSchemeDescription(),
                    ServiceName     = serviceNameUriBuilder.Build(),
                    ServiceTypeName = Names.EventsProcessorExtenderServiceTypeName
                };

                await this.fabricClient.ServiceManager.CreateServiceAsync(extenderService, this.operationTimeout, this.appLifetime.ApplicationStopping);
            }
            return(this.Ok());
        }
        public Task <Job> DiagStateful(int replicas)
        {
            var j = new Job()
            {
                NodeName = "", // TODO
                Id       = Guid.NewGuid().ToString(),
                Status   = JobStatus.Waiting
            };

            var ser = JsonSerializer.Create();

            var sw = new StringWriter();

            ser.Serialize(sw, j);

            StatefulServiceDescription desc = new StatefulServiceDescription();

            try
            {
                FabricClient client = new FabricClient();


                desc.ApplicationName            = new Uri("fabric:/Compute2");
                desc.DefaultMoveCost            = MoveCost.High;
                desc.ServiceName                = new Uri(string.Format("fabric:/Compute2/EmptyStatefulInstance{0}", System.DateTime.Now.Ticks));
                desc.ServiceTypeName            = "EmptyServiceType";
                desc.PartitionSchemeDescription = new SingletonPartitionSchemeDescription();
                desc.TargetReplicaSetSize       = replicas;
                desc.MinReplicaSetSize          = 1;
                desc.HasPersistedState          = false;
                desc.InitializationData         = Encoding.UTF8.GetBytes(sw.ToString());
                var metric = new StatefulServiceLoadMetricDescription();
                metric.PrimaryDefaultLoad   = 1;
                metric.SecondaryDefaultLoad = 1;
                metric.Name   = "calc";
                metric.Weight = ServiceLoadMetricWeight.Medium;
                desc.Metrics.Add(metric);


                client.ServiceManager.CreateServiceAsync(desc).Wait();
                //ServiceEventSource.Current.ServiceMessage(this, string.Format("created on svc {0}", desc.ServiceName));
            }
            catch (Exception ex)
            {
                // CreateServiceAsync throws when there's no capacity for StatefulServices
                // Handle appropriately
                //ServiceEventSource.Current.ServiceMessage(this, string.Format("ERROR creating svc {0}, {1}", desc.ServiceName, ex.ToString()));

                Debug.WriteLine(ex.ToString());
                return(Task.FromResult(RecordErrorStatus(j)));
            }
            return(Task.FromResult <Job>(j));
        }
        public static StatefulServiceDescription GetCloneStateful(this StatefulServiceDescription other)
        {
            StatefulServiceDescription clone = new StatefulServiceDescription()
            {
                HasPersistedState    = other.HasPersistedState,
                MinReplicaSetSize    = other.MinReplicaSetSize,
                TargetReplicaSetSize = other.TargetReplicaSetSize,
            };

            clone.Metrics.AddRangeNullSafe(other.Metrics.Select(m => (m as StatefulServiceLoadMetricDescription).GetClone()));
            // Copy properties
            clone.CopyFrom(other);
            return(clone);
        }
Пример #14
0
        private bool TryCreateStatefulServiceDescription(out StatefulServiceDescription sd)
        {
            sd = null;
            try
            {
                sd = new StatefulServiceDescription();
                sd.ApplicationName = new Uri(this.control.Package.ApplicationAddress);
                sd.ServiceName     = new Uri(this.control.Package.ServiceAddress);
                sd.ServiceTypeName = this.control.Package.ServiceType;

                int minRep;
                if (!this.TryGetData("ServiceStatefulMinReplica", out minRep))
                {
                    return(false);
                }

                sd.MinReplicaSetSize = minRep;

                int tgtSize;
                if (!this.TryGetData("ServiceStatefulTargetReplica", out tgtSize))
                {
                    return(false);
                }

                sd.TargetReplicaSetSize = tgtSize;
                sd.HasPersistedState    = false;
                string hasPersistedValue;
                if (this.control.Package.Data.TryGetValue("ServiceStatefulPersisted", out hasPersistedValue))
                {
                    if (hasPersistedValue == "true")
                    {
                        sd.HasPersistedState = true;
                    }
                }

                PartitionSchemeDescription psd;
                if (!this.TryCreatePartitionDescription(out psd))
                {
                    return(false);
                }

                sd.PartitionSchemeDescription = psd;
                return(true);
            }
            catch (Exception e)
            {
                log.Error("failed to create StatelessServiceDescription, exception={0}", e.Message);
                return(false);
            }
        }
        public async Task <IActionResult> Post([FromRoute] string tenantName, [FromBody] InsightApplicationParams parameters)
        {
            // First create the application instance.
            // This won't actually create the services yet.
            ApplicationDescription application = new ApplicationDescription(
                new Uri($"{Names.InsightApplicationNamePrefix}/{tenantName}"),
                Names.InsightApplicationTypeName,
                parameters.Version);

            await this.fabricClient.ApplicationManager.CreateApplicationAsync(application, this.operationTimeout, this.appLifetime.ApplicationStopping);

            // Now create the data service in the new application instance.
            ServiceUriBuilder          dataServiceNameUriBuilder = new ServiceUriBuilder(application.ApplicationName.ToString(), Names.InsightDataServiceName);
            StatefulServiceDescription dataServiceDescription    = new StatefulServiceDescription()
            {
                ApplicationName            = application.ApplicationName,
                HasPersistedState          = true,
                MinReplicaSetSize          = 3,
                TargetReplicaSetSize       = 3,
                PartitionSchemeDescription = new UniformInt64RangePartitionSchemeDescription(parameters.DataPartitionCount, Int64.MinValue, Int64.MaxValue),
                ServiceName     = dataServiceNameUriBuilder.Build(),
                ServiceTypeName = Names.InsightDataServiceTypeName
            };

            await this.fabricClient.ServiceManager.CreateServiceAsync(dataServiceDescription, this.operationTimeout, this.appLifetime.ApplicationStopping);

            // And finally, create the web service in the new application instance.
            ServiceUriBuilder           webServiceNameUriBuilder = new ServiceUriBuilder(application.ApplicationName.ToString(), Names.InsightWebServiceName);
            StatelessServiceDescription webServiceDescription    = new StatelessServiceDescription()
            {
                ApplicationName            = application.ApplicationName,
                InstanceCount              = parameters.WebInstanceCount,
                PartitionSchemeDescription = new SingletonPartitionSchemeDescription(),
                ServiceName     = webServiceNameUriBuilder.Build(),
                ServiceTypeName = Names.InsightWebServiceTypeName
            };

            await this.fabricClient.ServiceManager.CreateServiceAsync(webServiceDescription, this.operationTimeout, this.appLifetime.ApplicationStopping);


            return(this.Ok());
        }
        public async Task<IActionResult> Post([FromRoute] string tenantName, [FromBody] TenantApplicationParams parameters)
        {
            // First create the application instance.
            // This won't actually create the services yet.
            ApplicationDescription application = new ApplicationDescription(
                new Uri($"{Names.TenantApplicationNamePrefix}/{tenantName}"),
                Names.TenantApplicationTypeName,
                parameters.Version);

            await this.fabricClient.ApplicationManager.CreateApplicationAsync(application, this.operationTimeout, this.serviceCancellationToken);

            // Now create the data service in the new application instance.
            ServiceUriBuilder dataServiceNameUriBuilder = new ServiceUriBuilder(application.ApplicationName.ToString(), Names.TenantDataServiceName);
            StatefulServiceDescription dataServiceDescription = new StatefulServiceDescription()
            {
                ApplicationName = application.ApplicationName,
                HasPersistedState = true,
                MinReplicaSetSize = 3,
                TargetReplicaSetSize = 3,
                PartitionSchemeDescription = new UniformInt64RangePartitionSchemeDescription(parameters.DataPartitionCount, Int64.MinValue, Int64.MaxValue),
                ServiceName = dataServiceNameUriBuilder.Build(),
                ServiceTypeName = Names.TenantDataServiceTypeName
            };

            await this.fabricClient.ServiceManager.CreateServiceAsync(dataServiceDescription, this.operationTimeout, this.serviceCancellationToken);

            // And finally, create the web service in the new application instance.
            ServiceUriBuilder webServiceNameUriBuilder = new ServiceUriBuilder(application.ApplicationName.ToString(), Names.TenantWebServiceName);
            StatelessServiceDescription webServiceDescription = new StatelessServiceDescription()
            {
                ApplicationName = application.ApplicationName,
                InstanceCount = parameters.WebInstanceCount,
                PartitionSchemeDescription = new SingletonPartitionSchemeDescription(),
                ServiceName = webServiceNameUriBuilder.Build(),
                ServiceTypeName = Names.TenantWebServiceTypeName
            };

            await this.fabricClient.ServiceManager.CreateServiceAsync(webServiceDescription, this.operationTimeout, this.serviceCancellationToken);


            return this.Ok();
        }
Пример #17
0
        private void TestHelper(Action <StatefulServiceDescription> setup)
        {
            var expected = HelperInstance.CreateDefaultDescription();

            if (setup != null)
            {
                setup(expected);
            }

            using (var pc = new PinCollection())
            {
                NativeTypes.FABRIC_SERVICE_DESCRIPTION_KIND kind;
                IntPtr native = expected.ToNative(pc, out kind);


                var actual = StatefulServiceDescription.CreateFromNative(native);

                Assert.AreEqual(NativeTypes.FABRIC_SERVICE_DESCRIPTION_KIND.FABRIC_SERVICE_DESCRIPTION_KIND_STATEFUL, kind);
                HelperInstance.Compare(expected, actual);
            }
        }
        public async Task <string> ExecuteTaskAsync([FromBody] Dictionary <string, string> parameters)
        {
            try
            {
                // No error checking - just trusting the TaskExecutorClient :-)
                string taskAssemblyPath = parameters["taskAssemblyPath"];
                string taskClassName    = parameters["taskClassName"];
                string taskParameters   = parameters["taskParameters"];

                // Generate unique service name based on the assembly directory.
                Uri serviceUri = GetServiceUri(Path.GetDirectoryName(taskAssemblyPath));
                using (var client = new FabricClient())
                {
                    Service service = await FindExistingServiceAsync(client, serviceUri);

                    if (service == null)
                    {
                        // Service not yet created - first request for a task from within the directory since the
                        // service started. We now create a new service instance with the unique directory-based name.
                        var description = new StatefulServiceDescription()
                        {
                            ApplicationName            = GetApplicationUri(),
                            ServiceName                = serviceUri,
                            ServiceTypeName            = "TaskExecutorActorServiceType",
                            HasPersistedState          = true,
                            PartitionSchemeDescription = new UniformInt64RangePartitionSchemeDescription()
                        };
                        await client.ServiceManager.CreateServiceAsync(description);
                    }
                }

                // Now delegate the execution to the service by calling the actor.
                var taskExecutorProxy = ActorProxy.Create <ITaskExecutorActor>(ActorId.CreateRandom(), serviceUri);
                return(await taskExecutorProxy.ExecuteTaskAsync(taskAssemblyPath, taskClassName, taskParameters));
            }
            catch (Exception ex)
            {
                return(ex.ToString());
            }
        }
Пример #19
0
        public async Task <IActionResult> Put(string topicName, string name)
        {
            ServiceList services = await this.fabric.QueryManager.GetServiceListAsync(new Uri(applicationName));

            try
            {
                Service topicService = services.Where(x => x.ServiceTypeName == Constants.TOPIC_SERVICE_TYPE_NAME &&
                                                      x.ServiceName.IsTopic(topicName)).Single();
            }
            catch (InvalidOperationException)
            {
                //Topic is not availible
                return(NotFound($"No topic found with name '{topicName}'.  Please create topic before adding subscription."));
            }

            StatefulServiceDescription serviceDescription = new StatefulServiceDescription()
            {
                ApplicationName            = new Uri(this.applicationName),
                MinReplicaSetSize          = 3,
                TargetReplicaSetSize       = 3,
                PartitionSchemeDescription = new SingletonPartitionSchemeDescription(),
                HasPersistedState          = true,
                InitializationData         = Encoding.UTF8.GetBytes(topicName),
                ServiceTypeName            = Constants.SUBSCRIBER_SERVICE_TYPE_NAME,
                ServiceName = this.serviceContext.CreateSubscriptionUri(topicName, name)
            };

            try
            {
                await fabric.ServiceManager.CreateServiceAsync(serviceDescription);
            }
            catch (FabricElementAlreadyExistsException)
            {
                //idempotent so return 200
                return(Ok());
            }

            return(Ok());
        }
Пример #20
0
        public async Task <IActionResult> Post([FromRoute] string name, [FromBody] IngestionApplicationParams parameters)
        {
            // Determine the number of IoT Hub partitions.
            // The ingestion service will be created with the same number of partitions.
            EventHubClient             eventHubClient = EventHubClient.CreateFromConnectionString(parameters.IotHubConnectionString, "messages/events");
            EventHubRuntimeInformation eventHubInfo   = await eventHubClient.GetRuntimeInformationAsync();

            // Application parameters are passed to the Ingestion application instance.
            NameValueCollection appInstanceParameters = new NameValueCollection();

            appInstanceParameters["IotHubConnectionString"] = parameters.IotHubConnectionString;
            appInstanceParameters["ReplicaSetSize"]         = parameters.ReplicaSetSize.ToString();
            ApplicationDescription application = new ApplicationDescription(
                new Uri($"{Names.IngestionApplicationPrefix}/{name}"),
                Names.IngestionApplicationTypeName,
                parameters.Version,
                appInstanceParameters);

            // Create a named application instance
            await this.fabricClient.ApplicationManager.CreateApplicationAsync(application, this.operationTimeout, this.appLifetime.ApplicationStopping);

            // Next, create named instances of the services that run in the application.
            ServiceUriBuilder serviceNameUriBuilder = new ServiceUriBuilder(application.ApplicationName.ToString(), Names.IngestionRouterServiceName);

            StatefulServiceDescription service = new StatefulServiceDescription()
            {
                ApplicationName            = application.ApplicationName,
                HasPersistedState          = true,
                MinReplicaSetSize          = parameters.ReplicaSetSize, // Previous 3 for 5 node cluster and 1 for 1 node cluster
                TargetReplicaSetSize       = parameters.ReplicaSetSize,
                PartitionSchemeDescription = new UniformInt64RangePartitionSchemeDescription(eventHubInfo.PartitionCount, 0, eventHubInfo.PartitionCount - 1),
                ServiceName     = serviceNameUriBuilder.Build(),
                ServiceTypeName = Names.IngestionRouterServiceTypeName
            };

            await this.fabricClient.ServiceManager.CreateServiceAsync(service, this.operationTimeout, this.appLifetime.ApplicationStopping);

            return(this.Ok());
        }
Пример #21
0
        private async Task <ActorsCountInfo> CreateActor(int index)
        {
            var description = new StatefulServiceDescription()
            {
                HasPersistedState          = true,
                ApplicationName            = new Uri(this.context.CodePackageActivationContext.ApplicationName),
                ServiceName                = new Uri($"{this.context.CodePackageActivationContext.ApplicationName}/SimulationActorService{GetSimulationActorNameSuffix(index)}"),
                ServiceTypeName            = "SimulationActorServiceType",
                PartitionSchemeDescription = new UniformInt64RangePartitionSchemeDescription()
                {
                    LowKey         = -9223372036854775808,
                    HighKey        = 9223372036854775807,
                    PartitionCount = 1,
                },
                MinReplicaSetSize    = 3,
                TargetReplicaSetSize = 3,
            };

            await this.fabricClient.ServiceManager.CreateServiceAsync(description);

            return(PopulateActorInfo(index, poolInfo.pool));
        }
Пример #22
0
        internal static async Task <IGatewayMonitor> GetGatewaySupervisorServiceAsync(string nodeId, bool createIfnotExist)
        {
            var appName              = "fabric:/DeviceMonitorApp";
            var serviceName          = $"{appName}/{nodeId}";
            var fabricClient         = new FabricClient();
            var serviceAlreadyExists = false;

            try
            {
                var services = await fabricClient.QueryManager.GetServiceListAsync(new Uri(appName));

                serviceAlreadyExists = services.Select(s => s.ServiceName).Contains(new Uri(serviceName));
            }
            catch (FabricElementNotFoundException) { }

            if (!serviceAlreadyExists && createIfnotExist)
            {
                StatefulServiceDescription serviceDescription = new StatefulServiceDescription();
                serviceDescription.ApplicationName            = new Uri(appName);
                serviceDescription.PartitionSchemeDescription = new SingletonPartitionSchemeDescription();
                serviceDescription.ServiceName          = new Uri(serviceName);
                serviceDescription.ServiceTypeName      = "GatewayMonitorServiceType";
                serviceDescription.HasPersistedState    = true;
                serviceDescription.MinReplicaSetSize    = 3;
                serviceDescription.TargetReplicaSetSize = 3;
                await fabricClient.ServiceManager.CreateServiceAsync(serviceDescription);

                //TODO:Call GetService and then get partition instead of delay
                await Task.Delay(TimeSpan.FromSeconds(30));
            }
            else if (!serviceAlreadyExists)
            {
                throw new  ArgumentException("Invalid Arguments");
            }
            return(ServiceProxy.Create <IGatewayMonitor>(new Uri(serviceName)));
        }
Пример #23
0
        public async Task <IActionResult> Put(string name)
        {
            string applicationName = this.serviceContext.CodePackageActivationContext.ApplicationName;

            StatefulServiceDescription serviceDescription = new StatefulServiceDescription()
            {
                ApplicationName            = new Uri(applicationName),
                MinReplicaSetSize          = 3,
                TargetReplicaSetSize       = 3,
                PartitionSchemeDescription = new UniformInt64RangePartitionSchemeDescription()
                {
                    LowKey         = 0,
                    HighKey        = 10,
                    PartitionCount = 1
                },
                HasPersistedState = true,
                ServiceTypeName   = TOPIC_SERVICE_NAME,
                ServiceName       = CreateTopicUri(name)
            };

            await fabric.ServiceManager.CreateServiceAsync(serviceDescription);

            return(Ok());
        }
Пример #24
0
            public override async Task <ActionStateBase> RunAsync(CancellationToken cancellationToken, ServiceInternalFaultInfo serviceInternalFaultInfo)
            {
                InvokeQuorumLossState state = Convert(this.State);

                // get info about the service so we can check type and trss
                ServiceDescription result = await FabricClientRetryHelper.ExecuteFabricActionWithRetryAsync(
                    () => this.FabricClient.ServiceManager.GetServiceDescriptionAsync(
                        this.partitionSelector.ServiceName,
                        this.RequestTimeout,
                        cancellationToken),
                    this.OperationTimeout,
                    cancellationToken).ConfigureAwait(false);

                if (result.Kind != ServiceDescriptionKind.Stateful)
                {
                    // The message in the first arg is only for debugging, it is not returned to the user.
                    throw new FabricInvalidForStatelessServicesException("FabricInvalidForStatelessServicesException", FabricErrorCode.InvalidForStatelessServices);
                }

                StatefulServiceDescription statefulServiceDescription = result as StatefulServiceDescription;

                ReleaseAssert.AssertIf(statefulServiceDescription == null, string.Format(CultureInfo.InvariantCulture, "{0} - Service is not a stateful service", this.State.OperationId));

                if (!statefulServiceDescription.HasPersistedState)
                {
                    // The message in the first arg is only for debugging, it is not returned to the user.
                    throw new FabricOnlyValidForStatefulPersistentServicesException("This is only valid for stateful persistent services", FabricErrorCode.OnlyValidForStatefulPersistentServices);
                }

                SelectedPartition targetPartition = await FaultAnalysisServiceUtility.GetSelectedPartitionStateAsync(
                    this.FabricClient,
                    this.partitionSelector,
                    this.RequestTimeout,
                    this.OperationTimeout,
                    cancellationToken).ConfigureAwait(false);

                Guid partitionId = targetPartition.PartitionId;

                // get data about replicas in that partition
                ServiceReplicaList replicasResult = await FabricClientRetryHelper.ExecuteFabricActionWithRetryAsync(
                    () => this.FabricClient.QueryManager.GetReplicaListAsync(
                        partitionId,
                        0,
                        this.RequestTimeout,
                        cancellationToken),
                    this.OperationTimeout,
                    cancellationToken).ConfigureAwait(false);

                List <StatefulServiceReplica> tempReplicas = new List <StatefulServiceReplica>();

                foreach (var replica in replicasResult)
                {
                    StatefulServiceReplica statefulReplica = replica as StatefulServiceReplica;
                    ReleaseAssert.AssertIf(statefulReplica == null, "Expected stateful replica");
                    tempReplicas.Add(statefulReplica);
                }

                List <StatefulServiceReplica> targetReplicas = null;

                if (this.quorumLossMode == QuorumLossMode.AllReplicas)
                {
                    targetReplicas = tempReplicas.Where(r => r.ReplicaRole == ReplicaRole.Primary || r.ReplicaRole == ReplicaRole.ActiveSecondary).ToList();
                }
                else if (this.quorumLossMode == QuorumLossMode.QuorumReplicas)
                {
                    targetReplicas = FaultAnalysisServiceUtility.GetReplicasForPartialLoss(state.OperationId, tempReplicas);
                }
                else
                {
                    throw FaultAnalysisServiceUtility.CreateException(StepBase.TraceType, Interop.NativeTypes.FABRIC_ERROR_CODE.E_INVALIDARG, Strings.StringResources.Error_UnsupportedQuorumLossMode);
                }

                if (targetReplicas == null)
                {
                    // This will cause the command to rollback and retry
                    throw new FabricTransientException("The operation could not be performed, please retry", FabricErrorCode.NotReady);
                }

                List <string> targetNodes = new List <string>();

                foreach (var replica in targetReplicas)
                {
                    targetNodes.Add(replica.NodeName);
                }

                List <Tuple <string, string> > unreliableTransportInfoList = new List <Tuple <string, string> >();

                foreach (string nodeName in targetNodes)
                {
                    UnreliableTransportBehavior behavior = new UnreliableTransportBehavior("*", "StatefulServiceReopen");
                    behavior.AddFilterForPartitionId(partitionId);

                    // ApplyingUnreliableTransport.BehaviorNamePrefix + nodeName;
                    string behaviorName = this.CreateBehaviorName(nodeName);

                    unreliableTransportInfoList.Add(new Tuple <string, string>(nodeName, behaviorName));
                }

                state.StateProgress.Push(StepStateNames.PerformingActions);

                state.Info.PartitionId             = partitionId;
                state.Info.ReplicaIds              = targetReplicas.Select(r => r.Id).ToList();
                state.Info.UnreliableTransportInfo = unreliableTransportInfoList;

                return(state);
            }
Пример #25
0
            public override ServiceDescription Build()
            {
                var statefulDescription = new StatefulServiceDescription
                {
                    HasPersistedState    = this.HasPersistentState,
                    TargetReplicaSetSize = this.TargetReplicaSetSize,
                    MinReplicaSetSize    = this.MinReplicaSetSize
                };

                statefulDescription.ApplicationName            = this.ApplicationName;
                statefulDescription.PartitionSchemeDescription = this.PartitionSchemeDescriptionBuilder.Build();
                statefulDescription.ServiceName          = this.ServiceName;
                statefulDescription.ServiceTypeName      = this.ServiceTypeName;
                statefulDescription.PlacementConstraints = this.PlacementConstraints;
                statefulDescription.ServiceDnsName       = this.ServiceDnsName;

                if (this.ReplicaRestartWaitDuration.HasValue)
                {
                    statefulDescription.ReplicaRestartWaitDuration = this.ReplicaRestartWaitDuration.Value;
                }

                if (this.QuorumLossWaitDuration.HasValue)
                {
                    statefulDescription.QuorumLossWaitDuration = this.QuorumLossWaitDuration.Value;
                }

                if (this.StandByReplicaKeepDuration.HasValue)
                {
                    statefulDescription.StandByReplicaKeepDuration = this.StandByReplicaKeepDuration.Value;
                }

                if (this.Correlations != null)
                {
                    foreach (var str in this.Correlations)
                    {
                        statefulDescription.Correlations.Add(ServiceCmdletBase.ParseCorrelation(str));
                    }
                }

                if (this.PlacementPolicies != null)
                {
                    foreach (var str in this.PlacementPolicies)
                    {
                        statefulDescription.PlacementPolicies.Add(ServiceCmdletBase.ParsePlacementPolicy(str));
                    }
                }

                if (this.DefaultMoveCost != null)
                {
                    statefulDescription.DefaultMoveCost = ServiceCmdletBase.ParseMoveCost(this.DefaultMoveCost);
                }

                statefulDescription.ServicePackageActivationMode = this.ServicePackageActivationMode;

                if (this.Metrics != null)
                {
                    foreach (var str in this.Metrics)
                    {
                        statefulDescription.Metrics.Add(ServiceCmdletBase.ParseStatefulMetric(str));
                    }
                }

                if (this.ScalingPolicies != null)
                {
                    foreach (var scale in this.ScalingPolicies)
                    {
                        statefulDescription.ScalingPolicies.Add(scale);
                    }
                }

                return(statefulDescription);
            }
Пример #26
0
        protected override object FormatOutput(object output)
        {
            var result = new PSObject(output);

            if (output is ServiceGroupDescription)
            {
                var serviceGroupDescription = output as ServiceGroupDescription;

                // Adding a helper toString method for printing IList<MemberDescription>
                var memberDescriptionsPSObj = new PSObject(serviceGroupDescription.MemberDescriptions);
                memberDescriptionsPSObj.Members.Add(
                    new PSCodeMethod(
                        Constants.ToStringMethodName,
                        typeof(OutputFormatter).GetMethod(Constants.FormatObjectMethodName)));
                result.Properties.Add(new PSNoteProperty(Constants.MemberDescriptionsPropertyName, memberDescriptionsPSObj));

                result.Properties.Add(new PSNoteProperty(
                                          Constants.ApplicationNamePropertyName,
                                          serviceGroupDescription.ServiceDescription.ApplicationName));
                result.Properties.Add(new PSNoteProperty(
                                          Constants.ServiceNamePropertyName,
                                          serviceGroupDescription.ServiceDescription.ServiceName));
                result.Properties.Add(new PSNoteProperty(
                                          Constants.ServiceTypeNamePropertyName,
                                          serviceGroupDescription.ServiceDescription.ServiceTypeName));
                result.Properties.Add(new PSNoteProperty(
                                          Constants.ServiceKindPropertyName,
                                          serviceGroupDescription.ServiceDescription.Kind));
                if (serviceGroupDescription.ServiceDescription is StatefulServiceDescription)
                {
                    StatefulServiceDescription statefulServiceDescription = serviceGroupDescription.ServiceDescription as StatefulServiceDescription;
                    result.Properties.Add(new PSNoteProperty(
                                              Constants.HasPersistedStatePropertyName,
                                              statefulServiceDescription.HasPersistedState));
                    result.Properties.Add(new PSNoteProperty(
                                              Constants.MinReplicaSetSizePropertyName,
                                              statefulServiceDescription.MinReplicaSetSize));
                    result.Properties.Add(new PSNoteProperty(
                                              Constants.TargetReplicaSetSizePropertyName,
                                              statefulServiceDescription.TargetReplicaSetSize));

                    if (statefulServiceDescription.HasPersistedState)
                    {
                        result.Properties.Add(new PSNoteProperty(
                                                  Constants.ReplicaRestartWaitDurationPropertyName,
                                                  statefulServiceDescription.ReplicaRestartWaitDuration));
                        result.Properties.Add(new PSNoteProperty(
                                                  Constants.QuorumLossWaitDurationPropertyName,
                                                  statefulServiceDescription.QuorumLossWaitDuration));
                        result.Properties.Add(new PSNoteProperty(
                                                  Constants.StandByReplicaKeepDurationPropertyName,
                                                  statefulServiceDescription.StandByReplicaKeepDuration));
                    }
                }
                else if (serviceGroupDescription.ServiceDescription is StatelessServiceDescription)
                {
                    StatelessServiceDescription statelessServiceDescription = serviceGroupDescription.ServiceDescription as StatelessServiceDescription;
                    result.Properties.Add(new PSNoteProperty(
                                              Constants.InstanceCountPropertyName,
                                              statelessServiceDescription.InstanceCount));
                }

                result.Properties.Add(
                    new PSNoteProperty(
                        Constants.PartitionSchemePropertyName,
                        serviceGroupDescription.ServiceDescription.PartitionSchemeDescription.Scheme));
                result.Properties.Add(
                    new PSNoteProperty(
                        Constants.PlacementConstraintsPropertyName,
                        string.IsNullOrEmpty(serviceGroupDescription.ServiceDescription.PlacementConstraints) ? Constants.NoneResultOutput : serviceGroupDescription.ServiceDescription.PlacementConstraints));

                if (serviceGroupDescription.ServiceDescription.PartitionSchemeDescription.Scheme == PartitionScheme.UniformInt64Range)
                {
                    var info = serviceGroupDescription.ServiceDescription.PartitionSchemeDescription as UniformInt64RangePartitionSchemeDescription;
                    if (info != null)
                    {
                        result.Properties.Add(new PSNoteProperty(Constants.PartitionLowKeyPropertyName, info.LowKey));
                        result.Properties.Add(new PSNoteProperty(Constants.PartitionHighKeyPropertyName, info.HighKey));
                        result.Properties.Add(new PSNoteProperty(Constants.PartitionCountPropertyName, info.PartitionCount));
                    }
                }
                else if (serviceGroupDescription.ServiceDescription.PartitionSchemeDescription.Scheme == PartitionScheme.Named)
                {
                    var info = serviceGroupDescription.ServiceDescription.PartitionSchemeDescription as NamedPartitionSchemeDescription;
                    if (info != null)
                    {
                        var partitionNamesPropertyPSObj = new PSObject(info.PartitionNames);
                        partitionNamesPropertyPSObj.Members.Add(
                            new PSCodeMethod(
                                Constants.ToStringMethodName,
                                typeof(OutputFormatter).GetMethod(Constants.FormatObjectMethodName)));

                        result.Properties.Add(new PSNoteProperty(Constants.PartitionNamesPropertyName, partitionNamesPropertyPSObj));
                    }
                }

                return(result);
            }

            return(base.FormatOutput(output));
        }
        /// <inheritdoc/>
        protected override void ProcessRecordInternal()
        {
            PartitionSchemeDescription partitionSchemeDescription = null;

            if (this.Named.IsPresent)
            {
                partitionSchemeDescription = new NamedPartitionSchemeDescription(
                    count: this.Count,
                    names: this.Names);
            }
            else if (this.Singleton.IsPresent)
            {
                partitionSchemeDescription = new SingletonPartitionSchemeDescription();
            }
            else if (this.UniformInt64Range.IsPresent)
            {
                partitionSchemeDescription = new UniformInt64RangePartitionSchemeDescription(
                    count: this.Count,
                    lowKey: this.LowKey,
                    highKey: this.HighKey);
            }

            ServiceDescription serviceDescription = null;

            if (this.Stateful.IsPresent)
            {
                serviceDescription = new StatefulServiceDescription(
                    serviceName: this.ServiceName,
                    serviceTypeName: this.ServiceTypeName,
                    partitionDescription: partitionSchemeDescription,
                    targetReplicaSetSize: this.TargetReplicaSetSize,
                    minReplicaSetSize: this.MinReplicaSetSize,
                    hasPersistedState: this.HasPersistedState,
                    applicationName: this.ApplicationName,
                    initializationData: this.InitializationData,
                    placementConstraints: this.PlacementConstraints,
                    correlationScheme: this.CorrelationScheme,
                    serviceLoadMetrics: this.ServiceLoadMetrics,
                    servicePlacementPolicies: this.ServicePlacementPolicies,
                    defaultMoveCost: this.DefaultMoveCost,
                    isDefaultMoveCostSpecified: this.IsDefaultMoveCostSpecified,
                    servicePackageActivationMode: this.ServicePackageActivationMode,
                    serviceDnsName: this.ServiceDnsName,
                    scalingPolicies: this.ScalingPolicies,
                    tagsRequiredToPlace: this.TagsRequiredToPlace,
                    tagsRequiredToRun: this.TagsRequiredToRun,
                    flags: this.Flags,
                    replicaRestartWaitDurationSeconds: this.ReplicaRestartWaitDurationSeconds,
                    quorumLossWaitDurationSeconds: this.QuorumLossWaitDurationSeconds,
                    standByReplicaKeepDurationSeconds: this.StandByReplicaKeepDurationSeconds,
                    servicePlacementTimeLimitSeconds: this.ServicePlacementTimeLimitSeconds,
                    dropSourceReplicaOnMove: this.DropSourceReplicaOnMove,
                    replicaLifecycleDescription: this.ReplicaLifecycleDescription,
                    auxiliaryReplicaCount: this.AuxiliaryReplicaCount);
            }
            else if (this.Stateless.IsPresent)
            {
                serviceDescription = new StatelessServiceDescription(
                    serviceName: this.ServiceName,
                    serviceTypeName: this.ServiceTypeName,
                    partitionDescription: partitionSchemeDescription,
                    instanceCount: this.InstanceCount,
                    applicationName: this.ApplicationName,
                    initializationData: this.InitializationData,
                    placementConstraints: this.PlacementConstraints,
                    correlationScheme: this.CorrelationScheme,
                    serviceLoadMetrics: this.ServiceLoadMetrics,
                    servicePlacementPolicies: this.ServicePlacementPolicies,
                    defaultMoveCost: this.DefaultMoveCost,
                    isDefaultMoveCostSpecified: this.IsDefaultMoveCostSpecified,
                    servicePackageActivationMode: this.ServicePackageActivationMode,
                    serviceDnsName: this.ServiceDnsName,
                    scalingPolicies: this.ScalingPolicies,
                    tagsRequiredToPlace: this.TagsRequiredToPlace,
                    tagsRequiredToRun: this.TagsRequiredToRun,
                    minInstanceCount: this.MinInstanceCount,
                    minInstancePercentage: this.MinInstancePercentage,
                    flags: this.Flags,
                    instanceCloseDelayDurationSeconds: this.InstanceCloseDelayDurationSeconds,
                    instanceLifecycleDescription: this.InstanceLifecycleDescription,
                    instanceRestartWaitDurationSeconds: this.InstanceRestartWaitDurationSeconds);
            }

            this.ServiceFabricClient.Services.CreateServiceAsync(
                applicationId: this.ApplicationId,
                serviceDescription: serviceDescription,
                serverTimeout: this.ServerTimeout,
                cancellationToken: this.CancellationToken).GetAwaiter().GetResult();

            Console.WriteLine("Success!");
        }
Пример #28
0
        /// <summary>
        /// This API supports the Service Fabric platform and is not meant to be called from your code
        /// </summary>
        /// <param name="token">This API supports the Service Fabric platform and is not meant to be called from your code</param>
        /// <returns></returns>
        protected override async Task OnExecuteAsync(CancellationToken token)
        {
            this.serviceDescription = await FabricClientRetryHelper.ExecuteFabricActionWithRetryAsync(
                () => this.FabricClient.ServiceManager.GetServiceDescriptionAsync(
                    this.failoverTestScenarioParameters.PartitionSelector.ServiceName,
                    this.failoverTestScenarioParameters.RequestTimeout,
                    token),
                this.failoverTestScenarioParameters.OperationTimeout,
                token).ConfigureAwait(false);

            bool hasPersistedState = false;

            if (this.serviceDescription.IsStateful())
            {
                StatefulServiceDescription statefulDescription = this.serviceDescription as StatefulServiceDescription;
                ReleaseAssert.AssertIf(statefulDescription == null, "Stateful service description is not WinFabricStatefulServiceDescription");
                hasPersistedState = statefulDescription.HasPersistedState;
            }

            Log.WriteInfo(TraceType, "Validating Service health and availability");
            await this.FabricClient.TestManager.ValidateServiceAsync(
                this.failoverTestScenarioParameters.PartitionSelector.ServiceName,
                this.failoverTestScenarioParameters.MaxServiceStabilizationTimeout,
                token);

            Log.WriteInfo(TraceType, "Getting Selected Partition");
            var getPartitionStateAction = new GetSelectedPartitionStateAction(this.failoverTestScenarioParameters.PartitionSelector)
            {
                RequestTimeout = this.failoverTestScenarioParameters.RequestTimeout,
                ActionTimeout  = this.failoverTestScenarioParameters.OperationTimeout
            };

            await this.TestContext.ActionExecutor.RunAsync(getPartitionStateAction, token);

            Guid selectedPartitionId = getPartitionStateAction.Result.PartitionId;

            Log.WriteInfo(TraceType, "Running test for partition {0}", selectedPartitionId);

            this.ReportProgress("Selected partition {0} for testing failover", selectedPartitionId);

            PartitionSelector selectedPartition = PartitionSelector.PartitionIdOf(this.failoverTestScenarioParameters.PartitionSelector.ServiceName, selectedPartitionId);

            while (this.failoverTestScenarioParameters.TimeToRun - this.GetElapsedTime() > TimeSpan.Zero && !token.IsCancellationRequested)
            {
                if (this.serviceDescription.IsStateful())
                {
                    ReplicaSelector primaryReplicaSelector   = ReplicaSelector.PrimaryOf(selectedPartition);
                    ReplicaSelector secondaryReplicaSelector = ReplicaSelector.RandomSecondaryOf(selectedPartition);

                    // Make Primary go through RemoveReplica, RestartReplica and RestartCodePackage

                    await this.TestReplicaFaultsAsync(primaryReplicaSelector, "Primary", hasPersistedState, token);

                    // Make Secondary go through RemoveReplica, RestartReplica and RestartCodePackage

                    await this.TestReplicaFaultsAsync(secondaryReplicaSelector, "Secondary", hasPersistedState, token);
                }
                else
                {
                    ReplicaSelector randomInstanceSelector = ReplicaSelector.RandomOf(selectedPartition);

                    // Make Stateless Instance go through RemoveReplica, RestartReplica and RestartCodePackage

                    await this.TestReplicaFaultsAsync(randomInstanceSelector, "Stateless Instance", hasPersistedState, token);
                }

                if (this.serviceDescription.IsStateful())
                {
                    // Restart all secondary replicas and make sure the replica set recovers

                    await this.InvokeAndValidateFaultAsync(
                        "Restarting all the secondary replicas",
                        () =>
                    {
#pragma warning disable 618
                        return(this.FabricClient.TestManager.RestartPartitionAsync(
                                   selectedPartition,
                                   RestartPartitionMode.OnlyActiveSecondaries,
                                   this.failoverTestScenarioParameters.OperationTimeout,
                                   token));

#pragma warning restore 618
                    }, token);

                    // Restart all replicas if service is persisted

                    if (hasPersistedState)
                    {
                        await this.InvokeAndValidateFaultAsync(
                            "Restarting all replicas including Primary",
                            () =>
                        {
#pragma warning disable 618
                            return(this.FabricClient.TestManager.RestartPartitionAsync(
                                       selectedPartition,
                                       RestartPartitionMode.AllReplicasOrInstances,
                                       this.failoverTestScenarioParameters.OperationTimeout,
                                       token));

#pragma warning restore 618
                        }, token);
                    }

                    // Induce move and swap primary a few times

                    await this.InvokeAndValidateFaultAsync(
                        "Move Primary to a different node",
                        () =>
                    {
                        return(this.FabricClient.FaultManager.MovePrimaryAsync(
                                   string.Empty,
                                   selectedPartition,
                                   true,
                                   this.failoverTestScenarioParameters.OperationTimeout,
                                   token));
                    }, token);

                    // Induce move secondary a few times

                    await this.InvokeAndValidateFaultAsync(
                        "Move Secondary to a different node",
                        () =>
                    {
                        return(this.FabricClient.FaultManager.MoveSecondaryAsync(
                                   string.Empty,
                                   string.Empty,
                                   selectedPartition,
                                   true,
                                   this.failoverTestScenarioParameters.OperationTimeout,
                                   token));
                    }, token);
                }
                else
                {
                    // Restart all stateless instances

                    await this.InvokeAndValidateFaultAsync(
                        "Restarting all stateless instances for partition",
                        () =>
                    {
#pragma warning disable 618
                        return(this.FabricClient.TestManager.RestartPartitionAsync(
                                   selectedPartition,
                                   RestartPartitionMode.AllReplicasOrInstances,
                                   this.failoverTestScenarioParameters.OperationTimeout,
                                   token));

#pragma warning restore 618
                    }, token);
                }
            }
        }
Пример #29
0
        private bool TryCreateStatefulServiceDescription(out StatefulServiceDescription sd)
        {
            sd = null;
            try
            {
                sd = new StatefulServiceDescription();
                sd.ApplicationName = new Uri(this.control.Package.ApplicationAddress);
                sd.ServiceName = new Uri(this.control.Package.ServiceAddress);
                sd.ServiceTypeName = this.control.Package.ServiceType;

                int minRep;
                if (!this.TryGetData("ServiceStatefulMinReplica", out minRep))
                {
                    return false;
                }

                sd.MinReplicaSetSize = minRep;

                int tgtSize;
                if (!this.TryGetData("ServiceStatefulTargetReplica", out tgtSize))
                {
                    return false;
                }

                sd.TargetReplicaSetSize = tgtSize;
                sd.HasPersistedState = false;
                string hasPersistedValue;
                if (this.control.Package.Data.TryGetValue("ServiceStatefulPersisted", out hasPersistedValue))
                {
                    if (hasPersistedValue == "true")
                    {
                        sd.HasPersistedState = true;
                    }
                }

                PartitionSchemeDescription psd;
                if (!this.TryCreatePartitionDescription(out psd))
                {
                    return false;
                }

                sd.PartitionSchemeDescription = psd;
                return true;
            }
            catch (Exception e)
            {
                log.Error("failed to create StatelessServiceDescription, exception={0}", e.Message);
                return false;
            }
        }
Пример #30
0
            protected override async Task ExecuteActionAsync(FabricTestContext testContext, RestartPartitionAction action, CancellationToken cancellationToken)
            {
                ThrowIf.Null(action.PartitionSelector, "partitionSelector");

                this.helper = new TimeoutHelper(action.ActionTimeout);

                // get service info so we can validate if the operation is valid
                ServiceDescription result = await FabricClientRetryHelper.ExecuteFabricActionWithRetryAsync(
                    () => testContext.FabricClient.ServiceManager.GetServiceDescriptionAsync(
                        action.PartitionSelector.ServiceName,
                        action.RequestTimeout,
                        cancellationToken),
                    this.helper.GetRemainingTime(),
                    cancellationToken).ConfigureAwait(false);

                if (result.Kind != ServiceDescriptionKind.Stateful && action.RestartPartitionMode == RestartPartitionMode.OnlyActiveSecondaries)
                {
                    throw new InvalidOperationException(StringHelper.Format(StringResources.Error_InvalidServiceTypeTestability, "RestartPartitionMode.OnlyActiveSecondaries", "Stateful", action.PartitionSelector.ServiceName, "Stateless"));
                }

                bool hasPersistedState = false;

                if (result.Kind == ServiceDescriptionKind.Stateful)
                {
                    StatefulServiceDescription statefulDescription = result as StatefulServiceDescription;
                    ReleaseAssert.AssertIf(statefulDescription == null, "Stateful service description is not WinFabricStatefulServiceDescription");
                    hasPersistedState = statefulDescription.HasPersistedState;
                }

                // now actually select a partition
                var getPartitionStateAction = new GetSelectedPartitionStateAction(action.PartitionSelector)
                {
                    RequestTimeout = action.RequestTimeout,
                    ActionTimeout  = helper.GetRemainingTime()
                };

                await testContext.ActionExecutor.RunAsync(getPartitionStateAction, cancellationToken);

                Guid partitionId = getPartitionStateAction.Result.PartitionId;

                // get replicas for target
                ServiceReplicaList replicasResult = await FabricClientRetryHelper.ExecuteFabricActionWithRetryAsync(
                    () => testContext.FabricClient.QueryManager.GetReplicaListAsync(
                        partitionId,
                        0,
                        action.RequestTimeout,
                        cancellationToken),
                    this.helper.GetRemainingTime(),
                    cancellationToken).ConfigureAwait(false);

                // get replicas for fm in order to get the primary
                ServiceReplicaList fmReplicasResult = await FabricClientRetryHelper.ExecuteFabricActionWithRetryAsync(
                    () => testContext.FabricClient.QueryManager.GetReplicaListAsync(
                        Constants.FmPartitionId,
                        0,
                        action.RequestTimeout,
                        cancellationToken),
                    this.helper.GetRemainingTime(),
                    cancellationToken).ConfigureAwait(false);

                string fmPrimaryNodeName = string.Empty;
                var    readyFMReplicas   = fmReplicasResult.Where(r => r.ReplicaStatus == ServiceReplicaStatus.Ready).ToArray();

                foreach (var replica in readyFMReplicas)
                {
                    StatefulServiceReplica statefulReplica = replica as StatefulServiceReplica;
                    ReleaseAssert.AssertIf(statefulReplica == null, "FM Replica is not a stateful replica");
                    if (statefulReplica.ReplicaRole == ReplicaRole.Primary)
                    {
                        fmPrimaryNodeName = replica.NodeName;
                    }
                }

                if (string.IsNullOrEmpty(fmPrimaryNodeName))
                {
                    throw new FabricException(StringHelper.Format(StringResources.Error_PartitionPrimaryNotReady, "FailoverManager"), FabricErrorCode.NotReady);
                }

                ////------------------------------------------------------
                // target ut at the fm primary only
                UnreliableTransportBehavior behavior = new UnreliableTransportBehavior("*", "DoReconfiguration");

                behavior.AddFilterForPartitionId(partitionId);
                string behaviorName = "BlockDoReconfiguration";

                await FabricClientRetryHelper.ExecuteFabricActionWithRetryAsync(
                    () => testContext.FabricClient.TestManager.AddUnreliableTransportBehaviorAsync(
                        fmPrimaryNodeName,
                        behaviorName,
                        behavior,
                        action.RequestTimeout,
                        cancellationToken),
                    this.helper.GetRemainingTime(),
                    cancellationToken).ConfigureAwait(false);

                // TODO: Wait for some time so that the unreliable transport behavior can be read from the files.
                // Bug#2271465 - Unreliable transport through API should return only once the behavior has been successfully applied
                await Task.Delay(TimeSpan.FromSeconds(5.0), cancellationToken).ConfigureAwait(false);

                bool triedToRemovedBehavior = false;

                // inspect the actual replicas to restart, only operate on stable ones
                try
                {
                    var stableReplicasToRestart = replicasResult.Where(r => r.ReplicaStatus == ServiceReplicaStatus.Ready).ToArray();

                    foreach (var replica in stableReplicasToRestart)
                    {
                        var currentReplica = replica;
                        if (action.RestartPartitionMode == RestartPartitionMode.OnlyActiveSecondaries)
                        {
                            StatefulServiceReplica statefulReplica = currentReplica as StatefulServiceReplica;
                            ReleaseAssert.AssertIf(statefulReplica == null, "Stateful service replica is not StatefulServiceReplica");
                            if (statefulReplica.ReplicaRole == ReplicaRole.Primary)
                            {
                                continue;
                            }
                        }

                        if (hasPersistedState)
                        {
                            await FabricClientRetryHelper.ExecuteFabricActionWithRetryAsync(
                                () => testContext.FabricClient.FaultManager.RestartReplicaAsync(
                                    currentReplica.NodeName,
                                    partitionId,
                                    currentReplica.Id,
                                    CompletionMode.DoNotVerify,
                                    action.RequestTimeout.TotalSeconds,
                                    cancellationToken),
                                this.helper.GetRemainingTime(),
                                cancellationToken).ConfigureAwait(false);
                        }
                        else
                        {
                            await FabricClientRetryHelper.ExecuteFabricActionWithRetryAsync(
                                () => testContext.FabricClient.FaultManager.RemoveReplicaAsync(
                                    currentReplica.NodeName,
                                    partitionId,
                                    currentReplica.Id,
                                    CompletionMode.DoNotVerify,
                                    false, /*force remove*/
                                    action.RequestTimeout.TotalSeconds,
                                    cancellationToken),
                                this.helper.GetRemainingTime(),
                                cancellationToken).ConfigureAwait(false);
                        }
                    }

                    triedToRemovedBehavior = true;
                    await FabricClientRetryHelper.ExecuteFabricActionWithRetryAsync(
                        () => testContext.FabricClient.TestManager.RemoveUnreliableTransportBehaviorAsync(
                            fmPrimaryNodeName,
                            behaviorName,
                            action.RequestTimeout,
                            cancellationToken),
                        FabricClientRetryErrors.RemoveUnreliableTransportBehaviorErrors.Value,
                        this.helper.GetRemainingTime(),
                        cancellationToken).ConfigureAwait(false);

                    // TODO: Wait for some time so that the unreliable transport behavior can be read from the files.
                    // Bug#2271465 - Unreliable transport through API should return only once the behavior has been successfully applied
                    await Task.Delay(TimeSpan.FromSeconds(5.0)).ConfigureAwait(false);
                }
                finally
                {
                    // TODO: Provide a way to clear all behaviors just in case.
                    if (!triedToRemovedBehavior)
                    {
                        ActionTraceSource.WriteWarning(TraceType, "Exception after adding behavior to block messages. Removing behavior synchronously");
                        FabricClientRetryHelper.ExecuteFabricActionWithRetryAsync(
                            () => testContext.FabricClient.TestManager.RemoveUnreliableTransportBehaviorAsync(
                                fmPrimaryNodeName,
                                behaviorName,
                                action.RequestTimeout,
                                cancellationToken),
                            FabricClientRetryErrors.RemoveUnreliableTransportBehaviorErrors.Value,
                            this.helper.GetRemainingTime(),
                            cancellationToken).GetAwaiter().GetResult();

                        // TODO: Wait for some time so that the unreliable transport behavior can be read from the files.
                        // Bug#2271465 - Unreliable transport through API should return only once the behavior has been successfully applied
                        Task.Delay(TimeSpan.FromSeconds(5.0)).GetAwaiter().GetResult();
                    }
                }

                // -- note there's no explict validation

                // action result
                action.Result     = new RestartPartitionResult(getPartitionStateAction.Result);
                ResultTraceString = StringHelper.Format("RestartPartitionAction succeeded for {0} with RestartPartitionMode = {1}", partitionId, action.RestartPartitionMode);
            }
Пример #31
0
            protected override async Task ExecuteActionAsync(FabricTestContext testContext, InvokeQuorumLossAction action, CancellationToken cancellationToken)
            {
                ThrowIf.Null(action.PartitionSelector, "PartitionSelector");

                var helper = new TimeoutHelper(action.ActionTimeout);

                // get info about the service so we can check type and trss
                ServiceDescription result = await FabricClientRetryHelper.ExecuteFabricActionWithRetryAsync(
                    () => testContext.FabricClient.ServiceManager.GetServiceDescriptionAsync(
                        action.PartitionSelector.ServiceName,
                        action.RequestTimeout,
                        cancellationToken),
                    helper.GetRemainingTime(),
                    cancellationToken).ConfigureAwait(false);

                if (result.Kind != ServiceDescriptionKind.Stateful)
                {
                    throw new InvalidOperationException(StringHelper.Format(StringResources.Error_InvalidServiceTypeTestability, "QuorumLoss", "Stateful", action.PartitionSelector.ServiceName, "Stateless"));
                }

                StatefulServiceDescription statefulServiceDescription = result as StatefulServiceDescription;

                ReleaseAssert.AssertIf(statefulServiceDescription == null, "Service is not a stateful service");

                if (!statefulServiceDescription.HasPersistedState)
                {
                    throw new InvalidOperationException(StringHelper.Format(StringResources.Error_InvalidServiceTypeTestability, "QuorumLoss", "Stateful Persistent", action.PartitionSelector.ServiceName, "Stateful In-Memory Only"));
                }

                // figure out /which/ partition to select
                var getPartitionStateAction = new GetSelectedPartitionStateAction(action.PartitionSelector)
                {
                    RequestTimeout = action.RequestTimeout,
                    ActionTimeout  = helper.GetRemainingTime()
                };

                await testContext.ActionExecutor.RunAsync(getPartitionStateAction, cancellationToken);

                Guid partitionId = getPartitionStateAction.Result.PartitionId;

                // get data about replicas in that partition
                ServiceReplicaList replicasResult = await FabricClientRetryHelper.ExecuteFabricActionWithRetryAsync(
                    () => testContext.FabricClient.QueryManager.GetReplicaListAsync(
                        partitionId,
                        0,
                        action.RequestTimeout,
                        cancellationToken),
                    helper.GetRemainingTime(),
                    cancellationToken).ConfigureAwait(false);

                var removeUTRequestList = new List <Tuple <string, string> >();
                Dictionary <Tuple <string, string>, Task> removeUTTaskDictionary = new Dictionary <Tuple <string, string>, Task>();

                try
                {
                    var  stableReplicas                  = replicasResult.Where(r => r.ReplicaStatus == ServiceReplicaStatus.Ready).ToArray();
                    var  stableReplicasToRemove          = new List <StatefulServiceReplica>();
                    long replicasToRestartWithoutPrimary =
                        action.QuorumLossMode == QuorumLossMode.AllReplicas
                            ? stableReplicas.Length - 1
                            : FabricCluster.GetWriteQuorumSize(replicasResult.Count);
                    foreach (var replica in stableReplicas)
                    {
                        StatefulServiceReplica statefulReplica = replica as StatefulServiceReplica;
                        ReleaseAssert.AssertIf(statefulReplica == null, "Service Replica is not of stateful type even though service is stateful");
                        if (statefulReplica.ReplicaRole != ReplicaRole.Primary)
                        {
                            replicasToRestartWithoutPrimary--;
                        }

                        if (replicasToRestartWithoutPrimary >= 0 || statefulReplica.ReplicaRole == ReplicaRole.Primary)
                        {
                            stableReplicasToRemove.Add(statefulReplica);
                        }
                    }

                    // for selected replicas, block reopen so that when we restart the replica (NOT remove the replica) it doesn't come up
                    var utTaskList = new List <Task>();
                    foreach (var statefulReplica in stableReplicasToRemove)
                    {
                        string nodeName = statefulReplica.NodeName;
                        UnreliableTransportBehavior behavior = new UnreliableTransportBehavior("*", "StatefulServiceReopen");
                        behavior.AddFilterForPartitionId(partitionId);
                        string behaviorName = "BlockStatefulServiceReopen_" + nodeName;

                        removeUTRequestList.Add(new Tuple <string, string>(nodeName, behaviorName));
                        utTaskList.Add(
                            FabricClientRetryHelper.ExecuteFabricActionWithRetryAsync(
                                () =>
                                testContext.FabricClient.TestManager.AddUnreliableTransportBehaviorAsync(
                                    nodeName,
                                    behaviorName,
                                    behavior,
                                    action.RequestTimeout,
                                    cancellationToken),
                                helper.GetRemainingTime(),
                                cancellationToken));
                    }

                    await Task.WhenAll(utTaskList).ConfigureAwait(false);

                    // TODO: Wait for some time so that the unreliable transport behavior can be read from the files.
                    // Bug#2271465 - Unreliable transport through API should return only once the behavior has been successfully applied
                    await Task.Delay(TimeSpan.FromSeconds(5.0), cancellationToken);

                    var restartReplicaTaskList = new List <Task>();
                    foreach (var statefulReplica in stableReplicasToRemove)
                    {
                        ReplicaSelector replicaSelector = ReplicaSelector.ReplicaIdOf(PartitionSelector.PartitionIdOf(action.PartitionSelector.ServiceName, partitionId), statefulReplica.Id);

                        var restartReplicaAction = new RestartReplicaAction(replicaSelector)
                        {
                            CompletionMode = CompletionMode.DoNotVerify,
                            RequestTimeout = action.RequestTimeout,
                            ActionTimeout  = helper.GetRemainingTime()
                        };

                        restartReplicaTaskList.Add(testContext.ActionExecutor.RunAsync(restartReplicaAction, cancellationToken));
                    }

                    await Task.WhenAll(restartReplicaTaskList).ConfigureAwait(false);

                    await AsyncWaiter.WaitAsync(action.QuorumLossDuration, cancellationToken).ConfigureAwait(false);

                    // validate
                    ServicePartitionList partitionsResult = await FabricClientRetryHelper.ExecuteFabricActionWithRetryAsync(
                        () => testContext.FabricClient.QueryManager.GetPartitionListAsync(
                            action.PartitionSelector.ServiceName,
                            null,
                            action.RequestTimeout,
                            cancellationToken),
                        FabricClientRetryErrors.GetPartitionListFabricErrors.Value,
                        helper.GetRemainingTime(),
                        cancellationToken).ConfigureAwait(false);

                    foreach (StatefulServicePartition partition in partitionsResult)
                    {
                        if (partition.PartitionInformation.Id == partitionId)
                        {
                            ReleaseAssert.AssertIf(partition.PartitionStatus != ServicePartitionStatus.InQuorumLoss, "Partition failed to be in Quorum Loss.");
                            break;
                        }
                    }

                    foreach (var removeUTParams in removeUTRequestList)
                    {
                        var  currentParams = removeUTParams;
                        Task task          = FabricClientRetryHelper.ExecuteFabricActionWithRetryAsync(
                            () => testContext.FabricClient.TestManager.RemoveUnreliableTransportBehaviorAsync(
                                currentParams.Item1,  /*nodeName*/
                                currentParams.Item2,  /*behaviorName*/
                                action.RequestTimeout,
                                cancellationToken),
                            FabricClientRetryErrors.RemoveUnreliableTransportBehaviorErrors.Value,
                            helper.GetRemainingTime(),
                            cancellationToken);

                        removeUTTaskDictionary[currentParams] = task;
                    }

                    await Task.WhenAll(removeUTTaskDictionary.Values).ConfigureAwait(false);

                    // TODO: Wait for some time so that the removal of this unreliable transport behavior can be read from the files.
                    // Bug#2271465 - Unreliable transport through API should return only once the behavior has been successully applied
                    await Task.Delay(TimeSpan.FromSeconds(5.0), cancellationToken);
                }
                finally
                {
                    var removeUTTaskList = new List <Task>();

                    foreach (var removeUTRequest in removeUTTaskDictionary)
                    {
                        var currentRemoveUTRequest = removeUTRequest;
                        if (currentRemoveUTRequest.Value == null || currentRemoveUTRequest.Value.IsFaulted)
                        {
                            removeUTTaskList.Add(
                                FabricClientRetryHelper.ExecuteFabricActionWithRetryAsync(
                                    () => testContext.FabricClient.TestManager.RemoveUnreliableTransportBehaviorAsync(
                                        currentRemoveUTRequest.Key.Item1, /*nodeName*/
                                        currentRemoveUTRequest.Key.Item2, /*behaviorName*/
                                        action.RequestTimeout,
                                        cancellationToken),
                                    FabricClientRetryErrors.RemoveUnreliableTransportBehaviorErrors.Value,
                                    helper.GetRemainingTime(),
                                    cancellationToken));
                        }
                    }

                    Task.WhenAll(removeUTTaskList).Wait(cancellationToken);

                    // TODO: Wait for some time so that the removal of this unreliable transport behavior can be read from the files.
                    // Bug#2271465 - Unreliable transport through API should return only once the behavior has been successully applied
                    Task.Delay(TimeSpan.FromSeconds(5.0), cancellationToken).GetAwaiter().GetResult();
                }

                action.Result          = new InvokeQuorumLossResult(getPartitionStateAction.Result);
                this.ResultTraceString = StringHelper.Format("InvokeQuorumLossAction succeeded for {0} with QuorumLossMode = {1}", partitionId, action.QuorumLossMode);
            }
        /// <summary>
        /// Serializes the object to JSON.
        /// </summary>
        /// <param name="writer">The <see cref="T: Newtonsoft.Json.JsonWriter" /> to write to.</param>
        /// <param name="obj">The object to serialize to JSON.</param>
        internal static void Serialize(JsonWriter writer, StatefulServiceDescription obj)
        {
            // Required properties are always serialized, optional properties are serialized when not null.
            writer.WriteStartObject();
            writer.WriteProperty(obj.ServiceKind, "ServiceKind", ServiceKindConverter.Serialize);
            writer.WriteProperty(obj.ServiceName, "ServiceName", ServiceNameConverter.Serialize);
            writer.WriteProperty(obj.ServiceTypeName, "ServiceTypeName", JsonWriterExtensions.WriteStringValue);
            writer.WriteProperty(obj.PartitionDescription, "PartitionDescription", PartitionSchemeDescriptionConverter.Serialize);
            writer.WriteProperty(obj.TargetReplicaSetSize, "TargetReplicaSetSize", JsonWriterExtensions.WriteIntValue);
            writer.WriteProperty(obj.MinReplicaSetSize, "MinReplicaSetSize", JsonWriterExtensions.WriteIntValue);
            writer.WriteProperty(obj.HasPersistedState, "HasPersistedState", JsonWriterExtensions.WriteBoolValue);
            writer.WriteProperty(obj.DefaultMoveCost, "DefaultMoveCost", MoveCostConverter.Serialize);
            writer.WriteProperty(obj.ServicePackageActivationMode, "ServicePackageActivationMode", ServicePackageActivationModeConverter.Serialize);
            if (obj.ApplicationName != null)
            {
                writer.WriteProperty(obj.ApplicationName, "ApplicationName", ApplicationNameConverter.Serialize);
            }

            if (obj.InitializationData != null)
            {
                writer.WriteProperty(obj.InitializationData, "InitializationData", ByteArrayConverter.Serialize);
            }

            if (obj.PlacementConstraints != null)
            {
                writer.WriteProperty(obj.PlacementConstraints, "PlacementConstraints", JsonWriterExtensions.WriteStringValue);
            }

            if (obj.CorrelationScheme != null)
            {
                writer.WriteEnumerableProperty(obj.CorrelationScheme, "CorrelationScheme", ServiceCorrelationDescriptionConverter.Serialize);
            }

            if (obj.ServiceLoadMetrics != null)
            {
                writer.WriteEnumerableProperty(obj.ServiceLoadMetrics, "ServiceLoadMetrics", ServiceLoadMetricDescriptionConverter.Serialize);
            }

            if (obj.ServicePlacementPolicies != null)
            {
                writer.WriteEnumerableProperty(obj.ServicePlacementPolicies, "ServicePlacementPolicies", ServicePlacementPolicyDescriptionConverter.Serialize);
            }

            if (obj.IsDefaultMoveCostSpecified != null)
            {
                writer.WriteProperty(obj.IsDefaultMoveCostSpecified, "IsDefaultMoveCostSpecified", JsonWriterExtensions.WriteBoolValue);
            }

            if (obj.ServiceDnsName != null)
            {
                writer.WriteProperty(obj.ServiceDnsName, "ServiceDnsName", JsonWriterExtensions.WriteStringValue);
            }

            if (obj.ScalingPolicies != null)
            {
                writer.WriteEnumerableProperty(obj.ScalingPolicies, "ScalingPolicies", ScalingPolicyDescriptionConverter.Serialize);
            }

            if (obj.Flags != null)
            {
                writer.WriteProperty(obj.Flags, "Flags", JsonWriterExtensions.WriteIntValue);
            }

            if (obj.ReplicaRestartWaitDurationSeconds != null)
            {
                writer.WriteProperty(obj.ReplicaRestartWaitDurationSeconds, "ReplicaRestartWaitDurationSeconds", JsonWriterExtensions.WriteLongValue);
            }

            if (obj.QuorumLossWaitDurationSeconds != null)
            {
                writer.WriteProperty(obj.QuorumLossWaitDurationSeconds, "QuorumLossWaitDurationSeconds", JsonWriterExtensions.WriteLongValue);
            }

            if (obj.StandByReplicaKeepDurationSeconds != null)
            {
                writer.WriteProperty(obj.StandByReplicaKeepDurationSeconds, "StandByReplicaKeepDurationSeconds", JsonWriterExtensions.WriteLongValue);
            }

            if (obj.ServicePlacementTimeLimitSeconds != null)
            {
                writer.WriteProperty(obj.ServicePlacementTimeLimitSeconds, "ServicePlacementTimeLimitSeconds", JsonWriterExtensions.WriteLongValue);
            }

            if (obj.DropSourceReplicaOnMove != null)
            {
                writer.WriteProperty(obj.DropSourceReplicaOnMove, "DropSourceReplicaOnMove", JsonWriterExtensions.WriteBoolValue);
            }

            writer.WriteEndObject();
        }