| Lewanczyk, Dawid | c5b2abe | 2018-05-30 16:59:42 +0200 | [diff] [blame] | 1 | /* | 
|  | 2 | // Copyright (c) 2018 Intel Corporation | 
|  | 3 | // | 
|  | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | 5 | // you may not use this file except in compliance with the License. | 
|  | 6 | // You may obtain a copy of the License at | 
|  | 7 | // | 
|  | 8 | //      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | 9 | // | 
|  | 10 | // Unless required by applicable law or agreed to in writing, software | 
|  | 11 | // distributed under the License is distributed on an "AS IS" BASIS, | 
|  | 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | 13 | // See the License for the specific language governing permissions and | 
|  | 14 | // limitations under the License. | 
|  | 15 | */ | 
|  | 16 | #pragma once | 
|  | 17 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame^] | 18 | #include "boost/container/flat_map.hpp" | 
|  | 19 | #include "node.hpp" | 
|  | 20 |  | 
| Lewanczyk, Dawid | c5b2abe | 2018-05-30 16:59:42 +0200 | [diff] [blame] | 21 | #include <error_messages.hpp> | 
|  | 22 | #include <utils/json_utils.hpp> | 
| Lewanczyk, Dawid | c5b2abe | 2018-05-30 16:59:42 +0200 | [diff] [blame] | 23 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame^] | 24 | namespace redfish | 
|  | 25 | { | 
| Lewanczyk, Dawid | c5b2abe | 2018-05-30 16:59:42 +0200 | [diff] [blame] | 26 |  | 
|  | 27 | /** | 
|  | 28 | * SystemAsyncResp | 
|  | 29 | * Gathers data needed for response processing after async calls are done | 
|  | 30 | */ | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame^] | 31 | class SystemAsyncResp | 
|  | 32 | { | 
|  | 33 | public: | 
|  | 34 | SystemAsyncResp(crow::Response &response) : res(response) | 
|  | 35 | { | 
| Lewanczyk, Dawid | c5b2abe | 2018-05-30 16:59:42 +0200 | [diff] [blame] | 36 | } | 
| Lewanczyk, Dawid | c5b2abe | 2018-05-30 16:59:42 +0200 | [diff] [blame] | 37 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame^] | 38 | ~SystemAsyncResp() | 
|  | 39 | { | 
|  | 40 | if (res.result() != (boost::beast::http::status::ok)) | 
|  | 41 | { | 
|  | 42 | // Reset the json object to clear out any data that made it in | 
|  | 43 | // before the error happened todo(ed) handle error condition with | 
|  | 44 | // proper code | 
|  | 45 | res.jsonValue = messages::internalError(); | 
|  | 46 | } | 
|  | 47 | res.end(); | 
|  | 48 | } | 
| Lewanczyk, Dawid | c5b2abe | 2018-05-30 16:59:42 +0200 | [diff] [blame] | 49 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame^] | 50 | void setErrorStatus() | 
|  | 51 | { | 
|  | 52 | res.result(boost::beast::http::status::internal_server_error); | 
|  | 53 | } | 
|  | 54 |  | 
|  | 55 | crow::Response &res; | 
| Lewanczyk, Dawid | c5b2abe | 2018-05-30 16:59:42 +0200 | [diff] [blame] | 56 | }; | 
|  | 57 |  | 
|  | 58 | /** | 
|  | 59 | * OnDemandSystemsProvider | 
|  | 60 | * Board provider class that retrieves data directly from dbus, before seting | 
|  | 61 | * it into JSON output. This does not cache any data. | 
|  | 62 | * | 
|  | 63 | * Class can be a good example on how to scale different data providing | 
|  | 64 | * solutions to produce single schema output. | 
|  | 65 | * | 
|  | 66 | * TODO(Pawel) | 
|  | 67 | * This perhaps shall be different file, which has to be chosen on compile time | 
|  | 68 | * depending on OEM needs | 
|  | 69 | */ | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame^] | 70 | class OnDemandSystemsProvider | 
|  | 71 | { | 
|  | 72 | public: | 
|  | 73 | template <typename CallbackFunc> | 
|  | 74 | void getBaseboardList(CallbackFunc &&callback) | 
|  | 75 | { | 
|  | 76 | BMCWEB_LOG_DEBUG << "Get list of available boards."; | 
|  | 77 | crow::connections::systemBus->async_method_call( | 
|  | 78 | [callback{std::move(callback)}]( | 
|  | 79 | const boost::system::error_code ec, | 
|  | 80 | const std::vector<std::string> &resp) { | 
|  | 81 | // Callback requires vector<string> to retrieve all available | 
|  | 82 | // board list. | 
|  | 83 | std::vector<std::string> boardList; | 
|  | 84 | if (ec) | 
|  | 85 | { | 
|  | 86 | // Something wrong on DBus, the error_code is not important | 
|  | 87 | // at this moment, just return success=false, and empty | 
|  | 88 | // output. Since size of vector may vary depending on | 
|  | 89 | // information from Entity Manager, and empty output could | 
|  | 90 | // not be treated same way as error. | 
|  | 91 | callback(false, boardList); | 
|  | 92 | return; | 
|  | 93 | } | 
|  | 94 | BMCWEB_LOG_DEBUG << "Got " << resp.size() << " boards."; | 
|  | 95 | // Iterate over all retrieved ObjectPaths. | 
|  | 96 | for (const std::string &objpath : resp) | 
|  | 97 | { | 
|  | 98 | std::size_t lastPos = objpath.rfind("/"); | 
|  | 99 | if (lastPos != std::string::npos) | 
|  | 100 | { | 
|  | 101 | boardList.emplace_back(objpath.substr(lastPos + 1)); | 
|  | 102 | } | 
|  | 103 | } | 
|  | 104 | // Finally make a callback with useful data | 
|  | 105 | callback(true, boardList); | 
|  | 106 | }, | 
|  | 107 | "xyz.openbmc_project.ObjectMapper", | 
|  | 108 | "/xyz/openbmc_project/object_mapper", | 
|  | 109 | "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", | 
|  | 110 | "/xyz/openbmc_project/inventory", int32_t(0), | 
|  | 111 | std::array<const char *, 1>{ | 
|  | 112 | "xyz.openbmc_project.Inventory.Item.Board"}); | 
| Lewanczyk, Dawid | c5b2abe | 2018-05-30 16:59:42 +0200 | [diff] [blame] | 113 | }; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame^] | 114 |  | 
|  | 115 | /** | 
|  | 116 | * @brief Retrieves computer system properties over dbus | 
|  | 117 | * | 
|  | 118 | * @param[in] aResp Shared pointer for completing asynchronous calls | 
|  | 119 | * @param[in] name  Computer system name from request | 
|  | 120 | * | 
|  | 121 | * @return None. | 
|  | 122 | */ | 
|  | 123 | void getComputerSystem(std::shared_ptr<SystemAsyncResp> aResp, | 
|  | 124 | const std::string &name) | 
|  | 125 | { | 
|  | 126 | const std::array<const char *, 5> interfaces = { | 
|  | 127 | "xyz.openbmc_project.Inventory.Decorator.Asset", | 
|  | 128 | "xyz.openbmc_project.Inventory.Item.Cpu", | 
|  | 129 | "xyz.openbmc_project.Inventory.Item.Dimm", | 
|  | 130 | "xyz.openbmc_project.Inventory.Item.System", | 
|  | 131 | "xyz.openbmc_project.Common.UUID", | 
|  | 132 | }; | 
|  | 133 | BMCWEB_LOG_DEBUG << "Get available system components."; | 
|  | 134 | crow::connections::systemBus->async_method_call( | 
|  | 135 | [name, aResp{std::move(aResp)}]( | 
|  | 136 | const boost::system::error_code ec, | 
|  | 137 | const std::vector<std::pair< | 
|  | 138 | std::string, std::vector<std::pair< | 
|  | 139 | std::string, std::vector<std::string>>>>> | 
|  | 140 | &subtree) { | 
|  | 141 | if (ec) | 
|  | 142 | { | 
|  | 143 | BMCWEB_LOG_DEBUG << "DBUS response error"; | 
|  | 144 | aResp->setErrorStatus(); | 
|  | 145 | return; | 
|  | 146 | } | 
|  | 147 | bool foundName = false; | 
|  | 148 | // Iterate over all retrieved ObjectPaths. | 
|  | 149 | for (const std::pair< | 
|  | 150 | std::string, | 
|  | 151 | std::vector< | 
|  | 152 | std::pair<std::string, std::vector<std::string>>>> | 
|  | 153 | &object : subtree) | 
|  | 154 | { | 
|  | 155 | const std::string &path = object.first; | 
|  | 156 | BMCWEB_LOG_DEBUG << "Got path: " << path; | 
|  | 157 | const std::vector< | 
|  | 158 | std::pair<std::string, std::vector<std::string>>> | 
|  | 159 | &connectionNames = object.second; | 
|  | 160 | if (connectionNames.size() < 1) | 
|  | 161 | { | 
|  | 162 | continue; | 
| Lewanczyk, Dawid | c5b2abe | 2018-05-30 16:59:42 +0200 | [diff] [blame] | 163 | } | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame^] | 164 | // Check if computer system exist | 
|  | 165 | if (boost::ends_with(path, name)) | 
|  | 166 | { | 
|  | 167 | foundName = true; | 
|  | 168 | BMCWEB_LOG_DEBUG << "Found name: " << name; | 
|  | 169 | const std::string connectionName = | 
|  | 170 | connectionNames[0].first; | 
|  | 171 | crow::connections::systemBus->async_method_call( | 
|  | 172 | [aResp, name(std::string(name))]( | 
|  | 173 | const boost::system::error_code ec, | 
|  | 174 | const std::vector< | 
|  | 175 | std::pair<std::string, VariantType>> | 
|  | 176 | &propertiesList) { | 
|  | 177 | if (ec) | 
|  | 178 | { | 
|  | 179 | BMCWEB_LOG_ERROR << "DBUS response error: " | 
|  | 180 | << ec; | 
|  | 181 | aResp->setErrorStatus(); | 
|  | 182 | return; | 
| Lewanczyk, Dawid | c5b2abe | 2018-05-30 16:59:42 +0200 | [diff] [blame] | 183 | } | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame^] | 184 | BMCWEB_LOG_DEBUG << "Got " | 
|  | 185 | << propertiesList.size() | 
|  | 186 | << "properties for system"; | 
|  | 187 | for (const std::pair<std::string, VariantType> | 
|  | 188 | &property : propertiesList) | 
|  | 189 | { | 
|  | 190 | const std::string *value = | 
|  | 191 | mapbox::getPtr<const std::string>( | 
|  | 192 | property.second); | 
|  | 193 | if (value != nullptr) | 
|  | 194 | { | 
|  | 195 | aResp->res.jsonValue[property.first] = | 
|  | 196 | *value; | 
|  | 197 | } | 
| Lewanczyk, Dawid | c5b2abe | 2018-05-30 16:59:42 +0200 | [diff] [blame] | 198 | } | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame^] | 199 | aResp->res.jsonValue["Name"] = name; | 
|  | 200 | aResp->res.jsonValue["Id"] = | 
|  | 201 | aResp->res.jsonValue["SerialNumber"]; | 
|  | 202 | }, | 
|  | 203 | connectionName, path, | 
|  | 204 | "org.freedesktop.DBus.Properties", "GetAll", | 
|  | 205 | "xyz.openbmc_project.Inventory.Decorator.Asset"); | 
|  | 206 | } | 
|  | 207 | else | 
|  | 208 | { | 
|  | 209 | // This is not system, so check if it's cpu, dimm, UUID | 
|  | 210 | // or BiosVer | 
|  | 211 | for (auto const &s : connectionNames) | 
|  | 212 | { | 
|  | 213 | for (auto const &i : s.second) | 
|  | 214 | { | 
|  | 215 | if (boost::ends_with(i, "Dimm")) | 
|  | 216 | { | 
|  | 217 | BMCWEB_LOG_DEBUG | 
|  | 218 | << "Found Dimm, now get it properties."; | 
|  | 219 | crow::connections::systemBus->async_method_call( | 
|  | 220 | [&, aResp]( | 
|  | 221 | const boost::system::error_code ec, | 
|  | 222 | const std::vector<std::pair< | 
|  | 223 | std::string, VariantType>> | 
|  | 224 | &properties) { | 
|  | 225 | if (ec) | 
|  | 226 | { | 
|  | 227 | BMCWEB_LOG_ERROR | 
|  | 228 | << "DBUS response error " | 
|  | 229 | << ec; | 
|  | 230 | aResp->setErrorStatus(); | 
|  | 231 | return; | 
|  | 232 | } | 
|  | 233 | BMCWEB_LOG_DEBUG | 
|  | 234 | << "Got " << properties.size() | 
|  | 235 | << "Dimm properties."; | 
|  | 236 | for (const auto &p : properties) | 
|  | 237 | { | 
|  | 238 | if (p.first == "MemorySize") | 
|  | 239 | { | 
|  | 240 | const std::string *value = | 
|  | 241 | mapbox::getPtr< | 
|  | 242 | const std::string>( | 
|  | 243 | p.second); | 
|  | 244 | if ((value != nullptr) && | 
|  | 245 | (*value != "NULL")) | 
|  | 246 | { | 
|  | 247 | // Remove units char | 
|  | 248 | int32_t unitCoeff; | 
|  | 249 | if (boost::ends_with( | 
|  | 250 | *value, "MB")) | 
|  | 251 | { | 
|  | 252 | unitCoeff = 1000; | 
|  | 253 | } | 
|  | 254 | else if (boost:: | 
|  | 255 | ends_with( | 
|  | 256 | *value, | 
|  | 257 | "KB")) | 
|  | 258 | { | 
|  | 259 | unitCoeff = 1000000; | 
|  | 260 | } | 
|  | 261 | else | 
|  | 262 | { | 
|  | 263 | BMCWEB_LOG_ERROR | 
|  | 264 | << "Unsupported" | 
|  | 265 | " memory " | 
|  | 266 | "units"; | 
|  | 267 | aResp | 
|  | 268 | ->setErrorStatus(); | 
|  | 269 | return; | 
|  | 270 | } | 
|  | 271 |  | 
|  | 272 | auto memSize = | 
|  | 273 | boost::lexical_cast< | 
|  | 274 | int>(value->substr( | 
|  | 275 | 0, | 
|  | 276 | value->length() - | 
|  | 277 | 2)); | 
|  | 278 | aResp->res.jsonValue | 
|  | 279 | ["TotalSystemMemory" | 
|  | 280 | "GiB"] += | 
|  | 281 | memSize * unitCoeff; | 
|  | 282 | aResp->res.jsonValue | 
|  | 283 | ["MemorySummary"] | 
|  | 284 | ["Status"] | 
|  | 285 | ["State"] = | 
|  | 286 | "Enabled"; | 
|  | 287 | } | 
|  | 288 | } | 
|  | 289 | } | 
|  | 290 | }, | 
|  | 291 | s.first, path, | 
|  | 292 | "org.freedesktop.DBus.Properties", | 
|  | 293 | "GetAll", | 
|  | 294 | "xyz.openbmc_project.Inventory.Item." | 
|  | 295 | "Dimm"); | 
|  | 296 | } | 
|  | 297 | else if (boost::ends_with(i, "Cpu")) | 
|  | 298 | { | 
|  | 299 | BMCWEB_LOG_DEBUG | 
|  | 300 | << "Found Cpu, now get it properties."; | 
|  | 301 | crow::connections::systemBus | 
|  | 302 | ->async_method_call( | 
|  | 303 | [&, aResp]( | 
|  | 304 | const boost::system::error_code | 
|  | 305 | ec, | 
|  | 306 | const std::vector<std::pair< | 
|  | 307 | std::string, VariantType>> | 
|  | 308 | &properties) { | 
|  | 309 | if (ec) | 
|  | 310 | { | 
|  | 311 | BMCWEB_LOG_ERROR | 
|  | 312 | << "DBUS response " | 
|  | 313 | "error " | 
|  | 314 | << ec; | 
|  | 315 | aResp->setErrorStatus(); | 
|  | 316 | return; | 
|  | 317 | } | 
|  | 318 | BMCWEB_LOG_DEBUG | 
|  | 319 | << "Got " | 
|  | 320 | << properties.size() | 
|  | 321 | << "Cpu properties."; | 
|  | 322 | for (const auto &p : properties) | 
|  | 323 | { | 
|  | 324 | if (p.first == | 
|  | 325 | "ProcessorFamily") | 
|  | 326 | { | 
|  | 327 | const std::string | 
|  | 328 | *value = | 
|  | 329 | mapbox::getPtr< | 
|  | 330 | const std:: | 
|  | 331 | string>( | 
|  | 332 | p.second); | 
|  | 333 | if (value != nullptr) | 
|  | 334 | { | 
|  | 335 | aResp->res.jsonValue | 
|  | 336 | ["ProcessorSumm" | 
|  | 337 | "ary"] | 
|  | 338 | ["Count"] = | 
|  | 339 | aResp->res | 
|  | 340 | .jsonValue | 
|  | 341 | ["Proce" | 
|  | 342 | "ssorS" | 
|  | 343 | "ummar" | 
|  | 344 | "y"] | 
|  | 345 | ["Coun" | 
|  | 346 | "t"] | 
|  | 347 | .get< | 
|  | 348 | int>() + | 
|  | 349 | 1; | 
|  | 350 | aResp->res.jsonValue | 
|  | 351 | ["ProcessorSumm" | 
|  | 352 | "ary"] | 
|  | 353 | ["Status"] | 
|  | 354 | ["State"] = | 
|  | 355 | "Enabled"; | 
|  | 356 | aResp->res.jsonValue | 
|  | 357 | ["ProcessorSumm" | 
|  | 358 | "ary"] | 
|  | 359 | ["Model"] = | 
|  | 360 | *value; | 
|  | 361 | } | 
|  | 362 | } | 
|  | 363 | } | 
|  | 364 | }, | 
|  | 365 | s.first, path, | 
|  | 366 | "org.freedesktop.DBus.Properties", | 
|  | 367 | "GetAll", | 
|  | 368 | "xyz.openbmc_project.Inventory." | 
|  | 369 | "Item.Cpu"); | 
|  | 370 | } | 
|  | 371 | else if (boost::ends_with(i, "UUID")) | 
|  | 372 | { | 
|  | 373 | BMCWEB_LOG_DEBUG | 
|  | 374 | << "Found UUID, now get it properties."; | 
|  | 375 | crow::connections::systemBus->async_method_call( | 
|  | 376 | [aResp]( | 
|  | 377 | const boost::system::error_code ec, | 
|  | 378 | const std::vector<std::pair< | 
|  | 379 | std::string, VariantType>> | 
|  | 380 | &properties) { | 
|  | 381 | if (ec) | 
|  | 382 | { | 
|  | 383 | BMCWEB_LOG_DEBUG | 
|  | 384 | << "DBUS response error " | 
|  | 385 | << ec; | 
|  | 386 | aResp->setErrorStatus(); | 
|  | 387 | return; | 
|  | 388 | } | 
|  | 389 | BMCWEB_LOG_DEBUG | 
|  | 390 | << "Got " << properties.size() | 
|  | 391 | << "UUID properties."; | 
|  | 392 | for (const std::pair<std::string, | 
|  | 393 | VariantType> | 
|  | 394 | &p : properties) | 
|  | 395 | { | 
|  | 396 | if (p.first == "BIOSVer") | 
|  | 397 | { | 
|  | 398 | const std::string *value = | 
|  | 399 | mapbox::getPtr< | 
|  | 400 | const std::string>( | 
|  | 401 | p.second); | 
|  | 402 | if (value != nullptr) | 
|  | 403 | { | 
|  | 404 | aResp->res.jsonValue | 
|  | 405 | ["BiosVersion"] = | 
|  | 406 | *value; | 
|  | 407 | } | 
|  | 408 | } | 
|  | 409 | if (p.first == "UUID") | 
|  | 410 | { | 
|  | 411 | const std::string *value = | 
|  | 412 | mapbox::getPtr< | 
|  | 413 | const std::string>( | 
|  | 414 | p.second); | 
|  | 415 | BMCWEB_LOG_DEBUG | 
|  | 416 | << "UUID = " << *value | 
|  | 417 | << " length " | 
|  | 418 | << value->length(); | 
|  | 419 | if (value != nullptr) | 
|  | 420 | { | 
|  | 421 | // Workaround for to | 
|  | 422 | // short return str in | 
|  | 423 | // smbios demo app, 32 | 
|  | 424 | // bytes are described | 
|  | 425 | // by spec | 
|  | 426 | if (value->length() > | 
|  | 427 | 0 && | 
|  | 428 | value->length() < | 
|  | 429 | 32) | 
|  | 430 | { | 
|  | 431 | std::string | 
|  | 432 | correctedValue = | 
|  | 433 | *value; | 
|  | 434 | correctedValue.append( | 
|  | 435 | 32 - | 
|  | 436 | value | 
|  | 437 | ->length(), | 
|  | 438 | '0'); | 
|  | 439 | value = | 
|  | 440 | &correctedValue; | 
|  | 441 | } | 
|  | 442 | else if ( | 
|  | 443 | value->length() == | 
|  | 444 | 32) | 
|  | 445 | { | 
|  | 446 | aResp->res.jsonValue | 
|  | 447 | ["UUID"] = | 
|  | 448 | value->substr( | 
|  | 449 | 0, 8) + | 
|  | 450 | "-" + | 
|  | 451 | value->substr( | 
|  | 452 | 8, 4) + | 
|  | 453 | "-" + | 
|  | 454 | value->substr( | 
|  | 455 | 12, 4) + | 
|  | 456 | "-" + | 
|  | 457 | value->substr( | 
|  | 458 | 16, 4) + | 
|  | 459 | "-" + | 
|  | 460 | value->substr( | 
|  | 461 | 20, 12); | 
|  | 462 | } | 
|  | 463 | } | 
|  | 464 | } | 
|  | 465 | } | 
|  | 466 | }, | 
|  | 467 | s.first, path, | 
|  | 468 | "org.freedesktop.DBus.Properties", | 
|  | 469 | "GetAll", | 
|  | 470 | "xyz.openbmc_project.Common.UUID"); | 
|  | 471 | } | 
| Lewanczyk, Dawid | c5b2abe | 2018-05-30 16:59:42 +0200 | [diff] [blame] | 472 | } | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame^] | 473 | } | 
| Lewanczyk, Dawid | c5b2abe | 2018-05-30 16:59:42 +0200 | [diff] [blame] | 474 | } | 
| Lewanczyk, Dawid | c5b2abe | 2018-05-30 16:59:42 +0200 | [diff] [blame] | 475 | } | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame^] | 476 | if (foundName == false) | 
|  | 477 | { | 
|  | 478 | aResp->setErrorStatus(); | 
|  | 479 | } | 
|  | 480 | }, | 
|  | 481 | "xyz.openbmc_project.ObjectMapper", | 
|  | 482 | "/xyz/openbmc_project/object_mapper", | 
|  | 483 | "xyz.openbmc_project.ObjectMapper", "GetSubTree", | 
|  | 484 | "/xyz/openbmc_project/inventory", int32_t(0), interfaces); | 
|  | 485 | } | 
| Lewanczyk, Dawid | c5b2abe | 2018-05-30 16:59:42 +0200 | [diff] [blame] | 486 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame^] | 487 | /** | 
|  | 488 | * @brief Retrieves identify led group properties over dbus | 
|  | 489 | * | 
|  | 490 | * @param[in] aResp     Shared pointer for completing asynchronous calls. | 
|  | 491 | * @param[in] callback  Callback for process retrieved data. | 
|  | 492 | * | 
|  | 493 | * @return None. | 
|  | 494 | */ | 
|  | 495 | template <typename CallbackFunc> | 
|  | 496 | void getLedGroupIdentify(std::shared_ptr<SystemAsyncResp> aResp, | 
|  | 497 | CallbackFunc &&callback) | 
|  | 498 | { | 
|  | 499 | BMCWEB_LOG_DEBUG << "Get led groups"; | 
|  | 500 | crow::connections::systemBus->async_method_call( | 
|  | 501 | [aResp{std::move(aResp)}, | 
|  | 502 | &callback](const boost::system::error_code &ec, | 
|  | 503 | const ManagedObjectsType &resp) { | 
|  | 504 | if (ec) | 
|  | 505 | { | 
|  | 506 | BMCWEB_LOG_DEBUG << "DBUS response error " << ec; | 
|  | 507 | aResp->setErrorStatus(); | 
|  | 508 | return; | 
|  | 509 | } | 
|  | 510 | BMCWEB_LOG_DEBUG << "Got " << resp.size() | 
|  | 511 | << "led group objects."; | 
|  | 512 | for (const auto &objPath : resp) | 
|  | 513 | { | 
|  | 514 | const std::string &path = objPath.first; | 
|  | 515 | if (path.rfind("enclosure_identify") != std::string::npos) | 
|  | 516 | { | 
|  | 517 | for (const auto &interface : objPath.second) | 
|  | 518 | { | 
|  | 519 | if (interface.first == | 
|  | 520 | "xyz.openbmc_project.Led.Group") | 
|  | 521 | { | 
|  | 522 | for (const auto &property : interface.second) | 
|  | 523 | { | 
|  | 524 | if (property.first == "Asserted") | 
|  | 525 | { | 
|  | 526 | const bool *asserted = | 
|  | 527 | mapbox::getPtr<const bool>( | 
|  | 528 | property.second); | 
|  | 529 | if (nullptr != asserted) | 
|  | 530 | { | 
|  | 531 | callback(*asserted, aResp); | 
|  | 532 | } | 
|  | 533 | else | 
|  | 534 | { | 
|  | 535 | callback(false, aResp); | 
|  | 536 | } | 
|  | 537 | } | 
|  | 538 | } | 
|  | 539 | } | 
|  | 540 | } | 
| Lewanczyk, Dawid | c5b2abe | 2018-05-30 16:59:42 +0200 | [diff] [blame] | 541 | } | 
| Lewanczyk, Dawid | c5b2abe | 2018-05-30 16:59:42 +0200 | [diff] [blame] | 542 | } | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame^] | 543 | }, | 
|  | 544 | "xyz.openbmc_project.LED.GroupManager", | 
|  | 545 | "/xyz/openbmc_project/led/groups", | 
|  | 546 | "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); | 
|  | 547 | } | 
| Lewanczyk, Dawid | c5b2abe | 2018-05-30 16:59:42 +0200 | [diff] [blame] | 548 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame^] | 549 | template <typename CallbackFunc> | 
|  | 550 | void getLedIdentify(std::shared_ptr<SystemAsyncResp> aResp, | 
|  | 551 | CallbackFunc &&callback) | 
|  | 552 | { | 
|  | 553 | BMCWEB_LOG_DEBUG << "Get identify led properties"; | 
|  | 554 | crow::connections::systemBus->async_method_call( | 
|  | 555 | [aResp{std::move(aResp)}, | 
|  | 556 | &callback](const boost::system::error_code ec, | 
|  | 557 | const PropertiesType &properties) { | 
|  | 558 | if (ec) | 
|  | 559 | { | 
|  | 560 | BMCWEB_LOG_DEBUG << "DBUS response error " << ec; | 
|  | 561 | aResp->setErrorStatus(); | 
|  | 562 | return; | 
| Lewanczyk, Dawid | c5b2abe | 2018-05-30 16:59:42 +0200 | [diff] [blame] | 563 | } | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame^] | 564 | BMCWEB_LOG_DEBUG << "Got " << properties.size() | 
|  | 565 | << "led properties."; | 
|  | 566 | std::string output; | 
|  | 567 | for (const auto &property : properties) | 
|  | 568 | { | 
|  | 569 | if (property.first == "State") | 
|  | 570 | { | 
|  | 571 | const std::string *s = | 
|  | 572 | mapbox::getPtr<std::string>(property.second); | 
|  | 573 | if (nullptr != s) | 
|  | 574 | { | 
|  | 575 | BMCWEB_LOG_DEBUG << "Identify Led State: " << *s; | 
|  | 576 | const auto pos = s->rfind('.'); | 
|  | 577 | if (pos != std::string::npos) | 
|  | 578 | { | 
|  | 579 | auto led = s->substr(pos + 1); | 
|  | 580 | for (const std::pair<const char *, const char *> | 
|  | 581 | &p : | 
|  | 582 | std::array< | 
|  | 583 | std::pair<const char *, const char *>, | 
|  | 584 | 3>{{{"On", "Lit"}, | 
|  | 585 | {"Blink", "Blinking"}, | 
|  | 586 | {"Off", "Off"}}}) | 
|  | 587 | { | 
|  | 588 | if (led == p.first) | 
|  | 589 | { | 
|  | 590 | output = p.second; | 
|  | 591 | } | 
|  | 592 | } | 
|  | 593 | } | 
|  | 594 | } | 
|  | 595 | } | 
|  | 596 | } | 
|  | 597 | callback(output, aResp); | 
|  | 598 | }, | 
|  | 599 | "xyz.openbmc_project.LED.Controller.identify", | 
|  | 600 | "/xyz/openbmc_project/led/physical/identify", | 
|  | 601 | "org.freedesktop.DBus.Properties", "GetAll", | 
|  | 602 | "xyz.openbmc_project.Led.Physical"); | 
|  | 603 | } | 
|  | 604 |  | 
|  | 605 | /** | 
|  | 606 | * @brief Retrieves host state properties over dbus | 
|  | 607 | * | 
|  | 608 | * @param[in] aResp     Shared pointer for completing asynchronous calls. | 
|  | 609 | * | 
|  | 610 | * @return None. | 
|  | 611 | */ | 
|  | 612 | void getHostState(std::shared_ptr<SystemAsyncResp> aResp) | 
|  | 613 | { | 
|  | 614 | BMCWEB_LOG_DEBUG << "Get host information."; | 
|  | 615 | crow::connections::systemBus->async_method_call( | 
|  | 616 | [aResp{std::move(aResp)}](const boost::system::error_code ec, | 
|  | 617 | const PropertiesType &properties) { | 
|  | 618 | if (ec) | 
|  | 619 | { | 
|  | 620 | BMCWEB_LOG_DEBUG << "DBUS response error " << ec; | 
|  | 621 | aResp->setErrorStatus(); | 
|  | 622 | return; | 
|  | 623 | } | 
|  | 624 | BMCWEB_LOG_DEBUG << "Got " << properties.size() | 
|  | 625 | << "host properties."; | 
|  | 626 | for (const auto &property : properties) | 
|  | 627 | { | 
|  | 628 | if (property.first == "CurrentHostState") | 
|  | 629 | { | 
|  | 630 | const std::string *s = | 
|  | 631 | mapbox::getPtr<const std::string>(property.second); | 
|  | 632 | BMCWEB_LOG_DEBUG << "Host state: " << *s; | 
|  | 633 | if (nullptr != s) | 
|  | 634 | { | 
|  | 635 | const auto pos = s->rfind('.'); | 
|  | 636 | if (pos != std::string::npos) | 
|  | 637 | { | 
|  | 638 | // Verify Host State | 
|  | 639 | if (s->substr(pos + 1) == "Running") | 
|  | 640 | { | 
|  | 641 | aResp->res.jsonValue["PowerState"] = "On"; | 
|  | 642 | aResp->res.jsonValue["Status"]["State"] = | 
|  | 643 | "Enabled"; | 
|  | 644 | } | 
|  | 645 | else | 
|  | 646 | { | 
|  | 647 | aResp->res.jsonValue["PowerState"] = "Off"; | 
|  | 648 | aResp->res.jsonValue["Status"]["State"] = | 
|  | 649 | "Disabled"; | 
|  | 650 | } | 
|  | 651 | } | 
|  | 652 | } | 
|  | 653 | } | 
|  | 654 | } | 
|  | 655 | }, | 
|  | 656 | "xyz.openbmc_project.State.Host", | 
|  | 657 | "/xyz/openbmc_project/state/host0", | 
|  | 658 | "org.freedesktop.DBus.Properties", "GetAll", | 
|  | 659 | "xyz.openbmc_project.State.Host"); | 
|  | 660 | } | 
| Lewanczyk, Dawid | c5b2abe | 2018-05-30 16:59:42 +0200 | [diff] [blame] | 661 | }; | 
|  | 662 |  | 
|  | 663 | /** | 
|  | 664 | * SystemsCollection derived class for delivering ComputerSystems Collection | 
|  | 665 | * Schema | 
|  | 666 | */ | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame^] | 667 | class SystemsCollection : public Node | 
|  | 668 | { | 
|  | 669 | public: | 
|  | 670 | SystemsCollection(CrowApp &app) : Node(app, "/redfish/v1/Systems/") | 
|  | 671 | { | 
|  | 672 | Node::json["@odata.type"] = | 
|  | 673 | "#ComputerSystemCollection.ComputerSystemCollection"; | 
|  | 674 | Node::json["@odata.id"] = "/redfish/v1/Systems"; | 
|  | 675 | Node::json["@odata.context"] = | 
|  | 676 | "/redfish/v1/" | 
|  | 677 | "$metadata#ComputerSystemCollection.ComputerSystemCollection"; | 
|  | 678 | Node::json["Name"] = "Computer System Collection"; | 
| Lewanczyk, Dawid | c5b2abe | 2018-05-30 16:59:42 +0200 | [diff] [blame] | 679 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame^] | 680 | entityPrivileges = { | 
|  | 681 | {boost::beast::http::verb::get, {{"Login"}}}, | 
|  | 682 | {boost::beast::http::verb::head, {{"Login"}}}, | 
|  | 683 | {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, | 
|  | 684 | {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, | 
|  | 685 | {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, | 
|  | 686 | {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; | 
|  | 687 | } | 
| Lewanczyk, Dawid | c5b2abe | 2018-05-30 16:59:42 +0200 | [diff] [blame] | 688 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame^] | 689 | private: | 
|  | 690 | /** | 
|  | 691 | * Functions triggers appropriate requests on DBus | 
|  | 692 | */ | 
|  | 693 | void doGet(crow::Response &res, const crow::Request &req, | 
|  | 694 | const std::vector<std::string> ¶ms) override | 
|  | 695 | { | 
|  | 696 | // Get board list, and call the below callback for JSON preparation | 
|  | 697 | provider.getBaseboardList([&](const bool &success, | 
|  | 698 | const std::vector<std::string> &output) { | 
|  | 699 | if (success) | 
|  | 700 | { | 
|  | 701 | // ... prepare json array with appropriate @odata.id links | 
|  | 702 | nlohmann::json boardArray = nlohmann::json::array(); | 
|  | 703 | for (const std::string &boardItem : output) | 
|  | 704 | { | 
|  | 705 | boardArray.push_back( | 
|  | 706 | {{"@odata.id", "/redfish/v1/Systems/" + boardItem}}); | 
|  | 707 | } | 
|  | 708 | // Then attach members, count size and return, | 
|  | 709 | Node::json["Members"] = boardArray; | 
|  | 710 | Node::json["Members@odata.count"] = boardArray.size(); | 
|  | 711 | res.jsonValue = Node::json; | 
| Lewanczyk, Dawid | c5b2abe | 2018-05-30 16:59:42 +0200 | [diff] [blame] | 712 | } | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame^] | 713 | else | 
|  | 714 | { | 
|  | 715 | // ... otherwise, return INTERNALL ERROR | 
|  | 716 | res.result(boost::beast::http::status::internal_server_error); | 
|  | 717 | } | 
|  | 718 | res.end(); | 
| Lewanczyk, Dawid | c5b2abe | 2018-05-30 16:59:42 +0200 | [diff] [blame] | 719 | }); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame^] | 720 | } | 
| Lewanczyk, Dawid | c5b2abe | 2018-05-30 16:59:42 +0200 | [diff] [blame] | 721 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame^] | 722 | OnDemandSystemsProvider provider; | 
| Lewanczyk, Dawid | c5b2abe | 2018-05-30 16:59:42 +0200 | [diff] [blame] | 723 | }; | 
|  | 724 |  | 
|  | 725 | /** | 
|  | 726 | * Systems override class for delivering ComputerSystems Schema | 
|  | 727 | */ | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame^] | 728 | class Systems : public Node | 
|  | 729 | { | 
|  | 730 | public: | 
|  | 731 | /* | 
|  | 732 | * Default Constructor | 
|  | 733 | */ | 
|  | 734 | Systems(CrowApp &app) : | 
|  | 735 | Node(app, "/redfish/v1/Systems/<str>/", std::string()) | 
|  | 736 | { | 
|  | 737 | Node::json["@odata.type"] = "#ComputerSystem.v1_3_0.ComputerSystem"; | 
|  | 738 | Node::json["@odata.context"] = | 
|  | 739 | "/redfish/v1/$metadata#ComputerSystem.ComputerSystem"; | 
|  | 740 | Node::json["SystemType"] = "Physical"; | 
|  | 741 | Node::json["Description"] = "Computer System"; | 
|  | 742 | Node::json["Boot"]["BootSourceOverrideEnabled"] = | 
|  | 743 | "Disabled"; // TODO(Dawid), get real boot data | 
|  | 744 | Node::json["Boot"]["BootSourceOverrideTarget"] = | 
|  | 745 | "None"; // TODO(Dawid), get real boot data | 
|  | 746 | Node::json["Boot"]["BootSourceOverrideMode"] = | 
|  | 747 | "Legacy"; // TODO(Dawid), get real boot data | 
|  | 748 | Node::json["Boot"]["BootSourceOverrideTarget@Redfish.AllowableValues"] = | 
|  | 749 | {"None",      "Pxe",       "Hdd", "Cd", | 
|  | 750 | "BiosSetup", "UefiShell", "Usb"}; // TODO(Dawid), get real boot | 
|  | 751 | // data | 
|  | 752 | Node::json["ProcessorSummary"]["Count"] = int(0); | 
|  | 753 | Node::json["ProcessorSummary"]["Status"]["State"] = "Disabled"; | 
|  | 754 | Node::json["MemorySummary"]["TotalSystemMemoryGiB"] = int(0); | 
|  | 755 | Node::json["MemorySummary"]["Status"]["State"] = "Disabled"; | 
| Lewanczyk, Dawid | c5b2abe | 2018-05-30 16:59:42 +0200 | [diff] [blame] | 756 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame^] | 757 | entityPrivileges = { | 
|  | 758 | {boost::beast::http::verb::get, {{"Login"}}}, | 
|  | 759 | {boost::beast::http::verb::head, {{"Login"}}}, | 
|  | 760 | {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, | 
|  | 761 | {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, | 
|  | 762 | {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, | 
|  | 763 | {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; | 
| Lewanczyk, Dawid | c5b2abe | 2018-05-30 16:59:42 +0200 | [diff] [blame] | 764 | } | 
|  | 765 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame^] | 766 | private: | 
|  | 767 | OnDemandSystemsProvider provider; | 
| Lewanczyk, Dawid | c5b2abe | 2018-05-30 16:59:42 +0200 | [diff] [blame] | 768 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame^] | 769 | /** | 
|  | 770 | * Functions triggers appropriate requests on DBus | 
|  | 771 | */ | 
|  | 772 | void doGet(crow::Response &res, const crow::Request &req, | 
|  | 773 | const std::vector<std::string> ¶ms) override | 
|  | 774 | { | 
|  | 775 | // Check if there is required param, truly entering this shall be | 
|  | 776 | // impossible | 
|  | 777 | if (params.size() != 1) | 
|  | 778 | { | 
|  | 779 | res.result(boost::beast::http::status::internal_server_error); | 
|  | 780 | res.end(); | 
|  | 781 | return; | 
|  | 782 | } | 
| Lewanczyk, Dawid | c5b2abe | 2018-05-30 16:59:42 +0200 | [diff] [blame] | 783 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame^] | 784 | const std::string &name = params[0]; | 
| Lewanczyk, Dawid | c5b2abe | 2018-05-30 16:59:42 +0200 | [diff] [blame] | 785 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame^] | 786 | res.jsonValue = Node::json; | 
|  | 787 | res.jsonValue["@odata.id"] = "/redfish/v1/Systems/" + name; | 
| Lewanczyk, Dawid | c5b2abe | 2018-05-30 16:59:42 +0200 | [diff] [blame] | 788 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame^] | 789 | auto asyncResp = std::make_shared<SystemAsyncResp>(res); | 
|  | 790 |  | 
|  | 791 | provider.getLedGroupIdentify( | 
|  | 792 | asyncResp, [&](const bool &asserted, | 
|  | 793 | const std::shared_ptr<SystemAsyncResp> &aResp) { | 
|  | 794 | if (asserted) | 
|  | 795 | { | 
|  | 796 | // If led group is asserted, then another call is needed to | 
|  | 797 | // get led status | 
|  | 798 | provider.getLedIdentify( | 
|  | 799 | aResp, | 
|  | 800 | [](const std::string &ledStatus, | 
|  | 801 | const std::shared_ptr<SystemAsyncResp> &aResp) { | 
|  | 802 | if (!ledStatus.empty()) | 
|  | 803 | { | 
|  | 804 | aResp->res.jsonValue["IndicatorLED"] = | 
|  | 805 | ledStatus; | 
|  | 806 | } | 
|  | 807 | }); | 
|  | 808 | } | 
|  | 809 | else | 
|  | 810 | { | 
|  | 811 | aResp->res.jsonValue["IndicatorLED"] = "Off"; | 
|  | 812 | } | 
|  | 813 | }); | 
|  | 814 | provider.getComputerSystem(asyncResp, name); | 
|  | 815 | provider.getHostState(asyncResp); | 
| Lewanczyk, Dawid | c5b2abe | 2018-05-30 16:59:42 +0200 | [diff] [blame] | 816 | } | 
|  | 817 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame^] | 818 | void doPatch(crow::Response &res, const crow::Request &req, | 
|  | 819 | const std::vector<std::string> ¶ms) override | 
|  | 820 | { | 
|  | 821 | // Check if there is required param, truly entering this shall be | 
|  | 822 | // impossible | 
|  | 823 | if (params.size() != 1) | 
|  | 824 | { | 
|  | 825 | res.result(boost::beast::http::status::internal_server_error); | 
|  | 826 | res.end(); | 
|  | 827 | return; | 
|  | 828 | } | 
|  | 829 | // Parse JSON request body | 
|  | 830 | nlohmann::json patch; | 
|  | 831 | if (!json_util::processJsonFromRequest(res, req, patch)) | 
|  | 832 | { | 
|  | 833 | return; | 
|  | 834 | } | 
|  | 835 | // Find key with new led value | 
|  | 836 | const std::string &name = params[0]; | 
|  | 837 | const std::string *reqLedState = nullptr; | 
|  | 838 | json_util::Result r = json_util::getString( | 
|  | 839 | "IndicatorLED", patch, reqLedState, | 
|  | 840 | static_cast<int>(json_util::MessageSetting::TYPE_ERROR) | | 
|  | 841 | static_cast<int>(json_util::MessageSetting::MISSING), | 
|  | 842 | res.jsonValue, std::string("/" + name + "/IndicatorLED")); | 
|  | 843 | if ((r != json_util::Result::SUCCESS) || (reqLedState == nullptr)) | 
|  | 844 | { | 
|  | 845 | res.result(boost::beast::http::status::bad_request); | 
|  | 846 | res.end(); | 
|  | 847 | return; | 
|  | 848 | } | 
|  | 849 | // Verify key value | 
|  | 850 | std::string dbusLedState; | 
|  | 851 | for (const auto &p : | 
|  | 852 | boost::container::flat_map<const char *, const char *>{ | 
|  | 853 | {"On", "Lit"}, {"Blink", "Blinking"}, {"Off", "Off"}}) | 
|  | 854 | { | 
|  | 855 | if (*reqLedState == p.second) | 
|  | 856 | { | 
|  | 857 | dbusLedState = p.first; | 
| Lewanczyk, Dawid | c5b2abe | 2018-05-30 16:59:42 +0200 | [diff] [blame] | 858 | } | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame^] | 859 | } | 
|  | 860 |  | 
|  | 861 | // Update led status | 
|  | 862 | auto asyncResp = std::make_shared<SystemAsyncResp>(res); | 
|  | 863 | res.jsonValue = Node::json; | 
|  | 864 | res.jsonValue["@odata.id"] = "/redfish/v1/Systems/" + name; | 
|  | 865 |  | 
|  | 866 | provider.getHostState(asyncResp); | 
|  | 867 | provider.getComputerSystem(asyncResp, name); | 
|  | 868 |  | 
|  | 869 | if (dbusLedState.empty()) | 
|  | 870 | { | 
|  | 871 | messages::addMessageToJsonRoot( | 
|  | 872 | res.jsonValue, | 
|  | 873 | messages::propertyValueNotInList(*reqLedState, "IndicatorLED")); | 
|  | 874 | } | 
|  | 875 | else | 
|  | 876 | { | 
|  | 877 | // Update led group | 
|  | 878 | BMCWEB_LOG_DEBUG << "Update led group."; | 
|  | 879 | crow::connections::systemBus->async_method_call( | 
|  | 880 | [&, asyncResp{std::move(asyncResp)}]( | 
|  | 881 | const boost::system::error_code ec) { | 
|  | 882 | if (ec) | 
|  | 883 | { | 
|  | 884 | BMCWEB_LOG_DEBUG << "DBUS response error " << ec; | 
|  | 885 | asyncResp->setErrorStatus(); | 
|  | 886 | return; | 
|  | 887 | } | 
|  | 888 | BMCWEB_LOG_DEBUG << "Led group update done."; | 
|  | 889 | }, | 
|  | 890 | "xyz.openbmc_project.LED.GroupManager", | 
|  | 891 | "/xyz/openbmc_project/led/groups/enclosure_identify", | 
|  | 892 | "org.freedesktop.DBus.Properties", "Set", | 
|  | 893 | "xyz.openbmc_project.Led.Group", "Asserted", | 
|  | 894 | sdbusplus::message::variant<bool>( | 
|  | 895 | (dbusLedState == "Off" ? false : true))); | 
|  | 896 | // Update identify led status | 
|  | 897 | BMCWEB_LOG_DEBUG << "Update led SoftwareInventoryCollection."; | 
|  | 898 | crow::connections::systemBus->async_method_call( | 
|  | 899 | [&, asyncResp{std::move(asyncResp)}]( | 
|  | 900 | const boost::system::error_code ec) { | 
|  | 901 | if (ec) | 
|  | 902 | { | 
|  | 903 | BMCWEB_LOG_DEBUG << "DBUS response error " << ec; | 
|  | 904 | asyncResp->setErrorStatus(); | 
|  | 905 | return; | 
|  | 906 | } | 
|  | 907 | BMCWEB_LOG_DEBUG << "Led state update done."; | 
|  | 908 | res.jsonValue["IndicatorLED"] = *reqLedState; | 
|  | 909 | }, | 
|  | 910 | "xyz.openbmc_project.LED.Controller.identify", | 
|  | 911 | "/xyz/openbmc_project/led/physical/identify", | 
|  | 912 | "org.freedesktop.DBus.Properties", "Set", | 
|  | 913 | "xyz.openbmc_project.Led.Physical", "State", | 
|  | 914 | sdbusplus::message::variant<std::string>( | 
|  | 915 | "xyz.openbmc_project.Led.Physical.Action." + dbusLedState)); | 
|  | 916 | } | 
| Lewanczyk, Dawid | c5b2abe | 2018-05-30 16:59:42 +0200 | [diff] [blame] | 917 | } | 
| Lewanczyk, Dawid | c5b2abe | 2018-05-30 16:59:42 +0200 | [diff] [blame] | 918 | }; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame^] | 919 | } // namespace redfish |