Skip to content

Commit df1c3f9

Browse files
mint570divyagayathri-hcl
authored andcommitted
Add NSF warm restart registration support
1 parent 43771ee commit df1c3f9

File tree

4 files changed

+150
-0
lines changed

4 files changed

+150
-0
lines changed

common/schema.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,7 @@ after libswsscommon deb make.
412412
#define STATE_FDB_TABLE_NAME "FDB_TABLE"
413413
#define STATE_WARM_RESTART_TABLE_NAME "WARM_RESTART_TABLE"
414414
#define STATE_WARM_RESTART_ENABLE_TABLE_NAME "WARM_RESTART_ENABLE_TABLE"
415+
#define STATE_WARM_RESTART_REGISTRATION_TABLE_NAME "WARM_RESTART_REGISTRATION_TABLE"
415416
#define STATE_VRF_TABLE_NAME "VRF_TABLE"
416417
#define STATE_VRF_OBJECT_TABLE_NAME "VRF_OBJECT_TABLE"
417418
#define STATE_MGMT_PORT_TABLE_NAME "MGMT_PORT_TABLE"

common/warm_restart.cpp

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,17 @@
22
#include <climits>
33
#include "logger.h"
44
#include "schema.h"
5+
#include "timestamp.h"
56
#include "warm_restart.h"
67

78
namespace swss {
89

910
const std::string WarmStart::kNsfManagerNotificationChannel =
1011
"NSF_MANAGER_COMMON_NOTIFICATION_CHANNEL";
12+
const std::string WarmStart::kRegistrationFreezeKey = "freeze";
13+
const std::string WarmStart::kRegistrationCheckpointKey = "checkpoint";
14+
const std::string WarmStart::kRegistrationReconciliationKey = "reconciliation";
15+
const std::string WarmStart::kRegistrationTimestampKey = "timestamp";
1116

1217
const WarmStart::WarmStartStateNameMap WarmStart::warmStartStateNameMap =
1318
{
@@ -69,6 +74,9 @@ void WarmStart::initialize(const std::string &app_name,
6974
return;
7075
}
7176

77+
warmStart.m_appName = app_name;
78+
warmStart.m_dockerName = docker_name;
79+
7280
/* Use unix socket for db connection by default */
7381
warmStart.m_stateDb =
7482
std::make_shared<swss::DBConnector>("STATE_DB", db_timeout, isTcpConn);
@@ -85,6 +93,70 @@ void WarmStart::initialize(const std::string &app_name,
8593
warmStart.m_initialized = true;
8694
}
8795

96+
/*
97+
* registerWarmBootInfo
98+
*
99+
* Register an application with NSF Manager.
100+
*
101+
* Returns: true on success, false otherwise.
102+
*
103+
* wait_for_freeze: if true, NSF Manager waits for application to freeze
104+
* and become quiescent before proceeding to state
105+
* verification and checkpointing
106+
* wait_for_checkpoint: if true, NSF Manager waits for application to
107+
* complete checkpointing before reboot
108+
* wait_for_reconciliation: if true, NSF Manager waits for application to
109+
* complete reconciliation before unfreeze
110+
*/
111+
bool WarmStart::registerWarmBootInfo(bool wait_for_freeze,
112+
bool wait_for_checkpoint,
113+
bool wait_for_reconciliation) {
114+
auto& warmStart = getInstance();
115+
116+
if (!warmStart.m_initialized) {
117+
SWSS_LOG_ERROR("registerWarmBootInfo called before initialized");
118+
return false;
119+
}
120+
121+
if (warmStart.m_dockerName.empty()) {
122+
SWSS_LOG_ERROR("registerWarmBootInfo: m_dockerName is empty");
123+
return false;
124+
}
125+
126+
if (warmStart.m_appName.empty()) {
127+
SWSS_LOG_ERROR("registerWarmBootInfo: m_appName is empty");
128+
return false;
129+
}
130+
131+
std::unique_ptr<Table> stateWarmRestartRegistrationTable =
132+
std::unique_ptr<Table>(
133+
new Table(warmStart.m_stateDb.get(),
134+
STATE_WARM_RESTART_REGISTRATION_TABLE_NAME));
135+
136+
std::string separator =
137+
TableBase::getTableSeparator(warmStart.m_stateDb->getDbId());
138+
std::string tableName =
139+
warmStart.m_dockerName + separator + warmStart.m_appName;
140+
141+
std::vector<FieldValueTuple> values;
142+
143+
values.push_back(swss::FieldValueTuple(WarmStart::kRegistrationFreezeKey,
144+
wait_for_freeze ? "true" : "false"));
145+
values.push_back(swss::FieldValueTuple(
146+
WarmStart::kRegistrationCheckpointKey,
147+
wait_for_checkpoint ? "true" : "false"));
148+
values.push_back(swss::FieldValueTuple(
149+
WarmStart::kRegistrationReconciliationKey,
150+
wait_for_reconciliation ? "true" : "false"));
151+
values.push_back(swss::FieldValueTuple(
152+
WarmStart::kRegistrationTimestampKey,
153+
getTimestamp()));
154+
155+
stateWarmRestartRegistrationTable->set(tableName, values);
156+
157+
return true;
158+
}
159+
88160
/*
89161
* <1> Upon system reboot, the system enable knob will be checked.
90162
* If enabled, database data will be preserved, if not, database will be flushed.

common/warm_restart.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ class WarmStart
1414
{
1515
public:
1616
static const std::string kNsfManagerNotificationChannel;
17+
static const std::string kRegistrationFreezeKey;
18+
static const std::string kRegistrationCheckpointKey;
19+
static const std::string kRegistrationReconciliationKey;
20+
static const std::string kRegistrationTimestampKey;
1721

1822
enum WarmStartState
1923
{
@@ -63,6 +67,10 @@ class WarmStart
6367
unsigned int db_timeout = 0,
6468
bool isTcpConn = false);
6569

70+
static bool registerWarmBootInfo(bool wait_for_freeze,
71+
bool wait_for_checkpoint,
72+
bool wait_for_reconciliation);
73+
6674
static bool checkWarmStart(const std::string &app_name,
6775
const std::string &docker_name,
6876
const bool incr_restore_cnt = true);
@@ -95,6 +103,8 @@ class WarmStart
95103
bool m_initialized;
96104
bool m_enabled;
97105
bool m_systemWarmRebootEnabled;
106+
std::string m_appName;
107+
std::string m_dockerName;
98108
};
99109

100110
}

tests/warm_restart_ut.cpp

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@ using namespace swss;
1111
static const string testAppName = "TestApp";
1212
static const string testDockerName = "TestDocker";
1313

14+
// This test must be executed before first successful call to initialize()
15+
// The static elements of this class can only be initialized once.
16+
TEST(WarmRestart, testRegisterWarmBootInfoNotInitialized)
17+
{
18+
bool ret = WarmStart::registerWarmBootInfo(true,false,false);
19+
EXPECT_FALSE(ret);
20+
}
21+
1422
TEST(WarmRestart, checkWarmStart_and_State)
1523
{
1624
DBConnector stateDb("STATE_DB", 0, true);
@@ -252,3 +260,62 @@ TEST(WarmRestart, testNotificationMaps)
252260
EXPECT_EQ(notification, currNotification);
253261
}
254262
}
263+
264+
TEST(WarmRestart, testRegisterWarmBootInfo)
265+
{
266+
DBConnector stateDb("STATE_DB", 0, true);
267+
Table stateWarmRestartRegTable(&stateDb,
268+
STATE_WARM_RESTART_REGISTRATION_TABLE_NAME);
269+
270+
std::string tableName = testDockerName + "|" + testAppName;
271+
272+
//Clean up warm restart state for testAppName
273+
stateWarmRestartRegTable.del(tableName);
274+
275+
//Initialize WarmStart class for TestApp
276+
WarmStart::initialize(testAppName, testDockerName, 0, true);
277+
278+
bool ret = WarmStart::registerWarmBootInfo(true,false,false);
279+
EXPECT_TRUE(ret);
280+
281+
std::string value;
282+
ret = stateWarmRestartRegTable.hget(tableName,
283+
WarmStart::kRegistrationFreezeKey, value);
284+
EXPECT_TRUE(ret);
285+
EXPECT_EQ(value, "true");
286+
287+
ret = stateWarmRestartRegTable.hget(
288+
tableName, WarmStart::kRegistrationCheckpointKey, value);
289+
EXPECT_TRUE(ret);
290+
EXPECT_EQ(value, "false");
291+
292+
ret = stateWarmRestartRegTable.hget(
293+
tableName, WarmStart::kRegistrationReconciliationKey, value);
294+
EXPECT_TRUE(ret);
295+
EXPECT_EQ(value, "false");
296+
297+
ret = stateWarmRestartRegTable.hget(
298+
tableName, WarmStart::kRegistrationTimestampKey, value);
299+
EXPECT_TRUE(ret);
300+
301+
ret = WarmStart::registerWarmBootInfo(false,true,false);
302+
EXPECT_TRUE(ret);
303+
304+
ret = stateWarmRestartRegTable.hget(tableName,
305+
WarmStart::kRegistrationFreezeKey, value);
306+
EXPECT_TRUE(ret);
307+
EXPECT_EQ(value, "false");
308+
309+
ret = stateWarmRestartRegTable.hget(
310+
tableName, WarmStart::kRegistrationCheckpointKey, value);
311+
EXPECT_TRUE(ret);
312+
EXPECT_EQ(value, "true");
313+
314+
ret = WarmStart::registerWarmBootInfo(false,false,true);
315+
EXPECT_TRUE(ret);
316+
317+
ret = stateWarmRestartRegTable.hget(
318+
tableName, WarmStart::kRegistrationReconciliationKey, value);
319+
EXPECT_TRUE(ret);
320+
EXPECT_EQ(value, "true");
321+
}

0 commit comments

Comments
 (0)