Fix Task Monitor URI
Fixes #272
The TaskMonitor urls we create aren't correct per Redfish. Per DSP0266
section 12.2, our TaskMonitor URIs should take the form
/redfish/v1/TaskService/TaskMonitors/<id>
Note that even though this appears to be a collection, it is not, and
does not "exist" in the Redfish schema, hence why it is called out
explicitly.
Tested:
Started dump collection task with
POST
```
/redfish/v1/Managers/bmc/LogServices/Dump/Actions/LogService.CollectDiagnosticData
```
GET /redfish/v1/Tasks/0
Returned TaskMonitor = /redfish/v1/Tasks/TaskMonitors/0
GET /redfish/v1/Tasks/TaskMonitors/0 returned 200
Change-Id: I9fb1d62090f7787d7649c077b748b51ac3202f8a
Signed-off-by: Ed Tanous <ed@tanous.net>
diff --git a/redfish-core/include/aggregation_utils.hpp b/redfish-core/include/aggregation_utils.hpp
index f0b259e..78ff3c2 100644
--- a/redfish-core/include/aggregation_utils.hpp
+++ b/redfish-core/include/aggregation_utils.hpp
@@ -17,7 +17,7 @@
{
// Note that each URI actually begins with "/redfish/v1"
// They've been omitted to save space and reduce search time
-constexpr std::array<std::string_view, 49> topCollections{
+constexpr std::array<std::string_view, 50> topCollections{
"/AggregationService/Aggregates",
"/AggregationService/AggregationSources",
"/AggregationService/ConnectionMethods",
@@ -52,6 +52,7 @@
"/StorageServices",
"/StorageSystems",
"/Systems",
+ "/TaskService/TaskMonitors",
"/TaskService/Tasks",
"/TelemetryService/LogService/Entries",
"/TelemetryService/MetricDefinitions",
diff --git a/redfish-core/lib/task.hpp b/redfish-core/lib/task.hpp
index 8d81a29..ec92aca 100644
--- a/redfish-core/lib/task.hpp
+++ b/redfish-core/lib/task.hpp
@@ -144,7 +144,8 @@
{
res.result(boost::beast::http::status::accepted);
std::string strIdx = std::to_string(index);
- std::string uri = "/redfish/v1/TaskService/Tasks/" + strIdx;
+ boost::urls::url uri =
+ boost::urls::format("/redfish/v1/TaskService/Tasks/{}", strIdx);
res.jsonValue["@odata.id"] = uri;
res.jsonValue["@odata.type"] = "#Task.v1_4_3.Task";
@@ -152,8 +153,11 @@
res.jsonValue["TaskState"] = state;
res.jsonValue["TaskStatus"] = status;
+ boost::urls::url taskMonitor = boost::urls::format(
+ "/redfish/v1/TaskService/TaskMonitors/{}", strIdx);
+
res.addHeader(boost::beast::http::field::location,
- uri + "/Monitor");
+ taskMonitor.buffer());
res.addHeader(boost::beast::http::field::retry_after,
std::to_string(retryAfterSeconds));
}
@@ -313,7 +317,7 @@
inline void requestRoutesTaskMonitor(App& app)
{
- BMCWEB_ROUTE(app, "/redfish/v1/TaskService/Tasks/<str>/Monitor/")
+ BMCWEB_ROUTE(app, "/redfish/v1/TaskService/TaskMonitors/<str>/")
.privileges(redfish::privileges::getTask)
.methods(boost::beast::http::verb::get)(
[&app](const crow::Request& req,
@@ -402,8 +406,8 @@
boost::urls::format("/redfish/v1/TaskService/Tasks/{}", strParam);
if (!ptr->gave204)
{
- asyncResp->res.jsonValue["TaskMonitor"] =
- "/redfish/v1/TaskService/Tasks/" + strParam + "/Monitor";
+ asyncResp->res.jsonValue["TaskMonitor"] = boost::urls::format(
+ "/redfish/v1/TaskService/TaskMonitors/{}", strParam);
}
asyncResp->res.jsonValue["HidePayload"] = !ptr->payload;
diff --git a/scripts/generate_schema_collections.py b/scripts/generate_schema_collections.py
index cf1f2f3..039d32f 100755
--- a/scripts/generate_schema_collections.py
+++ b/scripts/generate_schema_collections.py
@@ -261,6 +261,12 @@
"ServiceRoot", curr_path, top_collections, False, "ServiceRoot_v1.xml"
)
+ # Task service is not called out by CSDL, and is technically not a
+ # collection, but functionally needs to be treated like a collection, per
+ # the Asynchronous operations section of DSP0266
+ # https://www.dmtf.org/sites/default/files/standards/documents/DSP0266_1.20.1.html#asynchronous-operations
+ top_collections.add("/redfish/v1/TaskService/TaskMonitors")
+
print("Finished traversal!")
TOTAL = len(top_collections)
diff --git a/test/redfish-core/include/redfish_aggregator_test.cpp b/test/redfish-core/include/redfish_aggregator_test.cpp
index 6986dcf..fe80964 100644
--- a/test/redfish-core/include/redfish_aggregator_test.cpp
+++ b/test/redfish-core/include/redfish_aggregator_test.cpp
@@ -61,6 +61,7 @@
"PowerEquipment/FloorPDUs",
"Systems",
"TaskService/Tasks",
+ "TaskService/TaskMonitors",
"TelemetryService/LogService/Entries",
"UpdateService/SoftwareInventory"};
@@ -214,6 +215,22 @@
"/redfish/v1/Chassis/5B42_TestChassis");
}
+TEST(addPrefixes, FixHttpTaskMonitor)
+{
+ // Previously bmcweb hosted task monitors incorrectly.
+ // It has been corrected in the next test, but ensure that the "old"
+ // way still produces the correct result.
+ nlohmann::json taskResp = R"(
+ {
+ "TaskMonitor": "/redfish/v1/TaskService/Tasks/0/Monitor"
+ }
+ )"_json;
+
+ addPrefixes(taskResp, "5B247A");
+ EXPECT_EQ(taskResp["TaskMonitor"],
+ "/redfish/v1/TaskService/Tasks/5B247A_0/Monitor");
+}
+
TEST(addPrefixes, FixHttpHeadersInResponseBody)
{
nlohmann::json taskResp = nlohmann::json::parse(R"(
@@ -230,7 +247,7 @@
]
},
"PercentComplete": 100,
- "TaskMonitor": "/redfish/v1/TaskService/Tasks/0/Monitor",
+ "TaskMonitor": "/redfish/v1/TaskService/TaskMonitors/0",
"TaskState": "Completed",
"TaskStatus": "OK"
}
@@ -240,7 +257,7 @@
addPrefixes(taskResp, "5B247A");
EXPECT_EQ(taskResp["@odata.id"], "/redfish/v1/TaskService/Tasks/5B247A_0");
EXPECT_EQ(taskResp["TaskMonitor"],
- "/redfish/v1/TaskService/Tasks/5B247A_0/Monitor");
+ "/redfish/v1/TaskService/TaskMonitors/5B247A_0");
nlohmann::json& httpHeaders = taskResp["Payload"]["HttpHeaders"];
EXPECT_EQ(
httpHeaders[4],