1081ebf06SWludzik, Jozef #pragma once 2081ebf06SWludzik, Jozef 3081ebf06SWludzik, Jozef #include "node.hpp" 4*4dbb8aeaSWludzik, Jozef #include "sensors.hpp" 5081ebf06SWludzik, Jozef #include "utils/telemetry_utils.hpp" 6081ebf06SWludzik, Jozef #include "utils/time_utils.hpp" 7081ebf06SWludzik, Jozef 8*4dbb8aeaSWludzik, Jozef #include <boost/container/flat_map.hpp> 9*4dbb8aeaSWludzik, Jozef 10081ebf06SWludzik, Jozef #include <tuple> 11081ebf06SWludzik, Jozef #include <variant> 12081ebf06SWludzik, Jozef 13081ebf06SWludzik, Jozef namespace redfish 14081ebf06SWludzik, Jozef { 15081ebf06SWludzik, Jozef 16081ebf06SWludzik, Jozef namespace telemetry 17081ebf06SWludzik, Jozef { 18081ebf06SWludzik, Jozef 19081ebf06SWludzik, Jozef using ReadingParameters = 20081ebf06SWludzik, Jozef std::vector<std::tuple<sdbusplus::message::object_path, std::string, 21081ebf06SWludzik, Jozef std::string, std::string>>; 22081ebf06SWludzik, Jozef 23081ebf06SWludzik, Jozef inline void fillReportDefinition( 24081ebf06SWludzik, Jozef const std::shared_ptr<AsyncResp>& asyncResp, const std::string& id, 25081ebf06SWludzik, Jozef const std::vector< 26081ebf06SWludzik, Jozef std::pair<std::string, std::variant<std::string, bool, uint64_t, 27081ebf06SWludzik, Jozef ReadingParameters>>>& ret) 28081ebf06SWludzik, Jozef { 29081ebf06SWludzik, Jozef asyncResp->res.jsonValue["@odata.type"] = 30081ebf06SWludzik, Jozef "#MetricReportDefinition.v1_3_0.MetricReportDefinition"; 31081ebf06SWludzik, Jozef asyncResp->res.jsonValue["@odata.id"] = 32081ebf06SWludzik, Jozef telemetry::metricReportDefinitionUri + id; 33081ebf06SWludzik, Jozef asyncResp->res.jsonValue["Id"] = id; 34081ebf06SWludzik, Jozef asyncResp->res.jsonValue["Name"] = id; 35081ebf06SWludzik, Jozef asyncResp->res.jsonValue["MetricReport"]["@odata.id"] = 36081ebf06SWludzik, Jozef telemetry::metricReportUri + id; 37081ebf06SWludzik, Jozef asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; 38081ebf06SWludzik, Jozef asyncResp->res.jsonValue["ReportUpdates"] = "Overwrite"; 39081ebf06SWludzik, Jozef 40081ebf06SWludzik, Jozef const bool* emitsReadingsUpdate = nullptr; 41081ebf06SWludzik, Jozef const bool* logToMetricReportsCollection = nullptr; 42081ebf06SWludzik, Jozef const ReadingParameters* readingParams = nullptr; 43081ebf06SWludzik, Jozef const std::string* reportingType = nullptr; 44081ebf06SWludzik, Jozef const uint64_t* interval = nullptr; 45081ebf06SWludzik, Jozef for (const auto& [key, var] : ret) 46081ebf06SWludzik, Jozef { 47081ebf06SWludzik, Jozef if (key == "EmitsReadingsUpdate") 48081ebf06SWludzik, Jozef { 49081ebf06SWludzik, Jozef emitsReadingsUpdate = std::get_if<bool>(&var); 50081ebf06SWludzik, Jozef } 51081ebf06SWludzik, Jozef else if (key == "LogToMetricReportsCollection") 52081ebf06SWludzik, Jozef { 53081ebf06SWludzik, Jozef logToMetricReportsCollection = std::get_if<bool>(&var); 54081ebf06SWludzik, Jozef } 55081ebf06SWludzik, Jozef else if (key == "ReadingParameters") 56081ebf06SWludzik, Jozef { 57081ebf06SWludzik, Jozef readingParams = std::get_if<ReadingParameters>(&var); 58081ebf06SWludzik, Jozef } 59081ebf06SWludzik, Jozef else if (key == "ReportingType") 60081ebf06SWludzik, Jozef { 61081ebf06SWludzik, Jozef reportingType = std::get_if<std::string>(&var); 62081ebf06SWludzik, Jozef } 63081ebf06SWludzik, Jozef else if (key == "Interval") 64081ebf06SWludzik, Jozef { 65081ebf06SWludzik, Jozef interval = std::get_if<uint64_t>(&var); 66081ebf06SWludzik, Jozef } 67081ebf06SWludzik, Jozef } 68081ebf06SWludzik, Jozef if (!emitsReadingsUpdate || !logToMetricReportsCollection || 69081ebf06SWludzik, Jozef !readingParams || !reportingType || !interval) 70081ebf06SWludzik, Jozef { 71081ebf06SWludzik, Jozef BMCWEB_LOG_ERROR << "Property type mismatch or property is missing"; 72081ebf06SWludzik, Jozef messages::internalError(asyncResp->res); 73081ebf06SWludzik, Jozef return; 74081ebf06SWludzik, Jozef } 75081ebf06SWludzik, Jozef 76081ebf06SWludzik, Jozef std::vector<std::string> redfishReportActions; 77081ebf06SWludzik, Jozef redfishReportActions.reserve(2); 78081ebf06SWludzik, Jozef if (*emitsReadingsUpdate) 79081ebf06SWludzik, Jozef { 80081ebf06SWludzik, Jozef redfishReportActions.emplace_back("RedfishEvent"); 81081ebf06SWludzik, Jozef } 82081ebf06SWludzik, Jozef if (*logToMetricReportsCollection) 83081ebf06SWludzik, Jozef { 84081ebf06SWludzik, Jozef redfishReportActions.emplace_back("LogToMetricReportsCollection"); 85081ebf06SWludzik, Jozef } 86081ebf06SWludzik, Jozef 87081ebf06SWludzik, Jozef nlohmann::json metrics = nlohmann::json::array(); 88081ebf06SWludzik, Jozef for (auto& [sensorPath, operationType, id, metadata] : *readingParams) 89081ebf06SWludzik, Jozef { 90081ebf06SWludzik, Jozef metrics.push_back({ 91081ebf06SWludzik, Jozef {"MetricId", id}, 92081ebf06SWludzik, Jozef {"MetricProperties", {metadata}}, 93081ebf06SWludzik, Jozef }); 94081ebf06SWludzik, Jozef } 95081ebf06SWludzik, Jozef asyncResp->res.jsonValue["Metrics"] = metrics; 96081ebf06SWludzik, Jozef asyncResp->res.jsonValue["MetricReportDefinitionType"] = *reportingType; 97081ebf06SWludzik, Jozef asyncResp->res.jsonValue["ReportActions"] = redfishReportActions; 98081ebf06SWludzik, Jozef asyncResp->res.jsonValue["Schedule"]["RecurrenceInterval"] = 99081ebf06SWludzik, Jozef time_utils::toDurationString(std::chrono::milliseconds(*interval)); 100081ebf06SWludzik, Jozef } 101*4dbb8aeaSWludzik, Jozef 102*4dbb8aeaSWludzik, Jozef struct AddReportArgs 103*4dbb8aeaSWludzik, Jozef { 104*4dbb8aeaSWludzik, Jozef std::string name; 105*4dbb8aeaSWludzik, Jozef std::string reportingType; 106*4dbb8aeaSWludzik, Jozef bool emitsReadingsUpdate = false; 107*4dbb8aeaSWludzik, Jozef bool logToMetricReportsCollection = false; 108*4dbb8aeaSWludzik, Jozef uint64_t interval = 0; 109*4dbb8aeaSWludzik, Jozef std::vector<std::pair<std::string, std::vector<std::string>>> metrics; 110*4dbb8aeaSWludzik, Jozef }; 111*4dbb8aeaSWludzik, Jozef 112*4dbb8aeaSWludzik, Jozef inline bool toDbusReportActions(crow::Response& res, 113*4dbb8aeaSWludzik, Jozef std::vector<std::string>& actions, 114*4dbb8aeaSWludzik, Jozef AddReportArgs& args) 115*4dbb8aeaSWludzik, Jozef { 116*4dbb8aeaSWludzik, Jozef size_t index = 0; 117*4dbb8aeaSWludzik, Jozef for (auto& action : actions) 118*4dbb8aeaSWludzik, Jozef { 119*4dbb8aeaSWludzik, Jozef if (action == "RedfishEvent") 120*4dbb8aeaSWludzik, Jozef { 121*4dbb8aeaSWludzik, Jozef args.emitsReadingsUpdate = true; 122*4dbb8aeaSWludzik, Jozef } 123*4dbb8aeaSWludzik, Jozef else if (action == "LogToMetricReportsCollection") 124*4dbb8aeaSWludzik, Jozef { 125*4dbb8aeaSWludzik, Jozef args.logToMetricReportsCollection = true; 126*4dbb8aeaSWludzik, Jozef } 127*4dbb8aeaSWludzik, Jozef else 128*4dbb8aeaSWludzik, Jozef { 129*4dbb8aeaSWludzik, Jozef messages::propertyValueNotInList( 130*4dbb8aeaSWludzik, Jozef res, action, "ReportActions/" + std::to_string(index)); 131*4dbb8aeaSWludzik, Jozef return false; 132*4dbb8aeaSWludzik, Jozef } 133*4dbb8aeaSWludzik, Jozef index++; 134*4dbb8aeaSWludzik, Jozef } 135*4dbb8aeaSWludzik, Jozef return true; 136*4dbb8aeaSWludzik, Jozef } 137*4dbb8aeaSWludzik, Jozef 138*4dbb8aeaSWludzik, Jozef inline bool getUserParameters(crow::Response& res, const crow::Request& req, 139*4dbb8aeaSWludzik, Jozef AddReportArgs& args) 140*4dbb8aeaSWludzik, Jozef { 141*4dbb8aeaSWludzik, Jozef std::vector<nlohmann::json> metrics; 142*4dbb8aeaSWludzik, Jozef std::vector<std::string> reportActions; 143*4dbb8aeaSWludzik, Jozef std::optional<nlohmann::json> schedule; 144*4dbb8aeaSWludzik, Jozef if (!json_util::readJson(req, res, "Id", args.name, "Metrics", metrics, 145*4dbb8aeaSWludzik, Jozef "MetricReportDefinitionType", args.reportingType, 146*4dbb8aeaSWludzik, Jozef "ReportActions", reportActions, "Schedule", 147*4dbb8aeaSWludzik, Jozef schedule)) 148*4dbb8aeaSWludzik, Jozef { 149*4dbb8aeaSWludzik, Jozef return false; 150*4dbb8aeaSWludzik, Jozef } 151*4dbb8aeaSWludzik, Jozef 152*4dbb8aeaSWludzik, Jozef constexpr const char* allowedCharactersInName = 153*4dbb8aeaSWludzik, Jozef "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"; 154*4dbb8aeaSWludzik, Jozef if (args.name.empty() || args.name.find_first_not_of( 155*4dbb8aeaSWludzik, Jozef allowedCharactersInName) != std::string::npos) 156*4dbb8aeaSWludzik, Jozef { 157*4dbb8aeaSWludzik, Jozef BMCWEB_LOG_ERROR << "Failed to match " << args.name 158*4dbb8aeaSWludzik, Jozef << " with allowed character " 159*4dbb8aeaSWludzik, Jozef << allowedCharactersInName; 160*4dbb8aeaSWludzik, Jozef messages::propertyValueIncorrect(res, "Id", args.name); 161*4dbb8aeaSWludzik, Jozef return false; 162*4dbb8aeaSWludzik, Jozef } 163*4dbb8aeaSWludzik, Jozef 164*4dbb8aeaSWludzik, Jozef if (args.reportingType != "Periodic" && args.reportingType != "OnRequest") 165*4dbb8aeaSWludzik, Jozef { 166*4dbb8aeaSWludzik, Jozef messages::propertyValueNotInList(res, args.reportingType, 167*4dbb8aeaSWludzik, Jozef "MetricReportDefinitionType"); 168*4dbb8aeaSWludzik, Jozef return false; 169*4dbb8aeaSWludzik, Jozef } 170*4dbb8aeaSWludzik, Jozef 171*4dbb8aeaSWludzik, Jozef if (!toDbusReportActions(res, reportActions, args)) 172*4dbb8aeaSWludzik, Jozef { 173*4dbb8aeaSWludzik, Jozef return false; 174*4dbb8aeaSWludzik, Jozef } 175*4dbb8aeaSWludzik, Jozef 176*4dbb8aeaSWludzik, Jozef if (args.reportingType == "Periodic") 177*4dbb8aeaSWludzik, Jozef { 178*4dbb8aeaSWludzik, Jozef if (!schedule) 179*4dbb8aeaSWludzik, Jozef { 180*4dbb8aeaSWludzik, Jozef messages::createFailedMissingReqProperties(res, "Schedule"); 181*4dbb8aeaSWludzik, Jozef return false; 182*4dbb8aeaSWludzik, Jozef } 183*4dbb8aeaSWludzik, Jozef 184*4dbb8aeaSWludzik, Jozef std::string durationStr; 185*4dbb8aeaSWludzik, Jozef if (!json_util::readJson(*schedule, res, "RecurrenceInterval", 186*4dbb8aeaSWludzik, Jozef durationStr)) 187*4dbb8aeaSWludzik, Jozef { 188*4dbb8aeaSWludzik, Jozef return false; 189*4dbb8aeaSWludzik, Jozef } 190*4dbb8aeaSWludzik, Jozef 191*4dbb8aeaSWludzik, Jozef std::optional<std::chrono::milliseconds> durationNum = 192*4dbb8aeaSWludzik, Jozef time_utils::fromDurationString(durationStr); 193*4dbb8aeaSWludzik, Jozef if (!durationNum) 194*4dbb8aeaSWludzik, Jozef { 195*4dbb8aeaSWludzik, Jozef messages::propertyValueIncorrect(res, "RecurrenceInterval", 196*4dbb8aeaSWludzik, Jozef durationStr); 197*4dbb8aeaSWludzik, Jozef return false; 198*4dbb8aeaSWludzik, Jozef } 199*4dbb8aeaSWludzik, Jozef args.interval = static_cast<uint64_t>(durationNum->count()); 200*4dbb8aeaSWludzik, Jozef } 201*4dbb8aeaSWludzik, Jozef 202*4dbb8aeaSWludzik, Jozef args.metrics.reserve(metrics.size()); 203*4dbb8aeaSWludzik, Jozef for (auto& m : metrics) 204*4dbb8aeaSWludzik, Jozef { 205*4dbb8aeaSWludzik, Jozef std::string id; 206*4dbb8aeaSWludzik, Jozef std::vector<std::string> uris; 207*4dbb8aeaSWludzik, Jozef if (!json_util::readJson(m, res, "MetricId", id, "MetricProperties", 208*4dbb8aeaSWludzik, Jozef uris)) 209*4dbb8aeaSWludzik, Jozef { 210*4dbb8aeaSWludzik, Jozef return false; 211*4dbb8aeaSWludzik, Jozef } 212*4dbb8aeaSWludzik, Jozef 213*4dbb8aeaSWludzik, Jozef args.metrics.emplace_back(std::move(id), std::move(uris)); 214*4dbb8aeaSWludzik, Jozef } 215*4dbb8aeaSWludzik, Jozef 216*4dbb8aeaSWludzik, Jozef return true; 217*4dbb8aeaSWludzik, Jozef } 218*4dbb8aeaSWludzik, Jozef 219*4dbb8aeaSWludzik, Jozef inline bool getChassisSensorNode( 220*4dbb8aeaSWludzik, Jozef const std::shared_ptr<AsyncResp>& asyncResp, 221*4dbb8aeaSWludzik, Jozef const std::vector<std::pair<std::string, std::vector<std::string>>>& 222*4dbb8aeaSWludzik, Jozef metrics, 223*4dbb8aeaSWludzik, Jozef boost::container::flat_set<std::pair<std::string, std::string>>& matched) 224*4dbb8aeaSWludzik, Jozef { 225*4dbb8aeaSWludzik, Jozef for (const auto& [id, uris] : metrics) 226*4dbb8aeaSWludzik, Jozef { 227*4dbb8aeaSWludzik, Jozef for (size_t i = 0; i < uris.size(); i++) 228*4dbb8aeaSWludzik, Jozef { 229*4dbb8aeaSWludzik, Jozef const std::string& uri = uris[i]; 230*4dbb8aeaSWludzik, Jozef std::string chassis; 231*4dbb8aeaSWludzik, Jozef std::string node; 232*4dbb8aeaSWludzik, Jozef 233*4dbb8aeaSWludzik, Jozef if (!boost::starts_with(uri, "/redfish/v1/Chassis/") || 234*4dbb8aeaSWludzik, Jozef !dbus::utility::getNthStringFromPath(uri, 3, chassis) || 235*4dbb8aeaSWludzik, Jozef !dbus::utility::getNthStringFromPath(uri, 4, node)) 236*4dbb8aeaSWludzik, Jozef { 237*4dbb8aeaSWludzik, Jozef BMCWEB_LOG_ERROR << "Failed to get chassis and sensor Node " 238*4dbb8aeaSWludzik, Jozef "from " 239*4dbb8aeaSWludzik, Jozef << uri; 240*4dbb8aeaSWludzik, Jozef messages::propertyValueIncorrect(asyncResp->res, uri, 241*4dbb8aeaSWludzik, Jozef "MetricProperties/" + 242*4dbb8aeaSWludzik, Jozef std::to_string(i)); 243*4dbb8aeaSWludzik, Jozef return false; 244*4dbb8aeaSWludzik, Jozef } 245*4dbb8aeaSWludzik, Jozef 246*4dbb8aeaSWludzik, Jozef if (boost::ends_with(node, "#")) 247*4dbb8aeaSWludzik, Jozef { 248*4dbb8aeaSWludzik, Jozef node.pop_back(); 249*4dbb8aeaSWludzik, Jozef } 250*4dbb8aeaSWludzik, Jozef 251*4dbb8aeaSWludzik, Jozef matched.emplace(std::move(chassis), std::move(node)); 252*4dbb8aeaSWludzik, Jozef } 253*4dbb8aeaSWludzik, Jozef } 254*4dbb8aeaSWludzik, Jozef return true; 255*4dbb8aeaSWludzik, Jozef } 256*4dbb8aeaSWludzik, Jozef 257*4dbb8aeaSWludzik, Jozef class AddReport 258*4dbb8aeaSWludzik, Jozef { 259*4dbb8aeaSWludzik, Jozef public: 260*4dbb8aeaSWludzik, Jozef AddReport(AddReportArgs argsIn, std::shared_ptr<AsyncResp> asyncResp) : 261*4dbb8aeaSWludzik, Jozef asyncResp{std::move(asyncResp)}, args{std::move(argsIn)} 262*4dbb8aeaSWludzik, Jozef {} 263*4dbb8aeaSWludzik, Jozef ~AddReport() 264*4dbb8aeaSWludzik, Jozef { 265*4dbb8aeaSWludzik, Jozef if (asyncResp->res.result() != boost::beast::http::status::ok) 266*4dbb8aeaSWludzik, Jozef { 267*4dbb8aeaSWludzik, Jozef return; 268*4dbb8aeaSWludzik, Jozef } 269*4dbb8aeaSWludzik, Jozef 270*4dbb8aeaSWludzik, Jozef telemetry::ReadingParameters readingParams; 271*4dbb8aeaSWludzik, Jozef readingParams.reserve(args.metrics.size()); 272*4dbb8aeaSWludzik, Jozef 273*4dbb8aeaSWludzik, Jozef for (const auto& [id, uris] : args.metrics) 274*4dbb8aeaSWludzik, Jozef { 275*4dbb8aeaSWludzik, Jozef for (size_t i = 0; i < uris.size(); i++) 276*4dbb8aeaSWludzik, Jozef { 277*4dbb8aeaSWludzik, Jozef const std::string& uri = uris[i]; 278*4dbb8aeaSWludzik, Jozef auto el = uriToDbus.find(uri); 279*4dbb8aeaSWludzik, Jozef if (el == uriToDbus.end()) 280*4dbb8aeaSWludzik, Jozef { 281*4dbb8aeaSWludzik, Jozef BMCWEB_LOG_ERROR << "Failed to find DBus sensor " 282*4dbb8aeaSWludzik, Jozef "corresponding to URI " 283*4dbb8aeaSWludzik, Jozef << uri; 284*4dbb8aeaSWludzik, Jozef messages::propertyValueNotInList(asyncResp->res, uri, 285*4dbb8aeaSWludzik, Jozef "MetricProperties/" + 286*4dbb8aeaSWludzik, Jozef std::to_string(i)); 287*4dbb8aeaSWludzik, Jozef return; 288*4dbb8aeaSWludzik, Jozef } 289*4dbb8aeaSWludzik, Jozef 290*4dbb8aeaSWludzik, Jozef const std::string& dbusPath = el->second; 291*4dbb8aeaSWludzik, Jozef readingParams.emplace_back(dbusPath, "SINGLE", id, uri); 292*4dbb8aeaSWludzik, Jozef } 293*4dbb8aeaSWludzik, Jozef } 294*4dbb8aeaSWludzik, Jozef 295*4dbb8aeaSWludzik, Jozef crow::connections::systemBus->async_method_call( 296*4dbb8aeaSWludzik, Jozef [asyncResp = std::move(asyncResp), name = args.name, 297*4dbb8aeaSWludzik, Jozef uriToDbus = std::move(uriToDbus)]( 298*4dbb8aeaSWludzik, Jozef const boost::system::error_code ec, const std::string&) { 299*4dbb8aeaSWludzik, Jozef if (ec == boost::system::errc::file_exists) 300*4dbb8aeaSWludzik, Jozef { 301*4dbb8aeaSWludzik, Jozef messages::resourceAlreadyExists( 302*4dbb8aeaSWludzik, Jozef asyncResp->res, "MetricReportDefinition", "Id", name); 303*4dbb8aeaSWludzik, Jozef return; 304*4dbb8aeaSWludzik, Jozef } 305*4dbb8aeaSWludzik, Jozef if (ec == boost::system::errc::too_many_files_open) 306*4dbb8aeaSWludzik, Jozef { 307*4dbb8aeaSWludzik, Jozef messages::createLimitReachedForResource(asyncResp->res); 308*4dbb8aeaSWludzik, Jozef return; 309*4dbb8aeaSWludzik, Jozef } 310*4dbb8aeaSWludzik, Jozef if (ec == boost::system::errc::argument_list_too_long) 311*4dbb8aeaSWludzik, Jozef { 312*4dbb8aeaSWludzik, Jozef nlohmann::json metricProperties = nlohmann::json::array(); 313*4dbb8aeaSWludzik, Jozef for (const auto& [uri, _] : uriToDbus) 314*4dbb8aeaSWludzik, Jozef { 315*4dbb8aeaSWludzik, Jozef metricProperties.emplace_back(uri); 316*4dbb8aeaSWludzik, Jozef } 317*4dbb8aeaSWludzik, Jozef messages::propertyValueIncorrect( 318*4dbb8aeaSWludzik, Jozef asyncResp->res, metricProperties, "MetricProperties"); 319*4dbb8aeaSWludzik, Jozef return; 320*4dbb8aeaSWludzik, Jozef } 321*4dbb8aeaSWludzik, Jozef if (ec) 322*4dbb8aeaSWludzik, Jozef { 323*4dbb8aeaSWludzik, Jozef messages::internalError(asyncResp->res); 324*4dbb8aeaSWludzik, Jozef BMCWEB_LOG_ERROR << "respHandler DBus error " << ec; 325*4dbb8aeaSWludzik, Jozef return; 326*4dbb8aeaSWludzik, Jozef } 327*4dbb8aeaSWludzik, Jozef 328*4dbb8aeaSWludzik, Jozef messages::created(asyncResp->res); 329*4dbb8aeaSWludzik, Jozef }, 330*4dbb8aeaSWludzik, Jozef telemetry::service, "/xyz/openbmc_project/Telemetry/Reports", 331*4dbb8aeaSWludzik, Jozef "xyz.openbmc_project.Telemetry.ReportManager", "AddReport", 332*4dbb8aeaSWludzik, Jozef "TelemetryService/" + args.name, args.reportingType, 333*4dbb8aeaSWludzik, Jozef args.emitsReadingsUpdate, args.logToMetricReportsCollection, 334*4dbb8aeaSWludzik, Jozef args.interval, readingParams); 335*4dbb8aeaSWludzik, Jozef } 336*4dbb8aeaSWludzik, Jozef 337*4dbb8aeaSWludzik, Jozef void insert(const boost::container::flat_map<std::string, std::string>& el) 338*4dbb8aeaSWludzik, Jozef { 339*4dbb8aeaSWludzik, Jozef uriToDbus.insert(el.begin(), el.end()); 340*4dbb8aeaSWludzik, Jozef } 341*4dbb8aeaSWludzik, Jozef 342*4dbb8aeaSWludzik, Jozef private: 343*4dbb8aeaSWludzik, Jozef std::shared_ptr<AsyncResp> asyncResp; 344*4dbb8aeaSWludzik, Jozef AddReportArgs args; 345*4dbb8aeaSWludzik, Jozef boost::container::flat_map<std::string, std::string> uriToDbus{}; 346*4dbb8aeaSWludzik, Jozef }; 347081ebf06SWludzik, Jozef } // namespace telemetry 348081ebf06SWludzik, Jozef 349081ebf06SWludzik, Jozef class MetricReportDefinitionCollection : public Node 350081ebf06SWludzik, Jozef { 351081ebf06SWludzik, Jozef public: 352081ebf06SWludzik, Jozef MetricReportDefinitionCollection(App& app) : 353081ebf06SWludzik, Jozef Node(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/") 354081ebf06SWludzik, Jozef { 355081ebf06SWludzik, Jozef entityPrivileges = { 356081ebf06SWludzik, Jozef {boost::beast::http::verb::get, {{"Login"}}}, 357081ebf06SWludzik, Jozef {boost::beast::http::verb::head, {{"Login"}}}, 358081ebf06SWludzik, Jozef {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 359081ebf06SWludzik, Jozef {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 360081ebf06SWludzik, Jozef {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 361081ebf06SWludzik, Jozef {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 362081ebf06SWludzik, Jozef } 363081ebf06SWludzik, Jozef 364081ebf06SWludzik, Jozef private: 365081ebf06SWludzik, Jozef void doGet(crow::Response& res, const crow::Request&, 366081ebf06SWludzik, Jozef const std::vector<std::string>&) override 367081ebf06SWludzik, Jozef { 368081ebf06SWludzik, Jozef res.jsonValue["@odata.type"] = "#MetricReportDefinitionCollection." 369081ebf06SWludzik, Jozef "MetricReportDefinitionCollection"; 370081ebf06SWludzik, Jozef res.jsonValue["@odata.id"] = 371081ebf06SWludzik, Jozef "/redfish/v1/TelemetryService/MetricReportDefinitions"; 372081ebf06SWludzik, Jozef res.jsonValue["Name"] = "Metric Definition Collection"; 373081ebf06SWludzik, Jozef 374081ebf06SWludzik, Jozef auto asyncResp = std::make_shared<AsyncResp>(res); 375081ebf06SWludzik, Jozef telemetry::getReportCollection(asyncResp, 376081ebf06SWludzik, Jozef telemetry::metricReportDefinitionUri); 377081ebf06SWludzik, Jozef } 378*4dbb8aeaSWludzik, Jozef 379*4dbb8aeaSWludzik, Jozef void doPost(crow::Response& res, const crow::Request& req, 380*4dbb8aeaSWludzik, Jozef const std::vector<std::string>&) override 381*4dbb8aeaSWludzik, Jozef { 382*4dbb8aeaSWludzik, Jozef auto asyncResp = std::make_shared<AsyncResp>(res); 383*4dbb8aeaSWludzik, Jozef telemetry::AddReportArgs args; 384*4dbb8aeaSWludzik, Jozef if (!telemetry::getUserParameters(res, req, args)) 385*4dbb8aeaSWludzik, Jozef { 386*4dbb8aeaSWludzik, Jozef return; 387*4dbb8aeaSWludzik, Jozef } 388*4dbb8aeaSWludzik, Jozef 389*4dbb8aeaSWludzik, Jozef boost::container::flat_set<std::pair<std::string, std::string>> 390*4dbb8aeaSWludzik, Jozef chassisSensors; 391*4dbb8aeaSWludzik, Jozef if (!telemetry::getChassisSensorNode(asyncResp, args.metrics, 392*4dbb8aeaSWludzik, Jozef chassisSensors)) 393*4dbb8aeaSWludzik, Jozef { 394*4dbb8aeaSWludzik, Jozef return; 395*4dbb8aeaSWludzik, Jozef } 396*4dbb8aeaSWludzik, Jozef 397*4dbb8aeaSWludzik, Jozef auto addReportReq = 398*4dbb8aeaSWludzik, Jozef std::make_shared<telemetry::AddReport>(std::move(args), asyncResp); 399*4dbb8aeaSWludzik, Jozef for (const auto& [chassis, sensorType] : chassisSensors) 400*4dbb8aeaSWludzik, Jozef { 401*4dbb8aeaSWludzik, Jozef retrieveUriToDbusMap( 402*4dbb8aeaSWludzik, Jozef chassis, sensorType, 403*4dbb8aeaSWludzik, Jozef [asyncResp, addReportReq]( 404*4dbb8aeaSWludzik, Jozef const boost::beast::http::status status, 405*4dbb8aeaSWludzik, Jozef const boost::container::flat_map<std::string, std::string>& 406*4dbb8aeaSWludzik, Jozef uriToDbus) { 407*4dbb8aeaSWludzik, Jozef if (status != boost::beast::http::status::ok) 408*4dbb8aeaSWludzik, Jozef { 409*4dbb8aeaSWludzik, Jozef BMCWEB_LOG_ERROR << "Failed to retrieve URI to dbus " 410*4dbb8aeaSWludzik, Jozef "sensors map with err " 411*4dbb8aeaSWludzik, Jozef << static_cast<unsigned>(status); 412*4dbb8aeaSWludzik, Jozef return; 413*4dbb8aeaSWludzik, Jozef } 414*4dbb8aeaSWludzik, Jozef addReportReq->insert(uriToDbus); 415*4dbb8aeaSWludzik, Jozef }); 416*4dbb8aeaSWludzik, Jozef } 417*4dbb8aeaSWludzik, Jozef } 418081ebf06SWludzik, Jozef }; 419081ebf06SWludzik, Jozef 420081ebf06SWludzik, Jozef class MetricReportDefinition : public Node 421081ebf06SWludzik, Jozef { 422081ebf06SWludzik, Jozef public: 423081ebf06SWludzik, Jozef MetricReportDefinition(App& app) : 424081ebf06SWludzik, Jozef Node(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/", 425081ebf06SWludzik, Jozef std::string()) 426081ebf06SWludzik, Jozef { 427081ebf06SWludzik, Jozef entityPrivileges = { 428081ebf06SWludzik, Jozef {boost::beast::http::verb::get, {{"Login"}}}, 429081ebf06SWludzik, Jozef {boost::beast::http::verb::head, {{"Login"}}}, 430081ebf06SWludzik, Jozef {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 431081ebf06SWludzik, Jozef {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 432081ebf06SWludzik, Jozef {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 433081ebf06SWludzik, Jozef {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 434081ebf06SWludzik, Jozef } 435081ebf06SWludzik, Jozef 436081ebf06SWludzik, Jozef private: 437081ebf06SWludzik, Jozef void doGet(crow::Response& res, const crow::Request&, 438081ebf06SWludzik, Jozef const std::vector<std::string>& params) override 439081ebf06SWludzik, Jozef { 440081ebf06SWludzik, Jozef auto asyncResp = std::make_shared<AsyncResp>(res); 441081ebf06SWludzik, Jozef 442081ebf06SWludzik, Jozef if (params.size() != 1) 443081ebf06SWludzik, Jozef { 444081ebf06SWludzik, Jozef messages::internalError(asyncResp->res); 445081ebf06SWludzik, Jozef return; 446081ebf06SWludzik, Jozef } 447081ebf06SWludzik, Jozef 448081ebf06SWludzik, Jozef const std::string& id = params[0]; 449081ebf06SWludzik, Jozef crow::connections::systemBus->async_method_call( 450081ebf06SWludzik, Jozef [asyncResp, 451081ebf06SWludzik, Jozef id](const boost::system::error_code ec, 452081ebf06SWludzik, Jozef const std::vector<std::pair< 453081ebf06SWludzik, Jozef std::string, std::variant<std::string, bool, uint64_t, 454081ebf06SWludzik, Jozef telemetry::ReadingParameters>>>& 455081ebf06SWludzik, Jozef ret) { 456081ebf06SWludzik, Jozef if (ec.value() == EBADR || 457081ebf06SWludzik, Jozef ec == boost::system::errc::host_unreachable) 458081ebf06SWludzik, Jozef { 459081ebf06SWludzik, Jozef messages::resourceNotFound(asyncResp->res, 460081ebf06SWludzik, Jozef "MetricReportDefinition", id); 461081ebf06SWludzik, Jozef return; 462081ebf06SWludzik, Jozef } 463081ebf06SWludzik, Jozef if (ec) 464081ebf06SWludzik, Jozef { 465081ebf06SWludzik, Jozef BMCWEB_LOG_ERROR << "respHandler DBus error " << ec; 466081ebf06SWludzik, Jozef messages::internalError(asyncResp->res); 467081ebf06SWludzik, Jozef return; 468081ebf06SWludzik, Jozef } 469081ebf06SWludzik, Jozef 470081ebf06SWludzik, Jozef telemetry::fillReportDefinition(asyncResp, id, ret); 471081ebf06SWludzik, Jozef }, 472081ebf06SWludzik, Jozef telemetry::service, telemetry::getDbusReportPath(id), 473081ebf06SWludzik, Jozef "org.freedesktop.DBus.Properties", "GetAll", 474081ebf06SWludzik, Jozef telemetry::reportInterface); 475081ebf06SWludzik, Jozef } 476*4dbb8aeaSWludzik, Jozef 477*4dbb8aeaSWludzik, Jozef void doDelete(crow::Response& res, const crow::Request&, 478*4dbb8aeaSWludzik, Jozef const std::vector<std::string>& params) override 479*4dbb8aeaSWludzik, Jozef { 480*4dbb8aeaSWludzik, Jozef auto asyncResp = std::make_shared<AsyncResp>(res); 481*4dbb8aeaSWludzik, Jozef if (params.size() != 1) 482*4dbb8aeaSWludzik, Jozef { 483*4dbb8aeaSWludzik, Jozef messages::internalError(asyncResp->res); 484*4dbb8aeaSWludzik, Jozef return; 485*4dbb8aeaSWludzik, Jozef } 486*4dbb8aeaSWludzik, Jozef 487*4dbb8aeaSWludzik, Jozef const std::string& id = params[0]; 488*4dbb8aeaSWludzik, Jozef const std::string reportPath = telemetry::getDbusReportPath(id); 489*4dbb8aeaSWludzik, Jozef 490*4dbb8aeaSWludzik, Jozef crow::connections::systemBus->async_method_call( 491*4dbb8aeaSWludzik, Jozef [asyncResp, id](const boost::system::error_code ec) { 492*4dbb8aeaSWludzik, Jozef /* 493*4dbb8aeaSWludzik, Jozef * boost::system::errc and std::errc are missing value for 494*4dbb8aeaSWludzik, Jozef * EBADR error that is defined in Linux. 495*4dbb8aeaSWludzik, Jozef */ 496*4dbb8aeaSWludzik, Jozef if (ec.value() == EBADR) 497*4dbb8aeaSWludzik, Jozef { 498*4dbb8aeaSWludzik, Jozef messages::resourceNotFound(asyncResp->res, 499*4dbb8aeaSWludzik, Jozef "MetricReportDefinition", id); 500*4dbb8aeaSWludzik, Jozef return; 501*4dbb8aeaSWludzik, Jozef } 502*4dbb8aeaSWludzik, Jozef 503*4dbb8aeaSWludzik, Jozef if (ec) 504*4dbb8aeaSWludzik, Jozef { 505*4dbb8aeaSWludzik, Jozef BMCWEB_LOG_ERROR << "respHandler DBus error " << ec; 506*4dbb8aeaSWludzik, Jozef messages::internalError(asyncResp->res); 507*4dbb8aeaSWludzik, Jozef return; 508*4dbb8aeaSWludzik, Jozef } 509*4dbb8aeaSWludzik, Jozef 510*4dbb8aeaSWludzik, Jozef asyncResp->res.result(boost::beast::http::status::no_content); 511*4dbb8aeaSWludzik, Jozef }, 512*4dbb8aeaSWludzik, Jozef telemetry::service, reportPath, "xyz.openbmc_project.Object.Delete", 513*4dbb8aeaSWludzik, Jozef "Delete"); 514*4dbb8aeaSWludzik, Jozef } 515081ebf06SWludzik, Jozef }; 516081ebf06SWludzik, Jozef } // namespace redfish 517