diff --git a/functor.hpp b/functor.hpp index 903cbd0..7731613 100644 --- a/functor.hpp +++ b/functor.hpp @@ -1,5 +1,6 @@ #pragma once +#include "remove_association.hpp" #include "types.hpp" #include "utils.hpp" @@ -152,6 +153,13 @@ auto setProperty(std::vector&& paths, { m.template invokeMethod(p, iface, member, value); } + bool* newValue = + std::get_if(getProperty(p, iface, member, "Functional")); + if (*newValue) + { + auto service = getService(p, iface); + removeCriticalAssociation(m._bus, p, service); + } } }; } @@ -208,7 +216,7 @@ struct PropertyChangedCondition * Extract the property from the PropertiesChanged * message and run the condition test. */ - bool operator()(sdbusplus::bus_t&, sdbusplus::message_t& msg, + bool operator()(sdbusplus::bus_t& bus, sdbusplus::message_t& msg, Manager&) const { std::map> properties; @@ -226,7 +234,16 @@ struct PropertyChangedCondition { return false; } - + if (!strcmp(_property, "Functional")) + { + const bool* value = std::get_if(&it->second); + if (*value) + { + std::string invObjectPath = msg.get_path(); + const std::string service = getService(invObjectPath, iface); + removeCriticalAssociation(bus, invObjectPath, service); + } + } return _condition(std::forward(std::get(it->second))); } diff --git a/manager.cpp b/manager.cpp index 2c4ee11..1a5049e 100644 --- a/manager.cpp +++ b/manager.cpp @@ -16,6 +16,7 @@ #include "manager.hpp" #include "errors.hpp" +#include "remove_association.hpp" #include #include @@ -41,6 +42,23 @@ auto _signal(sd_bus_message* m, void* data, sd_bus_error* /* e */) noexcept try { auto msg = sdbusplus::message_t(m); + std::string interfaceName{}; + std::map> properties; + msg.read(interfaceName, properties); + const auto it = properties.find("Functional"); + std::string invObjectPath = msg.get_path(); + if (it != properties.end()) + { + static auto bus = sdbusplus::bus::new_default(); + bus = msg.get_bus(); + const std::string service = + getService(invObjectPath, interfaceName); + const bool* value = std::get_if(&it->second); + if (*value) + { + removeCriticalAssociation(bus, invObjectPath, service); + } + } auto& args = *static_cast(data); sd_bus_message_ref(m); auto& mgr = *std::get<0>(args); @@ -82,6 +100,8 @@ Manager::Manager(sdbusplus::bus_t&& bus, const char* root) : _sigargs.emplace_back( std::make_unique(this, dbusEvent, &group)); + // check if functional + // Register our callback and the context for // each signal event. _matches.emplace_back(_bus, dbusEvent->signature, _signal, @@ -266,6 +286,22 @@ void Manager::updateObjects( }); } #endif + for (auto interface = (objit->second).begin(); + interface != (objit->second).end(); interface++) + { + const auto it = (interface->second).find("Functional"); + if (it != (interface->second).end()) + { + const std::string service = + getService(absPath, interface->first); + const bool* value = std::get_if(&it->second); + if (*value) + { + removeCriticalAssociation(_bus, absPath, service); + } + } + } + ++objit; } } @@ -287,6 +323,21 @@ void Manager::handleEvent(sdbusplus::message_t& msg, const Event& event, return; } } + std::string interfaceName{}; + std::map> properties; + msg.read(interfaceName, properties); + const auto it = properties.find("Functional"); + std::string invObjectPath = msg.get_path(); + if (it != properties.end()) + { + const std::string service = getService(invObjectPath, interfaceName); + const bool* value = std::get_if(&it->second); + if (*value) + { + removeCriticalAssociation(_bus, invObjectPath, service); + } + } + for (auto& action : actions) { action(_bus, *this); diff --git a/meson.build b/meson.build index 1886182..7159b57 100644 --- a/meson.build +++ b/meson.build @@ -106,6 +106,7 @@ sources += [ gen_serialization_hpp, 'app.cpp', 'errors.cpp', + 'remove_association.cpp', 'functor.cpp', 'manager.cpp', ] diff --git a/remove_association.cpp b/remove_association.cpp index 9dd3564..ba73f93 100644 --- a/remove_association.cpp +++ b/remove_association.cpp @@ -75,6 +75,30 @@ void getProperty(sdbusplus::bus::bus& bus, const std::string& service, reply.read(value); } +/** @brief get Dbus service + * + */ +const std::string getService(const std::string& path, + const std::string& interface) +{ + constexpr auto mapper_busname = "xyz.openbmc_project.objectmapper"; + constexpr auto mapper_obj_path = "/xyz/openbmc_project/object_mapper"; + constexpr auto mapper_iface = "xyz.openbmc_project.objectmapper"; + using interfacelist = std::vector; + std::map> mapperresponse; + + static auto bus = sdbusplus::bus::new_default(); + auto mapper = bus.new_method_call(mapper_busname, mapper_obj_path, + mapper_iface, "getobject"); + mapper.append(path, interfacelist({interface})); + + auto mapperresponsemsg = bus.call(mapper); + mapperresponsemsg.read(mapperresponse); + + // the value here will be the service name + return mapperresponse.cbegin()->first; +} + void removeCriticalAssociation(sdbusplus::bus::bus& bus, const std::string& objectPath, const std::string& service) diff --git a/remove_association.hpp b/remove_association.hpp index 1373b0c..bfbe90f 100644 --- a/remove_association.hpp +++ b/remove_association.hpp @@ -62,6 +62,14 @@ void removeCriticalAssociation(sdbusplus::bus::bus& bus, const std::string& objectPath, const std::string& service); +/** @brief get Dbus service + * + * @param[in] path - The D-Bus object path + * @param[in] interface - The DBus interface. + */ +const std::string getService(const std::string& path, + const std::string& interface); + } // namespace manager } // namespace inventory } // namespace phosphor