internal static IntPtr ToNative(PinCollection pin, ServiceGroupDescription description) { if (description == null) { return(IntPtr.Zero); } uint length = (uint)description.MemberDescriptions.Count; var nativeDescription = new NativeTypes.FABRIC_SERVICE_GROUP_DESCRIPTION[1]; nativeDescription[0].Description = description.ServiceDescription.ToNative(pin); nativeDescription[0].MemberCount = length; var members = new NativeTypes.FABRIC_SERVICE_GROUP_MEMBER_DESCRIPTION[length]; for (int i = 0; i < length; i++) { members[i].ServiceTypeName = pin.AddBlittable(description.MemberDescriptions[i].ServiceTypeName); members[i].ServiceName = pin.AddObject(description.MemberDescriptions[i].ServiceName); var initializationData = NativeTypes.ToNativeBytes(pin, description.MemberDescriptions[i].InitializationData); members[i].InitializationDataSize = initializationData.Item1; members[i].InitializationData = initializationData.Item2; var metrics = NativeTypes.ToNativeLoadMetrics(pin, description.MemberDescriptions[i].Metrics); members[i].MetricCount = metrics.Item1; members[i].Metrics = metrics.Item2; pin.AddBlittable(members[i]); } nativeDescription[0].MemberDescriptions = pin.AddBlittable(members); return(pin.AddBlittable(nativeDescription[0])); }
private Task CreateServiceGroupAsyncHelper(ServiceGroupDescription description, TimeSpan timeout, CancellationToken cancellationToken) { return(Utility.WrapNativeAsyncInvokeInMTA( (callback) => this.CreateServiceGroupBeginWrapper(description, timeout, callback), this.CreateServiceGroupEndWrapper, cancellationToken, "ServiceManager.CreateServiceGroup")); }
/// <summary> /// Asynchronously creates a service group from the given <see cref="System.Fabric.Description.ServiceGroupDescription" /> with the provided timeout /// and <see cref="System.Threading.CancellationToken" />. /// </summary> /// <param name="description">The <see cref="System.Fabric.Description.ServiceGroupDescription" /> which describes the group and its members.</param> /// <param name="timeout">Timespan that defines the maximum amount of time Service Fabric will allow this operation to continue before returning /// a Timeout Exception.</param> /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken" /> object that the operation is observing. It can be /// used to send a notification that the operation should be canceled. Note that cancellation is advisory and that the operation may /// still be completed even if it is canceled.</param> /// <returns>The task representing the asynchronous service group creation operation.</returns> public Task CreateServiceGroupAsync(ServiceGroupDescription description, TimeSpan timeout, CancellationToken cancellationToken) { this.fabricClient.ThrowIfDisposed(); Requires.Argument <ServiceGroupDescription>("description", description).NotNull(); ServiceGroupDescription.Validate(description); return(this.CreateServiceGroupAsyncHelper(description, timeout, cancellationToken)); }
public CreateServiceGroupRequest(IFabricClient fabricClient, ServiceGroupDescription serviceDescription, TimeSpan timeout) : base(fabricClient, timeout) { ThrowIf.Null(serviceDescription, "serviceDescription"); this.ServiceGroupDescription = serviceDescription; this.ConfigureErrorCodes(); }
public static void ValidateServiceGroupDescription(ServiceGroupDescription original, ServiceGroupDescription marshalled) { Assert.IsNotNull(marshalled); Assert.IsNotNull(marshalled.ServiceDescription); Assert.AreEqual(original.ServiceDescription.GetType(), marshalled.ServiceDescription.GetType()); Assert.AreEqual(original.ServiceDescription.ApplicationName, marshalled.ServiceDescription.ApplicationName); Assert.AreEqual(original.ServiceDescription.ServiceName, marshalled.ServiceDescription.ServiceName); Assert.AreEqual(original.ServiceDescription.ServiceTypeName, marshalled.ServiceDescription.ServiceTypeName); Assert.AreEqual(original.MemberDescriptions.Count, marshalled.MemberDescriptions.Count); foreach (var originalMember in original.MemberDescriptions) { var marshalledMember = marshalled.MemberDescriptions.Where(m => m.ServiceName == originalMember.ServiceName).FirstOrDefault(); Assert.IsNotNull(marshalledMember); Assert.AreEqual(originalMember.ServiceTypeName, marshalledMember.ServiceTypeName); if (originalMember.InitializationData == null) { Assert.IsTrue(marshalledMember.InitializationData == null || marshalledMember.InitializationData.Length == 0); } else { Assert.IsNotNull(marshalledMember.InitializationData); Assert.AreEqual(originalMember.InitializationData.Length, marshalledMember.InitializationData.Length); } Assert.AreEqual(originalMember.Metrics.Count, marshalledMember.Metrics.Count); foreach (var originalMetric in originalMember.Metrics) { var marshalledMetric = marshalledMember.Metrics.Where(m => m.Name == originalMetric.Name).FirstOrDefault(); Assert.IsNotNull(marshalledMetric); if (original.ServiceDescription.Kind == ServiceDescriptionKind.Stateful) { Assert.AreEqual((originalMetric as StatefulServiceLoadMetricDescription).PrimaryDefaultLoad, (marshalledMetric as StatefulServiceLoadMetricDescription).PrimaryDefaultLoad); Assert.AreEqual((originalMetric as StatefulServiceLoadMetricDescription).SecondaryDefaultLoad, (marshalledMetric as StatefulServiceLoadMetricDescription).SecondaryDefaultLoad); } else if (original.ServiceDescription.Kind == ServiceDescriptionKind.Stateless) { Assert.AreEqual((originalMetric as StatelessServiceLoadMetricDescription).DefaultLoad, (marshalledMetric as StatelessServiceLoadMetricDescription).DefaultLoad); } Assert.AreEqual(originalMetric.Weight, marshalledMetric.Weight); } } }
public static ServiceGroupDescription CreateServiceGroupDescription(int memberCount, int metricCount, bool isStateful) { ServiceGroupDescription description = new ServiceGroupDescription { ServiceDescription = CreateServiceDescription(isStateful) }; for (int i = 0; i < memberCount; i++) { description.MemberDescriptions.Add(CreateServiceGroupMemberDescription(description.ServiceDescription.ServiceName, i, metricCount, isStateful)); } return(description); }
private void RunServiceGroupDescriptionTest(int memberCount, int metricCount, bool isStateful) { var description = CreateServiceGroupDescription( memberCount: memberCount, metricCount: metricCount, isStateful: isStateful); using (var pin = new PinCollection()) { IntPtr nativePtr = InteropHelpers.ServiceGroupDescriptionHelper.ToNative(pin, description); var marshalled = ServiceGroupDescription.CreateFromNative(new ServiceGroupDescriptionResult(nativePtr)); ValidateServiceGroupDescription(description, marshalled); } }
protected void CreateServiceGroup(ServiceGroupDescription serviceGroupDescription) { var clusterConnection = this.GetClusterConnection(); try { clusterConnection.CreateServiceGroupAsync( serviceGroupDescription, this.GetTimeout(), this.GetCancellationToken()).Wait(); this.WriteObject(this.FormatOutput(serviceGroupDescription), true); } catch (AggregateException aggregateException) { aggregateException.Handle((ae) => { this.ThrowTerminatingError( ae, Constants.CreateServiceGroupErrorId, clusterConnection); return(true); }); } }
protected override void ProcessRecord() { ServiceCmdletBase.PartitionSchemeDescriptionBuilder partitionSchemeDescriptionBuilder; if (this.PartitionSchemeUniformInt64) { partitionSchemeDescriptionBuilder = new ServiceCmdletBase.UniformInt64RangePartitionSchemeDescriptionBuilder( this.PartitionCount, this.LowKey, this.HighKey); } else if (this.PartitionSchemeNamed) { partitionSchemeDescriptionBuilder = new ServiceCmdletBase.NamedPartitionSchemeDescriptionBuilder(this.PartitionNames); } else { partitionSchemeDescriptionBuilder = new ServiceCmdletBase.SingletonPartitionSchemeDescriptionBuilder(); } var activationMode = System.Fabric.Description.ServicePackageActivationMode.SharedProcess; if (this.ServicePackageActivationMode.HasValue) { activationMode = this.ServicePackageActivationMode.Value; } ServiceGroupDescriptionBuilder serviceGroupDescriptionBuilder; if (this.Stateful) { serviceGroupDescriptionBuilder = new StatefulServiceGroupDescriptionBuilder( this.Adhoc ? null : this.ApplicationName, partitionSchemeDescriptionBuilder, this.HasPersistedState, this.TargetReplicaSetSize, this.MinReplicaSetSize, this.ServiceName, this.ServiceTypeName, this.PlacementConstraint, this.Metric, this.Correlation, this.PlacementPolicy, this.ServiceGroupMemberDescription, this.ReplicaRestartWaitDuration, this.QuorumLossWaitDuration, activationMode); } else { serviceGroupDescriptionBuilder = new StatelessServiceGroupDescriptionBuilder( this.Adhoc ? null : this.ApplicationName, partitionSchemeDescriptionBuilder, this.InstanceCount, this.ServiceName, this.ServiceTypeName, this.PlacementConstraint, this.Metric, this.Correlation, this.PlacementPolicy, this.ServiceGroupMemberDescription, activationMode); } ServiceGroupDescription sd = null; try { sd = serviceGroupDescriptionBuilder.Build(); } catch (Exception exception) { this.ThrowTerminatingError( exception, Constants.CreateServiceGroupErrorId, null); } this.CreateServiceGroup(sd); }
public async Task <ValidationReport> EnsureStabilityWithReportAsync(TimeSpan maximumStabilizationTimeout, TimeSpan retryWait, CancellationToken ct) { TestabilityTrace.TraceSource.WriteInfo(TraceSource, "Ensuring that '{0}' is online with timeout '{1}'.", this.serviceName, maximumStabilizationTimeout); bool checkQuorumLoss = (this.checkFlags & ValidationCheckFlag.CheckQuorumLoss) != 0; // Load basic information about this service. TestabilityTrace.TraceSource.WriteNoise(TraceSource, "Querying basic information for {0}.", this.serviceName); await this.LoadPartitionAndReplicaCountAsync(ct); DateTime startTime = DateTime.Now; TimeoutHelper timer = new TimeoutHelper(maximumStabilizationTimeout); bool success = false; List <Guid> partitionsInQuorumLoss = new List <Guid>(); StringBuilder errorString = new StringBuilder(); int retryCount = 1; while (!success && timer.GetRemainingTime() > TimeSpan.Zero) { TestabilityTrace.TraceSource.WriteInfo(TraceSource, "EnsureStabilityWithReportAsync(): retryCount='{0}', timer.GetRemainingTime()='{1}'", retryCount, timer.GetRemainingTime()); var nodes = await this.TestContext.FabricCluster.GetLatestNodeInfoAsync(this.requestTimeout, this.operationTimeout, ct); // Empty error string and list of partitions in quorum loss partitionsInQuorumLoss.Clear(); errorString.Clear(); success = true; int totalPartitionsFound = 0; bool stateful; ReleaseAssert.AssertIfNot(this.isStateful.TryGetValue(out stateful), "isStateful flag is not available"); bool checkTarget = (this.checkFlags & ValidationCheckFlag.CheckTargetReplicaSetSize) != 0; bool checkInBuild = (this.checkFlags & ValidationCheckFlag.CheckInBuildReplica) != 0; if (stateful) { var partitionDictionary = await this.QueryPartitionAndReplicaResultAsyncStateful(ct); totalPartitionsFound = partitionDictionary.Count(); foreach (KeyValuePair <Partition, StatefulServiceReplica[]> partition in partitionDictionary) { bool partitionIsReady = partition.Key.PartitionStatus == ServicePartitionStatus.Ready; if (!partitionIsReady) { var message = StringHelper.Format("Partition '{0}' is not Ready", partition.Key.PartitionId()); TestabilityTrace.TraceSource.WriteInfo(TraceSource, "{0}", message); errorString.AppendLine(message); } if (partition.Key.PartitionStatus != ServicePartitionStatus.InQuorumLoss) { int validCount = 0; int inBuildReplicas = 0; foreach (StatefulServiceReplica replica in partition.Value) { if (replica.ReplicaStatus == ServiceReplicaStatus.Ready && (replica.ReplicaRole == ReplicaRole.Primary || replica.ReplicaRole == ReplicaRole.ActiveSecondary)) { ++validCount; } if (replica.ReplicaStatus == ServiceReplicaStatus.InBuild) { ++inBuildReplicas; var message = StringHelper.Format("Replica {0} for partition '{1}' is InBuild", replica.Id, partition.Key.PartitionId()); TestabilityTrace.TraceSource.WriteInfo(TraceSource, "{0}", message); errorString.AppendLine(message); } } bool targetAchieved = this.CheckReplicaSetSize(partition.Key.PartitionInformation.Id, validCount, startTime, nodes, errorString); if (!partitionIsReady || (checkInBuild && inBuildReplicas > 0) || (checkTarget && !targetAchieved)) { success = false; } } else { partitionsInQuorumLoss.Add(partition.Key.PartitionInformation.Id); } } } else { int targetInstanceCount = 0; ReleaseAssert.AssertIf(!this.targetReplicaSetSize.TryGetValue(out targetInstanceCount), "targetReplicaSetSize for service: {0} should have been populated at this point.", this.serviceName); bool placementConstraintsDefined = false; try { // Get the service description to find out if there are placement constraints on the service ServiceDescription result = await FabricClientRetryHelper.ExecuteFabricActionWithRetryAsync( () => this.TestContext.FabricClient.ServiceManager.GetServiceDescriptionAsync( this.serviceName, this.requestTimeout, ct), this.operationTimeout, ct).ConfigureAwait(false); ThrowIf.IsTrue(result == null, "A description must be associated with the service: {0}", this.serviceName); placementConstraintsDefined = !string.IsNullOrEmpty(result.PlacementConstraints); } catch (UnauthorizedAccessException) { ServiceGroupDescription groupDescription = await FabricClientRetryHelper.ExecuteFabricActionWithRetryAsync( () => this.TestContext.FabricClient.ServiceGroupManager.GetServiceGroupDescriptionAsync( this.serviceName, this.requestTimeout, ct), this.operationTimeout, ct).ConfigureAwait(false); ThrowIf.IsTrue(groupDescription == null, "A description must be associated with the service group: {0}", this.serviceName); placementConstraintsDefined = !string.IsNullOrEmpty(groupDescription.ServiceDescription.PlacementConstraints); } // If a stateless service has instance count == -1 and it has placement constraints such // that the possible number of instances cannot match the total number of nodes, // we need to find out the number of eligible nodes for the service which is tracked by RDBug 8993319. // Until RDBug 8993319 is fixed, we take the presence of placement constraints into consideration to make the // validation more accurate. if (targetInstanceCount == -1 && placementConstraintsDefined) { checkTarget = false; } var partitionDictionary = await this.QueryPartitionAndReplicaResultAsyncStateless(timer.GetRemainingTime(), ct); totalPartitionsFound = partitionDictionary.Count(); foreach (KeyValuePair <Partition, StatelessServiceInstance[]> partition in partitionDictionary) { bool partitionIsReady = partition.Key.PartitionStatus == ServicePartitionStatus.Ready; if (!partitionIsReady) { var message = StringHelper.Format("Partition '{0}' is not Ready", partition.Key.PartitionId()); TestabilityTrace.TraceSource.WriteInfo(TraceSource, "{0}", message); errorString.AppendLine(message); } int validCount = 0; foreach (StatelessServiceInstance instance in partition.Value) { if (instance.ReplicaStatus == ServiceReplicaStatus.Ready) { ++validCount; } } bool targetAchieved = this.CheckReplicaSetSize(partition.Key.PartitionInformation.Id, validCount, startTime, nodes, errorString); if (!partitionIsReady || (checkTarget && !targetAchieved)) { success = false; } } } if (!this.ValidatePartitionCount(totalPartitionsFound)) { success = false; } if (partitionsInQuorumLoss.Count > 0 && checkQuorumLoss) { string paritionIds = string.Join(",", partitionsInQuorumLoss.ToArray()); var message = StringHelper.Format("Partitions '{0}' in quorum loss for service {1}", paritionIds, this.serviceName); TestabilityTrace.TraceSource.WriteInfo(TraceSource, "{0}", message); errorString.AppendLine(message); success = false; } if (!success) { if (retryCount % 10 == 0) { TestabilityTrace.TraceSource.WriteWarning(TraceSource, "Service {0} validation failed due to issues below, will retry: \n{1}", this.serviceName, errorString); } // Delay before querying again so we allow some time for state to change - don't spam the node await AsyncWaiter.WaitAsync(retryWait, ct).ConfigureAwait(false); } retryCount++; } if (partitionsInQuorumLoss.Count > 0) { string partitionIds = string.Join(",", partitionsInQuorumLoss.ToArray()); TestabilityTrace.TraceSource.WriteInfo(TraceSource, "Partitions in quorum loss for service {0} are '{1}'", this.serviceName, partitionIds); if (checkQuorumLoss) { throw new FabricValidationException(StringHelper.Format(StringResources.Error_PartitionsInQuorumLoss, partitionIds, this.serviceName)); } } if (!success) { return(new ValidationReport( true, StringHelper.Format(StringResources.Error_ServiceNotStable, this.serviceName, maximumStabilizationTimeout, errorString))); } else { return(ValidationReport.Default); } }
/// <summary> /// Asynchronously creates a service group from the given <see cref="System.Fabric.Description.ServiceGroupDescription" />. /// </summary> /// <param name="description">The <see cref="System.Fabric.Description.ServiceGroupDescription" /> which describes the group and its members.</param> /// <returns>The task representing the asynchronous service group creation operation.</returns> public Task CreateServiceGroupAsync(ServiceGroupDescription description) { return(this.CreateServiceGroupAsync(description, FabricClient.DefaultTimeout, CancellationToken.None)); }
private ServiceGroupDescription GetServiceGroupDescriptionEndWrapper(NativeCommon.IFabricAsyncOperationContext context) { return(ServiceGroupDescription.CreateFromNative(this.nativeServiceGroupClient.EndGetServiceGroupDescription(context))); }
private NativeCommon.IFabricAsyncOperationContext CreateServiceGroupBeginWrapper(ServiceGroupDescription description, TimeSpan timeout, NativeCommon.IFabricAsyncOperationCallback callback) { using (var pin = new PinCollection()) { return(this.nativeServiceGroupClient.BeginCreateServiceGroup( InteropHelpers.ServiceGroupDescriptionHelper.ToNative(pin, description), Utility.ToMilliseconds(timeout, "timeout"), callback)); } }