| #include "tlbmc/redfish/routes/cable.h" |
| |
| #include <algorithm> |
| #include <functional> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include "absl/functional/bind_front.h" |
| #include "absl/log/log.h" |
| #include "absl/status/statusor.h" |
| #include "absl/strings/str_cat.h" |
| #include "absl/strings/str_format.h" |
| #include "absl/strings/string_view.h" |
| #include "nlohmann/json.hpp" |
| #include "topology_config.pb.h" |
| #include "tlbmc/redfish/app.h" |
| #include "tlbmc/redfish/data/stable_id.h" |
| #include "stable_id.pb.h" |
| #include "tlbmc/redfish/request.h" |
| #include "tlbmc/redfish/response.h" |
| #include "tlbmc/redfish/url.h" |
| #include "fru.pb.h" |
| #include "resource.pb.h" |
| #include "tlbmc/store/store.h" |
| |
| namespace milotic_tlbmc::cable { |
| |
| void HandleCableCollection(const RedfishApp& app, const RedfishRequest& req, |
| RedfishResponse& resp) { |
| resp.SetKeyInJsonBody("/@odata.id", "/redfish/v1/Cables"); |
| resp.SetKeyInJsonBody("/@odata.type", "#CableCollection.CableCollection"); |
| resp.SetKeyInJsonBody("/Name", "Cable Collection"); |
| |
| const Store& store = *app.GetStore(); |
| absl::StatusOr<std::vector<std::string>> config_keys = |
| store.GetAllConfigKeys(); |
| if (!config_keys.ok()) { |
| resp.SetToAbslStatus(config_keys.status()); |
| return; |
| } |
| |
| std::vector<std::string> cable_names; |
| for (const std::string& name : *config_keys) { |
| absl::StatusOr<std::string> fru_key = store.GetFruKeyByConfigKey(name); |
| if (!fru_key.ok()) { |
| continue; |
| } |
| absl::StatusOr<const Fru*> fru = store.GetFru(*fru_key); |
| if (!fru.ok() || |
| (*fru)->attributes().resource_type() != RESOURCE_TYPE_CABLE) { |
| continue; |
| } |
| cable_names.push_back(name); |
| } |
| std::sort(cable_names.begin(), cable_names.end()); |
| |
| nlohmann::json::array_t members; |
| for (const auto& name : cable_names) { |
| nlohmann::json::object_t member; |
| member["@odata.id"] = absl::StrCat("/redfish/v1/Cables/", name); |
| members.push_back(std::move(member)); |
| } |
| resp.SetKeyInJsonBody("/Members", members); |
| resp.SetKeyInJsonBody("/Members@odata.count", members.size()); |
| } |
| |
| void HandleCable(const RedfishApp& app, const RedfishRequest& req, |
| RedfishResponse& resp, absl::string_view cable_id) { |
| const Store& store = *app.GetStore(); |
| absl::StatusOr<std::string> fru_key = store.GetFruKeyByConfigKey(cable_id); |
| if (!fru_key.ok()) { |
| resp.SetToAbslStatus(fru_key.status()); |
| return; |
| } |
| absl::StatusOr<const Fru*> fru = store.GetFru(*fru_key); |
| if (!fru.ok()) { |
| resp.SetToAbslStatus(fru.status()); |
| return; |
| } |
| absl::StatusOr<const TopologyConfigNode*> topology_config_node = |
| store.GetFruTopology(cable_id); |
| if (!topology_config_node.ok()) { |
| resp.SetToAbslStatus(topology_config_node.status()); |
| return; |
| } |
| |
| FillResponseWithCableData(nlohmann::json::json_pointer(""), *fru, |
| *topology_config_node, resp); |
| } |
| |
| void FillResponseWithCableData( |
| const nlohmann::json::json_pointer& cable_ptr, const Fru* cable_fru_ptr, |
| const TopologyConfigNode* topology_config_node_ptr, RedfishResponse& resp) { |
| const std::string& cable_name = topology_config_node_ptr->name(); |
| |
| if (cable_fru_ptr->attributes().status() != STATUS_READY) { |
| resp.SetToNotReady( |
| absl::StrFormat("Cable %s is not ready in tlBMC Store", cable_name)); |
| return; |
| } |
| resp.SetKeyInJsonBody(cable_ptr / "@odata.id", |
| CreateUrl({"redfish", "v1", "Cables", cable_name})); |
| resp.SetKeyInJsonBody(cable_ptr / "@odata.type", "#Cable.v1_2_4.Cable"); |
| resp.SetKeyInJsonBody(cable_ptr / "Id", cable_name); |
| resp.SetKeyInJsonBody(cable_ptr / "Name", cable_name); |
| |
| nlohmann::json::array_t downstream_chassis; |
| for (const std::string& chassis_id : |
| topology_config_node_ptr->children_chassis_ids()) { |
| nlohmann::json::object_t downstream_chassis_obj; |
| downstream_chassis_obj["@odata.id"] = |
| CreateUrl({"redfish", "v1", "Chassis", chassis_id}); |
| downstream_chassis.emplace_back(std::move(downstream_chassis_obj)); |
| } |
| resp.SetKeyInJsonBody(cable_ptr / "Links" / "DownstreamChassis", |
| downstream_chassis); |
| resp.SetKeyInJsonBody(cable_ptr / "Links" / "DownstreamChassis@odata.count", |
| downstream_chassis.size()); |
| |
| nlohmann::json::array_t upstream_chassis; |
| for (const auto& chassis_id : |
| topology_config_node_ptr->parent_chassis_ids()) { |
| nlohmann::json::object_t upstream_chassis_obj; |
| upstream_chassis_obj["@odata.id"] = |
| CreateUrl({"redfish", "v1", "Chassis", chassis_id}); |
| upstream_chassis.emplace_back(std::move(upstream_chassis_obj)); |
| } |
| resp.SetKeyInJsonBody(cable_ptr / "Links" / "UpstreamChassis", |
| upstream_chassis); |
| resp.SetKeyInJsonBody(cable_ptr / "Links" / "UpstreamChassis@odata.count", |
| upstream_chassis.size()); |
| |
| StableId stable_id = GetStableId(*topology_config_node_ptr); |
| if (!stable_id.service_label().empty()) { |
| resp.SetKeyInJsonBody( |
| cable_ptr / "Location" / "PartLocation" / "ServiceLabel", |
| stable_id.service_label()); |
| } |
| if (!stable_id.part_location_context().empty() && |
| stable_id.part_location_context() != "phys") { |
| resp.SetKeyInJsonBody(cable_ptr / "Location" / "PartLocationContext", |
| stable_id.part_location_context()); |
| } |
| if (stable_id.has_location_type()) { |
| absl::string_view location_type; |
| switch (stable_id.location_type()) { |
| case PART_LOCATION_TYPE_CONNECTOR: |
| location_type = "Connector"; |
| break; |
| case PART_LOCATION_TYPE_BACKPLANE: |
| case PART_LOCATION_TYPE_BAY: |
| case PART_LOCATION_TYPE_EMBEDDED: |
| case PART_LOCATION_TYPE_SLOT: |
| case PART_LOCATION_TYPE_SOCKET: |
| default: |
| LOG(WARNING) << "Unsupported location type for cable: " |
| << stable_id.location_type(); |
| break; |
| } |
| if (!location_type.empty()) { |
| resp.SetKeyInJsonBody( |
| cable_ptr / "Location" / "PartLocation" / "LocationType", |
| location_type); |
| } |
| } |
| |
| resp.SetKeyInJsonBody(cable_ptr / "Status" / "Health", "OK"); |
| resp.SetKeyInJsonBody(cable_ptr / "Status" / "State", "Enabled"); |
| } |
| |
| void RegisterRoutes(RedfishApp& app) { |
| TLBMC_ROUTE(app, "/redfish/v1/Cables/") |
| .methods(boost::beast::http::verb::get)( |
| absl::bind_front(HandleCableCollection, std::cref(app))); |
| TLBMC_ROUTE(app, "/redfish/v1/Cables/<str>/") |
| .methods(boost::beast::http::verb::get)( |
| absl::bind_front(HandleCable, std::cref(app))); |
| } |
| |
| } // namespace milotic_tlbmc::cable |