Redfish: Add resolution property

This property is used to provide suggestions on how to resolve the
situation that caused the log entry. Services can replace the resolution
defined in the message registry with a more specific resolution in a log
entry.

Tested:
curl command was run with a resolution property set in the d-bus object

curl -k -X GET https://$bmc:18080/redfish/v1/Systems/system/\
                    LogServices/EventLog/Entries
  "Members": [
    {
      "@odata.id":
"/redfish/v1/Systems/system/LogServices/EventLog/Entries/1",
      "@odata.type": "#LogEntry.v1_9_0.LogEntry",
      "AdditionalDataURI":
"/redfish/v1/Systems/system/LogServices/EventLog/Entries/1/attachment",
      "Created": "2022-08-05T18:44:34.201+00:00",
      "EntryType": "Event",
      "Id": "1",
      "Message":
"xyz.openbmc_project.State.Error.CriticalServiceFailure",
      "Modified": "2022-08-05T18:44:34.201+00:00",
      "Name": "System Event Log Entry",
      "Resolution": "1. Priority: High, Procedure: BMC0002\n",
      "Resolved": false,
      "Severity": "Critical"
    },
...
   ]
Signed-off-by: Vijay Lobo <vijaylobo@gmail.com>
Change-Id: Ia28e97c17c1b9bd0e29b681727c3e36563ca7922
Signed-off-by: Shantappa Teekappanavar <shantappa.teekappanavar@ibm.com>
diff --git a/redfish-core/lib/log_services.hpp b/redfish-core/lib/log_services.hpp
index d460794..d4ef1f1 100644
--- a/redfish-core/lib/log_services.hpp
+++ b/redfish-core/lib/log_services.hpp
@@ -496,7 +496,7 @@
                 continue;
             }
 
-            thisEntry["@odata.type"] = "#LogEntry.v1_8_0.LogEntry";
+            thisEntry["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
             thisEntry["@odata.id"] = entriesPath + entryID;
             thisEntry["Id"] = entryID;
             thisEntry["EntryType"] = "Event";
@@ -588,7 +588,7 @@
             }
 
             asyncResp->res.jsonValue["@odata.type"] =
-                "#LogEntry.v1_8_0.LogEntry";
+                "#LogEntry.v1_9_0.LogEntry";
             asyncResp->res.jsonValue["@odata.id"] = entriesPath + entryID;
             asyncResp->res.jsonValue["Id"] = entryID;
             asyncResp->res.jsonValue["EntryType"] = "Event";
@@ -1157,7 +1157,7 @@
     }
 
     // Fill in the log entry with the gathered data
-    logEntryJson["@odata.type"] = "#LogEntry.v1_8_0.LogEntry";
+    logEntryJson["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
     logEntryJson["@odata.id"] =
         "/redfish/v1/Systems/system/LogServices/EventLog/Entries/" + logEntryID;
     logEntryJson["Name"] = "System Event Log Entry";
@@ -1376,6 +1376,7 @@
                 const std::string* severity = nullptr;
                 const std::string* message = nullptr;
                 const std::string* filePath = nullptr;
+                const std::string* resolution = nullptr;
                 bool resolved = false;
                 for (const auto& interfaceMap : objectPath.second)
                 {
@@ -1403,6 +1404,11 @@
                                 severity = std::get_if<std::string>(
                                     &propertyMap.second);
                             }
+                            else if (propertyMap.first == "Resolution")
+                            {
+                                resolution = std::get_if<std::string>(
+                                    &propertyMap.second);
+                            }
                             else if (propertyMap.first == "Message")
                             {
                                 message = std::get_if<std::string>(
@@ -1451,7 +1457,7 @@
                 }
                 entriesArray.push_back({});
                 nlohmann::json& thisEntry = entriesArray.back();
-                thisEntry["@odata.type"] = "#LogEntry.v1_8_0.LogEntry";
+                thisEntry["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
                 thisEntry["@odata.id"] =
                     "/redfish/v1/Systems/system/LogServices/EventLog/Entries/" +
                     std::to_string(*id);
@@ -1459,6 +1465,10 @@
                 thisEntry["Id"] = std::to_string(*id);
                 thisEntry["Message"] = *message;
                 thisEntry["Resolved"] = resolved;
+                if ((resolution != nullptr) && (!(*resolution).empty()))
+                {
+                    thisEntry["Resolution"] = *resolution;
+                }
                 thisEntry["EntryType"] = "Event";
                 thisEntry["Severity"] =
                     translateSeverityDbusToRedfish(*severity);
@@ -1528,13 +1538,14 @@
             const std::string* severity = nullptr;
             const std::string* message = nullptr;
             const std::string* filePath = nullptr;
+            const std::string* resolution = nullptr;
             bool resolved = false;
 
             const bool success = sdbusplus::unpackPropertiesNoThrow(
                 dbus_utils::UnpackErrorPrinter(), resp, "Id", id, "Timestamp",
                 timestamp, "UpdateTimestamp", updateTimestamp, "Severity",
-                severity, "Message", message, "Resolved", resolved, "Path",
-                filePath);
+                severity, "Message", message, "Resolved", resolved,
+                "Resolution", resolution, "Path", filePath);
 
             if (!success)
             {
@@ -1549,7 +1560,7 @@
                 return;
             }
             asyncResp->res.jsonValue["@odata.type"] =
-                "#LogEntry.v1_8_0.LogEntry";
+                "#LogEntry.v1_9_0.LogEntry";
             asyncResp->res.jsonValue["@odata.id"] =
                 "/redfish/v1/Systems/system/LogServices/EventLog/Entries/" +
                 std::to_string(*id);
@@ -1557,6 +1568,10 @@
             asyncResp->res.jsonValue["Id"] = std::to_string(*id);
             asyncResp->res.jsonValue["Message"] = *message;
             asyncResp->res.jsonValue["Resolved"] = resolved;
+            if ((resolution != nullptr) && (!(*resolution).empty()))
+            {
+                asyncResp->res.jsonValue["Resolution"] = *resolution;
+            }
             asyncResp->res.jsonValue["EntryType"] = "Event";
             asyncResp->res.jsonValue["Severity"] =
                 translateSeverityDbusToRedfish(*severity);
@@ -1819,7 +1834,7 @@
                                     nlohmann::json::object_t& logEntryJson)
 {
     // Fill in the log entry with the gathered data.
-    logEntryJson["@odata.type"] = "#LogEntry.v1_4_0.LogEntry";
+    logEntryJson["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
     logEntryJson["@odata.id"] =
         "/redfish/v1/Systems/system/LogServices/HostLogger/Entries/" +
         logEntryID;
@@ -2159,7 +2174,7 @@
     }
 
     // Fill in the log entry with the gathered data
-    bmcJournalLogEntryJson["@odata.type"] = "#LogEntry.v1_8_0.LogEntry";
+    bmcJournalLogEntryJson["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
     bmcJournalLogEntryJson["@odata.id"] =
         "/redfish/v1/Managers/bmc/LogServices/Journal/Entries/" +
         bmcJournalLogEntryID;
@@ -2720,7 +2735,7 @@
             "/redfish/v1/Systems/system/LogServices/Crashdump/Entries/" +
             logID + "/" + filename;
         nlohmann::json::object_t logEntry;
-        logEntry["@odata.type"] = "#LogEntry.v1_7_0.LogEntry";
+        logEntry["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
         logEntry["@odata.id"] =
             "/redfish/v1/Systems/system/LogServices/Crashdump/Entries/" + logID;
         logEntry["Name"] = "CPU Crashdump";
@@ -3272,7 +3287,7 @@
         // add to AsyncResp
         logEntryArray.push_back({});
         nlohmann::json& bmcLogEntry = logEntryArray.back();
-        bmcLogEntry["@odata.type"] = "#LogEntry.v1_8_0.LogEntry";
+        bmcLogEntry["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
         bmcLogEntry["@odata.id"] =
             "/redfish/v1/Systems/system/LogServices/PostCodes/Entries/" +
             postcodeEntryID;
@@ -3587,7 +3602,7 @@
                              << targetID;
         }
 
-        asyncResp->res.jsonValue["@odata.type"] = "#LogEntry.v1_4_0.LogEntry";
+        asyncResp->res.jsonValue["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
         asyncResp->res.jsonValue["@odata.id"] =
             "/redfish/v1/Systems/system/LogServices/PostCodes/Entries";
         asyncResp->res.jsonValue["Name"] = "BIOS POST Code Log Entries";