146229577SJames Feist /* 246229577SJames Feist // Copyright (c) 2020 Intel Corporation 346229577SJames Feist // 446229577SJames Feist // Licensed under the Apache License, Version 2.0 (the "License"); 546229577SJames Feist // you may not use this file except in compliance with the License. 646229577SJames Feist // You may obtain a copy of the License at 746229577SJames Feist // 846229577SJames Feist // http://www.apache.org/licenses/LICENSE-2.0 946229577SJames Feist // 1046229577SJames Feist // Unless required by applicable law or agreed to in writing, software 1146229577SJames Feist // distributed under the License is distributed on an "AS IS" BASIS, 1246229577SJames Feist // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1346229577SJames Feist // See the License for the specific language governing permissions and 1446229577SJames Feist // limitations under the License. 1546229577SJames Feist */ 1646229577SJames Feist #pragma once 1746229577SJames Feist 183ccb3adbSEd Tanous #include "app.hpp" 193ccb3adbSEd Tanous #include "dbus_utility.hpp" 203ccb3adbSEd Tanous #include "event_service_manager.hpp" 21d093c996SEd Tanous #include "health.hpp" 221aa0c2b8SEd Tanous #include "http/parsing.hpp" 233ccb3adbSEd Tanous #include "query.hpp" 243ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 253ccb3adbSEd Tanous #include "task_messages.hpp" 263ccb3adbSEd Tanous 27d43cd0caSEd Tanous #include <boost/asio/post.hpp> 28d43cd0caSEd Tanous #include <boost/asio/steady_timer.hpp> 29ef4c65b7SEd Tanous #include <boost/url/format.hpp> 303ccb3adbSEd Tanous #include <sdbusplus/bus/match.hpp> 311214b7e7SGunnar Mills 321214b7e7SGunnar Mills #include <chrono> 333ccb3adbSEd Tanous #include <memory> 3446229577SJames Feist #include <variant> 3546229577SJames Feist 3646229577SJames Feist namespace redfish 3746229577SJames Feist { 3846229577SJames Feist 3946229577SJames Feist namespace task 4046229577SJames Feist { 4146229577SJames Feist constexpr size_t maxTaskCount = 100; // arbitrary limit 4246229577SJames Feist 43cf9e417dSEd Tanous // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) 4446229577SJames Feist static std::deque<std::shared_ptr<struct TaskData>> tasks; 4546229577SJames Feist 4632898ceaSJames Feist constexpr bool completed = true; 4732898ceaSJames Feist 48fe306728SJames Feist struct Payload 49fe306728SJames Feist { 504e23a444SEd Tanous explicit Payload(const crow::Request& req) : 5139662a3bSEd Tanous targetUri(req.url().encoded_path()), httpOperation(req.methodString()), 521aa0c2b8SEd Tanous httpHeaders(nlohmann::json::array()) 53fe306728SJames Feist { 54fe306728SJames Feist using field_ns = boost::beast::http::field; 55fe306728SJames Feist constexpr const std::array<boost::beast::http::field, 7> 56fe306728SJames Feist headerWhitelist = {field_ns::accept, field_ns::accept_encoding, 57fe306728SJames Feist field_ns::user_agent, field_ns::host, 58fe306728SJames Feist field_ns::connection, field_ns::content_length, 59fe306728SJames Feist field_ns::upgrade}; 60fe306728SJames Feist 611aa0c2b8SEd Tanous JsonParseResult ret = parseRequestAsJson(req, jsonBody); 621aa0c2b8SEd Tanous if (ret != JsonParseResult::Success) 63fe306728SJames Feist { 641aa0c2b8SEd Tanous return; 65fe306728SJames Feist } 66fe306728SJames Feist 6798fe740bSEd Tanous for (const auto& field : req.fields()) 68fe306728SJames Feist { 69fe306728SJames Feist if (std::find(headerWhitelist.begin(), headerWhitelist.end(), 70fe306728SJames Feist field.name()) == headerWhitelist.end()) 71fe306728SJames Feist { 72fe306728SJames Feist continue; 73fe306728SJames Feist } 74fe306728SJames Feist std::string header; 75fe306728SJames Feist header.reserve(field.name_string().size() + 2 + 76fe306728SJames Feist field.value().size()); 77fe306728SJames Feist header += field.name_string(); 78fe306728SJames Feist header += ": "; 79fe306728SJames Feist header += field.value(); 80fe306728SJames Feist httpHeaders.emplace_back(std::move(header)); 81fe306728SJames Feist } 82fe306728SJames Feist } 83fe306728SJames Feist Payload() = delete; 84fe306728SJames Feist 85fe306728SJames Feist std::string targetUri; 86fe306728SJames Feist std::string httpOperation; 87fe306728SJames Feist nlohmann::json httpHeaders; 88fe306728SJames Feist nlohmann::json jsonBody; 89fe306728SJames Feist }; 90fe306728SJames Feist 9146229577SJames Feist struct TaskData : std::enable_shared_from_this<TaskData> 9246229577SJames Feist { 9346229577SJames Feist private: 9459d494eeSPatrick Williams TaskData( 9559d494eeSPatrick Williams std::function<bool(boost::system::error_code, sdbusplus::message_t&, 9646229577SJames Feist const std::shared_ptr<TaskData>&)>&& handler, 9723a21a1cSEd Tanous const std::string& matchIn, size_t idx) : 9846229577SJames Feist callback(std::move(handler)), 9923a21a1cSEd Tanous matchStr(matchIn), index(idx), 10046229577SJames Feist startTime(std::chrono::system_clock::to_time_t( 10146229577SJames Feist std::chrono::system_clock::now())), 10246229577SJames Feist status("OK"), state("Running"), messages(nlohmann::json::array()), 10346229577SJames Feist timer(crow::connections::systemBus->get_io_context()) 10446229577SJames Feist 1051214b7e7SGunnar Mills {} 10646229577SJames Feist 10746229577SJames Feist public: 108d609fd6eSEd Tanous TaskData() = delete; 109d609fd6eSEd Tanous 11046229577SJames Feist static std::shared_ptr<TaskData>& createTask( 11159d494eeSPatrick Williams std::function<bool(boost::system::error_code, sdbusplus::message_t&, 11246229577SJames Feist const std::shared_ptr<TaskData>&)>&& handler, 11346229577SJames Feist const std::string& match) 11446229577SJames Feist { 11546229577SJames Feist static size_t lastTask = 0; 11646229577SJames Feist struct MakeSharedHelper : public TaskData 11746229577SJames Feist { 11846229577SJames Feist MakeSharedHelper( 1191214b7e7SGunnar Mills std::function<bool(boost::system::error_code, 12059d494eeSPatrick Williams sdbusplus::message_t&, 12146229577SJames Feist const std::shared_ptr<TaskData>&)>&& handler, 12223a21a1cSEd Tanous const std::string& match2, size_t idx) : 12323a21a1cSEd Tanous TaskData(std::move(handler), match2, idx) 1241214b7e7SGunnar Mills {} 12546229577SJames Feist }; 12646229577SJames Feist 12746229577SJames Feist if (tasks.size() >= maxTaskCount) 12846229577SJames Feist { 12902cad96eSEd Tanous const auto& last = tasks.front(); 13046229577SJames Feist 13146229577SJames Feist // destroy all references 13246229577SJames Feist last->timer.cancel(); 13346229577SJames Feist last->match.reset(); 13446229577SJames Feist tasks.pop_front(); 13546229577SJames Feist } 13646229577SJames Feist 13746229577SJames Feist return tasks.emplace_back(std::make_shared<MakeSharedHelper>( 13846229577SJames Feist std::move(handler), match, lastTask++)); 13946229577SJames Feist } 14046229577SJames Feist 14146229577SJames Feist void populateResp(crow::Response& res, size_t retryAfterSeconds = 30) 14246229577SJames Feist { 14346229577SJames Feist if (!endTime) 14446229577SJames Feist { 14546229577SJames Feist res.result(boost::beast::http::status::accepted); 14646229577SJames Feist std::string strIdx = std::to_string(index); 14746229577SJames Feist std::string uri = "/redfish/v1/TaskService/Tasks/" + strIdx; 1481476687dSEd Tanous 1491476687dSEd Tanous res.jsonValue["@odata.id"] = uri; 1501476687dSEd Tanous res.jsonValue["@odata.type"] = "#Task.v1_4_3.Task"; 1511476687dSEd Tanous res.jsonValue["Id"] = strIdx; 1521476687dSEd Tanous res.jsonValue["TaskState"] = state; 1531476687dSEd Tanous res.jsonValue["TaskStatus"] = status; 1541476687dSEd Tanous 15546229577SJames Feist res.addHeader(boost::beast::http::field::location, 15646229577SJames Feist uri + "/Monitor"); 15746229577SJames Feist res.addHeader(boost::beast::http::field::retry_after, 15846229577SJames Feist std::to_string(retryAfterSeconds)); 15946229577SJames Feist } 16046229577SJames Feist else if (!gave204) 16146229577SJames Feist { 16246229577SJames Feist res.result(boost::beast::http::status::no_content); 16346229577SJames Feist gave204 = true; 16446229577SJames Feist } 16546229577SJames Feist } 16646229577SJames Feist 167d609fd6eSEd Tanous void finishTask() 16846229577SJames Feist { 16946229577SJames Feist endTime = std::chrono::system_clock::to_time_t( 17046229577SJames Feist std::chrono::system_clock::now()); 17146229577SJames Feist } 17246229577SJames Feist 173fd9ab9e1SJames Feist void extendTimer(const std::chrono::seconds& timeout) 17446229577SJames Feist { 17546229577SJames Feist timer.expires_after(timeout); 17646229577SJames Feist timer.async_wait( 17746229577SJames Feist [self = shared_from_this()](boost::system::error_code ec) { 17846229577SJames Feist if (ec == boost::asio::error::operation_aborted) 17946229577SJames Feist { 1804e0453b1SGunnar Mills return; // completed successfully 18146229577SJames Feist } 18246229577SJames Feist if (!ec) 18346229577SJames Feist { 18446229577SJames Feist // change ec to error as timer expired 18546229577SJames Feist ec = boost::asio::error::operation_aborted; 18646229577SJames Feist } 18746229577SJames Feist self->match.reset(); 18859d494eeSPatrick Williams sdbusplus::message_t msg; 18946229577SJames Feist self->finishTask(); 19046229577SJames Feist self->state = "Cancelled"; 19146229577SJames Feist self->status = "Warning"; 192e5d5006bSJames Feist self->messages.emplace_back( 193e5d5006bSJames Feist messages::taskAborted(std::to_string(self->index))); 194e7686576SSunitha Harish // Send event :TaskAborted 195e7686576SSunitha Harish self->sendTaskEvent(self->state, self->index); 19646229577SJames Feist self->callback(ec, msg, self); 19746229577SJames Feist }); 198fd9ab9e1SJames Feist } 199fd9ab9e1SJames Feist 20026ccae32SEd Tanous static void sendTaskEvent(std::string_view state, size_t index) 201e7686576SSunitha Harish { 20289492a15SPatrick Williams std::string origin = "/redfish/v1/TaskService/Tasks/" + 20389492a15SPatrick Williams std::to_string(index); 204e7686576SSunitha Harish std::string resType = "Task"; 205e7686576SSunitha Harish // TaskState enums which should send out an event are: 206e7686576SSunitha Harish // "Starting" = taskResumed 207e7686576SSunitha Harish // "Running" = taskStarted 208e7686576SSunitha Harish // "Suspended" = taskPaused 209e7686576SSunitha Harish // "Interrupted" = taskPaused 210e7686576SSunitha Harish // "Pending" = taskPaused 211e7686576SSunitha Harish // "Stopping" = taskAborted 212e7686576SSunitha Harish // "Completed" = taskCompletedOK 213e7686576SSunitha Harish // "Killed" = taskRemoved 214e7686576SSunitha Harish // "Exception" = taskCompletedWarning 215e7686576SSunitha Harish // "Cancelled" = taskCancelled 216e7686576SSunitha Harish if (state == "Starting") 217e7686576SSunitha Harish { 218e7686576SSunitha Harish redfish::EventServiceManager::getInstance().sendEvent( 219e7686576SSunitha Harish redfish::messages::taskResumed(std::to_string(index)), origin, 220e7686576SSunitha Harish resType); 221e7686576SSunitha Harish } 222e7686576SSunitha Harish else if (state == "Running") 223e7686576SSunitha Harish { 224e7686576SSunitha Harish redfish::EventServiceManager::getInstance().sendEvent( 225e7686576SSunitha Harish redfish::messages::taskStarted(std::to_string(index)), origin, 226e7686576SSunitha Harish resType); 227e7686576SSunitha Harish } 228e7686576SSunitha Harish else if ((state == "Suspended") || (state == "Interrupted") || 229e7686576SSunitha Harish (state == "Pending")) 230e7686576SSunitha Harish { 231e7686576SSunitha Harish redfish::EventServiceManager::getInstance().sendEvent( 232e7686576SSunitha Harish redfish::messages::taskPaused(std::to_string(index)), origin, 233e7686576SSunitha Harish resType); 234e7686576SSunitha Harish } 235e7686576SSunitha Harish else if (state == "Stopping") 236e7686576SSunitha Harish { 237e7686576SSunitha Harish redfish::EventServiceManager::getInstance().sendEvent( 238e7686576SSunitha Harish redfish::messages::taskAborted(std::to_string(index)), origin, 239e7686576SSunitha Harish resType); 240e7686576SSunitha Harish } 241e7686576SSunitha Harish else if (state == "Completed") 242e7686576SSunitha Harish { 243e7686576SSunitha Harish redfish::EventServiceManager::getInstance().sendEvent( 244e7686576SSunitha Harish redfish::messages::taskCompletedOK(std::to_string(index)), 245e7686576SSunitha Harish origin, resType); 246e7686576SSunitha Harish } 247e7686576SSunitha Harish else if (state == "Killed") 248e7686576SSunitha Harish { 249e7686576SSunitha Harish redfish::EventServiceManager::getInstance().sendEvent( 250e7686576SSunitha Harish redfish::messages::taskRemoved(std::to_string(index)), origin, 251e7686576SSunitha Harish resType); 252e7686576SSunitha Harish } 253e7686576SSunitha Harish else if (state == "Exception") 254e7686576SSunitha Harish { 255e7686576SSunitha Harish redfish::EventServiceManager::getInstance().sendEvent( 256e7686576SSunitha Harish redfish::messages::taskCompletedWarning(std::to_string(index)), 257e7686576SSunitha Harish origin, resType); 258e7686576SSunitha Harish } 259e7686576SSunitha Harish else if (state == "Cancelled") 260e7686576SSunitha Harish { 261e7686576SSunitha Harish redfish::EventServiceManager::getInstance().sendEvent( 262e7686576SSunitha Harish redfish::messages::taskCancelled(std::to_string(index)), origin, 263e7686576SSunitha Harish resType); 264e7686576SSunitha Harish } 265e7686576SSunitha Harish else 266e7686576SSunitha Harish { 267e7686576SSunitha Harish BMCWEB_LOG_INFO << "sendTaskEvent: No events to send"; 268e7686576SSunitha Harish } 269e7686576SSunitha Harish } 270e7686576SSunitha Harish 271fd9ab9e1SJames Feist void startTimer(const std::chrono::seconds& timeout) 272fd9ab9e1SJames Feist { 273fd9ab9e1SJames Feist if (match) 274fd9ab9e1SJames Feist { 275fd9ab9e1SJames Feist return; 276fd9ab9e1SJames Feist } 27759d494eeSPatrick Williams match = std::make_unique<sdbusplus::bus::match_t>( 27859d494eeSPatrick Williams static_cast<sdbusplus::bus_t&>(*crow::connections::systemBus), 279fd9ab9e1SJames Feist matchStr, 28059d494eeSPatrick Williams [self = shared_from_this()](sdbusplus::message_t& message) { 281fd9ab9e1SJames Feist boost::system::error_code ec; 282fd9ab9e1SJames Feist 283fd9ab9e1SJames Feist // callback to return True if callback is done, callback needs 284fd9ab9e1SJames Feist // to update status itself if needed 285fd9ab9e1SJames Feist if (self->callback(ec, message, self) == task::completed) 286fd9ab9e1SJames Feist { 287fd9ab9e1SJames Feist self->timer.cancel(); 288fd9ab9e1SJames Feist self->finishTask(); 289fd9ab9e1SJames Feist 290e7686576SSunitha Harish // Send event 291e7686576SSunitha Harish self->sendTaskEvent(self->state, self->index); 292e7686576SSunitha Harish 293fd9ab9e1SJames Feist // reset the match after the callback was successful 294fd9ab9e1SJames Feist boost::asio::post( 295fd9ab9e1SJames Feist crow::connections::systemBus->get_io_context(), 296fd9ab9e1SJames Feist [self] { self->match.reset(); }); 297fd9ab9e1SJames Feist return; 298fd9ab9e1SJames Feist } 299fd9ab9e1SJames Feist }); 300fd9ab9e1SJames Feist 301fd9ab9e1SJames Feist extendTimer(timeout); 302e5d5006bSJames Feist messages.emplace_back(messages::taskStarted(std::to_string(index))); 303e7686576SSunitha Harish // Send event : TaskStarted 304e7686576SSunitha Harish sendTaskEvent(state, index); 30546229577SJames Feist } 30646229577SJames Feist 30759d494eeSPatrick Williams std::function<bool(boost::system::error_code, sdbusplus::message_t&, 30846229577SJames Feist const std::shared_ptr<TaskData>&)> 30946229577SJames Feist callback; 31046229577SJames Feist std::string matchStr; 31146229577SJames Feist size_t index; 31246229577SJames Feist time_t startTime; 31346229577SJames Feist std::string status; 31446229577SJames Feist std::string state; 31546229577SJames Feist nlohmann::json messages; 31646229577SJames Feist boost::asio::steady_timer timer; 31759d494eeSPatrick Williams std::unique_ptr<sdbusplus::bus::match_t> match; 31846229577SJames Feist std::optional<time_t> endTime; 319fe306728SJames Feist std::optional<Payload> payload; 32046229577SJames Feist bool gave204 = false; 3216868ff50SGeorge Liu int percentComplete = 0; 32246229577SJames Feist }; 32346229577SJames Feist 32446229577SJames Feist } // namespace task 32546229577SJames Feist 3267e860f15SJohn Edward Broadbent inline void requestRoutesTaskMonitor(App& app) 32746229577SJames Feist { 3287e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/TaskService/Tasks/<str>/Monitor/") 329ed398213SEd Tanous .privileges(redfish::privileges::getTask) 3307e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 33145ca1b86SEd Tanous [&app](const crow::Request& req, 3327e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 3337e860f15SJohn Edward Broadbent const std::string& strParam) { 3343ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 33545ca1b86SEd Tanous { 33645ca1b86SEd Tanous return; 33745ca1b86SEd Tanous } 33846229577SJames Feist auto find = std::find_if( 33946229577SJames Feist task::tasks.begin(), task::tasks.end(), 34046229577SJames Feist [&strParam](const std::shared_ptr<task::TaskData>& task) { 34146229577SJames Feist if (!task) 34246229577SJames Feist { 34346229577SJames Feist return false; 34446229577SJames Feist } 34546229577SJames Feist 3467e860f15SJohn Edward Broadbent // we compare against the string version as on failure 3477e860f15SJohn Edward Broadbent // strtoul returns 0 34846229577SJames Feist return std::to_string(task->index) == strParam; 34946229577SJames Feist }); 35046229577SJames Feist 35146229577SJames Feist if (find == task::tasks.end()) 35246229577SJames Feist { 353d8a5d5d8SJiaqing Zhao messages::resourceNotFound(asyncResp->res, "Task", strParam); 35446229577SJames Feist return; 35546229577SJames Feist } 35646229577SJames Feist std::shared_ptr<task::TaskData>& ptr = *find; 35746229577SJames Feist // monitor expires after 204 35846229577SJames Feist if (ptr->gave204) 35946229577SJames Feist { 360d8a5d5d8SJiaqing Zhao messages::resourceNotFound(asyncResp->res, "Task", strParam); 36146229577SJames Feist return; 36246229577SJames Feist } 36346229577SJames Feist ptr->populateResp(asyncResp->res); 3647e860f15SJohn Edward Broadbent }); 36546229577SJames Feist } 36646229577SJames Feist 3677e860f15SJohn Edward Broadbent inline void requestRoutesTask(App& app) 36846229577SJames Feist { 3697e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/TaskService/Tasks/<str>/") 370ed398213SEd Tanous .privileges(redfish::privileges::getTask) 3717e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 37245ca1b86SEd Tanous [&app](const crow::Request& req, 3737e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 3747e860f15SJohn Edward Broadbent const std::string& strParam) { 3753ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 37645ca1b86SEd Tanous { 37745ca1b86SEd Tanous return; 37845ca1b86SEd Tanous } 37946229577SJames Feist auto find = std::find_if( 38046229577SJames Feist task::tasks.begin(), task::tasks.end(), 38146229577SJames Feist [&strParam](const std::shared_ptr<task::TaskData>& task) { 38246229577SJames Feist if (!task) 38346229577SJames Feist { 38446229577SJames Feist return false; 38546229577SJames Feist } 38646229577SJames Feist 3877e860f15SJohn Edward Broadbent // we compare against the string version as on failure 3887e860f15SJohn Edward Broadbent // strtoul returns 0 38946229577SJames Feist return std::to_string(task->index) == strParam; 39046229577SJames Feist }); 39146229577SJames Feist 39246229577SJames Feist if (find == task::tasks.end()) 39346229577SJames Feist { 394d8a5d5d8SJiaqing Zhao messages::resourceNotFound(asyncResp->res, "Task", strParam); 39546229577SJames Feist return; 39646229577SJames Feist } 39746229577SJames Feist 39802cad96eSEd Tanous const std::shared_ptr<task::TaskData>& ptr = *find; 39946229577SJames Feist 40046229577SJames Feist asyncResp->res.jsonValue["@odata.type"] = "#Task.v1_4_3.Task"; 40146229577SJames Feist asyncResp->res.jsonValue["Id"] = strParam; 40246229577SJames Feist asyncResp->res.jsonValue["Name"] = "Task " + strParam; 40346229577SJames Feist asyncResp->res.jsonValue["TaskState"] = ptr->state; 40446229577SJames Feist asyncResp->res.jsonValue["StartTime"] = 4052b82937eSEd Tanous redfish::time_utils::getDateTimeStdtime(ptr->startTime); 40646229577SJames Feist if (ptr->endTime) 40746229577SJames Feist { 40846229577SJames Feist asyncResp->res.jsonValue["EndTime"] = 4092b82937eSEd Tanous redfish::time_utils::getDateTimeStdtime(*(ptr->endTime)); 41046229577SJames Feist } 41146229577SJames Feist asyncResp->res.jsonValue["TaskStatus"] = ptr->status; 41246229577SJames Feist asyncResp->res.jsonValue["Messages"] = ptr->messages; 413ef4c65b7SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 414ef4c65b7SEd Tanous boost::urls::format("/redfish/v1/TaskService/Tasks/{}", strParam); 41546229577SJames Feist if (!ptr->gave204) 41646229577SJames Feist { 41746229577SJames Feist asyncResp->res.jsonValue["TaskMonitor"] = 418002d39b4SEd Tanous "/redfish/v1/TaskService/Tasks/" + strParam + "/Monitor"; 41946229577SJames Feist } 420*5db7dfd6SArun Thomas Baby 421*5db7dfd6SArun Thomas Baby asyncResp->res.jsonValue["HidePayload"] = !ptr->payload; 422*5db7dfd6SArun Thomas Baby 423fe306728SJames Feist if (ptr->payload) 424fe306728SJames Feist { 4255fb91ba4SEd Tanous const task::Payload& p = *(ptr->payload); 426002d39b4SEd Tanous asyncResp->res.jsonValue["Payload"]["TargetUri"] = p.targetUri; 4271476687dSEd Tanous asyncResp->res.jsonValue["Payload"]["HttpOperation"] = 4281476687dSEd Tanous p.httpOperation; 429002d39b4SEd Tanous asyncResp->res.jsonValue["Payload"]["HttpHeaders"] = p.httpHeaders; 430002d39b4SEd Tanous asyncResp->res.jsonValue["Payload"]["JsonBody"] = p.jsonBody.dump( 431002d39b4SEd Tanous 2, ' ', true, nlohmann::json::error_handler_t::replace); 432fe306728SJames Feist } 433002d39b4SEd Tanous asyncResp->res.jsonValue["PercentComplete"] = ptr->percentComplete; 4347e860f15SJohn Edward Broadbent }); 43546229577SJames Feist } 43646229577SJames Feist 4377e860f15SJohn Edward Broadbent inline void requestRoutesTaskCollection(App& app) 43846229577SJames Feist { 4397e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/TaskService/Tasks/") 440ed398213SEd Tanous .privileges(redfish::privileges::getTaskCollection) 4417e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 44245ca1b86SEd Tanous [&app](const crow::Request& req, 4437e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 4443ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 44545ca1b86SEd Tanous { 44645ca1b86SEd Tanous return; 44745ca1b86SEd Tanous } 44846229577SJames Feist asyncResp->res.jsonValue["@odata.type"] = 44946229577SJames Feist "#TaskCollection.TaskCollection"; 450002d39b4SEd Tanous asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/TaskService/Tasks"; 45146229577SJames Feist asyncResp->res.jsonValue["Name"] = "Task Collection"; 452002d39b4SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = task::tasks.size(); 45346229577SJames Feist nlohmann::json& members = asyncResp->res.jsonValue["Members"]; 45446229577SJames Feist members = nlohmann::json::array(); 45546229577SJames Feist 45646229577SJames Feist for (const std::shared_ptr<task::TaskData>& task : task::tasks) 45746229577SJames Feist { 45846229577SJames Feist if (task == nullptr) 45946229577SJames Feist { 46046229577SJames Feist continue; // shouldn't be possible 46146229577SJames Feist } 462613dabeaSEd Tanous nlohmann::json::object_t member; 463ef4c65b7SEd Tanous member["@odata.id"] = 464ef4c65b7SEd Tanous boost::urls::format("/redfish/v1/TaskService/Tasks/{}", 465eddfc437SWilly Tu std::to_string(task->index)); 466613dabeaSEd Tanous members.emplace_back(std::move(member)); 46746229577SJames Feist } 4687e860f15SJohn Edward Broadbent }); 46946229577SJames Feist } 47046229577SJames Feist 4717e860f15SJohn Edward Broadbent inline void requestRoutesTaskService(App& app) 47246229577SJames Feist { 4737e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/TaskService/") 474ed398213SEd Tanous .privileges(redfish::privileges::getTaskService) 4757e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 47645ca1b86SEd Tanous [&app](const crow::Request& req, 4777e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 4783ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 47945ca1b86SEd Tanous { 48045ca1b86SEd Tanous return; 48145ca1b86SEd Tanous } 48246229577SJames Feist asyncResp->res.jsonValue["@odata.type"] = 48346229577SJames Feist "#TaskService.v1_1_4.TaskService"; 484002d39b4SEd Tanous asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/TaskService"; 48546229577SJames Feist asyncResp->res.jsonValue["Name"] = "Task Service"; 48646229577SJames Feist asyncResp->res.jsonValue["Id"] = "TaskService"; 4877e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["DateTime"] = 4882b82937eSEd Tanous redfish::time_utils::getDateTimeOffsetNow().first; 489002d39b4SEd Tanous asyncResp->res.jsonValue["CompletedTaskOverWritePolicy"] = "Oldest"; 49046229577SJames Feist 491002d39b4SEd Tanous asyncResp->res.jsonValue["LifeCycleEventOnTaskStateChange"] = true; 49246229577SJames Feist 49346229577SJames Feist auto health = std::make_shared<HealthPopulate>(asyncResp); 49446229577SJames Feist health->populate(); 49546229577SJames Feist asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; 49646229577SJames Feist asyncResp->res.jsonValue["ServiceEnabled"] = true; 4971476687dSEd Tanous asyncResp->res.jsonValue["Tasks"]["@odata.id"] = 4981476687dSEd Tanous "/redfish/v1/TaskService/Tasks"; 4997e860f15SJohn Edward Broadbent }); 50046229577SJames Feist } 50146229577SJames Feist 50246229577SJames Feist } // namespace redfish 503