Example #1
0
            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]));
            }
Example #2
0
 private Task CreateServiceGroupAsyncHelper(ServiceGroupDescription description, TimeSpan timeout, CancellationToken cancellationToken)
 {
     return(Utility.WrapNativeAsyncInvokeInMTA(
                (callback) => this.CreateServiceGroupBeginWrapper(description, timeout, callback),
                this.CreateServiceGroupEndWrapper,
                cancellationToken,
                "ServiceManager.CreateServiceGroup"));
 }
Example #3
0
            /// <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));
            }
Example #4
0
        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);
                });
            }
        }
Example #9
0
        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);
            }
        }
Example #11
0
 /// <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));
 }
Example #12
0
 private ServiceGroupDescription GetServiceGroupDescriptionEndWrapper(NativeCommon.IFabricAsyncOperationContext context)
 {
     return(ServiceGroupDescription.CreateFromNative(this.nativeServiceGroupClient.EndGetServiceGroupDescription(context)));
 }
Example #13
0
 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));
     }
 }