Add DateTime & Offset in Managers & LogServices

This commit adds the support for "DateTimeLocalOffset" property under
"/redfish/v1/Managers/bmc/" Redfish URI.
And it also adds the support for "DateTime" & "DateTimeLocalOffset"
properties under "/redfish/v1/Systems/system/LogServices/<id>/" &
"/redfish/v1/Managers/bmc/LogServices/<id>/" Redfish URI's.

These properties shows the current Date, Time & the UTC offset that the
current DateTime property value contains.

Tested:

- Redfish Validator Test passed.

curl -k -H "X-Auth-Token: $token" -H "Content-Type: application/json" -X GET https://${bmc}/redfish/v1/Managers/bmc/
{
"@odata.id": "/redfish/v1/Managers/bmc",
"@odata.type": "#Manager.v1_11_0.Manager",
"Actions": {
"#Manager.Reset": {
"@Redfish.ActionInfo": "/redfish/v1/Managers/bmc/ResetActionInfo",
"target": "/redfish/v1/Managers/bmc/Actions/Manager.Reset"
},
"#Manager.ResetToDefaults": {
"ResetType@Redfish.AllowableValues": [
"ResetAll"
],
"target": "/redfish/v1/Managers/bmc/Actions/Manager.ResetToDefaults"
}
},
"DateTime": "2021-06-04T12:18:28+00:00",
"DateTimeLocalOffset": "+00:00",
"Description": "Baseboard Management Controller",
"EthernetInterfaces": {
"@odata.id": "/redfish/v1/Managers/bmc/EthernetInterfaces"
},
"FirmwareVersion": "2.11.0-dev-114-gc1989599d",
"GraphicalConsole": {
"ConnectTypesSupported": [
"KVMIP"
],
"MaxConcurrentSessions": 4,
"ServiceEnabled": true
},
"Id": "bmc",
"LastResetTime": "2021-06-04T12:07:02+00:00",
"Links": {
"ActiveSoftwareImage": {
"@odata.id": "/redfish/v1/UpdateService/FirmwareInventory/419c86fb"
},
"ManagerForServers": [
{
"@odata.id": "/redfish/v1/Systems/system"
}
],
"ManagerForServers@odata.count": 1,
"SoftwareImages": [
{
"@odata.id": "/redfish/v1/UpdateService/FirmwareInventory/419c86fb"
}
],
"SoftwareImages@odata.count": 1
},
"LogServices": {
"@odata.id": "/redfish/v1/Managers/bmc/LogServices"
},
"ManagerType": "BMC",
"Model": "OpenBmc",
"Name": "OpenBmc Manager",
"NetworkProtocol": {
"@odata.id": "/redfish/v1/Managers/bmc/NetworkProtocol"
},
"Oem": {
"@odata.id": "/redfish/v1/Managers/bmc#/Oem",
"@odata.type": "#OemManager.Oem",
"OpenBmc": {
"@odata.id": "/redfish/v1/Managers/bmc#/Oem/OpenBmc",
"@odata.type": "#OemManager.OpenBmc",
"Certificates": {
"@odata.id": "/redfish/v1/Managers/bmc/Truststore/Certificates"
}
}
},
"PowerState": "On",
"SerialConsole": {
"ConnectTypesSupported": [
"IPMI",
"SSH"
],
"MaxConcurrentSessions": 15,
"ServiceEnabled": true
},
"ServiceEntryPointUUID": "1832ebbb-0b54-44e9-90d7-b49108f6863c",
"Status": {
"Health": "OK",
"HealthRollup": "OK",
"State": "Enabled"
},
"UUID": "7fe3d13d-4ae7-4a4f-add1-2d60308124b4"
}

curl -k -H "X-Auth-Token: $token" -H "Content-Type: application/json" -X GET https://${bmc}/redfish/v1/Systems/system/LogServices/EventLog/
{
"@odata.id": "/redfish/v1/Systems/system/LogServices/EventLog",
"@odata.type": "#LogService.v1_1_0.LogService",
"Actions": {
"#LogService.ClearLog": {
"target": "/redfish/v1/Systems/system/LogServices/EventLog/Actions/LogService.ClearLog"
}
},
"DateTime": "2021-06-04T12:11:10+00:00",
"DateTimeLocalOffset": "+00:00",
"Description": "System Event Log Service",
"Entries": {
"@odata.id": "/redfish/v1/Systems/system/LogServices/EventLog/Entries"
},
"Id": "EventLog",
"Name": "Event Log Service",
"OverWritePolicy": "WrapsWhenFull"
}

Signed-off-by: Tejas Patil <tejaspp@ami.com>
Change-Id: I416d13ae11e236cf4552f817a9bd69b48f9b5afb
diff --git a/Redfish.md b/Redfish.md
index 103a22e..9970240 100644
--- a/Redfish.md
+++ b/Redfish.md
@@ -313,6 +313,7 @@
 ##### Manager
 - Actions
 - DateTime
+- DateTimeLocalOffset
 - Description
 - EthernetInterfaces
 - FirmwareVersion
@@ -553,6 +554,8 @@
 #### /redfish/v1/Systems/system/LogServices/EventLog/
 ##### LogService
 - Actions
+- DateTime
+- DateTimeLocalOffset
 - Description
 - Entries
 - OverWritePolicy
@@ -698,6 +701,7 @@
 - FirmwareInventory
 - HttpPushUri
 - HttpPushUriOptions
+- MaxImageSizeBytes
 - ServiceEnabled
 
 #### /redfish/v1/UpdateService/FirmwareInventory/
diff --git a/http/utility.hpp b/http/utility.hpp
index 19ffe9f..6f81be8 100644
--- a/http/utility.hpp
+++ b/http/utility.hpp
@@ -594,10 +594,32 @@
     return redfishDateTime;
 }
 
-inline std::string dateTimeNow()
+/**
+ * Returns the current Date, Time & the local Time Offset
+ * infromation in a pair
+ *
+ * @param[in] None
+ *
+ * @return std::pair<std::string, std::string>, which consist
+ * of current DateTime & the TimeOffset strings respectively.
+ */
+inline std::pair<std::string, std::string> getDateTimeOffsetNow()
 {
     std::time_t time = std::time(nullptr);
-    return getDateTime(time);
+    std::string dateTime = getDateTime(time);
+
+    /* extract the local Time Offset value from the
+     * recevied dateTime string.
+     */
+    std::string timeOffset("Z00:00");
+    std::size_t lastPos = dateTime.size();
+    std::size_t len = timeOffset.size();
+    if (lastPos > len)
+    {
+        timeOffset = dateTime.substr(lastPos - len);
+    }
+
+    return std::make_pair(dateTime, timeOffset);
 }
 
 inline bool constantTimeStringCompare(const std::string_view a,
diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp
index 11190ef..de40356 100644
--- a/redfish-core/include/event_service_manager.hpp
+++ b/redfish-core/include/event_service_manager.hpp
@@ -439,14 +439,15 @@
         logEntryArray.push_back({});
         nlohmann::json& logEntryJson = logEntryArray.back();
 
-        logEntryJson = {{"EventId", "TestID"},
-                        {"EventType", "Event"},
-                        {"Severity", "OK"},
-                        {"Message", "Generated test event"},
-                        {"MessageId", "OpenBMC.0.2.TestEventLog"},
-                        {"MessageArgs", nlohmann::json::array()},
-                        {"EventTimestamp", crow::utility::dateTimeNow()},
-                        {"Context", customText}};
+        logEntryJson = {
+            {"EventId", "TestID"},
+            {"EventType", "Event"},
+            {"Severity", "OK"},
+            {"Message", "Generated test event"},
+            {"MessageId", "OpenBMC.0.2.TestEventLog"},
+            {"MessageArgs", nlohmann::json::array()},
+            {"EventTimestamp", crow::utility::getDateTimeOffsetNow().first},
+            {"Context", customText}};
 
         nlohmann::json msg = {{"@odata.type", "#Event.v1_4_0.Event"},
                               {"Id", std::to_string(eventSeqNum)},
@@ -1060,7 +1061,7 @@
         nlohmann::json event = {
             {"EventId", eventId},
             {"MemberId", memberId},
-            {"EventTimestamp", crow::utility::dateTimeNow()},
+            {"EventTimestamp", crow::utility::getDateTimeOffsetNow().first},
             {"OriginOfCondition", origin}};
         for (nlohmann::json::iterator it = event.begin(); it != event.end();
              ++it)
@@ -1116,7 +1117,7 @@
         {
             std::shared_ptr<Subscription> entry = it.second;
             nlohmann::json msgJson = {
-                {"Timestamp", crow::utility::dateTimeNow()},
+                {"Timestamp", crow::utility::getDateTimeOffsetNow().first},
                 {"OriginOfCondition", "/ibm/v1/HMC/BroadcastService"},
                 {"Name", "Broadcast Message"},
                 {"Message", broadcastMsg}};
diff --git a/redfish-core/lib/log_services.hpp b/redfish-core/lib/log_services.hpp
index 2b06414..2800e86 100644
--- a/redfish-core/lib/log_services.hpp
+++ b/redfish-core/lib/log_services.hpp
@@ -995,6 +995,14 @@
                 "System Event Log Service";
             asyncResp->res.jsonValue["Id"] = "EventLog";
             asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";
+
+            std::pair<std::string, std::string> redfishDateTimeOffset =
+                crow::utility::getDateTimeOffsetNow();
+
+            asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
+            asyncResp->res.jsonValue["DateTimeLocalOffset"] =
+                redfishDateTimeOffset.second;
+
             asyncResp->res.jsonValue["Entries"] = {
                 {"@odata.id",
                  "/redfish/v1/Systems/system/LogServices/EventLog/Entries"}};
@@ -1830,6 +1838,14 @@
                     "BMC Journal Log Service";
                 asyncResp->res.jsonValue["Id"] = "BMC Journal";
                 asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";
+
+                std::pair<std::string, std::string> redfishDateTimeOffset =
+                    crow::utility::getDateTimeOffsetNow();
+                asyncResp->res.jsonValue["DateTime"] =
+                    redfishDateTimeOffset.first;
+                asyncResp->res.jsonValue["DateTimeLocalOffset"] =
+                    redfishDateTimeOffset.second;
+
                 asyncResp->res.jsonValue["Entries"] = {
                     {"@odata.id",
                      "/redfish/v1/Managers/bmc/LogServices/Journal/Entries"}};
@@ -2071,6 +2087,14 @@
                 asyncResp->res.jsonValue["Description"] = "BMC Dump LogService";
                 asyncResp->res.jsonValue["Id"] = "Dump";
                 asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";
+
+                std::pair<std::string, std::string> redfishDateTimeOffset =
+                    crow::utility::getDateTimeOffsetNow();
+                asyncResp->res.jsonValue["DateTime"] =
+                    redfishDateTimeOffset.first;
+                asyncResp->res.jsonValue["DateTimeLocalOffset"] =
+                    redfishDateTimeOffset.second;
+
                 asyncResp->res.jsonValue["Entries"] = {
                     {"@odata.id",
                      "/redfish/v1/Managers/bmc/LogServices/Dump/Entries"}};
@@ -2174,6 +2198,14 @@
                     "System Dump LogService";
                 asyncResp->res.jsonValue["Id"] = "Dump";
                 asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";
+
+                std::pair<std::string, std::string> redfishDateTimeOffset =
+                    crow::utility::getDateTimeOffsetNow();
+                asyncResp->res.jsonValue["DateTime"] =
+                    redfishDateTimeOffset.first;
+                asyncResp->res.jsonValue["DateTimeLocalOffset"] =
+                    redfishDateTimeOffset.second;
+
                 asyncResp->res.jsonValue["Entries"] = {
                     {"@odata.id",
                      "/redfish/v1/Systems/system/LogServices/Dump/Entries"}};
@@ -2285,6 +2317,13 @@
             asyncResp->res.jsonValue["Id"] = "Oem Crashdump";
             asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";
             asyncResp->res.jsonValue["MaxNumberOfRecords"] = 3;
+
+            std::pair<std::string, std::string> redfishDateTimeOffset =
+                crow::utility::getDateTimeOffsetNow();
+            asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
+            asyncResp->res.jsonValue["DateTimeLocalOffset"] =
+                redfishDateTimeOffset.second;
+
             asyncResp->res.jsonValue["Entries"] = {
                 {"@odata.id",
                  "/redfish/v1/Systems/system/LogServices/Crashdump/Entries"}};
@@ -2730,6 +2769,14 @@
                     {"Entries",
                      {{"@odata.id", "/redfish/v1/Systems/system/LogServices/"
                                     "PostCodes/Entries"}}}};
+
+                std::pair<std::string, std::string> redfishDateTimeOffset =
+                    crow::utility::getDateTimeOffsetNow();
+                asyncResp->res.jsonValue["DateTime"] =
+                    redfishDateTimeOffset.first;
+                asyncResp->res.jsonValue["DateTimeLocalOffset"] =
+                    redfishDateTimeOffset.second;
+
                 asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"] = {
                     {"target",
                      "/redfish/v1/Systems/system/LogServices/PostCodes/"
diff --git a/redfish-core/lib/managers.hpp b/redfish-core/lib/managers.hpp
index b286f19..c6e6019 100644
--- a/redfish-core/lib/managers.hpp
+++ b/redfish-core/lib/managers.hpp
@@ -1987,7 +1987,12 @@
                 "/redfish/v1/Managers/bmc/Actions/Manager.ResetToDefaults";
             resetToDefaults["ResetType@Redfish.AllowableValues"] = {"ResetAll"};
 
-            asyncResp->res.jsonValue["DateTime"] = crow::utility::dateTimeNow();
+            std::pair<std::string, std::string> redfishDateTimeOffset =
+                crow::utility::getDateTimeOffsetNow();
+
+            asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
+            asyncResp->res.jsonValue["DateTimeLocalOffset"] =
+                redfishDateTimeOffset.second;
 
             // TODO (Gunnar): Remove these one day since moved to ComputerSystem
             // Still used by OCP profiles
diff --git a/redfish-core/lib/task.hpp b/redfish-core/lib/task.hpp
index 33f983a..bca25a1 100644
--- a/redfish-core/lib/task.hpp
+++ b/redfish-core/lib/task.hpp
@@ -464,7 +464,7 @@
                 asyncResp->res.jsonValue["Name"] = "Task Service";
                 asyncResp->res.jsonValue["Id"] = "TaskService";
                 asyncResp->res.jsonValue["DateTime"] =
-                    crow::utility::dateTimeNow();
+                    crow::utility::getDateTimeOffsetNow().first;
                 asyncResp->res.jsonValue["CompletedTaskOverWritePolicy"] =
                     "Oldest";