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 crate::ModificationResponse;
52use core::fmt::Display;
53use core::fmt::Formatter;
54use core::fmt::Result as FmtResult;
55use serde::Deserialize;
56use serde::Serialize;
57use std::marker::PhantomData;
58
59/// URI reference for the `target` field of an action.
60///
61/// The [`Bmc`] implementation resolves this value when the action is run and
62/// may reject values that violate its outbound request policy before transport.
63#[derive(Debug, Clone, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
64#[repr(transparent)]
65pub struct ActionTarget(String);
66
67impl ActionTarget {
68 /// Creates new `ActionTarget`.
69 #[must_use]
70 pub const fn new(v: String) -> Self {
71 Self(v)
72 }
73
74 /// Returns the action target URI reference.
75 #[must_use]
76 pub fn as_str(&self) -> &str {
77 &self.0
78 }
79}
80
81impl Display for ActionTarget {
82 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
83 self.0.fmt(f)
84 }
85}
86
87/// Defines a deserializable Action. It is almost always a member of the
88/// `Actions` struct in different parts of the Redfish object tree.
89///
90/// `T` is the type for parameters.
91/// `R` is the type for the return value.
92#[derive(Deserialize, Debug)]
93pub struct Action<T, R> {
94 /// URI reference used to trigger the action.
95 #[serde(rename = "target")]
96 pub target: ActionTarget,
97 // TODO: we can retrieve constraints on attributes here.
98 /// Establishes a dependency on the `T` (parameters) type.
99 #[serde(skip_deserializing)]
100 _marker: PhantomData<T>,
101 /// Establishes a dependency on the `R` (return value) type.
102 #[serde(skip_deserializing)]
103 _marker_retval: PhantomData<R>,
104}
105
106/// Action error trait. Needed in generated code when an action function
107/// is called for an action that wasn't specified by the server.
108pub trait ActionError {
109 /// Create an error when the action is not supported.
110 fn not_supported() -> Self;
111}
112
113impl<T: Send + Sync + Serialize, R: Send + Sync + Sized + for<'de> Deserialize<'de>> Action<T, R> {
114 /// Run specific action with parameters passed as argument.
115 ///
116 /// URI-reference resolution and outbound request policy are handled by
117 /// [`Bmc::action`].
118 ///
119 /// # Errors
120 ///
121 /// Returns an error if the [`Bmc`] implementation rejects the action
122 /// request or if the Redfish service returns an error.
123 pub async fn run<B: Bmc>(
124 &self,
125 bmc: &B,
126 params: &T,
127 ) -> Result<ModificationResponse<R>, B::Error> {
128 bmc.action::<T, R>(self, params).await
129 }
130}