blob: 09a5a1fdc5e29afd8fe4f4ce4979c41d1624ec73 [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
Deepak Kodihalli5de09572017-05-16 23:53:40 -05007objects = list(settingsDict.viewkeys())
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>
37#include <fstream>
38#include <utility>
39#include <experimental/filesystem>
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -050040#include <regex>
41#include <phosphor-logging/elog.hpp>
42#include <phosphor-logging/elog-errors.hpp>
43#include <phosphor-logging/log.hpp>
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050044#include "config.h"
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -050045#include <xyz/openbmc_project/Common/error.hpp>
Tom Joseph4636e072017-09-24 20:47:24 +053046using namespace phosphor::logging;
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050047
48% for i in set(sdbusplus_includes):
Deepak Kodihalli5de09572017-05-16 23:53:40 -050049#include "${i}"
50% endfor
51
52% for object in objects:
Deepak Kodihallidb838622017-08-27 02:46:47 -050053 % for item in settingsDict[object]:
Deepak Kodihalli5de09572017-05-16 23:53:40 -050054<%
Deepak Kodihallidb838622017-08-27 02:46:47 -050055 ns = get_setting_sdbusplus_type(item['Interface'])
Deepak Kodihalli5de09572017-05-16 23:53:40 -050056 i = ns.rfind('::')
57 ns = ns[:i]
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050058 sdbusplus_namespaces.append(ns)
Deepak Kodihalli5de09572017-05-16 23:53:40 -050059%>\
Deepak Kodihallidb838622017-08-27 02:46:47 -050060 % endfor
Deepak Kodihalli5de09572017-05-16 23:53:40 -050061% endfor
Deepak Kodihalli5de09572017-05-16 23:53:40 -050062
63namespace phosphor
64{
65namespace settings
66{
67
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050068namespace fs = std::experimental::filesystem;
69
Deepak Kodihalli242bc772017-08-04 02:47:54 -050070namespace persistent
71{
72
73// A setting d-bus object /foo/bar/baz is persisted in the filesystem with the
74// same path. This eases re-construction of settings objects when we restore
75// from the filesystem. This can be a problem though when you have two objects
76// such as - /foo/bar and /foo/bar/baz. This is because 'bar' will be treated as
77// a file in the first case, and a subdir in the second. To solve this, suffix
78// files with a trailing __. The __ is a safe character sequence to use, because
79// we won't have d-bus object paths ending with this.
80// With this the objects would be persisted as - /foo/bar__ and /foo/bar/baz__.
81constexpr auto fileSuffix = "__";
82
83}
84
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050085% for n in set(sdbusplus_namespaces):
86using namespace ${n};
87% endfor
88
89% for object in objects:
90<%
Deepak Kodihallidb838622017-08-27 02:46:47 -050091 ns = object.split('/')
92 ns.pop(0)
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050093%>\
94% for n in ns:
95namespace ${n}
96{
97% endfor
Deepak Kodihallidb838622017-08-27 02:46:47 -050098<%
99 interfaces = []
100 aliases = []
101 for item in settingsDict[object]:
102 interfaces.append(item['Interface'])
103 for name, meta in item['Properties'].items():
104 if 'Validation' in meta:
105 dict = meta['Validation']
106 if dict['Type'] == "range":
107 validators[name] = (dict['Type'], dict['Validator'], dict['Unit'])
108 else:
109 validators[name] = (dict['Type'], dict['Validator'])
110%>
111% for index, intf in enumerate(interfaces):
112using Iface${index} = ${get_setting_sdbusplus_type(intf)};
113<% aliases.append("Iface" + str(index)) %>\
114% endfor
115<%
116 parent = "sdbusplus::server::object::object" + "<" + ", ".join(aliases) + ">"
117%>\
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500118using Parent = ${parent};
119
120class Impl : public Parent
121{
122 public:
123 Impl(sdbusplus::bus::bus& bus, const char* path):
124 Parent(bus, path, true),
125 path(path)
126 {
127 }
128 virtual ~Impl() = default;
129
Deepak Kodihallidb838622017-08-27 02:46:47 -0500130% for index, item in enumerate(settingsDict[object]):
131 % for propName, metaDict in item['Properties'].items():
132<% t = propName[:1].lower() + propName[1:] %>\
133<% fname = "validate" + propName %>\
134 decltype(std::declval<Iface${index}>().${t}()) ${t}(decltype(std::declval<Iface${index}>().${t}()) value) override
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500135 {
Deepak Kodihallidb838622017-08-27 02:46:47 -0500136 auto result = Iface${index}::${t}();
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500137 if (value != result)
138 {
Deepak Kodihallidb838622017-08-27 02:46:47 -0500139 % if propName in validators:
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500140 if (!${fname}(value))
141 {
142 namespace error =
143 sdbusplus::xyz::openbmc_project::Common::Error;
144 namespace metadata =
145 phosphor::logging::xyz::openbmc_project::Common;
146 phosphor::logging::report<error::InvalidArgument>(
147 metadata::InvalidArgument::ARGUMENT_NAME("${t}"),
Deepak Kodihallidb838622017-08-27 02:46:47 -0500148 % if validators[propName][0] != "regex":
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500149 metadata::InvalidArgument::ARGUMENT_VALUE(std::to_string(value).c_str()));
150 % else:
151 metadata::InvalidArgument::ARGUMENT_VALUE(value.c_str()));
152 % endif
153 return result;
154 }
155 % endif
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500156 fs::path p(SETTINGS_PERSIST_PATH);
157 p /= path;
Deepak Kodihalli242bc772017-08-04 02:47:54 -0500158 p += persistent::fileSuffix;
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500159 fs::create_directories(p.parent_path());
160 std::ofstream os(p.c_str(), std::ios::binary);
161 cereal::JSONOutputArchive oarchive(os);
Deepak Kodihallidb838622017-08-27 02:46:47 -0500162 result = Iface${index}::${t}(value);
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500163 oarchive(*this);
164 }
165 return result;
166 }
Deepak Kodihallidb838622017-08-27 02:46:47 -0500167 using Iface${index}::${t};
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500168
Deepak Kodihallidb838622017-08-27 02:46:47 -0500169 % endfor
Andrew Geisslerc15990a2017-07-06 11:36:31 -0500170% endfor
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500171 private:
172 fs::path path;
Deepak Kodihallidb838622017-08-27 02:46:47 -0500173% for index, item in enumerate(settingsDict[object]):
174 % for propName, metaDict in item['Properties'].items():
175<% t = propName[:1].lower() + propName[1:] %>\
176<% fname = "validate" + propName %>\
177 % if propName in validators:
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500178
Deepak Kodihallidb838622017-08-27 02:46:47 -0500179 bool ${fname}(decltype(std::declval<Iface${index}>().${t}()) value)
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500180 {
181 bool matched = false;
Deepak Kodihallidb838622017-08-27 02:46:47 -0500182 % if (validators[propName][0] == 'regex'):
183 std::regex regexToCheck("${validators[propName][1]}");
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500184 matched = std::regex_search(value, regexToCheck);
185 if (!matched)
186 {
Deepak Kodihallidb838622017-08-27 02:46:47 -0500187 std::string err = "Input parameter for ${propName} is invalid "
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500188 "Input: " + value + " not in the format of this regex: "
Deepak Kodihallidb838622017-08-27 02:46:47 -0500189 "${validators[propName][1]}";
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500190 using namespace phosphor::logging;
191 log<level::ERR>(err.c_str());
192 }
Deepak Kodihallidb838622017-08-27 02:46:47 -0500193 % elif (validators[propName][0] == 'range'):
194<% lowhigh = re.split('\.\.', validators[propName][1]) %>\
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500195 if ((value <= ${lowhigh[1]}) && (value >= ${lowhigh[0]}))
196 {
197 matched = true;
198 }
199 else
200 {
Deepak Kodihallidb838622017-08-27 02:46:47 -0500201 std::string err = "Input parameter for ${propName} is invalid "
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500202 "Input: " + std::to_string(value) + "in uint: "
Deepak Kodihallidb838622017-08-27 02:46:47 -0500203 "${validators[propName][2]} is not in range:${validators[propName][1]}";
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500204 using namespace phosphor::logging;
205 log<level::ERR>(err.c_str());
206 }
Deepak Kodihallidb838622017-08-27 02:46:47 -0500207 % else:
208 <% assert("Unknown validation type: propName") %>\
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500209 % endif
210 return matched;
211 }
Deepak Kodihallidb838622017-08-27 02:46:47 -0500212 % endif
213 % endfor
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500214% endfor
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500215};
216
217template<class Archive>
218void save(Archive& a,
Vishwanatha Subbannaa29a3eb2017-09-29 19:18:20 +0530219 const Impl& setting,
220 const std::uint32_t version)
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500221{
222<%
Deepak Kodihallidb838622017-08-27 02:46:47 -0500223props = []
224for index, item in enumerate(settingsDict[object]):
225 intfProps = ["setting." + propName[:1].lower() + propName[1:] + "()" for \
226 propName, metaDict in item['Properties'].items()]
227 props.extend(intfProps)
228props = ', '.join(props)
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500229%>\
Deepak Kodihallidb838622017-08-27 02:46:47 -0500230 a(${props});
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500231}
232
233template<class Archive>
234void load(Archive& a,
Vishwanatha Subbannaa29a3eb2017-09-29 19:18:20 +0530235 Impl& setting,
236 const std::uint32_t version)
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500237{
Deepak Kodihallidb838622017-08-27 02:46:47 -0500238<% props = [] %>\
239% for index, item in enumerate(settingsDict[object]):
240 % for prop, metaDict in item['Properties'].items():
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500241<%
Deepak Kodihallidb838622017-08-27 02:46:47 -0500242 t = "setting." + prop[:1].lower() + prop[1:] + "()"
243 props.append(prop)
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500244%>\
Deepak Kodihallidb838622017-08-27 02:46:47 -0500245 decltype(${t}) ${prop}{};
246 % endfor
247% endfor
248<% props = ', '.join(props) %>
249 a(${props});
250<% props = [] %>
251% for index, item in enumerate(settingsDict[object]):
252 % for prop, metaDict in item['Properties'].items():
253<%
254 t = "setting." + prop[:1].lower() + prop[1:] + "(" + prop + ")"
255%>\
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500256 ${t};
Deepak Kodihallidb838622017-08-27 02:46:47 -0500257 % endfor
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500258% endfor
259}
260
261% for n in reversed(ns):
262} // namespace ${n}
263% endfor
Deepak Kodihallidb838622017-08-27 02:46:47 -0500264
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500265% endfor
266
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500267/** @class Manager
268 *
269 * @brief Compose settings objects and put them on the bus.
270 */
271class Manager
272{
273 public:
274 Manager() = delete;
275 Manager(const Manager&) = delete;
276 Manager& operator=(const Manager&) = delete;
277 Manager(Manager&&) = delete;
278 Manager& operator=(Manager&&) = delete;
279 virtual ~Manager() = default;
280
281 /** @brief Constructor to put settings objects on to the bus.
282 * @param[in] bus - Bus to attach to.
283 */
284 Manager(sdbusplus::bus::bus& bus)
285 {
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500286 fs::path path{};
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500287 settings =
288 std::make_tuple(
Deepak Kodihallidb838622017-08-27 02:46:47 -0500289% for index, path in enumerate(objects):
290<% type = get_setting_type(path) + "::Impl" %>\
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500291 std::make_unique<${type}>(
292 bus,
293 % if index < len(settingsDict) - 1:
Deepak Kodihallidb838622017-08-27 02:46:47 -0500294 "${path}"),
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500295 % else:
Deepak Kodihallidb838622017-08-27 02:46:47 -0500296 "${path}"));
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500297 % endif
298% endfor
299
Deepak Kodihallidb838622017-08-27 02:46:47 -0500300% for index, path in enumerate(objects):
301 path = fs::path(SETTINGS_PERSIST_PATH) / "${path}";
Deepak Kodihalli242bc772017-08-04 02:47:54 -0500302 path += persistent::fileSuffix;
Tom Joseph4636e072017-09-24 20:47:24 +0530303 auto initSetting${index} = [&]()
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500304 {
Deepak Kodihallidb838622017-08-27 02:46:47 -0500305 % for item in settingsDict[path]:
306 % for propName, metaDict in item['Properties'].items():
307<% p = propName[:1].lower() + propName[1:] %>\
308<% defaultValue = metaDict['Default'] %>\
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500309 std::get<${index}>(settings)->
Tom Joseph4636e072017-09-24 20:47:24 +0530310 ${get_setting_sdbusplus_type(item['Interface'])}::${p}(${defaultValue});
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500311 % endfor
Tom Joseph4636e072017-09-24 20:47:24 +0530312% endfor
313 };
314
315 try
316 {
317 if (fs::exists(path))
318 {
319 std::ifstream is(path.c_str(), std::ios::in);
320 cereal::JSONInputArchive iarchive(is);
321 iarchive(*std::get<${index}>(settings));
322 }
323 else
324 {
325 initSetting${index}();
326 }
327 }
328 catch (cereal::Exception& e)
329 {
330 log<level::ERR>(e.what());
331 fs::remove(path);
332 initSetting${index}();
Deepak Kodihallidb838622017-08-27 02:46:47 -0500333 }
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500334 std::get<${index}>(settings)->emit_object_added();
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500335
336% endfor
337 }
338
339 private:
340 /* @brief Composition of settings objects. */
341 std::tuple<
Deepak Kodihallidb838622017-08-27 02:46:47 -0500342% for index, path in enumerate(objects):
343<% type = get_setting_type(path) + "::Impl" %>\
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500344 % if index < len(settingsDict) - 1:
345 std::unique_ptr<${type}>,
346 % else:
347 std::unique_ptr<${type}>> settings;
348 % endif
349% endfor
350};
351
352} // namespace settings
353} // namespace phosphor
Vishwanatha Subbannaa29a3eb2017-09-29 19:18:20 +0530354
355// Now register the class version with Cereal
356% for object in objects:
357<%
358 classname = "phosphor::settings"
359 ns = object.split('/')
360 ns.pop(0)
361%>\
362% for n in ns:
363<%
364 classname += "::" + n
365%>\
366% endfor
367CEREAL_CLASS_VERSION(${classname + "::Impl"}, CLASS_VERSION);
368% endfor