Skip to content

Commit da95253

Browse files
authored
Harden decommission checks for BlobDepot (#28216) (#28995)
2 parents 1da7d9a + 769973b commit da95253

File tree

4 files changed

+58
-24
lines changed

4 files changed

+58
-24
lines changed

ydb/apps/dstool/lib/dstool_cmd_group_decommit.py

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,26 @@
11
import ydb.apps.dstool.lib.common as common
22
import ydb.core.protos.blob_depot_config_pb2 as blob_depot_config
33
import sys
4+
import time
45

56
description = 'Decommit physical group'
67

78

89
def add_options(p):
910
common.add_group_ids_option(p, required=True)
1011
g = p.add_mutually_exclusive_group(required=True)
11-
g.add_argument('--hive-id', type=int, help='tablet id of containing hive')
12-
g.add_argument('--database', type=str, help='database path of containing hive')
12+
g.add_argument('--database', type=str, required=True, help='database path for storage pools with groups being decommitted')
1313
p.add_argument('--log-channel-sp', type=str, metavar='POOL_NAME', help='channel 0 specifier')
1414
p.add_argument('--snapshot-channel-sp', type=str, metavar='POOL_NAME', help='channel 1 specifier (defaults to channel 0)')
1515
p.add_argument('--data-channel-sp', type=str, metavar='POOL_NAME[*COUNT]', nargs='*', help='data channel specifier')
16+
p.add_argument('--wait', action='store_true', help='wait until group decommission is started')
1617

1718

1819
def do(args):
1920
request = common.create_bsc_request(args)
2021
cmd = request.Command.add().DecommitGroups
2122
cmd.GroupIds.extend(args.group_ids)
22-
if args.hive_id is not None:
23-
cmd.HiveId = args.hive_id
24-
if args.database is not None:
25-
cmd.Database = args.database
23+
cmd.Database = args.database
2624

2725
if args.log_channel_sp or args.snapshot_channel_sp or args.data_channel_sp:
2826
if args.log_channel_sp is None:
@@ -44,4 +42,39 @@ def do(args):
4442
cmd.ChannelProfiles.add(StoragePoolName=pool_name, ChannelKind=blob_depot_config.TChannelKind.Data, Count=count)
4543

4644
response = common.invoke_bsc_request(request)
47-
common.print_request_result(args, request, response)
45+
46+
if args.wait and response.Success:
47+
groups_of_interest = set(args.group_ids)
48+
49+
while groups_of_interest:
50+
time.sleep(1)
51+
base_config_and_storage_pools = common.fetch_base_config_and_storage_pools(virtualGroupsOnly=True)
52+
base_config = base_config_and_storage_pools['BaseConfig']
53+
group_map = common.build_group_map(base_config)
54+
for group_id in list(groups_of_interest):
55+
if group_id not in group_map:
56+
print(f'Group {group_id} is missing in group list', file=sys.stderr)
57+
groups_of_interest.remove(group_id)
58+
continue
59+
group = group_map[group_id]
60+
if group.VirtualGroupInfo is None:
61+
print(f'Group {group_id} is not virtual group', file=sys.stderr)
62+
elif group.VirtualGroupInfo.State == common.EVirtualGroupState.WORKING:
63+
pass
64+
elif group.VirtualGroupInfo.State == common.EVirtualGroupState.CREATE_FAILED:
65+
print(f'Group {group_id} decommission failed to start: {group.VirtualGroupInfo.ErrorReason}, canceling', file=sys.stderr)
66+
request = common.kikimr_bsconfig.TConfigRequest()
67+
cmd = request.Command.add().CancelVirtualGroup
68+
cmd.GroupId = group_id
69+
response = common.invoke_bsc_request(request)
70+
if not response.Success:
71+
print(f'Failed to cancel decommission for group {group_id}', file=sys.stderr)
72+
elif group.VirtualGroupInfo.State == common.EVirtualGroupState.DELETING:
73+
print(f'Group {group_id} is being deleted', file=sys.stderr)
74+
elif group.VirtualGroupInfo.State == common.EVirtualGroupState.NEW:
75+
continue
76+
else:
77+
print(f'Group {group_id} has unexpected virtual group state', file=sys.stderr)
78+
groups_of_interest.remove(group_id)
79+
else:
80+
common.print_request_result(args, request, response)

ydb/core/blobstorage/ut_blobstorage/blob_depot_test_functions.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ void DecommitGroup(TBlobDepotTestEnvironment& tenv, ui32 groupId) {
1515

1616
auto *cmd = request.AddCommand()->MutableDecommitGroups();
1717
cmd->AddGroupIds(groupId);
18-
cmd->SetHiveId(tenv.Env->Runtime->GetDomainsInfo()->GetHive());
18+
cmd->SetDatabase(TStringBuilder() << '/' << tenv.Env->Runtime->GetDomainsInfo()->GetDomain()->Name);
1919
auto *prof = cmd->AddChannelProfiles();
2020
prof->SetStoragePoolName(blobDepotPool);
2121
prof->SetCount(2);

ydb/core/mind/bscontroller/virtual_group.cpp

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -103,21 +103,17 @@ namespace NKikimr::NBsController {
103103
}
104104

105105
void TBlobStorageController::TConfigState::ExecuteStep(const NKikimrBlobStorage::TDecommitGroups& cmd, TStatus& /*status*/) {
106-
if (cmd.GetHiveDesignatorCase() == NKikimrBlobStorage::TDecommitGroups::HIVEDESIGNATOR_NOT_SET) {
107-
throw TExError() << "TDecommitGroups.HiveId/Database is not specified";
106+
if (!cmd.HasDatabase()) {
107+
throw TExError() << "TDecommitGroups.Database is not specified, but it is mandatory";
108108
}
109109

110110
for (const ui32 groupId : cmd.GetGroupIds()) {
111111
TGroupInfo *group = Groups.FindForUpdate(TGroupId::FromValue(groupId));
112112
if (!group) {
113113
throw TExGroupNotFound(groupId);
114114
} else if (group->DecommitStatus != NKikimrBlobStorage::TGroupDecommitStatus::NONE) {
115-
if (cmd.HasHiveId() && group->HiveId && *group->HiveId != cmd.GetHiveId()) {
116-
throw TExError() << "different hive specified for decommitting group" << TErrorParams::GroupId(groupId);
117-
} else if (cmd.HasDatabase() && group->Database && *group->Database != cmd.GetDatabase()) {
115+
if (group->Database != cmd.GetDatabase()) {
118116
throw TExError() << "different database specified for decommitting group" << TErrorParams::GroupId(groupId);
119-
} else if (cmd.HasHiveId() != group->HiveId.Defined() && cmd.HasDatabase() != group->Database.Defined()) {
120-
throw TExError() << "different hive designator specified for decommitting group" << TErrorParams::GroupId(groupId);
121117
}
122118
// group is already being decommitted -- make this operation idempotent
123119
continue;
@@ -127,8 +123,7 @@ namespace NKikimr::NBsController {
127123

128124
group->DecommitStatus = NKikimrBlobStorage::TGroupDecommitStatus::PENDING;
129125
group->VirtualGroupState = NKikimrBlobStorage::EVirtualGroupState::NEW;
130-
group->HiveId = cmd.HasHiveId() ? MakeMaybe(cmd.GetHiveId()) : Nothing();
131-
group->Database = cmd.HasDatabase() ? MakeMaybe(cmd.GetDatabase()) : Nothing();
126+
group->Database = cmd.GetDatabase();
132127
group->NeedAlter = true;
133128
GroupFailureModelChanged.insert(group->ID);
134129
group->CalculateGroupStatus();
@@ -424,24 +419,27 @@ namespace NKikimr::NBsController {
424419
ui64 RootHiveId = 0;
425420
bool TenantHiveInvalidated = false;
426421
bool TenantHiveInvalidateInProgress = false;
422+
bool IsDecommittingGroup = false;
427423

428424
void HiveCreate(TGroupInfo *group) {
429425
auto& config = GetConfig(group);
426+
IsDecommittingGroup = config.GetIsDecommittingGroup();
427+
430428
if (config.HasTabletId()) {
431429
ConfigureBlobDepot();
432430
} else if (!group->HiveId) {
433431
HiveResolve(group);
434432
} else if (TenantHiveInvalidateInProgress && TenantHivePipeId) {
435433
// tenant hive storage pool invalidation still in progress, wait
436-
} else if (config.GetIsDecommittingGroup() && config.HasTenantHiveId() && !TenantHiveInvalidated) {
434+
} else if (IsDecommittingGroup && config.HasTenantHiveId() && !TenantHiveInvalidated) {
437435
TenantHivePipeId = Register(NTabletPipe::CreateClient(SelfId(), config.GetTenantHiveId(),
438436
NTabletPipe::TClientRetryPolicy::WithRetries()));
439437
HiveInvalidateGroups(TenantHivePipeId, group);
440438
TenantHiveInvalidateInProgress = true;
441439
} else if (!HivePipeId) {
442440
Y_ABORT_UNLESS(group->HiveId);
443441
HivePipeId = Register(NTabletPipe::CreateClient(SelfId(), *group->HiveId, NTabletPipe::TClientRetryPolicy::WithRetries()));
444-
if (config.GetIsDecommittingGroup()) {
442+
if (IsDecommittingGroup) {
445443
HiveInvalidateGroups(HivePipeId, group);
446444
}
447445
} else {
@@ -483,7 +481,10 @@ namespace NKikimr::NBsController {
483481
(Result, response.ToString(*AppData()->TypeRegistry)));
484482

485483
if (item.Status != NSchemeCache::TSchemeCacheNavigate::EStatus::Ok || !domainInfo || !item.DomainDescription) {
486-
return CreateFailed(TStringBuilder() << "failed to resolve Hive -- erroneous reply from SchemeCache or not a domain");
484+
return CreateFailed(TStringBuilder() << "failed to resolve Hive -- erroneous reply from SchemeCache or not a domain"
485+
<< " Response# " << response.ToString(*AppData()->TypeRegistry)
486+
<< " DomainInfo# " << static_cast<bool>(domainInfo)
487+
<< " DomainDescription# " << static_cast<bool>(item.DomainDescription));
487488
} else if (const auto& params = domainInfo->Params; !params.HasHive() && !RootHiveId) {
488489
return CreateFailed("failed to resolve Hive -- no Hive in SchemeCache reply");
489490
} else {
@@ -513,7 +514,7 @@ namespace NKikimr::NBsController {
513514
}
514515
}
515516

516-
const ui64 hiveId = params.HasHive() ? params.GetHive() : RootHiveId;
517+
const ui64 hiveId = params.HasHive() && !IsDecommittingGroup ? params.GetHive() : RootHiveId;
517518
if (!hiveId) {
518519
return CreateFailed("failed to resolve Hive -- Hive is zero");
519520
}

ydb/docs/ru/core/maintenance/manual/blobdepot_decommit.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,14 @@
2424
Для запуска декомиссии выполняется команда BS\_CONTROLLER, в которой нужно указать список декомиссуемых групп, а также номер таблетки Hive, которая будет управлять блобовницами декомиссуемых групп. Также можно указать список пулов, в которых блобовница будет хранить свои данные. Если этот список не указан, то BS\_CONTROLLER автоматически выбирает для хранения данных те же пулы, в которых располагаются декомиссуемые группы, а число каналов данных делается равным числу физических групп в этих пулах (но не более 250 штук).
2525

2626
```bash
27-
dstool -e ... --direct group decommit --group-ids 2181038080 --database=/Root/db1 --hive-id=72057594037968897
27+
dstool -e ... --direct group decommit --group-ids 2181038080 --database=/Root/db1 --wait
2828
```
2929

3030
Параметры командной строки:
3131

32+
* --wait дождаться запуска декомиссии; в случае возникновения ошибки запуска ошибка выводится на экран, декомиссия отменяется автоматически (только при указании этой опции);
3233
* --group-ids GROUP\_ID GROUP\_ID список групп, для которых можно провести декомиссию;
33-
* --database=DB указать тенант, в котором нужно делать декомиссию;
34-
* --hive-id=N явно указать номер таблетки Hive, которая будет управлять данной блобовницей; нельзя указывать идентификатор Hive того тенанта, которому принадлежат пулы с декомиссуемыми группами, т.к. этот Hive может хранить свои данные поверх группы, которая управляется блобовницей, что приведёт к циклической зависимости; рекомендуется указывать корневой Hive;
34+
* --database=DB указать тенант, в котором нужно делать декомиссию (или домен, если декомиссия делается для групп внутри домена);
3535
* --log-channel-sp=POOL\_NAME название пула, в котором будет размещён канал 0 таблетки блобовницы;
3636
* --snapshot-channel-sp=POOL\_NAME название пула, в котором будет размещён кана 1 таблетки блобовницы; если не указан, то используется значение из --log-channel-sp;
3737
* --data-channel-sp=POOL\_NAME[\*COUNT] название пула, в котором размещаются каналы данных; если указан параметр COUNT (после знака "звёздочка"), то создаётся COUNT каналов данных в указанном пуле.

0 commit comments

Comments
 (0)