Files
OpenBMC/meta-luxshare/recipes-phosphor/interfaces/bmcweb/0001-Support-redfish-set-bmc-timezone.patch
T

180 lines
5.8 KiB
Diff
Raw Normal View History

2026-04-23 17:07:55 +08:00
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