180 lines
5.8 KiB
Diff
180 lines
5.8 KiB
Diff
|
|
From cfd7bb5a9175a2fa01aa314cace2c3fd0be85d07 Mon Sep 17 00:00:00 2001
|
||
|
|
From: roly <Rolyli.Li@luxshare-ict.com>
|
||
|
|
Date: Tue, 26 Nov 2024 16:49:35 +0800
|
||
|
|
Subject: [PATCH] Support redfish set bmc timezone
|
||
|
|
|
||
|
|
---
|
||
|
|
redfish-core/include/utils/time_utils.hpp | 40 ++++++++++++-
|
||
|
|
redfish-core/lib/managers.hpp | 68 ++++++++++++++++++++++-
|
||
|
|
2 files changed, 105 insertions(+), 3 deletions(-)
|
||
|
|
|
||
|
|
diff --git a/redfish-core/include/utils/time_utils.hpp b/redfish-core/include/utils/time_utils.hpp
|
||
|
|
index 314ea85d..c69eec28 100644
|
||
|
|
--- a/redfish-core/include/utils/time_utils.hpp
|
||
|
|
+++ b/redfish-core/include/utils/time_utils.hpp
|
||
|
|
@@ -13,6 +13,7 @@
|
||
|
|
#include <ratio>
|
||
|
|
#include <string>
|
||
|
|
#include <string_view>
|
||
|
|
+#include <regex>
|
||
|
|
|
||
|
|
// IWYU pragma: no_include <stddef.h>
|
||
|
|
// IWYU pragma: no_include <stdint.h>
|
||
|
|
@@ -284,6 +285,15 @@ std::string toISO8061ExtendedStr(std::chrono::duration<IntType, Period> t)
|
||
|
|
using days = std::chrono::duration<
|
||
|
|
IntType, std::ratio_multiply<hours::period, std::ratio<24>>>;
|
||
|
|
|
||
|
|
+ time_t timep;
|
||
|
|
+ time(&timep);
|
||
|
|
+ struct tm* localTime = localtime(&timep);
|
||
|
|
+ auto validLocalTime = mktime(localTime);
|
||
|
|
+ struct tm* gmTime = gmtime(&timep);
|
||
|
|
+ auto validGmTime = mktime(gmTime);
|
||
|
|
+ auto timeEquation = validLocalTime - validGmTime;
|
||
|
|
+
|
||
|
|
+ t += std::chrono::seconds(timeEquation);
|
||
|
|
// d is days since 1970-01-01
|
||
|
|
days d = std::chrono::duration_cast<days>(t);
|
||
|
|
|
||
|
|
@@ -348,8 +358,9 @@ std::string toISO8061ExtendedStr(std::chrono::duration<IntType, Period> t)
|
||
|
|
MicroDuration subsec = duration_cast<MicroDuration>(t);
|
||
|
|
out += details::padZeros(subsec.count(), 6);
|
||
|
|
}
|
||
|
|
-
|
||
|
|
- out += "+00:00";
|
||
|
|
+ char tzstring[32] = {0};
|
||
|
|
+ std::snprintf(tzstring, sizeof(tzstring), "%+03lld:00", timeEquation/3600);
|
||
|
|
+ out += tzstring;
|
||
|
|
return out;
|
||
|
|
}
|
||
|
|
} // namespace details
|
||
|
|
@@ -445,5 +456,30 @@ inline std::optional<usSinceEpoch> dateStringToEpoch(std::string_view datetime)
|
||
|
|
return std::chrono::duration<uint64_t, std::micro>{durMicroSecs};
|
||
|
|
}
|
||
|
|
|
||
|
|
+inline bool isValidTimeOffset(const std::string& timeOffset) {
|
||
|
|
+ std::regex timeOffsetRegex(R"(^([-+][0-1][0-9]:[0-5][0-9])$)");
|
||
|
|
+
|
||
|
|
+ return std::regex_match(timeOffset, timeOffsetRegex);
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+int convertTimeOffsetToMinutes(const std::string& timeOffset) {
|
||
|
|
+
|
||
|
|
+ if (!isValidTimeOffset(timeOffset)) {
|
||
|
|
+ return -1;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ int hours = std::stoi(timeOffset.substr(1, 2));
|
||
|
|
+ if(hours < -13 || hours > 12)
|
||
|
|
+ {
|
||
|
|
+ return -1;
|
||
|
|
+ }
|
||
|
|
+ int totalMinutes = hours * 60;
|
||
|
|
+
|
||
|
|
+ if (timeOffset[0] == '-') {
|
||
|
|
+ totalMinutes = -totalMinutes;
|
||
|
|
+ }
|
||
|
|
+ return totalMinutes;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
} // namespace time_utils
|
||
|
|
} // namespace redfish
|
||
|
|
diff --git a/redfish-core/lib/managers.hpp b/redfish-core/lib/managers.hpp
|
||
|
|
index a114d440..30395284 100644
|
||
|
|
--- a/redfish-core/lib/managers.hpp
|
||
|
|
+++ b/redfish-core/lib/managers.hpp
|
||
|
|
@@ -1879,6 +1879,67 @@ inline void setDateTime(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
+inline void setDateTimeLocalOffset(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
|
||
|
|
+ std::string datetimelocaloffset)
|
||
|
|
+{
|
||
|
|
+ int hrs = 0;
|
||
|
|
+ char ZoneInfoFile[128] = {0}, file[32] = {0};
|
||
|
|
+ static constexpr int16_t SEL_UTC_MAX_RANGE = 1440;
|
||
|
|
+ static constexpr int16_t SEL_UTC_MIN_RANGE = -1440;
|
||
|
|
+ static constexpr int16_t UNSPECIFIED_UTC_OFFSET = 0x7ff;
|
||
|
|
+ constexpr auto LOCALTIME = "/etc/localtime";
|
||
|
|
+ int UTCOffset = redfish::time_utils::convertTimeOffsetToMinutes(datetimelocaloffset);
|
||
|
|
+ if (((UTCOffset > SEL_UTC_MAX_RANGE ) || (UTCOffset < SEL_UTC_MIN_RANGE) || (UTCOffset % 60 != 0)) && UTCOffset != UNSPECIFIED_UTC_OFFSET)
|
||
|
|
+ {
|
||
|
|
+ messages::propertyValueOutOfRange(asyncResp->res, datetimelocaloffset,
|
||
|
|
+ "DateTimeLocalOffset");
|
||
|
|
+ return;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ hrs = UTCOffset / 60;
|
||
|
|
+ if(UTCOffset == UNSPECIFIED_UTC_OFFSET)
|
||
|
|
+ {
|
||
|
|
+ hrs = 0;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ if (0 > UTCOffset)
|
||
|
|
+ {
|
||
|
|
+ if (snprintf(file,sizeof(file), "GMT+%d", -hrs) >= static_cast<long int>(sizeof(file)))
|
||
|
|
+ {
|
||
|
|
+ messages::internalError(asyncResp->res);
|
||
|
|
+ return;
|
||
|
|
+ }
|
||
|
|
+ }
|
||
|
|
+ else
|
||
|
|
+ {
|
||
|
|
+ if (snprintf(file,sizeof(file), "GMT-%d", hrs) >= static_cast<long int>(sizeof(file)))
|
||
|
|
+ {
|
||
|
|
+ messages::internalError(asyncResp->res);
|
||
|
|
+ return;
|
||
|
|
+ }
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ if (snprintf (ZoneInfoFile, sizeof(ZoneInfoFile), "%s/%s", "/usr/share/zoneinfo/Etc", file) >= static_cast<long int>(sizeof(ZoneInfoFile)))
|
||
|
|
+ {
|
||
|
|
+ messages::internalError(asyncResp->res);
|
||
|
|
+ return;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ if((0 > unlink(LOCALTIME)) && errno != ENOENT)
|
||
|
|
+ {
|
||
|
|
+ messages::internalError(asyncResp->res);
|
||
|
|
+ return;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ if(symlink(ZoneInfoFile, LOCALTIME) < 0)
|
||
|
|
+ {
|
||
|
|
+ messages::internalError(asyncResp->res);
|
||
|
|
+ return;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ asyncResp->res.jsonValue["DateTimeLocalOffset"] = datetimelocaloffset;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
inline void
|
||
|
|
checkForQuiesced(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
|
||
|
|
{
|
||
|
|
@@ -2189,9 +2250,10 @@ inline void requestRoutesManager(App& app)
|
||
|
|
std::optional<nlohmann::json> oem;
|
||
|
|
std::optional<nlohmann::json> links;
|
||
|
|
std::optional<std::string> datetime;
|
||
|
|
+ std::optional<std::string> datatimelocaloffset;
|
||
|
|
|
||
|
|
if (!json_util::readJsonPatch(req, asyncResp->res, "Oem", oem,
|
||
|
|
- "DateTime", datetime, "Links", links))
|
||
|
|
+ "DateTime", datetime, "Links", links, "DateTimeLocalOffset", datatimelocaloffset))
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
@@ -2252,6 +2314,10 @@ inline void requestRoutesManager(App& app)
|
||
|
|
{
|
||
|
|
setDateTime(asyncResp, std::move(*datetime));
|
||
|
|
}
|
||
|
|
+ if (datatimelocaloffset)
|
||
|
|
+ {
|
||
|
|
+ setDateTimeLocalOffset(asyncResp, std::move(*datatimelocaloffset));
|
||
|
|
+ }
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
--
|
||
|
|
2.25.1
|
||
|
|
|