From 3c6f29a0d0c89186e5f8fe1dfb12f76a6e448b28 Mon Sep 17 00:00:00 2001 From: Dhruvaraj Subhashchandran Date: Thu, 20 Apr 2017 09:47:28 -0500 Subject: Implement led assert and deassert based on faults Change-Id: I28378b155da15282b1b5bf0403075b55bda5b70d Signed-off-by: Dhruvaraj Subhashchandran --- configure.ac | 6 + elog-errors.hpp | 402 ++++++++++++++++++++++ fault-monitor/Makefile.am | 27 +- fault-monitor/fru-fault-monitor.cpp | 196 ++++++++++- xyz/openbmc_project/Led/Fru/Monitor.errors.yaml | 7 + xyz/openbmc_project/Led/Fru/Monitor.metadata.yaml | 9 + xyz/openbmc_project/Led/Mapper.errors.yaml | 9 + xyz/openbmc_project/Led/Mapper.metadata.yaml | 17 + 8 files changed, 671 insertions(+), 2 deletions(-) create mode 100644 elog-errors.hpp create mode 100644 xyz/openbmc_project/Led/Fru/Monitor.errors.yaml create mode 100644 xyz/openbmc_project/Led/Fru/Monitor.metadata.yaml create mode 100644 xyz/openbmc_project/Led/Mapper.errors.yaml create mode 100644 xyz/openbmc_project/Led/Mapper.metadata.yaml diff --git a/configure.ac b/configure.ac index c0fc04a..ba1a152 100644 --- a/configure.ac +++ b/configure.ac @@ -45,6 +45,10 @@ PKG_CHECK_MODULES([SDBUSPLUS], [sdbusplus],, [AC_MSG_ERROR([Could not find sdbus PKG_CHECK_MODULES([PHOSPHOR_LOGGING], [phosphor-logging],, [AC_MSG_ERROR([Could not find phosphor-logging...openbmc/phosphor-logging package required])]) PKG_CHECK_MODULES([PHOSPHOR_DBUS_INTERFACES], [phosphor-dbus-interfaces],, [AC_MSG_ERROR([Could not find phosphor-dbus-interfaces...openbmc/phosphor-dbus-interfaces package required])]) +# Check for sdbus++ tool +AC_PATH_PROG([SDBUSPLUSPLUS], [sdbus++]) +AS_IF([test "x$SDBUSPLUSPLUS" == "x"], AC_MSG_ERROR([Cannot find sdbus++])) + # Dbus service name AC_ARG_VAR(BUSNAME, [The Dbus busname to own]) AS_IF([test "x$BUSNAME" == "x"], [BUSNAME="xyz.openbmc_project.LED.GroupManager"]) @@ -63,6 +67,8 @@ AC_SUBST(LEDGEN) AC_DEFINE(CALLOUT_FWD_ASSOCIATION, "callout", [The name of the callout's forward association.]) AC_DEFINE(CALLOUT_REV_ASSOCIATION, "fault", [The name of the callout's reverse association.]) +AC_DEFINE(ELOG_ENTRY, "entry", [Path element indicates an error log entry under logging namespace.]) +AC_DEFINE(LED_FAULT, "fault", [Path element to indicates a fault led under led groups.]) # Create configured output AC_CONFIG_FILES([Makefile test/Makefile fault-monitor/Makefile]) diff --git a/elog-errors.hpp b/elog-errors.hpp new file mode 100644 index 0000000..1cc6f4a --- /dev/null +++ b/elog-errors.hpp @@ -0,0 +1,402 @@ +// This file was autogenerated. Do not edit! +// See elog-gen.py for more details +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace sdbusplus +{ +namespace xyz +{ +namespace openbmc_project +{ +namespace Led +{ +namespace Fru +{ +namespace Monitor +{ +namespace Error +{ + struct AssociationRetrieveError; +} // namespace Error +} // namespace Monitor +} // namespace Fru +} // namespace Led +} // namespace openbmc_project +} // namespace xyz +} // namespace sdbusplus + +namespace sdbusplus +{ +namespace xyz +{ +namespace openbmc_project +{ +namespace Led +{ +namespace Fru +{ +namespace Monitor +{ +namespace Error +{ + struct InventoryPathError; +} // namespace Error +} // namespace Monitor +} // namespace Fru +} // namespace Led +} // namespace openbmc_project +} // namespace xyz +} // namespace sdbusplus + +namespace sdbusplus +{ +namespace xyz +{ +namespace openbmc_project +{ +namespace Led +{ +namespace Mapper +{ +namespace Error +{ + struct ObjectNotFoundError; +} // namespace Error +} // namespace Mapper +} // namespace Led +} // namespace openbmc_project +} // namespace xyz +} // namespace sdbusplus + +namespace sdbusplus +{ +namespace xyz +{ +namespace openbmc_project +{ +namespace Led +{ +namespace Mapper +{ +namespace Error +{ + struct MethodError; +} // namespace Error +} // namespace Mapper +} // namespace Led +} // namespace openbmc_project +} // namespace xyz +} // namespace sdbusplus + + +namespace phosphor +{ + +namespace logging +{ + +namespace xyz +{ +namespace openbmc_project +{ +namespace Led +{ +namespace Fru +{ +namespace Monitor +{ +namespace _InventoryPathError +{ + +struct PATH +{ + static constexpr auto str = "PATH=%s"; + static constexpr auto str_short = "PATH"; + using type = std::tuple,const char*>; + explicit constexpr PATH(const char* a) : _entry(entry(str, a)) {}; + type _entry; +}; + +} // namespace _InventoryPathError + +struct InventoryPathError : public sdbusplus::exception_t +{ + static constexpr auto errName = "xyz.openbmc_project.Led.Fru.Monitor.InventoryPathError"; + static constexpr auto errDesc = "Invalid Inventory Path."; + static constexpr auto L = level::INFO; + using PATH = _InventoryPathError::PATH; + using metadata_types = std::tuple; + + const char* name() const noexcept + { + return errName; + } + + const char* description() const noexcept + { + return errDesc; + } + + const char* what() const noexcept + { + return errName; + } +}; + +} // namespace Monitor +} // namespace Fru +} // namespace Led +} // namespace openbmc_project +} // namespace xyz + + +namespace details +{ + +template <> +struct map_exception_type +{ + using type = xyz::openbmc_project::Led::Fru::Monitor::InventoryPathError; +}; + +} + +namespace xyz +{ +namespace openbmc_project +{ +namespace Led +{ +namespace Fru +{ +namespace Monitor +{ +namespace _AssociationRetrieveError +{ + +struct ELOG_ENTRY_PATH +{ + static constexpr auto str = "ELOG_ENTRY_PATH=%s"; + static constexpr auto str_short = "ELOG_ENTRY_PATH"; + using type = std::tuple,const char*>; + explicit constexpr ELOG_ENTRY_PATH(const char* a) : _entry(entry(str, a)) {}; + type _entry; +}; + +} // namespace _AssociationRetrieveError + +struct AssociationRetrieveError : public sdbusplus::exception_t +{ + static constexpr auto errName = "xyz.openbmc_project.Led.Fru.Monitor.AssociationRetrieveError"; + static constexpr auto errDesc = "Error in retrieving the associations from elog entry."; + static constexpr auto L = level::INFO; + using ELOG_ENTRY_PATH = _AssociationRetrieveError::ELOG_ENTRY_PATH; + using metadata_types = std::tuple; + + const char* name() const noexcept + { + return errName; + } + + const char* description() const noexcept + { + return errDesc; + } + + const char* what() const noexcept + { + return errName; + } +}; + +} // namespace Monitor +} // namespace Fru +} // namespace Led +} // namespace openbmc_project +} // namespace xyz + + +namespace details +{ + +template <> +struct map_exception_type +{ + using type = xyz::openbmc_project::Led::Fru::Monitor::AssociationRetrieveError; +}; + +} + +namespace xyz +{ +namespace openbmc_project +{ +namespace Led +{ +namespace Mapper +{ +namespace _MethodError +{ + +struct METHOD_NAME +{ + static constexpr auto str = "METHOD_NAME=%s"; + static constexpr auto str_short = "METHOD_NAME"; + using type = std::tuple,const char*>; + explicit constexpr METHOD_NAME(const char* a) : _entry(entry(str, a)) {}; + type _entry; +}; +struct PATH +{ + static constexpr auto str = "PATH=%s"; + static constexpr auto str_short = "PATH"; + using type = std::tuple,const char*>; + explicit constexpr PATH(const char* a) : _entry(entry(str, a)) {}; + type _entry; +}; +struct INTERFACE +{ + static constexpr auto str = "INTERFACE=%s"; + static constexpr auto str_short = "INTERFACE"; + using type = std::tuple,const char*>; + explicit constexpr INTERFACE(const char* a) : _entry(entry(str, a)) {}; + type _entry; +}; + +} // namespace _MethodError + +struct MethodError : public sdbusplus::exception_t +{ + static constexpr auto errName = "xyz.openbmc_project.Led.Mapper.MethodError"; + static constexpr auto errDesc = "Failed to invoke ObjectMapper method"; + static constexpr auto L = level::INFO; + using METHOD_NAME = _MethodError::METHOD_NAME; + using PATH = _MethodError::PATH; + using INTERFACE = _MethodError::INTERFACE; + using metadata_types = std::tuple; + + const char* name() const noexcept + { + return errName; + } + + const char* description() const noexcept + { + return errDesc; + } + + const char* what() const noexcept + { + return errName; + } +}; + +} // namespace Mapper +} // namespace Led +} // namespace openbmc_project +} // namespace xyz + + +namespace details +{ + +template <> +struct map_exception_type +{ + using type = xyz::openbmc_project::Led::Mapper::MethodError; +}; + +} + +namespace xyz +{ +namespace openbmc_project +{ +namespace Led +{ +namespace Mapper +{ +namespace _ObjectNotFoundError +{ + +struct METHOD_NAME +{ + static constexpr auto str = "METHOD_NAME=%s"; + static constexpr auto str_short = "METHOD_NAME"; + using type = std::tuple,const char*>; + explicit constexpr METHOD_NAME(const char* a) : _entry(entry(str, a)) {}; + type _entry; +}; +struct PATH +{ + static constexpr auto str = "PATH=%s"; + static constexpr auto str_short = "PATH"; + using type = std::tuple,const char*>; + explicit constexpr PATH(const char* a) : _entry(entry(str, a)) {}; + type _entry; +}; +struct INTERFACE +{ + static constexpr auto str = "INTERFACE=%s"; + static constexpr auto str_short = "INTERFACE"; + using type = std::tuple,const char*>; + explicit constexpr INTERFACE(const char* a) : _entry(entry(str, a)) {}; + type _entry; +}; + +} // namespace _ObjectNotFoundError + +struct ObjectNotFoundError : public sdbusplus::exception_t +{ + static constexpr auto errName = "xyz.openbmc_project.Led.Mapper.ObjectNotFoundError"; + static constexpr auto errDesc = "Failed to get response from the method."; + static constexpr auto L = level::INFO; + using METHOD_NAME = _ObjectNotFoundError::METHOD_NAME; + using PATH = _ObjectNotFoundError::PATH; + using INTERFACE = _ObjectNotFoundError::INTERFACE; + using metadata_types = std::tuple; + + const char* name() const noexcept + { + return errName; + } + + const char* description() const noexcept + { + return errDesc; + } + + const char* what() const noexcept + { + return errName; + } +}; + +} // namespace Mapper +} // namespace Led +} // namespace openbmc_project +} // namespace xyz + + +namespace details +{ + +template <> +struct map_exception_type +{ + using type = xyz::openbmc_project::Led::Mapper::ObjectNotFoundError; +}; + +} + + +} // namespace logging + +} // namespace phosphor diff --git a/fault-monitor/Makefile.am b/fault-monitor/Makefile.am index ba7603f..044b638 100644 --- a/fault-monitor/Makefile.am +++ b/fault-monitor/Makefile.am @@ -7,7 +7,16 @@ sbin_PROGRAMS = phosphor-fru-fault-monitor phosphor_fru_fault_monitor_SOURCES = \ fru-fault-monitor.cpp \ - monitor-main.cpp + monitor-main.cpp \ + xyz/openbmc_project/Led/Mapper/error.cpp \ + xyz/openbmc_project/Led/Fru/Monitor/error.cpp + +BUILT_SOURCES = xyz/openbmc_project/Led/Mapper/error.hpp \ + xyz/openbmc_project/Led/Mapper/error.cpp \ + xyz/openbmc_project/Led/Fru/Monitor/error.hpp \ + xyz/openbmc_project/Led/Fru/Monitor/error.cpp + +CLEANFILES = ${BUILT_SOURCES} phosphor_fru_fault_monitor_LDFLAGS = $(SDBUSPLUS_LIBS) \ $(PHOSPHOR_LOGGING_LIBS) \ @@ -15,3 +24,19 @@ phosphor_fru_fault_monitor_LDFLAGS = $(SDBUSPLUS_LIBS) \ phosphor_fru_fault_monitor_CFLAGS = $(SDBUSPLUS_CFLAGS) \ $(PHOSPHOR_LOGGING_CFLAGS) \ $(PHOSPHOR_DBUS_INTERFACES_CFLAGS) + +xyz/openbmc_project/Led/Mapper/error.hpp: ${top_srcdir}/xyz/openbmc_project/Led/Mapper.errors.yaml + @mkdir -p `dirname $@` + $(SDBUSPLUSPLUS) -r $(top_srcdir) error exception-header xyz.openbmc_project.Led.Mapper > $@ + +xyz/openbmc_project/Led/Mapper/error.cpp: ${top_srcdir}/xyz/openbmc_project/Led/Mapper.errors.yaml + @mkdir -p `dirname $@` + $(SDBUSPLUSPLUS) -r $(top_srcdir) error exception-cpp xyz.openbmc_project.Led.Mapper > $@ + +xyz/openbmc_project/Led/Fru/Monitor/error.hpp: ${top_srcdir}/xyz/openbmc_project/Led/Fru/Monitor.errors.yaml + @mkdir -p `dirname $@` + $(SDBUSPLUSPLUS) -r $(top_srcdir) error exception-header xyz.openbmc_project.Led.Fru.Monitor > $@ + +xyz/openbmc_project/Led/Fru/Monitor/error.cpp: ${top_srcdir}/xyz/openbmc_project/Led/Fru/Monitor.errors.yaml + @mkdir -p `dirname $@` + $(SDBUSPLUSPLUS) -r $(top_srcdir) error exception-cpp xyz.openbmc_project.Led.Fru.Monitor > $@ diff --git a/fault-monitor/fru-fault-monitor.cpp b/fault-monitor/fru-fault-monitor.cpp index 1213128..e21727b 100644 --- a/fault-monitor/fru-fault-monitor.cpp +++ b/fault-monitor/fru-fault-monitor.cpp @@ -1,4 +1,9 @@ +#include +#include "xyz/openbmc_project/Led/Fru/Monitor/error.hpp" +#include "xyz/openbmc_project/Led/Mapper/error.hpp" +#include "elog-errors.hpp" #include "fru-fault-monitor.hpp" + namespace phosphor { namespace led @@ -10,10 +15,105 @@ namespace fault namespace monitor { +using namespace phosphor::logging; + +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"; +constexpr auto OBJMGR_IFACE = "org.freedesktop.DBus.ObjectManager"; +constexpr auto LED_GROUPS = "/xyz/openbmc_project/led/groups/"; +constexpr auto LOG_PATH = "/xyz/openbmc_project/logging"; + +using AssociationList = std::vector>; +using MethodErr = + sdbusplus::xyz::openbmc_project::Led::Mapper::Error::MethodError; +using ObjectNotFoundErr = + sdbusplus::xyz::openbmc_project::Led::Mapper::Error::ObjectNotFoundError; +using AssociationRetrieveErr = + sdbusplus::xyz::openbmc_project:: + Led::Fru::Monitor::Error::AssociationRetrieveError; +using InventoryPathErr = + sdbusplus::xyz::openbmc_project:: + Led::Fru::Monitor::Error::InventoryPathError; + +std::string getService(sdbusplus::bus::bus& bus, + const std::string& path) +{ + auto mapper = bus.new_method_call(MAPPER_BUSNAME, + MAPPER_OBJ_PATH, + MAPPER_IFACE, "GetObject"); + mapper.append(path.c_str(), std::vector({OBJMGR_IFACE})); + auto mapperResponseMsg = bus.call(mapper); + if (mapperResponseMsg.is_method_error()) + { + using namespace xyz::openbmc_project::Led::Mapper; + elog( + MethodError::METHOD_NAME("GetObject"), + MethodError::PATH(path.c_str()), + MethodError::INTERFACE( + OBJMGR_IFACE)); + } + + std::map> mapperResponse; + mapperResponseMsg.read(mapperResponse); + if (mapperResponse.empty()) + { + using namespace xyz::openbmc_project::Led::Mapper; + elog( + ObjectNotFoundError::METHOD_NAME("GetObject"), + ObjectNotFoundError::PATH(path.c_str()), + ObjectNotFoundError::INTERFACE( + OBJMGR_IFACE)); + } + + return mapperResponse.cbegin()->first; +} + void action(sdbusplus::bus::bus& bus, - const std::string& unit, + const std::string& path, bool assert) { + std::string service; + try + { + service = getService(bus, LED_GROUPS); + } + catch (MethodErr& e) + { + commit(); + return; + } + catch (ObjectNotFoundErr& e) + { + commit(); + return; + } + + auto pos = path.rfind("/"); + if (pos == std::string::npos) + { + using namespace xyz::openbmc_project::Led::Fru::Monitor; + report( + InventoryPathError::PATH( + path.c_str())); + return; + } + auto unit = path.substr(pos + 1); + + std::string ledPath = LED_GROUPS + + unit + '_' + LED_FAULT; + + auto method = bus.new_method_call(service.c_str(), + ledPath.c_str(), + "org.freedesktop.DBus.Properties", + "Set"); + method.append("xyz.openbmc_project.Led.Group"); + method.append("Asserted"); + + method.append(sdbusplus::message::variant(assert)); + bus.call_noreply(method); + return; } @@ -21,6 +121,72 @@ int Add::created(sd_bus_message* msg, void* data, sd_bus_error* retError) { + auto m = sdbusplus::message::message(msg); + auto bus = m.get_bus(); + + sdbusplus::message::object_path obPath; + m.read(obPath); + std::string objectPath(std::move(obPath)); + + std::size_t found = objectPath.find(ELOG_ENTRY); + if (found == std::string::npos) + { + //Not a new error entry skip + return 0; + } + + std::string service; + try + { + service = getService(bus, LOG_PATH); + } + catch (MethodErr& e) + { + commit(); + return 0; + } + catch (ObjectNotFoundErr& e) + { + commit(); + return 0; + } + + auto method = bus.new_method_call(service.c_str(), objectPath.c_str(), + "org.freedesktop.DBus.Properties", + "Get"); + + method.append("org.openbmc.Associations"); + method.append("associations"); + auto reply = bus.call(method); + if (reply.is_method_error()) + { + using namespace xyz::openbmc_project::Led::Fru::Monitor; + report( + AssociationRetrieveError::ELOG_ENTRY_PATH( + objectPath.c_str())); + return 0; + } + + sdbusplus::message::variant assoc; + reply.read(assoc); + + auto assocs = + sdbusplus::message::variant_ns::get(assoc); + if (assocs.empty()) + { + //No associations skip + return 0; + } + + for (const auto& item : assocs) + { + if (std::get<1>(item).compare(CALLOUT_REV_ASSOCIATION) == 0) + { + action(bus, std::get<2>(item), true); + static_cast(data)->removeWatches.emplace_back( + std::make_unique(bus, std::get<2>(item))); + } + } return 0; } @@ -28,6 +194,34 @@ int Remove::removed(sd_bus_message* msg, void* data, sd_bus_error* retError) { + auto m = sdbusplus::message::message(msg); + auto bus = m.get_bus(); + std::string assoc; + m.read(assoc); + + if (assoc.compare("org.openbmc.Association")) + { + //Skip if not about association + return 0; + } + + std::map> endPoints; + m.read(endPoints); + auto it = endPoints.find("endpoints"); + + if (it == endPoints.end()) + { + //No end points,skip + return 0; + } + + if (!((*it).second.empty())) + { + //Skip, end points are not empty + return 0; + } + + action(bus, static_cast(data)->inventoryPath, false); return 0; } diff --git a/xyz/openbmc_project/Led/Fru/Monitor.errors.yaml b/xyz/openbmc_project/Led/Fru/Monitor.errors.yaml new file mode 100644 index 0000000..bb77f45 --- /dev/null +++ b/xyz/openbmc_project/Led/Fru/Monitor.errors.yaml @@ -0,0 +1,7 @@ +#xyz.openbmc_project.Led.Fru.Monitor.InventoryPathError +- name: InventoryPathError + description: Invalid Inventory Path. + +#xyz.openbmc_project.Led.Fru.Monitor.AssociationRetrieveError +- name: AssociationRetrieveError + description: Error in retrieving the associations from elog entry. diff --git a/xyz/openbmc_project/Led/Fru/Monitor.metadata.yaml b/xyz/openbmc_project/Led/Fru/Monitor.metadata.yaml new file mode 100644 index 0000000..bd59e5f --- /dev/null +++ b/xyz/openbmc_project/Led/Fru/Monitor.metadata.yaml @@ -0,0 +1,9 @@ +- name: InventoryPathError + meta: + - str: "PATH=%s" + type: string + +- name: AssociationRetrieveError + meta: + - str: "ELOG_ENTRY_PATH=%s" + type: string diff --git a/xyz/openbmc_project/Led/Mapper.errors.yaml b/xyz/openbmc_project/Led/Mapper.errors.yaml new file mode 100644 index 0000000..c1cbd0f --- /dev/null +++ b/xyz/openbmc_project/Led/Mapper.errors.yaml @@ -0,0 +1,9 @@ +#xyz.openbmc_project.Led.Mapper.MethodError +- name: MethodError + description: Failed to invoke ObjectMapper method + +#xyz.openbmc_project.Led.Mapper.ObjectNotFoundError +- name: ObjectNotFoundError + description: Failed to get response from the method. + + diff --git a/xyz/openbmc_project/Led/Mapper.metadata.yaml b/xyz/openbmc_project/Led/Mapper.metadata.yaml new file mode 100644 index 0000000..0eb5c7f --- /dev/null +++ b/xyz/openbmc_project/Led/Mapper.metadata.yaml @@ -0,0 +1,17 @@ +- name: MethodError + meta: + - str: "METHOD_NAME=%s" + type: string + - str: "PATH=%s" + type: string + - str: "INTERFACE=%s" + type: string + +- name: ObjectNotFoundError + meta: + - str: "METHOD_NAME=%s" + type: string + - str: "PATH=%s" + type: string + - str: "INTERFACE=%s" + type: string -- cgit v1.2.1