summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGunnar Mills <gmills@us.ibm.com>2020-08-20 23:57:40 +0300
committerGunnar Mills <gmills@us.ibm.com>2020-09-02 16:31:59 +0300
commitf97ddba7015a553f13639233f7e5d3fb0152d0b2 (patch)
treeb3b610b63a35c9b88638b7544f510d30e7af06af
parentf92af38923c3651d5def0cc60abd5ed2f802fbe7 (diff)
downloadbmcweb-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.hpp184
-rw-r--r--redfish-core/lib/bios.hpp5
-rw-r--r--redfish-core/lib/managers.hpp4
-rw-r--r--redfish-core/lib/systems.hpp2
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);
},