Skip to main content

nv_redfish/update_service/
software_inventory.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
16use crate::patch_support::CollectionWithPatch;
17use crate::patch_support::Payload;
18use crate::patch_support::ReadPatchFn;
19use crate::schema::redfish::resource::ResourceCollection;
20use crate::schema::redfish::software_inventory::SoftwareInventory as SoftwareInventorySchema;
21use crate::schema::redfish::software_inventory_collection::SoftwareInventoryCollection as SoftwareInventoryCollectionSchema;
22use crate::Error;
23use crate::NvBmc;
24use crate::Resource;
25use crate::ResourceSchema;
26use nv_redfish_core::Bmc;
27use nv_redfish_core::EdmDateTimeOffset;
28use nv_redfish_core::NavProperty;
29use std::convert::identity;
30use std::sync::Arc;
31use tagged_types::TaggedType;
32
33/// Version of the software.
34pub type Version = TaggedType<String, VersionTag>;
35/// Reference to the version of software.
36pub type VersionRef<'a> = TaggedType<&'a str, VersionTag>;
37#[doc(hidden)]
38#[derive(tagged_types::Tag)]
39#[implement(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
40#[transparent(Debug, Display, FromStr, Serialize, Deserialize)]
41#[capability(inner_access, cloned)]
42pub enum VersionTag {}
43
44/// Release date of the software.
45pub type ReleaseDate = TaggedType<EdmDateTimeOffset, ReleaseDateTag>;
46#[doc(hidden)]
47#[derive(tagged_types::Tag)]
48#[implement(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
49#[transparent(Debug, Display, FromStr, Serialize, Deserialize)]
50#[capability(inner_access, cloned)]
51pub enum ReleaseDateTag {}
52
53/// Represents a software inventory item in the update service.
54///
55/// Provides access to software version information and metadata.
56pub struct SoftwareInventory<B: Bmc> {
57    #[allow(dead_code)]
58    bmc: NvBmc<B>,
59    data: Arc<SoftwareInventorySchema>,
60}
61
62impl<B: Bmc> SoftwareInventory<B> {
63    /// Create a new software inventory handle.
64    pub(crate) async fn new(
65        bmc: &NvBmc<B>,
66        nav: &NavProperty<SoftwareInventorySchema>,
67        read_patch_fn: Option<&ReadPatchFn>,
68    ) -> Result<Self, Error<B>> {
69        if let Some(read_patch_fn) = read_patch_fn {
70            Payload::get(bmc.as_ref(), nav, read_patch_fn.as_ref()).await
71        } else {
72            nav.get(bmc.as_ref()).await.map_err(Error::Bmc)
73        }
74        .map(|data| Self {
75            bmc: bmc.clone(),
76            data,
77        })
78    }
79
80    /// Get the raw schema data for this software inventory item.
81    ///
82    /// Returns an `Arc` to the underlying schema, allowing cheap cloning
83    /// and sharing of the data.
84    #[must_use]
85    pub fn raw(&self) -> Arc<SoftwareInventorySchema> {
86        self.data.clone()
87    }
88
89    /// Get the version of software inventory item.
90    #[must_use]
91    pub fn version(&self) -> Option<VersionRef<'_>> {
92        self.data
93            .version
94            .as_ref()
95            .and_then(Option::as_deref)
96            .map(VersionRef::new)
97    }
98
99    /// Get the release date of the software inventory item.
100    #[must_use]
101    pub fn release_date(&self) -> Option<ReleaseDate> {
102        self.data
103            .release_date
104            .and_then(identity)
105            .map(ReleaseDate::new)
106    }
107}
108
109impl<B: Bmc> Resource for SoftwareInventory<B> {
110    fn resource_ref(&self) -> &ResourceSchema {
111        &self.data.as_ref().base
112    }
113}
114
115pub struct SoftwareInventoryCollection<B: Bmc> {
116    bmc: NvBmc<B>,
117    collection: Arc<SoftwareInventoryCollectionSchema>,
118    read_patch_fn: Option<ReadPatchFn>,
119}
120
121impl<B: Bmc> CollectionWithPatch<SoftwareInventoryCollectionSchema, SoftwareInventorySchema, B>
122    for SoftwareInventoryCollection<B>
123{
124    fn convert_patched(
125        base: ResourceCollection,
126        members: Vec<NavProperty<SoftwareInventorySchema>>,
127    ) -> SoftwareInventoryCollectionSchema {
128        SoftwareInventoryCollectionSchema { base, members }
129    }
130}
131
132impl<B: Bmc> SoftwareInventoryCollection<B> {
133    pub(crate) async fn new(
134        bmc: &NvBmc<B>,
135        collection_ref: &NavProperty<SoftwareInventoryCollectionSchema>,
136        read_patch_fn: Option<ReadPatchFn>,
137    ) -> Result<Self, Error<B>> {
138        let collection =
139            Self::expand_collection(bmc, collection_ref, read_patch_fn.as_ref(), None).await?;
140        Ok(Self {
141            bmc: bmc.clone(),
142            collection,
143            read_patch_fn,
144        })
145    }
146
147    pub(crate) async fn members(&self) -> Result<Vec<SoftwareInventory<B>>, Error<B>> {
148        let mut items = Vec::new();
149        for nav in &self.collection.members {
150            items.push(SoftwareInventory::new(&self.bmc, nav, self.read_patch_fn.as_ref()).await?);
151        }
152        Ok(items)
153    }
154}