107148cf2SLukasz Kazmierczak #pragma once 207148cf2SLukasz Kazmierczak 33ccb3adbSEd Tanous #include "app.hpp" 4dd1c4a9cSSzymon Dompke #include "generated/enums/resource.hpp" 5dd1c4a9cSSzymon Dompke #include "generated/enums/triggers.hpp" 63ccb3adbSEd Tanous #include "query.hpp" 73ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 8dd1c4a9cSSzymon Dompke #include "sensors.hpp" 9dd1c4a9cSSzymon Dompke #include "utility.hpp" 1007148cf2SLukasz Kazmierczak #include "utils/collection.hpp" 113ccb3adbSEd Tanous #include "utils/dbus_utils.hpp" 1207148cf2SLukasz Kazmierczak #include "utils/telemetry_utils.hpp" 133ccb3adbSEd Tanous #include "utils/time_utils.hpp" 1407148cf2SLukasz Kazmierczak 15ef4c65b7SEd Tanous #include <boost/url/format.hpp> 1689474494SKrzysztof Grobelny #include <sdbusplus/asio/property.hpp> 1789474494SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp> 1807148cf2SLukasz Kazmierczak 197a1dbc48SGeorge Liu #include <array> 207a1dbc48SGeorge Liu #include <string_view> 211b7e696bSLukasz Kazmierczak #include <tuple> 221b7e696bSLukasz Kazmierczak #include <variant> 231b7e696bSLukasz Kazmierczak #include <vector> 241b7e696bSLukasz Kazmierczak 2507148cf2SLukasz Kazmierczak namespace redfish 2607148cf2SLukasz Kazmierczak { 2707148cf2SLukasz Kazmierczak namespace telemetry 2807148cf2SLukasz Kazmierczak { 2907148cf2SLukasz Kazmierczak constexpr const char* triggerInterface = 3007148cf2SLukasz Kazmierczak "xyz.openbmc_project.Telemetry.Trigger"; 3107148cf2SLukasz Kazmierczak 321b7e696bSLukasz Kazmierczak using NumericThresholdParams = 331b7e696bSLukasz Kazmierczak std::tuple<std::string, uint64_t, std::string, double>; 341b7e696bSLukasz Kazmierczak 351b7e696bSLukasz Kazmierczak using DiscreteThresholdParams = 361b7e696bSLukasz Kazmierczak std::tuple<std::string, std::string, uint64_t, std::string>; 371b7e696bSLukasz Kazmierczak 38dd1c4a9cSSzymon Dompke using TriggerThresholdParams = 39dd1c4a9cSSzymon Dompke std::variant<std::vector<NumericThresholdParams>, 40dd1c4a9cSSzymon Dompke std::vector<DiscreteThresholdParams>>; 41dd1c4a9cSSzymon Dompke 421b7e696bSLukasz Kazmierczak using TriggerThresholdParamsExt = 431b7e696bSLukasz Kazmierczak std::variant<std::monostate, std::vector<NumericThresholdParams>, 441b7e696bSLukasz Kazmierczak std::vector<DiscreteThresholdParams>>; 451b7e696bSLukasz Kazmierczak 461b7e696bSLukasz Kazmierczak using TriggerSensorsParams = 471b7e696bSLukasz Kazmierczak std::vector<std::pair<sdbusplus::message::object_path, std::string>>; 481b7e696bSLukasz Kazmierczak 491b7e696bSLukasz Kazmierczak using TriggerGetParamsVariant = 501b7e696bSLukasz Kazmierczak std::variant<std::monostate, bool, std::string, TriggerThresholdParamsExt, 513f215c92SSzymon Dompke TriggerSensorsParams, std::vector<std::string>, 523f215c92SSzymon Dompke std::vector<sdbusplus::message::object_path>>; 531b7e696bSLukasz Kazmierczak 54dd1c4a9cSSzymon Dompke inline triggers::TriggerActionEnum 55dd1c4a9cSSzymon Dompke toRedfishTriggerAction(std::string_view dbusValue) 561b7e696bSLukasz Kazmierczak { 57dd1c4a9cSSzymon Dompke if (dbusValue == 58dd1c4a9cSSzymon Dompke "xyz.openbmc_project.Telemetry.Trigger.TriggerAction.UpdateReport") 591b7e696bSLukasz Kazmierczak { 60dd1c4a9cSSzymon Dompke return triggers::TriggerActionEnum::RedfishMetricReport; 611b7e696bSLukasz Kazmierczak } 62dd1c4a9cSSzymon Dompke if (dbusValue == 63dd1c4a9cSSzymon Dompke "xyz.openbmc_project.Telemetry.Trigger.TriggerAction.LogToRedfishEventLog") 641b7e696bSLukasz Kazmierczak { 65dd1c4a9cSSzymon Dompke return triggers::TriggerActionEnum::RedfishEvent; 661b7e696bSLukasz Kazmierczak } 67dd1c4a9cSSzymon Dompke if (dbusValue == 68dd1c4a9cSSzymon Dompke "xyz.openbmc_project.Telemetry.Trigger.TriggerAction.LogToJournal") 691b7e696bSLukasz Kazmierczak { 70dd1c4a9cSSzymon Dompke return triggers::TriggerActionEnum::LogToLogService; 711b7e696bSLukasz Kazmierczak } 72dd1c4a9cSSzymon Dompke return triggers::TriggerActionEnum::Invalid; 731b7e696bSLukasz Kazmierczak } 741b7e696bSLukasz Kazmierczak 75dd1c4a9cSSzymon Dompke inline std::string toDbusTriggerAction(std::string_view redfishValue) 761b7e696bSLukasz Kazmierczak { 77dd1c4a9cSSzymon Dompke if (redfishValue == "RedfishMetricReport") 781b7e696bSLukasz Kazmierczak { 79dd1c4a9cSSzymon Dompke return "xyz.openbmc_project.Telemetry.Trigger.TriggerAction.UpdateReport"; 80dd1c4a9cSSzymon Dompke } 81dd1c4a9cSSzymon Dompke if (redfishValue == "RedfishEvent") 82dd1c4a9cSSzymon Dompke { 83dd1c4a9cSSzymon Dompke return "xyz.openbmc_project.Telemetry.Trigger.TriggerAction.LogToRedfishEventLog"; 84dd1c4a9cSSzymon Dompke } 85dd1c4a9cSSzymon Dompke if (redfishValue == "LogToLogService") 86dd1c4a9cSSzymon Dompke { 87dd1c4a9cSSzymon Dompke return "xyz.openbmc_project.Telemetry.Trigger.TriggerAction.LogToJournal"; 88dd1c4a9cSSzymon Dompke } 89dd1c4a9cSSzymon Dompke return ""; 90dd1c4a9cSSzymon Dompke } 911b7e696bSLukasz Kazmierczak 92dd1c4a9cSSzymon Dompke inline std::string toDbusSeverity(std::string_view redfishValue) 93dd1c4a9cSSzymon Dompke { 94dd1c4a9cSSzymon Dompke if (redfishValue == "OK") 95dd1c4a9cSSzymon Dompke { 96dd1c4a9cSSzymon Dompke return "xyz.openbmc_project.Telemetry.Trigger.Severity.OK"; 97dd1c4a9cSSzymon Dompke } 98dd1c4a9cSSzymon Dompke if (redfishValue == "Warning") 99dd1c4a9cSSzymon Dompke { 100dd1c4a9cSSzymon Dompke return "xyz.openbmc_project.Telemetry.Trigger.Severity.Warning"; 101dd1c4a9cSSzymon Dompke } 102dd1c4a9cSSzymon Dompke if (redfishValue == "Critical") 103dd1c4a9cSSzymon Dompke { 104dd1c4a9cSSzymon Dompke return "xyz.openbmc_project.Telemetry.Trigger.Severity.Critical"; 105dd1c4a9cSSzymon Dompke } 106dd1c4a9cSSzymon Dompke return ""; 107dd1c4a9cSSzymon Dompke } 108dd1c4a9cSSzymon Dompke 109dd1c4a9cSSzymon Dompke inline resource::Health toRedfishSeverity(std::string_view dbusValue) 110dd1c4a9cSSzymon Dompke { 111dd1c4a9cSSzymon Dompke if (dbusValue == "xyz.openbmc_project.Telemetry.Trigger.Severity.OK") 112dd1c4a9cSSzymon Dompke { 113dd1c4a9cSSzymon Dompke return resource::Health::OK; 114dd1c4a9cSSzymon Dompke } 115dd1c4a9cSSzymon Dompke if (dbusValue == "xyz.openbmc_project.Telemetry.Trigger.Severity.Warning") 116dd1c4a9cSSzymon Dompke { 117dd1c4a9cSSzymon Dompke return resource::Health::Warning; 118dd1c4a9cSSzymon Dompke } 119dd1c4a9cSSzymon Dompke if (dbusValue == "xyz.openbmc_project.Telemetry.Trigger.Severity.Critical") 120dd1c4a9cSSzymon Dompke { 121dd1c4a9cSSzymon Dompke return resource::Health::Critical; 122dd1c4a9cSSzymon Dompke } 123dd1c4a9cSSzymon Dompke return resource::Health::Invalid; 124dd1c4a9cSSzymon Dompke } 125dd1c4a9cSSzymon Dompke 126dd1c4a9cSSzymon Dompke inline std::string toRedfishThresholdName(std::string_view dbusValue) 127dd1c4a9cSSzymon Dompke { 128dd1c4a9cSSzymon Dompke if (dbusValue == "xyz.openbmc_project.Telemetry.Trigger.Type.UpperCritical") 129dd1c4a9cSSzymon Dompke { 130dd1c4a9cSSzymon Dompke return "UpperCritical"; 131dd1c4a9cSSzymon Dompke } 132dd1c4a9cSSzymon Dompke 133dd1c4a9cSSzymon Dompke if (dbusValue == "xyz.openbmc_project.Telemetry.Trigger.Type.LowerCritical") 134dd1c4a9cSSzymon Dompke { 135dd1c4a9cSSzymon Dompke return "LowerCritical"; 136dd1c4a9cSSzymon Dompke } 137dd1c4a9cSSzymon Dompke 138dd1c4a9cSSzymon Dompke if (dbusValue == "xyz.openbmc_project.Telemetry.Trigger.Type.UpperWarning") 139dd1c4a9cSSzymon Dompke { 140dd1c4a9cSSzymon Dompke return "UpperWarning"; 141dd1c4a9cSSzymon Dompke } 142dd1c4a9cSSzymon Dompke 143dd1c4a9cSSzymon Dompke if (dbusValue == "xyz.openbmc_project.Telemetry.Trigger.Type.LowerWarning") 144dd1c4a9cSSzymon Dompke { 145dd1c4a9cSSzymon Dompke return "LowerWarning"; 146dd1c4a9cSSzymon Dompke } 147dd1c4a9cSSzymon Dompke 148dd1c4a9cSSzymon Dompke return ""; 149dd1c4a9cSSzymon Dompke } 150dd1c4a9cSSzymon Dompke 151dd1c4a9cSSzymon Dompke inline std::string toDbusActivation(std::string_view redfishValue) 152dd1c4a9cSSzymon Dompke { 153dd1c4a9cSSzymon Dompke if (redfishValue == "Either") 154dd1c4a9cSSzymon Dompke { 155dd1c4a9cSSzymon Dompke return "xyz.openbmc_project.Telemetry.Trigger.Direction.Either"; 156dd1c4a9cSSzymon Dompke } 157dd1c4a9cSSzymon Dompke 158dd1c4a9cSSzymon Dompke if (redfishValue == "Decreasing") 159dd1c4a9cSSzymon Dompke { 160dd1c4a9cSSzymon Dompke return "xyz.openbmc_project.Telemetry.Trigger.Direction.Decreasing"; 161dd1c4a9cSSzymon Dompke } 162dd1c4a9cSSzymon Dompke 163dd1c4a9cSSzymon Dompke if (redfishValue == "Increasing") 164dd1c4a9cSSzymon Dompke { 165dd1c4a9cSSzymon Dompke return "xyz.openbmc_project.Telemetry.Trigger.Direction.Increasing"; 166dd1c4a9cSSzymon Dompke } 167dd1c4a9cSSzymon Dompke 168dd1c4a9cSSzymon Dompke return ""; 169dd1c4a9cSSzymon Dompke } 170dd1c4a9cSSzymon Dompke 171dd1c4a9cSSzymon Dompke inline triggers::ThresholdActivation 172dd1c4a9cSSzymon Dompke toRedfishActivation(std::string_view dbusValue) 173dd1c4a9cSSzymon Dompke { 174dd1c4a9cSSzymon Dompke if (dbusValue == "xyz.openbmc_project.Telemetry.Trigger.Direction.Either") 175dd1c4a9cSSzymon Dompke { 176dd1c4a9cSSzymon Dompke return triggers::ThresholdActivation::Either; 177dd1c4a9cSSzymon Dompke } 178dd1c4a9cSSzymon Dompke 179dd1c4a9cSSzymon Dompke if (dbusValue == 180dd1c4a9cSSzymon Dompke "xyz.openbmc_project.Telemetry.Trigger.Direction.Decreasing") 181dd1c4a9cSSzymon Dompke { 182dd1c4a9cSSzymon Dompke return triggers::ThresholdActivation::Decreasing; 183dd1c4a9cSSzymon Dompke } 184dd1c4a9cSSzymon Dompke 185dd1c4a9cSSzymon Dompke if (dbusValue == 186dd1c4a9cSSzymon Dompke "xyz.openbmc_project.Telemetry.Trigger.Direction.Increasing") 187dd1c4a9cSSzymon Dompke { 188dd1c4a9cSSzymon Dompke return triggers::ThresholdActivation::Increasing; 189dd1c4a9cSSzymon Dompke } 190dd1c4a9cSSzymon Dompke 191dd1c4a9cSSzymon Dompke return triggers::ThresholdActivation::Invalid; 192dd1c4a9cSSzymon Dompke } 193dd1c4a9cSSzymon Dompke 194dd1c4a9cSSzymon Dompke enum class MetricType 195dd1c4a9cSSzymon Dompke { 196dd1c4a9cSSzymon Dompke Discrete, 197dd1c4a9cSSzymon Dompke Numeric 198dd1c4a9cSSzymon Dompke }; 199dd1c4a9cSSzymon Dompke 200dd1c4a9cSSzymon Dompke enum class DiscreteCondition 201dd1c4a9cSSzymon Dompke { 202dd1c4a9cSSzymon Dompke Specified, 203dd1c4a9cSSzymon Dompke Changed 204dd1c4a9cSSzymon Dompke }; 205dd1c4a9cSSzymon Dompke 206dd1c4a9cSSzymon Dompke struct Context 207dd1c4a9cSSzymon Dompke { 208dd1c4a9cSSzymon Dompke std::string id; 209dd1c4a9cSSzymon Dompke std::string name; 210dd1c4a9cSSzymon Dompke std::vector<std::string> actions; 211dd1c4a9cSSzymon Dompke std::vector<std::pair<sdbusplus::message::object_path, std::string>> 212dd1c4a9cSSzymon Dompke sensors; 213dd1c4a9cSSzymon Dompke std::vector<sdbusplus::message::object_path> reports; 214dd1c4a9cSSzymon Dompke TriggerThresholdParams thresholds; 215dd1c4a9cSSzymon Dompke 216dd1c4a9cSSzymon Dompke std::optional<DiscreteCondition> discreteCondition; 217dd1c4a9cSSzymon Dompke std::optional<MetricType> metricType; 218dd1c4a9cSSzymon Dompke std::optional<std::vector<std::string>> metricProperties; 219dd1c4a9cSSzymon Dompke }; 220dd1c4a9cSSzymon Dompke 221dd1c4a9cSSzymon Dompke inline std::optional<sdbusplus::message::object_path> 222dd1c4a9cSSzymon Dompke getReportPathFromReportDefinitionUri(const std::string& uri) 223dd1c4a9cSSzymon Dompke { 2246fd29553SEd Tanous boost::system::result<boost::urls::url_view> parsed = 225dd1c4a9cSSzymon Dompke boost::urls::parse_relative_ref(uri); 226dd1c4a9cSSzymon Dompke 227dd1c4a9cSSzymon Dompke if (!parsed) 2281b7e696bSLukasz Kazmierczak { 2291b7e696bSLukasz Kazmierczak return std::nullopt; 2301b7e696bSLukasz Kazmierczak } 2311b7e696bSLukasz Kazmierczak 232dd1c4a9cSSzymon Dompke std::string id; 233dd1c4a9cSSzymon Dompke if (!crow::utility::readUrlSegments( 234dd1c4a9cSSzymon Dompke *parsed, "redfish", "v1", "TelemetryService", 235dd1c4a9cSSzymon Dompke "MetricReportDefinitions", std::ref(id))) 236dd1c4a9cSSzymon Dompke { 237dd1c4a9cSSzymon Dompke return std::nullopt; 2381b7e696bSLukasz Kazmierczak } 2391b7e696bSLukasz Kazmierczak 240dd1c4a9cSSzymon Dompke return sdbusplus::message::object_path( 241dd1c4a9cSSzymon Dompke "/xyz/openbmc_project/Telemetry/Reports") / 242dd1c4a9cSSzymon Dompke "TelemetryService" / id; 243dd1c4a9cSSzymon Dompke } 244dd1c4a9cSSzymon Dompke 245dd1c4a9cSSzymon Dompke inline std::optional<MetricType> getMetricType(const std::string& metricType) 246dd1c4a9cSSzymon Dompke { 247dd1c4a9cSSzymon Dompke if (metricType == "Discrete") 248dd1c4a9cSSzymon Dompke { 249dd1c4a9cSSzymon Dompke return MetricType::Discrete; 250dd1c4a9cSSzymon Dompke } 251dd1c4a9cSSzymon Dompke if (metricType == "Numeric") 252dd1c4a9cSSzymon Dompke { 253dd1c4a9cSSzymon Dompke return MetricType::Numeric; 254dd1c4a9cSSzymon Dompke } 255dd1c4a9cSSzymon Dompke return std::nullopt; 256dd1c4a9cSSzymon Dompke } 257dd1c4a9cSSzymon Dompke 258dd1c4a9cSSzymon Dompke inline std::optional<DiscreteCondition> 259dd1c4a9cSSzymon Dompke getDiscreteCondition(const std::string& discreteTriggerCondition) 260dd1c4a9cSSzymon Dompke { 261dd1c4a9cSSzymon Dompke if (discreteTriggerCondition == "Specified") 262dd1c4a9cSSzymon Dompke { 263dd1c4a9cSSzymon Dompke return DiscreteCondition::Specified; 264dd1c4a9cSSzymon Dompke } 265dd1c4a9cSSzymon Dompke if (discreteTriggerCondition == "Changed") 266dd1c4a9cSSzymon Dompke { 267dd1c4a9cSSzymon Dompke return DiscreteCondition::Changed; 268dd1c4a9cSSzymon Dompke } 269dd1c4a9cSSzymon Dompke return std::nullopt; 270dd1c4a9cSSzymon Dompke } 271dd1c4a9cSSzymon Dompke 272*2932dcb6SEd Tanous inline bool parseThreshold(crow::Response& res, 273*2932dcb6SEd Tanous nlohmann::json::object_t& threshold, 274*2932dcb6SEd Tanous std::string_view dbusThresholdName, 275*2932dcb6SEd Tanous std::vector<NumericThresholdParams>& parsedParams) 276dd1c4a9cSSzymon Dompke { 277dd1c4a9cSSzymon Dompke double reading = 0.0; 278dd1c4a9cSSzymon Dompke std::string activation; 279dd1c4a9cSSzymon Dompke std::string dwellTimeStr; 280dd1c4a9cSSzymon Dompke 281*2932dcb6SEd Tanous if (!json_util::readJsonObject(threshold, res, "Reading", reading, 282dd1c4a9cSSzymon Dompke "Activation", activation, "DwellTime", 283dd1c4a9cSSzymon Dompke dwellTimeStr)) 284dd1c4a9cSSzymon Dompke { 285dd1c4a9cSSzymon Dompke return false; 286dd1c4a9cSSzymon Dompke } 287dd1c4a9cSSzymon Dompke 288dd1c4a9cSSzymon Dompke std::string dbusActivation = toDbusActivation(activation); 289dd1c4a9cSSzymon Dompke 290dd1c4a9cSSzymon Dompke if (dbusActivation.empty()) 291dd1c4a9cSSzymon Dompke { 292dd1c4a9cSSzymon Dompke messages::propertyValueIncorrect(res, "Activation", activation); 293dd1c4a9cSSzymon Dompke return false; 294dd1c4a9cSSzymon Dompke } 295dd1c4a9cSSzymon Dompke 296dd1c4a9cSSzymon Dompke std::optional<std::chrono::milliseconds> dwellTime = 297dd1c4a9cSSzymon Dompke time_utils::fromDurationString(dwellTimeStr); 298dd1c4a9cSSzymon Dompke if (!dwellTime) 299dd1c4a9cSSzymon Dompke { 300dd1c4a9cSSzymon Dompke messages::propertyValueIncorrect(res, "DwellTime", dwellTimeStr); 301dd1c4a9cSSzymon Dompke return false; 302dd1c4a9cSSzymon Dompke } 303dd1c4a9cSSzymon Dompke 304dd1c4a9cSSzymon Dompke parsedParams.emplace_back(dbusThresholdName, 305dd1c4a9cSSzymon Dompke static_cast<uint64_t>(dwellTime->count()), 306dd1c4a9cSSzymon Dompke dbusActivation, reading); 307*2932dcb6SEd Tanous return true; 308*2932dcb6SEd Tanous } 309*2932dcb6SEd Tanous 310*2932dcb6SEd Tanous struct NumericThresholds 311*2932dcb6SEd Tanous { 312*2932dcb6SEd Tanous std::optional<nlohmann::json::object_t> upperCritical; 313*2932dcb6SEd Tanous std::optional<nlohmann::json::object_t> upperWarning; 314*2932dcb6SEd Tanous std::optional<nlohmann::json::object_t> lowerWarning; 315*2932dcb6SEd Tanous std::optional<nlohmann::json::object_t> lowerCritical; 316*2932dcb6SEd Tanous 317*2932dcb6SEd Tanous bool any() const 318*2932dcb6SEd Tanous { 319*2932dcb6SEd Tanous return upperCritical || upperWarning || lowerWarning || lowerCritical; 320*2932dcb6SEd Tanous } 321*2932dcb6SEd Tanous }; 322*2932dcb6SEd Tanous 323*2932dcb6SEd Tanous inline bool parseNumericThresholds(crow::Response& res, 324*2932dcb6SEd Tanous NumericThresholds& numericThresholds, 325*2932dcb6SEd Tanous Context& ctx) 326*2932dcb6SEd Tanous { 327*2932dcb6SEd Tanous std::vector<NumericThresholdParams> parsedParams; 328*2932dcb6SEd Tanous if (numericThresholds.upperCritical) 329*2932dcb6SEd Tanous { 330*2932dcb6SEd Tanous if (!parseThreshold( 331*2932dcb6SEd Tanous res, *numericThresholds.upperCritical, 332*2932dcb6SEd Tanous "xyz.openbmc_project.Telemetry.Trigger.Type.UpperCritical", 333*2932dcb6SEd Tanous parsedParams)) 334*2932dcb6SEd Tanous { 335*2932dcb6SEd Tanous return false; 336*2932dcb6SEd Tanous } 337*2932dcb6SEd Tanous } 338*2932dcb6SEd Tanous if (numericThresholds.upperWarning) 339*2932dcb6SEd Tanous { 340*2932dcb6SEd Tanous if (!parseThreshold( 341*2932dcb6SEd Tanous res, *numericThresholds.upperWarning, 342*2932dcb6SEd Tanous "xyz.openbmc_project.Telemetry.Trigger.Type.UpperWarning", 343*2932dcb6SEd Tanous parsedParams)) 344*2932dcb6SEd Tanous { 345*2932dcb6SEd Tanous return false; 346*2932dcb6SEd Tanous } 347*2932dcb6SEd Tanous } 348*2932dcb6SEd Tanous if (numericThresholds.lowerWarning) 349*2932dcb6SEd Tanous { 350*2932dcb6SEd Tanous if (!parseThreshold( 351*2932dcb6SEd Tanous res, *numericThresholds.lowerWarning, 352*2932dcb6SEd Tanous "xyz.openbmc_project.Telemetry.Trigger.Type.LowerWarning", 353*2932dcb6SEd Tanous parsedParams)) 354*2932dcb6SEd Tanous { 355*2932dcb6SEd Tanous return false; 356*2932dcb6SEd Tanous } 357*2932dcb6SEd Tanous } 358*2932dcb6SEd Tanous if (numericThresholds.lowerCritical) 359*2932dcb6SEd Tanous { 360*2932dcb6SEd Tanous if (!parseThreshold( 361*2932dcb6SEd Tanous res, *numericThresholds.lowerCritical, 362*2932dcb6SEd Tanous "xyz.openbmc_project.Telemetry.Trigger.Type.LowerCritical", 363*2932dcb6SEd Tanous parsedParams)) 364*2932dcb6SEd Tanous { 365*2932dcb6SEd Tanous return false; 366*2932dcb6SEd Tanous } 367dd1c4a9cSSzymon Dompke } 368dd1c4a9cSSzymon Dompke 369dd1c4a9cSSzymon Dompke ctx.thresholds = std::move(parsedParams); 370dd1c4a9cSSzymon Dompke return true; 371dd1c4a9cSSzymon Dompke } 372dd1c4a9cSSzymon Dompke 373dd1c4a9cSSzymon Dompke inline bool parseDiscreteTriggers( 374dd1c4a9cSSzymon Dompke crow::Response& res, 375*2932dcb6SEd Tanous std::optional<std::vector<nlohmann::json::object_t>>& discreteTriggers, 376*2932dcb6SEd Tanous Context& ctx) 377dd1c4a9cSSzymon Dompke { 378dd1c4a9cSSzymon Dompke std::vector<DiscreteThresholdParams> parsedParams; 379dd1c4a9cSSzymon Dompke if (!discreteTriggers) 380dd1c4a9cSSzymon Dompke { 381dd1c4a9cSSzymon Dompke ctx.thresholds = std::move(parsedParams); 382dd1c4a9cSSzymon Dompke return true; 383dd1c4a9cSSzymon Dompke } 384dd1c4a9cSSzymon Dompke 385dd1c4a9cSSzymon Dompke parsedParams.reserve(discreteTriggers->size()); 386*2932dcb6SEd Tanous for (nlohmann::json::object_t& thresholdInfo : *discreteTriggers) 387dd1c4a9cSSzymon Dompke { 388dd1c4a9cSSzymon Dompke std::optional<std::string> name = ""; 389dd1c4a9cSSzymon Dompke std::string value; 390dd1c4a9cSSzymon Dompke std::string dwellTimeStr; 391dd1c4a9cSSzymon Dompke std::string severity; 392dd1c4a9cSSzymon Dompke 393*2932dcb6SEd Tanous if (!json_util::readJsonObject(thresholdInfo, res, "Name", name, 394*2932dcb6SEd Tanous "Value", value, "DwellTime", 395*2932dcb6SEd Tanous dwellTimeStr, "Severity", severity)) 396dd1c4a9cSSzymon Dompke { 397dd1c4a9cSSzymon Dompke return false; 398dd1c4a9cSSzymon Dompke } 399dd1c4a9cSSzymon Dompke 400dd1c4a9cSSzymon Dompke std::optional<std::chrono::milliseconds> dwellTime = 401dd1c4a9cSSzymon Dompke time_utils::fromDurationString(dwellTimeStr); 402dd1c4a9cSSzymon Dompke if (!dwellTime) 403dd1c4a9cSSzymon Dompke { 404dd1c4a9cSSzymon Dompke messages::propertyValueIncorrect(res, "DwellTime", dwellTimeStr); 405dd1c4a9cSSzymon Dompke return false; 406dd1c4a9cSSzymon Dompke } 407dd1c4a9cSSzymon Dompke 408dd1c4a9cSSzymon Dompke std::string dbusSeverity = toDbusSeverity(severity); 409dd1c4a9cSSzymon Dompke if (dbusSeverity.empty()) 410dd1c4a9cSSzymon Dompke { 411dd1c4a9cSSzymon Dompke messages::propertyValueIncorrect(res, "Severity", severity); 412dd1c4a9cSSzymon Dompke return false; 413dd1c4a9cSSzymon Dompke } 414dd1c4a9cSSzymon Dompke 415dd1c4a9cSSzymon Dompke parsedParams.emplace_back(*name, dbusSeverity, 416dd1c4a9cSSzymon Dompke static_cast<uint64_t>(dwellTime->count()), 417dd1c4a9cSSzymon Dompke value); 418dd1c4a9cSSzymon Dompke } 419dd1c4a9cSSzymon Dompke 420dd1c4a9cSSzymon Dompke ctx.thresholds = std::move(parsedParams); 421dd1c4a9cSSzymon Dompke return true; 422dd1c4a9cSSzymon Dompke } 423dd1c4a9cSSzymon Dompke 424dd1c4a9cSSzymon Dompke inline bool parseTriggerThresholds( 425dd1c4a9cSSzymon Dompke crow::Response& res, 426*2932dcb6SEd Tanous std::optional<std::vector<nlohmann::json::object_t>>& discreteTriggers, 427*2932dcb6SEd Tanous NumericThresholds& numericThresholds, Context& ctx) 428dd1c4a9cSSzymon Dompke { 429*2932dcb6SEd Tanous if (discreteTriggers && numericThresholds.any()) 430dd1c4a9cSSzymon Dompke { 431dd1c4a9cSSzymon Dompke messages::propertyValueConflict(res, "DiscreteTriggers", 432dd1c4a9cSSzymon Dompke "NumericThresholds"); 433dd1c4a9cSSzymon Dompke messages::propertyValueConflict(res, "NumericThresholds", 434dd1c4a9cSSzymon Dompke "DiscreteTriggers"); 435dd1c4a9cSSzymon Dompke return false; 436dd1c4a9cSSzymon Dompke } 437dd1c4a9cSSzymon Dompke 438dd1c4a9cSSzymon Dompke if (ctx.discreteCondition) 439dd1c4a9cSSzymon Dompke { 440*2932dcb6SEd Tanous if (numericThresholds.any()) 441dd1c4a9cSSzymon Dompke { 442dd1c4a9cSSzymon Dompke messages::propertyValueConflict(res, "DiscreteTriggerCondition", 443dd1c4a9cSSzymon Dompke "NumericThresholds"); 444dd1c4a9cSSzymon Dompke messages::propertyValueConflict(res, "NumericThresholds", 445dd1c4a9cSSzymon Dompke "DiscreteTriggerCondition"); 446dd1c4a9cSSzymon Dompke return false; 447dd1c4a9cSSzymon Dompke } 448dd1c4a9cSSzymon Dompke } 449dd1c4a9cSSzymon Dompke 450dd1c4a9cSSzymon Dompke if (ctx.metricType) 451dd1c4a9cSSzymon Dompke { 452*2932dcb6SEd Tanous if (*ctx.metricType == MetricType::Discrete && numericThresholds.any()) 453dd1c4a9cSSzymon Dompke { 454dd1c4a9cSSzymon Dompke messages::propertyValueConflict(res, "NumericThresholds", 455dd1c4a9cSSzymon Dompke "MetricType"); 456dd1c4a9cSSzymon Dompke return false; 457dd1c4a9cSSzymon Dompke } 458dd1c4a9cSSzymon Dompke if (*ctx.metricType == MetricType::Numeric && discreteTriggers) 459dd1c4a9cSSzymon Dompke { 460dd1c4a9cSSzymon Dompke messages::propertyValueConflict(res, "DiscreteTriggers", 461dd1c4a9cSSzymon Dompke "MetricType"); 462dd1c4a9cSSzymon Dompke return false; 463dd1c4a9cSSzymon Dompke } 464dd1c4a9cSSzymon Dompke if (*ctx.metricType == MetricType::Numeric && ctx.discreteCondition) 465dd1c4a9cSSzymon Dompke { 466dd1c4a9cSSzymon Dompke messages::propertyValueConflict(res, "DiscreteTriggers", 467dd1c4a9cSSzymon Dompke "DiscreteTriggerCondition"); 468dd1c4a9cSSzymon Dompke return false; 469dd1c4a9cSSzymon Dompke } 470dd1c4a9cSSzymon Dompke } 471dd1c4a9cSSzymon Dompke 472dd1c4a9cSSzymon Dompke if (discreteTriggers || ctx.discreteCondition || 473dd1c4a9cSSzymon Dompke (ctx.metricType && *ctx.metricType == MetricType::Discrete)) 474dd1c4a9cSSzymon Dompke { 475dd1c4a9cSSzymon Dompke if (ctx.discreteCondition) 476dd1c4a9cSSzymon Dompke { 477dd1c4a9cSSzymon Dompke if (*ctx.discreteCondition == DiscreteCondition::Specified && 478dd1c4a9cSSzymon Dompke !discreteTriggers) 479dd1c4a9cSSzymon Dompke { 480dd1c4a9cSSzymon Dompke messages::createFailedMissingReqProperties(res, 481dd1c4a9cSSzymon Dompke "DiscreteTriggers"); 482dd1c4a9cSSzymon Dompke return false; 483dd1c4a9cSSzymon Dompke } 484dd1c4a9cSSzymon Dompke if (discreteTriggers && 485dd1c4a9cSSzymon Dompke ((*ctx.discreteCondition == DiscreteCondition::Specified && 486dd1c4a9cSSzymon Dompke discreteTriggers->empty()) || 487dd1c4a9cSSzymon Dompke (*ctx.discreteCondition == DiscreteCondition::Changed && 488dd1c4a9cSSzymon Dompke !discreteTriggers->empty()))) 489dd1c4a9cSSzymon Dompke { 490dd1c4a9cSSzymon Dompke messages::propertyValueConflict(res, "DiscreteTriggers", 491dd1c4a9cSSzymon Dompke "DiscreteTriggerCondition"); 492dd1c4a9cSSzymon Dompke return false; 493dd1c4a9cSSzymon Dompke } 494dd1c4a9cSSzymon Dompke } 495dd1c4a9cSSzymon Dompke if (!parseDiscreteTriggers(res, discreteTriggers, ctx)) 496dd1c4a9cSSzymon Dompke { 497dd1c4a9cSSzymon Dompke return false; 498dd1c4a9cSSzymon Dompke } 499dd1c4a9cSSzymon Dompke } 500*2932dcb6SEd Tanous else if (numericThresholds.any()) 501dd1c4a9cSSzymon Dompke { 502*2932dcb6SEd Tanous if (!parseNumericThresholds(res, numericThresholds, ctx)) 503dd1c4a9cSSzymon Dompke { 504dd1c4a9cSSzymon Dompke return false; 505dd1c4a9cSSzymon Dompke } 506dd1c4a9cSSzymon Dompke } 507dd1c4a9cSSzymon Dompke else 508dd1c4a9cSSzymon Dompke { 509dd1c4a9cSSzymon Dompke messages::createFailedMissingReqProperties( 510dd1c4a9cSSzymon Dompke res, "'DiscreteTriggers', 'NumericThresholds', " 511dd1c4a9cSSzymon Dompke "'DiscreteTriggerCondition' or 'MetricType'"); 512dd1c4a9cSSzymon Dompke return false; 513dd1c4a9cSSzymon Dompke } 514dd1c4a9cSSzymon Dompke return true; 515dd1c4a9cSSzymon Dompke } 516dd1c4a9cSSzymon Dompke 517*2932dcb6SEd Tanous inline bool parseLinks(crow::Response& res, 518*2932dcb6SEd Tanous const std::vector<std::string>& metricReportDefinitions, 519*2932dcb6SEd Tanous Context& ctx) 520dd1c4a9cSSzymon Dompke { 521*2932dcb6SEd Tanous ctx.reports.reserve(metricReportDefinitions.size()); 522*2932dcb6SEd Tanous for (const std::string& reportDefinionUri : metricReportDefinitions) 523dd1c4a9cSSzymon Dompke { 524dd1c4a9cSSzymon Dompke std::optional<sdbusplus::message::object_path> reportPath = 525dd1c4a9cSSzymon Dompke getReportPathFromReportDefinitionUri(reportDefinionUri); 526dd1c4a9cSSzymon Dompke if (!reportPath) 527dd1c4a9cSSzymon Dompke { 528dd1c4a9cSSzymon Dompke messages::propertyValueIncorrect(res, "MetricReportDefinitions", 529dd1c4a9cSSzymon Dompke reportDefinionUri); 530dd1c4a9cSSzymon Dompke return false; 531dd1c4a9cSSzymon Dompke } 532dd1c4a9cSSzymon Dompke ctx.reports.emplace_back(*reportPath); 533dd1c4a9cSSzymon Dompke } 534dd1c4a9cSSzymon Dompke return true; 535dd1c4a9cSSzymon Dompke } 536dd1c4a9cSSzymon Dompke 537dd1c4a9cSSzymon Dompke inline bool parseMetricProperties(crow::Response& res, Context& ctx) 538dd1c4a9cSSzymon Dompke { 539dd1c4a9cSSzymon Dompke if (!ctx.metricProperties) 540dd1c4a9cSSzymon Dompke { 541dd1c4a9cSSzymon Dompke return true; 542dd1c4a9cSSzymon Dompke } 543dd1c4a9cSSzymon Dompke 544dd1c4a9cSSzymon Dompke ctx.sensors.reserve(ctx.metricProperties->size()); 545dd1c4a9cSSzymon Dompke 546dd1c4a9cSSzymon Dompke size_t uriIdx = 0; 547dd1c4a9cSSzymon Dompke for (const std::string& uriStr : *ctx.metricProperties) 548dd1c4a9cSSzymon Dompke { 5496fd29553SEd Tanous boost::system::result<boost::urls::url_view> uri = 550dd1c4a9cSSzymon Dompke boost::urls::parse_relative_ref(uriStr); 551dd1c4a9cSSzymon Dompke if (!uri) 552dd1c4a9cSSzymon Dompke { 553dd1c4a9cSSzymon Dompke messages::propertyValueIncorrect( 554dd1c4a9cSSzymon Dompke res, "MetricProperties/" + std::to_string(uriIdx), uriStr); 555dd1c4a9cSSzymon Dompke return false; 556dd1c4a9cSSzymon Dompke } 557dd1c4a9cSSzymon Dompke std::string chassisName; 558dd1c4a9cSSzymon Dompke std::string sensorName; 559dd1c4a9cSSzymon Dompke if (!crow::utility::readUrlSegments(*uri, "redfish", "v1", "Chassis", 560dd1c4a9cSSzymon Dompke std::ref(chassisName), "Sensors", 561dd1c4a9cSSzymon Dompke std::ref(sensorName))) 562dd1c4a9cSSzymon Dompke { 563dd1c4a9cSSzymon Dompke messages::propertyValueIncorrect( 564dd1c4a9cSSzymon Dompke res, "MetricProperties/" + std::to_string(uriIdx), uriStr); 565dd1c4a9cSSzymon Dompke return false; 566dd1c4a9cSSzymon Dompke } 567dd1c4a9cSSzymon Dompke 568dd1c4a9cSSzymon Dompke std::pair<std::string, std::string> split = 569dd1c4a9cSSzymon Dompke splitSensorNameAndType(sensorName); 570dd1c4a9cSSzymon Dompke if (split.first.empty() || split.second.empty()) 571dd1c4a9cSSzymon Dompke { 572dd1c4a9cSSzymon Dompke messages::propertyValueIncorrect( 573dd1c4a9cSSzymon Dompke res, "MetricProperties/" + std::to_string(uriIdx), uriStr); 574dd1c4a9cSSzymon Dompke return false; 575dd1c4a9cSSzymon Dompke } 576dd1c4a9cSSzymon Dompke 577dd1c4a9cSSzymon Dompke std::string sensorPath = "/xyz/openbmc_project/sensors/" + split.first + 578dd1c4a9cSSzymon Dompke '/' + split.second; 579dd1c4a9cSSzymon Dompke 580dd1c4a9cSSzymon Dompke ctx.sensors.emplace_back(sensorPath, uriStr); 581dd1c4a9cSSzymon Dompke uriIdx++; 582dd1c4a9cSSzymon Dompke } 583dd1c4a9cSSzymon Dompke return true; 584dd1c4a9cSSzymon Dompke } 585dd1c4a9cSSzymon Dompke 586dd1c4a9cSSzymon Dompke inline bool parsePostTriggerParams(crow::Response& res, 587dd1c4a9cSSzymon Dompke const crow::Request& req, Context& ctx) 588dd1c4a9cSSzymon Dompke { 589dd1c4a9cSSzymon Dompke std::optional<std::string> id = ""; 590dd1c4a9cSSzymon Dompke std::optional<std::string> name = ""; 591dd1c4a9cSSzymon Dompke std::optional<std::string> metricType; 592dd1c4a9cSSzymon Dompke std::optional<std::vector<std::string>> triggerActions; 593dd1c4a9cSSzymon Dompke std::optional<std::string> discreteTriggerCondition; 594*2932dcb6SEd Tanous std::optional<std::vector<nlohmann::json::object_t>> discreteTriggers; 595*2932dcb6SEd Tanous std::optional<std::vector<std::string>> metricReportDefinitions; 596*2932dcb6SEd Tanous NumericThresholds thresholds; 597*2932dcb6SEd Tanous // clang-format off 598dd1c4a9cSSzymon Dompke if (!json_util::readJsonPatch( 599*2932dcb6SEd Tanous req, res, 600*2932dcb6SEd Tanous "Id", id, 601*2932dcb6SEd Tanous "Name", name, 602*2932dcb6SEd Tanous "MetricType", metricType, 603*2932dcb6SEd Tanous "TriggerActions", triggerActions, 604*2932dcb6SEd Tanous "DiscreteTriggerCondition", discreteTriggerCondition, 605*2932dcb6SEd Tanous "DiscreteTriggers", discreteTriggers, 606*2932dcb6SEd Tanous "NumericThresholds/UpperCritical", thresholds.upperCritical, 607*2932dcb6SEd Tanous "NumericThresholds/UpperWarning", thresholds.upperWarning, 608*2932dcb6SEd Tanous "NumericThresholds/LowerWarning", thresholds.lowerWarning, 609*2932dcb6SEd Tanous "NumericThresholds/LowerCritical", thresholds.lowerCritical, 610*2932dcb6SEd Tanous "MetricProperties", ctx.metricProperties, 611*2932dcb6SEd Tanous "Links/MetricReportDefinitions", metricReportDefinitions) 612*2932dcb6SEd Tanous ) 613dd1c4a9cSSzymon Dompke { 614dd1c4a9cSSzymon Dompke return false; 615dd1c4a9cSSzymon Dompke } 616*2932dcb6SEd Tanous // clang-format on 617dd1c4a9cSSzymon Dompke 618dd1c4a9cSSzymon Dompke ctx.id = *id; 619dd1c4a9cSSzymon Dompke ctx.name = *name; 620dd1c4a9cSSzymon Dompke 621dd1c4a9cSSzymon Dompke if (metricType) 622dd1c4a9cSSzymon Dompke { 623d5736ef2SEd Tanous ctx.metricType = getMetricType(*metricType); 624d5736ef2SEd Tanous if (!ctx.metricType) 625dd1c4a9cSSzymon Dompke { 626dd1c4a9cSSzymon Dompke messages::propertyValueIncorrect(res, "MetricType", *metricType); 627dd1c4a9cSSzymon Dompke return false; 628dd1c4a9cSSzymon Dompke } 629dd1c4a9cSSzymon Dompke } 630dd1c4a9cSSzymon Dompke 631dd1c4a9cSSzymon Dompke if (discreteTriggerCondition) 632dd1c4a9cSSzymon Dompke { 633d5736ef2SEd Tanous ctx.discreteCondition = getDiscreteCondition(*discreteTriggerCondition); 634d5736ef2SEd Tanous if (!ctx.discreteCondition) 635dd1c4a9cSSzymon Dompke { 636dd1c4a9cSSzymon Dompke messages::propertyValueIncorrect(res, "DiscreteTriggerCondition", 637dd1c4a9cSSzymon Dompke *discreteTriggerCondition); 638dd1c4a9cSSzymon Dompke return false; 639dd1c4a9cSSzymon Dompke } 640dd1c4a9cSSzymon Dompke } 641dd1c4a9cSSzymon Dompke 642dd1c4a9cSSzymon Dompke if (triggerActions) 643dd1c4a9cSSzymon Dompke { 644dd1c4a9cSSzymon Dompke ctx.actions.reserve(triggerActions->size()); 645dd1c4a9cSSzymon Dompke for (const std::string& action : *triggerActions) 646dd1c4a9cSSzymon Dompke { 647dd1c4a9cSSzymon Dompke std::string dbusAction = toDbusTriggerAction(action); 648dd1c4a9cSSzymon Dompke 649dd1c4a9cSSzymon Dompke if (dbusAction.empty()) 650dd1c4a9cSSzymon Dompke { 651dd1c4a9cSSzymon Dompke messages::propertyValueNotInList(res, action, "TriggerActions"); 652dd1c4a9cSSzymon Dompke return false; 653dd1c4a9cSSzymon Dompke } 654dd1c4a9cSSzymon Dompke 655dd1c4a9cSSzymon Dompke ctx.actions.emplace_back(dbusAction); 656dd1c4a9cSSzymon Dompke } 657dd1c4a9cSSzymon Dompke } 658dd1c4a9cSSzymon Dompke if (!parseMetricProperties(res, ctx)) 659dd1c4a9cSSzymon Dompke { 660dd1c4a9cSSzymon Dompke return false; 661dd1c4a9cSSzymon Dompke } 662dd1c4a9cSSzymon Dompke 663*2932dcb6SEd Tanous if (!parseTriggerThresholds(res, discreteTriggers, thresholds, ctx)) 664dd1c4a9cSSzymon Dompke { 665dd1c4a9cSSzymon Dompke return false; 666dd1c4a9cSSzymon Dompke } 667dd1c4a9cSSzymon Dompke 668*2932dcb6SEd Tanous if (metricReportDefinitions) 669dd1c4a9cSSzymon Dompke { 670*2932dcb6SEd Tanous if (!parseLinks(res, *metricReportDefinitions, ctx)) 671dd1c4a9cSSzymon Dompke { 672dd1c4a9cSSzymon Dompke return false; 673dd1c4a9cSSzymon Dompke } 674dd1c4a9cSSzymon Dompke } 675dd1c4a9cSSzymon Dompke return true; 676dd1c4a9cSSzymon Dompke } 677dd1c4a9cSSzymon Dompke 678dd1c4a9cSSzymon Dompke inline void afterCreateTrigger( 679dd1c4a9cSSzymon Dompke const boost::system::error_code& ec, const std::string& dbusPath, 680dd1c4a9cSSzymon Dompke const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id) 681dd1c4a9cSSzymon Dompke { 682dd1c4a9cSSzymon Dompke if (ec == boost::system::errc::file_exists) 683dd1c4a9cSSzymon Dompke { 684dd1c4a9cSSzymon Dompke messages::resourceAlreadyExists(asyncResp->res, "Trigger", "Id", id); 685dd1c4a9cSSzymon Dompke return; 686dd1c4a9cSSzymon Dompke } 687dd1c4a9cSSzymon Dompke if (ec == boost::system::errc::too_many_files_open) 688dd1c4a9cSSzymon Dompke { 689dd1c4a9cSSzymon Dompke messages::createLimitReachedForResource(asyncResp->res); 690dd1c4a9cSSzymon Dompke return; 691dd1c4a9cSSzymon Dompke } 692dd1c4a9cSSzymon Dompke if (ec) 693dd1c4a9cSSzymon Dompke { 694dd1c4a9cSSzymon Dompke messages::internalError(asyncResp->res); 69562598e31SEd Tanous BMCWEB_LOG_ERROR("respHandler DBus error {}", ec); 696dd1c4a9cSSzymon Dompke return; 697dd1c4a9cSSzymon Dompke } 698dd1c4a9cSSzymon Dompke 699dd1c4a9cSSzymon Dompke const std::optional<std::string>& triggerId = 700dd1c4a9cSSzymon Dompke getTriggerIdFromDbusPath(dbusPath); 701dd1c4a9cSSzymon Dompke if (!triggerId) 702dd1c4a9cSSzymon Dompke { 703dd1c4a9cSSzymon Dompke messages::internalError(asyncResp->res); 70462598e31SEd Tanous BMCWEB_LOG_ERROR("Unknown data returned by " 70562598e31SEd Tanous "AddTrigger DBus method"); 706dd1c4a9cSSzymon Dompke return; 707dd1c4a9cSSzymon Dompke } 708dd1c4a9cSSzymon Dompke 709dd1c4a9cSSzymon Dompke messages::created(asyncResp->res); 710dd1c4a9cSSzymon Dompke boost::urls::url locationUrl = boost::urls::format( 711dd1c4a9cSSzymon Dompke "/redfish/v1/TelemetryService/Triggers/{}", *triggerId); 712dd1c4a9cSSzymon Dompke asyncResp->res.addHeader("Location", locationUrl.buffer()); 713dd1c4a9cSSzymon Dompke } 714dd1c4a9cSSzymon Dompke 715dd1c4a9cSSzymon Dompke inline std::optional<nlohmann::json::array_t> 716dd1c4a9cSSzymon Dompke getTriggerActions(const std::vector<std::string>& dbusActions) 717dd1c4a9cSSzymon Dompke { 718dd1c4a9cSSzymon Dompke nlohmann::json::array_t triggerActions; 719dd1c4a9cSSzymon Dompke for (const std::string& dbusAction : dbusActions) 720dd1c4a9cSSzymon Dompke { 721dd1c4a9cSSzymon Dompke triggers::TriggerActionEnum redfishAction = 722dd1c4a9cSSzymon Dompke toRedfishTriggerAction(dbusAction); 723dd1c4a9cSSzymon Dompke 724dd1c4a9cSSzymon Dompke if (redfishAction == triggers::TriggerActionEnum::Invalid) 725dd1c4a9cSSzymon Dompke { 726dd1c4a9cSSzymon Dompke return std::nullopt; 727dd1c4a9cSSzymon Dompke } 728dd1c4a9cSSzymon Dompke 729dd1c4a9cSSzymon Dompke triggerActions.emplace_back(redfishAction); 730dd1c4a9cSSzymon Dompke } 731dd1c4a9cSSzymon Dompke 732dd1c4a9cSSzymon Dompke return triggerActions; 7331b7e696bSLukasz Kazmierczak } 7341b7e696bSLukasz Kazmierczak 7353f215c92SSzymon Dompke inline std::optional<nlohmann::json::array_t> 7361b7e696bSLukasz Kazmierczak getDiscreteTriggers(const TriggerThresholdParamsExt& thresholdParams) 7371b7e696bSLukasz Kazmierczak { 738dd1c4a9cSSzymon Dompke nlohmann::json::array_t triggers; 7391b7e696bSLukasz Kazmierczak const std::vector<DiscreteThresholdParams>* discreteParams = 7401b7e696bSLukasz Kazmierczak std::get_if<std::vector<DiscreteThresholdParams>>(&thresholdParams); 7411b7e696bSLukasz Kazmierczak 742e662eae8SEd Tanous if (discreteParams == nullptr) 7431b7e696bSLukasz Kazmierczak { 7441b7e696bSLukasz Kazmierczak return std::nullopt; 7451b7e696bSLukasz Kazmierczak } 7461b7e696bSLukasz Kazmierczak 7471b7e696bSLukasz Kazmierczak for (const auto& [name, severity, dwellTime, value] : *discreteParams) 7481b7e696bSLukasz Kazmierczak { 7491b7e696bSLukasz Kazmierczak std::optional<std::string> duration = 7501b7e696bSLukasz Kazmierczak time_utils::toDurationStringFromUint(dwellTime); 7511b7e696bSLukasz Kazmierczak 7521b7e696bSLukasz Kazmierczak if (!duration) 7531b7e696bSLukasz Kazmierczak { 7541b7e696bSLukasz Kazmierczak return std::nullopt; 7551b7e696bSLukasz Kazmierczak } 756613dabeaSEd Tanous nlohmann::json::object_t trigger; 757613dabeaSEd Tanous trigger["Name"] = name; 758dd1c4a9cSSzymon Dompke trigger["Severity"] = toRedfishSeverity(severity); 759613dabeaSEd Tanous trigger["DwellTime"] = *duration; 760613dabeaSEd Tanous trigger["Value"] = value; 761ad539545SPatrick Williams triggers.emplace_back(std::move(trigger)); 7621b7e696bSLukasz Kazmierczak } 7631b7e696bSLukasz Kazmierczak 764dd1c4a9cSSzymon Dompke return triggers; 7651b7e696bSLukasz Kazmierczak } 7661b7e696bSLukasz Kazmierczak 7671b7e696bSLukasz Kazmierczak inline std::optional<nlohmann::json> 7681b7e696bSLukasz Kazmierczak getNumericThresholds(const TriggerThresholdParamsExt& thresholdParams) 7691b7e696bSLukasz Kazmierczak { 770dd1c4a9cSSzymon Dompke nlohmann::json::object_t thresholds; 7711b7e696bSLukasz Kazmierczak const std::vector<NumericThresholdParams>* numericParams = 7721b7e696bSLukasz Kazmierczak std::get_if<std::vector<NumericThresholdParams>>(&thresholdParams); 7731b7e696bSLukasz Kazmierczak 774e662eae8SEd Tanous if (numericParams == nullptr) 7751b7e696bSLukasz Kazmierczak { 7761b7e696bSLukasz Kazmierczak return std::nullopt; 7771b7e696bSLukasz Kazmierczak } 7781b7e696bSLukasz Kazmierczak 7791b7e696bSLukasz Kazmierczak for (const auto& [type, dwellTime, activation, reading] : *numericParams) 7801b7e696bSLukasz Kazmierczak { 7811b7e696bSLukasz Kazmierczak std::optional<std::string> duration = 7821b7e696bSLukasz Kazmierczak time_utils::toDurationStringFromUint(dwellTime); 7831b7e696bSLukasz Kazmierczak 7841b7e696bSLukasz Kazmierczak if (!duration) 7851b7e696bSLukasz Kazmierczak { 7861b7e696bSLukasz Kazmierczak return std::nullopt; 7871b7e696bSLukasz Kazmierczak } 788dd1c4a9cSSzymon Dompke nlohmann::json& threshold = thresholds[toRedfishThresholdName(type)]; 7891476687dSEd Tanous threshold["Reading"] = reading; 790dd1c4a9cSSzymon Dompke threshold["Activation"] = toRedfishActivation(activation); 7911476687dSEd Tanous threshold["DwellTime"] = *duration; 7921b7e696bSLukasz Kazmierczak } 7931b7e696bSLukasz Kazmierczak 794dd1c4a9cSSzymon Dompke return thresholds; 7951b7e696bSLukasz Kazmierczak } 7961b7e696bSLukasz Kazmierczak 7973f215c92SSzymon Dompke inline std::optional<nlohmann::json> getMetricReportDefinitions( 7983f215c92SSzymon Dompke const std::vector<sdbusplus::message::object_path>& reportPaths) 7991b7e696bSLukasz Kazmierczak { 8001b7e696bSLukasz Kazmierczak nlohmann::json reports = nlohmann::json::array(); 8013f215c92SSzymon Dompke 8023f215c92SSzymon Dompke for (const sdbusplus::message::object_path& path : reportPaths) 8031b7e696bSLukasz Kazmierczak { 8043f215c92SSzymon Dompke std::string reportId = path.filename(); 8053f215c92SSzymon Dompke if (reportId.empty()) 8063f215c92SSzymon Dompke { 8073f215c92SSzymon Dompke { 80862598e31SEd Tanous BMCWEB_LOG_ERROR("Property Reports contains invalid value: {}", 80962598e31SEd Tanous path.str); 8103f215c92SSzymon Dompke return std::nullopt; 8113f215c92SSzymon Dompke } 8123f215c92SSzymon Dompke } 8133f215c92SSzymon Dompke 8141476687dSEd Tanous nlohmann::json::object_t report; 815ef4c65b7SEd Tanous report["@odata.id"] = boost::urls::format( 816ef4c65b7SEd Tanous "/redfish/v1/TelemetryService/MetricReportDefinitions/{}", 817ef4c65b7SEd Tanous reportId); 818b2ba3072SPatrick Williams reports.emplace_back(std::move(report)); 8191b7e696bSLukasz Kazmierczak } 8201b7e696bSLukasz Kazmierczak 8213f215c92SSzymon Dompke return {std::move(reports)}; 8221b7e696bSLukasz Kazmierczak } 8231b7e696bSLukasz Kazmierczak 8241b7e696bSLukasz Kazmierczak inline std::vector<std::string> 8251b7e696bSLukasz Kazmierczak getMetricProperties(const TriggerSensorsParams& sensors) 8261b7e696bSLukasz Kazmierczak { 8271b7e696bSLukasz Kazmierczak std::vector<std::string> metricProperties; 8281b7e696bSLukasz Kazmierczak metricProperties.reserve(sensors.size()); 8291b7e696bSLukasz Kazmierczak for (const auto& [_, metadata] : sensors) 8301b7e696bSLukasz Kazmierczak { 8311b7e696bSLukasz Kazmierczak metricProperties.emplace_back(metadata); 8321b7e696bSLukasz Kazmierczak } 8331b7e696bSLukasz Kazmierczak 8341b7e696bSLukasz Kazmierczak return metricProperties; 8351b7e696bSLukasz Kazmierczak } 8361b7e696bSLukasz Kazmierczak 8371b7e696bSLukasz Kazmierczak inline bool fillTrigger( 8381b7e696bSLukasz Kazmierczak nlohmann::json& json, const std::string& id, 8391b7e696bSLukasz Kazmierczak const std::vector<std::pair<std::string, TriggerGetParamsVariant>>& 8401b7e696bSLukasz Kazmierczak properties) 8411b7e696bSLukasz Kazmierczak { 8421b7e696bSLukasz Kazmierczak const std::string* name = nullptr; 8431b7e696bSLukasz Kazmierczak const bool* discrete = nullptr; 8441b7e696bSLukasz Kazmierczak const TriggerSensorsParams* sensors = nullptr; 8453f215c92SSzymon Dompke const std::vector<sdbusplus::message::object_path>* reports = nullptr; 84689474494SKrzysztof Grobelny const std::vector<std::string>* triggerActions = nullptr; 8471b7e696bSLukasz Kazmierczak const TriggerThresholdParamsExt* thresholds = nullptr; 8481b7e696bSLukasz Kazmierczak 84989474494SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 85089474494SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), properties, "Name", name, "Discrete", 85189474494SKrzysztof Grobelny discrete, "Sensors", sensors, "Reports", reports, "TriggerActions", 85289474494SKrzysztof Grobelny triggerActions, "Thresholds", thresholds); 85389474494SKrzysztof Grobelny 85489474494SKrzysztof Grobelny if (!success) 8551b7e696bSLukasz Kazmierczak { 85689474494SKrzysztof Grobelny return false; 8571b7e696bSLukasz Kazmierczak } 8581b7e696bSLukasz Kazmierczak 85989474494SKrzysztof Grobelny if (triggerActions != nullptr) 86089474494SKrzysztof Grobelny { 861dd1c4a9cSSzymon Dompke std::optional<nlohmann::json::array_t> redfishTriggerActions = 86289474494SKrzysztof Grobelny getTriggerActions(*triggerActions); 86389474494SKrzysztof Grobelny if (!redfishTriggerActions) 8641b7e696bSLukasz Kazmierczak { 86562598e31SEd Tanous BMCWEB_LOG_ERROR( 86662598e31SEd Tanous "Property TriggerActions is invalid in Trigger: {}", id); 8671b7e696bSLukasz Kazmierczak return false; 8681b7e696bSLukasz Kazmierczak } 869dd1c4a9cSSzymon Dompke json["TriggerActions"] = *redfishTriggerActions; 87089474494SKrzysztof Grobelny } 8711b7e696bSLukasz Kazmierczak 87289474494SKrzysztof Grobelny if (reports != nullptr) 8733f215c92SSzymon Dompke { 8743f215c92SSzymon Dompke std::optional<nlohmann::json> linkedReports = 8753f215c92SSzymon Dompke getMetricReportDefinitions(*reports); 8763f215c92SSzymon Dompke if (!linkedReports) 8773f215c92SSzymon Dompke { 87862598e31SEd Tanous BMCWEB_LOG_ERROR("Property Reports is invalid in Trigger: {}", id); 8793f215c92SSzymon Dompke return false; 8803f215c92SSzymon Dompke } 88189474494SKrzysztof Grobelny json["Links"]["MetricReportDefinitions"] = *linkedReports; 88289474494SKrzysztof Grobelny } 8831b7e696bSLukasz Kazmierczak 88489474494SKrzysztof Grobelny if (discrete != nullptr) 88589474494SKrzysztof Grobelny { 8861b7e696bSLukasz Kazmierczak if (*discrete) 8871b7e696bSLukasz Kazmierczak { 8883f215c92SSzymon Dompke std::optional<nlohmann::json::array_t> discreteTriggers = 8891b7e696bSLukasz Kazmierczak getDiscreteTriggers(*thresholds); 8901b7e696bSLukasz Kazmierczak 8911b7e696bSLukasz Kazmierczak if (!discreteTriggers) 8921b7e696bSLukasz Kazmierczak { 89362598e31SEd Tanous BMCWEB_LOG_ERROR("Property Thresholds is invalid for discrete " 89462598e31SEd Tanous "triggers in Trigger: {}", 89562598e31SEd Tanous id); 8961b7e696bSLukasz Kazmierczak return false; 8971b7e696bSLukasz Kazmierczak } 8981b7e696bSLukasz Kazmierczak 8991b7e696bSLukasz Kazmierczak json["DiscreteTriggers"] = *discreteTriggers; 9001b7e696bSLukasz Kazmierczak json["DiscreteTriggerCondition"] = 9011b7e696bSLukasz Kazmierczak discreteTriggers->empty() ? "Changed" : "Specified"; 9021b7e696bSLukasz Kazmierczak json["MetricType"] = "Discrete"; 9031b7e696bSLukasz Kazmierczak } 9041b7e696bSLukasz Kazmierczak else 9051b7e696bSLukasz Kazmierczak { 9061b7e696bSLukasz Kazmierczak std::optional<nlohmann::json> numericThresholds = 9071b7e696bSLukasz Kazmierczak getNumericThresholds(*thresholds); 9081b7e696bSLukasz Kazmierczak 9091b7e696bSLukasz Kazmierczak if (!numericThresholds) 9101b7e696bSLukasz Kazmierczak { 91162598e31SEd Tanous BMCWEB_LOG_ERROR("Property Thresholds is invalid for numeric " 91262598e31SEd Tanous "thresholds in Trigger: {}", 91362598e31SEd Tanous id); 9141b7e696bSLukasz Kazmierczak return false; 9151b7e696bSLukasz Kazmierczak } 9161b7e696bSLukasz Kazmierczak 9171b7e696bSLukasz Kazmierczak json["NumericThresholds"] = *numericThresholds; 9181b7e696bSLukasz Kazmierczak json["MetricType"] = "Numeric"; 9191b7e696bSLukasz Kazmierczak } 92089474494SKrzysztof Grobelny } 92189474494SKrzysztof Grobelny 92289474494SKrzysztof Grobelny if (name != nullptr) 92389474494SKrzysztof Grobelny { 92489474494SKrzysztof Grobelny json["Name"] = *name; 92589474494SKrzysztof Grobelny } 92689474494SKrzysztof Grobelny 92789474494SKrzysztof Grobelny if (sensors != nullptr) 92889474494SKrzysztof Grobelny { 92989474494SKrzysztof Grobelny json["MetricProperties"] = getMetricProperties(*sensors); 93089474494SKrzysztof Grobelny } 9311b7e696bSLukasz Kazmierczak 9323f215c92SSzymon Dompke json["@odata.type"] = "#Triggers.v1_2_0.Triggers"; 933ef4c65b7SEd Tanous json["@odata.id"] = 934ef4c65b7SEd Tanous boost::urls::format("/redfish/v1/TelemetryService/Triggers/{}", id); 9353f215c92SSzymon Dompke json["Id"] = id; 9361b7e696bSLukasz Kazmierczak 9371b7e696bSLukasz Kazmierczak return true; 9381b7e696bSLukasz Kazmierczak } 9391b7e696bSLukasz Kazmierczak 940dd1c4a9cSSzymon Dompke inline void handleTriggerCollectionPost( 941dd1c4a9cSSzymon Dompke App& app, const crow::Request& req, 942dd1c4a9cSSzymon Dompke const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 943dd1c4a9cSSzymon Dompke { 944dd1c4a9cSSzymon Dompke if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 945dd1c4a9cSSzymon Dompke { 946dd1c4a9cSSzymon Dompke return; 947dd1c4a9cSSzymon Dompke } 948dd1c4a9cSSzymon Dompke 949dd1c4a9cSSzymon Dompke telemetry::Context ctx; 950dd1c4a9cSSzymon Dompke if (!telemetry::parsePostTriggerParams(asyncResp->res, req, ctx)) 951dd1c4a9cSSzymon Dompke { 952dd1c4a9cSSzymon Dompke return; 953dd1c4a9cSSzymon Dompke } 954dd1c4a9cSSzymon Dompke 955dd1c4a9cSSzymon Dompke crow::connections::systemBus->async_method_call( 956dd1c4a9cSSzymon Dompke [asyncResp, id = ctx.id](const boost::system::error_code& ec, 957dd1c4a9cSSzymon Dompke const std::string& dbusPath) { 958dd1c4a9cSSzymon Dompke afterCreateTrigger(ec, dbusPath, asyncResp, id); 959dd1c4a9cSSzymon Dompke }, 960dd1c4a9cSSzymon Dompke service, "/xyz/openbmc_project/Telemetry/Triggers", 961dd1c4a9cSSzymon Dompke "xyz.openbmc_project.Telemetry.TriggerManager", "AddTrigger", 962dd1c4a9cSSzymon Dompke "TelemetryService/" + ctx.id, ctx.name, ctx.actions, ctx.sensors, 963dd1c4a9cSSzymon Dompke ctx.reports, ctx.thresholds); 964dd1c4a9cSSzymon Dompke } 965dd1c4a9cSSzymon Dompke 96607148cf2SLukasz Kazmierczak } // namespace telemetry 96707148cf2SLukasz Kazmierczak 96807148cf2SLukasz Kazmierczak inline void requestRoutesTriggerCollection(App& app) 96907148cf2SLukasz Kazmierczak { 97007148cf2SLukasz Kazmierczak BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/Triggers/") 97107148cf2SLukasz Kazmierczak .privileges(redfish::privileges::getTriggersCollection) 97207148cf2SLukasz Kazmierczak .methods(boost::beast::http::verb::get)( 97345ca1b86SEd Tanous [&app](const crow::Request& req, 97407148cf2SLukasz Kazmierczak const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 9753ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 97645ca1b86SEd Tanous { 97745ca1b86SEd Tanous return; 97845ca1b86SEd Tanous } 97907148cf2SLukasz Kazmierczak asyncResp->res.jsonValue["@odata.type"] = 98007148cf2SLukasz Kazmierczak "#TriggersCollection.TriggersCollection"; 981ae9031f0SWilly Tu asyncResp->res.jsonValue["@odata.id"] = 982ae9031f0SWilly Tu "/redfish/v1/TelemetryService/Triggers"; 98307148cf2SLukasz Kazmierczak asyncResp->res.jsonValue["Name"] = "Triggers Collection"; 9847a1dbc48SGeorge Liu constexpr std::array<std::string_view, 1> interfaces{ 9857a1dbc48SGeorge Liu telemetry::triggerInterface}; 98607148cf2SLukasz Kazmierczak collection_util::getCollectionMembers( 987ae9031f0SWilly Tu asyncResp, 988ae9031f0SWilly Tu boost::urls::url("/redfish/v1/TelemetryService/Triggers"), 989ae9031f0SWilly Tu interfaces, 99007148cf2SLukasz Kazmierczak "/xyz/openbmc_project/Telemetry/Triggers/TelemetryService"); 99107148cf2SLukasz Kazmierczak }); 992dd1c4a9cSSzymon Dompke 993dd1c4a9cSSzymon Dompke BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/Triggers/") 994dd1c4a9cSSzymon Dompke .privileges(redfish::privileges::postTriggersCollection) 995dd1c4a9cSSzymon Dompke .methods(boost::beast::http::verb::post)(std::bind_front( 996dd1c4a9cSSzymon Dompke telemetry::handleTriggerCollectionPost, std::ref(app))); 99707148cf2SLukasz Kazmierczak } 99807148cf2SLukasz Kazmierczak 9991b7e696bSLukasz Kazmierczak inline void requestRoutesTrigger(App& app) 10001b7e696bSLukasz Kazmierczak { 10011b7e696bSLukasz Kazmierczak BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/Triggers/<str>/") 10021b7e696bSLukasz Kazmierczak .privileges(redfish::privileges::getTriggers) 10031b7e696bSLukasz Kazmierczak .methods(boost::beast::http::verb::get)( 100445ca1b86SEd Tanous [&app](const crow::Request& req, 10051b7e696bSLukasz Kazmierczak const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 10061b7e696bSLukasz Kazmierczak const std::string& id) { 10073ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 100845ca1b86SEd Tanous { 100945ca1b86SEd Tanous return; 101045ca1b86SEd Tanous } 101189474494SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 101289474494SKrzysztof Grobelny *crow::connections::systemBus, telemetry::service, 101389474494SKrzysztof Grobelny telemetry::getDbusTriggerPath(id), telemetry::triggerInterface, 10141b7e696bSLukasz Kazmierczak [asyncResp, 10155e7e2dc5SEd Tanous id](const boost::system::error_code& ec, 10161b7e696bSLukasz Kazmierczak const std::vector<std::pair< 1017002d39b4SEd Tanous std::string, telemetry::TriggerGetParamsVariant>>& ret) { 10181b7e696bSLukasz Kazmierczak if (ec.value() == EBADR || 10191b7e696bSLukasz Kazmierczak ec == boost::system::errc::host_unreachable) 10201b7e696bSLukasz Kazmierczak { 1021002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "Triggers", id); 10221b7e696bSLukasz Kazmierczak return; 10231b7e696bSLukasz Kazmierczak } 10241b7e696bSLukasz Kazmierczak if (ec) 10251b7e696bSLukasz Kazmierczak { 102662598e31SEd Tanous BMCWEB_LOG_ERROR("respHandler DBus error {}", ec); 10271b7e696bSLukasz Kazmierczak messages::internalError(asyncResp->res); 10281b7e696bSLukasz Kazmierczak return; 10291b7e696bSLukasz Kazmierczak } 10301b7e696bSLukasz Kazmierczak 1031002d39b4SEd Tanous if (!telemetry::fillTrigger(asyncResp->res.jsonValue, id, ret)) 10321b7e696bSLukasz Kazmierczak { 10331b7e696bSLukasz Kazmierczak messages::internalError(asyncResp->res); 10341b7e696bSLukasz Kazmierczak } 103589474494SKrzysztof Grobelny }); 10361b7e696bSLukasz Kazmierczak }); 1037163994a8SSzymon Dompke 1038163994a8SSzymon Dompke BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/Triggers/<str>/") 1039163994a8SSzymon Dompke .privileges(redfish::privileges::deleteTriggers) 1040163994a8SSzymon Dompke .methods(boost::beast::http::verb::delete_)( 104145ca1b86SEd Tanous [&app](const crow::Request& req, 1042163994a8SSzymon Dompke const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1043163994a8SSzymon Dompke const std::string& id) { 10443ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 104545ca1b86SEd Tanous { 104645ca1b86SEd Tanous return; 104745ca1b86SEd Tanous } 1048002d39b4SEd Tanous const std::string triggerPath = telemetry::getDbusTriggerPath(id); 1049163994a8SSzymon Dompke 1050163994a8SSzymon Dompke crow::connections::systemBus->async_method_call( 10515e7e2dc5SEd Tanous [asyncResp, id](const boost::system::error_code& ec) { 1052163994a8SSzymon Dompke if (ec.value() == EBADR) 1053163994a8SSzymon Dompke { 1054002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "Triggers", id); 1055163994a8SSzymon Dompke return; 1056163994a8SSzymon Dompke } 1057163994a8SSzymon Dompke 1058163994a8SSzymon Dompke if (ec) 1059163994a8SSzymon Dompke { 106062598e31SEd Tanous BMCWEB_LOG_ERROR("respHandler DBus error {}", ec); 1061163994a8SSzymon Dompke messages::internalError(asyncResp->res); 1062163994a8SSzymon Dompke return; 1063163994a8SSzymon Dompke } 1064163994a8SSzymon Dompke 1065002d39b4SEd Tanous asyncResp->res.result(boost::beast::http::status::no_content); 1066163994a8SSzymon Dompke }, 1067163994a8SSzymon Dompke telemetry::service, triggerPath, 1068163994a8SSzymon Dompke "xyz.openbmc_project.Object.Delete", "Delete"); 1069163994a8SSzymon Dompke }); 10701b7e696bSLukasz Kazmierczak } 10711b7e696bSLukasz Kazmierczak 107207148cf2SLukasz Kazmierczak } // namespace redfish 1073