blob: 1ed4c1c759f23a8de6e0afe19f13d3157360ce75 [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);
George Liucb267c82022-01-05 17:53:28 +080024 lg2::error("Check and throw internal failure: {MSG}", "MSG", msgToLog);
Vernon Maueryba2c0832020-07-15 10:02:38 -070025 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 {
George Liucb267c82022-01-05 17:53:28 +080047 lg2::error("Unable to get job id from {PATH}.", "PATH", path);
Vernon Maueryba2c0832020-07-15 10:02:38 -070048 phosphor::logging::elog<
49 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure>();
50 }
51 return static_cast<uint32_t>(std::stoul(path.substr(pos + 1)));
52}
53
54void systemdUnitAction(const std::shared_ptr<sdbusplus::asio::connection>& conn,
55 boost::asio::yield_context yield,
56 const std::string& unitName,
57 const std::string& actionMethod)
58{
59 boost::system::error_code ec;
60 auto jobPath = conn->yield_method_call<sdbusplus::message::object_path>(
61 yield, ec, sysdService, sysdObjPath, sysdMgrIntf, actionMethod,
62 unitName, sysdReplaceMode);
63 checkAndThrowInternalFailure(ec,
64 "Systemd operation failed, " + actionMethod);
65 // Query the job till it doesn't exist anymore.
66 // this way we guarantee that queued job id is done.
67 // this is needed to make sure dependency list on units are
68 // properly handled.
Bruce Mitchella1fe1a22021-10-18 18:59:38 -050069 while (true)
Vernon Maueryba2c0832020-07-15 10:02:38 -070070 {
71 ec.clear();
72 conn->yield_method_call<>(yield, ec, sysdService, sysdObjPath,
73 sysdMgrIntf, sysdGetJobMethod,
74 getJobId(jobPath.str));
75 if (ec)
76 {
77 if (ec.value() == boost::system::errc::no_such_file_or_directory)
78 {
79 // Queued job is done, return now
80 return;
81 }
George Liucb267c82022-01-05 17:53:28 +080082 lg2::error("Systemd operation failed for job query: {EC}", "EC",
83 ec.value());
Vernon Maueryba2c0832020-07-15 10:02:38 -070084 phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common::
85 Error::InternalFailure>();
86 }
87 boost::asio::steady_timer sleepTimer(conn->get_io_context());
88 sleepTimer.expires_after(std::chrono::milliseconds(20));
89 ec.clear();
90 sleepTimer.async_wait(yield[ec]);
91 checkAndThrowInternalFailure(ec, "Systemd operation timer error");
92 }
93 return;
94}
95
96void systemdUnitFilesStateChange(
97 const std::shared_ptr<sdbusplus::asio::connection>& conn,
98 boost::asio::yield_context yield, const std::vector<std::string>& unitFiles,
99 const std::string& unitState, bool maskedState, bool enabledState)
100{
101 boost::system::error_code ec;
102
103 if (unitState == stateMasked && !maskedState)
104 {
105 conn->yield_method_call<>(yield, ec, sysdService, sysdObjPath,
106 sysdMgrIntf, "UnmaskUnitFiles", unitFiles,
107 false);
108 checkAndThrowInternalFailure(ec, "Systemd UnmaskUnitFiles() failed.");
109 }
110 else if (unitState != stateMasked && maskedState)
111 {
112 conn->yield_method_call<>(yield, ec, sysdService, sysdObjPath,
113 sysdMgrIntf, "MaskUnitFiles", unitFiles,
114 false, false);
115 checkAndThrowInternalFailure(ec, "Systemd MaskUnitFiles() failed.");
116 }
117 ec.clear();
118 if (unitState != stateEnabled && enabledState)
119 {
120 conn->yield_method_call<>(yield, ec, sysdService, sysdObjPath,
121 sysdMgrIntf, "EnableUnitFiles", unitFiles,
122 false, false);
123 checkAndThrowInternalFailure(ec, "Systemd EnableUnitFiles() failed.");
124 }
125 else if (unitState != stateDisabled && !enabledState)
126 {
127 conn->yield_method_call<>(yield, ec, sysdService, sysdObjPath,
128 sysdMgrIntf, "DisableUnitFiles", unitFiles,
129 false);
130 checkAndThrowInternalFailure(ec, "Systemd DisableUnitFiles() failed.");
131 }
132 return;
133}