blob: c0dac66c45b22277efece7ce00d80ab3afaf3f08 [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 Williamsbcf95782021-05-05 16:20:32 -05007from sdbusplus.namedelement import NamedElement
Patrick Williams2b7152f2020-04-02 07:18:32 -05008objects = settingsDict.keys()
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -05009sdbusplus_namespaces = []
10sdbusplus_includes = []
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050011props = defaultdict(list)
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -050012validators = defaultdict(tuple)
Deepak Kodihalli5de09572017-05-16 23:53:40 -050013
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050014def get_setting_sdbusplus_type(setting_intf):
Deepak Kodihalli5de09572017-05-16 23:53:40 -050015 setting = "sdbusplus::" + setting_intf.replace('.', '::')
16 i = setting.rfind('::')
17 setting = setting[:i] + '::server::' + setting[i+2:]
18 return setting
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050019
Deepak Kodihallidb838622017-08-27 02:46:47 -050020def get_setting_type(path):
21 path = path[1:]
22 path = path.replace('/', '::')
23 return path
Deepak Kodihalli5de09572017-05-16 23:53:40 -050024%>\
25#pragma once
26
27% for object in objects:
Deepak Kodihallidb838622017-08-27 02:46:47 -050028 % for item in settingsDict[object]:
Deepak Kodihalli5de09572017-05-16 23:53:40 -050029<%
Deepak Kodihallidb838622017-08-27 02:46:47 -050030 include = item['Interface']
Deepak Kodihalli5de09572017-05-16 23:53:40 -050031 include = include.replace('.', '/')
32 include = include + "/server.hpp"
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050033 sdbusplus_includes.append(include)
Deepak Kodihalli5de09572017-05-16 23:53:40 -050034%>\
Deepak Kodihallidb838622017-08-27 02:46:47 -050035 % endfor
Deepak Kodihalli5de09572017-05-16 23:53:40 -050036% endfor
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050037#include <cereal/archives/json.hpp>
James Feist74e3be72019-02-15 09:59:42 -080038#include <cereal/types/vector.hpp>
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050039#include <fstream>
40#include <utility>
41#include <experimental/filesystem>
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -050042#include <regex>
43#include <phosphor-logging/elog.hpp>
44#include <phosphor-logging/elog-errors.hpp>
45#include <phosphor-logging/log.hpp>
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050046#include "config.h"
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -050047#include <xyz/openbmc_project/Common/error.hpp>
Tom Joseph4636e072017-09-24 20:47:24 +053048using namespace phosphor::logging;
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050049
50% for i in set(sdbusplus_includes):
Deepak Kodihalli5de09572017-05-16 23:53:40 -050051#include "${i}"
52% endfor
53
54% for object in objects:
Deepak Kodihallidb838622017-08-27 02:46:47 -050055 % for item in settingsDict[object]:
Deepak Kodihalli5de09572017-05-16 23:53:40 -050056<%
Deepak Kodihallidb838622017-08-27 02:46:47 -050057 ns = get_setting_sdbusplus_type(item['Interface'])
Deepak Kodihalli5de09572017-05-16 23:53:40 -050058 i = ns.rfind('::')
59 ns = ns[:i]
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050060 sdbusplus_namespaces.append(ns)
Deepak Kodihalli5de09572017-05-16 23:53:40 -050061%>\
Deepak Kodihallidb838622017-08-27 02:46:47 -050062 % endfor
Deepak Kodihalli5de09572017-05-16 23:53:40 -050063% endfor
Deepak Kodihalli5de09572017-05-16 23:53:40 -050064
65namespace phosphor
66{
67namespace settings
68{
69
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050070namespace fs = std::experimental::filesystem;
71
Deepak Kodihalli242bc772017-08-04 02:47:54 -050072namespace persistent
73{
74
75// A setting d-bus object /foo/bar/baz is persisted in the filesystem with the
76// same path. This eases re-construction of settings objects when we restore
77// from the filesystem. This can be a problem though when you have two objects
78// such as - /foo/bar and /foo/bar/baz. This is because 'bar' will be treated as
79// a file in the first case, and a subdir in the second. To solve this, suffix
80// files with a trailing __. The __ is a safe character sequence to use, because
81// we won't have d-bus object paths ending with this.
82// With this the objects would be persisted as - /foo/bar__ and /foo/bar/baz__.
83constexpr auto fileSuffix = "__";
84
85}
86
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050087% for n in set(sdbusplus_namespaces):
88using namespace ${n};
89% endfor
90
91% for object in objects:
92<%
Deepak Kodihallidb838622017-08-27 02:46:47 -050093 ns = object.split('/')
94 ns.pop(0)
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050095%>\
96% for n in ns:
97namespace ${n}
98{
99% endfor
Deepak Kodihallidb838622017-08-27 02:46:47 -0500100<%
101 interfaces = []
102 aliases = []
103 for item in settingsDict[object]:
104 interfaces.append(item['Interface'])
105 for name, meta in item['Properties'].items():
106 if 'Validation' in meta:
107 dict = meta['Validation']
108 if dict['Type'] == "range":
109 validators[name] = (dict['Type'], dict['Validator'], dict['Unit'])
110 else:
111 validators[name] = (dict['Type'], dict['Validator'])
112%>
113% for index, intf in enumerate(interfaces):
114using Iface${index} = ${get_setting_sdbusplus_type(intf)};
115<% aliases.append("Iface" + str(index)) %>\
116% endfor
117<%
118 parent = "sdbusplus::server::object::object" + "<" + ", ".join(aliases) + ">"
119%>\
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500120using Parent = ${parent};
121
122class Impl : public Parent
123{
124 public:
125 Impl(sdbusplus::bus::bus& bus, const char* path):
126 Parent(bus, path, true),
127 path(path)
128 {
129 }
130 virtual ~Impl() = default;
131
Deepak Kodihallidb838622017-08-27 02:46:47 -0500132% for index, item in enumerate(settingsDict[object]):
133 % for propName, metaDict in item['Properties'].items():
Patrick Williamsbcf95782021-05-05 16:20:32 -0500134<% t = NamedElement(name=propName).camelCase %>\
Deepak Kodihallidb838622017-08-27 02:46:47 -0500135<% fname = "validate" + propName %>\
136 decltype(std::declval<Iface${index}>().${t}()) ${t}(decltype(std::declval<Iface${index}>().${t}()) value) override
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500137 {
Deepak Kodihallidb838622017-08-27 02:46:47 -0500138 auto result = Iface${index}::${t}();
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500139 if (value != result)
140 {
Deepak Kodihallidb838622017-08-27 02:46:47 -0500141 % if propName in validators:
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500142 if (!${fname}(value))
143 {
144 namespace error =
145 sdbusplus::xyz::openbmc_project::Common::Error;
146 namespace metadata =
147 phosphor::logging::xyz::openbmc_project::Common;
148 phosphor::logging::report<error::InvalidArgument>(
149 metadata::InvalidArgument::ARGUMENT_NAME("${t}"),
Deepak Kodihallidb838622017-08-27 02:46:47 -0500150 % if validators[propName][0] != "regex":
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500151 metadata::InvalidArgument::ARGUMENT_VALUE(std::to_string(value).c_str()));
152 % else:
153 metadata::InvalidArgument::ARGUMENT_VALUE(value.c_str()));
154 % endif
155 return result;
156 }
157 % endif
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500158 fs::path p(SETTINGS_PERSIST_PATH);
159 p /= path;
Deepak Kodihalli242bc772017-08-04 02:47:54 -0500160 p += persistent::fileSuffix;
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500161 fs::create_directories(p.parent_path());
162 std::ofstream os(p.c_str(), std::ios::binary);
163 cereal::JSONOutputArchive oarchive(os);
Deepak Kodihallidb838622017-08-27 02:46:47 -0500164 result = Iface${index}::${t}(value);
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500165 oarchive(*this);
166 }
167 return result;
168 }
Deepak Kodihallidb838622017-08-27 02:46:47 -0500169 using Iface${index}::${t};
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500170
Deepak Kodihallidb838622017-08-27 02:46:47 -0500171 % endfor
Andrew Geisslerc15990a2017-07-06 11:36:31 -0500172% endfor
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500173 private:
174 fs::path path;
Deepak Kodihallidb838622017-08-27 02:46:47 -0500175% for index, item in enumerate(settingsDict[object]):
176 % for propName, metaDict in item['Properties'].items():
Patrick Williamsbcf95782021-05-05 16:20:32 -0500177<% t = NamedElement(name=propName).camelCase %>\
Deepak Kodihallidb838622017-08-27 02:46:47 -0500178<% fname = "validate" + propName %>\
179 % if propName in validators:
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500180
Deepak Kodihallidb838622017-08-27 02:46:47 -0500181 bool ${fname}(decltype(std::declval<Iface${index}>().${t}()) value)
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500182 {
183 bool matched = false;
Deepak Kodihallidb838622017-08-27 02:46:47 -0500184 % if (validators[propName][0] == 'regex'):
185 std::regex regexToCheck("${validators[propName][1]}");
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500186 matched = std::regex_search(value, regexToCheck);
187 if (!matched)
188 {
Deepak Kodihallidb838622017-08-27 02:46:47 -0500189 std::string err = "Input parameter for ${propName} is invalid "
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500190 "Input: " + value + " not in the format of this regex: "
Deepak Kodihallidb838622017-08-27 02:46:47 -0500191 "${validators[propName][1]}";
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500192 using namespace phosphor::logging;
193 log<level::ERR>(err.c_str());
194 }
Deepak Kodihallidb838622017-08-27 02:46:47 -0500195 % elif (validators[propName][0] == 'range'):
196<% lowhigh = re.split('\.\.', validators[propName][1]) %>\
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500197 if ((value <= ${lowhigh[1]}) && (value >= ${lowhigh[0]}))
198 {
199 matched = true;
200 }
201 else
202 {
Deepak Kodihallidb838622017-08-27 02:46:47 -0500203 std::string err = "Input parameter for ${propName} is invalid "
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500204 "Input: " + std::to_string(value) + "in uint: "
Deepak Kodihallidb838622017-08-27 02:46:47 -0500205 "${validators[propName][2]} is not in range:${validators[propName][1]}";
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500206 using namespace phosphor::logging;
207 log<level::ERR>(err.c_str());
208 }
Deepak Kodihallidb838622017-08-27 02:46:47 -0500209 % else:
210 <% assert("Unknown validation type: propName") %>\
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500211 % endif
212 return matched;
213 }
Deepak Kodihallidb838622017-08-27 02:46:47 -0500214 % endif
215 % endfor
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500216% endfor
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500217};
218
219template<class Archive>
220void save(Archive& a,
Vishwanatha Subbannaa29a3eb2017-09-29 19:18:20 +0530221 const Impl& setting,
222 const std::uint32_t version)
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500223{
224<%
Deepak Kodihallidb838622017-08-27 02:46:47 -0500225props = []
226for index, item in enumerate(settingsDict[object]):
Patrick Williamsbcf95782021-05-05 16:20:32 -0500227 intfProps = ["setting." + NamedElement(name=propName).camelCase + "()" for \
Deepak Kodihallidb838622017-08-27 02:46:47 -0500228 propName, metaDict in item['Properties'].items()]
229 props.extend(intfProps)
230props = ', '.join(props)
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500231%>\
Deepak Kodihallidb838622017-08-27 02:46:47 -0500232 a(${props});
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500233}
234
235template<class Archive>
236void load(Archive& a,
Vishwanatha Subbannaa29a3eb2017-09-29 19:18:20 +0530237 Impl& setting,
238 const std::uint32_t version)
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500239{
Deepak Kodihallidb838622017-08-27 02:46:47 -0500240<% props = [] %>\
241% for index, item in enumerate(settingsDict[object]):
242 % for prop, metaDict in item['Properties'].items():
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500243<%
Patrick Williamsbcf95782021-05-05 16:20:32 -0500244 t = "setting." + NamedElement(name=prop).camelCase + "()"
Deepak Kodihallidb838622017-08-27 02:46:47 -0500245 props.append(prop)
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500246%>\
Deepak Kodihallidb838622017-08-27 02:46:47 -0500247 decltype(${t}) ${prop}{};
248 % endfor
249% endfor
250<% props = ', '.join(props) %>
251 a(${props});
252<% props = [] %>
253% for index, item in enumerate(settingsDict[object]):
254 % for prop, metaDict in item['Properties'].items():
255<%
Patrick Williamsbcf95782021-05-05 16:20:32 -0500256 t = "setting." + NamedElement(name=prop).camelCase + "(" + prop + ")"
Deepak Kodihallidb838622017-08-27 02:46:47 -0500257%>\
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500258 ${t};
Deepak Kodihallidb838622017-08-27 02:46:47 -0500259 % endfor
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500260% endfor
261}
262
263% for n in reversed(ns):
264} // namespace ${n}
265% endfor
Deepak Kodihallidb838622017-08-27 02:46:47 -0500266
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500267% endfor
268
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500269/** @class Manager
270 *
271 * @brief Compose settings objects and put them on the bus.
272 */
273class Manager
274{
275 public:
276 Manager() = delete;
277 Manager(const Manager&) = delete;
278 Manager& operator=(const Manager&) = delete;
279 Manager(Manager&&) = delete;
280 Manager& operator=(Manager&&) = delete;
281 virtual ~Manager() = default;
282
283 /** @brief Constructor to put settings objects on to the bus.
284 * @param[in] bus - Bus to attach to.
285 */
286 Manager(sdbusplus::bus::bus& bus)
287 {
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500288 fs::path path{};
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500289 settings =
290 std::make_tuple(
Deepak Kodihallidb838622017-08-27 02:46:47 -0500291% for index, path in enumerate(objects):
292<% type = get_setting_type(path) + "::Impl" %>\
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500293 std::make_unique<${type}>(
294 bus,
295 % if index < len(settingsDict) - 1:
Deepak Kodihallidb838622017-08-27 02:46:47 -0500296 "${path}"),
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500297 % else:
Deepak Kodihallidb838622017-08-27 02:46:47 -0500298 "${path}"));
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500299 % endif
300% endfor
301
Deepak Kodihallidb838622017-08-27 02:46:47 -0500302% for index, path in enumerate(objects):
303 path = fs::path(SETTINGS_PERSIST_PATH) / "${path}";
Deepak Kodihalli242bc772017-08-04 02:47:54 -0500304 path += persistent::fileSuffix;
Tom Joseph4636e072017-09-24 20:47:24 +0530305 auto initSetting${index} = [&]()
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500306 {
Deepak Kodihallidb838622017-08-27 02:46:47 -0500307 % for item in settingsDict[path]:
308 % for propName, metaDict in item['Properties'].items():
Patrick Williamsbcf95782021-05-05 16:20:32 -0500309<% p = NamedElement(name=propName).camelCase %>\
Deepak Kodihallidb838622017-08-27 02:46:47 -0500310<% defaultValue = metaDict['Default'] %>\
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500311 std::get<${index}>(settings)->
Tom Joseph4636e072017-09-24 20:47:24 +0530312 ${get_setting_sdbusplus_type(item['Interface'])}::${p}(${defaultValue});
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500313 % endfor
Tom Joseph4636e072017-09-24 20:47:24 +0530314% endfor
315 };
316
317 try
318 {
319 if (fs::exists(path))
320 {
321 std::ifstream is(path.c_str(), std::ios::in);
322 cereal::JSONInputArchive iarchive(is);
323 iarchive(*std::get<${index}>(settings));
324 }
325 else
326 {
327 initSetting${index}();
328 }
329 }
330 catch (cereal::Exception& e)
331 {
332 log<level::ERR>(e.what());
333 fs::remove(path);
334 initSetting${index}();
Deepak Kodihallidb838622017-08-27 02:46:47 -0500335 }
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500336 std::get<${index}>(settings)->emit_object_added();
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500337
338% endfor
339 }
340
341 private:
342 /* @brief Composition of settings objects. */
343 std::tuple<
Deepak Kodihallidb838622017-08-27 02:46:47 -0500344% for index, path in enumerate(objects):
345<% type = get_setting_type(path) + "::Impl" %>\
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500346 % if index < len(settingsDict) - 1:
347 std::unique_ptr<${type}>,
348 % else:
349 std::unique_ptr<${type}>> settings;
350 % endif
351% endfor
352};
353
354} // namespace settings
355} // namespace phosphor
Vishwanatha Subbannaa29a3eb2017-09-29 19:18:20 +0530356
357// Now register the class version with Cereal
358% for object in objects:
359<%
360 classname = "phosphor::settings"
361 ns = object.split('/')
362 ns.pop(0)
363%>\
364% for n in ns:
365<%
366 classname += "::" + n
367%>\
368% endfor
369CEREAL_CLASS_VERSION(${classname + "::Impl"}, CLASS_VERSION);
370% endfor