blob: 80ccdc5e5ed7c956e697f5fa7caf0b3cfc75c2ac [file] [log] [blame]
/*
// 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;
}