Skip to content

Commit c3b6888

Browse files
rkavitha-hclBibhuprasad Singh
authored and
Bibhuprasad Singh
committed
gNOI Warm Reboot - Added tests
1 parent 383cb08 commit c3b6888

File tree

3 files changed

+247
-8
lines changed

3 files changed

+247
-8
lines changed

src/sonic-framework/rebootbackend/rebootbe.cpp

+5-4
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ RebootBE::RebootBE(DbusInterface &dbus_interface)
3131
}
3232

3333
RebootBE::RebManagerStatus RebootBE::GetCurrentStatus() {
34-
const std::lock_guard<std::mutex> lock(m_StatusMutex);
3534
return m_CurrentStatus;
3635
}
3736

@@ -43,6 +42,9 @@ void RebootBE::SetCurrentStatus(RebManagerStatus newStatus) {
4342
void RebootBE::Start() {
4443
SWSS_LOG_ENTER();
4544
SWSS_LOG_NOTICE("--- Starting rebootbackend ---");
45+
swss::WarmStart::initialize("rebootbackend", "sonic-framework");
46+
swss::WarmStart::checkWarmStart("rebootbackend", "sonic-framework",
47+
/*incr_restore_cnt=*/false);
4648

4749
swss::Select s;
4850
s.addSelectable(&m_NotificationConsumer);
@@ -51,7 +53,6 @@ void RebootBE::Start() {
5153

5254

5355
if (swss::WarmStart::isWarmStart()) {
54-
SWSS_LOG_NOTICE("Launching init thread for warm start");
5556
SetCurrentStatus(RebManagerStatus::WARM_INIT_WAIT);
5657
} else {
5758
SWSS_LOG_NOTICE("Warm restart not enabled");
@@ -176,9 +177,9 @@ bool RebootBE::RebootAllowed(const gnoi::system::RebootMethod rebMethod) {
176177
case RebManagerStatus::WARM_REBOOT_IN_PROGRESS: {
177178
return false;
178179
}
179-
case RebManagerStatus::WARM_INIT_WAIT: {
180+
case RebManagerStatus::WARM_INIT_WAIT: {
180181
return rebMethod == gnoi::system::RebootMethod::COLD;
181-
}
182+
}
182183
case RebManagerStatus::IDLE: {
183184
return true;
184185
}

src/sonic-framework/tests/reboot_thread_test.cpp

+66-1
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,34 @@ TEST_F(RebootStatusTest, TestGetStatus) {
8787
EXPECT_EQ(0, response.when());
8888
}
8989

90+
TEST_F(RebootStatusTest, TestGetWarmStatus) {
91+
std::chrono::nanoseconds curr_ns = std::chrono::high_resolution_clock::now().time_since_epoch();
92+
93+
m_status.set_start_status(RebootMethod::WARM, "reboot because");
94+
95+
RebootStatusResponse response = m_status.get_response();
96+
EXPECT_EQ(response.status().status(),
97+
RebootStatus_Status::RebootStatus_Status_STATUS_UNKNOWN);
98+
99+
m_status.set_completed_status(
100+
RebootStatus_Status::RebootStatus_Status_STATUS_SUCCESS, "anything");
101+
102+
response = m_status.get_response();
103+
104+
// message should be empty while reboot is active
105+
EXPECT_THAT(response.status().message(), StrEq(""));
106+
107+
uint64_t reboot_ns = response.when();
108+
EXPECT_TRUE(reboot_ns > (uint64_t)curr_ns.count());
109+
110+
m_status.set_inactive();
111+
response = m_status.get_response();
112+
EXPECT_THAT(response.status().message(), StrEq("anything"));
113+
EXPECT_EQ(response.status().status(),
114+
RebootStatus_Status::RebootStatus_Status_STATUS_SUCCESS);
115+
EXPECT_EQ(0, response.when());
116+
}
117+
90118
class RebootThreadTest : public ::testing::Test {
91119
protected:
92120
RebootThreadTest()
@@ -269,7 +297,7 @@ TEST_F(RebootThreadTest, TestUnsupportedRebootType) {
269297
"RebootThread: Start rx'd unsupported method");
270298
}
271299

272-
TEST_F(RebootThreadTest, TestInvalidMethodfDoReboot) {
300+
TEST_F(RebootThreadTest, TestInvalidMethodOfDoReboot) {
273301
set_start_status(RebootMethod::POWERUP, "time to reboot");
274302
do_reboot();
275303
force_inactive();
@@ -279,4 +307,41 @@ TEST_F(RebootThreadTest, TestInvalidMethodfDoReboot) {
279307
IsStatus(RebootStatus_Status::RebootStatus_Status_STATUS_UNKNOWN, ""));
280308
}
281309

310+
TEST_F(RebootThreadTest, TestNoWarmIfNonRetriableFailure) {
311+
set_start_status(RebootMethod::WARM, "time to reboot");
312+
set_completed_status(RebootStatus_Status::RebootStatus_Status_STATUS_FAILURE,
313+
"failed to warm reboot");
314+
force_inactive();
315+
316+
RebootRequest request;
317+
request.set_method(RebootMethod::WARM);
318+
319+
NotificationResponse response = m_reboot_thread.Start(request);
320+
EXPECT_EQ(response.status, swss::StatusCode::SWSS_RC_FAILED_PRECONDITION);
321+
EXPECT_EQ(response.json_string,
322+
"RebootThread: last WARM reboot failed with non-retriable failure");
323+
}
324+
325+
TEST_F(RebootThreadTest, TestSigTermStartofDoReboot) {
326+
sigterm_requested = true;
327+
set_start_status(RebootMethod::WARM, "time to reboot");
328+
do_reboot();
329+
force_inactive();
330+
RebootStatusResponse response = m_reboot_thread.GetResponse();
331+
EXPECT_THAT(
332+
response,
333+
IsStatus(RebootStatus_Status::RebootStatus_Status_STATUS_UNKNOWN, ""));
334+
}
335+
336+
TEST_F(RebootThreadTest, TestWaitForRebootPositive) {
337+
overwrite_reboot_timeout(1);
338+
set_start_status(RebootMethod::WARM, "time to reboot");
339+
swss::Select s;
340+
swss::SelectableEvent m_stop;
341+
s.addSelectable(&m_stop);
342+
RebootThread::Progress progress = wait_for_platform_reboot(s);
343+
EXPECT_EQ(progress, RebootThread::Progress::PROCEED);
344+
}
345+
346+
282347
} // namespace rebootbackend

src/sonic-framework/tests/rebootbe_test.cpp

+176-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
#include <string>
99
#include <thread>
1010
#include <vector>
11-
#include<iostream>
1211

1312
#include "mock_reboot_interfaces.h"
1413
#include "reboot_common.h"
@@ -63,6 +62,7 @@ class RebootBETestWithoutStop : public ::testing::Test {
6362
m_rebootbeReponseChannel(&m_db, REBOOT_RESPONSE_NOTIFICATION_CHANNEL),
6463
m_rebootbe(m_dbus_interface) {
6564
sigterm_requested = false;
65+
// TestUtils::clear_tables(m_db);
6666

6767

6868
m_s.addSelectable(&m_rebootbeReponseChannel);
@@ -74,6 +74,15 @@ class RebootBETestWithoutStop : public ::testing::Test {
7474
}
7575
virtual ~RebootBETestWithoutStop() = default;
7676

77+
void force_warm_start_state(bool enabled) {
78+
swss::Table enable_table(&m_db, STATE_WARM_RESTART_ENABLE_TABLE_NAME);
79+
enable_table.hset("system", "enable", enabled ? "true" : "false");
80+
enable_table.hset("sonic-framework", "enable", enabled ? "true" : "false");
81+
82+
swss::Table restart_table(&m_db, STATE_WARM_RESTART_TABLE_NAME);
83+
restart_table.hset("rebootbackend", "restore_count", enabled ? "0" : "");
84+
}
85+
7786
void start_rebootbe() {
7887
m_rebootbe_thread =
7988
std::make_unique<std::thread>(&RebootBE::Start, &m_rebootbe);
@@ -202,18 +211,62 @@ class RebootBETest : public RebootBETestWithoutStop {
202211
}
203212
};
204213

214+
TEST_F(RebootBETest, WarmbootInProgressBlocksNewWarmboot) {
215+
force_warm_start_state(true);
216+
217+
start_rebootbe();
218+
std::this_thread::sleep_for(std::chrono::milliseconds(100));
219+
EXPECT_EQ(m_rebootbe.GetCurrentStatus(),
220+
RebootBE::RebManagerStatus::WARM_INIT_WAIT);
221+
222+
// Send a warmboot request, confirm it fails.
223+
RebootRequest request;
224+
request.set_method(RebootMethod::WARM);
225+
start_reboot_via_rpc(request, swss::StatusCode::SWSS_RC_IN_USE);
226+
227+
std::this_thread::sleep_for(std::chrono::milliseconds(TENTH_SECOND_MS));
228+
EXPECT_EQ(m_rebootbe.GetCurrentStatus(),
229+
RebootBE::RebManagerStatus::WARM_INIT_WAIT);
230+
force_warm_start_state(false);
231+
}
232+
233+
234+
TEST_F(RebootBETest, ColdbootWhileWarmbootInProgress) {
235+
force_warm_start_state(true);
236+
set_mock_defaults();
237+
238+
start_rebootbe();
239+
std::this_thread::sleep_for(std::chrono::milliseconds(100));
240+
EXPECT_EQ(m_rebootbe.GetCurrentStatus(),
241+
RebootBE::RebManagerStatus::WARM_INIT_WAIT);
242+
243+
// Send a coldboot request, confirm it starts.
244+
RebootRequest request;
245+
request.set_method(RebootMethod::COLD);
246+
start_reboot_via_rpc(request);
247+
248+
std::this_thread::sleep_for(std::chrono::milliseconds(TENTH_SECOND_MS));
249+
EXPECT_EQ(m_rebootbe.GetCurrentStatus(),
250+
RebootBE::RebManagerStatus::COLD_REBOOT_IN_PROGRESS);
251+
252+
// Cleanup without going through the whole reboot.
253+
send_stop_reboot_thread();
254+
force_warm_start_state(false);
255+
}
256+
257+
205258
// Test fixture to skip through the startup sequence into the main loop.
206259
// Param indicates if RebootBE should be initialized into a state where the
207260
// system came up in warmboot.
208261
class RebootBEAutoStartTest : public RebootBETest,
209262
public ::testing::WithParamInterface<bool> {
210263
protected:
211264
RebootBEAutoStartTest() {
212-
//force_warm_start_state(GetParam());
213265

214266
start_rebootbe();
215267

216-
std::this_thread::sleep_for(std::chrono::milliseconds(50));
268+
//std::this_thread::sleep_for(std::chrono::milliseconds(50));
269+
std::this_thread::sleep_for(std::chrono::milliseconds(ONE_SECOND_MS));
217270
EXPECT_EQ(m_rebootbe.GetCurrentStatus(), RebootBE::RebManagerStatus::IDLE);
218271
}
219272
};
@@ -312,6 +365,31 @@ TEST_P(RebootBEAutoStartTest, TestColdRebootDbusToCompletion) {
312365
"platform failed to reboot"));
313366
}
314367

368+
369+
TEST_P(RebootBEAutoStartTest, TestWarmRebootDbusToCompletion) {
370+
DbusInterface::DbusResponse dbus_response{
371+
DbusInterface::DbusStatus::DBUS_SUCCESS, ""};
372+
EXPECT_CALL(m_dbus_interface, Reboot(_))
373+
.Times(1)
374+
.WillRepeatedly(Return(dbus_response));
375+
376+
overwrite_reboot_timeout(1);
377+
RebootRequest request;
378+
request.set_method(RebootMethod::WARM);
379+
start_reboot_via_rpc(request);
380+
EXPECT_EQ(m_rebootbe.GetCurrentStatus(), RebootBE::RebManagerStatus::WARM_REBOOT_IN_PROGRESS);
381+
382+
sleep(TWO_SECONDS);
383+
384+
EXPECT_EQ(m_rebootbe.GetCurrentStatus(), RebootBE::RebManagerStatus::IDLE);
385+
gnoi::system::RebootStatusResponse response = do_reboot_status_rpc();
386+
EXPECT_THAT(response, ActiveCountMethod(false, 1, RebootMethod::WARM));
387+
EXPECT_THAT(response,
388+
IsStatus(RebootStatus_Status::RebootStatus_Status_STATUS_FAILURE,
389+
"failed to warm reboot"));
390+
391+
}
392+
315393
TEST_P(RebootBEAutoStartTest, TestColdBootSigterm) {
316394
sigterm_requested = true;
317395
set_mock_defaults();
@@ -331,6 +409,25 @@ TEST_P(RebootBEAutoStartTest, TestColdBootSigterm) {
331409
IsStatus(RebootStatus_Status::RebootStatus_Status_STATUS_UNKNOWN, ""));
332410
}
333411

412+
TEST_P(RebootBEAutoStartTest, TestWarmBootSigterm) {
413+
sigterm_requested = true;
414+
set_mock_defaults();
415+
overwrite_reboot_timeout(1);
416+
417+
RebootRequest request;
418+
request.set_method(RebootMethod::WARM);
419+
start_reboot_via_rpc(request);
420+
421+
sleep(ONE_SECOND);
422+
423+
EXPECT_EQ(m_rebootbe.GetCurrentStatus(), RebootBE::RebManagerStatus::IDLE);
424+
gnoi::system::RebootStatusResponse second_resp = do_reboot_status_rpc();
425+
EXPECT_THAT(second_resp, ActiveCountMethod(false, 1, RebootMethod::WARM));
426+
EXPECT_THAT(
427+
second_resp,
428+
IsStatus(RebootStatus_Status::RebootStatus_Status_STATUS_UNKNOWN, ""));
429+
}
430+
334431
TEST_P(RebootBEAutoStartTest, TestColdBootDbusError) {
335432
// Return FAIL from dbus reboot call.
336433
DbusInterface::DbusResponse dbus_response{
@@ -353,6 +450,28 @@ TEST_P(RebootBEAutoStartTest, TestColdBootDbusError) {
353450
"dbus reboot failed"));
354451
}
355452

453+
TEST_P(RebootBEAutoStartTest, TestWarmBootDbusError) {
454+
// Return FAIL from dbus reboot call.
455+
DbusInterface::DbusResponse dbus_response{
456+
DbusInterface::DbusStatus::DBUS_FAIL, "dbus reboot failed"};
457+
EXPECT_CALL(m_dbus_interface, Reboot(_))
458+
.Times(1)
459+
.WillOnce(Return(dbus_response));
460+
461+
RebootRequest request;
462+
request.set_method(RebootMethod::WARM);
463+
start_reboot_via_rpc(request);
464+
465+
sleep(TWO_SECONDS);
466+
467+
EXPECT_EQ(m_rebootbe.GetCurrentStatus(), RebootBE::RebManagerStatus::IDLE);
468+
gnoi::system::RebootStatusResponse second_resp = do_reboot_status_rpc();
469+
EXPECT_THAT(second_resp, ActiveCountMethod(false, 1, RebootMethod::WARM));
470+
EXPECT_THAT(second_resp,
471+
IsStatus(RebootStatus_Status::RebootStatus_Status_STATUS_FAILURE,
472+
"dbus reboot failed"));
473+
}
474+
356475
TEST_P(RebootBEAutoStartTest, TestStopDuringColdBoot) {
357476
set_mock_defaults();
358477

@@ -374,12 +493,66 @@ TEST_P(RebootBEAutoStartTest, TestStopDuringColdBoot) {
374493
IsStatus(RebootStatus_Status::RebootStatus_Status_STATUS_UNKNOWN, ""));
375494
}
376495

496+
TEST_P(RebootBEAutoStartTest, TestStopDuringWarmBoot) {
497+
set_mock_defaults();
498+
499+
RebootRequest request;
500+
request.set_method(RebootMethod::WARM);
501+
start_reboot_via_rpc(request);
502+
// std::this_thread::sleep_for(std::chrono::milliseconds(TENTH_SECOND_MS));
503+
EXPECT_EQ(m_rebootbe.GetCurrentStatus(),
504+
RebootBE::RebManagerStatus::WARM_REBOOT_IN_PROGRESS);
505+
506+
send_stop_reboot_thread();
507+
std::this_thread::sleep_for(std::chrono::milliseconds(TENTH_SECOND_MS));
508+
EXPECT_EQ(m_rebootbe.GetCurrentStatus(), RebootBE::RebManagerStatus::IDLE);
509+
510+
gnoi::system::RebootStatusResponse response = do_reboot_status_rpc();
511+
EXPECT_THAT(response, ActiveCountMethod(false, 1, RebootMethod::WARM));
512+
EXPECT_THAT(
513+
response,
514+
IsStatus(RebootStatus_Status::RebootStatus_Status_STATUS_UNKNOWN, ""));
515+
}
516+
377517
TEST_P(RebootBEAutoStartTest, TestInvalidJsonRebootRequest) {
378518
std::string json_request = "abcd";
379519
NotificationResponse response = handle_reboot_request(json_request);
380520
EXPECT_EQ(swss::StatusCode::SWSS_RC_INTERNAL, response.status);
381521
}
382522

523+
TEST_P(RebootBEAutoStartTest, TestWarmFailureFollowedByColdBoot) {
524+
DbusInterface::DbusResponse dbus_response{
525+
DbusInterface::DbusStatus::DBUS_SUCCESS, ""};
526+
overwrite_reboot_timeout(1);
527+
528+
RebootRequest request;
529+
request.set_method(RebootMethod::WARM);
530+
start_reboot_via_rpc(request);
531+
532+
std::this_thread::sleep_for(std::chrono::milliseconds(TENTH_SECOND_MS));
533+
EXPECT_EQ(m_rebootbe.GetCurrentStatus(),
534+
RebootBE::RebManagerStatus::WARM_REBOOT_IN_PROGRESS);
535+
536+
std::this_thread::sleep_for(std::chrono::milliseconds(TWO_SECONDS_MS));
537+
gnoi::system::RebootStatusResponse response = do_reboot_status_rpc();
538+
EXPECT_THAT(response, ActiveCountMethod(false, 1, RebootMethod::WARM));
539+
540+
541+
request.set_method(RebootMethod::COLD);
542+
start_reboot_via_rpc(request);
543+
544+
// We have to wait for the 1 second reboot Timeout
545+
std::this_thread::sleep_for(std::chrono::milliseconds(TWO_SECONDS_MS));
546+
547+
EXPECT_EQ(m_rebootbe.GetCurrentStatus(), RebootBE::RebManagerStatus::IDLE);
548+
response = do_reboot_status_rpc();
549+
EXPECT_THAT(response, ActiveCountMethod(false, 2, RebootMethod::COLD));
550+
EXPECT_THAT(response,
551+
IsStatus(RebootStatus_Status::RebootStatus_Status_STATUS_FAILURE,
552+
"platform failed to reboot"));
553+
}
554+
555+
383556
INSTANTIATE_TEST_SUITE_P(TestWithStartupWarmbootEnabledState,
384557
RebootBEAutoStartTest, testing::Values(true, false));
385558

0 commit comments

Comments
 (0)