Convert a log entry into a SEL record

Check the DBUS logging entry for callout associations, if there
is a mapping between the inventory path and sensor number then
populate the SEL record. Otherwise log a SEL against the sytem
event sensor.

Resolves openbmc/openbmc#1516

Change-Id: I516bdac70cf39260af1744a9cdb118d763009bd5
Signed-off-by: Tom Joseph <tomjoseph@in.ibm.com>
diff --git a/selutility.cpp b/selutility.cpp
index 68226f1..0107515 100644
--- a/selutility.cpp
+++ b/selutility.cpp
@@ -3,6 +3,7 @@
 #include <phosphor-logging/elog-errors.hpp>
 #include "host-ipmid/ipmid-api.h"
 #include "xyz/openbmc_project/Common/error.hpp"
+#include "config.h"
 #include "selutility.hpp"
 #include "types.hpp"
 #include "utils.hpp"
@@ -112,6 +113,75 @@
 
 } // namespace internal
 
+GetSELEntryResponse convertLogEntrytoSEL(const std::string& objPath)
+{
+    sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
+
+    static constexpr auto assocIntf = "org.openbmc.Associations";
+    static constexpr auto assocProp = "associations";
+
+    auto service = ipmi::getService(bus, assocIntf, objPath);
+
+    // Read the Associations interface.
+    auto methodCall = bus.new_method_call(service.c_str(),
+                                          objPath.c_str(),
+                                          propIntf,
+                                          "Get");
+    methodCall.append(assocIntf);
+    methodCall.append(assocProp);
+
+    auto reply = bus.call(methodCall);
+    if (reply.is_method_error())
+    {
+        log<level::ERR>("Error in reading Associations interface");
+        elog<InternalFailure>();
+    }
+
+    using AssociationList = std::vector<std::tuple<
+                            std::string, std::string, std::string>>;
+
+    sdbusplus::message::variant<AssociationList> list;
+    reply.read(list);
+
+    auto& assocs = sdbusplus::message::variant_ns::get<AssociationList>
+         (list);
+
+    /*
+     * Check if the log entry has any callout associations, if there is a
+     * callout association try to match the inventory path to the corresponding
+     * IPMI sensor.
+     */
+    for (const auto& item : assocs)
+    {
+        if (std::get<0>(item).compare(CALLOUT_FWD_ASSOCIATION) == 0)
+        {
+             auto iter = invSensors.find(std::get<2>(item));
+             if (iter == invSensors.end())
+             {
+                 iter = invSensors.find(BOARD_SENSOR);
+                 if (iter == invSensors.end())
+                 {
+                     log<level::ERR>("Motherboard sensor not found");
+                     elog<InternalFailure>();
+                 }
+             }
+
+             return internal::prepareSELEntry(objPath, iter);
+        }
+    }
+
+    // If there are no callout associations link the log entry to system event
+    // sensor
+    auto iter = invSensors.find(SYSTEM_SENSOR);
+    if (iter == invSensors.end())
+    {
+        log<level::ERR>("System event sensor not found");
+        elog<InternalFailure>();
+    }
+
+    return internal::prepareSELEntry(objPath, iter);
+}
+
 } // namespace sel
 
 } // namespace ipmi