blob: 80db518194214ba20b152c6786a93d01484e89e1 [file] [log] [blame]
James Feist46229572020-02-19 15:11:58 -08001/*
Ed Tanous6be832e2024-09-10 11:44:48 -07002Copyright (c) 2020 Intel Corporation
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
James Feist46229572020-02-19 15:11:58 -080015*/
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
Ed Tanousdaadfb22024-12-20 09:25:54 -0800200 sendTaskEvent(self->state, self->index);
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400201 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
Ed Tanousdaadfb22024-12-20 09:25:54 -0800284 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