Update PSU if version cannot be obtained
Currently this application will ignore a PSU if the PSU code version
cannot be obtained.
However, there are several scenarios where this could occur:
* A code update was previously attempted on the PSU, and the update
failed. The PSU is now in a bad state, and the update needs to be
performed again.
* The PSU is running old code that does not support reading the code
version.
In these scenarios performing a code update on the PSU is desired.
Enhance this application so that a PSU with an unknown code version will
be updated provided that it is the correct model.
Tested:
* Verified code update was still performed if version could not be
obtained.
* Tested where PSU information is found at start of application
* Tested where PSU information is found from InterfacesAdded event
* Tested where PSU information is found from PropertiesChanged event
* For the complete test plan, see
https://gist.github.com/smccarney/3846a97fef590eb69181edc669555a00
Change-Id: I6e60761fa20eeb4500529c00f33de16d69a8d84d
Signed-off-by: Shawn McCarney <shawnmm@us.ibm.com>
diff --git a/src/item_updater.cpp b/src/item_updater.cpp
index 8c92917..a545bf3 100644
--- a/src/item_updater.cpp
+++ b/src/item_updater.cpp
@@ -266,8 +266,6 @@
void ItemUpdater::removePsuObject(const std::string& psuInventoryPath)
{
- psuStatusMap[psuInventoryPath] = {false, ""};
-
auto it = psuPathActivationMap.find(psuInventoryPath);
if (it == psuPathActivationMap.end())
{
@@ -302,6 +300,24 @@
}
}
+void ItemUpdater::addPsuToStatusMap(const std::string& psuPath)
+{
+ if (!psuStatusMap.contains(psuPath))
+ {
+ psuStatusMap[psuPath] = {false, ""};
+
+ // Add matches for PSU Inventory's property changes
+ psuMatches.emplace_back(
+ bus, MatchRules::propertiesChanged(psuPath, ITEM_IFACE),
+ std::bind(&ItemUpdater::onPsuInventoryChangedMsg, this,
+ std::placeholders::_1)); // For present
+ psuMatches.emplace_back(
+ bus, MatchRules::propertiesChanged(psuPath, ASSET_IFACE),
+ std::bind(&ItemUpdater::onPsuInventoryChangedMsg, this,
+ std::placeholders::_1)); // For model
+ }
+}
+
std::unique_ptr<Version> ItemUpdater::createVersionObject(
const std::string& objPath, const std::string& versionId,
const std::string& versionString,
@@ -371,8 +387,6 @@
{
createPsuObject(psuPath, version);
}
- // Check if there is new PSU images to update
- syncToLatestImage();
}
else
{
@@ -380,6 +394,9 @@
log<level::ERR>("Failed to get PSU version",
entry("PSU=%s", psuPath.c_str()));
}
+ // Check if there are new PSU images to update
+ processStoredImage();
+ syncToLatestImage();
}
else
{
@@ -390,6 +407,8 @@
// handled by "Present" callback.
return;
}
+ psuStatusMap[psuPath].model = "";
+
// Remove object or association
removePsuObject(psuPath);
}
@@ -400,25 +419,18 @@
auto paths = utils::getPSUInventoryPath(bus);
for (const auto& p : paths)
{
+ addPsuToStatusMap(p);
+
auto service = utils::getService(bus, p.c_str(), ITEM_IFACE);
- auto present = utils::getProperty<bool>(bus, service.c_str(), p.c_str(),
- ITEM_IFACE, PRESENT);
+ psuStatusMap[p].present = utils::getProperty<bool>(
+ bus, service.c_str(), p.c_str(), ITEM_IFACE, PRESENT);
psuStatusMap[p].model = utils::getProperty<std::string>(
bus, service.c_str(), p.c_str(), ASSET_IFACE, MODEL);
auto version = utils::getVersion(p);
if ((psuPathActivationMap.find(p) == psuPathActivationMap.end()) &&
- present && !version.empty())
+ psuStatusMap[p].present && !version.empty())
{
createPsuObject(p, version);
- // Add matches for PSU Inventory's property changes
- psuMatches.emplace_back(
- bus, MatchRules::propertiesChanged(p, ITEM_IFACE),
- std::bind(&ItemUpdater::onPsuInventoryChangedMsg, this,
- std::placeholders::_1)); // For present
- psuMatches.emplace_back(
- bus, MatchRules::propertiesChanged(p, ASSET_IFACE),
- std::bind(&ItemUpdater::onPsuInventoryChangedMsg, this,
- std::placeholders::_1)); // For model
}
}
}
@@ -599,8 +611,14 @@
msg.read(objPath, interfaces);
std::string path = objPath.str;
- if (interfaces.find(PSU_INVENTORY_IFACE) == interfaces.end() ||
- (psuStatusMap[path].present && !psuStatusMap[path].model.empty()))
+ if (interfaces.find(PSU_INVENTORY_IFACE) == interfaces.end())
+ {
+ return;
+ }
+
+ addPsuToStatusMap(path);
+
+ if (psuStatusMap[path].present && !psuStatusMap[path].model.empty())
{
return;
}
diff --git a/src/item_updater.hpp b/src/item_updater.hpp
index e07aca8..885847a 100644
--- a/src/item_updater.hpp
+++ b/src/item_updater.hpp
@@ -163,6 +163,15 @@
*/
void removePsuObject(const std::string& psuInventoryPath);
+ /** @brief Add PSU inventory path to the PSU status map
+ * @details Also adds PropertiesChanged listeners for the inventory path so
+ * we are notified when the present or model properties change.
+ * Does nothing if the inventory path already exists in the map.
+ *
+ * @param[in] psuPath - The PSU inventory path
+ */
+ void addPsuToStatusMap(const std::string& psuPath);
+
/**
* @brief Create and populate the active PSU Version.
*/