1cf066aceSPatrick Venture /*
2cf066aceSPatrick Venture * Copyright 2019 Google Inc.
3cf066aceSPatrick Venture *
4cf066aceSPatrick Venture * Licensed under the Apache License, Version 2.0 (the "License");
5cf066aceSPatrick Venture * you may not use this file except in compliance with the License.
6cf066aceSPatrick Venture * You may obtain a copy of the License at
7cf066aceSPatrick Venture *
8cf066aceSPatrick Venture * http://www.apache.org/licenses/LICENSE-2.0
9cf066aceSPatrick Venture *
10cf066aceSPatrick Venture * Unless required by applicable law or agreed to in writing, software
11cf066aceSPatrick Venture * distributed under the License is distributed on an "AS IS" BASIS,
12cf066aceSPatrick Venture * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cf066aceSPatrick Venture * See the License for the specific language governing permissions and
14cf066aceSPatrick Venture * limitations under the License.
15cf066aceSPatrick Venture */
16cf066aceSPatrick Venture
17cf066aceSPatrick Venture #include "general_systemd.hpp"
18cf066aceSPatrick Venture
19cf066aceSPatrick Venture #include "status.hpp"
20cf066aceSPatrick Venture
219b37b095SPatrick Venture #include <sdbusplus/bus.hpp>
229b37b095SPatrick Venture
23cf066aceSPatrick Venture #include <fstream>
24cf066aceSPatrick Venture #include <memory>
25cf066aceSPatrick Venture #include <string>
26cf066aceSPatrick Venture #include <vector>
27cf066aceSPatrick Venture
28cf066aceSPatrick Venture namespace ipmi_flash
29cf066aceSPatrick Venture {
30cf066aceSPatrick Venture
31b22ebbf3SWilliam A. Kennington III static constexpr auto systemdService = "org.freedesktop.systemd1";
32b22ebbf3SWilliam A. Kennington III static constexpr auto systemdRoot = "/org/freedesktop/systemd1";
33b22ebbf3SWilliam A. Kennington III static constexpr auto systemdInterface = "org.freedesktop.systemd1.Manager";
3401593f96SWilliam A. Kennington III static constexpr auto jobInterface = "org.freedesktop.systemd1.Job";
35b22ebbf3SWilliam A. Kennington III
trigger()36b22ebbf3SWilliam A. Kennington III bool SystemdNoFile::trigger()
37b22ebbf3SWilliam A. Kennington III {
38b22ebbf3SWilliam A. Kennington III if (job)
39b22ebbf3SWilliam A. Kennington III {
40b22ebbf3SWilliam A. Kennington III std::fprintf(stderr, "Job alreading running %s: %s\n",
41b22ebbf3SWilliam A. Kennington III triggerService.c_str(), job->c_str());
42b22ebbf3SWilliam A. Kennington III return false;
43b22ebbf3SWilliam A. Kennington III }
44b22ebbf3SWilliam A. Kennington III
45b22ebbf3SWilliam A. Kennington III try
46b22ebbf3SWilliam A. Kennington III {
4740fbb0c6SPatrick Williams jobMonitor.emplace(bus,
48b22ebbf3SWilliam A. Kennington III "type='signal',"
49b22ebbf3SWilliam A. Kennington III "sender='org.freedesktop.systemd1',"
50b22ebbf3SWilliam A. Kennington III "path='/org/freedesktop/systemd1',"
51b22ebbf3SWilliam A. Kennington III "interface='org.freedesktop.systemd1.Manager',"
52b22ebbf3SWilliam A. Kennington III "member='JobRemoved',",
5340fbb0c6SPatrick Williams [&](sdbusplus::message_t& m) { this->match(m); });
54b22ebbf3SWilliam A. Kennington III
55b22ebbf3SWilliam A. Kennington III auto method = bus.new_method_call(systemdService, systemdRoot,
56b22ebbf3SWilliam A. Kennington III systemdInterface, "StartUnit");
57b22ebbf3SWilliam A. Kennington III method.append(triggerService);
58b22ebbf3SWilliam A. Kennington III method.append(mode);
59b22ebbf3SWilliam A. Kennington III
60b22ebbf3SWilliam A. Kennington III sdbusplus::message::object_path obj_path;
61b22ebbf3SWilliam A. Kennington III bus.call(method).read(obj_path);
62b22ebbf3SWilliam A. Kennington III job = std::move(obj_path);
63b22ebbf3SWilliam A. Kennington III std::fprintf(stderr, "Triggered %s mode %s: %s\n",
64b22ebbf3SWilliam A. Kennington III triggerService.c_str(), mode.c_str(), job->c_str());
65b22ebbf3SWilliam A. Kennington III currentStatus = ActionStatus::running;
66b22ebbf3SWilliam A. Kennington III return true;
67b22ebbf3SWilliam A. Kennington III }
68b22ebbf3SWilliam A. Kennington III catch (const std::exception& e)
69b22ebbf3SWilliam A. Kennington III {
70b22ebbf3SWilliam A. Kennington III job = std::nullopt;
71b22ebbf3SWilliam A. Kennington III jobMonitor = std::nullopt;
72b22ebbf3SWilliam A. Kennington III currentStatus = ActionStatus::failed;
73b22ebbf3SWilliam A. Kennington III std::fprintf(stderr, "Failed to trigger %s mode %s: %s\n",
74b22ebbf3SWilliam A. Kennington III triggerService.c_str(), mode.c_str(), e.what());
75b22ebbf3SWilliam A. Kennington III return false;
76b22ebbf3SWilliam A. Kennington III }
77b22ebbf3SWilliam A. Kennington III }
78b22ebbf3SWilliam A. Kennington III
abort()79b22ebbf3SWilliam A. Kennington III void SystemdNoFile::abort()
80b22ebbf3SWilliam A. Kennington III {
81b22ebbf3SWilliam A. Kennington III if (!job)
82b22ebbf3SWilliam A. Kennington III {
83b22ebbf3SWilliam A. Kennington III return;
84b22ebbf3SWilliam A. Kennington III }
85b22ebbf3SWilliam A. Kennington III
86b22ebbf3SWilliam A. Kennington III // Cancel the job
87b22ebbf3SWilliam A. Kennington III auto cancel_req = bus.new_method_call(systemdService, job->c_str(),
8801593f96SWilliam A. Kennington III jobInterface, "Cancel");
89b22ebbf3SWilliam A. Kennington III try
90b22ebbf3SWilliam A. Kennington III {
91b22ebbf3SWilliam A. Kennington III bus.call_noreply(cancel_req);
92b22ebbf3SWilliam A. Kennington III std::fprintf(stderr, "Canceled %s: %s\n", triggerService.c_str(),
93b22ebbf3SWilliam A. Kennington III job->c_str());
94b22ebbf3SWilliam A. Kennington III }
9540fbb0c6SPatrick Williams catch (const sdbusplus::exception_t& ex)
96b22ebbf3SWilliam A. Kennington III {
97b22ebbf3SWilliam A. Kennington III std::fprintf(stderr, "Failed to cancel job %s %s: %s\n",
98b22ebbf3SWilliam A. Kennington III triggerService.c_str(), job->c_str(), ex.what());
99b22ebbf3SWilliam A. Kennington III }
100b22ebbf3SWilliam A. Kennington III }
101b22ebbf3SWilliam A. Kennington III
status()102b22ebbf3SWilliam A. Kennington III ActionStatus SystemdNoFile::status()
103b22ebbf3SWilliam A. Kennington III {
104b22ebbf3SWilliam A. Kennington III return currentStatus;
105b22ebbf3SWilliam A. Kennington III }
106b22ebbf3SWilliam A. Kennington III
getMode() const107b22ebbf3SWilliam A. Kennington III const std::string& SystemdNoFile::getMode() const
108b22ebbf3SWilliam A. Kennington III {
109b22ebbf3SWilliam A. Kennington III return mode;
110b22ebbf3SWilliam A. Kennington III }
111b22ebbf3SWilliam A. Kennington III
match(sdbusplus::message_t & m)11240fbb0c6SPatrick Williams void SystemdNoFile::match(sdbusplus::message_t& m)
113b22ebbf3SWilliam A. Kennington III {
114b22ebbf3SWilliam A. Kennington III if (!job)
115b22ebbf3SWilliam A. Kennington III {
116b22ebbf3SWilliam A. Kennington III std::fprintf(stderr, "No running job %s\n", triggerService.c_str());
117b22ebbf3SWilliam A. Kennington III return;
118b22ebbf3SWilliam A. Kennington III }
119b22ebbf3SWilliam A. Kennington III
120b22ebbf3SWilliam A. Kennington III uint32_t job_id;
121b22ebbf3SWilliam A. Kennington III sdbusplus::message::object_path job_path;
122b22ebbf3SWilliam A. Kennington III std::string unit;
123b22ebbf3SWilliam A. Kennington III std::string result;
124b22ebbf3SWilliam A. Kennington III try
125b22ebbf3SWilliam A. Kennington III {
126b22ebbf3SWilliam A. Kennington III m.read(job_id, job_path, unit, result);
127b22ebbf3SWilliam A. Kennington III }
12840fbb0c6SPatrick Williams catch (const sdbusplus::exception_t& e)
129b22ebbf3SWilliam A. Kennington III {
130b22ebbf3SWilliam A. Kennington III std::fprintf(stderr, "Bad JobRemoved signal %s: %s\n",
131b22ebbf3SWilliam A. Kennington III triggerService.c_str(), e.what());
132b22ebbf3SWilliam A. Kennington III return;
133b22ebbf3SWilliam A. Kennington III }
134b22ebbf3SWilliam A. Kennington III
135b22ebbf3SWilliam A. Kennington III if (*job != job_path.str)
136b22ebbf3SWilliam A. Kennington III {
137b22ebbf3SWilliam A. Kennington III return;
138b22ebbf3SWilliam A. Kennington III }
139b22ebbf3SWilliam A. Kennington III
140b22ebbf3SWilliam A. Kennington III std::fprintf(stderr, "Job Finished %s %s: %s\n", triggerService.c_str(),
141b22ebbf3SWilliam A. Kennington III job->c_str(), result.c_str());
142b22ebbf3SWilliam A. Kennington III jobMonitor = std::nullopt;
143b22ebbf3SWilliam A. Kennington III job = std::nullopt;
144*42a44c28SPatrick Williams currentStatus =
145*42a44c28SPatrick Williams result == "done" ? ActionStatus::success : ActionStatus::failed;
1464175b4caSWilliam A. Kennington III
1474175b4caSWilliam A. Kennington III if (cb)
1484175b4caSWilliam A. Kennington III {
1494175b4caSWilliam A. Kennington III cb(*this);
1504175b4caSWilliam A. Kennington III }
151b22ebbf3SWilliam A. Kennington III }
152b22ebbf3SWilliam A. Kennington III
CreateSystemdNoFile(sdbusplus::bus_t && bus,const std::string & service,const std::string & mode)15340fbb0c6SPatrick Williams std::unique_ptr<TriggerableActionInterface> SystemdNoFile::CreateSystemdNoFile(
15440fbb0c6SPatrick Williams sdbusplus::bus_t&& bus, const std::string& service, const std::string& mode)
155b22ebbf3SWilliam A. Kennington III {
156b22ebbf3SWilliam A. Kennington III return std::make_unique<SystemdNoFile>(std::move(bus), service, mode);
157b22ebbf3SWilliam A. Kennington III }
158b22ebbf3SWilliam A. Kennington III
159cf066aceSPatrick Venture std::unique_ptr<TriggerableActionInterface>
CreateSystemdWithStatusFile(sdbusplus::bus_t && bus,const std::string & path,const std::string & service,const std::string & mode)160cf066aceSPatrick Venture SystemdWithStatusFile::CreateSystemdWithStatusFile(
16140fbb0c6SPatrick Williams sdbusplus::bus_t&& bus, const std::string& path,
162cf066aceSPatrick Venture const std::string& service, const std::string& mode)
163cf066aceSPatrick Venture {
164cf066aceSPatrick Venture return std::make_unique<SystemdWithStatusFile>(std::move(bus), path,
165cf066aceSPatrick Venture service, mode);
166cf066aceSPatrick Venture }
167cf066aceSPatrick Venture
trigger()16893f3c550SWilliam A. Kennington III bool SystemdWithStatusFile::trigger()
16993f3c550SWilliam A. Kennington III {
17093f3c550SWilliam A. Kennington III if (SystemdNoFile::status() != ActionStatus::running)
17193f3c550SWilliam A. Kennington III {
17293f3c550SWilliam A. Kennington III try
17393f3c550SWilliam A. Kennington III {
17493f3c550SWilliam A. Kennington III std::ofstream ofs;
17593f3c550SWilliam A. Kennington III ofs.open(checkPath);
17693f3c550SWilliam A. Kennington III ofs << "unknown";
17793f3c550SWilliam A. Kennington III }
17893f3c550SWilliam A. Kennington III catch (const std::exception& e)
17993f3c550SWilliam A. Kennington III {
18093f3c550SWilliam A. Kennington III return false;
18193f3c550SWilliam A. Kennington III }
18293f3c550SWilliam A. Kennington III }
18393f3c550SWilliam A. Kennington III return SystemdNoFile::trigger();
18493f3c550SWilliam A. Kennington III }
18593f3c550SWilliam A. Kennington III
status()186cf066aceSPatrick Venture ActionStatus SystemdWithStatusFile::status()
187cf066aceSPatrick Venture {
188b22ebbf3SWilliam A. Kennington III // Assume a status based on job execution if there is no file
189b22ebbf3SWilliam A. Kennington III ActionStatus result = SystemdNoFile::status() == ActionStatus::running
190b22ebbf3SWilliam A. Kennington III ? ActionStatus::running
191b22ebbf3SWilliam A. Kennington III : ActionStatus::failed;
192cf066aceSPatrick Venture
193cf066aceSPatrick Venture std::ifstream ifs;
194cf066aceSPatrick Venture ifs.open(checkPath);
195cf066aceSPatrick Venture if (ifs.good())
196cf066aceSPatrick Venture {
197cf066aceSPatrick Venture /*
198cf066aceSPatrick Venture * Check for the contents of the file, accepting:
199cf066aceSPatrick Venture * running, success, or failed.
200cf066aceSPatrick Venture */
201cf066aceSPatrick Venture std::string status;
202cf066aceSPatrick Venture ifs >> status;
203cf066aceSPatrick Venture if (status == "running")
204cf066aceSPatrick Venture {
205cf066aceSPatrick Venture result = ActionStatus::running;
206cf066aceSPatrick Venture }
207cf066aceSPatrick Venture else if (status == "success")
208cf066aceSPatrick Venture {
209cf066aceSPatrick Venture result = ActionStatus::success;
210cf066aceSPatrick Venture }
211cf066aceSPatrick Venture else if (status == "failed")
212cf066aceSPatrick Venture {
213cf066aceSPatrick Venture result = ActionStatus::failed;
214cf066aceSPatrick Venture }
21593f3c550SWilliam A. Kennington III else
21693f3c550SWilliam A. Kennington III {
21793f3c550SWilliam A. Kennington III result = ActionStatus::unknown;
21893f3c550SWilliam A. Kennington III }
219cf066aceSPatrick Venture }
220cf066aceSPatrick Venture
221cf066aceSPatrick Venture return result;
222cf066aceSPatrick Venture }
223cf066aceSPatrick Venture
224cf066aceSPatrick Venture } // namespace ipmi_flash
225