@@ -665,11 +665,19 @@ namespace NKikimr::NStorage {
665
665
? std::make_optional (request.GetSwitchDedicatedStorageSection ())
666
666
: std::nullopt;
667
667
668
- const TString *storageYamlPtr = newStorageYaml ? &newStorageYaml.value () :
669
- Self->StorageConfigYaml ? &Self->StorageConfigYaml .value () : nullptr ;
670
-
671
668
const bool targetDedicatedStorageSection = switchDedicatedStorageSection.value_or (Self->StorageConfigYaml .has_value ());
672
669
670
+ if (switchDedicatedStorageSection) {
671
+ // check that configs are explicitly defined when we are switching dual-config mode
672
+ if (!NewYaml) {
673
+ return FinishWithError (TResult::ERROR, " main config must be specified when switching dedicated"
674
+ " storage section mode" );
675
+ } else if (*switchDedicatedStorageSection && !newStorageYaml) {
676
+ return FinishWithError (TResult::ERROR, " storage config must be specified when turning on dedicated"
677
+ " storage section mode" );
678
+ }
679
+ }
680
+
673
681
if (request.GetDedicatedStorageSectionConfigMode () != targetDedicatedStorageSection) {
674
682
return FinishWithError (TResult::ERROR, " DedicatedStorageSectionConfigMode does not match target state" );
675
683
} else if (newStorageYaml && !targetDedicatedStorageSection) {
@@ -678,89 +686,109 @@ namespace NKikimr::NStorage {
678
686
} else if (switchDedicatedStorageSection && *switchDedicatedStorageSection == Self->StorageConfigYaml .has_value ()) {
679
687
// this enable/disable command does not change the state
680
688
return FinishWithError (TResult::ERROR, " dedicated storage config section is already in requested state" );
681
- } else if (targetDedicatedStorageSection && !storageYamlPtr) {
682
- // we are going to turn on dual-config mode, but no storage config provided
683
- return FinishWithError (TResult::ERROR, " no dedicated storage config section provided" );
684
689
}
685
690
686
- const TString *mainYamlPtr = NewYaml ? &NewYaml.value () : &Self->MainConfigYaml ;
687
-
688
- std::optional<ui64> newYamlVersion;
689
- std::optional<ui64> newStorageYamlVersion;
691
+ TString state;
692
+ NKikimrBlobStorage::TStorageConfig config (*Self->StorageConfig );
693
+ std::optional<ui64> newExpectedStorageYamlVersion;
690
694
691
- NKikimrConfig::TAppConfig appConfig;
692
- const char *state = " " ;
695
+ if (config.HasExpectedStorageYamlVersion ()) {
696
+ newExpectedStorageYamlVersion.emplace (config.GetExpectedStorageYamlVersion ());
697
+ }
693
698
694
699
try {
695
- if (storageYamlPtr) { // parse the storage yaml first
696
- state = " loading storage YAML" ;
697
- auto json = NYaml::Yaml2Json (YAML::Load (*storageYamlPtr), true );
698
- state = " parsing storage YAML" ;
699
- NYaml::Parse (json, NYaml::GetJsonToProtoConfig (), appConfig, true );
700
- state = " extracting storage YAML metadata" ;
701
- if (json.Has (" metadata" )) {
702
- if (auto & metadata = json[" metadata" ]; metadata.Has (" version" )) {
703
- newStorageYamlVersion = metadata[" version" ].GetUIntegerRobust ();
704
- }
700
+ auto load = [&](const TString& yaml, ui64& version, const char *expectedKind) {
701
+ state = TStringBuilder () << " loading " << expectedKind << " YAML" ;
702
+ NJson::TJsonValue json = NYaml::Yaml2Json (YAML::Load (yaml), true );
703
+
704
+ state = TStringBuilder () << " extracting " << expectedKind << " metadata" ;
705
+ if (!json.Has (" metadata" ) || !json[" metadata" ].IsMap ()) {
706
+ throw yexception () << " no metadata section" ;
705
707
}
708
+ auto & metadata = json[" metadata" ];
709
+ NYaml::ValidateMetadata (metadata);
710
+ if (!metadata.Has (" kind" ) || metadata[" kind" ] != expectedKind) {
711
+ throw yexception () << " missing or invalid kind provided" ;
712
+ }
713
+ version = metadata[" version" ].GetUIntegerRobust ();
714
+
715
+ state = TStringBuilder () << " validating " << expectedKind << " config section" ;
716
+ if (!json.Has (" config" ) || !json[" config" ].IsMap ()) {
717
+ throw yexception () << " missing config section" ;
718
+ }
719
+
720
+ return json;
721
+ };
722
+
723
+ NJson::TJsonValue main;
724
+ NJson::TJsonValue storage;
725
+ const NJson::TJsonValue *effective = nullptr ;
726
+
727
+ if (newStorageYaml) {
728
+ ui64 version = 0 ;
729
+ storage = load (*newStorageYaml, version, " StorageConfig" );
730
+ if (const ui64 expected = Self->StorageConfig ->GetExpectedStorageYamlVersion (); version != expected) {
731
+ return FinishWithError (TResult::ERROR, TStringBuilder ()
732
+ << " storage config version must be increasing by one"
733
+ << " new version# " << version
734
+ << " expected version# " << expected);
735
+ }
736
+
737
+ newExpectedStorageYamlVersion = version + 1 ;
738
+ effective = &storage;
706
739
}
707
740
708
- state = " loading main YAML" ;
709
- auto json = NYaml::Yaml2Json (YAML::Load (*mainYamlPtr), true );
710
- state = " parsing main YAML" ;
711
- NYaml::Parse (json, NYaml::GetJsonToProtoConfig (), appConfig, true );
712
- state = " extracting main YAML metadata" ;
713
- if (json.Has (" metadata" )) {
714
- if (auto & metadata = json[" metadata" ]; metadata.Has (" version" )) {
715
- newYamlVersion = metadata[" version" ].GetUIntegerRobust ();
741
+ if (NewYaml) {
742
+ ui64 version = 0 ;
743
+ main = load (*NewYaml, version, " MainConfig" );
744
+ if (const ui64 expected = *Self->MainConfigYamlVersion + 1 ; version != expected) {
745
+ return FinishWithError (TResult::ERROR, TStringBuilder ()
746
+ << " main config version must be increasing by one"
747
+ << " new version# " << version
748
+ << " expected version# " << expected);
749
+ }
750
+
751
+ if (!effective && !Self->StorageConfigYaml ) {
752
+ effective = &main;
716
753
}
717
754
}
718
- } catch (const std::exception& ex) {
719
- return FinishWithError (TResult::ERROR, TStringBuilder () << " exception while " << state
720
- << " : " << ex.what ());
721
- }
722
755
723
- if (newYamlVersion && *newYamlVersion != *Self->MainConfigYamlVersion + 1 ) {
724
- return FinishWithError (TResult::ERROR, TStringBuilder () << " version must be increasing by one"
725
- << " new version# " << *newYamlVersion << " expected version# " << *Self->MainConfigYamlVersion + 1 );
726
- } else if (newStorageYamlVersion && *newStorageYamlVersion != Self->StorageConfig ->GetExpectedStorageYamlVersion ()) {
727
- return FinishWithError (TResult::ERROR, TStringBuilder () << " version must be increasing by one"
728
- << " new version# " << *newStorageYamlVersion
729
- << " expected version# " << Self->StorageConfig ->GetExpectedStorageYamlVersion ());
730
- }
756
+ if (effective) {
757
+ state = " parsing final config" ;
731
758
732
- TString errorReason;
733
- NKikimrBlobStorage::TStorageConfig config (*Self->StorageConfig );
734
- const bool success = DeriveStorageConfig (appConfig, &config, &errorReason);
735
- if (!success) {
736
- return FinishWithError (TResult::ERROR, TStringBuilder () << " error while deriving StorageConfig: "
737
- << errorReason);
759
+ NKikimrConfig::TAppConfig appConfig;
760
+ NYaml::Parse (*effective, NYaml::GetJsonToProtoConfig (), appConfig, true );
761
+
762
+ if (TString errorReason; !DeriveStorageConfig (appConfig, &config, &errorReason)) {
763
+ return FinishWithError (TResult::ERROR, TStringBuilder ()
764
+ << " error while deriving StorageConfig: " << errorReason);
765
+ }
766
+ }
767
+ } catch (const std::exception& ex) {
768
+ return FinishWithError (TResult::ERROR, TStringBuilder () << " exception while " << state
769
+ << " : " << ex.what ());
738
770
}
739
771
740
772
if (NewYaml) {
741
773
if (const auto & error = UpdateConfigComposite (config, *NewYaml, std::nullopt)) {
742
774
return FinishWithError (TResult::ERROR, TStringBuilder () << " failed to update config yaml: " << *error);
743
775
}
744
- } else {
745
- config.SetConfigComposite (Self->StorageConfig ->GetConfigComposite ());
776
+ }
777
+
778
+ if (newExpectedStorageYamlVersion) {
779
+ config.SetExpectedStorageYamlVersion (*newExpectedStorageYamlVersion);
746
780
}
747
781
748
782
if (newStorageYaml) {
749
783
// make new compressed storage yaml section
750
784
TString s;
751
785
if (TStringOutput output (s); true ) {
752
786
TZstdCompress zstd (&output);
753
- ::Save (&zstd, *newStorageYaml);
754
- ::Save (&zstd, *newStorageYamlVersion);
787
+ zstd << *newStorageYaml;
755
788
}
756
789
config.SetCompressedStorageYaml (s);
757
- config.SetExpectedStorageYamlVersion (*newStorageYamlVersion + 1 );
758
- } else if (switchDedicatedStorageSection && !*switchDedicatedStorageSection) {
759
- // delete compressed storage yaml section as this request turns off dedicated storage yaml
760
- } else if (Self->StorageConfig ->HasCompressedStorageYaml ()) {
761
- // retain current storage yaml
762
- config.SetCompressedStorageYaml (Self->StorageConfig ->GetCompressedStorageYaml ());
763
- config.SetExpectedStorageYamlVersion (Self->StorageConfig ->GetExpectedStorageYamlVersion ());
790
+ } else if (!targetDedicatedStorageSection) {
791
+ config.ClearCompressedStorageYaml ();
764
792
}
765
793
766
794
// advance the config generation
@@ -774,9 +802,7 @@ namespace NKikimr::NStorage {
774
802
<< " ReplaceStorageConfig config validation failed: " << *error);
775
803
}
776
804
777
- const bool pushToConsole = true ;
778
-
779
- if (!pushToConsole || !request.GetSkipConsoleValidation ()) {
805
+ if (request.GetSkipConsoleValidation () || !NewYaml) {
780
806
return StartProposition (&config);
781
807
}
782
808
@@ -785,7 +811,7 @@ namespace NKikimr::NStorage {
785
811
!Self->SelfManagementEnabled &&
786
812
config.GetSelfManagementConfig ().GetEnabled ();
787
813
788
- if (NewYaml && !Self->EnqueueConsoleConfigValidation (SelfId (), enablingDistconf, *NewYaml)) {
814
+ if (!Self->EnqueueConsoleConfigValidation (SelfId (), enablingDistconf, *NewYaml)) {
789
815
FinishWithError (TResult::ERROR, " console pipe is not available" );
790
816
} else {
791
817
ProposedStorageConfig = std::move (config);
0 commit comments