| #include "redfish_devpath_injector.hpp" | |
| #include <fstream> | |
| #include <memory> | |
| #include <sstream> | |
| #include <string> | |
| #include <string_view> | |
| #include "absl/status/status.h" | |
| #include "absl/status/statusor.h" | |
| #include "absl/strings/str_cat.h" | |
| #include "boost/beast/http/status.hpp" // NOLINT | |
| #include "boost/beast/http/verb.hpp" // NOLINT | |
| #include "g3/macros.h" | |
| #include "redfish_to_uhm_mapping.pb.h" | |
| #include "redfish_to_uhm_mapping_value.hpp" | |
| #include "http_request.hpp" | |
| #include <nlohmann/json.hpp> | |
| #include "topology_config.pb.h" | |
| #include "tlbmc/redfish/data/stable_id.h" | |
| #include "stable_id.pb.h" | |
| #include "google/protobuf/text_format.h" | |
| namespace devpath_plugin { | |
| namespace { | |
| absl::StatusOr<std::string> ReadFileToString(std::string_view path) { | |
| std::ifstream input(std::string{path}); | |
| if (!input.is_open()) { | |
| return absl::NotFoundError( | |
| absl::StrCat("Failed to open RedfishToUhmMapping file at: ", path)); | |
| } | |
| std::stringstream buffer; | |
| buffer << input.rdbuf(); | |
| return buffer.str(); | |
| } | |
| } // namespace | |
| absl::StatusOr<std::unique_ptr<RedfishDevpathInjector>> | |
| RedfishDevpathInjector::Create(std::string_view mapping_config_path) { | |
| ECCLESIA_ASSIGN_OR_RETURN(std::string config_content, | |
| ReadFileToString(mapping_config_path)); | |
| RedfishToUhmMappingConfig config; | |
| if (!google::protobuf::TextFormat::ParseFromString(config_content, &config)) { | |
| return absl::InvalidArgumentError(absl::StrCat( | |
| "Failed to parse RedfishToUhmMappingConfig textproto from: ", | |
| mapping_config_path)); | |
| } | |
| // new keyword required to access private constructor | |
| std::unique_ptr<RedfishDevpathInjector> injector( | |
| new RedfishDevpathInjector()); | |
| for (const RedfishToUhmMapping& mapping : config.redfish_to_uhm_mapping()) { | |
| std::shared_ptr<RedfishToUhmMappingValue> value = | |
| std::make_shared<RedfishToUhmMappingValue>(); | |
| value->uhm_monitored_component_key = mapping.uhm_monitored_component_key(); | |
| value->redfish_expose_config = mapping.redfish_expose_config(); | |
| injector->trie_.Insert(mapping.key(), value); | |
| } | |
| return injector; | |
| } | |
| void RedfishDevpathInjector::Inject( | |
| const crow::Request& req, | |
| crow::Response& res) const { | |
| // No-op if response is not successful. | |
| if (res.result() != boost::beast::http::status::ok) { | |
| return; | |
| } | |
| // Only modify GET requests. | |
| if (req.method() != boost::beast::http::verb::get) { | |
| return; | |
| } | |
| Key lookup_key; | |
| lookup_key.set_redfish_url_pattern(std::string(req.url().path())); | |
| std::shared_ptr<const RedfishToUhmMappingValue> value = | |
| trie_.GetMappingFromUrl(lookup_key); | |
| if (value == nullptr) { | |
| return; | |
| } | |
| std::string_view barepath = value->uhm_monitored_component_key.barepath(); | |
| milotic_tlbmc::LocationContext location_context; | |
| location_context.set_devpath(std::string(barepath)); | |
| if (!value->redfish_expose_config.embedded_location_context().empty()) { | |
| location_context.add_logical_identifiers( | |
| value->redfish_expose_config.embedded_location_context()); | |
| } | |
| milotic_tlbmc::StableId stable_id = milotic_tlbmc::GetStableId( | |
| location_context, /*root_chassis_location_code=*/""); | |
| std::string_view location_key = | |
| value->redfish_expose_config.use_physical_location() ? "PhysicalLocation" | |
| : "Location"; | |
| nlohmann::json& location_json = res.jsonValue[location_key]; | |
| location_json["PartLocation"]["ServiceLabel"] = stable_id.service_label(); | |
| if (value->redfish_expose_config.set_plc_as_placeholder()) { | |
| location_json["PartLocationContext"] = "PlaceholderAndShouldNotBeUsed"; | |
| } else if (stable_id.has_part_location_context() && | |
| !stable_id.part_location_context().empty()) { | |
| location_json["PartLocationContext"] = stable_id.part_location_context(); | |
| } else { | |
| location_json.erase("PartLocationContext"); | |
| } | |
| if (value->redfish_expose_config.expose_oem_google_devpath()) { | |
| location_json["Oem"]["Google"]["Devpath"] = barepath; | |
| } | |
| if (stable_id.has_embedded_location_context() && | |
| !stable_id.embedded_location_context().empty()) { | |
| location_json["Oem"]["Google"]["EmbeddedLocationContext"] = | |
| stable_id.embedded_location_context(); | |
| } | |
| } | |
| } // namespace devpath_plugin |