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