diff options
author | Dhruvaraj Subhashchandran <dhruvaraj@in.ibm.com> | 2017-07-25 09:36:54 -0500 |
---|---|---|
committer | Dhruvaraj Subhashchandran <dhruvaraj@in.ibm.com> | 2017-07-28 13:42:44 -0500 |
commit | 61d3b6a1f283f0926cb3e92e14378175030da1b2 (patch) | |
tree | 3b8d8876351799d014d790d3053be3961e8d9c60 | |
parent | c15990a32063192e51c0c3ef5e65e149b2c44d70 (diff) | |
download | phosphor-settingsd-61d3b6a1f283f0926cb3e92e14378175030da1b2.tar.gz phosphor-settingsd-61d3b6a1f283f0926cb3e92e14378175030da1b2.zip |
Validate changes to default settings.
Resolves openbmc/openbmc#1771
Change-Id: I763e811e88710425131ec504ff933e3c41c458e6
Signed-off-by: Dhruvaraj Subhashchandran <dhruvaraj@in.ibm.com>
-rwxr-xr-x | Makefile.am | 4 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | settings_example.yaml | 30 | ||||
-rw-r--r-- | settings_manager.mako.hpp | 78 |
4 files changed, 106 insertions, 8 deletions
diff --git a/Makefile.am b/Makefile.am index 55ea2d6..50c380e 100755 --- a/Makefile.am +++ b/Makefile.am @@ -26,9 +26,11 @@ phosphor_settings_manager_SOURCES = \ phosphor_settings_manager_CXXFLAGS = \ $(PHOSPHOR_DBUS_INTERFACES_CFLAGS) \ - $(SDBUSPLUS_CFLAGS) + $(SDBUSPLUS_CFLAGS) \ + $(PHOSPHOR_LOGGING_CFLAGS) phosphor_settings_manager_LDADD = \ $(PHOSPHOR_DBUS_INTERFACES_LIBS) \ $(SDBUSPLUS_LIBS) \ + $(PHOSPHOR_LOGGING_LIBS) \ -lstdc++fs diff --git a/configure.ac b/configure.ac index 083d623..895ce17 100644 --- a/configure.ac +++ b/configure.ac @@ -16,6 +16,8 @@ PKG_CHECK_MODULES([PHOSPHOR_DBUS_INTERFACES], [phosphor-dbus-interfaces],,\ AC_MSG_ERROR(["Requires phosphor-dbus-interfaces package."])) PKG_CHECK_MODULES([SDBUSPLUS], [sdbusplus],, AC_MSG_ERROR(["Requires sdbusplus package."])) +PKG_CHECK_MODULES([PHOSPHOR_LOGGING], [phosphor-logging],,\ + AC_MSG_ERROR(["Requires phosphor-logging package."])) LT_INIT diff --git a/settings_example.yaml b/settings_example.yaml index d6e7f88..82b63be 100644 --- a/settings_example.yaml +++ b/settings_example.yaml @@ -1,9 +1,31 @@ /xyz/openbmc_project/control/host0/boot_mode: Interface: xyz.openbmc_project.Control.Boot.Mode - Defaults: - BootMode: Mode::Modes::Safe + Properties: + BootMode: + Default: Mode::Modes::Safe /xyz/openbmc_project/control/host1/boot_mode: Interface: xyz.openbmc_project.Control.Boot.Mode - Defaults: - BootMode: Mode::Modes::Regular + Properties: + BootMode: + Default: Mode::Modes::Regular + +/xyz/openbmc_project/network/host0/intf: + Interface: xyz.openbmc_project.Network.MACAddress + Properties: + MACAddress: + Default: '"00:00:00:00:00:00"' + Validation: + Type: "regex" + Validator: '^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$' +/xyz/openbmc_project/control/host0/power_cap: + Interface: xyz.openbmc_project.Control.Power.Cap + Properties: + PowerCap: + Default: 0 + Validation: + Type: "range" + Validator: "0..1000" + Unit: "Watts" + PowerCapEnable: + Default: 'false' diff --git a/settings_manager.mako.hpp b/settings_manager.mako.hpp index cc2ab5b..9fca3da 100644 --- a/settings_manager.mako.hpp +++ b/settings_manager.mako.hpp @@ -2,12 +2,14 @@ ## into the rendered file; feel free to edit this file. // WARNING: Generated header. Do not edit! <% +import re from collections import defaultdict objects = list(settingsDict.viewkeys()) sdbusplus_namespaces = [] sdbusplus_includes = [] interfaces = [] props = defaultdict(list) +validators = defaultdict(tuple) def get_setting_sdbusplus_type(setting_intf): setting = "sdbusplus::" + setting_intf.replace('.', '::') @@ -33,7 +35,12 @@ def get_setting_type(setting_intf): #include <fstream> #include <utility> #include <experimental/filesystem> +#include <regex> +#include <phosphor-logging/elog.hpp> +#include <phosphor-logging/elog-errors.hpp> +#include <phosphor-logging/log.hpp> #include "config.h" +#include <xyz/openbmc_project/Common/error.hpp> % for i in set(sdbusplus_includes): #include "${i}" @@ -64,8 +71,14 @@ using namespace ${n}; intf = settingsDict[object]['Interface'] interfaces.append(intf) if intf not in props: - for property, value in settingsDict[object]['Defaults'].items(): + for property, property_metadata in settingsDict[object]['Properties'].items(): props[intf].append(property) + for attribute, value in property_metadata.items(): + if attribute == 'Validation': + if value['Type'] == "range": + validators[property] = (value['Type'], value['Validator'], value['Unit']) + else: + validators[property] = (value['Type'], value['Validator']) %>\ % endfor % for intf in set(interfaces): @@ -94,11 +107,29 @@ class Impl : public Parent % for arg in props[intf]: <% t = arg[:1].lower() + arg[1:] %>\ +<% fname = "validate"+arg %>\ decltype(std::declval<Base>().${t}()) ${t}(decltype(std::declval<Base>().${t}()) value) override { auto result = Base::${t}(); if (value != result) { + % if arg in validators.keys(): + if (!${fname}(value)) + { + namespace error = + sdbusplus::xyz::openbmc_project::Common::Error; + namespace metadata = + phosphor::logging::xyz::openbmc_project::Common; + phosphor::logging::report<error::InvalidArgument>( + metadata::InvalidArgument::ARGUMENT_NAME("${t}"), + % if validators[arg][0] != "regex": + metadata::InvalidArgument::ARGUMENT_VALUE(std::to_string(value).c_str())); + % else: + metadata::InvalidArgument::ARGUMENT_VALUE(value.c_str())); + % endif + return result; + } + % endif fs::path p(SETTINGS_PERSIST_PATH); p /= path; fs::create_directories(p.parent_path()); @@ -114,6 +145,46 @@ class Impl : public Parent % endfor private: fs::path path; +% for arg in props[intf]: +% if arg in validators.keys(): +<% funcName = "validate"+arg %>\ +<% t = arg[:1].lower() + arg[1:] %>\ + + bool ${funcName}(decltype(std::declval<Base>().${t}()) value) + { + bool matched = false; + % if (arg in validators.keys()) and (validators[arg][0] == 'regex'): + std::regex regexToCheck("${validators[arg][1]}"); + matched = std::regex_search(value, regexToCheck); + if (!matched) + { + std::string err = "Input parameter for ${arg} is invalid " + "Input: " + value + " not in the format of this regex: " + "${validators[arg][1]}"; + using namespace phosphor::logging; + log<level::ERR>(err.c_str()); + } + % elif (arg in validators.keys()) and (validators[arg][0] == 'range'): +<% lowhigh = re.split('\.\.', validators[arg][1]) %>\ + if ((value <= ${lowhigh[1]}) && (value >= ${lowhigh[0]})) + { + matched = true; + } + else + { + std::string err = "Input parameter for ${arg} is invalid " + "Input: " + std::to_string(value) + "in uint: " + "${validators[arg][2]} is not in range:${validators[arg][1]}"; + using namespace phosphor::logging; + log<level::ERR>(err.c_str()); + } + % elif (arg in validators.keys()): + <% assert("Unknown validation type: arg") %>\ + % endif + return matched; + } +% endif +% endfor }; template<class Archive> @@ -184,8 +255,9 @@ class Manager % endfor % for index, object in enumerate(objects): - % for property, value in settingsDict[object]['Defaults'].items(): + % for property, value in settingsDict[object]['Properties'].items(): <% p = property[:1].lower() + property[1:] %>\ +<% defaultValue = value['Default'] %>\ path = fs::path(SETTINGS_PERSIST_PATH) / "${object}"; if (fs::exists(path)) { @@ -196,7 +268,7 @@ class Manager else { std::get<${index}>(settings)-> - ${get_setting_sdbusplus_type(settingsDict[object]['Interface'])}::${p}(${value}); + ${get_setting_sdbusplus_type(settingsDict[object]['Interface'])}::${p}(${defaultValue}); } % endfor std::get<${index}>(settings)->emit_object_added(); |