1*40e9b92eSEd Tanous // SPDX-License-Identifier: Apache-2.0 2*40e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright OpenBMC Authors 3*40e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright 2020 Intel Corporation 446229577SJames Feist #pragma once 546229577SJames Feist 63ccb3adbSEd Tanous #include "app.hpp" 73ccb3adbSEd Tanous #include "dbus_utility.hpp" 83ccb3adbSEd Tanous #include "event_service_manager.hpp" 9539d8c6bSEd Tanous #include "generated/enums/resource.hpp" 10539d8c6bSEd Tanous #include "generated/enums/task_service.hpp" 111aa0c2b8SEd Tanous #include "http/parsing.hpp" 123ccb3adbSEd Tanous #include "query.hpp" 133ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 143ccb3adbSEd Tanous #include "task_messages.hpp" 153ccb3adbSEd Tanous 16d43cd0caSEd Tanous #include <boost/asio/post.hpp> 17d43cd0caSEd Tanous #include <boost/asio/steady_timer.hpp> 18ef4c65b7SEd Tanous #include <boost/url/format.hpp> 193ccb3adbSEd Tanous #include <sdbusplus/bus/match.hpp> 201214b7e7SGunnar Mills 211214b7e7SGunnar Mills #include <chrono> 223ccb3adbSEd Tanous #include <memory> 233544d2a7SEd Tanous #include <ranges> 2446229577SJames Feist #include <variant> 2546229577SJames Feist 2646229577SJames Feist namespace redfish 2746229577SJames Feist { 2846229577SJames Feist 2946229577SJames Feist namespace task 3046229577SJames Feist { 3146229577SJames Feist constexpr size_t maxTaskCount = 100; // arbitrary limit 3246229577SJames Feist 33cf9e417dSEd Tanous // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) 3446229577SJames Feist static std::deque<std::shared_ptr<struct TaskData>> tasks; 3546229577SJames Feist 3632898ceaSJames Feist constexpr bool completed = true; 3732898ceaSJames Feist 38fe306728SJames Feist struct Payload 39fe306728SJames Feist { 404e23a444SEd Tanous explicit Payload(const crow::Request& req) : 4139662a3bSEd Tanous targetUri(req.url().encoded_path()), httpOperation(req.methodString()), 421aa0c2b8SEd Tanous httpHeaders(nlohmann::json::array()) 43fe306728SJames Feist { 44fe306728SJames Feist using field_ns = boost::beast::http::field; 45fe306728SJames Feist constexpr const std::array<boost::beast::http::field, 7> 46fe306728SJames Feist headerWhitelist = {field_ns::accept, field_ns::accept_encoding, 47fe306728SJames Feist field_ns::user_agent, field_ns::host, 48fe306728SJames Feist field_ns::connection, field_ns::content_length, 49fe306728SJames Feist field_ns::upgrade}; 50fe306728SJames Feist 511aa0c2b8SEd Tanous JsonParseResult ret = parseRequestAsJson(req, jsonBody); 521aa0c2b8SEd Tanous if (ret != JsonParseResult::Success) 53fe306728SJames Feist { 541aa0c2b8SEd Tanous return; 55fe306728SJames Feist } 56fe306728SJames Feist 5798fe740bSEd Tanous for (const auto& field : req.fields()) 58fe306728SJames Feist { 593544d2a7SEd Tanous if (std::ranges::find(headerWhitelist, field.name()) == 603544d2a7SEd Tanous headerWhitelist.end()) 61fe306728SJames Feist { 62fe306728SJames Feist continue; 63fe306728SJames Feist } 64fe306728SJames Feist std::string header; 65bd79bce8SPatrick Williams header.reserve( 66bd79bce8SPatrick Williams field.name_string().size() + 2 + field.value().size()); 67fe306728SJames Feist header += field.name_string(); 68fe306728SJames Feist header += ": "; 69fe306728SJames Feist header += field.value(); 70fe306728SJames Feist httpHeaders.emplace_back(std::move(header)); 71fe306728SJames Feist } 72fe306728SJames Feist } 73fe306728SJames Feist Payload() = delete; 74fe306728SJames Feist 75fe306728SJames Feist std::string targetUri; 76fe306728SJames Feist std::string httpOperation; 77fe306728SJames Feist nlohmann::json httpHeaders; 78fe306728SJames Feist nlohmann::json jsonBody; 79fe306728SJames Feist }; 80fe306728SJames Feist 8146229577SJames Feist struct TaskData : std::enable_shared_from_this<TaskData> 8246229577SJames Feist { 8346229577SJames Feist private: 8459d494eeSPatrick Williams TaskData( 8559d494eeSPatrick Williams std::function<bool(boost::system::error_code, sdbusplus::message_t&, 8646229577SJames Feist const std::shared_ptr<TaskData>&)>&& handler, 8723a21a1cSEd Tanous const std::string& matchIn, size_t idx) : 88bd79bce8SPatrick Williams callback(std::move(handler)), matchStr(matchIn), index(idx), 8946229577SJames Feist startTime(std::chrono::system_clock::to_time_t( 9046229577SJames Feist std::chrono::system_clock::now())), 9146229577SJames Feist status("OK"), state("Running"), messages(nlohmann::json::array()), 9246229577SJames Feist timer(crow::connections::systemBus->get_io_context()) 9346229577SJames Feist 941214b7e7SGunnar Mills {} 9546229577SJames Feist 9646229577SJames Feist public: 97d609fd6eSEd Tanous TaskData() = delete; 98d609fd6eSEd Tanous 9946229577SJames Feist static std::shared_ptr<TaskData>& createTask( 10059d494eeSPatrick Williams std::function<bool(boost::system::error_code, sdbusplus::message_t&, 10146229577SJames Feist const std::shared_ptr<TaskData>&)>&& handler, 10246229577SJames Feist const std::string& match) 10346229577SJames Feist { 10446229577SJames Feist static size_t lastTask = 0; 10546229577SJames Feist struct MakeSharedHelper : public TaskData 10646229577SJames Feist { 10746229577SJames Feist MakeSharedHelper( 1081214b7e7SGunnar Mills std::function<bool(boost::system::error_code, 10959d494eeSPatrick Williams sdbusplus::message_t&, 11046229577SJames Feist const std::shared_ptr<TaskData>&)>&& handler, 11123a21a1cSEd Tanous const std::string& match2, size_t idx) : 11223a21a1cSEd Tanous TaskData(std::move(handler), match2, idx) 1131214b7e7SGunnar Mills {} 11446229577SJames Feist }; 11546229577SJames Feist 11646229577SJames Feist if (tasks.size() >= maxTaskCount) 11746229577SJames Feist { 11802cad96eSEd Tanous const auto& last = tasks.front(); 11946229577SJames Feist 12046229577SJames Feist // destroy all references 12146229577SJames Feist last->timer.cancel(); 12246229577SJames Feist last->match.reset(); 12346229577SJames Feist tasks.pop_front(); 12446229577SJames Feist } 12546229577SJames Feist 12646229577SJames Feist return tasks.emplace_back(std::make_shared<MakeSharedHelper>( 12746229577SJames Feist std::move(handler), match, lastTask++)); 12846229577SJames Feist } 12946229577SJames Feist 13046229577SJames Feist void populateResp(crow::Response& res, size_t retryAfterSeconds = 30) 13146229577SJames Feist { 13246229577SJames Feist if (!endTime) 13346229577SJames Feist { 13446229577SJames Feist res.result(boost::beast::http::status::accepted); 13546229577SJames Feist std::string strIdx = std::to_string(index); 136fdbce79bSEd Tanous boost::urls::url uri = 137fdbce79bSEd Tanous boost::urls::format("/redfish/v1/TaskService/Tasks/{}", strIdx); 1381476687dSEd Tanous 1391476687dSEd Tanous res.jsonValue["@odata.id"] = uri; 1401476687dSEd Tanous res.jsonValue["@odata.type"] = "#Task.v1_4_3.Task"; 1411476687dSEd Tanous res.jsonValue["Id"] = strIdx; 1421476687dSEd Tanous res.jsonValue["TaskState"] = state; 1431476687dSEd Tanous res.jsonValue["TaskStatus"] = status; 1441476687dSEd Tanous 145fdbce79bSEd Tanous boost::urls::url taskMonitor = boost::urls::format( 146fdbce79bSEd Tanous "/redfish/v1/TaskService/TaskMonitors/{}", strIdx); 147fdbce79bSEd Tanous 14846229577SJames Feist res.addHeader(boost::beast::http::field::location, 149fdbce79bSEd Tanous taskMonitor.buffer()); 15046229577SJames Feist res.addHeader(boost::beast::http::field::retry_after, 15146229577SJames Feist std::to_string(retryAfterSeconds)); 15246229577SJames Feist } 15346229577SJames Feist else if (!gave204) 15446229577SJames Feist { 15546229577SJames Feist res.result(boost::beast::http::status::no_content); 15646229577SJames Feist gave204 = true; 15746229577SJames Feist } 15846229577SJames Feist } 15946229577SJames Feist 160d609fd6eSEd Tanous void finishTask() 16146229577SJames Feist { 16246229577SJames Feist endTime = std::chrono::system_clock::to_time_t( 16346229577SJames Feist std::chrono::system_clock::now()); 16446229577SJames Feist } 16546229577SJames Feist 166fd9ab9e1SJames Feist void extendTimer(const std::chrono::seconds& timeout) 16746229577SJames Feist { 16846229577SJames Feist timer.expires_after(timeout); 16946229577SJames Feist timer.async_wait( 17046229577SJames Feist [self = shared_from_this()](boost::system::error_code ec) { 17146229577SJames Feist if (ec == boost::asio::error::operation_aborted) 17246229577SJames Feist { 1734e0453b1SGunnar Mills return; // completed successfully 17446229577SJames Feist } 17546229577SJames Feist if (!ec) 17646229577SJames Feist { 17746229577SJames Feist // change ec to error as timer expired 17846229577SJames Feist ec = boost::asio::error::operation_aborted; 17946229577SJames Feist } 18046229577SJames Feist self->match.reset(); 18159d494eeSPatrick Williams sdbusplus::message_t msg; 18246229577SJames Feist self->finishTask(); 18346229577SJames Feist self->state = "Cancelled"; 18446229577SJames Feist self->status = "Warning"; 185e5d5006bSJames Feist self->messages.emplace_back( 186e5d5006bSJames Feist messages::taskAborted(std::to_string(self->index))); 187e7686576SSunitha Harish // Send event :TaskAborted 188daadfb2eSEd Tanous sendTaskEvent(self->state, self->index); 18946229577SJames Feist self->callback(ec, msg, self); 19046229577SJames Feist }); 191fd9ab9e1SJames Feist } 192fd9ab9e1SJames Feist 19326ccae32SEd Tanous static void sendTaskEvent(std::string_view state, size_t index) 194e7686576SSunitha Harish { 195e7686576SSunitha Harish // TaskState enums which should send out an event are: 196e7686576SSunitha Harish // "Starting" = taskResumed 197e7686576SSunitha Harish // "Running" = taskStarted 198e7686576SSunitha Harish // "Suspended" = taskPaused 199e7686576SSunitha Harish // "Interrupted" = taskPaused 200e7686576SSunitha Harish // "Pending" = taskPaused 201e7686576SSunitha Harish // "Stopping" = taskAborted 202e7686576SSunitha Harish // "Completed" = taskCompletedOK 203e7686576SSunitha Harish // "Killed" = taskRemoved 204e7686576SSunitha Harish // "Exception" = taskCompletedWarning 205e7686576SSunitha Harish // "Cancelled" = taskCancelled 206f8fe2211SEd Tanous nlohmann::json event; 207f8fe2211SEd Tanous std::string indexStr = std::to_string(index); 208e7686576SSunitha Harish if (state == "Starting") 209e7686576SSunitha Harish { 210f8fe2211SEd Tanous event = redfish::messages::taskResumed(indexStr); 211e7686576SSunitha Harish } 212e7686576SSunitha Harish else if (state == "Running") 213e7686576SSunitha Harish { 214f8fe2211SEd Tanous event = redfish::messages::taskStarted(indexStr); 215e7686576SSunitha Harish } 216e7686576SSunitha Harish else if ((state == "Suspended") || (state == "Interrupted") || 217e7686576SSunitha Harish (state == "Pending")) 218e7686576SSunitha Harish { 219f8fe2211SEd Tanous event = redfish::messages::taskPaused(indexStr); 220e7686576SSunitha Harish } 221e7686576SSunitha Harish else if (state == "Stopping") 222e7686576SSunitha Harish { 223f8fe2211SEd Tanous event = redfish::messages::taskAborted(indexStr); 224e7686576SSunitha Harish } 225e7686576SSunitha Harish else if (state == "Completed") 226e7686576SSunitha Harish { 227f8fe2211SEd Tanous event = redfish::messages::taskCompletedOK(indexStr); 228e7686576SSunitha Harish } 229e7686576SSunitha Harish else if (state == "Killed") 230e7686576SSunitha Harish { 231f8fe2211SEd Tanous event = redfish::messages::taskRemoved(indexStr); 232e7686576SSunitha Harish } 233e7686576SSunitha Harish else if (state == "Exception") 234e7686576SSunitha Harish { 235f8fe2211SEd Tanous event = redfish::messages::taskCompletedWarning(indexStr); 236e7686576SSunitha Harish } 237e7686576SSunitha Harish else if (state == "Cancelled") 238e7686576SSunitha Harish { 239f8fe2211SEd Tanous event = redfish::messages::taskCancelled(indexStr); 240e7686576SSunitha Harish } 241e7686576SSunitha Harish else 242e7686576SSunitha Harish { 24362598e31SEd Tanous BMCWEB_LOG_INFO("sendTaskEvent: No events to send"); 244f8fe2211SEd Tanous return; 245e7686576SSunitha Harish } 246f8fe2211SEd Tanous boost::urls::url origin = 247f8fe2211SEd Tanous boost::urls::format("/redfish/v1/TaskService/Tasks/{}", index); 248f8fe2211SEd Tanous EventServiceManager::getInstance().sendEvent(event, origin.buffer(), 249f8fe2211SEd Tanous "Task"); 250e7686576SSunitha Harish } 251e7686576SSunitha Harish 252fd9ab9e1SJames Feist void startTimer(const std::chrono::seconds& timeout) 253fd9ab9e1SJames Feist { 254fd9ab9e1SJames Feist if (match) 255fd9ab9e1SJames Feist { 256fd9ab9e1SJames Feist return; 257fd9ab9e1SJames Feist } 25859d494eeSPatrick Williams match = std::make_unique<sdbusplus::bus::match_t>( 25959d494eeSPatrick Williams static_cast<sdbusplus::bus_t&>(*crow::connections::systemBus), 260fd9ab9e1SJames Feist matchStr, 26159d494eeSPatrick Williams [self = shared_from_this()](sdbusplus::message_t& message) { 262fd9ab9e1SJames Feist boost::system::error_code ec; 263fd9ab9e1SJames Feist 264fd9ab9e1SJames Feist // callback to return True if callback is done, callback needs 265fd9ab9e1SJames Feist // to update status itself if needed 266fd9ab9e1SJames Feist if (self->callback(ec, message, self) == task::completed) 267fd9ab9e1SJames Feist { 268fd9ab9e1SJames Feist self->timer.cancel(); 269fd9ab9e1SJames Feist self->finishTask(); 270fd9ab9e1SJames Feist 271e7686576SSunitha Harish // Send event 272daadfb2eSEd Tanous sendTaskEvent(self->state, self->index); 273e7686576SSunitha Harish 274fd9ab9e1SJames Feist // reset the match after the callback was successful 275fd9ab9e1SJames Feist boost::asio::post( 276fd9ab9e1SJames Feist crow::connections::systemBus->get_io_context(), 277fd9ab9e1SJames Feist [self] { self->match.reset(); }); 278fd9ab9e1SJames Feist return; 279fd9ab9e1SJames Feist } 280fd9ab9e1SJames Feist }); 281fd9ab9e1SJames Feist 282fd9ab9e1SJames Feist extendTimer(timeout); 283e5d5006bSJames Feist messages.emplace_back(messages::taskStarted(std::to_string(index))); 284e7686576SSunitha Harish // Send event : TaskStarted 285e7686576SSunitha Harish sendTaskEvent(state, index); 28646229577SJames Feist } 28746229577SJames Feist 28859d494eeSPatrick Williams std::function<bool(boost::system::error_code, sdbusplus::message_t&, 28946229577SJames Feist const std::shared_ptr<TaskData>&)> 29046229577SJames Feist callback; 29146229577SJames Feist std::string matchStr; 29246229577SJames Feist size_t index; 29346229577SJames Feist time_t startTime; 29446229577SJames Feist std::string status; 29546229577SJames Feist std::string state; 29646229577SJames Feist nlohmann::json messages; 29746229577SJames Feist boost::asio::steady_timer timer; 29859d494eeSPatrick Williams std::unique_ptr<sdbusplus::bus::match_t> match; 29946229577SJames Feist std::optional<time_t> endTime; 300fe306728SJames Feist std::optional<Payload> payload; 30146229577SJames Feist bool gave204 = false; 3026868ff50SGeorge Liu int percentComplete = 0; 30346229577SJames Feist }; 30446229577SJames Feist 30546229577SJames Feist } // namespace task 30646229577SJames Feist 3077e860f15SJohn Edward Broadbent inline void requestRoutesTaskMonitor(App& app) 30846229577SJames Feist { 309fdbce79bSEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/TaskService/TaskMonitors/<str>/") 310ed398213SEd Tanous .privileges(redfish::privileges::getTask) 3117e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 31245ca1b86SEd Tanous [&app](const crow::Request& req, 3137e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 3147e860f15SJohn Edward Broadbent const std::string& strParam) { 3153ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 31645ca1b86SEd Tanous { 31745ca1b86SEd Tanous return; 31845ca1b86SEd Tanous } 3193544d2a7SEd Tanous auto find = std::ranges::find_if( 3203544d2a7SEd Tanous task::tasks, 32146229577SJames Feist [&strParam](const std::shared_ptr<task::TaskData>& task) { 32246229577SJames Feist if (!task) 32346229577SJames Feist { 32446229577SJames Feist return false; 32546229577SJames Feist } 32646229577SJames Feist 3277e860f15SJohn Edward Broadbent // we compare against the string version as on failure 3287e860f15SJohn Edward Broadbent // strtoul returns 0 32946229577SJames Feist return std::to_string(task->index) == strParam; 33046229577SJames Feist }); 33146229577SJames Feist 33246229577SJames Feist if (find == task::tasks.end()) 33346229577SJames Feist { 334bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Task", 335bd79bce8SPatrick Williams strParam); 33646229577SJames Feist return; 33746229577SJames Feist } 33846229577SJames Feist std::shared_ptr<task::TaskData>& ptr = *find; 33946229577SJames Feist // monitor expires after 204 34046229577SJames Feist if (ptr->gave204) 34146229577SJames Feist { 342bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Task", 343bd79bce8SPatrick Williams strParam); 34446229577SJames Feist return; 34546229577SJames Feist } 34646229577SJames Feist ptr->populateResp(asyncResp->res); 3477e860f15SJohn Edward Broadbent }); 34846229577SJames Feist } 34946229577SJames Feist 3507e860f15SJohn Edward Broadbent inline void requestRoutesTask(App& app) 35146229577SJames Feist { 3527e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/TaskService/Tasks/<str>/") 353ed398213SEd Tanous .privileges(redfish::privileges::getTask) 3547e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 35545ca1b86SEd Tanous [&app](const crow::Request& req, 3567e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 3577e860f15SJohn Edward Broadbent const std::string& strParam) { 3583ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 35945ca1b86SEd Tanous { 36045ca1b86SEd Tanous return; 36145ca1b86SEd Tanous } 3623544d2a7SEd Tanous auto find = std::ranges::find_if( 3633544d2a7SEd Tanous task::tasks, 36446229577SJames Feist [&strParam](const std::shared_ptr<task::TaskData>& task) { 36546229577SJames Feist if (!task) 36646229577SJames Feist { 36746229577SJames Feist return false; 36846229577SJames Feist } 36946229577SJames Feist 3707e860f15SJohn Edward Broadbent // we compare against the string version as on failure 3717e860f15SJohn Edward Broadbent // strtoul returns 0 37246229577SJames Feist return std::to_string(task->index) == strParam; 37346229577SJames Feist }); 37446229577SJames Feist 37546229577SJames Feist if (find == task::tasks.end()) 37646229577SJames Feist { 377bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Task", 378bd79bce8SPatrick Williams strParam); 37946229577SJames Feist return; 38046229577SJames Feist } 38146229577SJames Feist 38202cad96eSEd Tanous const std::shared_ptr<task::TaskData>& ptr = *find; 38346229577SJames Feist 38446229577SJames Feist asyncResp->res.jsonValue["@odata.type"] = "#Task.v1_4_3.Task"; 38546229577SJames Feist asyncResp->res.jsonValue["Id"] = strParam; 38646229577SJames Feist asyncResp->res.jsonValue["Name"] = "Task " + strParam; 38746229577SJames Feist asyncResp->res.jsonValue["TaskState"] = ptr->state; 38846229577SJames Feist asyncResp->res.jsonValue["StartTime"] = 3892b82937eSEd Tanous redfish::time_utils::getDateTimeStdtime(ptr->startTime); 39046229577SJames Feist if (ptr->endTime) 39146229577SJames Feist { 39246229577SJames Feist asyncResp->res.jsonValue["EndTime"] = 393bd79bce8SPatrick Williams redfish::time_utils::getDateTimeStdtime( 394bd79bce8SPatrick Williams *(ptr->endTime)); 39546229577SJames Feist } 39646229577SJames Feist asyncResp->res.jsonValue["TaskStatus"] = ptr->status; 39746229577SJames Feist asyncResp->res.jsonValue["Messages"] = ptr->messages; 398bd79bce8SPatrick Williams asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 399bd79bce8SPatrick Williams "/redfish/v1/TaskService/Tasks/{}", strParam); 40046229577SJames Feist if (!ptr->gave204) 40146229577SJames Feist { 402bd79bce8SPatrick Williams asyncResp->res.jsonValue["TaskMonitor"] = 403bd79bce8SPatrick Williams boost::urls::format( 404bd79bce8SPatrick Williams "/redfish/v1/TaskService/TaskMonitors/{}", 405bd79bce8SPatrick Williams strParam); 40646229577SJames Feist } 4075db7dfd6SArun Thomas Baby 4085db7dfd6SArun Thomas Baby asyncResp->res.jsonValue["HidePayload"] = !ptr->payload; 4095db7dfd6SArun Thomas Baby 410fe306728SJames Feist if (ptr->payload) 411fe306728SJames Feist { 4125fb91ba4SEd Tanous const task::Payload& p = *(ptr->payload); 413bd79bce8SPatrick Williams asyncResp->res.jsonValue["Payload"]["TargetUri"] = 414bd79bce8SPatrick Williams p.targetUri; 4151476687dSEd Tanous asyncResp->res.jsonValue["Payload"]["HttpOperation"] = 4161476687dSEd Tanous p.httpOperation; 417bd79bce8SPatrick Williams asyncResp->res.jsonValue["Payload"]["HttpHeaders"] = 418bd79bce8SPatrick Williams p.httpHeaders; 419bd79bce8SPatrick Williams asyncResp->res.jsonValue["Payload"]["JsonBody"] = 420bd79bce8SPatrick Williams p.jsonBody.dump( 421bd79bce8SPatrick Williams -1, ' ', true, 422bd79bce8SPatrick Williams nlohmann::json::error_handler_t::replace); 423fe306728SJames Feist } 424bd79bce8SPatrick Williams asyncResp->res.jsonValue["PercentComplete"] = 425bd79bce8SPatrick Williams ptr->percentComplete; 4267e860f15SJohn Edward Broadbent }); 42746229577SJames Feist } 42846229577SJames Feist 4297e860f15SJohn Edward Broadbent inline void requestRoutesTaskCollection(App& app) 43046229577SJames Feist { 4317e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/TaskService/Tasks/") 432ed398213SEd Tanous .privileges(redfish::privileges::getTaskCollection) 4337e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 43445ca1b86SEd Tanous [&app](const crow::Request& req, 4357e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 4363ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 43745ca1b86SEd Tanous { 43845ca1b86SEd Tanous return; 43945ca1b86SEd Tanous } 44046229577SJames Feist asyncResp->res.jsonValue["@odata.type"] = 44146229577SJames Feist "#TaskCollection.TaskCollection"; 442bd79bce8SPatrick Williams asyncResp->res.jsonValue["@odata.id"] = 443bd79bce8SPatrick Williams "/redfish/v1/TaskService/Tasks"; 44446229577SJames Feist asyncResp->res.jsonValue["Name"] = "Task Collection"; 445bd79bce8SPatrick Williams asyncResp->res.jsonValue["Members@odata.count"] = 446bd79bce8SPatrick Williams task::tasks.size(); 44746229577SJames Feist nlohmann::json& members = asyncResp->res.jsonValue["Members"]; 44846229577SJames Feist members = nlohmann::json::array(); 44946229577SJames Feist 45046229577SJames Feist for (const std::shared_ptr<task::TaskData>& task : task::tasks) 45146229577SJames Feist { 45246229577SJames Feist if (task == nullptr) 45346229577SJames Feist { 45446229577SJames Feist continue; // shouldn't be possible 45546229577SJames Feist } 456613dabeaSEd Tanous nlohmann::json::object_t member; 457ef4c65b7SEd Tanous member["@odata.id"] = 458ef4c65b7SEd Tanous boost::urls::format("/redfish/v1/TaskService/Tasks/{}", 459eddfc437SWilly Tu std::to_string(task->index)); 460613dabeaSEd Tanous members.emplace_back(std::move(member)); 46146229577SJames Feist } 4627e860f15SJohn Edward Broadbent }); 46346229577SJames Feist } 46446229577SJames Feist 4657e860f15SJohn Edward Broadbent inline void requestRoutesTaskService(App& app) 46646229577SJames Feist { 4677e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/TaskService/") 468ed398213SEd Tanous .privileges(redfish::privileges::getTaskService) 4697e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 47045ca1b86SEd Tanous [&app](const crow::Request& req, 4717e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 4723ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 47345ca1b86SEd Tanous { 47445ca1b86SEd Tanous return; 47545ca1b86SEd Tanous } 47646229577SJames Feist asyncResp->res.jsonValue["@odata.type"] = 47746229577SJames Feist "#TaskService.v1_1_4.TaskService"; 478bd79bce8SPatrick Williams asyncResp->res.jsonValue["@odata.id"] = 479bd79bce8SPatrick Williams "/redfish/v1/TaskService"; 48046229577SJames Feist asyncResp->res.jsonValue["Name"] = "Task Service"; 48146229577SJames Feist asyncResp->res.jsonValue["Id"] = "TaskService"; 4827e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["DateTime"] = 4832b82937eSEd Tanous redfish::time_utils::getDateTimeOffsetNow().first; 484539d8c6bSEd Tanous asyncResp->res.jsonValue["CompletedTaskOverWritePolicy"] = 485539d8c6bSEd Tanous task_service::OverWritePolicy::Oldest; 48646229577SJames Feist 487bd79bce8SPatrick Williams asyncResp->res.jsonValue["LifeCycleEventOnTaskStateChange"] = 488bd79bce8SPatrick Williams true; 48946229577SJames Feist 490bd79bce8SPatrick Williams asyncResp->res.jsonValue["Status"]["State"] = 491bd79bce8SPatrick Williams resource::State::Enabled; 49246229577SJames Feist asyncResp->res.jsonValue["ServiceEnabled"] = true; 4931476687dSEd Tanous asyncResp->res.jsonValue["Tasks"]["@odata.id"] = 4941476687dSEd Tanous "/redfish/v1/TaskService/Tasks"; 4957e860f15SJohn Edward Broadbent }); 49646229577SJames Feist } 49746229577SJames Feist 49846229577SJames Feist } // namespace redfish 499