// SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: Copyright 2017 IBM Corporation #include "monitor.hpp" #include namespace phosphor { namespace unit { namespace failure { using namespace phosphor::logging; constexpr auto failedState = "failed"; constexpr auto startMethod = "StartUnit"; constexpr auto stopMethod = "StopUnit"; constexpr auto systemdService = "org.freedesktop.systemd1"; constexpr auto systemdObjPath = "/org/freedesktop/systemd1"; constexpr auto systemdInterface = "org.freedesktop.systemd1.Manager"; constexpr auto systemdPropertyInterface = "org.freedesktop.DBus.Properties"; constexpr auto systemdUnitInterface = "org.freedesktop.systemd1.Unit"; void Monitor::analyze() { if (inFailedState(getSourceUnitPath())) { runTargetAction(); } } bool Monitor::inFailedState(const std::string& path) { std::variant property; auto method = bus.new_method_call(systemdService, path.c_str(), systemdPropertyInterface, "Get"); method.append(systemdUnitInterface, "ActiveState"); try { auto reply = bus.call(method); reply.read(property); } catch (const sdbusplus::exception_t&) { log("Failed reading ActiveState DBus property", entry("UNIT=%s", source.c_str())); throw; } auto value = std::get(property); return (value == failedState); } std::string Monitor::getSourceUnitPath() { sdbusplus::message::object_path path; auto method = bus.new_method_call(systemdService, systemdObjPath, systemdInterface, "GetUnit"); method.append(source); try { auto reply = bus.call(method); reply.read(path); } catch (const sdbusplus::exception_t&) { log("Failed GetUnit DBus method call", entry("UNIT=%s", source.c_str())); throw; } return static_cast(path); } void Monitor::runTargetAction() { // Start or stop the target unit const auto* methodCall = (action == Action::start) ? startMethod : stopMethod; log("The source unit is in failed state, " "running target action", entry("SOURCE=%s", source.c_str()), entry("TARGET=%s", target.c_str()), entry("ACTION=%s", methodCall)); auto method = this->bus.new_method_call(systemdService, systemdObjPath, systemdInterface, methodCall); method.append(target); method.append("replace"); try { auto reply = bus.call(method); } catch (const sdbusplus::exception_t&) { log("Failed to run action on the target unit", entry("UNIT=%s", target.c_str())); throw; } } } // namespace failure } // namespace unit } // namespace phosphor