blob: c3446414996a0d21912a9305c8e54b45a6d9328b [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_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
Deepak Kodihalli5de09572017-05-16 23:53:40 -050053namespace phosphor
54{
55namespace settings
56{
57
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050058namespace fs = std::experimental::filesystem;
59
Deepak Kodihalli242bc772017-08-04 02:47:54 -050060namespace persistent
61{
62
63// A setting d-bus object /foo/bar/baz is persisted in the filesystem with the
64// same path. This eases re-construction of settings objects when we restore
65// from the filesystem. This can be a problem though when you have two objects
66// such as - /foo/bar and /foo/bar/baz. This is because 'bar' will be treated as
67// a file in the first case, and a subdir in the second. To solve this, suffix
68// files with a trailing __. The __ is a safe character sequence to use, because
69// we won't have d-bus object paths ending with this.
70// With this the objects would be persisted as - /foo/bar__ and /foo/bar/baz__.
71constexpr auto fileSuffix = "__";
72
73}
74
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050075% for object in objects:
76<%
Deepak Kodihallidb838622017-08-27 02:46:47 -050077 ns = object.split('/')
78 ns.pop(0)
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050079%>\
80% for n in ns:
81namespace ${n}
82{
83% endfor
Deepak Kodihallidb838622017-08-27 02:46:47 -050084<%
85 interfaces = []
86 aliases = []
87 for item in settingsDict[object]:
88 interfaces.append(item['Interface'])
89 for name, meta in item['Properties'].items():
90 if 'Validation' in meta:
91 dict = meta['Validation']
92 if dict['Type'] == "range":
93 validators[name] = (dict['Type'], dict['Validator'], dict['Unit'])
94 else:
95 validators[name] = (dict['Type'], dict['Validator'])
96%>
97% for index, intf in enumerate(interfaces):
98using Iface${index} = ${get_setting_sdbusplus_type(intf)};
99<% aliases.append("Iface" + str(index)) %>\
100% endfor
101<%
102 parent = "sdbusplus::server::object::object" + "<" + ", ".join(aliases) + ">"
103%>\
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500104using Parent = ${parent};
105
106class Impl : public Parent
107{
108 public:
109 Impl(sdbusplus::bus::bus& bus, const char* path):
Patrick Williams74c4f3b2022-04-05 16:16:20 -0500110 Parent(bus, path, Parent::action::defer_emit),
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500111 path(path)
112 {
113 }
114 virtual ~Impl() = default;
115
Deepak Kodihallidb838622017-08-27 02:46:47 -0500116% for index, item in enumerate(settingsDict[object]):
117 % for propName, metaDict in item['Properties'].items():
Patrick Williamsbcf95782021-05-05 16:20:32 -0500118<% t = NamedElement(name=propName).camelCase %>\
Deepak Kodihallidb838622017-08-27 02:46:47 -0500119<% fname = "validate" + propName %>\
120 decltype(std::declval<Iface${index}>().${t}()) ${t}(decltype(std::declval<Iface${index}>().${t}()) value) override
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500121 {
Deepak Kodihallidb838622017-08-27 02:46:47 -0500122 auto result = Iface${index}::${t}();
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500123 if (value != result)
124 {
Deepak Kodihallidb838622017-08-27 02:46:47 -0500125 % if propName in validators:
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500126 if (!${fname}(value))
127 {
128 namespace error =
129 sdbusplus::xyz::openbmc_project::Common::Error;
130 namespace metadata =
131 phosphor::logging::xyz::openbmc_project::Common;
132 phosphor::logging::report<error::InvalidArgument>(
133 metadata::InvalidArgument::ARGUMENT_NAME("${t}"),
Deepak Kodihallidb838622017-08-27 02:46:47 -0500134 % if validators[propName][0] != "regex":
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500135 metadata::InvalidArgument::ARGUMENT_VALUE(std::to_string(value).c_str()));
136 % else:
137 metadata::InvalidArgument::ARGUMENT_VALUE(value.c_str()));
138 % endif
139 return result;
140 }
141 % endif
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500142 fs::path p(SETTINGS_PERSIST_PATH);
143 p /= path;
Deepak Kodihalli242bc772017-08-04 02:47:54 -0500144 p += persistent::fileSuffix;
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500145 fs::create_directories(p.parent_path());
146 std::ofstream os(p.c_str(), std::ios::binary);
147 cereal::JSONOutputArchive oarchive(os);
Deepak Kodihallidb838622017-08-27 02:46:47 -0500148 result = Iface${index}::${t}(value);
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500149 oarchive(*this);
150 }
151 return result;
152 }
Deepak Kodihallidb838622017-08-27 02:46:47 -0500153 using Iface${index}::${t};
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500154
Deepak Kodihallidb838622017-08-27 02:46:47 -0500155 % endfor
Andrew Geisslerc15990a2017-07-06 11:36:31 -0500156% endfor
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500157 private:
158 fs::path path;
Deepak Kodihallidb838622017-08-27 02:46:47 -0500159% for index, item in enumerate(settingsDict[object]):
160 % for propName, metaDict in item['Properties'].items():
Patrick Williamsbcf95782021-05-05 16:20:32 -0500161<% t = NamedElement(name=propName).camelCase %>\
Deepak Kodihallidb838622017-08-27 02:46:47 -0500162<% fname = "validate" + propName %>\
163 % if propName in validators:
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500164
Deepak Kodihallidb838622017-08-27 02:46:47 -0500165 bool ${fname}(decltype(std::declval<Iface${index}>().${t}()) value)
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500166 {
167 bool matched = false;
Deepak Kodihallidb838622017-08-27 02:46:47 -0500168 % if (validators[propName][0] == 'regex'):
169 std::regex regexToCheck("${validators[propName][1]}");
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500170 matched = std::regex_search(value, regexToCheck);
171 if (!matched)
172 {
Deepak Kodihallidb838622017-08-27 02:46:47 -0500173 std::string err = "Input parameter for ${propName} is invalid "
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500174 "Input: " + value + " not in the format of this regex: "
Deepak Kodihallidb838622017-08-27 02:46:47 -0500175 "${validators[propName][1]}";
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500176 using namespace phosphor::logging;
177 log<level::ERR>(err.c_str());
178 }
Deepak Kodihallidb838622017-08-27 02:46:47 -0500179 % elif (validators[propName][0] == 'range'):
180<% lowhigh = re.split('\.\.', validators[propName][1]) %>\
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500181 if ((value <= ${lowhigh[1]}) && (value >= ${lowhigh[0]}))
182 {
183 matched = true;
184 }
185 else
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: " + std::to_string(value) + "in uint: "
Deepak Kodihallidb838622017-08-27 02:46:47 -0500189 "${validators[propName][2]} is not in range:${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 % else:
194 <% assert("Unknown validation type: propName") %>\
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500195 % endif
196 return matched;
197 }
Deepak Kodihallidb838622017-08-27 02:46:47 -0500198 % endif
199 % endfor
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500200% endfor
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500201};
202
203template<class Archive>
204void save(Archive& a,
Vishwanatha Subbannaa29a3eb2017-09-29 19:18:20 +0530205 const Impl& setting,
206 const std::uint32_t version)
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500207{
208<%
Deepak Kodihallidb838622017-08-27 02:46:47 -0500209props = []
210for index, item in enumerate(settingsDict[object]):
Patrick Williamsbcf95782021-05-05 16:20:32 -0500211 intfProps = ["setting." + NamedElement(name=propName).camelCase + "()" for \
Deepak Kodihallidb838622017-08-27 02:46:47 -0500212 propName, metaDict in item['Properties'].items()]
213 props.extend(intfProps)
214props = ', '.join(props)
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500215%>\
Lei YUc0ce9922022-03-09 16:01:10 +0800216% if props:
Deepak Kodihallidb838622017-08-27 02:46:47 -0500217 a(${props});
Lei YUc0ce9922022-03-09 16:01:10 +0800218% endif
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500219}
220
221template<class Archive>
222void load(Archive& a,
Vishwanatha Subbannaa29a3eb2017-09-29 19:18:20 +0530223 Impl& setting,
224 const std::uint32_t version)
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500225{
Deepak Kodihallidb838622017-08-27 02:46:47 -0500226<% props = [] %>\
227% for index, item in enumerate(settingsDict[object]):
228 % for prop, metaDict in item['Properties'].items():
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500229<%
Patrick Williamsbcf95782021-05-05 16:20:32 -0500230 t = "setting." + NamedElement(name=prop).camelCase + "()"
Deepak Kodihallidb838622017-08-27 02:46:47 -0500231 props.append(prop)
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500232%>\
Deepak Kodihallidb838622017-08-27 02:46:47 -0500233 decltype(${t}) ${prop}{};
234 % endfor
235% endfor
236<% props = ', '.join(props) %>
Lei YUc0ce9922022-03-09 16:01:10 +0800237% if props:
Deepak Kodihallidb838622017-08-27 02:46:47 -0500238 a(${props});
Lei YUc0ce9922022-03-09 16:01:10 +0800239% endif
240
Deepak Kodihallidb838622017-08-27 02:46:47 -0500241<% props = [] %>
242% for index, item in enumerate(settingsDict[object]):
243 % for prop, metaDict in item['Properties'].items():
244<%
Patrick Williamsbcf95782021-05-05 16:20:32 -0500245 t = "setting." + NamedElement(name=prop).camelCase + "(" + prop + ")"
Deepak Kodihallidb838622017-08-27 02:46:47 -0500246%>\
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500247 ${t};
Deepak Kodihallidb838622017-08-27 02:46:47 -0500248 % endfor
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500249% endfor
250}
251
252% for n in reversed(ns):
253} // namespace ${n}
254% endfor
Deepak Kodihallidb838622017-08-27 02:46:47 -0500255
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500256% endfor
257
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500258/** @class Manager
259 *
260 * @brief Compose settings objects and put them on the bus.
261 */
262class Manager
263{
264 public:
265 Manager() = delete;
266 Manager(const Manager&) = delete;
267 Manager& operator=(const Manager&) = delete;
268 Manager(Manager&&) = delete;
269 Manager& operator=(Manager&&) = delete;
270 virtual ~Manager() = default;
271
272 /** @brief Constructor to put settings objects on to the bus.
273 * @param[in] bus - Bus to attach to.
274 */
275 Manager(sdbusplus::bus::bus& bus)
276 {
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500277 fs::path path{};
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500278 settings =
279 std::make_tuple(
Deepak Kodihallidb838622017-08-27 02:46:47 -0500280% for index, path in enumerate(objects):
281<% type = get_setting_type(path) + "::Impl" %>\
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500282 std::make_unique<${type}>(
283 bus,
284 % if index < len(settingsDict) - 1:
Deepak Kodihallidb838622017-08-27 02:46:47 -0500285 "${path}"),
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500286 % else:
Deepak Kodihallidb838622017-08-27 02:46:47 -0500287 "${path}"));
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500288 % endif
289% endfor
290
Deepak Kodihallidb838622017-08-27 02:46:47 -0500291% for index, path in enumerate(objects):
292 path = fs::path(SETTINGS_PERSIST_PATH) / "${path}";
Deepak Kodihalli242bc772017-08-04 02:47:54 -0500293 path += persistent::fileSuffix;
Tom Joseph4636e072017-09-24 20:47:24 +0530294 auto initSetting${index} = [&]()
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500295 {
Deepak Kodihallidb838622017-08-27 02:46:47 -0500296 % for item in settingsDict[path]:
297 % for propName, metaDict in item['Properties'].items():
Patrick Williamsbcf95782021-05-05 16:20:32 -0500298<% p = NamedElement(name=propName).camelCase %>\
Deepak Kodihallidb838622017-08-27 02:46:47 -0500299<% defaultValue = metaDict['Default'] %>\
Matt Spinler23552632021-05-14 09:24:09 -0500300% if isinstance(defaultValue, str) and not \
301 defaultValue.startswith('"') and '::' in defaultValue:
302<% ns = get_setting_sdbusplus_type(item['Interface'])
303i = ns.rfind('::')
304defaultValue = "{}::{}".format(ns[:i], defaultValue)
305%>\
306% endif
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500307 std::get<${index}>(settings)->
Tom Joseph4636e072017-09-24 20:47:24 +0530308 ${get_setting_sdbusplus_type(item['Interface'])}::${p}(${defaultValue});
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500309 % endfor
Tom Joseph4636e072017-09-24 20:47:24 +0530310% endfor
311 };
312
313 try
314 {
315 if (fs::exists(path))
316 {
317 std::ifstream is(path.c_str(), std::ios::in);
318 cereal::JSONInputArchive iarchive(is);
319 iarchive(*std::get<${index}>(settings));
320 }
321 else
322 {
323 initSetting${index}();
324 }
325 }
Patrick Williamsb6fa9bb2021-10-06 12:27:57 -0500326 catch (const cereal::Exception& e)
Tom Joseph4636e072017-09-24 20:47:24 +0530327 {
328 log<level::ERR>(e.what());
329 fs::remove(path);
330 initSetting${index}();
Deepak Kodihallidb838622017-08-27 02:46:47 -0500331 }
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500332 std::get<${index}>(settings)->emit_object_added();
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500333
334% endfor
335 }
336
337 private:
338 /* @brief Composition of settings objects. */
339 std::tuple<
Deepak Kodihallidb838622017-08-27 02:46:47 -0500340% for index, path in enumerate(objects):
341<% type = get_setting_type(path) + "::Impl" %>\
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500342 % if index < len(settingsDict) - 1:
343 std::unique_ptr<${type}>,
344 % else:
345 std::unique_ptr<${type}>> settings;
346 % endif
347% endfor
348};
349
350} // namespace settings
351} // namespace phosphor
Vishwanatha Subbannaa29a3eb2017-09-29 19:18:20 +0530352
353// Now register the class version with Cereal
354% for object in objects:
355<%
356 classname = "phosphor::settings"
357 ns = object.split('/')
358 ns.pop(0)
359%>\
360% for n in ns:
361<%
362 classname += "::" + n
363%>\
364% endfor
365CEREAL_CLASS_VERSION(${classname + "::Impl"}, CLASS_VERSION);
366% endfor