control: Extend actions from the config base object
Make actions also be base config objects to allow profiles to be defined
on an action. This also provides the parsing of variable values from the
JSON of a configured action.
Included in this commit is an action parsing error exception class that
actions will use when a required attribute fails to be parsed from the
JSON for the given action.
Change-Id: I0fb040afb09d17830e7bb1a587de1b501b638eae
Signed-off-by: Matthew Barth <msbarth@us.ibm.com>
diff --git a/control/json/actions/action.hpp b/control/json/actions/action.hpp
index 358e33a..1525175 100644
--- a/control/json/actions/action.hpp
+++ b/control/json/actions/action.hpp
@@ -15,6 +15,7 @@
*/
#pragma once
+#include "config_base.hpp"
#include "group.hpp"
#include "zone.hpp"
@@ -36,6 +37,40 @@
using namespace phosphor::logging;
/**
+ * @class ActionParseError - A parsing error exception
+ *
+ * A parsing error exception that can be used to terminate the application
+ * due to not being able to successfully parse a configured action.
+ */
+class ActionParseError : public std::runtime_error
+{
+ public:
+ ActionParseError() = delete;
+ ActionParseError(const ActionParseError&) = delete;
+ ActionParseError(ActionParseError&&) = delete;
+ ActionParseError& operator=(const ActionParseError&) = delete;
+ ActionParseError& operator=(ActionParseError&&) = delete;
+ ~ActionParseError() = default;
+
+ /**
+ * @brief Action parsing error object
+ *
+ * When parsing an action from the JSON configuration, any critical
+ * attributes that fail to be parsed for an action can throw an
+ * ActionParseError exception to log the parsing failure details and
+ * terminate the application.
+ *
+ * @param[in] name - Name of the action
+ * @param[in] details - Additional details of the parsing error
+ */
+ ActionParseError(const std::string& name, const std::string& details) :
+ std::runtime_error(
+ fmt::format("Failed to parse action {} [{}]", name, details)
+ .c_str())
+ {}
+};
+
+/**
* @brief Function used in creating action objects
*
* @param[in] jsonObj - JSON object for the action
@@ -53,7 +88,7 @@
*
* Base class for fan control's event actions
*/
-class ActionBase
+class ActionBase : public ConfigBase
{
public:
ActionBase() = delete;
@@ -67,11 +102,13 @@
* @brief Base action object
*
* All actions derived from this base action object must be given a name
- * that uniquely identifies the action.
+ * that uniquely identifies the action. Optionally, a configured action can
+ * have a list of explicit profiles it should be included in, otherwise
+ * always include the action where no profiles are given.
*
- * @param[in] name - Unique name of the action
+ * @param[in] jsonObj - JSON object containing name and any profiles
*/
- explicit ActionBase(const std::string& name) : _name(name)
+ explicit ActionBase(const json& jsonObj) : ConfigBase(jsonObj)
{}
/**
@@ -85,20 +122,6 @@
* @param[in] group - Group of dbus objects the action runs against
*/
virtual void run(Zone& zone, const Group& group) = 0;
-
- /**
- * @brief Get the action's name
- *
- * @return Name of the action
- */
- inline const auto& getName() const
- {
- return _name;
- }
-
- private:
- /* The action's name that is used within the JSON configuration */
- const std::string _name;
};
/**
diff --git a/control/json/actions/default_floor.cpp b/control/json/actions/default_floor.cpp
index 81bbd41..18c434e 100644
--- a/control/json/actions/default_floor.cpp
+++ b/control/json/actions/default_floor.cpp
@@ -28,7 +28,7 @@
using json = nlohmann::json;
-DefaultFloor::DefaultFloor(const json&) : ActionBase(DefaultFloor::name)
+DefaultFloor::DefaultFloor(const json& jsonObj) : ActionBase(jsonObj)
{
// There are no JSON configuration parameters for this action
}
diff --git a/control/json/actions/default_floor.hpp b/control/json/actions/default_floor.hpp
index 25d30bb..f5c994b 100644
--- a/control/json/actions/default_floor.hpp
+++ b/control/json/actions/default_floor.hpp
@@ -49,9 +49,9 @@
/**
* @brief Default the fan floor
*
- * No JSON configuration parameters required
+ * @param[in] jsonObj - JSON configuration of this action
*/
- explicit DefaultFloor(const json&);
+ explicit DefaultFloor(const json& jsonObj);
/**
* @brief Run the action
diff --git a/control/json/actions/missing_owner_target.cpp b/control/json/actions/missing_owner_target.cpp
index 3cbd8a1..3b081b0 100644
--- a/control/json/actions/missing_owner_target.cpp
+++ b/control/json/actions/missing_owner_target.cpp
@@ -33,7 +33,7 @@
using namespace phosphor::logging;
MissingOwnerTarget::MissingOwnerTarget(const json& jsonObj) :
- ActionBase(MissingOwnerTarget::name)
+ ActionBase(jsonObj)
{
setTarget(jsonObj);
}
@@ -58,13 +58,8 @@
{
if (!jsonObj.contains("speed"))
{
- log<level::ERR>(
- fmt::format("Action {}: Missing required speed value", getName())
- .c_str(),
- entry("JSON=%s", jsonObj.dump().c_str()));
- throw std::runtime_error(
- fmt::format("Action {}: Missing required speed value", getName())
- .c_str());
+ throw ActionParseError{ActionBase::getName(),
+ "Missing required speed value"};
}
_target = jsonObj["speed"].get<uint64_t>();
}
diff --git a/control/json/actions/missing_owner_target.hpp b/control/json/actions/missing_owner_target.hpp
index 35fb5a9..0bf6c84 100644
--- a/control/json/actions/missing_owner_target.hpp
+++ b/control/json/actions/missing_owner_target.hpp
@@ -51,7 +51,7 @@
/**
* @brief Set target on an owner missing
*
- * @param[in] jsonObj - JSON containing the configured target to use
+ * @param[in] jsonObj - JSON configuration of this action
*/
explicit MissingOwnerTarget(const json& jsonObj);
diff --git a/control/json/actions/request_target_base.cpp b/control/json/actions/request_target_base.cpp
index 2de3e46..5f53de3 100644
--- a/control/json/actions/request_target_base.cpp
+++ b/control/json/actions/request_target_base.cpp
@@ -32,8 +32,7 @@
using json = nlohmann::json;
using namespace phosphor::logging;
-RequestTargetBase::RequestTargetBase(const json&) :
- ActionBase(RequestTargetBase::name)
+RequestTargetBase::RequestTargetBase(const json& jsonObj) : ActionBase(jsonObj)
{
// There are no JSON configuration parameters for this action
}
diff --git a/control/json/actions/request_target_base.hpp b/control/json/actions/request_target_base.hpp
index 6285dc5..85e5ed9 100644
--- a/control/json/actions/request_target_base.hpp
+++ b/control/json/actions/request_target_base.hpp
@@ -54,9 +54,9 @@
/**
* @brief Update the requested target base
*
- * No JSON configuration parameters required
+ * @param[in] jsonObj - JSON configuration of this action
*/
- explicit RequestTargetBase(const json&);
+ explicit RequestTargetBase(const json& jsonObj);
/**
* @brief Run the action
diff --git a/control/json/config_base.hpp b/control/json/config_base.hpp
index 17287ce..816fcdf 100644
--- a/control/json/config_base.hpp
+++ b/control/json/config_base.hpp
@@ -48,6 +48,13 @@
{
// Set the name of this configuration object
setName(jsonObj);
+ if (jsonObj.contains("profiles"))
+ {
+ for (const auto& profile : jsonObj["profiles"])
+ {
+ _profiles.emplace_back(profile.get<std::string>());
+ }
+ }
}
/**
diff --git a/control/json/fan.cpp b/control/json/fan.cpp
index 16da07e..a880915 100644
--- a/control/json/fan.cpp
+++ b/control/json/fan.cpp
@@ -35,13 +35,6 @@
Fan::Fan(sdbusplus::bus::bus& bus, const json& jsonObj) :
ConfigBase(jsonObj), _bus(bus)
{
- if (jsonObj.contains("profiles"))
- {
- for (const auto& profile : jsonObj["profiles"])
- {
- _profiles.emplace_back(profile.get<std::string>());
- }
- }
setInterface(jsonObj);
setSensors(jsonObj);
setZone(jsonObj);
diff --git a/control/json/group.cpp b/control/json/group.cpp
index f193ef7..2930aac 100644
--- a/control/json/group.cpp
+++ b/control/json/group.cpp
@@ -26,13 +26,6 @@
Group::Group(const json& jsonObj) : ConfigBase(jsonObj), _service("")
{
- if (jsonObj.contains("profiles"))
- {
- for (const auto& profile : jsonObj["profiles"])
- {
- _profiles.emplace_back(profile.get<std::string>());
- }
- }
setMembers(jsonObj);
// Setting the group's service name is optional
if (jsonObj.contains("service"))
diff --git a/control/json/zone.cpp b/control/json/zone.cpp
index 5596d09..6dd4618 100644
--- a/control/json/zone.cpp
+++ b/control/json/zone.cpp
@@ -54,13 +54,6 @@
_incDelay(0), _floor(0), _target(0), _incDelta(0), _requestTargetBase(0),
_isActive(true)
{
- if (jsonObj.contains("profiles"))
- {
- for (const auto& profile : jsonObj["profiles"])
- {
- _profiles.emplace_back(profile.get<std::string>());
- }
- }
// Increase delay is optional, defaults to 0
if (jsonObj.contains("increase_delay"))
{