blob: 367c8aa17c0ee55f0d5ae8462b7b005c61d2f34f [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>
Patrick Williams6306e5e2022-06-16 17:14:54 -050040#include <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>
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
Jagpal Singh Gill4d28bcd2023-04-23 23:34:05 -070048/* The DBus busname to own */
49#define SETTINGS_BUSNAME "xyz.openbmc_project.Settings"
50/* Path of directory housing persisted settings */
51#define SETTINGS_PERSIST_PATH "/var/lib/phosphor-settings-manager/settings"
52
53/* Class version to register with Cereal */
54static constexpr size_t CLASS_VERSION = 1;
55
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050056% for i in set(sdbusplus_includes):
Deepak Kodihalli5de09572017-05-16 23:53:40 -050057#include "${i}"
58% endfor
59
Deepak Kodihalli5de09572017-05-16 23:53:40 -050060namespace phosphor
61{
62namespace settings
63{
64
Patrick Williams6306e5e2022-06-16 17:14:54 -050065namespace fs = std::filesystem;
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050066
Deepak Kodihalli242bc772017-08-04 02:47:54 -050067namespace persistent
68{
69
70// A setting d-bus object /foo/bar/baz is persisted in the filesystem with the
71// same path. This eases re-construction of settings objects when we restore
72// from the filesystem. This can be a problem though when you have two objects
73// such as - /foo/bar and /foo/bar/baz. This is because 'bar' will be treated as
74// a file in the first case, and a subdir in the second. To solve this, suffix
75// files with a trailing __. The __ is a safe character sequence to use, because
76// we won't have d-bus object paths ending with this.
77// With this the objects would be persisted as - /foo/bar__ and /foo/bar/baz__.
78constexpr auto fileSuffix = "__";
79
80}
81
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050082% for object in objects:
83<%
Deepak Kodihallidb838622017-08-27 02:46:47 -050084 ns = object.split('/')
85 ns.pop(0)
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -050086%>\
87% for n in ns:
88namespace ${n}
89{
90% endfor
Deepak Kodihallidb838622017-08-27 02:46:47 -050091<%
92 interfaces = []
93 aliases = []
94 for item in settingsDict[object]:
95 interfaces.append(item['Interface'])
96 for name, meta in item['Properties'].items():
97 if 'Validation' in meta:
98 dict = meta['Validation']
99 if dict['Type'] == "range":
100 validators[name] = (dict['Type'], dict['Validator'], dict['Unit'])
101 else:
102 validators[name] = (dict['Type'], dict['Validator'])
103%>
104% for index, intf in enumerate(interfaces):
105using Iface${index} = ${get_setting_sdbusplus_type(intf)};
106<% aliases.append("Iface" + str(index)) %>\
107% endfor
108<%
Patrick Williams7c4181c2022-07-22 19:26:52 -0500109 parent = "sdbusplus::server::object_t" + "<" + ", ".join(aliases) + ">"
Deepak Kodihallidb838622017-08-27 02:46:47 -0500110%>\
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500111using Parent = ${parent};
112
113class Impl : public Parent
114{
115 public:
Patrick Williams7c4181c2022-07-22 19:26:52 -0500116 Impl(sdbusplus::bus_t& bus, const char* path):
Patrick Williams74c4f3b2022-04-05 16:16:20 -0500117 Parent(bus, path, Parent::action::defer_emit),
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500118 path(path)
119 {
120 }
121 virtual ~Impl() = default;
122
Deepak Kodihallidb838622017-08-27 02:46:47 -0500123% for index, item in enumerate(settingsDict[object]):
124 % for propName, metaDict in item['Properties'].items():
Patrick Williamsbcf95782021-05-05 16:20:32 -0500125<% t = NamedElement(name=propName).camelCase %>\
Deepak Kodihallidb838622017-08-27 02:46:47 -0500126<% fname = "validate" + propName %>\
127 decltype(std::declval<Iface${index}>().${t}()) ${t}(decltype(std::declval<Iface${index}>().${t}()) value) override
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500128 {
Deepak Kodihallidb838622017-08-27 02:46:47 -0500129 auto result = Iface${index}::${t}();
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500130 if (value != result)
131 {
Deepak Kodihallidb838622017-08-27 02:46:47 -0500132 % if propName in validators:
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500133 if (!${fname}(value))
134 {
135 namespace error =
136 sdbusplus::xyz::openbmc_project::Common::Error;
137 namespace metadata =
138 phosphor::logging::xyz::openbmc_project::Common;
139 phosphor::logging::report<error::InvalidArgument>(
140 metadata::InvalidArgument::ARGUMENT_NAME("${t}"),
Deepak Kodihallidb838622017-08-27 02:46:47 -0500141 % if validators[propName][0] != "regex":
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500142 metadata::InvalidArgument::ARGUMENT_VALUE(std::to_string(value).c_str()));
143 % else:
144 metadata::InvalidArgument::ARGUMENT_VALUE(value.c_str()));
145 % endif
146 return result;
147 }
148 % endif
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500149 fs::path p(SETTINGS_PERSIST_PATH);
Adriana Kobylakf792a6d2022-07-20 15:07:08 -0500150 p /= path.relative_path();
Deepak Kodihalli242bc772017-08-04 02:47:54 -0500151 p += persistent::fileSuffix;
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500152 fs::create_directories(p.parent_path());
153 std::ofstream os(p.c_str(), std::ios::binary);
154 cereal::JSONOutputArchive oarchive(os);
Deepak Kodihallidb838622017-08-27 02:46:47 -0500155 result = Iface${index}::${t}(value);
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500156 oarchive(*this);
157 }
158 return result;
159 }
Deepak Kodihallidb838622017-08-27 02:46:47 -0500160 using Iface${index}::${t};
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500161
Deepak Kodihallidb838622017-08-27 02:46:47 -0500162 % endfor
Andrew Geisslerc15990a2017-07-06 11:36:31 -0500163% endfor
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500164 private:
165 fs::path path;
Deepak Kodihallidb838622017-08-27 02:46:47 -0500166% for index, item in enumerate(settingsDict[object]):
167 % for propName, metaDict in item['Properties'].items():
Patrick Williamsbcf95782021-05-05 16:20:32 -0500168<% t = NamedElement(name=propName).camelCase %>\
Deepak Kodihallidb838622017-08-27 02:46:47 -0500169<% fname = "validate" + propName %>\
170 % if propName in validators:
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500171
Deepak Kodihallidb838622017-08-27 02:46:47 -0500172 bool ${fname}(decltype(std::declval<Iface${index}>().${t}()) value)
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500173 {
174 bool matched = false;
Deepak Kodihallidb838622017-08-27 02:46:47 -0500175 % if (validators[propName][0] == 'regex'):
176 std::regex regexToCheck("${validators[propName][1]}");
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500177 matched = std::regex_search(value, regexToCheck);
178 if (!matched)
179 {
Deepak Kodihallidb838622017-08-27 02:46:47 -0500180 std::string err = "Input parameter for ${propName} is invalid "
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500181 "Input: " + value + " not in the format of this regex: "
Deepak Kodihallidb838622017-08-27 02:46:47 -0500182 "${validators[propName][1]}";
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500183 using namespace phosphor::logging;
184 log<level::ERR>(err.c_str());
185 }
Deepak Kodihallidb838622017-08-27 02:46:47 -0500186 % elif (validators[propName][0] == 'range'):
187<% lowhigh = re.split('\.\.', validators[propName][1]) %>\
Jagpal Singh Gillcfd49eb2023-04-23 23:09:09 -0700188 % if lowhigh[0] == '0':
189 if (value <= ${lowhigh[1]})
190 % else:
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500191 if ((value <= ${lowhigh[1]}) && (value >= ${lowhigh[0]}))
Jagpal Singh Gillcfd49eb2023-04-23 23:09:09 -0700192 % endif
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500193 {
194 matched = true;
195 }
196 else
197 {
Deepak Kodihallidb838622017-08-27 02:46:47 -0500198 std::string err = "Input parameter for ${propName} is invalid "
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500199 "Input: " + std::to_string(value) + "in uint: "
Deepak Kodihallidb838622017-08-27 02:46:47 -0500200 "${validators[propName][2]} is not in range:${validators[propName][1]}";
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500201 using namespace phosphor::logging;
202 log<level::ERR>(err.c_str());
203 }
Deepak Kodihallidb838622017-08-27 02:46:47 -0500204 % else:
205 <% assert("Unknown validation type: propName") %>\
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500206 % endif
207 return matched;
208 }
Deepak Kodihallidb838622017-08-27 02:46:47 -0500209 % endif
210 % endfor
Dhruvaraj Subhashchandran61d3b6a2017-07-25 09:36:54 -0500211% endfor
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500212};
213
214template<class Archive>
215void save(Archive& a,
Vishwanatha Subbannaa29a3eb2017-09-29 19:18:20 +0530216 const Impl& setting,
Jagpal Singh Gillcfd49eb2023-04-23 23:09:09 -0700217 [[maybe_unused]] const std::uint32_t version)
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500218{
219<%
Deepak Kodihallidb838622017-08-27 02:46:47 -0500220props = []
221for index, item in enumerate(settingsDict[object]):
Patrick Williamsbcf95782021-05-05 16:20:32 -0500222 intfProps = ["setting." + NamedElement(name=propName).camelCase + "()" for \
Deepak Kodihallidb838622017-08-27 02:46:47 -0500223 propName, metaDict in item['Properties'].items()]
224 props.extend(intfProps)
225props = ', '.join(props)
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500226%>\
Lei YUc0ce9922022-03-09 16:01:10 +0800227% if props:
Deepak Kodihallidb838622017-08-27 02:46:47 -0500228 a(${props});
Lei YUc0ce9922022-03-09 16:01:10 +0800229% endif
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500230}
231
232template<class Archive>
233void load(Archive& a,
Vishwanatha Subbannaa29a3eb2017-09-29 19:18:20 +0530234 Impl& setting,
Jagpal Singh Gillcfd49eb2023-04-23 23:09:09 -0700235 [[maybe_unused]] const std::uint32_t version)
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500236{
Deepak Kodihallidb838622017-08-27 02:46:47 -0500237<% props = [] %>\
238% for index, item in enumerate(settingsDict[object]):
239 % for prop, metaDict in item['Properties'].items():
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500240<%
Patrick Williamsbcf95782021-05-05 16:20:32 -0500241 t = "setting." + NamedElement(name=prop).camelCase + "()"
Deepak Kodihallidb838622017-08-27 02:46:47 -0500242 props.append(prop)
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500243%>\
Deepak Kodihallidb838622017-08-27 02:46:47 -0500244 decltype(${t}) ${prop}{};
245 % endfor
246% endfor
247<% props = ', '.join(props) %>
Lei YUc0ce9922022-03-09 16:01:10 +0800248% if props:
Deepak Kodihallidb838622017-08-27 02:46:47 -0500249 a(${props});
Lei YUc0ce9922022-03-09 16:01:10 +0800250% endif
251
Deepak Kodihallidb838622017-08-27 02:46:47 -0500252<% 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 */
Patrick Williams7c4181c2022-07-22 19:26:52 -0500286 explicit Manager(sdbusplus::bus_t& bus) :
Patrick Williams0f6903d2022-04-15 10:03:58 -0500287 settings(
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500288 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:
Patrick Williams0f6903d2022-04-15 10:03:58 -0500296 "${path}")
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500297 % endif
298% endfor
Patrick Williams0f6903d2022-04-15 10:03:58 -0500299 )
300 )
301 {
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500302
Patrick Williams0f6903d2022-04-15 10:03:58 -0500303 fs::path path{};
Deepak Kodihallidb838622017-08-27 02:46:47 -0500304% for index, path in enumerate(objects):
Adriana Kobylakf792a6d2022-07-20 15:07:08 -0500305<% relativePath = path[1:] %>\
306 path = fs::path(SETTINGS_PERSIST_PATH) / "${relativePath}";
Deepak Kodihalli242bc772017-08-04 02:47:54 -0500307 path += persistent::fileSuffix;
Tom Joseph4636e072017-09-24 20:47:24 +0530308 auto initSetting${index} = [&]()
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500309 {
Deepak Kodihallidb838622017-08-27 02:46:47 -0500310 % for item in settingsDict[path]:
311 % for propName, metaDict in item['Properties'].items():
Patrick Williamsbcf95782021-05-05 16:20:32 -0500312<% p = NamedElement(name=propName).camelCase %>\
Deepak Kodihallidb838622017-08-27 02:46:47 -0500313<% defaultValue = metaDict['Default'] %>\
Matt Spinler23552632021-05-14 09:24:09 -0500314% if isinstance(defaultValue, str) and not \
315 defaultValue.startswith('"') and '::' in defaultValue:
316<% ns = get_setting_sdbusplus_type(item['Interface'])
317i = ns.rfind('::')
318defaultValue = "{}::{}".format(ns[:i], defaultValue)
319%>\
320% endif
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500321 std::get<${index}>(settings)->
Tom Joseph4636e072017-09-24 20:47:24 +0530322 ${get_setting_sdbusplus_type(item['Interface'])}::${p}(${defaultValue});
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500323 % endfor
Tom Joseph4636e072017-09-24 20:47:24 +0530324% endfor
325 };
326
327 try
328 {
329 if (fs::exists(path))
330 {
331 std::ifstream is(path.c_str(), std::ios::in);
332 cereal::JSONInputArchive iarchive(is);
333 iarchive(*std::get<${index}>(settings));
334 }
335 else
336 {
337 initSetting${index}();
338 }
339 }
Patrick Williamsb6fa9bb2021-10-06 12:27:57 -0500340 catch (const cereal::Exception& e)
Tom Joseph4636e072017-09-24 20:47:24 +0530341 {
342 log<level::ERR>(e.what());
343 fs::remove(path);
344 initSetting${index}();
Deepak Kodihallidb838622017-08-27 02:46:47 -0500345 }
Deepak Kodihalli7a6f2522017-06-23 23:05:47 -0500346 std::get<${index}>(settings)->emit_object_added();
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500347
348% endfor
349 }
350
351 private:
352 /* @brief Composition of settings objects. */
353 std::tuple<
Deepak Kodihallidb838622017-08-27 02:46:47 -0500354% for index, path in enumerate(objects):
355<% type = get_setting_type(path) + "::Impl" %>\
Deepak Kodihalli5de09572017-05-16 23:53:40 -0500356 % if index < len(settingsDict) - 1:
357 std::unique_ptr<${type}>,
358 % else:
359 std::unique_ptr<${type}>> settings;
360 % endif
361% endfor
362};
363
364} // namespace settings
365} // namespace phosphor
Vishwanatha Subbannaa29a3eb2017-09-29 19:18:20 +0530366
367// Now register the class version with Cereal
368% for object in objects:
369<%
370 classname = "phosphor::settings"
371 ns = object.split('/')
372 ns.pop(0)
373%>\
374% for n in ns:
375<%
376 classname += "::" + n
377%>\
378% endfor
379CEREAL_CLASS_VERSION(${classname + "::Impl"}, CLASS_VERSION);
380% endfor