blob: 78193bc1b86974766b47b6d3472b94a94e77570f [file] [log] [blame]
James Feist46229572020-02-19 15:11:58 -08001/*
2// Copyright (c) 2020 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16#pragma once
17
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080018#include "app.hpp"
19#include "dbus_utility.hpp"
20#include "event_service_manager.hpp"
Ed Tanous539d8c62024-06-19 14:38:27 -070021#include "generated/enums/resource.hpp"
22#include "generated/enums/task_service.hpp"
Ed Tanous1aa0c2b2022-02-08 12:24:30 +010023#include "http/parsing.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080024#include "query.hpp"
25#include "registries/privilege_registry.hpp"
26#include "task_messages.hpp"
27
Ed Tanousd43cd0c2020-09-30 20:46:53 -070028#include <boost/asio/post.hpp>
29#include <boost/asio/steady_timer.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070030#include <boost/url/format.hpp>
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080031#include <sdbusplus/bus/match.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050032
33#include <chrono>
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080034#include <memory>
Ed Tanous3544d2a2023-08-06 18:12:20 -070035#include <ranges>
James Feist46229572020-02-19 15:11:58 -080036#include <variant>
37
38namespace redfish
39{
40
41namespace task
42{
43constexpr size_t maxTaskCount = 100; // arbitrary limit
44
Ed Tanouscf9e4172022-12-21 09:30:16 -080045// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
James Feist46229572020-02-19 15:11:58 -080046static std::deque<std::shared_ptr<struct TaskData>> tasks;
47
James Feist32898ce2020-03-10 16:16:52 -070048constexpr bool completed = true;
49
James Feistfe306722020-03-12 16:32:08 -070050struct Payload
51{
Ed Tanous4e23a442022-06-06 09:57:26 -070052 explicit Payload(const crow::Request& req) :
Ed Tanous39662a32023-02-06 15:09:46 -080053 targetUri(req.url().encoded_path()), httpOperation(req.methodString()),
Ed Tanous1aa0c2b2022-02-08 12:24:30 +010054 httpHeaders(nlohmann::json::array())
James Feistfe306722020-03-12 16:32:08 -070055 {
56 using field_ns = boost::beast::http::field;
57 constexpr const std::array<boost::beast::http::field, 7>
58 headerWhitelist = {field_ns::accept, field_ns::accept_encoding,
59 field_ns::user_agent, field_ns::host,
60 field_ns::connection, field_ns::content_length,
61 field_ns::upgrade};
62
Ed Tanous1aa0c2b2022-02-08 12:24:30 +010063 JsonParseResult ret = parseRequestAsJson(req, jsonBody);
64 if (ret != JsonParseResult::Success)
James Feistfe306722020-03-12 16:32:08 -070065 {
Ed Tanous1aa0c2b2022-02-08 12:24:30 +010066 return;
James Feistfe306722020-03-12 16:32:08 -070067 }
68
Ed Tanous98fe7402023-02-14 14:50:33 -080069 for (const auto& field : req.fields())
James Feistfe306722020-03-12 16:32:08 -070070 {
Ed Tanous3544d2a2023-08-06 18:12:20 -070071 if (std::ranges::find(headerWhitelist, field.name()) ==
72 headerWhitelist.end())
James Feistfe306722020-03-12 16:32:08 -070073 {
74 continue;
75 }
76 std::string header;
Patrick Williamsbd79bce2024-08-16 15:22:20 -040077 header.reserve(
78 field.name_string().size() + 2 + field.value().size());
James Feistfe306722020-03-12 16:32:08 -070079 header += field.name_string();
80 header += ": ";
81 header += field.value();
82 httpHeaders.emplace_back(std::move(header));
83 }
84 }
85 Payload() = delete;
86
87 std::string targetUri;
88 std::string httpOperation;
89 nlohmann::json httpHeaders;
90 nlohmann::json jsonBody;
91};
92
James Feist46229572020-02-19 15:11:58 -080093struct TaskData : std::enable_shared_from_this<TaskData>
94{
95 private:
Patrick Williams59d494e2022-07-22 19:26:55 -050096 TaskData(
97 std::function<bool(boost::system::error_code, sdbusplus::message_t&,
98 const std::shared_ptr<TaskData>&)>&& handler,
99 const std::string& matchIn, size_t idx) :
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400100 callback(std::move(handler)), matchStr(matchIn), index(idx),
James Feist46229572020-02-19 15:11:58 -0800101 startTime(std::chrono::system_clock::to_time_t(
102 std::chrono::system_clock::now())),
103 status("OK"), state("Running"), messages(nlohmann::json::array()),
104 timer(crow::connections::systemBus->get_io_context())
105
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500106 {}
James Feist46229572020-02-19 15:11:58 -0800107
108 public:
Ed Tanousd609fd62020-09-28 19:08:03 -0700109 TaskData() = delete;
110
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500111 static std::shared_ptr<TaskData>& createTask(
Patrick Williams59d494e2022-07-22 19:26:55 -0500112 std::function<bool(boost::system::error_code, sdbusplus::message_t&,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500113 const std::shared_ptr<TaskData>&)>&& handler,
114 const std::string& match)
James Feist46229572020-02-19 15:11:58 -0800115 {
116 static size_t lastTask = 0;
117 struct MakeSharedHelper : public TaskData
118 {
119 MakeSharedHelper(
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500120 std::function<bool(boost::system::error_code,
Patrick Williams59d494e2022-07-22 19:26:55 -0500121 sdbusplus::message_t&,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500122 const std::shared_ptr<TaskData>&)>&& handler,
Ed Tanous23a21a12020-07-25 04:45:05 +0000123 const std::string& match2, size_t idx) :
124 TaskData(std::move(handler), match2, idx)
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500125 {}
James Feist46229572020-02-19 15:11:58 -0800126 };
127
128 if (tasks.size() >= maxTaskCount)
129 {
Ed Tanous02cad962022-06-30 16:50:15 -0700130 const auto& last = tasks.front();
James Feist46229572020-02-19 15:11:58 -0800131
132 // destroy all references
133 last->timer.cancel();
134 last->match.reset();
135 tasks.pop_front();
136 }
137
138 return tasks.emplace_back(std::make_shared<MakeSharedHelper>(
139 std::move(handler), match, lastTask++));
140 }
141
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500142 void populateResp(crow::Response& res, size_t retryAfterSeconds = 30)
James Feist46229572020-02-19 15:11:58 -0800143 {
144 if (!endTime)
145 {
146 res.result(boost::beast::http::status::accepted);
147 std::string strIdx = std::to_string(index);
Ed Tanousfdbce792024-06-26 14:48:46 -0700148 boost::urls::url uri =
149 boost::urls::format("/redfish/v1/TaskService/Tasks/{}", strIdx);
Ed Tanous14766872022-03-15 10:44:42 -0700150
151 res.jsonValue["@odata.id"] = uri;
152 res.jsonValue["@odata.type"] = "#Task.v1_4_3.Task";
153 res.jsonValue["Id"] = strIdx;
154 res.jsonValue["TaskState"] = state;
155 res.jsonValue["TaskStatus"] = status;
156
Ed Tanousfdbce792024-06-26 14:48:46 -0700157 boost::urls::url taskMonitor = boost::urls::format(
158 "/redfish/v1/TaskService/TaskMonitors/{}", strIdx);
159
James Feist46229572020-02-19 15:11:58 -0800160 res.addHeader(boost::beast::http::field::location,
Ed Tanousfdbce792024-06-26 14:48:46 -0700161 taskMonitor.buffer());
James Feist46229572020-02-19 15:11:58 -0800162 res.addHeader(boost::beast::http::field::retry_after,
163 std::to_string(retryAfterSeconds));
164 }
165 else if (!gave204)
166 {
167 res.result(boost::beast::http::status::no_content);
168 gave204 = true;
169 }
170 }
171
Ed Tanousd609fd62020-09-28 19:08:03 -0700172 void finishTask()
James Feist46229572020-02-19 15:11:58 -0800173 {
174 endTime = std::chrono::system_clock::to_time_t(
175 std::chrono::system_clock::now());
176 }
177
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500178 void extendTimer(const std::chrono::seconds& timeout)
James Feist46229572020-02-19 15:11:58 -0800179 {
James Feist46229572020-02-19 15:11:58 -0800180 timer.expires_after(timeout);
181 timer.async_wait(
182 [self = shared_from_this()](boost::system::error_code ec) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400183 if (ec == boost::asio::error::operation_aborted)
184 {
185 return; // completed successfully
186 }
187 if (!ec)
188 {
189 // change ec to error as timer expired
190 ec = boost::asio::error::operation_aborted;
191 }
192 self->match.reset();
193 sdbusplus::message_t msg;
194 self->finishTask();
195 self->state = "Cancelled";
196 self->status = "Warning";
197 self->messages.emplace_back(
198 messages::taskAborted(std::to_string(self->index)));
199 // Send event :TaskAborted
200 self->sendTaskEvent(self->state, self->index);
201 self->callback(ec, msg, self);
202 });
James Feistfd9ab9e2020-05-19 13:48:07 -0700203 }
204
Ed Tanous26ccae32023-02-16 10:28:44 -0800205 static void sendTaskEvent(std::string_view state, size_t index)
Sunitha Harishe7686572020-07-15 02:32:44 -0500206 {
Sunitha Harishe7686572020-07-15 02:32:44 -0500207 // TaskState enums which should send out an event are:
208 // "Starting" = taskResumed
209 // "Running" = taskStarted
210 // "Suspended" = taskPaused
211 // "Interrupted" = taskPaused
212 // "Pending" = taskPaused
213 // "Stopping" = taskAborted
214 // "Completed" = taskCompletedOK
215 // "Killed" = taskRemoved
216 // "Exception" = taskCompletedWarning
217 // "Cancelled" = taskCancelled
Ed Tanousf8fe2212024-06-16 14:51:23 -0700218 nlohmann::json event;
219 std::string indexStr = std::to_string(index);
Sunitha Harishe7686572020-07-15 02:32:44 -0500220 if (state == "Starting")
221 {
Ed Tanousf8fe2212024-06-16 14:51:23 -0700222 event = redfish::messages::taskResumed(indexStr);
Sunitha Harishe7686572020-07-15 02:32:44 -0500223 }
224 else if (state == "Running")
225 {
Ed Tanousf8fe2212024-06-16 14:51:23 -0700226 event = redfish::messages::taskStarted(indexStr);
Sunitha Harishe7686572020-07-15 02:32:44 -0500227 }
228 else if ((state == "Suspended") || (state == "Interrupted") ||
229 (state == "Pending"))
230 {
Ed Tanousf8fe2212024-06-16 14:51:23 -0700231 event = redfish::messages::taskPaused(indexStr);
Sunitha Harishe7686572020-07-15 02:32:44 -0500232 }
233 else if (state == "Stopping")
234 {
Ed Tanousf8fe2212024-06-16 14:51:23 -0700235 event = redfish::messages::taskAborted(indexStr);
Sunitha Harishe7686572020-07-15 02:32:44 -0500236 }
237 else if (state == "Completed")
238 {
Ed Tanousf8fe2212024-06-16 14:51:23 -0700239 event = redfish::messages::taskCompletedOK(indexStr);
Sunitha Harishe7686572020-07-15 02:32:44 -0500240 }
241 else if (state == "Killed")
242 {
Ed Tanousf8fe2212024-06-16 14:51:23 -0700243 event = redfish::messages::taskRemoved(indexStr);
Sunitha Harishe7686572020-07-15 02:32:44 -0500244 }
245 else if (state == "Exception")
246 {
Ed Tanousf8fe2212024-06-16 14:51:23 -0700247 event = redfish::messages::taskCompletedWarning(indexStr);
Sunitha Harishe7686572020-07-15 02:32:44 -0500248 }
249 else if (state == "Cancelled")
250 {
Ed Tanousf8fe2212024-06-16 14:51:23 -0700251 event = redfish::messages::taskCancelled(indexStr);
Sunitha Harishe7686572020-07-15 02:32:44 -0500252 }
253 else
254 {
Ed Tanous62598e32023-07-17 17:06:25 -0700255 BMCWEB_LOG_INFO("sendTaskEvent: No events to send");
Ed Tanousf8fe2212024-06-16 14:51:23 -0700256 return;
Sunitha Harishe7686572020-07-15 02:32:44 -0500257 }
Ed Tanousf8fe2212024-06-16 14:51:23 -0700258 boost::urls::url origin =
259 boost::urls::format("/redfish/v1/TaskService/Tasks/{}", index);
260 EventServiceManager::getInstance().sendEvent(event, origin.buffer(),
261 "Task");
Sunitha Harishe7686572020-07-15 02:32:44 -0500262 }
263
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500264 void startTimer(const std::chrono::seconds& timeout)
James Feistfd9ab9e2020-05-19 13:48:07 -0700265 {
266 if (match)
267 {
268 return;
269 }
Patrick Williams59d494e2022-07-22 19:26:55 -0500270 match = std::make_unique<sdbusplus::bus::match_t>(
271 static_cast<sdbusplus::bus_t&>(*crow::connections::systemBus),
James Feistfd9ab9e2020-05-19 13:48:07 -0700272 matchStr,
Patrick Williams59d494e2022-07-22 19:26:55 -0500273 [self = shared_from_this()](sdbusplus::message_t& message) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400274 boost::system::error_code ec;
James Feistfd9ab9e2020-05-19 13:48:07 -0700275
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400276 // callback to return True if callback is done, callback needs
277 // to update status itself if needed
278 if (self->callback(ec, message, self) == task::completed)
279 {
280 self->timer.cancel();
281 self->finishTask();
James Feistfd9ab9e2020-05-19 13:48:07 -0700282
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400283 // Send event
284 self->sendTaskEvent(self->state, self->index);
Sunitha Harishe7686572020-07-15 02:32:44 -0500285
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400286 // reset the match after the callback was successful
287 boost::asio::post(
288 crow::connections::systemBus->get_io_context(),
289 [self] { self->match.reset(); });
290 return;
291 }
292 });
James Feistfd9ab9e2020-05-19 13:48:07 -0700293
294 extendTimer(timeout);
James Feiste5d50062020-05-11 17:29:00 -0700295 messages.emplace_back(messages::taskStarted(std::to_string(index)));
Sunitha Harishe7686572020-07-15 02:32:44 -0500296 // Send event : TaskStarted
297 sendTaskEvent(state, index);
James Feist46229572020-02-19 15:11:58 -0800298 }
299
Patrick Williams59d494e2022-07-22 19:26:55 -0500300 std::function<bool(boost::system::error_code, sdbusplus::message_t&,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500301 const std::shared_ptr<TaskData>&)>
James Feist46229572020-02-19 15:11:58 -0800302 callback;
303 std::string matchStr;
304 size_t index;
305 time_t startTime;
306 std::string status;
307 std::string state;
308 nlohmann::json messages;
309 boost::asio::steady_timer timer;
Patrick Williams59d494e2022-07-22 19:26:55 -0500310 std::unique_ptr<sdbusplus::bus::match_t> match;
James Feist46229572020-02-19 15:11:58 -0800311 std::optional<time_t> endTime;
James Feistfe306722020-03-12 16:32:08 -0700312 std::optional<Payload> payload;
James Feist46229572020-02-19 15:11:58 -0800313 bool gave204 = false;
George Liu6868ff52021-01-02 11:37:41 +0800314 int percentComplete = 0;
James Feist46229572020-02-19 15:11:58 -0800315};
316
317} // namespace task
318
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700319inline void requestRoutesTaskMonitor(App& app)
James Feist46229572020-02-19 15:11:58 -0800320{
Ed Tanousfdbce792024-06-26 14:48:46 -0700321 BMCWEB_ROUTE(app, "/redfish/v1/TaskService/TaskMonitors/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700322 .privileges(redfish::privileges::getTask)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700323 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700324 [&app](const crow::Request& req,
325 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
326 const std::string& strParam) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400327 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
328 {
329 return;
330 }
331 auto find = std::ranges::find_if(
332 task::tasks,
333 [&strParam](const std::shared_ptr<task::TaskData>& task) {
334 if (!task)
335 {
336 return false;
337 }
James Feist46229572020-02-19 15:11:58 -0800338
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400339 // we compare against the string version as on failure
340 // strtoul returns 0
341 return std::to_string(task->index) == strParam;
342 });
Ed Tanous002d39b2022-05-31 08:59:27 -0700343
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400344 if (find == task::tasks.end())
345 {
346 messages::resourceNotFound(asyncResp->res, "Task",
347 strParam);
348 return;
349 }
350 std::shared_ptr<task::TaskData>& ptr = *find;
351 // monitor expires after 204
352 if (ptr->gave204)
353 {
354 messages::resourceNotFound(asyncResp->res, "Task",
355 strParam);
356 return;
357 }
358 ptr->populateResp(asyncResp->res);
359 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700360}
361
362inline void requestRoutesTask(App& app)
363{
364 BMCWEB_ROUTE(app, "/redfish/v1/TaskService/Tasks/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700365 .privileges(redfish::privileges::getTask)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700366 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700367 [&app](const crow::Request& req,
368 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
369 const std::string& strParam) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400370 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
371 {
372 return;
373 }
374 auto find = std::ranges::find_if(
375 task::tasks,
376 [&strParam](const std::shared_ptr<task::TaskData>& task) {
377 if (!task)
378 {
379 return false;
380 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700381
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400382 // we compare against the string version as on failure
383 // strtoul returns 0
384 return std::to_string(task->index) == strParam;
385 });
Ed Tanous002d39b2022-05-31 08:59:27 -0700386
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400387 if (find == task::tasks.end())
388 {
389 messages::resourceNotFound(asyncResp->res, "Task",
390 strParam);
391 return;
392 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700393
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400394 const std::shared_ptr<task::TaskData>& ptr = *find;
Ed Tanous002d39b2022-05-31 08:59:27 -0700395
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400396 asyncResp->res.jsonValue["@odata.type"] = "#Task.v1_4_3.Task";
397 asyncResp->res.jsonValue["Id"] = strParam;
398 asyncResp->res.jsonValue["Name"] = "Task " + strParam;
399 asyncResp->res.jsonValue["TaskState"] = ptr->state;
400 asyncResp->res.jsonValue["StartTime"] =
401 redfish::time_utils::getDateTimeStdtime(ptr->startTime);
402 if (ptr->endTime)
403 {
404 asyncResp->res.jsonValue["EndTime"] =
405 redfish::time_utils::getDateTimeStdtime(
406 *(ptr->endTime));
407 }
408 asyncResp->res.jsonValue["TaskStatus"] = ptr->status;
409 asyncResp->res.jsonValue["Messages"] = ptr->messages;
410 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
411 "/redfish/v1/TaskService/Tasks/{}", strParam);
412 if (!ptr->gave204)
413 {
414 asyncResp->res.jsonValue["TaskMonitor"] =
415 boost::urls::format(
416 "/redfish/v1/TaskService/TaskMonitors/{}",
417 strParam);
418 }
Arun Thomas Baby5db7dfd2023-05-02 03:22:23 -0700419
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400420 asyncResp->res.jsonValue["HidePayload"] = !ptr->payload;
Arun Thomas Baby5db7dfd2023-05-02 03:22:23 -0700421
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400422 if (ptr->payload)
423 {
424 const task::Payload& p = *(ptr->payload);
425 asyncResp->res.jsonValue["Payload"]["TargetUri"] =
426 p.targetUri;
427 asyncResp->res.jsonValue["Payload"]["HttpOperation"] =
428 p.httpOperation;
429 asyncResp->res.jsonValue["Payload"]["HttpHeaders"] =
430 p.httpHeaders;
431 asyncResp->res.jsonValue["Payload"]["JsonBody"] =
432 p.jsonBody.dump(
433 -1, ' ', true,
434 nlohmann::json::error_handler_t::replace);
435 }
436 asyncResp->res.jsonValue["PercentComplete"] =
437 ptr->percentComplete;
438 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700439}
James Feist46229572020-02-19 15:11:58 -0800440
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700441inline void requestRoutesTaskCollection(App& app)
James Feist46229572020-02-19 15:11:58 -0800442{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700443 BMCWEB_ROUTE(app, "/redfish/v1/TaskService/Tasks/")
Ed Tanoused398212021-06-09 17:05:54 -0700444 .privileges(redfish::privileges::getTaskCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700445 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700446 [&app](const crow::Request& req,
447 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400448 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
449 {
450 return;
451 }
452 asyncResp->res.jsonValue["@odata.type"] =
453 "#TaskCollection.TaskCollection";
454 asyncResp->res.jsonValue["@odata.id"] =
455 "/redfish/v1/TaskService/Tasks";
456 asyncResp->res.jsonValue["Name"] = "Task Collection";
457 asyncResp->res.jsonValue["Members@odata.count"] =
458 task::tasks.size();
459 nlohmann::json& members = asyncResp->res.jsonValue["Members"];
460 members = nlohmann::json::array();
James Feist46229572020-02-19 15:11:58 -0800461
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400462 for (const std::shared_ptr<task::TaskData>& task : task::tasks)
463 {
464 if (task == nullptr)
465 {
466 continue; // shouldn't be possible
467 }
468 nlohmann::json::object_t member;
469 member["@odata.id"] =
470 boost::urls::format("/redfish/v1/TaskService/Tasks/{}",
471 std::to_string(task->index));
472 members.emplace_back(std::move(member));
473 }
474 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700475}
zhanghch058d1b46d2021-04-01 11:18:24 +0800476
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700477inline void requestRoutesTaskService(App& app)
James Feist46229572020-02-19 15:11:58 -0800478{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700479 BMCWEB_ROUTE(app, "/redfish/v1/TaskService/")
Ed Tanoused398212021-06-09 17:05:54 -0700480 .privileges(redfish::privileges::getTaskService)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700481 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700482 [&app](const crow::Request& req,
483 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400484 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
485 {
486 return;
487 }
488 asyncResp->res.jsonValue["@odata.type"] =
489 "#TaskService.v1_1_4.TaskService";
490 asyncResp->res.jsonValue["@odata.id"] =
491 "/redfish/v1/TaskService";
492 asyncResp->res.jsonValue["Name"] = "Task Service";
493 asyncResp->res.jsonValue["Id"] = "TaskService";
494 asyncResp->res.jsonValue["DateTime"] =
495 redfish::time_utils::getDateTimeOffsetNow().first;
496 asyncResp->res.jsonValue["CompletedTaskOverWritePolicy"] =
497 task_service::OverWritePolicy::Oldest;
James Feist46229572020-02-19 15:11:58 -0800498
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400499 asyncResp->res.jsonValue["LifeCycleEventOnTaskStateChange"] =
500 true;
James Feist46229572020-02-19 15:11:58 -0800501
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400502 asyncResp->res.jsonValue["Status"]["State"] =
503 resource::State::Enabled;
504 asyncResp->res.jsonValue["ServiceEnabled"] = true;
505 asyncResp->res.jsonValue["Tasks"]["@odata.id"] =
506 "/redfish/v1/TaskService/Tasks";
507 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700508}
James Feist46229572020-02-19 15:11:58 -0800509
510} // namespace redfish