Skip to content

Commit 088a1ce

Browse files
authored
Add cluster & database restore to YDB CLI (#14481)
1 parent 54f9570 commit 088a1ce

File tree

17 files changed

+807
-109
lines changed

17 files changed

+807
-109
lines changed

ydb/apps/ydb/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
* Added `ydb workload log import generator` command.
66
* Queries in `ydb workload run` command are now executed in random order.
77
* Include topics in local backups (`ydb tools dump` and `ydb tools restore`). In this release, only the settings of the topics are retained; messages are not included in the backup.
8+
* Added `ydb admin cluster dump` and `ydb admin cluster restore` commands for dumping all cluster-level data
9+
* Added `ydb admin database dump` and `ydb admin database restore` commands for dumping all database-level data
810

911
## 2.19.0 ##
1012

ydb/public/lib/ydb_cli/commands/ydb_admin.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class TCommandDatabase : public TClientCommandTree {
3030
{
3131
AddCommand(std::make_unique<NDynamicConfig::TCommandConfig>());
3232
AddCommand(std::make_unique<TCommandDatabaseDump>());
33+
AddCommand(std::make_unique<TCommandDatabaseRestore>());
3334
}
3435
};
3536

@@ -62,6 +63,47 @@ int TCommandDatabaseDump::Run(TConfig& config) {
6263
return EXIT_SUCCESS;
6364
}
6465

66+
TCommandDatabaseRestore::TCommandDatabaseRestore()
67+
: TYdbCommand("restore", {}, "Restore database from local dump")
68+
{}
69+
70+
void TCommandDatabaseRestore::Config(TConfig& config) {
71+
TYdbCommand::Config(config);
72+
config.SetFreeArgsNum(0);
73+
config.AllowEmptyDatabase = true; // it is possible to retrieve database path from dump
74+
75+
config.Opts->AddLongOption('i', "input", "Path in a local filesystem to a directory with dump.")
76+
.RequiredArgument("PATH")
77+
.StoreResult(&FilePath);
78+
79+
config.Opts->AddLongOption('w', "wait-nodes-duration", "Wait for available database nodes for specified duration. Example: 10s, 5m, 1h.")
80+
.DefaultValue(TDuration::Minutes(1))
81+
.RequiredArgument("DURATION")
82+
.StoreResult(&WaitNodesDuration);
83+
}
84+
85+
void TCommandDatabaseRestore::Parse(TConfig& config) {
86+
TClientCommand::Parse(config);
87+
}
88+
89+
int TCommandDatabaseRestore::Run(TConfig& config) {
90+
auto log = std::make_shared<TLog>(CreateLogBackend("cerr", TConfig::VerbosityLevelToELogPriority(config.VerbosityLevel)));
91+
log->SetFormatter(GetPrefixLogFormatter(""));
92+
93+
auto settings = NDump::TRestoreDatabaseSettings()
94+
.WaitNodesDuration(WaitNodesDuration);
95+
96+
if (!config.Database.empty()) {
97+
settings.Database(config.Database);
98+
config.Database.clear(); // always connect directly to cluster
99+
}
100+
101+
NDump::TClient client(CreateDriver(config), std::move(log));
102+
NStatusHelpers::ThrowOnErrorOrPrintIssues(client.RestoreDatabase(FilePath, settings));
103+
104+
return EXIT_SUCCESS;
105+
}
106+
65107
TCommandAdmin::TCommandAdmin()
66108
: TClientCommandTree("admin", {}, "Administrative cluster operations")
67109
{

ydb/public/lib/ydb_cli/commands/ydb_admin.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,17 @@ class TCommandDatabaseDump : public TYdbCommand {
2323
TString FilePath;
2424
};
2525

26+
class TCommandDatabaseRestore : public TYdbCommand {
27+
public:
28+
TCommandDatabaseRestore();
29+
void Config(TConfig& config) override;
30+
void Parse(TConfig& config) override;
31+
int Run(TConfig& config) override;
32+
33+
private:
34+
TString FilePath;
35+
TDuration WaitNodesDuration;
36+
};
37+
2638
}
2739
}

ydb/public/lib/ydb_cli/commands/ydb_cluster.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ TCommandCluster::TCommandCluster()
1919
AddCommand(std::make_unique<TCommandClusterBootstrap>());
2020
AddCommand(std::make_unique<NDynamicConfig::TCommandConfig>(true));
2121
AddCommand(std::make_unique<TCommandClusterDump>());
22+
AddCommand(std::make_unique<TCommandClusterRestore>());
2223
}
2324

2425
TCommandClusterBootstrap::TCommandClusterBootstrap()
@@ -74,4 +75,40 @@ int TCommandClusterDump::Run(TConfig& config) {
7475
return EXIT_SUCCESS;
7576
}
7677

78+
TCommandClusterRestore::TCommandClusterRestore()
79+
: TYdbCommand("restore", {}, "Restore cluster from local dump")
80+
{}
81+
82+
void TCommandClusterRestore::Config(TConfig& config) {
83+
TYdbCommand::Config(config);
84+
config.SetFreeArgsNum(0);
85+
config.AllowEmptyDatabase = true;
86+
87+
config.Opts->AddLongOption('i', "input", "Path in a local filesystem to a directory with dump.")
88+
.RequiredArgument("PATH")
89+
.StoreResult(&FilePath);
90+
91+
config.Opts->AddLongOption('w', "wait-nodes-duration", "Wait for available database nodes for specified duration. Example: 10s, 5m, 1h.")
92+
.DefaultValue(TDuration::Minutes(1))
93+
.RequiredArgument("DURATION")
94+
.StoreResult(&WaitNodesDuration);
95+
}
96+
97+
void TCommandClusterRestore::Parse(TConfig& config) {
98+
TClientCommand::Parse(config);
99+
}
100+
101+
int TCommandClusterRestore::Run(TConfig& config) {
102+
auto log = std::make_shared<TLog>(CreateLogBackend("cerr", TConfig::VerbosityLevelToELogPriority(config.VerbosityLevel)));
103+
log->SetFormatter(GetPrefixLogFormatter(""));
104+
105+
auto settings = NDump::TRestoreClusterSettings()
106+
.WaitNodesDuration(WaitNodesDuration);
107+
108+
NDump::TClient client(CreateDriver(config), std::move(log));
109+
NStatusHelpers::ThrowOnErrorOrPrintIssues(client.RestoreCluster(FilePath, settings));
110+
111+
return EXIT_SUCCESS;
112+
}
113+
77114
} // namespace NYdb::NConsoleClient::NCluster

ydb/public/lib/ydb_cli/commands/ydb_cluster.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,16 @@ class TCommandClusterDump : public TYdbCommand {
3333
TString FilePath;
3434
};
3535

36+
class TCommandClusterRestore : public TYdbCommand {
37+
public:
38+
TCommandClusterRestore();
39+
void Config(TConfig& config) override;
40+
void Parse(TConfig& config) override;
41+
int Run(TConfig& config) override;
42+
43+
private:
44+
TString FilePath;
45+
TDuration WaitNodesDuration;
46+
};
47+
3648
} // namespace NYdb::NConsoleClient::NCluster

ydb/public/lib/ydb_cli/dump/dump.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,21 @@ class TClient::TImpl {
3737
return client.DumpCluster(fsPath);
3838
}
3939

40+
TRestoreResult RestoreCluster(const TString& fsPath, const TRestoreClusterSettings& settings) {
41+
auto client = TRestoreClient(Driver, Log);
42+
return client.RestoreCluster(fsPath, settings);
43+
}
44+
4045
TDumpResult DumpDatabase(const TString& database, const TString& fsPath) {
4146
auto client = TDumpClient(Driver, Log);
4247
return client.DumpDatabase(database, fsPath);
4348
}
4449

50+
TRestoreResult RestoreDatabase(const TString& fsPath, const TRestoreDatabaseSettings& settings) {
51+
auto client = TRestoreClient(Driver, Log);
52+
return client.RestoreDatabase(fsPath, settings);
53+
}
54+
4555
private:
4656
const TDriver Driver;
4757
std::shared_ptr<TLog> Log;
@@ -80,8 +90,16 @@ TDumpResult TClient::DumpCluster(const TString& fsPath) {
8090
return Impl_->DumpCluster(fsPath);
8191
}
8292

93+
TRestoreResult TClient::RestoreCluster(const TString& fsPath, const TRestoreClusterSettings& settings) {
94+
return Impl_->RestoreCluster(fsPath, settings);
95+
}
96+
8397
TDumpResult TClient::DumpDatabase(const TString& database, const TString& fsPath) {
8498
return Impl_->DumpDatabase(database, fsPath);
8599
}
86100

101+
TRestoreResult TClient::RestoreDatabase(const TString& fsPath, const TRestoreDatabaseSettings& settings) {
102+
return Impl_->RestoreDatabase(fsPath, settings);
103+
}
104+
87105
} // NYdb::NDump

ydb/public/lib/ydb_cli/dump/dump.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,20 @@ struct TRestoreSettings: public TOperationRequestSettings<TRestoreSettings> {
112112

113113
}; // TRestoreSettings
114114

115+
struct TRestoreClusterSettings {
116+
using TSelf = TRestoreClusterSettings;
117+
118+
FLUENT_SETTING_DEFAULT(TDuration, WaitNodesDuration, TDuration::Minutes(1));
119+
}; // TRestoreClusterSettings
120+
121+
struct TRestoreDatabaseSettings {
122+
using TSelf = TRestoreDatabaseSettings;
123+
124+
FLUENT_SETTING_DEFAULT(TDuration, WaitNodesDuration, TDuration::Minutes(1));
125+
FLUENT_SETTING_OPTIONAL(TString, Database);
126+
FLUENT_SETTING_DEFAULT(bool, WithContent, true);
127+
}; // TRestoreDatabaseSettings
128+
115129
class TRestoreResult: public TStatus {
116130
public:
117131
TRestoreResult(TStatus&& status);
@@ -131,9 +145,11 @@ class TClient {
131145
TRestoreResult Restore(const TString& fsPath, const TString& dbPath, const TRestoreSettings& settings = {});
132146

133147
TDumpResult DumpCluster(const TString& fsPath);
148+
TRestoreResult RestoreCluster(const TString& fsPath, const TRestoreClusterSettings& settings = {});
134149

135150
TDumpResult DumpDatabase(const TString& database, const TString& fsPath);
136-
151+
TRestoreResult RestoreDatabase(const TString& fsPath, const TRestoreDatabaseSettings& settings = {});
152+
137153
private:
138154
std::shared_ptr<TImpl> Impl_;
139155

0 commit comments

Comments
 (0)