Skip to content

Commit

Permalink
Plumb inventory into nexus, omdb
Browse files Browse the repository at this point in the history
  • Loading branch information
smklein committed Jul 25, 2024
1 parent 817a397 commit 54b4658
Show file tree
Hide file tree
Showing 17 changed files with 392 additions and 21 deletions.
1 change: 1 addition & 0 deletions clients/sled-agent-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ progenitor::generate_api!(
RouterVersion = omicron_common::api::internal::shared::RouterVersion,
SourceNatConfig = omicron_common::api::internal::shared::SourceNatConfig,
SwitchLocation = omicron_common::api::external::SwitchLocation,
TypedUuidForDatasetKind = omicron_uuid_kinds::DatasetUuid,
TypedUuidForInstanceKind = omicron_uuid_kinds::InstanceUuid,
TypedUuidForPropolisKind = omicron_uuid_kinds::PropolisUuid,
TypedUuidForZpoolKind = omicron_uuid_kinds::ZpoolUuid,
Expand Down
38 changes: 38 additions & 0 deletions dev-tools/omdb/src/bin/omdb/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3720,6 +3720,44 @@ fn inv_collection_print_sleds(collection: &Collection) {
sled.reservoir_size.to_whole_gibibytes()
);

if !sled.zpools.is_empty() {
println!(" physical disks:");
}
for disk in &sled.disks {
let nexus_types::inventory::PhysicalDisk {
identity,
variant,
slot,
} = disk;
println!(" {variant:?}: {identity:?} in {slot}");
}

if !sled.zpools.is_empty() {
println!(" zpools");
}
for zpool in &sled.zpools {
let nexus_types::inventory::Zpool { id, total_size, .. } = zpool;
println!(" {id}: total size: {total_size}");
}

if !sled.datasets.is_empty() {
println!(" datasets:");
}
for dataset in &sled.datasets {
let nexus_types::inventory::Dataset {
id,
name,
available,
used,
quota,
reservation,
compression,
} = dataset;
println!(" {name} - id: {id:?}, compression: {compression}");
println!(" available: {available}, used: {used}");
println!(" reservation: {reservation:?}, quota: {quota:?}");
}

if let Some(zones) = collection.omicron_zones.get(&sled.sled_id) {
println!(
" zones collected from {} at {}",
Expand Down
33 changes: 33 additions & 0 deletions dev-tools/omdb/src/bin/omdb/sled_agent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ enum SledAgentCommands {
#[clap(subcommand)]
Zpools(ZpoolCommands),

/// print information about datasets
#[clap(subcommand)]
Datasets(DatasetCommands),

/// print information about the local bootstore node
#[clap(subcommand)]
Bootstore(BootstoreCommands),
Expand All @@ -55,6 +59,12 @@ enum ZpoolCommands {
List,
}

#[derive(Debug, Subcommand)]
enum DatasetCommands {
/// Print list of all datasets managed by the sled agent
List,
}

#[derive(Debug, Subcommand)]
enum BootstoreCommands {
/// Show the internal state of the local bootstore node
Expand Down Expand Up @@ -86,6 +96,9 @@ impl SledAgentArgs {
SledAgentCommands::Zpools(ZpoolCommands::List) => {
cmd_zpools_list(&client).await
}
SledAgentCommands::Datasets(DatasetCommands::List) => {
cmd_datasets_list(&client).await
}
SledAgentCommands::Bootstore(BootstoreCommands::Status) => {
cmd_bootstore_status(&client).await
}
Expand Down Expand Up @@ -130,6 +143,26 @@ async fn cmd_zpools_list(
Ok(())
}

/// Runs `omdb sled-agent datasets list`
async fn cmd_datasets_list(
client: &sled_agent_client::Client,
) -> Result<(), anyhow::Error> {
let response = client.datasets_get().await.context("listing datasets")?;
let response = response.into_inner();

println!("dataset configuration @ generation {}:", response.generation);
let datasets = response.datasets;

if datasets.is_empty() {
println!(" <none>");
}
for dataset in &datasets {
println!(" {:?}", dataset);
}

Ok(())
}

/// Runs `omdb sled-agent bootstore status`
async fn cmd_bootstore_status(
client: &sled_agent_client::Client,
Expand Down
1 change: 1 addition & 0 deletions dev-tools/omdb/tests/usage_errors.out
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,7 @@ Usage: omdb sled-agent [OPTIONS] <COMMAND>
Commands:
zones print information about zones
zpools print information about zpools
datasets print information about datasets
bootstore print information about the local bootstore node
help Print this message or the help of the given subcommand(s)

Expand Down
37 changes: 23 additions & 14 deletions illumos-utils/src/zfs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use crate::{execute, PFEXEC};
use anyhow::Context;
use camino::{Utf8Path, Utf8PathBuf};
use omicron_common::api::external::ByteCount;
use omicron_common::disk::DiskIdentity;
use omicron_uuid_kinds::DatasetUuid;
use std::fmt;
Expand Down Expand Up @@ -217,13 +218,13 @@ pub struct DatasetProperties {
/// The full name of the dataset.
pub name: String,
/// Remaining space in the dataset and descendents.
pub avail: u64,
pub avail: ByteCount,
/// Space used by dataset and descendents.
pub used: u64,
pub used: ByteCount,
/// Maximum space usable by dataset and descendents.
pub quota: Option<u64>,
pub quota: Option<ByteCount>,
/// Minimum space guaranteed to dataset and descendents.
pub reservation: Option<u64>,
pub reservation: Option<ByteCount>,
/// The compression algorithm used for this dataset.
pub compression: String,
}
Expand All @@ -240,20 +241,28 @@ impl FromStr for DatasetProperties {
};

let name = iter.next().context("Missing 'name'")?.to_string();
let avail = iter.next().context("Missing 'avail'")?.parse::<u64>()?;
let used = iter.next().context("Missing 'used'")?.parse::<u64>()?;
let avail = iter
.next()
.context("Missing 'avail'")?
.parse::<u64>()?
.try_into()?;
let used = iter
.next()
.context("Missing 'used'")?
.parse::<u64>()?
.try_into()?;
let quota =
match iter.next().context("Missing 'quota'")?.parse::<u64>()? {
0 => None,
q => Some(q),
q => Some(q.try_into()?),
};
let reservation = match iter
.next()
.context("Missing 'reservation'")?
.parse::<u64>()?
{
0 => None,
r => Some(r),
r => Some(r.try_into()?),
};
let compression =
iter.next().context("Missing 'compression'")?.to_string();
Expand Down Expand Up @@ -790,8 +799,8 @@ mod test {

assert_eq!(props.id, None);
assert_eq!(props.name, "dataset_name");
assert_eq!(props.avail, 1234);
assert_eq!(props.used, 5678);
assert_eq!(props.avail.to_bytes(), 1234);
assert_eq!(props.used.to_bytes(), 5678);
assert_eq!(props.quota, None);
assert_eq!(props.reservation, None);
assert_eq!(props.compression, "off");
Expand All @@ -808,10 +817,10 @@ mod test {
Some("d4e1e554-7b98-4413-809e-4a42561c3d0c".parse().unwrap())
);
assert_eq!(props.name, "dataset_name");
assert_eq!(props.avail, 1234);
assert_eq!(props.used, 5678);
assert_eq!(props.quota, Some(111));
assert_eq!(props.reservation, Some(222));
assert_eq!(props.avail.to_bytes(), 1234);
assert_eq!(props.used.to_bytes(), 5678);
assert_eq!(props.quota.map(|q| q.to_bytes()), Some(111));
assert_eq!(props.reservation.map(|r| r.to_bytes()), Some(222));
assert_eq!(props.compression, "off");
}

Expand Down
53 changes: 52 additions & 1 deletion nexus/db-model/src/inventory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use crate::omicron_zone_config::{OmicronZone, OmicronZoneNic};
use crate::schema::{
hw_baseboard_id, inv_caboose, inv_collection, inv_collection_error,
inv_omicron_zone, inv_omicron_zone_nic, inv_physical_disk,
inv_dataset, inv_omicron_zone, inv_omicron_zone_nic, inv_physical_disk,
inv_root_of_trust, inv_root_of_trust_page, inv_service_processor,
inv_sled_agent, inv_sled_omicron_zones, inv_zpool, sw_caboose,
sw_root_of_trust_page,
Expand All @@ -34,6 +34,7 @@ use nexus_types::inventory::{
use omicron_common::api::internal::shared::NetworkInterface;
use omicron_uuid_kinds::CollectionKind;
use omicron_uuid_kinds::CollectionUuid;
use omicron_uuid_kinds::DatasetKind;
use omicron_uuid_kinds::GenericUuid;
use omicron_uuid_kinds::SledKind;
use omicron_uuid_kinds::SledUuid;
Expand Down Expand Up @@ -921,6 +922,56 @@ impl From<InvZpool> for nexus_types::inventory::Zpool {
}
}

/// See [`nexus_types::inventory::Dataset`].
#[derive(Queryable, Clone, Debug, Selectable, Insertable)]
#[diesel(table_name = inv_dataset)]
pub struct InvDataset {
pub inv_collection_id: DbTypedUuid<CollectionKind>,
pub sled_id: DbTypedUuid<SledKind>,
pub id: Option<DbTypedUuid<DatasetKind>>,
pub name: String,
pub available: ByteCount,
pub used: ByteCount,
pub quota: Option<ByteCount>,
pub reservation: Option<ByteCount>,
pub compression: String,
}

impl InvDataset {
pub fn new(
inv_collection_id: CollectionUuid,
sled_id: SledUuid,
dataset: &nexus_types::inventory::Dataset,
) -> Self {
Self {
inv_collection_id: inv_collection_id.into(),
sled_id: sled_id.into(),

id: dataset.id.map(|id| id.into()),
name: dataset.name.clone(),
available: dataset.available.into(),
used: dataset.used.into(),
quota: dataset.quota.map(|q| q.into()),
reservation: dataset.reservation.map(|r| r.into()),
compression: dataset.compression.clone(),
}
}
}

impl From<InvDataset> for nexus_types::inventory::Dataset {
fn from(dataset: InvDataset) -> Self {
Self {
id: dataset.id.map(|id| id.0),
name: dataset.name,
available: *dataset.available,
used: *dataset.used,
quota: dataset.quota.map(|q| *q),
reservation: dataset.reservation.map(|r| *r),
compression: dataset.compression,
}
}
}

/// See [`nexus_types::inventory::OmicronZonesFound`].
#[derive(Queryable, Clone, Debug, Selectable, Insertable)]
#[diesel(table_name = inv_sled_omicron_zones)]
Expand Down
15 changes: 15 additions & 0 deletions nexus/db-model/src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1442,6 +1442,21 @@ table! {
}
}

table! {
inv_dataset (inv_collection_id, sled_id, name) {
inv_collection_id -> Uuid,
sled_id -> Uuid,

id -> Nullable<Uuid>,
name -> Text,
available -> Int8,
used -> Int8,
quota -> Nullable<Int8>,
reservation -> Nullable<Int8>,
compression -> Text,
}
}

table! {
inv_sled_omicron_zones (inv_collection_id, sled_id) {
inv_collection_id -> Uuid,
Expand Down
Loading

0 comments on commit 54b4658

Please sign in to comment.