blob: 97e6673e9cc6201dd8d0651eac9c5a7901582603 [file]
#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=*/"");
nlohmann::json& json = res.jsonValue;
json["Location"]["PartLocation"]["ServiceLabel"] = stable_id.service_label();
if (value->redfish_expose_config.set_plc_as_placeholder()) {
json["Location"]["PartLocationContext"] = "PlaceholderAndShouldNotBeUsed";
} else if (stable_id.has_part_location_context() &&
!stable_id.part_location_context().empty()) {
json["Location"]["PartLocationContext"] = stable_id.part_location_context();
}
if (value->redfish_expose_config.expose_oem_google_devpath()) {
json["Location"]["Oem"]["Google"]["Devpath"] = barepath;
}
if (stable_id.has_embedded_location_context() &&
!stable_id.embedded_location_context().empty()) {
json["Location"]["Oem"]["Google"]["EmbeddedLocationContext"] =
stable_id.embedded_location_context();
}
}
} // namespace devpath_plugin