diff options
-rw-r--r-- | meson.build | 3 | ||||
-rw-r--r-- | meson_options.txt | 8 | ||||
-rw-r--r-- | redfish-core/include/redfish_aggregator.hpp | 228 | ||||
-rw-r--r-- | src/webserver_main.cpp | 9 |
4 files changed, 247 insertions, 1 deletions
diff --git a/meson.build b/meson.build index d81270fa07..054b35fae0 100644 --- a/meson.build +++ b/meson.build @@ -72,6 +72,7 @@ feature_map = { 'insecure-tftp-update' : '-DBMCWEB_INSECURE_ENABLE_REDFISH_FW_TFTP_UPDATE', 'kvm' : '-DBMCWEB_ENABLE_KVM' , 'mutual-tls-auth' : '-DBMCWEB_ENABLE_MUTUAL_TLS_AUTHENTICATION', + 'redfish-aggregation' : '-DBMCWEB_ENABLE_REDFISH_AGGREGATION', 'redfish-allow-deprecated-power-thermal' : '-DBMCWEB_ALLOW_DEPRECATED_POWER_THERMAL', 'redfish-bmc-journal' : '-DBMCWEB_ENABLE_REDFISH_BMC_JOURNAL', 'redfish-cpu-log' : '-DBMCWEB_ENABLE_REDFISH_CPU_LOG', @@ -313,6 +314,8 @@ xss_enabled = get_option('insecure-disable-xss') conf_data.set10('BMCWEB_INSECURE_DISABLE_XSS_PREVENTION', xss_enabled.enabled()) enable_redfish_query = get_option('insecure-enable-redfish-query') conf_data.set10('BMCWEB_INSECURE_ENABLE_QUERY_PARAMS', enable_redfish_query.enabled()) +# enable_redfish_aggregation = get_option('redfish-aggregation') +# conf_data.set10('BMCWEB_ENABLE_REDFISH_AGGREGATION', enable_redfish_aggregation.enabled()) insecure_push_style_notification = get_option('insecure-push-style-notification') conf_data.set10('BMCWEB_INSECURE_ENABLE_HTTP_PUSH_STYLE_EVENTING', insecure_push_style_notification.enabled()) conf_data.set('MESON_INSTALL_PREFIX', get_option('prefix')) diff --git a/meson_options.txt b/meson_options.txt index f2b4f377ca..c81f185fd8 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -223,7 +223,6 @@ option( Option will be removed Q4 2022.''' ) - option( 'https_port', type: 'integer', @@ -233,6 +232,13 @@ option( description: 'HTTPS Port number.' ) +option( + 'redfish-aggregation', + type: 'feature', + value: 'disabled', + description: 'Allows this BMC to aggregate resources from satellite BMCs' +) + # Insecure options. Every option that starts with a `insecure` flag should # not be enabled by default for any platform, unless the author fully comprehends # the implications of doing so.In general, enabling these options will cause security diff --git a/redfish-core/include/redfish_aggregator.hpp b/redfish-core/include/redfish_aggregator.hpp new file mode 100644 index 0000000000..d076c6c1ea --- /dev/null +++ b/redfish-core/include/redfish_aggregator.hpp @@ -0,0 +1,228 @@ +#pragma once + +#include <http_client.hpp> + +namespace redfish +{ + +class RedfishAggregator +{ + private: + RedfishAggregator() + { + getSatelliteConfigs(constructorCallback); + } + + // Dummy callback used by the Constructor so that it can report the number + // of satellite configs when the class is first created + static void constructorCallback( + const std::unordered_map<std::string, boost::urls::url>& satelliteInfo) + { + BMCWEB_LOG_DEBUG << "There were " + << std::to_string(satelliteInfo.size()) + << " satellite configs found at startup"; + } + + // Polls D-Bus to get all available satellite config information + // Expects a handler which interacts with the returned configs + static void getSatelliteConfigs( + const std::function<void( + const std::unordered_map<std::string, boost::urls::url>&)>& handler) + { + BMCWEB_LOG_DEBUG << "Gathering satellite configs"; + crow::connections::systemBus->async_method_call( + [handler](const boost::system::error_code ec, + const dbus::utility::ManagedObjectType& objects) { + if (ec) + { + BMCWEB_LOG_ERROR << "DBUS response error " << ec.value() + << ", " << ec.message(); + return; + } + + // Maps a chosen alias representing a satellite BMC to a url + // containing the information required to create a http + // connection to the satellite + std::unordered_map<std::string, boost::urls::url> satelliteInfo; + + findSatelliteConfigs(objects, satelliteInfo); + + if (!satelliteInfo.empty()) + { + BMCWEB_LOG_DEBUG << "Redfish Aggregation enabled with " + << std::to_string(satelliteInfo.size()) + << " satellite BMCs"; + } + else + { + BMCWEB_LOG_DEBUG + << "No satellite BMCs detected. Redfish Aggregation not enabled"; + } + handler(satelliteInfo); + }, + "xyz.openbmc_project.EntityManager", "/", + "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); + } + + // Search D-Bus objects for satellite config objects and add their + // information if valid + static void findSatelliteConfigs( + const dbus::utility::ManagedObjectType& objects, + std::unordered_map<std::string, boost::urls::url>& satelliteInfo) + { + for (const auto& objectPath : objects) + { + for (const auto& interface : objectPath.second) + { + if (interface.first == + "xyz.openbmc_project.Configuration.SatelliteController") + { + BMCWEB_LOG_DEBUG << "Found Satellite Controller at " + << objectPath.first.str; + + addSatelliteConfig(interface.second, satelliteInfo); + } + } + } + } + + // Parse the properties of a satellite config object and add the + // configuration if the properties are valid + static void addSatelliteConfig( + 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") + { + const std::string* propVal = + std::get_if<std::string>(&prop.second); + if (propVal == nullptr) + { + BMCWEB_LOG_ERROR << "Invalid Hostname value"; + return; + } + url.set_host(*propVal); + } + + else if (prop.first == "Port") + { + const uint64_t* propVal = std::get_if<uint64_t>(&prop.second); + if (propVal == nullptr) + { + BMCWEB_LOG_ERROR << "Invalid Port value"; + return; + } + + if (*propVal > std::numeric_limits<uint16_t>::max()) + { + BMCWEB_LOG_ERROR << "Port value out of range"; + return; + } + url.set_port(static_cast<uint16_t>(*propVal)); + } + + else if (prop.first == "AuthType") + { + const std::string* propVal = + std::get_if<std::string>(&prop.second); + if (propVal == nullptr) + { + BMCWEB_LOG_ERROR << "Invalid AuthType value"; + return; + } + + // For now assume authentication not required to communicate + // with the satellite BMC + if (*propVal != "None") + { + BMCWEB_LOG_ERROR + << "Unsupported AuthType value: " << *propVal + << ", only \"none\" is supported"; + return; + } + url.set_scheme("http"); + } + } // 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"; + return; + } + + if (!url.has_port()) + { + BMCWEB_LOG_ERROR << "Satellite config " << name << " missing Port"; + return; + } + + if (!url.has_scheme()) + { + BMCWEB_LOG_ERROR << "Satellite config " << name + << " missing AuthType"; + return; + } + + std::string resultString; + auto result = satelliteInfo.insert_or_assign(name, std::move(url)); + if (result.second) + { + resultString = "Added new satellite config "; + } + else + { + resultString = "Updated existing satellite config "; + } + + BMCWEB_LOG_DEBUG << resultString << name << " at " + << result.first->second.scheme() << "://" + << result.first->second.encoded_host_and_port(); + } + + public: + RedfishAggregator(const RedfishAggregator&) = delete; + RedfishAggregator& operator=(const RedfishAggregator&) = delete; + RedfishAggregator(RedfishAggregator&&) = delete; + RedfishAggregator& operator=(RedfishAggregator&&) = delete; + ~RedfishAggregator() = default; + + static RedfishAggregator& getInstance() + { + static RedfishAggregator handler; + return handler; + } +}; + +} // namespace redfish diff --git a/src/webserver_main.cpp b/src/webserver_main.cpp index 6bdce98163..9d2aa8a13d 100644 --- a/src/webserver_main.cpp +++ b/src/webserver_main.cpp @@ -15,6 +15,7 @@ #include <obmc_console.hpp> #include <openbmc_dbus_rest.hpp> #include <redfish.hpp> +#include <redfish_aggregator.hpp> #include <redfish_v1.hpp> #include <sdbusplus/asio/connection.hpp> #include <sdbusplus/bus.hpp> @@ -86,8 +87,16 @@ static int run() redfish::requestRoutes(app); redfish::RedfishService redfish(app); + // Create HttpClient instance and initialize Config + crow::HttpClient::getInstance(); + // Create EventServiceManager instance and initialize Config redfish::EventServiceManager::getInstance(); + +#ifdef BMCWEB_ENABLE_REDFISH_AGGREGATION + // Create RedfishAggregator instance and initialize Config + redfish::RedfishAggregator::getInstance(); +#endif #endif #ifdef BMCWEB_ENABLE_DBUS_REST |