Activation: check compatiblity of uploaded software
Before activation, check if the PSU inventory's manufacturer and model
matches the uploaded software, to make sure the software is not updated
to a incompatible PSU.
The model check is mandatory, and if the PSU manufacturer is empty,
ignore the manufacturer check.
Tested: Upload a dummy tarball with incompatible model, verify the
activation fails;
Upload a dummy tarball with compatible model, verify the
activation succeeds with a dummy update service.
Also added unit tests for several cases:
* Update on a PSU that model is incompatible;
* Update on a PSU that the manufacture is incompatible;
* Update on a PSU that the menufacture is empty;
* Update on 4 PSUs that the second one is incompatible.
Signed-off-by: Lei YU <mine260309@gmail.com>
Change-Id: Ia1b6a3fa6c98cdea1ea93c917c0938d4a60f0911
diff --git a/src/activation.cpp b/src/activation.cpp
index f1181fb..5023712 100644
--- a/src/activation.cpp
+++ b/src/activation.cpp
@@ -183,7 +183,21 @@
for (const auto& p : psuPaths)
{
- psuQueue.push(p);
+ if (isCompatible(p))
+ {
+ psuQueue.push(p);
+ }
+ else
+ {
+ log<level::NOTICE>("PSU not compatible",
+ entry("PSU=%s", p.c_str()));
+ }
+ }
+
+ if (psuQueue.empty())
+ {
+ log<level::ERR>("No PSU compatible with the software");
+ return Status::Failed;
}
// The progress to be increased for each successful update of PSU
@@ -257,6 +271,28 @@
}
}
+bool Activation::isCompatible(const std::string& psuInventoryPath)
+{
+ auto service =
+ utils::getService(bus, psuInventoryPath.c_str(), ASSET_IFACE);
+ auto psuManufacturer = utils::getProperty<std::string>(
+ bus, service.c_str(), psuInventoryPath.c_str(), ASSET_IFACE,
+ MANUFACTURER);
+ auto psuModel = utils::getProperty<std::string>(
+ bus, service.c_str(), psuInventoryPath.c_str(), ASSET_IFACE, MODEL);
+ if (psuModel != model)
+ {
+ // The model shall match
+ return false;
+ }
+ if (!psuManufacturer.empty())
+ {
+ // If PSU inventory has manufacturer property, it shall match
+ return psuManufacturer == manufacturer;
+ }
+ return true;
+}
+
} // namespace updater
} // namespace software
} // namespace phosphor
diff --git a/src/activation.hpp b/src/activation.hpp
index d0fdaba..b46105b 100644
--- a/src/activation.hpp
+++ b/src/activation.hpp
@@ -4,6 +4,7 @@
#include "association_interface.hpp"
#include "types.hpp"
+#include "version.hpp"
#include <queue>
#include <sdbusplus/server.hpp>
@@ -142,6 +143,10 @@
activation(activationStatus);
associations(assocs);
+ auto info = Version::getExtVersionInfo(extVersion);
+ manufacturer = info["manufacturer"];
+ model = info["model"];
+
// Emit deferred signal.
emit_object_added();
}
@@ -212,6 +217,9 @@
/** @brief Finish PSU update */
void finishActivation();
+ /** @brief Check if the PSU is comaptible with this software*/
+ bool isCompatible(const std::string& psuInventoryPath);
+
/** @brief Persistent sdbusplus DBus bus connection */
sdbusplus::bus::bus& bus;
@@ -241,6 +249,12 @@
/** @brief The AssociationInterface pointer */
AssociationInterface* associationInterface;
+
+ /** @brief The PSU manufacturer of the software */
+ std::string manufacturer;
+
+ /** @brief The PSU model of the software */
+ std::string model;
};
} // namespace updater
diff --git a/src/version.cpp b/src/version.cpp
index 0ea6cc9..02cf6af 100644
--- a/src/version.cpp
+++ b/src/version.cpp
@@ -53,6 +53,29 @@
return ret;
}
+std::map<std::string, std::string>
+ Version::getExtVersionInfo(const std::string& extVersion)
+{
+ // The extVersion shall be key/value pairs separated by comma,
+ // e.g. key1=value1,key2=value2
+ std::map<std::string, std::string> result;
+ std::stringstream ss(extVersion);
+
+ while (ss.good())
+ {
+ std::string substr;
+ getline(ss, substr, ',');
+ auto pos = substr.find('=');
+ if (pos != std::string::npos)
+ {
+ std::string key = substr.substr(0, pos);
+ std::string value = substr.substr(pos + 1);
+ result.emplace(key, value);
+ }
+ }
+ return result;
+}
+
void Delete::delete_()
{
if (version.eraseCallback)
diff --git a/src/version.hpp b/src/version.hpp
index c3c2c54..d4106e6 100644
--- a/src/version.hpp
+++ b/src/version.hpp
@@ -129,6 +129,16 @@
getValues(const std::string& filePath,
const std::vector<std::string>& keys);
+ /** @brief Get information from extVersion
+ *
+ * @param[in] extVersion - The extended version string that contains
+ * key/value pairs separated by comma.
+ *
+ * @return The map of key/value pairs
+ */
+ static std::map<std::string, std::string>
+ getExtVersionInfo(const std::string& extVersion);
+
/** @brief The temUpdater's erase callback. */
eraseFunc eraseCallback;