Skip to content

Commit

Permalink
Integrated Rebootbackend changes
Browse files Browse the repository at this point in the history
  • Loading branch information
rkavitha-hcl authored and Bibhuprasad Singh committed Dec 3, 2024
1 parent 80a586a commit 4b8a987
Show file tree
Hide file tree
Showing 12 changed files with 1,234 additions and 0 deletions.
30 changes: 30 additions & 0 deletions src/sonic-framework/rebootbackend/gnoi_reboot.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?ignore
XML representation of dbus interface created by: sonic-host-services/host_modules/gnoi_reboot.py

XML generated on switch by executing:
dbus-send --system --type=method_call --print-reply --dest=org.SONiC.HostService.gnoi_reboot /org/SONiC/HostService/gnoi_reboot org.freedesktop.DBus.Introspectable.Introspect

C++ header file generated by:
sudo apt-get install libdbus-c++-dev
dbusxx-xml2cpp ./gnoi_reboot.xml --proxy=gnoi_reboot_dbus.h
?>

<node name="/org/SONiC/HostService/gnoi_reboot">
<interface name="org.freedesktop.DBus.Introspectable">
<method name="Introspect">
<arg direction="out" type="s" />
</method>
</interface>
<interface name="org.SONiC.HostService.gnoi_reboot">
<method name="issue_reboot">
<arg direction="in" type="as" name="options" />
<arg direction="out" type="i" />
<arg direction="out" type="s" />
</method>
<method name="get_reboot_status">
<arg direction="out" type="i" />
<arg direction="out" type="s" />
</method>
</interface>
</node>

72 changes: 72 additions & 0 deletions src/sonic-framework/rebootbackend/gnoi_reboot_dbus.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@

/*
* This file was automatically generated by dbusxx-xml2cpp; DO NOT EDIT!
*/

#ifndef __dbusxx__rebootbackend_gnoi_reboot_dbus_h__PROXY_MARSHAL_H
#define __dbusxx__rebootbackend_gnoi_reboot_dbus_h__PROXY_MARSHAL_H

#include <dbus-c++/dbus.h>
#include <cassert>

namespace org {
namespace SONiC {
namespace HostService {

class gnoi_reboot_proxy
: public ::DBus::InterfaceProxy
{
public:

gnoi_reboot_proxy()
: ::DBus::InterfaceProxy("org.SONiC.HostService.gnoi_reboot")
{
}

public:

/* properties exported by this interface */
public:

/* methods exported by this interface,
* this functions will invoke the corresponding methods on the remote objects
*/
void issue_reboot(const std::vector< std::string >& options, int32_t& argout0, std::string& argout1)
{
::DBus::CallMessage call;
::DBus::MessageIter wi = call.writer();

wi << options;
call.member("issue_reboot");
::DBus::Message ret = invoke_method (call);
::DBus::MessageIter ri = ret.reader();

ri >> argout0;
ri >> argout1;
}

void get_reboot_status(int32_t& argout0, std::string& argout1)
{
::DBus::CallMessage call;
call.member("get_reboot_status");
::DBus::Message ret = invoke_method (call);
::DBus::MessageIter ri = ret.reader();

ri >> argout0;
ri >> argout1;
}


public:

/* signal handlers for this interface
*/

private:

/* unmarshalers (to unpack the DBus message before calling the actual signal handler)
*/
};

} } }
#endif //__dbusxx__rebootbackend_gnoi_reboot_dbus_h__PROXY_MARSHAL_H
136 changes: 136 additions & 0 deletions src/sonic-framework/rebootbackend/init_thread.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
#pragma once

#include <mutex>
#include <thread>
#include <unordered_set>
#include <vector>

#include "dbconnector.h"
#include "notificationproducer.h"
#include "reboot_common.h"
#include "reboot_interfaces.h"
#include "redis_utils.h"
#include "select.h"
#include "selectableevent.h"
#include "selectabletimer.h"
#include "subscriberstatetable.h"
#include "system/system.pb.h"

namespace rebootbackend {

// Holds a thread safe representation of the InitThread internal state.
// Thread-safe: the expectation is one thread will write and multiple threads
// will read.
class InitThreadStatus {
public:
enum ThreadStatus {
NOT_STARTED = 0,
PENDING = 1,
WAITING_FOR_REGISTRATION = 2,
WAITING_FOR_RECONCILIATION = 3,
WAITING_FOR_STATE_VERIFICATION = 4,
WAITING_FOR_UNFREEZE = 5,
FINALIZE = 6,
DONE = 7,
ERROR = 8,
};

enum ErrorCondition {
NO_ERROR = 0,
UNKNOWN = 1,
INTERNAL_ERROR = 2,
REGISTRATION_FAILED = 3,
RECONCILIATION_FAILED = 4,
STATE_VERIFICATION_FAILED = 5,
UNFREEZE_FAILED = 6,
DETECTED_CRITICAL_STATE = 7,
};

struct DetailedStatus {
gnoi::system::RebootStatusResponse thread_state;
InitThreadStatus::ThreadStatus detailed_thread_status =
InitThreadStatus::ThreadStatus::NOT_STARTED;
InitThreadStatus::ErrorCondition detailed_thread_error_condition =
InitThreadStatus::ErrorCondition::NO_ERROR;
};

InitThreadStatus() {
m_status.detailed_thread_status = ThreadStatus::NOT_STARTED;
m_status.detailed_thread_error_condition = ErrorCondition::NO_ERROR;

m_status.thread_state.set_active(false);
m_status.thread_state.set_method(gnoi::system::RebootMethod::COLD);
m_status.thread_state.mutable_status()->set_status(
gnoi::system::RebootStatus_Status::RebootStatus_Status_STATUS_SUCCESS);
m_status.thread_state.mutable_status()->set_message("");
}

void set_start_status() {
const std::lock_guard<std::mutex> lock(m_mutex);
m_status.detailed_thread_status = ThreadStatus::PENDING;
m_status.detailed_thread_error_condition = ErrorCondition::NO_ERROR;

m_status.thread_state.set_active(true);
m_status.thread_state.set_method(gnoi::system::RebootMethod::NSF);
m_status.thread_state.mutable_status()->set_status(
gnoi::system::RebootStatus_Status::RebootStatus_Status_STATUS_UNKNOWN);
m_status.thread_state.mutable_status()->set_message("");
}

bool get_active(void) {
const std::lock_guard<std::mutex> lock(m_mutex);
return m_status.thread_state.active();
}

void set_detailed_thread_status(ThreadStatus new_status) {
const std::lock_guard<std::mutex> lock(m_mutex);
if (m_status.thread_state.active()) {
m_status.detailed_thread_status = new_status;
}
}

void set_success() {
const std::lock_guard<std::mutex> lock(m_mutex);
if (m_status.thread_state.active()) {
m_status.detailed_thread_status = ThreadStatus::DONE;
m_status.thread_state.mutable_status()->set_status(
gnoi::system::RebootStatus_Status::
RebootStatus_Status_STATUS_SUCCESS);
}
}

void set_error(ErrorCondition error_condition,
const std::string &error_message) {
const std::lock_guard<std::mutex> lock(m_mutex);
if (m_status.thread_state.active()) {
m_status.detailed_thread_status = ThreadStatus::ERROR;
m_status.detailed_thread_error_condition = error_condition;
m_status.thread_state.mutable_status()->set_status(
gnoi::system::RebootStatus_Status::
RebootStatus_Status_STATUS_FAILURE);
m_status.thread_state.mutable_status()->set_message(error_message);
}
}

void set_inactive() {
const std::lock_guard<std::mutex> lock(m_mutex);
m_status.thread_state.set_active(false);
}

DetailedStatus get_detailed_thread_status() {
const std::lock_guard<std::mutex> lock(m_mutex);
return m_status;
}

gnoi::system::RebootStatusResponse get_response() {
const std::lock_guard<std::mutex> lock(m_mutex);
return m_status.thread_state;
}

private:
std::mutex m_mutex;
DetailedStatus m_status;
};


} // namespace rebootbackend
73 changes: 73 additions & 0 deletions src/sonic-framework/rebootbackend/interfaces.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#include "interfaces.h"

#include <dbus-c++/dbus.h> // DBus

//#include "component_state_helper.h"
#include "reboot_interfaces.h"

constexpr char kRebootBusName[] = "org.SONiC.HostService.gnoi_reboot";
constexpr char kRebootPath[] = "/org/SONiC/HostService/gnoi_reboot";

constexpr char kContainerShutdownBusName[] = "org.SONiC.HostService.gnoi_container_shutdown";
constexpr char kContainerShutdownPath[] = "/org/SONiC/HostService/gnoi_container_shutdown";

// DBus::BusDispatcher dispatcher;
DBus::Connection& HostServiceDbus::getConnection(void) {
static DBus::Connection* connPtr = nullptr;
if (connPtr == nullptr) {
static DBus::BusDispatcher dispatcher;
DBus::default_dispatcher = &dispatcher;

static DBus::Connection conn = DBus::Connection::SystemBus();
connPtr = &conn;
}
return *connPtr;
}

DbusInterface::DbusResponse HostServiceDbus::Reboot(
const std::string& jsonRebootRequest) {
int32_t status;

GnoiDbusReboot reboot_client(getConnection(), kRebootBusName, kRebootPath);
std::string retString;
std::vector<std::string> options;
options.push_back(jsonRebootRequest);
try {
reboot_client.issue_reboot(options, status, retString);
} catch (DBus::Error& ex) {
return DbusResponse{
DbusStatus::DBUS_FAIL,
"HostServiceDbus::Reboot: failed to call reboot host service"};
}

// gnoi_reboot.py returns 0 for success, 1 for failure
if (status == 0) {
// Successful reboot response is an empty string.
return DbusResponse{DbusStatus::DBUS_SUCCESS, ""};
}
return DbusResponse{DbusStatus::DBUS_FAIL, retString};
}

DbusInterface::DbusResponse HostServiceDbus::RebootStatus(
const std::string& jsonStatusRequest) {

GnoiDbusReboot reboot_client(getConnection(), kRebootBusName, kRebootPath);
int32_t status;
std::string retString;

try {
reboot_client.get_reboot_status(status, retString);
} catch (DBus::Error& ex) {
return DbusResponse{
DbusStatus::DBUS_FAIL,
"HostServiceDbus::RebootStatus: failed to call reboot status "
"host service"};
}

// gnoi_reboot.py returns 0 for success, 1 for failure
if (status == 0) {
return DbusResponse{DbusStatus::DBUS_SUCCESS, retString};
}
return DbusResponse{DbusStatus::DBUS_FAIL, retString};
}

37 changes: 37 additions & 0 deletions src/sonic-framework/rebootbackend/interfaces.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#pragma once
#include <dbus-c++/dbus.h>

#include <string>

#include "gnoi_reboot_dbus.h" // auto generated gnoi_reboot_proxy
#include "reboot_interfaces.h"

/* Reboot is a request to the reboot sonic host service to request a reboot
from the platform. This takes as an argument a string based json formatted
Reboot request from system.proto.’https://github.com/openconfig/gnoi/blob/73a1e7675c5f963e7810bd3828203f2758eb47e8/system/system.proto#L107 */

class GnoiDbusReboot : public org::SONiC::HostService::gnoi_reboot_proxy,
public DBus::IntrospectableProxy,
public DBus::ObjectProxy {
public:
GnoiDbusReboot(DBus::Connection& connection, const char* dbus_bus_name_p,
const char* dbus_obj_name_p)
: DBus::ObjectProxy(connection, dbus_obj_name_p, dbus_bus_name_p) {}
};

/* DbusResponse consists of STATUS: success/fail: i.e. was the dbus request
successful DbusResponse.json_string: string based json formatted RebootResponse
defined here:
https://github.com/openconfig/gnoi/blob/73a1e7675c5f963e7810bd3828203f2758eb47e8/system/system.proto#L119 */


class HostServiceDbus : public DbusInterface {
public:
DbusInterface::DbusResponse Reboot(
const std::string& json_reboot_request) override;
DbusInterface::DbusResponse RebootStatus(
const std::string& json_status_request) override;

private:
static DBus::Connection& getConnection(void);
};
15 changes: 15 additions & 0 deletions src/sonic-framework/rebootbackend/reboot_common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#pragma once

#include <time.h>

#include "status_code_util.h"

namespace rebootbackend {

extern bool sigterm_requested;
struct NotificationResponse {
swss::StatusCode status;
std::string json_string;
};

} // namespace rebootbackend
21 changes: 21 additions & 0 deletions src/sonic-framework/rebootbackend/reboot_interfaces.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#pragma once

#include <string>

class DbusInterface {
public:
enum class DbusStatus {
DBUS_SUCCESS,
DBUS_FAIL,
};

struct DbusResponse {
DbusStatus status;
std::string json_string;
};

virtual ~DbusInterface() = default;
virtual DbusResponse Reboot(const std::string& jsonRebootRequest) = 0;
virtual DbusResponse RebootStatus(const std::string& jsonStatusRequest) = 0;
};

Loading

0 comments on commit 4b8a987

Please sign in to comment.