Attempt possible OSStatus interfaces
Newer dbus service will be all using hostX format instead of os.
To allow smooth transition, this commit allow trying all possible
interfaces.
Tested:
Manually verified on single host projects and one multi host
project.
https://paste.googleplex.com/4880312391434240?raw
https://paste.googleplex.com/4537823478415360?raw
Google-Bug-Id: 386135750
Change-Id: Ie83cfe50e75bd470b079dfcf4688223db68cea6f
Signed-off-by: Medicine Yeh <medicineyeh@google.com>
diff --git a/include/gen.hpp b/include/gen.hpp
index ccb4d1d..4332960 100644
--- a/include/gen.hpp
+++ b/include/gen.hpp
@@ -35,14 +35,25 @@
*/
inline psm::PSMConfig GenPSMConfig(int idx)
{
+ std::vector<btm::psm::DbusServiceLocation> possibleOsStatus = {
+ // New multi host nodes style.
+ {"xyz.openbmc_project.State.OperatingSystem",
+ fmt::format("/xyz/openbmc_project/state/host{}", idx)},
+ // Old multi host nodes style.
+ {fmt::format("xyz.openbmc_project.State.OperatingSystem{}", idx),
+ "/xyz/openbmc_project/state/os"},
+ };
+ if (idx == 0)
+ {
+ // Legacy style is only valid if idx == 0. Do not try this interface
+ // on other host nodes.
+ possibleOsStatus.push_back({"xyz.openbmc_project.State.OperatingSystem",
+ "/xyz/openbmc_project/state/os"});
+ }
return {
- .hostStateDbusService = fmt::format("xyz.openbmc_project.State.Host{}",
- idx),
- .hostStateDbusObjPath = fmt::format("/xyz/openbmc_project/state/host{}",
- idx),
- .osStateDbusService =
- fmt::format("xyz.openbmc_project.State.OperatingSystem{}", idx),
- .osStateDbusObjPath = "/xyz/openbmc_project/state/os",
+ .hostState = {fmt::format("xyz.openbmc_project.State.Host{}", idx),
+ fmt::format("/xyz/openbmc_project/state/host{}", idx)},
+ .possibleOsStatus = possibleOsStatus,
};
}
diff --git a/include/psm_handler.hpp b/include/psm_handler.hpp
index aa4c2a0..fa31db9 100644
--- a/include/psm_handler.hpp
+++ b/include/psm_handler.hpp
@@ -24,6 +24,13 @@
namespace btm = boot_time_monitor;
+// Define a structure to hold a path and interface pair.
+struct DbusServiceLocation
+{
+ std::string serviceName;
+ std::string objectPath;
+};
+
/**
* @brief Configuration for interacting with PSM D-Bus interfaces.
*
@@ -32,18 +39,14 @@
*/
struct PSMConfig
{
- /** @brief D-Bus service name for the Host State interface (e.g.,
- * "xyz.openbmc_project.State.Host"). */
- std::string hostStateDbusService;
- /** @brief D-Bus object path for the Host State interface (e.g.,
+ /** @brief Host State D-Bus interface (e.g.,
+ * "xyz.openbmc_project.State.Host",
* "/xyz/openbmc_project/state/host0"). */
- std::string hostStateDbusObjPath;
- /** @brief D-Bus service name for the OS State interface (e.g.,
- * "xyz.openbmc_project.State.OperatingSystem"). */
- std::string osStateDbusService;
- /** @brief D-Bus object path for the OS State interface (e.g.,
+ DbusServiceLocation hostState;
+ /** @brief OS Status D-Bus (e.g.
+ * "xyz.openbmc_project.State.OperatingSystem"
* "/xyz/openbmc_project/state/os"). */
- std::string osStateDbusObjPath;
+ std::vector<DbusServiceLocation> possibleOsStatus;
};
/**
@@ -94,7 +97,7 @@
/** @brief D-Bus match rule watcher for Host State property changes. */
std::unique_ptr<sdbusplus::bus::match::match> mHostStateWatcher;
/** @brief D-Bus match rule watcher for OS Status property changes. */
- std::unique_ptr<sdbusplus::bus::match::match> mOSStatusWatcher;
+ std::vector<std::unique_ptr<sdbusplus::bus::match::match>> mOSStatusWatcher;
};
} // namespace psm
} // namespace boot_time_monitor
diff --git a/src/psm_handler.cpp b/src/psm_handler.cpp
index 1ecac5f..a6405ca 100644
--- a/src/psm_handler.cpp
+++ b/src/psm_handler.cpp
@@ -35,10 +35,10 @@
std::string hostState;
BasicVariantType result;
auto method =
- bus.new_method_call(psmConfig.hostStateDbusService.c_str(), // Service
- psmConfig.hostStateDbusObjPath.c_str(), // Path
- "org.freedesktop.DBus.Properties", // Iface
- "Get"); // Function
+ bus.new_method_call(psmConfig.hostState.serviceName.c_str(), // Service
+ psmConfig.hostState.objectPath.c_str(), // Path
+ "org.freedesktop.DBus.Properties", // Iface
+ "Get"); // Function
method.append("xyz.openbmc_project.State.Host", "CurrentHostState");
try
{
@@ -52,7 +52,7 @@
"Failed to query `CurrentHostState` with busctl get-property {} {} "
"xyz.openbmc_project.State.Host CurrentHostState"
". Got error: {}\n",
- psmConfig.hostStateDbusService, psmConfig.hostStateDbusObjPath,
+ psmConfig.hostState.serviceName, psmConfig.hostState.objectPath,
e.what());
}
return hostState;
@@ -61,35 +61,46 @@
std::string inline queryOSStatus(sdbusplus::bus::bus& bus,
const btm::psm::PSMConfig& psmConfig)
{
- std::string oSState;
- BasicVariantType result;
- auto method =
- bus.new_method_call(psmConfig.osStateDbusService.c_str(), // Service
- psmConfig.osStateDbusObjPath.c_str(), // Path
- "org.freedesktop.DBus.Properties", // Iface
- "Get"); // Function
- method.append("xyz.openbmc_project.State.OperatingSystem.Status",
- "OperatingSystemState");
- try
+ std::vector<std::string> errors;
+ for (const auto& service : psmConfig.possibleOsStatus)
{
- bus.call(method).read(result);
- oSState = std::get<std::string>(result);
+ auto method =
+ bus.new_method_call(service.serviceName.c_str(), // Service
+ service.objectPath.c_str(), // Path
+ "org.freedesktop.DBus.Properties", // Iface
+ "Get"); // Function
+ method.append("xyz.openbmc_project.State.OperatingSystem.Status",
+ "OperatingSystemState");
+ try
+ {
+ BasicVariantType result;
+ bus.call(method).read(result);
+ return std::get<std::string>(result);
+ }
+ catch (const sdbusplus::exception::SdBusError& e)
+ {
+ std::string errorMessage = fmt::format(
+ "busctl get-property {} {} "
+ "xyz.openbmc_project.State.OperatingSystem.Status OperatingSystemState."
+ "Got error: {}\n",
+ service.serviceName, service.objectPath, e.what());
+ errors.push_back(errorMessage);
+ }
}
- catch (const sdbusplus::exception::SdBusError& e)
+
+ // If we reach here, all attempts have failed. Print all errors.
+ fmt::print(
+ stderr,
+ "Failed to query OperatingSystemState, the attempts are as followed:\n");
+ for (const auto& error : errors)
{
- fmt::print(
- stderr,
- "Failed to query OperatingSystemState with busctl get-property {} {} "
- "xyz.openbmc_project.State.OperatingSystem.Status OperatingSystemState."
- "Got error: {}\n",
- psmConfig.hostStateDbusService, psmConfig.hostStateDbusObjPath,
- e.what());
+ fmt::print(stderr, "{}\n", error);
}
- return oSState;
+ return "";
}
std::string inline queryNameOwner(sdbusplus::bus::bus& bus,
- const btm::psm::PSMConfig& psmConfig)
+ const btm::psm::DbusServiceLocation& service)
{
std::string ownerUniqueName;
try
@@ -97,7 +108,7 @@
auto method =
bus.new_method_call("org.freedesktop.DBus", "/org/freedesktop/DBus",
"org.freedesktop.DBus", "GetNameOwner");
- method.append(std::string(psmConfig.osStateDbusService));
+ method.append(std::string(service.serviceName));
bus.call(method).read(ownerUniqueName);
}
catch (const sdbusplus::exception::SdBusError& e)
@@ -119,7 +130,7 @@
mHostStateWatcher = std::make_unique<sdbusplus::bus::match::match>(
bus,
sdbusplus::bus::match::rules::propertiesChanged(
- psmConfig.hostStateDbusObjPath, "xyz.openbmc_project.State.Host"),
+ psmConfig.hostState.objectPath, "xyz.openbmc_project.State.Host"),
[this](sdbusplus::message::message& message) {
hostStateWatcherCallback(message);
});
@@ -127,21 +138,25 @@
mPreOSStatus = queryOSStatus(bus, psmConfig);
fmt::print("{} `OperatingSystemState` is `{}`\n", mNodeConfig.node_name,
mPreOSStatus);
- mOSStatusWatcher = std::make_unique<sdbusplus::bus::match::match>(
- bus,
- sdbusplus::bus::match::rules::propertiesChanged(
- psmConfig.osStateDbusObjPath,
- "xyz.openbmc_project.State.OperatingSystem.Status"),
- [this, &bus, psmConfig](sdbusplus::message::message& message) {
- const std::string& signalSenderUniqueName = message.get_sender();
- std::string ownerUniqueName = queryNameOwner(bus, psmConfig);
- // Compare the signal's sender to the name's rightful owner.
- if (signalSenderUniqueName != ownerUniqueName)
- {
- return; // The signal came from a different process. Ignore it.
- }
- oSStatusWatcherCallback(message);
- });
+ for (const auto& service : psmConfig.possibleOsStatus)
+ {
+ mOSStatusWatcher.emplace_back(
+ std::make_unique<sdbusplus::bus::match::match>(
+ bus,
+ sdbusplus::bus::match::rules::propertiesChanged(
+ service.objectPath,
+ "xyz.openbmc_project.State.OperatingSystem.Status"),
+ [this, &bus, service](sdbusplus::message::message& message) {
+ const std::string& signalSenderUniqueName = message.get_sender();
+ std::string ownerUniqueName = queryNameOwner(bus, service);
+ // Compare the signal's sender to the name's rightful owner.
+ if (signalSenderUniqueName != ownerUniqueName)
+ {
+ return; // The signal came from a different process. Ignore it.
+ }
+ oSStatusWatcherCallback(message);
+ }));
+ }
}
void Handler::hostStateWatcherCallback(sdbusplus::message::message& message)
@@ -159,6 +174,7 @@
{
const std::string curHostState =
std::get<std::string>(findState->second);
+ // NOTE: Some BMC may emit the same status on change.
if (curHostState == mPreHostState)
{
return;
@@ -194,6 +210,7 @@
{
const std::string curOSStatus =
std::get<std::string>(findState->second);
+ // NOTE: Some BMC may emit the same status on change.
if (curOSStatus == mPreOSStatus)
{
return;
@@ -213,5 +230,6 @@
mNodeConfig.node_name, curOSStatus);
}
}
+
} // namespace psm
} // namespace boot_time_monitor