blob: 1dbe550caad4cc4277324447fc03ca71fe4abf9b [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>
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050046
47% for i in set(sdbusplus_includes):
Deepak Kodihalli5de09572017-05-16 23:53:40 -050048#include "${i}"
49% endfor
50
51% for object in objects:
Deepak Kodihallidb838622017-08-27 02:46:47 -050052 % for item in settingsDict[object]:
Deepak Kodihalli5de09572017-05-16 23:53:40 -050053<%
Deepak Kodihallidb838622017-08-27 02:46:47 -050054 ns = get_setting_sdbusplus_type(item['Interface'])
Deepak Kodihalli5de09572017-05-16 23:53:40 -050055 i = ns.rfind('::')
56 ns = ns[:i]
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050057 sdbusplus_namespaces.append(ns)
Deepak Kodihalli5de09572017-05-16 23:53:40 -050058%>\
Deepak Kodihallidb838622017-08-27 02:46:47 -050059 % endfor
Deepak Kodihalli5de09572017-05-16 23:53:40 -050060% endfor
Deepak Kodihalli5de09572017-05-16 23:53:40 -050061
62namespace phosphor
63{
64namespace settings
65{
66
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050067namespace fs = std::experimental::filesystem;
68
Deepak Kodihalli242bc772017-08-04 02:47:54 -050069namespace persistent
70{
71
72// A setting d-bus object /foo/bar/baz is persisted in the filesystem with the
73// same path. This eases re-construction of settings objects when we restore
74// from the filesystem. This can be a problem though when you have two objects
75// such as - /foo/bar and /foo/bar/baz. This is because 'bar' will be treated as
76// a file in the first case, and a subdir in the second. To solve this, suffix
77// files with a trailing __. The __ is a safe character sequence to use, because
78// we won't have d-bus object paths ending with this.
79// With this the objects would be persisted as - /foo/bar__ and /foo/bar/baz__.
80constexpr auto fileSuffix = "__";
81
82}
83
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050084% for n in set(sdbusplus_namespaces):
85using namespace ${n};
86% endfor
87
88% for object in objects:
89<%
Deepak Kodihallidb838622017-08-27 02:46:47 -050090 ns = object.split('/')
91 ns.pop(0)
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050092%>\
93% for n in ns:
94namespace ${n}
95{
96% endfor
Deepak Kodihallidb838622017-08-27 02:46:47 -050097<%
98 interfaces = []
99 aliases = []
100 for item in settingsDict[object]:
101 interfaces.append(item['Interface'])
102 for name, meta in item['Properties'].items():
103 if 'Validation' in meta:
104 dict = meta['Validation']
105 if dict['Type'] == "range":
106 validators[name] = (dict['Type'], dict['Validator'], dict['Unit'])
107 else:
108 validators[name] = (dict['Type'], dict['Validator'])
109%>
110% for index, intf in enumerate(interfaces):
111using Iface${index} = ${get_setting_sdbusplus_type(intf)};
112<% aliases.append("Iface" + str(index)) %>\
113% endfor
114<%
115 parent = "sdbusplus::server::object::object" + "<" + ", ".join(aliases) + ">"
116%>\
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500117using Parent = ${parent};
118
119class Impl : public Parent
120{
121 public:
122 Impl(sdbusplus::bus::bus& bus, const char* path):
123 Parent(bus, path, true),
124 path(path)
125 {
126 }
127 virtual ~Impl() = default;
128
Deepak Kodihallidb838622017-08-27 02:46:47 -0500129% for index, item in enumerate(settingsDict[object]):
130 % for propName, metaDict in item['Properties'].items():
131<% t = propName[:1].lower() + propName[1:] %>\
132<% fname = "validate" + propName %>\
133 decltype(std::declval<Iface${index}>().${t}()) ${t}(decltype(std::declval<Iface${index}>().${t}()) value) override
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500134 {
Deepak Kodihallidb838622017-08-27 02:46:47 -0500135 auto result = Iface${index}::${t}();
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500136 if (value != result)
137 {
Deepak Kodihallidb838622017-08-27 02:46:47 -0500138 % if propName in validators:
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500139 if (!${fname}(value))
140 {
141 namespace error =
142 sdbusplus::xyz::openbmc_project::Common::Error;
143 namespace metadata =
144 phosphor::logging::xyz::openbmc_project::Common;
145 phosphor::logging::report<error::InvalidArgument>(
146 metadata::InvalidArgument::ARGUMENT_NAME("${t}"),
Deepak Kodihallidb838622017-08-27 02:46:47 -0500147 % if validators[propName][0] != "regex":
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500148 metadata::InvalidArgument::ARGUMENT_VALUE(std::to_string(value).c_str()));
149 % else:
150 metadata::InvalidArgument::ARGUMENT_VALUE(value.c_str()));
151 % endif
152 return result;
153 }
154 % endif
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500155 fs::path p(SETTINGS_PERSIST_PATH);
156 p /= path;
Deepak Kodihalli242bc772017-08-04 02:47:54 -0500157 p += persistent::fileSuffix;
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500158 fs::create_directories(p.parent_path());
159 std::ofstream os(p.c_str(), std::ios::binary);
160 cereal::JSONOutputArchive oarchive(os);
Deepak Kodihallidb838622017-08-27 02:46:47 -0500161 result = Iface${index}::${t}(value);
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500162 oarchive(*this);
163 }
164 return result;
165 }
Deepak Kodihallidb838622017-08-27 02:46:47 -0500166 using Iface${index}::${t};
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500167
Deepak Kodihallidb838622017-08-27 02:46:47 -0500168 % endfor
Andrew Geisslerc15990a2017-07-06 11:36:31 -0500169% endfor
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500170 private:
171 fs::path path;
Deepak Kodihallidb838622017-08-27 02:46:47 -0500172% for index, item in enumerate(settingsDict[object]):
173 % for propName, metaDict in item['Properties'].items():
174<% t = propName[:1].lower() + propName[1:] %>\
175<% fname = "validate" + propName %>\
176 % if propName in validators:
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500177
Deepak Kodihallidb838622017-08-27 02:46:47 -0500178 bool ${fname}(decltype(std::declval<Iface${index}>().${t}()) value)
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500179 {
180 bool matched = false;
Deepak Kodihallidb838622017-08-27 02:46:47 -0500181 % if (validators[propName][0] == 'regex'):
182 std::regex regexToCheck("${validators[propName][1]}");
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500183 matched = std::regex_search(value, regexToCheck);
184 if (!matched)
185 {
Deepak Kodihallidb838622017-08-27 02:46:47 -0500186 std::string err = "Input parameter for ${propName} is invalid "
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500187 "Input: " + value + " not in the format of this regex: "
Deepak Kodihallidb838622017-08-27 02:46:47 -0500188 "${validators[propName][1]}";
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500189 using namespace phosphor::logging;
190 log<level::ERR>(err.c_str());
191 }
Deepak Kodihallidb838622017-08-27 02:46:47 -0500192 % elif (validators[propName][0] == 'range'):
193<% lowhigh = re.split('\.\.', validators[propName][1]) %>\
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500194 if ((value <= ${lowhigh[1]}) && (value >= ${lowhigh[0]}))
195 {
196 matched = true;
197 }
198 else
199 {
Deepak Kodihallidb838622017-08-27 02:46:47 -0500200 std::string err = "Input parameter for ${propName} is invalid "
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500201 "Input: " + std::to_string(value) + "in uint: "
Deepak Kodihallidb838622017-08-27 02:46:47 -0500202 "${validators[propName][2]} is not in range:${validators[propName][1]}";
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500203 using namespace phosphor::logging;
204 log<level::ERR>(err.c_str());
205 }
Deepak Kodihallidb838622017-08-27 02:46:47 -0500206 % else:
207 <% assert("Unknown validation type: propName") %>\
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500208 % endif
209 return matched;
210 }
Deepak Kodihallidb838622017-08-27 02:46:47 -0500211 % endif
212 % endfor
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500213% endfor
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500214};
215
216template<class Archive>
217void save(Archive& a,
218 const Impl& setting)
219{
220<%
Deepak Kodihallidb838622017-08-27 02:46:47 -0500221props = []
222for index, item in enumerate(settingsDict[object]):
223 intfProps = ["setting." + propName[:1].lower() + propName[1:] + "()" for \
224 propName, metaDict in item['Properties'].items()]
225 props.extend(intfProps)
226props = ', '.join(props)
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500227%>\
Deepak Kodihallidb838622017-08-27 02:46:47 -0500228 a(${props});
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500229}
230
231template<class Archive>
232void load(Archive& a,
233 Impl& setting)
234{
Deepak Kodihallidb838622017-08-27 02:46:47 -0500235<% props = [] %>\
236% for index, item in enumerate(settingsDict[object]):
237 % for prop, metaDict in item['Properties'].items():
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500238<%
Deepak Kodihallidb838622017-08-27 02:46:47 -0500239 t = "setting." + prop[:1].lower() + prop[1:] + "()"
240 props.append(prop)
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500241%>\
Deepak Kodihallidb838622017-08-27 02:46:47 -0500242 decltype(${t}) ${prop}{};
243 % endfor
244% endfor
245<% props = ', '.join(props) %>
246 a(${props});
247<% props = [] %>
248% for index, item in enumerate(settingsDict[object]):
249 % for prop, metaDict in item['Properties'].items():
250<%
251 t = "setting." + prop[:1].lower() + prop[1:] + "(" + prop + ")"
252%>\
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500253 ${t};
Deepak Kodihallidb838622017-08-27 02:46:47 -0500254 % endfor
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500255% endfor
256}
257
258% for n in reversed(ns):
259} // namespace ${n}
260% endfor
Deepak Kodihallidb838622017-08-27 02:46:47 -0500261
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500262% endfor
263
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500264/** @class Manager
265 *
266 * @brief Compose settings objects and put them on the bus.
267 */
268class Manager
269{
270 public:
271 Manager() = delete;
272 Manager(const Manager&) = delete;
273 Manager& operator=(const Manager&) = delete;
274 Manager(Manager&&) = delete;
275 Manager& operator=(Manager&&) = delete;
276 virtual ~Manager() = default;
277
278 /** @brief Constructor to put settings objects on to the bus.
279 * @param[in] bus - Bus to attach to.
280 */
281 Manager(sdbusplus::bus::bus& bus)
282 {
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500283 fs::path path{};
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500284 settings =
285 std::make_tuple(
Deepak Kodihallidb838622017-08-27 02:46:47 -0500286% for index, path in enumerate(objects):
287<% type = get_setting_type(path) + "::Impl" %>\
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500288 std::make_unique<${type}>(
289 bus,
290 % if index < len(settingsDict) - 1:
Deepak Kodihallidb838622017-08-27 02:46:47 -0500291 "${path}"),
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500292 % else:
Deepak Kodihallidb838622017-08-27 02:46:47 -0500293 "${path}"));
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500294 % endif
295% endfor
296
Deepak Kodihallidb838622017-08-27 02:46:47 -0500297% for index, path in enumerate(objects):
298 path = fs::path(SETTINGS_PERSIST_PATH) / "${path}";
Deepak Kodihalli242bc772017-08-04 02:47:54 -0500299 path += persistent::fileSuffix;
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500300 if (fs::exists(path))
301 {
302 std::ifstream is(path.c_str(), std::ios::in);
303 cereal::JSONInputArchive iarchive(is);
304 iarchive(*std::get<${index}>(settings));
305 }
306 else
307 {
Deepak Kodihallidb838622017-08-27 02:46:47 -0500308 % for item in settingsDict[path]:
309 % for propName, metaDict in item['Properties'].items():
310<% p = propName[:1].lower() + propName[1:] %>\
311<% defaultValue = metaDict['Default'] %>\
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500312 std::get<${index}>(settings)->
Deepak Kodihallidb838622017-08-27 02:46:47 -0500313 ${get_setting_sdbusplus_type(item['Interface'])}::${p}(${defaultValue});
314 % endfor
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500315 % endfor
Deepak Kodihallidb838622017-08-27 02:46:47 -0500316 }
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500317 std::get<${index}>(settings)->emit_object_added();
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500318
319% endfor
320 }
321
322 private:
323 /* @brief Composition of settings objects. */
324 std::tuple<
Deepak Kodihallidb838622017-08-27 02:46:47 -0500325% for index, path in enumerate(objects):
326<% type = get_setting_type(path) + "::Impl" %>\
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500327 % if index < len(settingsDict) - 1:
328 std::unique_ptr<${type}>,
329 % else:
330 std::unique_ptr<${type}>> settings;
331 % endif
332% endfor
333};
334
335} // namespace settings
336} // namespace phosphor