Skip to content

Commit a01ae67

Browse files
authored
Add PDisk Move command (#21496)
(cherry picked from commit 63183ec)
2 parents 270a8a0 + e77e447 commit a01ae67

File tree

16 files changed

+425
-9
lines changed

16 files changed

+425
-9
lines changed

ydb/apps/dstool/lib/commands.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import ydb.apps.dstool.lib.dstool_cmd_pdisk_stop as pdisk_stop
88
import ydb.apps.dstool.lib.dstool_cmd_pdisk_restart as pdisk_restart
99
import ydb.apps.dstool.lib.dstool_cmd_pdisk_readonly as pdisk_readonly
10+
import ydb.apps.dstool.lib.dstool_cmd_pdisk_move as pdisk_move
1011

1112
import ydb.apps.dstool.lib.dstool_cmd_vdisk_evict as vdisk_evict
1213
import ydb.apps.dstool.lib.dstool_cmd_vdisk_list as vdisk_list
@@ -51,14 +52,14 @@
5152
pool_list, pool_create_virtual,
5253
group_check, group_decommit, group_show_blob_info, group_show_storage_efficiency, group_show_usage_by_tablets,
5354
group_state, group_take_snapshot, group_add, group_list, group_virtual_create, group_virtual_cancel,
54-
pdisk_add_by_serial, pdisk_remove_by_serial, pdisk_set, pdisk_list, pdisk_stop, pdisk_restart, pdisk_readonly,
55+
pdisk_add_by_serial, pdisk_remove_by_serial, pdisk_set, pdisk_list, pdisk_stop, pdisk_restart, pdisk_readonly, pdisk_move,
5556
vdisk_evict, vdisk_list, vdisk_set_read_only, vdisk_remove_donor, vdisk_wipe,
5657
device_list,
5758
]
5859

5960
default_structure = [
6061
('device', ['list']),
61-
('pdisk', ['add-by-serial', 'remove-by-serial', 'set', 'list', 'stop', 'restart', 'readonly']),
62+
('pdisk', ['add-by-serial', 'remove-by-serial', 'set', 'list', 'stop', 'restart', 'readonly', 'move']),
6263
('vdisk', ['evict', 'list', 'set-read-only', 'remove-donor', 'wipe']),
6364
('group', ['add', 'check', 'decommit', ('show', ['blob-info', 'storage-efficiency', 'usage-by-tablets']), 'state', 'take-snapshot', 'list', ('virtual', ['create', 'cancel'])]),
6465
('pool', ['list', ('create', ['virtual'])]),
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import ydb.apps.dstool.lib.common as common
2+
import sys
3+
4+
description = 'Move PDisk'
5+
6+
7+
def add_options(p):
8+
common.add_pdisk_select_options(p)
9+
common.add_ignore_degraded_group_check_option(p)
10+
common.add_ignore_failure_model_group_check_option(p)
11+
common.add_ignore_vslot_quotas_option(p)
12+
common.add_basic_format_options(p)
13+
p.add_argument('--source-pdisk', '-s', type=str, required=True,
14+
help='Source PDisk in the format nodeId:pdiskId (e.g. "1:1000")')
15+
p.add_argument('--destination-pdisk', '-d', type=str, required=True,
16+
help='Destination PDisk in the format nodeId:pdiskId (e.g. "2:1000")')
17+
18+
19+
def create_request(args, source_pdisk, target_pdisk):
20+
request = common.create_bsc_request(args)
21+
cmd = request.Command.add().MovePDisk
22+
23+
cmd.SourcePDisk.TargetPDiskId.NodeId = int(source_pdisk.split(';')[0])
24+
cmd.SourcePDisk.TargetPDiskId.PDiskId = int(source_pdisk.split(';')[1])
25+
26+
cmd.DestinationPDisk.TargetPDiskId.NodeId = int(target_pdisk.split(';')[0])
27+
cmd.DestinationPDisk.TargetPDiskId.PDiskId = int(target_pdisk.split(';')[1])
28+
29+
return request
30+
31+
32+
def perform_request(request):
33+
return common.invoke_bsc_request(request)
34+
35+
36+
def is_successful_response(response):
37+
return common.is_successful_bsc_response(response)
38+
39+
40+
def do(args):
41+
assert not args.dry_run, '--dry-run is not supported for this command'
42+
43+
src = args.source_pdisk
44+
if src is None:
45+
common.print_status(args, success=False, error_reason='Source PDisk is not specified')
46+
sys.exit(1)
47+
48+
dst = args.destination_pdisk
49+
if dst is None:
50+
common.print_status(args, success=False, error_reason='Destination PDisk is not specified')
51+
sys.exit(1)
52+
53+
success = True
54+
error_reason = ''
55+
56+
request = create_request(args, src, dst)
57+
response = perform_request(request)
58+
if not is_successful_response(response):
59+
success = False
60+
error_reason += 'Request has failed: \n{0}\n{1}\n'.format(request, response)
61+
62+
common.print_status(args, success, error_reason)
63+
if not success:
64+
sys.exit(1)

ydb/apps/dstool/lib/ya.make

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ PY_SRCS(
1818
dstool_cmd_pdisk_restart.py
1919
dstool_cmd_pdisk_set.py
2020
dstool_cmd_pdisk_stop.py
21+
dstool_cmd_pdisk_move.py
2122

2223
dstool_cmd_vdisk_evict.py
2324
dstool_cmd_vdisk_list.py

ydb/core/blobstorage/nodewarden/node_warden_vdisk.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@ namespace NKikimr::NStorage {
2525
STLOG(PRI_INFO, BS_NODE, NW00, "PoisonLocalVDisk", (VDiskId, vdisk.GetVDiskId()), (VSlotId, vdisk.GetVSlotId()),
2626
(RuntimeData, vdisk.RuntimeData.has_value()));
2727

28+
bool vdiskRunning = false;
29+
2830
if (vdisk.RuntimeData) {
31+
vdiskRunning = true;
2932
vdisk.TIntrusiveListItem<TVDiskRecord, TGroupRelationTag>::Unlink();
3033
TActivationContext::Send(new IEventHandle(TEvents::TSystem::Poison, 0, vdisk.GetVDiskServiceId(), {}, nullptr, 0));
3134
vdisk.RuntimeData.reset();
@@ -50,7 +53,7 @@ namespace NKikimr::NStorage {
5053
vdisk.ScrubCookie = 0; // disable reception of Scrub messages from this disk
5154
vdisk.ScrubCookieForController = 0; // and from controller too
5255
vdisk.Status = NKikimrBlobStorage::EVDiskStatus::ERROR;
53-
vdisk.ShutdownPending = true;
56+
vdisk.ShutdownPending = vdiskRunning; // Shutdown pending only if VDisk was running before poison
5457
VDiskStatusChanged = true;
5558
}
5659

ydb/core/blobstorage/pdisk/mock/pdisk_mock.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ struct TPDiskMockState::TImpl {
3434

3535
const ui32 NodeId;
3636
const ui32 PDiskId;
37-
const ui64 PDiskGuid;
37+
ui64 PDiskGuid;
3838
const ui64 Size;
3939
const ui32 ChunkSize;
4040
const ui32 TotalChunks;
@@ -904,6 +904,8 @@ class TPDiskMockActor : public TActorBootstrapped<TPDiskMockActor> {
904904
bool restartAllowed = ev->Get()->RestartAllowed;
905905

906906
if (restartAllowed) {
907+
Become(&TThis::StateNormal);
908+
Impl.StateErrorReason = "";
907909
Impl.IsDiskReadOnly = ev->Get()->Config->ReadOnly;
908910
Send(ev->Sender, new TEvBlobStorage::TEvNotifyWardenPDiskRestarted(Impl.PDiskId));
909911
}
@@ -1033,6 +1035,13 @@ class TPDiskMockActor : public TActorBootstrapped<TPDiskMockActor> {
10331035
Send(ev->Sender, new NPDisk::TEvWriteMetadataResult(NPDisk::EPDiskMetadataOutcome::OK, Impl.PDiskGuid), 0, ev->Cookie);
10341036
}
10351037

1038+
void Handle(TEvMoveDrive::TPtr& ev) {
1039+
State = ev->Get()->State;
1040+
Impl.Blocks = State->Impl->Blocks;
1041+
Impl.Owners = State->Impl->Owners;
1042+
Impl.PDiskGuid = State->Impl->PDiskGuid;
1043+
}
1044+
10361045
void HandleMoveToErrorState() {
10371046
Impl.StateErrorReason = "Some error reason";
10381047
Become(&TThis::StateError);
@@ -1064,6 +1073,7 @@ class TPDiskMockActor : public TActorBootstrapped<TPDiskMockActor> {
10641073
cFunc(TEvents::TSystem::Wakeup, ReportMetrics);
10651074
hFunc(NPDisk::TEvReadMetadata, Handle);
10661075
hFunc(NPDisk::TEvWriteMetadata, Handle);
1076+
hFunc(TEvMoveDrive, Handle);
10671077

10681078
cFunc(EvBecomeError, HandleMoveToErrorState);
10691079

@@ -1085,6 +1095,8 @@ class TPDiskMockActor : public TActorBootstrapped<TPDiskMockActor> {
10851095
hFunc(NPDisk::TEvReadMetadata, ErrorHandle);
10861096
hFunc(NPDisk::TEvWriteMetadata, ErrorHandle);
10871097
hFunc(TEvBlobStorage::TEvAskWardenRestartPDiskResult, Handle);
1098+
hFunc(NPDisk::TEvYardControl, Handle);
1099+
hFunc(TEvMoveDrive, Handle);
10881100

10891101
cFunc(TEvents::TSystem::Wakeup, ReportMetrics);
10901102
cFunc(EvBecomeNormal, HandleMoveToNormalState);

ydb/core/blobstorage/pdisk/mock/pdisk_mock.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ namespace NKikimr {
99

1010
enum EPDiskMockEvents {
1111
EvBecomeError = TEvBlobStorage::EvEnd + 1,
12-
EvBecomeNormal
12+
EvBecomeNormal,
13+
EvReplaceData,
1314
};
1415

1516
class TPDiskMockState : public TThrRefBase {
@@ -51,6 +52,14 @@ namespace NKikimr {
5152
bool IsDiskReadOnly() const;
5253
};
5354

55+
struct TEvMoveDrive : TEventLocal<TEvMoveDrive, EvReplaceData> {
56+
TIntrusivePtr<TPDiskMockState>& State;
57+
58+
TEvMoveDrive(TIntrusivePtr<TPDiskMockState>& state)
59+
: State(state)
60+
{}
61+
};
62+
5463
IActor *CreatePDiskMockActor(TPDiskMockState::TPtr state);
5564

5665
} // NKikimr

ydb/core/blobstorage/ut_blobstorage/lib/env.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,7 @@ struct TEnvironmentSetup {
542542
}
543543

544544
void CreateBoxAndPool(ui32 numDrivesPerNode = 0, ui32 numGroups = 0, ui32 numStorageNodes = 0,
545-
NKikimrBlobStorage::EPDiskType pdiskType = NKikimrBlobStorage::EPDiskType::ROT) {
545+
NKikimrBlobStorage::EPDiskType pdiskType = NKikimrBlobStorage::EPDiskType::ROT, const std::optional<NKikimrBlobStorage::TGroupGeometry>& geometry = std::nullopt) {
546546
NKikimrBlobStorage::TConfigRequest request;
547547

548548
auto *cmd = request.AddCommand()->MutableDefineHostConfig();
@@ -579,6 +579,10 @@ struct TEnvironmentSetup {
579579
cmd2->SetEncryptionMode(TBlobStorageGroupInfo::EEncryptionMode::EEM_ENC_V1);
580580
}
581581

582+
if (geometry) {
583+
cmd2->MutableGeometry()->CopyFrom(*geometry);
584+
}
585+
582586
auto response = Invoke(request);
583587
UNIT_ASSERT_C(response.GetSuccess(), response.GetErrorDescription());
584588
}

0 commit comments

Comments
 (0)