예제 #1
0
        private static ClusterVNode BuildNode(ClusterNodeOptions options, Func <ClusterNodeOptions> loadConfigFunc)
        {
            var quorumSize = GetQuorumSize(options.ClusterSize);

            var disableInternalTcpTls = options.Insecure;
            var disableExternalTcpTls = options.Insecure || options.DisableExternalTcpTls;

            var httpEndPoint = new IPEndPoint(options.ExtIp, options.HttpPort);
            var intTcp       = disableInternalTcpTls ? new IPEndPoint(options.IntIp, options.IntTcpPort) : null;
            var intSecTcp    = !disableInternalTcpTls ? new IPEndPoint(options.IntIp, options.IntTcpPort) : null;
            var extTcp       = options.EnableExternalTCP && disableExternalTcpTls
                                ? new IPEndPoint(options.ExtIp, options.ExtTcpPort)
                                : null;
            var extSecTcp = options.EnableExternalTCP && !disableExternalTcpTls
                                ? new IPEndPoint(options.ExtIp, options.ExtTcpPort)
                                : null;

            var intTcpPortAdvertiseAs    = disableInternalTcpTls ? options.IntTcpPortAdvertiseAs : 0;
            var intSecTcpPortAdvertiseAs = !disableInternalTcpTls ? options.IntTcpPortAdvertiseAs : 0;
            var extTcpPortAdvertiseAs    = options.EnableExternalTCP && disableExternalTcpTls
                                ? options.ExtTcpPortAdvertiseAs
                                : 0;
            var extSecTcpPortAdvertiseAs = options.EnableExternalTCP && !disableExternalTcpTls
                                ? options.ExtTcpPortAdvertiseAs
                                : 0;

            var prepareCount = options.PrepareCount > quorumSize ? options.PrepareCount : quorumSize;
            var commitCount  = options.CommitCount > quorumSize ? options.CommitCount : quorumSize;

            Log.Information("Quorum size set to {quorum}", prepareCount);

            if (options.ReadOnlyReplica && options.ClusterSize <= 1)
            {
                throw new InvalidConfigurationException(
                          "This node cannot be configured as a Read Only Replica as these node types are only supported in a clustered configuration.");
            }

            VNodeBuilder builder;

            if (options.ClusterSize > 1)
            {
                builder = ClusterVNodeBuilder.AsClusterMember(options.ClusterSize);
                if (options.ReadOnlyReplica)
                {
                    builder.EnableReadOnlyReplica();
                }
            }
            else
            {
                builder = ClusterVNodeBuilder.AsSingleNode();
            }

            builder.WithLoadConfigFunction(loadConfigFunc);

            if (options.MemDb)
            {
                builder = builder.RunInMemory();
            }
            else
            {
                builder = builder.RunOnDisk(options.Db);
            }

            if (options.WriteStatsToDb)
            {
                builder = builder.WithStatsStorage(StatsStorage.StreamAndFile);
            }
            else
            {
                builder = builder.WithStatsStorage(StatsStorage.File);
            }

            builder.WithInternalTcpOn(intTcp)
            .WithInternalSecureTcpOn(intSecTcp)
            .WithExternalTcpOn(extTcp)
            .WithExternalSecureTcpOn(extSecTcp)
            .WithHttpOn(httpEndPoint)
            .WithWorkerThreads(options.WorkerThreads)
            .WithInternalHeartbeatTimeout(TimeSpan.FromMilliseconds(options.IntTcpHeartbeatTimeout))
            .WithInternalHeartbeatInterval(TimeSpan.FromMilliseconds(options.IntTcpHeartbeatInterval))
            .WithExternalHeartbeatTimeout(TimeSpan.FromMilliseconds(options.ExtTcpHeartbeatTimeout))
            .WithExternalHeartbeatInterval(TimeSpan.FromMilliseconds(options.ExtTcpHeartbeatInterval))
            .MaximumMemoryTableSizeOf(options.MaxMemTableSize)
            .WithHashCollisionReadLimitOf(options.HashCollisionReadLimit)
            .WithGossipInterval(TimeSpan.FromMilliseconds(options.GossipIntervalMs))
            .WithGossipAllowedTimeDifference(TimeSpan.FromMilliseconds(options.GossipAllowedDifferenceMs))
            .WithGossipTimeout(TimeSpan.FromMilliseconds(options.GossipTimeoutMs))
            .WithClusterGossipPort(options.ClusterGossipPort)
            .WithMinFlushDelay(TimeSpan.FromMilliseconds(options.MinFlushDelayMs))
            .WithPrepareTimeout(TimeSpan.FromMilliseconds(options.PrepareTimeoutMs))
            .WithCommitTimeout(TimeSpan.FromMilliseconds(options.CommitTimeoutMs))
            .WithWriteTimeout(TimeSpan.FromMilliseconds(options.WriteTimeoutMs))
            .WithStatsPeriod(TimeSpan.FromSeconds(options.StatsPeriodSec))
            .WithDeadMemberRemovalPeriod(TimeSpan.FromSeconds(options.DeadMemberRemovalPeriodSec))
            .WithPrepareCount(prepareCount)
            .WithCommitCount(commitCount)
            .WithNodePriority(options.NodePriority)
            .WithScavengeHistoryMaxAge(options.ScavengeHistoryMaxAge)
            .WithIndexPath(options.Index)
            .WithIndexVerification(options.SkipIndexVerify)
            .WithIndexCacheDepth(options.IndexCacheDepth)
            .WithIndexMergeOptimization(options.OptimizeIndexMerge)
            .RunProjections(options.RunProjections, options.ProjectionThreads, options.FaultOutOfOrderProjections)
            .WithProjectionQueryExpirationOf(TimeSpan.FromMinutes(options.ProjectionsQueryExpiry))
            .WithTfCachedChunks(options.CachedChunks)
            .WithTfChunksCacheSize(options.ChunksCacheSize)
            .AdvertiseInternalHostAs(options.IntHostAdvertiseAs)
            .AdvertiseExternalHostAs(options.ExtHostAdvertiseAs)
            .AdvertiseHostToClientAs(options.AdvertiseHostToClientAs)
            .AdvertiseHttpPortToClientAs(options.AdvertiseHttpPortToClientAs)
            .AdvertiseTcpPortToClientAs(options.AdvertiseTcpPortToClientAs)
            .AdvertiseHttpPortAs(options.HttpPortAdvertiseAs)
            .AdvertiseInternalTCPPortAs(intTcpPortAdvertiseAs)
            .AdvertiseExternalTCPPortAs(extTcpPortAdvertiseAs)
            .AdvertiseInternalSecureTCPPortAs(intSecTcpPortAdvertiseAs)
            .AdvertiseExternalSecureTCPPortAs(extSecTcpPortAdvertiseAs)
            .HavingReaderThreads(options.ReaderThreadsCount)
            .WithConnectionPendingSendBytesThreshold(options.ConnectionPendingSendBytesThreshold)
            .WithConnectionQueueSizeThreshold(options.ConnectionQueueSizeThreshold)
            .WithChunkInitialReaderCount(options.ChunkInitialReaderCount)
            .WithInitializationThreads(options.InitializationThreads)
            .WithMaxAutoMergeIndexLevel(options.MaxAutoMergeIndexLevel)
            .WithMaxTruncation(options.MaxTruncation)
            .WithMaxAppendSize(options.MaxAppendSize)
            .WithEnableAtomPubOverHTTP(options.EnableAtomPubOverHTTP)
            .WithStreamInfoCacheCapacity(options.StreamInfoCacheCapacity);

            if (options.GossipSeed.Length > 0)
            {
                builder.WithGossipSeeds(options.GossipSeed);
            }

            if (options.DiscoverViaDns)
            {
                builder.WithClusterDnsName(options.ClusterDns);
            }
            else
            {
                builder.DisableDnsDiscovery();
            }

            if (options.GossipOnSingleNode)
            {
                builder.GossipAsSingleNode();
            }

            if (options.EnableTrustedAuth)
            {
                builder.EnableTrustedAuth();
            }
            if (options.StartStandardProjections)
            {
                builder.StartStandardProjections();
            }
            if (options.DisableHTTPCaching)
            {
                builder.DisableHTTPCaching();
            }
            if (options.DisableScavengeMerging)
            {
                builder.DisableScavengeMerging();
            }
            if (options.LogHttpRequests)
            {
                builder.EnableLoggingOfHttpRequests();
            }
            if (options.LogFailedAuthenticationAttempts)
            {
                builder.EnableLoggingOfFailedAuthenticationAttempts();
            }
            if (options.EnableHistograms)
            {
                builder.EnableHistograms();
            }
            if (options.UnsafeIgnoreHardDelete)
            {
                builder.WithUnsafeIgnoreHardDelete();
            }
            if (options.UnsafeDisableFlushToDisk)
            {
                builder.WithUnsafeDisableFlushToDisk();
            }
            if (options.Insecure)
            {
                if (options.DisableInternalTcpTls || options.DisableExternalTcpTls)
                {
                    throw new InvalidConfigurationException($"The '{nameof(options.Insecure)}' option cannot be combined with the '{nameof(options.DisableInternalTcpTls)}' or the '{nameof(options.DisableExternalTcpTls)}' options.");
                }

                builder.DisableInternalTcpTls();
                builder.DisableExternalTcpTls();
                builder.DisableHttps();
            }
            if (options.DisableExternalTcpTls)
            {
                builder.DisableExternalTcpTls();
            }
            if (options.EnableExternalTCP)
            {
                builder.EnableExternalTCP();
            }
            if (options.DisableAdminUi)
            {
                builder.NoAdminOnPublicInterface();
            }
            if (options.DisableStatsOnHttp)
            {
                builder.NoStatsOnPublicInterface();
            }
            if (options.DisableGossipOnHttp)
            {
                builder.NoGossipOnPublicInterface();
            }
            if (options.SkipDbVerify)
            {
                builder.DoNotVerifyDbHashes();
            }
            if (options.AlwaysKeepScavenged)
            {
                builder.AlwaysKeepScavenged();
            }
            if (options.Unbuffered)
            {
                builder.EnableUnbuffered();
            }
            if (options.WriteThrough)
            {
                builder.EnableWriteThrough();
            }
            if (options.SkipIndexScanOnReads)
            {
                builder.SkipIndexScanOnReads();
            }
            if (options.ReduceFileCachePressure)
            {
                builder.ReduceFileCachePressure();
            }
            if (options.DisableFirstLevelHttpAuthorization)
            {
                builder.DisableFirstLevelHttpAuthorization();
            }
            if (options.UnsafeAllowSurplusNodes)
            {
                builder.WithUnsafeAllowSurplusNodes();
            }

            builder.WithCertificateReservedNodeCommonName(options.CertificateReservedNodeCommonName);

            bool requireCertificates = !options.Insecure;

            if (options.Insecure)
            {
                Log.Warning(
                    "Authentication and Authorization is disabled on all TCP/HTTP interfaces. " +
                    "It is recommended to run with Authentication and Authorization enabled in production");
                Log.Warning(
                    "TLS is disabled on all TCP/HTTP interfaces - no certificates are required to run EventStoreDB. " +
                    "It is recommended to run with TLS enabled in production.");
            }
            else
            {
                Log.Information(
                    "TLS is enabled on at least one TCP/HTTP interface - a certificate is required to run EventStoreDB.");
            }

            if (requireCertificates)
            {
                if (!string.IsNullOrWhiteSpace(options.CertificateStoreLocation))
                {
                    var location = CertificateLoader.GetCertificateStoreLocation(options.CertificateStoreLocation);
                    var name     = CertificateLoader.GetCertificateStoreName(options.CertificateStoreName);
                    builder.WithServerCertificateFromStore(location, name, options.CertificateSubjectName,
                                                           options.CertificateThumbprint);
                }
                else if (!string.IsNullOrWhiteSpace(options.CertificateStoreName))
                {
                    var name = CertificateLoader.GetCertificateStoreName(options.CertificateStoreName);
                    builder.WithServerCertificateFromStore(name, options.CertificateSubjectName,
                                                           options.CertificateThumbprint);
                }
                else if (options.CertificateFile.IsNotEmptyString())
                {
                    builder.WithServerCertificateFromFile(
                        options.CertificateFile,
                        options.CertificatePrivateKeyFile,
                        options.CertificatePassword);
                }
                else
                {
                    throw new InvalidConfigurationException(
                              "A certificate is required unless insecure mode (--insecure) is set.");
                }

                if (!string.IsNullOrEmpty(options.TrustedRootCertificatesPath))
                {
                    builder.WithTrustedRootCertificatesPath(options.TrustedRootCertificatesPath);
                }
                else
                {
                    throw new InvalidConfigurationException(
                              $"{nameof(options.TrustedRootCertificatesPath)} must be specified unless insecure mode (--insecure) is set.");
                }
            }

            var authorizationConfig = String.IsNullOrEmpty(options.AuthorizationConfig)
                                ? options.Config
                                : options.AuthorizationConfig;

            var authenticationConfig = String.IsNullOrEmpty(options.AuthenticationConfig)
                                ? options.Config
                                : options.AuthenticationConfig;

            var pluginLoader = new PluginLoader(new DirectoryInfo(Locations.PluginsDirectory));

            AuthenticationProviderFactory authenticationProviderFactory;
            AuthorizationProviderFactory  authorizationProviderFactory;

            if (!options.Insecure)
            {
                authorizationProviderFactory =
                    GetAuthorizationProviderFactory(options.AuthorizationType, authorizationConfig, pluginLoader);
                authenticationProviderFactory =
                    GetAuthenticationProviderFactory(options.AuthenticationType, authenticationConfig, pluginLoader);
            }
            else
            {
                authorizationProviderFactory  = new AuthorizationProviderFactory(components => new PassthroughAuthorizationProviderFactory());
                authenticationProviderFactory = new AuthenticationProviderFactory(components => new PassthroughAuthenticationProviderFactory());
            }

            var plugInContainer = FindPlugins();

            var consumerStrategyFactories = GetPlugInConsumerStrategyFactories(plugInContainer);

            builder.WithAuthenticationProviderFactory(authenticationProviderFactory,
                                                      options.AuthenticationType == Opts.AuthenticationTypeDefault && !options.Insecure);
            builder.WithAuthorizationProvider(authorizationProviderFactory);
            var subsystemFactories = GetPlugInSubsystemFactories(plugInContainer);

            foreach (var subsystemFactory in subsystemFactories)
            {
                var subsystem = subsystemFactory.Create(options.Config);
                builder.AddCustomSubsystem(subsystem);
            }

            return(builder.Build(options, consumerStrategyFactories));
        }