1 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: Copyright OpenBMC Authors
3 #pragma once
4
5 #include "generated/enums/metric_report_definition.hpp"
6 #include "http/utility.hpp"
7 #include "logging.hpp"
8 #include "utility.hpp"
9
10 #include <boost/container/flat_set.hpp>
11 #include <boost/system/result.hpp>
12 #include <boost/url/parse.hpp>
13 #include <boost/url/url_view.hpp>
14 #include <nlohmann/json.hpp>
15 #include <sdbusplus/message/native_types.hpp>
16
17 #include <cstddef>
18 #include <functional>
19 #include <optional>
20 #include <span>
21 #include <string>
22 #include <string_view>
23 #include <utility>
24
25 namespace redfish
26 {
27
28 namespace telemetry
29 {
30 constexpr const char* service = "xyz.openbmc_project.Telemetry";
31 constexpr const char* reportInterface = "xyz.openbmc_project.Telemetry.Report";
32
getDbusReportPath(std::string_view id)33 inline std::string getDbusReportPath(std::string_view id)
34 {
35 sdbusplus::message::object_path reportsPath(
36 "/xyz/openbmc_project/Telemetry/Reports/TelemetryService");
37 return {reportsPath / id};
38 }
39
getDbusTriggerPath(std::string_view id)40 inline std::string getDbusTriggerPath(std::string_view id)
41 {
42 sdbusplus::message::object_path triggersPath(
43 "/xyz/openbmc_project/Telemetry/Triggers/TelemetryService");
44 return {triggersPath / id};
45 }
46
getTriggerIdFromDbusPath(const std::string & dbusPath)47 inline std::optional<std::string> getTriggerIdFromDbusPath(
48 const std::string& dbusPath)
49 {
50 sdbusplus::message::object_path converted(dbusPath);
51
52 if (converted.parent_path() !=
53 "/xyz/openbmc_project/Telemetry/Triggers/TelemetryService")
54 {
55 return std::nullopt;
56 }
57
58 const std::string& id = converted.filename();
59 if (id.empty())
60 {
61 return std::nullopt;
62 }
63 return id;
64 }
65
66 struct IncorrectMetricUri
67 {
68 std::string uri;
69 size_t index;
70 };
71
getChassisSensorNode(std::span<const std::string> uris,boost::container::flat_set<std::pair<std::string,std::string>> & matched)72 inline std::optional<IncorrectMetricUri> getChassisSensorNode(
73 std::span<const std::string> uris,
74 boost::container::flat_set<std::pair<std::string, std::string>>& matched)
75 {
76 size_t uriIdx = 0;
77 for (const std::string& uri : uris)
78 {
79 boost::system::result<boost::urls::url_view> parsed =
80 boost::urls::parse_relative_ref(uri);
81
82 if (!parsed)
83 {
84 BMCWEB_LOG_ERROR("Failed to get chassis and sensor Node "
85 "from {}",
86 uri);
87 return std::make_optional<IncorrectMetricUri>({uri, uriIdx});
88 }
89
90 std::string chassis;
91 std::string node;
92
93 if (crow::utility::readUrlSegments(*parsed, "redfish", "v1", "Chassis",
94 std::ref(chassis), std::ref(node)))
95 {
96 matched.emplace(std::move(chassis), std::move(node));
97 uriIdx++;
98 continue;
99 }
100
101 // Those 2 segments cannot be validated here, as we don't know which
102 // sensors exist at the moment of parsing.
103 std::string ignoredSenorId;
104
105 if (crow::utility::readUrlSegments(*parsed, "redfish", "v1", "Chassis",
106 std::ref(chassis), "Sensors",
107 std::ref(ignoredSenorId)))
108 {
109 matched.emplace(std::move(chassis), "Sensors");
110 uriIdx++;
111 continue;
112 }
113
114 BMCWEB_LOG_ERROR("Failed to get chassis and sensor Node "
115 "from {}",
116 uri);
117 return std::make_optional<IncorrectMetricUri>({uri, uriIdx});
118 }
119 return std::nullopt;
120 }
121
122 inline metric_report_definition::CalculationAlgorithmEnum
toRedfishCollectionFunction(std::string_view dbusValue)123 toRedfishCollectionFunction(std::string_view dbusValue)
124 {
125 if (dbusValue ==
126 "xyz.openbmc_project.Telemetry.Report.OperationType.Maximum")
127 {
128 return metric_report_definition::CalculationAlgorithmEnum::Maximum;
129 }
130 if (dbusValue ==
131 "xyz.openbmc_project.Telemetry.Report.OperationType.Minimum")
132 {
133 return metric_report_definition::CalculationAlgorithmEnum::Minimum;
134 }
135 if (dbusValue ==
136 "xyz.openbmc_project.Telemetry.Report.OperationType.Average")
137 {
138 return metric_report_definition::CalculationAlgorithmEnum::Average;
139 }
140 if (dbusValue ==
141 "xyz.openbmc_project.Telemetry.Report.OperationType.Summation")
142 {
143 return metric_report_definition::CalculationAlgorithmEnum::Summation;
144 }
145 return metric_report_definition::CalculationAlgorithmEnum::Invalid;
146 }
147
toDbusCollectionFunction(std::string_view redfishValue)148 inline std::string toDbusCollectionFunction(std::string_view redfishValue)
149 {
150 if (redfishValue == "Maximum")
151 {
152 return "xyz.openbmc_project.Telemetry.Report.OperationType.Maximum";
153 }
154 if (redfishValue == "Minimum")
155 {
156 return "xyz.openbmc_project.Telemetry.Report.OperationType.Minimum";
157 }
158 if (redfishValue == "Average")
159 {
160 return "xyz.openbmc_project.Telemetry.Report.OperationType.Average";
161 }
162 if (redfishValue == "Summation")
163 {
164 return "xyz.openbmc_project.Telemetry.Report.OperationType.Summation";
165 }
166 return "";
167 }
168
toRedfishCollectionFunctions(std::span<const std::string> dbusEnums)169 inline std::optional<nlohmann::json::array_t> toRedfishCollectionFunctions(
170 std::span<const std::string> dbusEnums)
171 {
172 nlohmann::json::array_t redfishEnums;
173 redfishEnums.reserve(dbusEnums.size());
174
175 for (const auto& dbusValue : dbusEnums)
176 {
177 metric_report_definition::CalculationAlgorithmEnum redfishValue =
178 toRedfishCollectionFunction(dbusValue);
179
180 if (redfishValue ==
181 metric_report_definition::CalculationAlgorithmEnum::Invalid)
182 {
183 return std::nullopt;
184 }
185
186 redfishEnums.emplace_back(redfishValue);
187 }
188 return redfishEnums;
189 }
190
191 } // namespace telemetry
192 } // namespace redfish
193