diff options
author | Gunnar Mills <gmills@us.ibm.com> | 2020-08-20 23:57:40 +0300 |
---|---|---|
committer | Gunnar Mills <gmills@us.ibm.com> | 2020-09-02 16:31:59 +0300 |
commit | f97ddba7015a553f13639233f7e5d3fb0152d0b2 (patch) | |
tree | b3b610b63a35c9b88638b7544f510d30e7af06af | |
parent | f92af38923c3651d5def0cc60abd5ed2f802fbe7 (diff) | |
download | bmcweb-f97ddba7015a553f13639233f7e5d3fb0152d0b2.tar.xz |
Add "Links""SoftwareImages"
SoftwareImages was added in Manager in 1_6_0 and Bios in 1_1_0.
Use the existing getActiveFwVersion function but rename to
populateFirmwareInformation. Changed the mapper call from a GetObject to a
GetSubTree. Added some debug to the function.
Tested: Validator passes.
curl -k https://$bmc/redfish/v1/Managers/bmc
....
"Links": {
"ActiveSoftwareImage": {
"@odata.id": "/redfish/v1/UpdateService/FirmwareInventory/e4e1c69d"
},
"ManagerForChassis": [
....
"@odata.id": "/redfish/v1/Chassis/chassis"
},
"SoftwareImages": [
{
"@odata.id": "/redfish/v1/UpdateService/FirmwareInventory/730944ed"
},
{
"@odata.id": "/redfish/v1/UpdateService/FirmwareInventory/e4e1c69d"
}
],
"SoftwareImages@odata.count": 2
},
...
Change-Id: I20798852a2f62575854820bff36175dda38c7dbc
Signed-off-by: Gunnar Mills <gmills@us.ibm.com>
-rw-r--r-- | redfish-core/include/utils/fw_utils.hpp | 184 | ||||
-rw-r--r-- | redfish-core/lib/bios.hpp | 5 | ||||
-rw-r--r-- | redfish-core/lib/managers.hpp | 4 | ||||
-rw-r--r-- | redfish-core/lib/systems.hpp | 2 |
4 files changed, 122 insertions, 73 deletions
diff --git a/redfish-core/include/utils/fw_utils.hpp b/redfish-core/include/utils/fw_utils.hpp index 65f19ca08b..8e040701d1 100644 --- a/redfish-core/include/utils/fw_utils.hpp +++ b/redfish-core/include/utils/fw_utils.hpp @@ -1,8 +1,10 @@ #pragma once #include <async_resp.hpp> +#include <algorithm> #include <string> #include <variant> +#include <vector> namespace redfish { @@ -17,28 +19,28 @@ constexpr const char* bmcPurpose = "xyz.openbmc_project.Software.Version.VersionPurpose.BMC"; /** - * @brief Put fw version of input type into async response json structure + * @brief Populate the running firmware version and image links * * @param[i,o] aResp Async response object * @param[i] fwVersionPurpose Indicates what target to look for * @param[i] activeVersionPropName Index in aResp->res.jsonValue to write * the running firmware version to - * @param[i] populateLinkToActiveImage Populate aResp->res "Links" - * "ActiveSoftwareImage" with a link to the running firmware image + * @param[i] populateLinkToImages Populate aResp->res "Links" + * "ActiveSoftwareImage" with a link to the running firmware image and + * "SoftwareImages" with a link to the all its firmware images * * @return void */ -inline void getActiveFwVersion(std::shared_ptr<AsyncResp> aResp, - const std::string& fwVersionPurpose, - const std::string& activeVersionPropName, - const bool populateLinkToActiveImage) +inline void populateFirmwareInformation( + std::shared_ptr<AsyncResp> aResp, const std::string& fwVersionPurpose, + const std::string& activeVersionPropName, const bool populateLinkToImages) { - // Get active FW images + // Used later to determine running (known on Redfish as active) FW images crow::connections::systemBus->async_method_call( - [aResp, fwVersionPurpose, activeVersionPropName, - populateLinkToActiveImage]( + [aResp, fwVersionPurpose, activeVersionPropName, populateLinkToImages]( const boost::system::error_code ec, const std::variant<std::vector<std::string>>& resp) { + BMCWEB_LOG_DEBUG << "populateFirmwareInformation enter"; if (ec) { BMCWEB_LOG_ERROR << "error_code = " << ec; @@ -46,76 +48,97 @@ inline void getActiveFwVersion(std::shared_ptr<AsyncResp> aResp, messages::internalError(aResp->res); return; } + const std::vector<std::string>* functionalFw = std::get_if<std::vector<std::string>>(&resp); if ((functionalFw == nullptr) || (functionalFw->size() == 0)) { + // Could keep going and try to populate SoftwareImages but + // something is seriously wrong, so just fail BMCWEB_LOG_ERROR << "Zero functional software in system"; messages::internalError(aResp->res); return; } + + std::vector<std::string> functionalFwIds; // example functionalFw: // v as 2 "/xyz/openbmc_project/software/ace821ef" // "/xyz/openbmc_project/software/230fb078" for (auto& fw : *functionalFw) { - // if can't parse fw id then return + std::string::size_type idPos = fw.rfind("/"); if (idPos == std::string::npos) { - messages::internalError(aResp->res); - BMCWEB_LOG_DEBUG << "Can't parse firmware ID!!"; - return; + BMCWEB_LOG_DEBUG << "Can't parse firmware ID!"; + continue; } idPos++; if (idPos >= fw.size()) { - messages::internalError(aResp->res); BMCWEB_LOG_DEBUG << "Invalid firmware ID"; - return; + continue; } - std::string swId = fw.substr(idPos); + functionalFwIds.push_back(fw.substr(idPos)); + } + + crow::connections::systemBus->async_method_call( + [aResp, fwVersionPurpose, activeVersionPropName, + populateLinkToImages, functionalFwIds]( + const boost::system::error_code ec2, + const std::vector< + std::pair<std::string, + std::vector<std::pair< + std::string, std::vector<std::string>>>>>& + subtree) { + if (ec2) + { + BMCWEB_LOG_ERROR << "error_code = " << ec2; + BMCWEB_LOG_ERROR << "error msg = " << ec2.message(); + messages::internalError(aResp->res); + return; + } + + BMCWEB_LOG_DEBUG << "Found " << subtree.size() << " images"; - // Now find service that hosts it - crow::connections::systemBus->async_method_call( - [aResp, fw, swId, fwVersionPurpose, activeVersionPropName, - populateLinkToActiveImage]( - const boost::system::error_code ec2, - const std::vector<std::pair< - std::string, std::vector<std::string>>>& objInfo) { - if (ec2) + for (const std::pair< + std::string, + std::vector<std::pair< + std::string, std::vector<std::string>>>>& obj : + subtree) + { + // if can't parse fw id then return + std::string::size_type idPos = obj.first.rfind("/"); + if (idPos == std::string::npos) { - BMCWEB_LOG_DEBUG << "error_code = " << ec2; - BMCWEB_LOG_DEBUG << "error msg = " << ec2.message(); messages::internalError(aResp->res); + BMCWEB_LOG_ERROR << "Can't parse firmware ID!!"; return; } - // Example objInfo - // a{sas} 1 "org.open_power.Software.Host.Updater" 10 - // "org.freedesktop.DBus.Introspectable" - // "org.freedesktop.DBus.Peer" - // "org.freedesktop.DBus.Properties" - // "org.openbmc.Associations" - // "xyz.openbmc_project.Common.FilePath" - // "xyz.openbmc_project.Object.Delete" - // "xyz.openbmc_project.Software.Activation" - // "xyz.openbmc_project.Software.ExtendedVersion" - // "xyz.openbmc_project.Software.RedundancyPriority" - // "xyz.openbmc_project.Software.Version" - - // Ensure we only got one service back - if (objInfo.size() != 1) + idPos++; + if (idPos >= obj.first.size()) { - BMCWEB_LOG_ERROR << "Invalid Object Size " - << objInfo.size(); messages::internalError(aResp->res); + BMCWEB_LOG_ERROR << "Invalid firmware ID"; return; } + std::string swId = obj.first.substr(idPos); + + bool runningImage = false; + // Look at Ids from + // /xyz/openbmc_project/software/functional + // to determine if this is a running image + if (std::find(functionalFwIds.begin(), + functionalFwIds.end(), + swId) != functionalFwIds.end()) + { + runningImage = true; + } // Now grab its version info crow::connections::systemBus->async_method_call( - [aResp, swId, fwVersionPurpose, - activeVersionPropName, populateLinkToActiveImage]( + [aResp, swId, runningImage, fwVersionPurpose, + activeVersionPropName, populateLinkToImages]( const boost::system::error_code ec3, const boost::container::flat_map< std::string, @@ -142,7 +165,7 @@ inline void getActiveFwVersion(std::shared_ptr<AsyncResp> aResp, propertiesList.find("Purpose"); if (it == propertiesList.end()) { - BMCWEB_LOG_DEBUG + BMCWEB_LOG_ERROR << "Can't find property \"Purpose\"!"; messages::internalError(aResp->res); return; @@ -151,37 +174,61 @@ inline void getActiveFwVersion(std::shared_ptr<AsyncResp> aResp, std::get_if<std::string>(&it->second); if (swInvPurpose == nullptr) { - BMCWEB_LOG_DEBUG << "wrong types for " + BMCWEB_LOG_ERROR << "wrong types for " "property \"Purpose\"!"; messages::internalError(aResp->res); return; } + BMCWEB_LOG_DEBUG << "Image ID: " << swId; + BMCWEB_LOG_DEBUG << "Image purpose: " + << *swInvPurpose; + BMCWEB_LOG_DEBUG << "Running image: " + << runningImage; + if (*swInvPurpose != fwVersionPurpose) { // Not purpose we're looking for return; } - if (populateLinkToActiveImage) + + if (populateLinkToImages) { + nlohmann::json& softwareImageMembers = + aResp->res.jsonValue["Links"] + ["SoftwareImages"]; // Firmware images are at // /redfish/v1/UpdateService/FirmwareInventory/<Id> // e.g. .../FirmwareInventory/82d3ec86 - // Create the link to the running one - aResp->res - .jsonValue["Links"] - ["ActiveSoftwareImage"] = { - {"@odata.id", - "/redfish/v1/UpdateService/" - "FirmwareInventory/" + - swId}}; + softwareImageMembers.push_back( + {{"@odata.id", + "/redfish/v1/UpdateService/" + "FirmwareInventory/" + + swId}}); + aResp->res.jsonValue + ["Links"] + ["SoftwareImages@odata.count"] = + softwareImageMembers.size(); + + if (runningImage) + { + // Create the link to the running image + aResp->res + .jsonValue["Links"] + ["ActiveSoftwareImage"] = + {{"@odata.id", + "/redfish/v1/UpdateService/" + "FirmwareInventory/" + + swId}}; + } } - if (!activeVersionPropName.empty()) + if (!activeVersionPropName.empty() && + runningImage) { it = propertiesList.find("Version"); if (it == propertiesList.end()) { - BMCWEB_LOG_DEBUG + BMCWEB_LOG_ERROR << "Can't find property " "\"Version\"!"; messages::internalError(aResp->res); @@ -191,7 +238,7 @@ inline void getActiveFwVersion(std::shared_ptr<AsyncResp> aResp, std::get_if<std::string>(&it->second); if (version == nullptr) { - BMCWEB_LOG_DEBUG + BMCWEB_LOG_ERROR << "Error getting fw version"; messages::internalError(aResp->res); return; @@ -202,16 +249,17 @@ inline void getActiveFwVersion(std::shared_ptr<AsyncResp> aResp, *version; } }, - objInfo[0].first, fw, + obj.second[0].first, obj.first, "org.freedesktop.DBus.Properties", "GetAll", "xyz.openbmc_project.Software.Version"); - }, - "xyz.openbmc_project.ObjectMapper", - "/xyz/openbmc_project/object_mapper", - "xyz.openbmc_project.ObjectMapper", "GetObject", fw, - std::array<const char*, 1>{ - "xyz.openbmc_project.Software.Activation"}); - } + } + }, + "xyz.openbmc_project.ObjectMapper", + "/xyz/openbmc_project/object_mapper", + "xyz.openbmc_project.ObjectMapper", "GetSubTree", + "/xyz/openbmc_project/software", static_cast<int32_t>(0), + std::array<const char*, 1>{ + "xyz.openbmc_project.Software.Version"}); }, "xyz.openbmc_project.ObjectMapper", "/xyz/openbmc_project/software/functional", diff --git a/redfish-core/lib/bios.hpp b/redfish-core/lib/bios.hpp index 8acf29be3d..2c3107723b 100644 --- a/redfish-core/lib/bios.hpp +++ b/redfish-core/lib/bios.hpp @@ -32,8 +32,9 @@ class BiosService : public Node {"target", "/redfish/v1/Systems/system/Bios/Actions/Bios.ResetBios"}}; - // Get the ActiveSoftwareImage - fw_util::getActiveFwVersion(asyncResp, fw_util::biosPurpose, "", true); + // Get the ActiveSoftwareImage and SoftwareImages + fw_util::populateFirmwareInformation(asyncResp, fw_util::biosPurpose, + "", true); } }; /** diff --git a/redfish-core/lib/managers.hpp b/redfish-core/lib/managers.hpp index 1d13cd3a66..f6747660da 100644 --- a/redfish-core/lib/managers.hpp +++ b/redfish-core/lib/managers.hpp @@ -1793,8 +1793,8 @@ class Manager : public Node health->isManagersHealth = true; health->populate(); - fw_util::getActiveFwVersion(asyncResp, fw_util::bmcPurpose, - "FirmwareVersion", true); + fw_util::populateFirmwareInformation(asyncResp, fw_util::bmcPurpose, + "FirmwareVersion", true); getLastResetTime(asyncResp); diff --git a/redfish-core/lib/systems.hpp b/redfish-core/lib/systems.hpp index fb1288e6b9..5d96649141 100644 --- a/redfish-core/lib/systems.hpp +++ b/redfish-core/lib/systems.hpp @@ -533,7 +533,7 @@ inline void getComputerSystem(std::shared_ptr<AsyncResp> aResp, } // Grab the bios version - fw_util::getActiveFwVersion( + fw_util::populateFirmwareInformation( aResp, fw_util::biosPurpose, "BiosVersion", false); }, |