diff options
-rw-r--r-- | redfish-core/include/query.hpp | 16 | ||||
-rw-r--r-- | redfish-core/include/redfish_aggregator.hpp | 124 |
2 files changed, 109 insertions, 31 deletions
diff --git a/redfish-core/include/query.hpp b/redfish-core/include/query.hpp index fd5d189193..007b262244 100644 --- a/redfish-core/include/query.hpp +++ b/redfish-core/include/query.hpp @@ -27,6 +27,8 @@ // IWYU pragma: no_include <boost/url/impl/params_view.hpp> // IWYU pragma: no_include <boost/url/impl/url_view.hpp> +#include <redfish_aggregator.hpp> + namespace redfish { @@ -62,10 +64,20 @@ namespace redfish return false; } + bool needToCallHandlers = true; + +#ifdef BMCWEB_ENABLE_REDFISH_AGGREGATION + needToCallHandlers = RedfishAggregator::getInstance().beginAggregation( + req, asyncResp) == Result::LocalHandle; + + // If the request should be forwarded to a satellite BMC then we don't want + // to write anything to the asyncResp since it will get overwritten later. +#endif + // If this isn't a get, no need to do anything with parameters if (req.method() != boost::beast::http::verb::get) { - return true; + return needToCallHandlers; } delegated = query_param::delegate(queryCapabilities, *queryOpt); @@ -78,7 +90,7 @@ namespace redfish processAllParams(app, query, handler, resIn); }); - return true; + return needToCallHandlers; } // Sets up the Redfish Route. All parameters are handled by the default handler. diff --git a/redfish-core/include/redfish_aggregator.hpp b/redfish-core/include/redfish_aggregator.hpp index 33f6fb4b53..0a5ff57d90 100644 --- a/redfish-core/include/redfish_aggregator.hpp +++ b/redfish-core/include/redfish_aggregator.hpp @@ -5,6 +5,27 @@ namespace redfish { +enum class Result +{ + LocalHandle, + NoLocalHandle +}; + +// Checks if the provided path is related to one of the resource collections +// under UpdateService +static inline bool + isUpdateServiceCollection(const std::vector<std::string>& segments) +{ + if (segments.size() < 4) + { + return false; + } + + return (segments[2] == "UpdateService") && + ((segments[3] == "FirmwareInventory") || + (segments[3] == "SoftwareInventory")); +} + class RedfishAggregator { private: @@ -105,7 +126,19 @@ class RedfishAggregator BMCWEB_LOG_DEBUG << "Found Satellite Controller at " << objectPath.first.str; - addSatelliteConfig(interface.second, satelliteInfo); + if (!satelliteInfo.empty()) + { + BMCWEB_LOG_ERROR + << "Redfish Aggregation only supports one satellite!"; + BMCWEB_LOG_DEBUG << "Clearing all satellite data"; + satelliteInfo.clear(); + return; + } + + // For now assume there will only be one satellite config. + // Assign it the name/prefix "5B247A" + addSatelliteConfig("5B247A", interface.second, + satelliteInfo); } } } @@ -114,35 +147,15 @@ class RedfishAggregator // Parse the properties of a satellite config object and add the // configuration if the properties are valid static void addSatelliteConfig( + const std::string& name, const dbus::utility::DBusPropertiesMap& properties, std::unordered_map<std::string, boost::urls::url>& satelliteInfo) { boost::urls::url url; - std::string name; for (const auto& prop : properties) { - if (prop.first == "Name") - { - const std::string* propVal = - std::get_if<std::string>(&prop.second); - if (propVal == nullptr) - { - BMCWEB_LOG_ERROR << "Invalid Name value"; - return; - } - - // The IDs will become <Name>_<ID> so the name should not - // contain a '_' - if (propVal->find('_') != std::string::npos) - { - BMCWEB_LOG_ERROR << "Name cannot contain a \"_\""; - return; - } - name = *propVal; - } - - else if (prop.first == "Hostname") + if (prop.first == "Hostname") { const std::string* propVal = std::get_if<std::string>(&prop.second); @@ -195,12 +208,6 @@ class RedfishAggregator } // Finished reading properties // Make sure all required config information was made available - if (name.empty()) - { - BMCWEB_LOG_ERROR << "Satellite config missing Name"; - return; - } - if (url.host().empty()) { BMCWEB_LOG_ERROR << "Satellite config " << name << " missing Host"; @@ -248,6 +255,65 @@ class RedfishAggregator static RedfishAggregator handler; return handler; } + + // Entry point to Redfish Aggregation + // Returns Result stating whether or not we still need to locally handle the + // request + static Result + beginAggregation(const crow::Request& thisReq, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) + { + using crow::utility::OrMorePaths; + using crow::utility::readUrlSegments; + const boost::urls::url_view& url = thisReq.urlView; + // UpdateService is the only top level resource that is not a Collection + if (readUrlSegments(url, "redfish", "v1", "UpdateService")) + { + return Result::LocalHandle; + } + + // Is the request for a resource collection?: + // /redfish/v1/<resource> + // e.g. /redfish/v1/Chassis + std::string collectionName; + if (readUrlSegments(url, "redfish", "v1", std::ref(collectionName))) + { + return Result::LocalHandle; + } + + // We know that the ID of an aggregated resource will begin with + // "5B247A". For the most part the URI will begin like this: + // /redfish/v1/<resource>/<resource ID> + // Note, FirmwareInventory and SoftwareInventory are "special" because + // they are two levels deep, but still need aggregated + // /redfish/v1/UpdateService/FirmwareInventory/<FirmwareInventory ID> + // /redfish/v1/UpdateService/SoftwareInventory/<SoftwareInventory ID> + std::string memberName; + if (readUrlSegments(url, "redfish", "v1", "UpdateService", + "SoftwareInventory", std::ref(memberName), + OrMorePaths()) || + readUrlSegments(url, "redfish", "v1", "UpdateService", + "FirmwareInventory", std::ref(memberName), + OrMorePaths()) || + readUrlSegments(url, "redfish", "v1", std::ref(collectionName), + std::ref(memberName), OrMorePaths())) + { + if (memberName.starts_with("5B247A")) + { + BMCWEB_LOG_DEBUG << "Need to forward a request"; + + // TODO: Extract the prefix from the request's URI, retrieve + // the associated satellite config information, and then + // forward the request to that satellite. + redfish::messages::internalError(asyncResp->res); + return Result::NoLocalHandle; + } + return Result::LocalHandle; + } + + BMCWEB_LOG_DEBUG << "Aggregation not required"; + return Result::LocalHandle; + } }; } // namespace redfish |