psutils: Move functions from updater to utils
Move common, utility functions from updater.*pp to utils.*pp. This will
enable those functions to be used by other command line options in the
psutils tool.
Modify --get-version and --get-model to use the new utility functions.
Also update --get-version to provide a single getVersion() function that
handles the existence of the psu.json file as a low-level implementation
detail.
Tested:
* Verified all automated tests run successfully
* Verified --get-version still works
* With psu.json file
* Without psu.json file
* Verified --get-model still works
* With psu.json file
* Without psu.json file
* Verified --update still gets correct device path, device name, and I2C
bus/address from functions that moved to utils.*pp
* The complete test plan is available at
https://gist.github.com/smccarney/c049e24655d32e22cab9d521d145774a
Change-Id: I51ceca10957dc9a924d0d7516dc29632a6ed82d3
Signed-off-by: Shawn McCarney <shawnmm@us.ibm.com>
diff --git a/tools/power-utils/version.cpp b/tools/power-utils/version.cpp
index 26507ee..738664d 100644
--- a/tools/power-utils/version.cpp
+++ b/tools/power-utils/version.cpp
@@ -39,6 +39,17 @@
namespace internal
{
+// PsuInfo contains the device path, PMBus access type, and sysfs file name
+using PsuVersionInfo =
+ std::tuple<std::string, phosphor::pmbus::Type, std::string>;
+
+/**
+ * @brief Get PSU version information
+ *
+ * @param[in] psuInventoryPath - The PSU inventory path.
+ *
+ * @return tuple - device path, PMBus access type, and sysfs file name
+ */
PsuVersionInfo getVersionInfo(const std::string& psuInventoryPath)
{
auto data = loadJSONFromFile(PSU_JSON_PATH);
@@ -64,24 +75,83 @@
auto type = getPMBusAccessType(data);
- std::string versionStr;
+ std::string fileName;
for (const auto& fru : data["fruConfigs"])
{
- if (fru["propertyName"] == "Version")
+ if (fru.contains("propertyName") &&
+ (fru["propertyName"] == "Version") && fru.contains("fileName"))
{
- versionStr = fru["fileName"].get<std::string>();
+ fileName = fru["fileName"];
break;
}
}
- if (versionStr.empty())
+ if (fileName.empty())
{
log<level::WARNING>("Unable to find Version file");
return {};
}
- return std::make_tuple(*devicePath, type, versionStr);
+ return std::make_tuple(*devicePath, type, fileName);
}
-// A default implemention compare the string itself
+/**
+ * @brief Get the PSU version from sysfs.
+ *
+ * Obtain PSU information from the PSU JSON file.
+ *
+ * Throws an exception if an error occurs.
+ *
+ * @param[in] psuInventoryPath - PSU D-Bus inventory path
+ *
+ * @return PSU version, or "" if none found
+ */
+std::string getVersionJson(const std::string& psuInventoryPath)
+{
+ // Get PSU device path, PMBus access type, and sysfs file name from JSON
+ const auto [devicePath, type, fileName] = getVersionInfo(psuInventoryPath);
+
+ // Read version from sysfs file
+ std::string version;
+ if (!devicePath.empty() && !fileName.empty())
+ {
+ phosphor::pmbus::PMBus pmbus(devicePath);
+ version = pmbus.readString(fileName, type);
+ }
+ return version;
+}
+
+/**
+ * @brief Get the PSU version from sysfs.
+ *
+ * Obtain PSU information from D-Bus.
+ *
+ * Throws an exception if an error occurs.
+ *
+ * @param[in] bus - D-Bus connection
+ * @param[in] psuInventoryPath - PSU D-Bus inventory path
+ *
+ * @return PSU version, or "" if none found
+ */
+std::string getVersionDbus(sdbusplus::bus_t& bus,
+ const std::string& psuInventoryPath)
+{
+ // Get PSU I2C bus/address and create PMBus interface
+ const auto [i2cbus, i2caddr] = getPsuI2c(bus, psuInventoryPath);
+ auto pmbus = getPmbusIntf(i2cbus, i2caddr);
+
+ // Read version from sysfs file
+ std::string name = "fw_version";
+ auto type = phosphor::pmbus::Type::HwmonDeviceDebug;
+ std::string version = pmbus->readString(name, type);
+ return version;
+}
+
+/**
+ * @brief Get firmware latest version
+ *
+ * @param[in] versions - String of versions
+ *
+ * @return version - latest firmware level
+ */
std::string getLatestDefault(const std::vector<std::string>& versions)
{
std::string latest;
@@ -97,38 +167,22 @@
} // namespace internal
-std::string getVersion(const std::string& psuInventoryPath)
-{
- const auto& [devicePath, type, versionStr] =
- internal::getVersionInfo(psuInventoryPath);
- if (devicePath.empty() || versionStr.empty())
- {
- return "";
- }
- std::string version;
- try
- {
- phosphor::pmbus::PMBus pmbus(devicePath);
- version = pmbus.readString(versionStr, type);
- }
- catch (const std::exception& ex)
- {
- log<level::ERR>(ex.what());
- }
- return version;
-}
-
std::string getVersion(sdbusplus::bus_t& bus,
const std::string& psuInventoryPath)
{
std::string version;
try
{
- const auto& [i2cbus, i2caddr] = getPsuI2c(bus, psuInventoryPath);
- auto pmbus = getPmbusIntf(i2cbus, i2caddr);
- std::string name = "fw_version";
- auto type = phosphor::pmbus::Type::HwmonDeviceDebug;
- version = pmbus->readString(name, type);
+ if (usePsuJsonFile())
+ {
+ // Obtain PSU information from JSON file
+ version = internal::getVersionJson(psuInventoryPath);
+ }
+ else
+ {
+ // Obtain PSU information from D-Bus
+ version = internal::getVersionDbus(bus, psuInventoryPath);
+ }
}
catch (const std::exception& e)
{
@@ -157,4 +211,5 @@
// So just compare by strings is OK for these cases
return internal::getLatestDefault(versions);
}
+
} // namespace version