blob: 10bb84dc5f6a49aa6d678645d71093f0460aa57c [file] [log] [blame]
Matthew Bartha227a162020-08-05 10:51:45 -05001/**
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 */
Matthew Barthb584d812021-03-11 15:55:04 -060016#include "config.h"
17
Matthew Bartha227a162020-08-05 10:51:45 -050018#include "manager.hpp"
19
Matt Spinler2fc0a352021-10-04 15:10:57 -050020#include "../utils/flight_recorder.hpp"
Matthew Barthd9cb63b2021-03-24 14:36:49 -050021#include "action.hpp"
Matthew Barth44ab7692021-03-26 11:40:10 -050022#include "event.hpp"
Matthew Barthde90fb42021-03-04 16:34:28 -060023#include "fan.hpp"
Matthew Barthd9cb63b2021-03-24 14:36:49 -050024#include "group.hpp"
Matthew Bartha227a162020-08-05 10:51:45 -050025#include "json_config.hpp"
Matthew Barth48f44da2021-05-27 15:43:34 -050026#include "power_state.hpp"
Matthew Barth06764942021-03-04 09:28:40 -060027#include "profile.hpp"
Matthew Barth9403a212021-05-17 09:31:50 -050028#include "sdbusplus.hpp"
Matthew Barthacd737c2021-03-04 11:04:01 -060029#include "zone.hpp"
Matthew Bartha227a162020-08-05 10:51:45 -050030
Matthew Barthacd737c2021-03-04 11:04:01 -060031#include <nlohmann/json.hpp>
Matthew Bartha227a162020-08-05 10:51:45 -050032#include <sdbusplus/bus.hpp>
Matthew Barth1542fb52021-06-10 14:09:09 -050033#include <sdbusplus/server/manager.hpp>
Matthew Barthacd737c2021-03-04 11:04:01 -060034#include <sdeventplus/event.hpp>
Matthew Barthd9cb63b2021-03-24 14:36:49 -050035#include <sdeventplus/utility/timer.hpp>
Matthew Bartha227a162020-08-05 10:51:45 -050036
Matthew Barthde90fb42021-03-04 16:34:28 -060037#include <algorithm>
Matthew Barthd9cb63b2021-03-24 14:36:49 -050038#include <chrono>
Matthew Bartha227a162020-08-05 10:51:45 -050039#include <filesystem>
Matthew Barthd9cb63b2021-03-24 14:36:49 -050040#include <functional>
41#include <map>
42#include <memory>
43#include <tuple>
44#include <utility>
Matthew Barth06764942021-03-04 09:28:40 -060045#include <vector>
Matthew Bartha227a162020-08-05 10:51:45 -050046
47namespace phosphor::fan::control::json
48{
49
Matthew Barthacd737c2021-03-04 11:04:01 -060050using json = nlohmann::json;
51
52std::vector<std::string> Manager::_activeProfiles;
Matthew Barth12cb1252021-03-08 16:47:30 -060053std::map<std::string,
Matthew Barth4ca87fa2021-04-14 11:31:13 -050054 std::map<std::string, std::pair<bool, std::vector<std::string>>>>
Matthew Barth12cb1252021-03-08 16:47:30 -060055 Manager::_servTree;
Matthew Barth07fecfc2021-01-29 09:04:43 -060056std::map<std::string,
57 std::map<std::string, std::map<std::string, PropertyVariantType>>>
58 Manager::_objects;
Matt Spinlerd76351b2021-08-05 16:23:09 -050059std::unordered_map<std::string, PropertyVariantType> Manager::_parameters;
Matthew Barthacd737c2021-03-04 11:04:01 -060060
Matt Spinler7787def2021-10-14 16:33:16 -050061const std::string Manager::dumpFile = "/tmp/fan_control_dump.json";
62
Matthew Barth9403a212021-05-17 09:31:50 -050063Manager::Manager(const sdeventplus::Event& event) :
Matthew Barth48f44da2021-05-27 15:43:34 -050064 _bus(util::SDBusPlus::getBus()), _event(event),
Matthew Barth3770a1d2021-06-10 15:09:37 -050065 _mgr(util::SDBusPlus::getBus(), CONTROL_OBJPATH), _loadAllowed(true),
Matthew Barth48f44da2021-05-27 15:43:34 -050066 _powerState(std::make_unique<PGoodState>(
67 util::SDBusPlus::getBus(),
68 std::bind(std::mem_fn(&Manager::powerStateChanged), this,
69 std::placeholders::_1)))
Matthew Barth3770a1d2021-06-10 15:09:37 -050070{}
Matthew Barthe91ac862021-05-25 16:22:17 -050071
72void Manager::sighupHandler(sdeventplus::source::Signal&,
73 const struct signalfd_siginfo*)
74{
75 // Save current set of available and active profiles
76 std::map<configKey, std::unique_ptr<Profile>> profiles;
77 profiles.swap(_profiles);
78 std::vector<std::string> activeProfiles;
79 activeProfiles.swap(_activeProfiles);
80
81 try
82 {
Matthew Barth3770a1d2021-06-10 15:09:37 -050083 _loadAllowed = true;
Matthew Barthe91ac862021-05-25 16:22:17 -050084 load();
85 }
Patrick Williamsddb773b2021-10-06 11:24:49 -050086 catch (const std::runtime_error& re)
Matthew Barthe91ac862021-05-25 16:22:17 -050087 {
88 // Restore saved available and active profiles
Matthew Barth3770a1d2021-06-10 15:09:37 -050089 _loadAllowed = false;
Matthew Barthe91ac862021-05-25 16:22:17 -050090 _profiles.swap(profiles);
91 _activeProfiles.swap(activeProfiles);
92 log<level::ERR>("Error reloading configs, no changes made",
93 entry("LOAD_ERROR=%s", re.what()));
94 }
95}
96
Matt Spinler2fc0a352021-10-04 15:10:57 -050097void Manager::sigUsr1Handler(sdeventplus::source::Signal&,
98 const struct signalfd_siginfo*)
99{
Matt Spinler7787def2021-10-14 16:33:16 -0500100 debugDumpEventSource = std::make_unique<sdeventplus::source::Defer>(
101 _event, std::bind(std::mem_fn(&Manager::dumpDebugData), this,
Matt Spinler2fc0a352021-10-04 15:10:57 -0500102 std::placeholders::_1));
103}
104
Matt Spinler7787def2021-10-14 16:33:16 -0500105void Manager::dumpDebugData(sdeventplus::source::EventBase& /*source*/)
Matt Spinler2fc0a352021-10-04 15:10:57 -0500106{
Matt Spinler7787def2021-10-14 16:33:16 -0500107 json data;
108 FlightRecorder::instance().dump(data);
109
110 std::ofstream file{Manager::dumpFile};
111 if (!file)
112 {
113 log<level::ERR>("Could not open file for fan dump");
114 return;
115 }
116
117 file << std::setw(4) << data;
118
119 debugDumpEventSource.reset();
Matt Spinler2fc0a352021-10-04 15:10:57 -0500120}
121
Matthew Barthe91ac862021-05-25 16:22:17 -0500122void Manager::load()
123{
Matthew Barth3770a1d2021-06-10 15:09:37 -0500124 if (_loadAllowed)
Matthew Barthde90fb42021-03-04 16:34:28 -0600125 {
Matthew Barth3770a1d2021-06-10 15:09:37 -0500126 // Load the available profiles and which are active
127 setProfiles();
128
129 // Load the zone configurations
130 auto zones = getConfig<Zone>(false, _event, this);
131 // Load the fan configurations and move each fan into its zone
132 auto fans = getConfig<Fan>(false);
133 for (auto& fan : fans)
Matthew Barthde90fb42021-03-04 16:34:28 -0600134 {
Matthew Barth3770a1d2021-06-10 15:09:37 -0500135 configKey fanProfile =
136 std::make_pair(fan.second->getZone(), fan.first.second);
137 auto itZone = std::find_if(
138 zones.begin(), zones.end(), [&fanProfile](const auto& zone) {
139 return Manager::inConfig(fanProfile, zone.first);
140 });
141 if (itZone != zones.end())
Matthew Barth6f787302021-03-25 15:01:01 -0500142 {
Matthew Barth3770a1d2021-06-10 15:09:37 -0500143 if (itZone->second->getTarget() != fan.second->getTarget() &&
144 fan.second->getTarget() != 0)
145 {
146 // Update zone target to current target of the fan in the
147 // zone
148 itZone->second->setTarget(fan.second->getTarget());
149 }
150 itZone->second->addFan(std::move(fan.second));
Matthew Barth6f787302021-03-25 15:01:01 -0500151 }
Matthew Barthde90fb42021-03-04 16:34:28 -0600152 }
Matthew Barth3770a1d2021-06-10 15:09:37 -0500153
Matthew Barth3695ac32021-10-06 14:55:30 -0500154 // Save all currently available groups, if any, then clear for reloading
155 auto groups = std::move(Event::getAllGroups(false));
156 Event::clearAllGroups();
157
158 std::map<configKey, std::unique_ptr<Event>> events;
159 try
160 {
161 // Load any events configured, including all the groups
162 events = getConfig<Event>(true, this, zones);
163 }
164 catch (const std::runtime_error& re)
165 {
166 // Restore saved set of all available groups for current events
167 Event::setAllGroups(std::move(groups));
168 throw re;
169 }
Matthew Barth3770a1d2021-06-10 15:09:37 -0500170
171 // Enable zones
172 _zones = std::move(zones);
173 std::for_each(_zones.begin(), _zones.end(),
174 [](const auto& entry) { entry.second->enable(); });
175
176 // Clear current timers and signal subscriptions before enabling events
177 // To save reloading services and/or objects into cache, do not clear
178 // cache
179 _timers.clear();
180 _signals.clear();
181
182 // Enable events
183 _events = std::move(events);
184 std::for_each(_events.begin(), _events.end(),
185 [](const auto& entry) { entry.second->enable(); });
186
187 _loadAllowed = false;
Matthew Barthde90fb42021-03-04 16:34:28 -0600188 }
Matthew Barthacd737c2021-03-04 11:04:01 -0600189}
190
Matthew Barth48f44da2021-05-27 15:43:34 -0500191void Manager::powerStateChanged(bool powerStateOn)
192{
193 if (powerStateOn)
194 {
Matthew Barth6a2418a2021-09-01 09:10:09 -0500195 if (_zones.empty())
196 {
197 throw std::runtime_error("No configured zones found at poweron");
198 }
Matthew Barth48f44da2021-05-27 15:43:34 -0500199 std::for_each(_zones.begin(), _zones.end(), [](const auto& entry) {
200 entry.second->setTarget(entry.second->getPoweronTarget());
201 });
202 }
203}
204
Matthew Barthacd737c2021-03-04 11:04:01 -0600205const std::vector<std::string>& Manager::getActiveProfiles()
206{
207 return _activeProfiles;
Matthew Bartha227a162020-08-05 10:51:45 -0500208}
209
Matthew Barth0206c722021-03-30 15:20:05 -0500210bool Manager::inConfig(const configKey& input, const configKey& comp)
211{
212 // Config names dont match, do not include in config
213 if (input.first != comp.first)
214 {
215 return false;
216 }
217 // No profiles specified by input config, can be used in any config
218 if (input.second.empty())
219 {
220 return true;
221 }
222 else
223 {
224 // Profiles must have one match in the other's profiles(and they must be
225 // an active profile) to be used in the config
226 return std::any_of(
227 input.second.begin(), input.second.end(),
228 [&comp](const auto& lProfile) {
229 return std::any_of(
230 comp.second.begin(), comp.second.end(),
231 [&lProfile](const auto& rProfile) {
232 if (lProfile != rProfile)
233 {
234 return false;
235 }
236 auto activeProfs = getActiveProfiles();
237 return std::find(activeProfs.begin(), activeProfs.end(),
238 lProfile) != activeProfs.end();
239 });
240 });
241 }
242}
243
Matthew Barth12cb1252021-03-08 16:47:30 -0600244bool Manager::hasOwner(const std::string& path, const std::string& intf)
245{
246 auto itServ = _servTree.find(path);
247 if (itServ == _servTree.end())
248 {
249 // Path not found in cache, therefore owner missing
250 return false;
251 }
Matthew Barth4ca87fa2021-04-14 11:31:13 -0500252 for (const auto& service : itServ->second)
Matthew Barth12cb1252021-03-08 16:47:30 -0600253 {
254 auto itIntf = std::find_if(
Matthew Barth4ca87fa2021-04-14 11:31:13 -0500255 service.second.second.begin(), service.second.second.end(),
Matthew Barth12cb1252021-03-08 16:47:30 -0600256 [&intf](const auto& interface) { return intf == interface; });
Matthew Barth4ca87fa2021-04-14 11:31:13 -0500257 if (itIntf != std::end(service.second.second))
Matthew Barth12cb1252021-03-08 16:47:30 -0600258 {
259 // Service found, return owner state
Matthew Barth4ca87fa2021-04-14 11:31:13 -0500260 return service.second.first;
Matthew Barth12cb1252021-03-08 16:47:30 -0600261 }
262 }
263 // Interface not found in cache, therefore owner missing
264 return false;
265}
266
Matthew Barth4ca87fa2021-04-14 11:31:13 -0500267void Manager::setOwner(const std::string& path, const std::string& serv,
268 const std::string& intf, bool isOwned)
269{
Matthew Barth2a9e7b22021-05-17 11:54:54 -0500270 // Set owner state for specific object given
271 auto& ownIntf = _servTree[path][serv];
272 ownIntf.first = isOwned;
273 auto itIntf = std::find_if(
274 ownIntf.second.begin(), ownIntf.second.end(),
275 [&intf](const auto& interface) { return intf == interface; });
276 if (itIntf == std::end(ownIntf.second))
Matthew Barth4ca87fa2021-04-14 11:31:13 -0500277 {
Matthew Barth2a9e7b22021-05-17 11:54:54 -0500278 ownIntf.second.emplace_back(intf);
Matthew Barth4ca87fa2021-04-14 11:31:13 -0500279 }
Matthew Barth2a9e7b22021-05-17 11:54:54 -0500280
281 // Update owner state on all entries of the same `serv` & `intf`
282 for (auto& itPath : _servTree)
Matthew Barth4ca87fa2021-04-14 11:31:13 -0500283 {
Matthew Barth2a9e7b22021-05-17 11:54:54 -0500284 if (itPath.first == path)
Matthew Barth4ca87fa2021-04-14 11:31:13 -0500285 {
Matthew Barth2a9e7b22021-05-17 11:54:54 -0500286 // Already set/updated owner on this path for `serv` & `intf`
287 continue;
288 }
289 for (auto& itServ : itPath.second)
290 {
291 if (itServ.first != serv)
Matthew Barth4ca87fa2021-04-14 11:31:13 -0500292 {
Matthew Barth2a9e7b22021-05-17 11:54:54 -0500293 continue;
294 }
295 auto itIntf = std::find_if(
296 itServ.second.second.begin(), itServ.second.second.end(),
297 [&intf](const auto& interface) { return intf == interface; });
298 if (itIntf != std::end(itServ.second.second))
299 {
300 itServ.second.first = isOwned;
Matthew Barth4ca87fa2021-04-14 11:31:13 -0500301 }
302 }
303 }
Matthew Barth4ca87fa2021-04-14 11:31:13 -0500304}
305
306const std::string& Manager::findService(const std::string& path,
307 const std::string& intf)
308{
309 static const std::string empty = "";
310
311 auto itServ = _servTree.find(path);
312 if (itServ != _servTree.end())
313 {
314 for (const auto& service : itServ->second)
315 {
316 auto itIntf = std::find_if(
317 service.second.second.begin(), service.second.second.end(),
318 [&intf](const auto& interface) { return intf == interface; });
319 if (itIntf != std::end(service.second.second))
320 {
321 // Service found, return service name
322 return service.first;
323 }
324 }
325 }
326
327 return empty;
328}
329
Matthew Barth98f6fc12021-04-16 10:48:37 -0500330void Manager::addServices(const std::string& intf, int32_t depth)
Matthew Barth4ca87fa2021-04-14 11:31:13 -0500331{
332 // Get all subtree objects for the given interface
Matt Spinler34835152021-07-01 12:28:58 -0600333 auto objects = util::SDBusPlus::getSubTreeRaw(util::SDBusPlus::getBus(),
334 "/", intf, depth);
Matthew Barth4ca87fa2021-04-14 11:31:13 -0500335 // Add what's returned to the cache of path->services
336 for (auto& itPath : objects)
337 {
338 auto pathIter = _servTree.find(itPath.first);
339 if (pathIter != _servTree.end())
340 {
341 // Path found in cache
342 for (auto& itServ : itPath.second)
343 {
344 auto servIter = pathIter->second.find(itServ.first);
345 if (servIter != pathIter->second.end())
346 {
347 // Service found in cache
348 for (auto& itIntf : itServ.second)
349 {
350 if (std::find(servIter->second.second.begin(),
351 servIter->second.second.end(),
352 itIntf) == servIter->second.second.end())
353 {
354 // Add interface to cache
355 servIter->second.second.emplace_back(itIntf);
356 }
357 }
358 }
359 else
360 {
361 // Service not found in cache
362 auto intfs = {intf};
363 pathIter->second[itServ.first] =
364 std::make_pair(true, intfs);
365 }
366 }
367 }
368 else
369 {
370 // Path not found in cache
371 auto intfs = {intf};
372 _servTree[itPath.first] = {
373 {itPath.second.begin()->first, std::make_pair(true, intfs)}};
374 }
375 }
376}
377
378const std::string& Manager::getService(const std::string& path,
379 const std::string& intf)
380{
381 // Retrieve service from cache
382 const auto& serviceName = findService(path, intf);
383 if (serviceName.empty())
384 {
Matthew Barth98f6fc12021-04-16 10:48:37 -0500385 addServices(intf, 0);
Matthew Barth4ca87fa2021-04-14 11:31:13 -0500386 return findService(path, intf);
387 }
388
389 return serviceName;
390}
391
Matthew Barthf41e9472021-05-13 16:38:06 -0500392std::vector<std::string> Manager::findPaths(const std::string& serv,
393 const std::string& intf)
394{
395 std::vector<std::string> paths;
396
397 for (const auto& path : _servTree)
398 {
399 auto itServ = path.second.find(serv);
400 if (itServ != path.second.end())
401 {
402 if (std::find(itServ->second.second.begin(),
403 itServ->second.second.end(),
404 intf) != itServ->second.second.end())
405 {
406 if (std::find(paths.begin(), paths.end(), path.first) ==
407 paths.end())
408 {
409 paths.push_back(path.first);
410 }
411 }
412 }
413 }
414
415 return paths;
416}
417
418std::vector<std::string> Manager::getPaths(const std::string& serv,
419 const std::string& intf)
420{
421 auto paths = findPaths(serv, intf);
422 if (paths.empty())
423 {
424 addServices(intf, 0);
425 return findPaths(serv, intf);
426 }
427
428 return paths;
429}
430
431void Manager::addObjects(const std::string& path, const std::string& intf,
432 const std::string& prop)
433{
434 auto service = getService(path, intf);
435 if (service.empty())
436 {
437 // Log service not found for object
Matt Spinler34835152021-07-01 12:28:58 -0600438 log<level::DEBUG>(
Matthew Barthf41e9472021-05-13 16:38:06 -0500439 fmt::format("Unable to get service name for path {}, interface {}",
440 path, intf)
441 .c_str());
442 return;
443 }
444
445 auto objMgrPaths = getPaths(service, "org.freedesktop.DBus.ObjectManager");
446 if (objMgrPaths.empty())
447 {
448 // No object manager interface provided by service?
449 // Attempt to retrieve property directly
450 auto variant = util::SDBusPlus::getPropertyVariant<PropertyVariantType>(
451 _bus, service, path, intf, prop);
452 _objects[path][intf][prop] = variant;
453 return;
454 }
455
456 for (const auto& objMgrPath : objMgrPaths)
457 {
458 // Get all managed objects of service
459 auto objects = util::SDBusPlus::getManagedObjects<PropertyVariantType>(
460 _bus, service, objMgrPath);
461
462 // Add what's returned to the cache of objects
463 for (auto& object : objects)
464 {
465 auto itPath = _objects.find(object.first);
466 if (itPath != _objects.end())
467 {
468 // Path found in cache
469 for (auto& interface : itPath->second)
470 {
471 auto itIntf = itPath->second.find(interface.first);
472 if (itIntf != itPath->second.end())
473 {
474 // Interface found in cache
475 for (auto& property : itIntf->second)
476 {
477 auto itProp = itIntf->second.find(property.first);
478 if (itProp != itIntf->second.end())
479 {
480 // Property found, update value
481 itProp->second = property.second;
482 }
483 else
484 {
485 itIntf->second.insert(property);
486 }
487 }
488 }
489 else
490 {
491 // Interface not found in cache
492 itPath->second.insert(interface);
493 }
494 }
495 }
496 else
497 {
498 // Path not found in cache
499 _objects.insert(object);
500 }
501 }
502 }
503}
504
505const std::optional<PropertyVariantType>
506 Manager::getProperty(const std::string& path, const std::string& intf,
507 const std::string& prop)
508{
509 // TODO Objects hosted by fan control (i.e. ThermalMode) are required to
510 // update the cache upon being set/updated
511 auto itPath = _objects.find(path);
512 if (itPath != _objects.end())
513 {
514 auto itIntf = itPath->second.find(intf);
515 if (itIntf != itPath->second.end())
516 {
517 auto itProp = itIntf->second.find(prop);
518 if (itProp != itIntf->second.end())
519 {
520 return itProp->second;
521 }
522 }
523 }
524
525 return std::nullopt;
526}
527
Matthew Barthd9cb63b2021-03-24 14:36:49 -0500528void Manager::addTimer(const TimerType type,
529 const std::chrono::microseconds interval,
530 std::unique_ptr<TimerPkg> pkg)
531{
532 auto dataPtr =
533 std::make_unique<TimerData>(std::make_pair(type, std::move(*pkg)));
534 Timer timer(_event,
535 std::bind(&Manager::timerExpired, this, std::ref(*dataPtr)));
536 if (type == TimerType::repeating)
537 {
538 timer.restart(interval);
539 }
540 else if (type == TimerType::oneshot)
541 {
542 timer.restartOnce(interval);
543 }
544 else
545 {
546 throw std::invalid_argument("Invalid Timer Type");
547 }
548 _timers.emplace_back(std::move(dataPtr), std::move(timer));
549}
550
551void Manager::timerExpired(TimerData& data)
552{
553 auto& actions =
554 std::get<std::vector<std::unique_ptr<ActionBase>>&>(data.second);
555 // Perform the actions in the timer data
556 std::for_each(actions.begin(), actions.end(),
Matthew Barth00f6aa02021-04-09 10:49:47 -0500557 [](auto& action) { action->run(); });
Matthew Barthd9cb63b2021-03-24 14:36:49 -0500558
559 // Remove oneshot timers after they expired
560 if (data.first == TimerType::oneshot)
561 {
562 auto itTimer = std::find_if(
563 _timers.begin(), _timers.end(), [&data](const auto& timer) {
564 return (data.first == timer.first->first &&
565 (std::get<std::string>(data.second) ==
566 std::get<std::string>(timer.first->second)));
567 });
568 if (itTimer != std::end(_timers))
569 {
570 _timers.erase(itTimer);
571 }
572 }
573}
574
Matthew Barthebabc042021-05-13 15:38:58 -0500575void Manager::handleSignal(sdbusplus::message::message& msg,
Matthew Barthfac8a2f2021-06-10 15:50:36 -0500576 const std::vector<SignalPkg>& pkgs)
Matthew Barthebabc042021-05-13 15:38:58 -0500577{
Matthew Barthfac8a2f2021-06-10 15:50:36 -0500578 for (auto& pkg : pkgs)
Matthew Barthebabc042021-05-13 15:38:58 -0500579 {
580 // Handle the signal callback and only run the actions if the handler
581 // updated the cache for the given SignalObject
582 if (std::get<SignalHandler>(pkg)(msg, std::get<SignalObject>(pkg),
583 *this))
584 {
585 // Perform the actions in the handler package
586 auto& actions = std::get<SignalActions>(pkg);
587 std::for_each(actions.begin(), actions.end(),
588 [](auto& action) { action.get()->run(); });
589 }
590 }
591}
592
Matthew Barthacd737c2021-03-04 11:04:01 -0600593void Manager::setProfiles()
594{
595 // Profiles JSON config file is optional
596 auto confFile = fan::JsonConfig::getConfFile(_bus, confAppName,
597 Profile::confFileName, true);
Matthew Barthe91ac862021-05-25 16:22:17 -0500598
599 _profiles.clear();
Matthew Barthacd737c2021-03-04 11:04:01 -0600600 if (!confFile.empty())
601 {
602 for (const auto& entry : fan::JsonConfig::load(confFile))
603 {
604 auto obj = std::make_unique<Profile>(entry);
605 _profiles.emplace(
606 std::make_pair(obj->getName(), obj->getProfiles()),
607 std::move(obj));
608 }
609 }
Matthew Barthe91ac862021-05-25 16:22:17 -0500610
Matthew Barthacd737c2021-03-04 11:04:01 -0600611 // Ensure all configurations use the same set of active profiles
612 // (In case a profile's active state changes during configuration)
Matthew Barthe91ac862021-05-25 16:22:17 -0500613 _activeProfiles.clear();
Matthew Barthacd737c2021-03-04 11:04:01 -0600614 for (const auto& profile : _profiles)
615 {
616 if (profile.second->isActive())
617 {
618 _activeProfiles.emplace_back(profile.first.first);
619 }
620 }
621}
622
Matthew Bartha227a162020-08-05 10:51:45 -0500623} // namespace phosphor::fan::control::json