srvcfg: Updated for dynamic service/socket mgmt
Fixed srvcfg crash manager issue, by doing the service &
socket unit file queries dynamically and exposing the objects
to be controlled. This takes care of instanced service &
socket files like phosphor-ipmi-net@eth0 or
phosphor-ipmi-net@eth1 dynamically.
Tested:
1. Verified as per the base service name, all the instanced
service & socket names are dynamically queried and exposed
2. Made sure to list the disabled services thorugh this method
3. Made sure new services listed after fw-update are also
exposed as objects
4. Verfied phosphor-ipmi-net@eth0 port change using ipmitool
-p <newport> option
5. Verified permanent disable of the unit.
6. Verified run time enable / disable of the service.
7. Verified phosphor-ipmi-kcs service permanent & run time
enable / disable
Change-Id: Ib933a2fbff73eae4348a5940d350ae7972db03fb
Signed-off-by: Richard Marian Thomaiyar <richard.marian.thomaiyar@linux.intel.com>
diff --git a/src/utils.cpp b/src/utils.cpp
index 32ac69d..cf15dee 100644
--- a/src/utils.cpp
+++ b/src/utils.cpp
@@ -15,133 +15,120 @@
*/
#include "utils.hpp"
-void systemdDaemonReload(
- const std::shared_ptr<sdbusplus::asio::connection> &conn)
+static inline void checkAndThrowInternalFailure(boost::system::error_code &ec,
+ const std::string &msg)
{
- try
+ if (ec)
{
- conn->async_method_call(
- [](boost::system::error_code ec) {
- if (ec)
- {
- phosphor::logging::log<phosphor::logging::level::ERR>(
- "async error: Failed to do systemd reload.");
- return;
- }
- return;
- },
- "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager", "Reload");
- }
- catch (const sdbusplus::exception::SdBusError &e)
- {
- phosphor::logging::log<phosphor::logging::level::ERR>(
- "daemon-reload operation failed.");
+ 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 systemdUnitAction(const std::shared_ptr<sdbusplus::asio::connection> &conn,
- const std::string &unitName,
- const std::string &actionMethod)
+void systemdDaemonReload(
+ const std::shared_ptr<sdbusplus::asio::connection> &conn,
+ boost::asio::yield_context yield)
{
- try
- {
- conn->async_method_call(
- [](boost::system::error_code ec,
- const sdbusplus::message::object_path &objPath) {
- if (ec)
- {
- phosphor::logging::log<phosphor::logging::level::ERR>(
- "async error: Failed to do systemd action");
- return;
- }
- phosphor::logging::log<phosphor::logging::level::ERR>(
- "Created unit action job.",
- phosphor::logging::entry("JobID=%s", objPath.str.c_str()));
- return;
- },
- "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager", actionMethod, unitName,
- "replace");
- }
- catch (const sdbusplus::exception::SdBusError &e)
+ 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>(
- "Systemd operation failed.",
- phosphor::logging::entry("ACTION=%s", actionMethod.c_str()));
+ "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::deadline_timer sleepTimer(conn->get_io_context());
+ sleepTimer.expires_from_now(boost::posix_time::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,
- const std::vector<std::string> &unitFiles, const std::string &unitState)
+ boost::asio::yield_context yield, const std::vector<std::string> &unitFiles,
+ const std::string &unitState, bool maskedState, bool enabledState)
{
- try
- {
- if (unitState == "enabled")
- {
- conn->async_method_call(
- [](boost::system::error_code ec) {
- if (ec)
- {
- phosphor::logging::log<phosphor::logging::level::ERR>(
- "async error: Failed to perform UnmaskUnitFiles.");
- return;
- }
- return;
- },
- "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager", "UnmaskUnitFiles",
- unitFiles, false);
- }
- else if (unitState == "disabled")
- {
- conn->async_method_call(
- [](boost::system::error_code ec) {
- if (ec)
- {
- phosphor::logging::log<phosphor::logging::level::ERR>(
- "async error: Failed to perform MaskUnitFiles.");
- return;
- }
- return;
- },
- "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager", "MaskUnitFiles", unitFiles,
- false, false);
- }
- else
- {
- // Not supported unit State
- phosphor::logging::log<phosphor::logging::level::ERR>(
- "invalid Unit state",
- phosphor::logging::entry("STATE=%s", unitState.c_str()));
- phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common::
- Error::InternalFailure>();
- }
- }
- catch (const sdbusplus::exception::SdBusError &e)
- {
- phosphor::logging::log<phosphor::logging::level::ERR>(
- "Systemd state change operation failed.");
- phosphor::logging::elog<
- sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure>();
- }
+ 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;
}
-
-bool checkSystemdUnitExist(const std::string &unitName)
-{
- std::experimental::filesystem::path unitFilePath(
- std::string("/lib/systemd/system/") + unitName);
- return std::experimental::filesystem::exists(unitFilePath);
-}