Get PSU version from vendor specific tool
The code was getting the version from PSU inventory object.
This commit changes the behavior to use a vendor-specific tool to get
the version directly, where the tool is expected to be configured during
build time.
Add an example get_version app that shows the expected behavior of the
tool:
* It accepts an argument of PSU inventory object;
* It outputs the version to stdout.
Tested: 1. Put and configure to use the example get_version on witherspoon,
verify that PSU software objects are created with the version
returned by the exmaple tool.
2. With the Witherspoon specific tool in
https://gerrit.openbmc-project.xyz/c/openbmc/witherspoon-pfault-analysis/+/24811,
verify the version is correctly got from the PSU inventory path
and the software objects are created.
Signed-off-by: Lei YU <mine260309@gmail.com>
Change-Id: I5195cb6fc8998a76b09abcfe0b107364cb180c01
diff --git a/src/item_updater.cpp b/src/item_updater.cpp
index 89bd388..cf691d7 100644
--- a/src/item_updater.cpp
+++ b/src/item_updater.cpp
@@ -356,12 +356,10 @@
auto paths = utils::getPSUInventoryPath(bus);
for (const auto& p : paths)
{
- // Assume the same service implement both Version and Item interface
- auto service = utils::getService(bus, p.c_str(), VERSION_IFACE);
- auto version = utils::getProperty<std::string>(
- bus, service.c_str(), p.c_str(), VERSION_IFACE, VERSION);
+ 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);
+ auto version = utils::getVersion(p);
if (present && !version.empty())
{
createPsuObject(p, version);
diff --git a/src/utils.cpp b/src/utils.cpp
index 5e92f4a..7a968b7 100644
--- a/src/utils.cpp
+++ b/src/utils.cpp
@@ -6,6 +6,7 @@
#include <fstream>
#include <phosphor-logging/log.hpp>
+#include <sstream>
using namespace phosphor::logging;
@@ -19,6 +20,39 @@
constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper";
} // namespace
+namespace internal
+{
+template <typename... Ts>
+std::string concat_string(Ts const&... ts)
+{
+ std::stringstream s;
+ ((s << ts << " "), ...) << std::endl;
+ return s.str();
+}
+
+// Helper function to run command
+// Returns return code and the stdout
+template <typename... Ts>
+std::pair<int, std::string> exec(Ts const&... ts)
+{
+ std::array<char, 512> buffer;
+ std::string cmd = concat_string(ts...);
+ std::stringstream result;
+ int rc;
+ FILE* pipe = popen(cmd.c_str(), "r");
+ if (!pipe)
+ {
+ throw std::runtime_error("popen() failed!");
+ }
+ while (fgets(buffer.data(), buffer.size(), pipe) != nullptr)
+ {
+ result << buffer.data();
+ }
+ rc = pclose(pipe);
+ return {rc, result.str()};
+}
+
+} // namespace internal
const UtilsInterface& getUtils()
{
static Utils utils;
@@ -98,6 +132,15 @@
return (hexId.substr(0, 8));
}
+std::string Utils::getVersion(const std::string& inventoryPath) const
+{
+ // Invoke vendor-specify tool to get the version string, e.g.
+ // psutils get-version
+ // /xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply0
+ auto [rc, r] = internal::exec(PSU_VERSION_UTIL, inventoryPath);
+ return (rc == 0) ? r : "";
+}
+
any Utils::getPropertyImpl(sdbusplus::bus::bus& bus, const char* service,
const char* path, const char* interface,
const char* propertyName) const
diff --git a/src/utils.hpp b/src/utils.hpp
index dd1317f..86ee5dd 100644
--- a/src/utils.hpp
+++ b/src/utils.hpp
@@ -63,6 +63,14 @@
*/
std::string getVersionId(const std::string& version);
+/** @brief Get version of PSU specified by the inventory path
+ *
+ * @param[in] inventoryPath - The PSU inventory object path
+ *
+ * @return The version string, or empry string if it fails to get the version
+ */
+std::string getVersion(const std::string& inventoryPath);
+
/**
* @brief The interface for utils
*/
@@ -82,6 +90,8 @@
virtual std::string getVersionId(const std::string& version) const = 0;
+ virtual std::string getVersion(const std::string& inventoryPath) const = 0;
+
virtual any getPropertyImpl(sdbusplus::bus::bus& bus, const char* service,
const char* path, const char* interface,
const char* propertyName) const = 0;
@@ -109,6 +119,8 @@
std::string getVersionId(const std::string& version) const override;
+ std::string getVersion(const std::string& inventoryPath) const override;
+
any getPropertyImpl(sdbusplus::bus::bus& bus, const char* service,
const char* path, const char* interface,
const char* propertyName) const override;
@@ -130,6 +142,11 @@
return getUtils().getVersionId(version);
}
+inline std::string getVersion(const std::string& inventoryPath)
+{
+ return getUtils().getVersion(inventoryPath);
+}
+
template <typename T>
T getProperty(sdbusplus::bus::bus& bus, const char* service, const char* path,
const char* interface, const char* propertyName)