Skip to content

Add PDisk Move command #21496

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions ydb/apps/dstool/lib/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import ydb.apps.dstool.lib.dstool_cmd_pdisk_stop as pdisk_stop
import ydb.apps.dstool.lib.dstool_cmd_pdisk_restart as pdisk_restart
import ydb.apps.dstool.lib.dstool_cmd_pdisk_readonly as pdisk_readonly
import ydb.apps.dstool.lib.dstool_cmd_pdisk_move as pdisk_move

import ydb.apps.dstool.lib.dstool_cmd_vdisk_evict as vdisk_evict
import ydb.apps.dstool.lib.dstool_cmd_vdisk_list as vdisk_list
Expand Down Expand Up @@ -51,14 +52,14 @@
pool_list, pool_create_virtual,
group_check, group_decommit, group_show_blob_info, group_show_storage_efficiency, group_show_usage_by_tablets,
group_state, group_take_snapshot, group_add, group_list, group_virtual_create, group_virtual_cancel,
pdisk_add_by_serial, pdisk_remove_by_serial, pdisk_set, pdisk_list, pdisk_stop, pdisk_restart, pdisk_readonly,
pdisk_add_by_serial, pdisk_remove_by_serial, pdisk_set, pdisk_list, pdisk_stop, pdisk_restart, pdisk_readonly, pdisk_move,
vdisk_evict, vdisk_list, vdisk_set_read_only, vdisk_remove_donor, vdisk_wipe,
device_list,
]

default_structure = [
('device', ['list']),
('pdisk', ['add-by-serial', 'remove-by-serial', 'set', 'list', 'stop', 'restart', 'readonly']),
('pdisk', ['add-by-serial', 'remove-by-serial', 'set', 'list', 'stop', 'restart', 'readonly', 'move']),
('vdisk', ['evict', 'list', 'set-read-only', 'remove-donor', 'wipe']),
('group', ['add', 'check', 'decommit', ('show', ['blob-info', 'storage-efficiency', 'usage-by-tablets']), 'state', 'take-snapshot', 'list', ('virtual', ['create', 'cancel'])]),
('pool', ['list', ('create', ['virtual'])]),
Expand Down
64 changes: 64 additions & 0 deletions ydb/apps/dstool/lib/dstool_cmd_pdisk_move.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import ydb.apps.dstool.lib.common as common
import sys

description = 'Move PDisk'


def add_options(p):
common.add_pdisk_select_options(p)
common.add_ignore_degraded_group_check_option(p)
common.add_ignore_failure_model_group_check_option(p)
common.add_ignore_vslot_quotas_option(p)
common.add_basic_format_options(p)
p.add_argument('--source-pdisk', '-s', type=str, required=True,
help='Source PDisk in the format nodeId:pdiskId (e.g. "1:1000")')
p.add_argument('--destination-pdisk', '-d', type=str, required=True,
help='Destination PDisk in the format nodeId:pdiskId (e.g. "2:1000")')


def create_request(args, source_pdisk, target_pdisk):
request = common.create_bsc_request(args)
cmd = request.Command.add().MovePDisk

cmd.SourcePDisk.TargetPDiskId.NodeId = int(source_pdisk.split(';')[0])
cmd.SourcePDisk.TargetPDiskId.PDiskId = int(source_pdisk.split(';')[1])

cmd.DestinationPDisk.TargetPDiskId.NodeId = int(target_pdisk.split(';')[0])
cmd.DestinationPDisk.TargetPDiskId.PDiskId = int(target_pdisk.split(';')[1])

return request


def perform_request(request):
return common.invoke_bsc_request(request)


def is_successful_response(response):
return common.is_successful_bsc_response(response)


def do(args):
assert not args.dry_run, '--dry-run is not supported for this command'

src = args.source_pdisk
if src is None:
common.print_status(args, success=False, error_reason='Source PDisk is not specified')
sys.exit(1)

dst = args.destination_pdisk
if dst is None:
common.print_status(args, success=False, error_reason='Destination PDisk is not specified')
sys.exit(1)

success = True
error_reason = ''

request = create_request(args, src, dst)
response = perform_request(request)
if not is_successful_response(response):
success = False
error_reason += 'Request has failed: \n{0}\n{1}\n'.format(request, response)

common.print_status(args, success, error_reason)
if not success:
sys.exit(1)
1 change: 1 addition & 0 deletions ydb/apps/dstool/lib/ya.make
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ PY_SRCS(
dstool_cmd_pdisk_restart.py
dstool_cmd_pdisk_set.py
dstool_cmd_pdisk_stop.py
dstool_cmd_pdisk_move.py

dstool_cmd_vdisk_evict.py
dstool_cmd_vdisk_list.py
Expand Down
5 changes: 4 additions & 1 deletion ydb/core/blobstorage/nodewarden/node_warden_vdisk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ namespace NKikimr::NStorage {
STLOG(PRI_INFO, BS_NODE, NW00, "PoisonLocalVDisk", (VDiskId, vdisk.GetVDiskId()), (VSlotId, vdisk.GetVSlotId()),
(RuntimeData, vdisk.RuntimeData.has_value()));

bool vdiskRunning = false;

if (vdisk.RuntimeData) {
vdiskRunning = true;
vdisk.TIntrusiveListItem<TVDiskRecord, TGroupRelationTag>::Unlink();
TActivationContext::Send(new IEventHandle(TEvents::TSystem::Poison, 0, vdisk.GetVDiskServiceId(), {}, nullptr, 0));
vdisk.RuntimeData.reset();
Expand All @@ -50,7 +53,7 @@ namespace NKikimr::NStorage {
vdisk.ScrubCookie = 0; // disable reception of Scrub messages from this disk
vdisk.ScrubCookieForController = 0; // and from controller too
vdisk.Status = NKikimrBlobStorage::EVDiskStatus::ERROR;
vdisk.ShutdownPending = true;
vdisk.ShutdownPending = vdiskRunning; // Shutdown pending only if VDisk was running before poison
VDiskStatusChanged = true;
}

Expand Down
14 changes: 13 additions & 1 deletion ydb/core/blobstorage/pdisk/mock/pdisk_mock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ struct TPDiskMockState::TImpl {

const ui32 NodeId;
const ui32 PDiskId;
const ui64 PDiskGuid;
ui64 PDiskGuid;
const ui64 Size;
const ui32 ChunkSize;
const ui32 TotalChunks;
Expand Down Expand Up @@ -904,6 +904,8 @@ class TPDiskMockActor : public TActorBootstrapped<TPDiskMockActor> {
bool restartAllowed = ev->Get()->RestartAllowed;

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

void Handle(TEvMoveDrive::TPtr& ev) {
State = ev->Get()->State;
Impl.Blocks = State->Impl->Blocks;
Impl.Owners = State->Impl->Owners;
Impl.PDiskGuid = State->Impl->PDiskGuid;
}

void HandleMoveToErrorState() {
Impl.StateErrorReason = "Some error reason";
Become(&TThis::StateError);
Expand Down Expand Up @@ -1064,6 +1073,7 @@ class TPDiskMockActor : public TActorBootstrapped<TPDiskMockActor> {
cFunc(TEvents::TSystem::Wakeup, ReportMetrics);
hFunc(NPDisk::TEvReadMetadata, Handle);
hFunc(NPDisk::TEvWriteMetadata, Handle);
hFunc(TEvMoveDrive, Handle);

cFunc(EvBecomeError, HandleMoveToErrorState);

Expand All @@ -1085,6 +1095,8 @@ class TPDiskMockActor : public TActorBootstrapped<TPDiskMockActor> {
hFunc(NPDisk::TEvReadMetadata, ErrorHandle);
hFunc(NPDisk::TEvWriteMetadata, ErrorHandle);
hFunc(TEvBlobStorage::TEvAskWardenRestartPDiskResult, Handle);
hFunc(NPDisk::TEvYardControl, Handle);
hFunc(TEvMoveDrive, Handle);

cFunc(TEvents::TSystem::Wakeup, ReportMetrics);
cFunc(EvBecomeNormal, HandleMoveToNormalState);
Expand Down
11 changes: 10 additions & 1 deletion ydb/core/blobstorage/pdisk/mock/pdisk_mock.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ namespace NKikimr {

enum EPDiskMockEvents {
EvBecomeError = TEvBlobStorage::EvEnd + 1,
EvBecomeNormal
EvBecomeNormal,
EvReplaceData,
};

class TPDiskMockState : public TThrRefBase {
Expand Down Expand Up @@ -51,6 +52,14 @@ namespace NKikimr {
bool IsDiskReadOnly() const;
};

struct TEvMoveDrive : TEventLocal<TEvMoveDrive, EvReplaceData> {
TIntrusivePtr<TPDiskMockState>& State;

TEvMoveDrive(TIntrusivePtr<TPDiskMockState>& state)
: State(state)
{}
};

IActor *CreatePDiskMockActor(TPDiskMockState::TPtr state);

} // NKikimr
6 changes: 5 additions & 1 deletion ydb/core/blobstorage/ut_blobstorage/lib/env.h
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,7 @@ struct TEnvironmentSetup {
}

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

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

if (geometry) {
cmd2->MutableGeometry()->CopyFrom(*geometry);
}

auto response = Invoke(request);
UNIT_ASSERT_C(response.GetSuccess(), response.GetErrorDescription());
}
Expand Down
Loading
Loading