/* // 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" static inline void checkAndThrowInternalFailure(boost::system::error_code &ec, const std::string &msg) { if (ec) { std::string msgToLog = ec.message() + (msg.empty() ? "" : " - " + msg); phosphor::logging::log(msgToLog.c_str()); phosphor::logging::elog< sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure>(); } return; } void systemdDaemonReload( const std::shared_ptr &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) { phosphor::logging::log( "Unable to get job id from job path"); phosphor::logging::elog< sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure>(); } return static_cast(std::stoul(path.substr(pos + 1))); } void systemdUnitAction(const std::shared_ptr &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( 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 (1) { 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; } phosphor::logging::log( "Systemd operation failed for job query"); phosphor::logging::elog(); } 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 &conn, boost::asio::yield_context yield, const std::vector &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; }