diff --git a/src/sonic-framework/rebootbackend/reboot_thread.cpp b/src/sonic-framework/rebootbackend/reboot_thread.cpp index a57a241e302f..97b918744a67 100644 --- a/src/sonic-framework/rebootbackend/reboot_thread.cpp +++ b/src/sonic-framework/rebootbackend/reboot_thread.cpp @@ -115,6 +115,8 @@ void RebootThread::do_reboot(void) { if (m_request.method() == RebootMethod::COLD) { do_cold_reboot(s); + } else if (m_request.method() == RebootMethod::WARM) { + do_warm_reboot(s); } else { // This shouldn't be possible. Reference check_start_preconditions() SWSS_LOG_ERROR("Received unrecognized method type = %s", @@ -161,11 +163,28 @@ void RebootThread::do_cold_reboot(swss::Select &s) { // We shouldn't be here. Platform reboot should've killed us. log_error_and_set_non_retry_failure("platform failed to reboot"); - // Set critical state - //m_critical_interface.report_critical_state("platform failed to reboot"); return; } +void RebootThread::do_warm_reboot(swss::Select &s) { + SWSS_LOG_ENTER(); + SWSS_LOG_NOTICE("Sending warm reboot request to platform"); + if (send_dbus_reboot_request() == Progress::EXIT_EARLY) { + return; + } + + // Wait for warm reboot. If we return, reboot failed. + if (wait_for_platform_reboot(s) == Progress::EXIT_EARLY) { + return; + } + + // We shouldn't be here. Platform reboot should've killed us. + log_error_and_set_non_retry_failure("failed to warm reboot"); + + return; +} + + void RebootThread::reboot_thread(void) { SWSS_LOG_ENTER(); @@ -188,6 +207,15 @@ bool RebootThread::check_start_preconditions(const RebootRequest &request, request.method() != RebootMethod::WARM) { response.json_string = "RebootThread: Start rx'd unsupported method"; response.status = swss::StatusCode::SWSS_RC_INVALID_PARAM; + } else if (request.method() == RebootMethod::WARM) { + if (m_status.get_last_reboot_status() == + RebootStatus_Status::RebootStatus_Status_STATUS_FAILURE) { + // If the last reboot failed with a non-retriable failure, don't retry. + // But, we will allow a cold boot to recover. + response.json_string = + "RebootThread: last WARM reboot failed with non-retriable failure"; + response.status = swss::StatusCode::SWSS_RC_FAILED_PRECONDITION; + } } else if (request.delay() != 0) { response.json_string = "RebootThread: delayed start not supported"; response.status = swss::StatusCode::SWSS_RC_INVALID_PARAM; diff --git a/src/sonic-framework/rebootbackend/reboot_thread.h b/src/sonic-framework/rebootbackend/reboot_thread.h index bd0b54aed2a2..9a8bc1be65ae 100644 --- a/src/sonic-framework/rebootbackend/reboot_thread.h +++ b/src/sonic-framework/rebootbackend/reboot_thread.h @@ -165,6 +165,7 @@ class RebootThread { void do_reboot(void); Progress send_dbus_reboot_request(); void do_cold_reboot(swss::Select &s); + void do_warm_reboot(swss::Select &s); // Inner loop select handler to wait for platform reboot. // wait for timeout diff --git a/src/sonic-framework/rebootbackend/rebootbe.cpp b/src/sonic-framework/rebootbackend/rebootbe.cpp index be8a55230e02..deeb473e36ab 100644 --- a/src/sonic-framework/rebootbackend/rebootbe.cpp +++ b/src/sonic-framework/rebootbackend/rebootbe.cpp @@ -53,6 +53,14 @@ void RebootBE::Start() { s.addSelectable(&m_done); s.addSelectable(&m_reboot_thread_finished); + + if (swss::WarmStart::isWarmStart()) { + SWSS_LOG_NOTICE("Launching init thread for warm start"); + SetCurrentStatus(RebManagerStatus::WARM_INIT_WAIT); + } else { + SWSS_LOG_NOTICE("Warm restart not enabled"); + } + SWSS_LOG_NOTICE("RebootBE entering operational loop"); while (true) { swss::Selectable *sel; diff --git a/src/sonic-framework/rebootbackend/redis_utils.cpp b/src/sonic-framework/rebootbackend/redis_utils.cpp deleted file mode 100644 index 4010e99d423a..000000000000 --- a/src/sonic-framework/rebootbackend/redis_utils.cpp +++ /dev/null @@ -1,80 +0,0 @@ -#include "redis_utils.h" - -#include -#include -#include -#include - -#include "dbconnector.h" -#include "notificationproducer.h" -//#include "stateverification.h" -#include "table.h" -#include "timestamp.h" -#include "warm_restart.h" - -namespace rebootbackend { - -using WarmStartState = ::swss::WarmStart::WarmStartState; - - -void init_warm_reboot_states(const swss::DBConnector &db) { - swss::Table table(&db, STATE_WARM_RESTART_TABLE_NAME); - std::vector keys; - - table.getKeys(keys); - for (auto &key : keys) { - table.hdel(key, "state"); - table.hdel(key, "timestamp"); - } -} - -void set_warm_restart_enable(const swss::DBConnector &db, bool enabled) { - swss::Table table(&db, STATE_WARM_RESTART_ENABLE_TABLE_NAME); - table.hset("system", "enable", enabled ? "true" : "false"); -} - -bool is_valid_key(const std::string &key, const std::string &separator) { - if (separator.empty()) { - return false; - } - - size_t pos = key.find(separator); - // The separator must exist in the string, and cannot be the first or last - // character. - return !(pos == std::string::npos || pos == 0 || pos == key.size() - 1); -} - -bool get_docker_app_from_key(const std::string &key, - const std::string &separator, std::string &docker, - std::string &app) { - SWSS_LOG_ENTER(); - - size_t pos = key.find(separator); - - if (separator.empty()) { - SWSS_LOG_ERROR("separator [%s] shouldn't be empty", separator.c_str()); - return false; - } - - if (pos == std::string::npos) { - SWSS_LOG_ERROR("key [%s] should contain separator [%s]", key.c_str(), - separator.c_str()); - return false; - } - - docker = key.substr(0, pos); - app = key.substr(pos + separator.length(), std::string::npos); - - if (docker.empty()) { - SWSS_LOG_ERROR("docker name shouldn't be empty, key = %s", key.c_str()); - return false; - } - - if (app.empty()) { - SWSS_LOG_ERROR("app name shouldn't be empty, key = %s", key.c_str()); - return false; - } - return true; -} - -} // namespace rebootbackend diff --git a/src/sonic-framework/rebootbackend/redis_utils.h b/src/sonic-framework/rebootbackend/redis_utils.h deleted file mode 100644 index 05d87c2aef1c..000000000000 --- a/src/sonic-framework/rebootbackend/redis_utils.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once -#include -#include -#include - -#include "dbconnector.h" -#include "notificationconsumer.h" -#include "notificationproducer.h" -#include "selectableevent.h" -#include "status_code_util.h" -#include "warm_restart.h" - -namespace rebootbackend { - -// Return string corresponding to state -std::string get_warm_start_state_name( - const swss::WarmStart::WarmStartState state); - -void init_warm_reboot_states(const swss::DBConnector &db); - -// Set the system warm start state to a new enabled/disabled state. -// STATE_WARM_RESTART_TABLE_NAME -// key = system, field = enable, value = "true"/"false" -void set_warm_restart_enable(const swss::DBConnector &db, bool enabled); - -// Returns true if key is in the formm "texttext", and false -// otherwise. -bool is_valid_key(const std::string &key, const std::string &separator); - -// Helper function: given key of form "docker|app" -// extract docker and app. (separator = | in this case) -// return false if docker or app are empty or separator -// isn't present, else true. -// key and separator are inputs -// docker and app are outputs -bool get_docker_app_from_key(const std::string &key, - const std::string &separator, std::string &docker, - std::string &app); - -} // namespace rebootbackend diff --git a/src/sonic-framework/tests/rebootbe_test.cpp b/src/sonic-framework/tests/rebootbe_test.cpp index 7c23f996bad3..a4eb79b642c1 100644 --- a/src/sonic-framework/tests/rebootbe_test.cpp +++ b/src/sonic-framework/tests/rebootbe_test.cpp @@ -63,7 +63,6 @@ class RebootBETestWithoutStop : public ::testing::Test { m_rebootbeReponseChannel(&m_db, REBOOT_RESPONSE_NOTIFICATION_CHANNEL), m_rebootbe(m_dbus_interface) { sigterm_requested = false; -// TestUtils::clear_tables(m_db); m_s.addSelectable(&m_rebootbeReponseChannel); @@ -75,21 +74,6 @@ class RebootBETestWithoutStop : public ::testing::Test { } virtual ~RebootBETestWithoutStop() = default; - gnoi::system::RebootStatusResponse default_not_started_status() { - InitThreadStatus status; - return status.get_response(); - } - - gnoi::system::RebootStatusResponse default_done_status() { - InitThreadStatus status; - // We can't edit the status without it being active. - status.set_start_status(); - status.set_success(); - status.set_inactive(); - return status.get_response(); - } - - void start_rebootbe() { m_rebootbe_thread = std::make_unique(&RebootBE::Start, &m_rebootbe); @@ -227,26 +211,8 @@ class RebootBEAutoStartTest : public RebootBETest, RebootBEAutoStartTest() { //force_warm_start_state(GetParam()); - /* if (GetParam()) { - EXPECT_CALL(*m_init_thread, Start()) - .WillOnce(Return(swss::StatusCode::SWSS_RC_SUCCESS)); - EXPECT_CALL(*m_init_thread, Join()).WillOnce(Return(true)); - EXPECT_CALL(*m_init_thread, GetResponse()) - .WillOnce(Return(default_running_status())) - .WillRepeatedly(Return(default_done_status())); - } else { - EXPECT_CALL(*m_init_thread, GetResponse()) - .WillRepeatedly(Return(default_not_started_status())); - } */ - start_rebootbe(); -/* if (GetParam()) { - get_stack_unfrozen_select().notify(); - std::this_thread::sleep_for(std::chrono::milliseconds(50)); - get_init_done_select().notify(); - } */ - std::this_thread::sleep_for(std::chrono::milliseconds(50)); EXPECT_EQ(m_rebootbe.GetCurrentStatus(), RebootBE::RebManagerStatus::IDLE); } diff --git a/src/sonic-framework/tests/redis_utils_test.cpp b/src/sonic-framework/tests/redis_utils_test.cpp deleted file mode 100644 index 00864059a21e..000000000000 --- a/src/sonic-framework/tests/redis_utils_test.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include "redis_utils.h" - -#include -#include -#include - -#include -#include -#include - -#include "select.h" -#include "table.h" -#include "test_utils_common.h" -#include "timestamp.h" - -namespace rebootbackend { - -using ::testing::AllOf; -using ::testing::HasSubstr; -using ::testing::StrEq; - - -} // namespace rebootbackend