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