xref: /openbmc/phosphor-ipmi-flash/bmc/general_systemd.cpp (revision b22ebbf39482eda6186406971c4e8d5e601d0fa2)
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 
21cf066aceSPatrick Venture #include <fstream>
22cf066aceSPatrick Venture #include <memory>
23cf066aceSPatrick Venture #include <sdbusplus/bus.hpp>
24cf066aceSPatrick Venture #include <string>
25cf066aceSPatrick Venture #include <vector>
26cf066aceSPatrick Venture 
27cf066aceSPatrick Venture namespace ipmi_flash
28cf066aceSPatrick Venture {
29cf066aceSPatrick Venture 
30*b22ebbf3SWilliam A. Kennington III static constexpr auto systemdService = "org.freedesktop.systemd1";
31*b22ebbf3SWilliam A. Kennington III static constexpr auto systemdRoot = "/org/freedesktop/systemd1";
32*b22ebbf3SWilliam A. Kennington III static constexpr auto systemdInterface = "org.freedesktop.systemd1.Manager";
33*b22ebbf3SWilliam A. Kennington III 
34*b22ebbf3SWilliam A. Kennington III bool SystemdNoFile::trigger()
35*b22ebbf3SWilliam A. Kennington III {
36*b22ebbf3SWilliam A. Kennington III     if (job)
37*b22ebbf3SWilliam A. Kennington III     {
38*b22ebbf3SWilliam A. Kennington III         std::fprintf(stderr, "Job alreading running %s: %s\n",
39*b22ebbf3SWilliam A. Kennington III                      triggerService.c_str(), job->c_str());
40*b22ebbf3SWilliam A. Kennington III         return false;
41*b22ebbf3SWilliam A. Kennington III     }
42*b22ebbf3SWilliam A. Kennington III 
43*b22ebbf3SWilliam A. Kennington III     try
44*b22ebbf3SWilliam A. Kennington III     {
45*b22ebbf3SWilliam A. Kennington III         jobMonitor.emplace(
46*b22ebbf3SWilliam A. Kennington III             bus,
47*b22ebbf3SWilliam A. Kennington III             "type='signal',"
48*b22ebbf3SWilliam A. Kennington III             "sender='org.freedesktop.systemd1',"
49*b22ebbf3SWilliam A. Kennington III             "path='/org/freedesktop/systemd1',"
50*b22ebbf3SWilliam A. Kennington III             "interface='org.freedesktop.systemd1.Manager',"
51*b22ebbf3SWilliam A. Kennington III             "member='JobRemoved',",
52*b22ebbf3SWilliam A. Kennington III             [&](sdbusplus::message::message& m) { this->match(m); });
53*b22ebbf3SWilliam A. Kennington III 
54*b22ebbf3SWilliam A. Kennington III         auto method = bus.new_method_call(systemdService, systemdRoot,
55*b22ebbf3SWilliam A. Kennington III                                           systemdInterface, "StartUnit");
56*b22ebbf3SWilliam A. Kennington III         method.append(triggerService);
57*b22ebbf3SWilliam A. Kennington III         method.append(mode);
58*b22ebbf3SWilliam A. Kennington III 
59*b22ebbf3SWilliam A. Kennington III         sdbusplus::message::object_path obj_path;
60*b22ebbf3SWilliam A. Kennington III         bus.call(method).read(obj_path);
61*b22ebbf3SWilliam A. Kennington III         job = std::move(obj_path);
62*b22ebbf3SWilliam A. Kennington III         std::fprintf(stderr, "Triggered %s mode %s: %s\n",
63*b22ebbf3SWilliam A. Kennington III                      triggerService.c_str(), mode.c_str(), job->c_str());
64*b22ebbf3SWilliam A. Kennington III         currentStatus = ActionStatus::running;
65*b22ebbf3SWilliam A. Kennington III         return true;
66*b22ebbf3SWilliam A. Kennington III     }
67*b22ebbf3SWilliam A. Kennington III     catch (const std::exception& e)
68*b22ebbf3SWilliam A. Kennington III     {
69*b22ebbf3SWilliam A. Kennington III         job = std::nullopt;
70*b22ebbf3SWilliam A. Kennington III         jobMonitor = std::nullopt;
71*b22ebbf3SWilliam A. Kennington III         currentStatus = ActionStatus::failed;
72*b22ebbf3SWilliam A. Kennington III         std::fprintf(stderr, "Failed to trigger %s mode %s: %s\n",
73*b22ebbf3SWilliam A. Kennington III                      triggerService.c_str(), mode.c_str(), e.what());
74*b22ebbf3SWilliam A. Kennington III         return false;
75*b22ebbf3SWilliam A. Kennington III     }
76*b22ebbf3SWilliam A. Kennington III }
77*b22ebbf3SWilliam A. Kennington III 
78*b22ebbf3SWilliam A. Kennington III void SystemdNoFile::abort()
79*b22ebbf3SWilliam A. Kennington III {
80*b22ebbf3SWilliam A. Kennington III     if (!job)
81*b22ebbf3SWilliam A. Kennington III     {
82*b22ebbf3SWilliam A. Kennington III         std::fprintf(stderr, "No running job %s\n", triggerService.c_str());
83*b22ebbf3SWilliam A. Kennington III         return;
84*b22ebbf3SWilliam A. Kennington III     }
85*b22ebbf3SWilliam A. Kennington III 
86*b22ebbf3SWilliam A. Kennington III     // Cancel the job
87*b22ebbf3SWilliam A. Kennington III     auto cancel_req = bus.new_method_call(systemdService, job->c_str(),
88*b22ebbf3SWilliam A. Kennington III                                           systemdInterface, "Cancel");
89*b22ebbf3SWilliam A. Kennington III     try
90*b22ebbf3SWilliam A. Kennington III     {
91*b22ebbf3SWilliam A. Kennington III         bus.call_noreply(cancel_req);
92*b22ebbf3SWilliam A. Kennington III         std::fprintf(stderr, "Canceled %s: %s\n", triggerService.c_str(),
93*b22ebbf3SWilliam A. Kennington III                      job->c_str());
94*b22ebbf3SWilliam A. Kennington III     }
95*b22ebbf3SWilliam A. Kennington III     catch (const sdbusplus::exception::SdBusError& ex)
96*b22ebbf3SWilliam A. Kennington III     {
97*b22ebbf3SWilliam A. Kennington III         std::fprintf(stderr, "Failed to cancel job %s %s: %s\n",
98*b22ebbf3SWilliam A. Kennington III                      triggerService.c_str(), job->c_str(), ex.what());
99*b22ebbf3SWilliam A. Kennington III     }
100*b22ebbf3SWilliam A. Kennington III }
101*b22ebbf3SWilliam A. Kennington III 
102*b22ebbf3SWilliam A. Kennington III ActionStatus SystemdNoFile::status()
103*b22ebbf3SWilliam A. Kennington III {
104*b22ebbf3SWilliam A. Kennington III     return currentStatus;
105*b22ebbf3SWilliam A. Kennington III }
106*b22ebbf3SWilliam A. Kennington III 
107*b22ebbf3SWilliam A. Kennington III const std::string& SystemdNoFile::getMode() const
108*b22ebbf3SWilliam A. Kennington III {
109*b22ebbf3SWilliam A. Kennington III     return mode;
110*b22ebbf3SWilliam A. Kennington III }
111*b22ebbf3SWilliam A. Kennington III 
112*b22ebbf3SWilliam A. Kennington III void SystemdNoFile::match(sdbusplus::message::message& m)
113*b22ebbf3SWilliam A. Kennington III {
114*b22ebbf3SWilliam A. Kennington III     if (!job)
115*b22ebbf3SWilliam A. Kennington III     {
116*b22ebbf3SWilliam A. Kennington III         std::fprintf(stderr, "No running job %s\n", triggerService.c_str());
117*b22ebbf3SWilliam A. Kennington III         return;
118*b22ebbf3SWilliam A. Kennington III     }
119*b22ebbf3SWilliam A. Kennington III 
120*b22ebbf3SWilliam A. Kennington III     uint32_t job_id;
121*b22ebbf3SWilliam A. Kennington III     sdbusplus::message::object_path job_path;
122*b22ebbf3SWilliam A. Kennington III     std::string unit;
123*b22ebbf3SWilliam A. Kennington III     std::string result;
124*b22ebbf3SWilliam A. Kennington III     try
125*b22ebbf3SWilliam A. Kennington III     {
126*b22ebbf3SWilliam A. Kennington III         m.read(job_id, job_path, unit, result);
127*b22ebbf3SWilliam A. Kennington III     }
128*b22ebbf3SWilliam A. Kennington III     catch (const sdbusplus::exception::SdBusError& e)
129*b22ebbf3SWilliam A. Kennington III     {
130*b22ebbf3SWilliam A. Kennington III         std::fprintf(stderr, "Bad JobRemoved signal %s: %s\n",
131*b22ebbf3SWilliam A. Kennington III                      triggerService.c_str(), e.what());
132*b22ebbf3SWilliam A. Kennington III         return;
133*b22ebbf3SWilliam A. Kennington III     }
134*b22ebbf3SWilliam A. Kennington III 
135*b22ebbf3SWilliam A. Kennington III     if (*job != job_path.str)
136*b22ebbf3SWilliam A. Kennington III     {
137*b22ebbf3SWilliam A. Kennington III         return;
138*b22ebbf3SWilliam A. Kennington III     }
139*b22ebbf3SWilliam A. Kennington III 
140*b22ebbf3SWilliam A. Kennington III     std::fprintf(stderr, "Job Finished %s %s: %s\n", triggerService.c_str(),
141*b22ebbf3SWilliam A. Kennington III                  job->c_str(), result.c_str());
142*b22ebbf3SWilliam A. Kennington III     jobMonitor = std::nullopt;
143*b22ebbf3SWilliam A. Kennington III     job = std::nullopt;
144*b22ebbf3SWilliam A. Kennington III     currentStatus =
145*b22ebbf3SWilliam A. Kennington III         result == "done" ? ActionStatus::success : ActionStatus::failed;
146*b22ebbf3SWilliam A. Kennington III }
147*b22ebbf3SWilliam A. Kennington III 
148*b22ebbf3SWilliam A. Kennington III std::unique_ptr<TriggerableActionInterface>
149*b22ebbf3SWilliam A. Kennington III     SystemdNoFile::CreateSystemdNoFile(sdbusplus::bus::bus&& bus,
150*b22ebbf3SWilliam A. Kennington III                                        const std::string& service,
151*b22ebbf3SWilliam A. Kennington III                                        const std::string& mode)
152*b22ebbf3SWilliam A. Kennington III {
153*b22ebbf3SWilliam A. Kennington III     return std::make_unique<SystemdNoFile>(std::move(bus), service, mode);
154*b22ebbf3SWilliam A. Kennington III }
155*b22ebbf3SWilliam A. Kennington III 
156cf066aceSPatrick Venture std::unique_ptr<TriggerableActionInterface>
157cf066aceSPatrick Venture     SystemdWithStatusFile::CreateSystemdWithStatusFile(
158cf066aceSPatrick Venture         sdbusplus::bus::bus&& bus, const std::string& path,
159cf066aceSPatrick Venture         const std::string& service, const std::string& mode)
160cf066aceSPatrick Venture {
161cf066aceSPatrick Venture     return std::make_unique<SystemdWithStatusFile>(std::move(bus), path,
162cf066aceSPatrick Venture                                                    service, mode);
163cf066aceSPatrick Venture }
164cf066aceSPatrick Venture 
165cf066aceSPatrick Venture ActionStatus SystemdWithStatusFile::status()
166cf066aceSPatrick Venture {
167*b22ebbf3SWilliam A. Kennington III     // Assume a status based on job execution if there is no file
168*b22ebbf3SWilliam A. Kennington III     ActionStatus result = SystemdNoFile::status() == ActionStatus::running
169*b22ebbf3SWilliam A. Kennington III                               ? ActionStatus::running
170*b22ebbf3SWilliam A. Kennington III                               : ActionStatus::failed;
171cf066aceSPatrick Venture 
172cf066aceSPatrick Venture     std::ifstream ifs;
173cf066aceSPatrick Venture     ifs.open(checkPath);
174cf066aceSPatrick Venture     if (ifs.good())
175cf066aceSPatrick Venture     {
176cf066aceSPatrick Venture         /*
177cf066aceSPatrick Venture          * Check for the contents of the file, accepting:
178cf066aceSPatrick Venture          * running, success, or failed.
179cf066aceSPatrick Venture          */
180cf066aceSPatrick Venture         std::string status;
181cf066aceSPatrick Venture         ifs >> status;
182cf066aceSPatrick Venture         if (status == "running")
183cf066aceSPatrick Venture         {
184cf066aceSPatrick Venture             result = ActionStatus::running;
185cf066aceSPatrick Venture         }
186cf066aceSPatrick Venture         else if (status == "success")
187cf066aceSPatrick Venture         {
188cf066aceSPatrick Venture             result = ActionStatus::success;
189cf066aceSPatrick Venture         }
190cf066aceSPatrick Venture         else if (status == "failed")
191cf066aceSPatrick Venture         {
192cf066aceSPatrick Venture             result = ActionStatus::failed;
193cf066aceSPatrick Venture         }
194cf066aceSPatrick Venture     }
195cf066aceSPatrick Venture 
196cf066aceSPatrick Venture     return result;
197cf066aceSPatrick Venture }
198cf066aceSPatrick Venture 
199cf066aceSPatrick Venture } // namespace ipmi_flash
200