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/// Type for the `target` field of an Action.
60#[derive(Debug, Clone, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
61#[repr(transparent)]
62pub struct ActionTarget(String);
63
64impl ActionTarget {
65 /// Creates new `ActionTarget`.
66 #[must_use]
67 pub const fn new(v: String) -> Self {
68 Self(v)
69 }
70}
71
72impl Display for ActionTarget {
73 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
74 self.0.fmt(f)
75 }
76}
77
78/// Defines a deserializable Action. It is almost always a member of the
79/// `Actions` struct in different parts of the Redfish object tree.
80///
81/// `T` is the type for parameters.
82/// `R` is the type for the return value.
83#[derive(Deserialize, Debug)]
84pub struct Action<T, R> {
85 /// Path that is used to trigger the action.
86 #[serde(rename = "target")]
87 pub target: ActionTarget,
88 // TODO: we can retrieve constraints on attributes here.
89 /// Establishes a dependency on the `T` (parameters) type.
90 #[serde(skip_deserializing)]
91 _marker: PhantomData<T>,
92 /// Establishes a dependency on the `R` (return value) type.
93 #[serde(skip_deserializing)]
94 _marker_retval: PhantomData<R>,
95}
96
97/// Action error trait. Needed in generated code when an action function
98/// is called for an action that wasn't specified by the server.
99pub trait ActionError {
100 /// Create an error when the action is not supported.
101 fn not_supported() -> Self;
102}
103
104impl<T: Send + Sync + Serialize, R: Send + Sync + Sized + for<'a> Deserialize<'a>> Action<T, R> {
105 /// Run specific action with parameters passed as argument.
106 ///
107 /// # Errors
108 ///
109 /// Return error if BMC returned error on action.
110 pub async fn run<B: Bmc>(
111 &self,
112 bmc: &B,
113 params: &T,
114 ) -> Result<ModificationResponse<R>, B::Error> {
115 bmc.action::<T, R>(self, params).await
116 }
117}