From e6af23313890b82c4fca4d61ec1d2d9ff4817870 Mon Sep 17 00:00:00 2001 From: Matthew Barth Date: Wed, 12 Apr 2017 13:37:29 -0500 Subject: 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 --- src/functor.cpp | 63 +++++++++++++++++++++++++++++++ src/functor.hpp | 115 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/monitor.cpp | 44 ++++++++++++++++++++++ src/monitor.hpp | 11 ++++++ 4 files changed, 233 insertions(+) create mode 100644 src/functor.cpp 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 +#include + +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({_iface})); + auto mapperResponseMsg = bus.call(mapperCall); + if (mapperResponseMsg.is_method_error()) + { + return false; + } + + std::map> 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 @@ auto make_action(T&& action) return Action(std::forward(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 +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(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 value; + msg.read(value); + return _condition(std::forward(value.template get())); + } + +private: + U _condition; +}; + +template +auto propertyStart(const char* path, + const char* iface, + const char* property, + U&& condition, + const char* service = nullptr) +{ + return PropertyCondition(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 dbus namespace monitoring { +// TODO Remove when generated.cpp included +const std::vector>, + std::vector>> + 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>>(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>& 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 @@ class Monitor explicit Monitor(sdbusplus::bus::bus& bus); + void processStart() noexcept; + + void handleEvent(sdbusplus::message::message& msg, + const Event& event, + const std::tuple>, + std::vector>& eventDef); + private: sdbusplus::bus::bus& bus; + static const std::vector< + std::tuple>, + std::vector>> events; + }; } // namespace monitoring -- cgit v1.2.1