|
1 | 1 | #include "node_warden_impl.h"
|
| 2 | +#include "distconf.h" |
2 | 3 |
|
3 | 4 | #include <ydb/core/blobstorage/crypto/secured_block.h>
|
4 | 5 | #include <ydb/core/blobstorage/dsproxy/dsproxy_request_reporting.h>
|
@@ -232,20 +233,13 @@ void TNodeWarden::Bootstrap() {
|
232 | 233 | // determine if we are running in 'mock' mode
|
233 | 234 | EnableProxyMock = Cfg->BlobStorageConfig.GetServiceSet().GetEnableProxyMock();
|
234 | 235 |
|
235 |
| - // fill in a storage config |
236 |
| - StorageConfig.MutableBlobStorageConfig()->CopyFrom(Cfg->BlobStorageConfig); |
237 |
| - for (const auto& node : Cfg->NameserviceConfig.GetNode()) { |
238 |
| - auto *r = StorageConfig.AddAllNodes(); |
239 |
| - r->SetHost(node.GetInterconnectHost()); |
240 |
| - r->SetPort(node.GetPort()); |
241 |
| - r->SetNodeId(node.GetNodeId()); |
242 |
| - if (node.HasLocation()) { |
243 |
| - r->MutableLocation()->CopyFrom(node.GetLocation()); |
244 |
| - } else if (node.HasWalleLocation()) { |
245 |
| - r->MutableLocation()->CopyFrom(node.GetWalleLocation()); |
246 |
| - } |
247 |
| - } |
248 |
| - StorageConfig.SetClusterUUID(Cfg->NameserviceConfig.GetClusterUUID()); |
| 236 | + // fill in a base storage config (from the file) |
| 237 | + NKikimrConfig::TAppConfig appConfig; |
| 238 | + appConfig.MutableBlobStorageConfig()->CopyFrom(Cfg->BlobStorageConfig); |
| 239 | + appConfig.MutableNameserviceConfig()->CopyFrom(Cfg->NameserviceConfig); |
| 240 | + TString errorReason; |
| 241 | + const bool success = DeriveStorageConfig(appConfig, &StorageConfig, &errorReason); |
| 242 | + Y_VERIFY_S(success, "failed to generate initial TStorageConfig: " << errorReason); |
249 | 243 |
|
250 | 244 | // Start a statically configured set
|
251 | 245 | if (Cfg->BlobStorageConfig.HasServiceSet()) {
|
@@ -831,6 +825,175 @@ bool NKikimr::ObtainPDiskKey(NPDisk::TMainKey *mainKey, const NKikimrProto::TKey
|
831 | 825 | return true;
|
832 | 826 | }
|
833 | 827 |
|
| 828 | +bool NKikimr::NStorage::DeriveStorageConfig(const NKikimrConfig::TAppConfig& appConfig, |
| 829 | + NKikimrBlobStorage::TStorageConfig *config, TString *errorReason) { |
| 830 | + // copy blob storage config |
| 831 | + if (!appConfig.HasBlobStorageConfig()) { |
| 832 | + *errorReason = "original config missing mandatory BlobStorageConfig section"; |
| 833 | + return false; |
| 834 | + } |
| 835 | + |
| 836 | + const auto& bsFrom = appConfig.GetBlobStorageConfig(); |
| 837 | + auto *bsTo = config->MutableBlobStorageConfig(); |
| 838 | + if (bsFrom.HasAutoconfigSettings()) { |
| 839 | + const auto& acFrom = bsFrom.GetAutoconfigSettings(); |
| 840 | + auto *acTo = bsTo->MutableAutoconfigSettings(); |
| 841 | + if (acFrom.HasGeneration() && acTo->HasGeneration() && acTo->GetGeneration() + 1 != acFrom.GetGeneration()) { |
| 842 | + *errorReason = TStringBuilder() << "generation mismatch for AutoconfigSettings section existing Generation# " |
| 843 | + << acTo->GetGeneration() << " newly provided Generation# " << acFrom.GetGeneration(); |
| 844 | + return false; |
| 845 | + } else if (acTo->HasGeneration() && !acFrom.HasGeneration()) { |
| 846 | + *errorReason = "existing AutoconfigSettings has set generation, but newly provided one doesn't have it"; |
| 847 | + return false; |
| 848 | + } |
| 849 | + |
| 850 | + acTo->CopyFrom(acFrom); |
| 851 | + } else { |
| 852 | + bsTo->ClearAutoconfigSettings(); |
| 853 | + } |
| 854 | + |
| 855 | + if (bsFrom.HasServiceSet()) { |
| 856 | + const auto& ssFrom = bsFrom.GetServiceSet(); |
| 857 | + auto *ssTo = bsTo->MutableServiceSet(); |
| 858 | + |
| 859 | + ssTo->MutableAvailabilityDomains()->CopyFrom(ssFrom.GetAvailabilityDomains()); |
| 860 | + if (ssFrom.HasReplBrokerConfig()) { |
| 861 | + ssTo->MutableReplBrokerConfig()->CopyFrom(ssFrom.GetReplBrokerConfig()); |
| 862 | + } |
| 863 | + if (!ssTo->PDisksSize() && !ssTo->VDisksSize() && !ssTo->GroupsSize()) { |
| 864 | + ssTo->MutablePDisks()->CopyFrom(ssFrom.GetPDisks()); |
| 865 | + ssTo->MutableVDisks()->CopyFrom(ssFrom.GetVDisks()); |
| 866 | + ssTo->MutableGroups()->CopyFrom(ssFrom.GetGroups()); |
| 867 | + } else { |
| 868 | + NProtoBuf::util::MessageDifferencer differ; |
| 869 | + |
| 870 | + auto error = [&](auto&& key, const char *error) { |
| 871 | + *errorReason = TStringBuilder() << key() << ' ' << error; |
| 872 | + return false; |
| 873 | + }; |
| 874 | + |
| 875 | + auto pdiskKey = [](const auto *item) { |
| 876 | + return TStringBuilder() << "PDisk NodeId# " << item->GetNodeID() << " PDiskId# " << item->GetPDiskID(); |
| 877 | + }; |
| 878 | + |
| 879 | + auto vdiskKey = [](const auto *item) { |
| 880 | + return TStringBuilder() << "VDisk NodeId# " << item->GetNodeID() << " PDiskId# " << item->GetPDiskID() |
| 881 | + << " VDiskSlotId# " << item->GetVDiskSlotID(); |
| 882 | + }; |
| 883 | + |
| 884 | + auto groupKey = [](const auto *item) { |
| 885 | + return TStringBuilder() << "group GroupId# " << item->GetGroupID(); |
| 886 | + }; |
| 887 | + |
| 888 | + auto duplicateKey = [&](auto&& key) { return error(std::move(key), "duplicate key in existing StorageConfig"); }; |
| 889 | + auto removed = [&](auto&& key) { return error(std::move(key), "was removed from BlobStorageConfig of newly provided configuration"); }; |
| 890 | + auto mismatch = [&](auto&& key) { return error(std::move(key), "configuration item mismatch"); }; |
| 891 | + |
| 892 | + THashMap<std::tuple<ui32, ui32>, const NKikimrBlobStorage::TNodeWardenServiceSet::TPDisk*> pdiskMap; |
| 893 | + for (const auto& item : ssTo->GetPDisks()) { |
| 894 | + if (const auto [it, inserted] = pdiskMap.emplace(std::make_tuple(item.GetNodeID(), item.GetPDiskID()), |
| 895 | + &item); !inserted) { |
| 896 | + return duplicateKey(std::bind(pdiskKey, &item)); |
| 897 | + } |
| 898 | + } |
| 899 | + for (const auto& item : ssFrom.GetPDisks()) { |
| 900 | + if (const auto it = pdiskMap.find(std::make_tuple(item.GetNodeID(), item.GetPDiskID())); it == pdiskMap.end()) { |
| 901 | + return removed(std::bind(pdiskKey, &item)); |
| 902 | + } else if (!differ.Equals(item, *it->second)) { |
| 903 | + return mismatch(std::bind(pdiskKey, &item)); |
| 904 | + } else { |
| 905 | + pdiskMap.erase(it); |
| 906 | + } |
| 907 | + } |
| 908 | + if (!pdiskMap.empty()) { |
| 909 | + *errorReason = "some PDisks were added in newly provided configuration"; |
| 910 | + return false; |
| 911 | + } |
| 912 | + |
| 913 | + THashMap<std::tuple<ui32, ui32, ui32>, const NKikimrBlobStorage::TNodeWardenServiceSet::TVDisk*> vdiskMap; |
| 914 | + for (const auto& item : ssTo->GetVDisks()) { |
| 915 | + if (!item.HasVDiskLocation()) { |
| 916 | + *errorReason = "VDisk in existing StorageConfig doesn't have VDiskLocation field set"; |
| 917 | + return false; |
| 918 | + } |
| 919 | + const auto& loc = item.GetVDiskLocation(); |
| 920 | + if (const auto [it, inserted] = vdiskMap.emplace(std::make_tuple(loc.GetNodeID(), loc.GetPDiskID(), |
| 921 | + loc.GetVDiskSlotID()), &item); !inserted) { |
| 922 | + return duplicateKey(std::bind(vdiskKey, &loc)); |
| 923 | + } |
| 924 | + } |
| 925 | + for (const auto& item : ssFrom.GetVDisks()) { |
| 926 | + if (!item.HasVDiskLocation()) { |
| 927 | + *errorReason = "VDisk in newly provided configuration doesn't have VDiskLocation field set"; |
| 928 | + return false; |
| 929 | + } |
| 930 | + const auto& loc = item.GetVDiskLocation(); |
| 931 | + if (const auto it = vdiskMap.find(std::make_tuple(loc.GetNodeID(), loc.GetPDiskID(), |
| 932 | + loc.GetVDiskSlotID())); it == vdiskMap.end()) { |
| 933 | + return removed(std::bind(vdiskKey, &loc)); |
| 934 | + } else if (!differ.Equals(item, *it->second)) { |
| 935 | + return mismatch(std::bind(vdiskKey, &loc)); |
| 936 | + } else { |
| 937 | + vdiskMap.erase(it); |
| 938 | + } |
| 939 | + } |
| 940 | + if (!vdiskMap.empty()) { |
| 941 | + *errorReason = "some VDisks were added in newly provided configuration"; |
| 942 | + return false; |
| 943 | + } |
| 944 | + |
| 945 | + THashMap<ui32, const NKikimrBlobStorage::TGroupInfo*> groupMap; |
| 946 | + for (const auto& item : ssTo->GetGroups()) { |
| 947 | + if (const auto [it, inserted] = groupMap.emplace(item.GetGroupID(), &item); !inserted) { |
| 948 | + return duplicateKey(std::bind(groupKey, &item)); |
| 949 | + } |
| 950 | + } |
| 951 | + for (const auto& item : ssFrom.GetGroups()) { |
| 952 | + if (const auto it = groupMap.find(item.GetGroupID()); it == groupMap.end()) { |
| 953 | + return removed(std::bind(groupKey, &item)); |
| 954 | + } else if (!differ.Equals(item, *it->second)) { |
| 955 | + return mismatch(std::bind(groupKey, &item)); |
| 956 | + } else { |
| 957 | + groupMap.erase(it); |
| 958 | + } |
| 959 | + } |
| 960 | + if (!groupMap.empty()) { |
| 961 | + *errorReason = "some groups were added in newly provided configuration"; |
| 962 | + return false; |
| 963 | + } |
| 964 | + } |
| 965 | + } |
| 966 | + |
| 967 | + // copy nameservice-related things |
| 968 | + if (!appConfig.HasNameserviceConfig()) { |
| 969 | + *errorReason = "origin config missing mandatory NameserviceConfig section"; |
| 970 | + return false; |
| 971 | + } |
| 972 | + |
| 973 | + const auto& nsFrom = appConfig.GetNameserviceConfig(); |
| 974 | + auto *nodes = config->MutableAllNodes(); |
| 975 | + |
| 976 | + // just copy AllNodes from TAppConfig into TStorageConfig |
| 977 | + nodes->Clear(); |
| 978 | + for (const auto& node : nsFrom.GetNode()) { |
| 979 | + auto *r = nodes->Add(); |
| 980 | + r->SetHost(node.GetInterconnectHost()); |
| 981 | + r->SetPort(node.GetPort()); |
| 982 | + r->SetNodeId(node.GetNodeId()); |
| 983 | + if (node.HasLocation()) { |
| 984 | + r->MutableLocation()->CopyFrom(node.GetLocation()); |
| 985 | + } else if (node.HasWalleLocation()) { |
| 986 | + r->MutableLocation()->CopyFrom(node.GetWalleLocation()); |
| 987 | + } |
| 988 | + } |
| 989 | + |
| 990 | + // and copy ClusterUUID from there too |
| 991 | + config->SetClusterUUID(nsFrom.GetClusterUUID()); |
| 992 | + |
| 993 | + // TODO(alexvru): apply SS, SSB, SB configs from there too |
| 994 | + |
| 995 | + return true; |
| 996 | +} |
834 | 997 |
|
835 | 998 | bool NKikimr::ObtainStaticKey(TEncryptionKey *key) {
|
836 | 999 | // TODO(cthulhu): Replace this with real data
|
|
0 commit comments