Skip to main content

nv_redfish_core/
action.rs

1// SPDX-FileCopyrightText: Copyright (c) 2025 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//! Redfish Action primitives
17//!
18//! The [`Action<T, R>`] type corresponds to the inner object found under the
19//! Redfish `Actions` section for a specific action (for example,
20//! `"#ComputerSystem.Reset"`). It captures the endpoint used to invoke the
21//! action via its `target` field. The type parameters are:
22//! - `T`: request parameters payload type (sent as the POST body when running the action)
23//! - `R`: response type returned by the BMC for that action
24//!
25//! Only the `target` field is deserialized. Any additional metadata
26//! (such as `...@Redfish.AllowableValues`) is ignored by this type
27//! and may be used by higher layers.
28//!
29//! Example: how an action appears in a Redfish resource and which part maps to [`Action`]
30//!
31//! ```json
32//! {
33//!   "Actions": {
34//!     "#ComputerSystem.Reset": {
35//!       "target": "/redfish/v1/Systems/1/Actions/ComputerSystem.Reset",
36//!       "ResetType@Redfish.AllowableValues": [
37//!         "On",
38//!         "GracefulRestart",
39//!         "ForceRestart"
40//!       ]
41//!     }
42//!   }
43//! }
44//! ```
45//!
46//! The [`Action<T, R>`] value corresponds to the inner object of
47//! `"#ComputerSystem.Reset"` and deserializes the `target` field only.
48//!
49
50use crate::Bmc;
51use core::fmt::Display;
52use core::fmt::Formatter;
53use core::fmt::Result as FmtResult;
54use serde::Deserialize;
55use serde::Serialize;
56use std::marker::PhantomData;
57
58/// Type for the `target` field of an Action.
59#[derive(Debug, Clone, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
60#[repr(transparent)]
61pub struct ActionTarget(String);
62
63impl ActionTarget {
64    /// Creates new `ActionTarget`.
65    #[must_use]
66    pub const fn new(v: String) -> Self {
67        Self(v)
68    }
69}
70
71impl Display for ActionTarget {
72    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
73        self.0.fmt(f)
74    }
75}
76
77/// Defines a deserializable Action. It is almost always a member of the
78/// `Actions` struct in different parts of the Redfish object tree.
79///
80/// `T` is the type for parameters.
81/// `R` is the type for the return value.
82#[derive(Deserialize, Debug)]
83pub struct Action<T, R> {
84    /// Path that is used to trigger the action.
85    #[serde(rename = "target")]
86    pub target: ActionTarget,
87    // TODO: we can retrieve constraints on attributes here.
88    /// Establishes a dependency on the `T` (parameters) type.
89    #[serde(skip_deserializing)]
90    _marker: PhantomData<T>,
91    /// Establishes a dependency on the `R` (return value) type.
92    #[serde(skip_deserializing)]
93    _marker_retval: PhantomData<R>,
94}
95
96/// Action error trait. Needed in generated code when an action function
97/// is called for an action that wasn't specified by the server.
98pub trait ActionError {
99    /// Create an error when the action is not supported.
100    fn not_supported() -> Self;
101}
102
103impl<T: Send + Sync + Serialize, R: Send + Sync + Sized + for<'a> Deserialize<'a>> Action<T, R> {
104    /// Run specific action with parameters passed as argument.
105    ///
106    /// # Errors
107    ///
108    /// Return error if BMC returned error on action.
109    pub async fn run<B: Bmc>(&self, bmc: &B, params: &T) -> Result<R, B::Error> {
110        bmc.action::<T, R>(self, params).await
111    }
112}