blob: d172f27d75d99272578e7bed71eb44e784db6ce2 [file] [log] [blame]
Matthew Barth29e9e382020-01-23 13:40:49 -06001/**
2 * Copyright © 2020 IBM 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
17#include "manager.hpp"
18
Shawn McCarneye0c6a2d2020-05-01 11:37:08 -050019#include "chassis.hpp"
20#include "config_file_parser.hpp"
21#include "exception_utils.hpp"
22#include "journal.hpp"
23#include "rule.hpp"
Matthew Barthbbc7c582020-02-03 15:55:15 -060024#include "utility.hpp"
25
Matthew Barth29e9e382020-01-23 13:40:49 -060026#include <sdbusplus/bus.hpp>
27
Matthew Barthf2bcf1f2020-01-29 14:42:47 -060028#include <chrono>
Shawn McCarneye0c6a2d2020-05-01 11:37:08 -050029#include <exception>
30#include <stdexcept>
31#include <tuple>
32#include <utility>
Matthew Barth250d0a92020-02-28 13:04:24 -060033#include <variant>
Matthew Barthf2bcf1f2020-01-29 14:42:47 -060034
Shawn McCarney84807b92020-04-30 18:40:03 -050035namespace phosphor::power::regulators
Matthew Barth29e9e382020-01-23 13:40:49 -060036{
37
Shawn McCarneye0c6a2d2020-05-01 11:37:08 -050038namespace fs = std::filesystem;
39
40/**
41 * Standard configuration file directory. This directory is part of the
42 * firmware install image. It contains the standard version of the config file.
43 */
44const fs::path standardConfigFileDir{"/usr/share/phosphor-regulators"};
45
46/**
47 * Test configuration file directory. This directory can contain a test version
48 * of the config file. The test version will override the standard version.
49 */
50const fs::path testConfigFileDir{"/etc/phosphor-regulators"};
51
Matthew Barthf2bcf1f2020-01-29 14:42:47 -060052Manager::Manager(sdbusplus::bus::bus& bus, const sdeventplus::Event& event) :
Shawn McCarneye0c6a2d2020-05-01 11:37:08 -050053 ManagerObject{bus, objPath, true}, bus{bus}, eventLoop{event}
Matthew Barth29e9e382020-01-23 13:40:49 -060054{
Shawn McCarney84807b92020-04-30 18:40:03 -050055 /* Temporarily comment out until D-Bus interface is defined and available.
56 // Subscribe to interfacesAdded signal for filename property
57 std::unique_ptr<sdbusplus::server::match::match> matchPtr =
58 std::make_unique<sdbusplus::server::match::match>(
59 bus,
60 sdbusplus::bus::match::rules::interfacesAdded(sysDbusObj).c_str(),
61 std::bind(std::mem_fn(&Manager::signalHandler), this,
62 std::placeholders::_1));
63 signals.emplace_back(std::move(matchPtr));
Matthew Barth250d0a92020-02-28 13:04:24 -060064
Shawn McCarney84807b92020-04-30 18:40:03 -050065 // Attempt to get the filename property from dbus
66 setFileName(getFileNameDbus());
67 */
68
69 // Temporarily hard-code JSON config file name to first system that will use
70 // this application. Remove this when D-Bus interface is available.
71 fileName = "ibm_rainier.json";
Matthew Barthbbc7c582020-02-03 15:55:15 -060072
Matthew Barthbbc7c582020-02-03 15:55:15 -060073 if (!fileName.empty())
74 {
Shawn McCarneye0c6a2d2020-05-01 11:37:08 -050075 loadConfigFile();
Matthew Barthbbc7c582020-02-03 15:55:15 -060076 }
Matthew Barth29e9e382020-01-23 13:40:49 -060077
78 // Obtain dbus service name
79 bus.request_name(busName);
80}
81
82void Manager::configure()
83{
84 // TODO Configuration errors that should halt poweron,
85 // throw InternalFailure exception (or similar) to
86 // fail the call(busctl) to this method
87}
88
89void Manager::monitor(bool enable)
90{
91 if (enable)
92 {
Matthew Barthf2bcf1f2020-01-29 14:42:47 -060093 Timer timer(eventLoop, std::bind(&Manager::timerExpired, this));
94 // Set timer as a repeating 1sec timer
95 timer.restart(std::chrono::milliseconds(1000));
96 timers.emplace_back(std::move(timer));
Matthew Barth29e9e382020-01-23 13:40:49 -060097 }
98 else
99 {
Matthew Barthf2bcf1f2020-01-29 14:42:47 -0600100 // Delete all timers to disable monitoring
101 timers.clear();
Matthew Barth29e9e382020-01-23 13:40:49 -0600102 }
103}
104
Matthew Barthf2bcf1f2020-01-29 14:42:47 -0600105void Manager::timerExpired()
106{
107 // TODO Analyze, refresh sensor status, and
108 // collect/update telemetry for each regulator
109}
110
Matthew Barth7cbc5532020-01-29 15:13:13 -0600111void Manager::sighupHandler(sdeventplus::source::Signal& /*sigSrc*/,
112 const struct signalfd_siginfo* /*sigInfo*/)
113{
Shawn McCarneye0c6a2d2020-05-01 11:37:08 -0500114 if (!fileName.empty())
115 {
116 loadConfigFile();
117 }
Matthew Barth7cbc5532020-01-29 15:13:13 -0600118}
119
Matthew Barth250d0a92020-02-28 13:04:24 -0600120void Manager::signalHandler(sdbusplus::message::message& msg)
121{
122 if (msg)
123 {
124 sdbusplus::message::object_path op;
125 msg.read(op);
126 if (static_cast<const std::string&>(op) != sysDbusPath)
127 {
128 // Object path does not match the path
129 return;
130 }
131
132 // An interfacesAdded signal returns a dictionary of interface
133 // names to a dictionary of properties and their values
134 // https://dbus.freedesktop.org/doc/dbus-specification.html
135 std::map<std::string, std::map<std::string, std::variant<std::string>>>
136 intfProp;
137 msg.read(intfProp);
138 auto itIntf = intfProp.find(sysDbusIntf);
139 if (itIntf == intfProp.cend())
140 {
141 // Interface not found on the path
142 return;
143 }
144 auto itProp = itIntf->second.find(sysDbusProp);
145 if (itProp == itIntf->second.cend())
146 {
147 // Property not found on the interface
148 return;
149 }
150 // Set fileName and call parse json function
151 setFileName(std::get<std::string>(itProp->second));
Shawn McCarneye0c6a2d2020-05-01 11:37:08 -0500152 if (!fileName.empty())
153 {
154 loadConfigFile();
155 }
Matthew Barth250d0a92020-02-28 13:04:24 -0600156 }
157}
158
Matthew Barthbbc7c582020-02-03 15:55:15 -0600159const std::string Manager::getFileNameDbus()
160{
161 std::string fileName = "";
162 using namespace phosphor::power::util;
163
164 try
165 {
166 // Do not log an error when service or property are not found
167 auto service = getService(sysDbusPath, sysDbusIntf, bus, false);
168 if (!service.empty())
169 {
170 getProperty(sysDbusIntf, sysDbusProp, sysDbusPath, service, bus,
171 fileName);
172 }
173 }
174 catch (const sdbusplus::exception::SdBusError&)
175 {
176 // File name property not available on dbus
177 fileName = "";
178 }
179
180 return fileName;
181}
182
Shawn McCarneye0c6a2d2020-05-01 11:37:08 -0500183fs::path Manager::findConfigFile()
184{
185 // First look in the test directory
186 fs::path pathName{testConfigFileDir / fileName};
187 if (!fs::exists(pathName))
188 {
189 // Look in the standard directory
190 pathName = standardConfigFileDir / fileName;
191 if (!fs::exists(pathName))
192 {
193 throw std::runtime_error{"Configuration file does not exist: " +
194 pathName.string()};
195 }
196 }
197
198 return pathName;
199}
200
201void Manager::loadConfigFile()
202{
203 try
204 {
205 // Find the absolute path to the config file
206 fs::path pathName = findConfigFile();
207
208 // Log info message in journal; config file path is important
209 journal::logInfo("Loading configuration file " + pathName.string());
210
211 // Parse the config file
212 std::vector<std::unique_ptr<Rule>> rules{};
213 std::vector<std::unique_ptr<Chassis>> chassis{};
214 std::tie(rules, chassis) = config_file_parser::parse(pathName);
215
216 // Store config file information in a new System object. The old System
217 // object, if any, is automatically deleted.
218 system = std::make_unique<System>(std::move(rules), std::move(chassis));
219 }
220 catch (const std::exception& e)
221 {
222 // Log error messages in journal
223 exception_utils::log(e);
224 journal::logErr("Unable to load configuration file");
225
226 // TODO: Create error log entry
227 }
228}
229
Shawn McCarney84807b92020-04-30 18:40:03 -0500230} // namespace phosphor::power::regulators