diff options
author | alexvru <[email protected]> | 2023-09-06 16:37:45 +0300 |
---|---|---|
committer | alexvru <[email protected]> | 2023-09-06 17:32:36 +0300 |
commit | faa30af20f59848791bb3d91a5502dbc8e8fed71 (patch) | |
tree | 6801bfd4b35ff35ebfd930af57c737b339a00e3e | |
parent | 28c5cef368ab81ae940eec907d122f958c3b54c7 (diff) |
Improve cluster.yaml static group generation KIKIMR-11082
-rw-r--r-- | ydb/core/driver_lib/cli_utils/cli_cmds_genconfig.cpp | 265 |
1 files changed, 117 insertions, 148 deletions
diff --git a/ydb/core/driver_lib/cli_utils/cli_cmds_genconfig.cpp b/ydb/core/driver_lib/cli_utils/cli_cmds_genconfig.cpp index e503162cf43..c64694c6010 100644 --- a/ydb/core/driver_lib/cli_utils/cli_cmds_genconfig.cpp +++ b/ydb/core/driver_lib/cli_utils/cli_cmds_genconfig.cpp @@ -1,7 +1,8 @@ #include <ydb/core/base/blobstorage.h> #include <ydb/core/protos/blobstorage.pb.h> #include <ydb/core/protos/config.pb.h> -#include <ydb/core/mind/bscontroller/grouper.h> +#include <ydb/core/mind/bscontroller/group_geometry_info.h> +#include <ydb/core/mind/bscontroller/group_mapper.h> #include "cli.h" #include "cli_cmds.h" #include "proto_common.h" @@ -9,15 +10,12 @@ namespace NKikimr { namespace NDriverClient { -using NBsController::TCandidate; -using NBsController::GroupFromCandidates; - class TClientCommandGenConfigStatic : public TClientCommandConfig { TString ErasureList; TString ErasureStr; TString DesiredPDiskType = "ROT"; - TString DistinctionLevelStr = "body"; + TString DistinctionLevelStr; TString BsFormatFile; TString RingDistinctionLevelStr; @@ -38,27 +36,20 @@ class TClientCommandGenConfigStatic : public TClientCommandConfig { int ExpectedSlotCount = -1; - ui64 Dc = -1; - ui64 Room = -1; - ui64 Rack = -1; - ui64 Body = -1; - - TFailDomain Prefix; - struct TPDiskInfo { - const TString Type; // PDisk type as mentioned in bs_format.txt - const TString Path; // path to device on a node - const TFailDomain FailDom; // physical location of a PDisk - const ui64 PDiskGuid; // PDisk unique identifier - const ui32 PDiskId; // PDisk per-node identifier - const ui32 NodeId; // the node PDisk resides on + const TString Type; // PDisk type as mentioned in bs_format.txt + const TString Path; // path to device on a node + const TNodeLocation Location; + const ui64 PDiskGuid; // PDisk unique identifier + const ui32 PDiskId; // PDisk per-node identifier + const ui32 NodeId; // the node PDisk resides on std::optional<NKikimrBlobStorage::TPDiskConfig> PDiskConfig; explicit TPDiskInfo(const NKikimrConfig::TBlobStorageFormatConfig::TDrive& drive) : Type(drive.GetType()) , Path(drive.GetPath()) - , FailDom(ParseFailDomain(drive)) + , Location(ParseLocation(drive)) , PDiskGuid(drive.GetGuid()) , PDiskId(drive.GetPDiskId()) , NodeId(drive.GetNodeId()) @@ -77,33 +68,19 @@ class TClientCommandGenConfigStatic : public TClientCommandConfig { TString ToString() const { TStringStream str; - str << "{Type# " << Type << " FailDom# " << FailDom.ToString() << " PDiskGuid# " << PDiskGuid << " PDiskId# " + str << "{Type# " << Type << " Location# " << Location.ToString() << " PDiskGuid# " << PDiskGuid << " PDiskId# " << PDiskId << " NodeId# " << NodeId << "}"; return str.Str(); } private: - static TFailDomain ParseFailDomain(const NKikimrConfig::TBlobStorageFormatConfig::TDrive& drive) { - TFailDomain fdom; - - using T = NKikimrConfig::TBlobStorageFormatConfig::TDrive; - TVector<std::tuple<int, bool(T::*)() const, ui64(T::*)() const>> levels = { - std::make_tuple(10, &T::HasDataCenterId, &T::GetDataCenterId), - std::make_tuple(20, &T::HasRoomId, &T::GetRoomId ), - std::make_tuple(30, &T::HasRackId, &T::GetRackId ), - std::make_tuple(40, &T::HasBodyId, &T::GetBodyId ) - }; - for (const auto& triplet : levels) { - ui32 level; - bool (T::*pfnHas)() const; - ui64 (T::*pfnGet)() const; - std::tie(level, pfnHas, pfnGet) = triplet; - if ((drive.*pfnHas)()) { - fdom.Levels[level] = (drive.*pfnGet)(); - } - } - - return fdom; + static TNodeLocation ParseLocation(const NKikimrConfig::TBlobStorageFormatConfig::TDrive& drive) { + return TNodeLocation( + ::ToString(drive.GetDataCenterId()), + ::ToString(drive.GetRoomId()), + ::ToString(drive.GetRackId()), + ::ToString(drive.GetBodyId()) + ); } }; @@ -137,13 +114,13 @@ public: config.Opts->AddLongOption("faildomains", "desired fail domains").RequiredArgument("NUM").StoreResult(&FailDomains); config.Opts->AddLongOption("vdisks", "vdisks per fail domain").RequiredArgument("NUM").StoreResult(&VDisksPerFailDomain); config.Opts->AddLongOption("vslot", "vslot id for created group").Optional().RequiredArgument("NUM").StoreResult(&VSlot); - config.Opts->AddLongOption("dc", "location: dc").RequiredArgument("NUM").StoreResult(&Dc); - config.Opts->AddLongOption("room", "location: room").RequiredArgument("NUM").StoreResult(&Room); - config.Opts->AddLongOption("rack", "location: rack").RequiredArgument("NUM").StoreResult(&Rack); - config.Opts->AddLongOption("body", "location: body").RequiredArgument("NUM").StoreResult(&Body); config.Opts->AddLongOption("dx", "distinction level").RequiredArgument("{dc|room|rack|body}").StoreResult(&DistinctionLevelStr); config.Opts->AddLongOption("ringdx", "ring distinction level").RequiredArgument("{dc|room|rack|body}").StoreResult(&RingDistinctionLevelStr); config.Opts->AddLongOption("rings", "number of rings").RequiredArgument("NUM").StoreResult(&NumRings); + config.Opts->AddLongOption("domain-level-begin", "domain distinction beginning level").RequiredArgument("NUM").StoreResult(&BeginLevel); + config.Opts->AddLongOption("domain-level-end", "domain distinction ending level").RequiredArgument("NUM").StoreResult(&EndLevel); + config.Opts->AddLongOption("ring-level-begin", "ring distinction beginning level").RequiredArgument("NUM").StoreResult(&RingBeginLevel); + config.Opts->AddLongOption("ring-level-end", "ring distinction ending level").RequiredArgument("NUM").StoreResult(&RingEndLevel); config.Opts->AddLongOption("bs-format-file", "path to bs_format.txt file").Required().RequiredArgument("PATH") .StoreResult(&BsFormatFile); @@ -170,26 +147,20 @@ public: ythrow TWithBackTrace<yexception>() << "unknown erasure species: \"" << ErasureStr << "\", valid values are: " << ErasureList; } - if (!RingDistinctionLevelStr && Type.GetErasure() == TBlobStorageGroupType::ErasureMirror3dc) { - RingDistinctionLevelStr = "dc"; + if (DistinctionLevelStr) { + BeginLevel = 0; + EndLevel = ParseDistinctionLevel(DistinctionLevelStr); } - - BeginLevel = 0; - EndLevel = ParseDistinctionLevel(DistinctionLevelStr); - RingBeginLevel = 0; - RingEndLevel = RingDistinctionLevelStr ? ParseDistinctionLevel(RingDistinctionLevelStr) : 0; - - if (Dc != (ui64)-1) { - Prefix.Levels[10] = Dc; + if (BeginLevel == 0 && EndLevel == 0) { + EndLevel = ParseDistinctionLevel("body"); } - if (Room != (ui64)-1) { - Prefix.Levels[20] = Room; - } - if (Rack != (ui64)-1) { - Prefix.Levels[30] = Rack; + + if (RingDistinctionLevelStr) { + RingBeginLevel = 0; + RingEndLevel = RingDistinctionLevelStr ? ParseDistinctionLevel(RingDistinctionLevelStr) : 0; } - if (Body != (ui64)-1) { - Prefix.Levels[40] = Body; + if (RingBeginLevel == 0 && RingEndLevel == 0 && Type.GetErasure() == TBlobStorageGroupType::ErasureMirror3dc) { + RingEndLevel = ParseDistinctionLevel("dc"); } if (!FailDomains) { @@ -227,30 +198,44 @@ public: return EXIT_FAILURE; } + NKikimrBlobStorage::TGroupGeometry g; + g.SetNumFailRealms(NumRings); + g.SetNumFailDomainsPerFailRealm(FailDomains); + g.SetNumVDisksPerFailDomain(VDisksPerFailDomain); + g.SetRealmLevelBegin(RingBeginLevel); + g.SetRealmLevelEnd(RingEndLevel); + g.SetDomainLevelBegin(BeginLevel); + g.SetDomainLevelEnd(EndLevel); + + NBsController::TGroupMapper mapper(NBsController::TGroupGeometryInfo(Type, g)); + // make a set of PDisks that fit our filtering condition TVector<TPDiskInfo> pdisks; + THashMap<NBsController::TPDiskId, size_t> pdiskMap; for (const NKikimrConfig::TBlobStorageFormatConfig::TDrive& drive : bsFormat.GetDrive()) { TPDiskInfo pdiskInfo(drive); - if (pdiskInfo.Type == DesiredPDiskType && Prefix.IsSubdomainOf(pdiskInfo.FailDom)) { + if (pdiskInfo.Type == DesiredPDiskType) { pdisks.push_back(std::move(pdiskInfo)); - } - } - TVector<TCandidate> candidates; - for (const TPDiskInfo& pdisk : pdisks) { - candidates.emplace_back(pdisk.FailDom, BeginLevel, EndLevel, 0 /*badness*/, pdisk.NodeId, pdisk.PDiskId, VSlot); + mapper.RegisterPDisk({ + .PDiskId{pdiskInfo.NodeId, pdiskInfo.PDiskId}, + .Location = pdiskInfo.Location, + .Usable = true, + .NumSlots = 0, + .MaxSlots = 1, + .SpaceAvailable = 0, + .Operational = true, + .Decommitted = false, + }); + + pdiskMap.emplace(NBsController::TPDiskId{pdiskInfo.NodeId, pdiskInfo.PDiskId}, pdisks.size() - 1); + } } - TVector<TVector<TVector<const TCandidate*>>> bestGroup; - if (!CreateGroupWithRings(candidates, NumRings, FailDomains, VDisksPerFailDomain, RingBeginLevel, RingEndLevel, - bestGroup)) { - Cerr << "Can't create group with given parameters" - << " NumRings = " << NumRings - << ", FailDomains = " << FailDomains - << ", VDisksPerFailDomain = " << VDisksPerFailDomain - << ", RingBeginLevel = " << RingBeginLevel - << ", RingEndLevel = " << RingEndLevel - << Endl; + NBsController::TGroupMapper::TGroupDefinition group; + TString error; + if (!mapper.AllocateGroup(0, group, {}, {}, 0, false, error)) { + Cerr << "Can't allocate group: " << error << Endl; return EXIT_FAILURE; } @@ -258,77 +243,61 @@ public: NKikimrBlobStorage::TNodeWardenServiceSet& serviceSet = *pb.MutableServiceSet(); serviceSet.AddAvailabilityDomains(AvailabilityDomain); - auto transformVDisk = [&](const TCandidate *vdisk, auto& outFailDomain, ui32 ringIdx, ui32 domainIdx, ui32& vdiskIdx) { - // calculate index of candidate inside our PDisk vector and find matching PDisk info - const ui32 index = vdisk - candidates.data(); - const TPDiskInfo& pdiskInfo = pdisks[index]; - - // add pdisk meta - auto& pdiskItem = *serviceSet.AddPDisks(); - pdiskItem.SetNodeID(pdiskInfo.NodeId); - pdiskItem.SetPDiskID(pdiskInfo.PDiskId); - pdiskItem.SetPath(pdiskInfo.Path); - pdiskItem.SetPDiskGuid(pdiskInfo.PDiskGuid); - - NPDisk::EDeviceType deviceType = NPDisk::DeviceTypeFromStr(pdiskInfo.Type); - if (deviceType == NPDisk::DEVICE_TYPE_UNKNOWN) { - ythrow yexception() << "invalid PDisk Type " << pdiskInfo.Type; - } - const ui64 kind = 0; - TPDiskCategory cat(deviceType, kind); - pdiskItem.SetPDiskCategory(cat.GetRaw()); - - if (pdiskInfo.PDiskConfig) { - auto *pdiskConfig = pdiskItem.MutablePDiskConfig(); - pdiskConfig->CopyFrom(*pdiskInfo.PDiskConfig); - } else if (config.ParseResult->Has("expected-slot-count")) { - auto *pdiskConfig = pdiskItem.MutablePDiskConfig(); - pdiskConfig->SetExpectedSlotCount(ExpectedSlotCount); + auto& pgroup = *serviceSet.AddGroups(); + pgroup.SetGroupID(GroupId); + pgroup.SetGroupGeneration(GroupGen); + pgroup.SetErasureSpecies(Type.GetErasure()); + + for (ui32 ringIdx = 0; ringIdx < group.size(); ++ringIdx) { + auto *ring = pgroup.AddRings(); + for (ui32 domainIdx = 0; domainIdx < group[ringIdx].size(); ++domainIdx) { + auto *domain = ring->AddFailDomains(); + for (ui32 vdiskIdx = 0; vdiskIdx < group[ringIdx][domainIdx].size(); ++vdiskIdx) { + const TPDiskInfo& pdiskInfo = pdisks[pdiskMap[group[ringIdx][domainIdx][vdiskIdx]]]; + + // add pdisk meta + auto& pdiskItem = *serviceSet.AddPDisks(); + pdiskItem.SetNodeID(pdiskInfo.NodeId); + pdiskItem.SetPDiskID(pdiskInfo.PDiskId); + pdiskItem.SetPath(pdiskInfo.Path); + pdiskItem.SetPDiskGuid(pdiskInfo.PDiskGuid); + + NPDisk::EDeviceType deviceType = NPDisk::DeviceTypeFromStr(pdiskInfo.Type); + if (deviceType == NPDisk::DEVICE_TYPE_UNKNOWN) { + ythrow yexception() << "invalid PDisk Type " << pdiskInfo.Type; + } + const ui64 kind = 0; + TPDiskCategory cat(deviceType, kind); + pdiskItem.SetPDiskCategory(cat.GetRaw()); + + if (pdiskInfo.PDiskConfig) { + auto *pdiskConfig = pdiskItem.MutablePDiskConfig(); + pdiskConfig->CopyFrom(*pdiskInfo.PDiskConfig); + } else if (config.ParseResult->Has("expected-slot-count")) { + auto *pdiskConfig = pdiskItem.MutablePDiskConfig(); + pdiskConfig->SetExpectedSlotCount(ExpectedSlotCount); + } + + // add vdisk meta + auto& vdiskItem = *serviceSet.AddVDisks(); + auto& vdiskId = *vdiskItem.MutableVDiskID(); + vdiskId.SetGroupID(GroupId); + vdiskId.SetGroupGeneration(GroupGen); + vdiskId.SetRing(ringIdx); + vdiskId.SetDomain(domainIdx); + vdiskId.SetVDisk(vdiskIdx); + auto& vdiskLocation = *vdiskItem.MutableVDiskLocation(); + vdiskLocation.SetNodeID(pdiskInfo.NodeId); + vdiskLocation.SetPDiskID(pdiskInfo.PDiskId); + vdiskLocation.SetVDiskSlotID(0); + vdiskLocation.SetPDiskGuid(pdiskInfo.PDiskGuid); + vdiskItem.SetVDiskKind((NKikimrBlobStorage::TVDiskKind_EVDiskKind)VDiskKindVal); + + // add vdisk location to the group descriptor + domain->AddVDiskLocations()->CopyFrom(vdiskLocation); + } } - - // add vdisk meta - auto& vdiskItem = *serviceSet.AddVDisks(); - auto& vdiskId = *vdiskItem.MutableVDiskID(); - vdiskId.SetGroupID(GroupId); - vdiskId.SetGroupGeneration(GroupGen); - vdiskId.SetRing(ringIdx); - vdiskId.SetDomain(domainIdx); - vdiskId.SetVDisk(vdiskIdx); - auto& vdiskLocation = *vdiskItem.MutableVDiskLocation(); - vdiskLocation.SetNodeID(vdisk->NodeId); - vdiskLocation.SetPDiskID(vdisk->PDiskId); - vdiskLocation.SetVDiskSlotID(vdisk->VDiskSlotId); - vdiskLocation.SetPDiskGuid(pdiskInfo.PDiskGuid); - vdiskItem.SetVDiskKind((NKikimrBlobStorage::TVDiskKind_EVDiskKind)VDiskKindVal); - - // add vdisk location to the group descriptor - *outFailDomain.AddVDiskLocations() = vdiskLocation; - - ++vdiskIdx; - }; - - auto transformDomain = [&](const TVector<const TCandidate*>& inVDisks, auto& outRing, ui32 ringIdx, ui32& domainIdx) { - ui32 vdiskIdx = 0; - std::for_each(inVDisks.begin(), inVDisks.end(), std::bind(transformVDisk, std::placeholders::_1, - std::ref(*outRing.AddFailDomains()), ringIdx, domainIdx, std::ref(vdiskIdx))); - ++domainIdx; - }; - - auto transformRing = [&](const TVector<TVector<const TCandidate*>>& inDomains, auto& outGroup, ui32& ringIdx) { - ui32 domainIdx = 0; - std::for_each(inDomains.begin(), inDomains.end(), std::bind(transformDomain, std::placeholders::_1, - std::ref(*outGroup.AddRings()), ringIdx, std::ref(domainIdx))); - ++ringIdx; - }; - - auto& group = *serviceSet.AddGroups(); - group.SetGroupID(GroupId); - group.SetGroupGeneration(GroupGen); - group.SetErasureSpecies(Type.GetErasure()); - - ui32 ringIdx = 0; - std::for_each(bestGroup.begin(), bestGroup.end(), std::bind(transformRing, std::placeholders::_1, - std::ref(group), std::ref(ringIdx))); + } TString message; if (!google::protobuf::TextFormat::PrintToString(pb, &message)) { |