diff options
| author | James Feist <james.feist@linux.intel.com> | 2019-03-15 15:14:00 -0700 |
|---|---|---|
| committer | James Feist <james.feist@linux.intel.com> | 2019-03-20 09:13:47 -0700 |
| commit | 8bd25ccda8030e5725ecdf5fa64d6083040ddf8a (patch) | |
| tree | f34f5fe0ce9c786ddee196f5082e46090c0ccfcf | |
| parent | de629b6ea81bf5308bdcbe5610ec8ea27a4016be (diff) | |
| download | bmcweb-8bd25ccda8030e5725ecdf5fa64d6083040ddf8a.tar.gz bmcweb-8bd25ccda8030e5725ecdf5fa64d6083040ddf8a.zip | |
Add Redundancy to Thermal Schema
This looks for the FanRedundancy Interface
https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/xyz/openbmc_project/Control/FanRedundancy.interface.yaml
and an association to type inventory. Using these it adds
Redundancy to the thermal schema.
Tested: Passes Redfish schema validator
Change-Id: Iffa32e445bd57234afeb5c682c9502c5daa227c1
Signed-off-by: James Feist <james.feist@linux.intel.com>
| -rw-r--r-- | redfish-core/lib/sensors.hpp | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/redfish-core/lib/sensors.hpp b/redfish-core/lib/sensors.hpp index 376c7e4..bbed047 100644 --- a/redfish-core/lib/sensors.hpp +++ b/redfish-core/lib/sensors.hpp @@ -578,6 +578,202 @@ void objectInterfacesToJson( BMCWEB_LOG_DEBUG << "Added sensor " << sensorName; } +static void + populateFanRedundancy(std::shared_ptr<SensorsAsyncResp> sensorsAsyncResp) +{ + crow::connections::systemBus->async_method_call( + [sensorsAsyncResp](const boost::system::error_code ec, + const GetSubTreeType& resp) { + if (ec) + { + return; // don't have to have this interface + } + for (const auto& [path, objDict] : resp) + { + if (objDict.empty()) + { + continue; // this should be impossible + } + + const std::string& owner = objDict.begin()->first; + crow::connections::systemBus->async_method_call( + [path, owner, + sensorsAsyncResp](const boost::system::error_code ec, + std::variant<std::vector<std::string>> + variantEndpoints) { + if (ec) + { + return; // if they don't have an association we + // can't tell what chassis is + } + // verify part of the right chassis + auto endpoints = std::get_if<std::vector<std::string>>( + &variantEndpoints); + + if (endpoints == nullptr) + { + BMCWEB_LOG_ERROR << "Invalid association interface"; + messages::internalError(sensorsAsyncResp->res); + return; + } + + auto found = std::find_if( + endpoints->begin(), endpoints->end(), + [sensorsAsyncResp](const std::string& entry) { + return entry.find( + sensorsAsyncResp->chassisId) != + std::string::npos; + }); + + if (found == endpoints->end()) + { + return; + } + crow::connections::systemBus->async_method_call( + [path, sensorsAsyncResp]( + const boost::system::error_code ec, + const boost::container::flat_map< + std::string, + std::variant<uint8_t, + std::vector<std::string>, + std::string>>& ret) { + if (ec) + { + return; // don't have to have this + // interface + } + auto findFailures = ret.find("AllowedFailures"); + auto findCollection = ret.find("Collection"); + auto findStatus = ret.find("Status"); + + if (findFailures == ret.end() || + findCollection == ret.end() || + findStatus == ret.end()) + { + BMCWEB_LOG_ERROR + << "Invalid redundancy interface"; + messages::internalError( + sensorsAsyncResp->res); + return; + } + + auto allowedFailures = std::get_if<uint8_t>( + &(findFailures->second)); + auto collection = + std::get_if<std::vector<std::string>>( + &(findCollection->second)); + auto status = std::get_if<std::string>( + &(findStatus->second)); + + if (allowedFailures == nullptr || + collection == nullptr || status == nullptr) + { + + BMCWEB_LOG_ERROR + << "Invalid redundancy interface " + "types"; + messages::internalError( + sensorsAsyncResp->res); + return; + } + size_t lastSlash = path.rfind("/"); + if (lastSlash == std::string::npos) + { + // this should be impossible + messages::internalError( + sensorsAsyncResp->res); + return; + } + std::string name = path.substr(lastSlash + 1); + std::replace(name.begin(), name.end(), '_', + ' '); + + std::string health; + + if (boost::ends_with(*status, "Full")) + { + health = "OK"; + } + else if (boost::ends_with(*status, "Degraded")) + { + health = "Warning"; + } + else + { + health = "Critical"; + } + std::vector<nlohmann::json> redfishCollection; + const auto& fanRedfish = + sensorsAsyncResp->res.jsonValue["Fans"]; + for (const std::string& item : *collection) + { + lastSlash = item.rfind("/"); + // make a copy as collection is const + std::string itemName = + item.substr(lastSlash + 1); + /* + todo(ed): merge patch that fixes the names + std::replace(itemName.begin(), + itemName.end(), '_', ' ');*/ + auto schemaItem = std::find_if( + fanRedfish.begin(), fanRedfish.end(), + [itemName](const nlohmann::json& fan) { + return fan["MemberId"] == itemName; + }); + if (schemaItem != fanRedfish.end()) + { + redfishCollection.push_back( + {{"@odata.id", + (*schemaItem)["@odata.id"]}}); + } + else + { + BMCWEB_LOG_ERROR + << "failed to find fan in schema"; + messages::internalError( + sensorsAsyncResp->res); + return; + } + } + + auto& resp = sensorsAsyncResp->res + .jsonValue["Redundancy"]; + resp.push_back( + {{"@odata.id", + "/refish/v1/Chassis/" + + sensorsAsyncResp->chassisId + "/" + + sensorsAsyncResp->chassisSubNode + + "#/Redundancy/" + + std::to_string(resp.size())}, + {"@odata.type", + "#Redundancy.v1_3_2.Redundancy"}, + {"MinNumNeeded", + collection->size() - *allowedFailures}, + {"MemberId", name}, + {"Mode", "N+m"}, + {"Name", name}, + {"RedundancySet", redfishCollection}, + {"Status", + {{"Health", health}, + {"State", "Enabled"}}}}); + }, + owner, path, "org.freedesktop.DBus.Properties", + "GetAll", + "xyz.openbmc_project.Control.FanRedundancy"); + }, + "xyz.openbmc_project.ObjectMapper", path + "/inventory", + "org.freedesktop.DBus.Properties", "Get", + "xyz.openbmc_project.Association", "endpoints"); + } + }, + "xyz.openbmc_project.ObjectMapper", + "/xyz/openbmc_project/object_mapper", + "xyz.openbmc_project.ObjectMapper", "GetSubTree", + "/xyz/openbmc_project/control", 2, + std::array<const char*, 1>{ + "xyz.openbmc_project.Control.FanRedundancy"}); +} + /** * @brief Gets the values of the specified sensors. * @@ -705,6 +901,11 @@ void getSensorData( objectInterfacesToJson(sensorName, sensorType, objDictEntry.second, sensorJson); } + if (SensorsAsyncResp.use_count() == 1 && + SensorsAsyncResp->chassisSubNode == "Thermal") + { + populateFanRedundancy(SensorsAsyncResp); + } BMCWEB_LOG_DEBUG << "getManagedObjectsCb exit"; }; |

