1 /* 2 // Copyright (c) 2018 Intel Corporation 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 */ 16 #include "utils.hpp" 17 18 void checkAndThrowInternalFailure(boost::system::error_code& ec, 19 const std::string& msg) 20 { 21 if (ec) 22 { 23 std::string msgToLog = ec.message() + (msg.empty() ? "" : " - " + msg); 24 phosphor::logging::log<phosphor::logging::level::ERR>(msgToLog.c_str()); 25 phosphor::logging::elog< 26 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure>(); 27 } 28 return; 29 } 30 31 void systemdDaemonReload( 32 const std::shared_ptr<sdbusplus::asio::connection>& conn, 33 boost::asio::yield_context yield) 34 { 35 boost::system::error_code ec; 36 conn->yield_method_call<>(yield, ec, sysdService, sysdObjPath, sysdMgrIntf, 37 sysdReloadMethod); 38 checkAndThrowInternalFailure(ec, "daemon-reload operation failed"); 39 return; 40 } 41 42 static inline uint32_t getJobId(const std::string& path) 43 { 44 auto pos = path.rfind("/"); 45 if (pos == std::string::npos) 46 { 47 phosphor::logging::log<phosphor::logging::level::ERR>( 48 "Unable to get job id from job path"); 49 phosphor::logging::elog< 50 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure>(); 51 } 52 return static_cast<uint32_t>(std::stoul(path.substr(pos + 1))); 53 } 54 55 void systemdUnitAction(const std::shared_ptr<sdbusplus::asio::connection>& conn, 56 boost::asio::yield_context yield, 57 const std::string& unitName, 58 const std::string& actionMethod) 59 { 60 boost::system::error_code ec; 61 auto jobPath = conn->yield_method_call<sdbusplus::message::object_path>( 62 yield, ec, sysdService, sysdObjPath, sysdMgrIntf, actionMethod, 63 unitName, sysdReplaceMode); 64 checkAndThrowInternalFailure(ec, 65 "Systemd operation failed, " + actionMethod); 66 // Query the job till it doesn't exist anymore. 67 // this way we guarantee that queued job id is done. 68 // this is needed to make sure dependency list on units are 69 // properly handled. 70 while (1) 71 { 72 ec.clear(); 73 conn->yield_method_call<>(yield, ec, sysdService, sysdObjPath, 74 sysdMgrIntf, sysdGetJobMethod, 75 getJobId(jobPath.str)); 76 if (ec) 77 { 78 if (ec.value() == boost::system::errc::no_such_file_or_directory) 79 { 80 // Queued job is done, return now 81 return; 82 } 83 phosphor::logging::log<phosphor::logging::level::ERR>( 84 "Systemd operation failed for job query"); 85 phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common:: 86 Error::InternalFailure>(); 87 } 88 boost::asio::steady_timer sleepTimer(conn->get_io_context()); 89 sleepTimer.expires_after(std::chrono::milliseconds(20)); 90 ec.clear(); 91 sleepTimer.async_wait(yield[ec]); 92 checkAndThrowInternalFailure(ec, "Systemd operation timer error"); 93 } 94 return; 95 } 96 97 void systemdUnitFilesStateChange( 98 const std::shared_ptr<sdbusplus::asio::connection>& conn, 99 boost::asio::yield_context yield, const std::vector<std::string>& unitFiles, 100 const std::string& unitState, bool maskedState, bool enabledState) 101 { 102 boost::system::error_code ec; 103 104 if (unitState == stateMasked && !maskedState) 105 { 106 conn->yield_method_call<>(yield, ec, sysdService, sysdObjPath, 107 sysdMgrIntf, "UnmaskUnitFiles", unitFiles, 108 false); 109 checkAndThrowInternalFailure(ec, "Systemd UnmaskUnitFiles() failed."); 110 } 111 else if (unitState != stateMasked && maskedState) 112 { 113 conn->yield_method_call<>(yield, ec, sysdService, sysdObjPath, 114 sysdMgrIntf, "MaskUnitFiles", unitFiles, 115 false, false); 116 checkAndThrowInternalFailure(ec, "Systemd MaskUnitFiles() failed."); 117 } 118 ec.clear(); 119 if (unitState != stateEnabled && enabledState) 120 { 121 conn->yield_method_call<>(yield, ec, sysdService, sysdObjPath, 122 sysdMgrIntf, "EnableUnitFiles", unitFiles, 123 false, false); 124 checkAndThrowInternalFailure(ec, "Systemd EnableUnitFiles() failed."); 125 } 126 else if (unitState != stateDisabled && !enabledState) 127 { 128 conn->yield_method_call<>(yield, ec, sysdService, sysdObjPath, 129 sysdMgrIntf, "DisableUnitFiles", unitFiles, 130 false); 131 checkAndThrowInternalFailure(ec, "Systemd DisableUnitFiles() failed."); 132 } 133 return; 134 } 135