| /* |
| // Copyright (c) 2018 Intel Corporation |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| */ |
| #include "utils.hpp" |
| |
| void checkAndThrowInternalFailure(boost::system::error_code& ec, |
| const std::string& msg) |
| { |
| if (ec) |
| { |
| std::string msgToLog = ec.message() + (msg.empty() ? "" : " - " + msg); |
| lg2::error("Check and throw internal failure: {MSG}", "MSG", msgToLog); |
| phosphor::logging::elog< |
| sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure>(); |
| } |
| return; |
| } |
| |
| void systemdDaemonReload( |
| const std::shared_ptr<sdbusplus::asio::connection>& conn, |
| boost::asio::yield_context yield) |
| { |
| boost::system::error_code ec; |
| conn->yield_method_call<>(yield, ec, sysdService, sysdObjPath, sysdMgrIntf, |
| sysdReloadMethod); |
| checkAndThrowInternalFailure(ec, "daemon-reload operation failed"); |
| return; |
| } |
| |
| static inline uint32_t getJobId(const std::string& path) |
| { |
| auto pos = path.rfind("/"); |
| if (pos == std::string::npos) |
| { |
| lg2::error("Unable to get job id from {PATH}.", "PATH", path); |
| phosphor::logging::elog< |
| sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure>(); |
| } |
| return static_cast<uint32_t>(std::stoul(path.substr(pos + 1))); |
| } |
| |
| void systemdUnitAction(const std::shared_ptr<sdbusplus::asio::connection>& conn, |
| boost::asio::yield_context yield, |
| const std::string& unitName, |
| const std::string& actionMethod) |
| { |
| boost::system::error_code ec; |
| auto jobPath = conn->yield_method_call<sdbusplus::message::object_path>( |
| yield, ec, sysdService, sysdObjPath, sysdMgrIntf, actionMethod, |
| unitName, sysdReplaceMode); |
| checkAndThrowInternalFailure(ec, |
| "Systemd operation failed, " + actionMethod); |
| // Query the job till it doesn't exist anymore. |
| // this way we guarantee that queued job id is done. |
| // this is needed to make sure dependency list on units are |
| // properly handled. |
| while (true) |
| { |
| ec.clear(); |
| conn->yield_method_call<>(yield, ec, sysdService, sysdObjPath, |
| sysdMgrIntf, sysdGetJobMethod, |
| getJobId(jobPath.str)); |
| if (ec) |
| { |
| if (ec.value() == boost::system::errc::no_such_file_or_directory) |
| { |
| // Queued job is done, return now |
| return; |
| } |
| lg2::error("Systemd operation failed for job query: {EC}", "EC", |
| ec.value()); |
| phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common:: |
| Error::InternalFailure>(); |
| } |
| boost::asio::steady_timer sleepTimer(conn->get_io_context()); |
| sleepTimer.expires_after(std::chrono::milliseconds(20)); |
| ec.clear(); |
| sleepTimer.async_wait(yield[ec]); |
| checkAndThrowInternalFailure(ec, "Systemd operation timer error"); |
| } |
| return; |
| } |
| |
| void systemdUnitFilesStateChange( |
| const std::shared_ptr<sdbusplus::asio::connection>& conn, |
| boost::asio::yield_context yield, const std::vector<std::string>& unitFiles, |
| const std::string& unitState, bool maskedState, bool enabledState) |
| { |
| boost::system::error_code ec; |
| |
| if (unitState == stateMasked && !maskedState) |
| { |
| conn->yield_method_call<>(yield, ec, sysdService, sysdObjPath, |
| sysdMgrIntf, "UnmaskUnitFiles", unitFiles, |
| false); |
| checkAndThrowInternalFailure(ec, "Systemd UnmaskUnitFiles() failed."); |
| } |
| else if (unitState != stateMasked && maskedState) |
| { |
| conn->yield_method_call<>(yield, ec, sysdService, sysdObjPath, |
| sysdMgrIntf, "MaskUnitFiles", unitFiles, |
| false, false); |
| checkAndThrowInternalFailure(ec, "Systemd MaskUnitFiles() failed."); |
| } |
| ec.clear(); |
| if (unitState != stateEnabled && enabledState) |
| { |
| conn->yield_method_call<>(yield, ec, sysdService, sysdObjPath, |
| sysdMgrIntf, "EnableUnitFiles", unitFiles, |
| false, false); |
| checkAndThrowInternalFailure(ec, "Systemd EnableUnitFiles() failed."); |
| } |
| else if (unitState != stateDisabled && !enabledState) |
| { |
| conn->yield_method_call<>(yield, ec, sysdService, sysdObjPath, |
| sysdMgrIntf, "DisableUnitFiles", unitFiles, |
| false); |
| checkAndThrowInternalFailure(ec, "Systemd DisableUnitFiles() failed."); |
| } |
| return; |
| } |