1 #pragma once
2 
3 #include "app.hpp"
4 #include "async_resp.hpp"
5 #include "http_request.hpp"
6 #include "privileges.hpp"
7 #include "query.hpp"
8 #include "registries/privilege_registry.hpp"
9 #include "routing.hpp"
10 
11 #include <nlohmann/json.hpp>
12 #include <sdbusplus/asio/property.hpp>
13 
14 #include <string>
15 
16 namespace redfish
17 {
18 
19 inline void
20     afterGetManagerStartTime(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
21                              const boost::system::error_code& ec,
22                              uint64_t bmcwebResetTime)
23 {
24     if (ec)
25     {
26         // Not all servers will be running in systemd, so ignore the error.
27         return;
28     }
29     using std::chrono::steady_clock;
30 
31     std::chrono::duration<steady_clock::rep, std::micro> usReset{
32         bmcwebResetTime};
33     steady_clock::time_point resetTime{usReset};
34 
35     steady_clock::time_point now = steady_clock::now();
36 
37     steady_clock::duration runTime = now - resetTime;
38 
39     if (runTime < steady_clock::duration::zero())
40     {
41         BMCWEB_LOG_CRITICAL << "Uptime was negative????";
42         messages::internalError(aResp->res);
43         return;
44     }
45 
46     // Floor to the closest millisecond
47     using Milli = std::chrono::duration<steady_clock::rep, std::milli>;
48     Milli milli = std::chrono::floor<Milli>(runTime);
49 
50     using SecondsFloat = std::chrono::duration<double>;
51     SecondsFloat sec = std::chrono::duration_cast<SecondsFloat>(milli);
52 
53     aResp->res.jsonValue["ServiceRootUptimeSeconds"] = sec.count();
54 }
55 
56 inline void
57     managerGetServiceRootUptime(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
58 {
59     sdbusplus::asio::getProperty<uint64_t>(
60         *crow::connections::systemBus, "org.freedesktop.systemd1",
61         "/org/freedesktop/systemd1/unit/bmcweb_2eservice",
62         "org.freedesktop.systemd1.Unit", "ActiveEnterTimestampMonotonic",
63         std::bind_front(afterGetManagerStartTime, aResp));
64 }
65 /**
66  * handleManagerDiagnosticData supports ManagerDiagnosticData.
67  * It retrieves BMC health information from various DBus resources and returns
68  * the information through the response.
69  */
70 inline void handleManagerDiagnosticDataGet(
71     crow::App& app, const crow::Request& req,
72     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
73 {
74     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
75     {
76         return;
77     }
78     asyncResp->res.jsonValue["@odata.type"] =
79         "#ManagerDiagnosticData.v1_2_0.ManagerDiagnosticData";
80     asyncResp->res.jsonValue["@odata.id"] =
81         "/redfish/v1/Managers/bmc/ManagerDiagnosticData";
82     asyncResp->res.jsonValue["Id"] = "ManagerDiagnosticData";
83     asyncResp->res.jsonValue["Name"] = "Manager Diagnostic Data";
84 
85     managerGetServiceRootUptime(asyncResp);
86 }
87 
88 inline void requestRoutesManagerDiagnosticData(App& app)
89 {
90     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/ManagerDiagnosticData")
91         .privileges(redfish::privileges::getManagerDiagnosticData)
92         .methods(boost::beast::http::verb::get)(
93             std::bind_front(handleManagerDiagnosticDataGet, std::ref(app)));
94 }
95 
96 } // namespace redfish
97