Roll forward of cl/707220915 Fixed the unit test. The test was failing because the error message is different in a forge test environment. Automated g4 rollback of changelist 707704110. *** Reason for rollback *** Rolling forward with fixes *** Original change description *** Automated g4 rollback of changelist 707220915. *** Reason for rollback *** Failing https://tap.corp.google.com/node_os. *** Original change description *** #gpowerd - Add build targets for HTTP connection and related *** *** PiperOrigin-RevId: 713781207 Change-Id: I09b65b089f3461a13cf5a452a617e1876a739f13
diff --git a/bmc/http_connection.cc b/bmc/http_connection.cc index 6e87ad7..8dec749 100644 --- a/bmc/http_connection.cc +++ b/bmc/http_connection.cc
@@ -1,18 +1,29 @@ -#include <nlohmann/json.hpp> #include "bmc/http_connection.h" -#include "bmc/daemon_context_bmc.h" -#include "boost/asio/ip/tcp.hpp" // NOLINT -#include "boost/asio/ssl.hpp" // NOLINT -#include "boost/asio/ssl/stream.hpp" // NOLINT -#include "boost/beast/core.hpp" // NOLINT -#include "boost/beast/core/tcp_stream.hpp" // NOLINT -#include "boost/beast/http.hpp" // NOLINT -#include "boost/beast/version.hpp" // NOLINT -#include "absl/status/status.h" -#include "absl/strings/string_view.h" -#include "absl/log/log.h" +#include <cstddef> +#include <cstdint> +#include <string> +#include <utility> +#include "bmc/daemon_context_bmc.h" +#include "absl/functional/any_invocable.h" +#include "absl/log/log.h" +#include "absl/status/status.h" +#include "absl/status/statusor.h" +#include "absl/strings/str_cat.h" +#include "absl/strings/string_view.h" +#include "absl/time/time.h" + +// NOLINTBEGIN(readability/boost) +#include "boost/asio/ip/tcp.hpp" +#include "boost/beast/core.hpp" +#include "boost/beast/core/tcp_stream.hpp" +#include "boost/beast/http.hpp" +#include "boost/beast/version.hpp" +// NOLINTEND(readability/boost) + +#include "nlohmann/json.hpp" +#include "nlohmann/json_fwd.hpp" namespace safepower_agent { @@ -22,24 +33,20 @@ using boost::beast::flat_buffer; using boost::beast::tcp_stream; - HttpConnection::HttpConnection(absl::Duration connection_timeout, - absl::Duration write_timeout): - stream_(boost::asio::make_strand - (DaemonContextBMC::Get().get_io_context())), - connection_timeout_(connection_timeout), - write_timeout_(write_timeout) -{} + absl::Duration write_timeout) + : stream_( + boost::asio::make_strand(DaemonContextBMC::Get().get_io_context())), + connection_timeout_(connection_timeout), + write_timeout_(write_timeout) {} // perform_connection = connect -> write -> read -> callback // all failing cases, skip to user provided callback with error void HttpConnection::PerformConnection( - http::verb verb, - absl::string_view target, - absl::AnyInvocable<void(absl::StatusOr<nlohmann::json>) && > in_callback, - const nlohmann::json& body, - const absl::string_view ip, - const uint16_t port){ + http::verb verb, absl::string_view target, + absl::AnyInvocable<void(absl::StatusOr<nlohmann::json>) &&> in_callback, + const nlohmann::json& body, const absl::string_view ip, + const uint16_t port) { verb_ = verb; body_ = body.dump(); target_ = target; @@ -47,10 +54,9 @@ boost::system::error_code ec; boost::asio::ip::address address = - boost::asio::ip::address::from_string(std::string(ip).c_str(), ec); - if (ec){ - LOG(INFO) << "Unable to build address from string ip:" << - std::string(ip); + boost::asio::ip::address::from_string(std::string(ip).c_str(), ec); + if (ec) { + LOG(INFO) << "Unable to build address from string ip:" << ip; } end_point_.address(address); end_point_.port(port); @@ -60,13 +66,10 @@ auto self = shared_from_this(); stream_.async_connect(end_point_, - [self](beast::error_code ec) { - self->Write(ec); - }); + [self](beast::error_code ec) { self->Write(ec); }); } -void HttpConnection::Write(beast::error_code ec) -{ +void HttpConnection::Write(beast::error_code ec) { if (ec) { std::move(provided_callback_)(absl::UnavailableError( absl::StrCat("Failed to connect to BMC: ", ec.message()))); @@ -83,30 +86,24 @@ req_.prepare_payload(); stream_.expires_after(absl::ToChronoMilliseconds(write_timeout_)); auto self = shared_from_this(); - http::async_write(stream_, req_, - [self](beast::error_code ec, size_t t){ - self->Read(ec, t); - }); + http::async_write(stream_, req_, [self](beast::error_code ec, size_t t) { + self->Read(ec, t); + }); } -void HttpConnection::Read(beast::error_code ec, size_t ) { +void HttpConnection::Read(beast::error_code ec, size_t) { if (ec) { std::move(provided_callback_)(absl::UnavailableError( absl::StrCat("Failed in http write:", ec.message()))); return; } auto self = shared_from_this(); - http::async_read(stream_, buffer_, res_, - [self](beast::error_code ec, size_t t) - { - self->Callback(ec, t); - }); + http::async_read( + stream_, buffer_, res_, + [self](beast::error_code ec, size_t t) { self->Callback(ec, t); }); } -void HttpConnection::Callback( - beast::error_code ec, - std::size_t ) -{ +void HttpConnection::Callback(beast::error_code ec, std::size_t) { absl::Status status = absl::OkStatus(); if (ec) { LOG(ERROR) << "callback error handler: " << ec.message(); @@ -134,6 +131,5 @@ return; } std::move(provided_callback_)(js_body); - return; } } // namespace safepower_agent
diff --git a/bmc/http_connection.h b/bmc/http_connection.h index 3a06bf6..d767632 100644 --- a/bmc/http_connection.h +++ b/bmc/http_connection.h
@@ -1,19 +1,26 @@ #ifndef PRODUCTION_SUSHID_SAFEPOWER_AGENT_BMC_HTTP_CONNECTION_H_ #define PRODUCTION_SUSHID_SAFEPOWER_AGENT_BMC_HTTP_CONNECTION_H_ -#include <nlohmann/json.hpp> -#include "absl/status/status.h" -#include "absl/status/statusor.h" +#include <cstddef> +#include <cstdint> +#include <memory> +#include <string> #include "absl/functional/any_invocable.h" +#include "absl/status/statusor.h" +#include "absl/strings/string_view.h" +#include "absl/time/time.h" -#include "boost/asio/ip/tcp.hpp" // NOLINT -#include "boost/asio/ssl.hpp" // NOLINT -#include "boost/asio/ssl/stream.hpp" // NOLINT -#include "boost/beast/core.hpp" // NOLINT -#include "boost/beast/core/tcp_stream.hpp" // NOLINT -#include "boost/beast/http.hpp" // NOLINT -#include "boost/beast/version.hpp" // NOLINT +// NOLINTBEGIN(readability/boost) +#include "boost/asio/ip/tcp.hpp" +#include "boost/beast/core.hpp" +#include "boost/beast/core/tcp_stream.hpp" +#include "boost/beast/http.hpp" +#include "boost/beast/http/string_body.hpp" +#include "boost/beast/version.hpp" +// NOLINTEND(readability/boost) + +#include "nlohmann/json_fwd.hpp" namespace safepower_agent { @@ -24,42 +31,34 @@ class HttpConnection : public std::enable_shared_from_this<HttpConnection> { public: - HttpConnection(absl::Duration connection_timeout = - absl::Seconds(10), - absl::Duration write_timeout = - absl::Seconds(10)); + explicit HttpConnection(absl::Duration connection_timeout = absl::Seconds(10), + absl::Duration write_timeout = absl::Seconds(10)); - void PerformConnection(http::verb verb, - absl::string_view target, - absl::AnyInvocable - <void(absl::StatusOr<nlohmann::json>) && > - callback, - const nlohmann::json& body, - absl::string_view ip = "127.0.0.1", - const uint16_t port = 80); + void PerformConnection( + http::verb verb, absl::string_view target, + absl::AnyInvocable<void(absl::StatusOr<nlohmann::json>) &&> callback, + const nlohmann::json& body, absl::string_view ip = "127.0.0.1", + uint16_t port = 80); - void Write(beast::error_code ec); - void Read(beast::error_code ec, - size_t bytes_transferred); - void Callback(beast::error_code ec, - std::size_t bytes_transferred); + void Write(beast::error_code ec); + void Read(beast::error_code ec, size_t bytes_transferred); + void Callback(beast::error_code ec, std::size_t bytes_transferred); private: - http::verb verb_; - std::string target_; - std::string body_; - beast::tcp_stream stream_; - beast::flat_buffer buffer_; - absl::AnyInvocable<void(absl::StatusOr<nlohmann::json>) &&> - provided_callback_; - http::request<http::string_body> req_; - http::response<http::string_body> res_; - boost::asio::ip::tcp::endpoint end_point_; - absl::Duration connection_timeout_; - absl::Duration write_timeout_; + http::verb verb_; + std::string target_; + std::string body_; + beast::tcp_stream stream_; + beast::flat_buffer buffer_; + absl::AnyInvocable<void(absl::StatusOr<nlohmann::json>) &&> + provided_callback_; + http::request<http::string_body> req_; + http::response<http::string_body> res_; + boost::asio::ip::tcp::endpoint end_point_; + absl::Duration connection_timeout_; + absl::Duration write_timeout_; }; -} // namespace safepower_agent +} // namespace safepower_agent #endif // PRODUCTION_SUSHID_SAFEPOWER_AGENT_BMC_HTTP_CONNECTION_H_ -
diff --git a/bmc/http_connection_test.cc b/bmc/http_connection_test.cc index 11318c8..8eb99dd 100644 --- a/bmc/http_connection_test.cc +++ b/bmc/http_connection_test.cc
@@ -1,33 +1,39 @@ -#include <absl/status/status.h> -#include <gmock/gmock.h> -#include <gtest/gtest.h> +#include "bmc/http_connection.h" -#include <safepower_agent_config.pb.h> - - -#include <chrono> // NOLINT -#include <cstdlib> -#include <ctime> -#include <iostream> +#include <chrono> // NOLINT(build/c++11) #include <memory> #include <string> +#include <utility> +#include <vector> -#include "state_updater.h" #include "bmc/daemon_context_bmc.h" -#include "bmc/http_connection.h" #include "bmc/mock_server.h" -#include "bmc/scheduler_bmc.h" #include "bmc/redfish.h" #include "bmc/state_monitor_bmc.h" +#include "safepower_agent.pb.h" +#include "safepower_agent_config.pb.h" +#include "state_updater.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" +#include "absl/status/status.h" +#include "absl/status/statusor.h" +#include "absl/strings/str_cat.h" +#include "absl/time/time.h" +// NOLINTBEGIN(readability/boost) +#include "boost/asio/io_context.hpp" +#include "boost/beast/core.hpp" +#include "boost/beast/http.hpp" +#include "boost/beast/version.hpp" +// NOLINTEND(readability/boost) -#include "boost/beast/core.hpp" // NOLINT -#include "boost/beast/http.hpp" // NOLINT -#include "boost/beast/version.hpp" // NOLINT -#include "boost/asio/io_context.hpp" // NOLINT - +#include "nlohmann/json.hpp" +#include "nlohmann/json_fwd.hpp" namespace safepower_agent { -namespace mock_server_test { +namespace { + +using mock_server_test::TestBoostServer; +using ::testing::StartsWith; TEST(http, NoConnection) { // DO NOT start the test sever @@ -37,12 +43,14 @@ bool callback_ran = false; my_connection->PerformConnection( (http::verb::post), "/redfish/v1/Systems/system/Actions/Power.Reset", - [&callback_ran](absl::StatusOr<nlohmann::json> jres){ - ASSERT_FALSE(jres.ok()); - ASSERT_EQ(jres.status(), absl::UnavailableError( - absl::StrCat("Failed to connect to BMC: ", "Connection refused"))); - callback_ran = true; - }, {}); + [&callback_ran](absl::StatusOr<nlohmann::json> jres) { + ASSERT_FALSE(jres.ok()); + ASSERT_EQ(jres.status(), + absl::UnavailableError(absl::StrCat( + "Failed to connect to BMC: ", "Connection refused"))); + callback_ran = true; + }, + {}); DaemonContextBMC::Get().get_io_context().run_for(std::chrono::seconds(1)); EXPECT_TRUE(callback_ran); @@ -50,21 +58,20 @@ TEST(http, BadAddress) { DaemonContextBMC context; // only use DaemonContextBMC::Get() - TestBoostServer my_server; + mock_server_test::TestBoostServer my_server; my_server.Start(DaemonContextBMC::Get().get_io_context()); - auto my_connection = std::make_shared<HttpConnection>(absl::Seconds(0)); + auto my_connection = std::make_shared<HttpConnection>(absl::ZeroDuration()); bool callback_ran = false; my_connection->PerformConnection( - (http::verb::post), "/redfish/v1/Systems/system/Actions/Power.Reset", - [&callback_ran](absl::StatusOr<nlohmann::json> jres){ - ASSERT_FALSE(jres.ok()); - ASSERT_EQ(jres.status(), absl::UnavailableError( - absl::StrCat("Failed to connect to BMC: ", - "The socket was closed due to a timeout"))); - callback_ran = true; - }, - {}, "240.0.0.0", 80); + (http::verb::post), "/redfish/v1/Systems/system/Actions/Power.Reset", + [&callback_ran](absl::StatusOr<nlohmann::json> jres) { + ASSERT_TRUE(absl::IsUnavailable(jres.status())); + ASSERT_THAT(jres.status().message(), + StartsWith("Failed to connect to BMC: ")); + callback_ran = true; + }, + {}, "240.0.0.0", 80); DaemonContextBMC::Get().get_io_context().run_for(std::chrono::seconds(1)); EXPECT_TRUE(callback_ran); @@ -75,18 +82,20 @@ TestBoostServer my_server; my_server.Start(DaemonContextBMC::Get().get_io_context()); - auto my_connection = std::make_shared<HttpConnection> - (absl::Seconds(2), absl::Seconds(0)); + auto my_connection = + std::make_shared<HttpConnection>(absl::Seconds(2), absl::ZeroDuration()); bool callback_ran = false; my_connection->PerformConnection( - (http::verb::post), - "/redfish/v1/Systems/system/Actions/Power.Reset_never_write", - [&callback_ran](absl::StatusOr<nlohmann::json> jres){ - ASSERT_FALSE(jres.ok()); - ASSERT_EQ(jres.status(), absl::UnknownError( - "Callback error handler: The socket was closed due to a timeout")); - callback_ran = true; - }, {}); + (http::verb::post), + "/redfish/v1/Systems/system/Actions/Power.Reset_never_write", + [&callback_ran](absl::StatusOr<nlohmann::json> jres) { + ASSERT_FALSE(jres.ok()); + ASSERT_EQ(jres.status(), + absl::UnknownError("Callback error handler: The socket was " + "closed due to a timeout")); + callback_ran = true; + }, + {}); DaemonContextBMC::Get().get_io_context().run_for(std::chrono::seconds(1)); EXPECT_TRUE(callback_ran); } @@ -99,14 +108,16 @@ auto my_connection = std::make_shared<HttpConnection>(); bool callback_ran = false; my_connection->PerformConnection( - http::verb::post, - "/redfish/v1/Systems/system/Actions/Power.Reset_malformed", - [&callback_ran](absl::StatusOr<nlohmann::json> jres){ - ASSERT_FALSE(jres.ok()); - ASSERT_EQ(jres.status(), absl::InvalidArgumentError( - absl::StrCat("Failed to parse JSON from BMC: ", malformedJson))); - callback_ran = true; - }, {}); + http::verb::post, + "/redfish/v1/Systems/system/Actions/Power.Reset_malformed", + [&callback_ran](absl::StatusOr<nlohmann::json> jres) { + ASSERT_FALSE(jres.ok()); + ASSERT_EQ(jres.status(), absl::InvalidArgumentError(absl::StrCat( + "Failed to parse JSON from BMC: ", + mock_server_test::malformedJson))); + callback_ran = true; + }, + {}); DaemonContextBMC::Get().get_io_context().run_for(std::chrono::seconds(1)); EXPECT_TRUE(callback_ran); } @@ -119,14 +130,15 @@ auto my_connection = std::make_shared<HttpConnection>(); bool callback_ran = false; my_connection->PerformConnection( - http::verb::post, - "/redfish/v1/Systems/system/Actions/Power.Reset_NotFound", - [&callback_ran](absl::StatusOr<nlohmann::json> jres){ - ASSERT_FALSE(jres.ok()); - ASSERT_EQ(jres.status(), absl::UnavailableError( - "HTTP request failed with status: 404")); - callback_ran = true; - }, {}); + http::verb::post, + "/redfish/v1/Systems/system/Actions/Power.Reset_NotFound", + [&callback_ran](absl::StatusOr<nlohmann::json> jres) { + ASSERT_FALSE(jres.ok()); + ASSERT_EQ(jres.status(), absl::UnavailableError( + "HTTP request failed with status: 404")); + callback_ran = true; + }, + {}); DaemonContextBMC::Get().get_io_context().run_for(std::chrono::seconds(1)); EXPECT_TRUE(callback_ran); } @@ -139,19 +151,19 @@ auto my_connection = std::make_shared<HttpConnection>(); bool callback_ran = false; my_connection->PerformConnection( - http::verb::post, "/redfish/v1/Systems/system/Actions/Power.Reset", - [&callback_ran](absl::StatusOr<nlohmann::json> jres){ - ASSERT_TRUE(jres.ok()); - callback_ran = true; - nlohmann::json good = nlohmann::json::parse(goodJson); - ASSERT_EQ(jres.value(), good); - }, {}); + http::verb::post, "/redfish/v1/Systems/system/Actions/Power.Reset", + [&callback_ran](absl::StatusOr<nlohmann::json> jres) { + ASSERT_TRUE(jres.ok()); + callback_ran = true; + nlohmann::json good = nlohmann::json::parse(mock_server_test::goodJson); + ASSERT_EQ(jres.value(), good); + }, + {}); DaemonContextBMC::Get().get_io_context().run_for(std::chrono::seconds(1)); EXPECT_TRUE(callback_ran); } - // redfish Tests // redfish and http test both use mock server // but they can not run at the same time @@ -161,15 +173,14 @@ TestBoostServer my_server; my_server.Start(DaemonContextBMC::Get().get_io_context()); bool callback_ran = false; - Redfish::Get( - "/redfish/v1/Systems/system_get", - [&callback_ran](absl::StatusOr<nlohmann::json> jres){ - ASSERT_TRUE(jres.ok()); - nlohmann::json good = nlohmann::json::parse(goodSystemGet); - ASSERT_EQ(jres.value(), good); - callback_ran = true; - }); - + Redfish::Get("/redfish/v1/Systems/system_get", + [&callback_ran](absl::StatusOr<nlohmann::json> jres) { + ASSERT_TRUE(jres.ok()); + nlohmann::json good = + nlohmann::json::parse(mock_server_test::goodSystemGet); + ASSERT_EQ(jres.value(), good); + callback_ran = true; + }); DaemonContextBMC::Get().get_io_context().run_for(std::chrono::seconds(1)); EXPECT_TRUE(callback_ran); @@ -180,14 +191,14 @@ TestBoostServer my_server; my_server.Start(DaemonContextBMC::Get().get_io_context()); bool callback_ran = false; - Redfish::Get( - "/redfish/v1/Systems/system_NotFound", - [&callback_ran](absl::StatusOr<nlohmann::json> jres){ - ASSERT_FALSE(jres.ok()); - ASSERT_EQ(jres.status(), absl::UnavailableError( - "HTTP request failed with status: 404")); - callback_ran = true; - }); + Redfish::Get("/redfish/v1/Systems/system_NotFound", + [&callback_ran](absl::StatusOr<nlohmann::json> jres) { + ASSERT_FALSE(jres.ok()); + ASSERT_EQ(jres.status(), + absl::UnavailableError( + "HTTP request failed with status: 404")); + callback_ran = true; + }); DaemonContextBMC::Get().get_io_context().run_for(std::chrono::seconds(1)); EXPECT_TRUE(callback_ran); } @@ -202,44 +213,41 @@ GpowerdConfig gpower_config; auto state_monitor_config = gpower_config.add_state_monitor_config(); state_monitor_config->set_state_name("test_state"); - state_monitor_config->mutable_state_gathering_info()-> - set_collection_interval_ms(100); - state_monitor_config->mutable_state_gathering_info()->mutable_redfish()-> - set_uri("/redfish/v1/Systems/system/_testingPowerState"); + state_monitor_config->mutable_state_gathering_info() + ->set_collection_interval_ms(100); + state_monitor_config->mutable_state_gathering_info() + ->mutable_redfish() + ->set_uri("/redfish/v1/Systems/system/_testingPowerState"); // if the config file has a key, it should also have the corresponding state - std::vector<std::pair - <std::string, safepower_agent_proto::PowerStateSpecifier>> - json_key_to_state_name = { - {"PowerState_On", - safepower_agent_proto::POWER_STATE_ON }, - {"PowerState_Off", - safepower_agent_proto::POWER_STATE_OFF}, - {"PowerState_Paused", - safepower_agent_proto::POWER_STATE_PAUSED}, - {"PowerState_PoweringOn", - safepower_agent_proto::POWER_STATE_POWERING_ON}, - {"PowerState_PoweringOff", - safepower_agent_proto::POWER_STATE_POWERING_OFF}, - {"PowerState_UNSPECIFIED_1", - safepower_agent_proto::POWER_STATE_UNSPECIFIED}, - {"PowerState_UNSPECIFIED_2", - safepower_agent_proto::POWER_STATE_UNSPECIFIED}, - {"", - safepower_agent_proto::POWER_STATE_UNSPECIFIED}, - {"b", - safepower_agent_proto::POWER_STATE_UNSPECIFIED} - }; + std::vector< + std::pair<std::string, safepower_agent_proto::PowerStateSpecifier>> + json_key_to_state_name = { + {"PowerState_On", safepower_agent_proto::POWER_STATE_ON}, + {"PowerState_Off", safepower_agent_proto::POWER_STATE_OFF}, + {"PowerState_Paused", safepower_agent_proto::POWER_STATE_PAUSED}, + {"PowerState_PoweringOn", + safepower_agent_proto::POWER_STATE_POWERING_ON}, + {"PowerState_PoweringOff", + safepower_agent_proto::POWER_STATE_POWERING_OFF}, + {"PowerState_UNSPECIFIED_1", + safepower_agent_proto::POWER_STATE_UNSPECIFIED}, + {"PowerState_UNSPECIFIED_2", + safepower_agent_proto::POWER_STATE_UNSPECIFIED}, + {"", safepower_agent_proto::POWER_STATE_UNSPECIFIED}, + {"b", safepower_agent_proto::POWER_STATE_UNSPECIFIED}}; for (auto str_state_pair : json_key_to_state_name) { - state_monitor_config->mutable_state_gathering_info()-> - mutable_redfish()->set_json_key(str_state_pair.first); + state_monitor_config->mutable_state_gathering_info() + ->mutable_redfish() + ->set_json_key(str_state_pair.first); state_monitor_config->set_state_name(str_state_pair.first); state_monitor_config->mutable_system_component()->set_node_entity_tag("cn"); state_monitor_config->mutable_system_component()->set_name("PowerState"); - state_monitor_config->mutable_state_gathering_info()-> - mutable_prototype()->mutable_power_state()->set_state( - safepower_agent_proto::POWER_STATE_POWERING_OFF); + state_monitor_config->mutable_state_gathering_info() + ->mutable_prototype() + ->mutable_power_state() + ->set_state(safepower_agent_proto::POWER_STATE_POWERING_OFF); // build a new system state safepower_agent_proto::SystemState initialState; // set default power state @@ -258,27 +266,27 @@ std::move(initialState), true); // monitor new systemd state, with specific key StateMonitorBMC state_monitor(reactor); - ASSERT_EQ(state_monitor.BuildFromConfig(gpower_config), - absl::OkStatus()); - DaemonContextBMC::Get().get_io_context().run_for - (std::chrono::milliseconds(300)); + ASSERT_EQ(state_monitor.BuildFromConfig(gpower_config), absl::OkStatus()); + DaemonContextBMC::Get().get_io_context().run_for( + std::chrono::milliseconds(300)); // check the state monitor updates its reactor with the correct state - EXPECT_EQ(reactor->state().node_state().at("cn") - .component_state().at("PowerState").power_state().state(), + EXPECT_EQ(reactor->state() + .node_state() + .at("cn") + .component_state() + .at("PowerState") + .power_state() + .state(), str_state_pair.second); ASSERT_EQ(DaemonContextBMC::Get().scheduler().CancelAll(), absl::OkStatus()); - DaemonContextBMC::Get().get_io_context(). - run_for(std::chrono::milliseconds(300)); + DaemonContextBMC::Get().get_io_context().run_for( + std::chrono::milliseconds(300)); } - DaemonContextBMC::Get().get_io_context() - .run_for(std::chrono::milliseconds(1000)); + DaemonContextBMC::Get().get_io_context().run_for( + std::chrono::milliseconds(1000)); } - - - -} // namespace mock_server_test -} // namespace safepower_agent - +} // namespace +} // namespace safepower_agent
diff --git a/bmc/mock_server.h b/bmc/mock_server.h index cd7773e..ab04e06 100644 --- a/bmc/mock_server.h +++ b/bmc/mock_server.h
@@ -1,23 +1,22 @@ #ifndef PRODUCTION_SUSHID_SAFEPOWER_AGENT_BMC_MOCK_SERVER_H_ #define PRODUCTION_SUSHID_SAFEPOWER_AGENT_BMC_MOCK_SERVER_H_ -#include <absl/status/status.h> -#include <gmock/gmock.h> -#include <gtest/gtest.h> - - -#include <chrono> // NOLINT +#include <chrono> // NOLINT(build/c++11) +#include <cstdint> #include <cstdlib> #include <ctime> #include <iostream> #include <memory> #include <string> +#include <utility> -#include "boost/beast/core.hpp" // NOLINT -#include "boost/beast/http.hpp" // NOLINT -#include "boost/beast/version.hpp" // NOLINT -#include "boost/asio/io_context.hpp" // NOLINT - +// NOLINTBEGIN(readability/boost) +#include "absl/strings/string_view.h" +#include "boost/asio/io_context.hpp" +#include "boost/beast/core.hpp" +#include "boost/beast/http.hpp" +#include "boost/beast/version.hpp" +// NOLINTEND(readability/boost) namespace safepower_agent { namespace mock_server_test { @@ -27,13 +26,12 @@ // // using a boost http server to test the http client used in gpowerd +namespace beast = boost::beast; // from <boost/beast.hpp> +namespace http = beast::http; // from <boost/beast/http.hpp> +namespace net = boost::asio; // from <boost/asio.hpp> +using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp> -namespace beast = boost::beast; // from <boost/beast.hpp> -namespace http = beast::http; // from <boost/beast/http.hpp> -namespace net = boost::asio; // from <boost/asio.hpp> -using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp> - -std::string_view goodJson = R"( +constexpr absl::string_view goodJson = R"( { "@Message.ExtendedInfo": [ { @@ -47,7 +45,7 @@ ] })"; -std::string_view testingPowerStateJson = R"( +constexpr absl::string_view testingPowerStateJson = R"( { "@odata.id": "/redfish/v1/Systems/system", "@odata.type": "#ComputerSystem.v1_16_0.ComputerSystem", @@ -67,7 +65,7 @@ "PowerState_UNSPECIFIED_2": "a" })"; -std::string_view malformedJson = R"( +constexpr absl::string_view malformedJson = R"( "@Message.ExtendedInfo": "@odata.type": "#Message.v1_1_1.Message", "Message": "The request completed successfully.", @@ -79,7 +77,7 @@ ] })"; -std::string_view goodSystemGet = R"( +constexpr absl::string_view goodSystemGet = R"( { "@odata.id": "/redfish/v1/Chassis", "@odata.type": "#ChassisCollection.ChassisCollection", @@ -116,211 +114,180 @@ "Name": "Chassis Collection" })"; -class http_connection : public std::enable_shared_from_this<http_connection> -{ +class http_connection : public std::enable_shared_from_this<http_connection> { public: - http_connection(tcp::socket socket) - : socket_(std::move(socket)), skip_write_(false) - { - std::cerr <<"Test server connection made" << std::endl; - } + explicit http_connection(tcp::socket socket) + : socket_(std::move(socket)), skip_write_(false) { + std::cerr << "Test server connection made" << std::endl; + } - // Initiate the asynchronous operations associated with the connection. - void start() - { - read_request(); - check_deadline(); - } + // Initiate the asynchronous operations associated with the connection. + void start() { + read_request(); + check_deadline(); + } + private: - // The socket for the currently connected client. - tcp::socket socket_; + // The socket for the currently connected client. + tcp::socket socket_; - // The buffer for performing reads. - beast::flat_buffer buffer_{8192}; + // The buffer for performing reads. + beast::flat_buffer buffer_{8192}; - // The request message. - http::request<http::dynamic_body> request_; + // The request message. + http::request<http::dynamic_body> request_; - // The response message. - http::response<http::dynamic_body> response_; + // The response message. + http::response<http::dynamic_body> response_; - // The timer for putting a deadline on connection processing. - net::steady_timer deadline_{ - socket_.get_executor(), std::chrono::seconds(60)}; - // Asynchronously receive a complete request message. + // The timer for putting a deadline on connection processing. + net::steady_timer deadline_{socket_.get_executor(), std::chrono::seconds(60)}; + // Asynchronously receive a complete request message. - bool skip_write_; + bool skip_write_; - void read_request() - { - auto self = shared_from_this(); + void read_request() { + auto self = shared_from_this(); - http::async_read( - socket_, - buffer_, - request_, - [self](beast::error_code ec, - std::size_t bytes_transferred) - { - boost::ignore_unused(bytes_transferred); - if (!ec) - { - self->process_request(); - } - }); - } + http::async_read( + socket_, buffer_, request_, + [self](beast::error_code ec, std::size_t bytes_transferred) { + boost::ignore_unused(bytes_transferred); + if (!ec) { + self->process_request(); + } + }); + } - void process_request() - { - response_.version(request_.version()); - response_.keep_alive(false); + void process_request() { + response_.version(request_.version()); + response_.keep_alive(false); - switch (request_.method()) - { + switch (request_.method()) { case http::verb::post: - response_.result(http::status::ok); - response_.set(http::field::server, "Beast"); - response_.set(http::field::content_type, "text/plain"); - create_post_response(); - break; + response_.result(http::status::ok); + response_.set(http::field::server, "Beast"); + response_.set(http::field::content_type, "text/plain"); + create_post_response(); + break; case http::verb::get: - response_.result(http::status::ok); - response_.set(http::field::server, "Beast"); - create_get_response(); - break; + response_.result(http::status::ok); + response_.set(http::field::server, "Beast"); + create_get_response(); + break; default: - // We return responses indicating an error if - // we do not recognize the request method. - response_.result(http::status::bad_request); - response_.set(http::field::content_type, "text/plain"); - beast::ostream(response_.body()) - << "Invalid request-method '" - << std::string(request_.method_string()) - << "'"; - break; - } - if (!skip_write_){ - write_response(); + // We return responses indicating an error if + // we do not recognize the request method. + response_.result(http::status::bad_request); + response_.set(http::field::content_type, "text/plain"); + beast::ostream(response_.body()) + << "Invalid request-method '" + << std::string(request_.method_string()) << "'"; + break; + } + if (!skip_write_) { + write_response(); + } + } + // Construct a response message based on the program state. + void create_post_response() { + response_.set(http::field::content_type, "text/html"); + if (request_.target() == "/count") { + beast::ostream(response_.body()) << "count_answer"; + } else if (request_.target() == "/time") { + beast::ostream(response_.body()) << "time_answer"; + } else if (request_.target() == + "/redfish/v1/Systems/system/Actions/Power.Reset") { + beast::ostream(response_.body()) << goodJson; + } else if (request_.target() == + "/redfish/v1/Systems/system/Actions/Power.Reset_never_write") { + skip_write_ = true; + } else if (request_.target() == + "/redfish/v1/Systems/system/Actions/Power.Reset_malformed") { + beast::ostream(response_.body()) << malformedJson; + } else { + std::cerr << "request_.target():" << request_.target() << std::endl; + response_.result(http::status::not_found); + response_.set(http::field::content_type, "text/plain"); + beast::ostream(response_.body()) << "File not found\r\n"; + } + } + void create_get_response() { + if (request_.target() == "/count") { + response_.set(http::field::content_type, "text/html"); + beast::ostream(response_.body()) << "count_answer"; + } else if (request_.target() == "/redfish/v1/Systems/system_get") { + response_.set(http::field::content_type, "text/html"); + beast::ostream(response_.body()) << goodSystemGet; + } else if (request_.target() == + "/redfish/v1/Systems/system/_testingPowerState") { + beast::ostream(response_.body()) << testingPowerStateJson; + } else { + std::cerr << "request_.target():" << request_.target() << std::endl; + response_.result(http::status::not_found); + response_.set(http::field::content_type, "text/plain"); + beast::ostream(response_.body()) << "File not found\r\n"; + } + } + + // Asynchronously transmit the response message. + void write_response() { + auto self = shared_from_this(); + + response_.content_length(response_.body().size()); + + http::async_write(socket_, response_, + [self](beast::error_code ec, std::size_t) { + self->socket_.shutdown(tcp::socket::shutdown_send, ec); + self->deadline_.cancel(); + }); + } + + // Check whether we have spent enough time on this connection. + void check_deadline() { + auto self = shared_from_this(); + + deadline_.async_wait([self](beast::error_code ec) { + if (!ec) { + // Close socket to cancel any outstanding operation. + self->socket_.close(ec); } - } - // Construct a response message based on the program state. - void create_post_response() - { - response_.set(http::field::content_type, "text/html"); - if (request_.target() == "/count"){ - beast::ostream(response_.body()) - << "count_answer"; - } else if (request_.target() == "/time"){ - beast::ostream(response_.body()) - << "time_answer"; - } else if (request_.target() == - "/redfish/v1/Systems/system/Actions/Power.Reset"){ - beast::ostream(response_.body()) << goodJson; - } else if (request_.target() == - "/redfish/v1/Systems/system/Actions/Power.Reset_never_write"){ - skip_write_ = true; - } else if (request_.target() == - "/redfish/v1/Systems/system/Actions/Power.Reset_malformed"){ - beast::ostream(response_.body()) << malformedJson; - } else { - std::cerr << "request_.target():" << request_.target() << std::endl; - response_.result(http::status::not_found); - response_.set(http::field::content_type, "text/plain"); - beast::ostream(response_.body()) << "File not found\r\n"; - } - } - void create_get_response() - { - if (request_.target() == "/count") - { - response_.set(http::field::content_type, "text/html"); - beast::ostream(response_.body()) - << "count_answer"; - }else if (request_.target() == "/redfish/v1/Systems/system_get"){ - response_.set(http::field::content_type, "text/html"); - beast::ostream(response_.body()) << goodSystemGet; - }else if (request_.target() == - "/redfish/v1/Systems/system/_testingPowerState"){ - beast::ostream(response_.body()) << testingPowerStateJson; - }else{ - std::cerr << "request_.target():" << request_.target() << std::endl; - response_.result(http::status::not_found); - response_.set(http::field::content_type, "text/plain"); - beast::ostream(response_.body()) << "File not found\r\n"; - } - } - - // Asynchronously transmit the response message. - void write_response() - { - auto self = shared_from_this(); - - response_.content_length(response_.body().size()); - - http::async_write( - socket_, - response_, - [self](beast::error_code ec, std::size_t) - { - self->socket_.shutdown(tcp::socket::shutdown_send, ec); - self->deadline_.cancel(); - }); - } - - // Check whether we have spent enough time on this connection. - void check_deadline() - { - auto self = shared_from_this(); - - deadline_.async_wait( - [self](beast::error_code ec) - { - if (!ec) - { - // Close socket to cancel any outstanding operation. - self->socket_.close(ec); - } - }); - } + }); + } }; -void http_server(tcp::acceptor& acceptor, tcp::socket& socket) -{ - acceptor.async_accept(socket, - [&](beast::error_code ec) - { - if (!ec){ - std::make_shared<http_connection>(std::move(socket))->start(); - }else{ - std::cerr << "http_server error:" << ec.what() << std::endl; - } - http_server(acceptor, socket); +inline void http_server(tcp::acceptor& acceptor, tcp::socket& socket) { + acceptor.async_accept(socket, [&](beast::error_code ec) { + if (!ec) { + std::make_shared<http_connection>(std::move(socket))->start(); + } else { + std::cerr << "http_server error:" << ec.what() << std::endl; + } + http_server(acceptor, socket); }); } -class TestBoostServer -{ +class TestBoostServer { public: - std::shared_ptr<tcp::acceptor> acceptor_; - std::shared_ptr<tcp::socket> socket_; + std::shared_ptr<tcp::acceptor> acceptor_; + std::shared_ptr<tcp::socket> socket_; - void Start(boost::asio::io_context& io_ctx) - { - auto const address = net::ip::make_address("0.0.0.0"); - uint16_t const port = 80; - auto const doc_root = std::make_shared<std::string>("/redfish/v1/"); - boost::asio::ip::tcp::endpoint ep(address, port); + void Start(boost::asio::io_context& io_ctx) { + auto const address = net::ip::make_address("0.0.0.0"); + uint16_t const port = 80; + auto const doc_root = std::make_shared<std::string>("/redfish/v1/"); + boost::asio::ip::tcp::endpoint ep(address, port); - socket_ = std::make_shared<tcp::socket>(io_ctx); - acceptor_ = std::make_shared<tcp::acceptor>(io_ctx, ep); + socket_ = std::make_shared<tcp::socket>(io_ctx); + acceptor_ = std::make_shared<tcp::acceptor>(io_ctx, ep); - http_server(*acceptor_, *socket_); + http_server(*acceptor_, *socket_); } - ~TestBoostServer(){ - acceptor_->cancel(); - socket_->close(); + ~TestBoostServer() { + acceptor_->cancel(); + socket_->close(); } };
diff --git a/bmc/redfish.cc b/bmc/redfish.cc index 6740cc8..7af5570 100644 --- a/bmc/redfish.cc +++ b/bmc/redfish.cc
@@ -1,17 +1,16 @@ #include "bmc/redfish.h" -#include <nlohmann/json.hpp> -#include <safepower_agent.h> -#include <safepower_agent.pb.h> +#include <cstdint> +#include <memory> +#include <utility> #include "bmc/http_connection.h" - -#include "absl/strings/string_view.h" -#include "absl/status/statusor.h" #include "absl/functional/any_invocable.h" -#include "absl/log/log.h" - -#include "boost/asio/ip/tcp.hpp" // NOLINT +#include "absl/status/statusor.h" +#include "absl/strings/string_view.h" +#include "boost/asio/ip/tcp.hpp" // NOLINT(readability/boost) +#include "nlohmann/json.hpp" +#include "nlohmann/json_fwd.hpp" namespace safepower_agent { @@ -20,22 +19,14 @@ namespace beast = boost::beast; namespace http = beast::http; -void Get( - absl::string_view target, - absl::AnyInvocable - <void(absl::StatusOr<nlohmann::json>) && > - callback, - absl::string_view ip, - uint16_t port){ - auto connection = std::make_shared<HttpConnection>(); - connection->PerformConnection(http::verb::get, - target, - std::move(callback), - "", - ip, - port); - } +void Get(absl::string_view target, + absl::AnyInvocable<void(absl::StatusOr<nlohmann::json>) &&> callback, + absl::string_view ip, uint16_t port) { + auto connection = std::make_shared<HttpConnection>(); + connection->PerformConnection(http::verb::get, target, std::move(callback), + nlohmann::json{}, ip, port); +} -} // namespace Redfish +} // namespace Redfish -} // namespace safepower_agent +} // namespace safepower_agent
diff --git a/bmc/redfish.h b/bmc/redfish.h index a307ccd..5f7b81a 100644 --- a/bmc/redfish.h +++ b/bmc/redfish.h
@@ -1,29 +1,24 @@ #ifndef PRODUCTION_SUSHID_SAFEPOWER_AGENT_BMC_REDFISH_H_ #define PRODUCTION_SUSHID_SAFEPOWER_AGENT_BMC_REDFISH_H_ -#include <nlohmann/json.hpp> -#include <safepower_agent.pb.h> -#include <state_persistence.pb.h> +#include <cstdint> -#include "absl/strings/string_view.h" -#include "absl/status/statusor.h" #include "absl/functional/any_invocable.h" - -#include "boost/asio/ip/tcp.hpp" // NOLINT +#include "absl/status/statusor.h" +#include "absl/strings/string_view.h" +#include "boost/asio/ip/tcp.hpp" // NOLINT(readability/boost) +#include "nlohmann/json_fwd.hpp" namespace safepower_agent { namespace Redfish { -void Get(absl::string_view URI, - absl::AnyInvocable - <void(absl::StatusOr<nlohmann::json>) && > - callback, - absl::string_view ip = "127.0.0.1", - uint16_t port = 80); +void Get(absl::string_view target, + absl::AnyInvocable<void(absl::StatusOr<nlohmann::json>) &&> callback, + absl::string_view ip = "127.0.0.1", uint16_t port = 80); -} // namespace Redfish +} // namespace Redfish -} // namespace safepower_agent +} // namespace safepower_agent #endif // PRODUCTION_SUSHID_SAFEPOWER_AGENT_BMC_REDFISH_H_
diff --git a/bmc/state_monitor_bmc.cc b/bmc/state_monitor_bmc.cc index a25c0f3..da0d856 100644 --- a/bmc/state_monitor_bmc.cc +++ b/bmc/state_monitor_bmc.cc
@@ -1,193 +1,169 @@ #include "bmc/state_monitor_bmc.h" -#include <safepower_agent_config.pb.h> - -#include <any> -#include <filesystem> // NOLINT -#include <fstream> +#include <cstdint> +#include <memory> #include <string> -#include <unordered_map> -#include <utility> - -#include "nlohmann/json.hpp" -#include "absl/status/status.h" -#include "absl/status/statusor.h" -#include "absl/strings/string_view.h" - -#include "safepower_agent.pb.h" -#include "state_updater.h" - - -#include "bmc/redfish.h" -#include "absl/base/log_severity.h" -#include "absl/log/log.h" #include "bmc/daemon_context_bmc.h" +#include "bmc/redfish.h" +#include "safepower_agent.pb.h" +#include "safepower_agent_config.pb.h" +#include "state_updater.h" +#include "absl/log/log.h" +#include "absl/status/status.h" +#include "absl/strings/str_cat.h" +#include "absl/strings/str_format.h" +#include "absl/strings/string_view.h" +#include "absl/time/time.h" +#include "nlohmann/json.hpp" +#include "nlohmann/json_fwd.hpp" namespace safepower_agent { -using safepower_agent_config::SafePowerAgentConfig; using safepower_agent_config::GpowerdConfig; -using safepower_agent_config::StateMonitorConfig; using safepower_agent_config::StateGatheringInfo; -using safepower_agent_config::RedfishInfo; -using safepower_agent_config::DbusInfo; StateMonitorBMC::StateMonitorBMC( std::shared_ptr<StateUpdater<safepower_agent_proto::SystemState>> reactor) : reactor_(reactor) {} -absl::Status StateMonitorBMC::BuildFromConfig(const GpowerdConfig& config) -{ - for (auto& resource_to_monitor : config.state_monitor_config()){ +absl::Status StateMonitorBMC::BuildFromConfig(const GpowerdConfig& config) { + for (auto& resource_to_monitor : config.state_monitor_config()) { if (resource_to_monitor.state_gathering_info().info_case() == StateGatheringInfo::kRedfish) { std::string state_name = resource_to_monitor.state_name(); - std::string uri = resource_to_monitor.state_gathering_info() - .redfish().uri(); - std::string json_key = resource_to_monitor.state_gathering_info() - .redfish().json_key(); - std::string node_entity_tag = resource_to_monitor.system_component() - .node_entity_tag(); - std::string component_name = resource_to_monitor.system_component() - .name(); + std::string uri = + resource_to_monitor.state_gathering_info().redfish().uri(); + std::string json_key = + resource_to_monitor.state_gathering_info().redfish().json_key(); + std::string node_entity_tag = + resource_to_monitor.system_component().node_entity_tag(); + std::string component_name = + resource_to_monitor.system_component().name(); uint64_t collection_interval_ms = resource_to_monitor.state_gathering_info().collection_interval_ms(); - auto prototype = resource_to_monitor.state_gathering_info() - .prototype(); - if (prototype.has_power_state() - && (prototype.power_state().has_state())) { - // create bmcweb state monitor for power state - if (!CreateRedfishUpdatePowerState( - state_name, uri, json_key, collection_interval_ms, node_entity_tag, - component_name).ok()){ + auto prototype = resource_to_monitor.state_gathering_info().prototype(); + if (prototype.has_power_state() && + (prototype.power_state().has_state())) { + // create bmcweb state monitor for power state + if (!CreateRedfishUpdatePowerState(state_name, uri, json_key, + collection_interval_ms, + node_entity_tag, component_name) + .ok()) { LOG(ERROR) << "failed to create bmcweb state monitor for: " - << state_name; - return absl::InvalidArgumentError - ("failed to create bmcweb state monitor for: " + state_name); + << state_name; + return absl::InvalidArgumentError( + "failed to create bmcweb state monitor for: " + state_name); } } else { LOG(ERROR) << "update function is not supported TODO b/372971177"; return absl::UnimplementedError("update function is not supported "); } - } else if (resource_to_monitor.state_gathering_info().info_case() == - StateGatheringInfo::kDbus) { - (void)CreateDbusStateMonitor("", "", "", "", "", 1000); + } else if (resource_to_monitor.state_gathering_info().info_case() == + StateGatheringInfo::kDbus) { + (void)CreateDbusStateMonitor("", "", "", "", "", 1000); } else { LOG(ERROR) << "state monitor type is not supported; " << resource_to_monitor.state_gathering_info().info_case(); - return absl::InvalidArgumentError - ("state monitor type is not supported: " + - resource_to_monitor.state_gathering_info().info_case()); + return absl::InvalidArgumentError( + absl::StrCat("state monitor type is not supported: ", + resource_to_monitor.state_gathering_info().info_case())); } } return absl::OkStatus(); } absl::Status StateMonitorBMC::CreateRedfishUpdatePowerState( - std::string state_name, - std::string uri, - std::string json_key, - int collection_interval_ms, - std::string node_entity_tag, - std::string component_name) - { + std::string state_name, std::string uri, std::string json_key, + int collection_interval_ms, std::string node_entity_tag, + std::string component_name) { LOG(INFO) << "creating bmcweb state monitor for:" << state_name; LOG(INFO) << "uri: " << uri; LOG(INFO) << "json_key: " << json_key; LOG(INFO) << "collection_interval_ms: " << collection_interval_ms; - return DaemonContextBMC::Get().scheduler().PeriodicCall( [state_name, uri, json_key, this, node_entity_tag, component_name] { - Redfish::Get(uri, - [state_name, uri, json_key, this, - node_entity_tag, component_name] - (absl::StatusOr<nlohmann::json> js) { - if (!js.ok()) { - LOG(ERROR) << "Failed to get " << uri << " from BMC: " - << js.status(); - return; - } - - auto js_value = js->find(json_key); - std::string state_str = js_value != js->end() ? *js_value : ""; - safepower_agent_proto::PowerStateSpecifier temp_power_state - = ConvertStatePowerStringToEnum(state_str); - const safepower_agent_proto::SystemState current_state - = this->reactor_->state(); - - safepower_agent_proto::PowerStateSpecifier last_ps = - safepower_agent_proto::POWER_STATE_UNSPECIFIED; - auto node_it = current_state.node_state().find(node_entity_tag); - if (node_it != current_state.node_state().end()){ - auto component_it = node_it->second.component_state(). - find(component_name); - if (component_it != node_it->second.component_state().end()){ - last_ps = component_it->second.power_state().state(); + Redfish::Get(uri, [state_name, uri, json_key, this, node_entity_tag, + component_name](absl::StatusOr<nlohmann::json> js) { + if (!js.ok()) { + LOG(ERROR) << "Failed to get " << uri + << " from BMC: " << js.status(); + return; } - } - if (last_ps == temp_power_state) return; - absl::string_view last_ps_str = - PowerStateSpecifier_Name(last_ps); - absl::string_view temp_ps_str = - PowerStateSpecifier_Name(temp_power_state); - LOG(INFO) << absl::StrFormat( - "state changed from: %d (%s) to: %d (%s)", last_ps, - last_ps_str, temp_power_state, temp_ps_str); - // add new state power state to a new system proto - safepower_agent_proto::SystemState new_state; - safepower_agent_proto::PowerState ps; - ps.set_state(temp_power_state); + auto js_value = js->find(json_key); + std::string state_str = js_value != js->end() ? *js_value : ""; + safepower_agent_proto::PowerStateSpecifier temp_power_state = + ConvertStatePowerStringToEnum(state_str); + const safepower_agent_proto::SystemState current_state = + this->reactor_->state(); - safepower_agent_proto::ComponentState cs; - *(cs.mutable_power_state()) = ps; + safepower_agent_proto::PowerStateSpecifier last_ps = + safepower_agent_proto::POWER_STATE_UNSPECIFIED; + auto node_it = current_state.node_state().find(node_entity_tag); + if (node_it != current_state.node_state().end()) { + auto component_it = + node_it->second.component_state().find(component_name); + if (component_it != node_it->second.component_state().end()) { + last_ps = component_it->second.power_state().state(); + } + } + if (last_ps == temp_power_state) return; + absl::string_view last_ps_str = PowerStateSpecifier_Name(last_ps); + absl::string_view temp_ps_str = + PowerStateSpecifier_Name(temp_power_state); + LOG(INFO) << absl::StrFormat( + "state changed from: %d (%s) to: %d (%s)", last_ps, last_ps_str, + temp_power_state, temp_ps_str); - safepower_agent_proto::NodeState ns; - ns.mutable_component_state()->insert({component_name, cs}); - new_state.mutable_node_state()->insert({node_entity_tag, ns}); + // add new state power state to a new system proto + safepower_agent_proto::SystemState new_state; + safepower_agent_proto::PowerState ps; + ps.set_state(temp_power_state); - reactor_->UpdateState(new_state); - }); + safepower_agent_proto::ComponentState cs; + *(cs.mutable_power_state()) = ps; + + safepower_agent_proto::NodeState ns; + ns.mutable_component_state()->insert({component_name, cs}); + new_state.mutable_node_state()->insert({node_entity_tag, ns}); + + reactor_->UpdateState(new_state); + }); }, absl::Milliseconds(collection_interval_ms), state_name); } safepower_agent_proto::PowerStateSpecifier - StateMonitorBMC::ConvertStatePowerStringToEnum(absl::string_view state_str){ - if (state_str == "On") { - return safepower_agent_proto::POWER_STATE_ON; - } else if (state_str == "Off") { - return safepower_agent_proto::POWER_STATE_OFF; - } else if (state_str == "Paused"){ // not in bmcweb - return safepower_agent_proto::POWER_STATE_PAUSED; - } else if (state_str == "PoweringOn") { - return safepower_agent_proto::POWER_STATE_POWERING_ON; - } else if (state_str == "PoweringOff") { - return safepower_agent_proto::POWER_STATE_POWERING_OFF; - } else { - LOG(ERROR) << "failed to map power state string to enum: " - << state_str; - return safepower_agent_proto::POWER_STATE_UNSPECIFIED; - } +StateMonitorBMC::ConvertStatePowerStringToEnum(absl::string_view state_str) { + if (state_str == "On") { + return safepower_agent_proto::POWER_STATE_ON; + } else if (state_str == "Off") { + return safepower_agent_proto::POWER_STATE_OFF; + } else if (state_str == "Paused") { // not in bmcweb + return safepower_agent_proto::POWER_STATE_PAUSED; + } else if (state_str == "PoweringOn") { + return safepower_agent_proto::POWER_STATE_POWERING_ON; + } else if (state_str == "PoweringOff") { + return safepower_agent_proto::POWER_STATE_POWERING_OFF; + } else { + LOG(ERROR) << "failed to map power state string to enum: " << state_str; + return safepower_agent_proto::POWER_STATE_UNSPECIFIED; + } } -absl::Status StateMonitorBMC::CreateDbusStateMonitor(std::string state_name, - std::string dbus_path, - std::string dbus_method, - std::string dbus_interface, - std::string dbus_value, - int collection_interval_ms) - { +absl::Status StateMonitorBMC::CreateDbusStateMonitor( + std::string state_name, std::string dbus_path, std::string dbus_method, + std::string dbus_interface, std::string dbus_value, + int collection_interval_ms) { LOG(INFO) << "creating dbus state monitor for:" << state_name; LOG(INFO) << "dbus_path: " << dbus_path; LOG(INFO) << "dbus_method: " << dbus_method; LOG(INFO) << "dbus_interface: " << dbus_interface; LOG(INFO) << "dbus_value: " << dbus_value; LOG(INFO) << "collection_interval_ms: " << collection_interval_ms; - return absl::UnimplementedError - ("CreateDbusStateMonitor is not implemented"); + return absl::UnimplementedError("CreateDbusStateMonitor is not implemented"); } } // namespace safepower_agent
diff --git a/bmc/state_monitor_bmc.h b/bmc/state_monitor_bmc.h index 618268d..9ae35f6 100644 --- a/bmc/state_monitor_bmc.h +++ b/bmc/state_monitor_bmc.h
@@ -1,24 +1,22 @@ #ifndef PRODUCTION_SUSHID_SAFEPOWER_AGENT_BMC_STATE_MONITOR_BMC_H_ #define PRODUCTION_SUSHID_SAFEPOWER_AGENT_BMC_STATE_MONITOR_BMC_H_ -#include <safepower_agent_config.pb.h> -#include <any> +#include <memory> #include <string> -#include <unordered_map> -#include "absl/strings/string_view.h" -#include "absl/status/status.h" -#include "absl/status/statusor.h" - -#include "state_updater.h" #include "safepower_agent.pb.h" +#include "safepower_agent_config.pb.h" +#include "state_updater.h" +#include "absl/status/status.h" +#include "absl/strings/string_view.h" namespace safepower_agent { class StateMonitorBMC { public: - StateMonitorBMC( - std::shared_ptr<StateUpdater<safepower_agent_proto::SystemState>> reactor); + explicit StateMonitorBMC( + std::shared_ptr<StateUpdater<safepower_agent_proto::SystemState>> + reactor); ~StateMonitorBMC() = default; absl::Status BuildFromConfig(