blob: eeedfd31b69ba88bb182ecffdc3163875c5374b3 [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 */
16#pragma once
17
Matthew Barthacd737c2021-03-04 11:04:01 -060018#include "json_config.hpp"
Matthew Barth06764942021-03-04 09:28:40 -060019#include "profile.hpp"
Matthew Barthacd737c2021-03-04 11:04:01 -060020#include "zone.hpp"
Matthew Barth06764942021-03-04 09:28:40 -060021
Matthew Bartha227a162020-08-05 10:51:45 -050022#include <nlohmann/json.hpp>
23#include <sdbusplus/bus.hpp>
Matthew Barth06764942021-03-04 09:28:40 -060024#include <sdeventplus/event.hpp>
Matthew Bartha227a162020-08-05 10:51:45 -050025
26namespace phosphor::fan::control::json
27{
28
29using json = nlohmann::json;
30
Matthew Barthacd737c2021-03-04 11:04:01 -060031/* Application name to be appended to the path for loading a JSON config file */
32constexpr auto confAppName = "control";
33
34/**
35 * Configuration object key to uniquely map to the configuration object
36 * Pair constructed of:
37 * std::string = Configuration object's name
38 * std::vector<std::string> = List of profiles the configuration object
39 * is included in
40 */
41using configKey = std::pair<std::string, std::vector<std::string>>;
42
Matthew Bartha227a162020-08-05 10:51:45 -050043/**
44 * @class Manager - Represents the fan control manager's configuration
45 *
46 * A fan control manager configuration is optional, therefore the "manager.json"
47 * file is also optional. The manager configuration is used to populate
48 * fan control's manager parameters which are used in how the application
49 * operates, not in how the fans are controlled.
50 *
51 * When no manager configuration exists, the fan control application starts,
52 * processes any configured events and then begins controlling fans according
53 * to those events.
54 */
55class Manager
56{
57 public:
58 Manager() = delete;
59 Manager(const Manager&) = delete;
60 Manager(Manager&&) = delete;
61 Manager& operator=(const Manager&) = delete;
62 Manager& operator=(Manager&&) = delete;
63 ~Manager() = default;
64
65 /**
66 * Constructor
67 * Parses and populates the fan control manager attributes from a json file
68 *
69 * @param[in] bus - sdbusplus bus object
Matthew Barth06764942021-03-04 09:28:40 -060070 * @param[in] event - sdeventplus event loop
Matthew Bartha227a162020-08-05 10:51:45 -050071 */
Matthew Barth06764942021-03-04 09:28:40 -060072 Manager(sdbusplus::bus::bus& bus, const sdeventplus::Event& event);
Matthew Bartha227a162020-08-05 10:51:45 -050073
74 /**
Matthew Barthacd737c2021-03-04 11:04:01 -060075 * @brief Get the active profiles of the system where an empty list
76 * represents that only configuration entries without a profile defined will
77 * be loaded.
78 *
79 * @return - The list of active profiles
80 */
81 static const std::vector<std::string>& getActiveProfiles();
82
83 /**
84 * @brief Load the configuration of a given JSON class object based on the
85 * active profiles
86 *
87 * @param[in] bus - The sdbusplus bus object
88 * @param[in] isOptional - JSON configuration file is optional or not
89 * Defaults to false
90 *
91 * @return Map of configuration entries
92 * Map of configuration keys to their corresponding configuration object
93 */
94 template <typename T>
95 static std::map<configKey, std::unique_ptr<T>>
96 getConfig(sdbusplus::bus::bus& bus, bool isOptional = false)
97 {
98 std::map<configKey, std::unique_ptr<T>> config;
99
100 auto confFile = fan::JsonConfig::getConfFile(
101 bus, confAppName, T::confFileName, isOptional);
102 if (!confFile.empty())
103 {
104 for (const auto& entry : fan::JsonConfig::load(confFile))
105 {
106 if (entry.contains("profiles"))
107 {
108 std::vector<std::string> profiles;
109 for (const auto& profile : entry["profiles"])
110 {
111 profiles.emplace_back(
112 profile.template get<std::string>());
113 }
114 // Do not create the object if its profiles are not in the
115 // list of active profiles
116 if (!std::any_of(profiles.begin(), profiles.end(),
117 [](const auto& name) {
118 return std::find(
119 getActiveProfiles().begin(),
120 getActiveProfiles().end(),
121 name) !=
122 getActiveProfiles().end();
123 }))
124 {
125 continue;
126 }
127 }
128 auto obj = std::make_unique<T>(bus, entry);
129 config.emplace(
130 std::make_pair(obj->getName(), obj->getProfiles()),
131 std::move(obj));
132 }
133 }
134 return config;
135 }
136
137 /**
Matthew Barth12cb1252021-03-08 16:47:30 -0600138 * @brief Check if the given path and inteface is owned by a dbus service
139 *
140 * @param[in] path - Dbus object path
141 * @param[in] intf - Dbus object interface
142 *
143 * @return - Whether the service has an owner for the given object path and
144 * interface
145 */
146 static bool hasOwner(const std::string& path, const std::string& intf);
147
148 /**
Matthew Barth07fecfc2021-01-29 09:04:43 -0600149 * @brief Get the object's property value as a variant
150 *
151 * @param[in] path - Path of the object containing the property
152 * @param[in] intf - Interface name containing the property
153 * @param[in] prop - Name of property
154 *
155 * @return - The object's property value as a variant
156 */
157 static inline auto getObjValueVariant(const std::string& path,
158 const std::string& intf,
159 const std::string& prop)
160 {
161 return _objects.at(path).at(intf).at(prop);
162 };
163
164 /**
Matthew Bartha227a162020-08-05 10:51:45 -0500165 * @brief Get the configured power on delay(OPTIONAL)
166 *
167 * @return Power on delay in seconds
168 * Configured power on delay in seconds, otherwise 0
169 */
170 unsigned int getPowerOnDelay();
171
172 private:
173 /* JSON file name for manager configuration attributes */
174 static constexpr auto confFileName = "manager.json";
175
176 /* The parsed JSON object */
177 json _jsonObj;
Matthew Barth06764942021-03-04 09:28:40 -0600178
Matthew Barthacd737c2021-03-04 11:04:01 -0600179 /**
180 * The sdbusplus bus object to use
181 */
182 sdbusplus::bus::bus& _bus;
183
184 /**
185 * The sdeventplus even loop to use
186 */
187 sdeventplus::Event _event;
188
Matthew Barth06764942021-03-04 09:28:40 -0600189 /* List of profiles configured */
Matthew Barthacd737c2021-03-04 11:04:01 -0600190 std::map<configKey, std::unique_ptr<Profile>> _profiles;
Matthew Barth06764942021-03-04 09:28:40 -0600191
192 /* List of active profiles */
Matthew Barthacd737c2021-03-04 11:04:01 -0600193 static std::vector<std::string> _activeProfiles;
194
Matthew Barth12cb1252021-03-08 16:47:30 -0600195 /* Subtree map of paths to services (with ownership state) of interfaces */
196 static std::map<std::string, std::map<std::pair<std::string, bool>,
197 std::vector<std::string>>>
198 _servTree;
199
Matthew Barth07fecfc2021-01-29 09:04:43 -0600200 /* Object map of paths to interfaces of properties and their values */
201 static std::map<
202 std::string,
203 std::map<std::string, std::map<std::string, PropertyVariantType>>>
204 _objects;
205
Matthew Barthacd737c2021-03-04 11:04:01 -0600206 /* List of zones configured */
207 std::map<configKey, std::unique_ptr<Zone>> _zones;
208
209 /**
210 * @brief Parse and set the configured profiles from the profiles JSON file
211 *
212 * Retrieves the optional profiles JSON configuration file, parses it, and
213 * creates a list of configured profiles available to the other
214 * configuration files. These profiles can be used to remove or include
215 * entries within the other configuration files.
216 */
217 void setProfiles();
Matthew Bartha227a162020-08-05 10:51:45 -0500218};
219
220} // namespace phosphor::fan::control::json