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 1846229577SJames Feist #include "node.hpp" 1946229577SJames Feist 20decde9efSZhenfei Tai #include <boost/asio.hpp> 2146229577SJames Feist #include <boost/container/flat_map.hpp> 22e5d5006bSJames Feist #include <task_messages.hpp> 231214b7e7SGunnar Mills 241214b7e7SGunnar Mills #include <chrono> 2546229577SJames Feist #include <variant> 2646229577SJames Feist 2746229577SJames Feist namespace redfish 2846229577SJames Feist { 2946229577SJames Feist 3046229577SJames Feist namespace task 3146229577SJames Feist { 3246229577SJames Feist constexpr size_t maxTaskCount = 100; // arbitrary limit 3346229577SJames Feist 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 { 40fe306728SJames Feist Payload(const crow::Request& req) : 41fe306728SJames Feist targetUri(req.url), httpOperation(req.methodString()), 42fe306728SJames Feist httpHeaders(nlohmann::json::array()) 43fe306728SJames Feist 44fe306728SJames Feist { 45fe306728SJames Feist using field_ns = boost::beast::http::field; 46fe306728SJames Feist constexpr const std::array<boost::beast::http::field, 7> 47fe306728SJames Feist headerWhitelist = {field_ns::accept, field_ns::accept_encoding, 48fe306728SJames Feist field_ns::user_agent, field_ns::host, 49fe306728SJames Feist field_ns::connection, field_ns::content_length, 50fe306728SJames Feist field_ns::upgrade}; 51fe306728SJames Feist 52fe306728SJames Feist jsonBody = nlohmann::json::parse(req.body, nullptr, false); 53fe306728SJames Feist if (jsonBody.is_discarded()) 54fe306728SJames Feist { 55fe306728SJames Feist jsonBody = nullptr; 56fe306728SJames Feist } 57fe306728SJames Feist 58fe306728SJames Feist for (const auto& field : req.fields) 59fe306728SJames Feist { 60fe306728SJames Feist if (std::find(headerWhitelist.begin(), headerWhitelist.end(), 61fe306728SJames Feist field.name()) == headerWhitelist.end()) 62fe306728SJames Feist { 63fe306728SJames Feist continue; 64fe306728SJames Feist } 65fe306728SJames Feist std::string header; 66fe306728SJames Feist header.reserve(field.name_string().size() + 2 + 67fe306728SJames Feist field.value().size()); 68fe306728SJames Feist header += field.name_string(); 69fe306728SJames Feist header += ": "; 70fe306728SJames Feist header += field.value(); 71fe306728SJames Feist httpHeaders.emplace_back(std::move(header)); 72fe306728SJames Feist } 73fe306728SJames Feist } 74fe306728SJames Feist Payload() = delete; 75fe306728SJames Feist 76fe306728SJames Feist std::string targetUri; 77fe306728SJames Feist std::string httpOperation; 78fe306728SJames Feist nlohmann::json httpHeaders; 79fe306728SJames Feist nlohmann::json jsonBody; 80fe306728SJames Feist }; 81fe306728SJames Feist 82fe306728SJames Feist inline void to_json(nlohmann::json& j, const Payload& p) 83fe306728SJames Feist { 84fe306728SJames Feist j = {{"TargetUri", p.targetUri}, 85fe306728SJames Feist {"HttpOperation", p.httpOperation}, 86fe306728SJames Feist {"HttpHeaders", p.httpHeaders}, 87fe306728SJames Feist {"JsonBody", p.jsonBody.dump()}}; 88fe306728SJames Feist } 89fe306728SJames Feist 9046229577SJames Feist struct TaskData : std::enable_shared_from_this<TaskData> 9146229577SJames Feist { 9246229577SJames Feist private: 9346229577SJames Feist TaskData(std::function<bool(boost::system::error_code, 9446229577SJames Feist sdbusplus::message::message&, 9546229577SJames Feist const std::shared_ptr<TaskData>&)>&& handler, 9623a21a1cSEd Tanous const std::string& matchIn, size_t idx) : 9746229577SJames Feist callback(std::move(handler)), 9823a21a1cSEd Tanous matchStr(matchIn), index(idx), 9946229577SJames Feist startTime(std::chrono::system_clock::to_time_t( 10046229577SJames Feist std::chrono::system_clock::now())), 10146229577SJames Feist status("OK"), state("Running"), messages(nlohmann::json::array()), 10246229577SJames Feist timer(crow::connections::systemBus->get_io_context()) 10346229577SJames Feist 1041214b7e7SGunnar Mills {} 10546229577SJames Feist TaskData() = delete; 10646229577SJames Feist 10746229577SJames Feist public: 10846229577SJames Feist static std::shared_ptr<TaskData>& createTask( 10946229577SJames Feist std::function<bool(boost::system::error_code, 11046229577SJames Feist sdbusplus::message::message&, 11146229577SJames Feist const std::shared_ptr<TaskData>&)>&& handler, 11246229577SJames Feist const std::string& match) 11346229577SJames Feist { 11446229577SJames Feist static size_t lastTask = 0; 11546229577SJames Feist struct MakeSharedHelper : public TaskData 11646229577SJames Feist { 11746229577SJames Feist MakeSharedHelper( 1181214b7e7SGunnar Mills std::function<bool(boost::system::error_code, 1191214b7e7SGunnar Mills sdbusplus::message::message&, 12046229577SJames Feist const std::shared_ptr<TaskData>&)>&& handler, 12123a21a1cSEd Tanous const std::string& match2, size_t idx) : 12223a21a1cSEd Tanous TaskData(std::move(handler), match2, idx) 1231214b7e7SGunnar Mills {} 12446229577SJames Feist }; 12546229577SJames Feist 12646229577SJames Feist if (tasks.size() >= maxTaskCount) 12746229577SJames Feist { 12846229577SJames Feist auto& last = tasks.front(); 12946229577SJames Feist 13046229577SJames Feist // destroy all references 13146229577SJames Feist last->timer.cancel(); 13246229577SJames Feist last->match.reset(); 13346229577SJames Feist tasks.pop_front(); 13446229577SJames Feist } 13546229577SJames Feist 13646229577SJames Feist return tasks.emplace_back(std::make_shared<MakeSharedHelper>( 13746229577SJames Feist std::move(handler), match, lastTask++)); 13846229577SJames Feist } 13946229577SJames Feist 14046229577SJames Feist void populateResp(crow::Response& res, size_t retryAfterSeconds = 30) 14146229577SJames Feist { 14246229577SJames Feist if (!endTime) 14346229577SJames Feist { 14446229577SJames Feist res.result(boost::beast::http::status::accepted); 14546229577SJames Feist std::string strIdx = std::to_string(index); 14646229577SJames Feist std::string uri = "/redfish/v1/TaskService/Tasks/" + strIdx; 14746229577SJames Feist res.jsonValue = {{"@odata.id", uri}, 14846229577SJames Feist {"@odata.type", "#Task.v1_4_3.Task"}, 14946229577SJames Feist {"Id", strIdx}, 15046229577SJames Feist {"TaskState", state}, 15146229577SJames Feist {"TaskStatus", status}}; 15246229577SJames Feist res.addHeader(boost::beast::http::field::location, 15346229577SJames Feist uri + "/Monitor"); 15446229577SJames Feist res.addHeader(boost::beast::http::field::retry_after, 15546229577SJames Feist std::to_string(retryAfterSeconds)); 15646229577SJames Feist } 15746229577SJames Feist else if (!gave204) 15846229577SJames Feist { 15946229577SJames Feist res.result(boost::beast::http::status::no_content); 16046229577SJames Feist gave204 = true; 16146229577SJames Feist } 16246229577SJames Feist } 16346229577SJames Feist 16446229577SJames Feist void finishTask(void) 16546229577SJames Feist { 16646229577SJames Feist endTime = std::chrono::system_clock::to_time_t( 16746229577SJames Feist std::chrono::system_clock::now()); 16846229577SJames Feist } 16946229577SJames Feist 170fd9ab9e1SJames Feist void extendTimer(const std::chrono::seconds& timeout) 17146229577SJames Feist { 17246229577SJames Feist timer.expires_after(timeout); 17346229577SJames Feist timer.async_wait( 17446229577SJames Feist [self = shared_from_this()](boost::system::error_code ec) { 17546229577SJames Feist if (ec == boost::asio::error::operation_aborted) 17646229577SJames Feist { 1774e0453b1SGunnar Mills return; // completed successfully 17846229577SJames Feist } 17946229577SJames Feist if (!ec) 18046229577SJames Feist { 18146229577SJames Feist // change ec to error as timer expired 18246229577SJames Feist ec = boost::asio::error::operation_aborted; 18346229577SJames Feist } 18446229577SJames Feist self->match.reset(); 18546229577SJames Feist sdbusplus::message::message msg; 18646229577SJames Feist self->finishTask(); 18746229577SJames Feist self->state = "Cancelled"; 18846229577SJames Feist self->status = "Warning"; 189e5d5006bSJames Feist self->messages.emplace_back( 190e5d5006bSJames Feist messages::taskAborted(std::to_string(self->index))); 191*e7686576SSunitha Harish // Send event :TaskAborted 192*e7686576SSunitha Harish self->sendTaskEvent(self->state, self->index); 19346229577SJames Feist self->callback(ec, msg, self); 19446229577SJames Feist }); 195fd9ab9e1SJames Feist } 196fd9ab9e1SJames Feist 197*e7686576SSunitha Harish void sendTaskEvent(const std::string_view state, size_t index) 198*e7686576SSunitha Harish { 199*e7686576SSunitha Harish std::string origin = 200*e7686576SSunitha Harish "/redfish/v1/TaskService/Tasks/" + std::to_string(index); 201*e7686576SSunitha Harish std::string resType = "Task"; 202*e7686576SSunitha Harish // TaskState enums which should send out an event are: 203*e7686576SSunitha Harish // "Starting" = taskResumed 204*e7686576SSunitha Harish // "Running" = taskStarted 205*e7686576SSunitha Harish // "Suspended" = taskPaused 206*e7686576SSunitha Harish // "Interrupted" = taskPaused 207*e7686576SSunitha Harish // "Pending" = taskPaused 208*e7686576SSunitha Harish // "Stopping" = taskAborted 209*e7686576SSunitha Harish // "Completed" = taskCompletedOK 210*e7686576SSunitha Harish // "Killed" = taskRemoved 211*e7686576SSunitha Harish // "Exception" = taskCompletedWarning 212*e7686576SSunitha Harish // "Cancelled" = taskCancelled 213*e7686576SSunitha Harish if (state == "Starting") 214*e7686576SSunitha Harish { 215*e7686576SSunitha Harish redfish::EventServiceManager::getInstance().sendEvent( 216*e7686576SSunitha Harish redfish::messages::taskResumed(std::to_string(index)), origin, 217*e7686576SSunitha Harish resType); 218*e7686576SSunitha Harish } 219*e7686576SSunitha Harish else if (state == "Running") 220*e7686576SSunitha Harish { 221*e7686576SSunitha Harish redfish::EventServiceManager::getInstance().sendEvent( 222*e7686576SSunitha Harish redfish::messages::taskStarted(std::to_string(index)), origin, 223*e7686576SSunitha Harish resType); 224*e7686576SSunitha Harish } 225*e7686576SSunitha Harish else if ((state == "Suspended") || (state == "Interrupted") || 226*e7686576SSunitha Harish (state == "Pending")) 227*e7686576SSunitha Harish { 228*e7686576SSunitha Harish redfish::EventServiceManager::getInstance().sendEvent( 229*e7686576SSunitha Harish redfish::messages::taskPaused(std::to_string(index)), origin, 230*e7686576SSunitha Harish resType); 231*e7686576SSunitha Harish } 232*e7686576SSunitha Harish else if (state == "Stopping") 233*e7686576SSunitha Harish { 234*e7686576SSunitha Harish redfish::EventServiceManager::getInstance().sendEvent( 235*e7686576SSunitha Harish redfish::messages::taskAborted(std::to_string(index)), origin, 236*e7686576SSunitha Harish resType); 237*e7686576SSunitha Harish } 238*e7686576SSunitha Harish else if (state == "Completed") 239*e7686576SSunitha Harish { 240*e7686576SSunitha Harish redfish::EventServiceManager::getInstance().sendEvent( 241*e7686576SSunitha Harish redfish::messages::taskCompletedOK(std::to_string(index)), 242*e7686576SSunitha Harish origin, resType); 243*e7686576SSunitha Harish } 244*e7686576SSunitha Harish else if (state == "Killed") 245*e7686576SSunitha Harish { 246*e7686576SSunitha Harish redfish::EventServiceManager::getInstance().sendEvent( 247*e7686576SSunitha Harish redfish::messages::taskRemoved(std::to_string(index)), origin, 248*e7686576SSunitha Harish resType); 249*e7686576SSunitha Harish } 250*e7686576SSunitha Harish else if (state == "Exception") 251*e7686576SSunitha Harish { 252*e7686576SSunitha Harish redfish::EventServiceManager::getInstance().sendEvent( 253*e7686576SSunitha Harish redfish::messages::taskCompletedWarning(std::to_string(index)), 254*e7686576SSunitha Harish origin, resType); 255*e7686576SSunitha Harish } 256*e7686576SSunitha Harish else if (state == "Cancelled") 257*e7686576SSunitha Harish { 258*e7686576SSunitha Harish redfish::EventServiceManager::getInstance().sendEvent( 259*e7686576SSunitha Harish redfish::messages::taskCancelled(std::to_string(index)), origin, 260*e7686576SSunitha Harish resType); 261*e7686576SSunitha Harish } 262*e7686576SSunitha Harish else 263*e7686576SSunitha Harish { 264*e7686576SSunitha Harish BMCWEB_LOG_INFO << "sendTaskEvent: No events to send"; 265*e7686576SSunitha Harish } 266*e7686576SSunitha Harish } 267*e7686576SSunitha Harish 268fd9ab9e1SJames Feist void startTimer(const std::chrono::seconds& timeout) 269fd9ab9e1SJames Feist { 270fd9ab9e1SJames Feist if (match) 271fd9ab9e1SJames Feist { 272fd9ab9e1SJames Feist return; 273fd9ab9e1SJames Feist } 274fd9ab9e1SJames Feist match = std::make_unique<sdbusplus::bus::match::match>( 275fd9ab9e1SJames Feist static_cast<sdbusplus::bus::bus&>(*crow::connections::systemBus), 276fd9ab9e1SJames Feist matchStr, 277fd9ab9e1SJames Feist [self = shared_from_this()](sdbusplus::message::message& message) { 278fd9ab9e1SJames Feist boost::system::error_code ec; 279fd9ab9e1SJames Feist 280fd9ab9e1SJames Feist // callback to return True if callback is done, callback needs 281fd9ab9e1SJames Feist // to update status itself if needed 282fd9ab9e1SJames Feist if (self->callback(ec, message, self) == task::completed) 283fd9ab9e1SJames Feist { 284fd9ab9e1SJames Feist self->timer.cancel(); 285fd9ab9e1SJames Feist self->finishTask(); 286fd9ab9e1SJames Feist 287*e7686576SSunitha Harish // Send event 288*e7686576SSunitha Harish self->sendTaskEvent(self->state, self->index); 289*e7686576SSunitha Harish 290fd9ab9e1SJames Feist // reset the match after the callback was successful 291fd9ab9e1SJames Feist boost::asio::post( 292fd9ab9e1SJames Feist crow::connections::systemBus->get_io_context(), 293fd9ab9e1SJames Feist [self] { self->match.reset(); }); 294fd9ab9e1SJames Feist return; 295fd9ab9e1SJames Feist } 296fd9ab9e1SJames Feist }); 297fd9ab9e1SJames Feist 298fd9ab9e1SJames Feist extendTimer(timeout); 299e5d5006bSJames Feist messages.emplace_back(messages::taskStarted(std::to_string(index))); 300*e7686576SSunitha Harish // Send event : TaskStarted 301*e7686576SSunitha Harish sendTaskEvent(state, index); 30246229577SJames Feist } 30346229577SJames Feist 30446229577SJames Feist std::function<bool(boost::system::error_code, sdbusplus::message::message&, 30546229577SJames Feist const std::shared_ptr<TaskData>&)> 30646229577SJames Feist callback; 30746229577SJames Feist std::string matchStr; 30846229577SJames Feist size_t index; 30946229577SJames Feist time_t startTime; 31046229577SJames Feist std::string status; 31146229577SJames Feist std::string state; 31246229577SJames Feist nlohmann::json messages; 31346229577SJames Feist boost::asio::steady_timer timer; 31446229577SJames Feist std::unique_ptr<sdbusplus::bus::match::match> match; 31546229577SJames Feist std::optional<time_t> endTime; 316fe306728SJames Feist std::optional<Payload> payload; 31746229577SJames Feist bool gave204 = false; 31846229577SJames Feist }; 31946229577SJames Feist 32046229577SJames Feist } // namespace task 32146229577SJames Feist 32246229577SJames Feist class TaskMonitor : public Node 32346229577SJames Feist { 32446229577SJames Feist public: 32552cc112dSEd Tanous TaskMonitor(App& app) : 3267af91514SGunnar Mills Node((app), "/redfish/v1/TaskService/Tasks/<str>/Monitor/", 32746229577SJames Feist std::string()) 32846229577SJames Feist { 32946229577SJames Feist entityPrivileges = { 33046229577SJames Feist {boost::beast::http::verb::get, {{"Login"}}}, 33146229577SJames Feist {boost::beast::http::verb::head, {{"Login"}}}, 33246229577SJames Feist {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 33346229577SJames Feist {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 33446229577SJames Feist {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 33546229577SJames Feist {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 33646229577SJames Feist } 33746229577SJames Feist 33846229577SJames Feist private: 339cb13a392SEd Tanous void doGet(crow::Response& res, const crow::Request&, 34046229577SJames Feist const std::vector<std::string>& params) override 34146229577SJames Feist { 34246229577SJames Feist auto asyncResp = std::make_shared<AsyncResp>(res); 34346229577SJames Feist if (params.size() != 1) 34446229577SJames Feist { 34546229577SJames Feist messages::internalError(asyncResp->res); 34646229577SJames Feist return; 34746229577SJames Feist } 34846229577SJames Feist 34946229577SJames Feist const std::string& strParam = params[0]; 35046229577SJames Feist auto find = std::find_if( 35146229577SJames Feist task::tasks.begin(), task::tasks.end(), 35246229577SJames Feist [&strParam](const std::shared_ptr<task::TaskData>& task) { 35346229577SJames Feist if (!task) 35446229577SJames Feist { 35546229577SJames Feist return false; 35646229577SJames Feist } 35746229577SJames Feist 35846229577SJames Feist // we compare against the string version as on failure strtoul 35946229577SJames Feist // returns 0 36046229577SJames Feist return std::to_string(task->index) == strParam; 36146229577SJames Feist }); 36246229577SJames Feist 36346229577SJames Feist if (find == task::tasks.end()) 36446229577SJames Feist { 36546229577SJames Feist messages::resourceNotFound(asyncResp->res, "Monitor", strParam); 36646229577SJames Feist return; 36746229577SJames Feist } 36846229577SJames Feist std::shared_ptr<task::TaskData>& ptr = *find; 36946229577SJames Feist // monitor expires after 204 37046229577SJames Feist if (ptr->gave204) 37146229577SJames Feist { 37246229577SJames Feist messages::resourceNotFound(asyncResp->res, "Monitor", strParam); 37346229577SJames Feist return; 37446229577SJames Feist } 37546229577SJames Feist ptr->populateResp(asyncResp->res); 37646229577SJames Feist } 37746229577SJames Feist }; 37846229577SJames Feist 37946229577SJames Feist class Task : public Node 38046229577SJames Feist { 38146229577SJames Feist public: 38252cc112dSEd Tanous Task(App& app) : 3837af91514SGunnar Mills Node((app), "/redfish/v1/TaskService/Tasks/<str>/", std::string()) 38446229577SJames Feist { 38546229577SJames Feist entityPrivileges = { 38646229577SJames Feist {boost::beast::http::verb::get, {{"Login"}}}, 38746229577SJames Feist {boost::beast::http::verb::head, {{"Login"}}}, 38846229577SJames Feist {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 38946229577SJames Feist {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 39046229577SJames Feist {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 39146229577SJames Feist {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 39246229577SJames Feist } 39346229577SJames Feist 39446229577SJames Feist private: 395cb13a392SEd Tanous void doGet(crow::Response& res, const crow::Request&, 39646229577SJames Feist const std::vector<std::string>& params) override 39746229577SJames Feist { 39846229577SJames Feist auto asyncResp = std::make_shared<AsyncResp>(res); 39946229577SJames Feist if (params.size() != 1) 40046229577SJames Feist { 40146229577SJames Feist messages::internalError(asyncResp->res); 40246229577SJames Feist return; 40346229577SJames Feist } 40446229577SJames Feist 40546229577SJames Feist const std::string& strParam = params[0]; 40646229577SJames Feist auto find = std::find_if( 40746229577SJames Feist task::tasks.begin(), task::tasks.end(), 40846229577SJames Feist [&strParam](const std::shared_ptr<task::TaskData>& task) { 40946229577SJames Feist if (!task) 41046229577SJames Feist { 41146229577SJames Feist return false; 41246229577SJames Feist } 41346229577SJames Feist 41446229577SJames Feist // we compare against the string version as on failure strtoul 41546229577SJames Feist // returns 0 41646229577SJames Feist return std::to_string(task->index) == strParam; 41746229577SJames Feist }); 41846229577SJames Feist 41946229577SJames Feist if (find == task::tasks.end()) 42046229577SJames Feist { 42146229577SJames Feist messages::resourceNotFound(asyncResp->res, "Tasks", strParam); 42246229577SJames Feist return; 42346229577SJames Feist } 42446229577SJames Feist 42546229577SJames Feist std::shared_ptr<task::TaskData>& ptr = *find; 42646229577SJames Feist 42746229577SJames Feist asyncResp->res.jsonValue["@odata.type"] = "#Task.v1_4_3.Task"; 42846229577SJames Feist asyncResp->res.jsonValue["Id"] = strParam; 42946229577SJames Feist asyncResp->res.jsonValue["Name"] = "Task " + strParam; 43046229577SJames Feist asyncResp->res.jsonValue["TaskState"] = ptr->state; 43146229577SJames Feist asyncResp->res.jsonValue["StartTime"] = 43246229577SJames Feist crow::utility::getDateTime(ptr->startTime); 43346229577SJames Feist if (ptr->endTime) 43446229577SJames Feist { 43546229577SJames Feist asyncResp->res.jsonValue["EndTime"] = 43646229577SJames Feist crow::utility::getDateTime(*(ptr->endTime)); 43746229577SJames Feist } 43846229577SJames Feist asyncResp->res.jsonValue["TaskStatus"] = ptr->status; 43946229577SJames Feist asyncResp->res.jsonValue["Messages"] = ptr->messages; 44046229577SJames Feist asyncResp->res.jsonValue["@odata.id"] = 44146229577SJames Feist "/redfish/v1/TaskService/Tasks/" + strParam; 44246229577SJames Feist if (!ptr->gave204) 44346229577SJames Feist { 44446229577SJames Feist asyncResp->res.jsonValue["TaskMonitor"] = 44546229577SJames Feist "/redfish/v1/TaskService/Tasks/" + strParam + "/Monitor"; 44646229577SJames Feist } 447fe306728SJames Feist if (ptr->payload) 448fe306728SJames Feist { 449fe306728SJames Feist asyncResp->res.jsonValue["Payload"] = *(ptr->payload); 450fe306728SJames Feist } 45146229577SJames Feist } 45246229577SJames Feist }; 45346229577SJames Feist 45446229577SJames Feist class TaskCollection : public Node 45546229577SJames Feist { 45646229577SJames Feist public: 45752cc112dSEd Tanous TaskCollection(App& app) : Node(app, "/redfish/v1/TaskService/Tasks/") 45846229577SJames Feist { 45946229577SJames Feist entityPrivileges = { 46046229577SJames Feist {boost::beast::http::verb::get, {{"Login"}}}, 46146229577SJames Feist {boost::beast::http::verb::head, {{"Login"}}}, 46246229577SJames Feist {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 46346229577SJames Feist {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 46446229577SJames Feist {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 46546229577SJames Feist {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 46646229577SJames Feist } 46746229577SJames Feist 46846229577SJames Feist private: 469cb13a392SEd Tanous void doGet(crow::Response& res, const crow::Request&, 470cb13a392SEd Tanous const std::vector<std::string>&) override 47146229577SJames Feist { 47246229577SJames Feist auto asyncResp = std::make_shared<AsyncResp>(res); 47346229577SJames Feist asyncResp->res.jsonValue["@odata.type"] = 47446229577SJames Feist "#TaskCollection.TaskCollection"; 47546229577SJames Feist asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/TaskService/Tasks"; 47646229577SJames Feist asyncResp->res.jsonValue["Name"] = "Task Collection"; 47746229577SJames Feist asyncResp->res.jsonValue["Members@odata.count"] = task::tasks.size(); 47846229577SJames Feist nlohmann::json& members = asyncResp->res.jsonValue["Members"]; 47946229577SJames Feist members = nlohmann::json::array(); 48046229577SJames Feist 48146229577SJames Feist for (const std::shared_ptr<task::TaskData>& task : task::tasks) 48246229577SJames Feist { 48346229577SJames Feist if (task == nullptr) 48446229577SJames Feist { 48546229577SJames Feist continue; // shouldn't be possible 48646229577SJames Feist } 48746229577SJames Feist members.emplace_back( 48846229577SJames Feist nlohmann::json{{"@odata.id", "/redfish/v1/TaskService/Tasks/" + 48946229577SJames Feist std::to_string(task->index)}}); 49046229577SJames Feist } 49146229577SJames Feist } 49246229577SJames Feist }; 49346229577SJames Feist 49446229577SJames Feist class TaskService : public Node 49546229577SJames Feist { 49646229577SJames Feist public: 49752cc112dSEd Tanous TaskService(App& app) : Node(app, "/redfish/v1/TaskService/") 49846229577SJames Feist { 49946229577SJames Feist entityPrivileges = { 50046229577SJames Feist {boost::beast::http::verb::get, {{"Login"}}}, 50146229577SJames Feist {boost::beast::http::verb::head, {{"Login"}}}, 50246229577SJames Feist {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 50346229577SJames Feist {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 50446229577SJames Feist {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 50546229577SJames Feist {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 50646229577SJames Feist } 50746229577SJames Feist 50846229577SJames Feist private: 509cb13a392SEd Tanous void doGet(crow::Response& res, const crow::Request&, 510cb13a392SEd Tanous const std::vector<std::string>&) override 51146229577SJames Feist { 51246229577SJames Feist auto asyncResp = std::make_shared<AsyncResp>(res); 51346229577SJames Feist asyncResp->res.jsonValue["@odata.type"] = 51446229577SJames Feist "#TaskService.v1_1_4.TaskService"; 51546229577SJames Feist asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/TaskService"; 51646229577SJames Feist asyncResp->res.jsonValue["Name"] = "Task Service"; 51746229577SJames Feist asyncResp->res.jsonValue["Id"] = "TaskService"; 51846229577SJames Feist asyncResp->res.jsonValue["DateTime"] = crow::utility::dateTimeNow(); 51946229577SJames Feist asyncResp->res.jsonValue["CompletedTaskOverWritePolicy"] = "Oldest"; 52046229577SJames Feist 521*e7686576SSunitha Harish asyncResp->res.jsonValue["LifeCycleEventOnTaskStateChange"] = true; 52246229577SJames Feist 52346229577SJames Feist auto health = std::make_shared<HealthPopulate>(asyncResp); 52446229577SJames Feist health->populate(); 52546229577SJames Feist asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; 52646229577SJames Feist asyncResp->res.jsonValue["ServiceEnabled"] = true; 52746229577SJames Feist asyncResp->res.jsonValue["Tasks"] = { 52846229577SJames Feist {"@odata.id", "/redfish/v1/TaskService/Tasks"}}; 52946229577SJames Feist } 53046229577SJames Feist }; 53146229577SJames Feist 53246229577SJames Feist } // namespace redfish 533