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 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 { 47b22ebbf3SWilliam A. Kennington III jobMonitor.emplace( 48b22ebbf3SWilliam A. Kennington III bus, 49b22ebbf3SWilliam A. Kennington III "type='signal'," 50b22ebbf3SWilliam A. Kennington III "sender='org.freedesktop.systemd1'," 51b22ebbf3SWilliam A. Kennington III "path='/org/freedesktop/systemd1'," 52b22ebbf3SWilliam A. Kennington III "interface='org.freedesktop.systemd1.Manager'," 53b22ebbf3SWilliam A. Kennington III "member='JobRemoved',", 54b22ebbf3SWilliam A. Kennington III [&](sdbusplus::message::message& m) { this->match(m); }); 55b22ebbf3SWilliam A. Kennington III 56b22ebbf3SWilliam A. Kennington III auto method = bus.new_method_call(systemdService, systemdRoot, 57b22ebbf3SWilliam A. Kennington III systemdInterface, "StartUnit"); 58b22ebbf3SWilliam A. Kennington III method.append(triggerService); 59b22ebbf3SWilliam A. Kennington III method.append(mode); 60b22ebbf3SWilliam A. Kennington III 61b22ebbf3SWilliam A. Kennington III sdbusplus::message::object_path obj_path; 62b22ebbf3SWilliam A. Kennington III bus.call(method).read(obj_path); 63b22ebbf3SWilliam A. Kennington III job = std::move(obj_path); 64b22ebbf3SWilliam A. Kennington III std::fprintf(stderr, "Triggered %s mode %s: %s\n", 65b22ebbf3SWilliam A. Kennington III triggerService.c_str(), mode.c_str(), job->c_str()); 66b22ebbf3SWilliam A. Kennington III currentStatus = ActionStatus::running; 67b22ebbf3SWilliam A. Kennington III return true; 68b22ebbf3SWilliam A. Kennington III } 69b22ebbf3SWilliam A. Kennington III catch (const std::exception& e) 70b22ebbf3SWilliam A. Kennington III { 71b22ebbf3SWilliam A. Kennington III job = std::nullopt; 72b22ebbf3SWilliam A. Kennington III jobMonitor = std::nullopt; 73b22ebbf3SWilliam A. Kennington III currentStatus = ActionStatus::failed; 74b22ebbf3SWilliam A. Kennington III std::fprintf(stderr, "Failed to trigger %s mode %s: %s\n", 75b22ebbf3SWilliam A. Kennington III triggerService.c_str(), mode.c_str(), e.what()); 76b22ebbf3SWilliam A. Kennington III return false; 77b22ebbf3SWilliam A. Kennington III } 78b22ebbf3SWilliam A. Kennington III } 79b22ebbf3SWilliam A. Kennington III 80b22ebbf3SWilliam A. Kennington III void SystemdNoFile::abort() 81b22ebbf3SWilliam A. Kennington III { 82b22ebbf3SWilliam A. Kennington III if (!job) 83b22ebbf3SWilliam A. Kennington III { 84b22ebbf3SWilliam A. Kennington III return; 85b22ebbf3SWilliam A. Kennington III } 86b22ebbf3SWilliam A. Kennington III 87b22ebbf3SWilliam A. Kennington III // Cancel the job 88b22ebbf3SWilliam A. Kennington III auto cancel_req = bus.new_method_call(systemdService, job->c_str(), 8901593f96SWilliam A. Kennington III jobInterface, "Cancel"); 90b22ebbf3SWilliam A. Kennington III try 91b22ebbf3SWilliam A. Kennington III { 92b22ebbf3SWilliam A. Kennington III bus.call_noreply(cancel_req); 93b22ebbf3SWilliam A. Kennington III std::fprintf(stderr, "Canceled %s: %s\n", triggerService.c_str(), 94b22ebbf3SWilliam A. Kennington III job->c_str()); 95b22ebbf3SWilliam A. Kennington III } 96b22ebbf3SWilliam A. Kennington III catch (const sdbusplus::exception::SdBusError& ex) 97b22ebbf3SWilliam A. Kennington III { 98b22ebbf3SWilliam A. Kennington III std::fprintf(stderr, "Failed to cancel job %s %s: %s\n", 99b22ebbf3SWilliam A. Kennington III triggerService.c_str(), job->c_str(), ex.what()); 100b22ebbf3SWilliam A. Kennington III } 101b22ebbf3SWilliam A. Kennington III } 102b22ebbf3SWilliam A. Kennington III 103b22ebbf3SWilliam A. Kennington III ActionStatus SystemdNoFile::status() 104b22ebbf3SWilliam A. Kennington III { 105b22ebbf3SWilliam A. Kennington III return currentStatus; 106b22ebbf3SWilliam A. Kennington III } 107b22ebbf3SWilliam A. Kennington III 108b22ebbf3SWilliam A. Kennington III const std::string& SystemdNoFile::getMode() const 109b22ebbf3SWilliam A. Kennington III { 110b22ebbf3SWilliam A. Kennington III return mode; 111b22ebbf3SWilliam A. Kennington III } 112b22ebbf3SWilliam A. Kennington III 113b22ebbf3SWilliam A. Kennington III void SystemdNoFile::match(sdbusplus::message::message& m) 114b22ebbf3SWilliam A. Kennington III { 115b22ebbf3SWilliam A. Kennington III if (!job) 116b22ebbf3SWilliam A. Kennington III { 117b22ebbf3SWilliam A. Kennington III std::fprintf(stderr, "No running job %s\n", triggerService.c_str()); 118b22ebbf3SWilliam A. Kennington III return; 119b22ebbf3SWilliam A. Kennington III } 120b22ebbf3SWilliam A. Kennington III 121b22ebbf3SWilliam A. Kennington III uint32_t job_id; 122b22ebbf3SWilliam A. Kennington III sdbusplus::message::object_path job_path; 123b22ebbf3SWilliam A. Kennington III std::string unit; 124b22ebbf3SWilliam A. Kennington III std::string result; 125b22ebbf3SWilliam A. Kennington III try 126b22ebbf3SWilliam A. Kennington III { 127b22ebbf3SWilliam A. Kennington III m.read(job_id, job_path, unit, result); 128b22ebbf3SWilliam A. Kennington III } 129b22ebbf3SWilliam A. Kennington III catch (const sdbusplus::exception::SdBusError& e) 130b22ebbf3SWilliam A. Kennington III { 131b22ebbf3SWilliam A. Kennington III std::fprintf(stderr, "Bad JobRemoved signal %s: %s\n", 132b22ebbf3SWilliam A. Kennington III triggerService.c_str(), e.what()); 133b22ebbf3SWilliam A. Kennington III return; 134b22ebbf3SWilliam A. Kennington III } 135b22ebbf3SWilliam A. Kennington III 136b22ebbf3SWilliam A. Kennington III if (*job != job_path.str) 137b22ebbf3SWilliam A. Kennington III { 138b22ebbf3SWilliam A. Kennington III return; 139b22ebbf3SWilliam A. Kennington III } 140b22ebbf3SWilliam A. Kennington III 141b22ebbf3SWilliam A. Kennington III std::fprintf(stderr, "Job Finished %s %s: %s\n", triggerService.c_str(), 142b22ebbf3SWilliam A. Kennington III job->c_str(), result.c_str()); 143b22ebbf3SWilliam A. Kennington III jobMonitor = std::nullopt; 144b22ebbf3SWilliam A. Kennington III job = std::nullopt; 145b22ebbf3SWilliam A. Kennington III currentStatus = 146b22ebbf3SWilliam A. Kennington III result == "done" ? ActionStatus::success : ActionStatus::failed; 147*4175b4caSWilliam A. Kennington III 148*4175b4caSWilliam A. Kennington III if (cb) 149*4175b4caSWilliam A. Kennington III { 150*4175b4caSWilliam A. Kennington III cb(*this); 151*4175b4caSWilliam A. Kennington III } 152b22ebbf3SWilliam A. Kennington III } 153b22ebbf3SWilliam A. Kennington III 154b22ebbf3SWilliam A. Kennington III std::unique_ptr<TriggerableActionInterface> 155b22ebbf3SWilliam A. Kennington III SystemdNoFile::CreateSystemdNoFile(sdbusplus::bus::bus&& bus, 156b22ebbf3SWilliam A. Kennington III const std::string& service, 157b22ebbf3SWilliam A. Kennington III const std::string& mode) 158b22ebbf3SWilliam A. Kennington III { 159b22ebbf3SWilliam A. Kennington III return std::make_unique<SystemdNoFile>(std::move(bus), service, mode); 160b22ebbf3SWilliam A. Kennington III } 161b22ebbf3SWilliam A. Kennington III 162cf066aceSPatrick Venture std::unique_ptr<TriggerableActionInterface> 163cf066aceSPatrick Venture SystemdWithStatusFile::CreateSystemdWithStatusFile( 164cf066aceSPatrick Venture sdbusplus::bus::bus&& bus, const std::string& path, 165cf066aceSPatrick Venture const std::string& service, const std::string& mode) 166cf066aceSPatrick Venture { 167cf066aceSPatrick Venture return std::make_unique<SystemdWithStatusFile>(std::move(bus), path, 168cf066aceSPatrick Venture service, mode); 169cf066aceSPatrick Venture } 170cf066aceSPatrick Venture 17193f3c550SWilliam A. Kennington III bool SystemdWithStatusFile::trigger() 17293f3c550SWilliam A. Kennington III { 17393f3c550SWilliam A. Kennington III if (SystemdNoFile::status() != ActionStatus::running) 17493f3c550SWilliam A. Kennington III { 17593f3c550SWilliam A. Kennington III try 17693f3c550SWilliam A. Kennington III { 17793f3c550SWilliam A. Kennington III std::ofstream ofs; 17893f3c550SWilliam A. Kennington III ofs.open(checkPath); 17993f3c550SWilliam A. Kennington III ofs << "unknown"; 18093f3c550SWilliam A. Kennington III } 18193f3c550SWilliam A. Kennington III catch (const std::exception& e) 18293f3c550SWilliam A. Kennington III { 18393f3c550SWilliam A. Kennington III return false; 18493f3c550SWilliam A. Kennington III } 18593f3c550SWilliam A. Kennington III } 18693f3c550SWilliam A. Kennington III return SystemdNoFile::trigger(); 18793f3c550SWilliam A. Kennington III } 18893f3c550SWilliam A. Kennington III 189cf066aceSPatrick Venture ActionStatus SystemdWithStatusFile::status() 190cf066aceSPatrick Venture { 191b22ebbf3SWilliam A. Kennington III // Assume a status based on job execution if there is no file 192b22ebbf3SWilliam A. Kennington III ActionStatus result = SystemdNoFile::status() == ActionStatus::running 193b22ebbf3SWilliam A. Kennington III ? ActionStatus::running 194b22ebbf3SWilliam A. Kennington III : ActionStatus::failed; 195cf066aceSPatrick Venture 196cf066aceSPatrick Venture std::ifstream ifs; 197cf066aceSPatrick Venture ifs.open(checkPath); 198cf066aceSPatrick Venture if (ifs.good()) 199cf066aceSPatrick Venture { 200cf066aceSPatrick Venture /* 201cf066aceSPatrick Venture * Check for the contents of the file, accepting: 202cf066aceSPatrick Venture * running, success, or failed. 203cf066aceSPatrick Venture */ 204cf066aceSPatrick Venture std::string status; 205cf066aceSPatrick Venture ifs >> status; 206cf066aceSPatrick Venture if (status == "running") 207cf066aceSPatrick Venture { 208cf066aceSPatrick Venture result = ActionStatus::running; 209cf066aceSPatrick Venture } 210cf066aceSPatrick Venture else if (status == "success") 211cf066aceSPatrick Venture { 212cf066aceSPatrick Venture result = ActionStatus::success; 213cf066aceSPatrick Venture } 214cf066aceSPatrick Venture else if (status == "failed") 215cf066aceSPatrick Venture { 216cf066aceSPatrick Venture result = ActionStatus::failed; 217cf066aceSPatrick Venture } 21893f3c550SWilliam A. Kennington III else 21993f3c550SWilliam A. Kennington III { 22093f3c550SWilliam A. Kennington III result = ActionStatus::unknown; 22193f3c550SWilliam A. Kennington III } 222cf066aceSPatrick Venture } 223cf066aceSPatrick Venture 224cf066aceSPatrick Venture return result; 225cf066aceSPatrick Venture } 226cf066aceSPatrick Venture 227cf066aceSPatrick Venture } // namespace ipmi_flash 228