Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dev-tools/ls-apis/tests/api_dependencies.out
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Maghemite DDM Admin (client: ddm-admin-client)
consumed by: wicketd (omicron/wicketd) via 1 path

DNS Server (client: dns-service-client)
consumed by: omicron-nexus (omicron/nexus) via 1 path
consumed by: omicron-nexus (omicron/nexus) via 2 paths
consumed by: omicron-sled-agent (omicron/sled-agent) via 1 path

Dendrite DPD (client: dpd-client)
Expand Down
38 changes: 35 additions & 3 deletions nexus/db-model/src/inventory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ use nexus_db_schema::schema::inv_zone_manifest_zone;
use nexus_db_schema::schema::{
hw_baseboard_id, inv_caboose, inv_clickhouse_keeper_membership,
inv_cockroachdb_status, inv_collection, inv_collection_error, inv_dataset,
inv_host_phase_1_flash_hash, inv_last_reconciliation_dataset_result,
inv_host_phase_1_flash_hash, inv_internal_dns,
inv_last_reconciliation_dataset_result,
inv_last_reconciliation_disk_result,
inv_last_reconciliation_orphaned_dataset,
inv_last_reconciliation_zone_result, inv_mupdate_override_non_boot,
Expand Down Expand Up @@ -62,8 +63,9 @@ use nexus_sled_agent_shared::inventory::{
OmicronZoneDataset, OmicronZoneImageSource, OmicronZoneType,
};
use nexus_types::inventory::{
BaseboardId, Caboose, CockroachStatus, Collection, NvmeFirmware,
PowerState, RotPage, RotSlot, TimeSync,
BaseboardId, Caboose, CockroachStatus, Collection,
InternalDnsGenerationStatus, NvmeFirmware, PowerState, RotPage, RotSlot,
TimeSync,
};
use omicron_common::api::external;
use omicron_common::api::internal::shared::NetworkInterface;
Expand Down Expand Up @@ -2964,6 +2966,36 @@ impl From<InvNtpTimesync> for nexus_types::inventory::TimeSync {
}
}

#[derive(Queryable, Clone, Debug, Selectable, Insertable)]
#[diesel(table_name = inv_internal_dns)]
pub struct InvInternalDns {
pub inv_collection_id: DbTypedUuid<CollectionKind>,
pub zone_id: DbTypedUuid<OmicronZoneKind>,
pub generation: Generation,
}

impl InvInternalDns {
pub fn new(
inv_collection_id: CollectionUuid,
status: &InternalDnsGenerationStatus,
) -> Result<Self, anyhow::Error> {
Ok(Self {
inv_collection_id: inv_collection_id.into(),
zone_id: status.zone_id.into(),
generation: Generation(status.generation),
})
}
}

impl From<InvInternalDns> for InternalDnsGenerationStatus {
fn from(value: InvInternalDns) -> Self {
Self {
zone_id: value.zone_id.into(),
generation: value.generation.into(),
}
}
}

#[cfg(test)]
mod test {
use nexus_types::inventory::NvmeFirmware;
Expand Down
3 changes: 2 additions & 1 deletion nexus/db-model/src/schema_versions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use std::{collections::BTreeMap, sync::LazyLock};
///
/// This must be updated when you change the database schema. Refer to
/// schema/crdb/README.adoc in the root of this repository for details.
pub const SCHEMA_VERSION: Version = Version::new(172, 0, 0);
pub const SCHEMA_VERSION: Version = Version::new(173, 0, 0);

/// List of all past database schema versions, in *reverse* order
///
Expand All @@ -28,6 +28,7 @@ static KNOWN_VERSIONS: LazyLock<Vec<KnownVersion>> = LazyLock::new(|| {
// | leaving the first copy as an example for the next person.
// v
// KnownVersion::new(next_int, "unique-dirname-with-the-sql-files"),
KnownVersion::new(173, "inv-internal-dns"),
KnownVersion::new(172, "add-zones-with-mupdate-override"),
KnownVersion::new(171, "inv-clear-mupdate-override"),
KnownVersion::new(170, "add-pending-mgs-updates-rot-bootloader"),
Expand Down
56 changes: 56 additions & 0 deletions nexus/db-queries/src/db/datastore/inventory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ use nexus_db_model::InvConfigReconcilerStatus;
use nexus_db_model::InvConfigReconcilerStatusKind;
use nexus_db_model::InvDataset;
use nexus_db_model::InvHostPhase1FlashHash;
use nexus_db_model::InvInternalDns;
use nexus_db_model::InvLastReconciliationDatasetResult;
use nexus_db_model::InvLastReconciliationDiskResult;
use nexus_db_model::InvLastReconciliationOrphanedDataset;
Expand Down Expand Up @@ -96,6 +97,7 @@ use nexus_sled_agent_shared::inventory::ZoneManifestNonBootInventory;
use nexus_types::inventory::BaseboardId;
use nexus_types::inventory::CockroachStatus;
use nexus_types::inventory::Collection;
use nexus_types::inventory::InternalDnsGenerationStatus;
use nexus_types::inventory::PhysicalDiskFirmware;
use nexus_types::inventory::SledAgent;
use nexus_types::inventory::TimeSync;
Expand Down Expand Up @@ -398,6 +400,13 @@ impl DataStore {
.collect::<Result<Vec<_>, _>>()
.map_err(|e| Error::internal_error(&e.to_string()))?;

let inv_internal_dns_records: Vec<InvInternalDns> = collection
.internal_dns_generation_status
.iter()
.map(|status| InvInternalDns::new(collection_id, status))
.collect::<Result<Vec<_>, _>>()
.map_err(|e| Error::internal_error(&e.to_string()))?;

// This implementation inserts all records associated with the
// collection in one transaction. This is primarily for simplicity. It
// means we don't have to worry about other readers seeing a
Expand Down Expand Up @@ -1516,6 +1525,15 @@ impl DataStore {
.await?;
}

// Insert the internal DNS generation status we've observed
if !inv_internal_dns_records.is_empty() {
use nexus_db_schema::schema::inv_internal_dns::dsl;
diesel::insert_into(dsl::inv_internal_dns)
.values(inv_internal_dns_records)
.execute_async(&conn)
.await?;
}

// Finally, insert the list of errors.
{
use nexus_db_schema::schema::inv_collection_error::dsl as errors_dsl;
Expand Down Expand Up @@ -1807,6 +1825,7 @@ impl DataStore {
nclickhouse_keeper_membership: usize,
ncockroach_status: usize,
nntp_timesync: usize,
ninternal_dns: usize,
}

let NumRowsDeleted {
Expand Down Expand Up @@ -1839,6 +1858,7 @@ impl DataStore {
nclickhouse_keeper_membership,
ncockroach_status,
nntp_timesync,
ninternal_dns,
} =
self.transaction_retry_wrapper("inventory_delete_collection")
.transaction(&conn, |conn| async move {
Expand Down Expand Up @@ -2117,6 +2137,18 @@ impl DataStore {
.await?
};

// Remove rows for internal DNS
let ninternal_dns = {
use nexus_db_schema::schema::inv_internal_dns::dsl;
diesel::delete(
dsl::inv_internal_dns.filter(
dsl::inv_collection_id.eq(db_collection_id),
),
)
.execute_async(&conn)
.await?
};

Ok(NumRowsDeleted {
ncollections,
nsps,
Expand Down Expand Up @@ -2147,6 +2179,7 @@ impl DataStore {
nclickhouse_keeper_membership,
ncockroach_status,
nntp_timesync,
ninternal_dns,
})
})
.await
Expand Down Expand Up @@ -2189,6 +2222,7 @@ impl DataStore {
"nclickhouse_keeper_membership" => nclickhouse_keeper_membership,
"ncockroach_status" => ncockroach_status,
"nntp_timesync" => nntp_timesync,
"ninternal_dns" => ninternal_dns,
);

Ok(())
Expand Down Expand Up @@ -3638,6 +3672,27 @@ impl DataStore {
.collect::<IdOrdMap<_>>()
};

// Load internal DNS generation status
let internal_dns_generation_status: IdOrdMap<
InternalDnsGenerationStatus,
> = {
use nexus_db_schema::schema::inv_internal_dns::dsl;

let records: Vec<InvInternalDns> = dsl::inv_internal_dns
.filter(dsl::inv_collection_id.eq(db_id))
.select(InvInternalDns::as_select())
.load_async(&*conn)
.await
.map_err(|e| {
public_error_from_diesel(e, ErrorHandler::Server)
})?;

records
.into_iter()
.map(|record| InternalDnsGenerationStatus::from(record))
.collect::<IdOrdMap<_>>()
};

// Finally, build up the sled-agent map using the sled agent and
// omicron zone rows. A for loop is easier to understand than into_iter
// + filter_map + return Result + collect.
Expand Down Expand Up @@ -3894,6 +3949,7 @@ impl DataStore {
clickhouse_keeper_cluster_membership,
cockroach_status,
ntp_timesync,
internal_dns_generation_status,
})
}
}
Expand Down
8 changes: 8 additions & 0 deletions nexus/db-schema/src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1925,6 +1925,14 @@ table! {
}
}

table! {
inv_internal_dns (inv_collection_id, zone_id) {
inv_collection_id -> Uuid,
zone_id -> Uuid,
generation -> Int8,
}
}

/* blueprints */

table! {
Expand Down
1 change: 1 addition & 0 deletions nexus/inventory/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ base64.workspace = true
camino.workspace = true
chrono.workspace = true
clickhouse-admin-keeper-client.workspace = true
dns-service-client.workspace = true
clickhouse-admin-server-client.workspace = true
clickhouse-admin-types.workspace = true
futures.workspace = true
Expand Down
18 changes: 18 additions & 0 deletions nexus/inventory/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ use nexus_types::inventory::CabooseWhich;
use nexus_types::inventory::CockroachStatus;
use nexus_types::inventory::Collection;
use nexus_types::inventory::HostPhase1FlashHash;
use nexus_types::inventory::InternalDnsGenerationStatus;
use nexus_types::inventory::RotPage;
use nexus_types::inventory::RotPageFound;
use nexus_types::inventory::RotPageWhich;
Expand Down Expand Up @@ -127,6 +128,7 @@ pub struct CollectionBuilder {
BTreeSet<ClickhouseKeeperClusterMembership>,
cockroach_status: BTreeMap<NodeId, CockroachStatus>,
ntp_timesync: IdOrdMap<TimeSync>,
internal_dns_generation_status: IdOrdMap<InternalDnsGenerationStatus>,
// CollectionBuilderRng is taken by value, rather than passed in as a
// mutable ref, to encourage a tree-like structure where each RNG is
// generally independent.
Expand Down Expand Up @@ -159,6 +161,7 @@ impl CollectionBuilder {
clickhouse_keeper_cluster_membership: BTreeSet::new(),
cockroach_status: BTreeMap::new(),
ntp_timesync: IdOrdMap::new(),
internal_dns_generation_status: IdOrdMap::new(),
rng: CollectionBuilderRng::from_entropy(),
}
}
Expand All @@ -184,6 +187,7 @@ impl CollectionBuilder {
.clickhouse_keeper_cluster_membership,
cockroach_status: self.cockroach_status,
ntp_timesync: self.ntp_timesync,
internal_dns_generation_status: self.internal_dns_generation_status,
}
}

Expand Down Expand Up @@ -652,6 +656,19 @@ impl CollectionBuilder {
metrics.get_metric_unsigned(CockroachMetric::LivenessLiveNodes);
self.cockroach_status.insert(node_id, status);
}

/// Record information about internal DNS generation status
pub fn found_internal_dns_generation_status(
&mut self,
status: InternalDnsGenerationStatus,
) -> Result<(), anyhow::Error> {
self.internal_dns_generation_status
.insert_unique(status)
.map_err(|err| err.into_owned())
.context(
"Internal DNS server reported generation status multiple times",
)
}
}

/// Returns the current time, truncated to the previous microsecond.
Expand Down Expand Up @@ -712,6 +729,7 @@ mod test {
assert!(collection.clickhouse_keeper_cluster_membership.is_empty());
assert!(collection.cockroach_status.is_empty());
assert!(collection.ntp_timesync.is_empty());
assert!(collection.internal_dns_generation_status.is_empty());
}

// Simple test of a single, fairly typical collection that contains just
Expand Down
Loading
Loading