Skip to content

Commit

Permalink
feat(baremetal): support reading baremetal nodes
Browse files Browse the repository at this point in the history
  • Loading branch information
dtantsur committed Oct 27, 2024
1 parent e9ceafb commit 7c0eca9
Show file tree
Hide file tree
Showing 14 changed files with 1,965 additions and 6 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
strategy:
fail-fast: false
matrix:
rust: [stable, nightly, 1.71.0]
rust: [stable, nightly, 1.76.0]
flags:
- ""
- "--no-default-features"
Expand Down
6 changes: 4 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ edition = "2021"
rust-version = "1.71"

[features]
default = ["block-storage", "compute", "image", "network", "native-tls", "object-storage"]
default = ["baremetal", "block-storage", "compute", "image", "network", "native-tls", "object-storage"]
baremetal = ["json-patch"]
block-storage = []
compute = []
identity = [] # reserved for future use
Expand All @@ -31,8 +32,9 @@ chrono = { version = "^0.4", features = ["serde"] }
macaddr = { version = "^1.0", features = ["serde_std"]}
futures = "^0.3"
ipnet = { version = "^2.0", features = ["serde"] }
json-patch = { version = "^3.0", default-features = false, optional = true }
log = "^0.4"
osauth = { version = "^0.4", default-features = false, features = ["stream"] }
osauth = { version = "^0.4.3", default-features = false, features = ["stream"] }
pin-project = "^1.0"
reqwest = { version = "^0.11", default-features = false, features = ["gzip", "json", "stream"] }
serde = "^1.0"
Expand Down
120 changes: 120 additions & 0 deletions src/baremetal/api.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// Copyright 2023 Dmitry Tantsur <[email protected]>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use osauth::services::BAREMETAL;
use osauth::{ApiVersion, Error, ErrorKind, Query, Session};

use crate::Result;

use super::{constants::*, protocol::*, types::*};

async fn node_api_version(session: &Session) -> Result<ApiVersion> {
session
.pick_api_version(
BAREMETAL,
vec![
API_VERSION_MINIMUM,
API_VERSION_AUTOMATED_CLEAN,
API_VERSION_PROTECTED,
API_VERSION_CONDUCTORS,
API_VERSION_OWNER,
API_VERSION_DESCRIPTION,
API_VERSION_ALLOCATIONS,
API_VERSION_RETIRED,
API_VERSION_LESSEE,
API_VERSION_NETWORK_DATA,
API_VERSION_BOOT_MODE,
API_VERSION_SHARDS,
],
)
.await?
.ok_or_else(|| {
Error::new(
ErrorKind::IncompatibleApiVersion,
"BareMetal API version 1.46 (Rocky) or newer is required",
)
})
}

fn node_query_version(query: &Query<NodeFilter>) -> ApiVersion {
let mut result = API_VERSION_MINIMUM;
for item in &query.0 {
let required_version = match item {
NodeFilter::DescriptionContains(..) => API_VERSION_DESCRIPTION,
NodeFilter::Lessee(..) => API_VERSION_LESSEE,
NodeFilter::Owner(..) => API_VERSION_OWNER,
NodeFilter::Project(..) => API_VERSION_LESSEE,
NodeFilter::Retired(..) => API_VERSION_RETIRED,
NodeFilter::Sharded(..) | NodeFilter::ShardIn(..) => API_VERSION_SHARDS,
NodeFilter::SortKey(key) => match key {
NodeSortKey::AutomatedClean => API_VERSION_AUTOMATED_CLEAN,
NodeSortKey::Protected => API_VERSION_PROTECTED,
NodeSortKey::Owner => API_VERSION_OWNER,
NodeSortKey::Description => API_VERSION_DESCRIPTION,
NodeSortKey::AllocationID => API_VERSION_ALLOCATIONS,
NodeSortKey::Retired => API_VERSION_RETIRED,
NodeSortKey::Lessee => API_VERSION_LESSEE,
NodeSortKey::Shard => API_VERSION_SHARDS,
_ => API_VERSION_MINIMUM,
},
NodeFilter::IncludeChildren(..) | NodeFilter::ParentNode(..) => API_VERSION_CHILD_NODES,
_ => API_VERSION_MINIMUM,
};
result = std::cmp::max(result, required_version);
}
result
}

/// Get a node.
pub async fn get_node<S: AsRef<str>>(session: &Session, id_or_name: S) -> Result<Node> {
let api_version = node_api_version(session).await?;
let root: Node = session
.get(BAREMETAL, &["nodes", id_or_name.as_ref()])
.api_version(api_version)
.fetch()
.await?;
trace!("Received {:?}", root);
Ok(root)
}

/// List nodes.
pub async fn list_nodes(session: &Session, query: &Query<NodeFilter>) -> Result<Vec<NodeSummary>> {
trace!("Listing baremetal nodes with {:?}", query);
let api_version = node_query_version(query);
let root: NodesRoot = session
.get(BAREMETAL, &["nodes"])
.api_version(api_version)
.query(query)
.fetch()
.await?;
trace!("Received baremetal nodes: {:?}", root.nodes);
Ok(root.nodes)
}

/// List nodes detailed.
pub async fn list_nodes_detailed(
session: &Session,
query: &Query<NodeFilter>,
) -> Result<Vec<Node>> {
trace!("Listing baremetal nodes with {:?}", query);
let api_version = node_query_version(query);
let root: NodesDetailRoot = session
.get(BAREMETAL, &["nodes", "detail"])
.api_version(api_version)
.query(query)
.fetch()
.await?;
trace!("Received baremetal nodes: {:?}", root.nodes);
Ok(root.nodes)
}
29 changes: 29 additions & 0 deletions src/baremetal/constants.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright 2023 Dmitry Tantsur <[email protected]>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use osauth::ApiVersion;

pub const API_VERSION_MINIMUM: ApiVersion = ApiVersion(1, 46); // Rocky
pub const API_VERSION_AUTOMATED_CLEAN: ApiVersion = ApiVersion(1, 47);
pub const API_VERSION_PROTECTED: ApiVersion = ApiVersion(1, 48);
pub const API_VERSION_CONDUCTORS: ApiVersion = ApiVersion(1, 49);
pub const API_VERSION_OWNER: ApiVersion = ApiVersion(1, 50);
pub const API_VERSION_DESCRIPTION: ApiVersion = ApiVersion(1, 51);
pub const API_VERSION_ALLOCATIONS: ApiVersion = ApiVersion(1, 52);
pub const API_VERSION_RETIRED: ApiVersion = ApiVersion(1, 61);
pub const API_VERSION_LESSEE: ApiVersion = ApiVersion(1, 65);
pub const API_VERSION_NETWORK_DATA: ApiVersion = ApiVersion(1, 66);
pub const API_VERSION_BOOT_MODE: ApiVersion = ApiVersion(1, 75);
pub const API_VERSION_SHARDS: ApiVersion = ApiVersion(1, 82);
pub const API_VERSION_CHILD_NODES: ApiVersion = ApiVersion(1, 83);
Loading

0 comments on commit 7c0eca9

Please sign in to comment.