From e12bcae094716f1e3153322e9903e9188a862aca Mon Sep 17 00:00:00 2001 From: ya-ksgamora Date: Mon, 27 Jan 2025 15:18:29 +0000 Subject: [PATCH] Allocation unit tests --- .../disk_registry/disk_registry_state.h | 2 +- .../disk_registry_state_ut_create.cpp | 277 ++++++++++++++++++ 2 files changed, 278 insertions(+), 1 deletion(-) diff --git a/cloud/blockstore/libs/storage/disk_registry/disk_registry_state.h b/cloud/blockstore/libs/storage/disk_registry/disk_registry_state.h index db43cdf4d0f..31a09cc106d 100644 --- a/cloud/blockstore/libs/storage/disk_registry/disk_registry_state.h +++ b/cloud/blockstore/libs/storage/disk_registry/disk_registry_state.h @@ -516,7 +516,7 @@ class TDiskRegistryState /// Mark selected device as clean and remove it /// from lists of suspended/dirty/pending cleanup devices - /// @return deallocated disk id of where selected device was deallocated + /// @return disk id where selected device was deallocated TDiskId MarkDeviceAsClean( TInstant now, TDiskRegistryDatabase& db, diff --git a/cloud/blockstore/libs/storage/disk_registry/disk_registry_state_ut_create.cpp b/cloud/blockstore/libs/storage/disk_registry/disk_registry_state_ut_create.cpp index 52db53ee190..568935722a5 100644 --- a/cloud/blockstore/libs/storage/disk_registry/disk_registry_state_ut_create.cpp +++ b/cloud/blockstore/libs/storage/disk_registry/disk_registry_state_ut_create.cpp @@ -492,6 +492,283 @@ Y_UNIT_TEST_SUITE(TDiskRegistryStateCreateTest) } } + Y_UNIT_TEST(ShouldAllocateLocalWithDirtyDevices) + { + TTestExecutor executor; + executor.WriteTx([&](TDiskRegistryDatabase db) { db.InitSchema(); }); + + constexpr ui64 LocalDeviceSize = 99999997952; // ~ 93.13 GiB + + auto makeLocalDevice = [](const auto* name, const auto* uuid) + { + return Device(name, uuid) | + WithPool("local-ssd", NProto::DEVICE_POOL_KIND_LOCAL) | + WithTotalSize(LocalDeviceSize); + }; + + auto agentConfig = AgentConfig( + 1, + { + makeLocalDevice("NVMELOCAL01", "uuid-1"), + makeLocalDevice("NVMELOCAL02", "uuid-2"), + makeLocalDevice("NVMELOCAL03", "uuid-3"), + }); + const TVector agents{ + agentConfig, + }; + + TDiskRegistryState state = + TDiskRegistryStateBuilder() + .WithConfig( + [&] + { + auto config = MakeConfig(0, agents); + + auto* pool = config.AddDevicePoolConfigs(); + pool->SetName("local-ssd"); + pool->SetKind(NProto::DEVICE_POOL_KIND_LOCAL); + pool->SetAllocationUnit(LocalDeviceSize); + + return config; + }()) + .WithAgents(agents) + .WithDirtyDevices( + {TDirtyDevice{"uuid-1", {}}, + TDirtyDevice{"uuid-2", {}}, + TDirtyDevice{"uuid-3", {}}}) + .Build(); + + auto allocate = [&](auto db, ui32 deviceCount) + { + TDiskRegistryState::TAllocateDiskResult result; + + auto error = state.AllocateDisk( + TInstant::Zero(), + db, + TDiskRegistryState::TAllocateDiskParams{ + .DiskId = "local0", + .BlockSize = DefaultLogicalBlockSize, + .BlocksCount = + deviceCount * LocalDeviceSize / DefaultLogicalBlockSize, + .MediaKind = NProto::STORAGE_MEDIA_SSD_LOCAL}, + &result); + + return std::make_pair(std::move(result), error); + }; + + // Register agents. + executor.WriteTx( + [&](TDiskRegistryDatabase db) { + UNIT_ASSERT_SUCCESS( + RegisterAgent(state, db, agentConfig, Now())); + }); + + UNIT_ASSERT_VALUES_EQUAL(1, state.GetConfig().KnownAgentsSize()); + UNIT_ASSERT_VALUES_EQUAL(1, state.GetAgents().size()); + UNIT_ASSERT_VALUES_EQUAL(0, state.GetSuspendedDevices().size()); + UNIT_ASSERT_VALUES_EQUAL(3, state.GetDirtyDevices().size()); + UNIT_ASSERT_VALUES_EQUAL(0, state.GetBrokenDevices().size()); + + // Allocate disk with dirty devices + executor.WriteTx( + [&](TDiskRegistryDatabase db) + { + auto [result, error] = allocate(db, 3U); + UNIT_ASSERT_SUCCESS(error); + UNIT_ASSERT_VALUES_EQUAL(3U, result.Devices.size()); + UNIT_ASSERT_VALUES_EQUAL(3U, result.DirtyDevices.size()); + UNIT_ASSERT_VALUES_EQUAL( + "NVMELOCAL01", + result.Devices[0].GetDeviceName()); + }); + } + + Y_UNIT_TEST(ShouldFavorCleanLocalDevices) + { + TTestExecutor executor; + executor.WriteTx([&](TDiskRegistryDatabase db) { db.InitSchema(); }); + + constexpr ui64 LocalDeviceSize = 99999997952; // ~ 93.13 GiB + + auto makeLocalDevice = [](const auto* name, const auto* uuid) + { + return Device(name, uuid) | + WithPool("local-ssd", NProto::DEVICE_POOL_KIND_LOCAL) | + WithTotalSize(LocalDeviceSize); + }; + + auto agentConfig = AgentConfig( + 1, + { + makeLocalDevice("NVMELOCAL01", "uuid-1"), + makeLocalDevice("NVMELOCAL02", "uuid-2"), + makeLocalDevice("NVMELOCAL03", "uuid-3"), + }); + const TVector agents{ + agentConfig, + }; + + TDiskRegistryState state = + TDiskRegistryStateBuilder() + .WithConfig( + [&] + { + auto config = MakeConfig(0, agents); + + auto* pool = config.AddDevicePoolConfigs(); + pool->SetName("local-ssd"); + pool->SetKind(NProto::DEVICE_POOL_KIND_LOCAL); + pool->SetAllocationUnit(LocalDeviceSize); + + return config; + }()) + .WithAgents(agents) + .WithDirtyDevices( + {TDirtyDevice{"uuid-1", {}}, + TDirtyDevice{"uuid-3", {}}}) + .Build(); + + auto allocate = [&](auto db, ui32 deviceCount) + { + TDiskRegistryState::TAllocateDiskResult result; + + auto error = state.AllocateDisk( + TInstant::Zero(), + db, + TDiskRegistryState::TAllocateDiskParams{ + .DiskId = "local0", + .BlockSize = DefaultLogicalBlockSize, + .BlocksCount = + deviceCount * LocalDeviceSize / DefaultLogicalBlockSize, + .MediaKind = NProto::STORAGE_MEDIA_SSD_LOCAL}, + &result); + + return std::make_pair(std::move(result), error); + }; + + // Register agents. + executor.WriteTx( + [&](TDiskRegistryDatabase db) { + UNIT_ASSERT_SUCCESS( + RegisterAgent(state, db, agentConfig, Now())); + }); + + UNIT_ASSERT_VALUES_EQUAL(1, state.GetConfig().KnownAgentsSize()); + UNIT_ASSERT_VALUES_EQUAL(1, state.GetAgents().size()); + UNIT_ASSERT_VALUES_EQUAL(0, state.GetSuspendedDevices().size()); + UNIT_ASSERT_VALUES_EQUAL(2, state.GetDirtyDevices().size()); + UNIT_ASSERT_VALUES_EQUAL(0, state.GetBrokenDevices().size()); + + // Allocate disk with dirty devices + executor.WriteTx( + [&](TDiskRegistryDatabase db) + { + auto [result, error] = allocate(db, 1U); + UNIT_ASSERT_SUCCESS(error); + UNIT_ASSERT_VALUES_EQUAL(1U, result.Devices.size()); + UNIT_ASSERT_VALUES_EQUAL(0U, result.DirtyDevices.size()); + UNIT_ASSERT_VALUES_EQUAL( + "NVMELOCAL02", + result.Devices[0].GetDeviceName()); + }); + } + + Y_UNIT_TEST(ShouldFavorCleanDevicesAndAllocateDirty) + { + TTestExecutor executor; + executor.WriteTx([&](TDiskRegistryDatabase db) { db.InitSchema(); }); + + constexpr ui64 LocalDeviceSize = 99999997952; // ~ 93.13 GiB + + auto makeLocalDevice = [](const auto* name, const auto* uuid) + { + return Device(name, uuid) | + WithPool("local-ssd", NProto::DEVICE_POOL_KIND_LOCAL) | + WithTotalSize(LocalDeviceSize); + }; + + auto agentConfig = AgentConfig( + 1, + { + makeLocalDevice("NVMELOCAL01", "uuid-1"), + makeLocalDevice("NVMELOCAL02", "uuid-2"), + makeLocalDevice("NVMELOCAL03", "uuid-3"), + }); + const TVector agents{ + agentConfig, + }; + + TDiskRegistryState state = + TDiskRegistryStateBuilder() + .WithConfig( + [&] + { + auto config = MakeConfig(0, agents); + + auto* pool = config.AddDevicePoolConfigs(); + pool->SetName("local-ssd"); + pool->SetKind(NProto::DEVICE_POOL_KIND_LOCAL); + pool->SetAllocationUnit(LocalDeviceSize); + + return config; + }()) + .WithAgents(agents) + .WithDirtyDevices( + {TDirtyDevice{"uuid-1", {}}, + TDirtyDevice{"uuid-3", {}}}) + .Build(); + + auto allocate = [&](auto db, ui32 deviceCount) + { + TDiskRegistryState::TAllocateDiskResult result; + + auto error = state.AllocateDisk( + TInstant::Zero(), + db, + TDiskRegistryState::TAllocateDiskParams{ + .DiskId = "local0", + .BlockSize = DefaultLogicalBlockSize, + .BlocksCount = + deviceCount * LocalDeviceSize / DefaultLogicalBlockSize, + .MediaKind = NProto::STORAGE_MEDIA_SSD_LOCAL}, + &result); + + return std::make_pair(std::move(result), error); + }; + + // Register agents. + executor.WriteTx( + [&](TDiskRegistryDatabase db) { + UNIT_ASSERT_SUCCESS( + RegisterAgent(state, db, agentConfig, Now())); + }); + + UNIT_ASSERT_VALUES_EQUAL(1, state.GetConfig().KnownAgentsSize()); + UNIT_ASSERT_VALUES_EQUAL(1, state.GetAgents().size()); + UNIT_ASSERT_VALUES_EQUAL(0, state.GetSuspendedDevices().size()); + UNIT_ASSERT_VALUES_EQUAL(2, state.GetDirtyDevices().size()); + UNIT_ASSERT_VALUES_EQUAL(0, state.GetBrokenDevices().size()); + + // Allocate disk with dirty devices + executor.WriteTx( + [&](TDiskRegistryDatabase db) + { + auto [result, error] = allocate(db, 2U); + UNIT_ASSERT_SUCCESS(error); + UNIT_ASSERT_VALUES_EQUAL(2U, result.Devices.size()); + UNIT_ASSERT_VALUES_EQUAL(1U, result.DirtyDevices.size()); + UNIT_ASSERT_VALUES_EQUAL( + "NVMELOCAL01", + result.DirtyDevices[0].GetDeviceName()); + UNIT_ASSERT_VALUES_EQUAL( + "NVMELOCAL02", + result.Devices[0].GetDeviceName()); + UNIT_ASSERT_VALUES_EQUAL( + "NVMELOCAL01", + result.Devices[1].GetDeviceName()); + }); + } + Y_UNIT_TEST(ShouldAllocateDiskWithAdjustedBlockCount) { TTestExecutor executor;