diff options
| author | Stefan Boberg <[email protected]> | 2025-10-14 11:32:16 +0200 |
|---|---|---|
| committer | GitHub Enterprise <[email protected]> | 2025-10-14 11:32:16 +0200 |
| commit | ca09abbeef5b1788f4a52b61eedd2f3dd07f81f2 (patch) | |
| tree | 005a50adfddf6982bab3a06bb93d4c50da1a11fd /src/zenserver/storageconfig.cpp | |
| parent | make asiohttp work without IPv6 (#562) (diff) | |
| download | zen-ca09abbeef5b1788f4a52b61eedd2f3dd07f81f2.tar.xz zen-ca09abbeef5b1788f4a52b61eedd2f3dd07f81f2.zip | |
move all storage-related services into storage tree (#571)
* move all storage-related services into storage tree
* move config into config/
* also move admin service into storage since it mostly has storage related functionality
* header consolidation
Diffstat (limited to 'src/zenserver/storageconfig.cpp')
| -rw-r--r-- | src/zenserver/storageconfig.cpp | 1055 |
1 files changed, 0 insertions, 1055 deletions
diff --git a/src/zenserver/storageconfig.cpp b/src/zenserver/storageconfig.cpp deleted file mode 100644 index 86bb09c21..000000000 --- a/src/zenserver/storageconfig.cpp +++ /dev/null @@ -1,1055 +0,0 @@ -// Copyright Epic Games, Inc. All Rights Reserved. - -#include "storageconfig.h" - -#include <zencore/basicfile.h> -#include <zencore/crypto.h> -#include <zencore/except.h> -#include <zencore/logging.h> - -#include "config/luaconfig.h" - -ZEN_THIRD_PARTY_INCLUDES_START -#include <fmt/format.h> -#include <cxxopts.hpp> -#include <json11.hpp> -ZEN_THIRD_PARTY_INCLUDES_END - -namespace zen { - -void -ValidateOptions(ZenStorageServerOptions& ServerOptions) -{ - if (ServerOptions.EncryptionKey.empty() == false) - { - const auto Key = AesKey256Bit::FromString(ServerOptions.EncryptionKey); - - if (Key.IsValid() == false) - { - throw OptionParseException(fmt::format("'--encryption-aes-key' ('{}') is malformed", ServerOptions.EncryptionKey), {}); - } - } - - if (ServerOptions.EncryptionIV.empty() == false) - { - const auto IV = AesIV128Bit::FromString(ServerOptions.EncryptionIV); - - if (IV.IsValid() == false) - { - throw OptionParseException(fmt::format("'--encryption-aes-iv' ('{}') is malformed", ServerOptions.EncryptionIV), {}); - } - } - if (ServerOptions.HttpServerConfig.ForceLoopback && ServerOptions.IsDedicated) - { - throw OptionParseException("'--dedicated' conflicts with '--http-forceloopback'", {}); - } - if (ServerOptions.GcConfig.AttachmentPassCount > ZenGcConfig::GcMaxAttachmentPassCount) - { - throw OptionParseException(fmt::format("'--gc-attachment-passes' ('{}') is invalid, maximum is {}.", - ServerOptions.GcConfig.AttachmentPassCount, - ZenGcConfig::GcMaxAttachmentPassCount), - {}); - } - if (ServerOptions.GcConfig.UseGCV2 == false) - { - ZEN_WARN("'--gc-v2=false' is deprecated, reverting to '--gc-v2=true'"); - ServerOptions.GcConfig.UseGCV2 = true; - } -} - -class ZenStructuredCacheBucketsConfigOption : public LuaConfig::OptionValue -{ -public: - ZenStructuredCacheBucketsConfigOption(std::vector<std::pair<std::string, ZenStructuredCacheBucketConfig>>& Value) : Value(Value) {} - virtual void Print(std::string_view Indent, StringBuilderBase& StringBuilder) override - { - if (Value.empty()) - { - StringBuilder.Append("{}"); - return; - } - LuaConfig::LuaContainerWriter Writer(StringBuilder, Indent); - for (const std::pair<std::string, ZenStructuredCacheBucketConfig>& Bucket : Value) - { - Writer.BeginContainer(""); - { - Writer.WriteValue("name", Bucket.first); - const ZenStructuredCacheBucketConfig& BucketConfig = Bucket.second; - - Writer.WriteValue("maxblocksize", fmt::format("{}", BucketConfig.MaxBlockSize)); - Writer.BeginContainer("memlayer"); - { - Writer.WriteValue("sizethreshold", fmt::format("{}", BucketConfig.MemCacheSizeThreshold)); - } - Writer.EndContainer(); - - Writer.WriteValue("payloadalignment", fmt::format("{}", BucketConfig.PayloadAlignment)); - Writer.WriteValue("largeobjectthreshold", fmt::format("{}", BucketConfig.PayloadAlignment)); - Writer.WriteValue("limitoverwrites", fmt::format("{}", BucketConfig.LimitOverwrites)); - } - Writer.EndContainer(); - } - } - virtual void Parse(sol::object Object) override - { - if (sol::optional<sol::table> Buckets = Object.as<sol::table>()) - { - for (const auto& Kv : Buckets.value()) - { - if (sol::optional<sol::table> Bucket = Kv.second.as<sol::table>()) - { - ZenStructuredCacheBucketConfig BucketConfig; - std::string Name = Kv.first.as<std::string>(); - if (Name.empty()) - { - throw OptionParseException("Cache bucket option must have a name.", {}); - } - - const uint64_t MaxBlockSize = Bucket.value().get_or("maxblocksize", BucketConfig.MaxBlockSize); - if (MaxBlockSize == 0) - { - throw OptionParseException( - fmt::format("'maxblocksize' option for cache bucket '{}' is invalid. It must be non-zero.", Name), - {}); - } - BucketConfig.MaxBlockSize = MaxBlockSize; - - if (sol::optional<sol::table> Memlayer = Bucket.value().get_or("memlayer", sol::table())) - { - const uint64_t MemCacheSizeThreshold = Bucket.value().get_or("sizethreshold", BucketConfig.MemCacheSizeThreshold); - if (MemCacheSizeThreshold == 0) - { - throw OptionParseException( - fmt::format("'memlayer.sizethreshold' option for cache bucket '{}' is invalid. It must be non-zero.", Name), - {}); - } - BucketConfig.MemCacheSizeThreshold = Bucket.value().get_or("sizethreshold", BucketConfig.MemCacheSizeThreshold); - } - - const uint32_t PayloadAlignment = Bucket.value().get_or("payloadalignment", BucketConfig.PayloadAlignment); - if (PayloadAlignment == 0 || !IsPow2(PayloadAlignment)) - { - throw OptionParseException( - fmt::format( - "'payloadalignment' option for cache bucket '{}' is invalid. It needs to be non-zero and a power of two.", - Name), - {}); - } - BucketConfig.PayloadAlignment = PayloadAlignment; - - const uint64_t LargeObjectThreshold = Bucket.value().get_or("largeobjectthreshold", BucketConfig.LargeObjectThreshold); - if (LargeObjectThreshold == 0) - { - throw OptionParseException( - fmt::format("'largeobjectthreshold' option for cache bucket '{}' is invalid. It must be non-zero.", Name), - {}); - } - BucketConfig.LargeObjectThreshold = LargeObjectThreshold; - - BucketConfig.LimitOverwrites = Bucket.value().get_or("limitoverwrites", BucketConfig.LimitOverwrites); - - Value.push_back(std::make_pair(std::move(Name), BucketConfig)); - } - } - } - } - std::vector<std::pair<std::string, ZenStructuredCacheBucketConfig>>& Value; -}; - -UpstreamCachePolicy -ParseUpstreamCachePolicy(std::string_view Options) -{ - if (Options == "readonly") - { - return UpstreamCachePolicy::Read; - } - else if (Options == "writeonly") - { - return UpstreamCachePolicy::Write; - } - else if (Options == "disabled") - { - return UpstreamCachePolicy::Disabled; - } - else - { - return UpstreamCachePolicy::ReadWrite; - } -} - -ZenObjectStoreConfig -ParseBucketConfigs(std::span<std::string> Buckets) -{ - using namespace std::literals; - - ZenObjectStoreConfig Cfg; - - // split bucket args in the form of "{BucketName};{LocalPath}" - for (std::string_view Bucket : Buckets) - { - ZenObjectStoreConfig::BucketConfig NewBucket; - - if (auto Idx = Bucket.find_first_of(";"); Idx != std::string_view::npos) - { - NewBucket.Name = Bucket.substr(0, Idx); - NewBucket.Directory = Bucket.substr(Idx + 1); - } - else - { - NewBucket.Name = Bucket; - } - - Cfg.Buckets.push_back(std::move(NewBucket)); - } - - return Cfg; -} - -class CachePolicyOption : public LuaConfig::OptionValue -{ -public: - CachePolicyOption(UpstreamCachePolicy& Value) : Value(Value) {} - virtual void Print(std::string_view, StringBuilderBase& StringBuilder) override - { - switch (Value) - { - case UpstreamCachePolicy::Read: - StringBuilder.Append("readonly"); - break; - case UpstreamCachePolicy::Write: - StringBuilder.Append("writeonly"); - break; - case UpstreamCachePolicy::Disabled: - StringBuilder.Append("disabled"); - break; - case UpstreamCachePolicy::ReadWrite: - StringBuilder.Append("readwrite"); - break; - default: - ZEN_ASSERT(false); - } - } - virtual void Parse(sol::object Object) override - { - std::string PolicyString = Object.as<std::string>(); - if (PolicyString == "readonly") - { - Value = UpstreamCachePolicy::Read; - } - else if (PolicyString == "writeonly") - { - Value = UpstreamCachePolicy::Write; - } - else if (PolicyString == "disabled") - { - Value = UpstreamCachePolicy::Disabled; - } - else if (PolicyString == "readwrite") - { - Value = UpstreamCachePolicy::ReadWrite; - } - } - UpstreamCachePolicy& Value; -}; - -class ZenAuthConfigOption : public LuaConfig::OptionValue -{ -public: - ZenAuthConfigOption(ZenAuthConfig& Value) : Value(Value) {} - virtual void Print(std::string_view Indent, StringBuilderBase& StringBuilder) override - { - if (Value.OpenIdProviders.empty()) - { - StringBuilder.Append("{}"); - return; - } - LuaConfig::LuaContainerWriter Writer(StringBuilder, Indent); - for (const ZenOpenIdProviderConfig& Config : Value.OpenIdProviders) - { - Writer.BeginContainer(""); - { - Writer.WriteValue("name", Config.Name); - Writer.WriteValue("url", Config.Url); - Writer.WriteValue("clientid", Config.ClientId); - } - Writer.EndContainer(); - } - } - virtual void Parse(sol::object Object) override - { - if (sol::optional<sol::table> OpenIdProviders = Object.as<sol::table>()) - { - for (const auto& Kv : OpenIdProviders.value()) - { - if (sol::optional<sol::table> OpenIdProvider = Kv.second.as<sol::table>()) - { - std::string Name = OpenIdProvider.value().get_or("name", std::string("Default")); - std::string Url = OpenIdProvider.value().get_or("url", std::string()); - std::string ClientId = OpenIdProvider.value().get_or("clientid", std::string()); - - Value.OpenIdProviders.push_back({.Name = std::move(Name), .Url = std::move(Url), .ClientId = std::move(ClientId)}); - } - } - } - } - ZenAuthConfig& Value; -}; - -class ZenObjectStoreConfigOption : public LuaConfig::OptionValue -{ -public: - ZenObjectStoreConfigOption(ZenObjectStoreConfig& Value) : Value(Value) {} - virtual void Print(std::string_view Indent, StringBuilderBase& StringBuilder) override - { - if (Value.Buckets.empty()) - { - StringBuilder.Append("{}"); - return; - } - LuaConfig::LuaContainerWriter Writer(StringBuilder, Indent); - for (const ZenObjectStoreConfig::BucketConfig& Config : Value.Buckets) - { - Writer.BeginContainer(""); - { - Writer.WriteValue("name", Config.Name); - std::string Directory = Config.Directory.string(); - LuaConfig::EscapeBackslash(Directory); - Writer.WriteValue("directory", Directory); - } - Writer.EndContainer(); - } - } - virtual void Parse(sol::object Object) override - { - if (sol::optional<sol::table> Buckets = Object.as<sol::table>()) - { - for (const auto& Kv : Buckets.value()) - { - if (sol::optional<sol::table> Bucket = Kv.second.as<sol::table>()) - { - std::string Name = Bucket.value().get_or("name", std::string("Default")); - std::string Directory = Bucket.value().get_or("directory", std::string()); - - Value.Buckets.push_back({.Name = std::move(Name), .Directory = MakeSafeAbsolutePath(Directory)}); - } - } - } - } - ZenObjectStoreConfig& Value; -}; - -std::shared_ptr<LuaConfig::OptionValue> -MakeOption(UpstreamCachePolicy& Value) -{ - return std::make_shared<CachePolicyOption>(Value); -}; - -std::shared_ptr<LuaConfig::OptionValue> -MakeOption(ZenAuthConfig& Value) -{ - return std::make_shared<ZenAuthConfigOption>(Value); -}; - -std::shared_ptr<LuaConfig::OptionValue> -MakeOption(ZenObjectStoreConfig& Value) -{ - return std::make_shared<ZenObjectStoreConfigOption>(Value); -}; - -std::shared_ptr<LuaConfig::OptionValue> -MakeOption(std::vector<std::pair<std::string, ZenStructuredCacheBucketConfig>>& Value) -{ - return std::make_shared<ZenStructuredCacheBucketsConfigOption>(Value); -}; - -void -ParseConfigFile(const std::filesystem::path& Path, - ZenStorageServerOptions& ServerOptions, - const cxxopts::ParseResult& CmdLineResult, - std::string_view OutputConfigFile) -{ - ZEN_TRACE_CPU("ParseConfigFile"); - - using namespace std::literals; - - LuaConfig::Options LuaOptions; - - AddServerConfigOptions(LuaOptions, ServerOptions); - - ////// server - LuaOptions.AddOption("server.pluginsconfigfile"sv, ServerOptions.PluginsConfigFile, "plugins-config"sv); - - ////// objectstore - LuaOptions.AddOption("server.objectstore.enabled"sv, ServerOptions.ObjectStoreEnabled, "objectstore-enabled"sv); - LuaOptions.AddOption("server.objectstore.buckets"sv, ServerOptions.ObjectStoreConfig); - - ////// buildsstore - LuaOptions.AddOption("server.buildstore.enabled"sv, ServerOptions.BuildStoreConfig.Enabled, "buildstore-enabled"sv); - LuaOptions.AddOption("server.buildstore.disksizelimit"sv, ServerOptions.BuildStoreConfig.MaxDiskSpaceLimit, "buildstore-disksizelimit"); - - ////// cache - LuaOptions.AddOption("cache.enable"sv, ServerOptions.StructuredCacheConfig.Enabled); - LuaOptions.AddOption("cache.writelog"sv, ServerOptions.StructuredCacheConfig.WriteLogEnabled, "cache-write-log"sv); - LuaOptions.AddOption("cache.accesslog"sv, ServerOptions.StructuredCacheConfig.AccessLogEnabled, "cache-access-log"sv); - - LuaOptions.AddOption("cache.buckets"sv, ServerOptions.StructuredCacheConfig.PerBucketConfigs, "cache.buckets"sv); - - LuaOptions.AddOption("cache.memlayer.sizethreshold"sv, - ServerOptions.StructuredCacheConfig.BucketConfig.MemCacheSizeThreshold, - "cache-memlayer-sizethreshold"sv); - LuaOptions.AddOption("cache.memlayer.targetfootprint"sv, - ServerOptions.StructuredCacheConfig.MemTargetFootprintBytes, - "cache-memlayer-targetfootprint"sv); - LuaOptions.AddOption("cache.memlayer.triminterval"sv, - ServerOptions.StructuredCacheConfig.MemTrimIntervalSeconds, - "cache-memlayer-triminterval"sv); - LuaOptions.AddOption("cache.memlayer.maxage"sv, ServerOptions.StructuredCacheConfig.MemMaxAgeSeconds, "cache-memlayer-maxage"sv); - - LuaOptions.AddOption("cache.bucket.maxblocksize"sv, - ServerOptions.StructuredCacheConfig.BucketConfig.MaxBlockSize, - "cache-bucket-maxblocksize"sv); - LuaOptions.AddOption("cache.bucket.memlayer.sizethreshold"sv, - ServerOptions.StructuredCacheConfig.BucketConfig.MemCacheSizeThreshold, - "cache-bucket-memlayer-sizethreshold"sv); - LuaOptions.AddOption("cache.bucket.payloadalignment"sv, - ServerOptions.StructuredCacheConfig.BucketConfig.PayloadAlignment, - "cache-bucket-payloadalignment"sv); - LuaOptions.AddOption("cache.bucket.largeobjectthreshold"sv, - ServerOptions.StructuredCacheConfig.BucketConfig.LargeObjectThreshold, - "cache-bucket-largeobjectthreshold"sv); - LuaOptions.AddOption("cache.bucket.limitoverwrites"sv, - ServerOptions.StructuredCacheConfig.BucketConfig.LimitOverwrites, - "cache-bucket-limit-overwrites"sv); - - ////// cache.upstream - LuaOptions.AddOption("cache.upstream.policy"sv, ServerOptions.UpstreamCacheConfig.CachePolicy, "upstream-cache-policy"sv); - LuaOptions.AddOption("cache.upstream.upstreamthreadcount"sv, - ServerOptions.UpstreamCacheConfig.UpstreamThreadCount, - "upstream-thread-count"sv); - LuaOptions.AddOption("cache.upstream.connecttimeoutms"sv, - ServerOptions.UpstreamCacheConfig.ConnectTimeoutMilliseconds, - "upstream-connect-timeout-ms"sv); - LuaOptions.AddOption("cache.upstream.timeoutms"sv, ServerOptions.UpstreamCacheConfig.TimeoutMilliseconds, "upstream-timeout-ms"sv); - - ////// cache.upstream.jupiter - LuaOptions.AddOption("cache.upstream.jupiter.name"sv, ServerOptions.UpstreamCacheConfig.JupiterConfig.Name); - LuaOptions.AddOption("cache.upstream.jupiter.url"sv, ServerOptions.UpstreamCacheConfig.JupiterConfig.Url, "upstream-jupiter-url"sv); - LuaOptions.AddOption("cache.upstream.jupiter.oauthprovider"sv, - ServerOptions.UpstreamCacheConfig.JupiterConfig.OAuthUrl, - "upstream-jupiter-oauth-url"sv); - LuaOptions.AddOption("cache.upstream.jupiter.oauthclientid"sv, - ServerOptions.UpstreamCacheConfig.JupiterConfig.OAuthClientId, - "upstream-jupiter-oauth-clientid"); - LuaOptions.AddOption("cache.upstream.jupiter.oauthclientsecret"sv, - ServerOptions.UpstreamCacheConfig.JupiterConfig.OAuthClientSecret, - "upstream-jupiter-oauth-clientsecret"sv); - LuaOptions.AddOption("cache.upstream.jupiter.openidprovider"sv, - ServerOptions.UpstreamCacheConfig.JupiterConfig.OpenIdProvider, - "upstream-jupiter-openid-provider"sv); - LuaOptions.AddOption("cache.upstream.jupiter.token"sv, - ServerOptions.UpstreamCacheConfig.JupiterConfig.AccessToken, - "upstream-jupiter-token"sv); - LuaOptions.AddOption("cache.upstream.jupiter.namespace"sv, - ServerOptions.UpstreamCacheConfig.JupiterConfig.Namespace, - "upstream-jupiter-namespace"sv); - LuaOptions.AddOption("cache.upstream.jupiter.ddcnamespace"sv, - ServerOptions.UpstreamCacheConfig.JupiterConfig.DdcNamespace, - "upstream-jupiter-namespace-ddc"sv); - - ////// cache.upstream.zen - // LuaOptions.AddOption("cache.upstream.zen"sv, ServerOptions.UpstreamCacheConfig.ZenConfig); - LuaOptions.AddOption("cache.upstream.zen.name"sv, ServerOptions.UpstreamCacheConfig.ZenConfig.Name); - LuaOptions.AddOption("cache.upstream.zen.dns"sv, ServerOptions.UpstreamCacheConfig.ZenConfig.Dns); - LuaOptions.AddOption("cache.upstream.zen.url"sv, ServerOptions.UpstreamCacheConfig.ZenConfig.Urls); - - ////// gc - LuaOptions.AddOption("gc.enabled"sv, ServerOptions.GcConfig.Enabled, "gc-enabled"sv); - LuaOptions.AddOption("gc.v2"sv, ServerOptions.GcConfig.UseGCV2, "gc-v2"sv); - - LuaOptions.AddOption("gc.monitorintervalseconds"sv, ServerOptions.GcConfig.MonitorIntervalSeconds, "gc-monitor-interval-seconds"sv); - LuaOptions.AddOption("gc.intervalseconds"sv, ServerOptions.GcConfig.IntervalSeconds, "gc-interval-seconds"sv); - LuaOptions.AddOption("gc.collectsmallobjects"sv, ServerOptions.GcConfig.CollectSmallObjects, "gc-small-objects"sv); - LuaOptions.AddOption("gc.diskreservesize"sv, ServerOptions.GcConfig.DiskReserveSize, "disk-reserve-size"sv); - LuaOptions.AddOption("gc.disksizesoftlimit"sv, ServerOptions.GcConfig.DiskSizeSoftLimit, "gc-disksize-softlimit"sv); - LuaOptions.AddOption("gc.lowdiskspacethreshold"sv, - ServerOptions.GcConfig.MinimumFreeDiskSpaceToAllowWrites, - "gc-low-diskspace-threshold"sv); - LuaOptions.AddOption("gc.lightweightintervalseconds"sv, - ServerOptions.GcConfig.LightweightIntervalSeconds, - "gc-lightweight-interval-seconds"sv); - LuaOptions.AddOption("gc.compactblockthreshold"sv, - ServerOptions.GcConfig.CompactBlockUsageThresholdPercent, - "gc-compactblock-threshold"sv); - LuaOptions.AddOption("gc.verbose"sv, ServerOptions.GcConfig.Verbose, "gc-verbose"sv); - LuaOptions.AddOption("gc.single-threaded"sv, ServerOptions.GcConfig.SingleThreaded, "gc-single-threaded"sv); - LuaOptions.AddOption("gc.cache.attachment.store"sv, ServerOptions.GcConfig.StoreCacheAttachmentMetaData, "gc-cache-attachment-store"); - LuaOptions.AddOption("gc.projectstore.attachment.store"sv, - ServerOptions.GcConfig.StoreProjectAttachmentMetaData, - "gc-projectstore-attachment-store"); - LuaOptions.AddOption("gc.attachment.passes"sv, ServerOptions.GcConfig.AttachmentPassCount, "gc-attachment-passes"sv); - LuaOptions.AddOption("gc.validation"sv, ServerOptions.GcConfig.EnableValidation, "gc-validation"); - - LuaOptions.AddOption("gc.cache.maxdurationseconds"sv, ServerOptions.GcConfig.Cache.MaxDurationSeconds, "gc-cache-duration-seconds"sv); - LuaOptions.AddOption("gc.projectstore.duration.seconds"sv, - ServerOptions.GcConfig.ProjectStore.MaxDurationSeconds, - "gc-projectstore-duration-seconds"); - LuaOptions.AddOption("gc.buildstore.duration.seconds"sv, - ServerOptions.GcConfig.BuildStore.MaxDurationSeconds, - "gc-buildstore-duration-seconds"); - - ////// security - LuaOptions.AddOption("security.encryptionaeskey"sv, ServerOptions.EncryptionKey, "encryption-aes-key"sv); - LuaOptions.AddOption("security.encryptionaesiv"sv, ServerOptions.EncryptionIV, "encryption-aes-iv"sv); - LuaOptions.AddOption("security.openidproviders"sv, ServerOptions.AuthConfig); - - ////// workspaces - LuaOptions.AddOption("workspaces.enabled"sv, ServerOptions.WorksSpacesConfig.Enabled, "workspaces-enabled"sv); - LuaOptions.AddOption("workspaces.allowconfigchanges"sv, - ServerOptions.WorksSpacesConfig.AllowConfigurationChanges, - "workspaces-allow-changes"sv); - - LuaOptions.Parse(Path, CmdLineResult); - - // These have special command line processing so we make sure we export them if they were configured on command line - if (!ServerOptions.AuthConfig.OpenIdProviders.empty()) - { - LuaOptions.Touch("security.openidproviders"sv); - } - if (!ServerOptions.ObjectStoreConfig.Buckets.empty()) - { - LuaOptions.Touch("server.objectstore.buckets"sv); - } - if (!ServerOptions.StructuredCacheConfig.PerBucketConfigs.empty()) - { - LuaOptions.Touch("cache.buckets"sv); - } - - if (!OutputConfigFile.empty()) - { - std::filesystem::path WritePath(MakeSafeAbsolutePath(OutputConfigFile)); - ExtendableStringBuilder<512> ConfigStringBuilder; - LuaOptions.Print(ConfigStringBuilder, CmdLineResult); - BasicFile Output; - Output.Open(WritePath, BasicFile::Mode::kTruncate); - Output.Write(ConfigStringBuilder.Data(), ConfigStringBuilder.Size(), 0); - } -} - -void -ParsePluginsConfigFile(const std::filesystem::path& Path, ZenStorageServerOptions& ServerOptions, int BasePort) -{ - using namespace std::literals; - - IoBuffer Body = IoBufferBuilder::MakeFromFile(Path); - std::string JsonText(reinterpret_cast<const char*>(Body.GetData()), Body.GetSize()); - std::string JsonError; - json11::Json PluginsInfo = json11::Json::parse(JsonText, JsonError); - if (!JsonError.empty()) - { - ZEN_WARN("failed parsing plugins config file '{}'. Reason: '{}'", Path, JsonError); - return; - } - for (const json11::Json& PluginInfo : PluginsInfo.array_items()) - { - if (!PluginInfo.is_object()) - { - ZEN_WARN("the json file '{}' does not contain a valid plugin definition, object expected, got '{}'", Path, PluginInfo.dump()); - continue; - } - - HttpServerPluginConfig Config = {}; - - bool bNeedsPort = true; - - for (const std::pair<const std::string, json11::Json>& Items : PluginInfo.object_items()) - { - if (!Items.second.is_string()) - { - ZEN_WARN("the json file '{}' does not contain a valid plugins definition, string expected, got '{}'", - Path, - Items.second.dump()); - continue; - } - - const std::string& Name = Items.first; - const std::string& Value = Items.second.string_value(); - - if (Name == "name"sv) - Config.PluginName = Value; - else - { - Config.PluginOptions.push_back({Name, Value}); - - if (Name == "port"sv) - { - bNeedsPort = false; - } - } - } - - // add a default base port in case if json config didn't provide one - if (bNeedsPort) - { - Config.PluginOptions.push_back({"port", std::to_string(BasePort)}); - } - - ServerOptions.HttpServerConfig.PluginConfigs.push_back(Config); - } -} - -void -ZenStorageServerCmdLineOptions::AddCliOptions(cxxopts::Options& options, ZenStorageServerOptions& ServerOptions) -{ - options.add_options()("snapshot-dir", - "Specify a snapshot of server state to mirror into the persistence root at startup", - cxxopts::value<std::string>(BaseSnapshotDir)); - options.add_options()("plugins-config", "Path to plugins config file", cxxopts::value<std::string>(PluginsConfigFile)); - options.add_options()("scrub", - "Validate state at startup", - cxxopts::value(ServerOptions.ScrubOptions)->implicit_value("yes"), - "(nocas,nogc,nodelete,yes,no)*"); - - AddSecurityOptions(options, ServerOptions); - AddCacheOptions(options, ServerOptions); - AddGcOptions(options, ServerOptions); - AddObjectStoreOptions(options, ServerOptions); - AddBuildStoreOptions(options, ServerOptions); - AddWorkspacesOptions(options, ServerOptions); -} - -void -ZenStorageServerCmdLineOptions::AddSecurityOptions(cxxopts::Options& options, ZenStorageServerOptions& ServerOptions) -{ - options.add_option("security", - "", - "encryption-aes-key", - "256 bit AES encryption key", - cxxopts::value<std::string>(ServerOptions.EncryptionKey), - ""); - - options.add_option("security", - "", - "encryption-aes-iv", - "128 bit AES encryption initialization vector", - cxxopts::value<std::string>(ServerOptions.EncryptionIV), - ""); - - options.add_option("security", - "", - "openid-provider-name", - "Open ID provider name", - cxxopts::value<std::string>(OpenIdProviderName), - "Default"); - - options.add_option("security", "", "openid-provider-url", "Open ID provider URL", cxxopts::value<std::string>(OpenIdProviderUrl), ""); - options.add_option("security", "", "openid-client-id", "Open ID client ID", cxxopts::value<std::string>(OpenIdClientId), ""); -} - -void -ZenStorageServerCmdLineOptions::AddCacheOptions(cxxopts::Options& options, ZenStorageServerOptions& ServerOptions) -{ - options.add_option("cache", - "", - "upstream-cache-policy", - "", - cxxopts::value<std::string>(UpstreamCachePolicyOptions)->default_value(""), - "Upstream cache policy (readwrite|readonly|writeonly|disabled)"); - - options.add_option("cache", - "", - "upstream-jupiter-url", - "URL to a Jupiter instance", - cxxopts::value<std::string>(ServerOptions.UpstreamCacheConfig.JupiterConfig.Url)->default_value(""), - ""); - - options.add_option("cache", - "", - "upstream-jupiter-oauth-url", - "URL to the OAuth provier", - cxxopts::value<std::string>(ServerOptions.UpstreamCacheConfig.JupiterConfig.OAuthUrl)->default_value(""), - ""); - - options.add_option("cache", - "", - "upstream-jupiter-oauth-clientid", - "The OAuth client ID", - cxxopts::value<std::string>(ServerOptions.UpstreamCacheConfig.JupiterConfig.OAuthClientId)->default_value(""), - ""); - - options.add_option("cache", - "", - "upstream-jupiter-oauth-clientsecret", - "The OAuth client secret", - cxxopts::value<std::string>(ServerOptions.UpstreamCacheConfig.JupiterConfig.OAuthClientSecret)->default_value(""), - ""); - - options.add_option("cache", - "", - "upstream-jupiter-openid-provider", - "Name of a registered Open ID provider", - cxxopts::value<std::string>(ServerOptions.UpstreamCacheConfig.JupiterConfig.OpenIdProvider)->default_value(""), - ""); - - options.add_option("cache", - "", - "upstream-jupiter-token", - "A static authentication token", - cxxopts::value<std::string>(ServerOptions.UpstreamCacheConfig.JupiterConfig.AccessToken)->default_value(""), - ""); - - options.add_option("cache", - "", - "upstream-jupiter-namespace", - "The Common Blob Store API namespace", - cxxopts::value<std::string>(ServerOptions.UpstreamCacheConfig.JupiterConfig.Namespace)->default_value(""), - ""); - - options.add_option("cache", - "", - "upstream-jupiter-namespace-ddc", - "The lecacy DDC namespace", - cxxopts::value<std::string>(ServerOptions.UpstreamCacheConfig.JupiterConfig.DdcNamespace)->default_value(""), - ""); - - options.add_option("cache", - "", - "upstream-zen-url", - "URL to remote Zen server. Use a comma separated list to choose the one with the best latency.", - cxxopts::value<std::vector<std::string>>(ServerOptions.UpstreamCacheConfig.ZenConfig.Urls), - ""); - - options.add_option("cache", - "", - "upstream-zen-dns", - "DNS that resolves to one or more Zen server instance(s)", - cxxopts::value<std::vector<std::string>>(ServerOptions.UpstreamCacheConfig.ZenConfig.Dns), - ""); - - options.add_option("cache", - "", - "upstream-thread-count", - "Number of threads used for upstream procsssing", - cxxopts::value<int32_t>(ServerOptions.UpstreamCacheConfig.UpstreamThreadCount)->default_value("4"), - ""); - - options.add_option("cache", - "", - "upstream-connect-timeout-ms", - "Connect timeout in millisecond(s). Default 5000 ms.", - cxxopts::value<int32_t>(ServerOptions.UpstreamCacheConfig.ConnectTimeoutMilliseconds)->default_value("5000"), - ""); - - options.add_option("cache", - "", - "upstream-timeout-ms", - "Timeout in millisecond(s). Default 0 ms", - cxxopts::value<int32_t>(ServerOptions.UpstreamCacheConfig.TimeoutMilliseconds)->default_value("0"), - ""); - - options.add_option("cache", - "", - "cache-write-log", - "Whether cache write log is enabled", - cxxopts::value<bool>(ServerOptions.StructuredCacheConfig.WriteLogEnabled)->default_value("false"), - ""); - - options.add_option("cache", - "", - "cache-access-log", - "Whether cache access log is enabled", - cxxopts::value<bool>(ServerOptions.StructuredCacheConfig.AccessLogEnabled)->default_value("false"), - ""); - - options.add_option( - "cache", - "", - "cache-memlayer-sizethreshold", - "The largest size of a cache entry that may be cached in memory. Default set to 1024 (1 Kb). Set to 0 to disable memory " - "caching. " - "Obsolete, replaced by `--cache-bucket-memlayer-sizethreshold`", - cxxopts::value<uint64_t>(ServerOptions.StructuredCacheConfig.BucketConfig.MemCacheSizeThreshold)->default_value("1024"), - ""); - - options.add_option("cache", - "", - "cache-memlayer-targetfootprint", - "Max allowed memory used by cache memory layer per namespace in bytes. Default set to 536870912 (512 Mb).", - cxxopts::value<uint64_t>(ServerOptions.StructuredCacheConfig.MemTargetFootprintBytes)->default_value("536870912"), - ""); - - options.add_option("cache", - "", - "cache-memlayer-triminterval", - "Minimum time between each attempt to trim cache memory layers in seconds. Default set to 60 (1 min).", - cxxopts::value<uint64_t>(ServerOptions.StructuredCacheConfig.MemTrimIntervalSeconds)->default_value("60"), - ""); - - options.add_option("cache", - "", - "cache-memlayer-maxage", - "Maximum age of payloads when trimming cache memory layers in seconds. Default set to 86400 (1 day).", - cxxopts::value<uint64_t>(ServerOptions.StructuredCacheConfig.MemMaxAgeSeconds)->default_value("86400"), - ""); - - options.add_option("cache", - "", - "cache-bucket-maxblocksize", - "Max size of cache bucket blocks. Default set to 1073741824 (1GB).", - cxxopts::value<uint64_t>(ServerOptions.StructuredCacheConfig.BucketConfig.MaxBlockSize)->default_value("1073741824"), - ""); - - options.add_option("cache", - "", - "cache-bucket-payloadalignment", - "Payload alignement for cache bucket blocks. Default set to 16.", - cxxopts::value<uint32_t>(ServerOptions.StructuredCacheConfig.BucketConfig.PayloadAlignment)->default_value("16"), - ""); - - options.add_option( - "cache", - "", - "cache-bucket-largeobjectthreshold", - "Threshold for storing cache bucket values as loose files. Default set to 131072 (128 KB).", - cxxopts::value<uint64_t>(ServerOptions.StructuredCacheConfig.BucketConfig.LargeObjectThreshold)->default_value("131072"), - ""); - - options.add_option( - "cache", - "", - "cache-bucket-memlayer-sizethreshold", - "The largest size of a cache entry that may be cached in memory. Default set to 1024 (1 Kb). Set to 0 to disable memory " - "caching.", - cxxopts::value<uint64_t>(ServerOptions.StructuredCacheConfig.BucketConfig.MemCacheSizeThreshold)->default_value("1024"), - ""); - - options.add_option("cache", - "", - "cache-bucket-limit-overwrites", - "Whether to require policy flag pattern before allowing overwrites in cache bucket", - cxxopts::value<bool>(ServerOptions.StructuredCacheConfig.BucketConfig.LimitOverwrites)->default_value("false"), - ""); -} - -void -ZenStorageServerCmdLineOptions::AddGcOptions(cxxopts::Options& options, ZenStorageServerOptions& ServerOptions) -{ - options.add_option("gc", - "", - "gc-cache-attachment-store", - "Enable storing attachments referenced by a cache record in block store meta data.", - cxxopts::value<bool>(ServerOptions.GcConfig.StoreCacheAttachmentMetaData)->default_value("false"), - ""); - - options.add_option("gc", - "", - "gc-projectstore-attachment-store", - "Enable storing attachments referenced by project oplogs in meta data.", - cxxopts::value<bool>(ServerOptions.GcConfig.StoreProjectAttachmentMetaData)->default_value("false"), - ""); - - options.add_option("gc", - "", - "gc-validation", - "Enable validation of references after full GC.", - cxxopts::value<bool>(ServerOptions.GcConfig.EnableValidation)->default_value("true"), - ""); - - options.add_option("gc", - "", - "gc-enabled", - "Whether garbage collection is enabled or not.", - cxxopts::value<bool>(ServerOptions.GcConfig.Enabled)->default_value("true"), - ""); - - options.add_option("gc", - "", - "gc-v2", - "Use V2 of GC implementation or not.", - cxxopts::value<bool>(ServerOptions.GcConfig.UseGCV2)->default_value("true"), - ""); - - options.add_option("gc", - "", - "gc-small-objects", - "Whether garbage collection of small objects is enabled or not.", - cxxopts::value<bool>(ServerOptions.GcConfig.CollectSmallObjects)->default_value("true"), - ""); - - options.add_option("gc", - "", - "gc-interval-seconds", - "Garbage collection interval in seconds. Default set to 3600 (1 hour).", - cxxopts::value<int32_t>(ServerOptions.GcConfig.IntervalSeconds)->default_value("3600"), - ""); - - options.add_option("gc", - "", - "gc-lightweight-interval-seconds", - "Lightweight garbage collection interval in seconds. Default set to 900 (30 min).", - cxxopts::value<int32_t>(ServerOptions.GcConfig.LightweightIntervalSeconds)->default_value("900"), - ""); - - options.add_option("gc", - "", - "gc-cache-duration-seconds", - "Max duration in seconds before Z$ entries get evicted. Default set to 1209600 (2 weeks)", - cxxopts::value<int32_t>(ServerOptions.GcConfig.Cache.MaxDurationSeconds)->default_value("1209600"), - ""); - - options.add_option("gc", - "", - "gc-projectstore-duration-seconds", - "Max duration in seconds before project store entries get evicted. Default set to 1209600 (2 weeks)", - cxxopts::value<int32_t>(ServerOptions.GcConfig.ProjectStore.MaxDurationSeconds)->default_value("1209600"), - ""); - - options.add_option("gc", - "", - "gc-buildstore-duration-seconds", - "Max duration in seconds before build store entries get evicted. Default set to 604800 (1 week)", - cxxopts::value<int32_t>(ServerOptions.GcConfig.BuildStore.MaxDurationSeconds)->default_value("604800"), - ""); - - options.add_option("gc", - "", - "disk-reserve-size", - "Size of gc disk reserve in bytes. Default set to 268435456 (256 Mb). Set to zero to disable.", - cxxopts::value<uint64_t>(ServerOptions.GcConfig.DiskReserveSize)->default_value("268435456"), - ""); - - options.add_option("gc", - "", - "gc-monitor-interval-seconds", - "Garbage collection monitoring interval in seconds. Default set to 30 (30 seconds)", - cxxopts::value<int32_t>(ServerOptions.GcConfig.MonitorIntervalSeconds)->default_value("30"), - ""); - - options.add_option("gc", - "", - "gc-low-diskspace-threshold", - "Minimum free space on disk to allow writes to disk. Default set to 268435456 (256 Mb). Set to zero to disable.", - cxxopts::value<uint64_t>(ServerOptions.GcConfig.MinimumFreeDiskSpaceToAllowWrites)->default_value("268435456"), - ""); - - options.add_option("gc", - "", - "gc-disksize-softlimit", - "Garbage collection disk usage soft limit. Default set to 0 (Off).", - cxxopts::value<uint64_t>(ServerOptions.GcConfig.DiskSizeSoftLimit)->default_value("0"), - ""); - - options.add_option("gc", - "", - "gc-compactblock-threshold", - "Garbage collection - how much of a compact block should be used to skip compacting the block. 0 - compact only " - "empty eligible blocks, 100 - compact all non-full eligible blocks.", - cxxopts::value<uint32_t>(ServerOptions.GcConfig.CompactBlockUsageThresholdPercent)->default_value("60"), - ""); - - options.add_option("gc", - "", - "gc-verbose", - "Enable verbose logging for GC.", - cxxopts::value<bool>(ServerOptions.GcConfig.Verbose)->default_value("false"), - ""); - - options.add_option("gc", - "", - "gc-single-threaded", - "Force GC to run single threaded.", - cxxopts::value<bool>(ServerOptions.GcConfig.SingleThreaded)->default_value("false"), - ""); - - options.add_option("gc", - "", - "gc-attachment-passes", - "Limit the range of unreferenced attachments included in GC check by breaking it into passes. Default is one pass " - "which includes all the attachments.", - cxxopts::value<uint16_t>(ServerOptions.GcConfig.AttachmentPassCount)->default_value("1"), - ""); -} - -void -ZenStorageServerCmdLineOptions::AddObjectStoreOptions(cxxopts::Options& options, ZenStorageServerOptions& ServerOptions) -{ - options.add_option("objectstore", - "", - "objectstore-enabled", - "Whether the object store is enabled or not.", - cxxopts::value<bool>(ServerOptions.ObjectStoreEnabled)->default_value("false"), - ""); - - options.add_option("objectstore", - "", - "objectstore-bucket", - "Object store bucket mappings.", - cxxopts::value<std::vector<std::string>>(BucketConfigs), - ""); -} - -void -ZenStorageServerCmdLineOptions::AddBuildStoreOptions(cxxopts::Options& options, ZenStorageServerOptions& ServerOptions) -{ - options.add_option("buildstore", - "", - "buildstore-enabled", - "Whether the builds store is enabled or not.", - cxxopts::value<bool>(ServerOptions.BuildStoreConfig.Enabled)->default_value("false"), - ""); - options.add_option("buildstore", - "", - "buildstore-disksizelimit", - "Max number of bytes before build store entries get evicted. Default set to 1099511627776 (1TB week)", - cxxopts::value<uint64_t>(ServerOptions.BuildStoreConfig.MaxDiskSpaceLimit)->default_value("1099511627776"), - ""); -} - -void -ZenStorageServerCmdLineOptions::AddWorkspacesOptions(cxxopts::Options& options, ZenStorageServerOptions& ServerOptions) -{ - options.add_option("workspaces", - "", - "workspaces-enabled", - "", - cxxopts::value<bool>(ServerOptions.WorksSpacesConfig.Enabled)->default_value("true"), - "Enable workspaces support with folder sharing"); - - options.add_option("workspaces", - "", - "workspaces-allow-changes", - "", - cxxopts::value<bool>(ServerOptions.WorksSpacesConfig.AllowConfigurationChanges)->default_value("false"), - "Allow adding/modifying/deleting of workspace and shares via http endpoint"); -} - -void -ZenStorageServerCmdLineOptions::ApplyOptions(cxxopts::Options& options, ZenStorageServerOptions& ServerOptions) -{ - ServerOptions.BaseSnapshotDir = MakeSafeAbsolutePath(BaseSnapshotDir); - ServerOptions.PluginsConfigFile = MakeSafeAbsolutePath(PluginsConfigFile); - ServerOptions.UpstreamCacheConfig.CachePolicy = ParseUpstreamCachePolicy(UpstreamCachePolicyOptions); - - if (!BaseSnapshotDir.empty()) - { - if (ServerOptions.DataDir.empty()) - throw OptionParseException("'--snapshot-dir' requires '--data-dir'", options.help()); - - if (!IsDir(ServerOptions.BaseSnapshotDir)) - throw std::runtime_error(fmt::format("'--snapshot-dir' ('{}') must be a directory", ServerOptions.BaseSnapshotDir)); - } - - if (OpenIdProviderUrl.empty() == false) - { - if (OpenIdClientId.empty()) - { - throw OptionParseException("'--openid-provider-url' requires '--openid-client-id'", options.help()); - } - - ServerOptions.AuthConfig.OpenIdProviders.push_back( - {.Name = OpenIdProviderName, .Url = OpenIdProviderUrl, .ClientId = OpenIdClientId}); - } - - ServerOptions.ObjectStoreConfig = ParseBucketConfigs(BucketConfigs); -} - -} // namespace zen |