blob: 6f8841fb63de3873343f8517f93ce0ed119dd49c [file] [log] [blame]
Deepak Kodihalli5de09572017-05-16 23:53:40 -05001## This file is a template. The comment below is emitted
2## into the rendered file; feel free to edit this file.
3// WARNING: Generated header. Do not edit!
Deepak Kodihalli5de09572017-05-16 23:53:40 -05004<%
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -05005import re
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -05006from collections import defaultdict
Patrick Williams2b7152f2020-04-02 07:18:32 -05007objects = settingsDict.keys()
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -05008sdbusplus_namespaces = []
9sdbusplus_includes = []
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050010props = defaultdict(list)
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -050011validators = defaultdict(tuple)
Deepak Kodihalli5de09572017-05-16 23:53:40 -050012
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050013def get_setting_sdbusplus_type(setting_intf):
Deepak Kodihalli5de09572017-05-16 23:53:40 -050014 setting = "sdbusplus::" + setting_intf.replace('.', '::')
15 i = setting.rfind('::')
16 setting = setting[:i] + '::server::' + setting[i+2:]
17 return setting
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050018
Deepak Kodihallidb838622017-08-27 02:46:47 -050019def get_setting_type(path):
20 path = path[1:]
21 path = path.replace('/', '::')
22 return path
Deepak Kodihalli5de09572017-05-16 23:53:40 -050023%>\
24#pragma once
25
26% for object in objects:
Deepak Kodihallidb838622017-08-27 02:46:47 -050027 % for item in settingsDict[object]:
Deepak Kodihalli5de09572017-05-16 23:53:40 -050028<%
Deepak Kodihallidb838622017-08-27 02:46:47 -050029 include = item['Interface']
Deepak Kodihalli5de09572017-05-16 23:53:40 -050030 include = include.replace('.', '/')
31 include = include + "/server.hpp"
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050032 sdbusplus_includes.append(include)
Deepak Kodihalli5de09572017-05-16 23:53:40 -050033%>\
Deepak Kodihallidb838622017-08-27 02:46:47 -050034 % endfor
Deepak Kodihalli5de09572017-05-16 23:53:40 -050035% endfor
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050036#include <cereal/archives/json.hpp>
James Feist74e3be72019-02-15 09:59:42 -080037#include <cereal/types/vector.hpp>
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050038#include <fstream>
39#include <utility>
40#include <experimental/filesystem>
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -050041#include <regex>
42#include <phosphor-logging/elog.hpp>
43#include <phosphor-logging/elog-errors.hpp>
44#include <phosphor-logging/log.hpp>
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050045#include "config.h"
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -050046#include <xyz/openbmc_project/Common/error.hpp>
Tom Joseph4636e072017-09-24 20:47:24 +053047using namespace phosphor::logging;
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050048
49% for i in set(sdbusplus_includes):
Deepak Kodihalli5de09572017-05-16 23:53:40 -050050#include "${i}"
51% endfor
52
53% for object in objects:
Deepak Kodihallidb838622017-08-27 02:46:47 -050054 % for item in settingsDict[object]:
Deepak Kodihalli5de09572017-05-16 23:53:40 -050055<%
Deepak Kodihallidb838622017-08-27 02:46:47 -050056 ns = get_setting_sdbusplus_type(item['Interface'])
Deepak Kodihalli5de09572017-05-16 23:53:40 -050057 i = ns.rfind('::')
58 ns = ns[:i]
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050059 sdbusplus_namespaces.append(ns)
Deepak Kodihalli5de09572017-05-16 23:53:40 -050060%>\
Deepak Kodihallidb838622017-08-27 02:46:47 -050061 % endfor
Deepak Kodihalli5de09572017-05-16 23:53:40 -050062% endfor
Deepak Kodihalli5de09572017-05-16 23:53:40 -050063
64namespace phosphor
65{
66namespace settings
67{
68
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050069namespace fs = std::experimental::filesystem;
70
Deepak Kodihalli242bc772017-08-04 02:47:54 -050071namespace persistent
72{
73
74// A setting d-bus object /foo/bar/baz is persisted in the filesystem with the
75// same path. This eases re-construction of settings objects when we restore
76// from the filesystem. This can be a problem though when you have two objects
77// such as - /foo/bar and /foo/bar/baz. This is because 'bar' will be treated as
78// a file in the first case, and a subdir in the second. To solve this, suffix
79// files with a trailing __. The __ is a safe character sequence to use, because
80// we won't have d-bus object paths ending with this.
81// With this the objects would be persisted as - /foo/bar__ and /foo/bar/baz__.
82constexpr auto fileSuffix = "__";
83
84}
85
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050086% for n in set(sdbusplus_namespaces):
87using namespace ${n};
88% endfor
89
90% for object in objects:
91<%
Deepak Kodihallidb838622017-08-27 02:46:47 -050092 ns = object.split('/')
93 ns.pop(0)
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050094%>\
95% for n in ns:
96namespace ${n}
97{
98% endfor
Deepak Kodihallidb838622017-08-27 02:46:47 -050099<%
100 interfaces = []
101 aliases = []
102 for item in settingsDict[object]:
103 interfaces.append(item['Interface'])
104 for name, meta in item['Properties'].items():
105 if 'Validation' in meta:
106 dict = meta['Validation']
107 if dict['Type'] == "range":
108 validators[name] = (dict['Type'], dict['Validator'], dict['Unit'])
109 else:
110 validators[name] = (dict['Type'], dict['Validator'])
111%>
112% for index, intf in enumerate(interfaces):
113using Iface${index} = ${get_setting_sdbusplus_type(intf)};
114<% aliases.append("Iface" + str(index)) %>\
115% endfor
116<%
117 parent = "sdbusplus::server::object::object" + "<" + ", ".join(aliases) + ">"
118%>\
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500119using Parent = ${parent};
120
121class Impl : public Parent
122{
123 public:
124 Impl(sdbusplus::bus::bus& bus, const char* path):
125 Parent(bus, path, true),
126 path(path)
127 {
128 }
129 virtual ~Impl() = default;
130
Deepak Kodihallidb838622017-08-27 02:46:47 -0500131% for index, item in enumerate(settingsDict[object]):
132 % for propName, metaDict in item['Properties'].items():
133<% t = propName[:1].lower() + propName[1:] %>\
134<% fname = "validate" + propName %>\
135 decltype(std::declval<Iface${index}>().${t}()) ${t}(decltype(std::declval<Iface${index}>().${t}()) value) override
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500136 {
Deepak Kodihallidb838622017-08-27 02:46:47 -0500137 auto result = Iface${index}::${t}();
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500138 if (value != result)
139 {
Deepak Kodihallidb838622017-08-27 02:46:47 -0500140 % if propName in validators:
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500141 if (!${fname}(value))
142 {
143 namespace error =
144 sdbusplus::xyz::openbmc_project::Common::Error;
145 namespace metadata =
146 phosphor::logging::xyz::openbmc_project::Common;
147 phosphor::logging::report<error::InvalidArgument>(
148 metadata::InvalidArgument::ARGUMENT_NAME("${t}"),
Deepak Kodihallidb838622017-08-27 02:46:47 -0500149 % if validators[propName][0] != "regex":
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500150 metadata::InvalidArgument::ARGUMENT_VALUE(std::to_string(value).c_str()));
151 % else:
152 metadata::InvalidArgument::ARGUMENT_VALUE(value.c_str()));
153 % endif
154 return result;
155 }
156 % endif
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500157 fs::path p(SETTINGS_PERSIST_PATH);
158 p /= path;
Deepak Kodihalli242bc772017-08-04 02:47:54 -0500159 p += persistent::fileSuffix;
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500160 fs::create_directories(p.parent_path());
161 std::ofstream os(p.c_str(), std::ios::binary);
162 cereal::JSONOutputArchive oarchive(os);
Deepak Kodihallidb838622017-08-27 02:46:47 -0500163 result = Iface${index}::${t}(value);
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500164 oarchive(*this);
165 }
166 return result;
167 }
Deepak Kodihallidb838622017-08-27 02:46:47 -0500168 using Iface${index}::${t};
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500169
Deepak Kodihallidb838622017-08-27 02:46:47 -0500170 % endfor
Andrew Geisslerc15990a2017-07-06 11:36:31 -0500171% endfor
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500172 private:
173 fs::path path;
Deepak Kodihallidb838622017-08-27 02:46:47 -0500174% for index, item in enumerate(settingsDict[object]):
175 % for propName, metaDict in item['Properties'].items():
176<% t = propName[:1].lower() + propName[1:] %>\
177<% fname = "validate" + propName %>\
178 % if propName in validators:
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500179
Deepak Kodihallidb838622017-08-27 02:46:47 -0500180 bool ${fname}(decltype(std::declval<Iface${index}>().${t}()) value)
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500181 {
182 bool matched = false;
Deepak Kodihallidb838622017-08-27 02:46:47 -0500183 % if (validators[propName][0] == 'regex'):
184 std::regex regexToCheck("${validators[propName][1]}");
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500185 matched = std::regex_search(value, regexToCheck);
186 if (!matched)
187 {
Deepak Kodihallidb838622017-08-27 02:46:47 -0500188 std::string err = "Input parameter for ${propName} is invalid "
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500189 "Input: " + value + " not in the format of this regex: "
Deepak Kodihallidb838622017-08-27 02:46:47 -0500190 "${validators[propName][1]}";
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500191 using namespace phosphor::logging;
192 log<level::ERR>(err.c_str());
193 }
Deepak Kodihallidb838622017-08-27 02:46:47 -0500194 % elif (validators[propName][0] == 'range'):
195<% lowhigh = re.split('\.\.', validators[propName][1]) %>\
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500196 if ((value <= ${lowhigh[1]}) && (value >= ${lowhigh[0]}))
197 {
198 matched = true;
199 }
200 else
201 {
Deepak Kodihallidb838622017-08-27 02:46:47 -0500202 std::string err = "Input parameter for ${propName} is invalid "
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500203 "Input: " + std::to_string(value) + "in uint: "
Deepak Kodihallidb838622017-08-27 02:46:47 -0500204 "${validators[propName][2]} is not in range:${validators[propName][1]}";
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500205 using namespace phosphor::logging;
206 log<level::ERR>(err.c_str());
207 }
Deepak Kodihallidb838622017-08-27 02:46:47 -0500208 % else:
209 <% assert("Unknown validation type: propName") %>\
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500210 % endif
211 return matched;
212 }
Deepak Kodihallidb838622017-08-27 02:46:47 -0500213 % endif
214 % endfor
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500215% endfor
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500216};
217
218template<class Archive>
219void save(Archive& a,
Vishwanatha Subbannaa29a3eb2017-09-29 19:18:20 +0530220 const Impl& setting,
221 const std::uint32_t version)
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500222{
223<%
Deepak Kodihallidb838622017-08-27 02:46:47 -0500224props = []
225for index, item in enumerate(settingsDict[object]):
226 intfProps = ["setting." + propName[:1].lower() + propName[1:] + "()" for \
227 propName, metaDict in item['Properties'].items()]
228 props.extend(intfProps)
229props = ', '.join(props)
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500230%>\
Deepak Kodihallidb838622017-08-27 02:46:47 -0500231 a(${props});
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500232}
233
234template<class Archive>
235void load(Archive& a,
Vishwanatha Subbannaa29a3eb2017-09-29 19:18:20 +0530236 Impl& setting,
237 const std::uint32_t version)
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500238{
Deepak Kodihallidb838622017-08-27 02:46:47 -0500239<% props = [] %>\
240% for index, item in enumerate(settingsDict[object]):
241 % for prop, metaDict in item['Properties'].items():
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500242<%
Deepak Kodihallidb838622017-08-27 02:46:47 -0500243 t = "setting." + prop[:1].lower() + prop[1:] + "()"
244 props.append(prop)
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500245%>\
Deepak Kodihallidb838622017-08-27 02:46:47 -0500246 decltype(${t}) ${prop}{};
247 % endfor
248% endfor
249<% props = ', '.join(props) %>
250 a(${props});
251<% props = [] %>
252% for index, item in enumerate(settingsDict[object]):
253 % for prop, metaDict in item['Properties'].items():
254<%
255 t = "setting." + prop[:1].lower() + prop[1:] + "(" + prop + ")"
256%>\
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500257 ${t};
Deepak Kodihallidb838622017-08-27 02:46:47 -0500258 % endfor
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500259% endfor
260}
261
262% for n in reversed(ns):
263} // namespace ${n}
264% endfor
Deepak Kodihallidb838622017-08-27 02:46:47 -0500265
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500266% endfor
267
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500268/** @class Manager
269 *
270 * @brief Compose settings objects and put them on the bus.
271 */
272class Manager
273{
274 public:
275 Manager() = delete;
276 Manager(const Manager&) = delete;
277 Manager& operator=(const Manager&) = delete;
278 Manager(Manager&&) = delete;
279 Manager& operator=(Manager&&) = delete;
280 virtual ~Manager() = default;
281
282 /** @brief Constructor to put settings objects on to the bus.
283 * @param[in] bus - Bus to attach to.
284 */
285 Manager(sdbusplus::bus::bus& bus)
286 {
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500287 fs::path path{};
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500288 settings =
289 std::make_tuple(
Deepak Kodihallidb838622017-08-27 02:46:47 -0500290% for index, path in enumerate(objects):
291<% type = get_setting_type(path) + "::Impl" %>\
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500292 std::make_unique<${type}>(
293 bus,
294 % if index < len(settingsDict) - 1:
Deepak Kodihallidb838622017-08-27 02:46:47 -0500295 "${path}"),
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500296 % else:
Deepak Kodihallidb838622017-08-27 02:46:47 -0500297 "${path}"));
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500298 % endif
299% endfor
300
Deepak Kodihallidb838622017-08-27 02:46:47 -0500301% for index, path in enumerate(objects):
302 path = fs::path(SETTINGS_PERSIST_PATH) / "${path}";
Deepak Kodihalli242bc772017-08-04 02:47:54 -0500303 path += persistent::fileSuffix;
Tom Joseph4636e072017-09-24 20:47:24 +0530304 auto initSetting${index} = [&]()
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500305 {
Deepak Kodihallidb838622017-08-27 02:46:47 -0500306 % for item in settingsDict[path]:
307 % for propName, metaDict in item['Properties'].items():
308<% p = propName[:1].lower() + propName[1:] %>\
309<% defaultValue = metaDict['Default'] %>\
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500310 std::get<${index}>(settings)->
Tom Joseph4636e072017-09-24 20:47:24 +0530311 ${get_setting_sdbusplus_type(item['Interface'])}::${p}(${defaultValue});
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500312 % endfor
Tom Joseph4636e072017-09-24 20:47:24 +0530313% endfor
314 };
315
316 try
317 {
318 if (fs::exists(path))
319 {
320 std::ifstream is(path.c_str(), std::ios::in);
321 cereal::JSONInputArchive iarchive(is);
322 iarchive(*std::get<${index}>(settings));
323 }
324 else
325 {
326 initSetting${index}();
327 }
328 }
329 catch (cereal::Exception& e)
330 {
331 log<level::ERR>(e.what());
332 fs::remove(path);
333 initSetting${index}();
Deepak Kodihallidb838622017-08-27 02:46:47 -0500334 }
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500335 std::get<${index}>(settings)->emit_object_added();
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500336
337% endfor
338 }
339
340 private:
341 /* @brief Composition of settings objects. */
342 std::tuple<
Deepak Kodihallidb838622017-08-27 02:46:47 -0500343% for index, path in enumerate(objects):
344<% type = get_setting_type(path) + "::Impl" %>\
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500345 % if index < len(settingsDict) - 1:
346 std::unique_ptr<${type}>,
347 % else:
348 std::unique_ptr<${type}>> settings;
349 % endif
350% endfor
351};
352
353} // namespace settings
354} // namespace phosphor
Vishwanatha Subbannaa29a3eb2017-09-29 19:18:20 +0530355
356// Now register the class version with Cereal
357% for object in objects:
358<%
359 classname = "phosphor::settings"
360 ns = object.split('/')
361 ns.pop(0)
362%>\
363% for n in ns:
364<%
365 classname += "::" + n
366%>\
367% endfor
368CEREAL_CLASS_VERSION(${classname + "::Impl"}, CLASS_VERSION);
369% endfor