1 #pragma once 2 #include <app.h> 3 #include <tinyxml2.h> 4 5 #include <async_resp.hpp> 6 #include <boost/algorithm/string.hpp> 7 #include <boost/container/flat_set.hpp> 8 #include <error_messages.hpp> 9 #include <event_service_manager.hpp> 10 #include <ibm/locks.hpp> 11 #include <nlohmann/json.hpp> 12 #include <resource_messages.hpp> 13 #include <sdbusplus/message/types.hpp> 14 #include <utils/json_utils.hpp> 15 16 #include <filesystem> 17 #include <fstream> 18 #include <regex> 19 20 using SType = std::string; 21 using SegmentFlags = std::vector<std::pair<std::string, uint32_t>>; 22 using LockRequest = std::tuple<SType, SType, SType, uint64_t, SegmentFlags>; 23 using LockRequests = std::vector<LockRequest>; 24 using Rc = std::pair<bool, std::variant<uint32_t, LockRequest>>; 25 using RcGetLockList = 26 std::variant<std::string, std::vector<std::pair<uint32_t, LockRequests>>>; 27 using ListOfSessionIds = std::vector<std::string>; 28 namespace crow 29 { 30 namespace ibm_mc 31 { 32 constexpr const char* methodNotAllowedMsg = "Method Not Allowed"; 33 constexpr const char* resourceNotFoundMsg = "Resource Not Found"; 34 constexpr const char* contentNotAcceptableMsg = "Content Not Acceptable"; 35 constexpr const char* internalServerError = "Internal Server Error"; 36 37 constexpr size_t maxSaveareaFileSize = 38 500000; // Allow save area file size upto 500KB 39 constexpr size_t maxBroadcastMsgSize = 40 1000; // Allow Broadcast message size upto 1KB 41 42 inline bool createSaveAreaPath(crow::Response& res) 43 { 44 // The path /var/lib/obmc will be created by initrdscripts 45 // Create the directories for the save-area files, when we get 46 // first file upload request 47 std::error_code ec; 48 if (!std::filesystem::is_directory("/var/lib/obmc/bmc-console-mgmt", ec)) 49 { 50 std::filesystem::create_directory("/var/lib/obmc/bmc-console-mgmt", ec); 51 } 52 if (ec) 53 { 54 res.result(boost::beast::http::status::internal_server_error); 55 res.jsonValue["Description"] = internalServerError; 56 BMCWEB_LOG_DEBUG 57 << "handleIbmPost: Failed to prepare save-area directory. ec : " 58 << ec; 59 return false; 60 } 61 62 if (!std::filesystem::is_directory( 63 "/var/lib/obmc/bmc-console-mgmt/save-area", ec)) 64 { 65 std::filesystem::create_directory( 66 "/var/lib/obmc/bmc-console-mgmt/save-area", ec); 67 } 68 if (ec) 69 { 70 res.result(boost::beast::http::status::internal_server_error); 71 res.jsonValue["Description"] = internalServerError; 72 BMCWEB_LOG_DEBUG 73 << "handleIbmPost: Failed to prepare save-area directory. ec : " 74 << ec; 75 return false; 76 } 77 return true; 78 } 79 80 inline void handleFilePut(const crow::Request& req, crow::Response& res, 81 const std::string& fileID) 82 { 83 // Check the content-type of the request 84 std::string_view contentType = req.getHeaderValue("content-type"); 85 if (boost::starts_with(contentType, "multipart/form-data")) 86 { 87 BMCWEB_LOG_DEBUG 88 << "This is multipart/form-data. Invalid content for PUT"; 89 90 res.result(boost::beast::http::status::not_acceptable); 91 res.jsonValue["Description"] = contentNotAcceptableMsg; 92 return; 93 } 94 BMCWEB_LOG_DEBUG << "Not a multipart/form-data. Continue.."; 95 96 BMCWEB_LOG_DEBUG 97 << "handleIbmPut: Request to create/update the save-area file"; 98 if (!createSaveAreaPath(res)) 99 { 100 res.result(boost::beast::http::status::not_found); 101 res.jsonValue["Description"] = resourceNotFoundMsg; 102 return; 103 } 104 // Create the file 105 std::ofstream file; 106 std::filesystem::path loc("/var/lib/obmc/bmc-console-mgmt/save-area"); 107 loc /= fileID; 108 109 const std::string& data = req.body; 110 BMCWEB_LOG_DEBUG << "data capaticty : " << data.capacity(); 111 if (data.capacity() > maxSaveareaFileSize) 112 { 113 res.result(boost::beast::http::status::bad_request); 114 res.jsonValue["Description"] = 115 "File size exceeds maximum allowed size[500KB]"; 116 return; 117 } 118 BMCWEB_LOG_DEBUG << "Writing to the file: " << loc; 119 120 bool fileExists = false; 121 if (std::filesystem::exists(loc)) 122 { 123 fileExists = true; 124 } 125 file.open(loc, std::ofstream::out); 126 if (file.fail()) 127 { 128 BMCWEB_LOG_DEBUG << "Error while opening the file for writing"; 129 res.result(boost::beast::http::status::internal_server_error); 130 res.jsonValue["Description"] = "Error while creating the file"; 131 return; 132 } 133 file << data; 134 std::string origin = "/ibm/v1/Host/ConfigFiles/" + fileID; 135 // Push an event 136 if (fileExists) 137 { 138 BMCWEB_LOG_DEBUG << "config file is updated"; 139 res.jsonValue["Description"] = "File Updated"; 140 141 redfish::EventServiceManager::getInstance().sendEvent( 142 redfish::messages::resourceChanged(), origin, "IBMConfigFile"); 143 } 144 else 145 { 146 BMCWEB_LOG_DEBUG << "config file is created"; 147 res.jsonValue["Description"] = "File Created"; 148 149 redfish::EventServiceManager::getInstance().sendEvent( 150 redfish::messages::resourceCreated(), origin, "IBMConfigFile"); 151 } 152 } 153 154 inline void handleConfigFileList(crow::Response& res) 155 { 156 std::vector<std::string> pathObjList; 157 std::filesystem::path loc("/var/lib/obmc/bmc-console-mgmt/save-area"); 158 if (std::filesystem::exists(loc) && std::filesystem::is_directory(loc)) 159 { 160 for (const auto& file : std::filesystem::directory_iterator(loc)) 161 { 162 const std::filesystem::path& pathObj = file.path(); 163 pathObjList.push_back("/ibm/v1/Host/ConfigFiles/" + 164 pathObj.filename().string()); 165 } 166 } 167 res.jsonValue["@odata.type"] = "#IBMConfigFile.v1_0_0.IBMConfigFile"; 168 res.jsonValue["@odata.id"] = "/ibm/v1/Host/ConfigFiles/"; 169 res.jsonValue["Id"] = "ConfigFiles"; 170 res.jsonValue["Name"] = "ConfigFiles"; 171 172 res.jsonValue["Members"] = std::move(pathObjList); 173 res.jsonValue["Actions"]["#IBMConfigFiles.DeleteAll"] = { 174 {"target", 175 "/ibm/v1/Host/ConfigFiles/Actions/IBMConfigFiles.DeleteAll"}}; 176 res.end(); 177 } 178 179 inline void deleteConfigFiles(crow::Response& res) 180 { 181 std::vector<std::string> pathObjList; 182 std::error_code ec; 183 std::filesystem::path loc("/var/lib/obmc/bmc-console-mgmt/save-area"); 184 if (std::filesystem::exists(loc) && std::filesystem::is_directory(loc)) 185 { 186 std::filesystem::remove_all(loc, ec); 187 if (ec) 188 { 189 res.result(boost::beast::http::status::internal_server_error); 190 res.jsonValue["Description"] = internalServerError; 191 BMCWEB_LOG_DEBUG << "deleteConfigFiles: Failed to delete the " 192 "config files directory. ec : " 193 << ec; 194 } 195 } 196 res.end(); 197 } 198 199 inline void getLockServiceData(crow::Response& res) 200 { 201 res.jsonValue["@odata.type"] = "#LockService.v1_0_0.LockService"; 202 res.jsonValue["@odata.id"] = "/ibm/v1/HMC/LockService/"; 203 res.jsonValue["Id"] = "LockService"; 204 res.jsonValue["Name"] = "LockService"; 205 206 res.jsonValue["Actions"]["#LockService.AcquireLock"] = { 207 {"target", "/ibm/v1/HMC/LockService/Actions/LockService.AcquireLock"}}; 208 res.jsonValue["Actions"]["#LockService.ReleaseLock"] = { 209 {"target", "/ibm/v1/HMC/LockService/Actions/LockService.ReleaseLock"}}; 210 res.jsonValue["Actions"]["#LockService.GetLockList"] = { 211 {"target", "/ibm/v1/HMC/LockService/Actions/LockService.GetLockList"}}; 212 res.end(); 213 } 214 215 inline void handleFileGet(crow::Response& res, const std::string& fileID) 216 { 217 BMCWEB_LOG_DEBUG << "HandleGet on SaveArea files on path: " << fileID; 218 std::filesystem::path loc("/var/lib/obmc/bmc-console-mgmt/save-area/" + 219 fileID); 220 if (!std::filesystem::exists(loc)) 221 { 222 BMCWEB_LOG_ERROR << loc << "Not found"; 223 res.result(boost::beast::http::status::not_found); 224 res.jsonValue["Description"] = resourceNotFoundMsg; 225 return; 226 } 227 228 std::ifstream readfile(loc.string()); 229 if (!readfile) 230 { 231 BMCWEB_LOG_ERROR << loc.string() << "Not found"; 232 res.result(boost::beast::http::status::not_found); 233 res.jsonValue["Description"] = resourceNotFoundMsg; 234 return; 235 } 236 237 std::string contentDispositionParam = 238 "attachment; filename=\"" + fileID + "\""; 239 res.addHeader("Content-Disposition", contentDispositionParam); 240 std::string fileData; 241 fileData = {std::istreambuf_iterator<char>(readfile), 242 std::istreambuf_iterator<char>()}; 243 res.jsonValue["Data"] = fileData; 244 return; 245 } 246 247 inline void handleFileDelete(crow::Response& res, const std::string& fileID) 248 { 249 std::string filePath("/var/lib/obmc/bmc-console-mgmt/save-area/" + fileID); 250 BMCWEB_LOG_DEBUG << "Removing the file : " << filePath << "\n"; 251 252 std::ifstream fileOpen(filePath.c_str()); 253 if (static_cast<bool>(fileOpen)) 254 { 255 if (remove(filePath.c_str()) == 0) 256 { 257 BMCWEB_LOG_DEBUG << "File removed!\n"; 258 res.jsonValue["Description"] = "File Deleted"; 259 } 260 else 261 { 262 BMCWEB_LOG_ERROR << "File not removed!\n"; 263 res.result(boost::beast::http::status::internal_server_error); 264 res.jsonValue["Description"] = internalServerError; 265 } 266 } 267 else 268 { 269 BMCWEB_LOG_ERROR << "File not found!\n"; 270 res.result(boost::beast::http::status::not_found); 271 res.jsonValue["Description"] = resourceNotFoundMsg; 272 } 273 return; 274 } 275 276 inline void handleBroadcastService(const crow::Request& req, 277 crow::Response& res) 278 { 279 std::string broadcastMsg; 280 281 if (!redfish::json_util::readJson(req, res, "Message", broadcastMsg)) 282 { 283 BMCWEB_LOG_DEBUG << "Not a Valid JSON"; 284 res.result(boost::beast::http::status::bad_request); 285 return; 286 } 287 if (broadcastMsg.size() > maxBroadcastMsgSize) 288 { 289 BMCWEB_LOG_ERROR << "Message size exceeds maximum allowed size[1KB]"; 290 res.result(boost::beast::http::status::bad_request); 291 return; 292 } 293 redfish::EventServiceManager::getInstance().sendBroadcastMsg(broadcastMsg); 294 res.end(); 295 return; 296 } 297 298 inline void handleFileUrl(const crow::Request& req, crow::Response& res, 299 const std::string& fileID) 300 { 301 if (req.method() == boost::beast::http::verb::put) 302 { 303 handleFilePut(req, res, fileID); 304 res.end(); 305 return; 306 } 307 if (req.method() == boost::beast::http::verb::get) 308 { 309 handleFileGet(res, fileID); 310 res.end(); 311 return; 312 } 313 if (req.method() == boost::beast::http::verb::delete_) 314 { 315 handleFileDelete(res, fileID); 316 res.end(); 317 return; 318 } 319 } 320 321 inline void handleAcquireLockAPI(const crow::Request& req, crow::Response& res, 322 std::vector<nlohmann::json> body) 323 { 324 LockRequests lockRequestStructure; 325 for (auto& element : body) 326 { 327 std::string lockType; 328 uint64_t resourceId; 329 330 SegmentFlags segInfo; 331 std::vector<nlohmann::json> segmentFlags; 332 333 if (!redfish::json_util::readJson(element, res, "LockType", lockType, 334 "ResourceID", resourceId, 335 "SegmentFlags", segmentFlags)) 336 { 337 BMCWEB_LOG_DEBUG << "Not a Valid JSON"; 338 res.result(boost::beast::http::status::bad_request); 339 res.end(); 340 return; 341 } 342 BMCWEB_LOG_DEBUG << lockType; 343 BMCWEB_LOG_DEBUG << resourceId; 344 345 BMCWEB_LOG_DEBUG << "Segment Flags are present"; 346 347 for (auto& e : segmentFlags) 348 { 349 std::string lockFlags; 350 uint32_t segmentLength; 351 352 if (!redfish::json_util::readJson(e, res, "LockFlag", lockFlags, 353 "SegmentLength", segmentLength)) 354 { 355 res.result(boost::beast::http::status::bad_request); 356 res.end(); 357 return; 358 } 359 360 BMCWEB_LOG_DEBUG << "Lockflag : " << lockFlags; 361 BMCWEB_LOG_DEBUG << "SegmentLength : " << segmentLength; 362 363 segInfo.push_back(std::make_pair(lockFlags, segmentLength)); 364 } 365 lockRequestStructure.push_back( 366 make_tuple(req.session->uniqueId, req.session->clientId, lockType, 367 resourceId, segInfo)); 368 } 369 370 // print lock request into journal 371 372 for (auto& i : lockRequestStructure) 373 { 374 BMCWEB_LOG_DEBUG << std::get<0>(i); 375 BMCWEB_LOG_DEBUG << std::get<1>(i); 376 BMCWEB_LOG_DEBUG << std::get<2>(i); 377 BMCWEB_LOG_DEBUG << std::get<3>(i); 378 379 for (const auto& p : std::get<4>(i)) 380 { 381 BMCWEB_LOG_DEBUG << p.first << ", " << p.second; 382 } 383 } 384 385 const LockRequests& t = lockRequestStructure; 386 387 auto varAcquireLock = crow::ibm_mc_lock::Lock::getInstance().acquireLock(t); 388 389 if (varAcquireLock.first) 390 { 391 // Either validity failure of there is a conflict with itself 392 393 auto validityStatus = 394 std::get<std::pair<bool, int>>(varAcquireLock.second); 395 396 if ((!validityStatus.first) && (validityStatus.second == 0)) 397 { 398 BMCWEB_LOG_DEBUG << "Not a Valid record"; 399 BMCWEB_LOG_DEBUG << "Bad json in request"; 400 res.result(boost::beast::http::status::bad_request); 401 res.end(); 402 return; 403 } 404 if (validityStatus.first && (validityStatus.second == 1)) 405 { 406 BMCWEB_LOG_DEBUG << "There is a conflict within itself"; 407 res.result(boost::beast::http::status::bad_request); 408 res.end(); 409 return; 410 } 411 } 412 else 413 { 414 auto conflictStatus = 415 std::get<crow::ibm_mc_lock::Rc>(varAcquireLock.second); 416 if (!conflictStatus.first) 417 { 418 BMCWEB_LOG_DEBUG << "There is no conflict with the locktable"; 419 res.result(boost::beast::http::status::ok); 420 421 auto var = std::get<uint32_t>(conflictStatus.second); 422 nlohmann::json returnJson; 423 returnJson["id"] = var; 424 res.jsonValue["TransactionID"] = var; 425 res.end(); 426 return; 427 } 428 BMCWEB_LOG_DEBUG << "There is a conflict with the lock table"; 429 res.result(boost::beast::http::status::conflict); 430 auto var = 431 std::get<std::pair<uint32_t, LockRequest>>(conflictStatus.second); 432 nlohmann::json returnJson, segments; 433 nlohmann::json myarray = nlohmann::json::array(); 434 returnJson["TransactionID"] = var.first; 435 returnJson["SessionID"] = std::get<0>(var.second); 436 returnJson["HMCID"] = std::get<1>(var.second); 437 returnJson["LockType"] = std::get<2>(var.second); 438 returnJson["ResourceID"] = std::get<3>(var.second); 439 440 for (auto& i : std::get<4>(var.second)) 441 { 442 segments["LockFlag"] = i.first; 443 segments["SegmentLength"] = i.second; 444 myarray.push_back(segments); 445 } 446 447 returnJson["SegmentFlags"] = myarray; 448 449 res.jsonValue["Record"] = returnJson; 450 res.end(); 451 return; 452 } 453 } 454 inline void handleRelaseAllAPI(const crow::Request& req, crow::Response& res) 455 { 456 crow::ibm_mc_lock::Lock::getInstance().releaseLock(req.session->uniqueId); 457 res.result(boost::beast::http::status::ok); 458 res.end(); 459 return; 460 } 461 462 inline void 463 handleReleaseLockAPI(const crow::Request& req, crow::Response& res, 464 const std::vector<uint32_t>& listTransactionIds) 465 { 466 BMCWEB_LOG_DEBUG << listTransactionIds.size(); 467 BMCWEB_LOG_DEBUG << "Data is present"; 468 for (unsigned int listTransactionId : listTransactionIds) 469 { 470 BMCWEB_LOG_DEBUG << listTransactionId; 471 } 472 473 // validate the request ids 474 475 auto varReleaselock = crow::ibm_mc_lock::Lock::getInstance().releaseLock( 476 listTransactionIds, 477 std::make_pair(req.session->clientId, req.session->uniqueId)); 478 479 if (!varReleaselock.first) 480 { 481 // validation Failed 482 res.result(boost::beast::http::status::bad_request); 483 res.end(); 484 return; 485 } 486 auto statusRelease = 487 std::get<crow::ibm_mc_lock::RcRelaseLock>(varReleaselock.second); 488 if (statusRelease.first) 489 { 490 // The current hmc owns all the locks, so we already released 491 // them 492 res.result(boost::beast::http::status::ok); 493 res.end(); 494 return; 495 } 496 497 // valid rid, but the current hmc does not own all the locks 498 BMCWEB_LOG_DEBUG << "Current HMC does not own all the locks"; 499 res.result(boost::beast::http::status::unauthorized); 500 501 auto var = statusRelease.second; 502 nlohmann::json returnJson, segments; 503 nlohmann::json myArray = nlohmann::json::array(); 504 returnJson["TransactionID"] = var.first; 505 returnJson["SessionID"] = std::get<0>(var.second); 506 returnJson["HMCID"] = std::get<1>(var.second); 507 returnJson["LockType"] = std::get<2>(var.second); 508 returnJson["ResourceID"] = std::get<3>(var.second); 509 510 for (auto& i : std::get<4>(var.second)) 511 { 512 segments["LockFlag"] = i.first; 513 segments["SegmentLength"] = i.second; 514 myArray.push_back(segments); 515 } 516 517 returnJson["SegmentFlags"] = myArray; 518 res.jsonValue["Record"] = returnJson; 519 res.end(); 520 return; 521 } 522 523 inline void handleGetLockListAPI(crow::Response& res, 524 const ListOfSessionIds& listSessionIds) 525 { 526 BMCWEB_LOG_DEBUG << listSessionIds.size(); 527 528 auto status = 529 crow::ibm_mc_lock::Lock::getInstance().getLockList(listSessionIds); 530 auto var = std::get<std::vector<std::pair<uint32_t, LockRequests>>>(status); 531 532 nlohmann::json lockRecords = nlohmann::json::array(); 533 534 for (const auto& transactionId : var) 535 { 536 for (const auto& lockRecord : transactionId.second) 537 { 538 nlohmann::json returnJson; 539 540 returnJson["TransactionID"] = transactionId.first; 541 returnJson["SessionID"] = std::get<0>(lockRecord); 542 returnJson["HMCID"] = std::get<1>(lockRecord); 543 returnJson["LockType"] = std::get<2>(lockRecord); 544 returnJson["ResourceID"] = std::get<3>(lockRecord); 545 546 nlohmann::json segments; 547 nlohmann::json segmentInfoArray = nlohmann::json::array(); 548 549 for (const auto& segment : std::get<4>(lockRecord)) 550 { 551 segments["LockFlag"] = segment.first; 552 segments["SegmentLength"] = segment.second; 553 segmentInfoArray.push_back(segments); 554 } 555 556 returnJson["SegmentFlags"] = segmentInfoArray; 557 lockRecords.push_back(returnJson); 558 } 559 } 560 res.result(boost::beast::http::status::ok); 561 res.jsonValue["Records"] = lockRecords; 562 res.end(); 563 } 564 565 inline void requestRoutes(App& app) 566 { 567 568 // allowed only for admin 569 BMCWEB_ROUTE(app, "/ibm/v1/") 570 .privileges({"ConfigureComponents", "ConfigureManager"}) 571 .methods(boost::beast::http::verb::get)( 572 [](const crow::Request&, crow::Response& res) { 573 res.jsonValue["@odata.type"] = 574 "#ibmServiceRoot.v1_0_0.ibmServiceRoot"; 575 res.jsonValue["@odata.id"] = "/ibm/v1/"; 576 res.jsonValue["Id"] = "IBM Rest RootService"; 577 res.jsonValue["Name"] = "IBM Service Root"; 578 res.jsonValue["ConfigFiles"] = { 579 {"@odata.id", "/ibm/v1/Host/ConfigFiles"}}; 580 res.jsonValue["LockService"] = { 581 {"@odata.id", "/ibm/v1/HMC/LockService"}}; 582 res.jsonValue["BroadcastService"] = { 583 {"@odata.id", "/ibm/v1/HMC/BroadcastService"}}; 584 res.end(); 585 }); 586 587 BMCWEB_ROUTE(app, "/ibm/v1/Host/ConfigFiles") 588 .privileges({"ConfigureComponents", "ConfigureManager"}) 589 .methods(boost::beast::http::verb::get)( 590 [](const crow::Request&, crow::Response& res) { 591 handleConfigFileList(res); 592 }); 593 594 BMCWEB_ROUTE(app, 595 "/ibm/v1/Host/ConfigFiles/Actions/IBMConfigFiles.DeleteAll") 596 .privileges({"ConfigureComponents", "ConfigureManager"}) 597 .methods(boost::beast::http::verb::post)( 598 [](const crow::Request&, crow::Response& res) { 599 deleteConfigFiles(res); 600 }); 601 602 BMCWEB_ROUTE(app, "/ibm/v1/Host/ConfigFiles/<path>") 603 .privileges({"ConfigureComponents", "ConfigureManager"}) 604 .methods(boost::beast::http::verb::put, boost::beast::http::verb::get, 605 boost::beast::http::verb::delete_)( 606 [](const crow::Request& req, crow::Response& res, 607 const std::string& path) { handleFileUrl(req, res, path); }); 608 609 BMCWEB_ROUTE(app, "/ibm/v1/HMC/LockService") 610 .privileges({"ConfigureComponents", "ConfigureManager"}) 611 .methods(boost::beast::http::verb::get)( 612 [](const crow::Request&, crow::Response& res) { 613 getLockServiceData(res); 614 }); 615 616 BMCWEB_ROUTE(app, "/ibm/v1/HMC/LockService/Actions/LockService.AcquireLock") 617 .privileges({"ConfigureComponents", "ConfigureManager"}) 618 .methods(boost::beast::http::verb::post)( 619 [](const crow::Request& req, crow::Response& res) { 620 std::vector<nlohmann::json> body; 621 if (!redfish::json_util::readJson(req, res, "Request", body)) 622 { 623 BMCWEB_LOG_DEBUG << "Not a Valid JSON"; 624 res.result(boost::beast::http::status::bad_request); 625 res.end(); 626 return; 627 } 628 handleAcquireLockAPI(req, res, body); 629 }); 630 BMCWEB_ROUTE(app, "/ibm/v1/HMC/LockService/Actions/LockService.ReleaseLock") 631 .privileges({"ConfigureComponents", "ConfigureManager"}) 632 .methods(boost::beast::http::verb::post)([](const crow::Request& req, 633 crow::Response& res) { 634 std::string type; 635 std::vector<uint32_t> listTransactionIds; 636 637 if (!redfish::json_util::readJson(req, res, "Type", type, 638 "TransactionIDs", 639 listTransactionIds)) 640 { 641 res.result(boost::beast::http::status::bad_request); 642 res.end(); 643 return; 644 } 645 if (type == "Transaction") 646 { 647 handleReleaseLockAPI(req, res, listTransactionIds); 648 } 649 else if (type == "Session") 650 { 651 handleRelaseAllAPI(req, res); 652 } 653 else 654 { 655 BMCWEB_LOG_DEBUG << " Value of Type : " << type 656 << "is Not a Valid key"; 657 redfish::messages::propertyValueNotInList(res, type, "Type"); 658 } 659 }); 660 BMCWEB_ROUTE(app, "/ibm/v1/HMC/LockService/Actions/LockService.GetLockList") 661 .privileges({"ConfigureComponents", "ConfigureManager"}) 662 .methods(boost::beast::http::verb::post)( 663 [](const crow::Request& req, crow::Response& res) { 664 ListOfSessionIds listSessionIds; 665 666 if (!redfish::json_util::readJson(req, res, "SessionIDs", 667 listSessionIds)) 668 { 669 res.result(boost::beast::http::status::bad_request); 670 res.end(); 671 return; 672 } 673 handleGetLockListAPI(res, listSessionIds); 674 }); 675 676 BMCWEB_ROUTE(app, "/ibm/v1/HMC/BroadcastService") 677 .privileges({"ConfigureComponents", "ConfigureManager"}) 678 .methods(boost::beast::http::verb::post)( 679 [](const crow::Request& req, crow::Response& res) { 680 handleBroadcastService(req, res); 681 }); 682 } 683 684 } // namespace ibm_mc 685 } // namespace crow 686