Skip to content

Commit a1991d1

Browse files
mint570divyagayathri-hcl
authored andcommitted
Add NSF warm restart registration support
1 parent ab6a562 commit a1991d1

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
{
@@ -81,6 +86,9 @@ void WarmStart::initialize(const std::string &app_name,
8186
return;
8287
}
8388

89+
warmStart.m_appName = app_name;
90+
warmStart.m_dockerName = docker_name;
91+
8492
/* Use unix socket for db connection by default */
8593
warmStart.m_stateDb =
8694
std::make_shared<swss::DBConnector>("STATE_DB", db_timeout, isTcpConn);
@@ -97,6 +105,70 @@ void WarmStart::initialize(const std::string &app_name,
97105
warmStart.m_initialized = true;
98106
}
99107

108+
/*
109+
* registerWarmBootInfo
110+
*
111+
* Register an application with NSF Manager.
112+
*
113+
* Returns: true on success, false otherwise.
114+
*
115+
* wait_for_freeze: if true, NSF Manager waits for application to freeze
116+
* and become quiescent before proceeding to state
117+
* verification and checkpointing
118+
* wait_for_checkpoint: if true, NSF Manager waits for application to
119+
* complete checkpointing before reboot
120+
* wait_for_reconciliation: if true, NSF Manager waits for application to
121+
* complete reconciliation before unfreeze
122+
*/
123+
bool WarmStart::registerWarmBootInfo(bool wait_for_freeze,
124+
bool wait_for_checkpoint,
125+
bool wait_for_reconciliation) {
126+
auto& warmStart = getInstance();
127+
128+
if (!warmStart.m_initialized) {
129+
SWSS_LOG_ERROR("registerWarmBootInfo called before initialized");
130+
return false;
131+
}
132+
133+
if (warmStart.m_dockerName.empty()) {
134+
SWSS_LOG_ERROR("registerWarmBootInfo: m_dockerName is empty");
135+
return false;
136+
}
137+
138+
if (warmStart.m_appName.empty()) {
139+
SWSS_LOG_ERROR("registerWarmBootInfo: m_appName is empty");
140+
return false;
141+
}
142+
143+
std::unique_ptr<Table> stateWarmRestartRegistrationTable =
144+
std::unique_ptr<Table>(
145+
new Table(warmStart.m_stateDb.get(),
146+
STATE_WARM_RESTART_REGISTRATION_TABLE_NAME));
147+
148+
std::string separator =
149+
TableBase::getTableSeparator(warmStart.m_stateDb->getDbId());
150+
std::string tableName =
151+
warmStart.m_dockerName + separator + warmStart.m_appName;
152+
153+
std::vector<FieldValueTuple> values;
154+
155+
values.push_back(swss::FieldValueTuple(WarmStart::kRegistrationFreezeKey,
156+
wait_for_freeze ? "true" : "false"));
157+
values.push_back(swss::FieldValueTuple(
158+
WarmStart::kRegistrationCheckpointKey,
159+
wait_for_checkpoint ? "true" : "false"));
160+
values.push_back(swss::FieldValueTuple(
161+
WarmStart::kRegistrationReconciliationKey,
162+
wait_for_reconciliation ? "true" : "false"));
163+
values.push_back(swss::FieldValueTuple(
164+
WarmStart::kRegistrationTimestampKey,
165+
getTimestamp()));
166+
167+
stateWarmRestartRegistrationTable->set(tableName, values);
168+
169+
return true;
170+
}
171+
100172
/*
101173
* <1> Upon system reboot, the system enable knob will be checked.
102174
* 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
{
@@ -67,6 +71,10 @@ class WarmStart
6771
unsigned int db_timeout = 0,
6872
bool isTcpConn = false);
6973

74+
static bool registerWarmBootInfo(bool wait_for_freeze,
75+
bool wait_for_checkpoint,
76+
bool wait_for_reconciliation);
77+
7078
static bool checkWarmStart(const std::string &app_name,
7179
const std::string &docker_name,
7280
const bool incr_restore_cnt = true);
@@ -99,6 +107,8 @@ class WarmStart
99107
bool m_initialized;
100108
bool m_enabled;
101109
bool m_systemWarmRebootEnabled;
110+
std::string m_appName;
111+
std::string m_dockerName;
102112
};
103113

104114
}

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);
@@ -295,3 +303,62 @@ TEST(WarmRestart, testNotificationMaps)
295303
EXPECT_EQ(notification, currNotification);
296304
}
297305
}
306+
307+
TEST(WarmRestart, testRegisterWarmBootInfo)
308+
{
309+
DBConnector stateDb("STATE_DB", 0, true);
310+
Table stateWarmRestartRegTable(&stateDb,
311+
STATE_WARM_RESTART_REGISTRATION_TABLE_NAME);
312+
313+
std::string tableName = testDockerName + "|" + testAppName;
314+
315+
//Clean up warm restart state for testAppName
316+
stateWarmRestartRegTable.del(tableName);
317+
318+
//Initialize WarmStart class for TestApp
319+
WarmStart::initialize(testAppName, testDockerName, 0, true);
320+
321+
bool ret = WarmStart::registerWarmBootInfo(true,false,false);
322+
EXPECT_TRUE(ret);
323+
324+
std::string value;
325+
ret = stateWarmRestartRegTable.hget(tableName,
326+
WarmStart::kRegistrationFreezeKey, value);
327+
EXPECT_TRUE(ret);
328+
EXPECT_EQ(value, "true");
329+
330+
ret = stateWarmRestartRegTable.hget(
331+
tableName, WarmStart::kRegistrationCheckpointKey, value);
332+
EXPECT_TRUE(ret);
333+
EXPECT_EQ(value, "false");
334+
335+
ret = stateWarmRestartRegTable.hget(
336+
tableName, WarmStart::kRegistrationReconciliationKey, value);
337+
EXPECT_TRUE(ret);
338+
EXPECT_EQ(value, "false");
339+
340+
ret = stateWarmRestartRegTable.hget(
341+
tableName, WarmStart::kRegistrationTimestampKey, value);
342+
EXPECT_TRUE(ret);
343+
344+
ret = WarmStart::registerWarmBootInfo(false,true,false);
345+
EXPECT_TRUE(ret);
346+
347+
ret = stateWarmRestartRegTable.hget(tableName,
348+
WarmStart::kRegistrationFreezeKey, value);
349+
EXPECT_TRUE(ret);
350+
EXPECT_EQ(value, "false");
351+
352+
ret = stateWarmRestartRegTable.hget(
353+
tableName, WarmStart::kRegistrationCheckpointKey, value);
354+
EXPECT_TRUE(ret);
355+
EXPECT_EQ(value, "true");
356+
357+
ret = WarmStart::registerWarmBootInfo(false,false,true);
358+
EXPECT_TRUE(ret);
359+
360+
ret = stateWarmRestartRegTable.hget(
361+
tableName, WarmStart::kRegistrationReconciliationKey, value);
362+
EXPECT_TRUE(ret);
363+
EXPECT_EQ(value, "true");
364+
}

0 commit comments

Comments
 (0)