Skip to content

Commit

Permalink
Teach omdb db network list-eips and `DataStore::vpc_resolve_to_sled…
Browse files Browse the repository at this point in the history
…s` about blueprints (#5202)

While working on #4886, I ran into a couple places that expect all
services to have rows in the `service` table, but Reconfigurator does
not add new rows to `service` when it spins up new services (see #4947
for rationale). This PR teaches these two users of `service` to _also_
check the current target blueprint when checking for services.

I also removed `LookupPath::service_id` and `lookup_resource! { ...
Service ... }`; the only user of these was `omdb`, and I think their
existence is misleading in the post-`service`-table world we're moving
toward.
  • Loading branch information
jgallagher authored Mar 8, 2024
1 parent 87c9b13 commit 8697f39
Show file tree
Hide file tree
Showing 6 changed files with 550 additions and 42 deletions.
99 changes: 82 additions & 17 deletions dev-tools/omdb/src/bin/omdb/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ use nexus_db_queries::db::DataStore;
use nexus_reconfigurator_preparation::policy_from_db;
use nexus_test_utils::db::ALLOW_FULL_TABLE_SCAN_SQL;
use nexus_types::deployment::Blueprint;
use nexus_types::deployment::OmicronZoneType;
use nexus_types::deployment::UnstableReconfiguratorState;
use nexus_types::identity::Resource;
use nexus_types::internal_api::params::DnsRecord;
Expand Down Expand Up @@ -628,7 +629,7 @@ fn first_page<'a, T>(limit: NonZeroU32) -> DataPageParams<'a, T> {
}
}

/// Helper function to looks up an instance with the given ID.
/// Helper function to look up an instance with the given ID.
async fn lookup_instance(
datastore: &DataStore,
instance_id: Uuid,
Expand All @@ -646,7 +647,71 @@ async fn lookup_instance(
.with_context(|| format!("loading instance {instance_id}"))
}

/// Helper function to looks up a project with the given ID.
/// Helper function to look up the kind of the service with the given ID.
///
/// Requires the caller to first have fetched the current target blueprint, so
/// we can find services that have been added by Reconfigurator.
async fn lookup_service_kind(
datastore: &DataStore,
service_id: Uuid,
current_target_blueprint: Option<&Blueprint>,
) -> anyhow::Result<Option<ServiceKind>> {
let conn = datastore.pool_connection_for_tests().await?;

// We need to check the `service` table (populated during rack setup)...
{
use db::schema::service::dsl;
if let Some(kind) = dsl::service
.filter(dsl::id.eq(service_id))
.limit(1)
.select(dsl::kind)
.get_result_async(&*conn)
.await
.optional()
.with_context(|| format!("loading service {service_id}"))?
{
return Ok(Some(kind));
}
}

// ...and if we don't find the service, check the latest blueprint, because
// the service might have been added by Reconfigurator after RSS ran.
let Some(blueprint) = current_target_blueprint else {
return Ok(None);
};

let Some(zone_config) =
blueprint.all_omicron_zones().find_map(|(_sled_id, zone_config)| {
if zone_config.id == service_id {
Some(zone_config)
} else {
None
}
})
else {
return Ok(None);
};

let service_kind = match &zone_config.zone_type {
OmicronZoneType::BoundaryNtp { .. }
| OmicronZoneType::InternalNtp { .. } => ServiceKind::Ntp,
OmicronZoneType::Clickhouse { .. } => ServiceKind::Clickhouse,
OmicronZoneType::ClickhouseKeeper { .. } => {
ServiceKind::ClickhouseKeeper
}
OmicronZoneType::CockroachDb { .. } => ServiceKind::Cockroach,
OmicronZoneType::Crucible { .. } => ServiceKind::Crucible,
OmicronZoneType::CruciblePantry { .. } => ServiceKind::CruciblePantry,
OmicronZoneType::ExternalDns { .. } => ServiceKind::ExternalDns,
OmicronZoneType::InternalDns { .. } => ServiceKind::InternalDns,
OmicronZoneType::Nexus { .. } => ServiceKind::Nexus,
OmicronZoneType::Oximeter { .. } => ServiceKind::Oximeter,
};

Ok(Some(service_kind))
}

/// Helper function to look up a project with the given ID.
async fn lookup_project(
datastore: &DataStore,
project_id: Uuid,
Expand Down Expand Up @@ -1886,26 +1951,26 @@ async fn cmd_db_eips(

let mut rows = Vec::new();

let current_target_blueprint = datastore
.blueprint_target_get_current_full(opctx)
.await
.context("loading current target blueprint")?
.map(|(_, blueprint)| blueprint);

for ip in &ips {
let owner = if let Some(owner_id) = ip.parent_id {
if ip.is_service {
let service = match LookupPath::new(opctx, datastore)
.service_id(owner_id)
.fetch()
.await
let kind = match lookup_service_kind(
datastore,
owner_id,
current_target_blueprint.as_ref(),
)
.await?
{
Ok(instance) => instance,
Err(e) => {
eprintln!(
"error looking up service with id {owner_id}: {e}"
);
continue;
}
Some(kind) => format!("{kind:?}"),
None => "UNKNOWN (service ID not found)".to_string(),
};
Owner::Service {
id: owner_id,
kind: format!("{:?}", service.1.kind),
}
Owner::Service { id: owner_id, kind }
} else {
let instance =
match lookup_instance(datastore, owner_id).await? {
Expand Down
21 changes: 19 additions & 2 deletions nexus/db-model/src/inventory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ use crate::schema::{
inv_sled_omicron_zones, sw_caboose, sw_root_of_trust_page,
};
use crate::{
impl_enum_type, ipv6, ByteCount, Generation, MacAddr, Name, SqlU16, SqlU32,
SqlU8,
impl_enum_type, ipv6, ByteCount, Generation, MacAddr, Name, ServiceKind,
SqlU16, SqlU32, SqlU8,
};
use anyhow::anyhow;
use chrono::DateTime;
Expand Down Expand Up @@ -715,6 +715,23 @@ impl_enum_type!(
Oximeter => b"oximeter"
);

impl From<ZoneType> for ServiceKind {
fn from(zone_type: ZoneType) -> Self {
match zone_type {
ZoneType::BoundaryNtp | ZoneType::InternalNtp => Self::Ntp,
ZoneType::Clickhouse => Self::Clickhouse,
ZoneType::ClickhouseKeeper => Self::ClickhouseKeeper,
ZoneType::CockroachDb => Self::Cockroach,
ZoneType::Crucible => Self::Crucible,
ZoneType::CruciblePantry => Self::CruciblePantry,
ZoneType::ExternalDns => Self::ExternalDns,
ZoneType::InternalDns => Self::InternalDns,
ZoneType::Nexus => Self::Nexus,
ZoneType::Oximeter => Self::Oximeter,
}
}
}

/// See [`nexus_types::inventory::OmicronZoneConfig`].
#[derive(Queryable, Clone, Debug, Selectable, Insertable)]
#[diesel(table_name = inv_omicron_zone)]
Expand Down
2 changes: 2 additions & 0 deletions nexus/db-model/src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1550,6 +1550,8 @@ allow_tables_to_appear_in_same_query!(
allow_tables_to_appear_in_same_query!(hw_baseboard_id, inv_sled_agent,);

allow_tables_to_appear_in_same_query!(
bp_omicron_zone,
bp_target,
dataset,
disk,
image,
Expand Down
6 changes: 3 additions & 3 deletions nexus/db-queries/src/db/datastore/deployment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1201,7 +1201,7 @@ mod tests {
#[tokio::test]
async fn test_empty_blueprint() {
// Setup
let logctx = dev::test_setup_log("inventory_insert");
let logctx = dev::test_setup_log("test_empty_blueprint");
let mut db = test_setup_database(&logctx.log).await;
let (opctx, datastore) = datastore_test(&logctx, &db).await;

Expand Down Expand Up @@ -1264,7 +1264,7 @@ mod tests {
#[tokio::test]
async fn test_representative_blueprint() {
// Setup
let logctx = dev::test_setup_log("inventory_insert");
let logctx = dev::test_setup_log("test_representative_blueprint");
let mut db = test_setup_database(&logctx.log).await;
let (opctx, datastore) = datastore_test(&logctx, &db).await;

Expand Down Expand Up @@ -1448,7 +1448,7 @@ mod tests {
#[tokio::test]
async fn test_set_target() {
// Setup
let logctx = dev::test_setup_log("inventory_insert");
let logctx = dev::test_setup_log("test_set_target");
let mut db = test_setup_database(&logctx.log).await;
let (opctx, datastore) = datastore_test(&logctx, &db).await;

Expand Down
Loading

0 comments on commit 8697f39

Please sign in to comment.