Skip to main content

nv_redfish/task_service/
mod.rs

1// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2// SPDX-License-Identifier: Apache-2.0
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//! Task Service entities and helpers.
17//!
18//! This module provides typed access to Redfish `TaskService`.
19//! A `TaskService` value is a lightweight handle to the service schema and BMC
20//! transport. It validates task locations returned by asynchronous operations
21//! against this service's Tasks collection and returns lazy task links that can
22//! be fetched when polling is needed.
23
24use std::sync::Arc;
25
26use crate::Error;
27use crate::NvBmc;
28use crate::Resource;
29use crate::ResourceSchema;
30use crate::ServiceRoot;
31use crate::core::Bmc;
32use crate::core::EntityTypeRef as _;
33use crate::core::NavProperty;
34use crate::entity_link::EntityLink;
35use crate::schema::task::Task as TaskSchema;
36use crate::schema::task_service::TaskService as TaskServiceSchema;
37
38use nv_redfish_core::AsyncTask;
39
40/// Link to a Redfish Task returned by an asynchronous operation.
41pub type TaskLink<B> = EntityLink<B, TaskSchema>;
42
43/// Task service.
44///
45/// Provides task links for task locations returned by asynchronous operations.
46///
47/// # Example
48///
49/// ```ignore
50/// let Some(task_service) = root.task_service().await? else {
51///     return Ok(());
52/// };
53///
54/// let task_link = task_service.task_link(async_task)?;
55/// let task = task_link.fetch().await?;
56///
57/// println!("{:?}", task.task_state);
58/// ```
59pub struct TaskService<B: Bmc> {
60    data: Arc<TaskServiceSchema>,
61    bmc: NvBmc<B>,
62}
63
64impl<B: Bmc> TaskService<B> {
65    /// Create a new task service handle.
66    pub(crate) async fn new(
67        bmc: &NvBmc<B>,
68        root: &ServiceRoot<B>,
69    ) -> Result<Option<Self>, Error<B>> {
70        let Some(service_ref) = &root.root.tasks else {
71            return Ok(None);
72        };
73
74        let data = service_ref.get(bmc.as_ref()).await.map_err(Error::Bmc)?;
75
76        // Task links need the BMC-advertised Tasks collection as the allowed
77        // parent path for all async task locations.
78        if data.tasks.is_none() {
79            return Err(Error::TaskServiceTasksUnavailable);
80        }
81
82        Ok(Some(Self {
83            data,
84            bmc: bmc.clone(),
85        }))
86    }
87
88    /// Get the raw schema data for this task service.
89    #[must_use]
90    pub fn raw(&self) -> Arc<TaskServiceSchema> {
91        self.data.clone()
92    }
93
94    /// Create a task link from an asynchronous operation result.
95    ///
96    /// The task location must be a child of this service's Tasks collection,
97    /// such as `/redfish/v1/TaskService/Tasks/{id}`. The returned link does not
98    /// fetch the task until [`TaskLink::fetch`] is called.
99    ///
100    /// # Errors
101    ///
102    /// Returns error if the task location is not a child of this service's Tasks
103    /// collection.
104    pub fn task_link(&self, task: AsyncTask) -> Result<TaskLink<B>, Error<B>> {
105        let Some(tasks) = self.data.tasks.as_ref() else {
106            return Err(Error::TaskServiceTasksUnavailable);
107        };
108
109        let task_collection = tasks.odata_id();
110        let task_location = task.location.0;
111        if task_collection == &task_location || !task_collection.is_path_prefix(&task_location) {
112            return Err(Error::TaskLocationNotInTaskService {
113                task_location,
114                task_collection: task_collection.clone(),
115            });
116        }
117
118        let task_ref = NavProperty::new_reference(task_location);
119        Ok(TaskLink::new(&self.bmc, task_ref))
120    }
121}
122
123impl<B: Bmc> Resource for TaskService<B> {
124    fn resource_ref(&self) -> &ResourceSchema {
125        &self.data.as_ref().base
126    }
127}