Implement indicator LED control in Redfish routes PiperOrigin-RevId: 975965402 Change-Id: Ic3e62ab3e0eb665164c98ea6c63d3f9e6d32a24b
diff --git a/tlbmc/redfish/routes/all_routes.cc b/tlbmc/redfish/routes/all_routes.cc index afaf813..9324be4 100644 --- a/tlbmc/redfish/routes/all_routes.cc +++ b/tlbmc/redfish/routes/all_routes.cc
@@ -111,6 +111,9 @@ PowerControlType::POWER_CONTROL_TYPE_GPIO)) { system::RegisterAppendModeRoutes(app); } + if (GetTlbmcConfig().led_collector_module().enabled()) { + system::RegisterIndicatorRoutes(app); + } if (GetTlbmcConfig().fru_collector_module().own_assemblies_in_redfish()) { assembly::RegisterRoutes(app); }
diff --git a/tlbmc/redfish/routes/chassis.cc b/tlbmc/redfish/routes/chassis.cc index d2a4ddc..b3597ac 100644 --- a/tlbmc/redfish/routes/chassis.cc +++ b/tlbmc/redfish/routes/chassis.cc
@@ -17,7 +17,9 @@ #include <nlohmann/json_fwd.hpp> #include "json_utils.h" #include "tlbmc/central_config/config.h" +#include "tlbmc/collector/led_collector.h" #include "tlbmc/collector/power_control_collector.h" +#include "led_config.pb.h" #include "power_control.pb.h" #include "topology_config.pb.h" #include "tlbmc/redfish/app.h" @@ -34,6 +36,9 @@ namespace milotic_tlbmc::chassis { +using ::milotic::authz::GetValueAsBool; +using ::milotic::authz::GetValueAsString; + namespace { void HandleChassisCollection(const RedfishApp& app, const RedfishRequest& req, @@ -170,6 +175,45 @@ } return child_resources; } + +// Injects the IndicatorLED and LocationIndicatorActive properties into the +// chassis Redfish response if an indicator LED is configured. +void InjectIndicatorLed(const Store& store, + const nlohmann::json::json_pointer& chassis_pointer, + RedfishResponse& resp) { + LedCollector* led_collector = store.GetLedCollector(); + if (led_collector == nullptr) { + return; + } + if (!led_collector->HasIndicatorConfig()) { + return; + } + if (absl::StatusOr<LedState> state = led_collector->GetIndicatorState(); + state.ok()) { + switch (*state) { + case LED_STATE_ON: + resp.SetKeyInJsonBody(chassis_pointer / "IndicatorLED", "Lit"); + resp.SetKeyInJsonBody(chassis_pointer / "LocationIndicatorActive", + true); + break; + case LED_STATE_BLINK: + resp.SetKeyInJsonBody(chassis_pointer / "IndicatorLED", "Blinking"); + resp.SetKeyInJsonBody(chassis_pointer / "LocationIndicatorActive", + true); + break; + case LED_STATE_OFF: + resp.SetKeyInJsonBody(chassis_pointer / "IndicatorLED", "Off"); + resp.SetKeyInJsonBody(chassis_pointer / "LocationIndicatorActive", + false); + break; + case LED_STATE_UNSPECIFIED: + default: + resp.SetKeyInJsonBody(chassis_pointer / "IndicatorLED", "Unknown"); + break; + } + } +} + } // namespace void FillResponseWithFruData( @@ -532,6 +576,8 @@ systems); } + InjectIndicatorLed(store, chassis_pointer, resp); + resp.SetKeyInJsonBody(chassis_pointer / "Status" / "Health", "OK"); resp.SetKeyInJsonBody(chassis_pointer / "Status" / "HealthRollup", "OK"); resp.SetKeyInJsonBody(chassis_pointer / "Status" / "State", "Enabled"); @@ -705,10 +751,78 @@ resp.SetKeyInJsonBody("/Parameters", parameters); } +// Handles PATCH requests to update the indicator LED state on a Chassis +// resource. +void HandleChassisPatch(const RedfishApp& app, const RedfishRequest& req, + RedfishResponse& resp, + const std::string& /*chassis_id*/) { + const Store* store = app.GetStore(); + if (store == nullptr) { + resp.SetToInternalError("Store is null"); + return; + } + + LedCollector* led_collector = store->GetLedCollector(); + if (led_collector == nullptr) { + resp.SetToNoContent(); + return; + } + if (!led_collector->HasIndicatorConfig()) { + resp.SetToNoContent(); + return; + } + + nlohmann::json req_json = nlohmann::json::parse(req.Body(), nullptr, false); + if (req_json.is_discarded()) { + resp.SetToBadRequest("Failed to parse request body"); + return; + } + + const std::string* indicator_led = GetValueAsString(req_json, "IndicatorLED"); + const bool* location_indicator_active = + GetValueAsBool(req_json, "LocationIndicatorActive"); + + if (indicator_led == nullptr && location_indicator_active == nullptr) { + resp.SetToNoContent(); + return; + } + + absl::Status status = absl::OkStatus(); + if (indicator_led != nullptr) { + if (*indicator_led == "Lit") { + status = led_collector->SetIndicatorState(LED_STATE_ON); + } else if (*indicator_led == "Blinking") { + status = led_collector->SetIndicatorState(LED_STATE_BLINK); + } else if (*indicator_led == "Off") { + status = led_collector->SetIndicatorState(LED_STATE_OFF); + } else { + resp.SetToBadRequest("Invalid IndicatorLED value"); + return; + } + } else if (location_indicator_active != nullptr) { + if (*location_indicator_active) { + status = led_collector->SetIndicatorState(LED_STATE_BLINK); + } else { + status = led_collector->SetIndicatorState(LED_STATE_OFF); + } + } + + if (!status.ok()) { + LOG(ERROR) << "Failed to set indicator LED: " << status; + resp.SetToInternalError("Failed to set indicator LED"); + return; + } + + resp.SetToNoContent(); +} + void RegisterRoutes(RedfishApp& app) { TLBMC_ROUTE(app, "/redfish/v1/Chassis/<str>/") .methods(boost::beast::http::verb::get)( absl::bind_front(HandleChassis, std::cref(app))); + TLBMC_ROUTE(app, "/redfish/v1/Chassis/<str>/") + .methods(boost::beast::http::verb::patch)( + absl::bind_front(HandleChassisPatch, std::cref(app))); if (GetTlbmcConfig().fru_collector_module().enabled() && GetTlbmcConfig() .fru_collector_module()
diff --git a/tlbmc/redfish/routes/system.cc b/tlbmc/redfish/routes/system.cc index 3ac43d4..5cc12db 100644 --- a/tlbmc/redfish/routes/system.cc +++ b/tlbmc/redfish/routes/system.cc
@@ -19,7 +19,9 @@ #include "async_resp.hpp" #include <nlohmann/json.hpp> #include "json_utils.h" +#include "tlbmc/collector/led_collector.h" #include "tlbmc/collector/power_control_collector.h" +#include "led_config.pb.h" #include "power_control.pb.h" #include "tlbmc/host_state/power_control.h" #include "tlbmc/redfish/app.h" @@ -33,11 +35,10 @@ namespace milotic_tlbmc::system { +using ::milotic::authz::GetValueAsBool; using ::milotic::authz::GetValueAsString; using ::milotic::authz::GetValueAsUintFromStringOrInteger; - - void HandleSystemReset(const RedfishApp& app, const RedfishRequest& req, RedfishResponse& resp, const std::string& system_id) { LOG(INFO) << "HandleSystemReset: " << system_id; @@ -155,6 +156,105 @@ InjectBiosKeyMetrics(*store, json); } +// Appends indicator LED properties (IndicatorLED, LocationIndicatorActive) +// to the GET response of a System resource if an indicator LED is configured. +void HandleSystemIndicatorGetAfterGbmcweb( + const RedfishApp& app, const ::crow::Request& /*request*/, + const std::shared_ptr<bmcweb::AsyncResp>& async_resp, + const std::string& system_id) { + const Store* store = app.GetStore(); + LedCollector* led_collector = store->GetLedCollector(); + if (led_collector == nullptr) { + return; + } + if (!led_collector->HasIndicatorConfig(system_id)) { + return; + } + if (absl::StatusOr<LedState> state = + led_collector->GetIndicatorState(system_id); + state.ok()) { + nlohmann::json& json = async_resp->res.jsonValue; + switch (*state) { + case LED_STATE_ON: + json["IndicatorLED"] = "Lit"; + json["LocationIndicatorActive"] = true; + break; + case LED_STATE_BLINK: + json["IndicatorLED"] = "Blinking"; + json["LocationIndicatorActive"] = true; + break; + case LED_STATE_OFF: + json["IndicatorLED"] = "Off"; + json["LocationIndicatorActive"] = false; + break; + case LED_STATE_UNSPECIFIED: + default: + json["IndicatorLED"] = "Unknown"; + break; + } + } +} + +// Handles append-mode PATCH requests to update the indicator LED state on a +// System resource. +void HandleSystemIndicatorPatchAfterGbmcweb( + const RedfishApp& app, const ::crow::Request& request, + const std::shared_ptr<bmcweb::AsyncResp>& async_resp, + const std::string& system_id) { + const Store* store = app.GetStore(); + LedCollector* led_collector = store->GetLedCollector(); + if (led_collector == nullptr) { + return; + } + if (!led_collector->HasIndicatorConfig(system_id)) { + return; + } + + nlohmann::json req_json = + nlohmann::json::parse(request.body(), nullptr, false); + if (req_json.is_discarded()) { + return; + } + + const std::string* indicator_led = GetValueAsString(req_json, "IndicatorLED"); + const bool* location_indicator_active = + GetValueAsBool(req_json, "LocationIndicatorActive"); + + if (indicator_led == nullptr && location_indicator_active == nullptr) { + return; + } + + absl::Status status = absl::OkStatus(); + if (indicator_led != nullptr) { + if (*indicator_led == "Lit") { + status = led_collector->SetIndicatorState(system_id, LED_STATE_ON); + } else if (*indicator_led == "Blinking") { + status = led_collector->SetIndicatorState(system_id, LED_STATE_BLINK); + } else if (*indicator_led == "Off") { + status = led_collector->SetIndicatorState(system_id, LED_STATE_OFF); + } else { + async_resp->res.result(boost::beast::http::status::bad_request); + return; + } + } else if (location_indicator_active != nullptr) { + if (*location_indicator_active) { + status = led_collector->SetIndicatorState(system_id, LED_STATE_BLINK); + } else { + status = led_collector->SetIndicatorState(system_id, LED_STATE_OFF); + } + } + + if (!status.ok()) { + LOG(ERROR) << "Failed to set indicator LED: " << status; + async_resp->res.result(boost::beast::http::status::internal_server_error); + return; + } + + if (async_resp->res.result() == boost::beast::http::status::ok) { + async_resp->res.result(boost::beast::http::status::no_content); + } +} + void RegisterResetRoutes(RedfishApp& app) { TLBMC_ROUTE(app, "/redfish/v1/Systems/<str>/Actions/ComputerSystem.Reset/") .methods(boost::beast::http::verb::post)( @@ -172,4 +272,15 @@ absl::bind_front(HandleSystemGetAfterGbmcweb, std::cref(app))); } +void RegisterIndicatorRoutes(RedfishApp& app) { + TLBMC_APPEND_GBMCWEB( + app.GetSmartRouter(), "/redfish/v1/Systems/<str>/", + boost::beast::http::verb::get, + absl::bind_front(HandleSystemIndicatorGetAfterGbmcweb, std::cref(app))); + TLBMC_APPEND_GBMCWEB( + app.GetSmartRouter(), "/redfish/v1/Systems/<str>/", + boost::beast::http::verb::patch, + absl::bind_front(HandleSystemIndicatorPatchAfterGbmcweb, std::cref(app))); +} + } // namespace milotic_tlbmc::system
diff --git a/tlbmc/redfish/routes/system.h b/tlbmc/redfish/routes/system.h index dc53b3f..43d7aab 100644 --- a/tlbmc/redfish/routes/system.h +++ b/tlbmc/redfish/routes/system.h
@@ -10,6 +10,10 @@ void RegisterAppendModeRoutes(RedfishApp& app); +// Registers append-mode routes for system indicator LEDs +// (GET and PATCH handlers on /redfish/v1/Systems/<str>/). +void RegisterIndicatorRoutes(RedfishApp& app); + } // namespace milotic_tlbmc::system #endif // THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_REDFISH_ROUTES_SYSTEM_H_