/* | |
// 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<phosphor::logging::level::ERR>(msgToLog.c_str()); | |
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) | |
{ | |
phosphor::logging::log<phosphor::logging::level::ERR>( | |
"Unable to get job id from job 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 (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<phosphor::logging::level::ERR>( | |
"Systemd operation failed for job query"); | |
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; | |
} |