Skip to content

Commit ee6d0b9

Browse files
mint570divyagayathri-hcl
authored andcommitted
Upstream SONiC getWarmStartState() API and Create returnWarmStartState as a wrapper.
1 parent e0c3dad commit ee6d0b9

File tree

3 files changed

+174
-2
lines changed

3 files changed

+174
-2
lines changed

common/warm_restart.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,18 @@ WarmStart &WarmStart::getInstance(void)
5959
return m_warmStart;
6060
}
6161

62+
void WarmStart::updateStateOnColdBoot(const std::string& app_name)
63+
{
64+
/* Default state for cold boot is:
65+
* a) COMPLETED when state verification is enabled. This is because
66+
* enabling state verification results in unfreeze notification.
67+
* b) RECONCILED when state verification is disabled. This is the
68+
* default behavior.
69+
*/
70+
const auto state = isStateVerificationEnabled() ? COMPLETED : RECONCILED;
71+
setWarmStartState(app_name, state);
72+
}
73+
6274
/*
6375
* WarmStart's initialization method -- to be invoked once per application.
6476
*/
@@ -221,6 +233,10 @@ bool WarmStart::checkWarmStart(const std::string &app_name,
221233
warmStart.m_enabled = false;
222234
warmStart.m_systemWarmRebootEnabled = false;
223235
warmStart.m_stateWarmRestartTable->hset(app_name, "restore_count", "0");
236+
if (app_name == warmStart.m_appName)
237+
{
238+
updateStateOnColdBoot(app_name);
239+
}
224240
return false;
225241
}
226242

@@ -329,6 +345,15 @@ void WarmStart::getWarmStartState(const std::string &app_name, WarmStartState &s
329345
return;
330346
}
331347

348+
// Wrap getWarmStartState to return state vs passing a state variable by
349+
// reference. SWIG (for python) does not handle passing enum by reference
350+
// cleanly.
351+
WarmStart::WarmStartState WarmStart::returnWarmStartState(const std::string &app_name)
352+
{
353+
WarmStartState state;
354+
getWarmStartState(app_name, state);
355+
return state;
356+
}
332357
// Set the WarmStart FSM state for a particular application.
333358
void WarmStart::setWarmStartState(const std::string &app_name, WarmStartState state)
334359
{
@@ -404,4 +429,24 @@ WarmStart::DataCheckState WarmStart::getDataCheckState(const std::string &app_na
404429
return state;
405430
}
406431

432+
bool WarmStart::isStateVerificationEnabled()
433+
{
434+
auto& warmStart = getInstance();
435+
436+
std::string value;
437+
warmStart.m_stateWarmRestartEnableTable->hget("system",
438+
"state_verification", value);
439+
if (value == "true")
440+
{
441+
return true;
442+
}
443+
return false;
444+
}
445+
446+
bool WarmStart::waitForUnfreeze()
447+
{
448+
// Wait for unfreeze notification only if state verification is enabled.
449+
return isStateVerificationEnabled();
450+
}
451+
407452
} // namespace swss

common/warm_restart.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ class WarmStart
6262

6363
static WarmStart &getInstance(void);
6464

65+
static void updateStateOnColdBoot(const std::string& app_name);
66+
6567
static void initialize(const std::string &app_name,
6668
const std::string &docker_name,
6769
unsigned int db_timeout = 0,
@@ -82,6 +84,10 @@ class WarmStart
8284
static void getWarmStartState(const std::string &app_name,
8385
WarmStartState &state);
8486

87+
// For python via SWIG: return state instead of passing state
88+
// variable by reference as a parameter.
89+
static WarmStartState returnWarmStartState(const std::string &app_name);
90+
8591
static void setWarmStartState(const std::string &app_name,
8692
WarmStartState state);
8793

@@ -94,6 +100,8 @@ class WarmStart
94100

95101
static DataCheckState getDataCheckState(const std::string &app_name,
96102
DataCheckStage stage);
103+
static bool isStateVerificationEnabled();
104+
static bool waitForUnfreeze();
97105
private:
98106
std::shared_ptr<swss::DBConnector> m_stateDb;
99107
std::shared_ptr<swss::DBConnector> m_cfgDb;

tests/warm_restart_ut.cpp

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

14+
void verifyWarmbootState(std::string app,
15+
WarmStart::WarmStartState expected_state)
16+
{
17+
WarmStart::WarmStartState state;
18+
WarmStart::getWarmStartState(app, state);
19+
EXPECT_EQ(state, expected_state);
20+
21+
DBConnector stateDb("STATE_DB", 0, true);
22+
Table stateWarmRestartTable(&stateDb, STATE_WARM_RESTART_TABLE_NAME);
23+
std::string state_str;
24+
stateWarmRestartTable.hget(app, "state", state_str);
25+
EXPECT_EQ(state_str, WarmStart::warmStartStateNameMap()->at(state).c_str());
26+
}
27+
28+
void configureStateVerification(std::string value)
29+
{
30+
DBConnector stateDb("STATE_DB", 0, true);
31+
Table stateWarmRestartEnableTable(&stateDb,
32+
STATE_WARM_RESTART_ENABLE_TABLE_NAME);
33+
stateWarmRestartEnableTable.hset("system", "state_verification", value);
34+
}
35+
1436
// This test must be executed before first successful call to initialize()
1537
// The static elements of this class can only be initialized once.
1638
TEST(WarmRestart, testRegisterWarmBootInfoNotInitialized)
@@ -144,8 +166,6 @@ TEST(WarmRestart, checkWarmStart_and_State)
144166
EXPECT_FALSE(system_enabled);
145167
}
146168

147-
148-
149169
TEST(WarmRestart, getWarmStartTimer)
150170
{
151171
DBConnector configDb("CONFIG_DB", 0, true);
@@ -168,6 +188,42 @@ TEST(WarmRestart, getWarmStartTimer)
168188
EXPECT_EQ(timer, 5000u);
169189
}
170190

191+
TEST(WarmRestart, returnWarmStartState)
192+
{
193+
DBConnector stateDb("STATE_DB", 0, true);
194+
Table stateWarmRestartTable(&stateDb, STATE_WARM_RESTART_TABLE_NAME);
195+
//
196+
//Initialize WarmStart class for TestApp
197+
WarmStart::initialize(testAppName, testDockerName, 0, true);
198+
199+
WarmStart::WarmStartState warmStartStates[] =
200+
{
201+
WarmStart::INITIALIZED,
202+
WarmStart::RESTORED,
203+
WarmStart::REPLAYED,
204+
WarmStart::RECONCILED,
205+
WarmStart::WSDISABLED,
206+
WarmStart::WSUNKNOWN,
207+
WarmStart::FROZEN,
208+
WarmStart::QUIESCENT,
209+
WarmStart::CHECKPOINTED,
210+
WarmStart::COMPLETED,
211+
WarmStart::FAILED,
212+
};
213+
214+
for (const auto &currState : warmStartStates) {
215+
WarmStart::setWarmStartState(testAppName, currState);
216+
217+
string state;
218+
stateWarmRestartTable.hget(testAppName, "state", state);
219+
EXPECT_EQ(state, WarmStart::warmStartStateNameMap()->at(currState).c_str());
220+
221+
WarmStart::WarmStartState ret_state;
222+
ret_state = WarmStart::returnWarmStartState(testAppName);
223+
EXPECT_EQ(ret_state, currState);
224+
}
225+
}
226+
171227
TEST(WarmRestart, set_get_DataCheckState)
172228
{
173229
DBConnector stateDb("STATE_DB", 0, true);
@@ -319,3 +375,66 @@ TEST(WarmRestart, testRegisterWarmBootInfo)
319375
EXPECT_TRUE(ret);
320376
EXPECT_EQ(value, "true");
321377
}
378+
379+
TEST(WarmRestart, testOptionalStateVerification)
380+
{
381+
DBConnector stateDb("STATE_DB", 0, true);
382+
Table stateWarmRestartTable(&stateDb, STATE_WARM_RESTART_TABLE_NAME);
383+
Table stateWarmRestartEnableTable(&stateDb,
384+
STATE_WARM_RESTART_ENABLE_TABLE_NAME);
385+
386+
DBConnector configDb("CONFIG_DB", 0, true);
387+
Table cfgWarmRestartTable(&configDb, CFG_WARM_RESTART_TABLE_NAME);
388+
389+
// Clean up warm restart state for testAppName and warm restart config for
390+
// testDockerName
391+
stateWarmRestartTable.del(testAppName);
392+
cfgWarmRestartTable.del(testDockerName);
393+
stateWarmRestartEnableTable.del("system");
394+
stateWarmRestartEnableTable.del(testDockerName);
395+
396+
// Initialize WarmStart class for TestApp
397+
WarmStart::initialize(testAppName, testDockerName, 0, true);
398+
399+
// perform checkWarmStart for TestApp running in TestDocker. This updates
400+
// warmboot state in the DB.
401+
EXPECT_FALSE(WarmStart::checkWarmStart(testAppName, testDockerName));
402+
403+
// State verification is disabled by default.
404+
EXPECT_FALSE(WarmStart::isStateVerificationEnabled());
405+
EXPECT_FALSE(WarmStart::waitForUnfreeze());
406+
// Since state verification is disabled by default, warmboot state should be
407+
// RECONCILED.
408+
verifyWarmbootState(testAppName, WarmStart::RECONCILED);
409+
410+
// Disable system level warm restart. Verify that checkWarmStart() still
411+
// updates warmboot state to RECONCILED since state verification is disabled
412+
// by default.
413+
stateWarmRestartEnableTable.hset("system", "enable", "false");
414+
EXPECT_FALSE(WarmStart::isStateVerificationEnabled());
415+
EXPECT_FALSE(WarmStart::waitForUnfreeze());
416+
EXPECT_FALSE(WarmStart::checkWarmStart(testAppName, testDockerName));
417+
verifyWarmbootState(testAppName, WarmStart::RECONCILED);
418+
419+
// Enable state verification but disable warm restart. Verify that
420+
// checkWarmStart() updates warmboot state to COMPLETED since state
421+
// verification is enabled.
422+
configureStateVerification("true");
423+
EXPECT_TRUE(WarmStart::isStateVerificationEnabled());
424+
EXPECT_TRUE(WarmStart::waitForUnfreeze());
425+
EXPECT_FALSE(WarmStart::checkWarmStart(testAppName, testDockerName));
426+
verifyWarmbootState(testAppName, WarmStart::COMPLETED);
427+
428+
// Set warmboot state and enable system level warm restart. Verify that
429+
// warmboot state reflects the configured state and doesn't get updated by
430+
// checkWarmStart().
431+
WarmStart::setWarmStartState(testAppName, WarmStart::INITIALIZED);
432+
stateWarmRestartEnableTable.hset("system", "enable", "true");
433+
EXPECT_TRUE(WarmStart::checkWarmStart(testAppName, testDockerName));
434+
verifyWarmbootState(testAppName, WarmStart::INITIALIZED);
435+
436+
// Disable state verification.
437+
configureStateVerification("false");
438+
EXPECT_FALSE(WarmStart::isStateVerificationEnabled());
439+
EXPECT_FALSE(WarmStart::waitForUnfreeze());
440+
}

0 commit comments

Comments
 (0)