Add support for processing start event triggers
Process application start event triggers' list of conditions on a group
and perform the defined actions.
This re-uses the following structs(and their necessary functions)
directly from phosphor-inventory-manager:
--struct PropertyConditionBase
--struct PropertyCondition
Change-Id: If4090299fe887ef940320091d4d4be9f6aa7dd29
Signed-off-by: Matthew Barth <msbarth@us.ibm.com>
diff --git a/src/functor.cpp b/src/functor.cpp
new file mode 100644
index 0000000..f4d2574
--- /dev/null
+++ b/src/functor.cpp
@@ -0,0 +1,63 @@
+#include "functor.hpp"
+#include <sdbusplus/bus.hpp>
+#include <sdbusplus/message.hpp>
+
+namespace phosphor
+{
+namespace dbus
+{
+namespace monitoring
+{
+
+bool PropertyConditionBase::operator()(sdbusplus::bus::bus& bus,
+ sdbusplus::message::message&,
+ Monitor& mon) const
+{
+ std::string host;
+
+ if (_service)
+ {
+ host.assign(_service);
+ }
+ else
+ {
+ auto mapperCall = bus.new_method_call(
+ "xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper",
+ "GetObject");
+ mapperCall.append(_path);
+ mapperCall.append(std::vector<std::string>({_iface}));
+ auto mapperResponseMsg = bus.call(mapperCall);
+ if (mapperResponseMsg.is_method_error())
+ {
+ return false;
+ }
+
+ std::map<std::string, std::vector<std::string>> mapperResponse;
+ mapperResponseMsg.read(mapperResponse);
+ if (mapperResponse.empty())
+ {
+ return false;
+ }
+
+ host = mapperResponse.begin()->first;
+ }
+ auto hostCall = bus.new_method_call(host.c_str(),
+ _path.c_str(),
+ "org.freedesktop.DBus.Properties",
+ "Get");
+ hostCall.append(_iface);
+ hostCall.append(_property);
+ auto hostResponseMsg = bus.call(hostCall);
+ if (hostResponseMsg.is_method_error())
+ {
+ return false;
+ }
+
+ return eval(hostResponseMsg);
+}
+
+} // namespace monitoring
+} // namespace dbus
+} // namespace phosphor
diff --git a/src/functor.hpp b/src/functor.hpp
index 9353763..c2c586e 100644
--- a/src/functor.hpp
+++ b/src/functor.hpp
@@ -23,6 +23,121 @@
return Action(std::forward<T>(action));
}
+struct PropertyConditionBase
+{
+ PropertyConditionBase() = delete;
+ virtual ~PropertyConditionBase() = default;
+ PropertyConditionBase(const PropertyConditionBase&) = default;
+ PropertyConditionBase& operator=(const PropertyConditionBase&) = default;
+ PropertyConditionBase(PropertyConditionBase&&) = default;
+ PropertyConditionBase& operator=(PropertyConditionBase&&) = default;
+
+ /** @brief Constructor
+ *
+ * The service argument can be nullptr. If something
+ * else is provided the function will call the the
+ * service directly. If omitted, the function will
+ * look up the service in the ObjectMapper.
+ *
+ * @param path - The path of the object containing
+ * the property to be tested.
+ * @param iface - The interface hosting the property
+ * to be tested.
+ * @param property - The property to be tested.
+ * @param service - The DBus service hosting the object.
+ */
+ PropertyConditionBase(
+ const char* path,
+ const char* iface,
+ const char* property,
+ const char* service) :
+ _path(path ? path : std::string()),
+ _iface(iface),
+ _property(property),
+ _service(service) {}
+
+ /** @brief Forward comparison to type specific implementation. */
+ virtual bool eval(sdbusplus::message::message&) const = 0;
+
+ /** @brief Test a property value.
+ *
+ * Make a DBus call and test the value of any property.
+ */
+ bool operator()(
+ sdbusplus::bus::bus&,
+ sdbusplus::message::message&,
+ Monitor&) const;
+
+private:
+ std::string _path;
+ std::string _iface;
+ std::string _property;
+ const char* _service;
+};
+
+template <typename T, typename U>
+struct PropertyCondition final : public PropertyConditionBase
+{
+ PropertyCondition() = delete;
+ ~PropertyCondition() = default;
+ PropertyCondition(const PropertyCondition&) = default;
+ PropertyCondition& operator=(const PropertyCondition&) = default;
+ PropertyCondition(PropertyCondition&&) = default;
+ PropertyCondition& operator=(PropertyCondition&&) = default;
+
+ /** @brief Constructor
+ *
+ * The service argument can be nullptr. If something
+ * else is provided the function will call the the
+ * service directly. If omitted, the function will
+ * look up the service in the ObjectMapper.
+ *
+ * @param path - The path of the object containing
+ * the property to be tested.
+ * @param iface - The interface hosting the property
+ * to be tested.
+ * @param property - The property to be tested.
+ * @param condition - The test to run on the property.
+ * @param service - The DBus service hosting the object.
+ */
+ PropertyCondition(
+ const char* path,
+ const char* iface,
+ const char* property,
+ U&& condition,
+ const char* service) :
+ PropertyConditionBase(path, iface, property, service),
+ _condition(std::forward<decltype(condition)>(condition)) {}
+
+ /** @brief Test a property value.
+ *
+ * Make a DBus call and test the value of any property.
+ */
+ bool eval(sdbusplus::message::message& msg) const override
+ {
+ sdbusplus::message::variant<T> value;
+ msg.read(value);
+ return _condition(std::forward<T>(value.template get<T>()));
+ }
+
+private:
+ U _condition;
+};
+
+template <typename T, typename U>
+auto propertyStart(const char* path,
+ const char* iface,
+ const char* property,
+ U&& condition,
+ const char* service = nullptr)
+{
+ return PropertyCondition<T, U>(path,
+ iface,
+ property,
+ std::move(condition),
+ service);
+}
+
} // namespace monitoring
} // namespace dbus
} // namespace phosphor
diff --git a/src/monitor.cpp b/src/monitor.cpp
index f734b00..2864924 100644
--- a/src/monitor.cpp
+++ b/src/monitor.cpp
@@ -7,12 +7,56 @@
namespace monitoring
{
+// TODO Remove when generated.cpp included
+const std::vector<std::tuple<std::vector<std::shared_ptr<Event>>,
+ std::vector<Action>>>
+ Monitor::events
+{};
+
Monitor::Monitor(sdbusplus::bus::bus& bus) :
bus(bus)
{
}
+void Monitor::processStart() noexcept
+{
+ sdbusplus::message::message nullMsg{nullptr};
+
+ // Process thru given events that are type 'start'
+ for (auto& event : events)
+ {
+ for (auto& pEvent : std::get<std::vector<std::shared_ptr<Event>>>(event))
+ {
+ if (pEvent->trigger == Event::Trigger::START)
+ {
+ handleEvent(nullMsg, *pEvent, event);
+ }
+ }
+ }
+}
+
+void Monitor::handleEvent(sdbusplus::message::message& msg,
+ const Event& event,
+ const std::tuple<std::vector<std::shared_ptr<Event>>,
+ std::vector<Action>>& eventDef)
+{
+ // Iterate over conditions
+ for (auto& cond : event)
+ {
+ if (!cond(bus, msg, *this))
+ {
+ continue;
+ }
+ // Perform defined actions
+ for (auto& act : std::get<1>(eventDef))
+ {
+ act(bus, *this);
+ }
+ return;
+ }
+}
+
} // namespace monitoring
} // namespace dbus
} // namespace phosphor
diff --git a/src/monitor.hpp b/src/monitor.hpp
index 2fc91b5..aca64d8 100644
--- a/src/monitor.hpp
+++ b/src/monitor.hpp
@@ -23,9 +23,20 @@
explicit Monitor(sdbusplus::bus::bus& bus);
+ void processStart() noexcept;
+
+ void handleEvent(sdbusplus::message::message& msg,
+ const Event& event,
+ const std::tuple<std::vector<std::shared_ptr<Event>>,
+ std::vector<Action>>& eventDef);
+
private:
sdbusplus::bus::bus& bus;
+ static const std::vector<
+ std::tuple<std::vector<std::shared_ptr<Event>>,
+ std::vector<Action>>> events;
+
};
} // namespace monitoring