blob: 908f34f24be2a784ed1cc990b47a42a60dad411e [file] [log] [blame]
Vernon Maueryba2c0832020-07-15 10:02:38 -07001/*
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
George Liua19b5092021-05-24 15:54:02 +080018void checkAndThrowInternalFailure(boost::system::error_code& ec,
19 const std::string& msg)
Vernon Maueryba2c0832020-07-15 10:02:38 -070020{
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
31void 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
42static 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
55void 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.
Bruce Mitchella1fe1a22021-10-18 18:59:38 -050070 while (true)
Vernon Maueryba2c0832020-07-15 10:02:38 -070071 {
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
97void 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}