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