From 124edf03816799409f62823193efa65d740e02d7 Mon Sep 17 00:00:00 2001 From: Stepanyuk Vladislav Date: Fri, 10 Jan 2025 06:48:23 +0000 Subject: [PATCH] issue-2732: add config flag for buttons --- cloud/blockstore/config/storage.proto | 7 ++++ cloud/blockstore/libs/storage/core/config.cpp | 2 + cloud/blockstore/libs/storage/core/config.h | 2 + ...disk_registry_actor_change_agent_state.cpp | 38 ++++++++++++++++++- ...isk_registry_actor_change_device_state.cpp | 28 +++++++++++--- .../disk_registry_actor_monitoring.cpp | 29 ++++++++++---- cloud/blockstore/tests/monitoring/test.py | 17 ++------- 7 files changed, 94 insertions(+), 29 deletions(-) diff --git a/cloud/blockstore/config/storage.proto b/cloud/blockstore/config/storage.proto index c7fd81f92d..93e2ccc544 100644 --- a/cloud/blockstore/config/storage.proto +++ b/cloud/blockstore/config/storage.proto @@ -1083,4 +1083,11 @@ message TStorageServiceConfig // percentage, then the rejection of such agents does not occur - we assume // a connectivity failure in the cluster. optional double DiskRegistryInitialAgentRejectionThreshold = 396; + + // Enable buttons for agent/device state changing. + optional bool EnableToChangeStatesFromMonpage = 397; + + // Enable buttons for agent/device state changing, + // when they in unavailable/error state. + optional bool EnableToChangeErrorStatesFromMonpage = 398; } diff --git a/cloud/blockstore/libs/storage/core/config.cpp b/cloud/blockstore/libs/storage/core/config.cpp index 827ad3a8a0..f82d200745 100644 --- a/cloud/blockstore/libs/storage/core/config.cpp +++ b/cloud/blockstore/libs/storage/core/config.cpp @@ -521,6 +521,8 @@ TDuration MSeconds(ui32 value) xxx(EncryptionAtRestForDiskRegistryBasedDisksEnabled, bool, false )\ xxx(DisableFullPlacementGroupCountCalculation, bool, false )\ xxx(DiskRegistryInitialAgentRejectionThreshold, double, 50 )\ + xxx(EnableToChangeStatesFromMonpage, bool, false )\ + xxx(EnableToChangeErrorStatesFromMonpage, bool, false )\ // BLOCKSTORE_STORAGE_CONFIG_RW #define BLOCKSTORE_STORAGE_CONFIG(xxx) \ diff --git a/cloud/blockstore/libs/storage/core/config.h b/cloud/blockstore/libs/storage/core/config.h index 96ed8b1968..00bc62662c 100644 --- a/cloud/blockstore/libs/storage/core/config.h +++ b/cloud/blockstore/libs/storage/core/config.h @@ -622,6 +622,8 @@ class TStorageConfig [[nodiscard]] bool GetDisableFullPlacementGroupCountCalculation() const; [[nodiscard]] double GetDiskRegistryInitialAgentRejectionThreshold() const; + [[nodiscard]] bool GetEnableToChangeStatesFromMonpage() const; + [[nodiscard]] bool GetEnableToChangeErrorStatesFromMonpage() const; }; ui64 GetAllocationUnit( diff --git a/cloud/blockstore/libs/storage/disk_registry/disk_registry_actor_change_agent_state.cpp b/cloud/blockstore/libs/storage/disk_registry/disk_registry_actor_change_agent_state.cpp index f5ccf0e751..1bcd856af3 100644 --- a/cloud/blockstore/libs/storage/disk_registry/disk_registry_actor_change_agent_state.cpp +++ b/cloud/blockstore/libs/storage/disk_registry/disk_registry_actor_change_agent_state.cpp @@ -130,7 +130,7 @@ void TChangeAgentStateActor::HandlePoisonPill( const TActorContext& ctx) { Y_UNUSED(ev); - ReplyAndDie(ctx, MakeError(E_REJECTED, "Tablet is dead")); + ReplyAndDie(ctx, MakeTabletIsDeadError(E_REJECTED, __LOCATION__)); } void TChangeAgentStateActor::HandleChangeAgentStateResponse( @@ -170,6 +170,11 @@ void TDiskRegistryActor::HandleHttpInfo_ChangeAgentState( const TCgiParameters& params, TRequestInfoPtr requestInfo) { + if (!Config->GetEnableToChangeStatesFromMonpage()) { + RejectHttpRequest(ctx, *requestInfo, "Can't change state from monpage"); + return; + } + const auto& newStateRaw = params.Get("NewState"); const auto& agentId = params.Get("AgentID"); @@ -189,7 +194,7 @@ void TDiskRegistryActor::HandleHttpInfo_ChangeAgentState( return; } - static const THashSet NewStateWhiteList = { + static const THashSet NewStateWhiteList{ NProto::EAgentState::AGENT_STATE_ONLINE, NProto::EAgentState::AGENT_STATE_WARNING, }; @@ -199,6 +204,35 @@ void TDiskRegistryActor::HandleHttpInfo_ChangeAgentState( return; } + const auto agentState = State->GetAgentState(agentId); + if (agentState.Empty()) { + RejectHttpRequest(ctx, *requestInfo, "Unknown agent"); + return; + } + + static const auto OldStateWhiteList = [&]() + { + THashSet whitelist = { + NProto::EAgentState::AGENT_STATE_ONLINE, + NProto::EAgentState::AGENT_STATE_WARNING, + }; + + if (Config->GetEnableToChangeErrorStatesFromMonpage()) { + whitelist.emplace(NProto::EAgentState::AGENT_STATE_UNAVAILABLE); + } + + return whitelist; + }(); + + + if (!OldStateWhiteList.contains(*agentState.Get())) { + RejectHttpRequest( + ctx, + *requestInfo, + "Can't change agent state from " + + EAgentState_Name(*agentState.Get())); + } + LOG_INFO( ctx, TBlockStoreComponents::DISK_REGISTRY, diff --git a/cloud/blockstore/libs/storage/disk_registry/disk_registry_actor_change_device_state.cpp b/cloud/blockstore/libs/storage/disk_registry/disk_registry_actor_change_device_state.cpp index 865658d71f..4a408f4033 100644 --- a/cloud/blockstore/libs/storage/disk_registry/disk_registry_actor_change_device_state.cpp +++ b/cloud/blockstore/libs/storage/disk_registry/disk_registry_actor_change_device_state.cpp @@ -131,7 +131,7 @@ void TChangeDeviceStateActor::HandlePoisonPill( const TActorContext& ctx) { Y_UNUSED(ev); - ReplyAndDie(ctx, MakeError(E_REJECTED, "Tablet is dead")); + ReplyAndDie(ctx, MakeTabletIsDeadError(E_REJECTED, __LOCATION__)); } void TChangeDeviceStateActor::HandleChangeDeviceStateResponse( @@ -171,15 +171,17 @@ void TDiskRegistryActor::HandleHttpInfo_ChangeDeviseState( const TCgiParameters& params, TRequestInfoPtr requestInfo) { + if (!Config->GetEnableToChangeStatesFromMonpage()) { + RejectHttpRequest(ctx, *requestInfo, "Can't change state from monpage"); + return; + } const auto& newStateRaw = params.Get("NewState"); const auto& deviceUUID = params.Get("DeviceUUID"); - if (!newStateRaw) { RejectHttpRequest(ctx, *requestInfo, "No new state is given"); return; } - if (!deviceUUID) { RejectHttpRequest(ctx, *requestInfo, "No device id is given"); return; @@ -195,18 +197,32 @@ void TDiskRegistryActor::HandleHttpInfo_ChangeDeviseState( NProto::EDeviceState::DEVICE_STATE_ONLINE, NProto::EDeviceState::DEVICE_STATE_WARNING, }; - if (!NewStateWhiteList.contains(newState)) { RejectHttpRequest(ctx, *requestInfo, "Invalid new state"); return; } + static const auto OldStateWhiteList = [&]() + { + THashSet whitelist = { + NProto::EDeviceState::DEVICE_STATE_ONLINE, + NProto::EDeviceState::DEVICE_STATE_WARNING, + }; + + if (Config->GetEnableToChangeErrorStatesFromMonpage()) { + whitelist.emplace(NProto::EDeviceState::DEVICE_STATE_ERROR); + } + + return whitelist; + }(); + const auto& device = State->GetDevice(deviceUUID); - if (device.GetState() == NProto::DEVICE_STATE_ERROR) { + if (!OldStateWhiteList.contains(device.GetState())) { RejectHttpRequest( ctx, *requestInfo, - "Can't change state of device in ERROR state"); + "Can't change device state from " + + EDeviceState_Name(device.GetState())); return; } diff --git a/cloud/blockstore/libs/storage/disk_registry/disk_registry_actor_monitoring.cpp b/cloud/blockstore/libs/storage/disk_registry/disk_registry_actor_monitoring.cpp index 49bf9330f7..3e59638938 100644 --- a/cloud/blockstore/libs/storage/disk_registry/disk_registry_actor_monitoring.cpp +++ b/cloud/blockstore/libs/storage/disk_registry/disk_registry_actor_monitoring.cpp @@ -512,13 +512,17 @@ void TDiskRegistryActor::RenderDeviceHtmlInfo( } DIV() { out << "State Message: " << device.GetStateMessage(); } - if (device.GetState() != NProto::EDeviceState::DEVICE_STATE_ERROR) { - DIV() + if (Config->GetEnableToChangeStatesFromMonpage()) { + if (device.GetState() != NProto::EDeviceState::DEVICE_STATE_ERROR || + Config->GetEnableToChangeErrorStatesFromMonpage()) { - BuildChangeDeviceStateButton( - out, - TabletID(), - device.GetDeviceUUID()); + DIV() + { + BuildChangeDeviceStateButton( + out, + TabletID(), + device.GetDeviceUUID()); + } } } @@ -593,7 +597,18 @@ void TDiskRegistryActor::RenderAgentHtmlInfo( << TInstant::MicroSeconds(agent->GetStateTs()); } DIV() { - BuildChangeAgentStateButton(out, TabletID(), agent->GetAgentId()); + if (Config->GetEnableToChangeStatesFromMonpage()) { + if (agent->GetState() != + NProto::EAgentState::AGENT_STATE_UNAVAILABLE || + Config->GetEnableToChangeErrorStatesFromMonpage()) + { + BuildChangeAgentStateButton( + out, + TabletID(), + agent->GetAgentId()); + } + } + } DIV() { out << "State Message: " << agent->GetStateMessage(); } DIV() { diff --git a/cloud/blockstore/tests/monitoring/test.py b/cloud/blockstore/tests/monitoring/test.py index f5827408fa..c9dba1b1de 100644 --- a/cloud/blockstore/tests/monitoring/test.py +++ b/cloud/blockstore/tests/monitoring/test.py @@ -436,20 +436,6 @@ def check_change_device_state(self): self.session, self.base_url, self.dr_id, params, "

Invalid new state

") - self.client.change_device_state("FileDevice-1", "2") - - params = { - "action": "changeDeviceState", - "NewState" : "DEVICE_STATE_ONLINE", - "DeviceUUID": "FileDevice-1" - } - - check_tablet_post_redirect( - self.session, self.base_url, - self.dr_id, params, "

Can't change state of device in ERROR state

") - - self.client.change_device_state("FileDevice-1", "0") - params = { "action": "changeDeviceState", "NewState" : "DEVICE_STATE_WARNING", @@ -879,6 +865,9 @@ def __run_test(test_case): storage.NonReplicatedAgentMaxTimeout = 3000 storage.NonReplicatedDiskRecyclingPeriod = 5000 + storage.EnableToChangeStatesFromMonpage = True + storage.EnableToChangeErrorStatesFromMonpage = True + nbs = Nbs( kikimr_port, configurator.domains_txt,