Browse Source

Support BlobDepot through BSC KIKIMR-14867

ref:8007970beb7663337fa7ad03844f74fed43b49f3
Alexander Rutkovsky 2 years ago
parent
commit
2bb316e5e5

+ 8 - 8
CMakeLists.darwin.txt

@@ -721,20 +721,20 @@ add_subdirectory(ydb/core/cms/console/validators)
 add_subdirectory(ydb/core/mind)
 add_subdirectory(ydb/core/blobstorage/dsproxy/mock)
 add_subdirectory(ydb/core/mind/bscontroller)
-add_subdirectory(ydb/core/sys_view/processor)
-add_subdirectory(ydb/core/kqp/counters)
+add_subdirectory(ydb/core/tx/tx_proxy)
+add_subdirectory(ydb/core/tx/balance_coverage)
 add_subdirectory(ydb/core/tx/scheme_cache)
-add_subdirectory(ydb/core/test_tablet)
-add_subdirectory(ydb/core/tx/replication/controller)
-add_subdirectory(ydb/core/tx/replication/ydb_proxy)
-add_subdirectory(ydb/core/tx/scheme_board)
 add_subdirectory(ydb/core/tx/schemeshard)
 add_subdirectory(ydb/core/blockstore/core)
 add_subdirectory(ydb/core/filestore/core)
+add_subdirectory(ydb/core/tx/scheme_board)
 add_subdirectory(ydb/core/tx/tx_allocator_client)
 add_subdirectory(ydb/core/tx/tx_allocator)
-add_subdirectory(ydb/core/tx/tx_proxy)
-add_subdirectory(ydb/core/tx/balance_coverage)
+add_subdirectory(ydb/core/sys_view/processor)
+add_subdirectory(ydb/core/kqp/counters)
+add_subdirectory(ydb/core/test_tablet)
+add_subdirectory(ydb/core/tx/replication/controller)
+add_subdirectory(ydb/core/tx/replication/ydb_proxy)
 add_subdirectory(ydb/core/ymq/base)
 add_subdirectory(ydb/core/ymq/proto)
 add_subdirectory(ydb/library/http_proxy/authorization)

+ 8 - 8
CMakeLists.linux.txt

@@ -801,20 +801,20 @@ add_subdirectory(ydb/core/cms/console/validators)
 add_subdirectory(ydb/core/mind)
 add_subdirectory(ydb/core/blobstorage/dsproxy/mock)
 add_subdirectory(ydb/core/mind/bscontroller)
-add_subdirectory(ydb/core/sys_view/processor)
-add_subdirectory(ydb/core/kqp/counters)
+add_subdirectory(ydb/core/tx/tx_proxy)
+add_subdirectory(ydb/core/tx/balance_coverage)
 add_subdirectory(ydb/core/tx/scheme_cache)
-add_subdirectory(ydb/core/test_tablet)
-add_subdirectory(ydb/core/tx/replication/controller)
-add_subdirectory(ydb/core/tx/replication/ydb_proxy)
-add_subdirectory(ydb/core/tx/scheme_board)
 add_subdirectory(ydb/core/tx/schemeshard)
 add_subdirectory(ydb/core/blockstore/core)
 add_subdirectory(ydb/core/filestore/core)
+add_subdirectory(ydb/core/tx/scheme_board)
 add_subdirectory(ydb/core/tx/tx_allocator_client)
 add_subdirectory(ydb/core/tx/tx_allocator)
-add_subdirectory(ydb/core/tx/tx_proxy)
-add_subdirectory(ydb/core/tx/balance_coverage)
+add_subdirectory(ydb/core/sys_view/processor)
+add_subdirectory(ydb/core/kqp/counters)
+add_subdirectory(ydb/core/test_tablet)
+add_subdirectory(ydb/core/tx/replication/controller)
+add_subdirectory(ydb/core/tx/replication/ydb_proxy)
 add_subdirectory(ydb/core/ymq/base)
 add_subdirectory(ydb/core/ymq/proto)
 add_subdirectory(ydb/library/http_proxy/authorization)

+ 2 - 0
ydb/core/mind/bscontroller/CMakeLists.txt

@@ -22,6 +22,7 @@ target_link_libraries(core-mind-bscontroller PUBLIC
   core-sys_view-common
   ydb-core-tablet
   ydb-core-tablet_flat
+  core-tx-tx_proxy
 )
 target_sources(core-mind-bscontroller PRIVATE
   ${CMAKE_SOURCE_DIR}/ydb/core/mind/bscontroller/bsc.cpp
@@ -56,4 +57,5 @@ target_sources(core-mind-bscontroller PRIVATE
   ${CMAKE_SOURCE_DIR}/ydb/core/mind/bscontroller/update_group_latencies.cpp
   ${CMAKE_SOURCE_DIR}/ydb/core/mind/bscontroller/update_last_seen_ready.cpp
   ${CMAKE_SOURCE_DIR}/ydb/core/mind/bscontroller/update_seen_operational.cpp
+  ${CMAKE_SOURCE_DIR}/ydb/core/mind/bscontroller/virtual_group.cpp
 )

+ 7 - 0
ydb/core/mind/bscontroller/bsc.cpp

@@ -170,6 +170,12 @@ void TBlobStorageController::Handle(TEvents::TEvPoisonPill::TPtr&) {
             TActivationContext::Send(new IEventHandle(TEvents::TSystem::Poison, 0, actorId, SelfId(), nullptr, 0));
         }
     }
+    for (const auto& [id, info] : GroupMap) {
+        if (auto& actorId = info->VirtualGroupSetupMachineId) {
+            TActivationContext::Send(new IEventHandle(TEvents::TSystem::Poison, 0, actorId, SelfId(), nullptr, 0));
+            actorId = {};
+        }
+    }
     TActivationContext::Send(new IEventHandle(TEvents::TSystem::Poison, 0, Tablet(), SelfId(), nullptr, 0));
 }
 
@@ -320,6 +326,7 @@ ui32 TBlobStorageController::GetEventPriority(IEventHandle *ev) {
                     case NKikimrBlobStorage::TConfigRequest::TCommand::kSetPDiskSpaceMarginPromille:
                     case NKikimrBlobStorage::TConfigRequest::TCommand::kUpdateSettings:
                     case NKikimrBlobStorage::TConfigRequest::TCommand::kReassignGroupDisk:
+                    case NKikimrBlobStorage::TConfigRequest::TCommand::kAllocateVirtualGroup:
                         return 2; // read-write commands go with higher priority as they are needed to keep cluster intact
 
                     case NKikimrBlobStorage::TConfigRequest::TCommand::kReadHostConfig:

+ 9 - 0
ydb/core/mind/bscontroller/config.cpp

@@ -190,6 +190,10 @@ namespace NKikimr::NBsController {
             ////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
             void ApplyGroupCreated(const TGroupId& /*groupId*/, const TGroupInfo &groupInfo) {
+                if (groupInfo.VirtualGroupState && *groupInfo.VirtualGroupState != NKikimrBlobStorage::EVirtualGroupState::WORKING) {
+                    return; // do not report virtual groups that are not properly created yet
+                }
+
                 // create ordered map of VDisk entries for group
                 THashSet<TNodeId> nodes;
                 for (const TVSlotInfo *vslot : groupInfo.VDisksInGroup) {
@@ -326,6 +330,7 @@ namespace NKikimr::NBsController {
             MakeTableMerger<Schema::Box>(&Boxes, &state.Boxes.Get(), this)(txc);
             MakeTableMerger<Schema::BoxStoragePool>(&StoragePools, &state.StoragePools.Get(), this)(txc);
             MakeTableMerger<Schema::Node>(&Nodes, &state.Nodes.Get(), this)(txc);
+            MakeTableMerger<Schema::VirtualGroupPool>(&VirtualGroupPools, &state.VirtualGroupPools.Get(), this)(txc);
 
             // apply overlay maps to their respective tables
             state.PDisks.ApplyToTable(this, txc);
@@ -384,6 +389,7 @@ namespace NKikimr::NBsController {
             CommitScrubUpdates(state, txc);
             CommitStoragePoolStatUpdates(state);
             CommitSysViewUpdates(state);
+            CommitVirtualGroupUpdates(state);
 
             // remove deleted vslots from VSlotReadyTimestampQ
             for (auto&& [base, overlay] : state.VSlots.Diff()) {
@@ -538,6 +544,9 @@ namespace NKikimr::NBsController {
             for (auto& msg : Outbox) {
                 TActivationContext::Send(msg.release());
             }
+            for (auto& fn : Callbacks) {
+                fn();
+            }
         }
 
         void TBlobStorageController::TConfigState::DestroyVSlot(const TVSlotId vslotId) {

+ 12 - 1
ydb/core/mind/bscontroller/config.h

@@ -54,11 +54,13 @@ namespace NKikimr {
             // system-level configuration
             TOverlayMap<TPDiskId, TPDiskInfo> PDisks;
             TOverlayMap<TSerial, TDriveSerialInfo> DrivesSerials;
+            TCowHolder<TMap<Schema::VirtualGroupPool::TKey::Type, TVirtualGroupPool>> VirtualGroupPools;
             TCowHolder<TMap<TNodeId, TNodeInfo>> Nodes;
             TOverlayMap<TVSlotId, TVSlotInfo> VSlots;
             TOverlayMap<TGroupId, TGroupInfo> Groups;
             TCowHolder<TMap<TGroupSpecies, TVector<TGroupId>>> IndexGroupSpeciesToGroup;
             TCowHolder<Schema::Group::ID::Type> NextGroupId;
+            TCowHolder<Schema::Group::ID::Type> NextVirtualGroupId;
             TCowHolder<Schema::State::NextStoragePoolId::Type> NextStoragePoolId;
 
             // helper classes
@@ -83,6 +85,9 @@ namespace NKikimr {
             // outgoing messages
             std::deque<std::unique_ptr<IEventHandle>> Outbox;
 
+            // deferred callbacks
+            std::deque<std::function<void()>> Callbacks;
+
             // when the config cmd received
             const TInstant Timestamp;
 
@@ -110,11 +115,13 @@ namespace NKikimr {
                 , StoragePoolGroups(&controller.StoragePoolGroups)
                 , PDisks(controller.PDisks)
                 , DrivesSerials(controller.DrivesSerials)
+                , VirtualGroupPools(&controller.VirtualGroupPools)
                 , Nodes(&controller.Nodes)
                 , VSlots(controller.VSlots)
                 , Groups(controller.GroupMap)
                 , IndexGroupSpeciesToGroup(&controller.IndexGroupSpeciesToGroup)
                 , NextGroupId(&controller.NextGroupID)
+                , NextVirtualGroupId(&controller.NextVirtualGroupId)
                 , NextStoragePoolId(&controller.NextStoragePoolId)
                 , HostRecords(hostRecords)
                 , Timestamp(timestamp)
@@ -137,11 +144,13 @@ namespace NKikimr {
                 StoragePoolGroups.Commit();
                 PDisks.Commit();
                 DrivesSerials.Commit();
+                VirtualGroupPools.Commit();
                 Nodes.Commit();
                 VSlots.Commit();
                 Groups.Commit();
                 IndexGroupSpeciesToGroup.Commit();
                 NextGroupId.Commit();
+                NextVirtualGroupId.Commit();
                 NextStoragePoolId.Commit();
                 SerialManagementStage.Commit();
             }
@@ -156,7 +165,8 @@ namespace NKikimr {
                 return HostConfigs.Changed() || Boxes.Changed() || StoragePools.Changed() ||
                     StoragePoolGroups.Changed() || PDisks.Changed() || DrivesSerials.Changed() || Nodes.Changed() ||
                     VSlots.Changed() || Groups.Changed() || IndexGroupSpeciesToGroup.Changed() || NextGroupId.Changed() ||
-                    NextStoragePoolId.Changed() || SerialManagementStage.Changed();
+                    NextStoragePoolId.Changed() || SerialManagementStage.Changed() || VirtualGroupPools.Changed() ||
+                    NextVirtualGroupId.Changed();
             }
 
             bool NormalizeHostKey(NKikimrBlobStorage::THostKey *host) const {
@@ -246,6 +256,7 @@ namespace NKikimr {
             void ExecuteStep(const NKikimrBlobStorage::TRemoveDriveSerial& cmd, TStatus& status);
             void ExecuteStep(const NKikimrBlobStorage::TForgetDriveSerial& cmd, TStatus& status);
             void ExecuteStep(const NKikimrBlobStorage::TMigrateToSerial& cmd, TStatus& status);
+            void ExecuteStep(const NKikimrBlobStorage::TAllocateVirtualGroup& cmd, TStatus& status);
         };
 
     } // NBsController

+ 37 - 25
ydb/core/mind/bscontroller/config_cmd.cpp

@@ -299,33 +299,45 @@ namespace NKikimr::NBsController {
                         state.ExecuteStep(cmd.Get ## NAME(), status); \
                         fitPDisks = FP; \
                         fitGroups = FG; \
-                        break;
-
-                    HANDLE_COMMAND(DefineHostConfig,    true,  false)
-                    HANDLE_COMMAND(ReadHostConfig,      false, false)
-                    HANDLE_COMMAND(DeleteHostConfig,    false, false)
-                    HANDLE_COMMAND(DefineBox,           true,  false)
-                    HANDLE_COMMAND(ReadBox,             false, false)
-                    HANDLE_COMMAND(DeleteBox,           true,  false)
-                    HANDLE_COMMAND(DefineStoragePool,   false, true )
-                    HANDLE_COMMAND(ReadStoragePool,     false, false)
-                    HANDLE_COMMAND(DeleteStoragePool,   false, false)
-                    HANDLE_COMMAND(UpdateDriveStatus,   false, true )
-                    HANDLE_COMMAND(ReadDriveStatus,     false, false)
-                    HANDLE_COMMAND(ProposeStoragePools, false, false)
-                    HANDLE_COMMAND(QueryBaseConfig,     false, false)
-                    HANDLE_COMMAND(ReassignGroupDisk,   false, true )
-                    HANDLE_COMMAND(MergeBoxes,          false, false)
-                    HANDLE_COMMAND(MoveGroups,          false, false)
-                    HANDLE_COMMAND(DropDonorDisk,       false, false)
-                    HANDLE_COMMAND(AddDriveSerial,      true,  false)
-                    HANDLE_COMMAND(RemoveDriveSerial,   true,  false)
-                    HANDLE_COMMAND(ForgetDriveSerial,   false, false)
-                    HANDLE_COMMAND(MigrateToSerial,     false, false)
-
-                    default:
+                        return;
+
+                    HANDLE_COMMAND(DefineHostConfig,     true,  false)
+                    HANDLE_COMMAND(ReadHostConfig,       false, false)
+                    HANDLE_COMMAND(DeleteHostConfig,     false, false)
+                    HANDLE_COMMAND(DefineBox,            true,  false)
+                    HANDLE_COMMAND(ReadBox,              false, false)
+                    HANDLE_COMMAND(DeleteBox,            true,  false)
+                    HANDLE_COMMAND(DefineStoragePool,    false, true )
+                    HANDLE_COMMAND(ReadStoragePool,      false, false)
+                    HANDLE_COMMAND(DeleteStoragePool,    false, false)
+                    HANDLE_COMMAND(UpdateDriveStatus,    false, true )
+                    HANDLE_COMMAND(ReadDriveStatus,      false, false)
+                    HANDLE_COMMAND(ProposeStoragePools,  false, false)
+                    HANDLE_COMMAND(QueryBaseConfig,      false, false)
+                    HANDLE_COMMAND(ReassignGroupDisk,    false, true )
+                    HANDLE_COMMAND(MergeBoxes,           false, false)
+                    HANDLE_COMMAND(MoveGroups,           false, false)
+                    HANDLE_COMMAND(DropDonorDisk,        false, false)
+                    HANDLE_COMMAND(AddDriveSerial,       true,  false)
+                    HANDLE_COMMAND(RemoveDriveSerial,    true,  false)
+                    HANDLE_COMMAND(ForgetDriveSerial,    false, false)
+                    HANDLE_COMMAND(MigrateToSerial,      false, false)
+                    HANDLE_COMMAND(AllocateVirtualGroup, false, false)
+
+                    case NKikimrBlobStorage::TConfigRequest::TCommand::kAddMigrationPlan:
+                    case NKikimrBlobStorage::TConfigRequest::TCommand::kDeleteMigrationPlan:
+                    case NKikimrBlobStorage::TConfigRequest::TCommand::kDeclareIntent:
+                    case NKikimrBlobStorage::TConfigRequest::TCommand::kReadIntent:
+                    case NKikimrBlobStorage::TConfigRequest::TCommand::kEnableSelfHeal:
+                    case NKikimrBlobStorage::TConfigRequest::TCommand::kEnableDonorMode:
+                    case NKikimrBlobStorage::TConfigRequest::TCommand::kSetScrubPeriodicity:
+                    case NKikimrBlobStorage::TConfigRequest::TCommand::kSetPDiskSpaceMarginPromille:
+                    case NKikimrBlobStorage::TConfigRequest::TCommand::kUpdateSettings:
+                    case NKikimrBlobStorage::TConfigRequest::TCommand::COMMAND_NOT_SET:
                         throw TExError() << "unsupported command";
                 }
+
+                Y_FAIL();
             }
 
             void Complete(const TActorContext&) override {

+ 2 - 0
ydb/core/mind/bscontroller/defs.h

@@ -29,6 +29,8 @@
 #include <ydb/core/tablet/tablet_counters_protobuf.h>
 #include <ydb/core/tablet/tablet_metrics.h>
 #include <ydb/core/tablet/tablet_responsiveness_pinger.h>
+#include <ydb/core/tx/schemeshard/schemeshard.h>
+#include <ydb/core/tx/tx_proxy/proxy.h>
 #include <ydb/core/util/pb.h>
 #include <ydb/core/util/format.h>
 #include <ydb/core/util/stlog.h>

+ 83 - 2
ydb/core/mind/bscontroller/impl.h

@@ -494,6 +494,19 @@ public:
         bool PersistedDown = false; // the value stored in the database
         bool SeenOperational = false;
 
+        Table::DecommitStatus::Type DecommitStatus = NKikimrBlobStorage::EGroupDecommitStatus::NONE;
+        TMaybe<Table::VirtualGroupPool::Type> VirtualGroupPool;
+        TMaybe<Table::VirtualGroupState::Type> VirtualGroupState;
+        TMaybe<Table::ParentDir::Type> ParentDir;
+        TMaybe<Table::Name::Type> Name;
+        TMaybe<Table::SchemeshardId::Type> SchemeshardId;
+        TMaybe<Table::BlobDepotConfig::Type> BlobDepotConfig;
+        TMaybe<Table::TxId::Type> TxId;
+        TMaybe<Table::PathId::Type> PathId;
+        TMaybe<Table::BlobDepotId::Type> BlobDepotId;
+        TMaybe<Table::ErrorReason::Type> ErrorReason;
+        bool CommitInProgress = false;
+
         bool Down = false; // is group are down right now (not selectable)
         TVector<TIndirectReferable<TVSlotInfo>::TPtr> VDisksInGroup;
         TGroupLatencyStats LatencyStats;
@@ -501,6 +514,8 @@ public:
         mutable TStorageStatusFlags StatusFlags;
         bool ContentChanged = false;
 
+        TActorId VirtualGroupSetupMachineId;
+
         // group's geometry; it doesn't ever change since the group is created
         const ui32 NumFailRealms = 0;
         const ui32 NumFailDomainsPerFailRealm = 0;
@@ -541,7 +556,18 @@ public:
                     Table::EncryptedGroupKey,
                     Table::GroupKeyNonce,
                     Table::MainKeyVersion,
-                    Table::SeenOperational
+                    Table::SeenOperational,
+                    Table::DecommitStatus,
+                    Table::VirtualGroupPool,
+                    Table::VirtualGroupState,
+                    Table::ParentDir,
+                    Table::Name,
+                    Table::SchemeshardId,
+                    Table::BlobDepotConfig,
+                    Table::TxId,
+                    Table::PathId,
+                    Table::BlobDepotId,
+                    Table::ErrorReason
                 > adapter(
                     &TGroupInfo::Generation,
                     &TGroupInfo::Owner,
@@ -554,7 +580,18 @@ public:
                     &TGroupInfo::EncryptedGroupKey,
                     &TGroupInfo::GroupKeyNonce,
                     &TGroupInfo::MainKeyVersion,
-                    &TGroupInfo::SeenOperational
+                    &TGroupInfo::SeenOperational,
+                    &TGroupInfo::DecommitStatus,
+                    &TGroupInfo::VirtualGroupPool,
+                    &TGroupInfo::VirtualGroupState,
+                    &TGroupInfo::ParentDir,
+                    &TGroupInfo::Name,
+                    &TGroupInfo::SchemeshardId,
+                    &TGroupInfo::BlobDepotConfig,
+                    &TGroupInfo::TxId,
+                    &TGroupInfo::PathId,
+                    &TGroupInfo::BlobDepotId,
+                    &TGroupInfo::ErrorReason
                 );
             callback(&adapter);
         }
@@ -1259,6 +1296,28 @@ public:
         void OnClone(const THolder<TDriveSerialInfo>&) {}
     };
 
+    struct TVirtualGroupPool {
+        using Table = Schema::VirtualGroupPool;
+
+        TMaybe<Table::Generation::Type> Generation;
+
+        TVirtualGroupPool() = default;
+        TVirtualGroupPool(const TVirtualGroupPool&) = default;
+
+        template<typename T>
+        static void Apply(TBlobStorageController* /*controller*/, T&& callback) {
+            static TTableAdapter<Table, TVirtualGroupPool,
+                    Table::Generation
+                > adapter(
+                    &TVirtualGroupPool::Generation
+                );
+            callback(&adapter);
+        }
+
+        void OnCommit() {}
+        void OnClone(const THolder<TVirtualGroupPool>&) {}
+    };
+
     struct THostRecord {
         TNodeId NodeId;
         TNodeLocation Location;
@@ -1330,11 +1389,13 @@ private:
     TVSlots VSlots; // ordering is important
     TPDisks PDisks; // ordering is important
     TMap<TSerial, THolder<TDriveSerialInfo>> DrivesSerials;
+    TMap<Schema::VirtualGroupPool::TKey::Type, TVirtualGroupPool> VirtualGroupPools;
     TGroups GroupMap;
     THashMap<TGroupId, TGroupInfo*> GroupLookup;
     TMap<TGroupSpecies, TVector<TGroupId>> IndexGroupSpeciesToGroup;
     TMap<TNodeId, TNodeInfo> Nodes;
     Schema::Group::ID::Type NextGroupID = 0;
+    Schema::Group::ID::Type NextVirtualGroupId = 0;
     Schema::State::NextStoragePoolId::Type NextStoragePoolId = 0;
     ui32 DefaultMaxSlots = 0;
     ui32 PDiskSpaceMarginPromille = 0;
@@ -1549,6 +1610,11 @@ private:
                 TActivationContext::Send(new IEventHandle(TEvents::TSystem::Poison, 0, actorId, SelfId(), nullptr, 0));
             }
         }
+        for (const auto& [id, info] : GroupMap) {
+            if (const auto& actorId = info->VirtualGroupSetupMachineId) {
+                TActivationContext::Send(new IEventHandle(TEvents::TSystem::Poison, 0, actorId, SelfId(), nullptr, 0));
+            }
+        }
         return TActor::PassAway();
     }
 
@@ -1877,6 +1943,12 @@ public:
         UpdateSystemViews();
         UpdateSelfHealCounters();
         SignalTabletActive(TActivationContext::AsActorContext());
+
+        for (const auto& [id, info] : GroupMap) {
+            if (info->VirtualGroupState) {
+                StartVirtualGroupSetupMachine(info.Get());
+            }
+        }
     }
 
     void UpdatePDisksCounters() {
@@ -1914,6 +1986,15 @@ public:
         counters[NBlobStorageController::COUNTER_DRIVE_SERIAL_ERROR].Set(numError);
     }
 
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    // VIRTUAL GROUP MANAGEMENT
+
+    class TVirtualGroupSetupMachine;
+
+    void CommitVirtualGroupUpdates(TConfigState& state);
+
+    void StartVirtualGroupSetupMachine(TGroupInfo *group);
+
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     // VSLOT READINESS EVALUATION
 

+ 39 - 16
ydb/core/mind/bscontroller/load_everything.cpp

@@ -68,6 +68,7 @@ public:
                 return false;
             if (state.IsValid()) {
                 Self->NextGroupID = state.GetValue<T::NextGroupID>();
+                Self->NextVirtualGroupId = state.GetValueOrDefault<T::NextVirtualGroupId>();
                 Self->NextStoragePoolId = state.GetValue<T::NextStoragePoolId>();
                 Self->NextOperationLogIndex = state.GetValueOrDefault<T::NextOperationLogIndex>(1);
                 Self->DefaultMaxSlots = state.GetValue<T::DefaultMaxSlots>();
@@ -165,7 +166,8 @@ public:
         Self->OwnerIdIdxToGroup.clear();
         Self->IndexGroupSpeciesToGroup.clear();
         {
-            auto groups = db.Table<Schema::Group>().Range().Select();
+            using T = Schema::Group;
+            auto groups = db.Table<T>().Range().Select();
             if (!groups.IsReady())
                 return false;
             while (!groups.EndOfSet()) {
@@ -178,24 +180,44 @@ public:
                 Y_VERIFY(geomIt != geometry.end());
 
                 TGroupInfo& group = Self->AddGroup(groups.GetKey(),
-                                                   groups.GetValue<Schema::Group::Generation>(),
-                                                   groups.GetValue<Schema::Group::Owner>(),
-                                                   groups.GetValue<Schema::Group::ErasureSpecies>(),
-                                                   groups.GetValue<Schema::Group::DesiredPDiskCategory>(),
-                                                   groups.GetValueOrDefault<Schema::Group::DesiredVDiskCategory>(NKikimrBlobStorage::TVDiskKind::Default),
-                                                   groups.GetValueOrDefault<Schema::Group::EncryptionMode>(),
-                                                   groups.GetValueOrDefault<Schema::Group::LifeCyclePhase>(),
-                                                   groups.GetValueOrDefault<Schema::Group::MainKeyId>(nullptr),
-                                                   groups.GetValueOrDefault<Schema::Group::EncryptedGroupKey>(nullptr),
-                                                   groups.GetValueOrDefault<Schema::Group::GroupKeyNonce>(),
-                                                   groups.GetValueOrDefault<Schema::Group::MainKeyVersion>(),
-                                                   groups.GetValueOrDefault<Schema::Group::Down>(),
-                                                   groups.GetValueOrDefault<Schema::Group::SeenOperational>(),
+                                                   groups.GetValue<T::Generation>(),
+                                                   groups.GetValue<T::Owner>(),
+                                                   groups.GetValue<T::ErasureSpecies>(),
+                                                   groups.GetValue<T::DesiredPDiskCategory>(),
+                                                   groups.GetValueOrDefault<T::DesiredVDiskCategory>(NKikimrBlobStorage::TVDiskKind::Default),
+                                                   groups.GetValueOrDefault<T::EncryptionMode>(),
+                                                   groups.GetValueOrDefault<T::LifeCyclePhase>(),
+                                                   groups.GetValueOrDefault<T::MainKeyId>(nullptr),
+                                                   groups.GetValueOrDefault<T::EncryptedGroupKey>(nullptr),
+                                                   groups.GetValueOrDefault<T::GroupKeyNonce>(),
+                                                   groups.GetValueOrDefault<T::MainKeyVersion>(),
+                                                   groups.GetValueOrDefault<T::Down>(),
+                                                   groups.GetValueOrDefault<T::SeenOperational>(),
                                                    storagePoolId,
                                                    std::get<0>(geomIt->second),
                                                    std::get<1>(geomIt->second),
                                                    std::get<2>(geomIt->second));
-                Self->OwnerIdIdxToGroup.emplace(groups.GetValue<Schema::Group::Owner>(), groups.GetKey());
+
+                group.DecommitStatus = groups.GetValueOrDefault<T::DecommitStatus>();
+#define OPTIONAL(NAME) \
+                if (groups.HaveValue<T::NAME>()) { \
+                    group.NAME = groups.GetValue<T::NAME>(); \
+                }
+
+                OPTIONAL(VirtualGroupPool)
+                OPTIONAL(VirtualGroupState)
+                OPTIONAL(ParentDir)
+                OPTIONAL(Name)
+                OPTIONAL(SchemeshardId)
+                OPTIONAL(BlobDepotConfig)
+                OPTIONAL(TxId)
+                OPTIONAL(PathId)
+                OPTIONAL(BlobDepotId)
+                OPTIONAL(ErrorReason)
+
+#undef OPTIONAL
+
+                Self->OwnerIdIdxToGroup.emplace(groups.GetValue<T::Owner>(), groups.GetKey());
                 Self->IndexGroupSpeciesToGroup[group.GetGroupSpecies()].push_back(group.ID);
                 if (!groups.Next())
                     return false;
@@ -207,7 +229,8 @@ public:
         if (!NTableAdapter::FetchTable<Schema::HostConfig>(db, Self, Self->HostConfigs)
                 || !NTableAdapter::FetchTable<Schema::Box>(db, Self, Self->Boxes)
                 || !NTableAdapter::FetchTable<Schema::BoxStoragePool>(db, Self, Self->StoragePools)
-                || !NTableAdapter::FetchTable<Schema::DriveSerial>(db, Self, Self->DrivesSerials)) {
+                || !NTableAdapter::FetchTable<Schema::DriveSerial>(db, Self, Self->DrivesSerials)
+                || !NTableAdapter::FetchTable<Schema::VirtualGroupPool>(db, Self, Self->VirtualGroupPools)) {
             return false;
         }
         for (const auto& [storagePoolId, storagePool] : Self->StoragePools) {

Some files were not shown because too many files changed in this diff